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 StatefulSet và PersistentVolumes để đả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 PersistentVolumes và Services, 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
- Kubernetes Documentation – StatefulSet
- Kubernetes Documentation – Services
- Kubernetes Documentation – ConfigMaps
- Kubernetes Documentation – PersistentVolumes
- Prometheus Documentation
- Grafana Documentation
- Helm Documentation
- ELK Stack Documentation
- The Kubernetes Book
- Kubernetes Up & Running
- Cassandra Documentation
- ZooKeeper Documentation
- StatefulSet Best Practices