Distribution av applikationer över flera Kubernetes-kluster med Helm

Hur Dailymotion anvÀnder Kubernetes: distribution av applikationer

Vi pÄ Dailymotion började anvÀnda Kubernetes i produktion för tre Är sedan. Men att distribuera applikationer pÄ flera kluster Àr en utmaning, sÄ under de senaste Ären har vi försökt förbÀttra vÄra verktyg och arbetsflöden.

Hur det började

HÀr berÀttar vi hur vi distribuerar vÄra applikationer pÄ flera Kubernetes-kluster runt om i vÀrlden.

För att distribuera flera Kubernetes-objekt samtidigt anvÀnder vi Helm, och alla vÄra chartar lagras i ett enda git-repositorium. För att distribuera en fullstÀndig applikationsstack bestÄende av flera tjÀnster, anvÀnder vi en sÄ kallad övergripande chart. I grund och botten Àr det en chart som deklarerar beroenden och gör det möjligt att initiera API:er och deras tjÀnster med ett enda kommando.

Vi har ocksÄ skrivit ett litet Python-skript ovanpÄ Helm för att göra kontroller, skapa chartar, lÀgga till hemligheter och distribuera applikationer. Alla dessa uppgifter utförs pÄ en central CI-plattform med hjÀlp av en docker-image.

LÄt oss gÄ till kÀrnan.

Obs. NÀr du lÀser detta har den första releasekandidaten för Helm 3 redan tillkÀnnagivits. Huvudversionen innehÄller en hel uppsÀttning förbÀttringar som syftar till att lösa vissa problem vi har stött pÄ tidigare.

Utvecklingsarbetsflöde för chartar

För applikationer anvÀnder vi grenar, och vi bestÀmde oss för att tillÀmpa denna metod Àven pÄ chartarna.

  • Grenen dev anvĂ€nds för att skapa chartar som kommer att testas pĂ„ utvecklingskluster.
  • NĂ€r en pull-begĂ€ran överförs till master, de testas i staging.
  • Slutligen skapar vi en pull-begĂ€ran för att överföra Ă€ndringar till grenen prod och tillĂ€mpa dem i produktion.

Varje miljö har sitt eget privata repositorium som lagrar vÄra chartar, och vi anvÀnder Chartmuseum med mycket anvÀndbara API:er. PÄ sÄ sÀtt sÀkerstÀller vi strikt isolering mellan miljöerna och testning av chartarna under verkliga förhÄllanden innan vi anvÀnder dem i produktion.

Repositorier för chartar i olika miljöer

Det Àr vÀrt att notera att nÀr utvecklare skickar en dev-gren, skickas versionen av deras chart automatiskt till dev Chartmuseum. SÄledes anvÀnder alla utvecklare ett gemensamt dev-repositorium, och det Àr viktigt att noggrant ange sin chart-version för att inte av misstag anvÀnda nÄgon annans Àndringar.

Dessutom kontrollerar vÄrt lilla Python-skript Kubernetes-objekt mot specifikationerna för Kubernetes OpenAPI med hjÀlp av Kubeval, innan de publiceras i Chartmuseum.

Översikt över arbetsflödet för chartutveckling

  1. InstÀllning av pipeline-uppgifter enligt specifikationen gazr.io för kvalitetskontroll (lint, enhetstest).
  2. Skicka dockerbilden med Python-verktyg som distribuerar vÄra applikationer.
  3. Konfigurera miljön efter grenens namn.
  4. Kontrollera Kubernetes yaml-filer med hjÀlp av Kubeval.
  5. Automatisk ökning av versionen pÄ chartet och dess förÀldrarchart (de chart som beror pÄ det Àndrade chartet).
  6. Skicka chartet till Chartmuseum som motsvarar dess miljö

Hantera skillnader mellan kluster

Federering av kluster

Det var en tid nÀr vi anvÀnde federering av Kubernetes-kluster, dÀr man kunde deklarera Kubernetes-objekt frÄn en API-slutpunkt. Men det uppstod problem. Till exempel kunde vissa Kubernetes-objekt inte skapas vid federationsslutpunkten, vilket gjorde det svÄrt att underhÄlla sammanstÀllda objekt och andra objekt för individuella kluster.

För att lösa problemet började vi hantera kluster oberoende, vilket avsevÀrt förenklade processen (vi anvÀnde den första versionen av federation; i den andra kunde nÄgot ha Àndrats).

Geodistribuerad plattform

Nu Ă€r vĂ„r plattform distribuerad över 6 regioner — 3 lokalt och 3 i molnet.


Distribuerad distribution

Globala vÀrden för Helm

4 globala vÀrden för Helm gör det möjligt att definiera skillnader mellan kluster. För alla vÄra chart finns det minimivÀrden som standard.

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

Globala vÀrden

Dessa vÀrden hjÀlper till att definiera kontexten för vÄra applikationer och anvÀnds för olika uppgifter: övervakning, spÄrning, loggning, externa anrop, automatisering och sÄ vidare.

  • "cloud": vi har en hybrid Kubernetes-plattform. Till exempel distribueras vĂ„rt API i GCP-zoner och i vĂ„ra datacenter.
  • "env": vissa vĂ€rden kan variera för icke-produktionsmiljöer. Till exempel resursdefinitioner och konfigurationer för automatisk skalning.
  • "region": denna information hjĂ€lper till att definiera klustrets lĂ€ge och kan anvĂ€ndas för att faststĂ€lla nĂ€rmaste slutpunkter för externa tjĂ€nster.
  • "clusterName": om och nĂ€r vi vill definiera ett vĂ€rde för ett enskilt kluster.

HÀr Àr ett konkret exempel:

{{
/* Returnerar Horizontal Pod Autoscaler-replikat för GraphQL*/}}
{{- definiera "graphql.hpaReplicas" -}}
{{- om eq .Values.global.env "prod" }}
{{- om eq .Values.global.region "europe-west1" }}
minReplicas: 40
{{- annars }}
minReplicas: 150
{{- slut }}
maxReplicas: 1400
{{- annars }}
minReplicas: 4
maxReplicas: 20
{{- slut }}
{{- slut -}}

Exempel pÄ en Helm-mall

Denna logik definieras i en hjÀlpmall för att inte överbelasta Kubernetes YAML.

Applikationsdeklaration

VÄra distributionsverktyg baseras pÄ flera YAML-filer. Nedan Àr ett exempel pÄ hur vi deklarerar en tjÀnst och dess skalningstopologi (antal replikat) i klustret.

releases:
  - foo.world

foo.world:                # Namn pÄ releasen
  services:               # Lista över dailymotion's appar/projekt
    foobar:
      chart_name: foo-foobar
      repo: git@github.com:dailymotion/foobar
      contexts:
        prod-europe-west1:
          deployments:
            - name: foo-bar-baz
              replicas: 18
            - name: another-deployment
              replicas: 3

TjÀnstedeklaration

Detta Àr en översikt av alla steg som definierar vÄr distributionsarbetsflöde. Det sista steget distribuerar applikationen samtidigt i flera arbetskluster.


Distributionssteg i Jenkins

Och hemligheterna?

Vad gÀller sÀkerhet sÄ följer vi alla hemligheter frÄn olika platser och lagrar dem i ett unikt förrÄd Vault i Paris.

VÄra distributionsverktyg hÀmtar hemligheternas vÀrden frÄn Vault och, nÀr det Àr dags för distribution, infogar dem i Helm.

För detta har vi definierat en mappning mellan hemligheterna i Vault och de hemligheter som vÄra applikationer behöver:

hemligheter:                                                                                                                                                                                                        
     - secret_id: "stack1-app1-password"                                                                                                                                                                                  
       kontexter:                                                                                                                                                                                                   
         - namn: "default"                                                                                                                                                                                         
           vaultPath: "\/kv\/dev\/stack1\/app1\/test"                                                                                                                                                               
           vaultKey: "password"                                                                                                                                                                                    
         - namn: "cluster1"                                                                                                                                                                           
           vaultPath: "\/kv\/dev\/stack1\/app1\/test"                                                                                                                                                               
           vaultKey: "password"

  • Vi har faststĂ€llt allmĂ€nna regler som mĂ„ste följas vid inspelning av hemligheter i Vault.
  • Om hemligheten hör till en viss kontext eller kluster, mĂ„ste en specifik post lĂ€ggas till. (HĂ€r har kontexten cluster1 sitt eget vĂ€rde för hemligheten stack-app1-password).
  • Annars anvĂ€nds vĂ€rdet standard.
  • För varje punkt i denna lista i Kubernetes-hemligheten infogas ett nyckel-vĂ€rde-par. DĂ€rför Ă€r mallen för hemligheten i vĂ„ra diagram mycket enkel.

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 }}"
typ: Opaque

Problem och begrÀnsningar

Arbeta med flera lager

Just nu delar vi utvecklingen av diagram och applikationer. Det innebÀr att utvecklarna mÄste arbeta i tvÄ git-repositorier: ett för applikationen och ett annat för att definiera dess distribution i Kubernetes. 2 git-repositorier innebÀr 2 arbetsflöden, och det Àr lÀtt för en nybörjare att bli förvirrad.

Att hantera generiska diagram Àr besvÀrligt

Som redan nÀmnts Àr generiska diagram mycket anvÀndbara för att definiera beroenden och snabbt distribuera flera applikationer. Men vi anvÀnder --reuse-values, för att undvika att skicka vidare alla vÀrden varje gÄng vi distribuerar en applikation som ingÄr i det generiska diagrammet.

I den kontinuerliga leveransprocessen har vi bara tvÄ vÀrden som Àndras regelbundet: antalet repliker och bildtaggen (version). Andra, mer stabila vÀrden Àndras manuellt, vilket Àr ganska svÄrt. Dessutom kan ett enda fel i distributionen av en generell chart leda till allvarliga fel, som vi har sett av egen erfarenhet.

Uppdatering av flera konfigurationsfiler

NÀr en utvecklare lÀgger till en ny applikation mÄste han Àndra flera filer: applikationsdeklarationen, listan över hemligheter och lÀgga till applikationen i beroendena om den ingÄr i den generella charten.

Jenkins-behörigheter Àr för omfattande i Vault

Nu har vi en AppRole, som lÀser alla hemligheter frÄn Vault.

Rollback-processen Àr inte automatiserad

För rollback mÄste man köra kommandot pÄ flera kluster, vilket kan leda till fel. Vi utför denna operation manuellt för att sÀkerstÀlla att rÀtt versionsidentifierare anges.

Vi rör oss mot GitOps

VÄrt mÄl

Vi vill föra tillbaka charten till applikationsrepositoryt som den distribuerar.

Arbetsflödet kommer att vara detsamma som för utveckling. Till exempel, nÀr en gren skickas till master, kommer distributionen att starta automatiskt. Den huvudsakliga skillnaden mellan detta tillvÀgagÄngssÀtt och det nuvarande arbetsflödet Àr att allt kommer att hanteras i git (sjÀlva applikationen och hur den distribueras i Kubernetes).

Det finns flera fördelar:

  • Mycket mer begripligt för utvecklaren. Det Ă€r enklare att lĂ€ra sig tillĂ€mpa Ă€ndringar i den lokala charten.
  • Definitionen av distributionen av tjĂ€nsten kan anges dĂ€r dĂ€r koden för tjĂ€nsten.
  • Hantering av borttagning av generella charts. TjĂ€nsten kommer att ha sin egen Helm-release. Detta kommer att möjliggöra hantering av applikationens livscykel (rollback, uppgradering) pĂ„ den minsta nivĂ„n, sĂ„ att andra tjĂ€nster inte pĂ„verkas.
  • Fördelar med git för hantering av charts: Ă€ndringsĂ„terkallelse, revisionslogg osv. Om en Ă€ndring av charten mĂ„ste Ă„terkallas kan detta göras med hjĂ€lp av git. Distributionen startar automatiskt.
  • Man kan övervĂ€ga att förbĂ€ttra utvecklingsarbetsflödet med hjĂ€lp av sĂ„dana verktyg som Skaffold, dĂ€r utvecklare kan testa Ă€ndringar i en kontext som liknar produktionsmiljön.

TvÄstegs migrering

VÄra utvecklare har anvÀnt denna arbetsprocess i 2 Är, sÄ vi behöver en sÄ smidig migrering som möjligt. DÀrför beslutade vi att lÀgga till ett mellanliggande steg pÄ vÀgen mot mÄlet.
Det första steget Àr enkelt:

  • Vi behĂ„ller en liknande struktur för att konfigurera distributionen av applikationer, men i ett objekt med namnet 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 release per applikation (utan allmĂ€nna diagram).
  • Diagram i applikations Git-förvaret.

Vi har pratat med alla utvecklare, sÄ migrationsprocessen har redan pÄbörjats. Det första steget kontrolleras fortfarande med hjÀlp av CI-plattformen. Snart kommer jag att skriva ett inlÀgg om det andra steget: hur vi gick över till arbetsprocessen GitOps med Flux. Jag kommer att berÀtta hur vi konfigurerade allt och vilka svÄrigheter vi stötte pÄ (flera förvar, hemligheter osv.). HÄll dig uppdaterad.

HÀr har vi försökt beskriva vÄra framsteg inom distributionsprocessen av applikationer de senaste Ären, vilket har lett till tankar om GitOps-ansatsen. Vi har Ànnu inte nÄtt mÄlet och kommer att rapportera om resultaten, men vi Àr nu övertygade om att vi gjorde rÀtt nÀr vi beslutade att förenkla allt och anpassa det till utvecklarnas vanor.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster