diff --git a/Containers/docker-registry b/Containers/docker-registry new file mode 100644 index 0000000..0fac64c --- /dev/null +++ b/Containers/docker-registry @@ -0,0 +1,460 @@ += Private Docker Registry +Sottotitolo documento +:authors: Celestino Amoroso +:docinfo: shared +:encoding: utf-8 +:toc: right +:toclevels: 4 +:toc-title: Indice Generale +:icons: font +:icon-set: fi +:numbered: +:table-caption: Tabella +:figure-caption: Figura +:docinfo1: +:sectlinks: +:sectanchors: +:source-highlighter: rouge +// :rouge-style: ThankfulEyes +:rouge-style: gruvbox +// :rouge-style: colorful +//:rouge-style: monokay + +toc::[] + +## Introduzione +Le informazioni contenute in questa guida sono frutto di una serie di approfondimenti condotti al fine di realizzare un ambiente operativo idoneo allo studio e alla sperimentazione di Docker e Kubernetes. +In particolare, l'impulso iniziale per tale approfondimento è scaturito dal tentativo di esecuzione del comando _kubectl_ per creare ed esegure un Pod: + +`kubectl run` _nome-pod_ ``--image=``_nome-immagine_ + +L'effettivo funzionamento di questo comando è subordinato alla reperibilità dell'immagine richiesta. Se l'immagine specificata con _nome-immagine_ non può essere ritrovata, il Pod creato non entrerà in funzione. Questa situazione si è in effetti verificata seguendo le indicazioni pratiche del libro _Kubernetes Up and Running_. Le istruzioni fornite nel libro presuppongono la disponibilità del servizio *_gcr.io_* per il caricamento e il recupero di immagini Docker, ovvero un servizio _registry_. + +.Attivazione di Pod con immagine su *gcr.io* +[source,shell] +---- +$ kubectl run kuard --image=gcr.io/kuar-demo/kuard-amd64:blue +pod/kuard created + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +kuard 0/1 ErrImagePull 0 6s +---- + +L'errore riportato, _ErrImagePull_, indica l'impossibilità di scaricare l'immagine richiesta. Le cause di queto tipo di problema possono essere diverse. In questo caso l'errore è dovuto al fatto che il servizio _gcr.io_ è stato deprecato e che quindi non è stato possibile caricarvi l'immagine non essendo il servizio più disponibile. + +Per proseguire con lo studio del libro è stato perciò necessario trovare una soluzione alternativa al registry _gcr.io_. Fra le possibilità considerate, si è alla fine deciso predisporre un registry privato. + +Questa guida descrive appunto l'infrastruttura hardware e software impiegata per la soluzione e le procedure per realizzarla. + +## Infrastruttura hardware e software +Lo studio sui container e sulla loro orchestrazione si è inizialmente concentrato sulla costruzione e gestione di un cluster Kubernetes. Per tale finalità è stata impiegata una macchina virtuale Linux con sistema operativo Fedora 42. La macchina virtuale è attiva su un mini-pc casalingo anch'esso funzionante con Fedora 42. + +In seguito al verificarsi della situazione descritta in introduzione, nell'ambiente è stato incluso anche un server remoto VPS esposto su Internet nel quale è stato appunto realizzato il servizio registry privato. + +### Cluster Kubernetes +Per la realizzazione del cluster Kubernetes è stata impiegata una macchina virtuale Fedora 42 con le seguenti caratteristiche. + +#### Componenti hadware + +.VM Fedora 42 *fedoravm* +[cols="<2,^2"] +|=== +|*Caratteristica*|*Valore* +|Host-name| fedoravm +|Sistema operativo|Fedora 42 +|Hypervisor|QEMU/KVM +|Tipo CPU| x86_64 +|Numero CPU| 2 +|Memoria| 4 GB +|Storage| 60 GB +|Network| Bridge (rete LAN domestica) +|=== + +La macchina virtuale _fedoravm_ è eseguita su host Minis Forum, attualmente connesso alla rete LAN domestica mediante link WiFi. +Il sistema operativo del mini-pc è raggiungibile via SSH da Internet grazie all'impostazione di un port-forward sul router di casa. + +.Mini-PC Minis Forum +[cols="<2,^4"] +|=== +|*Caratteristica*|*Valore* +|Host-name| minis.portale-stac.it +|Sistema operativo|Fedora 42 +|Tipo CPU| 12th Gen Intel(R) Core(TM) i7-12650H (x86_64) +|Numero CPU logiche| 16 +|Memoria| 32 GB +|Storage| 1 TB SSD M.2 NVMe +|Network| 2 Ethernet, 1 WiFi +|=== + +#### Componenti software +Per l'uso di Docker su _fedoravm_ sono stati installati i pacchetti disponibili in Fedora 42. + +.Pacchetti Docker di Fedora 42 +---- +docker-buildx.x86_64 0.25.0-1.fc42 +docker-cli.x86_64 28.2.2-1.fc42 +---- + +Per altre sperimentazioni, sul sistema è anche presente il pacchetto _podman.x86_64_ 5:5.5.2-1.fc42. + +Fra le opzioni dispobili per la creazione di un cluster Kubernetes è stato scelto *_KinD_*, _Kubernetes in Docker_, o più semplicemente https://kind.sigs.k8s.io/[_kind_]. I requisiti per l'installazione di _kind_ sono + +* https://golang.org/[go] 1.17+ +* https://www.docker.com/[docker], https://podman.io/[podman], oppure https://github.com/containerd/nerdctl[nerdctl] + +.Installazione di kind +[source,shell] +---- +[fedoravm]$ go install sigs.k8s.io/kind@v0.29.0 +... +---- + +Il commando di soprà scaricherà una serie di moduli Go e produrrà l'eseguibile kind nel path `~/go/bin/kind`. + +.Installazione di kubectl +[source,shell] +---- +[fedoravm]$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + +[fedoravm]$ sudo mv kubectl /usr/local/bin <1> +---- +<1> #todo# verificare funzionamento comando + +Per ulteriori informazioni vedere https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/[Install and Set Up kubectl on Linux +Before you] + +.Crezione del cluster Kubernetes +[source,shell] +---- +[fedoravm]$ kind create cluster +... + +[fedoravm]$ kubectl cluster-info +Kubernetes control plane is running at https://127.0.0.1:34905 +CoreDNS is running at https://127.0.0.1:34905/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy + +To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. +---- + +Per soluzioni alternive a _kind_ vedere https://minikube.sigs.k8s.io/docs/tutorials/multi_node/[minikube], https://killercoda.com/playgrounds/scenario/kubernetes[Killercoda], https://kodekloud.com/public-playgrounds[KodeKloud], https://labs.play-with-k8s.com/[Play with Kubernetes]. + +### Docker registry +Per la realizzazione di un docker registry esistono diverse guide nel web. Tali guide spiegano come attivare un servizio registry basato sull'omonima immagine disponibile su Docker Hub e utilizzando una configurazione Docker Compose. Ecco alcuni riferimenti per l'attivazione di un registry su un proprio sistema: + +* https://hub.docker.com/_/registry[Docker Hub] +* https://distribution.github.io/distribution/about/deploying/[CNCF Distribution] +* https://www.freecodecamp.org/news/how-to-self-host-a-container-registry/#heading-how-to-self-host-a-container-registry[freeCodeCamp] + + +Un'altra possibilità è l'uso di https://goharbor.io/[Harbor]. + +La soluzione descritta in questa guida si basa su un Virtual Private Server, VPS, sul quale sono già attivi dei servizi raggiungibili tramite il dominio _portale-stac.it_. Esempi: + +* https://git.portale-stac.it[Git server] +* https://cloud.portale-stac.it[OCIS Cloud service] + +Sullo stesso server è inoltre in corso di sperimentazione un'installazione di https://caprover.com/[CapRover], la cui console è raggiungibile all'URL https://captain.paas.portale-stac.it/#/login[Captain]. Per le app attive in CapRover è stato registrato nel DNS di Aruba il recordo _*.paas.portale-stac.it_. In tal modo ad un'app chiamata ad esempio _myapp_ sarà automaticamente assgnato il nome host _myapp.paas.portale-stac.it_. + +Sia i servizi preesstenti che la console CapRover non sono direttamente esposti su Internet ma mediati tramite un _reverse proxy_ basato su Apache web server, _httpd_, e i suoi virtual host. + +In questo contesto si è deciso quindi di realizzare un registry attraverso i seguenti passaggi: + +. Creazione di un app CapRover con nome _hub_ in cui eseguire il servizio registry +.. Definizione dell'app basata sull'immagine _registry_ di Docker Hub. +.. Creazione di un volume per lo storage delle immagini +.. Configurazione di un meccanismo di autenticazione +. Configurazione di un nuovo virtual-host per la raggiungibilità del registry da Internet (gateway). +.. Il nome di dominio assegnato è _hub.paas.portale-stac.it_. + +#### Creazione registry come app CapRover +Come accennato sopra, il nome scelto per l'app CapRover che implementarà il registry Docker è *_hub_* e, di conseguenza, essendo _paas.portale-stac.it_ il sotto-dominio assegnato all'istanza CapRover, il suo nome di dominio completo risulta *_hub.paas.portale-stac.it_*. + +Il registry si basa sull'immagine *registry:3* disponibile in Docker Hub. Il programma contenuto nell'immagine e che implementa il servizio registry si chiama anch'esso *registry*. Ciò che serve sapere dell'immagine e del programma che esegue sono le variabili d'ambiente necessarie al suo funzionamento. Quelle considerate nel caso in esame sono le seguenti: + +[[a_env_vars,Variabili d'ambiente]] +.Variabili d'ambiente per l'app registry +[source,shell] +---- +# Tipo di credenziali +REGISTRY_AUTH=htpasswd +# Dominio delle credenziali +REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm +# Percorso logico dell'archivio (file) delle credenziali +REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password +# Percorso logico della directory delle immagini Docker +REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data +---- + +L'app _hub_ attualmente in funzione sull'istanza CapRover è stata creata attraverso l'interfaccia web https://captain.paas.portale-stac.it/#/login[Captain]. + +In questa sezione si ripercorrono i passaggi eseguiti nel VPS per giungere al docker registry funzionante. + +[[a_volumes,Volumi]] +##### Predisposizione dei volumi logici del registry +Dai valori delle variabili d'ambiente _REGISTRY_AUTH_HTPASSWD_PATH_ e _REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY_ si ricava che, per il suo funzionamento, l'appplicazione eseguita nell'immagine registry necessita di due aree di storage che sopravvivano all'app stessa: + +. File delle credenziali degli utenti per l'accesso al registry +. Directory del registro vero e proprio, dove l'app archivia le immagini dei container. + +Nel container dell'app saranno definiti quindi due volumi logici: + +. */auth* nel quale sarà reperibile il file delle credenziali _registry.password_. +. */data* in cui saranno registrate le immagini. + +La configurazione predefinita di Docker in Fedora predispone nel server host la directory fisica `/var/lib/docker/volumes` nella quale sono creati i volumi fisici corrispondenti a quelli logici dei container. + +Normalmente i nomi delle directory fisiche dei volumi sono identificate con stringhe alfanumeriche, ad esempio _fc17967070f949c325b6417388d6e600f69d6fe8b55fda99e04ff4a48cce072d_, non riconducibili immediatamente ai container che fanno riferimento a quelle directory tramite i rispettivi volumi logici. + +CapRover ha fissato una convenzione basata su etichette per la creazione delle directory dei volumi fisici con nomi predittibili. Nell'associazione fra volumi logici e fisici, CapRover consente in alternativa di indicare in modo esplicito il percorso fisico delle directory. Quest'ultima soluzione è quella adottata per l'app registry _hub_. + +Per l'esecuzione dei comandi seguenti sono richiesti privilegi di amministratore sul server fisico, accessibilità SSH e il tool _htpasswd_. + +Accedere al VPS mediante SSH. + +.Creazione dei volumi (directory) fisici +[source,shell] +---- +# Variabile utile per abbreviare i percorsi +[vps]$ VOLUMES=/var/lib/docker/volumes +# Creazione delle directory fisiche +[vps]$ sudo mkdir -p ${VOLUMES}/manual--hub-registry/data +# Creazione archivio delle credenziali con l'utente iniziale camoroso +[vps]$ sudo htpasswd -c -B ${VOLUMES}/manual--hub-registry/registry.password camoroso +---- + +NOTE: Per ragioni storiche, il vero host name del VPS è impostato col nome di dominio _www.portale-stac.it_. In questa sede, nelle sessioni CLI si è preferito indicare il VPS con il nome _vps_ per meglio identificare l'host su cui si deve operare. + +IMPORTANT: Nel comando _htpasswd_ l'opzione `-c` è richiesta solo per la creazione del file, mentre `-B` è necessario per selezionare la modalità _bcrypt_ riconosciuta dal programma _registry_. + +##### Creazione del reverse proxy +Per consetire l'accesso al registry da Internet, l'implementazione del gateway, anche detto reverse proxy, richiede di: + +. Creare un nuovo record di tipo *A* nel servizio DNS per impostare il puntamento del nome _hub.paas.portale-stac.it_ all'indirizzo IP del server VPS. +. Ottenere un certificato digtale firmato da una CA pubblica per il nome _hub.paas.portale-stac.it_. +. Configurare un nuovo virtual-host in Apache web server per il gateway vero e proprio. + +Nel caso del dominio _portale-stac.it_ il DNS di riferimento (Aruba) è già configurato per indirizzare l'intero sotto-dominio _paas.portale-stac.it_ all'indirizzo IP del VPS. + +Per quanto riguarda il certificato digitale, il web server Apache fa già uso di un certificato _Let's encrypt_ SAN (Subject Alternative Names),. Per semplificare le operazioni si effettua una nuova richiesta per lo stesso certificato SAN con l'aggiunta del nome _hub.paas.portale-stac.it_. + +Prima di procedere con il certificato, conviene definire il virtual-host Apache perché nella sua configurazione si specifica il percorso del _DocumentRoot_ utilizzato dal tool di richiesta dei certificati _Let's encrypt_. + +.Configurazione del virtual-host hub.paas.portale-stac.it +[source,apache] +---- +include::vhost_hub.conf[] +---- + +Usando privilegi di amministratore (root o sudo), copiare la configurazione del virtual-host nel file: + + /etc/httpd/conf.d/vhost_hub.paas.conf + +La configurazione del virtual-host potrebbe eventualmente essere completata con ulteriori parametri di _mod_ssl_ per, ad esempio, selezionare i protocolli SSL/TLS supportati e gli algoritmi crittografici ammessi. Ciò però non è necessario perché il tool _certbot_, utilizzato per l'aggiornamento del certificato SAN, estende automaticamente la configurazione con i parametri più appropriati e sicuri (vedi oltre). + +.Preparazione del contesto del virtual-host +[source,shell] +---- +# Directory DocumentRoot +[vps]$ sudo mkdir -p /var/www/vhosts/paas.portale-stac.it/hub +# Directory log +[vps]$ sudo mkdir -p /var/log/httpd/paas.portale-stac.it/hub + +# Riavvio Apache web server +[vps]$ sudo systemctl restart httpd.service + +# Verifica assenza di problemi +[vps]$ sudo systemctl httpd.service +---- + +Per l'estensione del certificato SAN con il nuovo nome si utilizza il tool _certbot_, disponibile nei pacchetti di Fedora. + +.Estensione certificato SAN +[source,shell] +---- +# Elenco abbreviato dei domini (notare puntini sospensivi ...) +[vps]$ sudo certbot -d cloud.portale-stac.it,git.portale-stac.it,captain.paas.portale-stac.it,hub.paas.portale-stac.it,...,www.portale-stac.it +---- + +Il comando _certbot_, dopo aver ottenuto il nuovo certificato, procede con la revisione di tutti i virtual-host presenti in `/etc/httpd/conf.d` aggiungendo o aggiornando le seguenti righe alle loro configurazioni: + +.Integrazione Let's encrypt nei virtual-host Apache +[source,apache] +---- +include::letsencrypt-section.conf[] +---- + + +.Attivazione del virtual-host +[source,shell] +---- +# Riavvio Apache web server +[vps]$ sudo systemctl restart httpd.service + +# Verifica assenza di problemi +[vps]$ sudo systemctl httpd.service +---- + +La configurazione del virtual-host a questo punto è completa ma non è ancora operativo in quanto il server effettivo al quale il gateway punta, _hub.paas.portale-stac.it:5000_, non è ancora stato creato. + +#### Creazione app registry in CapRover +Per la creazione dell'app registry in CapRover, si farà uso della console Captain. + +Accedere alla console puntando il browser all'URL https://captain.paas.portale-stac.it[] e autenticarsi nella form di login. + +##### Creazione app +Nel menù di sinistra cliccare su *Apps* e, quindi, sul bottone *Create A New App* sulla destra, in alto. + +.Porzione GUI per la creazione di una nuova app +image::Screenshot_new-app.png[New App] + +Nella casella di testo *my amazing app* inserire il nome dell'app, in questo caso _hub_, e sotto la casella spuntare il check-box *Has Persistent Data*. + +IMPORTANT: La spunta su "Has Persistent Data" è fondamentale perché, se assente, non si potranno definire i volumi logici nel container. + +.Creazione app *hub* +image::Screenshot_hub-create.png[Creazione hub,380,align=center] + +A questo punto procedere con la creazione cliccando sul bottone *Create New App*. + +Dopo la creazione, l'app _hub_ compare nell'elenco delle app dell'istanza CapRover. + +.Selezione app *hub* per la configurazione +image::Screenshot_app-list.png[App list] + +Cliccare sul nome [blue]_hub_ nella colonna *App Name* per accedere alla GUI di configurazione dell'app. + +##### Porta HTTP interna dell'app +Nella prima scheda, *HTTP Settings*, impostare solo il parametro *Container HTTP Port* con il valore 5000: image:Screenshot_container-port.png[Porta HTTP,220]. + +##### Variabili d'ambiente +Attivare la scheda *App Config*. Qui si imposterà il maggior numero di parametri richiesti per il registry. + +Definire le variabili d'ambiente anticipate in <> nella sezione "Environment Variables". Per facilitare l'inserimento cliccare sul commutatore "Bulk Edit" che attiverà l'inserimento testuale. Copiare le variabili seguenti nell'editor appena attivato. + +.Variabili del container +[source] +---- +REGISTRY_AUTH=htpasswd +REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm +REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password +REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data +---- + +A propria convenienza, dopo l'inserimento disattivare l'editor cliccando nuovamente sul commutatore *Bulk Edit*. + +.Variabili d'ambiente +image::Screenshot_env-vars.png[Env-Vars] + +##### Port mapping +Definizione della mappatura fra la porta interna 5000 impostanta nella sezione HTTP e quella esterna, anch'essa di valore 5000: + +.Port mapping +image::Screenshot_port-map.png[Port mapping] + +##### Definizione volumi +Nella sezione *Persistent Directory* aggiungere due directory cliccando sul bottone *Add Persistent Directory*: + +.Persistent directory +image::Screenshot_persist-dirs.png[Persistent directory] + +Attivare la corrispondenza esplicita fra i volumi logici e le directory fisiche cliccando sui bottoni *Set specific host path* e impostare le caselle di testo con i valori indicati in <>. + +.Corrispondenza volumi/directory +---- +/auth --> /var/lib/docker/volumes/manual--hub-registry +/data --> /var/lib/docker/volumes/manual--hub-registry/data +---- + +Il risultato dovrà apparire come in figura. + +.Associazioni volumi/directory +image::Screenshot_volumes.png[Volumi] + +##### Deploy immagine registry +Infine si deve indicare l'immagine _registry_ di Docker Hub in cui è presente l'applicazione che implementa effettivamente il servizio. + +La scheda *Deployment* consente diversi metodi per il deploy di un'applicazione, sia partendo dai sorgenti che da immagini già pronte all'uso. Per il registry fornito come immagine si possono considerare i metodi dal 4 al 6. + +Nel caso attuale è stato utilizzato il metodo 4, *Method 4: Deploy plain Dockerfile*. In pratica, nella corrispondente casella di testo è stato inserita la sola direttiva _FROM_ del _Dockerfile_ con il testo seguente. + +.Dockerfile +[source,docker] +---- +FROM registry:3 AS registry +---- + +Copiare il testo di sopra nella casella di testo come mostrato in figura. + +.Deploy dell'immagine +image::Screenshot_deploy.png[Deploy] + +Cliccare sul bottone *Deploy Now* per avviare il caricamento dell'immagine e la sua attivazione. + +##### Verifica finale +La procedura di deploy è completa. Verificare il funzionamento del registry effettuando il login e provare a caricarvi un'immagine Docker. + +.Autenticazione per l'accesso al servizio +[source,shell] +---- +[fedoravm]$ docker login -u camoroso https://hub.paas.portale-stac.it +Password: +Login Succeeded +---- + +.Caricamento di un'immagine (già presente) nel registry +[source,shell] +---- +[fedoravm]$ docker push hub.paas.portale-stac.it/kuard-amd64:amo1 +The push refers to repository [hub.paas.portale-stac.it/kuard-amd64] +96844c0866be: Layer already exists +fd2758d7a50e: Layer already exists +amo1: digest: sha256:f8ff90f6715f4708afe556f5b708befeb5f0480c175fc369c2e59202f3374f04 size: 739 +---- + +//// +Add ImagePullSecrets to a service account +https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account +//// + +//// +In questa sezione però si descrivono i passaggi per ottenere lo stesso risultato attraverso l'interfaccia a riga di comando _caprover_. Per l'installazione di _caprover_ è necessario il tool _npm_ disponibile nei pacchetti Fedora. + +.Installazione della CLI *caprover* +[source,shell] +---- +$ npm install -g caprover +---- + +.Accesso all'istanza CapRover +[source,shell] +---- +$ caprover login -u paas.portale-stac.it + +Login to a CapRover machine... + +? CapRover machine password: [hidden] +? CapRover machine name, with whom the login credentials are stored locally: captain-01 <1> + +Logged in successfully. +Authorization token is now saved as captain-01 at https://captain.paas.portale-stac.it. + +# Verifica +$ caprover list + + +Logged in CapRover Machines: + +>> captain-01 at https://captain.paas.portale-stac.it +---- + <1> Il nome della macchina in cui sono registrate le credenziali presumibilmente è stato fissato automaticamente in fase di attivazione del servizio CapRover. +//// + + +''' +*Celestino Amoroso* + +*celestino . amoroso @ gmail . com* + + +image::https://gravatar.com/avatar/88d204d546890e5d89073fb1cec29fe9.png?size=48[] +