มาลอง Setup Gitops ด้วย ArgoCD + Kustomize กันเถอะ Part 2

Samithiwat
Thinc.
Published in
8 min readDec 27, 2022
Argo CD & Kustomize

สวัสดีครับเนื้อหาของบทความนี้จะพูดถึงการ 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 จะประกอบไปด้วย

มาเริ่มสร้าง Application ใน Argo CD กันเลย

เริ่มจากสร้าง Repository ใน Git ของคุณ (ในบทความนี้ผมจะใช้ Github เป็นหลัก)

สร้าง repository ใน 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 ไว้ที่ namespace argocd แต่เรา deploy Application เหลือที่ namespace gitops-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 มาใส่แบบในรูปข้างล่าง

สร้างไฟล์ชื่อ 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

สร้างไฟล์ 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
สร้าง SSH Key

จากนั้นให้ 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 ไฟล์พร้อมที่จะใช้งาน

สร้างไฟล์ repo-config.yaml

และ push ขึ้น git เพื่อให้ Argo CD สามารถ fetch ไป ที่ repository ได้ (ถ้า repository ยังไม่มีอะไรเลย Argo CD จะ error ตอน fetch)

push ขึ้น git

หลังจากที่เรียบร้อนแล้วให้ apply manifest ทั้งหมดด้วยคำสั่ง kubectl apply -f ./argo

apply manifest
มี Application ถูกสร้างขึ้น

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 เลย

Argo CD หา folder ชื่อ apps ใน repository ไม่เจอ

เพราะฉะนั้น 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

เมื่อเสร็จเรียบร้อยแล้วจะได้หน้าตาประมาณนี้

สร้าง Chart.yaml และ values.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/*

เมื่อเสร็จเรียบร้อยแล้วจะได้หน้าตาแบบนี้

สร้างไฟล์ chula-sso-mock.yaml
สร้างไฟล์ .prettierignore

แต่เดี๋ยวก่อน!!! (อีกละ) ถ้าสังเกตุดีๆเรายังไม่มี namespace ชื่อ gitops-example เลยนะะ

เพราะฉะนั้นเราต้องสร้าง namespace ด้วย

สร้างไฟล์ใน templates folder ชื่อ namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
name: gitops-example
annotations:
argocd.argoproj.io/sync-wave: "-1"

เมื่อเสร็จแล้วจะได้หน้าตาแบบนี้

สร้างไฟล์ namespace.yaml

และ push ขึ้น git ได้เลยยย

push ขึ้น git

เมื่อเราเข้าไปเช็คใน Argo Application เราจะเจอว่ามี resource งอกขึ้นมา 2 ส่วนคือ namespace และ chula-sso-mock ที่เราเพิ่ง commit ขึ้น git นั่นเอง

Argo CD update application state

ให้ทำการกด sync ที่ namespace gitops-example และ chula-sso-mock ตามลำดับ

กด Sync Application
Sync เรียบร้อย
Application 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 นั่นเอง

Argo CD หา folder chula-sso-mock ไม่เจอ

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

กด refresh chula-sso-mock application

ถ้าไม่มีอะไรผิดพลาดจะเป็นไปตามรูป Application Synced ถือว่า setup เรียบร้อย

Application synced

Example Code

สามารถดูตัวอย่าง code ใน repository ได้ใน GitHub

ตอนต่อไป!

หลังจากที่เรา Setup Application เสร็จเรียบร้อยแล้วแต่ว่าตอนนี้ยังขาดการแยก Configuration ของ Application ตามแต่ละ Environment อยู่ใน Part ต่อไปเราจะมาใช้ Kustomize มาช่วยในการแยก Environment ใน Gitops กัน

--

--