+4

Lựa chọn Deployment, StatefulSet hay DaemonSet cho ứng dụng Kubernetes của bạn?

Lời mở đầu

Trong Kubernetes, Pod là đơn vị triển khai cơ bản nhất, đóng vai trò chứa các container của ứng dụng. Tuy nhiên, chỉ với Pod không thì không đủ để quản lý và duy trì các ứng dụng phức tạp trong một môi trường sản xuất. Điều này đặt ra nhu cầu phải có các công cụ và đối tượng khác để quản lý các nhóm Pod một cách hiệu quả. Từ đây, các đối tượng Deployment, StatefulSet và DaemonSet xuất hiện như những công cụ quan trọng trong việc điều chỉnh và quản lý Pod. Chúng cung cấp các cơ chế và chiến lược khác nhau để quản lý lifecycle, tính sẵn sàng và sự phân tán của các Pod trên Kubernetes. Việc hiểu rõ vai trò và ứng dụng của chúng sẽ giúp bạn tự tin hơn trong việc lựa chọn và triển khai ứng dụng trên nền tảng Kubernetes phức tạp này.

Trong bài viết này, mình sẽ cùng bạn làm rõ các khái niệm, cách hoạt động, khi nào nên sử dụng và khi nào không nên sử dụng từng loại đối tượng này nhé 🫡

## Deployment

Deployment là một đối tượng trong Kubernetes dùng để quản lý việc triển khai và mở rộng các ứng dụng không trạng thái (stateless applications). Nó giúp duy trì số lượng bản sao (replica) của các pod luôn sẵn sàng và đảm bảo rằng các pod đó đang chạy phiên bản đúng của ứng dụng.

image.png

Deployment quản lý các ReplicaSet, và mỗi ReplicaSet quản lý một nhóm các pod. Khi bạn tạo hoặc cập nhật một Deployment, Kubernetes sẽ tự động tạo hoặc cập nhật ReplicaSet tương ứng. Deployment sẽ đảm bảo số lượng pod luôn đạt yêu cầu bằng cách thêm hoặc xóa pod khi cần thiết.

Ví dụ: bạn có một ứng dụng web đơn giản cần triển khai trên Kubernetes. Bạn muốn đảm bảo rằng luôn có ít nhất 2 bản sao của ứng dụng này đang chạy. Bạn có thể sử dụng Deployment để quản lý các bản sao này. Nếu một pod bị lỗi, Deployment sẽ tự động tạo một pod mới để thay thế, đảm bảo ứng dụng của bạn luôn sẵn sàng phục vụ người dùng.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:latest
        ports:
        - containerPort: 80

Vậy thì chúng ta nên sử dụng Deployment khi nào nhỉ?

  • Khi bạn cần triển khai các ứng dụng không trạng thái (stateless applications).
  • Khi bạn cần khả năng tự động cập nhật và triển khai phiên bản mới của ứng dụng.
  • Khi bạn cần khả năng tự động quay lui (rollback) về phiên bản trước đó nếu có lỗi xảy ra.

Deployment sẽ không phù hợp khi:

  • Khi bạn cần quản lý các ứng dụng có trạng thái (stateful applications) hoặc các ứng dụng yêu cầu dữ liệu lưu trữ ổn định. Do pod trong Deployment có tính chất tạm thời, khi pod được lên lịch lại hoặc xóa, nó sẽ mất tất cả trạng thái và dữ liệu liên quan nếu được lưu trữ cục bộ. Việc gắn PV (Persistent Volumn) cho 1 deployment để lưu trạng thái triển khai cũng có thể là 1 cách make stateful, tuy nhiên cách này cũng ít được sử dụng vì các pod sẽ chia sẻ chung dữ liệu với nhau do dùng cùng 1 volume.
  • Khi bạn cần đảm bảo mỗi node trong cluster chỉ cần chạy một pod của ứng dụng, lúc này chỉ cần sử dụng tới tài nguyên pod thôi là đủ rồi.

## StatefulSet

StatefulSet là một loại Controller trong Kubernetes, được sử dụng để quản lý việc triển khai và vận hành các ứng dụng có trạng thái (stateful applications). Nó đảm bảo rằng các pod trong một StatefulSet luôn được duy trì đúng số lượng mong muốn, đồng thời lưu giữ trạng thái và dữ liệu của ứng dụng được an toàn.

image.png

StatefulSet quản lý các pod với một danh tính cố định. Các pod này được tạo ra theo thứ tự và được xóa bỏ ngược lại. Dữ liệu của mỗi pod là độc lập và được lưu trữ trong PersistentVolume và sẽ được gắn lại vào pod tương ứng nếu pod đó được tạo lại.

Mỗi Pod được tạo ra bởi StatefulSet sẽ được gán với một index, index này sẽ được sử dụng để định danh cho mỗi Pod. Và danh tính cố định của Pod sẽ được đặt theo kiểu <statefulset name>-<index>, chứ không phải random như của ReplicaSet. Kể cả khi bạn xóa 1 pod được quản lý bởi StatefulSet thì nó sẽ tạo lại 1 pod mới thay thế thằng cũ với tên và hostname "như chưa hề có cuộc chia ly" :v

image.png

Ví dụ: Bạn đang cần triển khai một cụm (cluster) cơ sở dữ liệu MySQL trên Kubernetes. Mỗi pod trong cụm này cần có dữ liệu riêng và phải duy trì thứ tự khởi tạo chính xác để đảm bảo tính toàn vẹn của dữ liệu. StatefulSet sẽ giúp bạn quản lý các pod này, đảm bảo rằng mỗi pod có một danh tính duy nhất và dữ liệu của chúng được lưu trữ ổn định trên PersistentVolume.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-statefulset
spec:
  serviceName: "mysql"
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password"
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

Vậy thì chúng ta nên sử dụng StatefulSet khi nào?

  • Khi bạn cần triển khai các ứng dụng có trạng thái, như cơ sở dữ liệu, Kafka, Hadoop, Rook hoặc thậm chí là local persistent volume.
  • Khi bạn cần đảm bảo rằng mỗi pod có một danh tính cố định và dữ liệu của chúng không bị mất đi khi pod được tạo lại.
  • Khi bạn cần triển khai các ứng dụng yêu cầu khởi tạo và xóa bỏ theo thứ tự nhất định.

Không nên sử dụng khi nào?

  • Khi bạn cần triển khai các ứng dụng không trạng thái.
  • Khi bạn không cần dữ liệu lưu trữ ổn định hoặc danh tính cố định cho các pod.
  • Giới hạn triển khai tuần tự: Việc triển khai và mở rộng quy mô trong StatefulSets diễn ra tuần tự, hạn chế tính song song có sẵn so với các giải pháp thay thế không trạng thái, có khả năng ảnh hưởng đến tốc độ triển khai tổng thể.

## DaemonSet

DaemonSet cũng là một controller trong Kubernetes, nó dùng để đảm bảo rằng một bản sao của một pod sẽ chạy trên mỗi node trong cluster. Nó thường được sử dụng để triển khai các ứng dụng cần chạy trên mọi node, chẳng hạn như các ứng dụng giám sát hoặc thu thập log.

image.png

DaemonSet quản lý các pod và đảm bảo rằng mỗi node trong cluster sẽ có một pod đang chạy, số lượng Pod sẽ tương ứng với số Node được chọn, nó sẽ không có thuộc tính replicas. Khi một node mới được thêm vào cluster, một pod mới sẽ được tạo ra trên node đó. Khi một node bị xóa khỏi cluster, pod tương ứng trên node đó cũng sẽ bị xóa bỏ.

Ví dụ: Trong trường hợp bạn cần triển khai một công cụ giám sát như Prometheus Node Exporter để thu thập số liệu từ tất cả các node trong cluster. Sử dụng DaemonSet, bạn có thể đảm bảo rằng mỗi node đều có một pod của Node Exporter đang chạy, giúp bạn thu thập dữ liệu giám sát từ toàn bộ cluster. Cụ thể, bạn chỉ muốn giám sát các Node có label type=monitor, hãy bổ sung thêm vào thuộc tính nodeSelector của DaemonSets như config dưới đây:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter-daemonset
spec:
  selector:
    matchLabels:
      name: node-exporter
  template:
    metadata:
      labels:
        name: node-exporter
    spec:
      nodeSelector:
        type: monitor
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest
        ports:
        - containerPort: 9100

Một số trường hợp phù hợp sử dụng DaemonSet:

  • Giám sát và thu thập log: Khi bạn cần triển khai các công cụ giám sát như Prometheus Node Exporter hoặc Fluentd để thu thập log từ tất cả các node trong cluster.
  • Dịch vụ hệ thống cần có mặt trên tất cả các node: Khi bạn cần triển khai các dịch vụ hệ thống như kube-proxy hoặc các dịch vụ cần có mặt trên mọi node để đảm bảo chức năng của cluster.
  • Chạy các công cụ bảo mật và quản lý: Khi bạn cần triển khai các công cụ bảo mật như các agents của hệ thống bảo mật (e.g., Falco) hoặc các công cụ quản lý tài nguyên như các agents của hệ thống phân phối tài nguyên.

DaemonSet không phù hợp khi:

  • Ứng dụng không cần chạy trên mọi node: Khi ứng dụng của bạn không cần thiết phải chạy trên mỗi node trong cluster. Trong trường hợp này, Deployment hoặc StatefulSet có thể là lựa chọn tốt hơn.
  • Yêu cầu mở rộng theo nhu cầu tải: Khi bạn cần ứng dụng có thể mở rộng số lượng pod dựa trên nhu cầu tải. DaemonSet không hỗ trợ tự động mở rộng theo nhu cầu tải.
  • Ứng dụng có trạng thái phức tạp: Khi bạn cần triển khai các ứng dụng có trạng thái mà cần duy trì dữ liệu ổn định và danh tính cố định cho mỗi pod. StatefulSet sẽ phù hợp hơn cho các trường hợp này.

Tổng kết

Việc chọn đúng loại đối tượng Kubernetes để quản lý các ứng dụng container của bạn là rất quan trọng. Deployment, StatefulSet và DaemonSet đều có những đặc điểm riêng và phù hợp với các trường hợp sử dụng khác nhau. Deployment là lựa chọn tốt cho các ứng dụng không trạng thái, StatefulSet là lựa chọn tốt cho các ứng dụng có trạng thái và DaemonSet là lựa chọn tốt cho các agent chạy trên mỗi node trong cluster. Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về từng loại đối tượng này và có thể áp dụng chúng một cách hiệu quả trong các dự án Kubernetes của mình.

Cảm ơn bạn đã dành thời gian đọc bài. Upvote nếu thấy bài viết này có ích và để lại comment nếu bạn muốn thảo luận thêm về chủ đề này nhé 🤩

Tham khảo


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í