2026年8月5日
2026年8月5日
KubernetesのRBACでアクセス制御する方法|Role・RoleBindingの書き方と最小権限、Forbiddenエラーの読み方
KubernetesのRBAC(ロールベースのアクセス制御)は、「誰が」「どの名前空間で」「どのリソースに」「何をしてよいか」を決める仕組みです。RoleかClusterRoleで操作の許可をまとめ、RoleBindingかClusterRoleBindingでユーザーやサービスアカウントに結び付けます。この記事では、4つのオブジェクトの関係、YAMLとkubectlでの設定方法、CI/CD用サービスアカウントへの最小権限の与え方、権限の確認方法とForbiddenエラーの読み方を説明します。
内容は、Kubernetesの現行のサポート対象の版(2026年10月現在)で共通して使える範囲に絞っています。EKS・GKE・AKSでは、クラウドのアカウントとKubernetesのユーザーを結び付ける方法がサービスごとに異なるため、その部分は各サービスのドキュメントを参照してください。
4つのオブジェクトの関係
- Role:ある名前空間の中での許可をまとめたものです。
- ClusterRole:名前空間をまたぐ許可、またはノードなど名前空間に属さないリソースの許可をまとめたものです。
- RoleBinding:RoleまたはClusterRoleを、ある名前空間の中で特定の相手に与えます。
- ClusterRoleBinding:ClusterRoleを、クラスター全体で特定の相手に与えます。
押さえておきたい性質が3つあります。
- 許可を足していく方式で、拒否のルールはありません。何も与えられていなければ何もできず、与えた許可の合計がその相手の権限になります。「この操作だけ禁止」はできないため、広い権限を与えてから削る設計はできません。
- RoleBindingからClusterRoleを参照できます。この場合、ClusterRoleの内容がその名前空間の中だけで有効になります。共通の権限セットをClusterRoleとして1つ作り、名前空間ごとにRoleBindingで配る、という使い方が一般的です。
- **Bindingの
roleRefは作成後に変更できません**。参照するロールを変えたいときは、Bindingを削除して作り直します。
与える相手(subjects)
- User / Group:Kubernetesにはユーザーを登録するオブジェクトがありません。クライアント証明書やOIDCなど、クラスターの認証方式が伝える名前がそのまま使われます。
- ServiceAccount:Podや自動化の処理が使う、名前空間ごとのアカウントです。RBACの中では
system:serviceaccount:<名前空間>:<名前>という名前で扱われます。
Roleを書く
wordpress 名前空間で、Podとログを見るだけの権限を作る例です。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: wordpress
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups:リソースが属するAPIグループです。Pod・Service・Secret・ConfigMapなどのコアのリソースは空文字
""、Deployment・StatefulSet・DaemonSetはappsです。どのグループかはkubectl api-resourcesのAPIVERSION列で確かめられます。 - resources:
pods/logやpods/execのような「サブリソース」は、親とは別に指定します。podsを許可しても、ログの閲覧やkubectl execは許可されません。 - verbs:
get・list・watch(読み取り)、create・update・patch・delete(書き込み)などです。
kubectl exec を許可するには pods/exec に create が必要です。コンテナの中でコマンドを実行できる強い権限なので、閲覧用のロールには入れません。
RoleBindingで結び付ける
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-alice
namespace: wordpress
subjects:
- kind: User
name: alice@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
同じことはkubectlでも作れます。試すときは便利ですが、運用するものはYAMLにしてGitで管理すると、誰にどの権限を与えたかを後から追えます。
kubectl create role pod-reader --verb=get,list,watch --resource=pods,pods/log -n wordpress
kubectl create rolebinding pod-reader-alice --role=pod-reader --user=alice@example.com -n wordpress
組み込みのClusterRoleを使う
Kubernetesには利用者向けのClusterRoleが最初から用意されています。
- view:ほとんどのリソースの閲覧。Secretは読めません。
- edit:ほとんどのリソースの読み書き。Secretの読み書きもでき、その名前空間のどのサービスアカウントでもPodを動かせます。ロールやBindingの変更はできません。
- admin:名前空間の管理者向け。editに加えて、名前空間内のRoleとRoleBindingを管理できます。
- cluster-admin:クラスター全体のあらゆる操作。
開発者にeditを配ると、本番のデータベースのパスワードが入ったSecretも読める状態になります。Secretを見せたくない場合は、editを使わず、必要なリソースだけを並べたロールを作ります。cluster-adminをClusterRoleBindingで与えるのは、クラスターの管理者に限ります。
CI/CDのサービスアカウントに最小権限を与える
GitHub ActionsなどからDeploymentのイメージを更新するだけの権限を作る例です。
apiVersion: v1
kind: ServiceAccount
metadata:
name: deployer
namespace: wordpress
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: wordpress
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
resourceNames: ["wordpress"]
verbs: ["get", "patch"]
- apiGroups: ["apps"]
resources: ["replicasets"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: deployer
namespace: wordpress
subjects:
- kind: ServiceAccount
name: deployer
namespace: wordpress
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
resourceNames で、操作できるDeploymentを wordpress の1つに限っています。ReplicaSetとPodの閲覧は、kubectl rollout status で更新の完了を待つためのものです。kubectl apply で新しいリソースを作る運用なら create も必要になりますが、resourceNames は create を名前で絞れない点に注意してください。
このサービスアカウント用のトークンは、kubectl create token deployer -n wordpress --duration=1h のように有効期限付きで発行できます。期限のないトークンをCIの秘密情報に長期間置くより、漏れたときの被害が小さくなります。クラウドのCIからは、OIDCの連携で短期の認証情報を使える場合もあります。
Kubernetes APIを使わないPodでは、トークンの自動マウントを止めておくと、Podが乗っ取られたときに権限を悪用されにくくなります。
apiVersion: v1
kind: ServiceAccount
metadata:
name: wordpress
namespace: wordpress
automountServiceAccountToken: false
権限を確かめる
kubectl auth can-i で、ある相手がある操作をできるかを確かめられます。
kubectl auth can-i patch deployments/wordpress -n wordpress \
--as=system:serviceaccount:wordpress:deployer
kubectl auth can-i get secrets -n wordpress \
--as=system:serviceaccount:wordpress:deployer
kubectl auth can-i --list -n wordpress \
--as=system:serviceaccount:wordpress:deployer
--as で他人として確かめるには、実行する人自身に「なりすまし(impersonate)」の権限が必要です。権限を作ったら、できてほしい操作が yes、できてほしくない操作が no になることを両方確かめておくと、与えすぎに気付けます。
Forbiddenエラーの読み方
権限が足りないと、次のようなエラーが返ります。
Error from server (Forbidden): deployments.apps "wordpress" is forbidden:
User "system:serviceaccount:wordpress:deployer" cannot patch resource
"deployments" in API group "apps" in the namespace "wordpress"
ここから、「誰が(User)」「何を(patch)」「どのリソースに(deployments)」「どのAPIグループで(apps)」「どの名前空間で」が読み取れます。直すときは、次の順に確かめます。
- 名前空間が合っているか:RoleBindingを別の名前空間に作っている、
-nを付け忘れている、がよくある原因です。 - APIグループが合っているか:Deploymentを
""のグループで許可しているなど、apiGroupsの誤りです。 - サブリソースが漏れていないか:ログなら
pods/log、execならpods/exec、スケールならdeployments/scaleが別に必要です。 - 相手の名前が合っているか:サービスアカウントの名前空間の誤りや、ユーザー名の表記の違いです。エラーに出ている名前をそのままsubjectsに使います。
なお、自分が持っていない権限を含むロールは、原則として作ることも他人に与えることもできません。これは権限の昇格を防ぐための仕組みで、その場合も同じくForbiddenになります。
まとめ
- RBACは許可を足していく方式で、拒否のルールはない。必要な許可だけを足していく。
- 共通の権限はClusterRoleにまとめ、名前空間ごとにRoleBindingで配る。
- editはSecretを読める。Secretを見せたくない相手には専用のロールを作る。
- CI用のサービスアカウントは
resourceNamesや名前空間で範囲を絞り、有効期限付きのトークンを使う。 - 権限は
kubectl auth can-iで「できること」「できないこと」の両方を確かめ、Forbiddenはエラー文の各項目から原因を特定する。