kubernetes - 使用 google 容器注册表持续部署到 Google Kubernetes Engine

标签 kubernetes google-kubernetes-engine continuous-deployment

我尝试为我的 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 to ClusterRole



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

好的,一切都完成了。现在我们需要创建一个部署作为示例来演示:

部署示例:n​​ginx

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/

相关文章:

kubernetes - Traefik https重定向(通过kubernetes部署)

postgresql - IBM Bluemix 容器上的 Kubernetes 上的 Postgres

go - 在 Kubernetes 中,Go 容器是否会在另一个容器使用内核时使用所有内核

java - 如何处理 DirectVmConsumerNotAvailableException

reactjs - 如何将 React 应用程序从 Github 部署到 AWS S3 存储桶并设置环境变量 注意 : I didn't push . github 中的 env 文件

git - 运行 Github Action 以使分支与主分支保持同步

ssl - Kubernetes: Nginx Ingress注解----> nginx.ingress.kubernetes.io/secure-backends

kubernetes - 在 Kubernetes 集群上使用 Jmeter GUI 运行性能测试

kubernetes - 与 etcd 直接通信的 Kubernetes 模块是什么

google-kubernetes-engine - 我的虚拟机可以直接访问谷歌容器引擎中的 "services"吗?