0

Lab 4 — Kubernetes Configuration với Helm

🎯 Mục tiêu

Sau Lab này, bạn sẽ:

  • Hiểu Helm dùng Values để customize Kubernetes resources như thế nào.
  • Biết cách cấu hình các thành phần thường gặp: Deployment, Service, ConfigMap, Secret và Ingress.
  • Hiểu cách một application Chart gom các configuration vào values.yaml.
  • Biết cách review một Chart để tìm configuration quan trọng.
  • Hiểu một số lỗi production thường gặp khi configuration Helm không khớp với Kubernetes.

Mục tiêu của Lab này không phải học syntax của từng Kubernetes resource.

Bạn đã học Kubernetes ở các Lab trước. Ở đây chúng ta tập trung vào câu hỏi:

"Nếu đã có Kubernetes resource, Helm giúp chúng ta configure nó như thế nào?"


1. 🤔 Vấn đề thực tế

Giả sử bạn có Todo API chạy trên Kubernetes.

Application cần:

Todo API
   │
   ├── Deployment
   ├── Service
   ├── ConfigMap
   ├── Secret
   └── Ingress

Nếu viết YAML trực tiếp, bạn có thể phải sửa:

deployment.yaml
service.yaml
configmap.yaml
secret.yaml
ingress.yaml

khi muốn thay đổi:

replica
image
port
environment
domain
resource

Vấn đề xuất hiện khi có nhiều environment:

Dev
 └── todo.example-dev.com

Staging
 └── todo.example-staging.com

Production
 └── todo.example.com

Bạn không muốn copy toàn bộ Kubernetes YAML cho từng environment.

Helm cho phép chúng ta tách:

              Kubernetes Structure
                      │
                      │ Template
                      ▼
                 Helm Chart
                      ▲
                      │ Values
                      │
          ┌───────────┼───────────┐
          │           │           │
         Dev       Staging      Prod

Template giữ cấu trúc.

Values chứa phần cần thay đổi.


2. 🧠 Hiểu nhanh

Một application Chart thường có:

my-app/
├── values.yaml
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── configmap.yaml
    ├── secret.yaml
    └── ingress.yaml

Có thể hiểu:

values.yaml
     │
     ├── image
     ├── replicaCount
     ├── resources
     ├── service
     ├── ingress
     └── config
             │
             ▼
        templates/
             │
             ├── Deployment
             ├── Service
             ├── ConfigMap
             ├── Secret
             └── Ingress

3. 🏗️ Architecture

Một application thực tế có thể có flow:

                         User
                           │
                           ▼
                        Ingress
                           │
                           ▼
                        Service
                           │
                           ▼
                      Deployment
                           │
                     ┌─────┴─────┐
                     ▼           ▼
                   Pod         Pod
                   │
          ┌────────┴────────┐
          │                 │
     ConfigMap           Secret
          │                 │
          └────────┬────────┘
                   ▼
              Application

Helm đứng bên ngoài để tạo và configure toàn bộ:

                    Helm Chart
                        │
             ┌──────────┴──────────┐
             │                     │
        values.yaml             templates/
             │                     │
             └──────────┬──────────┘
                        ▼
                Kubernetes Resources

4. 🧪 Chuẩn bị Lab

Tạo Chart:

helm create todo-app
cd todo-app

Để bài học dễ hiểu, chúng ta sẽ tập trung vào các resource chính.

Bạn có thể xóa bớt các template mặc định nếu muốn:

rm -f templates/tests/test-connection.yaml

Các file chính:

templates/
├── deployment.yaml
├── service.yaml
├── configmap.yaml
├── secret.yaml
└── ingress.yaml

5. 🚀 Deployment — Cấu hình Application

Tại sao cần?

Deployment quyết định application chạy như thế nào:

image
replicas
resources
probes
environment

Ví dụ configuration:

replicaCount: 3

image:
  repository: todo-api
  tag: "1.0.0"

Template:

spec:
  replicas: {{ .Values.replicaCount }}

  template:
    spec:
      containers:
        - name: todo-api
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Helm render:

spec:
  replicas: 3

  template:
    spec:
      containers:
        - name: todo-api
          image: "todo-api:1.0.0"

Mental Model

values.yaml
     │
     ├── replicaCount
     └── image
          │
          ▼
deployment.yaml
          │
          ▼
Kubernetes Deployment

6. 🧪 Thực hành — Customize Image

Trong values.yaml:

image:
  repository: nginx
  tag: "1.27"

Render:

helm template todo-app .

Tìm:

image:

Bạn sẽ thấy:

image: nginx:1.27

Thử:

helm template todo-app . \
  --set image.tag=1.28

Kết quả:

image: nginx:1.28

Understand

Bạn vừa thay đổi image của application mà không sửa:

templates/deployment.yaml

7. 📈 Resource Requests & Limits

Trong production, đây là configuration rất quan trọng.

Nếu Pod không có resource request/limit, Kubernetes khó biết nên phân bổ CPU và Memory như thế nào.

Values:

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

  limits:
    cpu: 500m
    memory: 512Mi

Template:

resources:
  {{- toYaml .Values.resources | nindent 12 }}

Bạn không cần học thuộc toYaml hay nindent.

Chỉ cần hiểu:

values.resources
       │
       ▼
Deployment.resources

Render:

helm template todo-app .

Kết quả:

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

8. ❤️ Health Check

Application production nên có:

Liveness Probe
Readiness Probe

Ví dụ Values:

probes:
  enabled: true

Template có thể condition:

if probes.enabled
       │
       ├── true  → render probes
       │
       └── false → không render

Ví dụ:

livenessProbe:
  httpGet:
    path: /actuator/health
    port: 8080

readinessProbe:
  httpGet:
    path: /actuator/health
    port: 8080

Tại sao Helm cần phần này?

Dev có thể:

probe.enabled = false

Production:

probe.enabled = true

hoặc thay đổi endpoint:

probes:
  path: /health

mà không sửa template.


9. 🌐 Service — Cho Pod một địa chỉ ổn định

Pod có thể bị tạo lại.

Vì vậy application không nên phụ thuộc trực tiếp vào IP của Pod.

Service cung cấp một endpoint ổn định:

Client
  │
  ▼
Service
  │
  ├── Pod
  ├── Pod
  └── Pod

Values:

service:
  type: ClusterIP
  port: 80
  targetPort: 8080

Template:

spec:
  type: {{ .Values.service.type }}

  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetPort }}

Helm render:

spec:
  type: ClusterIP

  ports:
    - port: 80
      targetPort: 8080

10. ⚠️ Một lỗi production rất hay gặp

Ví dụ:

Service
port: 80
targetPort: 8080

Application thực tế lại chạy:

port: 8081

Kết quả:

Ingress
   ↓
Service :80
   ↓
Pod :8080
   X
Application :8081

Request sẽ fail.

Khi debug Helm application, đừng chỉ nhìn:

helm status

Hãy kiểm tra cả:

kubectl get svc
kubectl describe svc <service>
kubectl get pods

và đặc biệt:

kubectl get endpoints

Mental model:

Service.targetPort
        │
        ▼
Container.port
        │
        ▼
Application listening port

Ba thứ này phải khớp về mặt logic.


11. 📋 ConfigMap — Configuration không nhạy cảm

Application thường cần configuration:

LOG_LEVEL=info
SPRING_PROFILES_ACTIVE=production
API_URL=https://api.example.com

Không nên hard-code trực tiếp trong Deployment template.

Dùng ConfigMap:

config:
  LOG_LEVEL: info
  ENVIRONMENT: production

Helm có thể render:

apiVersion: v1
kind: ConfigMap
metadata:
  name: todo-app-config
data:
  LOG_LEVEL: info
  ENVIRONMENT: production

Application Pod sử dụng ConfigMap:

ConfigMap
    │
    │ environment variables
    ▼
  Pod
    │
    ▼
Application

12. 🧪 Thực hành — ConfigMap

Thêm vào values.yaml:

config:
  LOG_LEVEL: info
  ENVIRONMENT: dev

Template:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "todo-app.fullname" . }}
data:
  LOG_LEVEL: {{ .Values.config.LOG_LEVEL | quote }}
  ENVIRONMENT: {{ .Values.config.ENVIRONMENT | quote }}

Render:

helm template todo-app .

Kết quả:

data:
  LOG_LEVEL: "info"
  ENVIRONMENT: "dev"

Thử:

helm template todo-app . \
  --set config.ENVIRONMENT=production

Kết quả:

ENVIRONMENT: "production"

13. 🔐 Secret — Configuration nhạy cảm

Một số configuration không nên để trong ConfigMap:

Database password
API key
Token
Credential

Ví dụ:

database:
  username: app
  password: secret

Về mặt Helm, bạn có thể render thành Kubernetes Secret.

Nhưng:

Không có nghĩa đặt password trực tiếp trong values.yaml rồi commit Git là an toàn.

Đây là lỗi production rất phổ biến.

Có thể dùng:

External Secrets
SOPS
Sealed Secrets
Cloud Secret Manager
Vault

Tùy architecture.

Ở Lab này, bạn chỉ cần hiểu:

ConfigMap
    ↓
Non-sensitive configuration

Secret
    ↓
Sensitive configuration

Các phương pháp quản lý Secret thực tế sẽ được học sâu hơn sau.


14. 🌍 Ingress — Expose Application ra bên ngoài

Nếu application cần truy cập từ Internet:

Internet
    │
    ▼
Ingress
    │
    ▼
Service
    │
    ▼
Pod

Values:

ingress:
  enabled: true

  host: todo.example.com

  path: /

Template sử dụng:

.Values.ingress.enabled
.Values.ingress.host
.Values.ingress.path

Nếu:

enabled: false

Ingress không được render.

Nếu:

enabled: true

Ingress được tạo.


15. 🧪 Thực hành — Dev vs Production

Tạo:

values-dev.yaml
values-prod.yaml

Dev

replicaCount: 1

image:
  tag: dev

ingress:
  enabled: false

config:
  ENVIRONMENT: dev

Production

replicaCount: 3

image:
  tag: "1.0.0"

ingress:
  enabled: true
  host: todo.example.com

config:
  ENVIRONMENT: production

Render Dev:

helm template todo-dev . \
  -f values-dev.yaml

Render Production:

helm template todo-prod . \
  -f values-prod.yaml

Bây giờ cùng một Chart tạo ra hai cấu hình khác nhau:

                 todo-app Chart
                       │
              ┌────────┴────────┐
              │                 │
        values-dev.yaml   values-prod.yaml
              │                 │
              ▼                 ▼
           Dev YAML          Prod YAML
              │                 │
              ▼                 ▼
          Kubernetes         Kubernetes

16. 🔍 Review một Helm Chart

Khi nhận một Helm Chart từ đồng nghiệp hoặc AI, bạn không cần đọc từng dòng.

Hãy đi theo thứ tự:

1. Đọc values.yaml

Hỏi:

Application có thể customize những gì?

Tìm:

image
replica
resources
service
config
secret
ingress
autoscaling

2. Đọc templates/deployment.yaml

Hỏi:

Values nào được sử dụng?

Kiểm tra:

image
resources
env
probes
ports

3. Đọc service.yaml

Kiểm tra:

port
targetPort
selector

4. Đọc ingress.yaml

Kiểm tra:

host
path
service
TLS

5. Render

Cuối cùng:

helm template todo-app . \
  -f values-prod.yaml

Đừng chỉ review template.

Review output cũng rất quan trọng.


17. 🧠 Một Helm Chart tốt trông như thế nào?

Một Chart tốt nên cho phép developer configure application thông qua:

values.yaml

thay vì sửa:

templates/

Ví dụ:

image:
  repository: todo-api
  tag: "1.5.0"

replicaCount: 3

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

service:
  port: 8080

ingress:
  enabled: true
  host: todo.example.com

Developer chỉ cần thay values.

Không cần biết sâu về:

deployment.yaml
service.yaml
ingress.yaml

Đây chính là một dấu hiệu của Reusable Chart.


18. ⚠️ Production Tips

1. Đừng expose mọi thứ thành Value

Không phải configuration nào cũng cần:

foo:
bar:
baz:

Nếu một configuration không có lý do để customize, có thể giữ trực tiếp trong template.

Mục tiêu:

Enough flexibility
        +
Simple interface

Không phải:

Maximum flexibility

2. Cẩn thận với replicaCount và HPA

Nếu:

replicaCount: 3

và:

autoscaling:
  enabled: true

thì HPA có thể quản lý số replica.

Do đó Chart cần thiết kế rõ:

Manual scaling
      OR
HPA scaling

Không nên để người dùng không biết:

"Ai đang quyết định số replica?"


3. Resource requests rất quan trọng

Production nên có:

resources:
  requests:
    cpu: ...
    memory: ...

  limits:
    cpu: ...
    memory: ...

Nếu AI tạo Chart mà bỏ hoàn toàn resources, hãy đặt câu hỏi:

Application này sẽ chạy production với resource configuration nào?


4. Đừng nhầm Helm configuration với Kubernetes behavior

Ví dụ:

replicaCount: 3

là Helm value.

Nhưng:

replicas: 3

là Kubernetes Deployment configuration.

Flow là:

Helm Value
    │
    ▼
Template
    │
    ▼
Kubernetes Field

Helm chỉ là lớp tạo configuration.


19. 🧪 Bài tập thực hành

Exercise 1 — Application Configuration

Tạo các values:

image:
  repository: nginx
  tag: "1.27"

replicaCount: 3

service:
  port: 80

Render Chart và kiểm tra:

Deployment
Service

Exercise 2 — ConfigMap

Tạo:

config:
  APP_ENV: production
  LOG_LEVEL: info

Render và kiểm tra ConfigMap.


Exercise 3 — Ingress

Tạo:

ingress:
  enabled: true
  host: todo.example.com

Render.

Sau đó:

ingress:
  enabled: false

Render lại.

Quan sát sự khác biệt.


Exercise 4 — Production Values

Tạo:

values-prod.yaml

với:

replicaCount: 3

image:
  tag: "1.0.0"

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

  limits:
    cpu: 500m
    memory: 512Mi

ingress:
  enabled: true
  host: todo.example.com

Render:

helm template todo-prod . \
  -f values-prod.yaml

Sau đó kiểm tra output.


20. 🎯 Tổng kết

Trong Lab này, bạn đã thấy cách Helm biến một Kubernetes application thành một configuration-driven deployment.

Mental model:

                       values.yaml
                            │
              ┌─────────────┼─────────────┐
              │             │             │
            Image        Replicas      Ingress
              │             │             │
              └─────────────┼─────────────┘
                            │
                            ▼
                       templates/
                            │
            ┌───────────────┼───────────────┐
            ▼               ▼               ▼
        Deployment        Service         Ingress
            │               │               │
            └───────────────┼───────────────┘
                            ▼
                       Kubernetes

🧠 Những gì cần nhớ

values.yaml
    ↓
Configuration

templates/
    ↓
Kubernetes resources

Deployment
    ↓
Chạy application

Service
    ↓
Địa chỉ ổn định cho Pod

ConfigMap
    ↓
Non-sensitive configuration

Secret
    ↓
Sensitive configuration

Ingress
    ↓
Expose application ra bên ngoài

Và khi review một Helm Chart, hãy luôn hỏi:

"Value này cuối cùng được render vào Kubernetes resource nào?"

Ví dụ:

.Values.replicaCount
        ↓
Deployment.spec.replicas

.Values.image.tag
        ↓
Deployment.container.image

.Values.service.port
        ↓
Service.spec.ports

.Values.ingress.host
        ↓
Ingress.spec.rules

Nếu bạn đọc một Chart và trace được các value theo cách này, bạn đã hiểu phần quan trọng của Helm Configuration mà không cần thuộc syntax.

Ở Lab tiếp theo, chúng ta sẽ tập trung vào Helm Debugging & Troubleshooting — cách tìm ra vấn đề khi Chart render sai, Kubernetes resource sai hoặc Release upgrade thất bại.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí