Implementa applicazioni in più cluster Kubernetes cù Helm

Cumu Dailymotion usa Kubernetes: Implementazione di l'applicazioni

Noi di Dailymotion hà cuminciatu à aduprà Kubernetes in a produzzione 3 anni fà. Ma implementà applicazioni in più clusters hè divertente, cusì in l'ultimi anni avemu pruvatu à migliurà i nostri strumenti è flussi di travagliu.

Induve hà principiatu

Quì copreremu cumu implementemu e nostre applicazioni in parechje cluster Kubernetes in u mondu.

Per implementà parechji oggetti Kubernetes à una volta, usemu Helm, è tutti i nostri charts sò guardati in un repository git. Per implementà una pila d'applicazioni cumpleta da parechji servizii, usemu u chjamatu schema di riassuntu. Essenzialmente, questu hè un graficu chì dichjara dipendenze è permette di inizializza l'API è i so servizii cù un cumandamentu.

Avemu ancu scrittu un picculu script Python nantu à Helm per fà cuntrolli, creà grafici, aghjunghje sicreti è implementà applicazioni. Tutti questi travaglii sò realizati nantu à una piattaforma CI cintrali utilizendu una maghjina docker.

Andemu à u puntu.

Nota. Mentre leghjite questu, u primu candidatu di liberazione per Helm 3 hè digià statu annunziatu. A versione principale cuntene una mansa di migliure per affruntà alcuni di i prublemi chì avemu scontru in u passatu.

Flussu di travagliu di sviluppu di carta

Avemu aduprà branching per l'applicazioni, è avemu decisu di applicà u listessu approcciu à i charts.

  • Branca dev utilizatu per creà grafici chì saranu pruvati in clusters di sviluppu.
  • Quandu una dumanda di pull hè sottumessa à Maestru, sò verificati in staging.
  • Infine, creemu una dumanda di pull per cummette i cambiamenti à u ramu prod è applicà in a produzzione.

Ogni ambiente hà u so propiu repositoriu privatu chì guarda i nostri charts, è avemu aduprà Chartmuseum cù API assai utili. In questu modu, assicuremu un isolamentu strettu trà l'ambienti è a prova in u mondu reale di i grafici prima di usà in a produzzione.

Repositori di carta in diversi ambienti

Vale a pena nutà chì quandu i sviluppatori spinghjanu una filiera di dev, una versione di u so graficu hè automaticamente imbuttata à u dev Chartmuseum. Cusì, tutti i sviluppatori utilizanu u stessu repository dev, è avete bisognu di specificà currettamente a vostra versione di u graficu per ùn aduprà accidentalmente i cambiamenti di l'altru.

Inoltre, u nostru picculu script Python valida l'uggetti Kubernetes contr'à e specificazioni Kubernetes OpenAPI utilizendu Kubeval, prima di pubblicà nantu à Chartmusem.

Descrizzione generale di u flussu di travagliu di sviluppu di carta

  1. Configurazione di e attività di pipeline secondu e specificazioni gazr.io per u cuntrollu di qualità (lint, unit-test).
  2. Spingendu una maghjina docker cù strumenti Python chì implementanu e nostre applicazioni.
  3. Configurazione di l'ambiente per nome di filiale.
  4. Validazione di i fugliali yaml di Kubernetes cù Kubeval.
  5. Aumenta automaticamente a versione di un graficu è i so grafici parenti (carti chì dipendenu da u graficu chì hè cambiatu).
  6. Invia una carta à un Chartmuseum chì currisponde à u so ambiente

Gestisce e differenze trà i clusters

Federazione di i Clusters

Ci era un tempu quandu avemu usatu Federazione di clusters Kubernetes, induve l'uggetti Kubernetes puderanu esse dichjarati da un unicu endpoint API. Ma i prublemi sò ghjunti. Per esempiu, certi ogetti Kubernetes ùn puderanu micca esse creati in l'endpoint di a federazione, rendendu difficiuli di mantene l'uggetti federati è altri oggetti per i clusters individuali.

Per risolve u prublema, avemu cuminciatu à gestisce i clusters indipindentamente, chì simplificà assai u prucessu (avemu utilizatu a prima versione di federazione; qualcosa puderia avè cambiatu in a seconda).

piattaforma geo-distribuita

A nostra piattaforma hè attualmente distribuita in 6 regioni - 3 in u locu è 3 in u nuvulu.


Impiegazione distribuita

Valori Global Helm

4 valori globale Helm vi permettenu di identificà e differenze trà i clusters. Tutti i nostri charts anu valori minimi predeterminati.

global:
  cloud: True
  env: staging
  region: us-central1
  clusterName: staging-us-central1

I valori globali

Questi valori aiutanu à definisce u cuntestu per e nostre applicazioni è sò usati per diversi scopi: monitoraghju, traccia, logging, fà chjamate esterne, scaling, etc.

  • "cloud": Avemu una piattaforma hibrida Kubernetes. Per esempiu, a nostra API hè implementata in zoni GCP è in i nostri centri di dati.
  • "env": Certi valori ponu cambià per ambienti chì ùn sò micca produzzione. Per esempiu, definizione di risorse è cunfigurazioni autoscaling.
  • "regione": Questa informazione aiuta à determinà u locu di u cluster è pò esse aduprata per determinà l'endpoint vicini per i servizii esterni.
  • "clusterName": se è quandu vulemu definisce un valore per un cluster individuale.

Eccu un esempiu specificu:

{{/* Returns Horizontal Pod Autoscaler replicas for GraphQL*/}}
{{- define "graphql.hpaReplicas" -}}
{{- if eq .Values.global.env "prod" }}
{{- if eq .Values.global.region "europe-west1" }}
minReplicas: 40
{{- else }}
minReplicas: 150
{{- end }}
maxReplicas: 1400
{{- else }}
minReplicas: 4
maxReplicas: 20
{{- end }}
{{- end -}}

Esempiu di mudellu Helm

Questa logica hè definita in un mudellu d'aiutu per evità l'ingaghjamentu di Kubernetes YAML.

L'annunziu di l'applicazione

I nostri strumenti di implementazione sò basati nantu à parechji fugliali YAML. Quì sottu hè un esempiu di cumu dichjarà un serviziu è a so topologia di scala (number of replicas) in un cluster.

releases:
  - foo.world

foo.world:                # Release name
  services:               # List of dailymotion's apps/projects
    foobar:
      chart_name: foo-foobar
      repo: [email protected]:dailymotion/foobar
      contexts:
        prod-europe-west1:
          deployments:
            - name: foo-bar-baz
              replicas: 18
            - name: another-deployment
              replicas: 3

Definizione di serviziu

Questu hè un schema di tutti i passi chì definiscenu u nostru flussu di travagliu di implementazione. L'ultimu passu implementa l'applicazione à parechji gruppi di travagliadori simultaneamente.


Passi di implementazione di Jenkins

E sicreti ?

In quantu à a sicurità, tracciamu tutti i sicreti da diversi lochi è i guardemu in una volta unica Vault in Parigi.

I nostri strumenti di implementazione estrae valori secreti da Vault è, quandu vene u tempu di implementazione, inseriscili in Helm.

Per fà questu, avemu definitu una mappatura trà i sicreti in Vault è i sicreti chì e nostre applicazioni necessitanu:

secrets:                                                                                                                                                                                                        
     - secret_id: "stack1-app1-password"                                                                                                                                                                                  
       contexts:                                                                                                                                                                                                   
         - name: "default"                                                                                                                                                                                         
           vaultPath: "/kv/dev/stack1/app1/test"                                                                                                                                                               
           vaultKey: "password"                                                                                                                                                                                    
         - name: "cluster1"                                                                                                                                                                           
           vaultPath: "/kv/dev/stack1/app1/test"                                                                                                                                                               
           vaultKey: "password"

  • Avemu definitu e regule generale da seguità quandu si registra i secreti in Vault.
  • Se u sicretu s'applica à un cuntestu specificu o cluster, avete bisognu di aghjunghje una voce specifica. (Qui u cuntestu cluster1 hà u so propiu valore per u secret stack-app1-password).
  • Altrimenti u valore hè usatu per difettu.
  • Per ogni articulu in questa lista in U secretu di Kubernetes una coppia chjave-valore hè inserita. Dunque, u mudellu secretu in i nostri charts hè assai simplice.

apiVersion: v1
data:
{{- range $key,$value := .Values.secrets }}
  {{ $key }}: {{ $value | b64enc | quote }}
{{ end }}
kind: Secret
metadata:
  name: "{{ .Chart.Name }}"
  labels:
    chartVersion: "{{ .Chart.Version }}"
    tillerVersion: "{{ .Capabilities.TillerVersion.SemVer }}"
type: Opaque

Prublemi è limitazioni

U travagliu cù parechji repositori

Avà separemu u sviluppu di charts è applicazioni. Questu significa chì i sviluppatori anu da travaglià in dui repositori git: unu per l'applicazione, è unu per definisce a so implementazione à Kubernetes. I repositori 2 git significanu 2 flussi di travagliu, è hè faciule per un novu cunfunditu.

A gestione di charts generalizati hè un fastidiu

Cume avemu digià dettu, i grafici generici sò assai utili per identificà e dipendenze è implementà rapidamente parechje applicazioni. Ma avemu aduprà --reuse-valuesper evità di passà tutti i valori ogni volta chì implementemu una applicazione chì face parte di stu graficu generalizatu.

In un flussu di travagliu cuntinuu di consegna, avemu solu dui valori chì cambianu regularmente: u numeru di repliche è l'etichetta di l'imaghjini (versione). Altri valori più stabili sò cambiati manualmente, è questu hè abbastanza difficiule. Inoltre, un sbagliu in l'implementazione di un graficu generalizatu pò purtà à fallimenti seri, cum'è avemu vistu da a nostra sperienza.

Aghjurnà parechji schedarii di cunfigurazione

Quandu un sviluppatore aghjunghje una nova applicazione, hà da cambià parechji schedari: a dichjarazione di l'applicazione, a lista di i sicreti, aghjunghjendu l'applicazione cum'è una dependenza s'ellu hè inclusu in a carta generalizata.

I permessi di Jenkins sò troppu estesi in Vault

Avà avemu unu AppRole, chì leghje tutti i sicreti da u Vault.

U prucessu di rollback ùn hè micca automatizatu

Per ripiglià, avete bisognu di eseguisce u cumandamentu nantu à parechji clusters, è questu hè pienu di errore. Facemu sta operazione manualmente per assicurà chì l'ID di versione curretta hè specificatu.

Andemu versu GitOps

U nostru scopu

Vulemu rinvià u graficu à u repositoriu di l'applicazione chì implementa.

U flussu di travagliu serà u stessu per u sviluppu. Per esempiu, quandu un ramu hè imbuttatu à maestru, a implementazione serà attivata automaticamente. A principal diferenza trà questu approcciu è u flussu di travagliu attuale seria quellu tuttu serà gestitu in git (l'applicazione stessa è a manera chì hè implementata in Kubernetes).

Ci sò parechji vantaghji:

  • Moltu più chjaru per u sviluppatore. Hè più faciule d'amparà cumu applicà cambiamenti in una carta lucale.
  • A definizione di implementazione di u serviziu pò esse specificata listessu locu cum'è u codice serviziu.
  • Gestisce a rimuzione di charts generalizati. U serviziu hà a so propria liberazione Helm. Questu permetterà di gestisce u ciclu di vita di l'applicazioni (rollback, upgrade) à u livellu più chjucu, per ùn avè micca affettà altri servizii.
  • Beneficii di git per a gestione di u graficu: annullà i cambiamenti, u log di auditu, etc. Se avete bisognu di annullà un cambiamentu di un graficu, pudete fà questu cù git. A implementazione principia automaticamente.
  • Puderete cunsiderà migliurà u vostru flussu di travagliu di sviluppu cù arnesi cum'è Scaffold, cù quale i sviluppatori ponu pruvà cambiamenti in un cuntestu vicinu à a produzzione.

Migrazione in dui passi

I nostri sviluppatori anu utilizatu stu flussu di travagliu dapoi 2 anni, cusì vulemu chì a migrazione sia u più indolore pussibule. Dunque, avemu decisu di aghjunghje un passu intermediu nantu à a strada di u scopu.
U primu stadiu hè simplice:

  • Mantenemu una struttura simili per a stallazione di implementazione di l'applicazioni, ma in un oggettu unicu chjamatu DailymotionRelease.

apiVersion: "v1"
kind: "DailymotionRelease"
metadata:
  name: "app1.ns1"
  environment: "dev"
  branch: "mybranch"
spec:
  slack_channel: "#admin"
  chart_name: "app1"
  scaling:
    - context: "dev-us-central1-0"
      replicas:
        - name: "hermes"
          count: 2
    - context: "dev-europe-west1-0"
      replicas:
        - name: "app1-deploy"
          count: 2
  secrets:
    - secret_id: "app1"
      contexts:
        - name: "default"
          vaultPath: "/kv/dev/ns1/app1/test"
          vaultKey: "password"
        - name: "dev-europe-west1-0"
          vaultPath: "/kv/dev/ns1/app1/test"
          vaultKey: "password"

  • 1 liberazione per applicazione (senza charts generalizati).
  • Grafici in u repository git di l'applicazione.

Avemu parlatu cù tutti i sviluppatori, cusì u prucessu di migrazione hè digià principiatu. U primu stadiu hè sempre cuntrullatu cù a piattaforma CI. Scriveraghju un altru post prestu nantu à a seconda fase: cumu avemu passatu à un flussu di travagliu GitOps purtata. Vi dicu cumu avemu stabilitu tuttu è quale difficultà avemu scontru (repositori multipli, sicreti, etc.). Segui a nutizia.

Quì avemu pruvatu à descriverà u nostru prugressu in u flussu di travagliu di implementazione di l'applicazioni in l'ultimi anni, chì hà purtatu à penseri nantu à l'approcciu GitOps. Ùn avemu micca ghjuntu à l'ughjettu è rendemu nantu à i risultati, ma avà simu cunvinti chì avemu fattu u dirittu quandu avemu decisu di simplificà tuttu è avvicinassi à l'abitudini di i sviluppatori.

Source: www.habr.com

Add a comment