Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Përshëndetje! Kohët e fundit, shumë mjete të lezetshme të automatizimit janë lëshuar si për ndërtimin e imazheve të Docker ashtu edhe për vendosjen në Kubernetes. Në këtë drejtim, vendosa të luaj me GitLab, të studioj plotësisht aftësitë e tij dhe, natyrisht, të vendos tubacionin.

Kjo punë është frymëzuar nga faqja e internetit kubernetes.io, e cila krijohet nga kodet burimore automatikisht dhe për çdo kërkesë për grup të dërguar, roboti gjeneron automatikisht një version paraprak të faqes me ndryshimet tuaja dhe ofron një lidhje për shikim.

Unë u përpoqa të ndërtoj një proces të ngjashëm nga e para, por i ndërtuar tërësisht në Gitlab CI dhe mjete falas që jam mësuar t'i përdor për të vendosur aplikacione në Kubernetes. Sot më në fund do t'ju tregoj më shumë rreth tyre.

Artikulli do të diskutojë mjete të tilla si:
Hugo, qbec, kaniko, git-crypt и GitLab CI me krijimin e mjediseve dinamike.

Përmbajtje

  1. Njihuni me Hugo
  2. Përgatitja e skedarit Docker
  3. Njohja me kaniko
  4. Njohja me qbec
  5. Duke provuar Gitlab-runner me Kubernetes-executor
  6. Vendosja e tabelave të Helm me qbec
  7. Prezantimi i git-crypt
  8. Krijimi i një imazhi të kutisë së veglave
  9. Tubacioni ynë i parë dhe montimi i imazheve sipas etiketave
  10. Automatizimi i vendosjes
  11. Artefakte dhe montim kur shtyni për të zotëruar
  12. Mjedise dinamike
  13. Rishikoni aplikacionet

1. Njohja me Hugo

Si shembull i projektit tonë, ne do të përpiqemi të krijojmë një faqe publikimi dokumentacioni të ndërtuar mbi Hugo. Hugo është një gjenerues i përmbajtjes statike.

Për ata që nuk janë të njohur me gjeneratorët statikë, do t'ju tregoj pak më shumë rreth tyre. Ndryshe nga motorët e zakonshëm të uebsajteve me një bazë të dhënash dhe disa PHP, të cilat, kur kërkohet nga një përdorues, gjenerojnë faqe në fluturim, gjeneratorët statikë janë projektuar pak më ndryshe. Ato ju lejojnë të merrni burime, zakonisht një grup skedarësh në markup-in dhe shabllonet e temave të Markdown, pastaj t'i përpiloni ato në një faqe interneti plotësisht të përfunduar.

Kjo do të thotë, si rezultat, ju do të merrni një strukturë drejtorie dhe një grup skedarësh HTML të krijuar, të cilat thjesht mund t'i ngarkoni në çdo host të lirë dhe të merrni një faqe interneti funksionale.

Mund ta instaloni Hugo në nivel lokal dhe ta provoni:

Inicializimi i një faqeje të re:

hugo new site docs.example.org

Dhe në të njëjtën kohë depoja e git:

cd docs.example.org
git init

Deri më tani, faqja jonë është e pacenuar dhe në mënyrë që diçka të shfaqet në të, së pari duhet të lidhim një temë; një temë është vetëm një grup shabllonesh dhe rregullash të specifikuara me të cilat krijohet faqja jonë.

Për temën që do të përdorim Mësoj, e cila, për mendimin tim, është e përshtatshme për një vend dokumentimi.

Do të doja t'i kushtoja vëmendje të veçantë faktit që nuk kemi nevojë të ruajmë skedarët e temave në depon e projektit tonë; në vend të kësaj, ne thjesht mund ta lidhim atë duke përdorur nënmodul git:

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

Kështu, depoja jonë do të përmbajë vetëm skedarë që lidhen drejtpërdrejt me projektin tonë, dhe tema e lidhur do të mbetet si një lidhje me një depo specifike dhe një angazhim në të, domethënë, gjithmonë mund të tërhiqet nga burimi origjinal dhe të mos ketë frikë nga ndryshime të papajtueshme.

Le të korrigjojmë konfigurimin konfigurim.toml:

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

Tashmë në këtë fazë mund të vraponi:

hugo server

Dhe në adresën http://localhost:1313/ kontrolloni faqen tonë të krijuar rishtazi, të gjitha ndryshimet e bëra në drejtori përditësojnë automatikisht faqen e hapur në shfletues, shumë i përshtatshëm!

Le të përpiqemi të krijojmë një faqe kopertine përmbajtje/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Pamja e ekranit të faqes së krijuar rishtazi

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Për të krijuar një faqe, thjesht ekzekutoni:

hugo

Përmbajtja e drejtorisë publike/ dhe do të jetë faqja juaj e internetit.
Po, meqë ra fjala, le ta shtojmë menjëherë .gitignore:

echo /public > .gitignore

Mos harroni të bëni ndryshimet tona:

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

2. Përgatitja e skedarit Docker

Është koha për të përcaktuar strukturën e depove tona. Unë zakonisht përdor diçka si:

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

  • dockerfiles/ — përmbajnë direktori me Dockerfiles dhe gjithçka të nevojshme për ndërtimin e imazheve tona Docker.
  • vendos/ — përmban direktori për vendosjen e aplikacioneve tona në Kubernetes

Kështu, ne do të krijojmë Dockerfile-in tonë të parë përgjatë rrugës dockerfiles/website/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" ]

Siç mund ta shihni, Dockerfile përmban dy NGA, kjo mundësi quhet ndërtim me shumë faza dhe ju lejon të përjashtoni gjithçka të panevojshme nga imazhi përfundimtar i Docker.
Kështu, imazhi përfundimtar do të përmbajë vetëm errëthttpd (server i lehtë HTTP) dhe publike/ — përmbajtja e faqes sonë të internetit të krijuar në mënyrë statike.

Mos harroni të bëni ndryshimet tona:

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

3. Njohja me kaniko

Si ndërtues i imazheve docker, vendosa të përdor kaniko, meqenëse funksionimi i tij nuk kërkon një daemon docker, dhe vetë ndërtimi mund të kryhet në çdo makinë dhe cache mund të ruhet direkt në regjistër, duke eliminuar kështu nevojën për të pasur një ruajtje të vazhdueshme të plotë.

Për të ndërtuar imazhin, thjesht drejtoni kontejnerin me të kaniko ekzekutor dhe ia kaloni kontekstin aktual të ndërtimit; kjo mund të bëhet gjithashtu në nivel lokal, nëpërmjet docker:

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

ku registry.gitlab.com/kvaps/docs.example.org/website — emri i imazhit tuaj doker; pas ndërtimit, ai do të futet automatikisht në regjistrin e dokerit.

Parametër --cache ju lejon të ruani shtresat në regjistrin e dokerit; për shembullin e dhënë, ato do të ruhen registry.gitlab.com/kvaps/docs.example.org/website/cache, por mund të specifikoni një shteg tjetër duke përdorur parametrin --cache-repo.

Pamja e ekranit të regjistrit docker

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

4. Njohja me qbec

Qbec është një mjet vendosjeje që ju lejon të përshkruani në mënyrë deklarative manifestet e aplikacionit tuaj dhe t'i vendosni ato në Kubernetes. Përdorimi i Jsonnet si sintaksë kryesore ju lejon të thjeshtoni shumë përshkrimin e dallimeve në mjedise të shumta, dhe gjithashtu eliminon pothuajse plotësisht përsëritjen e kodit.

Kjo mund të jetë veçanërisht e vërtetë në rastet kur ju duhet të vendosni një aplikacion në disa grupe me parametra të ndryshëm dhe dëshironi t'i përshkruani ato në mënyrë deklarative në Git.

Qbec gjithashtu ju lejon të jepni diagramet Helm duke u kaluar atyre parametrat e nevojshëm dhe më pas t'i përdorni ato në të njëjtën mënyrë si manifestet e rregullta, duke përfshirë ju mund të aplikoni mutacione të ndryshme në to, dhe kjo, nga ana tjetër, ju lejon të heqni qafe nevojën për të përdorni ChartMuseum. Kjo do të thotë, ju mund të ruani dhe jepni grafikët direkt nga git, ku ato bëjnë pjesë.

Siç thashë më herët, ne do t'i ruajmë të gjitha vendosjet në një direktori vendos/:

mkdir deploy
cd deploy

Le të inicializojmë aplikacionin tonë të parë:

qbec init website
cd website

Tani struktura e aplikacionit tonë duket si kjo:

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

le të shohim dosjen qbec.yaml:

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

Këtu ne jemi të interesuar në radhë të parë spec.mjedise, qbec ka krijuar tashmë një mjedis të paracaktuar për ne dhe ka marrë adresën e serverit, si dhe hapësirën e emrave nga kubeconfig ynë aktual.
Tani kur vendoset në parazgjedhur mjedisi, qbec do të vendoset gjithmonë vetëm në grupin e specifikuar të Kubernetes dhe në hapësirën e specifikuar të emrave, domethënë, nuk duhet të kaloni më midis konteksteve dhe hapësirave të emrave për të kryer një vendosje.
Nëse është e nevojshme, gjithmonë mund të përditësoni cilësimet në këtë skedar.

Të gjitha mjediset tuaja përshkruhen në qbec.yaml, dhe në dosje params.libsonnet, ku thotë se ku mund të merren parametrat për ta.

Më pas shohim dy drejtori:

  • komponentet / - të gjitha manifestet për aplikacionin tonë do të ruhen këtu; ato mund të përshkruhen si në skedarë jsonnet ashtu edhe në skedarë të rregullt yaml
  • mjedise/ — këtu do të përshkruajmë të gjitha variablat (parametrat) për mjediset tona.

Si parazgjedhje kemi dy skedarë:

  • mjedise/bazë.libsonnet - do të përmbajë parametra të përbashkët për të gjitha mjediset
  • mjediset/default.libsonnet — përmban parametra të anashkaluar për mjedisin parazgjedhur

le të hapim mjedise/bazë.libsonnet dhe shtoni parametra për komponentin tonë të parë atje:

{
  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',
    },
  },
}

Le të krijojmë gjithashtu komponentin tonë të parë komponentët/faqja e internetit.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,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

Në këtë skedar kemi përshkruar tre entitete Kubernetes menjëherë, këto janë: shpërndarje, Shërbime и Hyrje. Nëse dëshironim, mund t'i vendosnim në komponentë të ndryshëm, por në këtë fazë një do të na mjaftojë.

sintaksë jsonnet është shumë e ngjashme me json të rregullt, në parim, json i rregullt tashmë është i vlefshëm jsonnet, kështu që në fillim mund të jetë më e lehtë për ju të përdorni shërbime në internet si p.sh. yaml2json për të kthyer yaml-in tuaj të zakonshëm në json, ose, nëse komponentët tuaj nuk përmbajnë ndonjë ndryshore, atëherë ato mund të përshkruhen në formën e yaml-it të rregullt.

Kur punoni me jsonnet Unë rekomandoj shumë të instaloni një shtojcë për redaktorin tuaj

Për shembull, ekziston një shtojcë për vim vim-jsonnet, i cili aktivizon theksimin e sintaksës dhe ekzekutohet automatikisht jsonnet fmt sa herë që kurseni (kërkon të instaluar jsonnet).

Gjithçka është gati, tani mund të fillojmë vendosjen:

Për të parë se çfarë kemi, le të vrapojmë:

qbec show default

Në dalje, do të shihni manifeste të renderuara yaml që do të aplikohen në grupin e paracaktuar.

E shkëlqyeshme, tani aplikoni:

qbec apply default

Në dalje do të shihni gjithmonë se çfarë do të bëhet në grupin tuaj, qbec do t'ju kërkojë të pajtoheni me ndryshimet duke shtypur y do të jeni në gjendje të konfirmoni qëllimet tuaja.

Aplikacioni ynë është gati dhe i vendosur!

Nëse bëni ndryshime, gjithmonë mund të bëni:

qbec diff default

për të parë se si këto ndryshime do të ndikojnë në vendosjen aktuale

Mos harroni të bëni ndryshimet tona:

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

5. Provimi i Gitlab-runner me Kubernetes-executor

Deri vonë kam përdorur vetëm të rregullt gitlab-vrapues në një makinë të parapërgatitur (kontejner LXC) me guaskë ose doker-ekzekutues. Fillimisht, ne kishim disa vrapues të tillë të përcaktuar globalisht në gitlab tonë. Ata mblodhën imazhe doker për të gjitha projektet.

Por siç ka treguar praktika, ky opsion nuk është më ideali, si për sa i përket prakticitetit ashtu edhe sigurisë. Është shumë më mirë dhe ideologjikisht më korrekte që të vendosen vrapues të veçantë për çdo projekt, apo edhe për çdo mjedis.

Për fat të mirë, ky nuk është aspak problem, pasi tani do të vendosemi gitlab-vrapues direkt si pjesë e projektit tonë pikërisht në Kubernetes.

Gitlab ofron një tabelë të gatshme të drejtimit për vendosjen e gitlab-runner në Kubernetes. Pra, gjithçka që duhet të bëni është ta zbuloni shenjë regjistrimi për projektin tonë në Cilësimet -> CI / CD -> Vrapues dhe ia kaloni në krye:

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

Ku:

  • https://gitlab.com — adresa e serverit tuaj Gitlab.
  • yga8y-jdCusVDn_t4Wxc — shenjë regjistrimi për projektin tuaj.
  • rbac.krijoj=vërtetë — i siguron vrapuesit sasinë e nevojshme të privilegjeve për të qenë në gjendje të krijojë pods për të kryer detyrat tona duke përdorur kubernetes-executor.

Nëse gjithçka është bërë si duhet, duhet të shihni një vrapues të regjistruar në seksion Germa në ledhore, në cilësimet e projektit tuaj.

Pamja e ekranit të vrapuesit të shtuar

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

A është kaq e thjeshtë? - Po, është kaq e thjeshtë! Nuk ka më telashe me regjistrimin manual të vrapuesve, tani e tutje vrapuesit do të krijohen dhe shkatërrohen automatikisht.

6. Vendosni tabelat e Helm me QBEC

Që kur vendosëm ta konsiderojmë gitlab-vrapues pjesë e projektit tonë, është koha për ta përshkruar atë në depon tonë të Git.

Mund ta përshkruajmë si një komponent të veçantë , por në të ardhmen ne planifikojmë të vendosim kopje të ndryshme shumë shpesh, ndryshe nga gitlab-vrapues, i cili do të vendoset vetëm një herë për grup Kubernetes. Pra, le të inicializojmë një aplikacion të veçantë për të:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Këtë herë ne nuk do t'i përshkruajmë entitetet e Kubernetes me dorë, por do të marrim një tabelë të gatshme Helm. Një nga avantazhet e qbec është aftësia për të dhënë diagramet Helm direkt nga një depo Git.

Le ta lidhim duke përdorur nënmodulin git:

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

Tani drejtoria shitës/gitlab-runner Ne kemi një depo me një tabelë për gitlab-runner.

Në mënyrë të ngjashme, ju mund të lidhni depo të tjera, për shembull, të gjithë depo me grafikët zyrtarë https://github.com/helm/charts

Le të përshkruajmë komponentin komponentët/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,
  }
)

Argumenti i parë për zgjerimHelmTemplate kalojmë rrugën drejt tabelës, atëherë paramat.vlerat, të cilin e marrim nga parametrat e mjedisit, më pas vjen objekti me të

  • emri shabllon - titulli i publikimit
  • namespace — emri i transferuar në krye
  • këtë Skedar — një parametër i kërkuar që kalon shtegun për në skedarin aktual
  • i folur - tregon komanda shabllon i timonit me të gjitha argumentet gjatë paraqitjes së grafikut

Tani le të përshkruajmë parametrat për komponentin tonë në mjedise/bazë.libsonnet:

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

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

Обратите внимание RunerRegistrationToken marrim nga një skedar i jashtëm sekrete/bazë.libsonnet, le ta krijojmë:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Le të kontrollojmë nëse gjithçka funksionon:

qbec show default

nëse gjithçka është në rregull, atëherë ne mund të fshijmë lëshimin tonë të vendosur më parë përmes Helm:

helm uninstall gitlab-runner

dhe vendoseni në të njëjtën mënyrë, por përmes qbec:

qbec apply default

7. Hyrje në git-crypt

Git-crypt është një mjet që ju lejon të vendosni enkriptim transparent për depon tuaj.

Për momentin, struktura jonë e drejtorisë për gitlab-runner duket si kjo:

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

Por ruajtja e sekreteve në Git nuk është e sigurt, apo jo? Pra, ne duhet t'i kodojmë ato siç duhet.

Zakonisht, për hir të një ndryshoreje, kjo nuk ka gjithmonë kuptim. Ju mund të transferoni sekretet në qbec dhe përmes variablave të mjedisit të sistemit tuaj CI.
Por vlen të përmendet se ka edhe projekte më komplekse që mund të përmbajnë shumë më tepër sekrete; transferimi i tyre përmes variablave të mjedisit do të jetë jashtëzakonisht i vështirë.

Për më tepër, në këtë rast nuk do të mund t'ju tregoja për një mjet kaq të mrekullueshëm si git-crypt.

git-crypt Është gjithashtu i përshtatshëm në atë që ju lejon të ruani të gjithë historinë e sekreteve, si dhe të krahasoni, bashkoni dhe zgjidhni konfliktet në të njëjtën mënyrë siç jemi mësuar të bëjmë në rastin e Git.

Gjëja e parë pas instalimit git-crypt ne duhet të gjenerojmë çelësa për depon tonë:

git crypt init

Nëse keni një çelës PGP, atëherë mund të shtoni menjëherë veten si bashkëpunëtor për këtë projekt:

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

Në këtë mënyrë ju gjithmonë mund të deshifroni këtë depo duke përdorur çelësin tuaj privat.

Nëse nuk keni një çelës PGP dhe nuk e prisni atë, atëherë mund të shkoni në anën tjetër dhe të eksportoni çelësin e projektit:

git crypt export-key /path/to/keyfile

Kështu, kushdo që ka një eksportuar dosje kyçe do të jetë në gjendje të deshifrojë depon tuaj.

Është koha për të vendosur sekretin tonë të parë.
Më lejoni t'ju kujtoj se ne jemi ende në drejtori deploy/gitlab-runner/, ku kemi një direktori sekretet/, le të enkriptojmë të gjithë skedarët në të, për këtë do të krijojmë një skedar sekrete/.gitattribute me përmbajtjen e mëposhtme:

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

Siç shihet nga përmbajtja, të gjithë skedarët janë të maskuar * do të përshkohet git-crypt, me përjashtim të shumicës .gitattribute

Ne mund ta kontrollojmë këtë duke ekzekutuar:

git crypt status -e

Dalja do të jetë një listë e të gjithë skedarëve në depo për të cilat është aktivizuar enkriptimi

Kjo është e gjitha, tani ne mund të kryejmë me siguri ndryshimet tona:

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

Për të bllokuar një depo, thjesht ekzekutoni:

git crypt lock

dhe menjëherë të gjithë skedarët e koduar do të kthehen në diçka binare, do të jetë e pamundur t'i lexoni ato.
Për të deshifruar depon, ekzekutoni:

git crypt unlock

8. Krijo një imazh të kutisë së veglave

Një imazh i kutisë së veglave është një imazh me të gjitha mjetet që do të përdorim për të vendosur projektin tonë. Do të përdoret nga vrapuesi Gitlab për të kryer detyra tipike të vendosjes.

Gjithçka është e thjeshtë këtu, le të krijojmë një të re dockerfiles/toolbox/Dockerfile me përmbajtjen e mëposhtme:

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

Siç mund ta shihni, në këtë imazh ne instalojmë të gjitha shërbimet që kemi përdorur për të vendosur aplikacionin tonë. Nuk na duhet këtu përveçse kubectl, por mund të dëshironi të luani me të gjatë fazës së konfigurimit të tubacionit.

Gjithashtu, në mënyrë që të jemi në gjendje të komunikojmë me Kubernetes dhe të vendosemi në të, duhet të konfigurojmë një rol për podet e krijuara nga gitlab-runner.

Për ta bërë këtë, le të shkojmë te drejtoria me gitlab-runner:

cd deploy/gitlab-runner

dhe shtoni një komponent të ri komponente/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,
      },
    ],
  },
]

Ne gjithashtu do të përshkruajmë parametrat e rinj në mjedise/bazë.libsonnet, e cila tani duket si kjo:

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',
    },
  },
}

Обратите внимание $.components.rbac.name i referohet emër për komponent rbac

Le të kontrollojmë se çfarë ka ndryshuar:

qbec diff default

dhe zbatoni ndryshimet tona në Kubernetes:

qbec apply default

Gjithashtu, mos harroni të kryeni ndryshimet tona në git:

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. Tubacioni ynë i parë dhe montimi i imazheve sipas etiketave

Në themel të projektit ne do të krijojmë .gitlab-ci.yml me përmbajtjen e mëposhtme:

.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

Ju lutemi vini re që përdorim GIT_SUBMODULE_STRATEGY: normale për ato punë ku ju duhet të inicializoni në mënyrë eksplicite nënmodulet përpara ekzekutimit.

Mos harroni të bëni ndryshimet tona:

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

Unë mendoj se mund ta quajmë me siguri këtë një version v0.0.1 dhe shtoni etiketën:

git tag v0.0.1

Ne do të shtojmë etiketa sa herë që kemi nevojë të lëshojmë një version të ri. Etiketat në imazhet e Docker do të lidhen me etiketat Git. Çdo shtytje me një etiketë të re do të inicializojë ndërtimin e imazheve me këtë etiketë.

Do të ekzekutojë git push --tags, dhe le të shohim tubacionin tonë të parë:

Pamja e ekranit të tubacionit të parë

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Vlen të tërheqë vëmendjen tuaj për faktin se montimi me etiketa është i përshtatshëm për ndërtimin e imazheve të dokerit, por nuk është i përshtatshëm për vendosjen e një aplikacioni në Kubernetes. Meqenëse etiketat e reja mund t'u caktohen angazhimeve të vjetra, në këtë rast, inicializimi i tubacionit për to do të çojë në vendosjen e versionit të vjetër.

Për të zgjidhur këtë problem, zakonisht ndërtimi i imazheve doker është i lidhur me etiketat dhe vendosja e aplikacionit në një degë mjeshtër, në të cilën versionet e imazheve të mbledhura janë të koduara. Këtu mund të inicializoni rikthimin me një rikthim të thjeshtë mjeshtër-degët.

10. Automatizimi i vendosjes

Në mënyrë që Gitlab-runner të deshifrojë sekretet tona, do të na duhet të eksportojmë çelësin e ruajtjes dhe ta shtojmë atë në variablat tona të mjedisit CI:

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

Ne do ta ruajmë linjën që rezulton në Gitlab; për ta bërë këtë, le të shkojmë te cilësimet e projektit tonë:
Cilësimet -> CI / CD -> Variablat

Dhe le të krijojmë një ndryshore të re:

Tipi
Kyç
vlerë
Mbrojtur
i maskuar
Fusha

File
GITCRYPT_KEY
<your string>
true (gjatë trajnimit mundeni false)
true
All environments

Pamja e ekranit të ndryshores së shtuar

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Tani le të përditësojmë tonën .gitlab-ci.yml duke i shtuar asaj:

.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

Këtu kemi aktivizuar disa opsione të reja për qbec:

  • -- rrënjos disa/aplikacione — ju lejon të përcaktoni drejtorinë e një aplikacioni specifik
  • --force:k8s-context __incluster__ - kjo është një variabël magjike që thotë se vendosja do të ndodhë në të njëjtin grup në të cilin po funksionon gtilab-runner. Kjo është e nevojshme sepse përndryshe qbec do të përpiqet të gjejë një server të përshtatshëm Kubernetes në kubeconfig
  • -- prit — detyron qbec të presë derisa burimet që krijon të kalojnë në gjendjen Ready dhe vetëm më pas të dalë me një kod daljeje të suksesshme.
  • -po - thjesht çaktivizon guaskën interaktive A je i sigurt? kur vendoset.

Mos harroni të bëni ndryshimet tona:

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

Dhe pastaj shtytje git do të shohim se si janë vendosur aplikacionet tona:

Pamja e ekranit të tubacionit të dytë

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

11. Artefaktet dhe montimi kur shtyhet për të zotëruar

Në mënyrë tipike, hapat e përshkruar më sipër janë të mjaftueshëm për të ndërtuar dhe ofruar pothuajse çdo mikroshërbim, por ne nuk duam të shtojmë një etiketë sa herë që na duhet të përditësojmë faqen. Prandaj, ne do të marrim një rrugë më dinamike dhe do të vendosim një dislokim të përmbledhjes në degën kryesore.

Ideja është e thjeshtë: tani imazhi ynë do të rindërtohet sa herë që futeni në mjeshtër, dhe më pas vendoset automatikisht në Kubernetes.

Le të përditësojmë këto dy punë në faqen tonë .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"

Ju lutemi vini re se kemi shtuar një temë mjeshtër к ref për punë build_website dhe ne tani përdorim $CI_COMMIT_REF_NAME në vend të $CI_COMMIT_TAG, domethënë, ne jemi shkëputur nga etiketat në Git dhe tani do të shtyjmë një imazh me emrin e degës së commit që inicializoi tubacionin. Vlen të përmendet se kjo do të funksionojë edhe me etiketa, të cilat do të na lejojnë të ruajmë fotografitë e një siti me një version specifik në regjistrin e docker-it.

Kur emri i etiketës docker për një version të ri të faqes mund të jetë i pandryshuar, ne ende duhet të përshkruajmë ndryshimet në Kubernetes, përndryshe ai thjesht nuk do të rishpërndajë aplikacionin nga imazhi i ri, pasi nuk do të vërejë ndonjë ndryshim në manifestimi i vendosjes.

Opsioni —vm:ext-str digest="$DIGEST" për qbec - ju lejon të kaloni një ndryshore të jashtme në jsonnet. Ne duam që ai të rishpërndahet në grup me çdo lëshim të aplikacionit tonë. Ne nuk mund të përdorim më emrin e etiketës, i cili tani mund të jetë i pandryshueshëm, pasi duhet të jemi të lidhur me një version specifik të imazhit dhe të aktivizojmë vendosjen kur ai ndryshon.

Këtu do të ndihmohemi nga aftësia e Kaniko për të ruajtur një imazh të përmbledhur në një skedar (opsion --digest-skedar)
Më pas do ta transferojmë këtë skedar dhe do ta lexojmë në momentin e vendosjes.

Le të përditësojmë parametrat për tonën disploy/website/environments/base.libsonnet e cila tani do të duket kështu:

{
  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',
    },
  },
}

U krye, tani çdo angazhohem mjeshtër inicializon ndërtimin e imazhit docker për , dhe më pas vendoseni në Kubernetes.

Mos harroni të bëni ndryshimet tona:

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

Ne do të kontrollojmë më vonë shtytje git ne duhet të shohim diçka të tillë:

Pamja e ekranit të tubacionit për master

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Në parim, ne nuk kemi nevojë të ripërcaktojmë gitlab-runner me çdo shtytje, përveç nëse, natyrisht, asgjë nuk ka ndryshuar në konfigurimin e tij, le ta rregullojmë atë në .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/**/*

ndryshimet do t'ju lejojë të monitoroni ndryshimet në deploy/gitlab-runner/ dhe do të nxisë punën tonë vetëm nëse ka

Mos harroni të bëni ndryshimet tona:

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

shtytje git, kjo eshte më mirë:

Pamja e ekranit të tubacionit të përditësuar

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

12. Mjediset dinamike

Është koha për të diversifikuar tubacionin tonë me mjedise dinamike.

Së pari, le të përditësojmë punën build_website në tonë .gitlab-ci.yml, duke hequr bllokun prej tij është vetëm, e cila do ta detyrojë Gitlab-in ta aktivizojë atë në çdo angazhim në çdo degë:

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/

Pastaj përditësoni punën deploy_website, shtoni një bllok atje mjedis:

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"

Kjo do të lejojë Gitlab të shoqërojë punën me stimuloj mjedisin dhe shfaq lidhjen e saktë me të.

Tani le të shtojmë dy punë të tjera:

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

Ato do të lansohen me shtytje në çdo degë përveç masterit dhe do të vendosin versionin paraprak të faqes.

Ne shohim një opsion të ri për qbec: ---tag-app — ju lejon të etiketoni versionet e vendosura të aplikacionit dhe të punoni vetëm brenda kësaj etikete; kur krijoni dhe shkatërroni burime në Kubernetes, qbec do të funksionojë vetëm me to.
Në këtë mënyrë nuk mund të krijojmë një mjedis të veçantë për çdo rishikim, por thjesht të ripërdorim të njëjtin.

Këtu përdorim edhe ne qbec aplikoni rishikimin, në vend të qbec aplikoni parazgjedhjen - ky është pikërisht momenti kur ne do të përpiqemi të përshkruajmë ndryshimet për mjediset tona (rishikim dhe parazgjedhje):

Le të shtojmë rishikuar mjedisi në deploy/website/qbec.yaml

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

Më pas do ta deklarojmë 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

Dhe shkruani parametrat e personalizuar për të në 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',
    },
  },
}

Le të hedhim një vështrim më të afërt në punë stop_rishikimi, do të aktivizohet kur dega të fshihet dhe në mënyrë që gitlab të mos përpiqet të arkëtojë, përdoret GIT_STRATEGY: asnjë, më vonë ne klonojmë mjeshtër-degëzoni dhe fshini rishikimin përmes tij.
Është pak konfuze, por nuk kam gjetur ende një mënyrë më të bukur.
Një opsion alternativ do të ishte vendosja e çdo rishikimi në një hapësirë ​​emri hoteli, i cili gjithmonë mund të shkatërrohet tërësisht.

Mos harroni të bëni ndryshimet tona:

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

shtytje git, git arka -b test, testi i origjinës git push, kontrolloni:

Pamje e mjediseve të krijuara në Gitlab

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Gjithçka funksionon? - shkëlqyeshëm, fshi degën tonë të testimit: master arka git, git push origjina :test, kontrollojmë që punët e fshirjes së mjedisit funksionuan pa gabime.

Këtu do të doja të sqaroja menjëherë se çdo zhvillues në një projekt mund të krijojë degë, ai gjithashtu mund të ndryshojë .gitlab-ci.yml skedari dhe aksesoni variablat sekrete.
Prandaj, rekomandohet fuqimisht të lejohet përdorimi i tyre vetëm për degët e mbrojtura, për shembull në mjeshtër, ose krijoni një grup të veçantë variablash për çdo mjedis.

13. Rishikoni aplikacionet

Rishikoni aplikacionet Ky është një veçori GitLab që ju lejon të shtoni një buton për çdo skedar në depo për ta parë shpejt atë në një mjedis të vendosur.

Në mënyrë që këto butona të shfaqen, duhet të krijoni një skedar .gitlab/route-map.yml dhe përshkruani të gjitha transformimet e rrugës në të; në rastin tonë do të jetë shumë e thjeshtë:

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

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

Mos harroni të bëni ndryshimet tona:

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

shtytje git, dhe kontrolloni:

Pamja e ekranit të butonit të aplikacionit të rishikimit

Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Puna u krye!

Burimet e projektit:

Faleminderit për vëmendjen tuaj, shpresoj se ju ka pëlqyer Provimi i mjeteve të reja për ndërtimin dhe automatizimin e vendosjes në Kubernetes

Burimi: www.habr.com

Shto një koment