Triển Khai IRSA Trên EKS: Hướng Dẫn Chi Tiết Về OIDC Provider & IAM Trust Policy

Triển Khai IRSA Trên EKS: Hướng Dẫn Chi Tiết Về OIDC Provider & IAM Trust Policy
Trong hệ sinh thái Kubernetes trên AWS, việc quản lý quyền truy cập vào các tài nguyên AWS (như S3, DynamoDB, SQS, …) cho Pod là một nhiệm vụ quản trị quan trọng. AWS cung cấp cơ chế IRSA (IAM Roles for Service Accounts) để Pod trong EKS có thể assume IAM Role an toàn và linh hoạt.
Bài viết này sẽ đưa bạn đi từ những khái niệm cơ bản như OIDC Provider, JWT Token, đến việc viết IAM Trust Policy an toàn chỉ cho phép Pod của một Service Account cụ thể assume role.
🔹 Service Account là gì?
Trong Kubernetes, có 2 loại tài khoản dùng để xác thực:
User Account: dành cho người dùng thực (con người).
Service Account (SA): dành cho các pod, deployment, hoặc controller trong cluster khi chúng cần tương tác với Kubernetes API.
Ví dụ: Một Pod muốn gọi Kubernetes API để đọc secret hoặc xem các pod khác — nó sẽ dùng service account để xác thực.
🔹 Tại sao cần Service Account?
Mỗi pod trong Kubernetes có thể cần truy cập API server để thực hiện hành động như:
Lấy thông tin các pod khác (để service discovery).
Gọi API để tạo/update resource (ví dụ: job, configmap).
Tải secret/credential để kết nối dịch vụ ngoài.
Vì lý do bảo mật, bạn nên giới hạn quyền truy cập theo principle of least privilege (chỉ cấp đúng những gì cần).
🔹 Cách hoạt động
Mặc định, khi bạn tạo một Pod mà không chỉ rõ Service Account, Kubernetes sẽ tự động gán default
service account trong namespace đó cho Pod.
Khi Pod khởi chạy:
Nó được mount 1 token ở đường dẫn
/var/run/secrets/
kubernetes.io/serviceaccount/token
.Token này là một JWT có thể dùng để gọi đến Kubernetes API server.
🔹 Tạo và gán Service Account
Tạo một Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
Gán vào Pod
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
serviceAccountName: my-service-account
containers:
- name: mycontainer
image: busybox
command: ["sleep", "3600"]
🔹 Gán quyền cho Service Account với RBAC
Mặc định, Service Account không có quyền gì cả. Bạn cần tạo Role/ClusterRole và gán chúng bằng RoleBinding/ClusterRoleBinding.
Ví dụ: Cấp quyền đọc pod
# Tạo Role (giới hạn trong namespace)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Gán Role cho Service Account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: default
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
🔹 Thực hành kiểm tra
Bạn có thể chạy pod dùng kubectl proxy
hoặc mount kubectl
vào trong pod rồi dùng biến môi trường:
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -H "Authorization: Bearer $TOKEN" https://kubernetes.default.svc/api
🔹 Tổng kết
Thành phần | Mục đích |
ServiceAccount | Đại diện cho một pod hay app trong cluster |
Role / ClusterRole | Xác định các quyền |
RoleBinding / ClusterRoleBinding | Gán Role cho Service Account |
Tổng Quan Về IRSA
IRSA cho phép mỗi pod trong Kubernetes assume một IAM Role mà không cần lồng AWS credentials trong image hay inject environment variables.
Mô Hình Hoạt Động:
Pod dùng Service Account được gán annotation IAM Role.
Kubelet mount token JWT OIDC vào pod.
Pod gọi lệnh
AssumeRoleWithWebIdentity
đến AWS STS.AWS dùng OIDC Provider để xác thực token JWT.
Nếu token hợp lệ và policy cho phép, AWS trả về temporary credentials.
OIDC Provider là gì?
OIDC (OpenID Connect) là chuẩn xác thực danh tính dựa trên OAuth2, sử dụng rộng rãi để trao đổi token xác thực giữa các hệ thống.
Trong EKS, AWS cần biết token JWT kia có được Kubernetes ký và có hợp lệ không. Đó là lý do OIDC Provider tồn tại trong IAM.
OIDC Provider trong EKS có dạng:
https://oidc.eks.<region>.amazonaws.com/id/<eks-cluster-id>
Khi bạn chạy:
eksctl utils associate-iam-oidc-provider \
--region <region> \
--cluster <cluster-name> \
--approve
AWS sẽ tự đăng ký OIDC Provider trong IAM.
JWT Token Trong IRSA
Pod được mount token từ Service Account:
{
"sub": "system:serviceaccount:default:my-service-account",
"aud": "sts.amazonaws.com",
"iss": "https://oidc.eks.ap-southeast-1.amazonaws.com/id/ABCD1234EFGH"
}
Các trường quan trọng:
sub: Service Account nào dùng token.
aud: phải là
sts.amazonaws.com
iss: issuer, phải khớp với OIDC Provider trong IAM
Tạo IAM Role Cho Service Account
IAM Role cho Pod phải có trust policy chi tiết:
Mẫu Trust Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.ap-southeast-1.amazonaws.com/id/ABCD1234EFGH"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.ap-southeast-1.amazonaws.com/id/ABCD1234EFGH:sub": "system:serviceaccount:default:my-service-account",
"oidc.eks.ap-southeast-1.amazonaws.com/id/ABCD1234EFGH:aud": "sts.amazonaws.com"
}
}
}
]
}
Giải thích các thành phần
Trường | Ý nghĩa |
Principal.Federated | Cho phép OIDC Provider đại diện pod gọi sts:AssumeRoleWithWebIdentity |
Action | Chỉ cho phép assume role qua OIDC (sts:AssumeRoleWithWebIdentity ) |
Condition.StringEquals | Rất quan trọng: chỉ cho phép SA cụ thể (sub ) và đúng aud (người nhận là sts.amazonaws.com ) |
sub
bắt buộc có dạng:
system:serviceaccount:<namespace>:<serviceaccount-name>
Nếu bạn bỏ qua phần
"Condition"
thì mọi SA trong toàn bộ cluster có thể assume IAM Role => rất nguy hiểm!
Gắn Role vào Service Account:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/my-irsa-role
Sau khi khai báo, bất kỳ Pod nào dùng SA này sẽ tự động có AWS credentials.
Kiểm Tra Token Trong Pod
Bạn có thể exec và decode token:
kubectl exec -it <pod> -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | \
jq -R 'split(".") | .[1] | @base64d | fromjson'
Sẽ xuất ra payload JWT.
✅ Tóm tắt quy trình bảo mật với OIDC Trust Policy
EKS cấp token JWT có
sub = system:serviceaccount:ns:name
Pod gửi token đến AWS STS để assume IAM Role
IAM Role kiểm tra:
Token có đúng issuer (OIDC)
Token có đúng
sub
Token có đúng
aud
Nếu đúng, cấp temporary credentials
Kết Luận
Việc sử dụng IRSA giúp:
Tách biệt quyền truy cập AWS theo pod.
Không cần embed AWS credentials.
Tuân thủ principle of least privilege.
OIDC Provider trong EKS là gốc của trust chain, cùng với JWT token từ Service Account và IAM Trust Policy chi tiết sẽ đảm bảo bạn có hệ thống an toàn và linh hoạt.
Subscribe to my newsletter
Read articles from Kilo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
