I-deploy ang mga application sa maraming Kubernetes cluster gamit ang Helm

Paano ginagamit ng Dailymotion ang Kubernetes: Application Deployment

Kami sa Dailymotion ay nagsimulang gumamit ng Kubernetes sa produksyon 3 taon na ang nakakaraan. Ngunit ang pag-deploy ng mga application sa maraming cluster ay masaya, kaya sa nakalipas na ilang taon sinubukan naming pahusayin ang aming mga tool at workflow.

Saan nagsimula

Dito namin sasaklawin kung paano namin i-deploy ang aming mga application sa maraming Kubernetes cluster sa buong mundo.

Para mag-deploy ng maraming Kubernetes object nang sabay-sabay, ginagamit namin timon, at lahat ng aming mga chart ay nakaimbak sa isang git repository. Upang mag-deploy ng buong application stack mula sa ilang mga serbisyo, ginagamit namin ang tinatawag na summary chart. Sa pangkalahatan, ito ay isang tsart na nagdedeklara ng mga dependency at nagbibigay-daan sa iyong simulan ang API at ang mga serbisyo nito sa isang command.

Nagsulat din kami ng maliit na script ng Python sa ibabaw ng Helm para magsagawa ng mga pagsusuri, gumawa ng mga chart, magdagdag ng mga lihim, at mag-deploy ng mga application. Ang lahat ng mga gawaing ito ay ginagawa sa isang sentral na platform ng CI gamit ang isang docker na imahe.

Dumating tayo sa punto.

Tandaan. Habang binabasa mo ito, ang unang release na kandidato para sa Helm 3 ay inihayag na. Ang pangunahing bersyon ay naglalaman ng isang buong host ng mga pagpapabuti upang matugunan ang ilan sa mga isyu na nakatagpo namin sa nakaraan.

Daloy ng trabaho sa pagbuo ng tsart

Gumagamit kami ng branching para sa mga application, at nagpasya kaming ilapat ang parehong diskarte sa mga chart.

  • Sangay dev ginagamit para gumawa ng mga chart na susuriin sa mga development cluster.
  • Kapag ang isang pull request ay isinumite sa panginoon, sila ay naka-check in sa pagtatanghal.
  • Sa wakas, gumawa kami ng pull request para i-commit ang mga pagbabago sa branch prod at ilapat ang mga ito sa produksyon.

Ang bawat kapaligiran ay may sariling pribadong imbakan na nag-iimbak ng aming mga chart, at ginagamit namin Chartmuseum na may napakakapaki-pakinabang na mga API. Sa ganitong paraan, tinitiyak namin ang mahigpit na paghihiwalay sa pagitan ng mga kapaligiran at pagsubok sa totoong mundo ng mga chart bago gamitin ang mga ito sa produksyon.

Mga imbakan ng tsart sa iba't ibang kapaligiran

Kapansin-pansin na kapag nagtulak ang mga developer ng isang dev branch, isang bersyon ng kanilang chart ang awtomatikong mapupunta sa dev Chartmuseum. Kaya, ang lahat ng mga developer ay gumagamit ng parehong dev repository, at kailangan mong maingat na tukuyin ang iyong bersyon ng chart upang hindi aksidenteng magamit ang mga pagbabago ng ibang tao.

Bukod dito, pinapatunayan ng aming maliit na script ng Python ang mga bagay ng Kubernetes laban sa mga pagtutukoy ng Kubernetes OpenAPI na ginagamit Kubeval, bago i-publish ang mga ito sa Chartmusem.

Pangkalahatang paglalarawan ng daloy ng trabaho sa pagbuo ng tsart

  1. Pagse-set up ng mga gawain sa pipeline ayon sa detalye gazr.io para sa kontrol ng kalidad (lint, unit-test).
  2. Pagtulak ng imahe ng docker gamit ang mga tool sa Python na nagde-deploy ng aming mga application.
  3. Pagse-set up ng kapaligiran ayon sa pangalan ng sangay.
  4. Pagpapatunay ng mga Kubernetes yaml file gamit ang Kubeval.
  5. Awtomatikong taasan ang bersyon ng isang chart at ang mga parent chart nito (mga chart na nakadepende sa chart na binago).
  6. Pagsusumite ng tsart sa isang Chartmuseum na tumutugma sa kapaligiran nito

Pamamahala ng mga pagkakaiba sa mga cluster

Federation of Clusters

May time na ginamit namin pederasyon ng mga kumpol ng Kubernetes, kung saan maaaring ideklara ang mga bagay ng Kubernetes mula sa isang endpoint ng API. Ngunit lumitaw ang mga problema. Halimbawa, hindi magawa ang ilang bagay sa Kubernetes sa endpoint ng federation, na nagpapahirap sa pagpapanatili ng mga federated object at iba pang object para sa mga indibidwal na cluster.

Upang malutas ang problema, sinimulan naming pamahalaan ang mga kumpol nang nakapag-iisa, na lubos na pinasimple ang proseso (ginamit namin ang unang bersyon ng federation; maaaring may nagbago sa pangalawa).

Platform na ibinahagi ng geo

Ang aming platform ay kasalukuyang ipinamamahagi sa 6 na rehiyon - 3 sa lokal at 3 sa cloud.


Ibinahagi ang Deployment

Mga halaga ng Global Helm

Pinapayagan ka ng 4 na pandaigdigang Helm na halaga na matukoy ang mga pagkakaiba sa pagitan ng mga kumpol. Ang lahat ng aming mga chart ay may mga default na minimum na halaga.

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

Mga pandaigdigang halaga

Ang mga halagang ito ay tumutulong na tukuyin ang konteksto para sa aming mga aplikasyon at ginagamit para sa iba't ibang layunin: pagsubaybay, pagsubaybay, pag-log, paggawa ng mga panlabas na tawag, pag-scale, atbp.

  • "cloud": Mayroon kaming hybrid na platform ng Kubernetes. Halimbawa, ang aming API ay naka-deploy sa mga GCP zone at sa aming mga data center.
  • "env": Maaaring magbago ang ilang value para sa mga environment na hindi produksyon. Halimbawa, ang mga kahulugan ng mapagkukunan at mga pagsasaayos ng autoscaling.
  • "rehiyon": Nakakatulong ang impormasyong ito na matukoy ang lokasyon ng cluster at maaaring magamit upang matukoy ang mga kalapit na endpoint para sa mga panlabas na serbisyo.
  • "clusterName": kung at kailan namin gustong tumukoy ng value para sa isang indibidwal na cluster.

Narito ang isang partikular na halimbawa:

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

Halimbawa ng helm template

Ang logic na ito ay tinukoy sa isang helper template upang maiwasan ang kalat sa Kubernetes YAML.

Anunsyo ng Application

Ang aming mga tool sa pag-deploy ay batay sa maraming YAML file. Nasa ibaba ang isang halimbawa kung paano namin idineklara ang isang serbisyo at ang scaling topology nito (bilang ng mga replika) sa isang 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

Kahulugan ng Serbisyo

Ito ay isang outline ng lahat ng mga hakbang na tumutukoy sa aming deployment workflow. Ang huling hakbang ay nagde-deploy ng application sa maraming kumpol ng manggagawa nang sabay-sabay.


Mga Hakbang sa Pag-deploy ng Jenkins

Paano ang tungkol sa mga lihim?

Tungkol sa seguridad, sinusubaybayan namin ang lahat ng mga lihim mula sa iba't ibang lugar at iniimbak ang mga ito sa isang natatanging vault Vault sa Paris.

Ang aming mga tool sa pag-deploy ay kumukuha ng mga lihim na halaga mula sa Vault at, kapag dumating ang oras ng pag-deploy, ipasok ang mga ito sa Helm.

Para magawa ito, tinukoy namin ang pagmamapa sa pagitan ng mga lihim sa Vault at ng mga lihim na kailangan ng aming mga application:

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"

  • Tinukoy namin ang mga pangkalahatang tuntunin na dapat sundin kapag nagre-record ng mga lihim sa Vault.
  • Kung nalalapat ang sikreto sa isang partikular na konteksto o kumpol, kailangan mong magdagdag ng isang partikular na entry. (Narito ang cluster1 ng konteksto ay may sariling halaga para sa lihim na stack-app1-password).
  • Kung hindi, ang halaga ay ginagamit bilang default.
  • Para sa bawat item sa listahang ito sa Sikreto ng Kubernetes may ipinasok na key-value pair. Samakatuwid, ang lihim na template sa aming mga chart ay napaka-simple.

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

Mga problema at limitasyon

Paggawa gamit ang maramihang mga repositoryo

Ngayon ay pinaghihiwalay namin ang pagbuo ng mga chart at application. Nangangahulugan ito na ang mga developer ay kailangang magtrabaho sa dalawang git repository: isa para sa application, at isa para sa pagtukoy sa deployment nito sa Kubernetes. Ang ibig sabihin ng 2 git repository ay 2 workflow, at madali para sa isang newbie na malito.

Ang pamamahala ng mga pangkalahatang chart ay isang abala

Gaya ng nasabi na namin, ang mga generic na chart ay lubhang kapaki-pakinabang para sa pagtukoy ng mga dependency at mabilis na pag-deploy ng maraming application. Pero ginagamit namin --reuse-valuesupang maiwasang maipasa ang lahat ng value sa tuwing magde-deploy kami ng application na bahagi ng pangkalahatang chart na ito.

Sa tuluy-tuloy na daloy ng trabaho sa paghahatid, mayroon lang kaming dalawang value na regular na nagbabago: ang bilang ng mga replika at ang tag ng larawan (bersyon). Ang iba, mas matatag na mga halaga ay binago nang manu-mano, at ito ay medyo mahirap. Bukod dito, ang isang pagkakamali sa pag-deploy ng isang pangkalahatang tsart ay maaaring humantong sa mga malubhang pagkabigo, tulad ng nakita natin mula sa sarili nating karanasan.

Pag-update ng maramihang configuration file

Kapag nagdagdag ang isang developer ng isang bagong application, kailangan niyang baguhin ang ilang mga file: ang deklarasyon ng application, ang listahan ng mga lihim, pagdaragdag ng application bilang dependency kung ito ay kasama sa pangkalahatang tsart.

Masyadong pinahaba ang mga pahintulot ni Jenkins sa Vault

Ngayon mayroon kaming isa AppRole, na nagbabasa ng lahat ng mga lihim mula sa Vault.

Ang proseso ng rollback ay hindi awtomatiko

Upang mag-rollback, kailangan mong patakbuhin ang command sa ilang mga kumpol, at ito ay puno ng mga error. Isinasagawa namin ang operasyong ito nang manu-mano upang matiyak na ang tamang ID ng bersyon ay tinukoy.

Kami ay gumagalaw patungo sa GitOps

Ang aming layunin

Gusto naming ibalik ang chart sa repository ng application na ini-deploy nito.

Ang daloy ng trabaho ay magiging kapareho ng para sa pag-unlad. Halimbawa, kapag ang isang sangay ay na-push sa master, ang deployment ay awtomatikong ma-trigger. Ang pangunahing pagkakaiba sa pagitan ng diskarteng ito at ng kasalukuyang daloy ng trabaho ay iyon lahat ay pamamahalaan sa git (ang application mismo at ang paraan ng pag-deploy nito sa Kubernetes).

Mayroong ilang mga pakinabang:

  • marami mas malinaw para sa developer. Mas madaling matutunan kung paano maglapat ng mga pagbabago sa isang lokal na chart.
  • Maaaring tukuyin ang kahulugan ng deployment ng serbisyo parehong lugar tulad ng code serbisyo.
  • Pamamahala sa pag-alis ng mga pangkalahatang chart. Ang serbisyo ay magkakaroon ng sarili nitong Helm release. Papayagan ka nitong pamahalaan ang lifecycle ng application (rollback, upgrade) sa pinakamaliit na antas, upang hindi maapektuhan ang iba pang mga serbisyo.
  • Mga pakinabang ng git para sa pamamahala ng tsart: i-undo ang mga pagbabago, audit log, atbp. Kung kailangan mong i-undo ang pagbabago sa isang tsart, magagawa mo ito gamit ang git. Awtomatikong magsisimula ang deployment.
  • Maaari mong isaalang-alang ang pagpapabuti ng iyong daloy ng trabaho sa pag-unlad gamit ang mga tool tulad ng Skaffold, kung saan masusubok ng mga developer ang mga pagbabago sa isang kontekstong malapit sa produksyon.

Dalawang hakbang na paglipat

Ginagamit ng aming mga developer ang daloy ng trabaho na ito sa loob ng 2 taon na, kaya gusto naming maging walang sakit hangga't maaari ang paglipat. Samakatuwid, nagpasya kaming magdagdag ng isang intermediate na hakbang sa daan patungo sa layunin.
Ang unang yugto ay simple:

  • Nagpapanatili kami ng katulad na istraktura para sa pagse-set up ng pag-deploy ng application, ngunit sa isang bagay na tinatawag na 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 sa bawat application (nang walang mga pangkalahatang chart).
  • Mga chart sa git repository ng application.

Nakipag-usap kami sa lahat ng mga developer, kaya nagsimula na ang proseso ng paglipat. Ang unang yugto ay kinokontrol pa rin gamit ang CI platform. Magsusulat ako ng isa pang post sa lalong madaling panahon tungkol sa ikalawang yugto: kung paano kami lumipat sa isang daloy ng trabaho sa GitOps Pagkilos ng bagay. Sasabihin ko sa iyo kung paano namin na-set up ang lahat at kung anong mga paghihirap ang naranasan namin (maraming mga repositoryo, mga lihim, atbp.). Sundan ang balita.

Dito, sinubukan naming ilarawan ang aming pag-unlad sa daloy ng trabaho sa pag-deploy ng application sa mga nakaraang taon, na humantong sa mga pag-iisip tungkol sa diskarte sa GitOps. Hindi pa namin naabot ang layunin at mag-uulat sa mga resulta, ngunit ngayon ay kumbinsido kami na ginawa namin ang tamang bagay noong nagpasya kaming pasimplehin ang lahat at ilapit ito sa mga gawi ng mga developer.

Pinagmulan: www.habr.com

Magdagdag ng komento