#การใช้งาน Helm Chart บน DigitalOcean Kubernetes (DOKS)

Helm เป็น Package Manager สำหรับ Kubernetes ที่ช่วยให้เราจัดชุด Kubernetes Manifest เช่น Deployment, Service, Ingress, ConfigMap และ resource อื่น ๆ ให้อยู่ในรูปแบบที่ติดตั้งซ้ำ ปรับค่า และอัปเกรดได้ง่าย

เมื่อใช้งานร่วมกับ DigitalOcean Kubernetes (DOKS) เราสามารถใช้ Helm เพื่อ deploy ระบบจริงบน Cloud ได้โดยไม่ต้องจัดการ Kubernetes Control Plane เอง และยังเชื่อมต่อกับ DigitalOcean Load Balancer, Container Registry และ Storage ได้อีกด้วย

บทความนี้อธิบาย workflow ตั้งแต่เครื่อง Local ไปจนถึง Production Deployment


#1. ภาพรวม Architecture

Developer / CI/CD
        |
        | doctl + kubectl + helm
        v
DigitalOcean Kubernetes (DOKS)
        |
        +-- Namespace
        |     |
        |     +-- Helm Release
        |           |
        |           +-- Deployment
        |           +-- Service
        |           +-- ConfigMap
        |           +-- Secret
        |           +-- Ingress
        |
        +-- DigitalOcean Load Balancer
        |
        +-- DigitalOcean Container Registry
        |
        +-- DigitalOcean Volumes

Helm ไม่ได้แทนที่ Kubernetes แต่ทำหน้าที่เป็นชั้นสำหรับ Packaging, Configuration และ Release Management


#2. สิ่งที่ต้องมี

ตัวอย่างนี้สมมติว่าใช้ macOS เป็นเครื่องสำหรับ deploy

ตรวจสอบเครื่องมือ

kubectl version --client
helm version
doctl version

ติดตั้งผ่าน Homebrew

brew install kubectl
brew install helm
brew install doctl

จากนั้น Login เข้า DigitalOcean CLI

doctl auth init

ระบบจะให้ใส่ DigitalOcean Personal Access Token

ควรเก็บ Token ไว้ในที่ปลอดภัยและไม่ commit ลง Git Repository


#3. สร้าง DigitalOcean Kubernetes Cluster

สามารถสร้างผ่าน DigitalOcean Control Panel ได้ที่เมนู Kubernetes

หรือสร้างผ่าน doctl

doctl kubernetes cluster create my-doks-cluster \
  --region sgp1

สำหรับระบบจริงควรเลือกจำนวน worker node, machine size, Kubernetes version, VPC และ High Availability ให้เหมาะกับ workload

ตรวจสอบ cluster

doctl kubernetes cluster list

#4. เชื่อมเครื่อง Local กับ DOKS

DigitalOcean แนะนำให้ใช้ doctl สำหรับนำ kubeconfig ของ cluster มารวมกับ kubeconfig บนเครื่อง

doctl kubernetes cluster kubeconfig save my-doks-cluster

ตรวจสอบ context

kubectl config current-context

ตรวจสอบ node

kubectl get nodes

ตัวอย่างผลลัพธ์

NAME                   STATUS   ROLES    AGE   VERSION
pool-abcd1234-worker   Ready    <none>   10m   v1.xx.x
pool-abcd5678-worker   Ready    <none>   10m   v1.xx.x

หากเห็นสถานะ Ready แสดงว่าเครื่อง Local สามารถควบคุม DOKS ได้แล้ว


#5. Helm Chart คืออะไร

Helm ใช้แนวคิดหลัก 3 ส่วน

ส่วน ความหมาย
Chart Package ที่เก็บ Kubernetes Templates
Release Instance ของ Chart ที่ถูกติดตั้ง
Values Configuration ที่ใช้กำหนดค่าของ Chart

ตัวอย่าง

helm install my-web bitnami/nginx

ในตัวอย่างนี้

my-web         = Release
bitnami/nginx  = Chart

#6. เพิ่ม Helm Repository

ตัวอย่างเพิ่ม Bitnami Repository

helm repo add bitnami https://charts.bitnami.com/bitnami

อัปเดตข้อมูล repository

helm repo update

ตรวจสอบ

helm repo list

ค้นหา chart

helm search repo nginx

#7. ติดตั้ง Chart ลง DOKS

สร้าง namespace

kubectl create namespace production

ติดตั้ง NGINX

helm install web \
  bitnami/nginx \
  --namespace production

ตรวจสอบ release

helm list -n production

ตรวจสอบ Kubernetes resources

kubectl get all -n production

#8. ใช้ helm upgrade --install

สำหรับการ deploy จริง คำสั่งที่นิยมมากกว่า helm install คือ

helm upgrade --install

เพราะคำสั่งเดียวรองรับทั้ง

  • ยังไม่มี release → Install
  • มี release อยู่แล้ว → Upgrade

ตัวอย่าง

helm upgrade --install web \
  bitnami/nginx \
  --namespace production \
  --create-namespace

เหมาะมากสำหรับ CI/CD Pipeline


#9. ปรับค่าด้วย values.yaml

ดูค่า default ของ chart

helm show values bitnami/nginx

บันทึกเป็นไฟล์

helm show values bitnami/nginx > values.yaml

จากนั้นแก้ไขเฉพาะค่าที่ต้องการ

ตัวอย่างแนวคิด

replicaCount: 2

service:
  type: LoadBalancer

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi

ติดตั้งด้วยไฟล์ values

helm upgrade --install web \
  bitnami/nginx \
  -f values.yaml \
  -n production \
  --create-namespace

ชื่อ key ของแต่ละ Chart ไม่เหมือนกัน ควรตรวจสอบด้วย helm show values <chart> ก่อนเสมอ


#10. Override ค่าโดยไม่แก้ไฟล์

สามารถใช้ --set

helm upgrade --install web \
  bitnami/nginx \
  -n production \
  --set replicaCount=3

หรือหลายค่า

helm upgrade --install web \
  bitnami/nginx \
  -n production \
  --set replicaCount=3 \
  --set service.type=LoadBalancer

แนวทางที่แนะนำคือ

  • ค่า config จำนวนมาก → ใช้ values.yaml
  • ค่าเล็กน้อยหรือ Dynamic Value จาก CI/CD → ใช้ --set

#11. ใช้ DigitalOcean Load Balancer

บน DOKS เมื่อ Kubernetes Service ใช้

type: LoadBalancer

DigitalOcean Cloud Controller สามารถ provision DigitalOcean Load Balancer ให้กับ Service ได้

ตรวจสอบ Service

kubectl get svc -n production

ตัวอย่าง

NAME   TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)
web    LoadBalancer   10.245.10.101   157.xxx.xxx.x   80:30001/TCP

เมื่อ EXTERNAL-IP ถูกกำหนดแล้ว สามารถเข้าถึง Application ผ่าน IP นั้นได้

curl http://157.xxx.xxx.x

#12. ติดตั้ง Ingress NGINX ด้วย Helm

สำหรับหลาย Web Application ควรใช้ Ingress Controller แทนการสร้าง Load Balancer แยกทุก Service

เพิ่ม repository

helm repo add ingress-nginx \
  https://kubernetes.github.io/ingress-nginx

อัปเดต

helm repo update

ติดตั้ง

helm upgrade --install ingress-nginx \
  ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.service.type=LoadBalancer

ตรวจสอบ

kubectl get svc -n ingress-nginx

รอจน EXTERNAL-IP ถูกกำหนด

kubectl get svc -n ingress-nginx -w

Architecture จะเป็น

Internet
   |
DigitalOcean Load Balancer
   |
Ingress NGINX
   |
   +----------+----------+
   |                     |
app1.example.com     app2.example.com
   |                     |
Service A            Service B
   |                     |
Pods                 Pods

ข้อดีคือสามารถใช้ Load Balancer ตัวเดียวรองรับหลาย application ได้


#13. สร้าง Helm Chart ของ Application เอง

สร้าง Chart

helm create myapp

โครงสร้าง

myapp/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── ingress.yaml
    ├── serviceaccount.yaml
    ├── hpa.yaml
    ├── NOTES.txt
    └── tests/

#14. Chart.yaml

ตัวอย่าง

apiVersion: v2

name: myapp

description: Helm chart for my application

type: application

version: 0.1.0

appVersion: "1.0.0"

ค่าที่สำคัญ

version     = Version ของ Helm Chart
appVersion  = Version ของ Application

#15. ตัวอย่าง values.yaml

สมมติ Application ถูกเก็บไว้ใน Container Registry

replicaCount: 2

image:
  repository: registry.digitalocean.com/my-registry/myapp
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx

  hosts:
    - host: app.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  requests:
    cpu: 100m
    memory: 128Mi

  limits:
    cpu: 500m
    memory: 512Mi

Deploy

helm upgrade --install myapp \
  ./myapp \
  -f ./myapp/values.yaml \
  -n production \
  --create-namespace

#16. ใช้ DigitalOcean Container Registry

หาก Image เป็น Private Image ใน DigitalOcean Container Registry (DOCR) ควร integrate registry กับ DOKS

แนวทางหนึ่งคือเข้า DigitalOcean Control Panel

Kubernetes
   ↓
เลือก Cluster
   ↓
Settings
   ↓
DigitalOcean Container Registry Integration
   ↓
เลือก Registry
   ↓
Save

จากนั้น workload ใน cluster สามารถ pull private image ตามสิทธิ์ที่ตั้งไว้ได้

ตรวจสอบ Pod

kubectl get pods -n production

ถ้าพบ

ImagePullBackOff

ให้ตรวจสอบ

kubectl describe pod <pod-name> -n production

#17. แยก Values ตาม Environment

ไม่ควรใช้ค่าชุดเดียวกับทุก environment

ตัวอย่าง

myapp/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-staging.yaml
├── values-prod.yaml
└── templates/

Development

helm upgrade --install myapp-dev \
  ./myapp \
  -f values-dev.yaml \
  -n development \
  --create-namespace

Production

helm upgrade --install myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production \
  --create-namespace

ตัวอย่าง values-prod.yaml

replicaCount: 3

image:
  tag: "1.2.0"

resources:
  requests:
    cpu: 250m
    memory: 256Mi

  limits:
    cpu: "1"
    memory: 1Gi

#18. ตรวจสอบ Chart ก่อน Deploy

#Lint

helm lint ./myapp

#Render YAML โดยไม่ Deploy

helm template myapp ./myapp

พร้อม values

helm template myapp ./myapp \
  -f values-prod.yaml

#Dry Run

helm upgrade --install myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production \
  --dry-run

ขั้นตอนเหล่านี้ช่วยตรวจพบ YAML/Template Error ก่อน deploy จริง


#19. Deploy แบบปลอดภัยขึ้น

Production สามารถใช้

helm upgrade --install myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production \
  --create-namespace \
  --atomic \
  --wait \
  --timeout 5m

แนวคิดของ option ที่สำคัญ

Option หน้าที่
--wait รอให้ resource พร้อมใช้งาน
--timeout กำหนดเวลารอสูงสุด
--atomic หาก deploy ล้มเหลว ให้ rollback/cleanup ตาม semantics ของคำสั่ง

เหมาะสำหรับ CI/CD เพราะลดโอกาสที่ pipeline จะรายงานว่า deploy สำเร็จทั้งที่ application ยังไม่พร้อม


#20. ตรวจสอบ Release

ดูรายการ release

helm list -A

หรือเฉพาะ namespace

helm list -n production

ดูสถานะ

helm status myapp -n production

ดู values ที่ release ใช้งาน

helm get values myapp -n production

ดู manifest

helm get manifest myapp -n production

#21. Upgrade Application

สมมติเปลี่ยน image จาก

1.0.0

เป็น

1.1.0

สามารถ deploy ได้ด้วย

helm upgrade myapp \
  ./myapp \
  -n production \
  --set image.tag=1.1.0

หรือแก้ values-prod.yaml

image:
  tag: "1.1.0"

จากนั้น

helm upgrade myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production

ตรวจสอบ rollout

kubectl rollout status deployment/myapp -n production

#22. ดูประวัติ Release

helm history myapp -n production

ตัวอย่าง

REVISION  STATUS      CHART        APP VERSION
1         superseded  myapp-0.1.0  1.0.0
2         deployed    myapp-0.2.0  1.1.0

#23. Rollback

หาก release revision 2 มีปัญหา สามารถกลับไป revision 1

helm rollback myapp 1 -n production

ตรวจสอบ

helm history myapp -n production

และ

kubectl get pods -n production

นี่คือหนึ่งในประโยชน์สำคัญของ Helm ในงาน Production


#24. Uninstall

ลบ release

helm uninstall myapp -n production

ตรวจสอบ

helm list -n production

ถ้าต้องการลบ namespace

kubectl delete namespace production

การลบ namespace จะลบ resource ภายใน namespace นั้นจำนวนมาก ควรตรวจสอบก่อนใช้งานใน Production


#25. Debug เมื่อ Deploy ไม่สำเร็จ

เริ่มจาก Helm

helm status myapp -n production

ดู Pods

kubectl get pods -n production

ดูรายละเอียด Pod

kubectl describe pod <pod-name> -n production

ดู logs

kubectl logs <pod-name> -n production

ถ้ามีหลาย container

kubectl logs <pod-name> \
  -c <container-name> \
  -n production

ดู events

kubectl get events \
  -n production \
  --sort-by=.metadata.creationTimestamp

#26. ปัญหาที่พบบ่อย

#ImagePullBackOff

สาเหตุที่เป็นไปได้

  • Image name ผิด
  • Image tag ไม่มี
  • Registry เป็น Private
  • Cluster ไม่มีสิทธิ์ pull image

ตรวจสอบ

kubectl describe pod <pod-name> -n production

#CrashLoopBackOff

ตรวจสอบ log

kubectl logs <pod-name> -n production

และ log ของ instance ก่อนหน้า

kubectl logs <pod-name> \
  -n production \
  --previous

#Pending

ตรวจสอบ

kubectl describe pod <pod-name> -n production

สาเหตุที่พบบ่อย

  • CPU/Memory ไม่พอ
  • PVC ยัง bind ไม่สำเร็จ
  • Scheduling Constraint
  • Node Selector / Taint / Affinity ไม่ตรง

#Service ยังไม่มี External IP

ตรวจสอบ

kubectl get svc -n production

และ

kubectl describe svc <service-name> -n production

การสร้าง DigitalOcean Load Balancer อาจใช้เวลาระยะหนึ่งก่อน IP จะพร้อม


#27. Helm Workflow ที่แนะนำสำหรับ DOKS

Developer
   |
   v
Build Docker Image
   |
   v
Push Image
   |
   v
DigitalOcean Container Registry
   |
   v
helm lint
   |
   v
helm template / dry-run
   |
   v
helm upgrade --install
   |
   v
DOKS
   |
   +-- Deployment
   +-- Service
   +-- Ingress
   +-- ConfigMap
   +-- Secret
   |
   v
DigitalOcean Load Balancer
   |
   v
Users

#28. ตัวอย่าง CI/CD Command

เมื่อ Pipeline build image สำเร็จและมี tag เช่น

sha-a1b2c3d

สามารถ deploy

helm upgrade --install myapp \
  ./helm/myapp \
  -f ./helm/myapp/values-prod.yaml \
  -n production \
  --create-namespace \
  --set image.tag=sha-a1b2c3d \
  --atomic \
  --wait \
  --timeout 5m

ข้อดีคือ Image Version ถูกผูกกับ Git Commit ได้โดยตรง


#29. แนวทางจัด Repository

ตัวอย่าง

myapp/
├── src/
├── Dockerfile
├── .github/
│   └── workflows/
│       └── deploy.yml
└── helm/
    └── myapp/
        ├── Chart.yaml
        ├── values.yaml
        ├── values-dev.yaml
        ├── values-prod.yaml
        └── templates/

อีกแนวทางคือแยก Application Repository และ GitOps Repository ออกจากกัน

application-repo
   |
   +-- source code
   +-- Dockerfile

gitops-repo
   |
   +-- helm/
   +-- values/
   +-- environments/

เหมาะกับระบบที่ใช้ Argo CD หรือ Flux


#30. Security Best Practices

ไม่ควรใส่ password หรือ token แบบ plaintext ใน values.yaml

ตัวอย่างที่ไม่ควรทำ

database:
  password: my-secret-password

เพราะ values อาจถูก commit เข้า Git

แนวทางที่ดีกว่า เช่น

  • Kubernetes Secret
  • External Secrets Operator
  • Secret Manager
  • SOPS
  • Sealed Secrets

รวมถึงควร

  • กำหนด Resource Request/Limit
  • ใช้ namespace แยก environment
  • ใช้ RBAC
  • ไม่ใช้ latest tag ใน production
  • ตรวจสอบ Helm Chart จากแหล่งที่เชื่อถือได้
  • ใช้ TLS/HTTPS สำหรับ public endpoint
  • ตั้งค่า readiness/liveness probe
  • ใช้ PodDisruptionBudget กับ workload สำคัญ
  • วางแผน backup สำหรับ persistent data

#31. คำสั่ง Helm ที่ใช้บ่อย

helm repo add
helm repo update

helm search repo

helm install

helm upgrade --install

helm list

helm status

helm get values

helm get manifest

helm history

helm rollback

helm uninstall

helm lint

helm template

#32. Cheat Sheet

#เชื่อม DOKS

doctl auth init

doctl kubernetes cluster kubeconfig save my-doks-cluster

kubectl get nodes

#Deploy

helm upgrade --install myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production \
  --create-namespace

#ตรวจสอบ

helm list -n production

helm status myapp -n production

kubectl get all -n production

#Upgrade

helm upgrade myapp \
  ./myapp \
  -f values-prod.yaml \
  -n production

#Rollback

helm history myapp -n production

helm rollback myapp 1 -n production

#Delete

helm uninstall myapp -n production

#สรุป

Helm ทำให้การ deploy application บน DigitalOcean Kubernetes มีรูปแบบที่จัดการง่ายและทำซ้ำได้ โดยเฉพาะเมื่อระบบมี Kubernetes resources หลายไฟล์หรือมีหลาย environment

Workflow ที่แนะนำคือ

Docker Image
   ↓
DigitalOcean Container Registry
   ↓
Helm Chart
   ↓
values-dev / values-staging / values-prod
   ↓
helm upgrade --install
   ↓
DigitalOcean Kubernetes
   ↓
Ingress Controller
   ↓
DigitalOcean Load Balancer
   ↓
Application

สำหรับระบบ Production ควรใช้ Helm ร่วมกับ CI/CD หรือ GitOps เพื่อให้ทุก deployment ตรวจสอบย้อนกลับได้ และสามารถ rollback ได้อย่างเป็นระบบ


#เอกสารอ้างอิง