Kubernetes Secrets trong Git: Hướng dẫn thực chiến về Bitnami Sealed Secrets

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

Vấn đề “Chìa khóa đặt dưới thảm” trong GitOps

GitOps đã thay đổi căn bản cách chúng ta triển khai ứng dụng lên Kubernetes. Dù bạn dùng ArgoCD hay Flux, việc đồng bộ hóa trạng thái cluster với một kho lưu trữ Git mang lại cảm giác thật kỳ diệu. Tuy nhiên, vấn đề bảo mật secrets vẫn là một “con voi trong phòng” (trở ngại lớn khó lờ đi). Các Kubernetes Secret tiêu chuẩn chỉ được mã hóa Base64 — chứ không phải được mã hóa thực sự (encrypted). Việc commit chúng lên Git về mặt bảo mật cũng tương tự như việc bạn để chìa khóa cửa chính dưới thảm và hy vọng không ai dòm ngó.

Tôi đã dành nhiều tháng để tìm kiếm một giải pháp “Goldilocks” (vừa vặn nhất) nằm giữa sự cồng kềnh của HashiCorp Vault và phương pháp “kubectl apply” thủ công đầy rủi ro. Sau khi vận hành Bitnami Sealed Secrets trên môi trường production trong 8 tháng — quản lý hơn 150 secrets trên 12 namespace — tôi tin rằng đây là lựa chọn tối ưu cho hầu hết các đội ngũ kỹ thuật.

Cách tiếp cận này cho phép bạn quản lý dữ liệu nhạy cảm y hệt như code: có versioning, có lịch sử audit và được triển khai tự động.

Nguyên lý hoạt động: Cơ chế mã hóa

Sealed Secrets sử dụng mã hóa bất đối xứng để giải quyết bài toán secret-trong-Git. Hệ thống dựa trên hai thành phần chính:

  • The Controller: Một Pod chạy trong cluster của bạn, giữ private key. Đây là thực thể duy nhất có thể chuyển dữ liệu đã mã hóa trở lại thành các secret có thể sử dụng được.
  • The CLI (kubeseal): Một công cụ trên máy cục bộ của bạn, sử dụng public key của controller để mã hóa dữ liệu.

Kết quả là một Custom Resource SealedSecret. Bạn có thể commit file này lên GitHub repo công khai một cách an toàn. Ngay cả khi kẻ xấu có quyền truy cập vào repository, họ cũng không thể giải mã các giá trị nếu không có private key được lưu trữ trong bộ nhớ của cluster.

Bước 1: Triển khai và Cài đặt

Helm là con đường cài đặt dễ dàng nhất. Tôi khuyên bạn nên triển khai vào namespace kube-system để tách biệt controller khỏi các workload ứng dụng thông thường.

# Thêm repository của Bitnami
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets

# Cài đặt controller
helm install sealed-secrets-controller sealed-secrets/sealed-secrets -n kube-system

Tải binary kubeseal cho môi trường cục bộ. Trên Linux, lệnh một dòng này sẽ lấy phiên bản mới nhất trực tiếp từ GitHub:

KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//')
wget "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz"
tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

Bước 2: Quy trình làm việc thực tế

Quy trình rất đơn giản: tạo một secret cục bộ tạm thời, “seal” (niêm phong) nó, sau đó xóa file gốc. Hãy cùng xem ví dụ về thông tin xác thực database.

Tạo file YAML

Đầu tiên, chúng ta tạo một Secret tiêu chuẩn mà không áp dụng nó vào cluster. Chúng ta sử dụng flag --dry-run=client để chuyển output vào một file.

kubectl create secret generic db-credentials \
    --from-literal=password='mat-khau-sieu-bao-mat' \
    --dry-run=client -o yaml > db-secret.yaml

Mã hóa dữ liệu (Seal)

Tiếp theo là bước mã hóa. Công cụ kubeseal giao tiếp với cluster để lấy public key, sau đó chuyển đổi secret của bạn thành một SealedSecret.

kubeseal < db-secret.yaml --format yaml > db-sealed-secret.yaml

Bây giờ, hãy xóa db-secret.yaml ngay lập tức. File db-sealed-secret.yaml còn lại hiện là “nguồn sự thật duy nhất” (source of truth) cho pipeline GitOps của bạn.

Bước 3: Chi tiết quan trọng: Hiểu về Scope

Một sắc thái nhỏ từng khiến tôi bối rối lúc đầu là “Scope” (Phạm vi). Sealed Secrets cung cấp ba ranh giới bảo mật:

  1. strict (mặc định): Secret được gắn chặt với một tên và namespace cụ thể. Nếu bạn di chuyển nó, nó sẽ không thể giải mã.
  2. namespace-wide: Bạn có thể đổi tên secret, nhưng nó phải nằm trong cùng một namespace.
  3. cluster-wide: Secret có thể được giải mã ở bất kỳ đâu trong cluster.

Hãy luôn dùng strict cho môi trường production. Nó ngăn chặn việc một lập trình viên vô tình (hoặc cố ý) giải mã mật khẩu database production trong một namespace phát triển (development).

Kiểm tra và Xử lý sự cố

Sau khi apply file vào cluster, controller sẽ hoạt động ngầm để tạo ra Secret tiêu chuẩn. Kiểm tra trạng thái đồng bộ bằng lệnh sau:

kubectl get sealedsecret db-credentials
# Tìm dòng: Condition: Synced

Xử lý sự cố thường chỉ là kiểm tra log của controller. Nếu secret không xuất hiện, log trong kube-system sẽ cho bạn biết nếu có sự không khớp về scope hoặc lỗi giải mã.

kubectl logs -n kube-system -l app.kubernetes.io/name=sealed-secrets

Khôi phục sau thảm họa: Quy tắc “Đừng để mất chìa khóa”

Private key là linh hồn của hệ thống mã hóa. Nếu cluster của bạn “chết” và bạn chưa backup master key, kho lưu trữ Git của bạn sẽ trở thành một nghĩa trang của những file mã hóa vô dụng. Tôi luôn lưu trữ một bản sao của master key trong một kho lưu trữ bảo mật của công ty.

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > master-key-backup.yaml

Kết luận cuối cùng

Việc chuyển sang Sealed Secrets đã chấm dứt những tin nhắn Slack kiểu “ai đang giữ file secret của production thế?” và giải quyết được một điểm nghẽn lớn cho đội ngũ của chúng tôi. Nó phù hợp hoàn hảo với quy trình Pull Request, nơi mọi thay đổi đều được kiểm tra và minh bạch. Trong khi các doanh nghiệp cực lớn có thể cần các tính năng của HashiCorp Vault, Sealed Secrets mang lại sự cân bằng tốt nhất giữa bảo mật và tốc độ cho các đội ngũ phát triển đang tăng trưởng.

Share: