Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Ahoj! Nedávno bolo vydaných veľa skvelých automatizačných nástrojov na vytváranie obrazov Docker a na nasadenie v Kubernetes. V tomto smere som sa rozhodol pohrať sa s GitLabom, poriadne si naštudovať jeho možnosti a samozrejme nastaviť pipeline.

Táto práca bola inšpirovaná webovou stránkou kubernetes.io, ktorý sa generuje z zdrojové kódy automaticky a pre každú odoslanú žiadosť o fond robot automaticky vygeneruje ukážkovú verziu stránky s vašimi zmenami a poskytne odkaz na prezeranie.

Pokúsil som sa vytvoriť podobný proces od začiatku, ale úplne postavený na Gitlab CI a bezplatných nástrojoch, ktoré som zvykol používať na nasadenie aplikácií do Kubernetes. Dnes vám o nich konečne poviem viac.

Článok sa bude zaoberať nástrojmi, ako sú:
Hugo, qbec, kaniko, git-crypt и GitLab CI s vytváraním dynamických prostredí.

Obsah

  1. Zoznámte sa s Hugom
  2. Príprava súboru Dockerfile
  3. Zoznámenie sa s kaniko
  4. Zoznámenie sa s qbec
  5. Vyskúšajte Gitlab-runner s Kubernetes-executorom
  6. Nasadenie grafov Helm pomocou qbec
  7. Predstavujeme git-crypt
  8. Vytvorenie obrazu sady nástrojov
  9. Naše prvé potrubie a zostavovanie obrázkov podľa značiek
  10. Automatizácia nasadenia
  11. Artefakty a montáž pri tlačení na master
  12. Dynamické prostredia
  13. Kontrola aplikácií

1. Zoznámenie sa s Hugom

Ako príklad nášho projektu sa pokúsime vytvoriť stránku na publikovanie dokumentácie postavenú na Hugovi. Hugo je generátor statického obsahu.

Pre tých, ktorí nepoznajú statické generátory, vám o nich poviem trochu viac. Na rozdiel od bežných webových enginov s databázou a nejakým PHP, ktoré na žiadosť používateľa generujú stránky za chodu, sú statické generátory navrhnuté trochu inak. Umožňujú vám vziať zdroje, zvyčajne súbor súborov v šablónach značiek a tém Markdown, a potom ich skompilovať do úplne dokončenej webovej stránky.

To znamená, že v dôsledku toho dostanete adresárovú štruktúru a sadu vygenerovaných HTML súborov, ktoré jednoducho nahráte na akýkoľvek lacný hosting a získate funkčný web.

Hugo si môžete nainštalovať lokálne a vyskúšať:

Inicializácia nového webu:

hugo new site docs.example.org

A zároveň úložisko git:

cd docs.example.org
git init

Zatiaľ je naša stránka nepoškvrnená a aby sa na nej niečo objavilo, musíme najprv prepojiť tému, téma je len súbor šablón a určených pravidiel, podľa ktorých sa naša stránka generuje.

Pre tému, ktorú použijeme KTO SME, ktorý sa podľa môjho názoru dokonale hodí na dokumentačné miesto.

Chcel by som venovať osobitnú pozornosť skutočnosti, že nemusíme ukladať súbory tém do nášho projektového úložiska, ale môžeme ich jednoducho pripojiť pomocou submodul git:

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

Náš repozitár teda bude obsahovať iba súbory priamo súvisiace s naším projektom a pripojená téma zostane ako odkaz na konkrétny repozitár a commit v ňom, to znamená, že sa dá vždy stiahnuť z pôvodného zdroja a nebáť sa nekompatibilné zmeny.

Opravme konfiguráciu config.toml:

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

Už v tejto fáze môžete spustiť:

hugo server

A na adrese http://localhost:1313/ skontrolujte našu novovytvorenú webovú stránku, všetky zmeny vykonané v adresári automaticky aktualizujú otvorenú stránku v prehliadači, veľmi pohodlné!

Skúsme vytvoriť titulnú stranu v content/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Snímka obrazovky novovytvorenej stránky

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Ak chcete vygenerovať stránku, stačí spustiť:

hugo

Obsah adresára verejné/ a bude to vaša webová stránka.
Áno, mimochodom, okamžite to pridajte .gitignore:

echo /public > .gitignore

Nezabudnite potvrdiť naše zmeny:

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

2. Príprava súboru Dockerfile

Je čas definovať štruktúru nášho úložiska. Zvyčajne používam niečo ako:

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

  • dockerfiles/ — obsahuje adresáre so súbormi Dockerfiles a všetko potrebné na vytvorenie našich obrazov Docker.
  • nasadiť/ — obsahuje adresáre na nasadenie našich aplikácií do Kubernetes

Takto vytvoríme náš prvý Dockerfile pozdĺž cesty 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" ]

Ako vidíte, súbor Dockerfile obsahuje dva Z, nazýva sa táto príležitosť viacstupňová konštrukcia a umožňuje vám vylúčiť z konečného obrazu Docker všetko nepotrebné.
Výsledný obrázok teda bude obsahovať iba darkhttpd (odľahčený server HTTP) a verejné/ — obsah našej staticky generovanej webovej stránky.

Nezabudnite potvrdiť naše zmeny:

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

3. Zoznámenie sa s kaniko

Ako tvorca obrázkov docker som sa rozhodol použiť kaniko, keďže jeho činnosť nevyžaduje docker démona a samotné zostavenie je možné vykonať na akomkoľvek počítači a vyrovnávaciu pamäť je možné uložiť priamo do registra, čím odpadá potreba mať plnohodnotné trvalé úložisko.

Ak chcete vytvoriť obrázok, stačí spustiť kontajner pomocou kaniko exekútor a odovzdať mu aktuálny kontext zostavenia; dá sa to urobiť aj lokálne prostredníctvom ukotvenia:

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

kde register.gitlab.com/kvaps/docs.example.org/website — názov vášho docker image; po vytvorení sa automaticky spustí do registra docker.

Parameter --vyrovnávacia pamäť umožňuje ukladať vrstvy do vyrovnávacej pamäte v registri dockerov; v uvedenom príklade budú uložené v register.gitlab.com/kvaps/docs.example.org/website/cache, ale pomocou parametra môžete zadať inú cestu --cache-repo.

Snímka obrazovky docker-registra

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

4. Zoznámenie sa s qbec

Qbec je nástroj nasadenia, ktorý vám umožňuje deklaratívne opísať manifesty vašej aplikácie a nasadiť ich do Kubernetes. Použitie Jsonnet ako hlavnej syntaxe vám umožňuje výrazne zjednodušiť popis rozdielov vo viacerých prostrediach a tiež takmer úplne eliminuje opakovanie kódu.

To môže platiť najmä v prípadoch, keď potrebujete nasadiť aplikáciu do niekoľkých klastrov s rôznymi parametrami a chcete ich deklaratívne opísať v Gite.

Qbec vám tiež umožňuje vykresľovať Helmove diagramy tak, že im odošlete potrebné parametre a potom ich budete ovládať rovnakým spôsobom ako bežné manifesty, vrátane toho, že na ne môžete aplikovať rôzne mutácie, čo vám zase umožňuje zbaviť sa potreby použite ChartMuseum. To znamená, že môžete ukladať a vykresľovať grafy priamo z git, kam patria.

Ako som už povedal, všetky nasadenia uložíme do adresára nasadiť/:

mkdir deploy
cd deploy

Inicializujeme našu prvú aplikáciu:

qbec init website
cd website

Teraz štruktúra našej aplikácie vyzerá takto:

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

pozrime sa na súbor qbec.yaml:

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

Tu nás zaujíma predovšetkým spec.prostredia, qbec už pre nás vytvoril predvolené prostredie a prevzal adresu servera, ako aj menný priestor z nášho aktuálneho kubeconfigu.
Teraz pri nasadzovaní do štandardné prostredí, qbec sa vždy nasadí iba do určeného klastra Kubernetes a do určeného priestoru názvov, to znamená, že už nemusíte prepínať medzi kontextami a priestormi názvov, aby ste mohli vykonať nasadenie.
V prípade potreby môžete kedykoľvek aktualizovať nastavenia v tomto súbore.

Všetky vaše prostredia sú popísané v qbec.yamla v súbore params.libsonnet, kde je napísané, kde pre ne získať parametre.

Ďalej vidíme dva adresáre:

  • komponenty/ — tu budú uložené všetky manifesty pre našu aplikáciu; možno ich popísať v súboroch jsonnet aj bežných yaml
  • prostredia/ — tu popíšeme všetky premenné (parametre) pre naše prostredia.

V predvolenom nastavení máme dva súbory:

  • environments/base.libsonnet - bude obsahovať spoločné parametre pre všetky prostredia
  • environments/default.libsonnet — obsahuje parametre prepísané pre prostredie štandardné

poďme otvoriť environments/base.libsonnet a tam pridajte parametre pre náš prvý komponent:

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

Vytvorme tiež náš prvý komponent komponenty/website.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,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

V tomto súbore sme opísali tri entity Kubernetes naraz, sú to: rozvinutie, Služba sa и Ingress. Keby sme chceli, mohli by sme ich dať do rôznych komponentov, ale v tejto fáze nám bude stačiť jeden.

syntax jsonnet je veľmi podobný bežnému json, v princípe je bežný json už platným jsonnetom, takže na začiatku môže byť pre vás jednoduchšie používať online služby ako yaml2json na konverziu vášho obvyklého yaml na json, alebo ak vaše komponenty neobsahujú žiadne premenné, potom ich možno opísať vo forme bežného yaml.

Pri práci s jsonnet Dôrazne odporúčam nainštalovať doplnok pre váš editor

Existuje napríklad plugin pre vim vim-jsonnet, ktorý zapne zvýraznenie syntaxe a automaticky sa spustí jsonnet fmt zakaždým, keď uložíte (vyžaduje nainštalovaný jsonnet).

Všetko je pripravené, teraz môžeme začať nasadzovať:

Aby sme videli, čo máme, bežme:

qbec show default

Na výstupe uvidíte vykreslené yaml manifesty, ktoré sa použijú na predvolený klaster.

Skvelé, teraz aplikujte:

qbec apply default

Na výstupe vždy uvidíte, čo sa bude robiť vo vašom klastri, qbec vás požiada, aby ste súhlasili so zmenami zadaním y budete môcť potvrdiť svoje zámery.

Naša aplikácia je pripravená a nasadená!

Ak vykonáte zmeny, vždy môžete:

qbec diff default

aby ste videli, ako tieto zmeny ovplyvnia aktuálne nasadenie

Nezabudnite potvrdiť naše zmeny:

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

5. Vyskúšajte Gitlab-runner s Kubernetes-executorom

Až donedávna som používal iba bežné gitlab-runner na vopred pripravenom stroji (kontajner LXC) s shellom alebo docker-executorom. Spočiatku sme mali niekoľko takýchto bežcov globálne definovaných v našom gitlabe. Zozbierali obrázky dockerov pre všetky projekty.

Ale ako ukázala prax, táto možnosť nie je najideálnejšia z hľadiska praktickosti aj bezpečnosti. Oveľa lepšie a ideologicky správnejšie je mať pre každý projekt alebo dokonca pre každé prostredie nasadených samostatných bežcov.

Našťastie to vôbec nie je problém, keďže teraz budeme nasadzovať gitlab-runner priamo v rámci nášho projektu priamo v Kubernetes.

Gitlab poskytuje hotový graf kormidla na nasadenie gitlab-runnera do Kubernetes. Takže všetko, čo musíte urobiť, je zistiť registračný token pre náš projekt v Nastavenia -> CI / CD -> Runners a odovzdať to kormidlu:

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

Kde:

  • https://gitlab.com — adresa vášho servera Gitlab.
  • yga8y-jdCusVDn_t4Wxc — registračný token pre váš projekt.
  • rbac.create=true — poskytuje bežcovi potrebné množstvo privilégií, aby mohol vytvárať moduly na vykonávanie našich úloh pomocou kubernetes-executor.

Ak je všetko vykonané správne, mali by ste v sekcii vidieť registrovaného bežca Bežci, v nastaveniach projektu.

Snímka obrazovky pridaného bežca

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Je to také jednoduché? - áno, je to také jednoduché! Už žiadne problémy s manuálnou registráciou bežcov, odteraz sa budú bežci vytvárať a ničiť automaticky.

6. Nasaďte grafy Helm pomocou QBEC

Keďže sme sa rozhodli zvážiť gitlab-runner časť nášho projektu, je čas opísať ju v našom úložisku Git.

Mohli by sme ho opísať ako samostatnú zložku webové stránky, no v budúcnosti plánujeme nasadiť rôzne kópie webové stránky veľmi často, na rozdiel od gitlab-runner, ktorý bude nasadený iba raz na klaster Kubernetes. Spustite na to samostatnú aplikáciu:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Tentoraz nebudeme entity Kubernetes popisovať ručne, ale vezmeme si hotový Helmov graf. Jednou z výhod qbec je schopnosť vykresľovať Helmove grafy priamo z úložiska Git.

Poďme to pripojiť pomocou submodulu git:

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

Teraz adresár predajca/gitlab-runner Máme úložisko s grafom pre gitlab-runner.

Podobným spôsobom môžete prepojiť ďalšie úložiská, napríklad celé úložisko s oficiálnymi grafmi https://github.com/helm/charts

Poďme si popísať komponent komponenty/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,
  }
)

Prvý argument k expandHelmTemplate potom prejdeme cestou k grafu parametre.hodnoty, ktorý berieme z parametrov prostredia, potom prichádza objekt s

  • názov šablóny — názov vydania
  • namespace — menný priestor prenesený na kormidlo
  • tentoSúbor — požadovaný parameter, ktorý odovzdáva cestu k aktuálnemu súboru
  • ukecaný - ukazuje príkaz šablóna kormidla so všetkými argumentmi pri vykresľovaní grafu

Teraz popíšme parametre pre náš komponent v environments/base.libsonnet:

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

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

Venujte pozornosť runnerRegistrationToken berieme z externého súboru secrets/base.libsonnet, poďme si ho vytvoriť:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Skontrolujeme, či všetko funguje:

qbec show default

ak je všetko v poriadku, môžeme odstrániť naše predtým nasadené vydanie cez Helm:

helm uninstall gitlab-runner

a nasaďte ho rovnakým spôsobom, ale cez qbec:

qbec apply default

7. Úvod do git-crypt

Git-crypt je nástroj, ktorý vám umožňuje nastaviť transparentné šifrovanie pre vaše úložisko.

V súčasnosti naša adresárová štruktúra pre gitlab-runner vyzerá takto:

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

Ale ukladanie tajomstiev v Git nie je bezpečné, však? Preto ich musíme správne zašifrovať.

Zvyčajne to kvôli jednej premennej nie vždy dáva zmysel. Tajomstvá môžete preniesť na qbec a prostredníctvom premenných prostredia vášho systému CI.
Je však potrebné poznamenať, že existujú aj zložitejšie projekty, ktoré môžu obsahovať oveľa viac tajomstiev; preniesť ich cez premenné prostredia bude mimoriadne ťažké.

Navyše, v tomto prípade by som vám nemohol povedať o takom úžasnom nástroji, ako je git-crypt.

git-crypt Je tiež pohodlný v tom, že umožňuje uložiť celú históriu tajomstiev, ako aj porovnávať, spájať a riešiť konflikty rovnakým spôsobom, ako sme zvyknutí robiť v prípade Gitu.

Prvá vec po inštalácii git-crypt potrebujeme vygenerovať kľúče pre naše úložisko:

git crypt init

Ak máte kľúč PGP, môžete sa okamžite pridať ako spolupracovník tohto projektu:

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

Týmto spôsobom môžete vždy dešifrovať toto úložisko pomocou svojho súkromného kľúča.

Ak nemáte kľúč PGP a neočakávate ho, môžete ísť iným spôsobom a exportovať kľúč projektu:

git crypt export-key /path/to/keyfile

Teda každý, kto má vyvezený kľúčový súbor bude môcť dešifrovať vaše úložisko.

Je čas nastaviť naše prvé tajomstvo.
Pripomínam, že sme stále v adresári deploy/gitlab-runner/, kde máme adresár tajomstvá/, zašifrujme všetky súbory v ňom, na to vytvoríme súbor tajomstvá/.gitatribúty s nasledujúcim obsahom:

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

Ako je zrejmé z obsahu, všetky súbory sú maskované * bude prechádzať git-crypt, okrem väčšiny .gitattributes

Môžeme to skontrolovať spustením:

git crypt status -e

Výstupom bude zoznam všetkých súborov v úložisku, pre ktoré je povolené šifrovanie

To je všetko, teraz môžeme bezpečne vykonať naše zmeny:

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

Ak chcete zablokovať úložisko, stačí spustiť:

git crypt lock

a všetky zašifrované súbory sa okamžite zmenia na binárne niečo, nebude možné ich prečítať.
Ak chcete dešifrovať úložisko, spustite:

git crypt unlock

8. Vytvorte obrázok súpravy nástrojov

Obrázok sady nástrojov je obrázok so všetkými nástrojmi, ktoré použijeme na nasadenie nášho projektu. Bude ho používať bežec Gitlab na vykonávanie typických úloh nasadenia.

Všetko je tu jednoduché, poďme vytvoriť nový dockerfiles/toolbox/Dockerfile s nasledujúcim obsahom:

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

Ako vidíte, na tomto obrázku inštalujeme všetky nástroje, ktoré sme použili na nasadenie našej aplikácie. Nepotrebujeme to tu, pokiaľ kubectl, ale možno sa s tým budete chcieť pohrať počas fázy nastavovania potrubia.

Aby sme mohli komunikovať s Kubernetes a nasadzovať sa do neho, musíme nakonfigurovať rolu pre moduly generované gitlab-runnerom.

Ak to chcete urobiť, prejdite do adresára s gitlab-runner:

cd deploy/gitlab-runner

a pridajte nový komponent komponenty/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,
      },
    ],
  },
]

Nové parametre popíšeme aj v environments/base.libsonnet, ktorý teraz vyzerá takto:

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

Venujte pozornosť $.components.rbac.name odkazuje na názov pre komponent rbac

Pozrime sa, čo sa zmenilo:

qbec diff default

a použite naše zmeny na Kubernetes:

qbec apply default

Nezabudnite tiež odovzdať naše zmeny do 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. Naša prvá pipeline a zostavovanie obrázkov podľa značiek

V koreni projektu vytvoríme .gitlab-ci.yml s nasledujúcim obsahom:

.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

Upozorňujeme, že používame GIT_SUBMODULE_STRATEGY: normálne pre tie úlohy, kde musíte pred spustením explicitne inicializovať podmoduly.

Nezabudnite potvrdiť naše zmeny:

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

Myslím, že to môžeme pokojne nazvať verziou v0.0.1 a pridajte značku:

git tag v0.0.1

Značky pridáme vždy, keď budeme potrebovať vydať novú verziu. Značky v obrázkoch Docker budú prepojené so značkami Git. Každé zatlačenie s novou značkou inicializuje zostavenie obrázkov s touto značkou.

Vykoná sa git push --tags, a pozrime sa na náš prvý kanál:

Snímka obrazovky prvého potrubia

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Stojí za to upozorniť na skutočnosť, že zostava podľa značiek je vhodná na vytváranie obrazov dockerov, ale nie je vhodná na nasadenie aplikácie do Kubernetes. Keďže k starým odovzdaniam možno priradiť nové značky, v tomto prípade inicializácia kanála pre ne povedie k nasadeniu starej verzie.

Na vyriešenie tohto problému je zvyčajne zostavovanie obrázkov dockerov viazané na značky a nasadenie aplikácie do pobočky majster, v ktorej sú verzie zhromaždených obrázkov pevne zakódované. Tu môžete inicializovať rollback jednoduchým návratom majster- konáre.

10. Automatizácia nasadenia

Aby Gitlab-runner dešifroval naše tajomstvá, budeme musieť exportovať kľúč úložiska a pridať ho do našich premenných prostredia CI:

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

Výsledný riadok uložíme do Gitlabu; aby sme to urobili, prejdime do našich nastavení projektu:
Nastavenia -> CI / CD -> Premenné

A vytvoríme novú premennú:

Typ
Kľúč
Hodnota
chránený
maskovaný
Rozsah

File
GITCRYPT_KEY
<your string>
true (počas školenia môžete false)
true
All environments

Snímka obrazovky pridanej premennej

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Teraz poďme aktualizovať naše .gitlab-ci.yml pridávam k tomu:

.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

Tu sme povolili niekoľko nových možností pre qbec:

  • --root some/app — umožňuje určiť adresár konkrétnej aplikácie
  • --force:k8s-context __incluster__ - toto je magická premenná, ktorá hovorí, že nasadenie sa uskutoční v rovnakom klastri, v ktorom beží gtilab-runner. Je to potrebné, pretože inak sa qbec pokúsi nájsť vhodný server Kubernetes vo vašom kubeconfig
  • --počkaj — prinúti qbec počkať, kým prostriedky, ktoré vytvorí, neprejdú do stavu Pripravené a až potom sa ukončia s úspešným výstupným kódom.
  • -Áno - jednoducho vypne interaktívny shell Si si istý? pri nasadení.

Nezabudnite potvrdiť naše zmeny:

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

A potom git push uvidíme, ako boli naše aplikácie nasadené:

Snímka obrazovky druhého potrubia

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

11. Artefakty a montáž pri tlačení na master

Vyššie opísané kroky zvyčajne postačujú na vytvorenie a poskytovanie takmer akejkoľvek mikroslužby, ale nechceme pridávať značku zakaždým, keď potrebujeme aktualizovať web. Preto sa vyberieme dynamickejšou cestou a nastavíme nasadenie digestu v hlavnej vetve.

Myšlienka je jednoduchá: teraz obraz nášho webové stránky bude prestavaný zakaždým, keď doň zatlačíte majstera potom automaticky nasadiť do Kubernetes.

Poďme aktualizovať tieto dve úlohy v našom .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"

Upozorňujeme, že sme pridali vlákno majster к refs pre pracovné miesta build_website a teraz používame $CI_COMMIT_REF_NAME namiesto $CI_COMMIT_TAG, to znamená, že sme sa odpojili od značiek v Git a teraz vložíme obrázok s názvom vetvy odovzdania, ktorá inicializovala kanál. Stojí za zmienku, že to bude fungovať aj so značkami, čo nám umožní uložiť snímky lokality s konkrétnou verziou v registri dockerov.

Keď môže byť názov docker tagu pre novú verziu stránky nezmenený, stále musíme opísať zmeny Kubernetes, inak jednoducho nepresadí aplikáciu z nového obrázka, pretože nezaznamená žiadne zmeny v manifest nasadenia.

Možnosť —vm:ext-str digest=”$DIGEST” pre qbec - umožňuje odovzdať externú premennú do jsonnet. Chceme, aby sa znova nasadil v klastri s každým vydaním našej aplikácie. Už nemôžeme používať názov značky, ktorý je teraz nemenný, pretože musíme byť viazaní na konkrétnu verziu obrázka a spustiť nasadenie, keď sa zmení.

Tu nám pomôže Kanikoova schopnosť uložiť súhrnný obrázok do súboru (možnosť --digest-file)
Potom tento súbor prenesieme a prečítame v čase nasadenia.

Poďme aktualizovať parametre pre naše deploy/website/environments/base.libsonnet ktorý bude teraz vyzerať takto:

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

Hotovo, teraz sa zapojte majster inicializuje zostavenie obrazu docker pre webové stránkya potom ho nasaďte do Kubernetes.

Nezabudnite potvrdiť naše zmeny:

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

Skontrolujeme neskôr git push mali by sme vidieť niečo takéto:

Snímka obrazovky potrubia pre master

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

V zásade nemusíme presadzovať gitlab-runner pri každom stlačení, pokiaľ sa, samozrejme, nič nezmenilo v jeho konfigurácii, opravme to v .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/**/*

zmeny vám umožní sledovať zmeny v deploy/gitlab-runner/ a spustí našu prácu iba vtedy, ak nejaké budú

Nezabudnite potvrdiť naše zmeny:

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

git push, to je lepšie:

Snímka obrazovky aktualizovaného potrubia

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

12. Dynamické prostredia

Je čas diverzifikovať náš kanál o dynamické prostredia.

Najprv aktualizujme úlohu build_website v našej .gitlab-ci.yml, odstráňte z neho blok iba, čo prinúti Gitlab, aby ho spustil pri akomkoľvek odovzdaní akejkoľvek vetve:

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/

Potom aktualizujte úlohu deploy_website, pridajte tam blok prostredie:

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"

To umožní Gitlabu priradiť úlohu prod prostredia a zobraziť naň správny odkaz.

Teraz pridajme ďalšie dve úlohy:

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

Spustia sa po odoslaní do ktorejkoľvek pobočky okrem hlavnej a nasadia ukážkovú verziu lokality.

Vidíme novú možnosť pre qbec: --app-tag — umožňuje označovať nasadené verzie aplikácie a pracovať iba v rámci tejto značky; pri vytváraní a ničení zdrojov v Kubernetes bude qbec pracovať iba s nimi.
Týmto spôsobom nemôžeme vytvoriť samostatné prostredie pre každú recenziu, ale jednoducho znova použiť to isté.

Tu tiež používame qbec aplikovať recenziu, namiesto qbec použiť predvolené - toto je presne ten moment, kedy sa pokúsime popísať rozdiely pre naše prostredia (recenzia a predvolené):

pridať preskúma prostredie v deploy/website/qbec.yaml

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

Potom to vyhlásime 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

A zapíšte si jeho vlastné parametre 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',
    },
  },
}

Pozrime sa tiež bližšie na jobu stop_review, spustí sa, keď je vetva zmazaná a aby sa gitlab nepokúšal zaplatiť, používa sa GIT_STRATEGY: žiadna, neskôr klonujeme majster-rozvetviť a odstrániť recenziu cez ňu.
Je to trochu mätúce, ale zatiaľ som nenašiel krajší spôsob.
Alternatívnou možnosťou by bolo nasadenie každej recenzie do menného priestoru hotela, ktorý možno vždy úplne zničiť.

Nezabudnite potvrdiť naše zmeny:

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

git push, git checkout -b test, test pôvodu git push, skontrolujte:

Snímka obrazovky vytvorených prostredí v Gitlabe

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Všetko funguje? - skvelé, odstráňte našu testovaciu vetvu: git checkout master, git push origin :test, skontrolujeme, či úlohy odstraňovania prostredia fungovali bez chýb.

Tu by som chcel hneď objasniť, že každý developer v projekte môže vytvárať pobočky, môže sa aj meniť .gitlab-ci.yml súbor a prístup k tajným premenným.
Preto sa dôrazne odporúča povoliť ich použitie len pre chránené konáre, napríklad v majsteralebo vytvorte samostatnú množinu premenných pre každé prostredie.

13. Skontrolujte aplikácie

Kontrola aplikácií Toto je funkcia GitLab, ktorá vám umožňuje pridať tlačidlo pre každý súbor v úložisku, aby ste ho mohli rýchlo zobraziť v nasadenom prostredí.

Aby sa tieto tlačidlá zobrazili, musíte vytvoriť súbor .gitlab/route-map.yml a popíšte v ňom všetky transformácie ciest; v našom prípade to bude veľmi jednoduché:

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

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

Nezabudnite potvrdiť naše zmeny:

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

git pusha skontrolujte:

Snímka obrazovky tlačidla Skontrolovať aplikáciu

Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Práca je hotová!

Zdroje projektu:

Ďakujem za pozornosť, dúfam, že sa vám to páčilo Skúšanie nových nástrojov na vytváranie a automatizáciu nasadenia v Kubernetes

Zdroj: hab.com

Pridať komentár