Razmestite aplikacije v več gruč Kubernetes s Helmom

Kako Dailymotion uporablja Kubernetes: uvedba aplikacije

Pri Dailymotion smo začeli uporabljati Kubernetes v proizvodnji pred 3 leti. Toda uvajanje aplikacij v več gruč je zabavno, zato smo v zadnjih nekaj letih poskušali izboljšati naša orodja in poteke dela.

Kje se je začelo

Tukaj bomo opisali, kako uvajamo naše aplikacije v več gruč Kubernetes po vsem svetu.

Za namestitev več objektov Kubernetes hkrati uporabljamo Helm, vsi naši grafikoni pa so shranjeni v enem repozitoriju git. Za razmestitev celotnega sklada aplikacij iz več storitev uporabljamo tako imenovani sumarni grafikon. V bistvu je to grafikon, ki deklarira odvisnosti in vam omogoča, da z enim ukazom inicializirate API in njegove storitve.

Poleg Helma smo napisali tudi majhen skript Python za preverjanje, ustvarjanje grafikonov, dodajanje skrivnosti in uvajanje aplikacij. Vse te naloge se izvajajo na osrednji platformi CI z uporabo docker slike.

Preidimo k bistvu.

Opomba. Ko to berete, je bil prvi kandidat za izdajo Helm 3 že objavljen. Glavna različica vsebuje celo vrsto izboljšav za odpravo nekaterih težav, s katerimi smo se srečali v preteklosti.

Potek dela za razvoj grafikona

Za aplikacije uporabljamo razvejanje in odločili smo se, da uporabimo enak pristop za grafikone.

  • Podružnica dev uporablja za ustvarjanje grafikonov, ki bodo preizkušeni na razvojnih grozdih.
  • Ko je vložena zahteva za vlečenje mojster, se preverjajo v uprizoritvi.
  • Nazadnje ustvarimo zahtevo za vlečenje za objavo sprememb v veji prod in jih uporabiti v proizvodnji.

Vsako okolje ima svoj zasebni repozitorij, ki shranjuje naše grafikone in jih uporabljamo Chartmuseum z zelo uporabnimi API-ji. Na ta način zagotavljamo strogo izolacijo med okolji in testiranje grafikonov v resničnem svetu, preden jih uporabimo v produkciji.

Repozitoriji grafikonov v različnih okoljih

Omeniti velja, da ko razvijalci potisnejo vejo v razvijalce, je različica njihovega grafikona samodejno potisnjena v dev Chartmuseum. Tako vsi razvijalci uporabljajo isto skladišče razvijalcev in morate skrbno določiti svojo različico grafikona, da ne bi slučajno uporabili sprememb nekoga drugega.

Poleg tega naš mali skript Python potrdi objekte Kubernetes glede na specifikacije Kubernetes OpenAPI z uporabo Kubeval, preden jih objavite na Chartmusemu.

Splošni opis poteka dela za razvoj grafikona

  1. Nastavitev nalog cevovoda v skladu s specifikacijo gazr.io za nadzor kakovosti (lint, unit-test).
  2. Potiskanje docker slike z orodji Python, ki uvajajo naše aplikacije.
  3. Nastavitev okolja po imenu veje.
  4. Preverjanje datotek Kubernetes yaml z uporabo Kubevala.
  5. Samodejno povečajte različico grafikona in njegovih nadrejenih grafikonov (grafov, ki so odvisni od grafikona, ki se spreminja).
  6. Pošiljanje grafikona v Chartmuseum, ki ustreza njegovemu okolju

Upravljanje razlik med grozdi

Zveza grozdov

Bil je čas, ko smo uporabljali federacija grozdov Kubernetes, kjer je bilo mogoče objekte Kubernetes deklarirati iz ene same končne točke API-ja. Toda pojavile so se težave. Na primer, nekaterih predmetov Kubernetes ni bilo mogoče ustvariti v končni točki združevanja, zaradi česar je težko vzdrževati zvezne objekte in druge objekte za posamezne gruče.

Za rešitev problema smo začeli samostojno upravljati gruče, kar je zelo poenostavilo proces (uporabili smo prvo različico federacije, v drugi se je morda kaj spremenilo).

Geo-distribuirana platforma

Naša platforma je trenutno razdeljena v 6 regij - 3 lokalne in 3 v oblaku.


Porazdeljeno uvajanje

Vrednosti Global Helm

4 globalne vrednosti Helm vam omogočajo prepoznavanje razlik med grozdi. Vsi naši grafikoni imajo privzete minimalne vrednosti.

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

Globalne vrednote

Te vrednosti pomagajo definirati kontekst za naše aplikacije in se uporabljajo za različne namene: spremljanje, sledenje, beleženje, opravljanje zunanjih klicev, skaliranje itd.

  • "cloud": Imamo hibridno platformo Kubernetes. Na primer, naš API je nameščen v območjih GCP in v naših podatkovnih centrih.
  • "env": Nekatere vrednosti se lahko spremenijo za neprodukcijska okolja. Na primer definicije virov in konfiguracije samodejnega skaliranja.
  • "regija": te informacije pomagajo določiti lokacijo gruče in jih je mogoče uporabiti za določitev bližnjih končnih točk za zunanje storitve.
  • "clusterName": če in kdaj želimo definirati vrednost za posamezno gručo.

Tukaj je konkreten primer:

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

Primer predloge Helm

Ta logika je definirana v predlogi za pomoč, da se izognemo neredu Kubernetes YAML.

Obvestilo o prijavi

Naša orodja za uvajanje temeljijo na več datotekah YAML. Spodaj je primer, kako deklariramo storitev in njeno topologijo skaliranja (število replik) v gruči.

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

Definicija storitve

To je oris vseh korakov, ki opredeljujejo naš delovni tok uvajanja. Zadnji korak razmesti aplikacijo v več delovnih gruč hkrati.


Jenkinsovi koraki uvajanja

Kaj pa skrivnosti?

Kar zadeva varnost, spremljamo vse skrivnosti z različnih krajev in jih hranimo v edinstvenem trezorju Vault v Parizu.

Naša orodja za uvajanje izvabijo skrivne vrednosti iz Vaulta in jih, ko pride čas za uvajanje, vstavijo v Helm.

Da bi to naredili, smo definirali preslikavo med skrivnostmi v trezorju in skrivnostmi, ki jih potrebujejo naše aplikacije:

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"

  • Določili smo splošna pravila, ki jih je treba upoštevati pri snemanju skrivnosti v Vault.
  • Če skrivnost velja v določen kontekst ali skupino, morate dodati določen vnos. (Tukaj ima kontekstni grozd1 svojo vrednost za skrivno geslo stack-app1).
  • V nasprotnem primeru se uporabi vrednost privzeto.
  • Za vsako postavko na tem seznamu v Skrivnost Kubernetesa vstavljen je par ključ-vrednost. Zato je skrivna predloga v naših grafikonih zelo preprosta.

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

Težave in omejitve

Delo z več repozitoriji

Zdaj ločimo razvoj grafikonov in aplikacij. To pomeni, da morajo razvijalci delati v dveh repozitorijih git: enem za aplikacijo in enem za definiranje njene umestitve v Kubernetes. 2 repozitorija git pomenita 2 delovna toka in novinec se zlahka zmede.

Upravljanje posplošenih grafikonov je težavno

Kot smo že povedali, so generični grafikoni zelo uporabni za prepoznavanje odvisnosti in hitro uvajanje več aplikacij. Vendar uporabljamo --reuse-valuesda se izognemo posredovanju vseh vrednosti vsakič, ko uvedemo aplikacijo, ki je del tega splošnega grafikona.

V neprekinjenem delovnem procesu dostave imamo samo dve vrednosti, ki se redno spreminjata: število replik in slikovno oznako (različica). Druge, bolj stabilne vrednosti se spremenijo ročno, kar je precej težko. Poleg tega lahko ena napaka pri uvajanju splošnega grafikona povzroči resne napake, kot smo videli iz lastnih izkušenj.

Posodabljanje več konfiguracijskih datotek

Ko razvijalec doda novo aplikacijo, mora spremeniti več datotek: deklaracijo aplikacije, seznam skrivnosti, dodajanje aplikacije kot odvisnosti, če je vključena v generalizirani grafikon.

Jenkinsova dovoljenja so v Vaultu preveč razširjena

Zdaj imamo enega AppRole, ki prebere vse skrivnosti iz trezorja.

Postopek povrnitve ni avtomatiziran

Če se želite vrniti nazaj, morate zagnati ukaz v več gručih, kar je polno napak. To operacijo izvedemo ročno, da zagotovimo, da je naveden pravilen ID različice.

Premikamo se proti GitOps

Naš cilj

Grafikon želimo vrniti v repozitorij aplikacije, ki jo uporablja.

Potek dela bo enak kot pri razvoju. Na primer, ko je veja potisnjena v master, se bo uvedba samodejno sprožila. Glavna razlika med tem pristopom in trenutnim potekom dela bi bila ta vse bo upravljano v git (sama aplikacija in način njene umestitve v Kubernetes).

Obstaja več prednosti:

  • Veliko jasneje za razvijalca. Lažje se je naučiti uveljaviti spremembe v lokalnem grafikonu.
  • Podate lahko definicijo uvedbe storitve na istem mestu kot koda storitev.
  • Upravljanje odstranjevanja generaliziranih grafikonov. Storitev bo imela svojo izdajo Helm. To vam bo omogočilo upravljanje življenjskega cikla aplikacije (povrnitev nazaj, nadgradnja) na najmanjši ravni, da ne boste vplivali na druge storitve.
  • Prednosti git za upravljanje grafikonov: razveljavitev sprememb, revizijski dnevnik itd. Če morate razveljaviti spremembo grafikona, lahko to storite z uporabo git. Uvajanje se začne samodejno.
  • Morda razmislite o izboljšanju svojega razvojnega poteka dela z orodji, kot je Skafold, s katerim lahko razvijalci preizkusijo spremembe v kontekstu, ki je blizu produkcije.

Selitev v dveh korakih

Naši razvijalci ta potek dela uporabljajo že 2 leti, zato želimo, da je selitev čim bolj neboleča. Zato smo se odločili dodati vmesni korak na poti do cilja.
Prva faza je preprosta:

  • Ohranjamo podobno strukturo za nastavitev uvajanja aplikacije, vendar v enem samem objektu, imenovanem 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 izdaja na aplikacijo (brez posplošenih grafikonov).
  • Grafikoni v repozitoriju git aplikacije.

Pogovarjali smo se z vsemi razvijalci, tako da se je proces migracije že začel. Prva stopnja je še vedno nadzorovana s platformo CI. Kmalu bom napisal še eno objavo o drugi fazi: kako smo prešli na potek dela GitOps z Flux. Povedal vam bom, kako smo vse nastavili in na kakšne težave smo naleteli (več repozitorijev, skrivnosti itd.). Spremljajte novice.

Tukaj smo poskušali opisati naš napredek pri delovnem toku uvajanja aplikacij v preteklih letih, kar je vodilo do razmišljanj o pristopu GitOps. Cilja še nismo dosegli in bomo o rezultatih še poročali, zdaj pa smo prepričani, da smo naredili prav, ko smo se odločili vse poenostaviti in približati navadam razvijalcev.

Vir: www.habr.com

Dodaj komentar