Scheduling, Preemption, và Eviction trong Kubernetes

Scheduling, Preemption, và Eviction trong Kubernetes

1. Giới Thiệu Về Scheduling, Preemption và Eviction Trong Kubernetes

Kubernetes là nền tảng mã nguồn mở hàng đầu cho việc tự động hóa triển khai, mở rộng và quản lý các ứng dụng containerized. Trong Kubernetes, scheduling, preemption, và eviction là những khái niệm quan trọng liên quan đến việc quản lý tài nguyên và đảm bảo rằng các ứng dụng luôn hoạt động hiệu quả và ổn định.

  • Scheduling: Quá trình Kubernetes đảm bảo rằng Pods được phân bổ vào các Nodes phù hợp để kubelet có thể chạy chúng.
  • Preemption: Quá trình chấm dứt các Pods có Priority thấp hơn để dành chỗ cho Pods có Priority cao hơn.
  • Eviction: Quá trình chấm dứt một hoặc nhiều Pods trên Nodes khi tài nguyên trên Node bị thiếu hụt hoặc khi xảy ra các sự cố khác.

Bài viết này sẽ cung cấp một cái nhìn toàn diện về cách Kubernetes quản lý scheduling, preemption và eviction, cùng với các best practices để tối ưu hóa hiệu suất và bảo mật của cluster.


2. Scheduling Trong Kubernetes

2.1. Kubernetes Scheduler

Kubernetes Scheduler là một thành phần quan trọng trong control plane, chịu trách nhiệm phân bổ Pods vào các Nodes phù hợp dựa trên các yếu tố như tài nguyên yêu cầu, chính sách, và các ràng buộc khác. Scheduler sử dụng thuật toán để lựa chọn Node tối ưu cho mỗi Pod, đảm bảo hiệu quả sử dụng tài nguyên và đáp ứng yêu cầu ứng dụng.

Vai trò chính của Scheduler:

  • Phân bổ Pods: Chọn Node thích hợp để chạy Pods dựa trên tài nguyên sẵn có và yêu cầu của Pods.
  • Tuân thủ chính sách: Đảm bảo rằng các Pods được triển khai theo các chính sách bảo mật và ràng buộc đã định.
  • Cân bằng tải: Phân phối Pods một cách cân bằng trên các Nodes để tối ưu hóa hiệu suất và khả năng chịu lỗi.

2.2. Assigning Pods to Nodes

Quá trình gán Pods vào Nodes được Scheduler thực hiện dựa trên nhiều tiêu chí, bao gồm:

  • Tài nguyên: CPU, Memory, và các tài nguyên mở rộng.
  • Ràng buộc về vị trí: Topology Spread Constraints, Affinity/Anti-Affinity.
  • Chính sách về taints và tolerations: Đảm bảo Pods có thể chạy trên Nodes đã được cấu hình taints.
  • Chính sách về ưu tiên: Pods có Priority cao sẽ được ưu tiên gán Node.

Ví dụ về yêu cầu tài nguyên trong Pod:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

2.3. Pod Overhead

Pod Overhead là một khái niệm liên quan đến việc thêm các tài nguyên bổ sung cho mỗi Pod để đảm bảo rằng các tài nguyên hệ thống được quản lý hiệu quả. Pod Overhead thường bao gồm tài nguyên cần thiết cho các tiện ích bổ sung như init containers hoặc sidecar containers.

Ví dụ về Pod Overhead:

apiVersion: v1
kind: Pod
metadata:
  name: overhead-pod
spec:
  overhead:
    cpu: "100m"
    memory: "200Mi"
  containers:
  - name: main-container
    image: my-app:latest
    resources:
      requests:
        memory: "256Mi"
        cpu: "500m"
      limits:
        memory: "512Mi"
        cpu: "1000m"

2.4. Pod Topology Spread Constraints

Pod Topology Spread Constraints giúp đảm bảo rằng các Pods được phân bổ một cách cân bằng trên các Node hoặc các khu vực khác nhau trong cluster, giảm thiểu rủi ro về sự cố đồng thời và tăng tính sẵn sàng của ứng dụng.

Ví dụ về Pod Topology Spread Constraints:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spread-deployment
spec:
  replicas: 6
  selector:
    matchLabels:
      app: spread-app
  template:
    metadata:
      labels:
        app: spread-app
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "kubernetes.io/hostname"
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: spread-app
      containers:
      - name: spread-container
        image: nginx

2.5. Taints and Tolerations

Taints and Tolerations là một cơ chế trong Kubernetes cho phép Nodes từ chối hoặc chấp nhận các Pods dựa trên các điều kiện nhất định. Taints được áp dụng lên Nodes để ngăn không cho Pods không có tolerations phù hợp chạy trên đó.

Ví dụ về Taints:

kubectl taint nodes node1 key=value:NoSchedule

Ví dụ về Tolerations trong Pod:

apiVersion: v1
kind: Pod
metadata:
  name: tainted-pod
spec:
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
  containers:
  - name: my-container
    image: nginx

2.6. Scheduling Framework

Scheduling Framework là một kiến trúc linh hoạt của Kubernetes Scheduler cho phép mở rộng và tùy chỉnh quá trình scheduling. Framework này bao gồm các plugins được gọi tại các giai đoạn khác nhau của quá trình scheduling, giúp bạn thêm các logic tùy chỉnh theo nhu cầu.

Các giai đoạn chính trong Scheduling Framework:

  • Filter: Loại bỏ các Nodes không phù hợp dựa trên các tiêu chí.
  • Score: Đánh giá và chấm điểm các Nodes phù hợp để lựa chọn Node tối ưu.
  • Bind: Gán Pod vào Node được chọn.

Ví dụ về việc sử dụng một plugin trong Scheduling Framework:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      filter:
        enabled:
          - Name: NodeUnschedulable
      score:
        enabled:
          - Name: LeastRequested

2.7. Dynamic Resource Allocation

Dynamic Resource Allocation là khả năng của Kubernetes để tự động điều chỉnh việc phân bổ tài nguyên dựa trên nhu cầu thực tế của ứng

cation. Điều này bao gồm việc mở rộng (scaling) hoặc thu nhỏ (scaling down) số lượng Pods dựa trên các chỉ số tài nguyên như CPU và Memory.

Ví dụ về Horizontal Pod Autoscaler:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: example-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: example-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

2.8. Scheduler Performance Tuning

Để đảm bảo Kubernetes Scheduler hoạt động hiệu quả, việc tối ưu hóa hiệu suất là cần thiết. Điều này bao gồm:

  • Cấu hình Scheduler: Điều chỉnh các tham số cấu hình để phù hợp với kích thước và nhu cầu của cluster.
  • Caching: Sử dụng caching để giảm thời gian xử lý các Pods đã được phân bổ trước đó.
  • Parallel Processing: Kích hoạt xử lý song song để tăng tốc độ scheduling.

Ví dụ về cấu hình Scheduler với cache:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      queueSort:
        enabled:
          - Name: PrioritySort
      bind:
        enabled:
          - Name: DefaultBinder
    leaderElection:
      leaderElect: true

2.9. Resource Bin Packing for Extended Resources

Resource Bin Packing là kỹ thuật phân bổ tài nguyên tối ưu, nhằm tối đa hóa việc sử dụng tài nguyên sẵn có bằng cách “đóng gói” các Pods vào Nodes một cách hiệu quả. Điều này đặc biệt quan trọng khi sử dụng các tài nguyên mở rộng (extended resources) như GPUs.

Ví dụ về sử dụng GPU trong Pod:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
  - name: gpu-container
    image: tensorflow:latest-gpu
    resources:
      limits:
        nvidia.com/gpu: 1

2.10. Pod Scheduling Readiness

Pod Scheduling Readiness đảm bảo rằng Pods chỉ được lên lịch khi chúng sẵn sàng để hoạt động. Điều này bao gồm việc kiểm tra các điều kiện cần thiết trước khi Pod được gán vào Node.

Ví dụ về Pod Scheduling Readiness với Init Containers:

apiVersion: v1
kind: Pod
metadata:
  name: ready-pod
spec:
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'echo Initializing... && sleep 5']
  containers:
  - name: myservice
    image: nginx

2.11. Descheduler

Descheduler là một công cụ cho phép bạn di chuyển Pods giữa các Nodes để tối ưu hóa việc sử dụng tài nguyên hoặc đáp ứng các chính sách mới. Nó thực hiện các hành động như cân bằng tải, loại bỏ Pods bị thiếu tài nguyên, hoặc tái phân bổ Pods dựa trên các thay đổi trong cluster.

Cài đặt Descheduler bằng Helm:

helm repo add descheduler https://kubernetes-sigs.github.io/descheduler/
helm repo update
helm install descheduler descheduler/descheduler

Ví dụ về cấu hình Descheduler:

apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
  RemovePodsViolatingNodeAffinity:
    enabled: true
    params:
      nodeAffinityType: "requiredDuringSchedulingIgnoredDuringExecution"

3. Pod Disruption Trong Kubernetes

Pod Disruption là quá trình chấm dứt Pods trên các Nodes, có thể xảy ra một cách tự nguyện hoặc không tự nguyện.

3.1. Voluntary Disruptions

Voluntary disruptions là các hành động được khởi xướng bởi người dùng hoặc quản trị viên cluster nhằm thực hiện các nhiệm vụ bảo trì hoặc cập nhật mà không ảnh hưởng đến dịch vụ.

Ví dụ về Voluntary disruptions:

  • Rolling Updates: Cập nhật phiên bản mới của ứng dụng.
  • Pod Eviction: Xóa Pods để cập nhật Node hoặc thay đổi cấu hình.
  • Node Maintenance: Chạy các lệnh bảo trì trên Node mà không gây gián đoạn dịch vụ.

3.2. Involuntary Disruptions

Involuntary disruptions xảy ra khi Pods bị chấm dứt do các vấn đề không lường trước như hết tài nguyên, lỗi phần cứng, hoặc sự cố mạng.

Ví dụ về Involuntary disruptions:

  • Node Failure: Node bị mất kết nối hoặc gặp sự cố phần cứng.
  • Resource Pressure: Node chạy hết CPU hoặc Memory, dẫn đến việc Kubernetes cần giải phóng tài nguyên bằng cách chấm dứt Pods.
  • Accidental Deletion: Xóa Pods hoặc các tài nguyên khác một cách vô tình.

4. Pod Priority và Preemption

4.1. Pod Priority

Pod Priority xác định mức độ ưu tiên của Pods trong quá trình scheduling và preemption. Pods có Priority cao hơn sẽ được ưu tiên lên lịch trước các Pods có Priority thấp hơn.

Ví dụ về định nghĩa PriorityClass:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000
globalDefault: false
description: "This priority class should be used for high priority pods."

Ví dụ về Pod sử dụng PriorityClass:

apiVersion: v1
kind: Pod
metadata:
  name: high-priority-pod
spec:
  priorityClassName: high-priority
  containers:
  - name: my-container
    image: nginx

4.2. Preemption

Preemption là quá trình Kubernetes chấm dứt các Pods có Priority thấp hơn để dành chỗ cho các Pods có Priority cao hơn. Điều này đảm bảo rằng các ứng dụng quan trọng luôn được chạy trên cluster.

Quy trình Preemption:

  1. Pod với Priority cao hơn được yêu cầu: Scheduler nhận thấy rằng không có Node nào có đủ tài nguyên để chạy Pod này.
  2. Tìm Pods có Priority thấp hơn: Scheduler xác định các Pods hiện tại trên các Nodes có Priority thấp hơn để có thể chấm dứt.
  3. Chấm dứt Pods thấp hơn: Các Pods bị chọn sẽ bị chấm dứt để giải phóng tài nguyên.
  4. Lên lịch Pod Priority cao hơn: Pod mới sẽ được lên lịch trên Node vừa giải phóng tài nguyên.

4.3. Node-pressure Eviction

Node-pressure Eviction xảy ra khi Node gặp áp lực tài nguyên như thiếu CPU, Memory, hoặc Disk. Kubernetes sẽ tự động chấm dứt các Pods không quan trọng để giải phóng tài nguyên.

Chi tiết về Node-pressure Eviction:

  • Eviction Thresholds: Đặt các ngưỡng tài nguyên mà khi vượt quá, Kubernetes sẽ bắt đầu chấm dứt Pods.
  • Eviction Priorities: Chấm dứt Pods dựa trên các tiêu chí ưu tiên như QoS (Quality of Service) và Priority.

Ví dụ về cấu hình eviction thresholds:

kubectl edit node <node-name>

Trong tệp cấu hình Node, bạn có thể thiết lập các tham số eviction thresholds như:

evictionHard:
  memory.available: "200Mi"
  nodefs.available: "10%"
  nodefs.inodesFree: "5%"

4.4. API-initiated Eviction

API-initiated Eviction là quá trình chấm dứt Pods thông qua API Kubernetes, thường được thực hiện bởi người dùng hoặc các công cụ quản lý để thực hiện các hành động bảo trì hoặc khắc phục sự cố.

Ví dụ về API-initiated Eviction:

kubectl drain <node-name> --ignore-daemonsets --delete-local-data

Lệnh này sẽ chấm dứt tất cả các Pods trên Node, ngoại trừ DaemonSets và Pods sử dụng dữ liệu cục bộ, để chuẩn bị cho bảo trì Node.


5. Best Practices Cho Scheduling, Preemption và Eviction Trong Kubernetes

Để đảm bảo rằng việc scheduling, preemption và eviction diễn ra một cách hiệu quả và an toàn, hãy tuân thủ các best practices sau:

5.1. Sử Dụng Pod Priority và Preemption Một Cách Thông Minh

  • Đặt Priority hợp lý: Xác định rõ ràng các Pods quan trọng và đặt Priority cao cho chúng.
  • Tránh sử dụng Preemption không cần thiết: Chỉ sử dụng Preemption cho các Pods thực sự cần thiết để tránh gây gián đoạn không mong muốn.

5.2. Thiết Lập Resource Requests và Limits Chính Xác

  • Xác định tài nguyên chính xác: Đặt các yêu cầu (requests) và giới hạn (limits) cho CPU và Memory một cách chính xác để Scheduler có thể phân bổ tài nguyên hiệu quả.
  • Sử dụng Resource Quotas: Giới hạn tổng số tài nguyên mà một namespace có thể sử dụng để tránh tình trạng một namespace chiếm dụng quá nhiều tài nguyên.

5.3. Sử Dụng Taints và Tolerations Để Quản Lý Node

  • Taints cho Nodes: Sử dụng taints để ngăn Pods không mong muốn chạy trên Nodes cụ thể.
  • Tolerations cho Pods: Sử dụng tolerations để cho phép Pods chạy trên Nodes có taints phù hợp.

5.4. Áp Dụng Pod Topology Spread Constraints

  • Đảm bảo cân bằng tải: Sử dụng Pod Topology Spread Constraints để phân bổ Pods một cách cân bằng trên các Node hoặc khu vực khác nhau.
  • Tăng tính sẵn sàng: Giảm thiểu rủi ro mất dịch vụ khi một khu vực hoặc Node gặp sự cố.

5.5. Sử Dụng Descheduler Để Cải Thiện Phân Bổ Pods

  • Rebalance Pods: Sử dụng Descheduler để cân bằng lại Pods trên các Nodes khi cluster thay đổi hoặc khi có sự bất cân bằng về tài nguyên.
  • Tuân thủ chính sách: Đảm bảo rằng các Pods tuân thủ các chính sách mới sau khi thay đổi cấu hình.

5.6. Giám Sát và Đánh Giá Hiệu Suất Scheduler

  • Theo dõi logs Scheduler: Sử dụng các công cụ giám sát như Prometheus và Grafana để theo dõi hoạt động của Scheduler.
  • Tối ưu hóa cấu hình Scheduler: Điều chỉnh các tham số cấu hình Scheduler dựa trên hiệu suất và nhu cầu của cluster.

5.7. Đảm Bảo Cluster Stability Với Pod Disruption Budgets (PDBs)

  • Thiết lập PDBs: Định nghĩa Pod Disruption Budgets để giới hạn số lượng Pods có thể bị chấm dứt đồng thời, đảm bảo rằng dịch vụ không bị gián đoạn quá mức.

Ví dụ về Pod Disruption Budget:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: pdb-example
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: my-app

6. Giám Sát và Quản Lý Scheduling, Preemption và Eviction

Để đảm bảo rằng các quy trình scheduling, preemption và eviction hoạt động hiệu quả và không gây ra sự cố, việc giám sát và quản lý là cần thiết.

6.1. Sử Dụng Prometheus và Grafana

  • Prometheus: Thu thập và lưu trữ các metrics về hoạt động của Scheduler, Preemption và Eviction. Bạn có thể theo dõi các chỉ số như thời gian scheduling, số lượng preempted Pods, và số lượng evicted Pods.
  • Grafana: Trực quan hóa dữ liệu từ Prometheus thông qua các dashboard, giúp bạn dễ dàng theo dõi và phân tích hiệu suất của các quy trình này.

Ví dụ về Dashboard Grafana cho Scheduler:

  • Scheduling Latency: Thời gian từ khi Pod được tạo đến khi nó được lên lịch trên Node.
  • Preemption Count: Số lượng Pods bị preempted trong một khoảng thời gian nhất định.
  • Eviction Events: Số lượng Pods bị chấm dứt do eviction.

6.2. Kiểm Tra và Báo Cáo Việc Tuân Thủ Chính Sách

  • Automated Compliance Checks: Sử dụng các công cụ như Open Policy Agent (OPA) để tự động kiểm tra việc tuân thủ các chính sách về scheduling, preemption và eviction.
  • Alerting: Thiết lập các cảnh báo khi có sự cố liên quan đến scheduling, preemption hoặc eviction, giúp bạn phản ứng kịp thời để giải quyết vấn đề.

6.3. Đánh Giá và Điều Chỉnh Chính Sách Định Kỳ

  • Periodic Reviews: Định kỳ đánh giá lại các chính sách về scheduling, preemption và eviction để đảm bảo rằng chúng vẫn phù hợp với nhu cầu kinh doanh và kỹ thuật.
  • Adjust Limits and Quotas: Điều chỉnh các giới hạn tài nguyên và quota dựa trên thay đổi trong nhu cầu sử dụng tài nguyên và sự phát triển của ứng dụng.

7. Kết Luận

Scheduling, Preemption và Eviction là những khía cạnh quan trọng trong quản lý tài nguyên và đảm bảo hiệu suất của cluster Kubernetes. Bằng cách hiểu rõ cách Kubernetes thực hiện các quy trình này và áp dụng các best practices, bạn có thể tối ưu hóa việc sử dụng tài nguyên, đảm bảo rằng các ứng dụng quan trọng luôn được ưu tiên và cluster hoạt động ổn định.

Những Điểm Chính:

  • Kubernetes Scheduler: Quản lý việc phân bổ Pods vào Nodes một cách hiệu quả dựa trên yêu cầu tài nguyên và các ràng buộc.
  • Pod Priority và Preemption: Đảm bảo rằng các Pods có Priority cao luôn được ưu tiên chạy trên cluster.
  • Eviction: Quản lý việc chấm dứt Pods khi Node gặp áp lực tài nguyên hoặc khi thực hiện bảo trì.
  • Best Practices: Sử dụng Limit Ranges, Resource Quotas, Taints và Tolerations, và Descheduler để tối ưu hóa và bảo mật cluster.
  • Giám Sát và Quản Lý: Sử dụng các công cụ giám sát như Prometheus và Grafana để theo dõi hiệu suất và phát hiện sớm các vấn đề liên quan đến scheduling, preemption và eviction.

Chúc bạn thành công trong việc quản lý và tối ưu hóa cluster Kubernetes của mình! Nếu bạn có bất kỳ câu hỏi nào thêm hoặc cần hỗ trợ, đừng ngần ngại tham khảo tài liệu chính thức của Kubernetes hoặc tham gia cộng đồng Kubernetes để được giúp đỡ.


8. 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 *