我尝试为我的 GKE 集群构建一个持续部署管道。我使用自己的 gitlab-runner 作为 CI 管道构建并将图像推送到 gcr.io/PROJECT/APP:google 标记。
是否有可能在更新后实现使用此镜像的容器的滚动重启?我已经看到很多关于如何在 Kubernetes 集群中直接使用 Jenkins 和 Google Source Repository 的示例,但是是否有可能仅在图像更改时触发?
我在这里找到了我需要的东西https://cloud.google.com/container-registry/docs/configuring-notifications .但是,我仍然不知道如何将这些通知与集群连接起来。
最佳答案
经过一些测试,最后我使用 PubSub 和 Kubernetes Cronjob 使它工作。
这个怎么运作:
当新图片推送到容器注册 , 一条消息被发送到 发布/订阅 其中包含一些重要数据,如下所示:
{
"action":"INSERT",
"digest":"gcr.io/my-project/hello-world@sha256:6ec128e26cd5...",
"tag":"gcr.io/my-project/hello-world:1.1"
}
action
有值 INSERT
表示将新图像推送到 Pub/Sub。key
tag
包含被推送的图像的名称。因此,我们需要做的就是读取这些数据并更新部署镜像。
首先,我们需要一些代码来从 Pub/Sub 中检索消息。不幸的是,我找不到任何“准备好”的东西来完成这项任务,所以你需要自己创建。 Here有一些示例说明如何从 Pub/Sub 中检索消息。
As a proof-of-concept, my choice was to use a shell script (imageUpdater.sh) to retrieve the message from Pub/Sub and execute the
kubectl set image...
command to update the deployment image.
其次,使用第一个代码创建一个 Cronjob 来读取消息并更新部署。
In my example, I've create a docker image with gcloud and kubectl command to perform the tasks, you can find the code Here.
但是,要使这一切正常工作,您必须授予作业 pod 执行“kubectl set image”的权限,为此我们需要配置 RBAC权限。
To create a "isolated" PoC, I will create every resources describe here in a new namespace named "myns". The RBAC will only work in this name space, because
Role
is namespace, if you what to use in all namespaces, change toClusterRole
1.PubSub 配置
首先,您需要配置 Container Registry 以向 Pub/Sub 发送消息。您可以关注 this指导。
In this example I will use a nginx image to demonstrate.
gcloud pubsub topics create projects/[PROJECT-ID]/topics/gcr
从推送或标记 Docker 镜像的系统运行以下命令:
gcloud pubsub subscriptions create nginx --topic=gcr
2. GKE 集群
GKE 需要权限才能访问 Pub/Sub,并且只能在使用
--scope "https://www.googleapis.com/auth/pubsub"
创建新集群时完成。 .因此,我将为我们的示例创建一个新集群:为我们的示例创建一个新集群:
gcloud container clusters create "my-cluster" --num-nodes "1" --scopes "https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/pubsub","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append"
关于
scopes
的更多信息here .获取集群凭据:
gcloud container clusters get-credentials my-cluster
3.配置RBAC权限
如前所述,所有资源都将在命名空间
myns
中创建。 .所以让我们创建命名空间:kubectl create ns myns
之后,我们可以创建一个名为
sa-image-update
的新服务帐户。并应用 RBAC 权限:apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-image-update
namespace: myns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: myns
name: role-set-image
rules:
- apiGroups: ["apps", "extensions"]
resources: ["deployments"]
verbs: ["get", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rolebinding-set-image
namespace: myns
roleRef:
kind: Role
name: role-set-image
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: sa-image-update
namespace: myns
4. 配置图
为了使其尽可能简单,我将使用 shell 脚本文件创建一个 configmap,该文件将由 pod 挂载和执行:
# Download script
wget https://raw.githubusercontent.com/MrKoopaKiller/docker-gcloud-kubectl/master/imageUpdater.sh
# Create configmap
kubectl create configmap imageupdater -n myns --from-file imageUpdater.sh
5. 定时任务
shell 脚本需要 3 个变量才能工作:
PROJECT-NAME
: gcloud 项目名称DEPLOYMENT-NAME
:将要更新的部署的名称IMAGE-NAME
:要更新的不带标签的图像的名称。在这种情况下,我的示例部署将被称为
nginx
和图片 nginx
.图片来自我之前提到的dockerfile,可以找到here并 build 它。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: image-updater
namespace: myns
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: sa-image-update
volumes:
- name: imageupdater
configMap:
name: imageupdater
containers:
- name: image-updater
image: <your_custom_image>
volumeMounts:
- name: imageupdater
mountPath: /bin/imageUpdater.sh
subPath: imageUpdater.sh
command: ['bash', '/bin/imageUpdater.sh', 'PROJECT-NAME', 'nginx', 'nginx']
restartPolicy: Never
好的,一切都完成了。现在我们需要创建一个部署作为示例来演示:
部署示例:nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: myns
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: myns
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
好的,现在当你的gitlab推送一个新镜像到容器注册表时,会向Pub/Sub发送一条消息,cronjob每2分钟运行一次,验证镜像名称是否为
nginx
如果是,将运行 kubectl set image
.引用:
https://medium.com/better-programming/k8s-tips-using-a-serviceaccount-801c433d0023
https://cloud.google.com/solutions/integrating-microservices-with-pubsub#creating_a_gke_cluster
关于kubernetes - 使用 google 容器注册表持续部署到 Google Kubernetes Engine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62190365/