我们将使用Gitlab CI和手动GitOps在Kubernetes中实现和使用Canary部署
本系列文章:
- (本文)
使用 ArgoCI 进行金丝雀部署 - 使用 Istio 进行金丝雀部署
- 使用 Jenkins-X Istio Flagger 进行金丝雀部署
我们将通过 GitOps 手动执行 Canary 部署并创建/修改主要 Kubernetes 资源。 这篇文章主要是为了介绍 Kubernetes Canary 中的部署工作方式,因为有更有效的自动化方法,我们将在下面的文章中考虑这些方法。
金丝雀部署
使用金丝雀策略,更新首先仅应用于一部分用户。 通过监控、日志数据、手动测试或其他反馈渠道,在发布给所有用户之前对版本进行测试。
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
你需要分叉 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
应输出以下内容:
我们看到了 app
部署有 10 个副本,app-canary 有 0 个副本。还有一个 LoadBalancer,我们可以通过它访问 curl
通过外部IP:
while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done
我们看到我们的测试应用程序仅返回“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 的默认随机化,我们应该看到约 10% 的请求有不同的响应:
我们的应用程序(GitOps,取自 Git 作为单一事实来源)的当前状态是存在两个具有活动副本的部署,每个版本一个。
大约 10% 的用户熟悉新版本并无意中测试它。 现在是检查日志和监控数据中是否有错误以发现问题的时候了。
步骤2:向所有用户发布新版本
我们认为一切都很顺利,现在我们需要向所有用户推出新版本。 为此,我们只需更新 deploy.yaml
安装新版本的镜像,副本数等于 10。 deploy-canary.yaml
我们将副本数设置回0。部署后,结果如下:
总结
对我来说,以这种方式手动运行部署有助于了解使用 k8s 配置它是多么容易。 由于 Kubernetes 允许您通过 API 更新所有内容,因此这些步骤可以通过脚本自动化。
需要实现的另一件事是测试人员入口点(LoadBalancer 或通过 Ingress),通过它只能访问新版本。 可用于手动浏览。
在以后的文章中,我们将查看其他自动化解决方案,这些解决方案实现了我们所做的大部分工作。
另请阅读我们博客上的其他文章:
从无授权的ClickHouse迁移到授权的ClickHouse导致了什么? 为 Nginx 构建动态模块 更新 nxs-build-tools - 构建 deb 和 rpm 包的助手 Hashicorp Consul Kubernetes 授权介绍 使用 Csync2 实用程序时我们必须面对的问题 Redmine 的 Telegram 机器人。 如何简化自己和他人的生活
来源: habr.com