Come creare un cluster Kubernetes sicuro per impostazione predefinita con una pipeline CI / CD di base su AWS

Scritto da Matthew Sheppard e Donald Carnegie

Kuber-what-es?

Kubernetes (pronunciato "koo-burr-NET-eez") è una piattaforma open source per automatizzare la distribuzione, il ridimensionamento e il funzionamento dei contenitori di applicazioni. I ragazzi fantastici spesso si riferiscono ad esso con (IOHO) non un'ottima abbreviazione “k8s”. Il lavoro di Kubernetes consiste nell'utilizzare nel modo più efficiente la tua infrastruttura, garantendo nel contempo che i tuoi carichi di lavoro containerizzati siano disponibili e possano ridimensionare secondo necessità. Alcune aziende hanno riferito di essere in grado di ridurre i costi dell'infrastruttura cloud tra il 50% e il 70% rispetto alla tradizionale architettura basata su VM.

Contenere (erigere) il tuo successo

Kubernetes è una grande storia di successo per la Cloud Native Computing Foundation e la comunità open-source dietro di essa. Annunciato per la prima volta a metà 2014 come un piccolo progetto guidato da un team di ingegneri di Google, è cresciuto fino a diventare la piattaforma di orchestrazione dei container di fatto e una merce di tutto l'ecosistema del cloud pubblico. Microsoft, Google, Amazon e IBM hanno tutti un'offerta Kubernetes gestita in qualche modo. In termini di collaboratori e velocità, Kubernetes è secondo solo nei progetti open source al kernel Linux. Viene utilizzato su larga scala per molti carichi di lavoro interessanti, dal potenziamento di Pokemon Go all'assicurazione che gli abbonati HBO GO possano trasmettere in streaming senza problemi la stagione 7 di Game of Thrones.

Kubernetes continui

Come utenti e ingegneri delle moderne applicazioni Web, ci aspettiamo che siano disponibili 24 ore al giorno, 7 giorni alla settimana e che siano in grado di implementare nuove versioni di esse più volte al giorno. Kubernetes in sé non è abbastanza per raggiungere questo obiettivo. Garantisce l'esecuzione delle nostre applicazioni in container quando e dove vogliamo e può trovare gli strumenti e le risorse di cui hanno bisogno. Per potenziare pienamente i nostri ingegneri, tuttavia, dobbiamo costruire una pipeline CI / CD attorno a Kubernetes.

GitOps è un termine che è stato coniato da Weaveworks per descrivere l'utilizzo di Git come fonte dichiarativa di verità per lo stato del cluster di Kubernetes. Git diventa il nostro mezzo per tracciare lo stato del sistema e usiamo costrutti all'interno di git come pull request come mezzo per unire lo stato tenuto in git con lo stato dell'infrastruttura cloud. In breve, le richieste di pull approvate comportano modifiche in tempo reale alla produzione. Si tratta di un approccio davvero potente poiché è possibile applicare un flusso di lavoro di codice sorgente comprovato per gestire l'infrastruttura: afferrarlo completamente può liberarci dai processi burocratici di controllo delle modifiche della vecchia scuola che sono complicati, richiedono troppo tempo e privi di responsabilità. Le modifiche apportate sulla tua infrastruttura sono sempre visibili, tracciabili e responsabili al 100%. La storia è memorizzata perennemente nel repository git e il rollback a qualsiasi punto della storia è un gioco da ragazzi.

Perché dovrei usare Kubernetes?

I container sono già un enorme successo nel cloud computing. Nonostante il relativamente breve periodo di tempo in cui sono stati nella nostra cassetta degli attrezzi, sono diventati un punto fermo del cloud computing moderno e sono sfruttati da molte app di nomi familiari. Tuttavia, l'onere di orchestrare, gestire e mantenere i sistemi containerizzati può essere enorme - è qui che entra in gioco Kubernetes. Kubernetes prende tutti i grandi punti di forza dietro la containerizzazione e fornisce una piattaforma per implementarli e gestirli con maggiore facilità.

Kubernetes è un componente abilitante per DevOps; aiuta a implementare le pratiche DevOps chiave e apre la strada alle organizzazioni per implementare DevOps. Ovunque tu lo installi, sia sul tuo laptop, un provider cloud o un data center on-premise, fornisce distribuzioni automatizzate delle tue applicazioni containerizzate con ambienti completamente coerenti. Con Kubernetes, sono passati i tempi della creazione e del collaudo locale, solo per scoprire che la tua applicazione si comporta diversamente negli ambienti di test o di produzione!

YATR? (Ancora un altro tutorial, davvero?)

Esistono molti tutorial su Kubernetes, quindi perché scriverne un altro? Buona domanda! Nel costruire cluster Kubernetes per il nostro divertimento e per i clienti, non abbiamo trovato un tutorial che riunisce tutti i pezzi necessari per impostare un cluster su AWS che potrebbe rendere pronta la produzione. La documentazione è per lo più lì, ma è una caccia al tesoro per rintracciarla e capire come farla funzionare in ogni situazione particolare. Ciò lo rende particolarmente impegnativo per chiunque intraprenda il primo pilot di Kubernetes o faccia un passo avanti da un cluster di minikube locale.

Lo scopo di questo tutorial è di colmare questa lacuna e passare attraverso l'installazione del cluster Kubernetes che:

  • È altamente disponibile: vogliamo assicurarci che i nostri ambienti possano gestire i guasti e che le nostre applicazioni in container continuino a funzionare se alcuni dei nostri nodi falliscono o se una zona di disponibilità AWS subisce un'interruzione. Per raggiungere questo obiettivo, eseguiremo master e nodi Kubernetes su 3 zone di disponibilità AWS.
  • Applica il "principio del privilegio minimo": per impostazione predefinita, tutti i pod devono essere eseguiti in un contesto di sicurezza restrittivo; non dovrebbero avere la possibilità di apportare modifiche al cluster Kubernetes o all'ambiente AWS sottostante. Qualsiasi pod che deve apportare modifiche al cluster Kubernetes deve utilizzare un account di servizio denominato con il ruolo e le politiche appropriati allegati. Se un pod deve effettuare chiamate all'API AWS, le chiamate devono essere mediate per garantire che il pod disponga dell'autorizzazione sufficiente per effettuarle e utilizzare solo credenziali IAM temporanee. Raggiungeremo questo obiettivo utilizzando il controllo degli accessi in base al ruolo (RBAC) di Kubernetes per garantire che per impostazione predefinita i pod vengano eseguiti senza possibilità di modificare la configurazione del cluster. Laddove specifici servizi del cluster necessitano di autorizzazioni, creeremo un account di servizio specifico e lo assoceremo a un ambito di autorizzazione richiesto (ovvero, a livello di cluster o in un solo spazio dei nomi) e garantiremo le autorizzazioni necessarie a tale account di servizio. L'accesso all'API AWS verrà mediato tramite kube2iam; tutto il traffico dai pod destinati all'API AWS verrà reindirizzato a kube2iam. Sulla base delle annotazioni nelle configurazioni del pod, kube2iam effettuerà una chiamata all'API AWS per recuperare le credenziali temporanee corrispondenti al ruolo specificato nell'annotazione e restituirle al chiamante. Tutte le altre chiamate API AWS verranno sottoposte a proxy tramite kube2iam per garantire che venga applicato il principio del privilegio minimo e che la politica non possa essere ignorata.
  • Si integra con Route53 e Classic Load Balancer: quando distribuiamo un'applicazione, vogliamo la possibilità di dichiarare nella configurazione come è resa disponibile al mondo e dove può essere trovata, e averla automatizzata per noi. Kubernetes eseguirà automaticamente il provisioning di un bilanciamento del carico classico a un'applicazione e un DNS esterno ci consente di assegnargli un nome di dominio completo (FQDN), il tutto attraverso l'infrastruttura come codice.
  • Presenta una pipeline di base CI / CD: vogliamo automatizzare il modo in cui apportiamo modifiche al cluster e il modo in cui implementiamo / aggiorniamo le applicazioni. I file di configurazione che specificano la nostra configurazione del cluster verranno assegnati a un repository Git e la pipeline CI / CD li applicherà al cluster. Per raggiungere questo obiettivo, utilizzeremo Travis-CI per applicare la configurazione che viene impegnata nella nostra filiale principale al cluster Kubernetes. Questo è un primo passo nella direzione di GitOps, tuttavia non ci offre una funzionalità GitOps completa.

Alla fine del tutorial, finiremo con un cluster Kubernetes che assomiglia a questo:

Il nostro cluster Kubernetes dello stato finale

Prima di iniziare

Supponiamo che tu abbia già una certa familiarità con Kubernetes. Se sei nuovo di zecca su Kubernetes, ti consigliamo di leggere il tutorial di Kubernetes Basics e familiarizzare con i concetti chiave.

Per costruire il nostro cluster, dobbiamo assicurarci di avere i seguenti strumenti installati:

  • kubectl
    kubectl (Kubernetes Control) è uno strumento da riga di comando per interagire con un cluster Kubernetes, in esecuzione localmente sul tuo computer (usando minikube) o nel cloud.
  • Kops
    Il progetto Kubernetes Operations (kops) fornisce strumenti per la creazione e il funzionamento di cluster Kubernetes nel cloud. Attualmente supporta Google Cloud e AWS (con altri provider in versione beta). In questo tutorial useremo kops per creare e gestire il nostro cluster.
  • Terraform
    Terraform è uno strumento di infrastruttura come codice (IAC) che consente agli utenti di definire l'infrastruttura in un linguaggio di configurazione di alto livello che può quindi essere utilizzato per costruire infrastrutture in un fornitore di servizi come AWS o Google Cloud Platform. Utilizzeremo Terraform per creare i nostri prerequisiti per kops e per modificare le norme IAM create da kops.
  • CLI AWS
    AWS CLI è uno strumento da riga di comando per interagire con AWS. Ciò è richiesto da Kops & Terraform per eseguire operazioni su AWS.

Le istruzioni di installazione sono disponibili ai link forniti.

Questo tutorial è stato creato usando Kubernetes v1.8 e kops v1.8.1.

Stiamo eseguendo Mac OS X con Homebrew, quindi tutto ciò che dobbiamo fare è eseguire i seguenti comandi per installarli:

$ brew update
$ brew installa kubectl
$ brew install kops
$ brew installa python3
$ easy_install pip
$ pip install awscli - upgrade - utente
$ export PATH = ~ / .local / bin: $ PATH
$ brew installa terraform

Creare il cluster

Passaggio 1: clonare il nostro repository

$ git clone https://github.com/slalom-london/k8s-tutorial

Passaggio 2: configurare un nome di dominio completo che verrà utilizzato per il cluster in Route53

Il cluster Kubernetes che installeremo utilizzerà un nome di dominio completo ospitato in Route53 per esporre gli endpoint di servizio e il piano di controllo API. È possibile registrare un nuovo nome di dominio completo o trasferire un nome di dominio completo esistente. AWS ha un passaggio completo per ciascuna di queste opzioni:

Passaggio 3: creare i prerequisiti necessari per kops

Affinché kops costruisca il cluster, ha bisogno di un archivio S3 per contenere la configurazione del cluster e un account utente IAM a cui siano associati i seguenti criteri:

AmazonEC2FullAccess
AmazonRoute53FullAccess
AmazonS3FullAccess
IAMFullAccess
AmazonVPCFullAccess

prereqs / kops_pre_reqs.tf creerà questo per te. Creerà anche un bucket S3 che verrà utilizzato come archivio remoto per il nostro stato Terraform. Ciò consente a più utenti di lavorare con un set di infrastrutture come codice senza causare conflitti. Dovrai aggiornare il file per sostituire {my_bucket_name} e {my_tf_bucket_name} con il nome del bucket selezionato.

Quindi eseguire i seguenti comandi:

$ cd prereqs
$ terraform init
$ piano terraform
$ terraform si applica

Se accedi al tuo account AWS, ora vedrai un utente IAM kops appena creato, un bucket S3 per l'archivio stato kops e un altro bucket S3 per l'archivio stato Terraform

Passaggio 4: utilizzare kops per alzare in piedi il cluster

Nel passaggio precedente, abbiamo creato un account IAM per kops. Ora dobbiamo configurare il nostro client CLI AWS per utilizzare quell'account. Possiamo prendere l'ID IAM di kops e la chiave segreta dal file che Terraform utilizza per memorizzare lo stato di ciò che ha creato nel passaggio precedente. Apri terraform.tfstate nel tuo editor di testo e cerca la sezione simile alla seguente:

Prendi nota del valore nei campi {iam_id} e {aws_secret_key} ed esegui il comando seguente:

$ aws configure --profile kops
ID chiave di accesso AWS [Nessuno]: {iam_id}
Chiave di accesso segreta AWS [Nessuna]: {aws_secret_key}
Nome regione predefinita [Nessuno]: {your_chosen_aws_region}
Formato di output predefinito [Nessuno]: testo

Quindi dobbiamo impostare un paio di variabili ambientali in modo che kops sappia quale account AWS IAM usare e dove dovrebbe mettere il suo archivio di stato:

$ export AWS_PROFILE = kops
$ export KOPS_STATE_STORE = s3: // {my_bucket_name}

Ora per l'evento principale: usiamo kops per costruire il nostro cluster. Esegui il comando seguente, sostituendo la tua regione AWS, la tua zona DNS e il nome del cluster scelto:

$ kops create cluster --cloud aws \
 --bastion \
 --node-count 3 \
 --node-size t2.medium \
 --master-size t2.medium \
 --zones {your_chosen_aws_region} a, {your_chosen_aws_region} b, {your_chosen_aws_region} c \
 --master-zone {your_chosen_aws_region} a, {your_chosen_aws_region} b, {your_chosen_aws_region} c \
 --dns-zone {your_dns_zone} \
 --topologia privata \
 --networking calico \
 --autorizzazione RBAC \
 --name {your_cluster_name} \
 --out = k8s \
 --target = terraform --yes

Questo comando dice a Kops che vogliamo costruire un cluster che:

  • Userà AWS
  • Ha un nodo principale di dimensioni t2.medium in ciascuna delle zone di disponibilità specificate
  • Ha 3 nodi di lavoro di dimensione t2.medium. kops distribuirà i nodi di lavoro in modo uniforme su ciascuna delle zone di disponibilità
  • Utilizza una topologia di rete privata, il che significa che tutti i nodi hanno indirizzi IP privati ​​e non sono direttamente accessibili da Internet pubblico
  • Utilizza Calico come interfaccia di rete del contenitore in sostituzione di kubenet come risultato dei requisiti della topologia di rete privata
  • Utilizza RBAC per le autorizzazioni di accesso a Kubernetes
  • Viene descritto in un file di configurazione Terraform da scrivere nella directory specificata da --out

kops genera un set di file di configurazione Terraform in una directory k8s appena creata che può essere applicata per creare il cluster. Prima di costruire il nostro cluster, vogliamo aggiungere un file di configurazione per dire a Terraform di mantenere il suo archivio di stato sul bucket S3 che abbiamo appena creato.

$ cd k8s
$ terraform init
$ piano terraform
$ terraform si applica

Ci vorranno tra 10 e 15 minuti affinché il cluster diventi disponibile. È possibile verificare lo stato del cluster eseguendo il comando seguente:

$ kops convalida il cluster

Al termine della creazione del cluster, dovresti vedere un output come questo:

Utilizzo del cluster dal contesto kubectl: cluster.zigzag-london.com
Convalida del cluster cluster.zigzag-london.com
GRUPPI DI ISTANZA
NOME RUOLO MACHINETYPE MIN MAX SUBNETS
bastioni Bastione t2.micro 1 1 utility-eu-west-1a, utility-eu-west-1b, utility-eu-west-1c
master-eu-west-1a Master t2.medium 1 1 eu-west-1a
master-eu-west-1b Master t2.medium 1 1 eu-west-1b
master-eu-west-1c Master t2.medium 1 1 eu-west-1c
nodi Nodo t2.medium 3 3 eu-ovest-1a, eu-ovest-1b, eu-ovest-1c
STATO DEL NODO
NOME RUOLO PRONTO
ip-172-20-107-234.eu-west-1.compute.internal master Vero
ip-172-20-124-39.eu-west-1.compute.inode node True
ip-172-20-44-152.eu-west-1.compute.internal master Vero
ip-172-20-60-188.eu-west-1.compute.inode node True
ip-172-20-79-79.eu-west-1.compute.internal master Vero
ip-172-20-87-125.eu-west-1.compute.inode node True
Il cluster cluster.zigzag-london.com è pronto

In piedi in un ambiente CI / CD

Per implementare GitOps, abbiamo bisogno di un ambiente CI / CD per monitorare il nostro repository ed eseguire gli aggiornamenti. Per questa esercitazione configureremo il nostro ambiente CI / CD per eseguire le fasi di distribuzione su ogni push nel ramo principale del nostro repository. Lo stiamo facendo ai fini della convenienza della dimostrazione; consentire agli sviluppatori di farlo è sicuramente una cattiva pratica. In un progetto di vita reale raccomandiamo una strategia di diramazione delle caratteristiche con una revisione del codice e una fase di approvazione del lead di sviluppo.

Per questa esercitazione, utilizzeremo TravisCI, un servizio CI basato su cloud. TravisCI è gratuito a condizione che:

  • Ospiti il ​​tuo repository in Github
  • Il repository è accessibile pubblicamente

Passaggio 1: Configura repository Account e clone

  • Vai a GitHub e registrati \ accedi
  • Crea un nuovo repository vuoto e chiamalo "k8s-ci"
  • Clona questo repository sul tuo computer locale:
$ git clone 
  • Passare a TravisCI e registrarsi utilizzando il proprio account GitHub. Passa al tuo profilo utente facendo clic sul tuo nome in alto a destra.
  • Fare clic sul dispositivo di scorrimento sul repository GitHub per abilitare TravisCI per questo repository.

Passaggio 2: trigger di installazione

Mentre pratichiamo GitOps, vogliamo implementare solo una richiesta pull approvata. Possiamo configurarlo in Travis facendo clic su Altre opzioni → Impostazioni.

  • Assicurati che "crea rami spinti" sia attivato
  • Assicurati che "crea richieste pull pull" sia attivato

Travis ottiene la stragrande maggioranza delle sue istruzioni da un file yaml memorizzato nel repository. Crea un file vuoto chiamato .travis.yml nella radice del tuo repository e possiamo iniziare a configurarlo in base a .travis.yml nel nostro repository:

  • Riga 1: specifica che vogliamo solo eseguire una build sul ramo principale. In un ambiente reale, verremmo probabilmente implementati anche sulla spinta di un ramo, ma in un ambiente di test rispetto a un ambiente di produzione. Un modo per farlo è usare le variabili di ambiente per applicare la logica condizionale allo script deploy, ma questo non rientra nell'ambito di questo post.
  • Riga 4: specifica che sono necessarie le autorizzazioni di root utilizzando sudo per installare le nostre dipendenze
  • Riga 5: questo è l'inizio del blocco in cui impostiamo le autorizzazioni su ciascuno dei nostri script in modo che siano eseguibili.
  • Riga 10: questo è l'inizio del blocco in cui specifichiamo gli script che devono essere eseguiti per primi al fine di configurare l'ambiente CI prima di poter eseguire gli script che eseguono la distribuzione effettiva.
  • Riga 13: questo è l'inizio del blocco in cui specifichiamo gli script che verranno eseguiti per eseguire le attività di distribuzione.

Passaggio 3: gestire i segreti

Non vogliamo mantenere i nostri segreti AWS in un repository pubblico in chiaro; questa sarebbe una pratica di sicurezza delle informazioni estremamente negativa. Praticamente, Travis fornisce uno strumento CLI che può essere utilizzato per memorizzare i tuoi segreti da iniettare al momento della creazione. Travis genera una nuova coppia di chiavi pubblica \ privata per ogni nuovo account e questi segreti verranno crittografati usando quella coppia di chiavi e iniettati come variabili di ambiente ogni volta che viene eseguita la compilazione. Per configurarlo, esegui i seguenti comandi nella radice del tuo repository e accedi usando i dettagli richiesti:

$ sudo gem installa travis
$ travis login --org

Esistono due script precaricati nella directory build-scripts del nostro repository pronti per l'inserimento dei tuoi segreti. Copia la directory build_scripts dalla tua copia locale del nostro repository k8s-tutorial nel tuo repository k8s-ci e aggiornali come segue:

  • large-secrets.txt: aggiungi le tue chiavi di accesso a Kubernetes. Questi possono essere trovati in ~ / .kube / config
  • setup-secrets.sh: aggiungi la tua password Kubernetes (trovata di nuovo in ~ / .kube / config) e le chiavi di accesso AWS da ~ / .aws / credentials

Quindi, dalla radice del tuo repository, esegui lo script setup-secrets.sh usando il seguente comando:

$ chmod 755 build-scripts / setup-secrets.sh
$ ./build-scripts/setup-secrets.sh

Prendi nota del comando openssl che lo script setup-secrets.sh restituisce per dopo, poiché avremo bisogno di questo per decrittografare i segreti.

Questo script crittograferà i tuoi segreti usando Travis e aggiornerà il tuo file .travis.yml. Conferma i segreti crittografati nel tuo repository:

$ git aggiungi build-scripts / large-secrets.txt.enc .travis.yml
$ git commit -m "Commettere segreti criptati"

Ora i tuoi segreti sono protetti in Travis, ti consigliamo vivamente di rimuoverli da tutti i file e gli script. Può essere super facile commettere accidentalmente segreti per il controllo del codice sorgente, ei tuoi autori sono entrambi colpevoli di questo peccato! Per catturare qualsiasi commit accidentale di segreti, usiamo git-secrets. Puoi configurarlo usando i seguenti passi:

$ brew installa git-secrets
$ git-secrets --install

Passaggio 4: installare le dipendenze

Poiché TravisCI esegue ogni build in un contenitore Docker pulito, è necessario installare le dipendenze ogni volta. Queste dipendenze sono le stesse descritte nella sezione "Prima di iniziare" di questo post. Crea un file chiamato install-dependencies.sh nella cartella build-scripts e incolla la seguente configurazione:

Ora esegui il commit di questo file nel tuo repository:

$ git aggiungi install-dependencies.sh
$ git commit -m "Aggiunta di script per installare dipendenze"

Passaggio 5: iniettare i nostri segreti

Ora abbiamo bisogno di uno script per impostare i nostri segreti nel contenitore Docker in cui eseguiremo i nostri passaggi di creazione. Crea un file chiamato inject-secrets.sh nella cartella build-scripts. Incolla lo script seguente e aggiornalo come segue:

  • Sostituisci {l'URL del tuo cluster qui} con l'URL del tuo cluster Kubernetes
  • Sostituisci il comando OpenSSL di cui abbiamo preso nota nel passaggio 3 di questa sezione con {Il tuo comando openssl dalla fase di crittografia dei segreti qui} aggiungendo ./build-scripts/ prima di large-secrets.txt.enc
  • Sostituisci {your-aws-region} con la regione AWS che stai utilizzando

Questo script trarrà i nostri segreti dall'ambiente Travis, li decifrerà e li inietterà nei file di configurazione pertinenti.

Noterai nello script sopra che si riferisce a un file nella directory build-scripts chiamato kubeconfig - dovremo creare anche questo. Incollare i contenuti di seguito, scambiando la variabile {URL del cluster qui} con l'URL del cluster Kubernetes.

Conferma entrambi questi file nel tuo repository:

$ git aggiungi inject-secrets.sh kubeconfig
$ git commit -m "Aggiunta di script per iniettare segreti e file kubeconfig"

Passaggio 6: installazione dell'ambiente

Prima di essere pronti a distribuire le applicazioni, dobbiamo preparare il cluster distribuendo la configurazione per kube2iam e external-dns. La configurazione per ciascuno di questi strumenti deve essere applicata in un ordine prestabilito:

  • Applicare la configurazione Terraform per creare un nuovo ruolo IAM AWS (e la politica richiesta concede a quel ruolo) e una relazione di fiducia con il ruolo IAM AWS in cui i nodi vengono eseguiti. La relazione di trust consente a un nodo di assumere il nuovo ruolo IAM.
  • Applicare la configurazione RBAC di Kubernetes per creare un account di servizio, associarlo a un ambito di autorizzazione richiesto e concedere le autorizzazioni necessarie a tale account di servizio. Questo account di servizio viene quindi specificato come parte della configurazione dei pod che forniscono ciascuno dei servizi specifici.
  • Applicare le configurazioni Kubernetes per distribuire i servizi. A seconda del servizio distribuito, potrebbe trattarsi di un Kubernetes Deployment o DaemonSet.

Costruiremo il nostro script di distribuzione in modo che il cluster sia sempre configurato per primo.

Copia le cartelle contenenti i modelli per external-dns e kube2iam dal nostro repository al tuo repository.

Innanzitutto, creeremo uno script che applicherà la nostra configurazione Terraform. Crea un file chiamato deploy-terraform.sh nella directory build-scripts e aggiungi il seguente codice:

Questo script attraverserà la struttura delle directory nel nostro repository e applicherà tutti i file di configurazione Terraform che trova.

(NB: in un ambiente di produzione reale, aggiungeremmo controlli nella nostra pipeline CI per garantire che Terraform non sia usato in modo dannoso)

Commettilo nel tuo repository:

$ git add deploy-terraform.sh
$ git commit -m "Aggiunta di script di distribuzione Terraform"

Ora siamo pronti per aggiornare e impegnare la configurazione Terraform per ciascuno dei nostri 3 servizi nel repository:

  • Aggiorna external_dns / pod-role-trust-policy.json e sostituisci {your-node-iam-role-arn} con l'AMN IAM per i nodi Kubernetes nel tuo cluster. Questo può essere trovato eseguendo il seguente comando:
$ aws iam lista-ruoli | nodo grep
  • Aggiorna external_dns / main.tf per sostituire {your-aws-region} con la regione AWS in cui stai lavorando e {your-tf-bucket} con il nome del bucket che hai scelto di contenere l'archivio di stato Terraform.

Conferma la configurazione del servizio nel tuo repository:

$ git add external_dns / pod-role-trust-policy.json external_dns / external-dns-iam-setup.tf external_dns / external-dns-role-rights.json external_dns / main.tf
$ git commit -m "Aggiunta della configurazione del servizio Terraform del cluster"

Travis è configurato per applicare la configurazione di ogni push al master, quindi se eseguiamo un push ora:

$ git push

Dovremmo essere in grado di vedere tutta la nostra configurazione Terraform applicata al nostro account AWS nel job log.

Ora abbiamo creato tutti i ruoli IAM e le relazioni di fiducia necessarie per il nostro ambiente Kubernetes.

Successivamente, abbiamo bisogno di uno script per applicare le nostre configurazioni Kubernetes per i prerequisiti dell'ambiente. Per completare questo passaggio dovrai copiare e aggiornare i seguenti file dal nostro repository nel tuo repository:

  • external_dns / external_dns.yaml: sostituisci {your-dns-zone} con la zona DNS che stai utilizzando, {your-identifier} con qualcosa che differenzierà i record DNS che la produzione di external-dns (es. il tuo nome) e {your -external-dns-iam-role-arn} con IAM ARN per il ruolo che è stato creato quando è stata applicata la configurazione Terraform. Questo può essere trovato eseguendo il seguente comando:
$ aws iam get-role --role-name external_dns_pod_role
  • kube2iam e rbac /: nessun aggiornamento richiesto

Questi aggiornamenti specificano quale ruolo IAM deve assumere ciascuno dei pod quando devono accedere all'API AWS.

Ora esegui il commit di questi file nel repository:

$ git add external_dns / external_dns.yaml rbac / kube2iam /
$ git commit -m "Aggiunta della configurazione di k8s di external-dns"

Ora inizieremo a creare il nostro script di distribuzione per i nostri servizi Kubernetes. Crea un file chiamato deploy-k8s.sh nella cartella build-scripts. Inizia il file con un'intestazione come questa:

Quindi, aggiungere i passaggi seguenti che distribuiscono la configurazione RBAC di Kubernetes al cluster:

Questi passaggi sono necessari perché il servizio dns esterno richiede i diritti API Kubernetes per funzionare e fornire il proprio servizio al cluster. Come promemoria, RBAC garantisce che i pod non abbiano accesso all'API Kubernetes per impostazione predefinita. Ciò è in linea con il "principio del privilegio minimo" e impedisce ai pod di modificare le impostazioni del cluster se vengono compromessi per qualsiasi motivo.

Per fare in modo che TravisCI applichi queste modifiche, è necessario aggiungere un ulteriore passaggio al nostro .travis.yml per eseguire deploy-k8s.sh. Aggiungi quanto segue alla sezione before_install:

- chmod + x ./build-scripts/deploy-k8s.sh

E quanto segue nello script: sezione:

- "./build-scripts/deploy-k8s.sh"

Ora commetti deploy-k8s.sh, .travis.yml e invia il tuo repository al master e assicurati che non ci siano errori nel registro di build di Travis:

$ git aggiungi build-scripts / deploy-k8s.sh .travis.yml
$ git commit -m "Aggiunta della configurazione di Travis alla distribuzione della configurazione di k8s"
$ git push

Ora che abbiamo aggiunto la configurazione Terraform e RBAC alla nostra pipeline CI / CD, aggiungiamo i passaggi per distribuire kube2iam al nostro script deploy-k8s.sh:

kube2iam viene distribuito per primo in quanto external-dns effettuerà chiamate all'API AWS utilizzando kube2iam come broker.

Ora invia il tuo repository al master e assicurati che non ci siano errori nel registro di build:

$ git aggiungi build-scripts / deploy-k8s.sh
$ git commit -m "Aggiornamento della configurazione di Travis per distribuire la configurazione di k8s"
$ git push

Ora, controlliamo sul nostro cluster per assicurarci che tutti i servizi siano stati distribuiti correttamente. external-dns è una distribuzione, quindi possiamo eseguire il seguente comando per ottenere il suo stato:

$ kubectl get deployments --namespace = kube-system

Se tutto è stato distribuito correttamente, dovremmo vedere qualcosa di simile:

NOME DESIDERATO CORRENTE AGGIORNAMENTO DISPONIBILE
controllori calico-kube 1 1 1 1 1h
calico-policy-controller 0 0 0 0 1h
dns-controller 1 1 1 1 1h
external-dns 1 1 1 1 1m
kube-dns 2 2 2 2 1h
kube-dns-autoscaler 1 1 1 1 1h

kube2iam è distribuito come DaemonSet poiché deve essere in esecuzione su tutti i nodi per mediare le chiamate all'API AWS. Eseguiamo il seguente comando per ottenere il suo stato:

$ kubectl get ds --namespace = kube-system

Se tutto va bene, dovremmo vedere qualcosa di simile:

NOME DESIDERATO CORRENTE PRONTO AGGIORNAMENTO DISPONIBILE ETÀ NODO-SELETTORE
nodo calico 6 6 6 6 6  1h
kube2iam 3 3 3 3 3  7m

Passaggio 7: distribuire un'applicazione di prova

Ora è il momento di raccogliere i benefici del duro lavoro di impostazione del nostro cluster e vedere la potenza del nostro flusso di lavoro e dell'infrastruttura come codice per distribuire facilmente un'applicazione di prova!

Innanzitutto, è necessario aggiungere un passaggio di distribuzione al nostro script deploy-k8s.sh che distribuirà le nostre applicazioni:

Questo passaggio applica al cluster tutti i file di configurazione di Kubernetes nella directory delle app del nostro repository. Commetti questa modifica e spingi verso il master:

$ git aggiungi build-scripts / deploy-k8s.sh
$ git commit -m "Aggiornamento della configurazione di Travis per distribuire la configurazione di k8s per le app"
$ git push

Mentre stiamo iniziando il nostro viaggio verso GitOps, seguiamo un flusso di processo GitOps per la distribuzione di un'applicazione di prova:

  • Creare un ramo locale eseguendo il comando seguente:
$ git checkout -b testapp
  • Crea una cartella sotto le app chiamate nel tuo repository
  • Nella cartella delle app, crea un file chiamato hello_app_deployment.yaml e aggiungi quanto segue:

Questa configurazione ha 2 sezioni:

  1. Distribuzione: specifica i dettagli del contenitore che eseguiremo, la quantità di risorse da fornire, la porta su cui è possibile accedere all'applicazione all'interno del contenitore e il numero di repliche di quell'applicazione che vogliamo eseguire. In questo caso, eseguiremo un semplice contenitore che stampa "Saluti, globo!" E quindi il nome host del contenitore sulla porta 8080. Specificheremo che eseguiremo 3 repliche, una per ciascuno dei nostri nodi del cluster.
  2. Servizio: specifica come deve essere esposta la distribuzione, internamente o esternamente. Nel caso della nostra applicazione di test, la stiamo esponendo internamente sull'IP del cluster sulla porta 80. Specifichiamo anche l'FQDN descrittivo (ad esempio qualcosa come saluations.tuodominio.com) a cui è possibile accedere alla nostra applicazione qui. Dovrai sostituire {il tuo nome di dominio completo qui} con il tuo nome di dominio completo amichevole.

Ora invia questo file al tuo ramo locale e invia il ramo al repository remoto:

$ git aggiungi hello_app_deployment.yaml
$ git commit -m "Aggiunta dell'app di test"
$ git push -u origine testapp

Se accediamo a GitHub, dovremmo ora vedere che abbiamo un nuovo ramo chiamato "testapp":

Vogliamo raccogliere una richiesta pull e unire a master, quindi fare clic su "Confronta e pull richiesta" e seguire il processo per completare questa attività.

Una volta completata la distribuzione, possiamo verificare che la nostra applicazione di test sia stata distribuita correttamente eseguendo i comandi seguenti e controllando un output simile:

$ kubectl ottiene distribuzioni salutations-deploy
NOME DESIDERATO CORRENTE AGGIORNAMENTO DISPONIBILE
salutations-deploy 3 3 3 3 24d
$ kubectl ottiene servizi saluti-servizio
NOME CLUSTER-IP EXTERNAL-IP PORT (S) ETÀ
salutations-service 100.65.66.9 a78b874f74ed0 ... 80: 32439 / TCP 6d

La vera prova, tuttavia, è la connessione alla nostra applicazione utilizzando il nostro FQDN amichevole! Se tutto è stato distribuito correttamente, dovresti vedere qualcosa del genere:

Successo! Se ora aggiorni questa pagina, dovresti vedere il nome host cambiare quando il tuo browser accede all'app in esecuzione su un nodo Kubernetes diverso tramite il Classic Load Balancer.

Sommario

Usando questo tutorial, abbiamo creato un cluster Kubernetes con una buona serie di impostazioni predefinite di sicurezza e quindi avvolto attorno ad esso una semplice pipeline CI / CD. Abbiamo quindi specificato tramite Infrastruttura come codice il modo in cui volevamo distribuire una semplice applicazione containerizzata e utilizzare la nostra pipeline CI / CD e il cluster Kubernetes per distribuirla come definito - automaticamente.

Questa è solo una semplice illustrazione dei ricchi vantaggi che Kubernetes può apportare ai tuoi sviluppatori e alle tue capacità DevOps se incluso come parte della tua toolchain!