Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

hello! Baru-baru ini, banyak alat automasi yang hebat telah dikeluarkan untuk membina imej Docker dan untuk penempatan ke Kubernetes. Dalam hal ini, saya memutuskan untuk bermain-main dengan GitLab, mengkaji dengan teliti keupayaannya dan, sudah tentu, menyediakan saluran paip.

Kerja ini diilhamkan oleh laman web kubernetes.io, yang dihasilkan daripada kod sumber secara automatik, dan untuk setiap permintaan kumpulan yang dihantar, robot secara automatik menjana versi pratonton tapak dengan perubahan anda dan menyediakan pautan untuk dilihat.

Saya cuba membina proses yang sama dari awal, tetapi dibina sepenuhnya pada Gitlab CI dan alatan percuma yang biasa saya gunakan untuk menggunakan aplikasi ke Kubernetes. Hari ini saya akhirnya akan memberitahu anda lebih lanjut tentang mereka.

Artikel itu akan membincangkan alat seperti:
Hugo, qbec, kaniko, git-crypt и GitLab CI dengan penciptaan persekitaran yang dinamik.

Kandungan

  1. Temui Hugo
  2. Menyediakan fail Docker
  3. Mengenali kaniko
  4. Mengenali qbec
  5. Mencuba Gitlab-runner dengan Kubernetes-executor
  6. Menggunakan carta Helm dengan qbec
  7. Memperkenalkan git-crypt
  8. Mencipta imej kotak alat
  9. Saluran paip pertama kami dan pemasangan imej mengikut tag
  10. Automasi penggunaan
  11. Artifak dan pemasangan apabila menolak untuk menguasai
  12. Persekitaran dinamik
  13. Semak Apl

1. Mengenali Hugo

Sebagai contoh projek kami, kami akan cuba mencipta tapak penerbitan dokumentasi yang dibina di Hugo. Hugo ialah penjana kandungan statik.

Bagi mereka yang tidak biasa dengan penjana statik, saya akan memberitahu anda lebih lanjut mengenainya. Tidak seperti enjin laman web konvensional dengan pangkalan data dan beberapa PHP, yang, apabila diminta oleh pengguna, menjana halaman dengan cepat, penjana statik direka sedikit berbeza. Mereka membenarkan anda mengambil sumber, biasanya satu set fail dalam markup Markdown dan templat tema, kemudian menyusunnya ke dalam tapak web yang telah siap sepenuhnya.

Iaitu, sebagai hasilnya, anda akan menerima struktur direktori dan satu set fail HTML yang dijana, yang anda boleh muat naik ke mana-mana pengehosan murah dan mendapatkan tapak web yang berfungsi.

Anda boleh memasang Hugo secara tempatan dan mencubanya:

Memulakan tapak baharu:

hugo new site docs.example.org

Dan pada masa yang sama repositori git:

cd docs.example.org
git init

Setakat ini, tapak kami adalah murni dan agar sesuatu muncul di atasnya, kami perlu menyambungkan tema terlebih dahulu; tema hanyalah satu set templat dan peraturan tertentu yang mana tapak kami dihasilkan.

Untuk tema yang akan kami gunakan Belajar, yang, pada pendapat saya, sangat sesuai untuk tapak dokumentasi.

Saya ingin memberi perhatian khusus kepada fakta bahawa kami tidak perlu menyimpan fail tema dalam repositori projek kami; sebaliknya, kami hanya boleh menyambungkannya menggunakan submodul git:

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

Oleh itu, repositori kami hanya akan mengandungi fail yang berkaitan secara langsung dengan projek kami, dan tema yang disambungkan akan kekal sebagai pautan ke repositori tertentu dan komit di dalamnya, iaitu, ia sentiasa boleh ditarik dari sumber asal dan tidak takut perubahan yang tidak serasi.

Mari betulkan konfigurasi config.toml:

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

Sudah pada peringkat ini anda boleh menjalankan:

hugo server

Dan di alamat http://localhost:1313/ semak laman web kami yang baru dibuat, semua perubahan yang dibuat dalam direktori secara automatik mengemas kini halaman terbuka dalam penyemak imbas, sangat mudah!

Mari cuba buat muka depan dalam kandungan/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Tangkapan skrin halaman yang baru dibuat

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Untuk menjana tapak, jalankan sahaja:

hugo

Kandungan direktori awam/ dan akan menjadi laman web anda.
Ya, dengan cara ini, mari segera menambahnya .giignore:

echo /public > .gitignore

Jangan lupa untuk melakukan perubahan kami:

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

2. Menyediakan Fail Docker

Sudah tiba masanya untuk menentukan struktur repositori kami. Saya biasanya menggunakan sesuatu seperti:

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

  • dockerfiles/ — mengandungi direktori dengan Dockerfiles dan semua yang diperlukan untuk membina imej Docker kami.
  • menempatkan/ — mengandungi direktori untuk menggunakan aplikasi kami ke Kubernetes

Oleh itu, kami akan mencipta Dockerfile pertama kami di sepanjang laluan dockerfiles/laman web/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" ]

Seperti yang anda lihat, Dockerfile mengandungi dua DARIPADA, ciri ini dipanggil binaan berbilang peringkat dan membolehkan anda mengecualikan semua yang tidak perlu daripada imej Docker akhir.
Oleh itu, imej akhir hanya akan mengandungi gelaphttpd (pelayan HTTP ringan) dan awam/ — kandungan laman web kami yang dijana secara statik.

Jangan lupa untuk melakukan perubahan kami:

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

3. Mengenali kaniko

Sebagai pembina imej docker, saya memutuskan untuk menggunakan kaniko, memandangkan operasinya tidak memerlukan daemon docker, dan binaan itu sendiri boleh dijalankan pada mana-mana mesin dan cache boleh disimpan terus dalam registri, dengan itu menghapuskan keperluan untuk mempunyai storan berterusan yang lengkap.

Untuk membina imej, jalankan sahaja bekas dengan pelaksana kaniko dan luluskan konteks binaan semasa; ini juga boleh dilakukan secara tempatan, melalui docker:

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

Где registry.gitlab.com/kvaps/docs.example.org/website — nama imej docker anda; selepas dibina, ia akan dilancarkan secara automatik ke dalam pendaftaran docker.

Parameter --cache membolehkan anda membuat cache lapisan dalam pendaftaran docker; untuk contoh yang diberikan, ia akan disimpan dalam registry.gitlab.com/kvaps/docs.example.org/website/cache, tetapi anda boleh menentukan laluan lain menggunakan parameter --cache-repo.

Tangkapan skrin docker-registry

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

4. Mengenali qbec

Qbec ialah alat pengerahan yang membolehkan anda mengisytiharkan manifes aplikasi anda secara deklaratif dan menggunakannya ke Kubernetes. Menggunakan Jsonnet sebagai sintaks utama membolehkan anda memudahkan huraian perbezaan merentasi pelbagai persekitaran, dan juga hampir menghapuskan pengulangan kod sepenuhnya.

Ini boleh berlaku terutamanya dalam kes di mana anda perlu menggunakan aplikasi ke beberapa kluster dengan parameter yang berbeza dan ingin menerangkannya secara deklaratif dalam Git.

Qbec juga membolehkan anda membuat carta Helm dengan menghantar parameter yang diperlukan dan kemudian mengendalikannya dengan cara yang sama seperti manifes biasa, termasuk anda boleh menggunakan pelbagai mutasi padanya, dan ini, seterusnya, membolehkan anda menyingkirkan keperluan untuk gunakan ChartMuseum. Iaitu, anda boleh menyimpan dan membuat carta terus dari git, tempat ia berada.

Seperti yang saya katakan sebelum ini, kami akan menyimpan semua penempatan dalam direktori menempatkan/:

mkdir deploy
cd deploy

Mari kita mulakan aplikasi pertama kita:

qbec init website
cd website

Sekarang struktur aplikasi kami kelihatan seperti ini:

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

mari lihat fail qbec.yaml:

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

Di sini kami sangat berminat spec.persekitaran, qbec telah pun mencipta persekitaran lalai untuk kami dan mengambil alamat pelayan, serta ruang nama daripada kubeconfig semasa kami.
Sekarang apabila digunakan untuk lalai persekitaran, qbec akan sentiasa menggunakan hanya pada gugusan Kubernetes yang ditentukan dan ke ruang nama yang ditentukan, iaitu, anda tidak perlu lagi menukar antara konteks dan ruang nama untuk melaksanakan penggunaan.
Jika perlu, anda sentiasa boleh mengemas kini tetapan dalam fail ini.

Semua persekitaran anda diterangkan dalam qbec.yaml, dan dalam fail params.libsonnet, di mana ia menyatakan tempat untuk mendapatkan parameter untuk mereka.

Seterusnya kita melihat dua direktori:

  • komponen/ — semua manifes untuk aplikasi kami akan disimpan di sini; ia boleh diterangkan dalam jsonnet dan fail yaml biasa
  • persekitaran/ — di sini kita akan menerangkan semua pembolehubah (parameter) untuk persekitaran kita.

Secara lalai kami mempunyai dua fail:

  • environments/base.libsonnet - ia akan mengandungi parameter biasa untuk semua persekitaran
  • environments/default.libsonnet — mengandungi parameter yang ditindih untuk persekitaran lalai

jom buka environments/base.libsonnet dan tambah parameter untuk komponen pertama kami di sana:

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

Mari kita buat juga komponen pertama kita component/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,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

Dalam fail ini, kami menerangkan tiga entiti Kubernetes sekaligus, ini ialah: Deployment, Servis и Ingress. Jika kita mahu, kita boleh memasukkannya ke dalam komponen yang berbeza, tetapi pada peringkat ini satu sudah cukup untuk kita.

sintaks jsonnet adalah sangat serupa dengan json biasa, pada dasarnya, json biasa sudah pun sah jsonnet, jadi pada mulanya mungkin lebih mudah untuk anda menggunakan perkhidmatan dalam talian seperti yaml2json untuk menukar yaml biasa anda kepada json, atau, jika komponen anda tidak mengandungi sebarang pembolehubah, maka ia boleh diterangkan dalam bentuk yaml biasa.

Semasa bekerja dengan jsonnet Saya sangat mengesyorkan memasang pemalam untuk editor anda

Sebagai contoh, terdapat pemalam untuk vim vim-jsonnet, yang menghidupkan penyerlahan sintaks dan dilaksanakan secara automatik jsonnet fmt setiap kali anda menyimpan (memerlukan jsonnet dipasang).

Segala-galanya sudah sedia, kini kita boleh mula menggunakan:

Untuk melihat apa yang kami dapat, mari jalankan:

qbec show default

Pada output, anda akan melihat manifes yaml yang diberikan yang akan digunakan pada kelompok lalai.

Bagus, sekarang mohon:

qbec apply default

Pada output anda akan sentiasa melihat apa yang akan dilakukan dalam kluster anda, qbec akan meminta anda bersetuju dengan perubahan dengan menaip y anda akan dapat mengesahkan niat anda.

Permohonan kami sedia dan digunakan!

Jika anda membuat perubahan, anda sentiasa boleh melakukan:

qbec diff default

untuk melihat cara perubahan ini akan mempengaruhi penggunaan semasa

Jangan lupa untuk melakukan perubahan kami:

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

5. Mencuba Gitlab-runner dengan Kubernetes-executor

Sehingga baru-baru ini saya hanya menggunakan biasa gitlab-runner pada mesin yang telah disediakan sebelumnya (bekas LXC) dengan cangkerang atau pelaksana docker. Pada mulanya, kami mempunyai beberapa pelari sedemikian yang ditakrifkan secara global dalam gitlab kami. Mereka mengumpul imej buruh pelabuhan untuk semua projek.

Tetapi seperti yang ditunjukkan oleh amalan, pilihan ini bukanlah yang paling ideal, baik dari segi praktikal dan keselamatan. Adalah lebih baik dan lebih tepat dari segi ideologi untuk mempunyai pelari yang berasingan digunakan untuk setiap projek, atau bahkan untuk setiap persekitaran.

Nasib baik, ini tidak menjadi masalah sama sekali, kerana sekarang kami akan menggunakan gitlab-runner secara langsung sebagai sebahagian daripada projek kami di Kubernetes.

Gitlab menyediakan carta helm siap sedia untuk menggunakan gitlab-runner ke Kubernetes. Jadi apa yang anda perlu lakukan ialah mengetahui token pendaftaran untuk projek kami di Tetapan -> CI / CD -> Pelari dan serahkan kepada pimpinan:

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

Di mana:

  • https://gitlab.com — alamat pelayan Gitlab anda.
  • yga8y-jdCusVDn_t4Wxc — token pendaftaran untuk projek anda.
  • rbac.create=true — menyediakan pelari dengan jumlah keistimewaan yang diperlukan untuk dapat membuat pod untuk melaksanakan tugas kami menggunakan kubernetes-executor.

Jika semuanya dilakukan dengan betul, anda sepatutnya melihat pelari berdaftar dalam bahagian tersebut Runners, dalam tetapan projek anda.

Tangkapan skrin pelari yang ditambah

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Adakah semudah itu? - ya, semudah itu! Tiada lagi kerumitan untuk mendaftar pelari secara manual, mulai sekarang pelari akan dicipta dan dimusnahkan secara automatik.

6. Pasang carta Helm dengan QBEC

Sejak kami memutuskan untuk mempertimbangkan gitlab-runner sebahagian daripada projek kami, sudah tiba masanya untuk menerangkannya dalam repositori Git kami.

Kita boleh menggambarkannya sebagai komponen yang berasingan laman web, tetapi pada masa hadapan kami merancang untuk menggunakan salinan yang berbeza laman web sangat kerap, tidak seperti gitlab-runner, yang akan digunakan sekali sahaja bagi setiap kelompok Kubernetes. Jadi mari kita mulakan aplikasi berasingan untuknya:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Kali ini kami tidak akan menerangkan entiti Kubernetes secara manual, tetapi akan mengambil carta Helm siap sedia. Salah satu kelebihan qbec ialah keupayaan untuk memaparkan carta Helm terus daripada repositori Git.

Mari sambungkannya menggunakan submodul git:

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

Sekarang direktori vendor/gitlab-runner Kami mempunyai repositori dengan carta untuk gitlab-runner.

Dengan cara yang sama, anda boleh menyambungkan repositori lain, contohnya, keseluruhan repositori dengan carta rasmi https://github.com/helm/charts

Mari kita terangkan komponen components/gitlab-runner.jsonnet:

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

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

Hujah pertama kepada expandHelmTemplate kita lulus laluan ke carta, kemudian params.values, yang kita ambil daripada parameter persekitaran, kemudian datang objek dengan

  • nameTemplate - nama keluaran
  • ruang nama — ruang nama dipindahkan ke pimpinan
  • Fail ini — parameter yang diperlukan yang melepasi laluan ke fail semasa
  • kata kerja - menunjukkan arahan templat helm dengan semua hujah semasa memaparkan carta

Sekarang mari kita terangkan parameter untuk komponen kita dalam 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,
      },
    },
  },
}

Perhatikan runnerRegistrationToken kami ambil dari fail luaran rahsia/base.libsonnet, mari kita buat:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Mari semak sama ada semuanya berfungsi:

qbec show default

jika semuanya teratur, maka kami boleh memadam keluaran kami yang digunakan sebelum ini melalui Helm:

helm uninstall gitlab-runner

dan gunakannya dengan cara yang sama, tetapi melalui qbec:

qbec apply default

7. Pengenalan kepada git-crypt

Git-crypt ialah alat yang membolehkan anda menyediakan penyulitan telus untuk repositori anda.

Pada masa ini, struktur direktori kami untuk gitlab-runner kelihatan seperti ini:

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

Tetapi menyimpan rahsia dalam Git tidak selamat, bukan? Jadi kita perlu menyulitkannya dengan betul.

Biasanya, demi satu pembolehubah, ini tidak selalu masuk akal. Anda boleh memindahkan rahsia kepada qbec dan melalui pembolehubah persekitaran sistem CI anda.
Tetapi perlu diingat bahawa terdapat juga projek yang lebih kompleks yang boleh mengandungi lebih banyak rahsia; memindahkan mereka semua melalui pembolehubah persekitaran akan menjadi sangat sukar.

Lebih-lebih lagi, dalam kes ini saya tidak akan dapat memberitahu anda tentang alat yang hebat seperti itu git-crypt.

git-crypt Ia juga mudah kerana ia membolehkan anda menyimpan keseluruhan sejarah rahsia, serta membandingkan, menggabungkan dan menyelesaikan konflik dengan cara yang sama seperti yang biasa kita lakukan dalam kes Git.

Perkara pertama selepas pemasangan git-crypt kami perlu menjana kunci untuk repositori kami:

git crypt init

Jika anda mempunyai kunci PGP, maka anda boleh menambah diri anda dengan segera sebagai kolaborator untuk projek ini:

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

Dengan cara ini anda sentiasa boleh menyahsulit repositori ini menggunakan kunci peribadi anda.

Jika anda tidak mempunyai kunci PGP dan tidak mengharapkannya, maka anda boleh pergi ke arah lain dan mengeksport kunci projek:

git crypt export-key /path/to/keyfile

Oleh itu, sesiapa sahaja yang telah dieksport fail kunci akan dapat menyahsulit repositori anda.

Sudah tiba masanya untuk menetapkan rahsia pertama kami.
Izinkan saya mengingatkan anda bahawa kami masih dalam direktori deploy/gitlab-runner/, di mana kami mempunyai direktori rahsia/, mari kita menyulitkan semua fail di dalamnya, untuk ini kita akan membuat fail rahsia/.gitattributes dengan kandungan berikut:

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

Seperti yang dapat dilihat dari kandungan, semua fail bertopeng * akan dipandu melalui git-crypt, kecuali yang paling banyak .gitattributes

Kita boleh menyemak ini dengan menjalankan:

git crypt status -e

Output akan menjadi senarai semua fail dalam repositori yang mana penyulitan didayakan

Itu sahaja, kini kami boleh melakukan perubahan kami dengan selamat:

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

Untuk menyekat repositori, jalankan sahaja:

git crypt lock

dan dengan serta-merta semua fail yang disulitkan akan bertukar menjadi sesuatu binari, ia akan menjadi mustahil untuk membacanya.
Untuk menyahsulit repositori, jalankan:

git crypt unlock

8. Buat imej kotak alat

Imej kotak alat ialah imej dengan semua alatan yang akan kami gunakan untuk menggunakan projek kami. Ia akan digunakan oleh pelari Gitlab untuk melaksanakan tugas penempatan biasa.

Semuanya mudah di sini, mari buat yang baru dockerfiles/toolbox/Dockerfile dengan kandungan berikut:

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

Seperti yang anda lihat, dalam imej ini kami memasang semua utiliti yang kami gunakan untuk menggunakan aplikasi kami. Kami tidak memerlukannya di sini melainkan kubectl, tetapi anda mungkin mahu bermain-main dengannya semasa fasa persediaan saluran paip.

Selain itu, untuk dapat berkomunikasi dengan Kubernetes dan menggunakannya, kita perlu mengkonfigurasi peranan untuk pod yang dijana oleh gitlab-runner.

Untuk melakukan ini, mari pergi ke direktori dengan gitlab-runner:

cd deploy/gitlab-runner

dan tambah komponen baharu components/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,
      },
    ],
  },
]

Kami juga akan menerangkan parameter baharu dalam environments/base.libsonnet, yang kini kelihatan seperti ini:

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

Perhatikan $.components.rbac.name merujuk kepada nama untuk komponen rbac

Mari semak apa yang telah berubah:

qbec diff default

dan gunakan perubahan kami pada Kubernetes:

qbec apply default

Juga, jangan lupa untuk melakukan perubahan kami kepada 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. Saluran paip pertama kami dan pemasangan imej mengikut tag

Pada akar projek yang akan kami buat .gitlab-ci.yml dengan kandungan berikut:

.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

Sila ambil perhatian kami menggunakan GIT_SUBMODULE_STRATEGY: biasa untuk pekerjaan yang anda perlukan untuk memulakan submodul secara eksplisit sebelum pelaksanaan.

Jangan lupa untuk melakukan perubahan kami:

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

Saya fikir kita boleh memanggil ini versi dengan selamat v0.0.1 dan tambah tag:

git tag v0.0.1

Kami akan menambah tag apabila kami perlu mengeluarkan versi baharu. Teg dalam imej Docker akan terikat dengan tag Git. Setiap tolakan dengan teg baharu akan memulakan binaan imej dengan teg ini.

Mari lakukannya git push --tags, dan mari kita lihat saluran paip pertama kami:

Tangkapan skrin saluran paip pertama

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Perlu menarik perhatian anda kepada fakta bahawa pemasangan mengikut tag sesuai untuk membina imej docker, tetapi tidak sesuai untuk menggunakan aplikasi ke Kubernetes. Memandangkan teg baharu boleh diberikan kepada komit lama, dalam kes ini, memulakan saluran paip untuknya akan membawa kepada penggunaan versi lama.

Untuk menyelesaikan masalah ini, biasanya binaan imej docker terikat pada tag, dan penggunaan aplikasi ke cawangan master, di mana versi imej yang dikumpul dikodkan keras. Di sinilah anda boleh memulakan pemulangan semula dengan pemulangan mudah master-cawangan.

10. Automasi penggunaan

Untuk membolehkan Gitlab-runner menyahsulit rahsia kami, kami perlu mengeksport kunci repositori dan menambahkannya pada pembolehubah persekitaran CI kami:

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

Kami akan menyimpan baris yang terhasil dalam Gitlab; untuk melakukan ini, mari pergi ke tetapan projek kami:
Tetapan -> CI / CD -> Pembolehubah

Dan mari buat pembolehubah baharu:

Jenis
Utama
nilai
Dilindungi
Masked
Skop

File
GITCRYPT_KEY
<your string>
true (semasa latihan anda boleh false)
true
All environments

Tangkapan skrin pembolehubah yang ditambah

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Sekarang mari kemas kini kami .gitlab-ci.yml menambahnya:

.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

Di sini kami telah mendayakan beberapa pilihan baharu untuk qbec:

  • --root some/app — membolehkan anda menentukan direktori aplikasi tertentu
  • --force:k8s-context __incluster__ - ini ialah pembolehubah ajaib yang mengatakan bahawa penggunaan akan berlaku dalam kelompok yang sama di mana gtilab-runner sedang berjalan. Ini perlu kerana jika tidak qbec akan cuba mencari pelayan Kubernetes yang sesuai dalam kubeconfig anda
  • --tunggu — memaksa qbec menunggu sehingga sumber yang diciptanya masuk ke dalam keadaan Sedia dan hanya kemudian keluar dengan kod keluar yang berjaya.
  • —ya - hanya melumpuhkan shell interaktif Adakah anda pasti? apabila dikerahkan.

Jangan lupa untuk melakukan perubahan kami:

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

Dan selepas tolak git kami akan melihat bagaimana aplikasi kami telah digunakan:

Tangkapan skrin saluran paip kedua

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

11. Artifak dan pemasangan apabila menolak untuk menguasai

Biasanya, langkah yang diterangkan di atas adalah mencukupi untuk membina dan menyampaikan hampir mana-mana perkhidmatan mikro, tetapi kami tidak mahu menambah teg setiap kali kami perlu mengemas kini tapak. Oleh itu, kami akan mengambil laluan yang lebih dinamik dan menyediakan penempatan ringkasan dalam cawangan induk.

Ideanya mudah: kini imej kami laman web akan dibina semula setiap kali anda menolak masuk master, dan kemudian secara automatik digunakan ke Kubernetes.

Mari kemas kini dua kerja ini dalam kami .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"

Sila ambil perhatian bahawa kami telah menambah urutan master к ref untuk pekerjaan build_website dan kini kami gunakan $CI_COMMIT_REF_NAME bukannya $CI_COMMIT_TAG, iaitu, kami dilepaskan daripada teg dalam Git dan kini kami akan menolak imej dengan nama cawangan komit yang memulakan saluran paip. Perlu diingat bahawa ini juga akan berfungsi dengan teg, yang membolehkan kami menyimpan syot kilat tapak dengan versi tertentu dalam pendaftaran docker.

Apabila nama tag docker untuk versi baharu tapak boleh tidak diubah, kami masih perlu menerangkan perubahan kepada Kubernetes, jika tidak, ia tidak akan menggunakan semula aplikasi daripada imej baharu, kerana ia tidak akan melihat sebarang perubahan dalam manifes penempatan.

Pilihan —vm:ext-str digest=”$DIGEST” untuk qbec - membolehkan anda menghantar pembolehubah luaran ke jsonnet. Kami mahu ia digunakan semula dalam kluster dengan setiap keluaran aplikasi kami. Kami tidak lagi boleh menggunakan nama teg, yang kini tidak boleh diubah, kerana kami perlu terikat pada versi imej tertentu dan mencetuskan penggunaan apabila ia berubah.

Di sini kita akan dibantu oleh keupayaan Kaniko untuk menyimpan imej ringkasan ke fail (pilihan --digest-file)
Kemudian kami akan memindahkan fail ini dan membacanya pada masa penggunaan.

Mari kemas kini parameter untuk kami deploy/website/environments/base.libsonnet yang kini akan kelihatan seperti ini:

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

Selesai, kini sebarang komitmen master memulakan binaan imej docker untuk laman web, dan kemudian gunakannya ke Kubernetes.

Jangan lupa untuk melakukan perubahan kami:

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

Nanti kita semak tolak git kita harus melihat sesuatu seperti ini:

Tangkapan skrin saluran paip untuk induk

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Pada dasarnya, kita tidak perlu menggunakan semula gitlab-runner dengan setiap tolakan, melainkan, sudah tentu, tiada apa yang berubah dalam konfigurasinya, mari kita perbaikinya dalam .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/**/*

perubahan akan membolehkan anda memantau perubahan dalam deploy/gitlab-runner/ dan akan mencetuskan kerja kita hanya jika ada

Jangan lupa untuk melakukan perubahan kami:

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

tolak git, itu lebih baik:

Tangkapan skrin saluran paip yang dikemas kini

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

12. Persekitaran dinamik

Sudah tiba masanya untuk mempelbagaikan saluran paip kami dengan persekitaran yang dinamik.

Mula-mula, mari kemas kini kerja build_website dalam kita .gitlab-ci.yml, mengalih keluar blok daripadanya hanyalah , yang akan memaksa Gitlab untuk mencetuskannya pada sebarang komit ke mana-mana cawangan:

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/

Kemudian kemas kini kerja deploy_website, tambah blok di sana persekitaran:

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"

Ini akan membolehkan Gitlab mengaitkan kerja dengan prod persekitaran dan paparkan pautan yang betul kepadanya.

Sekarang mari tambah dua lagi pekerjaan:

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

Ia akan dilancarkan selepas menolak ke mana-mana cawangan kecuali induk dan akan menggunakan versi pratonton tapak tersebut.

Kami melihat pilihan baharu untuk qbec: --app-tag — ia membolehkan anda menandai versi aplikasi yang digunakan dan berfungsi hanya dalam teg ini; apabila mencipta dan memusnahkan sumber dalam Kubernetes, qbec akan beroperasi hanya dengan mereka.
Dengan cara ini kita tidak boleh mencipta persekitaran yang berasingan untuk setiap semakan, tetapi hanya menggunakan semula persekitaran yang sama.

Di sini kami juga menggunakan qbec memohon semakan, bukannya qbec gunakan lalai - inilah saatnya apabila kami akan cuba menerangkan perbezaan untuk persekitaran kami (semakan dan lalai):

Mari tambah mengkaji persekitaran dalam deploy/website/qbec.yaml

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

Kemudian kami akan mengisytiharkannya 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

Dan tuliskan parameter tersuai untuknya 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',
    },
  },
}

Mari kita lihat jobu dengan lebih dekat stop_review, ia akan dicetuskan apabila cawangan dipadamkan dan supaya gitlab tidak cuba menyemak ia digunakan GIT_STRATEGY: tiada, nanti kita klon master-cabang dan padam semakan melaluinya.
Ia agak mengelirukan, tetapi saya belum menemui cara yang lebih indah lagi.
Pilihan alternatif ialah menggunakan setiap ulasan ke ruang nama hotel, yang sentiasa boleh dirobohkan sepenuhnya.

Jangan lupa untuk melakukan perubahan kami:

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

tolak git, ujian git checkout -b, ujian asal tolak git, semak:

Tangkapan skrin persekitaran yang dicipta dalam Gitlab

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Semuanya berfungsi? - bagus, padamkan cawangan ujian kami: git checkout master, git push origin :test, kami menyemak bahawa kerja pemadaman persekitaran berfungsi tanpa ralat.

Di sini saya ingin segera menjelaskan bahawa mana-mana pemaju dalam projek boleh membuat cawangan, dia juga boleh menukar .gitlab-ci.yml fail dan akses pembolehubah rahsia.
Oleh itu, sangat disyorkan untuk membenarkan penggunaannya hanya untuk cawangan yang dilindungi, contohnya dalam master, atau buat set pembolehubah yang berasingan untuk setiap persekitaran.

13. Semak Apl

Semak Apl Ini ialah ciri GitLab yang membolehkan anda menambah butang untuk setiap fail dalam repositori untuk melihatnya dengan cepat dalam persekitaran yang digunakan.

Untuk membolehkan butang ini muncul, anda perlu mencipta fail .gitlab/route-map.yml dan terangkan semua transformasi laluan di dalamnya; dalam kes kami ia akan menjadi sangat mudah:

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

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

Jangan lupa untuk melakukan perubahan kami:

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

tolak git, dan semak:

Tangkapan skrin butang Apl Semakan

Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Kerja sudah selesai!

Sumber projek:

Terima kasih atas perhatian anda, saya harap anda menyukainya Mencuba alatan baharu untuk membina dan mengautomasikan penggunaan dalam Kubernetes

Sumber: www.habr.com

Tambah komen