はじめに
こんにちは!
本記事は「本気で学ぶKubernetes」シリーズの第7回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。
このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!
今回は、KubernetesのRBAC(Role-Based Access Control)という権限管理の仕組みについて触れていきたいと思います。
この記事は人間がKubernetesの公式ドキュメントを読み漁りながら、人間の手で書いていますのでご安心ください!
Kubernetesのアカウント体系
Kubernetesには2種類のアカウントがあります。
ユーザーアカウント(Users)
こちらはKubernetesを使用するユーザーのアカウントです。
LDAPやGoogle AccountsなどKubernetesの外部で管理でき、kubectlコマンドを実行するときこのユーザーアカウントとして認証することもできます。
サービスアカウント(ServiceAccount)
サービスアカウントはPod内のプロセスが利用するアカウントです。
Kubernetes APIにて管理されており、namespace単位で作成することができます。
kubectl create serviceaccount my-app
Podにサービスアカウントを割り当てると、そのPodはKubernetes APIにアクセスできるようになります。
今回の記事では、主にこのサービスアカウントに対する権限管理について触れていこうと思います。
出典: Kubernetes公式ドキュメント - Authenticating
なぜRBACが必要なのか
デフォルトでは、すべてのPodが同じdefaultサービスアカウントを使います。もしdefaultに広い権限を与えてしまうと、すべてのPodが同じ権限を持ってしまい、権限の分離ができません。
例えば、あるアプリケーションがConfigMapを読み取るだけでいいのに、Secretやその他のリソースも操作できてしまう状態は望ましくありません。
RBACを使うことでサービスアカウントごとに細かく権限を設定できます。
RBACの基本概念
RBACは簡単にいうと「誰が」「何に対して」「何をできるか」をロールを割り当てることで制御していく仕組みです。
AWSやGoogle Cloudクラウドなどのクラウドサービスをすでに利用されている方にはおなじみの概念かと思います。
ServiceAccount
PodがKubernetes APIにアクセスする際のアカウントの実態です。デフォルトではdefault ServiceAccountが使われますが、カスタムServiceAccountを作成して権限を個別に設定することも可能です。
Role と ClusterRole
権限のセットを定義するリソースです。
- Roleは特定のnamespace内での権限を定義します。
- ClusterRoleはクラスタ全体での権限を定義します。
どちらも「どのリソースに対して、どんな操作ができるか」をrulesで指定します。
そして作成した権限のセットは実際にnamespaceやクラスタなどの範囲で、ServiceAccountに結びつけていく必要があります。
namespace内でのバインディングを行う場合はRoleBinding、クラスタ全体でのバインディングを行う場合はClusterRoleBindingを利用します。
指定可能な権限例
権限で指定できる主な操作には以下のようなものが用意されています。
こちらもクラウドを利用されている方はイメージがしやすいかと多います。
-
get,list,watch: 読み取り系 -
create: 新規作成 -
update,patch: 更新 -
delete: 削除 -
*: すべての操作(管理者向け、通常は避けるべき)
出典: Kubernetes公式ドキュメント - Using RBAC Authorization
出典: Kubernetes公式ドキュメント - Configure Service Accounts for Pods
RBACで権限制御を試してみる
ここからは実際にRBACを使ってPodに最小限の権限だけを与える方法を確認していきます。
今回は、default namespaceのPod情報を読み取る権限だけを与えて、Secretなど他のリソースは操作させないようにしてみます。
まず、必要なリソースを一つのマニフェストファイルにまとめます。
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "my-service-account" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# You can specify more than one "subject"
- kind: ServiceAccount
name: my-service-account # "name" is case sensitive
namespace: default
roleRef:
# "roleRef" specifies the binding to a Role / ClusterRole
kind: Role # this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
name: rbac-test-pod
namespace: default
spec:
serviceAccountName: my-service-account
containers:
- name: kubectl-container
image: bitnami/kubectl
command: ["sleep", "3600"]
このマニフェストには4つのリソースを含めています。
簡単に説明すると、ServiceAccountのmy-service-accountを作成し、そこにPodの読み取り権限(get, watch, list)だけを与えるpod-readerというRoleを定義しています。
そしてRoleBindingのread-podsでこの2つを結びつけて、最後にテスト用のPodを作成します。
デプロイと動作確認
kubectl apply -f rbac-pod-reader.yaml
# serviceaccount/my-service-account created
# role.rbac.authorization.k8s.io/pod-reader created
# rolebinding.rbac.authorization.k8s.io/read-pods created
# pod/rbac-test-pod created
Pod内からPodの情報を取得してみます。
kubectl exec rbac-test-pod -- kubectl get pods
# NAME READY STATUS RESTARTS AGE
# rbac-test-pod 1/1 Running 0 30s
成功しましたので、次に権限のないSecretを取得してみます。
kubectl exec rbac-test-pod -- kubectl get secrets
# Error from server (Forbidden): secrets is forbidden: User "system:serviceaccount:default:my-service-account" cannot list resource "secrets" in API group "" in the namespace "default"
こちらは権限エラーになりました。これでPodの読み取り権限だけが付与されていることが確認できました。
権限の確認コマンド
kubectl auth can-iコマンドを使うと、特定のServiceAccountがどんな操作を許可されているか確認できます。
kubectl auth can-i get pods --as=system:serviceaccount:default:my-service-account
# yes
kubectl auth can-i get secrets --as=system:serviceaccount:default:my-service-account
# no
ちなみに、ユーザーアカウント(自分自身)の権限を確認したい場合は--asオプションを付けずに実行します。
# 自分の権限を確認
kubectl auth can-i get pods
# yes
kubectl auth can-i create deployments
# yes
# 自分が持っている全権限の一覧
kubectl auth can-i --list
# Resources # Non-Resource URLs Resource Names Verbs
# *.* # [] [] [*]
# [*] # # [] # [*]
# selfsubjectreviews.authentication.k8s.io # [] [] [create]
# selfsubjectaccessreviews.authorization.k8s.io # [] [] [create]
# selfsubjectrulesreviews.authorization.k8s.io # [] [] [create]
# [/api/# *] # # [] # # [get]
RoleBindingの確認
さらに今回作成したRoleBindingの設定内容も確認してみます。
kubectl get rolebinding read-pods -o yaml
出力結果は以下の通りになりました。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"name":"read-pods","namespace":"default"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"Role","name":"pod-reader"},"subjects":[{"kind":"ServiceAccount","name":"my-service-account","namespace":"default"}]}
creationTimestamp: "2025-12-07T12:19:17Z"
name: read-pods
namespace: default
resourceVersion: "32792"
uid: 762103ec-253a-4bbd-838f-212757207b94
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: default
出力を見ると、subjectsでServiceAccountを指定し、roleRefでRoleを参照していることが分かりますね。
もし権限が効いていない場合は、RoleやRoleBindingが同じnamespaceにあるかどうか、またsubjectsのnameとnamespaceが合っているかを確認してみてください!
ClusterRoleの例
ここまではnamespace内での権限管理(Role/RoleBinding)を見てきましたが、クラスタ全体での権限が必要な場合はClusterRoleを使う必要があります。
ユースケースとしては以下の場合が挙げられます。
- 複数namespaceにまたがる権限が必要な場合
- クラスタ全体のリソース(Node、PersistentVolumeなど)を扱う場合
Kubernetesには、よく使われる権限セットが組み込みのClusterRoleとして用意されています。
kubectl get clusterrole | grep -E "^(view|edit|admin|cluster-admin)"
# admin 2024-12-01T00:00:00Z
# cluster-admin 2024-12-01T00:00:00Z
# edit 2024-12-01T00:00:00Z
# view 2024-12-01T00:00:00Z
- view: 読み取り専用
- edit: リソースの編集可能(SecretやRoleは除く)
- admin: namespace内のほぼすべての権限
- cluster-admin: クラスタ全体の全権限
これらを使うことで、一から権限を定義する手間を省けます。
ベストプラクティス
RBACの権限管理のベストプラクティスは、AWSやGoogle Cloudなどのクラウドサービスと基本的に同じ考え方になると思います。
以下のような内容は必ず押さえておいた方が良いでしょう。
-
最小権限の原則:必要最低限の権限だけを付与。
*(すべての権限)は避け、具体的なverbsを指定 -
ServiceAccountの分離:アプリケーションごとに専用のServiceAccountを作成。
defaultServiceAccountは使わない - 定期的な権限の見直し:不要になった権限は削除し、定期的に見直す
-
明示的な指定:Podのマニフェストで
serviceAccountNameを明示的に指定する
まとめと次回予告
今回は、KubernetesのRBACを使って、Podやユーザーの権限を細かく制御する方法を確認しました。
RBACは、ServiceAccount、Role/ClusterRole、RoleBinding/ClusterRoleBindingの3つの要素を最低限押さえておけば良いと思います。その上で最小権限の原則に従って、セキュリティを向上させていきましょう!
次回はサービスの健康状態を監視するための仕組みであるProbeのLiveness/Readiness/Startupについて触れていきたいと思います!
それでは、また明日!