Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Zdravo! U posljednje vrijeme objavljeno je mnogo zgodnih alata za automatizaciju i za pravljenje Docker slika i za implementaciju u Kubernetes. S tim u vezi, odlučio sam da se poigram sa Gitlabom, kako da proučim njegove mogućnosti i, naravno, postavim cevovod.

Ovaj sajt je inspirisan kubernetes.io, koji se generiše iz izvorni kodovi automatski, a za svaki poslani zahtjev za povlačenjem, robot automatski generiše pretpreglednu verziju stranice s vašim promjenama i pruža vezu za pregled.

Pokušao sam da napravim sličan proces od nule, ali u potpunosti izgrađen na Gitlab CI i besplatnim alatima koje sam koristio za postavljanje aplikacija na Kubernetes. Danas ću vam konačno reći nešto više o njima.

Članak će pokriti alate kao što su:
hugo, qbec, kaniko, git-crypt и GitLab CI sa stvaranjem dinamičnog okruženja.

Sadržaj

  1. Upoznavanje Huga
  2. Priprema Dockerfile-a
  3. Upoznavanje kaniko
  4. Uvod u qbec
  5. Isprobavanje Gitlab-runnera sa Kubernetes-executorom
  6. Postavite Helm karte sa qbec-om
  7. Uvod u git-crypt
  8. Kreirajte sliku kutije sa alatima
  9. Naš prvi pipeline i sastavljanje slika po oznakama
  10. Automatizacija implementacije
  11. Artefakti i montaža prilikom guranja do mastera
  12. Dinamična okruženja
  13. Pregledajte aplikacije

1. Upoznavanje Huga

Kao primjer našeg projekta, pokušat ćemo napraviti web stranicu za objavljivanje dokumentacije izgrađenu na Hugu. Hugo je generator statičkog sadržaja.

Za one koji nisu upoznati sa statičkim generatorima, reći ću vam nešto više o njima. Za razliku od običnih motora sajtova sa bazom podataka i nekom vrstom php-a, koji na zahtev korisnika generišu stranice u hodu, statički generatori su raspoređeni malo drugačije. Oni vam omogućavaju da uzmete izvor, obično skup datoteka u Markdown markup i predlošcima tema, a zatim ih prevedete u potpuno gotovu stranicu.

Odnosno, na izlazu ćete dobiti strukturu direktorija i skup generiranih html datoteka koje možete jednostavno prenijeti na bilo koji jeftini hosting i dobiti radnu stranicu.

Možete instalirati Hugo lokalno i isprobati ga:

Inicijalizacija nove stranice:

hugo new site docs.example.org

I u isto vrijeme git spremište:

cd docs.example.org
git init

Za sada je naš sajt netaknut i da bi se nešto pojavilo na njemu, prvo treba da povežemo temu, tema je samo skup šablona i postavljenih pravila po kojima se generiše naš sajt.

Kao temu ćemo koristiti naučiti, koji je, po mom mišljenju, najprikladniji za sajt sa dokumentacijom.

Želeo bih da obratim posebnu pažnju na činjenicu da ne moramo da spremamo fajlove tema u spremište našeg projekta, već ga jednostavno možemo povezati pomoću git podmodul:

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

Tako će u našem spremištu biti samo fajlovi direktno povezani sa našim projektom, a povezana tema će ostati kao veza do određenog spremišta i urezivanje u njemu, odnosno uvijek se može izvući iz originalnog izvora i ne plašiti se nekompatibilnih promjena.

Popravimo konfiguraciju config.toml:

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

Već u ovoj fazi možete pokrenuti:

hugo server

I to na adresi http://localhost:1313/ provjerite našu novokreiranu stranicu, sve promjene napravljene u direktoriju automatski ažuriraju otvorenu stranicu u pretraživaču, vrlo zgodno!

Pokušajmo napraviti naslovnu stranicu u content/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Snimak ekrana novokreirane stranice

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Da biste generirali web lokaciju, samo pokrenite:

hugo

Sadržaj direktorija publika/ i biće vaša stranica.
Da, usput, hajde da to odmah uvedemo .gitignore:

echo /public > .gitignore

Ne zaboravite izvršiti naše promjene:

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

2. Priprema Dockerfile-a

Vrijeme je da definiramo strukturu našeg spremišta. Obično koristim nešto poput:

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

  • dockerfiles/ - sadrže direktorije s Dockerfiles i sve što je potrebno za izgradnju naših docker slika.
  • razviti/ - sadrži direktorije za postavljanje naših aplikacija u Kubernetes

Tako ćemo usput kreirati naš prvi Dockerfile 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" ]

Kao što vidite, Dockerfile sadrži dva OD, ova mogućnost se zove višestepena izgradnja i omogućava vam da isključite sve nepotrebno iz završne docker slike.
Dakle, konačna slika će sadržavati samo darkhttpd (laki HTTP server) i publika/ - sadržaj naše statički generirane stranice.

Ne zaboravite izvršiti naše promjene:

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

3. Upoznavanje kaniko

Kao graditelj docker slika, odlučio sam koristiti kaniko, budući da njegov rad ne zahtijeva prisustvo docker demona, a sam sklop se može izvesti na bilo kojoj mašini i pohraniti keš direktno u registar, čime se oslobađa potrebe za punopravnim postojanim skladištem.

Da biste napravili sliku, samo pokrenite kontejner sa kaniko executor i proslijedite mu trenutni kontekst izgradnje, možete to učiniti lokalno, putem dockera:

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

Gde registry.gitlab.com/kvaps/docs.example.org/website - naziv vaše docker slike, nakon izgradnje će se automatski pokrenuti u docker registru.

Parametar --skladiste omogućava vam da keširate slojeve u docker registru, u datom primjeru oni će biti pohranjeni registry.gitlab.com/kvaps/docs.example.org/website/cache, ali možete odrediti drugu stazu s parametrom --cache-repo.

Snimak ekrana docker-registra

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

4. Uvod u qbec

Qbec je alat za primenu koji vam omogućava da deklarativno opišete manifeste svoje aplikacije i primenite ih na Kubernetes. Korištenje Jsonnet-a kao glavne sintakse čini vrlo lakim opisivanje razlika za više okruženja, a također gotovo potpuno eliminira ponavljanje koda.

Ovo može biti posebno istinito u slučajevima kada trebate implementirati aplikaciju u nekoliko klastera s različitim parametrima i želite ih deklarativno opisati u Gitu.

Qbec vam također omogućava da prikažete Helmove karte tako što ćete im proslijediti potrebne parametre i zatim raditi na njima na isti način kao i obični manifesti, uključujući mogućnost primjene različitih mutacija na njih, a to, zauzvrat, eliminira potrebu za korištenjem ChartMuseuma. To jest, možete pohraniti i prikazati grafikone direktno iz git-a, gdje im je mjesto.

Kao što sam već rekao, sve implementacije ćemo pohraniti u direktorij razviti/:

mkdir deploy
cd deploy

Inicijalizirajmo našu prvu aplikaciju:

qbec init website
cd website

Sada struktura naše aplikacije izgleda ovako:

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

pogledaj fajl qbec.yaml:

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

Ovdje nas prvenstveno zanima spec.environments, qbec je već kreirao podrazumevano okruženje za nas i uzeo adresu servera i imenski prostor iz našeg trenutnog kubeconfig-a.
Sada prilikom raspoređivanja na default okruženje, qbec će se uvijek implementirati samo na specificirani Kubernetes klaster i na specificirani imenski prostor, tj. više ne morate prelaziti između konteksta i prostora imena da biste se implementirali.
Ako je potrebno, uvijek možete ažurirati postavke u ovoj datoteci.

Sva vaša okruženja su opisana u qbec.yaml, i u datoteci params.libsonnet, koji kaže gdje trebate uzeti parametre za njih.

Zatim vidimo dva direktorija:

  • komponente / - svi manifesti za našu aplikaciju će biti pohranjeni ovdje, mogu se opisati iu jsonnet iu regularnim yaml datotekama
  • okruženja/ - ovdje ćemo opisati sve varijable (parametre) za naše okruženje.

Podrazumevano imamo dva fajla:

  • environments/base.libsonnet - sadržavat će zajedničke parametre za sva okruženja
  • okruženja/default.libsonnet - sadrži parametre redefinirane za okruženje default

hajde da otvorimo environments/base.libsonnet i tamo dodajte parametre za našu prvu komponentu:

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

Kreirajmo i našu prvu komponentu 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,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

U ovoj datoteci smo opisali tri Kubernetes entiteta odjednom, a to su: razvoj, usluga и Ulaz. Po želji, mogli bismo ih premjestiti u različite komponente, ali u ovoj fazi nam je jedna dovoljna.

sintaksa jsonnet vrlo sličan običnom json-u, u principu, običan json je već važeći jsonnet, tako da će vam u početku možda biti lakše koristiti online usluge kao što su yaml2json da konvertujete vaš uobičajeni yaml u json, ili ako vaše komponente ne sadrže nikakve varijable, onda se one mogu opisati u obliku običnog yaml-a.

Prilikom rada sa jsonnet Preporučujem vam da instalirate dodatak za svoj uređivač

Na primjer, postoji dodatak za vim vim-jsonnet, koji uključuje isticanje sintakse i automatski se izvršava jsonnet fmt pri svakom spremanju (zahteva da se instalira jsonnet).

Sve je spremno, sada možemo početi sa implementacijom:

Da vidimo šta imamo, pokrenimo:

qbec show default

Na izlazu ćete vidjeti renderirane yaml manifeste koji će biti primijenjeni na zadani klaster.

Odlično, sada se prijavite:

qbec apply default

Na izlazu ćete uvijek vidjeti šta će se raditi u vašem klasteru, qbec će od vas tražiti da prihvatite promjene upisivanjem y možete potvrditi svoje namjere.

Gotovo, naša aplikacija je postavljena!

Ako su promjene napravljene, uvijek možete pokrenuti:

qbec diff default

da vidite kako će ove promjene utjecati na trenutnu implementaciju

Ne zaboravite izvršiti naše promjene:

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

5. Isprobajte Gitlab-runner sa Kubernetes-executorom

Do nedavno sam koristio samo obične gitlab-runner na unaprijed pripremljenoj mašini (LXC kontejner) sa shell- ili docker-executorom. U početku smo imali nekoliko ovih trkača globalno definiranih u našem gitlabu. Napravili su docker slike za sve projekte.

Ali, kako je praksa pokazala, ova opcija nije najidealnija, kako u pogledu praktičnosti, tako iu smislu sigurnosti. Mnogo je bolje i ideološki ispravno imati odvojene trkače raspoređene za svaki projekat, pa čak i za svako okruženje.

Srećom, to uopće nije problem, jer ćemo se sada rasporediti gitlab-runner direktno kao dio našeg projekta u Kubernetesu.

Gitlab pruža gotov helm chart za implementaciju gitlab-runnera u Kubernetes. Dakle, sve što trebate znati je registracioni token za naš projekat u Postavke -> CI / CD -> Runners i prenesi ga na kormilo:

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

Gde:

  • https://gitlab.com je adresa vašeg Gitlab servera.
  • yga8y-jdCusVDn_t4Wxc - registracioni token za vaš projekat.
  • rbac.create=true - daje trkaču potreban broj privilegija da može kreirati podove za obavljanje naših zadataka koristeći kubernetes-executor.

Ako je sve urađeno kako treba, trebali biste vidjeti registrovanog trkača u odjeljku Runners, u postavkama vašeg projekta.

Snimak ekrana dodanog trkača

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Je li to tako jednostavno? - da, tako je jednostavno! Nema više muke s ručnom registracijom trkača, od sada će se trkači automatski kreirati i uništavati.

6. Postavite Helm karte s QBEC-om

Pošto smo odlučili da razmotrimo gitlab-runner dio našeg projekta, vrijeme je da ga opišemo u našem Git repozitoriju.

Mogli bismo ga opisati kao zasebnu komponentu sajt, ali u budućnosti planiramo implementirati različite kopije sajt vrlo često, za razliku od gitlab-runner, koji će biti raspoređen samo jednom po Kubernetes klasteru. Pa hajde da inicijalizujemo zasebnu aplikaciju za to:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Ovaj put nećemo ručno opisivati ​​Kubernetes entitete, već ćemo uzeti gotov Helm grafikon. Jedna od prednosti qbec-a je mogućnost prikazivanja Helmovih grafikona direktno iz Git repozitorija.

Omogućimo ga pomoću git podmodula:

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

Sada imenik vendor/gitlab-runner sadrži naše spremište sa grafikonom za gitlab-runner.

Ostala spremišta mogu se povezati na sličan način, na primjer, cijelo spremište sa zvaničnim grafikonima https://github.com/helm/charts

Hajde da opišemo komponentu 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 onda prolazimo put do grafikona params.values, koje uzimamo iz parametara okruženja, zatim dolazi objekt sa

  • nameTemplate - naziv izdanja
  • namespace - imenski prostor proslijeđen na kormilo
  • thisFile - obavezan parametar koji prosljeđuje putanju do trenutnog fajla
  • opširno - pokazuje komandu helm template sa svim argumentima prilikom prikazivanja grafikona

Sada opišimo parametre za našu komponentu u 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,
      },
    },
  },
}

Obrati pažnju runnerRegistrationToken preuzimamo iz eksterne datoteke secrets/base.libsonnet, kreirajmo ga:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Provjerimo da li sve radi:

qbec show default

ako je sve u redu, onda možemo ukloniti naše ranije raspoređeno putem Helm izdanja:

helm uninstall gitlab-runner

i implementirajte ga na isti način, ali kroz qbec:

qbec apply default

7. Uvod u git-crypt

git-crypt je alat koji vam omogućava da postavite transparentnu enkripciju za vaše spremište.

U ovom trenutku, naša struktura direktorija za gitlab-runner izgleda ovako:

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

Ali čuvanje tajni u Gitu nije sigurno, zar ne? Dakle, moramo ih pravilno šifrirati.

Obično zbog jedne varijable to nema uvijek smisla. Možete prenijeti tajne na qbec i kroz varijable okruženja vašeg CI sistema.
Ali vrijedi napomenuti da postoje i složeniji projekti koji mogu sadržavati mnogo više tajni, bit će izuzetno teško sve ih proći kroz varijable okruženja.

Osim toga, u ovom slučaju, ne bih vam mogao reći o tako divnom alatu kao što je git-crypt.

git-crypt Pogodan je i po tome što vam omogućava da sačuvate čitavu istoriju tajni, kao i da upoređujete, spajate i rešavate konflikte na isti način kao što smo to radili u slučaju Gita.

Prva stvar nakon instalacije git-crypt moramo generirati ključeve za naše spremište:

git crypt init

Ako imate PGP ključ, odmah se možete dodati kao saradnika za ovaj projekat:

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

Na ovaj način uvijek možete dešifrirati ovo spremište koristeći svoj privatni ključ.

Ako nemate PGP ključ i od njega se ne očekuje, onda možete ići drugim putem i izvesti ključ projekta:

git crypt export-key /path/to/keyfile

Dakle, svako ko posjeduje izvezen keyfile moći će dešifrirati vaše spremište.

Vrijeme je da otkrijemo našu prvu tajnu.
Da vas podsjetim da smo još uvijek u imeniku deploy/gitlab-runner/gdje imamo imenik tajne/, šifrirajmo sve datoteke u njemu, za to ćemo kreirati datoteku secrets/.gitattributes sa ovakvim sadržajem:

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

Kao što se vidi iz sadržaja, svi fajlovi po maski * proći će git-crypt, sa izuzetkom .gitattributes

Ovo možemo provjeriti pokretanjem:

git crypt status -e

Na izlazu dobijamo listu svih fajlova u spremištu za koje je omogućeno šifrovanje

To je to, sada možemo bezbedno izvršiti naše promene:

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

Da biste blokirali spremište, dovoljno je izvršiti:

git crypt lock

i odmah će se svi šifrirani fajlovi pretvoriti u nešto binarno, biće ih nemoguće pročitati.
Da dešifrujete spremište, pokrenite:

git crypt unlock

8. Kreirajte sliku kutije sa alatima

Slika kutije alata je slika sa svim alatima koje ćemo koristiti za implementaciju našeg projekta. Koristit će ga gitlab runner za obavljanje tipičnih zadataka postavljanja.

Ovdje je sve jednostavno, stvaramo novo dockerfiles/toolbox/Dockerfile sa ovakvim sadržajem:

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

Kao što možete vidjeti, na ovoj slici instaliramo sve uslužne programe koje smo koristili za implementaciju naše aplikacije. Ne trebamo ovde osim ako kubectl, ali biste se možda željeli poigrati s tim prilikom postavljanja cjevovoda.

Takođe, da bismo mogli da komuniciramo sa Kubernetesom i da se rasporedimo na njega, moramo da postavimo ulogu za podove koje generiše gitlab-runner.

Da biste to učinili, idite u direktorij sa gitlab-runner'om:

cd deploy/gitlab-runner

i dodajte novu komponentu komponenti/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,
      },
    ],
  },
]

Također opisujemo nove parametre u environments/base.libsonnet, koji sada izgleda ovako:

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

Obrati pažnju $.components.rbac.name odnosi se na ime za komponentu rbac

Hajde da proverimo šta se promenilo:

qbec diff default

i primijeniti naše promjene na Kubernetes:

qbec apply default

Takođe, ne zaboravite da unesete naše promene u 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 pipeline i sklapanje slika po tagovima

U osnovi projekta ćemo kreirati .gitlab-ci.yml sa ovakvim sadržajem:

.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

Imajte na umu da koristimo GIT_SUBMODULE_STRATEGY: normalno za one poslove gdje trebate eksplicitno inicijalizirati podmodule prije izvršenja.

Ne zaboravite izvršiti naše promjene:

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

Mislim da to možete sa sigurnošću nazvati verzijom v0.0.1 i dodajte oznaku:

git tag v0.0.1

Okačiti ćemo oznake kad god trebamo objaviti novu verziju. Oznake u Docker slikama bit će mapirane na Git oznake. Svaki push s novom oznakom će inicijalizirati izgradnju slike s tom oznakom.

Hoće izvršiti git push --tags, i pogledajte naš prvi cjevovod:

Snimak ekrana prvog cjevovoda

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Vrijedi naglasiti da su gradnje zasnovane na oznakama dobre za pravljenje docker slika, ali ne i za implementaciju aplikacije u Kubernetes. Budući da se nove oznake također mogu dodijeliti starim urezivanju, u ovom slučaju, inicijalizacija cjevovoda za njih će dovesti do postavljanja stare verzije.

Da bi se riješio ovaj problem, izrada docker slika obično je vezana za oznake, a implementacija aplikacije na granu majstor, u kojem su verzije prikupljenih slika tvrdo kodirane. U ovom slučaju možete inicijalizirati vraćanje jednostavnim vraćanjem majstor-grane.

10. Pokrenite automatizaciju

Da bi Gitlab-runner dešifrirao naše tajne, moramo eksportirati ključ spremišta i dodati ga našim varijablama CI okruženja:

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

rezultujući string ćemo sačuvati u Gitlabu, za to ćemo otići na postavke našeg projekta:
Postavke —> CI / CD —> Varijable

I kreirajte novu varijablu:

tip
ključ
vrijednost
zaštićen
maskiran
obim

File
GITCRYPT_KEY
<your string>
true (u vrijeme treninga možete false)
true
All environments

Snimak ekrana dodane varijable

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Sada ažurirajmo naše .gitlab-ci.yml dodajući tome:

.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

Ovdje smo omogućili neke nove opcije za qbec:

  • --root some/app - omogućava vam da definirate direktorij određene aplikacije
  • --force:k8s-context __incluster__ - ovo je magična varijabla koja kaže da će se implementacija dogoditi u istom klasteru u kojem je pokrenut gtilab-runner. Ovo je neophodno, inače će qbec pokušati pronaći odgovarajući Kubernetes server u vašem kubeconfigu
  • -cekaj - prisiljava qbec da čeka dok resursi koje kreira ne pređu u stanje Ready i tek onda završi uspješnim izlaznim kodom.
  • -da - samo onemogućava interaktivnu ljusku Jesi li siguran? tokom raspoređivanja.

Ne zaboravite izvršiti naše promjene:

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

I poslije git push vidjet ćemo kako su naše aplikacije raspoređene:

Snimak ekrana drugog cjevovoda

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

11. Artefakti i sklapanje pri guranje do mastera

Obično su gornji koraci dovoljni za izgradnju i isporuku gotovo svih mikroservisa, ali ne želimo da dodajemo oznaku svaki put kada trebamo ažurirati web lokaciju. Stoga ćemo ići na dinamičniji način i podesiti implementaciju sažetka u glavnoj grani.

Ideja je jednostavna: sada naša slika sajt će se obnavljati svaki put kada to budete pritisnuli majstor, a zatim se automatski implementira u Kubernetes.

Ažurirajmo ova dva posla u 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"

Napominjemo da smo dodali granu majstor к ref za posao build_website i sada koristimo $CI_COMMIT_REF_NAME umjesto $CI_COMMIT_TAG, to jest, riješimo se tagova u Gitu i sada ćemo gurnuti sliku s imenom grane urezivanja koja je inicijalizirala vaš cjevovod. Vrijedi napomenuti da će ovo raditi i sa oznakama, što će nam omogućiti da sačuvamo snimke stranice sa određenom verzijom u docker-registru.

Kada naziv docker oznake za novu verziju stranice može biti nepromijenjen, još uvijek moramo opisati promjene za Kubernetes, inače jednostavno neće ponovo postaviti aplikaciju sa nove slike, jer neće primijetiti nikakve promjene u manifest raspoređivanja.

Opcija --vm:ext-str digest="$DIGEST" za qbec - omogućava vam da proslijedite eksternu varijablu u jsonnet. Želimo da se naša aplikacija ponovo raspoređuje u klaster sa svakim izdanjem. Više ne možemo koristiti ime oznake, koje sada može biti nepromijenjeno, jer se moramo vezati za određenu verziju slike i pokrenuti implementaciju kada se promijeni.

Ovdje će nam pomoći Kanikova sposobnost da sačuva sažetak slike u datoteku (opcija --digest-file)
Zatim ćemo prenijeti ovu datoteku i pročitati je u vrijeme postavljanja.

Ažurirajmo parametre za naše deploy/website/environments/base.libsonnet koji će sada izgledati ovako:

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

Gotovo, sada uključite bilo kakvu obvezu majstor inicijalizira izgradnju docker slike za sajt, a zatim ga rasporedite u Kubernetes.

Ne zaboravite izvršiti naše promjene:

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

Provjerite to poslije git push trebali bismo vidjeti nešto ovako:

Snimak ekrana cjevovoda za master

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

U principu, ne moramo ponovo postavljati gitlab-runner sa svakim pritiskom, osim ako se, naravno, ništa nije promijenilo u njegovoj konfiguraciji, popravimo to u .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/**/*

promjene će pratiti promjene u deploy/gitlab-runner/ i pokrenuće naš posao samo ako ih ima

Ne zaboravite izvršiti naše promjene:

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

git push, to je bolje:

Snimak ekrana ažuriranog cjevovoda

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

12. Dinamička okruženja

Vrijeme je da diverzificiramo naš cevovod dinamičnim okruženjima.

Prvo, ažurirajmo posao build_website u našem .gitlab-ci.yml, uklanjajući blok sa njega samo, što će primorati Gitlab da ga pokrene na bilo kojem urezivanju na bilo koju granu:

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/

Zatim ažurirajte posao deploy_website, dodajte blok tamo ambijent:

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"

Ovo će omogućiti Gitlabu da poveže posao sa prod okruženje i prikažite ispravnu vezu do njega.

Sada dodajmo još dva posla:

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

Oni će se pokrenuti pritiskom na bilo koju granu osim master i pokrenut će verziju stranice za pregled.

Vidimo novu opciju za qbec: --app-tag - omogućava vam da označite implementirane verzije aplikacije i radite samo unutar ove oznake; kada kreirate i uništavate resurse u Kubernetesu, qbec će raditi samo na njima.
Dakle, ne možemo kreirati posebno okruženje za svaku recenziju, već jednostavno ponovo koristiti isto.

Ovdje također koristimo qbec primijeniti pregledumjesto qbec primijeniti default - ovo je upravo trenutak kada ćemo pokušati opisati razlike za naše sredine (recenzija i zadano):

Hajde da dodamo pregled okruženje u deploy/website/qbec.yaml

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

Zatim ga deklariramo 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

I upišite prilagođene parametre za to 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',
    },
  },
}

Pogledajmo i posao izbliza stop_review, aktivirat će se kada se grana ukloni i tako da gitlab ne pokuša provjeriti na njoj se koristi GIT_STRATEGY: nema, kasnije ćemo klonirati majstor-granati i brisati recenziju kroz nju.
Malo zbunjujuće, ali još nisam pronašao ljepši način.
Alternativna opcija bi bila da se svaka recenzija rasporedi u imenski prostor hotela, koji se uvijek može uništiti u cijelosti.

Ne zaboravite izvršiti naše promjene:

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

git push, git checkout -b test, git push origin test, provjerite:

Snimak ekrana kreiranih okruženja u Gitlabu

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Sve radi? - super, izbrišite našu test granu: git checkout master, git push origin :test, provjeravamo da li su poslovi za brisanje okruženja radili bez grešaka.

Ovdje odmah želim pojasniti da bilo koji programer u projektu može kreirati grane, može se i mijenjati .gitlab-ci.yml fajl i pristupne tajne varijable.
Stoga se snažno preporučuje da se njihova upotreba dozvoli samo za zaštićene grane, na primjer u majstorili kreirajte poseban skup varijabli za svako okruženje.

13 Pregledajte aplikacije

Pregledajte aplikacije ovo je gitlab funkcija koja vam omogućava da dodate dugme za svaki fajl u spremištu da biste ga brzo pregledali u primenjenom okruženju.

Da bi se ova dugmad pojavila, potrebno je da kreirate datoteku .gitlab/route-map.yml i opisati u njemu sve transformacije staza, u našem slučaju to će biti vrlo jednostavno:

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

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

Ne zaboravite izvršiti naše promjene:

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

git push, i provjerite:

Snimak ekrana dugmeta za pregled aplikacije

Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

Posao je gotov!

Izvori projekta:

Hvala na pažnji, nadam se da vam se svidjelo Isprobavanje novih alata za izgradnju i automatizaciju implementacije u Kubernetesu

izvor: www.habr.com

Dodajte komentar