Stateful Applications trên Kubernetes

Stateful Applications trên Kubernetes

1. Giới Thiệu

Trong Kubernetes, ứng dụng trạng thái (Stateful Applications) là những ứng dụng cần lưu trữ và quản lý trạng thái bên ngoài container, như cơ sở dữ liệu, hệ thống lưu trữ, hoặc các dịch vụ phân tán. Để triển khai và quản lý các ứng dụng trạng thái một cách hiệu quả, Kubernetes cung cấp StatefulSet – một đối tượng quản lý Pods với đặc điểm duy trì danh tính ổn định và quản lý các tài nguyên lưu trữ bền vững.

Bài viết này sẽ hướng dẫn bạn về StatefulSet, cùng với các ví dụ triển khai thực tế như WordPress và MySQL, Cassandra, và ZooKeeper, giúp bạn hiểu rõ cách quản lý ứng dụng trạng thái trên Kubernetes.


2. StatefulSet Basics

2.1. StatefulSet là gì?

StatefulSet là một đối tượng trong Kubernetes được thiết kế để quản lý các ứng dụng trạng thái, đảm bảo rằng các Pods được tạo ra duy trì danh tính ổn định, thứ tự triển khai và xóa Pod theo trình tự. StatefulSet cung cấp các tính năng như:

  • Stable, unique network identifiers: Mỗi Pod trong StatefulSet có tên duy nhất và DNS định danh ổn định.
  • Stable, persistent storage: Mỗi Pod được liên kết với một PersistentVolume riêng biệt, giữ dữ liệu bền vững ngay cả khi Pod bị xóa hoặc tái tạo.
  • Ordered, graceful deployment and scaling: Pods được triển khai và xóa theo thứ tự, đảm bảo tính nhất quán của ứng dụng.

2.2. So Sánh StatefulSet với Deployment

Tính Năng Deployment StatefulSet
Danh tính Pod Thay đổi mỗi lần Pod được tái tạo Duy trì danh tính ổn định với số thứ tự
Quản lý Storage Không quản lý PersistentVolume riêng cho mỗi Pod Quản lý PersistentVolumeClaim riêng cho mỗi Pod
Triển khai và Scaling Mở rộng và giảm số lượng Pods không theo thứ tự Triển khai và scaling Pods theo thứ tự
Ứng dụng phù hợp Ứng dụng không trạng thái (Stateless) Ứng dụng trạng thái (Stateful)

2.3. Các Thành Phần Chính của StatefulSet

  • Headless Service: Service không có Cluster IP, giúp các Pods có thể được truy cập trực tiếp thông qua DNS.
  • PersistentVolumeClaims (PVCs): Yêu cầu lưu trữ bền vững cho mỗi Pod.
  • Ordered Deployment and Scaling: StatefulSet đảm bảo Pods được triển khai và scaling theo thứ tự.

3. Ví Dụ: Triển Khai WordPress và MySQL với Persistent Volumes

Trong ví dụ này, chúng ta sẽ triển khai một ứng dụng WordPress kết hợp với MySQL sử dụng StatefulSetPersistentVolumes để đảm bảo dữ liệu được lưu trữ bền vững.

3.1. Tạo Namespace cho Ứng Dụng

Đầu tiên, tạo một namespace để quản lý các tài nguyên liên quan đến ứng dụng WordPress và MySQL.

kubectl create namespace wordpress

3.2. Triển Khai MySQL với StatefulSet và Persistent Volume

Bước 1: Tạo Secret cho MySQL

Tạo một secret để lưu trữ mật khẩu MySQL.

# mysql-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-pass
  namespace: wordpress
type: Opaque
data:
  password: cGFzc3dvcmQ= # 'password' base64 encoded

Áp dụng Secret:

kubectl apply -f mysql-secret.yaml

Bước 2: Tạo StatefulSet cho MySQL

Tạo file mysql-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: wordpress
spec:
  serviceName: "mysql"
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 1Gi

Áp dụng StatefulSet:

kubectl apply -f mysql-statefulset.yaml

Bước 3: Tạo Service cho MySQL

Tạo file mysql-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: wordpress
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql

Áp dụng Service:

kubectl apply -f mysql-service.yaml

3.3. Triển Khai WordPress với StatefulSet và Persistent Volume

Bước 1: Tạo StatefulSet cho WordPress

Tạo file wordpress-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: wordpress
  namespace: wordpress
spec:
  serviceName: "wordpress"
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:5.7.2-apache
        env:
        - name: WORDPRESS_DB_HOST
          value: mysql:3306
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
  volumeClaimTemplates:
  - metadata:
      name: wordpress-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 1Gi

Áp dụng StatefulSet:

kubectl apply -f wordpress-statefulset.yaml

Bước 2: Tạo Service cho WordPress

Tạo file wordpress-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  namespace: wordpress
spec:
  ports:
  - port: 80
    name: wordpress
  clusterIP: None
  selector:
    app: wordpress

Áp dụng Service:

kubectl apply -f wordpress-service.yaml

3.4. Triển Khai Service để Expose WordPress

Để truy cập WordPress từ bên ngoài cluster, tạo một Service loại LoadBalancer.

Tạo file wordpress-external-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: wordpress-external
  namespace: wordpress
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: wordpress

Áp dụng Service:

kubectl apply -f wordpress-external-service.yaml

3.5. Kiểm Tra và Truy Cập Ứng Dụng

Bước 1: Kiểm Tra Pods và Services

kubectl get pods -n wordpress
kubectl get services -n wordpress

Kết Quả Ví Dụ:

NAME                      READY   STATUS    RESTARTS   AGE
mysql-0                  1/1     Running   0          10m
wordpress-0              1/1     Running   0          10m

NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
mysql                 ClusterIP      10.96.144.78    <none>          3306/TCP       10m
wordpress             ClusterIP      10.96.0.15      <none>          80/TCP         10m
wordpress-external    LoadBalancer   10.96.224.101   <pending>       80:30912/TCP   5m

Bước 2: Truy Cập Ứng Dụng

Trên các nhà cung cấp đám mây hỗ trợ LoadBalancer, External IP sẽ được gán tự động. Trên Minikube, sử dụng lệnh sau để truy cập ứng dụng:

minikube service wordpress-external -n wordpress

Lệnh này sẽ mở trình duyệt với địa chỉ IP của ứng dụng WordPress đang chạy.


4. Ví Dụ: Triển Khai Cassandra với StatefulSet

Cassandra là một cơ sở dữ liệu phân tán được thiết kế để xử lý dữ liệu lớn trên nhiều node mà không có điểm yếu trung tâm. Triển khai Cassandra với StatefulSet giúp đảm bảo tính nhất quán và ổn định của cluster.

4.1. Tạo StatefulSet cho Cassandra

Tạo file cassandra-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cassandra
  namespace: cassandra
spec:
  serviceName: "cassandra"
  replicas: 3
  selector:
    matchLabels:
      app: cassandra
  template:
    metadata:
      labels:
        app: cassandra
    spec:
      containers:
      - name: cassandra
        image: cassandra:3.11
        ports:
        - containerPort: 9042
          name: cql
        env:
        - name: CASSANDRA_CLUSTER_NAME
          value: "CassandraCluster"
        - name: CASSANDRA_SEEDS
          value: "cassandra-0.cassandra.cassandra.svc.cluster.local"
        - name: CASSANDRA_NUM_TOKENS
          value: "256"
        volumeMounts:
        - name: cassandra-data
          mountPath: /var/lib/cassandra
  volumeClaimTemplates:
  - metadata:
      name: cassandra-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 5Gi

Bước 1: Tạo Namespace cho Cassandra

kubectl create namespace cassandra

Bước 2: Triển Khai StatefulSet

kubectl apply -f cassandra-statefulset.yaml

4.2. Triển Khai Service cho Cassandra

Tạo file cassandra-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: cassandra
  namespace: cassandra
spec:
  clusterIP: None
  ports:
  - port: 9042
    name: cql
  selector:
    app: cassandra

Áp dụng Service:

kubectl apply -f cassandra-service.yaml

4.3. Kiểm Tra StatefulSet Cassandra

Kiểm tra các Pods và Services:

kubectl get pods -n cassandra
kubectl get services -n cassandra

Kết Quả Ví Dụ:

NAME         READY   STATUS    RESTARTS   AGE
cassandra-0   1/1     Running   0          10m
cassandra-1   1/1     Running   0          10m
cassandra-2   1/1     Running   0          10m

NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
cassandra   ClusterIP   10.96.224.202   <none>        9042/TCP   10m

Bước 4: Truy Cập Cassandra

Để truy cập Cassandra từ bên ngoài cluster, bạn có thể sử dụng một Service loại NodePort hoặc LoadBalancer. Trong ví dụ này, chúng ta sẽ tạo một Service loại NodePort.

Tạo file cassandra-external-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: cassandra-external
  namespace: cassandra
spec:
  type: NodePort
  ports:
  - port: 9042
    targetPort: 9042
    nodePort: 30042
  selector:
    app: cassandra

Áp dụng Service:

kubectl apply -f cassandra-external-service.yaml

Truy cập Cassandra thông qua địa chỉ IP của bất kỳ Node nào trong cluster và cổng 30042.


5. Chạy ZooKeeper: Một Bộ Điều Phối Hệ Thống Phân Tán

ZooKeeper là một dịch vụ điều phối phân tán được sử dụng để quản lý cấu hình, tên, và cung cấp dịch vụ đồng bộ hóa. Việc triển khai ZooKeeper trên Kubernetes với StatefulSet giúp đảm bảo tính nhất quán và độ tin cậy cao.

5.1. Tạo ConfigMap cho ZooKeeper

Tạo file zookeeper-configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: zookeeper-config
  namespace: zookeeper
data:
  zoo.cfg: |
    tickTime=2000
    dataDir=/data
    clientPort=2181
    initLimit=5
    syncLimit=2
    server.1=zookeeper-0.zookeeper-headless.zookeeper.svc.cluster.local:2888:3888
    server.2=zookeeper-1.zookeeper-headless.zookeeper.svc.cluster.local:2888:3888
    server.3=zookeeper-2.zookeeper-headless.zookeeper.svc.cluster.local:2888:3888

Áp dụng ConfigMap:

kubectl apply -f zookeeper-configmap.yaml

5.2. Tạo StatefulSet cho ZooKeeper

Tạo file zookeeper-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zookeeper
  namespace: zookeeper
spec:
  serviceName: "zookeeper-headless"
  replicas: 3
  selector:
    matchLabels:
      app: zookeeper
  template:
    metadata:
      labels:
        app: zookeeper
    spec:
      containers:
      - name: zookeeper
        image: zookeeper:3.6
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: quorum
        - containerPort: 3888
          name: leader-election
        volumeMounts:
        - name: zookeeper-data
          mountPath: /data
        - name: zookeeper-config
          mountPath: /conf/zoo.cfg
          subPath: zoo.cfg
  volumeClaimTemplates:
  - metadata:
      name: zookeeper-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 1Gi

5.3. Triển Khai Service cho ZooKeeper

Bước 1: Tạo Headless Service cho ZooKeeper

Headless Service cho phép các Pods trong StatefulSet giao tiếp trực tiếp thông qua DNS.

Tạo file zookeeper-headless-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: zookeeper-headless
  namespace: zookeeper
spec:
  clusterIP: None
  ports:
  - port: 2181
    name: client
  - port: 2888
    name: quorum
  - port: 3888
    name: leader-election
  selector:
    app: zookeeper

Áp dụng Service:

kubectl apply -f zookeeper-headless-service.yaml

Bước 2: Tạo Service để Expose ZooKeeper

Tạo Service loại NodePort để truy cập ZooKeeper từ bên ngoài.

Tạo file zookeeper-external-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: zookeeper-external
  namespace: zookeeper
spec:
  type: NodePort
  ports:
  - port: 2181
    targetPort: 2181
    nodePort: 32181
  selector:
    app: zookeeper

Áp dụng Service:

kubectl apply -f zookeeper-external-service.yaml

5.4. Kiểm Tra và Truy Cập ZooKeeper

Bước 1: Kiểm Tra Pods và Services

kubectl get pods -n zookeeper
kubectl get services -n zookeeper

Kết Quả Ví Dụ:

NAME           READY   STATUS    RESTARTS   AGE
zookeeper-0    1/1     Running   0          10m
zookeeper-1    1/1     Running   0          10m
zookeeper-2    1/1     Running   0          10m

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
zookeeper-headless    ClusterIP   None            <none>        2181/TCP       10m
zookeeper-external    NodePort    10.96.224.203   <none>        2181:32181/TCP 5m

Bước 2: Truy Cập ZooKeeper

Truy cập ZooKeeper thông qua địa chỉ IP của bất kỳ Node nào trong cluster và cổng 32181.

Ví dụ, sử dụng zkCli:

zkCli -server <node-ip>:32181

6. Best Practices Cho Ứng Dụng Trạng Thái

6.1. Sử Dụng PersistentVolumeClaims (PVCs) Hiệu Quả

  • Quy Định Kích Thước Lưu Trữ: Đảm bảo rằng các PVC được đặt kích thước phù hợp với nhu cầu lưu trữ của ứng dụng.
  • Sử Dụng StorageClasses: Định nghĩa các StorageClasses khác nhau để cung cấp các loại lưu trữ phù hợp với từng ứng dụng.

6.2. Đặt Chính Xác Chính Sách Storage

  • Access Modes: Chọn đúng Access Modes (ReadWriteOnce, ReadOnlyMany, ReadWriteMany) dựa trên yêu cầu của ứng dụng.
  • Retention Policies: Xác định chính sách retention phù hợp để đảm bảo dữ liệu không bị mất khi PVC bị xóa.

6.3. Giám Sát và Logging

  • Theo Dõi Dung Lượng Lưu Trữ: Sử dụng các công cụ giám sát để theo dõi dung lượng sử dụng của PVCs và PVC đang được sử dụng bởi Pods.
  • Quản Lý Logs: Đảm bảo rằng logs của StatefulSet được lưu trữ và quản lý một cách hiệu quả để dễ dàng truy xuất và phân tích.

7. Giám Sát và Quản Lý Ứng Dụng Trạng Thái

7.1. Sử Dụng Prometheus và Grafana

  • Prometheus: Thu thập và lưu trữ các metrics về hiệu suất và trạng thái của ứng dụng và cluster.
  • Grafana: Trực quan hóa dữ liệu từ Prometheus thông qua các dashboard tùy chỉnh, giúp bạn dễ dàng theo dõi và phân tích các chỉ số tài nguyên.

Ví Dụ: Cài Đặt Prometheus và Grafana với Helm

helm install prometheus prometheus-community/prometheus -n monitoring --create-namespace
helm install grafana grafana/grafana -n monitoring

7.2. Sử Dụng ELK Stack

  • Elasticsearch: Lưu trữ và tìm kiếm logs.
  • Logstash: Thu thập và xử lý logs từ các nguồn khác nhau.
  • Kibana: Trực quan hóa logs thông qua giao diện web.

Ví Dụ: Triển Khai ELK Stack với Helm

helm install elasticsearch elastic/elasticsearch -n logging --create-namespace
helm install kibana elastic/kibana -n logging
helm install logstash elastic/logstash -n logging

8. Kết Luận

StatefulSet là một công cụ mạnh mẽ trong Kubernetes để quản lý các ứng dụng trạng thái, đảm bảo tính nhất quán và ổn định của các Pods. Bằng cách sử dụng StatefulSet kết hợp với PersistentVolumesServices, bạn có thể triển khai các ứng dụng như WordPress và MySQL, Cassandra, và ZooKeeper một cách hiệu quả và đáng tin cậy.

Những Điểm Chính:

  • StatefulSet: Quản lý Pods với danh tính ổn định và lưu trữ bền vững.
  • PersistentVolumes và PersistentVolumeClaims: Đảm bảo dữ liệu của ứng dụng được lưu trữ một cách bền vững.
  • Services với External IP: Expose ứng dụng ra ngoài cluster để truy cập từ bên ngoài.
  • Best Practices: Áp dụng các phương pháp tốt nhất để quản lý và bảo mật ứng dụng trạng thái.
  • Giám Sát và Logging: Sử dụng các công cụ giám sát để theo dõi và quản lý ứng dụng một cách hiệu quả.

9. Tiếp Theo

  • Deploy an App trên Kubernetes với Minikube: Hướng dẫn chi tiết cách triển khai và quản lý ứng dụng sử dụng Minikube.
  • Expose Your App Publicly trên Kubernetes: Hướng dẫn cách sử dụng Service để expose ứng dụng ra ngoài cluster.
  • Scale Your App trên Kubernetes: Hướng dẫn chi tiết cách scale ứng dụng sử dụng kubectl và Horizontal Pod Autoscaler.
  • Update Your App trên Kubernetes: Hướng dẫn cách thực hiện Rolling Update cho ứng dụng sử dụng kubectl.
  • Security trên Kubernetes: Hướng dẫn cách áp dụng các tiêu chuẩn bảo mật và giới hạn quyền truy cập trong cluster.
  • Sử Dụng Helm để Quản Lý Các Ứng Dụng Kubernetes: Tìm hiểu cách sử dụng Helm charts để dễ dàng triển khai và quản lý các ứng dụng phức tạp.

10. Tài Nguyên Tham Khảo

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *