Kubernetes 中的金丝雀部署 #1:Gitlab CI

我们将使用Gitlab CI和手动GitOps在Kubernetes中实现和使用Canary部署

Kubernetes 中的金丝雀部署 #1:Gitlab CI

本系列文章:

我们将通过 GitOps 手动执行 Canary 部署并创建/修改主要 Kubernetes 资源。 这篇文章主要是为了介绍 Kubernetes Canary 中的部署工作方式,因为有更有效的自动化方法,我们将在下面的文章中考虑这些方法。


Kubernetes 中的金丝雀部署 #1:Gitlab CI

https://www.norberteder.com/canary-deployment/

金丝雀部署

使用金丝雀策略,更新首先仅应用于一部分用户。 通过监控、日志数据、手动测试或其他反馈渠道,在发布给所有用户之前对版本进行测试。

Kubernetes 部署(滚动更新)

Kubernetes 部署的默认策略是滚动更新,即使用新版本的映像启动一定数量的 pod。 如果创建时没有出现问题,则具有旧版本映像的 Pod 将被终止,并并行创建新的 Pod。

Git 操作

我们在本例中使用 GitOps 是因为:

  • 使用 Git 作为单一事实来源
  • 我们使用 Git Operations 进行构建和部署(除了 git tag/merge 之外不需要任何命令)

例子

让我们采取一种良好的做法 - 拥有一个用于应用程序代码的存储库和一个用于基础设施的存储库。

应用程序存储库

这是一个非常简单的 Python+Flask API,以 JSON 形式返回响应。 我们将通过 GitlabCI 构建包并将结果推送到 Gitlab 注册表。 在注册表中我们有两个不同的发行版本:

  • wuestkamp/k8s-deployment-example-app:v1
  • wuestkamp/k8s-deployment-example-app:v2

它们之间的唯一区别是返回的 JSON 文件的变化。 我们使用此应用程序尽可能轻松地可视化我们正在与哪个版本进行通信。

基础设施存储库

在这个萝卜中,我们将通过 GitlabCI 部署到 Kubernetes, .gitlab-ci.yml 如下:

image: traherom/kustomize-docker

before_script:
   - printenv
   - kubectl version

stages:
 - deploy

deploy test:
   stage: deploy
   before_script:
     - echo $KUBECONFIG
   script:
     - kubectl get all
     - kubectl apply -f i/k8s

   only:
     - master

要自己运行它,您需要一个集群,您可以使用 Gcloud:

gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b

gcloud compute firewall-rules create incoming-80 --allow tcp:80

你需要分叉 https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure 并创建一个变量 KUBECONFIG 在 GitlabCI 中,其中将包含访问配置 kubectl 到您的集群。

您可以阅读有关如何获取集群 (Gcloud) 凭据的信息 这里.

基础设施 YAML

在基础设施存储库中,我们有服务:

apiVersion: v1
kind: Service
metadata:
 labels:
   id: app
 name: app
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 5000
 selector:
   id: app
 type: LoadBalancer

并部署在 deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: app
spec:
 replicas: 10
 selector:
   matchLabels:
     id: app
     type: main
 template:
   metadata:
     labels:
       id: app
       type: main
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v1
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

另一个部署在 deploy-canary.yaml:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 0
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

请注意,app-deploy 尚未定义任何副本。

执行初始部署

要开始初始部署,您可以在 master 分支上手动启动 GitlabCI 管道。 在那之后 kubectl 应输出以下内容:

Kubernetes 中的金丝雀部署 #1:Gitlab CI

我们看到了 app 部署有 10 个副本,app-canary 有 0 个副本。还有一个 LoadBalancer,我们可以通过它访问 curl 通过外部IP:

while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Kubernetes 中的金丝雀部署 #1:Gitlab CI

我们看到我们的测试应用程序仅返回“v1”。

执行金丝雀部署

步骤1:为部分用户发布新版本

我们在deploy-canary.yaml文件和新版本镜像中将副本数设置为1:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 1
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

在文件中 deploy.yaml 我们将副本数量更改为 9:

kind: Deployment
metadata:
 name: app
spec:
 replicas: 9
 selector:
   matchLabels:
     id: app
...

我们将这些更改推送到将启动部署的存储库(通过 GitlabCI)并查看结果:

Kubernetes 中的金丝雀部署 #1:Gitlab CI

我们的服务将指向这两个部署,因为两者都有应用程序选择器。 由于 Kubernetes 的默认随机化,我们应该看到约 10% 的请求有不同的响应:

Kubernetes 中的金丝雀部署 #1:Gitlab CI

我们的应用程序(GitOps,取自 Git 作为单一事实来源)的当前状态是存在两个具有活动副本的部署,每个版本一个。

大约 10% 的用户熟悉新版本并无意中测试它。 现在是检查日志和监控数据中是否有错误以发现问题的时候了。

步骤2:向所有用户发布新版本

我们认为一切都很顺利,现在我们需要向所有用户推出新版本。 为此,我们只需更新 deploy.yaml 安装新版本的镜像,副本数等于 10。 deploy-canary.yaml 我们将副本数设置回0。部署后,结果如下:

Kubernetes 中的金丝雀部署 #1:Gitlab CI

总结

对我来说,以这种方式手动运行部署有助于了解使用 k8s 配置它是多么容易。 由于 Kubernetes 允许您通过 API 更新所有内容,因此这些步骤可以通过脚本自动化。

需要实现的另一件事是测试人员入口点(LoadBalancer 或通过 Ingress),通过它只能访问新版本。 可用于手动浏览。

在以后的文章中,我们将查看其他自动化解决方案,这些解决方案实现了我们所做的大部分工作。

另请阅读我们博客上的其他文章:

来源: habr.com

添加评论