Giới thiệu
Bảo mật truy cập AWS từ Kubernetes là một thách thức lớn đối với nhiều nhà phát triển. Phương pháp truyền thống thường sử dụng IAM users với khóa truy cập vĩnh viễn và lưu trữ chúng trong cluster. Tuy nhiên, với sự phát triển của các giải pháp hiện đại, việc này đã trở nên lạc hậu. Trong bài viết này, chúng ta sẽ khám phá cách chuyển đổi từ việc sử dụng Secrets sang các phương pháp hiện đại như IRSA (IAM Roles for Service Accounts) và Pod Identity.
Phương pháp cũ: Lưu trữ thông tin xác thực (những gì cần tránh)
Trước khi tìm hiểu các giải pháp hiện đại, hãy cùng nhìn lại những rủi ro mà phương pháp truyền thống gây ra. Các bước chính để truy cập AWS từ Kubernetes thường bao gồm:
- Tạo IAM users với khóa truy cập (AWS_ACCESS_KEY_ID và AWS_SECRET_ACCESS_KEY)
- Lưu trữ thông tin xác thực trong Kubernetes secrets, biến môi trường hoặc tệp cấu hình
- Hardcode chúng vào hình ảnh container hoặc mã ứng dụng
Ví dụ về cách triển khai này trong một môi trường Kubernetes:
yaml
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
namespace: default
type: Opaque
data:
AWS_ACCESS_KEY_ID: ABCDEF
AWS_SECRET_ACCESS_KEY: GHIJKL
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: legacy-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: legacy-app
template:
metadata:
labels:
app: legacy-app
spec:
containers:
- name: legacy-app
image: my-app:latest
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: aws-credentials
key: AWS_ACCESS_KEY_ID
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: aws-credentials
key: AWS_SECRET_ACCESS_KEY
- name: AWS_REGION
value: "us-west-2"
Rủi ro bảo mật
Phương pháp này tạo ra nhiều thách thức bảo mật và vận hành:
-
Rủi ro bảo mật:
- Thông tin xác thực dài hạn không tự động hết hạn
- Khóa có thể bị trích xuất từ các container đang chạy hoặc từ Kubernetes secrets
- Rò rỉ thông tin xác thực dẫn đến việc truy cập liên tục cho đến khi bị thu hồi thủ công
- Khó khăn trong việc kiểm tra việc sử dụng thông tin xác thực giữa các pod và namespaces
-
Thách thức vận hành:
- Cần phải xoay vòng khóa thủ công qua tất cả các pod và cluster
- Khó khăn trong việc quản lý thông tin xác thực khi chúng bị sao chép qua nhiều namespaces và môi trường
- Quản lý secret phức tạp giữa nhiều cluster Kubernetes
Phương pháp ủy quyền hiện đại cho Kubernetes
Các phương pháp ủy quyền AWS hiện đại từ Kubernetes loại bỏ việc lưu trữ thông tin xác thực bằng cách sử dụng các mã thông báo tạm thời tự động được làm mới. Có hai giải pháp chính cho xác thực Kubernetes-to-AWS:
IRSA (IAM Roles for Service Accounts)
IRSA sử dụng OpenID Connect (OIDC) để kết nối giữa tài khoản dịch vụ Kubernetes với các vai trò IAM AWS. Khi một pod cần truy cập AWS, nó sẽ trình bày một mã thông báo JWT mà AWS xác thực qua nhà cung cấp OIDC của cluster, nhận lại thông tin xác thực tạm thời.
Cách hoạt động:
- Pod nhận mã thông báo JWT từ máy chủ API Kubernetes tự động
- AWS SDK đưa mã thông báo này vào các yêu cầu API
- AWS STS xác thực mã thông báo thông qua nhà cung cấp OIDC của cluster EKS
- STS trả lại thông tin xác thực AWS tạm thời cho pod
- Pod sử dụng thông tin xác thực này để truy cập các dịch vụ AWS
EKS Pod Identity
EKS Pod Identity là phương pháp mới hơn của AWS, sử dụng một tiện ích mở rộng cluster tự động xử lý việc trao đổi thông tin xác thực. Một agent Pod Identity chạy dưới dạng DaemonSet trên mỗi nút Kubernetes, chặn các cuộc gọi API AWS và lấy thông tin xác thực từ dịch vụ Pod Identity của AWS.
Cách hoạt động:
- Pod thực hiện các cuộc gọi API AWS thông qua AWS SDK
- Agent Pod Identity (chạy dưới dạng DaemonSet) chặn các cuộc gọi này
- Agent yêu cầu thông tin xác thực từ dịch vụ EKS Pod Identity
- Dịch vụ trả lại thông tin xác thực tạm thời cho agent
- Cuộc gọi API ban đầu tiếp tục với thông tin xác thực hợp lệ
Triển khai với Terraform
Hãy cùng triển khai cả hai phương pháp này bằng cách sử dụng các chính sách IAM nhất quán. Chúng ta sẽ sử dụng một chính sách truy cập S3 chung cho cả hai ví dụ để các pod có thể truy cập các dịch vụ AWS:
hcl
resource "aws_iam_policy" "s3_access" {
name = "kubernetes-app-s3-access"
description = "Chính sách truy cập S3 cho ứng dụng Kubernetes"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
]
Resource = "arn:aws:s3:::my-k8s-app-bucket/*"
},
{
Effect = "Allow"
Action = [
"s3:ListBucket"
]
Resource = "arn:aws:s3:::my-k8s-app-bucket"
}
]
})
}
Cấu hình IRSA cho EKS
Cấu hình cluster EKS của bạn với OIDC được bật để hỗ trợ IRSA:
hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 19.0.0"
cluster_name = "my-k8s-cluster"
cluster_version = "1.28"
enable_irsa = true
vpc_id = var.vpc_id
subnet_ids = var.private_subnets
eks_managed_node_groups = {
main = {
desired_size = 2
max_size = 4
min_size = 1
instance_types = ["t3.medium"]
}
}
}
Tạo vai trò IAM cho tài khoản dịch vụ Kubernetes
hcl
module "irsa_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
role_name = "k8s-app-irsa-role"
role_policy_arns = {
s3_access = aws_iam_policy.s3_access.arn
}
oidc_providers = {
main = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["default:k8s-app-service-account"]
}
}
}
Cấu hình EKS Pod Identity
Bật tiện ích mở rộng Pod Identity trong cluster EKS của bạn:
hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 19.0.0"
cluster_name = "my-k8s-cluster"
cluster_version = "1.28"
cluster_addons = {
eks-pod-identity-agent = {
addon_version = "v1.3.4-eksbuild.1"
}
}
vpc_id = var.vpc_id
subnet_ids = var.private_subnets
eks_managed_node_groups = {
main = {
desired_size = 2
max_size = 4
min_size = 1
instance_types = ["t3.medium"]
}
}
}
Manifest Kubernetes
Triển khai ứng dụng IRSA
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8s-app-service-account
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/k8s-app-irsa-role
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-app-irsa
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: k8s-app-irsa
template:
metadata:
labels:
app: k8s-app-irsa
spec:
serviceAccountName: k8s-app-service-account
containers:
- name: app
image: my-app:latest
env:
- name: AWS_REGION
value: "us-west-2"
ports:
- containerPort: 8080
Triển khai ứng dụng Pod Identity
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8s-app-service-account
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-app-pod-identity
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: k8s-app-pod-identity
template:
metadata:
labels:
app: k8s-app-pod-identity
spec:
serviceAccountName: k8s-app-service-account
containers:
- name: app
image: my-app:latest
env:
- name: AWS_REGION
value: "us-west-2"
ports:
- containerPort: 8080
So sánh các phương pháp hiện đại cho Kubernetes
Điểm mạnh và hạn chế của IRSA
Điểm mạnh:
- Hoạt động với bất kỳ cluster Kubernetes nào, không chỉ EKS
- Công nghệ trưởng thành với sự hỗ trợ từ cộng đồng rộng rãi
- Kiểm soát tinh vi đối với cấu hình mã thông báo JWT
- Tương thích với các hệ thống dựa trên OIDC và service meshes khác
Hạn chế:
- Cài đặt và xử lý sự cố phức tạp hơn trong Kubernetes
- Cần cấu hình nhà cung cấp OIDC ở cấp cluster
- Mã thông báo JWT có thể trở nên lớn và gây ra vấn đề với một số ứng dụng
- Cần quản lý chú thích thủ công cho mỗi tài khoản dịch vụ
Điểm mạnh và hạn chế của Pod Identity
Điểm mạnh:
- Cài đặt và quản lý đơn giản hơn trong EKS
- Tích hợp gốc AWS với hiệu suất tốt hơn
- Tự động làm mới và xoay vòng thông tin xác thực được xử lý bởi agent
- Có khả năng ghi nhật ký kiểm tra tích hợp thông qua CloudTrail
- Không có giới hạn kích thước mã thông báo JWT hay độ phức tạp
Hạn chế:
- Giải pháp chỉ dành cho EKS, không thể di chuyển sang các phân phối Kubernetes khác
- Công nghệ mới hơn với ít kiến thức và hướng dẫn xử lý sự cố từ cộng đồng
- Cần phiên bản cluster EKS 1.24 trở lên
- Ít linh hoạt tùy chỉnh hơn so với các phương pháp dựa trên OIDC
Các thực tiễn tốt nhất về bảo mật cho workloads Kubernetes
Dù bạn chọn phương pháp nào cho cluster Kubernetes của mình, hãy tuân thủ các nguyên tắc bảo mật sau:
Nguyên tắc tối thiểu quyền hạn
hcl
# Tốt: Quyền cụ thể cho các tài nguyên cụ thể mà pods sử dụng
resource "aws_iam_policy" "restricted_s3" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject"]
Resource = "arn:aws:s3:::k8s-specific-bucket/app-folder/*"
}
]
})
}
# Tránh: Quyền quá rộng mà pods không cần
resource "aws_iam_policy" "too_broad" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:*"]
Resource = "*"
}
]
})
}
Các biện pháp bảo mật bổ sung cho Kubernetes
- Sử dụng cách ly namespace Kubernetes để hạn chế phạm vi tài khoản dịch vụ
- Thực hiện kiểm tra định kỳ việc sử dụng vai trò và quyền hạn qua các cluster
- Giám sát việc sử dụng thông tin xác thực thông qua AWS CloudTrail và nhật ký audit Kubernetes
- Thiết lập cảnh báo cho các mẫu truy cập bất thường từ các pods
- Sử dụng các chính sách mạng Kubernetes để hạn chế giao tiếp giữa các pods
- Đánh giá và xoay vòng định kỳ bất kỳ thông tin xác thực dài hạn nào còn lại trong cluster của bạn
Chọn phương pháp phù hợp
Chọn IRSA khi:
- Bạn cần hỗ trợ multi-cloud hoặc hybrid Kubernetes
- Bạn có yêu cầu tích hợp OIDC phức tạp
- Nhóm của bạn có kinh nghiệm với IRSA
- Bạn cần kiểm soát chi tiết mã thông báo
Chọn Pod Identity khi:
- Bạn chỉ sử dụng EKS
- Bạn muốn giảm bớt gánh nặng quản lý
- Bạn đang bắt đầu các dự án mới từ đầu
- Bạn ưu tiên các giải pháp gốc AWS
Di chuyển từ thông tin xác thực đã lưu khi:
- Bạn hiện đang sử dụng các khóa truy cập dài hạn
- Bạn muốn cải thiện tư duy bảo mật
- Bạn cần xoay vòng thông tin xác thực tốt hơn
- Bạn muốn giảm bớt gánh nặng vận hành
Kết luận
Các phương pháp ủy quyền AWS hiện đại loại bỏ rủi ro bảo mật và độ phức tạp vận hành của thông tin xác thực đã lưu trong các môi trường Kubernetes. Cả IRSA và EKS Pod Identity đều cung cấp truy cập thông tin xác thực tạm thời, an toàn, theo các phương pháp bảo mật đám mây tốt nhất, đồng thời tích hợp liền mạch với quy trình làm việc Kubernetes.
Đối với các dự án EKS mới, Pod Identity cung cấp con đường đơn giản nhất với tích hợp gốc AWS và giảm bớt gánh nặng quản lý. Đối với các môi trường Kubernetes hiện có hoặc yêu cầu đa nền tảng, IRSA cung cấp độ tin cậy và linh hoạt đã được chứng minh qua nhiều loại cluster khác nhau.
Bước quan trọng nhất là từ bỏ hoàn toàn thông tin xác thực đã lưu trong các cluster Kubernetes của bạn. Hãy chọn phương pháp hiện đại phù hợp nhất với chuyên môn và yêu cầu cơ sở hạ tầng của nhóm bạn - cả hai đều đại diện cho những cải tiến đáng kể so với quản lý thông tin xác thực truyền thống và sẽ nâng cao tư thế bảo mật của cluster đồng thời đơn giản hóa hoạt động.