Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Merhaba! Son zamanlarda hem Docker görüntüleri oluşturmak hem de Kubernetes'e dağıtım için pek çok harika otomasyon aracı piyasaya sürüldü. Bu bağlamda GitLab'la denemeler yapmaya, yeteneklerini iyice incelemeye ve tabii ki işlem hattını kurmaya karar verdim.

Bu çalışma web sitesinden ilham almıştır. kubernetes.iodan oluşturulan kaynak kodları otomatik olarak ve gönderilen her havuz isteği için robot, değişikliklerinizi içeren sitenin önizleme sürümünü otomatik olarak oluşturur ve görüntüleme için bir bağlantı sağlar.

Benzer bir süreci sıfırdan oluşturmaya çalıştım, ancak tamamen Gitlab CI'yı ve uygulamaları Kubernetes'e dağıtmak için kullanmaya alışkın olduğum ücretsiz araçları temel aldım. Bugün nihayet size onlar hakkında daha fazla bilgi vereceğim.

Makalede aşağıdaki gibi araçlar tartışılacaktır:
Hugo, qbec, Kaniko, git-kript и GitLab CI Dinamik ortamların yaratılmasıyla.

içindekiler

  1. Hugo'yla tanışın
  2. Docker dosyasının hazırlanması
  3. Kaniko'yu tanımak
  4. Qbec'i tanıma
  5. Gitlab-runner'ı Kubernetes-executor ile denemek
  6. Helm grafiklerini qbec ile dağıtma
  7. git-crypt'e giriş
  8. Araç kutusu görüntüsü oluşturma
  9. İlk işlem hattımız ve görüntülerin etiketlere göre birleştirilmesi
  10. Dağıtım otomasyonu
  11. Ustalaşmaya çalışırken eserler ve montaj
  12. dinamik ortamlar
  13. Uygulamaları İncele

1. Hugo'yu tanımak

Projemize örnek olarak Hugo üzerine kurulu bir dokümantasyon yayınlama sitesi oluşturmaya çalışacağız. Hugo statik bir içerik oluşturucudur.

Statik jeneratörlere aşina olmayanlar için size onlar hakkında biraz daha bilgi vereceğim. Bir kullanıcı tarafından istendiğinde anında sayfalar oluşturan bir veritabanına ve biraz PHP'ye sahip geleneksel web sitesi motorlarının aksine, statik oluşturucular biraz farklı tasarlanmıştır. Kaynakları (genellikle Markdown işaretleme ve tema şablonlarındaki bir dizi dosya) almanıza ve ardından bunları tamamen bitmiş bir web sitesinde derlemenize olanak tanır.

Yani, sonuç olarak, herhangi bir ucuz barındırma sistemine kolayca yükleyebileceğiniz ve çalışan bir web sitesi elde edebileceğiniz bir dizin yapısı ve oluşturulmuş bir dizi HTML dosyası alacaksınız.

Hugo'yu yerel olarak yükleyebilir ve deneyebilirsiniz:

Yeni bir site başlatılıyor:

hugo new site docs.example.org

Ve aynı zamanda git deposu:

cd docs.example.org
git init

Şu ana kadar sitemiz bozulmamış durumda ve üzerinde bir şeyin görünmesi için öncelikle bir tema bağlamamız gerekiyor; tema yalnızca bir dizi şablon ve sitemizin oluşturulduğu belirli kurallardır.

Kullanacağımız tema için Öğrenmek, bence bir dokümantasyon sitesi için mükemmel bir şekilde uygundur.

Tema dosyalarını proje depomuza kaydetmemize gerek olmadığı gerçeğine özellikle dikkat etmek istiyorum; bunun yerine, onu kullanarak kolayca bağlayabiliriz. git alt modülü:

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

Böylece, havuzumuz yalnızca projemizle doğrudan ilgili dosyaları içerecek ve bağlı tema, belirli bir depoya bağlantı ve içindeki bir taahhüt olarak kalacaktır, yani her zaman orijinal kaynaktan çekilebilir ve korkmaz. uyumsuz değişiklikler

Yapılandırmayı düzeltelim yapılandırma.toml:

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

Zaten bu aşamada koşabilirsiniz:

hugo server

Ve adreste http://localhost:1313/ Yeni oluşturulan web sitemizi kontrol edin, dizinde yapılan tüm değişiklikler tarayıcıdaki açık sayfayı otomatik olarak günceller, çok kullanışlı!

Bir kapak sayfası oluşturmaya çalışalım içerik/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

Yeni oluşturulan sayfanın ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Bir site oluşturmak için şunu çalıştırın:

hugo

Dizin içeriği halka açık/ ve web siteniz olacak.
Evet bu arada hemen ekleyelim .gitignore:

echo /public > .gitignore

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

2. Docker dosyasının hazırlanması

Depomuzun yapısını tanımlamanın zamanı geldi. Genellikle şöyle bir şey kullanırım:

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

  • liman işçisi dosyaları/ — Docker dosyalarının bulunduğu dizinleri ve Docker görüntülerimizi oluşturmak için gereken her şeyi içerir.
  • dağıtmak/ — uygulamalarımızı Kubernetes'e dağıtmak için dizinleri içerir

Böylece yol boyunca ilk Docker dosyamızı oluşturacağız. dockerfiles/web sitesi/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" ]

Gördüğünüz gibi Dockerfile iki tane içeriyor DAN, bu fırsata denir çok aşamalı yapı ve son Docker görüntüsünden gereksiz olan her şeyi hariç tutmanıza olanak tanır.
Böylece son görüntü yalnızca şunları içerecektir: karanlıkhttpd (hafif HTTP sunucusu) ve halka açık/ — statik olarak oluşturulmuş web sitemizin içeriği.

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

3. Kaniko'yu tanımak

Docker imaj oluşturucusu olarak şunu kullanmaya karar verdim: Kaniko, işlemi bir docker arka plan programı gerektirmediğinden ve yapının kendisi herhangi bir makinede gerçekleştirilebildiğinden ve önbellek doğrudan kayıt defterinde saklanabildiğinden, tam teşekküllü bir kalıcı depolamaya olan ihtiyacı ortadan kaldırır.

Görüntüyü oluşturmak için kapsayıcıyı çalıştırmanız yeterlidir. kaniko vasisi ve mevcut derleme bağlamını iletin; bu aynı zamanda yerel olarak docker aracılığıyla da yapılabilir:

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

Nerede kayıt defteri.gitlab.com/kvaps/docs.example.org/website — liman işçisi görüntünüzün adı; oluşturulduktan sonra otomatik olarak liman işçisi kayıt defterinde başlatılacaktır.

Parametre --önbellek katmanları liman işçisi kayıt defterinde önbelleğe almanıza olanak tanır; verilen örnekte, bunlar kayıt defteri.gitlab.com/kvaps/docs.example.org/website/cacheancak parametreyi kullanarak başka bir yol belirleyebilirsiniz. --önbellek-repo.

Liman işçisi kaydının ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

4. qbec'i tanıma

Qbec uygulama bildirimlerinizi bildirimli olarak tanımlamanıza ve bunları Kubernetes'e dağıtmanıza olanak tanıyan bir dağıtım aracıdır. Jsonnet'i ana sözdizimi olarak kullanmak, birden çok ortam arasındaki farklılıkların açıklamasını büyük ölçüde basitleştirmenize olanak tanır ve ayrıca kod tekrarını neredeyse tamamen ortadan kaldırır.

Bu, özellikle bir uygulamayı farklı parametrelere sahip birkaç kümeye dağıtmanız gerektiği ve bunları Git'te bildirimsel olarak tanımlamak istediğiniz durumlarda geçerli olabilir.

Qbec ayrıca Helm grafiklerini gerekli parametreleri ileterek oluşturmanıza ve ardından bunları normal bildirimlerle aynı şekilde çalıştırmanıza olanak tanır, bunlara çeşitli mutasyonlar uygulayabilmeniz de dahil ve bu da, sırayla, ihtiyaçtan kurtulmanıza olanak tanır. ChartMuseum'u kullanın. Yani, grafikleri doğrudan ait oldukları yerde, git'ten saklayabilir ve oluşturabilirsiniz.

Daha önce de söylediğim gibi, tüm dağıtımları bir dizinde saklayacağız dağıtmak/:

mkdir deploy
cd deploy

İlk uygulamamızı başlatalım:

qbec init website
cd website

Artık uygulamamızın yapısı şu şekilde görünüyor:

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

hadi dosyaya bakalım qbec.yaml:

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

Burada öncelikle ilgilendiğimiz spesifik ortamlarqbec bizim için zaten varsayılan bir ortam oluşturdu ve mevcut kubeconfig'imizden sunucu adresinin yanı sıra ad alanını da aldı.
Şimdi dağıtım yaparken varsayılan ortamında, qbec her zaman yalnızca belirtilen Kubernetes kümesine ve belirtilen ad alanına dağıtım yapacaktır; yani, dağıtım gerçekleştirmek için artık bağlamlar ve ad alanları arasında geçiş yapmanız gerekmez.
Gerekirse bu dosyadaki ayarları her zaman güncelleyebilirsiniz.

Tüm ortamlarınız şurada açıklanmıştır: qbec.yamlve dosyada params.libsonnet, burada onlar için parametrelerin nereden alınacağı yazıyor.

Daha sonra iki dizin görüyoruz:

  • bileşenler / — uygulamamızın tüm bildirimleri burada saklanacaktır; hem jsonnet hem de normal yaml dosyalarında açıklanabilirler
  • ortamlar/ — burada ortamlarımız için tüm değişkenleri (parametreleri) tanımlayacağız.

Varsayılan olarak iki dosyamız var:

  • ortamlar/base.libsonnet - tüm ortamlar için ortak parametreler içerecektir
  • ortamlar/default.libsonnet — ortam için geçersiz kılınan parametreleri içerir varsayılan

Hadi açalım ortamlar/base.libsonnet ve buraya ilk bileşenimiz için parametreler ekleyin:

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

Ayrıca ilk bileşenimizi de oluşturalım bileşenler/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,
                },
              },
            ],
          },
        },
      ],
    },
  },
]

Bu dosyada aynı anda üç Kubernetes varlığını tanımladık, bunlar: açılma, Hizmet и Giriş. İsteseydik bunları farklı bileşenlere koyabilirdik ama bu aşamada bir tanesi bize yeterli olacaktır.

sözdizimi jsonnet normal json'a çok benzer, prensip olarak normal json zaten geçerli bir jsonnet'tir, bu nedenle ilk başta aşağıdaki gibi çevrimiçi hizmetleri kullanmanız sizin için daha kolay olabilir yaml2json her zamanki yaml'inizi json'a dönüştürmek için veya bileşenleriniz herhangi bir değişken içermiyorsa, normal yaml biçiminde tanımlanabilirler.

İle çalışırken jsonnet Editörünüz için bir eklenti yüklemenizi şiddetle tavsiye ederim

Örneğin vim için bir eklenti var vim-jsonnet, sözdizimi vurgulamayı etkinleştirir ve otomatik olarak yürütür jsonnet fmt her kaydettiğinizde (jsonnet'in kurulu olmasını gerektirir).

Her şey hazır, artık konuşlandırmaya başlayabiliriz:

Ne elde ettiğimizi görmek için koşalım:

qbec show default

Çıktıda, varsayılan kümeye uygulanacak işlenmiş yaml bildirimlerini göreceksiniz.

Harika, şimdi başvurun:

qbec apply default

Çıktıda her zaman kümenizde ne yapılacağını göreceksiniz, qbec sizden değişiklikleri kabul etmenizi isteyecektir. y niyetinizi doğrulayabileceksiniz.

Uygulamamız hazır ve kullanıma sunuldu!

Değişiklik yaparsanız her zaman şunları yapabilirsiniz:

qbec diff default

bu değişikliklerin mevcut dağıtımı nasıl etkileyeceğini görmek için

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

5. Gitlab çalıştırıcısını Kubernetes yürütücüsüyle denemek

Yakın zamana kadar sadece normal kullanıyordum gitlab koşucusu Shell veya docker-executor ile önceden hazırlanmış bir makinede (LXC konteyneri). Başlangıçta, gitlab'ımızda küresel olarak tanımlanmış bu tür birkaç koşucumuz vardı. Tüm projeler için liman işçisi görüntüleri topladılar.

Ancak uygulamanın gösterdiği gibi, bu seçenek hem pratiklik hem de güvenlik açısından en ideal seçenek değildir. Her proje için, hatta her ortam için ayrı koşucuların görevlendirilmesi çok daha iyi ve ideolojik olarak daha doğrudur.

Neyse ki bu hiç sorun değil, çünkü artık konuşlandıracağız gitlab koşucusu doğrudan Kubernetes'teki projemizin bir parçası olarak.

Gitlab, gitlab-runner'ı Kubernetes'e dağıtmak için hazır bir dümen grafiği sağlar. Yani tek yapmanız gereken öğrenmek kayıt jetonu projemiz için Ayarlar -> CI / CD -> Çalıştırıcılar ve onu dümene ilet:

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

Nerede:

  • https://gitlab.com — Gitlab sunucunuzun adresi.
  • yga8y-jdCusVDn_t4Wxc — projeniz için kayıt jetonu.
  • rbac.create=true — koşucuya kubernetes-executor kullanarak görevlerimizi gerçekleştirmek için bölmeler oluşturabilmesi için gerekli miktarda ayrıcalık sağlar.

Her şey doğru yapılırsa bölümde kayıtlı bir koşucu görmelisiniz. İkincisi, proje ayarlarınızda.

Eklenen koşucunun ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Bu kadar basit mi? - evet, bu kadar basit! Artık koşucuları manuel olarak kaydetme zahmetine gerek yok, artık koşucular otomatik olarak oluşturulacak ve yok edilecek.

6. Helm grafiklerini QBEC ile dağıtın

Düşünmeye karar verdiğimizden beri gitlab koşucusu projemizin bir parçası, onu Git depomuzda açıklamanın zamanı geldi.

Ayrı bir bileşen olarak tanımlayabiliriz Web sitesi, ancak gelecekte farklı kopyalar dağıtmayı planlıyoruz Web sitesi aksine çok sık gitlab koşucusuKubernetes kümesi başına yalnızca bir kez dağıtılacak. Öyleyse bunun için ayrı bir uygulama başlatalım:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

Bu sefer Kubernetes varlıklarını manuel olarak tanımlamayacağız, ancak hazır bir Helm grafiği alacağız. Qbec'in avantajlarından biri Helm grafiklerini doğrudan Git deposundan oluşturma yeteneğidir.

Git alt modülünü kullanarak bağlayalım:

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

Şimdi dizin satıcı/gitlab çalıştırıcısı Gitlab-runner için bir grafik içeren bir havuzumuz var.

Benzer şekilde, diğer depoları, örneğin tüm depoyu resmi grafiklerle bağlayabilirsiniz. https://github.com/helm/charts

Bileşeni tanımlayalım bileşenler/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,
  }
)

İlk argüman HelmTemplate'i genişlet grafiğe giden yolu geçiyoruz, sonra parametreler.değerlerortam parametrelerinden aldığımız, ardından nesneyle birlikte gelir

  • isimŞablon — yayın başlığı
  • ad — ad alanı dümene devredildi
  • bu dosya — geçerli dosyanın yolunu ileten gerekli bir parametre
  • gereksiz sözlerle dolu - komutu gösterir dümen şablonu grafiği oluştururken tüm argümanlarla birlikte

Şimdi bileşenimizin parametrelerini açıklayalım. ortamlar/base.libsonnet:

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

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

Dikkat koşucuRegistrationToken harici bir dosyadan alıyoruz sırlar/base.libsonnet, hadi oluşturalım:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

Her şeyin işe yarayıp yaramadığını kontrol edelim:

qbec show default

her şey yolundaysa, daha önce konuşlandırılan sürümümüzü Helm aracılığıyla silebiliriz:

helm uninstall gitlab-runner

ve aynı şekilde konuşlandırın, ancak qbec aracılığıyla:

qbec apply default

7. git-crypt'e giriş

Git-kript deponuz için şeffaf şifreleme ayarlamanıza olanak tanıyan bir araçtır.

Şu anda gitlab-runner için dizin yapımız şöyle görünüyor:

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

Ancak sırları Git'te saklamak güvenli değil, değil mi? Bu yüzden onları doğru şekilde şifrelememiz gerekiyor.

Genellikle tek bir değişken uğruna bu her zaman anlamlı değildir. Sırları şuraya aktarabilirsiniz: qbec ve CI sisteminizin ortam değişkenleri aracılığıyla.
Ancak çok daha fazla sır içerebilen daha karmaşık projelerin de bulunduğunu belirtmekte fayda var; bunların tamamını ortam değişkenleri aracılığıyla aktarmak son derece zor olacaktır.

Üstelik bu durumda size böyle harika bir araçtan bahsetmem mümkün olmazdı. git-kript.

git-kript Ayrıca, sırların tüm geçmişini kaydetmenize ve Git'te yapmaya alışkın olduğumuz şekilde çatışmaları karşılaştırmanıza, birleştirmenize ve çözmenize olanak sağlaması açısından da kullanışlıdır.

Kurulumdan sonraki ilk şey git-kript depomuz için anahtarlar oluşturmamız gerekiyor:

git crypt init

Bir PGP anahtarınız varsa, kendinizi bu projenin ortak çalışanı olarak hemen ekleyebilirsiniz:

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

Bu şekilde her zaman özel anahtarınızı kullanarak bu havuzun şifresini çözebilirsiniz.

PGP anahtarınız yoksa ve bunu beklemiyorsanız diğer tarafa giderek proje anahtarını dışa aktarabilirsiniz:

git crypt export-key /path/to/keyfile

Bu nedenle, ihraç ürünü olan herkes Anahtar dosya deponuzun şifresini çözebilecektir.

İlk sırrımızı oluşturmanın zamanı geldi.
Hala dizinde olduğumuzu hatırlatmama izin verin dağıtma/gitlab-runner/, burada bir dizinimiz var sırlar/, içindeki tüm dosyaları şifreleyelim, bunun için bir dosya oluşturacağız sırlar/.gitattributes aşağıdaki içerikle:

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

İçerikten de anlaşılacağı üzere tüm dosyalar maskelenmiştir * içinden geçilecek git-kriptçoğu hariç .gitattributes

Bunu aşağıdakileri çalıştırarak kontrol edebiliriz:

git crypt status -e

Çıktı, depodaki şifrelemenin etkinleştirildiği tüm dosyaların bir listesi olacaktır.

Hepsi bu kadar, artık değişikliklerimizi güvenle gerçekleştirebiliriz:

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

Bir depoyu engellemek için şunu çalıştırın:

git crypt lock

ve hemen tüm şifrelenmiş dosyalar ikili bir şeye dönüşecek, onları okumak imkansız olacak.
Deponun şifresini çözmek için şunu çalıştırın:

git crypt unlock

8. Bir araç kutusu görüntüsü oluşturun

Araç kutusu görüntüsü, projemizi dağıtmak için kullanacağımız tüm araçları içeren bir görüntüdür. Gitlab çalıştırıcısı tarafından tipik dağıtım görevlerini gerçekleştirmek için kullanılacaktır.

Burada her şey basit, hadi yeni bir tane yaratalım dockerfiles/araç kutusu/Dockerfile aşağıdaki içerikle:

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

Gördüğünüz gibi bu görüntüde uygulamamızı dağıtmak için kullandığımız tüm yardımcı programları kuruyoruz. sürece burada ihtiyacımız yok Kubectl, ancak boru hattı kurulum aşamasında bununla oynamak isteyebilirsiniz.

Ayrıca Kubernetes ile iletişim kurabilmek ve dağıtabilmek için gitlab-runner tarafından oluşturulan pod'lara yönelik bir rol yapılandırmamız gerekiyor.

Bunu yapmak için gitlab-runner'ın bulunduğu dizine gidelim:

cd deploy/gitlab-runner

ve yeni bir bileşen ekleyin bileşenler/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,
      },
    ],
  },
]

Ayrıca yeni parametreleri de açıklayacağız. ortamlar/base.libsonnet, şimdi şöyle görünüyor:

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

Dikkat $.components.rbac.name kastediyor isim bileşen için rbac

Neyin değiştiğini kontrol edelim:

qbec diff default

ve değişikliklerimizi Kubernetes'e uygulayın:

qbec apply default

Ayrıca değişikliklerimizi git'e kaydetmeyi de unutmayın:

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. İlk işlem hattımız ve görsellerin etiketlere göre birleştirilmesi

Oluşturacağımız projenin temelinde .gitlab-ci.yml aşağıdaki içerikle:

.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

Lütfen kullandığımızı unutmayın GIT_SUBMODULE_STRATEGY: normal yürütmeden önce alt modülleri açıkça başlatmanız gereken işler için.

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

Sanırım buna rahatlıkla bir versiyon diyebiliriz v0.0.1 ve etiketi ekleyin:

git tag v0.0.1

Yeni bir sürüm yayınlamamız gerektiğinde etiketler ekleyeceğiz. Docker görsellerindeki etiketler Git etiketlerine bağlanacaktır. Yeni bir etiketin her basılması, bu etikete sahip görsellerin oluşturulmasını başlatacaktır.

yapmak git push --tagsve ilk boru hattımıza bakalım:

İlk boru hattının ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Etiketlere göre birleştirmenin liman işçisi görüntüleri oluşturmak için uygun olduğu, ancak Kubernetes'e bir uygulama dağıtmak için uygun olmadığı gerçeğine dikkatinizi çekmekte fayda var. Eski kayıtlara yeni etiketler atanabileceğinden, bu durumda onlar için işlem hattının başlatılması eski sürümün dağıtımına yol açacaktır.

Bu sorunu çözmek için genellikle docker görüntülerinin yapısı etiketlere bağlanır ve uygulamanın bir şubeye dağıtımı yapılır. usta, toplanan görüntülerin sürümlerinin sabit kodlandığı. Basit bir geri dönüşle geri dönüşü başlatabileceğiniz yer burasıdır usta-dallar.

10. Dağıtımın otomasyonu

Gitlab-runner'ın sırlarımızın şifresini çözmesi için depo anahtarını dışa aktarmamız ve onu CI ortam değişkenlerimize eklememiz gerekecek:

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

Ortaya çıkan satırı Gitlab'a kaydedeceğiz; bunun için proje ayarlarımıza gidelim:
Ayarlar -> CI / CD -> Değişkenler

Ve yeni bir değişken oluşturalım:

Tip
anahtar
Özellik
korumalı
Maskeli
kapsam

File
GITCRYPT_KEY
<your string>
true (eğitim sırasında şunları yapabilirsiniz: false)
true
All environments

Eklenen değişkenin ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Şimdi güncelleyelim .gitlab-ci.yml ona şunu ekliyorum:

.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

Burada qbec için birkaç yeni seçeneği etkinleştirdik:

  • --bazı/uygulamaları rootlayın — belirli bir uygulamanın dizinini belirlemenizi sağlar
  • --force:k8s-context __incluster__ - bu, dağıtımın gtilab-runner'ın çalıştığı kümede gerçekleşeceğini söyleyen sihirli bir değişkendir. Bu gereklidir çünkü aksi takdirde qbec, kubeconfig'inizde uygun bir Kubernetes sunucusu bulmaya çalışacaktır.
  • --Beklemek - qbec'i, oluşturduğu kaynaklar Hazır durumuna geçene kadar beklemeye ve ancak o zaman başarılı bir çıkış koduyla çıkmaya zorlar.
  • -Evet - etkileşimli kabuğu basitçe devre dışı bırakır Emin misiniz? konuşlandırıldığında.

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

Ve sonra git basma uygulamalarımızın nasıl konuşlandırıldığını göreceğiz:

İkinci boru hattının ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

11. Ustalaşmaya çalışırken eserler ve montaj

Genellikle yukarıda açıklanan adımlar hemen hemen her mikro hizmeti oluşturmak ve sunmak için yeterlidir, ancak siteyi her güncellememiz gerektiğinde bir etiket eklemek istemiyoruz. Bu nedenle daha dinamik bir yol izleyeceğiz ve ana dalda bir özet dağıtımı kuracağız.

Fikir basit: şimdi bizim imajımız Web sitesi her bastığınızda yeniden inşa edilecek ustave ardından otomatik olarak Kubernetes'e dağıtın.

Bu iki işi programımızda güncelleyelim. .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"

Lütfen bir konu eklediğimizi unutmayın usta к ref işler için build_website ve şimdi kullanıyoruz $CI_COMMIT_REF_NAME yerine $CI_COMMIT_TAGyani Git'teki etiketlerden kurtulduk ve şimdi boru hattını başlatan taahhüt dalının adını taşıyan bir görüntüyü aktaracağız. Bunun aynı zamanda etiketlerle de çalışacağını ve bu sayede belirli bir sürüme sahip bir sitenin anlık görüntülerini docker-kayıt defterine kaydetmemize olanak tanıyacağını belirtmekte fayda var.

Sitenin yeni bir sürümü için docker etiketinin adı değiştirilebildiğinde, yine de Kubernetes'teki değişiklikleri açıklamamız gerekir, aksi takdirde uygulamayı yeni görüntüden yeniden dağıtmayacaktır çünkü herhangi bir değişiklik fark etmeyecektir. dağıtım bildirimi.

Seçenek —vm:ext-str özet=”$DIGEST” qbec için - harici bir değişkeni jsonnet'e aktarmanıza olanak tanır. Uygulamamızın her sürümünde kümede yeniden konuşlandırılmasını istiyoruz. Görüntünün belirli bir sürümüne bağlanmamız ve değiştiğinde dağıtımı tetiklememiz gerektiğinden, artık değiştirilemeyen etiket adını artık kullanamıyoruz.

Burada Kaniko'nun özet görüntüsünü bir dosyaya kaydetme yeteneği bize yardımcı olacak (seçenek) --digest-dosyası)
Daha sonra bu dosyayı aktaracağız ve dağıtım sırasında okuyacağız.

Parametrelerimizi güncelleyelim konuşlandırma/web sitesi/ortamlar/base.libsonnet şimdi şuna benzeyecek:

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

Bitti, şimdi herhangi bir taahhüt var usta için liman işçisi görüntüsünün yapısını başlatır Web sitesive ardından bunu Kubernetes'e dağıtın.

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

Daha sonra kontrol edeceğiz git basma şöyle bir şey görmeliyiz:

Ana işlem hattının ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Prensip olarak, konfigürasyonunda hiçbir şey değişmediği sürece gitlab-runner'ı her basışta yeniden konuşlandırmamıza gerek yok, hadi düzeltelim .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/**/*

değişiklikler değişiklikleri izlemenize olanak tanır. dağıtma/gitlab-runner/ ve yalnızca herhangi bir şey varsa işimizi tetikleyecektir

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

git basma, bu daha iyi:

Güncellenen işlem hattının ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

12. Dinamik ortamlar

Boru hattımızı dinamik ortamlarla çeşitlendirmenin zamanı geldi.

Öncelikle işi güncelleyelim build_website içinde bizim .gitlab-ci.yml, bloğun buradan kaldırılması bir tekGitlab'ı herhangi bir şubeye yapılan herhangi bir taahhütte tetiklemeye zorlayacak:

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/

Daha sonra işi güncelleyin konuşlandırma_web sitesi, oraya bir blok ekleyin çevre:

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"

Bu Gitlab'ın işi ilişkilendirmesine olanak tanıyacak dürtme çevre ve ona doğru bağlantıyı görüntüleyin.

Şimdi iki iş daha ekleyelim:

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

Ana şube dışındaki herhangi bir şubeye gönderildiğinde başlatılacaklar ve sitenin önizleme sürümünü dağıtacaklar.

Qbec için yeni bir seçenek görüyoruz: --app-etiketi — uygulamanın dağıtılan sürümlerini etiketlemenize ve yalnızca bu etiket dahilinde çalışmanıza olanak tanır; Kubernetes'te kaynaklar oluştururken ve yok ederken, qbec yalnızca onlarla çalışacaktır.
Bu şekilde her inceleme için ayrı bir ortam oluşturamayız, aynı ortamı yeniden kullanabiliriz.

Burada da kullanıyoruz qbec başvuru incelemesiyerine qbec varsayılanı uygula - bu tam olarak ortamlarımız için farklılıkları (inceleme ve varsayılan) açıklamaya çalışacağımız an:

eklemek yorum çevre konuşlandırma/web sitesi/qbec.yaml

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

O zaman bunu ilan edeceğiz konuşlandırma/web sitesi/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

Ve bunun için özel parametreleri yazın konuşlandırma/web sitesi/ortamlar/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',
    },
  },
}

Ayrıca jobu'ya daha yakından bakalım stop_review, şube silindiğinde tetiklenir ve gitlab'ın ödeme yapmaya çalışmaması için kullanılır GIT_STRATEGY: yok, daha sonra klonlarız usta- incelemeyi dallandırın ve silin.
Biraz kafa karıştırıcı ama daha güzel bir yolunu henüz bulamadım.
Alternatif bir seçenek de her incelemeyi, her zaman tamamen yıkılabilecek bir otel ad alanına dağıtmak olabilir.

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

git basma, git ödeme -b testi, git push orijin testi, kontrol etmek:

Gitlab'da oluşturulan ortamların ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Her şey çalışıyor mu? - harika, test şubemizi silin: git ödeme yöneticisi, git push orijini :test, ortam silme işlerinin hatasız çalıştığını kontrol ediyoruz.

Burada hemen şunu belirtmek isterim ki, bir projedeki herhangi bir geliştirici şube oluşturabilir, aynı zamanda değişiklik yapabilir. .gitlab-ci.yml gizli değişkenleri dosyalayın ve bunlara erişin.
Bu nedenle, bunların yalnızca korunan dallar için kullanılmasına izin verilmesi önemle tavsiye edilir; örneğin ustaveya her ortam için ayrı bir değişken kümesi oluşturun.

13. Uygulamaları İnceleyin

Uygulamaları İncele Bu, depodaki her dosya için bir düğme eklemenizi ve konuşlandırılmış bir ortamda hızlı bir şekilde görüntülemenizi sağlayan bir GitLab özelliğidir.

Bu düğmelerin görünmesi için bir dosya oluşturmanız gerekir. .gitlab/route-map.yml ve içindeki tüm yol dönüşümlerini açıklayın; bizim durumumuzda çok basit olacak:

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

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

Değişikliklerimizi gerçekleştirmeyi unutmayın:

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

git basmave şunu kontrol edin:

Uygulamayı İncele düğmesinin ekran görüntüsü

Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Görev tamamlandı!

Proje kaynakları:

İlginiz için teşekkür ederim umarım beğenmişsinizdir Kubernetes'te dağıtımı oluşturmak ve otomatikleştirmek için yeni araçlar denemek

Kaynak: habr.com

Yorum ekle