Introduction
ကျွန်တော်ဒီနေ့ရေးမှာကတော့ gke cluster တစ်ခုပေါ်ကို cloud build နဲ့ continuous deployment လုပ်တဲ့အကြောင်းပဲဖြစ်ပါတယ်။ ဒီ topic ကကျွန်တော်မနေ့ကမှဖတ်ထားတာဖြစ်ပါတယ်။ နားလည်သလောက်လေးပြန်ရေးလိုက်တာပါ။ cloud build ဆိုတာ google cloud ရဲ့ ci cd tool တစ်ခုဖြစ်ပါတယ်။ cloud build မှာ trigger တွေ create ပြီး ci cd pipeline တွေလုပ်ကြပါတယ်။ ဒီနေ့ lab ရဲ့ သဘောတရားကတော့ github က repo ကို cloud build မှာ trigger ပေးထားမှာဖြစ်ပါတယ်။ main branch နဲ့ တစ်ခြား branch တွေက commit တစ်ခုလာတိုင်း trigger event က continuous deployments steps တွေရေးထားတဲ့ file ကိုသွားအလုပ်လုပ်မှာဖြစ်ပါတယ်။ main branch က လာရင် docker image ကို latest tag ပေးပြီး gke ပေါ်မှာ deployment တစ်ခုအဖြစ်သွား run မယ်။ တစ်ခြား branch ကလာရင် docker image ကို branch name ပေးမယ်။ ပြီးရင် gke ပေါ်ကို deployment တစ်ခု run မယ်။ ဒီလောက်ပါပဲ lab ရဲ့သဘောတရားကတော့။ ဒါဆိုအခုပဲ lab ကို စလိုက်ကြရအောင်နော်။
Create a GKE cluster
ပထမဆုံးအနေနဲ့ gke cluster တစ်ခုကို create ပေးရပါမယ်။ cloud shell ထဲကို သွားလိုက်ပါ။ cloud shell ထဲကို ရောက်ပြီဆိုလျှင် ကျွန်တော်တို့ လိုအပ်တာတွေစလုပ်လို့ရပါပြီ။ ပထမဆုံး gcloud auth login အရင်လုပ်ပေးရပါမယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317905)$ gcloud auth login
Go to the following link in your browser:
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=wFQ4YUqdUgZxfvYdALW8wSi9GK0Url&prompt=consent&access_type=offline&code_challenge=MThbWkkc2LCeQ9lq4ymjlpbYb03-PPPWCKLXRPpfUjA&code_challenge_method
Enter verification code: <your_code>
You are now logged in as [thaunghtikeoo.tho1234@gmail.com].
Your current project is [clever-circlet-317904]. You can change this setting by running:
$ gcloud config set project PROJECT_ID
login ပြီးတဲ့အခါ လိုအပ်တဲ့ variables တွေသတ်မှတ်ပေးရပါမယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ export PROJECT=$(gcloud info --format='value(config.project)')
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ export ZONE=us-central1-b
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ export CLUSTER=gke-deploy-cluster
ပြီးသွားရင်တော့ gcloud config ထဲမှာ values တွေထည့်ပေးရပါမယ်။ gke cluster အတွက်သုံးမယ့် cluter name ၊ zone ၊ project_id စသည့် values တွေကိုအောက်ကလိုသတ်မှတ်ပေးရပါမယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ gcloud config set project $PROJECT
Updated property [core/project].
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ gcloud config set compute/zone $ZONE
Updated property [compute/zone].
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ gcloud config set container/cluster $CLUSTER
Updated property [container/cluster].
ပြီးသွားရင်တော့ console ကနေ အောက်ပါ services တွေအတွက် api တွေကို access ရဖို့လုပ်ပေးရပါမယ်။
gcloud services enable container.googleapis.com \
containerregistry.googleapis.com \
cloudbuild.googleapis.com \
sourcerepo.googleapis.com
အပေါ်က steps တွေအကုန်ပြီးရင်တော့ gke cluster တစ်ခုကို create ပါမယ်။ အပေါ်မှာ သတ်မှတ်ခဲ့တဲ့ variables တွေကိုပြန်သုံးထားပါတယ်။
gcloud container clusters create ${CLUSTER} \
--project=${PROJECT} \
--zone=${ZONE} \
--scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"
ပြီးသွားရင်တော့ cluster ကို access လုပ်ဖို့ credentials ကိုယူရပါမယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ gcloud container clusters get-credentials $CLUSTER --zone $ZONE
Fetching cluster endpoint and auth data.
kubeconfig entry generated for gke-deploy-cluster.
kubeconfig file ရပြီဆိုတော့ cluster ထဲကို access ရပါပြီ။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-gke-deploy-cluster-default-pool-3b77fbf9-530t Ready <none> 5m59s v1.19.9-gke.1900
gke-gke-deploy-cluster-default-pool-3b77fbf9-cqv4 Ready <none> 6m v1.19.9-gke.1900
gke-gke-deploy-cluster-default-pool-3b77fbf9-wb40 Ready <none> 6m v1.19.9-gke.1900
Sample Web App
lab မှာသုံးမယ့် app ကတော့ docker curriculum က cat app လေးပဲဖြစ်ပါတယ်။ app ကအောက်ကပုံထဲကလိုဖြစ်ပြီး အပေါ်မှာ branch name ကိုတွေ့ရမှာဖြစ်ပါတယ်။

ပြီးရင် cluster ကို cloud build နဲ့ access ရဖို့ အောက်ကလို rolebinding တွေလုပ်ပေးရပါမယ်။ cluster က cloud build က deployment တွေကို RUN နိုင်ဖို့ပါ။
export PROJECT_NUMBER="$(gcloud projects describe \
$(gcloud config get-value core/project -q) --format='get(projectNumber)')"
gcloud projects add-iam-policy-binding ${PROJECT} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/container.developer
Setup Build Triggers
ဒီအဆင့်မှာတော့ cicd အတွက် trigger တွေလုပ်ပေးရမှာဖြစ်ပါတယ်။ main branch အတွက် trigger တစ်ကြောင်းကို အောက်ကအတိုင်း တစ်ဆင့်ချင်း create ပါမယ်။ အရင်ဆုံး console ထဲက cloud build ထဲကိုသွားပါ။ ပြီးရင် trigger အတွက်လိုအပ်တာတွေလုပ်ပေးရပါမယ်။ name ကိုတော့ cat-main-branch လို့ပေးလိုက်ပြီး event မှာ push to a branch ကို ရွေးလိုက်ပါတယ်။ main branch ကို commit ဖြစ်တိုင်း trigger ကအလုပ်လုပ်မှာဖြစ်ပါတယ်။ source မှာတော့ github ကကျွန်တော့်ရဲ့ rep ကိုချိတ်ပေးလိုက်ပါတယ်။

configuration မှာ trigger အလုပ်လုပ်မယ့် file path ကိုထည့်ပေးပါ။ ကျွန်တော် ကတော့ git repo ထဲက /builder/cloudbuild-canary.yaml ထဲမှာ deployment configuration တွေကိုထည့်ထားလို့ အဲ့ဒီ path ကိုထည့်ပေးလိုက်တာပါ။ variables တွေက cloudbuild-canary.yaml ထဲမှာသုံးမယ့် var တွေပါ။ gke cluster name နဲ့ zone ကိုထည့်ထားပေးတာပါ။ ပြီးရင် create ကိုနှိပ်လိုက်ပါ။

ကျွန်တော့်ရဲ့ configuration ကတော့ အောက်ကအတိုင်း cat:latest docker image တစ်ခု gcr ထဲကို build မယ်။ gke cluster credentials တွေကို ယူမယ်။ gke ပေါ်ကို deploy လုပ်မယ်။ ဒါပါပဲ
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
steps:
### Build
- id: 'build'
name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args:
- '-c'
- |
docker build -t gcr.io/$PROJECT_ID/cat:latest .
### Test
### Publish
- id: 'publish'
name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args:
- '-c'
- |
docker push gcr.io/$PROJECT_ID/cat:latest
### Deploy
- id: 'deploy'
name: 'gcr.io/cloud-builders/gcloud'
env:
- 'CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}'
- 'CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}'
- 'KUBECONFIG=/kube/config'
entrypoint: 'bash'
args:
- '-c'
- |
CLUSTER=$$(gcloud config get-value container/cluster)
PROJECT=$$(gcloud config get-value core/project)
ZONE=$$(gcloud config get-value compute/zone)
gcloud container clusters get-credentials "$${CLUSTER}" \
--project "$${PROJECT}" \
--zone "$${ZONE}"
kubectl apply -f kubernetes/deploy.yaml
kubectl apply -f kubernetes/svc.yaml
Run Trigger
ပြီးသွားရင်တော့ trigger ကို run လို့ရပါပြီ။ ဒါပေမယ့် trigger ကဒီအတိုင်းဆိုအလုပ်လုပ်မှာမဟုတ်သေးပါဘူး။ commit တစ်ခုလာမှ လုပ်မှာဆိုတော့ initial commit တစ်ခုကိုတော့ လုပ်ပေးရပါမယ်။ git repo ထဲသွားပြီး file တစ်ခုခုကို commit လုပ်ပေးလိုက်ပါ။

ခဏကြာတော့ build history ထဲက ထိပ်ဆုံးမှာ build တစ်ခုကိုတွေ့ရမှာဖြစ်ပါတယ်။

build တာပြီးသွားတဲ့အခါ build log တွေကိုကြည့်ဖို့ build ကို click ပြီး logs တွေကိုကြည့်နိုင်ပါပြီ။

Deployments On Gke
build success ဖြစ်တဲ့အခါ gke ပေါ်မှာ git repo ထဲက kubernetes directory ထဲမှာသတ်မှတ်ခဲ့တဲ့အတိုင်း cat deployment နဲ့ service တစ်ခုကိုတွေ့ရမှာဖြစ်ပါတယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ kubectl get all -n cat
NAME READY STATUS RESTARTS AGE
pod/cat-master-69d7bc46cf-zkbqv 1/1 Running 0 17m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cat LoadBalancer 10.3.252.79 35.224.48.100 80:32637/TCP 17m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/cat-master 1/1 1 1 17m
NAME DESIRED CURRENT READY AGE
replicaset.apps/cat-master-69d7bc46cf 1 1 1 17m
cat service က LoadBalancer IP ကိုခေါ်ကြည့်ရင် sample app ထဲကအတိုင်းပဲတွေ့ရမှာဖြစ်တယ်။

Other Branches
main branch အကြောင်းပြီးပြီဆိုတော့ တစ်ခြား branch တွေအတွက်လည်း စမ်းကြည့်ပါဦးမယ်။ အခုလက်ရှိမှာတော့ dev branch တစ်ခုပဲရှိပါသေးတယ်။ demo အတွက်က တစ်ခုဆိုလုံလောက်တာမို့ dev နဲ့ပဲစမ်းလိုက်ပါမယ်။ အရင်ဆုံး main branch trigger တုန်းကလို trigger တစ်ခု create ပါမယ်။ name ကိုတော့ cat-other-branch လို့ပေးလိုက်မယ်။ repo က cat github repo ၊ branch မှာ main ကလွဲပြီး ကျန်တဲ့ branch အကုန်ဆိုတော့ invert regex ကိုရွေးခဲ့တယ်။ အခုတော့ dev တစ်ခုပဲရှိတာကိုတွေ့ရပါလိမ့်မယ်။

configuration မှာ file ကိုထည့်ပါ။ file ထဲမှာသုံးမယ့် လိုအပ်တဲ့ variable တွေကို သတ်မှတ်ပေးပါ။ ပြီးရင် create ကိုနှိပ်ပေးပါ။

ကျွန်တော့်ရဲ့ cloud build deployment configuration ကတော့ အောက်ကအတိုင်းပဲဖြစ်တယ်။ docker image ကို cat ၊ tag ကို branch name ပေးမယ်။ ပြီးရင် gcr ထဲကို push မယ်။ gke cluster access ယူမယ်။ kubernetes deployment ထဲက image ကို tag latest အစား create ခဲ့တဲ့ branch name နဲ့အစားထိုးမယ်။ kubernetes deployment တွေလုပ်မယ်။ ဒီလောက်ပါပဲ။
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
steps:
### Build
- id: 'build'
name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args:
- '-c'
- |
docker build -t gcr.io/$PROJECT_ID/cat:${BRANCH_NAME} .
### Test
### Publish
- id: 'publish'
name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args:
- '-c'
- |
docker push gcr.io/$PROJECT_ID/cat:${BRANCH_NAME}
### Deploy
- id: 'deploy'
name: 'gcr.io/cloud-builders/gcloud'
env:
- 'CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}'
- 'CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}'
- 'KUBECONFIG=/kube/config'
entrypoint: 'bash'
args:
- '-c'
- |
CLUSTER=$$(gcloud config get-value container/cluster)
PROJECT=$$(gcloud config get-value core/project)
ZONE=$$(gcloud config get-value compute/zone)
gcloud container clusters get-credentials "$${CLUSTER}" \
--project "$${PROJECT}" \
--zone "$${ZONE}"
sed -i 's|gcr.io/$PROJECT_ID/cat:latest|gcr.io/$PROJECT_ID/cat:${BRANCH_NAME}|' ./kubernetes/deploy.yaml
sed -i 's|cat-master|cat-${BRANCH_NAME}|' ./kubernetes/deploy.yaml
sed -i 's|cat-branch|cat-${BRANCH_NAME}|' ./kubernetes/svc.yaml
kubectl apply -f kubernetes/deploy.yaml
kubectl apply -f kubernetes/svc.yaml
အခု trigger ကို run ပါမယ်။ initial commit တစ်ခုလိုတဲ့အတွက် dev branch ကို commit တစ်ခုလုပ်ပေးလိုက်ပါ။ ခဏကြာတော့ build တစ်ခုကို ထိပ်ဆုံးမှာတွေ့ရမှာပါ။

build တာပြီးသွားတဲ့အခါ logs ထဲကို ဝင်ကြည့်ရင် gke ပေါ်ကို deploy ခဲ့တာကိုတွေ့ရမှာပါ။

container registry ထဲက cat repo ထဲမှာလည်း dev နဲ့ latest ဆိုပြီး tag တွေကိုတွေ့နိုင်ပါတယ်။

gke မှာလည်း cat-dev ဆိုပြီး deployment နဲ့ service တစ်ခုကိုတွေ့ရမှာဖြစ်ပါတယ်။
thaunghtikeoo_tho1234@cloudshell:~ (clever-circlet-317904)$ kubectl get all -n cat
NAME READY STATUS RESTARTS AGE
pod/cat-dev-d69c88fc7-7lbsn 1/1 Running 0 11m
pod/cat-master-69d7bc46cf-zkbqv 1/1 Running 0 59m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cat LoadBalancer 10.3.252.79 35.224.48.100 80:32637/TCP 59m
service/cat-dev LoadBalancer 10.3.251.179 35.202.92.182 80:31828/TCP 33s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/cat-dev 1/1 1 1 11m
deployment.apps/cat-master 1/1 1 1 59m
NAME DESIRED CURRENT READY AGE
replicaset.apps/cat-dev-d69c88fc7 1 1 1 11m
replicaset.apps/cat-master-69d7bc46cf 1 1 1 59m
cat-dev service ရဲ့ loadbalancer ip ကိုခေါ်ကြည့်ရင်လည်း အောက်ကလိုတွေ့ရမှာဖြစ်ပါတယ်။

Conclusion
demo ကနည်းနည်းရှည်သွားတော့ မျက်လုံးနဲ့ကြည့်ရင်တော့နည်းနည်းခက်နိုင်ပါတယ်။ gcp account ရှိရင်တော့လိုက်စမ်းကြည့်လို့ရပါတယ်။ ကျွန်တော်နားလည်တာကို ပြန်လည်ရှင်းပြတာပဲဖြစ်ပါတယ်။ အမှားတွေပါရင်လည်း နားလည်ပေးကြပါခင်ဗျာ။ ဆက်လက်ကြိုးစားပါဦးမယ်။ အားလုံးကိုကျေးဇူးတင်ပါတယ်။
Thanks for reading …