你好! 最近,發布了許多很酷的自動化工具,用於建立 Docker 映像和部署到 Kubernetes。 在這方面,我決定嘗試 GitLab,徹底研究它的功能,當然,也建立了管道。
這項工作的靈感來自於網站
我嘗試從頭開始建立一個類似的流程,但完全基於 Gitlab CI 和我習慣用來將應用程式部署到 Kubernetes 的免費工具。 今天我終於要告訴你更多關於他們的事了。
本文將討論以下工具:
雨果, 魁北克, 卡尼科, git 密碼 и 亞搏體育app CI 隨著動態環境的創建。
內容
認識雨果 準備 Dockerfile 認識卡尼科 了解qbec 嘗試使用 Gitlab-runner 和 Kubernetes-executor 使用 qbec 部署 Helm 圖表 介紹 git-crypt 建立工具箱影像 我們的第一個管道和按標籤組裝圖像 部署自動化 推動掌握時的工件和組裝 動態環境 評論應用程序
1. 認識雨果
作為我們專案的一個例子,我們將嘗試建立一個基於 Hugo 的文件發佈網站。 Hugo 是一個靜態內容產生器。
對於那些不熟悉靜態發生器的人,我會告訴你更多關於它們的資訊。 與具有資料庫和一些 PHP 的傳統網站引擎(當使用者要求時動態產生頁面)不同,靜態產生器的設計略有不同。 它們允許您獲取原始程式碼,通常是 Markdown 標記和主題模板中的一組文件,然後將它們編譯成一個完整完成的網站。
也就是說,您將收到一個目錄結構和一組生成的 HTML 文件,您可以簡單地將其上傳到任何廉價託管並獲得可用的網站。
您可以在本地安裝 Hugo 並嘗試:
初始化新站點:
hugo new site docs.example.org
同時 git 儲存庫:
cd docs.example.org
git init
到目前為止,我們的網站是原始的,為了在其上顯示某些內容,我們首先需要連接一個主題;主題只是一組模板和生成我們網站的指定規則。
對於我們將使用的主題
我要特別注意的是,我們不需要將主題檔案保存在專案儲存庫中;相反,我們可以簡單地使用以下命令連接它 git 子模組:
git submodule add https://github.com/matcornic/hugo-theme-learn themes/learn
因此,我們的儲存庫將僅包含與我們的專案直接相關的文件,並且連接的主題將保留為特定儲存庫的連結以及其中的提交,也就是說,它始終可以從原始來源中拉取,而不必擔心不相容的更改。
讓我們更正一下配置 配置文件:
baseURL = "http://docs.example.org/"
languageCode = "en-us"
title = "My Docs Site"
theme = "learn"
在此階段您可以運行:
hugo server
並在地址
讓我們嘗試建立一個封面頁 內容/_index.md:
# My docs site
## Welcome to the docs!
You will be very smart :-)
新建立的頁面的螢幕截圖
要產生站點,只需運行:
hugo
目錄內容 上市/ 並將成為您的網站。
是的,順便說一下,我們立即將其添加到 的.gitignore:
echo /public > .gitignore
不要忘記提交我們的更改:
git add .
git commit -m "New site created"
2. 準備Dockerfile
是時候定義我們的儲存庫的結構了。 我通常使用類似的東西:
.
├── deploy
│ ├── app1
│ └── app2
└── dockerfiles
├── image1
└── image2
- dockerfiles/ — 包含包含 Dockerfile 的目錄以及建置 Docker 映像所需的所有內容。
- 部署/ — 包含用於將我們的應用程式部署到 Kubernetes 的目錄
因此,我們將沿著路徑建立第一個 Dockerfile dockerfiles/網站/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" ]
如您所見,Dockerfile 包含兩個 獲取你的,這個特徵稱為
因此,最終圖像將僅包含 暗httpd (輕量級 HTTP 伺服器)和 上市/ — 我們靜態產生的網站的內容。
不要忘記提交我們的更改:
git add dockerfiles/website
git commit -m "Add Dockerfile for website"
3.認識卡尼科
身為 docker 映像建置者,我決定使用
要建立映像,只需運行容器即可 卡尼科執行人 並將當前建置上下文傳遞給它;這也可以透過 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 — 您的 docker 映像的名稱;建置後,它將自動啟動到 docker 註冊表中。
參數 - 快取 允許您在 docker 註冊表中快取層;對於給出的範例,它們將保存在 registry.gitlab.com/kvaps/docs.example.org/website/cache,但您可以使用參數指定另一個路徑 --快取儲存庫.
docker-registry 的截圖
4. 了解qbec
當您需要將應用程式部署到具有不同參數的多個叢集並希望在 Git 中以聲明方式描述它們時,尤其如此。
Qbec 還允許您透過向 Helm 圖表傳遞必要的參數來渲染 Helm 圖表,然後以與常規清單相同的方式操作它們,包括您可以對它們應用各種突變,而這反過來又使您無需使用圖表博物館。 也就是說,您可以直接從它們所屬的 git 儲存和渲染圖表。
正如我之前所說,我們將把所有部署儲存在一個目錄中 部署/:
mkdir deploy
cd deploy
讓我們初始化我們的第一個應用程式:
qbec init website
cd website
現在我們的應用程式的結構如下所示:
.
├── components
├── environments
│ ├── base.libsonnet
│ └── default.libsonnet
├── params.libsonnet
└── qbec.yaml
讓我們看一下文件 qbec.yaml:
apiVersion: qbec.io/v1alpha1
kind: App
metadata:
name: website
spec:
environments:
default:
defaultNamespace: docs
server: https://kubernetes.example.org:8443
vars: {}
在這裡我們主要感興趣的是 規範環境,qbec 已經為我們創建了一個預設環境,並從我們目前的 kubeconfig 中取得了伺服器位址和命名空間。
現在當部署到 默認 在環境中,qbec 將始終僅部署到指定的 Kubernetes 叢集和指定的命名空間,也就是說,您不再需要在上下文和命名空間之間切換來執行部署。
如有必要,您可以隨時更新此文件中的設定。
您的所有環境均在中描述 qbec.yaml,並在文件中 params.libsonnet,其中表示從哪裡獲取它們的參數。
接下來我們看到兩個目錄:
- 組件/ — 我們應用程式的所有清單都將儲存在這裡;它們可以在 jsonnet 和常規 yaml 檔案中進行描述
- 環境/ - 在這裡我們將描述我們環境的所有變數(參數)。
預設我們有兩個檔案:
- 環境/base.libsonnet - 它將包含所有環境的通用參數
- 環境/default.libsonnet — 包含環境覆蓋的參數 默認
讓我們打開 環境/base.libsonnet 並為我們的第一個組件添加參數:
{
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',
},
},
}
我們還創建我們的第一個組件 組件/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,
},
},
],
},
},
],
},
},
]
在此文件中,我們同時描述了三個 Kubernetes 實體,它們是: 部署, 服務 и 入口。 如果我們願意,我們可以將它們放入不同的組件中,但在現階段,一個對我們來說就足夠了。
句法 jsonnet 與常規 json 非常相似,原則上,常規 json 已經是有效的 jsonnet,所以首先您可能會更容易使用線上服務,例如 yaml2json 將您常用的 yaml 轉換為 json,或者,如果您的元件不包含任何變量,則可以以常規 yaml 的形式描述它們。
當與 jsonnet 我強烈建議為您的編輯器安裝一個插件
例如,有一個 vim 的插件 vim-jsonnet,開啟語法高亮並自動執行 jsonnet fmt 每次儲存時(需要安裝 jsonnet)。
一切準備就緒,現在我們可以開始部署了:
要查看我們得到了什麼,讓我們運行:
qbec show default
在輸出中,您將看到將套用於預設叢集的渲染 yaml 清單。
太好了,現在申請:
qbec apply default
在輸出中,您將始終看到叢集中將執行的操作,qbec 會要求您輸入同意更改 y 您將能夠確認您的意圖。
我們的應用程式已準備就緒並已部署!
如果您進行更改,您始終可以執行以下操作:
qbec diff default
查看這些變更將如何影響目前部署
不要忘記提交我們的更改:
cd ../..
git add deploy/website
git commit -m "Add deploy for website"
5. 嘗試使用 Kubernetes-executor 來使用 Gitlab-runner
直到最近我只使用常規 gitlab-runner 在具有 shell 或 docker-executor 的預先準備好的機器(LXC 容器)上。 最初,我們在 gitlab 中全域定義了幾個這樣的運行程式。 他們收集了所有專案的 docker 映像。
但實踐表明,這種選擇無論是從實用性還是安全性來看都不是最理想的。 為每個專案甚至每個環境部署單獨的運行程序會更好,在意識形態上也更正確。
幸運的是,這根本不是問題,因為現在我們將部署 gitlab-runner 直接作為我們 Kubernetes 專案的一部分。
Gitlab 提供了一個現成的 Helm Chart,用於將 gitlab-runner 部署到 Kubernetes。 所以你需要做的就是找出 註冊令牌 對於我們的項目 設定 -> CI / CD -> 跑者 並將其傳遞給掌舵:
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
在哪裡:
https://gitlab.com — 您的 Gitlab 伺服器的位址。- yga8y-jdCusVDn_t4Wxc — 您的專案的註冊令牌。
- rbac.create=true — 為運行者提供必要的權限,以便能夠使用 kubernetes-executor 建立 pod 來執行我們的任務。
如果一切都正確完成,您應該會在 部分中看到已註冊的跑步者 運動員,在您的項目設定中。
新增的跑步者的螢幕截圖
真有這麼簡單嗎? - 是的,就是這麼簡單! 不再需要手動註冊跑步者的麻煩,從現在開始,跑步者將自動創建和銷毀。
6. 使用 QBEC 部署 Helm 圖表
既然我們決定考慮 gitlab-runner 作為我們專案的一部分,是時候在我們的 Git 儲存庫中描述它了。
我們可以將其描述為一個單獨的組件 網站,但未來我們計劃部署不同的副本 網站 很多時候,不像 gitlab-runner,每個 Kubernetes 叢集僅部署一次。 因此,讓我們為其初始化一個單獨的應用程式:
cd deploy
qbec init gitlab-runner
cd gitlab-runner
這次我們不會手動描述 Kubernetes 實體,而是採用現成的 Helm 圖表。 qbec 的優點之一是能夠直接從 Git 儲存庫渲染 Helm 圖表。
讓我們使用 git 子模組連接它:
git submodule add https://gitlab.com/gitlab-org/charts/gitlab-runner vendor/gitlab-runner
現在目錄 供應商/gitlab-runner 我們有一個帶有 gitlab-runner 圖表的儲存庫。
以類似的方式,您可以連接其他儲存庫,例如帶有官方圖表的整個儲存庫
https://github.com/helm/charts
讓我們來描述一下這個元件 元件/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,
}
)
第一個參數 展開Helm模板 我們將路徑傳遞給圖表,然後 參數值,我們從環境參數中獲取,然後得到對象
- 名稱模板 — 發布標題
- 命名空間 — 命名空間轉移到 helm
- 這個文件 — 傳遞目前檔案路徑的必要參數
- 冗長的 - 顯示指令 舵模板 渲染圖表時使用所有參數
現在讓我們來描述一下我們元件的參數 環境/base.libsonnet:
local secrets = import '../secrets/base.libsonnet';
{
components: {
gitlabRunner: {
name: 'gitlab-runner',
values: {
gitlabUrl: 'https://gitlab.com/',
rbac: {
create: true,
},
runnerRegistrationToken: secrets.runnerRegistrationToken,
},
},
},
}
請注意 跑者註冊令牌 我們從外部文件中獲取 秘密/base.libsonnet,讓我們創建它:
{
runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}
讓我們檢查一下是否一切正常:
qbec show default
如果一切正常,那麼我們可以透過 Helm 刪除先前部署的版本:
helm uninstall gitlab-runner
並以相同的方式部署它,但透過 qbec:
qbec apply default
7.git-crypt簡介
目前,我們的 gitlab-runner 目錄結構如下所示:
.
├── components
│ ├── gitlab-runner.jsonnet
├── environments
│ ├── base.libsonnet
│ └── default.libsonnet
├── params.libsonnet
├── qbec.yaml
├── secrets
│ └── base.libsonnet
└── vendor
└── gitlab-runner (submodule)
但是在 Git 中儲存秘密並不安全,不是嗎? 所以我們需要對它們進行正確的加密。
通常,為了一個變量,這並不總是有意義的。 您可以將秘密轉移到 魁北克 並通過 CI 系統的環境變數。
但值得注意的是,還有更複雜的項目可以包含更多秘密;透過環境變數將它們全部傳輸將非常困難。而且,在這種情況下,我將無法告訴您這樣一個出色的工具 git 密碼.
git 密碼 它還很方便,因為它允許您保存整個秘密歷史記錄,以及比較、合併和解決衝突,就像我們在 Git 中習慣做的那樣。
安裝後第一件事 git 密碼 我們需要為我們的儲存庫產生金鑰:
git crypt init
如果您有 PGP 金鑰,那麼您可以立即將自己新增為該專案的合作者:
git-crypt add-gpg-user [email protected]
這樣,您始終可以使用您的私鑰解密此儲存庫。
如果您沒有 PGP 金鑰並且不希望有它,那麼您可以採用其他方法並匯出專案金鑰:
git crypt export-key /path/to/keyfile
因此,任何擁有出口的人 密鑰檔案 將能夠解密您的儲存庫。
是時候建立我們的第一個秘密了。
讓我提醒您,我們仍在目錄中 部署/gitlab-runner/,我們有一個目錄 秘密/,讓我們加密其中的所有文件,為此我們將創建一個文件 秘密/.gitattributes 包含以下內容:
* filter=git-crypt diff=git-crypt
.gitattributes !filter !diff
從內容可以看出,所有文件都被封鎖了 * 將被驅動通過 git 密碼,除了大多數 .gitattributes
我們可以透過運行來檢查這一點:
git crypt status -e
輸出將是儲存庫中啟用加密的所有檔案的列表
就這樣,現在我們可以安全地提交更改了:
cd ../..
git add .
git commit -m "Add deploy for gitlab-runner"
要阻止存儲庫,只需運行:
git crypt lock
所有加密的文件都會立即變成二進位文件,無法讀取它們。
若要解密儲存庫,請執行:
git crypt unlock
8. 建立工具箱鏡像
工具箱映像是包含我們將用於部署專案的所有工具的映像。 Gitlab 運行程式將使用它將來執行典型的部署任務。
這裡一切都很簡單,讓我們創造一個新的 dockerfiles/工具箱/Dockerfile 包含以下內容:
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
正如您所看到的,在此映像中,我們安裝了用於部署應用程式的所有實用程式。 我們這裡不需要它,除非 Kubectl,但您可能想在管道設定階段使用它。
此外,為了能夠與 Kubernetes 通訊並部署到它,我們需要為 gitlab-runner 產生的 pod 設定角色。
為此,我們使用 gitlab-runner 進入目錄:
cd deploy/gitlab-runner
並新增一個組件 組件/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,
},
],
},
]
我們還將在中描述新參數 環境/base.libsonnet,現在看起來像這樣:
local secrets = import '../secrets/base.libsonnet';
{
components: {
gitlabRunner: {
name: 'gitlab-runner',
values: {
gitlabUrl: 'https://gitlab.com/',
rbac: {
create: true,
},
runnerRegistrationToken: secrets.runnerRegistrationToken,
runners: {
serviceAccountName: $.components.rbac.name,
image: 'registry.gitlab.com/kvaps/docs.example.org/toolbox:v0.0.1',
},
},
},
rbac: {
name: 'gitlab-runner-deploy',
},
},
}
請注意 $.components.rbac.name 指的是 名稱 對於組件 紅細胞
讓我們檢查一下發生了什麼變化:
qbec diff default
並將我們的變更應用到 Kubernetes:
qbec apply default
另外,不要忘記將我們的更改提交到 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. 我們的第一個管道和按標籤組裝圖像
我們將在專案的根目錄中創建 .gitlab-ci.yml 包含以下內容:
.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
請注意我們使用 GIT_SUBMODULE_STRATEGY:正常 對於那些需要在執行之前明確初始化子模組的作業。
不要忘記提交我們的更改:
git add .gitlab-ci.yml
git commit -m "Automate docker build"
我想我們可以放心地稱之為一個版本 v0.0.1 並添加標籤:
git tag v0.0.1
每當我們需要發布新版本時,我們都會新增標籤。 Docker 映像中的標籤將與 Git 標籤綁定。 每次帶有新標籤的推送都會使用該標籤初始化鏡像的建置。
我們開始做吧 git push --標籤,讓我們看看我們的第一個管道:
第一個管道的螢幕截圖
值得注意的是,透過標籤組裝適合建置 docker 映像,但不適合將應用程式部署到 Kubernetes。 由於新標籤可以分配給舊提交,在這種情況下,為它們初始化管道將導致舊版本的部署。
為了解決這個問題,通常將docker映像的建置與標籤綁定在一起,並將應用程式部署到分支 主,其中收集的圖像的版本是硬編碼的。 您可以在此處透過簡單的恢復來初始化回滾 主- 分公司。
10. 部署自動化
為了讓 Gitlab-runner 解密我們的秘密,我們需要匯出儲存庫金鑰並將其新增至我們的 CI 環境變數:
git crypt export-key /tmp/docs-repo.key
base64 -w0 /tmp/docs-repo.key; echo
我們將把生成的行保存在 Gitlab 中;為此,我們進入專案設定:
設定 -> CI / CD -> 變數
讓我們建立一個新變數:
類別
關鍵
值
保護
蒙面
範圍
File
GITCRYPT_KEY
<your string>
true
(在培訓期間您可以 false
)
true
All environments
新增的變數的螢幕截圖
現在讓我們更新我們的 .gitlab-ci.yml 添加到它:
.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
在這裡,我們為 qbec 啟用了幾個新選項:
- --根一些/應用程式 — 允許您確定特定應用程式的目錄
- --force:k8s-context __incluster__ - 這是一個神奇的變量,表示部署將在 gtilab-runner 運行的同一叢集中進行。 這是必要的,因為否則 qbec 會嘗試在您的 kubeconfig 中找到合適的 Kubernetes 伺服器
- - 等待 — 強制 qbec 等待,直到它建立的資源進入就緒狀態,然後才以成功的退出程式碼退出。
- -是的 - 簡單地停用互動式 shell 你確定嗎? 部署時。
不要忘記提交我們的更改:
git add .gitlab-ci.yml
git commit -m "Automate deploy"
之後 git push 我們將看到我們的應用程式是如何部署的:
第二條管道的截圖
11. 推到master時的工件和組裝
通常,上述步驟足以建置和交付幾乎任何微服務,但我們不想每次需要更新網站時都會新增標籤。 因此,我們將採取更動態的路線,在 master 分支中設定摘要部署。
這個想法很簡單:現在我們的形象 網站 每次你推入時都會重建 主,然後自動部署到Kubernetes。
讓我們更新這兩個作業 .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"
請注意我們添加了一個線程 主 к 裁判 為了工作 建立網站 我們現在使用 $CI_COMMIT_REF_NAME 而不是 $CI_COMMIT_TAG,也就是說,我們擺脫了 Git 中的標籤,現在我們將推送一個帶有初始化管道的提交分支名稱的鏡像。 值得注意的是,這也適用於標籤,這將允許我們在 docker-registry 中保存具有特定版本的網站的快照。
當新版本網站的 docker 標籤名稱可以不變時,我們仍然需要向 Kubernetes 描述這些更改,否則它根本不會從新映像中重新部署應用程序,因為它不會注意到 Kubernetes 中的任何變化。部署清單。
選項 —vm:ext-str 摘要=”$DIGEST” for qbec - 允許您將外部變數傳遞給 jsonnet。 我們希望隨著應用程式的每個版本將其重新部署到叢集中。 我們不能再使用標籤名稱,它現在是不可更改的,因為我們需要綁定到映像的特定版本並在其更改時觸發部署。
在這裡,我們將受益於 Kaniko 將摘要圖像保存到文件的能力(選項 --摘要文件)
然後我們將傳輸這個檔案並在部署時讀取它。
讓我們更新我們的參數 部署/網站/環境/base.libsonnet 現在看起來像這樣:
{
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',
},
},
}
完成,現在任何提交 主 初始化 docker 映像的構建 網站,然後部署到Kubernetes。
不要忘記提交我們的更改:
git add .
git commit -m "Configure dynamic build"
我們稍後會檢查 git push 我們應該看到這樣的東西:
master 管道的螢幕截圖
原則上,我們不需要在每次推送時重新部署 gitlab-runner,當然,除非它的配置沒有任何變化,讓我們修復它 .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/**/*
變化 將允許您監視變化 部署/gitlab-runner/ 並且只有在有任何情況時才會觸發我們的工作
不要忘記提交我們的更改:
git add .gitlab-ci.yml
git commit -m "Reduce gitlab-runner deploy"
git push,這樣更好:
更新後的管道的螢幕截圖
12. 動態環境
是時候透過動態環境使我們的管道多樣化了。
首先我們來更新一下作業 建立網站 在我們的 .gitlab-ci.yml,從中刪除區塊 僅由,這將強制 Gitlab 在對任何分支的任何提交時觸發它:
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/
然後更新作業 部署網站,在那裡添加一個塊 環境:
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"
這將允許 Gitlab 將作業與 產品 環境並顯示正確的連結。
現在讓我們再新增兩個作業:
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
它們將在推送到 master 以外的任何分支時啟動,並將部署網站的預覽版本。
我們看到 qbec 的一個新選項: --應用程式標籤 — 它允許您標記應用程式的已部署版本,並且僅在該標記內工作;在 Kubernetes 中建立和銷毀資源時,qbec 將僅對它們進行操作。
這樣我們就不能為每次評審創造一個單獨的環境,而只是重複使用同一個環境。
這裡我們也使用 qbec申請審查, 代替 qbec 應用預設值 - 這正是我們嘗試描述我們的環境差異(審核和預設)的時刻:
讓我們添加 檢討 環境在 部署/網站/qbec.yaml
spec:
environments:
review:
defaultNamespace: docs
server: https://kubernetes.example.org:8443
然後我們將在中聲明它 部署/網站/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
並記下它的自訂參數 部署/網站/環境/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',
},
},
}
我們也來仔細看看jobu 停止評論,當分支被刪除時會觸發,這樣gitlab就不會嘗試檢查它是否被使用 GIT_STRATEGY:無,稍後我們克隆 主- 透過它分支和刪除評論。
這有點令人困惑,但我還沒有找到更漂亮的方法。
另一種選擇是將每個評論部署到酒店名稱空間,該名稱空間始終可以完全拆除。
不要忘記提交我們的更改:
git add .
git commit -m "Enable automatic review"
git push, git checkout -b 測試, git推送原點測試, 查看:
Gitlab 中建立的環境截圖
一切正常嗎? - 太好了,刪除我們的測試分支: git checkout master, git推送原點:測試,我們檢查環境刪除作業是否正常運作。
這裡我想立即澄清,專案中的任何開發人員都可以建立分支,他也可以更改 .gitlab-ci.yml 文件和存取秘密變數。
因此,強烈建議僅允許將它們用於受保護的分支,例如 主,或為每個環境建立一組單獨的變數。
13.審查應用程式
為了顯示這些按鈕,您需要建立一個文件 .gitlab/route-map.yml 並描述其中的所有路徑轉換;在我們的例子中,它會非常簡單:
# Indices
- source: /content/(.+?)_index.(md|html)/
public: '1'
# Pages
- source: /content/(.+?).(md|html)/
public: '1/'
不要忘記提交我們的更改:
git add .gitlab/
git commit -m "Enable review apps"
git push,並檢查:
“查看應用程式”按鈕的螢幕截圖
工作完成了!
專案來源:
- 在亞特實驗室上:
https://gitlab.com/kvaps/docs.example.org - 在 GitHub 上:
https://github.com/kvaps/docs.example.org
感謝您的關注,希望您喜歡
來源: www.habr.com