學習前置條件:
- gcloud 已經在本地安裝起來了
- GitHub Branch protection rules (分支保護) - 多環境的需求 (Prod/Qa/Dev)
- SSH 連線機制 - GCE 連線的時候所需
- 搭建一台 Private GKE - 會經由 IAP 連線至 GCE 部署到 Private GKE 走權限內網的方式
- Docker Image Tag 分類 - 多環境的需求 (Prod/Qa/Dev)
- Firewall 設置
- Cloud Nat 的統一 VPC 出口
- GCS 的 gsutil cli工具 - cp 檔案
- 自動化 CI/CD 部署 DevOps 概念
知識介紹
Git 分類與分支概念
- 由 branch 分多環境 (Prod/Qa/Dev)
- 由 tag 給予 release 版本
(範例分支圖)
GitHub 專案設置
分支保護的目的是為了讓職責分開,開發人員可以專心的開發需求
主要會有分幾種狀態 - Git flow
Settings/Manage access
分支名稱 | 角色職責 | 由local端推送至remote端 |
---|---|---|
master( or prod) | Maintain | x |
demo ( or qa) | Maintain | x |
develop ( or dev) | Write | o |
feature/功能 ( or feat) | Write | o |
hot-fix/修補 | Write | o |
Settings/Branch protection rules
用途是來保護分支讓分支有審核機制,官方文件:因應各個公司不同流程不同。
基本上會使用這幾種:
- Require a pull request before merging (合併前需要拉取請求,設立最少幾位同仁檢查)
- Require status checks to pass before merging (合併前需要通過狀態檢查,檢查CloudBuild健康狀態)
- Include administrators (包括 管理者不能直接 local 直推受保護的 branch 需要Pull Request)
Google Compute Engine (GCE)
create GCE
GCE 簡單說就是一台 VM 這台機器在這次演練中扮演者跳板機的角色,目的是讓 Cloud Build 能夠操作 GKE 的 Master 主機:
# 生一把 bastion 的 ssh key
ssh-keygen -t rsa -C "bastion"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/xufangde/.ssh/id_rsa): bastion
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in bastion.
Your public key has been saved in bastion.pub.
The key fingerprint is:
SHA256:pdil3UsrmhF/cO8MYEj4klzXP0/J/jhuxhSoJEK4nq4 bastion
The key's randomart image is:
+---[RSA 3072]----+
| . |
| . .. . |
| o. o + .. |
| ...B.O....o .|
| . .=.So=.+ o+.|
| o . +.= +o+ |
| . . o =o...|
| . + o +=..|
| E. o +=..|
+----[SHA256]-----+
<!-- 相關機器設定 -->
name: bastion
zone: asia-east1-b <!-- 範例使用 -->
machine-type: n1-f1-micro <!-- 能小就小 -->
Network interfaces: default / external-ip: none <!-- 記得關掉 external-ip -->
Security/SSH: <!-- ~/.ssh/bastion.pub -->
Service Account: default <!-- 預設的SA會是 [email protected] -->
<!-- [!] 讓 GCE 的 能夠操作的話 Service Account 的 IAM
要加上一個 Rule `Kubernetes Engine Admin Editor` -->
Google Kubernetes Engine (GKE)
create private GKE
基本上也是預設的,如果怕練習時間太長就用便宜的機器吧Networking
要記得設定 Private cluster
,control plane IP range
就用 example
最下方有 Enable control plane authorized networks
控制介面,加上自己的外網IP
不知道怎麼算的可以這樣操作:
- 查自己的外網IP且複製起來
- CIDR計算器,將IP貼上至
IPv4 / IPv6
再按計算,就可以看相關詳細數字
基本上就是 x.x.x.x/32
限制一台IP入口 這樣,通常都用辦公室的固網,之後設定就直接建立
(其他相關設定由各自參閱GKE相關文章,非本次手把手重點)
建立完之後呢,可以到 GKE的操作介面有一台 GKE 正在運行,可以看到最右邊有 三個點點/Connect/Command-line access 看到似下方指令:
gcloud container clusters get-credentials <gke-name> --region <region-name> --project <project-name>
執行完之後可以嘗試看看操作是否有連線到 gke,會類似下方回饋(因為有用 control plane authorized networks
控制介面)
kubectl version --short
Client Version: v1.21.4
Server Version: v1.20.9-gke.1001
IAP 是什麼?
GCP 有一種連線方式是IAP,VM外網都關閉,由角色權限所分發認可角色進行連線的方式。
Cloud Nat 是什麼?
Cloud Nat 是用來 統一 Cloud Router 所指定的 Network 暴露出一個 External IP
。
我們的 GKE 與 GCE 都在同一個 Network (default)
如果要 GCE 要操作 GKE 這樣就要在我們的 GKE control plane authorized networks
加上 Cloud Nat 的 External IP/32
Cloud Build
Trigger 觸發器
我覺得 Cloud Build 與 Github 整合的相關功能蠻齊全的算不錯使用
Event
- Push to a branch (Pull Request 後 會進行 Merge branch 這時候觸發導致 -> CD 部署至Prod或Qa環境)
- Push new tag (新增Tag時會觸發 -> dev分支推送 git tag 的時候新增 Docker Image)
- Pull Request (Pull Request時觸發 -> 進行 Coding Test 讓 Maintainer 判斷是否可以合併至branch)
Source
可以使用正規表達式去指定你要觸發的條件,且都有選項範例
- 選
Push to a branch
或Pull Request
就是指定哪個 正規表達Branch - 選
Push new tag
就是指定哪個 正規表達Tag
Configuration
我會使用 Cloud Build configuration file (yaml or json)
可以指定部署的yaml在哪
Advanced
於 CloudBuild 使用的變數,也可以在 yaml 中寫
手把手
- Local SSH remote GCE connect Private GKE
- Local SSH remote proxy GCE connect Private GKE
- Cloud Build ssh remote proxy GCE connect Private GKE
Local SSH remote GCE connect GKE
調整 Firewall
讓 使用者能夠透過 gcloud cli 通過 iap 抵達機器 先加上 Firewall 的規則 (本次是使用SSH連線)
gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
--direction=INGRESS \
--action=allow \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20
(預設其實原本有一個 0.0.0.0/0 全開的,建議刪除 default-allow-ssh
, 一律透過 IAP 渠道進出)
調整 Identity-Aware Proxy (iap)
Security / Identity-Aware Proxy / SSH AND TCP RESOURCES
選取 bastion 那台機器添加這項Roll:IAP-secured Tunnel User
讓操作人員透過 gcloud cli 通過 iap 抵達機器
可以把 allUsers
改成自己操作者的帳號或用 SA 操作專案也可以用 SA
本地連線 GCE
# gcloud compute ssh bastion@bastion --project <project-id> --zone <zone> --ssh-key-file=<ssh private key path>
gcloud compute ssh bastion@bastion --project example-project-0123 --zone asia-east1-b --ssh-key-file=~/.ssh/bastion
External IP address was not found; defaulting to using IAP tunneling.
...
bastion@bastion:~$
這樣就成功使用 bastion ssh key
連線至 GCE
完成 IAP -> Firewall -> GCE
GCE 操作 Private GKE
由於 知識介紹 有講到 GKE 使用是 Private GKE 所以 GKE control plane authorized networks
需加上 Cloud Nat 的 External IP/32
# gcloud 安裝 kubectl
gcloud components install kubectl
...
# gcloud 連線 gke
bastion@bastion:~$ gcloud container clusters get-credentials example-gke --region asia-east1 --project example-project-0123
Fetching cluster endpoint and auth data.
kubeconfig entry generated for example-gke.
# kubectl 指令
bastion@bastion:~$ kubectl version --short
Client Version: v1.22.1
Server Version: v1.20.9-gke.1001
這樣 GCE 就可以操作 GKE
Local SSH remote proxy GCE connect Private GKE
這個方式就可以完全的不用把 Office IP 寫進 GKE control plane authorized networks
這是我參考這篇文章的做法,將其筆記進此篇
調整 GCE
- 安裝 tinyproxy
gcloud compute ssh bastion@bastion --project example-project-0123 --zone asia-east1-b --ssh-key-file=~/.ssh/bastion
External IP address was not found; defaulting to using IAP tunneling.
...
bastion@bastion:~$ sudo apt-get install tinyproxy # 安裝 tinyproxy
...
- 修改
tinyproxy.conf
vim /etc/tinyproxy/tinyproxy.conf
添加下拉至最後一行 按下a
填上Allow localhost
按下esc
輸入:wq!
編輯退出 - 重啟
sudo service tinyproxy restart
若使用 ssh 對等至 local 可以操作 gce
對等 Local Port 且嘗試操作 kubectl
Local 端也需要有 GKE 的 Conntent 方式
gcloud container clusters get-credentials example-gke --region asia-east1 --project example-project-0123
Fetching cluster endpoint and auth data.
kubeconfig entry generated for example-gke.
Local 端對等 port 8888
gcloud compute ssh bastion@bastion \
--project example-project-0123 \
--zone asia-east1-b \
--ssh-key-file=~/.ssh/bastion \
-- -L 8888:0.0.0.0:8888 -N -q -f
檢查是否連線 lsof -i:8888
lsof -i:8888
COMMAND PID ................
ssh 17020 ................
# 這樣代表有一個進程正在執行 ssh PID
嘗試使用 kubectl 碰觸 private gke
HTTPS_PROXY=localhost:8888 kubectl version --short
Client Version: v1.21.4
Server Version: v1.20.9-gke.1001
# 成功
將進程刪除
kill 17020
HTTPS_PROXY=localhost:8888 kubectl version --short
Client Version: v1.21.4
The connection to the server xx.xxx.xxx.xxx was refused - did you specify the right host or port?
# 這樣就連不到了
Cloud Build SSH remote proxy GCE connect Private GKE
終於來到最後的環節,如何撰寫 CloudBuild,我相信官方文件寫得很清楚,先把權限設定先寫一下
Cloud Build SA 設定 (Cloud Build / Setting / Service Account)
Kubernetes Engine / Kubernetes Engine Developer : Enable
Compute Engine / Compute Instance Admin (v1) : Enable
Service Accounts / Service Account User : Enable
Cloud Build Tiggers
由 知識介紹 中 選擇其相關的方式
將 SSH Key 放進 GCS
可以點去 GCS 看到 asia.artifacts.example-project-0123.appspot.com
, 這個是管理 GCR Image,我自己是習慣把它放在 asia 區 因為,我們就在亞洲區,在這個 Storage 中 新增一個放置 SSH key 的資料夾 .ssh
,把 bastion
的 private/public key 上傳至GCS \
可以用本地測試這個指令看可否複製 key 至 Local
gsutil cp -r gs://asia.artifacts.$PROJECT_ID.appspot.com/.ssh .
重頭戲 cloudbuild.yaml
在使用這個之前我會先把環境先架設一遍,後續維護交給 Cloud Build 去更新上版
K8s 相關的設定 yaml 每個專案不同,我自己是習慣先建立一個 Projest 是 先建立起環境的 kustomiz Project 去管理最開始的初始化 GKE
steps:
- name: 'gcr.io/cloud-builders/docker'
id: Docker Pull / Tag / Push.
entrypoint: sh
args:
- -c
- |
docker build -t asia.gcr.io/$PROJECT_ID/$_DOCKER_NAME:$TAG_NAME -t asia.gcr.io/$PROJECT_ID/$_DOCKER_NAME:dev . &&
docker push asia.gcr.io/$PROJECT_ID/$_DOCKER_NAME:$TAG_NAME &&
docker push asia.gcr.io/$PROJECT_ID/$_DOCKER_NAME:dev
- name: 'gcr.io/cloud-builders/gsutil'
id: get ssh key
entrypoint: sh
args:
- -c
- gsutil cp -r gs://asia.artifacts.$PROJECT_ID.appspot.com/.ssh /builder/home/
- name: 'gcr.io/cloud-builders/gsutil'
id: chmod 400
entrypoint: sh
args:
- -c
- chmod 400 /builder/home/.ssh/bastion
- name: gcr.io/cloud-builders/gcloud
id: GKE - content gke > ssh bastion > Install `kubectl` > Rollout
entrypoint: sh
args:
- -c
- gcloud container clusters get-credentials example-gke --region asia-east1 --project $PROJECT_ID &&
gcloud compute ssh bastion@bastion --project $PROJECT_ID --zone asia-east1-b --ssh-key-file=/builder/home/.ssh/bastion -- -L 8888:0.0.0.0:8888 -N -q -f &&
gcloud components install kubectl &&
HTTPS_PROXY=localhost:8888 kubectl rollout restart deploy example-deployname
結語:
我在嘗試 Cloud Build 用了很多 id 去分開步驟讓自己更清晰,但最後發現 當我把 gcloud compute ssh 和 kubectl 分開之後 就不能操作了,所以我將其動作和並就可以操作,可喜可賀可喜可賀
每一間公司的 CICD 都有其適合的地方,也許這種方式其實蠻不適合傳統維運人員 ,這種方式主要是以 Git Branch 去觸發 Deploy,以現階段來說這個方式蠻適合我的。