一直很想把 CI/CD 流程整進去新架設的 Kubernetes 內(透過 GKE 提供的),花了點時間終於搞定了。
建立 Service Account,產生 JSON 格式的 private key,並給予 GCR 及 GKE 權限,分別拿來上傳編譯好的 Docker Image 以及操作 GKE。整個流程大致上如最上面的圖片,其實不難,只是中間如果有東西沒串好,整個流程就不會動。
建立 Kubernetes Role 並綁定 RBAC,這邊設定 extensions/deployments 給予 get/patch/list 權限。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: deployment-manager-gitlab
rules:
- apiGroups: ["extensions"]
resources: ["deployments"]
verbs: ["get", "patch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: deployment-manager
namespace: default
subjects:
- kind: User
name: "[[前面建立的 IAM 帳號]]"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: deployment-manager-gitlab
apiGroup: rbac.authorization.k8s.io
透過 kubectl apply 設定後,確認 RBAC 綁定狀況:
# kubectl get Role,RoleBinding
NAME AGE
role.rbac.authorization.k8s.io/deployment-manager-gitlab 138m
role.rbac.authorization.k8s.io/nginx-ingress 14d
NAME AGE
rolebinding.rbac.authorization.k8s.io/deployment-manager 138m
rolebinding.rbac.authorization.k8s.io/nginx-ingress 14d
設定 GitLab Repo 的 CI/CD 環境變數:
在 GibLab 專案內選單進入 Settings -> CI/CD,展開 Variables 區塊,指定變數名稱(這邊範例是 GCP_SERVICE_ACCOUNT
)並將前面取得的 JSON 檔案的內容貼進變數的值。
這邊要先手動方式在 Kubernetes 產生好 Deployment,GitLab CD 只透過 set image 指令更新 image 版本。
撰寫 .gitlab-ci.yaml 檔案,這邊實作兩個步驟:
- 編譯 Docker Image 並上傳到 GCR(build-docker)
- 透過 kubectl set image 方式更新 Deployment 的 image(deploy-k8s)
stages: - build-docker - deploy-k8s variables: GCP_GCR: asia.gcr.io/[[BUCKET_NAME]]/[[IMAGE_NAME]] build_docker: image: "docker:18.09" services: - docker:18-dind stage: build-docker before_script: - apk -Uuv add curl bash python - curl https://sdk.cloud.google.com | CLOUDSDK_CORE_DISABLE_PROMPTS=1 bash - export PATH=$PATH:/root/google-cloud-sdk/bin/ - echo $GCP_SERVICE_ACCOUNT > /root/key.json - gcloud auth activate-service-account --key-file /root/key.json - gcloud auth configure-docker --quiet - docker login -u _json_key --password-stdin https://asia.gcr.io < /root/key.json script: - docker build -t ${GCP_GCR}:${CI_COMMIT_SHA:0:8} . - docker push ${GCP_GCR}:${CI_COMMIT_SHA:0:8} deploy-k8s-test: image: google/cloud-sdk:latest stage: deploy-k8s before_script: - echo $GCP_SERVICE_ACCOUNT > /root/$key.json - gcloud auth activate-service-account --key-file /root/key.json - gcloud container clusters get-credentials [[K8S_CLUSTER_NAME]] --zone asia-east2-c --project [[GCP_PROJECT_NAME]] script: - kubectl set image deployment app app=${GCP_GCR}:${CI_COMMIT_SHA:0:8} --record dependencies: - build_docker
(記得自行替換掉 BUCKET_NAME
以及 IMAGE_NAME
甚至是 gcr.io 的 region)
接下來每次 commit 就會自動觸發 GitLab CI/CD,自動編譯出 Docker Image 並上傳到 GCR,然後自動 deploy 到 Kubernetes 上,完成整個持續建置與持續部署的動作。
-
參考:Publishing Google Cloud Container Registry Images from Gitlab CI