Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Zdravo! Nedavno je bilo izdanih veliko kul orodij za avtomatizacijo za gradnjo slik Docker in za uvajanje v Kubernetes. V zvezi s tem sem se odločil poigrati z GitLabom, temeljito preučiti njegove zmožnosti in seveda vzpostaviti cevovod.

To delo je navdihnilo spletno mesto kubernetes.io, ki je ustvarjen iz izvorne kode samodejno in za vsako poslano zahtevo za skupino robot samodejno ustvari predogledno različico spletnega mesta z vašimi spremembami in zagotovi povezavo za ogled.

Poskušal sem zgraditi podoben postopek iz nič, vendar v celoti zgrajen na Gitlab CI in brezplačnih orodjih, ki sem jih vajen uporabljati za uvajanje aplikacij v Kubernetes. Danes vam bom končno povedal več o njih.

Članek bo obravnaval orodja, kot so:
Hugo, qbec, kaniko, git-crypt и GitLab CI z ustvarjanjem dinamičnih okolij.

Vsebina

  1. Spoznajte Huga
  2. Priprava datoteke Docker
  3. Spoznavanje kaniko
  4. Spoznavanje qbec
  5. Preizkušam Gitlab-runner z Kubernetes-executorjem
  6. Uvajanje grafikonov Helm s qbec
  7. Predstavljamo git-crypt
  8. Ustvarjanje slike orodjarne
  9. Naš prvi cevovod in sestavljanje slik po oznakah
  10. Avtomatizacija uvajanja
  11. Artefakti in sestavljanje pri potiskanju na master
  12. Dinamična okolja
  13. Pregled aplikacij

1. Spoznavanje Huga

Kot primer našega projekta bomo poskušali ustvariti spletno mesto za objavo dokumentacije, zgrajeno na Hugu. Hugo je generator statične vsebine.

Za tiste, ki ne poznate statičnih generatorjev, vam bom povedal nekaj več o njih. Za razliko od običajnih spletnih mehanizmov z bazo podatkov in nekaj PHP-ja, ki na zahtevo uporabnika generirajo strani sproti, so statični generatorji zasnovani nekoliko drugače. Omogočajo vam, da vzamete vire, običajno nabor datotek v oznaki Markdown in predloge tem, nato pa jih sestavite v popolnoma dokončano spletno mesto.

To pomeni, da boste kot rezultat prejeli strukturo imenika in niz ustvarjenih datotek HTML, ki jih lahko preprosto naložite na katero koli poceni gostovanje in dobite delujoče spletno mesto.

Hugo lahko namestite lokalno in ga preizkusite:

Inicializacija novega mesta:

hugo new site docs.example.org

In hkrati repozitorij git:

cd docs.example.org
git init

Zaenkrat je naše spletno mesto nedotaknjeno in da se na njem nekaj pojavi, moramo najprej povezati temo, tema je le skupek predlog in določenih pravil, po katerih se generira naša stran.

Za temo, ki jo bomo uporabili Izvedite več, ki je po mojem mnenju popolnoma primeren za mesto z dokumentacijo.

Posebno pozornost bi rad namenil dejstvu, da nam datotek teme ni treba shranjevati v našem repozitoriju projekta; namesto tega ga lahko preprosto povežemo z podmodul git:

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

Tako bo naš repozitorij vseboval samo datoteke, ki so neposredno povezane z našim projektom, povezana tema pa bo ostala kot povezava do določenega repozitorija in potrditev v njem, kar pomeni, da jo je mogoče vedno potegniti iz izvirnega vira in se ne bati nezdružljive spremembe.

Popravimo konfiguracijo config.toml:

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

Že na tej stopnji lahko izvajate:

hugo server

In na naslovu http://localhost:1313/ preverite našo novo ustvarjeno spletno stran, vse spremembe v imeniku samodejno posodobijo odprto stran v brskalniku, zelo priročno!

Poskusimo ustvariti naslovnico v vsebina/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Posnetek zaslona novo ustvarjene strani

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Če želite ustvariti spletno mesto, zaženite:

hugo

Vsebina imenika javno / in bo vaše spletno mesto.
Da, mimogrede, takoj ga dodamo .gitignore:

echo /public > .gitignore

Ne pozabite potrditi naših sprememb:

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

2. Priprava datoteke Docker

Čas je, da definiramo strukturo našega skladišča. Ponavadi uporabljam nekaj takega:

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

  • dockerfiles/ — vsebujejo imenike z datotekami Docker in vsem, kar je potrebno za gradnjo naših slik Docker.
  • razporedi/ — vsebuje imenike za uvajanje naših aplikacij v Kubernetes

Tako bomo na tej poti ustvarili svojo prvo datoteko Dockerfile dockerfiles/spletno mesto/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" ]

Kot lahko vidite, datoteka Dockerfile vsebuje dva OD, se ta funkcija imenuje večstopenjska gradnja in vam omogoča, da iz končne slike dockerja izključite vse nepotrebno.
Tako bo končna slika vsebovala samo temnohttpd (lahek strežnik HTTP) in javno / — vsebino naše statično ustvarjene spletne strani.

Ne pozabite potrditi naših sprememb:

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

3. Spoznavanje kaniko

Kot graditelj slik dockerja sem se odločil uporabiti kaniko, saj njegovo delovanje ne zahteva docker demona, samo gradnjo pa je mogoče izvesti na katerem koli stroju, predpomnilnik pa je mogoče shraniti neposredno v register, s čimer se odpravi potreba po popolni trajni shrambi.

Če želite zgraditi sliko, zaženite vsebnik z kaniko izvršitelj in mu posredujte trenutni gradbeni kontekst; to je mogoče storiti tudi lokalno prek dockerja:

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

kjer je registry.gitlab.com/kvaps/docs.example.org/website — ime vaše docker slike; po gradnji bo samodejno zagnana v docker register.

Parameter --predpomnilnik vam omogoča, da predpomnite plasti v registru dockerjev; za navedeni primer bodo shranjene v registry.gitlab.com/kvaps/docs.example.org/website/cache, vendar lahko s parametrom določite drugo pot --cache-repo.

Posnetek zaslona docker-registra

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

4. Spoznavanje qbec

Qbec je orodje za uvajanje, ki vam omogoča, da deklarativno opišete manifeste svoje aplikacije in jih uvedete v Kubernetes. Uporaba Jsonneta kot glavne sintakse vam omogoča močno poenostavitev opisa razlik v več okoljih in skoraj popolnoma odpravi ponavljanje kode.

To lahko še posebej velja v primerih, ko morate razmestiti aplikacijo v več gruč z različnimi parametri in jih želite deklarativno opisati v Gitu.

Qbec vam omogoča tudi upodabljanje grafikonov Helm tako, da jim posredujete potrebne parametre in jih nato upravljate na enak način kot običajne manifeste, vključno z uporabo različnih mutacij zanje, kar vam posledično omogoča, da se znebite potrebe po uporabite ChartMuseum. To pomeni, da lahko shranjujete in upodabljate grafikone neposredno iz gita, kamor spadajo.

Kot sem že rekel, bomo vse uvedbe shranili v imenik razporedi/:

mkdir deploy
cd deploy

Inicializirajmo našo prvo aplikacijo:

qbec init website
cd website

Sedaj je struktura naše aplikacije videti takole:

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

poglejmo datoteko qbec.yaml:

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

Tukaj nas zanima predvsem spec.okolja, je qbec za nas že ustvaril privzeto okolje in vzel naslov strežnika ter imenski prostor iz našega trenutnega kubeconfiga.
Zdaj pri uvajanju v privzeto okolje, se bo qbec vedno uvedel le v določeno gručo Kubernetes in v navedeni imenski prostor, kar pomeni, da vam ni več treba preklapljati med konteksti in imenskimi prostori, da izvedete uvajanje.
Če je potrebno, lahko vedno posodobite nastavitve v tej datoteki.

Vsa vaša okolja so opisana v qbec.yaml, in v datoteki params.libsonnet, kjer piše kje dobiti parametre zanje.

Nato vidimo dva imenika:

  • komponente / — vsi manifesti za našo aplikacijo bodo shranjeni tukaj; opisati jih je mogoče v jsonnet in običajnih datotekah yaml
  • okolja/ — tukaj bomo opisali vse spremenljivke (parametre) za naša okolja.

Privzeto imamo dve datoteki:

  • okolju/base.libsonnet - vseboval bo skupne parametre za vsa okolja
  • okolju/default.libsonnet — vsebuje parametre, preglasljene za okolje privzeto

odprimo okolju/base.libsonnet in tam dodajte parametre za našo prvo komponento:

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

Ustvarimo tudi prvo komponento komponente/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 tej datoteki smo opisali tri entitete Kubernetes hkrati, to so: Deployment, Service и Vstop. Če bi želeli, bi jih lahko razdelili v različne komponente, a na tej stopnji nam bo ena zadostovala.

sintaksa jsonnet je zelo podoben navadnemu jsonu, načeloma je običajni json že veljaven jsonnet, zato vam bo sprva morda lažje uporabljati spletne storitve, kot je yaml2json za pretvorbo vašega običajnega yamla v json ali, če vaše komponente ne vsebujejo nobenih spremenljivk, jih je mogoče opisati v obliki običajnega yamla.

Pri delu z jsonnet Toplo priporočam, da namestite vtičnik za svoj urejevalnik

Na primer, obstaja vtičnik za vim vim-jsonnet, ki vklopi označevanje sintakse in se samodejno izvede jsonnet fmt vsakič, ko shranite (zahteva nameščen jsonnet).

Vse je pripravljeno, zdaj lahko začnemo z uvajanjem:

Da vidimo, kaj imamo, zaženimo:

qbec show default

Na izhodu boste videli upodobljene manifeste yaml, ki bodo uporabljeni za privzeto gručo.

Super, zdaj se prijavi:

qbec apply default

Na izhodu boste vedno videli, kaj bo narejeno v vaši gruči, qbec vas bo pozval, da se strinjate s spremembami tako, da vnesete y boste lahko potrdili svoje namere.

Naša aplikacija je pripravljena in nameščena!

Če naredite spremembe, lahko vedno storite:

qbec diff default

da vidite, kako bodo te spremembe vplivale na trenutno uvajanje

Ne pozabite potrditi naših sprememb:

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

5. Preizkušanje Gitlab-runnerja s Kubernetes-executorjem

Do nedavnega sem uporabljal le običajne gitlab-runner na vnaprej pripravljenem stroju (LXC kontejner) z lupino ali docker-executorjem. Na začetku smo imeli v našem gitlabu globalno definiranih več takih tekačev. Zbrali so slike dockerjev za vse projekte.

Toda kot je pokazala praksa, ta možnost ni najbolj idealna, tako v smislu praktičnosti kot varnosti. Veliko bolje in ideološko pravilneje je imeti za vsak projekt ali celo za vsako okolje nameščene ločene tekače.

Na srečo to sploh ni problem, saj bomo zdaj namestili gitlab-runner neposredno kot del našega projekta kar v Kubernetesu.

Gitlab ponuja že pripravljen krmilni grafikon za uvajanje gitlab-runnerja v Kubernetes. Torej vse, kar morate storiti, je izvedeti žeton za registracijo za naš projekt v Nastavitve -> CI / CD -> Tekači in ga podajte krmilu:

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

Kje:

  • https://gitlab.com — naslov vašega strežnika Gitlab.
  • yga8y-jdCusVDn_t4Wxc — registracijski žeton za vaš projekt.
  • rbac.create=true — zagotavlja tekaču potrebno količino privilegijev, da lahko ustvari pode za izvajanje naših nalog z uporabo kubernetes-executor.

Če je vse narejeno pravilno, bi morali v razdelku videti registriranega tekača Tekačev, v nastavitvah vašega projekta.

Posnetek zaslona dodanega tekača

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Je tako preprosto? - ja, tako preprosto je! Nič več težav z ročno registracijo tekačev, odslej bodo tekači ustvarjeni in uničeni samodejno.

6. Razmestite karte Helm s QBEC

Ker smo se odločili razmisliti gitlab-runner del našega projekta, je čas, da ga opišemo v našem repozitoriju Git.

Lahko bi ga opisali kot ločeno komponento spletna stran, vendar v prihodnosti načrtujemo uvedbo različnih kopij spletna stran zelo pogosto, za razliko od gitlab-runner, ki bo uveden samo enkrat na gručo Kubernetes. Torej inicializirajmo ločeno aplikacijo za to:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Tokrat entitet Kubernetes ne bomo opisovali ročno, ampak bomo vzeli že pripravljen grafikon Helm. Ena od prednosti qbec je zmožnost upodabljanja grafikonov Helm neposredno iz repozitorija Git.

Povežimo ga s podmodulom git:

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

Zdaj imenik prodajalec/gitlab-runner Imamo repozitorij z grafikonom za gitlab-runner.

Na podoben način lahko povežete druge repozitorije, na primer celotno repozitorij z uradnimi grafikoni https://github.com/helm/charts

Opišimo komponento komponente/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,
  }
)

Prvi argument za expandHelmTemplate preidemo pot do grafikona, nato params.values, ki ga vzamemo iz parametrov okolja, potem pride objekt s

  • nameTemplate — ime izdaje
  • imenski prostor — imenski prostor prenesen na krmilo
  • ta datoteka — zahtevan parameter, ki posreduje pot do trenutne datoteke
  • glasen - prikaže ukaz šablona za krmilo z vsemi argumenti pri upodabljanju grafikona

Zdaj pa opišimo parametre za našo komponento v okolju/base.libsonnet:

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

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

Обратите внимание runnerRegistrationToken vzamemo iz zunanje datoteke skrivnosti/base.libsonnet, ustvarimo ga:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Preverimo, če vse deluje:

qbec show default

če je vse v redu, lahko izbrišemo našo predhodno nameščeno izdajo prek Helma:

helm uninstall gitlab-runner

in ga namestite na enak način, vendar prek qbec:

qbec apply default

7. Uvod v git-crypt

Git-kripta je orodje, ki vam omogoča nastavitev preglednega šifriranja za vaš repozitorij.

Trenutno je struktura našega imenika za gitlab-runner videti takole:

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

Toda shranjevanje skrivnosti v Gitu ni varno, kajne? Zato jih moramo pravilno šifrirati.

Običajno zaradi ene spremenljivke to ni vedno smiselno. Skrivnosti lahko prenesete na qbec in prek spremenljivk okolja vašega sistema CI.
Vendar je treba omeniti, da obstajajo tudi bolj zapleteni projekti, ki lahko vsebujejo veliko več skrivnosti; prenos vseh skozi spremenljivke okolja bo izjemno težaven.

Poleg tega vam v tem primeru ne bi mogel povedati o tako čudovitem orodju, kot je git-crypt.

git-crypt Prav tako je priročno, ker vam omogoča shranjevanje celotne zgodovine skrivnosti, pa tudi primerjavo, združevanje in reševanje konfliktov na enak način, kot smo vajeni v primeru Git.

Prva stvar po namestitvi git-crypt ustvariti moramo ključe za naš repozitorij:

git crypt init

Če imate ključ PGP, se lahko takoj dodate kot sodelavec za ta projekt:

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

Tako lahko vedno dešifrirate to skladišče s svojim zasebnim ključem.

Če nimate ključa PGP in ga ne pričakujete, lahko greste v drugo smer in izvozite ključ projekta:

git crypt export-key /path/to/keyfile

Tako vsak, ki ima izvoženo ključna datoteka bo lahko dešifriral vaš repozitorij.

Čas je, da postavimo prvo skrivnost.
Naj vas spomnim, da smo še vedno v imeniku razmesti/gitlab-runner/, kjer imamo imenik skrivnosti/, šifrirajmo vse datoteke v njej, za to bomo ustvarili datoteko skrivnosti/.gitattributes z naslednjo vsebino:

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

Kot je razvidno iz vsebine, so vse datoteke maskirane * se bo vozil skozi git-crypt, razen najbolj .gitattributes

To lahko preverimo tako, da zaženemo:

git crypt status -e

Izhod bo seznam vseh datotek v repozitoriju, za katere je omogočeno šifriranje

To je vse, zdaj lahko varno potrdimo svoje spremembe:

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

Če želite blokirati repozitorij, zaženite:

git crypt lock

in takoj se bodo vse šifrirane datoteke spremenile v nekaj binarnega, nemogoče jih bo brati.
Če želite dešifrirati repozitorij, zaženite:

git crypt unlock

8. Ustvarite sliko orodjarne

Slika orodjarne je slika z vsemi orodji, ki jih bomo uporabili za uvedbo našega projekta. Uporabljal ga bo izvajalec Gitlab za izvajanje tipičnih nalog uvajanja.

Tukaj je vse preprosto, ustvarimo novo dockerfiles/toolbox/Dockerfile z naslednjo vsebino:

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

Kot lahko vidite, na tej sliki namestimo vse pripomočke, ki smo jih uporabili za uvedbo naše aplikacije. Tukaj ga ne potrebujemo, razen če kubectl, vendar se boste morda želeli poigrati z njim med fazo nastavitve cevovoda.

Poleg tega, da bi lahko komunicirali s Kubernetesom in ga uvedli, moramo konfigurirati vlogo za pode, ki jih generira gitlab-runner.

Če želite to narediti, pojdimo v imenik z gitlab-runner:

cd deploy/gitlab-runner

in dodajte novo komponento 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,
      },
    ],
  },
]

Opisali bomo tudi nove parametre v okolju/base.libsonnet, ki je zdaj videti takole:

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 se nanaša na Ime za komponento rbac

Poglejmo, kaj se je spremenilo:

qbec diff default

in uporabite naše spremembe za Kubernetes:

qbec apply default

Prav tako ne pozabite potrditi naših sprememb v 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š prvi cevovod in sestavljanje slik po oznakah

V korenu projekta bomo ustvarjali .gitlab-ci.yml z naslednjo vsebino:

.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

Upoštevajte, da uporabljamo GIT_SUBMODULE_STRATEGY: normalno za tista opravila, kjer morate eksplicitno inicializirati podmodule pred izvedbo.

Ne pozabite potrditi naših sprememb:

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

Mislim, da lahko temu mirno rečemo različica v0.0.1 in dodajte oznako:

git tag v0.0.1

Oznake bomo dodali vsakič, ko bomo morali izdati novo različico. Oznake v slikah Docker bodo povezane z oznakami Git. Vsak pritisk z novo oznako bo inicializiral gradnjo slik s to oznako.

Naredimo to git push --tagsin poglejmo naš prvi cevovod:

Posnetek zaslona prvega cevovoda

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Vredno je opozoriti na dejstvo, da je sestavljanje z oznakami primerno za izdelavo slik dockerjev, ni pa primerno za uvajanje aplikacije v Kubernetes. Ker se nove oznake lahko dodelijo starim povabilom, bo v tem primeru inicializacija cevovoda zanje vodila do uvedbe stare različice.

Da bi rešili to težavo, je izdelava slik dockerja običajno vezana na oznake, uvedba aplikacije pa v vejo mojster, v kateri so različice zbranih slik trdo kodirane. Tukaj lahko inicializirate povrnitev s preprostim povrnitvijo mojster- veje.

10. Avtomatizacija uvajanja

Da bo Gitlab-runner dešifriral naše skrivnosti, bomo morali izvoziti ključ repozitorija in ga dodati našim spremenljivkam okolja CI:

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

Nastalo vrstico bomo shranili v Gitlab; za to pojdimo v nastavitve našega projekta:
Nastavitve -> CI / CD -> Spremenljivke

In ustvarimo novo spremenljivko:

tip
Ključne
vrednost
Zaščiteno
Maskirana
področje uporabe

File
GITCRYPT_KEY
<your string>
true (med usposabljanjem lahko false)
true
All environments

Posnetek zaslona dodane spremenljivke

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Zdaj pa posodobimo naše .gitlab-ci.yml temu dodal:

.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

Tukaj smo omogočili več novih možnosti za qbec:

  • --root some/app — vam omogoča, da določite imenik določene aplikacije
  • --force:k8s-kontekst __incluster__ - to je čarobna spremenljivka, ki pove, da se bo uvedba zgodila v isti gruči, v kateri se izvaja gtilab-runner. To je potrebno, ker bo drugače qbec poskušal poiskati ustrezen strežnik Kubernetes v vašem kubeconfigu
  • --počakaj — prisili qbec, da počaka, da viri, ki jih ustvari, preidejo v stanje pripravljenosti, in šele nato zapre z uspešno izhodno kodo.
  • —da - preprosto onemogoči interaktivno lupino Ali si prepričan? ko je razporejen.

Ne pozabite potrditi naših sprememb:

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

In potem git push videli bomo, kako so bile naše aplikacije uvedene:

Posnetek zaslona drugega cevovoda

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

11. Artefakti in sestavljanje pri potiskanju na master

Običajno zgoraj opisani koraki zadoščajo za izdelavo in dostavo skoraj katere koli mikrostoritve, vendar ne želimo dodajati oznake vsakič, ko moramo posodobiti spletno mesto. Zato bomo ubrali bolj dinamično pot in v glavni veji vzpostavili povzetek.

Ideja je preprosta: zdaj podoba našega spletna stran bo znova zgrajen vsakič, ko pritisnete vanj mojster, in nato samodejno razmesti v Kubernetes.

Posodobimo ti dve delovni mesti v našem .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"

Upoštevajte, da smo dodali nit mojster к refs za delovna mesta build_website in zdaj uporabljamo $CI_COMMIT_REF_NAME namesto $CI_COMMIT_TAG, to pomeni, da smo odvezani od oznak v Gitu in zdaj bomo potisnili sliko z imenom veje objave, ki je inicializirala cevovod. Omeniti velja, da bo to delovalo tudi z oznakami, kar nam bo omogočilo shranjevanje posnetkov spletnega mesta z določeno različico v registru dockerjev.

Ko je ime oznake docker za novo različico spletnega mesta lahko nespremenjeno, moramo še vedno opisati spremembe v Kubernetesu, sicer preprosto ne bo ponovno razmestil aplikacije iz nove slike, saj ne bo opazil nobenih sprememb v manifest uvajanja.

Možnost —vm:ext-str digest=”$DIGEST” za qbec - omogoča posredovanje zunanje spremenljivke v jsonnet. Želimo, da se znova razporedi v gruči z vsako izdajo naše aplikacije. Ne moremo več uporabljati imena oznake, ki je zdaj lahko nespremenljivo, saj moramo biti vezani na določeno različico slike in sprožiti uvajanje, ko se spremeni.

Tu nam bo pomagala Kanikova sposobnost shranjevanja povzetka v datoteko (možnost --digest-datoteka)
Nato bomo to datoteko prenesli in jo prebrali v času uvajanja.

Posodobimo parametre za naše deploy/website/environments/base.libsonnet ki bo zdaj videti takole:

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

Končano, zdaj lahko vnesete vse obveznosti mojster inicializira gradnjo docker slike za spletna stranin ga nato razmestite v Kubernetes.

Ne pozabite potrditi naših sprememb:

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

Bomo preverili pozneje git push morali bi videti nekaj takega:

Posnetek zaslona cevovoda za master

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Načeloma nam gitlab-runnerja ni treba znova namestiti z vsakim pritiskom, razen če se seveda ni nič spremenilo v njegovi konfiguraciji, popravimo 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/**/*

spremembe vam bo omogočil spremljanje sprememb v razmesti/gitlab-runner/ in bo sprožil naše delo le, če jih bo

Ne pozabite potrditi naših sprememb:

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

git push, to je bolje:

Posnetek zaslona posodobljenega cevovoda

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

12. Dinamična okolja

Čas je, da popestrimo našo ponudbo z dinamičnimi okolji.

Najprej posodobimo delovno mesto build_website v našem .gitlab-ci.yml, odstranitev bloka iz njega samo, kar bo prisililo Gitlab, da ga sproži ob vsaki objavi v kateri koli veji:

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/

Nato posodobite opravilo deploy_website, tam dodajte blok okolje:

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 bo Gitlabu omogočilo, da delo poveže z prod okolje in prikaže pravilno povezavo do njega.

Zdaj pa dodamo še dve opravili:

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

Zagnali se bodo ob pritisku na katero koli vejo razen glavne in bodo uvedli predogledno različico mesta.

Vidimo novo možnost za qbec: --oznaka-aplikacije — omogoča označevanje nameščenih različic aplikacije in delo samo znotraj te oznake; pri ustvarjanju in uničevanju virov v Kubernetesu bo qbec deloval samo z njimi.
Na ta način ne moremo ustvariti ločenega okolja za vsako recenzijo, ampak preprosto ponovno uporabimo isto.

Tudi tukaj uporabljamo qbec uporabi pregled, namesto qbec uporabi privzeto - ravno to je trenutek, ko bomo poskušali opisati razlike za naša okolja (pregled in privzeto):

Dodajmo pregleda okolje v deploy/website/qbec.yaml

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

Nato ga bomo prijavili 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

In zapišite parametre po meri zanj 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',
    },
  },
}

Oglejmo si tudi jobu pobližje stop_review, se bo sprožil, ko bo veja izbrisana in da gitlab ne poskuša preveriti, se uporablja GIT_STRATEGY: nič, kasneje kloniramo mojster-veja in prek nje izbrišite pregled.
Malo je zmedeno, a lepšega načina še nisem našel.
Druga možnost bi bila umestitev vsake ocene v hotelski imenski prostor, ki ga je vedno mogoče v celoti porušiti.

Ne pozabite potrditi naših sprememb:

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

git push, git checkout -b test, test izvora git push, preveri:

Posnetek zaslona ustvarjenih okolij v Gitlabu

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Ali vse deluje? - super, izbrišite našo testno vejo: git checkout master, git push origin :test, preverimo, ali so opravila brisanja okolja delovala brez napak.

Tukaj bi rad takoj pojasnil, da lahko vsak razvijalec v projektu ustvarja veje, lahko tudi spreminja .gitlab-ci.yml datoteko in dostop do skrivnih spremenljivk.
Zato je močno priporočljivo, da se dovoli njihova uporaba samo za zaščitene veje, na primer v mojsterali ustvarite ločen nabor spremenljivk za vsako okolje.

13. Pregled aplikacij

Pregled aplikacij To je funkcija GitLab, ki vam omogoča, da dodate gumb za vsako datoteko v repozitoriju, da si jo hitro ogledate v razporejenem okolju.

Da se ti gumbi prikažejo, morate ustvariti datoteko .gitlab/route-map.yml in opišite vse transformacije poti v njej; v našem primeru bo zelo preprosto:

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

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

Ne pozabite potrditi naših sprememb:

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

git pushin preverite:

Posnetek zaslona gumba Pregled aplikacije

Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Delo je opravljeno!

Viri projekta:

Hvala za vašo pozornost, upam, da vam je bilo všeč Preizkušanje novih orodij za gradnjo in avtomatizacijo uvajanja v Kubernetes

Vir: www.habr.com

Dodaj komentar