มาลองทำ GitOps ด้วย ArgoCD
เนื่องจากว่าช่วงนี้ผมกำลังหา tools ใหม่ๆ สำหรับการทำโปรเจคจบ ซึ่งผมได้ออกแบบไว้ว่าจะใช้ Kubernetes ในการรัน applications โดยสำหรับ Kubernetes แล้ว เรามี "ท่า" มากมายในการทำ CI/CD โดยไม่ว่าจะเป็น kubectl apply
ตรงๆ หรือว่าการใช้ Kustomize ซึ่งในงานที่ผ่าน ๆ มา ผมได้เลือกใช้ GitHub Actions ในการรัน kubectl apply
เป็นส่วนใหญ่ ครั้งนี้จึงอยากที่จะลองวิธีใหม่ ๆ บ้าง จนได้มาเจอกับ GitOps
GitOps
GitOps คือการสร้างระบบ Continuous Delivery (CD) ด้วย tools ที่เราใช้กันเป็นอยู่แล้ว ซึ่งก็คือ Git นั้นเอง โดยเราจะทำการเก็บสิ่งต่าง ๆ ที่ใช้ในการสร้าง infrastructure ให้ application ของเรา ให้อยู่ใน Git repository และเมื่อข้อมูลในนั้นมีการเปลี่ยนแปลง (มี commit ใหม่) ระบบก็จะจัดการสร้างสิ่งต่าง ๆ ที่เราทำการระบุไว้ใน Git ให้โดยอัตโนมัติ
โดยข้อดีของ GitOps ที่ผมชอบมากๆ ก็คือการที่เราใช้ Git นั้นเป็น single source of truth สิ่งที่มันอยู่ใน Git ก็จะตรงกับสิ่งที่เราใช้งานอยู่เสมอ การแก้ไขทุกอย่างจะต้องทำผ่าน Git ทำให้เราไม่มี configuration ที่ผิดเพี้ยนไปจากที่เราเขียนไว้ และเมื่อเราใช้ Git เราก็จะได้ประโยชน์จากการทำงานของ Git ด้วยอย่างเช่น การ revert commit ที่ทำได้ง่ายดายและการจัดการประวัติการแก้ไขทั้งหมด
ถ้าหากใครสนใจเรื่อง GitOps สามารถอ่านบทความของคุณ Somkiat ได้ที่ GitOps คืออะไร
Argo CD
ซึ่ง tools ที่ผมสนใจและเลือกมาทดลองใช้ก็คือ Argo CD โดยตัวของ Argo CD ทำงานในรูปแบบ pull deployment ซึ่ง Argo CD ที่เราติดตั้งลงไปใน Kubernetes Cluster ของเรา จะเฝ้าดู Git Repository และทำให้ states ใน Cluster ของเราตรงกับที่ config ที่อยู่ใน Git และเมื่อมี commit ใหม่ใน Git repository มันก็จะทำการจัดการ สร้าง ลบ อัพเดท resources ต่างๆ ใน cluster ของเรา ให้ตรงกับใน Git นั้นเอง
Setup Argo CD
ก่อนที่เราจะเริ่มใช้งาน Argo CD เรามีสองอย่างที่เราต้องมีก็คือ
1) ติดตั้ง Argo CD ใน Kubernetes Cluster
เราสามารถติดตั้ง Argo CD ได้ผ่านคำสั่ง
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
ซึ่งคำสั่งนี้เป็นการติดตั้งแบบ Non-High Availability ซึ่งไม่แนะนำสำหรับการใช้ใน production การติดตั้งรูปแบบอื่นสามารถดูได้จาก Installation Manual ของ Argo CD
2) Git repository ที่เก็บ Kubernetes manifest ไว้
สำหรับ Git repository ก็ต้องอยู่ในที่ ที่ Argo CD จะสามารถเข้าถึงได้ ไม่ว่าจะเป็น GitHub หรือที่อื่นๆ โดยถ้าหากเป็น private repository เราก็จะต้องเพิ่ม credential ให้ Argo CD เข้าถึงได้ด้วย แต่ผมจะขอใช้เป็น public repository เพื่อความง่ายในการ demo
ซึ่งสิ่งที่ผมจะเอามา demo ก็เป็น Todo app ง่าย ๆ ที่เคยทำไว้ตอนไปพูดเรื่อง Basic of Kubernetes with Google Kubernetes Engine สามารถเข้าไปดู Code ได้ที่ repo นี้เลย
การที่เราจะให้ Argo CD จัดการสร้าง Kubernetes resources ขึ้นมา เราจะต้องสร้างสิ่งที่เรียกว่า Application
ขึ้นมา ในเว็บไซต์เขาให้คำจำกัดความไว้ว่า มันคือ
A group of Kubernetes resources as defined by a manifest
แปลเป็นไทยก็คือ Kubernetes resources จำนวนหนึ่งหรือมากกว่า ที่ถูกเขียนไว้ใน config/manifest file อย่างเช่น YAML หรือ Helm Chart
ดังนั้นเราจะสร้าง application ขึ้นมา 2 ตัวก็คือ nginx-ingress
ที่เราจะเอามาจาก Helm Chart และ todo-app
ที่จะสร้างจาก Kubernetes manifest (YAML) ซึ่งประกอบไปด้วย backend, frontend, และ database รวมไปถึง PVC และ service ต่าง ๆ ด้วย
Access Argo CD UI Interface
Argo CD มีช่องทางให้เราเข้าไปจัดการการทำงานของตัวมันได้อยู่หลายวิธี ไม่ว่าจะเป็น CLI, Web UI หรือ delarative file โดยเพื่อความง่ายในการจัดการเราสามารถเข้าถึง Web UI ได้โดยการเข้าถึง service argocd-server
ที่ port 443 ซึ่งผมจะใช้วิธีการ forward port เพื่อเข้าถึง service นี้ผ่านคำสั่ง
kubectl port-forward svc/argocd-server -n argocd 8080:443
ทีนี้ถ้าเราเข้าไปที่ http://localhost:8080
เราก็จะเจอกับหน้า login ของ Argo CD ที่ทำงานอยู่ใน cluster ของเราแล้ว โดยมี username เป็น admin
และ password สามารถดูได้จากการรันคำสั่ง kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}"| base64 -d;echo
พอเข้ามาในหน้า UI แล้วเราก็จะเจอกับ dashboard ที่บอกเราว่าเรายังไม่มี application อะไรอยู่เลย ดังนั้นเราจะเพิ่ม application เข้าไปให้ Argo CD นำไปสร้าง resources ใน Kubernetes cluster ของเรากัน
Deploy Application with Helm Chart
สำหรับตัว nginx-ingress เราจะใช้ Helm Chart ในการ deploy ดังนั้น เราก็สามารถกดเลือก Create Application โดยสิ่งที่เราต้องใส่ก็จะมีตามนี้
General
- Application Name: ชื่อเรียกของ Application ของเราใน Argo CD
- Project Name: ชื่อ project ใน Argo CD โดยปกติแล้วจะมีอยู่อันเดียวคือ
default
ซึ่งเราสามารถสร้างเพิ่มได้ - Sync Policy: คือการตั้งค่าว่าเราต้องการจะให้ Argo CD สร้าง ปรับเปลี่ยน เพิ่มลด Kubernetes resource โดยอัตโนมัติเลยรึเปล่า ซึ่งในกรณีนี้เราต้องการ ดังนั้นให้เลือกเป็น
Automatic
ถ้าหากเราเลือกเป็นแบบManual
เราก็จะต้องมากด Sync ให้มันทำงานเอง - Prune Resources: กำหนดว่าถ้าเราลบ manifest นั้นออกจาก Git ไป ให้ Argo CD ลบ resource นั้นออกจาก cluster เราด้วยรึเปล่า ซึ่งให้เลือกตัวนี้ด้วย
- Self Heal: ใช้กำหนดว่าถ้าหากมีใครแก้ไขอะไรที่ทำให้ states ของ Cluster ไม่ตรงกับ Git จะให้ Argo CD บังคับให้กลับเป็นเหมือนใน Git ซึ่งให้เลือกตัวนี้ด้วยเช่นกัน
Source
- Repository URL: คือ Repo URL ของ Chart หรือ Git นั้นๆ อย่างเช่น
https://kubernetes.github.io/ingress-nginx
- Chart: ชื่อของ Chart ที่เราต้องการ ซึ่งคือ
ingress-nginx
- Version: Version ของ Chart ที่เราต้องการจะใช้
4.1.4
ก็จะเป็น version ล่าสุดของ ingress-nginx
Destination
- Cluster URL: เลือก
https://kubernetes.default.svc
เนื่องจากเราต้องการสร้าง resource บน cluster ที่ Argo CD ทำงานอยู่ - Namespace: คือ namespace ที่เราต้องการสร้าง resources ลงไป
ถ้าเราลองกดมุมขวาบน ตรงคำว่า EDIT AS YAML
เราจะสามารถดูและแก้ไข configuration ของ Application ที่เรากำลังจะสร้างได้ ถ้าหากเราเซฟเก็บไว้ เราก็จะสามารถใช้คำสั่ง kubectl apply -n argocd -f <file-name>
กับไฟล์นี้ได้เลย และถ้าหากเรามี Argo CD ที่ทำงานอยู่ใน cluster แล้ว มันก็จะให้ผลเหมือนกับการสร้าง Application ผ่านหน้า Web UI นั้นเอง
โดยเมื่อเรากด Create เราจะเห็นว่า Status ของ Application เรานั้นเป็น OutOfSync
หมายความว่า Resource ใน manifest (ในที่นี้คือ Helm Chart) ไม่ตรงกับ Resource ที่อยู่ใน Cluster ของเรา และในเมื่อเราตั้ง Sync Policy เป็น Automatic
ไว้ Argo CD จะทำการ Sync หรือว่าทำยังไงก็ได้ให้ Resource ใน cluster ของเรา ตรงกับ manifest เมื่อเรารอไปสักพักจะเห็นว่า Status เปลี่ยนเป็น Synced
เมื่อมันทำการสร้าง resource เสร็จเรียบร้อย
K8S Manifest in Git
หลังจากเราได้ nginx-ingress มาแล้ว เราก็จะมา deploy todo application กัน โดยขั้นตอนก็จะเหมือนกับ nginx-ingress เลย ต่างกันแค่ตรงที่เราจะเลือก source ให้เป็น Git และใส่ Git repository URL ลงไปแทน โดยสำหรับการสร้าง Application ผมจะขอใช้เป็นแบบ declarative หรือว่าการเขียน config แล้วทำการ kubectl apply -f
แทนการใช้ Web UI ตัว Configuration ก็จะมีหน้าตาประมาณนี้
เราก็เพียงใช้คำสั่ง kubectl apply -f todo-app.yaml
เพียงเท่านี้ เราก็จะได้ Application ที่ Argo CD จะช่วยจัดการเรียบร้อยแล้ว
Explore the Web UI
Web UI ของ Argo CD เป็นสิ่งที่อำนวยความสะดวกให้เราสามารถสร้าง Application ได้อย่างง่ายดาย นอกจากนี้มันยังเป็น dashboard เพื่อบอกสถานะของ Application ของเราได้อย่างดีอีกด้วย
เมื่อเราคลิกเข้ามาดูใน Application ที่เราสร้างไว้ เราจะเห็นกราฟว่า Application ของเรา ประกอบไปด้วย resources อะไรบ้าง และสถานะของแต่ละอย่างเป็นอย่างไร ทำให้เราสามารถที่จะดูและ debug ปัญหาที่เกิดขึ้นได้อย่าง่ายดายมาก ๆ
เราสามารถที่จะกดเข้าไปดูใน resources แต่ละตัว อย่างเช่น Pod ที่ทำงานอยู่ เพื่อดู event และ logs ได้เช่นกัน
When Changes Occured
จากที่เราได้บอกไปแล้วว่า Argo CD คือสิ่งที่ทำงานกับ GitOps แล้วถ้าเราต้องการจะเปลี่ยน config ยกตัวอย่างเช่นเปลี่ยน image tag ของ deployment เราจะทำได้อย่างไร
ง่าย ๆ เลยครับ ก็คือแก้สิ่งที่เราจะแก้ แล้วก็ commit, push ขึ้น Git repository เท่านั้นเอง สมมติว่าผมอยากเปลี่ยน image tag ของ todo-backend ให้เป็น v2
ผมก็ทำการแก้ไข YAML ของ backend-depl เป็นดังนี้
แล้วจึงทำการ commit และ push ไป
Argo CD ก็จะพบว่ามี commit ใหม่ขึ้นมา และทำการดูไฟล์ manifest ว่ามีอะไรไม่ตรงกับ state ของ cluster ตอนนี้รึเปล่า และถ้ามีก็จะจัดการทำให้มันตรงกัน อย่างในกรณีนี้ก็คือการเปลี่ยน image ของ backend-depl ใน todo-app นั้นเอง
ซึ่งกระบวนการการเช็ค Git Repository จะมีการเช็คทุก ๆ 3 นาที ซึ่งเราสามารถที่จะปรับแต่งได้ตามใจเรา ส่วนถ้าหากใครต้องการเห็นผลเลย เราก็สามารถกดปุ่ม Refresh
เพื่อบังคับให้ Argo CD ทำการเช็ค Git Repository ได้เลย