KubernetesのForbiddenエラーを修正: ユーザーがリソースを作成できない(RBAC)

intermediate☸️ Kubernetes2026-03-21| Kubernetes 1.20以降、kubectl CLI、各種クラウドプロバイダー(EKS、GKE、AKS)またはセルフホスト型クラスター

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#パーミッション#forbidden#serviceaccount

エラーの内容

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"

このエラーは、Pod・CI/CDパイプライン・kubectlコマンドが、現在のIDに許可されていない操作を実行しようとしたときに発生します。User "system:serviceaccount:default:default" に注目してください — これは人間のユーザーではなく、default ネームスペース内の default という名前のServiceAccountです。解決策は、適切な権限を持つRole(またはClusterRole)を作成し、そのIDにバインドすることです。

何が起きているのか

Kubernetes RBACはデフォルトですべてを拒否します。Roleのバインディングがなければアクセスも一切なし、以上です。バインドされていないServiceAccountで動作するPodやパイプラインは、APIに触れた瞬間にこの壁にぶつかります。

エラーメッセージは自己説明的で、付与すべき内容を正確に教えてくれています:

  • 誰がsystem:serviceaccount:default:default — ネームスペース default 内のServiceAccount default
  • 何を:リソース pods に対する create 操作
  • どこで:APIグループ ""(コアAPIグループ)、ネームスペース default

ステップごとの修正手順

Step 1 — 既存の権限を確認する

まず確認する価値があります — バインディングがすでに存在しているがスコープが間違っている可能性があります。重複した設定を避けるために先に確認しましょう:

# ネームスペース内のRoleBindingを確認
kubectl get rolebindings -n default -o wide

# ClusterRoleBindingを確認
kubectl get clusterrolebindings -o wide | grep default

# エラーに記載された権限を直接テスト
kubectl auth can-i create pods --as=system:serviceaccount:default:default -n default

最後のコマンドが no を返した場合は、次の手順に進んでください。

Step 2 — 必要な権限を持つRoleを作成する

ネームスペーススコープのアクセスには Role を使用します。これはエラーに記載された内容 — default ネームスペースの pods に対する create — に直接対応しています:

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

Step 3 — Roleを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

Step 4 — クラスター全体のアクセスにはClusterRole + ClusterRoleBindingを使用する

コントローラー・オペレーター・監視エージェントは通常、複数のネームスペースにまたがるアクセスが必要です。その場合は、Role の代わりに 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

Step 5 — kubectlをローカルで実行している場合(ServiceAccountではない場合)

エラーにServiceAccountではなく User "john@example.com" のような通常のユーザーが表示されている場合は、そのユーザーに直接ロールをバインドします:

kubectl create clusterrolebinding john-admin \
  --clusterrole=cluster-admin \
  --user=john@example.com

本番環境では cluster-admin を使用しないでください。クラスター内のすべてのリソースに対する完全な読み書き権限を付与するため — 設定ミスが一つあるだけで深刻な影響範囲になります。必要な権限のみを持つスコープを絞ったClusterRoleを作成してください。

修正の確認

# 権限が付与されたことを確認
kubectl auth can-i create pods --as=system:serviceaccount:default:default -n default
# 期待される結果: yes

# ServiceAccountがpodsに対して持つすべての動詞を確認
kubectl auth can-i --list --as=system:serviceaccount:default:default -n default | grep pods

# 失敗したコマンドを再実行
kubectl run my-pod --image=nginx -n default

補足Tips

defaultではなく専用のServiceAccountを使用する

serviceAccountName を指定していないすべてのPodは default として実行されます。そのSAに権限を付与すると、後から他のチームがデプロイしたものも含め、ネームスペース内のすべてのPodにその権限が与えられます。ワークロードごとに専用のSAを作成してください:

kubectl create serviceaccount my-app -n default

# その後、PodのspecでServiceAccountを参照する:
# spec:
#   serviceAccountName: my-app

エラーメッセージをよく読む — 修正すべき内容が正確にわかる

フォーマットは常に: User "X" cannot VERB resource "Y" in API group "Z" in namespace "N" です。これをRoleの rules に直接変換してください:

  • VERBverbs に記述
  • resource "Y"resources に記述
  • API group "Z"apiGroups に記述(空文字列 "" = コアグループ)

よく使うAPIグループ一覧

  • "" — コア: pods, services, configmaps, secrets, persistentvolumeclaims
  • apps — deployments, replicasets, statefulsets, daemonsets
  • batch — jobs, cronjobs
  • networking.k8s.io — ingresses, networkpolicies
  • rbac.authorization.k8s.io — roles, rolebindings

RBACを修正してもスクリプトが失敗する場合

RBACを修正することで別の問題が明らかになることがあります:Pod内のバイナリやスクリプトが、Unixファイルパーミッションの設定ミスにより実行できない場合です。そのような場合は、ToolCraftのUnix Permissions Calculatorchmod の数値とシンボル表記の変換における手間を省いてくれます — 完全にブラウザ上で動作し、データは外部に送信されません。

Related Error Notes