Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Kaixo! Duela gutxi, automatizazio-tresna eder asko kaleratu dira bai Docker irudiak eraikitzeko, bai Kubernetes-en zabaltzeko. Zentzu honetan, GitLab-ekin jolastea erabaki nuen, bere gaitasunak ondo aztertzea eta, noski, kanalizazioa konfiguratzea.

Lan hau webgunean inspiratu zen kubernetes.io, sortzen dena iturburu-kodeak automatikoki, eta bidalitako igerilekuko eskaera bakoitzeko, robotak automatikoki webgunearen aurrebista bertsio bat sortzen du zure aldaketekin eta ikusteko esteka bat eskaintzen du.

Hutsetik antzeko prozesu bat eraikitzen saiatu nintzen, baina guztiz eraikita Gitlab CI eta Kubernetes-en aplikazioak zabaltzeko erabiltzen ohi ditudan doako tresnetan eraikia. Gaur azkenean beraiei buruz gehiago kontatuko dizuet.

Artikuluan, besteak beste, tresnak eztabaidatuko dira:
Hugo, qbec, kaniko, git-crypt и GitLab CI ingurune dinamikoak sortzearekin.

Edukia

  1. Ezagutu Hugo
  2. Dockerfile prestatzen
  3. Kaniko ezagutzea
  4. qbec ezagutzea
  5. Gitlab-runner probatzen Kubernetes-executor-ekin
  6. Helm diagramak qbec-ekin zabaltzen
  7. git-crypt aurkezten
  8. Tresna-kutxaren irudia sortzea
  9. Gure lehen kanalizazioa eta etiketen bidez irudien muntaketa
  10. Inplementazio automatizazioa
  11. Artefaktuak eta muntaia menperatzera bultzatzean
  12. Ingurune dinamikoak
  13. Berrikusi aplikazioak

1. Hugo ezagutzea

Gure proiektuaren adibide gisa, Hugoren gainean eraikitako dokumentazioa argitaratzeko gune bat sortzen saiatuko gara. Hugo eduki-sortzaile estatiko bat da.

Sorgailu estatikoekin ezagutzen ez dutenentzat, apur bat gehiago kontatuko dizuet. Datu-basea eta PHP batzuk dituzten ohiko webguneen motorrak ez bezala, zeinek, erabiltzaile batek eskatutakoan, orrialdeak etengabe sortzen dituzten, sorgailu estatikoak apur bat ezberdin diseinatzen dira. Iturburuak hartzeko aukera ematen dizute, normalean Markdown markaketa eta gaien txantiloietako fitxategi multzo bat, eta ondoren guztiz amaitutako webgune batean biltzeko.

Hau da, ondorioz, direktorio-egitura bat eta sortutako HTML fitxategi multzo bat jasoko duzu, edozein ostalaritza merke batera igo eta funtzionatzen duen webgune bat lortzeko.

Hugo lokalean instala dezakezu eta probatu:

Gune berri bat hasieratzen:

hugo new site docs.example.org

Eta aldi berean git biltegia:

cd docs.example.org
git init

Orain arte, gure gunea erabatekoa da eta bertan zerbait ager dadin, gai bat konektatu behar dugu lehenik; gai bat gure webgunea sortzen den txantiloi eta arau zehatzen multzo bat besterik ez da.

Erabiliko dugun gairako Argibide, nire ustez dokumentazio gune baterako primeran egokitzen dena.

Arreta berezia jarri nahiko nuke ez dugula gai-fitxategiak gure proiektuaren biltegian gorde behar; horren ordez, konektatu besterik ez dugu egin behar erabiliz. git azpimodulua:

git submodule add https://github.com/matcornic/hugo-theme-learn themes/learn

Horrela, gure biltegiak gure proiektuarekin zuzenean erlazionatutako fitxategiak soilik edukiko ditu, eta konektatutako gaia biltegi jakin baterako esteka gisa eta bertan konprometitu gisa geratuko da, hau da, beti jatorrizko iturritik atera daiteke eta ez du beldurrik izan. aldaketa bateraezinak.

Zuzen dezagun konfigurazioa konfiguratu.toml:

baseURL = "http://docs.example.org/"
languageCode = "en-us"
title = "My Docs Site"
theme = "learn"

Dagoeneko fase honetan exekutatu dezakezu:

hugo server

Eta helbidean http://localhost:1313/ begiratu gure sortu berri den webgunea, direktorioan egindako aldaketa guztiak automatikoki eguneratzen ditu irekitako orria arakatzailean, oso erosoa!

Saia gaitezen azaleko orri bat sortzen edukia/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Sortu berri den orriaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Gune bat sortzeko, exekutatu:

hugo

Direktorioaren edukiak publiko/ eta zure webgunea izango da.
Bai, bide batez, berehala gehi diezaiogun .gitignore:

echo /public > .gitignore

Ez ahaztu gure aldaketak konprometitzea:

git add .
git commit -m "New site created"

2. Dockerfile prestatzea

Gure biltegiaren egitura definitzeko garaia da. Normalean horrelako zerbait erabiltzen dut:

.
├── deploy
│   ├── app1
│   └── app2
└── dockerfiles
    ├── image1
    └── image2

  • dockerfiles/ — Dockerfiles eta gure Docker irudiak eraikitzeko beharrezkoa den direktorioekin.
  • zabaldu/ — Gure aplikazioak Kubernetesen zabaltzeko direktorioak ditu

Horrela, gure lehen Dockerfile sortuko dugu bidean dockerfiles/webgunea/Dockerfile

FROM alpine:3.11 as builder
ARG HUGO_VERSION=0.62.0
RUN wget -O- https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-64bit.tar.gz | tar -xz -C /usr/local/bin
ADD . /src
RUN hugo -s /src

FROM alpine:3.11
RUN apk add --no-cache darkhttpd
COPY --from=builder /src/public /var/www
ENTRYPOINT [ "/usr/bin/darkhttpd" ]
CMD [ "/var/www" ]

Ikus dezakezunez, Dockerfile-k bi ditu FROM, aukera honi deitzen zaio etapa anitzeko eraikuntza eta beharrezkoa ez dena azken docker iruditik kanpo uzteko aukera ematen du.
Horrela, azken irudiak bakarrik edukiko du ilunahttpd (HTTP zerbitzari arina) eta publiko/ — Estatikoki sortutako gure webgunearen edukia.

Ez ahaztu gure aldaketak konprometitzea:

git add dockerfiles/website
git commit -m "Add Dockerfile for website"

3. Kaniko ezagutzea

Docker irudien eraikitzaile gisa, erabiltzea erabaki nuen kaniko, bere funtzionamenduak ez duelako docker deabrurik behar, eta eraikuntza bera edozein makinatan egin daiteke eta cachea zuzenean erregistroan gorde daiteke, horrela biltegiratze iraunkor osoa edukitzeko beharra ezabatuz.

Irudia eraikitzeko, exekutatu edukiontziarekin kaniko executor eta pasa ezazu egungo eraikuntza testuingurua; hau lokalean ere egin daiteke, docker bidez:

docker run -ti --rm 
  -v $PWD:/workspace 
  -v ~/.docker/config.json:/kaniko/.docker/config.json:ro 
  gcr.io/kaniko-project/executor:v0.15.0 
  --cache 
  --dockerfile=dockerfiles/website/Dockerfile 
  --destination=registry.gitlab.com/kvaps/docs.example.org/website:v0.0.1

non registry.gitlab.com/kvaps/docs.example.org/websitea — zure docker irudiaren izena; eraiki ondoren, automatikoki abiaraziko da docker erregistroan.

Parametroa --cachea Docker erregistroan geruzak gordetzeko aukera ematen du; emandako adibiderako, bertan gordeko dira registry.gitlab.com/kvaps/docs.example.org/website/cache, baina beste bide bat zehaztu dezakezu parametroa erabiliz --cache-repo.

Docker-registry-ren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

4. qbec ezagutzea

Qbec Zure aplikazioaren manifestuak modu deklaratiboan deskribatzeko eta Kubernetesen zabaltzeko aukera ematen duen hedapen-tresna bat da. Jsonnet sintaxi nagusi gisa erabiltzeak hainbat ingurunetan dauden desberdintasunen deskribapena asko errazten du eta, gainera, kodearen errepikapena ia erabat ezabatzen du.

Hau bereziki egia izan daiteke aplikazio bat parametro desberdinak dituzten hainbat klustertara zabaldu behar duzun kasuetan eta Git-en modu deklaratiboan deskribatu nahi dituzun kasuetan.

Qbec-ek Helm diagramak errendatzeko aukera ematen dizu, beharrezko parametroak pasatuz eta, ondoren, ohiko manifestuen modu berean funtzionatzeko, hainbat mutazio aplika ditzakezula barne, eta honek, aldi berean, beharrizana kentzeko aukera ematen du. erabili ChartMuseum. Hau da, grafikoak zuzenean gorde eta errenda ditzakezu git-etik, dagokien tokitik.

Lehen esan dudan bezala, inplementazio guztiak direktorio batean gordeko ditugu zabaldu/:

mkdir deploy
cd deploy

Hasi dezagun gure lehen aplikazioa:

qbec init website
cd website

Orain gure aplikazioaren egitura honelakoa da:

.
├── components
├── environments
│   ├── base.libsonnet
│   └── default.libsonnet
├── params.libsonnet
└── qbec.yaml

ikus dezagun fitxategia qbec.yaml:

apiVersion: qbec.io/v1alpha1
kind: App
metadata:
  name: website
spec:
  environments:
    default:
      defaultNamespace: docs
      server: https://kubernetes.example.org:8443
  vars: {}

Hemen interesatzen zaigu batez ere espez.inguruak, qbec-ek jada ingurune lehenetsi bat sortu digu eta zerbitzariaren helbidea hartu du, baita izen-espazioa ere gure egungo kubeconfig-etik.
Orain zabaltzean lehenetsi ingurunean, qbec-ek zehaztutako Kubernetes klusterera eta zehaztutako izen-espaziora soilik zabalduko du beti, hau da, jada ez duzu testuinguru eta izen-espazio batetik bestera aldatu behar inplementazio bat egiteko.
Beharrezkoa izanez gero, fitxategi honetako ezarpenak beti egunera ditzakezu.

Zure ingurune guztiak deskribatzen dira qbec.yaml, eta fitxategian params.libsonnet, non haien parametroak non lortu dioen.

Hurrengo bi direktorio ikusiko ditugu:

  • osagaiak/ — Gure aplikaziorako manifestu guztiak hemen gordeko dira; jsonnet zein yaml fitxategi arruntetan deskriba daitezke
  • inguruneak/ — hemen gure inguruneetarako aldagai (parametro) guztiak deskribatuko ditugu.

Lehenespenez, bi fitxategi ditugu:

  • inguruneak/base.libsonnet - ingurune guztietarako parametro komunak izango ditu
  • inguruneak/default.libsonnet — ingurunerako baliogabetutako parametroak ditu lehenetsi

ireki gaitezen inguruneak/base.libsonnet eta gehitu gure lehen osagaiaren parametroak bertan:

{
  components: {
    website: {
      name: 'example-docs',
      image: 'registry.gitlab.com/kvaps/docs.example.org/website:v0.0.1',
      replicas: 1,
      containerPort: 80,
      servicePort: 80,
      nodeSelector: {},
      tolerations: [],
      ingressClass: 'nginx',
      domain: 'docs.example.org',
    },
  },
}

Sor dezagun gure lehen osagaia ere osagaiak/webgunea.jsonnet:

local env = {
  name: std.extVar('qbec.io/env'),
  namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.website;

[
  {
    apiVersion: 'apps/v1',
    kind: 'Deployment',
    metadata: {
      labels: { app: params.name },
      name: params.name,
    },
    spec: {
      replicas: params.replicas,
      selector: {
        matchLabels: {
          app: params.name,
        },
      },
      template: {
        metadata: {
          labels: { app: params.name },
        },
        spec: {
          containers: [
            {
              name: 'darkhttpd',
              image: params.image,
              ports: [
                {
                  containerPort: params.containerPort,
                },
              ],
            },
          ],
          nodeSelector: params.nodeSelector,
          tolerations: params.tolerations,
          imagePullSecrets: [{ name: 'regsecret' }],
        },
      },
    },
  },
  {
    apiVersion: 'v1',
    kind: 'Service',
    metadata: {
      labels: { app: params.name },
      name: params.name,
    },
    spec: {
      selector: {
        app: params.name,
      },
      ports: [
        {
          port: params.servicePort,
          targetPort: params.containerPort,
        },
      ],
    },
  },
  {
    apiVersion: 'extensions/v1beta1',
    kind: 'Ingress',
    metadata: {
      annotations: {
        'kubernetes.io/ingress.class': params.ingressClass,
      },
      labels: { app: params.name },
      name: params.name,
    },
    spec: {
      rules: [
        {
          host: params.domain,
          http: {
            paths: [
              {
                backend: {
                  serviceName: params.name,
                  servicePort: params.servicePort,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

Fitxategi honetan Kuberneteseko hiru entitate deskribatu ditugu aldi berean, hauek dira: Inplementazio, zerbitzua и Ingress. Nahi izanez gero, osagai ezberdinetan jar genitzake, baina fase honetan bat nahikoa izango zaigu.

sintaxia jsonnet json arruntaren oso antzekoa da, printzipioz, json arrunta jsonnet baliozkoa da dagoeneko, beraz, hasieran errazagoa izan daiteke lineako zerbitzuak erabiltzea bezalako yaml2json zure ohiko yaml json bihurtzeko, edo, zure osagaiek aldagairik ez badute, orduan yaml arruntaren moduan deskriba daitezke.

Lanean ari zarenean jsonnet Zure editorerako plugin bat instalatzea gomendatzen dut

Adibidez, vim-erako plugin bat dago vim-jsonnet, sintaxia nabarmentzea aktibatzen duena eta automatikoki exekutatzen duena jsonnet fmt gordetzen duzun bakoitzean (jsonnet instalatu behar da).

Dena prest dago, orain inplementatzen has gaitezke:

Zer lortu dugun ikusteko, egin dezagun korrika:

qbec show default

Irteeran, lehenetsitako clusterra aplikatuko diren yaml manifestuak ikusiko dituzu.

Bikaina, orain aplikatu:

qbec apply default

Irteeran beti ikusiko duzu zer egingo den zure klusterrean, qbec-ek aldaketak onartzeko eskatuko dizu idatziz y zure asmoak berretsi ahal izango dituzu.

Gure aplikazioa prest eta zabalduta dago!

Aldaketak egiten badituzu, beti egin dezakezu:

qbec diff default

aldaketa hauek egungo hedapenari nola eragingo dioten ikusteko

Ez ahaztu gure aldaketak konprometitzea:

cd ../..
git add deploy/website
git commit -m "Add deploy for website"

5. Gitlab-runner probatzen Kubernetes-executor-ekin

Duela gutxi arte ohikoa baino ez nuen erabiltzen gitlab-runner aurrez prestatutako makina batean (LXC edukiontzia) shell edo docker-exekutorearekin. Hasieran, gure gitlab-en globalki definitutako hainbat korrikalari genituen. Docker irudiak bildu zituzten proiektu guztietarako.

Baina praktikak erakutsi duen moduan, aukera hau ez da egokiena, bai praktikotasunari bai segurtasunari dagokionez. Askoz hobea da eta ideologikoki zuzenagoa da proiektu bakoitzerako, edota ingurune bakoitzerako, korrikalari bereiziak hedatzea.

Zorionez, hau ez da batere arazorik, orain zabalduko baitugu gitlab-runner zuzenean gure proiektuaren parte gisa Kubernetes-en.

Gitlab-ek prest egindako lema-diagrama eskaintzen du gitlab-runner Kubernetes-en zabaltzeko. Beraz, egin behar duzun guztia jakitea da izena emateko tokena gure proiekturako Ezarpenak -> CI / CD -> Korrikalariak eta pasa ezazu lemara:

helm repo add gitlab https://charts.gitlab.io

helm install gitlab-runner 
  --set gitlabUrl=https://gitlab.com 
  --set runnerRegistrationToken=yga8y-jdCusVDn_t4Wxc 
  --set rbac.create=true 
  gitlab/gitlab-runner

Non:

  • https://gitlab.com — zure Gitlab zerbitzariaren helbidea.
  • yga8y-jdCusVDn_t4Wxc — zure proiekturako erregistratzeko tokena.
  • rbac.create=egia — Korrikalariari beharrezko pribilegioak ematen dizkio kubernetes-executor erabiliz gure zereginak egiteko pod-ak sortu ahal izateko.

Dena ondo egiten bada, izena emanda dagoen korrikalari bat ikusi beharko zenuke atalean Korrikalariek, zure proiektuaren ezarpenetan.

Gehitutako korrikalariaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Hain sinplea al da? - Bai, hain erraza da! Ez da arazorik lasterkariak eskuz erregistratzeko, hemendik aurrera korrikalariak automatikoki sortu eta suntsitu egingo dira.

6. Inplementatu Helm diagramak QBEC-ekin

Kontuan hartzea erabaki genuenetik gitlab-runner gure proiektuaren parte, gure Git biltegian deskribatzeko garaia da.

Osagai bereizi gisa deskriba genezake , baina etorkizunean kopia desberdinak zabaltzeko asmoa dugu askotan, ez bezala gitlab-runner, behin bakarrik zabalduko dena Kubernetes kluster bakoitzeko. Beraz, hasieratu dezagun aplikazio berezi bat:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Oraingoan ez ditugu Kubernetes entitateak eskuz deskribatuko, baina prest egindako Helm diagrama bat hartuko dugu. qbec-en abantailetako bat Helm diagramak Git biltegitik zuzenean errendatzeko gaitasuna da.

Konektatu dezagun git azpimodulua erabiliz:

git submodule add https://gitlab.com/gitlab-org/charts/gitlab-runner vendor/gitlab-runner

Orain direktorioa saltzailea/gitlab-runner Biltegi bat dugu gitlab-runner-erako diagrama batekin.

Era berean, beste biltegi batzuk konekta ditzakezu, adibidez, biltegi osoa diagrama ofizialekin https://github.com/helm/charts

Deskriba dezagun osagaia components/gitlab-runner.jsonnet:

local env = {
  name: std.extVar('qbec.io/env'),
  namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.gitlabRunner;

std.native('expandHelmTemplate')(
  '../vendor/gitlab-runner',
  params.values,
  {
    nameTemplate: params.name,
    namespace: env.namespace,
    thisFile: std.thisFile,
    verbose: true,
  }
)

Lehenengo argudioa zabaldu HelmTemplate diagramarako bidea pasatzen dugu, orduan parametroak.balioak, inguruneko parametroetatik hartzen duguna, gero objektua dator

  • izena Txantiloia - askapenaren izena
  • namespace — izen-espazioa helm-era transferitu da
  • Fitxategi hau — uneko fitxategirako bidea pasatzen duen beharrezko parametroa
  • berbak - komandoa erakusten du lema txantiloia diagrama errendatzerakoan argumentu guztiekin

Orain deskriba ditzagun gure osagaiaren parametroak inguruneak/base.libsonnet:

local secrets = import '../secrets/base.libsonnet';

{
  components: {
    gitlabRunner: {
      name: 'gitlab-runner',
      values: {
        gitlabUrl: 'https://gitlab.com/',
        rbac: {
          create: true,
        },
        runnerRegistrationToken: secrets.runnerRegistrationToken,
      },
    },
  },
}

Arreta ezazu runnerRegistrationToken kanpoko fitxategi batetik hartzen dugu secrets/base.libsonnet, sortu dezagun:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Egiazta dezagun dena funtzionatzen duen:

qbec show default

dena ondo badago, aurretik zabaldutako bertsioa ezabatu dezakegu Helm bidez:

helm uninstall gitlab-runner

eta zabaldu era berean, baina qbec bidez:

qbec apply default

7. Git-crypt-en sarrera

Git-kripta zure biltegirako enkriptazio gardena konfiguratzeko aukera ematen duen tresna da.

Momentuz, gitlab-runner-erako gure direktorio-egiturak hauxe du:

.
├── components
│   ├── gitlab-runner.jsonnet
├── environments
│   ├── base.libsonnet
│   └── default.libsonnet
├── params.libsonnet
├── qbec.yaml
├── secrets
│   └── base.libsonnet
└── vendor
    └── gitlab-runner (submodule)

Baina sekretuak Git-en gordetzea ez da segurua, ezta? Beraz, behar bezala enkriptatu behar ditugu.

Normalean, aldagai baten mesedetan, horrek ez du beti zentzurik. Sekretuak transferi ditzakezu qbec eta zure CI sistemaren ingurune-aldagaien bidez.
Baina nabarmentzekoa da proiektu konplexuagoak ere badirela sekretu gehiago eduki ditzaketenak; horiek guztiak ingurune-aldagaien bidez transferitzea oso zaila izango da.

Gainera, kasu honetan ezingo nuke horrelako tresna zoragarri bati buruz esan git-crypt.

git-crypt Erosoa da, gainera, sekretuen historia osoa gordetzeko aukera ematen baitu, baita gatazkak alderatu, batu eta konpontzeko ere Git-en kasuan ohituta gauden moduan.

Instalatu ondoren lehenengo gauza git-crypt gakoak sortu behar ditugu gure biltegirako:

git crypt init

PGP gako bat baduzu, berehala gehi dezakezu zure burua proiektu honetarako kolaboratzaile gisa:

git-crypt add-gpg-user [email protected]

Horrela, beti deszifratu dezakezu biltegi hau zure gako pribatua erabiliz.

PGP gakorik ez baduzu eta espero ez baduzu, beste aldera joan eta proiektuaren gakoa esportatu dezakezu:

git crypt export-key /path/to/keyfile

Horrela, esportatu duen edonork gako-fitxategia zure biltegia deszifratzeko gai izango da.

Gure lehen sekretua konfiguratzeko garaia da.
Gogorarazten dizut oraindik direktorioan gaudela deploy/gitlab-runner/, non direktorio bat daukagu sekretuak/, zifra ditzagun bertan dauden fitxategi guztiak, horretarako fitxategi bat sortuko dugu sekretuak/.gitattributes eduki honekin:

* filter=git-crypt diff=git-crypt
.gitattributes !filter !diff

Edukian ikus daitekeenez, fitxategi guztiak maskaratuta daude * zeharkatuko da git-crypt, gehienetan izan ezik .gitattributes

Hau egiazta dezakegu exekutatuz:

git crypt status -e

Irteera enkriptatzea gaituta dagoen biltegiko fitxategi guztien zerrenda izango da

Hori da guztia, orain gure aldaketak segurtasunez egin ditzakegu:

cd ../..
git add .
git commit -m "Add deploy for gitlab-runner"

Biltegi bat blokeatzeko, exekutatu:

git crypt lock

eta berehala enkriptatutako fitxategi guztiak zerbait bitar bihurtuko dira, ezinezkoa izango da irakurtzea.
Biltegia deszifratzeko, exekutatu:

git crypt unlock

8. Sortu tresna-kutxaren irudia

Tresna-kutxako irudia gure proiektua zabaltzeko erabiliko ditugun tresna guztiak dituen irudia da. Gitlab-eko korrikalariak erabiliko du inplementazio-zeregin arruntak egiteko.

Hemen dena erraza da, sortu dezagun berri bat dockerfiles/toolbox/Dockerfile eduki honekin:

FROM alpine:3.11

RUN apk add --no-cache git git-crypt

RUN QBEC_VER=0.10.3 
 && wget -O- https://github.com/splunk/qbec/releases/download/v${QBEC_VER}/qbec-linux-amd64.tar.gz 
     | tar -C /tmp -xzf - 
 && mv /tmp/qbec /tmp/jsonnet-qbec /usr/local/bin/

RUN KUBECTL_VER=1.17.0 
 && wget -O /usr/local/bin/kubectl 
      https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/linux/amd64/kubectl 
 && chmod +x /usr/local/bin/kubectl

RUN HELM_VER=3.0.2 
 && wget -O- https://get.helm.sh/helm-v${HELM_VER}-linux-amd64.tar.gz 
     | tar -C /tmp -zxf - 
 && mv /tmp/linux-amd64/helm /usr/local/bin/helm

Ikus dezakezunez, irudi honetan gure aplikazioa zabaltzeko erabili ditugun utilitate guztiak instalatzen ditugu. Ez dugu hemen behar izan ezik kubectl, baina baliteke horrekin jolastu nahi izatea kanalizazioa konfiguratzeko fasean.

Gainera, Kubernetesekin komunikatu eta bertan zabaldu ahal izateko, gitlab-runner-ek sortutako pods-etarako rol bat konfiguratu behar dugu.

Horretarako, goazen direktoriora gitlab-runner-ekin:

cd deploy/gitlab-runner

eta gehitu osagai berri bat osagaiak/rbac.jsonnet:

local env = {
  name: std.extVar('qbec.io/env'),
  namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.rbac;

[
  {
    apiVersion: 'v1',
    kind: 'ServiceAccount',
    metadata: {
      labels: {
        app: params.name,
      },
      name: params.name,
    },
  },
  {
    apiVersion: 'rbac.authorization.k8s.io/v1',
    kind: 'Role',
    metadata: {
      labels: {
        app: params.name,
      },
      name: params.name,
    },
    rules: [
      {
        apiGroups: [
          '*',
        ],
        resources: [
          '*',
        ],
        verbs: [
          '*',
        ],
      },
    ],
  },
  {
    apiVersion: 'rbac.authorization.k8s.io/v1',
    kind: 'RoleBinding',
    metadata: {
      labels: {
        app: params.name,
      },
      name: params.name,
    },
    roleRef: {
      apiGroup: 'rbac.authorization.k8s.io',
      kind: 'Role',
      name: params.name,
    },
    subjects: [
      {
        kind: 'ServiceAccount',
        name: params.name,
        namespace: env.namespace,
      },
    ],
  },
]

Parametro berriak ere deskribatuko ditugu inguruneak/base.libsonnet, orain itxura hau duena:

local secrets = import '../secrets/base.libsonnet';

{
  components: {
    gitlabRunner: {
      name: 'gitlab-runner',
      values: {
        gitlabUrl: 'https://gitlab.com/',
        rbac: {
          create: true,
        },
        runnerRegistrationToken: secrets.runnerRegistrationToken,
        runners: {
          serviceAccountName: $.components.rbac.name,
          image: 'registry.gitlab.com/kvaps/docs.example.org/toolbox:v0.0.1',
        },
      },
    },
    rbac: {
      name: 'gitlab-runner-deploy',
    },
  },
}

Arreta ezazu $.components.rbac.name aipatzen du izena osagairako rbac

Ikus dezagun zer aldatu den:

qbec diff default

eta aplikatu gure aldaketak Kubernetes-en:

qbec apply default

Gainera, ez ahaztu gure aldaketak git-en konprometitzea:

cd ../..
git add dockerfiles/toolbox
git commit -m "Add Dockerfile for toolbox"
git add deploy/gitlab-runner
git commit -m "Configure gitlab-runner to use toolbox"

9. Gure lehen kanalizazioa eta irudien muntaia etiketen bidez

Proiektuaren oinarrian sortuko dugu .gitlab-ci.yml eduki honekin:

.build_docker_image:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug-v0.15.0
    entrypoint: [""]
  before_script:
    - echo "{"auths":{"$CI_REGISTRY":{"username":"$CI_REGISTRY_USER","password":"$CI_REGISTRY_PASSWORD"}}}" > /kaniko/.docker/config.json

build_toolbox:
  extends: .build_docker_image
  script:
    - /kaniko/executor --cache --context $CI_PROJECT_DIR/dockerfiles/toolbox --dockerfile $CI_PROJECT_DIR/dockerfiles/toolbox/Dockerfile --destination $CI_REGISTRY_IMAGE/toolbox:$CI_COMMIT_TAG
  only:
    refs:
      - tags

build_website:
  extends: .build_docker_image
  variables:
    GIT_SUBMODULE_STRATEGY: normal
  script:
    - /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_TAG
  only:
    refs:
      - tags

Kontuan izan erabiltzen dugula GIT_SUBMODULE_STRATEGY: normala exekutatu aurretik azpimoduluak espresuki hasieratu behar dituzun lanetarako.

Ez ahaztu gure aldaketak konprometitzea:

git add .gitlab-ci.yml
git commit -m "Automate docker build"

Uste dut seguru dei dezakegula honi bertsio bat v0.0.1 eta gehitu etiketa:

git tag v0.0.1

Etiketak gehituko ditugu bertsio berri bat kaleratu behar dugunean. Docker irudietako etiketak Git etiketekin lotuko dira. Etiketa berri bat duen bultzada bakoitzak etiketa honekin irudien eraikuntza hasieratuko du.

Egin dezagun git push --tags, eta ikus dezagun gure lehen kanalizazioa:

Lehen kanalizazioaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Merezi du arreta erakartzea etiketen bidez muntatzea docker irudiak eraikitzeko egokia dela, baina ez dela egokia Kubernetesen aplikazio bat zabaltzeko. Konpromiso zaharrei etiketa berriak esleitu daitezkeenez, kasu honetan, horien kanalizazioa hasieratzeak bertsio zaharra hedatzea ekarriko du.

Arazo hau konpontzeko, normalean docker irudien eraikuntza etiketekin lotzen da, eta aplikazioa adar batean zabaltzea. master, bildutako irudien bertsioak gogor kodetzen diren. Hau da, non abiaraz dezakezu itzulera itzulera sinple batekin master- adarrak.

10. Hedapenaren automatizazioa

Gitlab-runner-ek gure sekretuak deszifratu ahal izateko, biltegiaren gakoa esportatu eta gure CI inguruneko aldagaietan gehitu beharko dugu:

git crypt export-key /tmp/docs-repo.key
base64 -w0 /tmp/docs-repo.key; echo

Sortutako lerroa Gitlab-en gordeko dugu; horretarako, joan gaitezen gure proiektuaren ezarpenetara:
Ezarpenak -> CI / CD -> Aldagaiak

Eta sor dezagun aldagai berri bat:

Mota
Key
Balio
Babestutako
mozorro
Scope

File
GITCRYPT_KEY
<your string>
true (Ahal duzun prestakuntzan false)
true
All environments

Gehitutako aldagaiaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Orain egunera dezagun gure .gitlab-ci.yml horri gehituz:

.deploy_qbec_app:
  stage: deploy
  only:
    refs:
      - master

deploy_gitlab_runner:
  extends: .deploy_qbec_app
  variables:
    GIT_SUBMODULE_STRATEGY: normal
  before_script:
    - base64 -d "$GITCRYPT_KEY" | git-crypt unlock -
  script:
    - qbec apply default --root deploy/gitlab-runner --force:k8s-context __incluster__ --wait --yes

deploy_website:
  extends: .deploy_qbec_app
  script:
    - qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes

Hemen qbec-erako hainbat aukera berri gaitu ditugu:

  • --root some/app — aplikazio zehatz baten direktorioa zehazteko aukera ematen du
  • --force:k8s-context __incluster__ - hau gtilab-runner exekutatzen ari den kluster berean egingo dela dioen aldagai magiko bat da. Hau beharrezkoa da, bestela qbec zure kubeconfig-en Kubernetes zerbitzari egoki bat bilatzen saiatuko delako
  • --itxaron — qbec-ek sortzen dituen baliabideak Prest egoerara joan arte itxarontzera behartzen du eta gero irtetera irtetera behartzen du irteera-kode arrakastatsu batekin.
  • —bai - shell interaktiboa desgaitzen du Ziur zaude? zabaldutakoan.

Ez ahaztu gure aldaketak konprometitzea:

git add .gitlab-ci.yml
git commit -m "Automate deploy"

Eta ondoren git push gure aplikazioak nola zabaldu diren ikusiko dugu:

Bigarren kanalizazioaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

11. Artefaktuak eta muntaketa maisua bultzatzean

Normalean, goian deskribatutako urratsak nahikoak dira ia edozein mikrozerbitzu eraikitzeko eta emateko, baina ez dugu etiketarik gehitu nahi gunea eguneratu behar dugun bakoitzean. Hori dela eta, ibilbide dinamikoagoa hartuko dugu eta digestio-inplementazioa ezarriko dugu master adarrean.

Ideia sinplea da: orain gure irudia sartzen zaren bakoitzean berreraikiko da master, eta gero automatikoki zabaldu Kubernetes-en.

Eguneratu ditzagun bi lan hauek gurean .gitlab-ci.yml:

build_website:
  extends: .build_docker_image
  variables:
    GIT_SUBMODULE_STRATEGY: normal
  script:
    - mkdir -p $CI_PROJECT_DIR/artifacts
    - /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_REF_NAME --digest-file $CI_PROJECT_DIR/artifacts/website.digest
  artifacts:
    paths:
      - artifacts/
  only:
    refs:
      - master
      - tags

deploy_website:
  extends: .deploy_qbec_app
  script:
    - DIGEST="$(cat artifacts/website.digest)"
    - qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"

Kontuan izan hari bat gehitu dugula master к refs lanpostuetarako eraiki_webgunea eta orain erabiltzen dugu $CI_COMMIT_REF_NAME ordez $CI_COMMIT_TAG, hau da, Git-en etiketetatik askatuta gaude eta orain kanalizazioa hasieratu duen commit-adarraren izena duen irudi bat bultzatuko dugu. Aipatzekoa da hau etiketekin ere funtzionatuko duela, eta horri esker, bertsio zehatz bat duen gune baten argazkiak docker-erregistroan gordetzeko aukera izango dugu.

Gunearen bertsio berri baten docker etiketaren izena aldatu gabe egon daitekeenean, oraindik Kubernetes-en egindako aldaketak deskribatu behar ditugu, bestela ez du aplikazioa irudi berritik berriro zabalduko, ez baitu inplementazioan aldaketarik nabarituko. manifestua.

Aukera —vm:ext-str digest="$DIGEST" qbec-erako - kanpoko aldagai bat jsonnet-era pasatzeko aukera ematen du. Gure aplikazioaren bertsio bakoitzarekin klusterrean berriro zabaltzea nahi dugu. Jada ezin dugu erabili etiketaren izena, orain aldaezina izan daitekeena, irudiaren bertsio zehatz bati lotuta egon behar baitugu eta hura aldatzen denean hedapena piztu.

Hemen Kanikok digestio-irudi bat fitxategi batean gordetzeko duen gaitasunak lagunduko digu (aukera --digest-fitxategia)
Ondoren, fitxategi hau transferituko dugu eta zabalduko den unean irakurriko dugu.

Eguneratu ditzagun gure parametroak deploy/website/environments/base.libsonnet orain itxura hau izango duena:

{
  components: {
    website: {
      name: 'example-docs',
      image: 'registry.gitlab.com/kvaps/docs.example.org/website@' + std.extVar('digest'),
      replicas: 1,
      containerPort: 80,
      servicePort: 80,
      nodeSelector: {},
      tolerations: [],
      ingressClass: 'nginx',
      domain: 'docs.example.org',
    },
  },
}

Eginda, orain edozein konpromiso sartu master Docker irudiaren eraikuntza hasieratzen du , eta gero zabaldu Kubernetesen.

Ez ahaztu gure aldaketak konprometitzea:

git add .
git commit -m "Configure dynamic build"

Geroago egiaztatuko dugu git push honelako zerbait ikusi beharko genuke:

Masterrentzako kanalizazioaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Printzipioz, ez dugu gitlab-runner berriro zabaldu behar bultzada bakoitzean, ez bada, jakina, ezer aldatu bere konfigurazioan, konpon dezagun. .gitlab-ci.yml:

deploy_gitlab_runner:
  extends: .deploy_qbec_app
  variables:
    GIT_SUBMODULE_STRATEGY: normal
  before_script:
    - base64 -d "$GITCRYPT_KEY" | git-crypt unlock -
  script:
    - qbec apply default --root deploy/gitlab-runner --force:k8s-context __incluster__ --wait --yes
  only:
    changes:
      - deploy/gitlab-runner/**/*

aldaketak aldaketak kontrolatzeko aukera emango dizu deploy/gitlab-runner/ eta gure lana abiaraziko du halakorik balego

Ez ahaztu gure aldaketak konprometitzea:

git add .gitlab-ci.yml
git commit -m "Reduce gitlab-runner deploy"

git push, hori hobe:

Eguneratutako kanalizazioaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

12. Ingurune dinamikoak

Gure kanalizazioa ingurune dinamikoekin dibertsifikatzeko garaia da.

Lehenik eta behin, egunera dezagun lana eraiki_webgunea gurean .gitlab-ci.yml, blokea kenduz bakarrik, Gitlab-ek edozein adarretako edozein konpromisotan abiarazteko behartuko duena:

build_website:
  extends: .build_docker_image
  variables:
    GIT_SUBMODULE_STRATEGY: normal
  script:
    - mkdir -p $CI_PROJECT_DIR/artifacts
    - /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_REF_NAME --digest-file $CI_PROJECT_DIR/artifacts/website.digest
  artifacts:
    paths:
      - artifacts/

Ondoren, eguneratu lana zabaldu_webgunea, gehitu bloke bat hor ingurumena:

deploy_website:
  extends: .deploy_qbec_app
  environment:
    name: prod
    url: https://docs.example.org
  script:
    - DIGEST="$(cat artifacts/website.digest)"
    - qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"

Honek Gitlab-i lana lotzea ahalbidetuko dio prod ingurunea eta bistaratu harako esteka zuzena.

Orain gehi ditzagun beste bi lan:

deploy_website:
  extends: .deploy_qbec_app
  environment:
    name: prod
    url: https://docs.example.org
  script:
    - DIGEST="$(cat artifacts/website.digest)"
    - qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"

deploy_review:
  extends: .deploy_qbec_app
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: http://$CI_ENVIRONMENT_SLUG.docs.example.org
    on_stop: stop_review
  script:
    - DIGEST="$(cat artifacts/website.digest)"
    - qbec apply review --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST" --vm:ext-str subdomain="$CI_ENVIRONMENT_SLUG" --app-tag "$CI_ENVIRONMENT_SLUG"
  only:
    refs:
    - branches
  except:
    refs:
      - master

stop_review:
  extends: .deploy_qbec_app
  environment:
    name: review/$CI_COMMIT_REF_NAME
    action: stop
  stage: deploy
  before_script:
    - git clone "$CI_REPOSITORY_URL" master
    - cd master
  script:
    - qbec delete review --root deploy/website --force:k8s-context __incluster__ --yes --vm:ext-str digest="$DIGEST" --vm:ext-str subdomain="$CI_ENVIRONMENT_SLUG" --app-tag "$CI_ENVIRONMENT_SLUG"
  variables:
    GIT_STRATEGY: none
  only:
    refs:
    - branches
  except:
    refs:
      - master
  when: manual

Bultzatzean abiaraziko dira edozein adarretara izan ezik, eta gunearen aurrebista bertsioa zabalduko dute.

Qbec-erako aukera berri bat ikusten dugu: --app-etiketa — aplikazioaren inplementatutako bertsioak etiketatzeko eta etiketa honen barruan bakarrik lan egiteko aukera ematen du; Kubernetes-en baliabideak sortu eta suntsitzean, qbec-ek haiekin bakarrik funtzionatuko du.
Horrela, ezin dugu berrikuspen bakoitzeko ingurune bereizi bat sortu, baizik eta bera berrerabili.

Hemen ere erabiltzen dugu qbec aplikatu berrikuspena, ordez qbec aplikatu lehenetsia - Hauxe da gure inguruneetarako desberdintasunak deskribatzen saiatuko garen unea (berrikuspena eta lehenetsia):

gehitu berrikusi ingurunean deploy/website/qbec.yaml

spec:
  environments:
    review:
      defaultNamespace: docs
      server: https://kubernetes.example.org:8443

Orduan deklaratuko dugu deploy/website/params.libsonnet:

local env = std.extVar('qbec.io/env');
local paramsMap = {
  _: import './environments/base.libsonnet',
  default: import './environments/default.libsonnet',
  review: import './environments/review.libsonnet',
};

if std.objectHas(paramsMap, env) then paramsMap[env] else error 'environment ' + env + ' not defined in ' + std.thisFile

Eta idatzi horretarako parametro pertsonalizatuak deploy/website/environments/review.libsonnet:

// this file has the param overrides for the default environment
local base = import './base.libsonnet';
local slug = std.extVar('qbec.io/tag');
local subdomain = std.extVar('subdomain');

base {
  components+: {
    website+: {
      name: 'example-docs-' + slug,
      domain: subdomain + '.docs.example.org',
    },
  },
}

Ikus diezaiogun ere gertuagotik jobu stop_review, adarra ezabatzean abiaraziko da eta gitlab-ek egiaztatzen saiatu ez dadin, erabiltzen da GIT_STRATEGY: bat ere ez, geroago klonatzen dugu master-adar eta ezabatu berrikuspena haren bidez.
Pixka bat nahasia da, baina oraindik ez dut bide politagoa aurkitu.
Aukera alternatibo bat berrikuspen bakoitza hoteleko izen-espazio batean zabaltzea litzateke, beti erabat eraitsi daitekeena.

Ez ahaztu gure aldaketak konprometitzea:

git add .
git commit -m "Enable automatic review"

git push, git checkout -b proba, git push jatorriaren proba, egiaztatu:

Gitlab-en sortutako inguruneen pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Dena dabil? - bikaina, ezabatu gure proba-adarra: git checkout maisua, git push jatorria :test, ingurumena ezabatzeko lanek akatsik gabe funtzionatu dutela egiaztatzen dugu.

Hemen berehala argitu nahiko nuke proiektu bateko edozein garatzaileek adarrak sor ditzakeela, bera ere alda daitekeela .gitlab-ci.yml fitxategia eta aldagai sekretuak atzitu.
Hori dela eta, oso gomendagarria da babestutako adarretarako soilik erabiltzea baimentzea, adibidez master, edo sortu aldagai-multzo bereizi bat ingurune bakoitzerako.

13. Berrikusi aplikazioak

Berrikusi aplikazioak Hau GitLab-en eginbide bat da, biltegiko fitxategi bakoitzeko botoi bat gehitzeko aukera ematen duena, inplementatutako ingurune batean azkar ikusteko.

Botoi hauek agertzeko, fitxategi bat sortu behar duzu .gitlab/route-map.yml eta deskribatu bertan bide-eraldaketa guztiak; gure kasuan oso erraza izango da:

# Indices
- source: /content/(.+?)_index.(md|html)/ 
  public: '1'

# Pages
- source: /content/(.+?).(md|html)/ 
  public: '1/'

Ez ahaztu gure aldaketak konprometitzea:

git add .gitlab/
git commit -m "Enable review apps"

git push, eta egiaztatu:

Berrikusi aplikazioa botoiaren pantaila-argazkia

Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Lana eginda dago!

Proiektuaren iturriak:

Eskerrik asko zure arretagatik, espero dut gustatu izana Kubernetesen inplementazioa eraikitzeko eta automatizatzeko tresna berriak probatzen

Iturria: www.habr.com

Gehitu iruzkin berria