[K8S Seri] Kubernetes từ A-Z (Phần 2)

1. Cài đặt ConfigMap

Mục đích: Tách cấu hình ra khỏi mã nguồn ứng dụng, giúp thay đổi cấu hình mà không cần rebuild Docker image hoặc redeploy ứng dụng.

Lợi ích:

  • Lưu trữ cấu hình dưới dạng key-value không nhạy cảm
  • Truyền cấu hình vào container dưới dạng biến môi trường hoặc file
  • Tăng tính tái sử dụng và nhất quán giữa các Pod

2. Chuẩn bị Dockerfile và Image

  • Viết Dockerfile cho phần backend
  • Build và push image lên Docker Hub

3. Tạo ConfigMap ecommerce-backend-application-properties-configmap

  • Deployment đã có volumeMountsvolumes để sử dụng ConfigMap
  • Rebuild backend để áp dụng cấu hình mới
apiVersion: v1
kind: ConfigMap
metadata:
  name: ecommerce-backend-application-properties-configmap
  namespace: ecommerce
data:
  application.properties: |
    spring.datasource.url=jdbc:mysql://192.168.9.26:3306/full-stack-ecommerce #chú ý thay đổi địa chỉ IP của bạn 
    spring.datasource.username=ecommerceapp
    spring.datasource.password=StrongPa55WorD
    spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
    spring.datasource.sql-script-encoding=UTF-8

    spring.jpa.properties.hibernate.globally_quoted_i/dentifiers=true
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
    spring.jpa.hibernate.ddl-auto=none
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true

    spring.data.rest.base-path=/api
    spring.data.rest.detection-strategy=ANNOTATED

    allowed.origins=http://ecommerce.hoatran.local

    okta.oauth2.client-id=0oab0lzwjoN1Rjsar5d7
    okta.oauth2.issuer=https://dev-82108115.okta.com/oauth2/default

4. Tạo Secret trong Kubernetes

Secret là đối tượng dùng để lưu trữ thông tin nhạy cảm như:

  • Mật khẩu
  • Token
  • API key

Lợi ích:

  • Tách biệt dữ liệu nhạy cảm khỏi mã nguồn
  • Tăng cường bảo mật khi triển khai ứng dụng

5. File cấu hình Secret

yaml

apiVersion: v1
kind: Secret
metadata:
  name: ecommerce-backend-database-connection
  namespace: hoatraclocal-ecommerce
type: Opaque
stringData:
  MARIADB_HOST: "192.168.9.26"
  MARIADB_DB: "full-stack-ecommerce"
  MARIADB_PORT: "3306"
  MARIADB_USERNAME: "ecommerceapp"
  MARIADB_PASSWORD: "StrongPa55WorD"

6. Điều chỉnh nội dung trong ConfigMap

spring.datasource.url=jdbc:mysql://${MARIADB_HOST}:${MARIADB_PORT}/${MARIADB_DB}
spring.datasource.username=${MARIADB_USERNAME}
spring.datasource.password=${MARIADB_PASSWORD}
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.sql-script-encoding=UTF-8
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.data.rest.base-path=/api
spring.data.rest.detection-strategy=ANNOTATED
allowed.origins=http://ecommerce.hoatran.local
okta.oauth2.client-id=0aab0lzvjoN1Rjsar5d7
okta.oauth2.issuer=https://dev-82108115.okta.com/oauth2/default

7. Thêm Secret vào Deployment backend

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-deployment
  namespace: your-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: your-app
  template:
    metadata:
      labels:
        app: your-app
    spec:
      containers:
        - name: your-container
          image: hoatrancntt/befm:v1
          imagePullSecrets:
            - name: auth-registry

8. StorageClass trong Kubernetes

Là gì? Định nghĩa loại lưu trữ mà Kubernetes có thể cung cấp.

Tính năng:

  • Cấp phát động PV khi tạo PVC
  • Mô tả cách tạo PV với đặc tính như loại ổ đĩa, hiệu năng, vùng lưu trữ

Thành phần chính:

  • provisioner: Plugin tạo PV (ví dụ: kubernetes.io/aws-ebs)
  • parameters: Loại ổ đĩa, zone, mã hóa
  • reclaimPolicy: Delete, Retain, Recycle
  • volumeBindingMode: Immediate, WaitForFirstConsumer
  • allowVolumeExpansion: Cho phép mở rộng dung lượng

9. PV và PVC trong Kubernetes

Persistent Volume (PV)
  • Tài nguyên lưu trữ trong cụm K8s
  • Được cấp phát bởi admin hoặc tự động qua StorageClass
  • Tồn tại độc lập với Pod
  • Hỗ trợ NFS, iSCSI, CSI, hostPath…
Persistent Volume Claim (PVC)
  • Yêu cầu sử dụng lưu trữ từ PV
  • Xác định kích thước, loại truy cập, StorageClass
  • PVC được mount vào Pod như một volume
Mối quan hệ
  • PVC yêu cầu → K8s gán PV phù hợp → PVC mount vào Pod → Pod sử dụng lưu trữ

10. Triển khai NFS lưu trữ

Cài đặt NFS Server

bash

sudo apt install nfs-server -y
sudo mkdir /data
sudo chown -R nobody:nogroup /data
sudo chmod -R 777 /data
sudo vi /etc/exports
# Thêm dòng:
/data *(rw,sync,no_subtree_check)
sudo exportfs -rav
sudo systemctl restart nfs-server
Cài đặt NFS Client

Thực hiện trên các node: k8s-master-1, k8s-master-2, k8s-master-3

Cấu hình PV

yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /data
    server: 192.168.9.29 # Server NFS của bạn
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs-storage
Cấu hình PVC

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
  namespace: hoatranlocal-ecommerce
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: nfs-storage
Mount dữ liệu từ Pod vào thư mục /data

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-blog
  namespace: hoatranlocal-ecommerce
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress-blog-selector
  template:
    metadata:
      labels:
        app: wordpress-blog-selector
    spec:
      containers:
        - name: blog
          image: litespeedtech/openlitespeed:latest
          ports:
            - containerPort: 7080
            - containerPort: 80
          volumeMounts:
            - mountPath: /var/www
              name: wwwdata
      volumes:
        - name: wwwdata
          persistentVolumeClaim:
            claimName: nfs-pvc
Kết quả kiểm tra
  • PVC chuyển từ PendingBound
  • /data trên NFS server đã mount thành công
  • Dữ liệu upload vào /var/www trong Pod sẽ lưu trực tiếp vào NFS

11. Triển khai MariaDB với StatefulSet

Cấu hình NFS Server

bash

# Trong /etc/exports
/data *(rw,sync,no_subtree_check,no_root_squash)

no_root_squash: Cho phép container ghi dữ liệu với quyền root (chỉ dùng cho môi trường test/lab)

StatefulSet MariaDB

yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mariadb
  namespace: hoatranlocal-ecommerce
spec:
  serviceName: mariadb-service
  replicas: 1
  selector:
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      securityContext:
        fsGroup: 65534
      containers:
        - name: mariadb
          image: mariadb:latest
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "tonytechlab"
          ports:
            - containerPort: 3306
          volumeMounts:
            - mountPath: /var/lib/mysql
              name: mariadb-storage
      volumes:
        - name: mariadb-storage
          persistentVolumeClaim:
            claimName: nfs-pvc
Service NodePort

yaml

apiVersion: v1
kind: Service
metadata:
  name: mariadb-service
  namespace: hoatranlocal-ecommerce
spec:
  selector:
    app: mariadb
  type: NodePort
  ports:
    - port: 3306
      targetPort: 3306
      nodePort: 31306
Service ClusterIP

yaml

apiVersion: v1
kind: Service
metadata:
  name: mariadb
  namespace: hoatranlocal-ecommerce
spec:
  type: ClusterIP
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306
  selector:
    app: mariadb

DNS nội bộ để kết nối: mariadb.hoatranlocal-ecommerce.svc.cluster.local

Kiểm tra kết nối từ Pod OpenLiteSpeed

bash

mysql -h mariadb.hoatranlocal-ecommerce.svc.cluster.local -u root -p

Hoặc dùng telnet