มาลอง Setup Gitops ด้วย ArgoCD + Kustomize กันเถอะ Part 2
สวัสดีครับเนื้อหาของบทความนี้จะพูดถึงการ setup gitops ด้วย Argo CD ในรูปแบบของ App of Apps Pattern ตามที่เคยพูดถึงในบทความที่แล้วบทความที่แล้ว
ถ้าใครยังไม่ได้อ่านแนะนำให้ไปลองอ่านดูก่อนนะ
ขอให้ทุกคน install Argo CD ตามที่เขียนไว้ใน Official Docs ให้เรียบร้อยด้วยนะค้าบ
หลังจากที่เกริ่นไปซะยาวในบทความที่แล้วเรามาเริ่มสร้าง Application ใน Argo กันเลยย
Example Applications
ในบทความนี้จะยกตัวอย่างเป็น Service ที่เป็น Opensource จากสมาชิกของชมรม Thinc. และทำการ Self Host อยู่ใน Server ของคณะ
Application ที่จะ Deploy จะประกอบไปด้วย
- Chula SSO Mock
- Paradis Bot
- PostgreSQL Database
- Redis Database
มาเริ่มสร้าง Application ใน Argo CD กันเลย
เริ่มจากสร้าง Repository ใน Git ของคุณ (ในบทความนี้ผมจะใช้ Github เป็นหลัก)
เมื่อสร้าง repository เสร็จแล้วต่อมาเราต้องมี Argo Application หลักเพื่อที่จะชี้ไปที่ templates folder ในรูปแบบของ App of Apps Pattern ตามที่เคยพูดถึงในบทความที่แล้ว (ใครที่ยังไม่ได้อ่านลองไปอ่านดูก่อนนะ ;-;)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: gitops-example-apps
namespace: argocd
spec:
destination:
namespace: gitops-example
server: https://kubernetes.default.svc
project: gitops-example
source:
helm:
valueFiles:
- values.yaml
path: apps
repoURL: git@github.com:thinc-org/gitops-example.git
targetRevision: HEAD
syncPolicy: {}
จากใน Code จะเห็นว่า Application manifest จะประกอบไปด้วยส่วนหลักคือ
Destination
คือสถานที่ๆจะ deploy resource ต่างๆของ Application หลัก (ในที่นี้คือ Application อื่นๆที่อยู่ใน folder templates)
- namespace คือ namespace ที่จะ deploy resource ไปใส่ (ไม่จำเป็นต้องเป็น namespace เดียวกันกับ Application หลักก็ได้) เช่นในตัวอย่างเรา deploy
gitops-example-apps
ไว้ที่ namespaceargocd
แต่เรา deploy Application เหลือที่ namespacegitops-example
- server คือ server ที่จะ deploy resource ไปใส่
Source
คือ directory ที่ Argo CD จะทำการอ่าน manifest เพื่อมา deploy ต่อไป
- path คือ path ของ directory ที่จะให้ Argo CD ทำการอ่าน manifest ซึ่งเราชี้ ไปที่ folder ชื่อ
apps
เพราะฉะนั้น manifest ต่างๆของ template application ก็จะต้องอยู่ใน folder นี้
จากการที่ path ชี้ไปที่ folder apps ทำให้ project structure จะหน้าตาประมาณนี้ (เดี๋ยวจะมีการพูดถึงอย่างละเอียดในส่วนถัดไป)
gitops-repository
|
|-- apps
| |
| |-- templates <-- manifest ของ template application จะอยู่ในนี้
|
|-- argo
|-- app.yaml
- repoUrl คือ URL ของ repository ที่เก็บ manifest ต่างๆเอาไว้เพื่อให้ Argo CD fetch (repository ที่เพิ่งสร้างใหม่)
- helm คือ setting ของ Helm Chart ในที่นี้คือ set ให้ Argo CD อ่านไฟล์ values จาก
apps/values.yaml
(เดี๋ยวจะมีการยกตัวอย่าง Helm Chart อย่างละเอียดในภายหลัง)
หลังจากที่ทำความเข้าใจ code ไปแล้วให้สร้าง folder ชื่อ argo ใน folder project ของเราและสร้างไฟล์ใหม่ชื่อ apps.yaml
+ copy code มาใส่แบบในรูปข้างล่าง
ในตอนนี้เราก็จะมี manifest ของ Application สำหรับชี้ไปที่ template file แล้ว
แต่เดี๋ยวก่อน! ถ้าลองสังเกตุใน manifest ดูจะเห็นว่าเรายังไม่มี project และ repository config สำหรับเก็บ credential เพื่อ fetch update จาก repository เลย เพราะฉะนั้นเราต้องสร้าง manifest สำหรับ resource ที่ยังขาดอยู่
Project manifest
ให้สร้างไฟล์ใหม่ใน folder argo ชื่อ projects.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: gitops-example
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
description: An example applications of gitops by samithiwat
sourceRepos:
- "*"
destinations:
- namespace: "*"
server: "*"
clusterResourceWhitelist:
- group: "*"
kind: "*"
จากใน Code จะเห็นว่า AppProject manifest จะเป็นการ setup access control สำหรับ project ที่เรากำลังจะสร้างขึ้นมาใหม่
ในส่วนของเรื่อง access control ใน Argo CD รวมไปถึง access control ของ project ขอติดไว้ไปพูดถึงในภายหลังนะครับ
สามารถอ่านเพิ่มเติมเรื่อง Project Setup ได้จาก Official Docs
ในตอนนี้ folder argo จะมีไฟล์ทั้งหมด 2 ไฟล์ด้วยกันคือ apps.yaml
และ projects.yaml
Repository Configuration
ก่อนอื่นให้ทุกคนสร้าง ssh key เพื่อนำมาเป็น deploy key ก่อนด้วยคำสั่ง
Window 10 or later
ssh-keygen -t rsa -f C:\Users\WINDOWS_USER\.ssh\KEY_FILENAME -b 2048
MacOS
ssh-keygen -t rsa -f ~/.ssh/KEY_FILENAME -b 2048
จากนั้นให้ copy public key
จากไฟล์ที่เพิ่งสร้างขึ้นมา (.pub) ไปใส่ไว้ใน deploy key ที่ GitHub Repository
และสร้างไฟล์ใหม่ใน folder argo ชื่อ repo-config.yaml
apiVersion: v1
kind: Secret
metadata:
name: example-apps-repo-config
namespace: argocd
labels:
app.kubernetes.io/name: example-apps-repo-config
app.kubernetes.io/part-of: argocd
argocd.argoproj.io/secret-type: repository
stringData:
name: Gitops Example Repository
project: gitops-example
type: git
url: git@github.com:thinc-org/gitops-example.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
จากใน Code จะเห็นว่า Secret Repository จะมีส่วนสำคัญหลักๆคือ
labels
argocd.argoproj.io/secret-type: repository เอาไว้บอก Argo CD ว่าไฟล์นี้คือ config ของ repository
type
ชนิดของ repository เช่น git
หรือhelm
เป็นต้น
url
url ของ repository
sshPrivateKey
Private key ของ deploy key ที่เพิ่งสร้างมา
เมื่อเสร็จเรียบร้อยแล้วตอนนี้เราก็จะมีไฟล์ manifest ทั้งหมด 3 ไฟล์พร้อมที่จะใช้งาน
และ push ขึ้น git เพื่อให้ Argo CD สามารถ fetch ไป ที่ repository ได้ (ถ้า repository ยังไม่มีอะไรเลย Argo CD จะ error ตอน fetch)
หลังจากที่เรียบร้อนแล้วให้ apply manifest ทั้งหมดด้วยคำสั่ง kubectl apply -f ./argo
NOTE
สำหรับคนที่เปิด repository เป็นแบบ public ให้ไปกด approve deploy key ด้วยไม่งั่นมันจะ error (จริงๆ repository ที่ทำเป็น gitops ไม่ควรเปิด public เพราะในนี้มี secret ค่อนข้างเยอะ)
สร้าง Template Folder
หลังจากที่ apply manifest ไปเรียบร้อยแล้วและเข้าไปดูใน Application ที่ถูกสร้างขึ้นจะเจอ error ว่า rpc error: code = Unknown desc = apps: app path does not exist
ซึ่งก็ไม่ใช่เรื่องแปลกอะไรเพราะในตอนนี้ Git Repository ของเรามีแค่ folder argo แต่ยังไม่มี templates folder เลย
เพราะฉะนั้น Step ถัดไปสิ่งที่เราจะต้องทำก็คือการสร้าง templates folder สำหรับ example apps ของเรา
เริ่มด้วยการสร้าง folder ใหม่ใน root directory ชื่อ apps
และสร้าง folder ข้างในชื่อ templates
(อย่าลืม s
นะ)
ต่อมาสร้างไฟล์ชื่อ Chart.yaml
และ copy ไปใส่ได้เลย
apiVersion: v2
name: applications
description: Applications
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: "1.0"
และสร้างอีกไฟล์นึงใน apps
ชื่อไฟล์ values.yaml
spec:
destination:
server: https://kubernetes.default.svc
source:
repoURL: git@github.com:thinc-org/gitops-example.git
targetRevision: HEAD
repoUrl
คือ url ของ repository อันเดียวกันกับที่ setup ไว้ใน repo-config.yaml
เมื่อเสร็จเรียบร้อยแล้วจะได้หน้าตาประมาณนี้
และก็มาถึงพระเองของ Part นี้คือ template files นั่นเองง
ใน templates folder ให้สร้างไฟล์ใหม่ชื่อเป็น <application name>.yaml
เช่น ถ้าจำทำ manifest ของ chula-sso-mock
ก็ให้ตั้งชื่อเป็น chula-sso-mock.yaml
และนำ content เหล่านี้ไปใส่ในไฟล์
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: chula-sso-mock
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: gitops-example
server: {{ .Values.spec.destination.server }}
project: gitops-example
source:
path: chula-sso-mock
repoURL: {{ .Values.spec.source.repoURL }}
targetRevision: {{ .Values.spec.source.targetRevision }}
syncPolicy:
automated: {}
จาก Application manifest จะเห็นว่า pattern จะคล้ายๆกับ Argo Application manifest ที่เราเพิ่งทำไปก่อนหน้านี้
ค่า server
, repoUrl
และ targetRevision
จะดึงเอามาจาก values.yaml
ที่เราเพิ่ง setup ไว้ก่อนหน้านี้
Destination
- namespace คือ namespace ที่จะ deploy k8s resource ไปใส่ในที่นี้คือ
gitops-example
Source
- Path คือ path ใน repository ที่เก็บค่า configuration ของ Application เอาไว้ในที่นี้คือ folder ชื่อ
chula-sso-mock
SyncPolicy
- automated ตั้งค่าให้ sync automate
NOTE
สำหรับคนที่ใช้ extension prettier
แล้วมัน auto format ทำให้วงเล็บปีกกาของ Helm Chart Values พังอย่าลืมไป add templates folder ใส่ .prettierignore
ด้วยนะ
// .prettierignore
apps/templates/*
เมื่อเสร็จเรียบร้อยแล้วจะได้หน้าตาแบบนี้
แต่เดี๋ยวก่อน!!! (อีกละ) ถ้าสังเกตุดีๆเรายังไม่มี namespace ชื่อ gitops-example
เลยนะะ
เพราะฉะนั้นเราต้องสร้าง namespace ด้วย
สร้างไฟล์ใน templates folder ชื่อ namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: gitops-example
annotations:
argocd.argoproj.io/sync-wave: "-1"
เมื่อเสร็จแล้วจะได้หน้าตาแบบนี้
และ push ขึ้น git ได้เลยยย
เมื่อเราเข้าไปเช็คใน Argo Application เราจะเจอว่ามี resource งอกขึ้นมา 2 ส่วนคือ namespace
และ chula-sso-mock
ที่เราเพิ่ง commit ขึ้น git นั่นเอง
ให้ทำการกด sync
ที่ namespace gitops-example
และ chula-sso-mock
ตามลำดับ
และถ้ากดเข้าไปดูที่ chula-sso-mock จะเจอ error ว่า rpc error: code = Unknown desc = Manifest generation error (cached): chula-sso-mock: app path does not exist
เพราะเรายังไม่ได้สร้าง folder chula-sso-mock เอาไว้เก็บ k8s resource นั่นเอง
Application Folder
หลังจากที่ Sync Application เรียบร้อยแล้วก็มาถึงเวลาที่เราจะ setup directory สำหรับเก็บ manifest ของ k8s resource ที่เราต้องการ
ในตอนนี้ Argo CD มันยังขึ้น error เพราะว่าหา folder ชื่อ chula-sso-mock
ไม่เจอเพราะฉะนั้นถึงเวลาที่เราจะสร้างมันขึ้นมาแล้ว
ให้สร้าง folder ชื่อ chula-sso-mock
ขึ้นมาที่ root directory ของเรา
จากนั้นสร้างไฟล์ deployment.yaml
service.yaml
และ config-map.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: chula-sso-mock
spec:
replicas: 1
selector:
matchLabels:
app: chula-sso-mock
template:
metadata:
labels:
app: chula-sso-mock
spec:
volumes:
- name: chula-sso-mock-config
configMap:
name: chula-sso-mock-config
containers:
- name: chula-sso-mock
image: pay2630/chulassomock
imagePullPolicy: Always
envFrom:
- configMapRef:
name: chula-sso-mock-config
ports:
- name: chula-sso-mock
containerPort: 8080
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
resources:
requests:
cpu: 20m
memory: 100Mi
limits:
cpu: 80m
memory: 200Mi
apiVersion: v1
kind: Service
metadata:
name: chula-sso-mock
spec:
selector:
app: chula-sso-mock
ports:
- port: 8080
targetPort: chula-sso-mock
apiVersion: v1
kind: ConfigMap
metadata:
name: chula-sso-mock-config
data:
PORT: "8080"
APPID: APPID
APPSECRET: APPSECRET
จากใน README.md
ของ Chula SSO Mock ให้เรา setup โดยการใส่ env ทั้งหมด 3 อย่างคือ
APPID
DeeAppId ของ Chula SSO
APPSECRET
DeeAppSecret ของ Chula SSO
PORT
port ของ Application
เมื่อเสร็จแล้วจะได้หน้าตาประมาณนี้
จากนั้นให้ push ขึ้น git ได้เลยย
จากนั้นให้ไปกด refresh ที่ chula-sso-mock
Application
ถ้าไม่มีอะไรผิดพลาดจะเป็นไปตามรูป Application Synced ถือว่า setup เรียบร้อย
Example Code
สามารถดูตัวอย่าง code ใน repository ได้ใน GitHub
ตอนต่อไป!
หลังจากที่เรา Setup Application เสร็จเรียบร้อยแล้วแต่ว่าตอนนี้ยังขาดการแยก Configuration ของ Application ตามแต่ละ Environment อยู่ใน Part ต่อไปเราจะมาใช้ Kustomize มาช่วยในการแยก Environment ใน Gitops กัน