Dọn dẹp Kubernetes: Sử dụng Kube-janitor để cắt giảm chi phí Dev và Staging

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Chi phí của các tài nguyên “ma” trong Kubernetes

Việc vận hành một cụm Kubernetes cho một đội ngũ kỹ thuật đang phát triển cuối cùng sẽ dẫn đến tình trạng tràn lan tài nguyên. Để giải quyết vấn đề quản lý, bạn có thể cần xem xét bảo mật multi-tenancy trên Kubernetes. Trong các môi trường Dev hoặc Staging bận rộn, các lập trình viên liên tục tạo mới các namespace để kiểm thử tính năng hoặc xem trước PR (Pull Request). Rắc rối bắt đầu khi công việc kết thúc nhưng các tài nguyên vẫn còn đó.

Các namespace bị bỏ quên không chỉ nằm yên đó. Chúng tiêu tốn địa chỉ IP của VPC, chiếm dụng các slot của load balancer và giữ các phần CPU và bộ nhớ (reservations). Trên các dịch vụ được quản lý như EKS hoặc GKE, sự lãng phí này rất tốn kém. Trong một đợt kiểm tra gần đây, tôi đã tìm thấy một cụm máy chủ mà 40% các node đang hỗ trợ cho các dự án đã kết thúc từ nhiều tuần trước. Điều đó đồng nghĩa với việc hàng trăm đô la bị lãng phí mỗi tháng cho các instance EC2 nhàn rỗi.

Tại sao dọn dẹp thủ công và script tự viết lại thất bại

Phản xạ đầu tiên của hầu hết các đội ngũ là tiếp cận thủ công. Bạn có thể yêu cầu một kỹ sư cao cấp dành các buổi chiều thứ Sáu để săn tìm các namespace cũ. Đây là một cách sử dụng thời gian kém hiệu quả đối với các kỹ sư đắt giá. Cuối cùng, ai đó sẽ viết một script bash “nhanh” để chạy kubectl delete thông qua một cron job.

Các script tự viết thường mong manh và nguy hiểm. Chúng thiếu nhật ký (logging) chi tiết và hiếm khi xử lý tốt các phụ thuộc phức tạp. Một lỗi regex nhỏ có thể vô tình xóa sạch cơ sở dữ liệu production của bạn. Chúng ta cần một cách tiếp cận mang tính khai báo (declarative) và chuẩn Kubernetes (Kubernetes-native) để quản lý vòng đời của đối tượng. Kube-janitor giải quyết vấn đề này bằng cách coi việc dọn dẹp là một chính sách (policy), không phải là một công việc vặt.

Cài đặt Kube-janitor

Kube-janitor là một controller nhẹ được tạo bởi Zalando. Nó giám sát cụm của bạn và xóa các tài nguyên dựa trên các quy tắc hoặc metadata cụ thể. Không giống như một script chạy mù quáng, nó hiểu các đối tượng Kubernetes và tôn trọng các ranh giới an toàn.

Tôi khuyên bạn nên sử dụng Helm để cài đặt nhằm quản lý các quyền RBAC một cách chính xác. Chạy các lệnh sau để bắt đầu:

# Thêm repository của Zalando
helm repo add kube-janitor https://zalando.github.io/kube-janitor/
helm repo update

# Cài đặt controller
helm install kube-janitor kube-janitor/kube-janitor \
  --namespace kube-janitor \
  --create-namespace

Kube-janitor sẽ ở trạng thái chờ sau khi cài đặt. Nó sẽ không xóa bất cứ thứ gì cho đến khi bạn cung cấp các hướng dẫn cụ thể thông qua ConfigMaps hoặc các annotation cho tài nguyên.

Cấu hình các chính sách dọn dẹp

Sử dụng annotation là cách hiệu quả nhất để quản lý tài nguyên. Điều này chuyển trách nhiệm về vòng đời tài nguyên cho chính người đã tạo ra nó. Tôi đã sử dụng phương pháp này trong nhiều cụm production và đạt được thành công lớn.

1. Thiết lập thời gian tồn tại (TTL)

Bạn có thể yêu cầu Kube-janitor xóa một namespace đúng 4 giờ sau khi nó được tạo. Điều này rất lý tưởng cho các pipeline CI/CD tạo ra các môi trường xem trước ngắn hạn. Đơn giản chỉ cần thêm annotation janitor/ttl vào manifest của bạn.

apiVersion: v1
kind: Namespace
metadata:
  name: feature-x-preview
  annotations:
    janitor/ttl: "4h"
spec: {}

2. Thiết lập ngày hết hạn cụ thể

Đôi khi bạn biết chính xác khi nào một giai đoạn thử nghiệm kết thúc, chẳng hạn như ngày cuối cùng của một sprint. Trong những trường hợp này, hãy sử dụng mốc thời gian tuyệt đối. Điều này đảm bảo tài nguyên sẽ biến mất ngay cả khi bạn không có mặt ở văn phòng.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: temporary-worker
  annotations:
    janitor/expires: "2024-12-31T23:59:59Z"
spec:
  # ... cấu hình deployment

3. Tạo các quy tắc toàn cục

Thực tế là các lập trình viên thường quên thêm annotation. Bạn có thể định nghĩa các quy tắc toàn cục trong tệp values.yaml của mình để xử lý những thiếu sót này. Ví dụ, bạn có thể nhắm mục tiêu vào bất kỳ namespace nào bắt đầu bằng “test-” và đã tồn tại hơn bảy ngày.

rules:
  - name: "cleanup-test-namespaces"
    resources:
      - namespaces
    condition: |
      metadata.name =~ "^test-.*" and age > "7d"
    action: delete

Kiểm tra và An toàn

Đừng bao giờ để một công cụ dọn dẹp chạy tự do mà không có sự kiểm tra. Kube-janitor bao gồm chế độ “dry-run” (chạy thử), điều này rất quan trọng cho việc thử nghiệm ban đầu. Luôn kiểm tra nhật ký trước khi kích hoạt các hành động xóa thực tế.

Sử dụng lệnh này để xem controller đang nhắm mục tiêu vào đối tượng nào:

kubectl logs -f deployment/kube-janitor -n kube-janitor

Bạn sẽ thấy các bản ghi như: Tài nguyên namespaces/test-app-123 đã hết hạn, đang xóa.... Nếu chế độ dry-run đang hoạt động, nhật ký sẽ thông báo rằng tài nguyên lẽ ra đã bị xóa mà không thực sự gỡ bỏ nó.

Bảo vệ các hệ thống quan trọng

Để ngăn chặn việc vô tình xóa kube-system hoặc production, hãy sử dụng một annotation loại trừ. Tôi khuyên bạn nên áp dụng điều này cho tất cả các namespace hạ tầng cốt lõi ngay lập tức.

kubectl annotate namespace production janitor/policy=keep

Các thực hành tốt nhất

Sau khi quản lý Kube-janitor trên nhiều cụm máy chủ, tôi đã tìm thấy ba chiến lược hiệu quả nhất. Đầu tiên, hãy thiết lập TTL mặc định là 14 ngày cho tất cả các namespace staging. Điều này buộc các đội ngũ phải giải trình lý do tại sao một tài nguyên nên được giữ lại lâu hơn.

Thứ hai, tích hợp các annotation vào các template CI/CD của bạn. Cho dù bạn sử dụng GitHub Actions hay GitLab CI, các script triển khai của bạn nên tự động tính toán và chèn janitor/ttl. Cuối cùng, hãy gửi nhật ký của bạn đến một công cụ như Grafana Loki. Nếu bạn thấy số lượng xóa tăng đột biến, bạn có thể kiểm tra trước khi nó ảnh hưởng đến quy trình làm việc của lập trình viên.

Dọn dẹp tự động giúp bạn chuyển từ việc quản lý chi phí mang tính đối phó sang chủ động. Bạn không còn cần phải cuống cuồng khi hóa đơn đến. Thay vào đó, cụm máy chủ của bạn luôn gọn nhẹ, dễ dự đoán và tiết kiệm chi phí ngay từ khâu thiết kế.

Share: