Sửa lỗi Kubernetes Forbidden: User cannot create resource (RBAC)

intermediate☸️ Kubernetes2026-03-21| Kubernetes 1.20+, kubectl CLI, mọi cloud provider (EKS, GKE, AKS) hoặc cluster tự triển khai

Error Message

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"
#kubernetes#rbac#permission#forbidden#serviceaccount

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 — ServiceAccount default trong namespace default
  • Làm gì: create trên resource pods
  • Ở đâu: API group "" (core API group), namespace default

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ào verbs
  • resource "Y" → điền vào resources
  • API group "Z" → điền vào apiGroups (chuỗi rỗng "" = core group)

Tham khảo các API group thông dụng

  • "" — core: pods, services, configmaps, secrets, persistentvolumeclaims
  • apps — deployments, replicasets, statefulsets, daemonsets
  • batch — jobs, cronjobs
  • networking.k8s.io — ingresses, networkpolicies
  • rbac.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.

Related Error Notes