Lỗi gặp phải
Error from server (Forbidden): pods "my-pod" is forbidden: User "system:serviceaccount:default:default" cannot create resource "pods" in API group "" in the namespace "default"
Lỗi này xuất hiện khi một pod, CI/CD pipeline, hoặc lệnh kubectl thực hiện thao tác mà danh tính hiện tại không được phép. Chú ý đến User "system:serviceaccount:default:default" — đây là ServiceAccount tên default trong namespace default, không phải người dùng thật. Cách khắc phục: tạo Role (hoặc ClusterRole) với quyền phù hợp, sau đó bind nó vào danh tính đó.
Nguyên nhân gốc rễ
Kubernetes RBAC mặc định từ chối tất cả. Không có Role binding = không có quyền truy cập. Bất kỳ pod hoặc pipeline nào chạy dưới ServiceAccount chưa được bind đều sẽ gặp lỗi này ngay khi tương tác với API.
Thông báo lỗi đã nói rõ — nó cho bạn biết chính xác cần cấp quyền gì:
- Ai:
system:serviceaccount:default:default— ServiceAccountdefaulttrong namespacedefault - Làm gì:
createtrên resourcepods - Ở đâu: API group
""(core API group), namespacedefault
Các bước khắc phục
Bước 1 — Kiểm tra quyền đã tồn tại chưa
Nên kiểm tra trước — binding có thể đã tồn tại nhưng sai phạm vi. Tránh tạo cấu hình trùng lặp:
# Kiểm tra RoleBindings trong namespace
kubectl get rolebindings -n default -o wide
# Kiểm tra ClusterRoleBindings
kubectl get clusterrolebindings -o wide | grep default
# Kiểm tra đúng quyền từ thông báo lỗi
kubectl auth can-i create pods --as=system:serviceaccount:default:default -n default
Nếu lệnh cuối trả về no, tiếp tục các bước dưới đây.
Bước 2 — Tạo Role với quyền cần thiết
Cần quyền trong phạm vi namespace? Dùng Role. Role này ánh xạ trực tiếp từ thông báo lỗi — create trên pods trong namespace default:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-manager
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "create", "delete", "watch"]
kubectl apply -f role-pod-manager.yaml
Bước 3 — Bind Role vào ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-manager-binding
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: Role
name: pod-manager
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rolebinding-pod-manager.yaml
Bước 4 — Cần quyền toàn cluster, dùng ClusterRole + ClusterRoleBinding
Controller, operator, và monitoring agent thường cần quyền truy cập trên nhiều namespace. Trong trường hợp đó, thay Role bằng ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-manager-global
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/status"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-manager-global-binding
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: pod-manager-global
apiGroup: rbac.authorization.k8s.io
kubectl apply -f clusterrole-binding.yaml
Bước 5 — Khi chạy kubectl từ máy local (không phải ServiceAccount)
Khi lỗi hiển thị người dùng thông thường như User "john@example.com" thay vì ServiceAccount, bind role trực tiếp vào người dùng đó:
kubectl create clusterrolebinding john-admin \
--clusterrole=cluster-admin \
--user=john@example.com
Không dùng cluster-admin trong môi trường production. Quyền này cho phép đọc/ghi toàn bộ resource trong cluster — một pod cấu hình sai có thể gây hậu quả nghiêm trọng. Hãy tạo ClusterRole giới hạn chỉ những quyền thực sự cần thiết.
Kiểm tra sau khi sửa
# Xác nhận quyền đã được cấp
kubectl auth can-i create pods --as=system:serviceaccount:default:default -n default
# Kết quả mong đợi: yes
# Xem tất cả các verb mà ServiceAccount có trên pods
kubectl auth can-i --list --as=system:serviceaccount:default:default -n default | grep pods
# Chạy lại lệnh bị lỗi trước đó
kubectl run my-pod --image=nginx -n default
Lưu ý thêm
Dùng ServiceAccount riêng biệt thay vì dùng default
Mọi pod không chỉ định serviceAccountName đều chạy dưới ServiceAccount default. Cấp quyền cho SA này đồng nghĩa với việc cấp quyền cho tất cả pod trong namespace — bao gồm cả những pod được deploy sau bởi team khác. Hãy tạo SA riêng cho từng workload:
kubectl create serviceaccount my-app -n default
# Sau đó tham chiếu trong Pod spec:
# spec:
# serviceAccountName: my-app
Đọc kỹ thông báo lỗi — nó cho biết chính xác cần sửa gì
Định dạng luôn là: User "X" cannot VERB resource "Y" in API group "Z" in namespace "N". Dịch trực tiếp sang rules trong Role:
VERB→ điền vàoverbsresource "Y"→ điền vàoresourcesAPI group "Z"→ điền vàoapiGroups(chuỗi rỗng""= core group)
Tham khảo các API group thông dụng
""— core: pods, services, configmaps, secrets, persistentvolumeclaimsapps— deployments, replicasets, statefulsets, daemonsetsbatch— jobs, cronjobsnetworking.k8s.io— ingresses, networkpoliciesrbac.authorization.k8s.io— roles, rolebindings
Đã sửa RBAC nhưng script vẫn lỗi
Đôi khi sau khi sửa RBAC lại lộ ra vấn đề thứ hai: file binary hoặc script bên trong pod không thể thực thi do phân quyền Unix sai. Khi đó, Unix Permissions Calculator trên ToolCraft giúp bạn chuyển đổi nhanh giữa số chmod và ký hiệu symbolic mà không cần tính tay — chạy hoàn toàn trên trình duyệt, không gửi dữ liệu ra ngoài.

