Desplegueu aplicacions a diversos clústers de Kubernetes amb Helm

Com fa servir Dailymotion Kubernetes: desplegament d'aplicacions

A Dailymotion vam començar a utilitzar Kubernetes en producció fa 3 anys. Però desplegar aplicacions en diversos clústers és divertit, així que durant els últims anys hem intentat millorar les nostres eines i fluxos de treball.

On va començar

Aquí parlarem de com implementem les nostres aplicacions a diversos clústers de Kubernetes arreu del món.

Per desplegar diversos objectes de Kubernetes alhora, fem servir Timó, i tots els nostres gràfics s'emmagatzemen en un dipòsit git. Per desplegar una pila d'aplicacions completa des de diversos serveis, utilitzem l'anomenat gràfic de resum. Essencialment, aquest és un gràfic que declara dependències i us permet inicialitzar l'API i els seus serveis amb una ordre.

També vam escriure un petit script de Python a la part superior de Helm per fer comprovacions, crear gràfics, afegir secrets i desplegar aplicacions. Totes aquestes tasques es realitzen en una plataforma central de CI mitjançant una imatge Docker.

Anem al punt.

Nota. Mentre llegiu això, ja s'ha anunciat el primer llançament candidat per a Helm 3. La versió principal conté una sèrie de millores per resoldre alguns dels problemes que hem trobat en el passat.

Flux de treball de desenvolupament de gràfics

Utilitzem la ramificació per a les aplicacions i vam decidir aplicar el mateix enfocament als gràfics.

  • Sucursal dev s'utilitza per crear gràfics que es provaran en clústers de desenvolupament.
  • Quan s'envia una sol·licitud d'extracció a mestre, es comproven a la posada en escena.
  • Finalment, creem una sol·licitud d'extracció per confirmar els canvis a la branca producció i aplicar-los a la producció.

Cada entorn té el seu propi dipòsit privat que emmagatzema els nostres gràfics, i el fem servir Chartmuseum amb API molt útils. D'aquesta manera, garantim un estricte aïllament entre entorns i proves reals dels gràfics abans d'utilitzar-los en producció.

Repositoris de gràfics en diferents entorns

Val la pena assenyalar que quan els desenvolupadors empenyen una branca de desenvolupament, una versió del seu gràfic s'envia automàticament al Museu de les cartes de desenvolupament. Per tant, tots els desenvolupadors utilitzen el mateix dipòsit de desenvolupament i cal que especifiqueu acuradament la vostra versió del gràfic per no utilitzar accidentalment els canvis d'una altra persona.

A més, el nostre petit script de Python valida els objectes de Kubernetes amb les especificacions de Kubernetes OpenAPI utilitzant Kubeval, abans de publicar-los a Chartmusem.

Descripció general del flux de treball de desenvolupament de gràfics

  1. Configuració de tasques de pipeline segons especificació gazr.io per al control de qualitat (pelusa, prova d'unitat).
  2. Empènyer una imatge docker amb eines de Python que despleguen les nostres aplicacions.
  3. Configuració de l'entorn pel nom de la branca.
  4. Validació dels fitxers yaml de Kubernetes mitjançant Kubeval.
  5. Augmenta automàticament la versió d'un gràfic i els seus gràfics primaris (gràfics que depenen del gràfic que es canvia).
  6. Enviar un gràfic a un Chartmuseum que coincideixi amb el seu entorn

Gestió de les diferències entre clústers

Federació de Clústers

Hi va haver un temps en què vam fer servir federació de clústers de Kubernetes, on els objectes de Kubernetes es podrien declarar des d'un únic punt final de l'API. Però van sorgir problemes. Per exemple, alguns objectes de Kubernetes no s'han pogut crear al punt final de la federació, cosa que dificulta el manteniment dels objectes federats i altres objectes per a clústers individuals.

Per resoldre el problema, vam començar a gestionar els clústers de manera independent, la qual cosa va simplificar molt el procés (vam utilitzar la primera versió de federació; alguna cosa podria haver canviat en la segona).

Plataforma geodistribuïda

Actualment, la nostra plataforma es distribueix en 6 regions: 3 localment i 3 al núvol.


Desplegament distribuït

Valors globals de Helm

4 valors globals de Helm us permeten identificar diferències entre clústers. Tots els nostres gràfics tenen valors mínims predeterminats.

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

Valors globals

Aquests valors ajuden a definir el context de les nostres aplicacions i s'utilitzen per a diferents finalitats: seguiment, traça, registre, fer trucades externes, escalar, etc.

  • "cloud": tenim una plataforma híbrida Kubernetes. Per exemple, la nostra API es desplega a les zones GCP i als nostres centres de dades.
  • "env": alguns valors poden canviar per a entorns que no són de producció. Per exemple, definicions de recursos i configuracions d'escala automàtica.
  • "regió": aquesta informació ajuda a determinar la ubicació del clúster i es pot utilitzar per determinar punts finals propers per a serveis externs.
  • "clusterName": si i quan volem definir un valor per a un clúster individual.

Aquí teniu un exemple concret:

{{/* 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 -}}

Exemple de plantilla Helm

Aquesta lògica es defineix en una plantilla d'ajuda per evitar desordenar Kubernetes YAML.

Anunci de sol·licitud

Les nostres eines de desplegament es basen en diversos fitxers YAML. A continuació es mostra un exemple de com declarem un servei i la seva topologia d'escala (nombre de rèpliques) en un clúster.

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

Definició del servei

Aquest és un esquema de tots els passos que defineixen el nostre flux de treball de desplegament. L'últim pas desplega l'aplicació a diversos clústers de treball simultàniament.


Passos de desplegament de Jenkins

Què passa amb els secrets?

Pel que fa a la seguretat, rastregem tots els secrets des de diferents llocs i els emmagatzemem en una volta única Volta a París.

Les nostres eines de desplegament extreuen valors secrets de Vault i, quan arribi el moment de desplegament, els inserim a Helm.

Per fer-ho, hem definit un mapeig entre els secrets de Vault i els secrets que necessiten les nostres aplicacions:

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"

  • Hem definit regles generals a seguir quan enregistrem secrets a Vault.
  • Si el secret s'aplica a un context o clúster específic, heu d'afegir una entrada específica. (Aquí el context cluster1 té el seu propi valor per a la secret stack-app1-password).
  • En cas contrari, s'utilitza el valor per defecte.
  • Per a cada element d'aquesta llista a Secret de Kubernetes s'insereix un parell clau-valor. Per tant, la plantilla secreta dels nostres gràfics és molt senzilla.

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

Problemes i limitacions

Treballant amb diversos repositoris

Ara separem el desenvolupament de gràfics i aplicacions. Això vol dir que els desenvolupadors han de treballar en dos repositoris git: un per a l'aplicació i un altre per definir el seu desplegament a Kubernetes. 2 repositoris git signifiquen 2 fluxos de treball, i és fàcil que un novell es confongui.

Gestionar gràfics generalitzats és una molèstia

Com ja hem dit, els gràfics genèrics són molt útils per identificar dependències i desplegar ràpidament múltiples aplicacions. Però fem servir --reuse-valuesper evitar passar tots els valors cada vegada que despleguem una aplicació que forma part d'aquest gràfic generalitzat.

En un flux de treball de lliurament continu, només tenim dos valors que canvien regularment: el nombre de rèpliques i l'etiqueta de la imatge (versió). Altres valors més estables es canvien manualment, i això és bastant difícil. A més, un error en el desplegament d'un gràfic generalitzat pot conduir a fracassos greus, com hem vist per la nostra pròpia experiència.

Actualització de diversos fitxers de configuració

Quan un desenvolupador afegeix una nova aplicació, ha de canviar diversos fitxers: la declaració de l'aplicació, la llista de secrets, afegint l'aplicació com a dependència si està inclosa en el gràfic generalitzat.

Els permisos de Jenkins estan massa estès a Vault

Ara en tenim un AppRole, que llegeix tots els secrets de la Volta.

El procés de retrocés no està automatitzat

Per retrocedir, heu d'executar l'ordre en diversos clústers, i això està ple d'errors. Realitzem aquesta operació manualment per assegurar-nos que s'especifica l'ID de versió correcta.

Estem avançant cap a GitOps

El nostre objectiu

Volem tornar el gràfic al repositori de l'aplicació que desplega.

El flux de treball serà el mateix que el de desenvolupament. Per exemple, quan s'envia una branca a master, el desplegament s'activarà automàticament. La principal diferència entre aquest enfocament i el flux de treball actual seria aquesta tot es gestionarà a git (l'aplicació en si i la forma en què es desplega a Kubernetes).

Hi ha diversos avantatges:

  • Molt més clar per al desenvolupador. És més fàcil aprendre a aplicar els canvis en un gràfic local.
  • Es pot especificar la definició de desplegament del servei mateix lloc que el codi servei.
  • Gestionar l'eliminació de gràfics generalitzats. El servei tindrà la seva pròpia versió Helm. Això us permetrà gestionar el cicle de vida de l'aplicació (rollback, actualització) al nivell més petit, per no afectar altres serveis.
  • Beneficis de git per a la gestió de gràfics: desfer canvis, registre d'auditoria, etc. Si necessiteu desfer un canvi a un gràfic, podeu fer-ho amb git. El desplegament s'inicia automàticament.
  • Podeu considerar millorar el vostre flux de treball de desenvolupament amb eines com ara Bastida, amb la qual els desenvolupadors poden provar els canvis en un context proper a la producció.

Migració en dos passos

Els nostres desenvolupadors fa 2 anys que utilitzen aquest flux de treball, així que volem que la migració sigui el més indolora possible. Per tant, vam decidir afegir un pas intermedi en el camí cap a l'objectiu.
La primera etapa és senzilla:

  • Mantenim una estructura similar per configurar el desplegament d'aplicacions, però en un únic objecte anomenat 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 versió per aplicació (sense gràfics generalitzats).
  • Gràfics al repositori git de l'aplicació.

Hem parlat amb tots els desenvolupadors, així que el procés de migració ja ha començat. La primera etapa encara es controla mitjançant la plataforma CI. Aviat escriuré una altra publicació sobre la segona fase: com vam passar a un flux de treball de GitOps Flux. Us explicaré com ho hem configurat tot i quines dificultats hem trobat (diversos repositoris, secrets, etc.). Segueix les notícies.

Aquí hem intentat descriure el nostre progrés en el flux de treball de desplegament d'aplicacions durant els darrers anys, cosa que va fer pensar sobre l'enfocament de GitOps. Encara no hem assolit l'objectiu i n'informarem dels resultats, però ara estem convençuts que hem fet el correcte quan hem decidit simplificar-ho tot i apropar-ho als hàbits dels desenvolupadors.

Font: www.habr.com

Afegeix comentari