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つあります。

  1. 許可を足していく方式で、拒否のルールはありません。何も与えられていなければ何もできず、与えた許可の合計がその相手の権限になります。「この操作だけ禁止」はできないため、広い権限を与えてから削る設計はできません。
  2. RoleBindingからClusterRoleを参照できます。この場合、ClusterRoleの内容がその名前空間の中だけで有効になります。共通の権限セットをClusterRoleとして1つ作り、名前空間ごとにRoleBindingで配る、という使い方が一般的です。
  3. **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)」「どの名前空間で」が読み取れます。直すときは、次の順に確かめます。

  1. 名前空間が合っているか:RoleBindingを別の名前空間に作っている、-n を付け忘れている、がよくある原因です。
  2. APIグループが合っているか:Deploymentを "" のグループで許可しているなど、apiGroups の誤りです。
  3. サブリソースが漏れていないか:ログなら pods/log、execなら pods/exec、スケールなら deployments/scale が別に必要です。
  4. 相手の名前が合っているか:サービスアカウントの名前空間の誤りや、ユーザー名の表記の違いです。エラーに出ている名前をそのままsubjectsに使います。

なお、自分が持っていない権限を含むロールは、原則として作ることも他人に与えることもできません。これは権限の昇格を防ぐための仕組みで、その場合も同じくForbiddenになります。

まとめ

  • RBACは許可を足していく方式で、拒否のルールはない。必要な許可だけを足していく。
  • 共通の権限はClusterRoleにまとめ、名前空間ごとにRoleBindingで配る。
  • editはSecretを読める。Secretを見せたくない相手には専用のロールを作る。
  • CI用のサービスアカウントは resourceNames や名前空間で範囲を絞り、有効期限付きのトークンを使う。
  • 権限は kubectl auth can-i で「できること」「できないこと」の両方を確かめ、Forbiddenはエラー文の各項目から原因を特定する。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲