Deplojante Aplikojn al Multoblaj Kubernetes Clusters kun Helm

Kiel Dailymotion uzas Kubernetes: Aplika Deplojo

Ni ĉe Dailymotion komencis uzi Kubernetes en produktado antaŭ 3 jaroj. Sed deploji aplikaĵojn tra pluraj aretoj estas amuza, do dum la lastaj jaroj ni provis plibonigi niajn ilojn kaj laborfluojn.

Kie ĝi komenciĝis

Ĉi tie ni kovros kiel ni disvastigas niajn aplikojn tra pluraj Kubernetes-grupoj tra la mondo.

Por disfaldi plurajn Kubernetes-objektojn samtempe, ni uzas Kasko, kaj ĉiuj niaj diagramoj estas konservitaj en unu git-deponejo. Por deploji plenan aplikaĵan stakon de pluraj servoj, ni uzas la tielnomitan resuman diagramon. Esence, ĉi tio estas diagramo, kiu deklaras dependecojn kaj permesas al vi praligi la API kaj ĝiajn servojn per unu komando.

Ni ankaŭ skribis malgrandan Python-skripton sur Helm por fari kontrolojn, krei leterojn, aldoni sekretojn kaj disfaldi aplikaĵojn. Ĉiuj ĉi tiuj taskoj estas faritaj sur centra CI-platformo uzante docker-bildon.

Ni iru al la afero.

Notu. Dum vi legas ĉi tion, la unua eldona kandidato por Helm 3 jam estis anoncita. La ĉefa versio enhavas multajn plibonigojn por trakti iujn problemojn, kiujn ni renkontis en la pasinteco.

Chart-disvolva laborfluo

Ni uzas disbranĉigon por aplikoj, kaj ni decidis apliki la saman aliron al diagramoj.

  • Branĉo dev uzata por krei leterojn kiuj estos testitaj sur evolugrupoj.
  • Kiam tirpeto estas sendita al majstro, ili estas kontrolitaj en surscenigo.
  • Fine, ni kreas tiran peton por fari la ŝanĝojn al la branĉo prod kaj apliki ilin en produktado.

Ĉiu medio havas sian propran privatan deponejon, kiu konservas niajn leterojn, kaj ni uzas Chartmuseum kun tre utilaj API-oj. Tiel ni certigas striktan izolitecon inter medioj kaj realan testadon de leteroj antaŭ ol uzi ilin en produktado.

Chart-deponejoj en malsamaj medioj

Indas noti, ke kiam programistoj puŝas dev-branĉon, versio de ilia diagramo estas aŭtomate puŝita al la dev Chartmuseum. Tiel, ĉiuj programistoj uzas la saman dev-deponejon, kaj vi devas zorge specifi vian version de la diagramo por ne hazarde uzi la ŝanĝojn de iu alia.

Plie, nia malgranda Python-skripto validas Kubernetes-objektojn kontraŭ la specifoj de Kubernetes OpenAPI uzante Kubeval, antaŭ publikigado de ili sur Chartmusem.

Ĝenerala priskribo de la laborfluo de disvolvado de diagramo

  1. Agordi duktotaskojn laŭ specifo gazr.io por kvalito-kontrolo (lint, unutesto).
  2. Puŝante docker-bildon per Python-iloj, kiuj deplojas niajn aplikojn.
  3. Agordi la medion per filionomo.
  4. Validigante Kubernetes-yaml-dosierojn per Kubeval.
  5. Aŭtomate pliigu la version de diagramo kaj ĝiaj gepatraj diagramoj (diagramoj kiuj dependas de la letero ŝanĝita).
  6. Sendu diagramon al Chartmuseum kiu kongruas kun sia medio

Administri diferencojn inter aretoj

Federacio de Aretoj

Estis tempo, kiam ni uzis federacio de Kubernetes-aretoj, kie Kubernetes-objektoj povus esti deklaritaj de ununura API-finpunkto. Sed problemoj ekestis. Ekzemple, kelkaj Kubernetes-objektoj ne povus esti kreitaj en la federacia finpunkto, malfaciligante konservi federaciajn objektojn kaj aliajn objektojn por individuaj aretoj.

Por solvi la problemon, ni komencis administri la aretojn sendepende, kio multe simpligis la procezon (ni uzis la unuan version de federacio; io eble ŝanĝiĝis en la dua).

Geo-distribuita platformo

Nia platformo estas nuntempe distribuita tra 6 regionoj - 3 loke kaj 3 en la nubo.


Distribuita Deplojo

Tutmondaj Helm-valoroj

4 tutmondaj Helm-valoroj permesas vin identigi diferencojn inter aretoj. Ĉiuj niaj leteroj havas defaŭltajn minimumajn valorojn.

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

Tutmondaj valoroj

Ĉi tiuj valoroj helpas difini la kuntekston por niaj aplikoj kaj estas uzataj por diversaj celoj: monitorado, spurado, registrado, farado de eksteraj vokoj, skalado ktp.

  • "nubo": Ni havas hibridan Kubernetes-platformon. Ekzemple, nia API estas deplojita en GCP-zonoj kaj en niaj datumcentroj.
  • "env": Iuj valoroj povas ŝanĝiĝi por ne-produktaj medioj. Ekzemple, rimeddifinoj kaj aŭtoskalaj agordoj.
  • "regiono": Ĉi tiu informo helpas determini la lokon de la areto kaj povas esti uzata por determini proksimajn finpunktojn por eksteraj servoj.
  • "clusterName": se kaj kiam ni volas difini valoron por individua areto.

Jen specifa ekzemplo:

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

Helm ŝablono ekzemplo

Ĉi tiu logiko estas difinita en helpa ŝablono por eviti malordigi Kubernetes YAML.

Aplika Anonco

Niaj disfaldaj iloj baziĝas sur multoblaj YAML-dosieroj. Malsupre estas ekzemplo de kiel ni deklaras servon kaj ĝian skalan topologion (nombro da kopioj) en areto.

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

Difino de Servo

Ĉi tio estas skizo de ĉiuj paŝoj, kiuj difinas nian deplojan laborfluon. La lasta paŝo deplojas la aplikaĵon al pluraj laborgrupoj samtempe.


Jenkins Deploj Paŝoj

Kio pri sekretoj?

Koncerne sekurecon, ni spuras ĉiujn sekretojn de malsamaj lokoj kaj konservas ilin en unika trezorejo volbo en Parizo.

Niaj deplojiloj ĉerpas sekretajn valorojn el Vault kaj, kiam venos la tempo de deplojo, enmetu ilin en Helm.

Por fari tion, ni difinis mapadon inter la sekretoj en Vault kaj la sekretoj, kiujn niaj aplikaĵoj bezonas:

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"

  • Ni difinis ĝeneralajn regulojn por sekvi dum registrado de sekretoj en Vault.
  • Se la sekreto validas al specifa kunteksto aŭ areto, vi devas aldoni specifan enskribon. (Ĉi tie la kunteksto cluster1 havas sian propran valoron por la sekreta stack-app1-password).
  • Alie la valoro estas uzata implicite.
  • Por ĉiu ero en ĉi tiu listo en Kubernetes sekreto ŝlosil-valora paro estas enmetita. Tial la sekreta ŝablono en niaj leteroj estas tre simpla.

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

Problemoj kaj limigoj

Laborante kun pluraj deponejoj

Nun ni apartigas la disvolviĝon de leteroj kaj aplikoj. Ĉi tio signifas, ke programistoj devas labori en du git-deponejoj: unu por la aplikaĵo, kaj unu por difini ĝian deplojon al Kubernetes. 2 git-deponejoj signifas 2 laborfluojn, kaj estas facile por novulo konfuziĝi.

Administri ĝeneraligitajn leterojn estas ĝeno

Kiel ni jam diris, ĝeneralaj leteroj estas tre utilaj por identigi dependecojn kaj rapide deploji plurajn aplikojn. Sed ni uzas --reuse-valuespor eviti preterpasi ĉiujn valorojn ĉiufoje kiam ni deplojas aplikaĵon, kiu estas parto de ĉi tiu ĝeneraligita diagramo.

En kontinua livera laborfluo, ni havas nur du valorojn, kiuj regule ŝanĝiĝas: la nombro da kopioj kaj la bilda etikedo (versio). Aliaj pli stabilaj valoroj estas ŝanĝitaj permane, kaj ĉi tio estas sufiĉe malfacila. Plie, unu eraro en deplojado de ĝeneraligita diagramo povas konduki al gravaj fiaskoj, kiel ni vidis el nia propra sperto.

Ĝisdatigante plurajn agordajn dosierojn

Kiam programisto aldonas novan aplikaĵon, li devas ŝanĝi plurajn dosierojn: la aplikan deklaron, la liston de sekretoj, aldonante la aplikaĵon kiel dependecon se ĝi estas inkluzivita en la ĝeneraligita diagramo.

Jenkins-permesoj estas tro etenditaj en Vault

Nun ni havas unu AppRole, kiu legas ĉiujn sekretojn de la Trezorejo.

La retroprocezo ne estas aŭtomatigita

Por restarigi, vi devas ruli la komandon sur pluraj aretoj, kaj ĉi tio estas plena de eraroj. Ni plenumas ĉi tiun operacion permane por certigi, ke la ĝusta versio ID estas specifita.

Ni iras al GitOps

Nia celo

Ni volas resendi la diagramon al la deponejo de la aplikaĵo, kiun ĝi deplojas.

La laborfluo estos la sama kiel por evoluo. Ekzemple, kiam branĉo estas puŝita por majstri, la deplojo estos ekigita aŭtomate. La ĉefa diferenco inter ĉi tiu aliro kaj la nuna laborfluo estus tio ĉio estos administrita en git (la aplikaĵo mem kaj la maniero kiel ĝi estas deplojita en Kubernetes).

Estas pluraj avantaĝoj:

  • Multe pli klara por la programisto. Estas pli facile lerni kiel apliki ŝanĝojn en loka diagramo.
  • La difino de servodeplojo povas esti precizigita sama loko kiel la kodo servo.
  • Administri la forigon de ĝeneraligitaj leteroj. La servo havos sian propran Helm-eldonon. Ĉi tio permesos al vi administri la aplikaĵan vivociklon (revenigi, ĝisdatigi) je la plej malgranda nivelo, por ne influi aliajn servojn.
  • Avantaĝoj de git por administrado de diagramo: malfari ŝanĝojn, revizioprotokolo, ktp. Se vi bezonas malfari ŝanĝon al diagramo, vi povas fari tion uzante git. La deplojo komenciĝas aŭtomate.
  • Vi eble pripensos plibonigi vian disvolvan laborfluon per iloj kiel Skafodo, kun kiu programistoj povas testi ŝanĝojn en kunteksto proksima al produktado.

Dupaŝa migrado

Niaj programistoj uzas ĉi tiun laborfluon jam de 2 jaroj, do ni volas, ke la migrado estu kiel eble plej sendolora. Tial ni decidis aldoni mezan paŝon survoje al la celo.
La unua etapo estas simpla:

  • Ni konservas similan strukturon por starigi aplikaĵon, sed en ununura objekto nomata 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 eldono per aplikaĵo (sen ĝeneraligitaj diagramoj).
  • Diagramoj en la git-deponejo de la aplikaĵo.

Ni parolis kun ĉiuj programistoj, do la migra procezo jam komenciĝis. La unua etapo daŭre estas kontrolita per la CI-platformo. Mi skribos alian afiŝon baldaŭ pri fazo du: kiel ni moviĝis al GitOps-laborfluo kun fluo. Mi rakontos al vi, kiel ni aranĝis ĉion kaj kiajn malfacilaĵojn ni renkontis (multoblajn deponejojn, sekretojn, ktp.). Sekvu la novaĵojn.

Ĉi tie ni provis priskribi nian progreson en la aplikaĵa disfalda laborfluo dum la pasintaj jaroj, kio kondukis al pensoj pri la aliro GitOps. Ni ankoraŭ ne atingis la celon kaj raportos pri la rezultoj, sed nun ni estas konvinkitaj, ke ni faris la ĝustan aferon, kiam ni decidis simpligi ĉion kaj proksimigi ĝin al la kutimoj de programistoj.

fonto: www.habr.com

Aldoni komenton