Pod内でkubectlを利用する

権限を追加設定することで、コンテナ内でkubectlを実行してクラスタ操作できます。
コンテナの権限を管理するkubernetes標準の方法はRoleリソースを用います。

RBMACの保証と拡張性のため、Roleを直接Podに割りあてることはできず、RoleBindingServiceAccountがセットで必要となり、次のような参照関係になります。

Role <- RoleBinding -> ServiceAccount <- Pod

また、GKEなどの各ホスティングがこのk8s標準のアカウンティングとは別の認証を提供している場合もあります。
後述のとおり、Roleを用いた認可では個別リソース単位の少ない権限割りあてが可能で、操作対象が明確な場合に適しています。 gkeの認証などは、クラスタの広範囲なリソースを制御する場合や、クラスタ外のGCP機能をAPI制御する場合に適しています。

なお、kubernetesのバージョンがとても古いクラスタではRBAC認可機能じたいが有効になっていない場合があります。その場合、バージョンアップや設定変更が必要です。

コンテナ用kubectl

最終的に動作させるkubectlはあらかじめコンテナイメージに追加しておきます。
ディストリビューションが提供するパッケージ追加、または 公式配布のバイナリのいずれでも動作するでしょう。

Roleによるセットアップではk8sの標準APIを使用するため、追加の認証プラグインは不要です。

Role

Roleのリソース定義は 公式ガイドにひと通り解説があります。

既述のとおり、認可権限を定義するのはRoleです。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

この権限セットを付与したコンテナ内では、kubectl get podsが意図どおり動作します。

rulesに利用できる権限を定義するのですが、指定すべきキーワードを手軽に知る方法がないという難点があります。

  • rules.[].apiGroupsはリソース分類を指定する。各リソースのapiVersionからversionを除去したURI。
    • Pod操作などを含むコアAPIは""の省略記法で指定できる。文字列としては簡素だが概念は自明ではない。たとえばnetworking.k8s.ioはコアAPIではないためURIを明示しないと動作しない、という点に気づきづらい
  • rules.[].resourcesは具体的な操作対象。この例のとおり、とくにサブリソースが自明ではない
    • k8sのHTTP APIのパスを指定する項目のため、HTTP APIリファレンスがあれば特定できるだろう
  • rules.[].verbsはHTTPメソッド風の操作カテゴリー。kubectlのサブコマンドに対応するが完全に同じラベルではなく、自明でない
    • kubectl applyに対応するリソース更新操作は、updateまたはpatch権限が必要だがいずれであかを知る手段はない

RoleとClusterRole

Roleで指定した権限はmetadata.namespace内のリソースに限られます。
より広いリソースの権限を一括で付与するにはClusterRoleとそれに対応するClusterBindingを用います。

操作対象を特定できる場合、スコープの狭いRoleを使用した方がセキュアです。

ServiceAccount

ServiceAccountは、無人ユーザーです。基本的には目的を表すラベルを定義します。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-serviceaccount
  namespace: default

DeploymentなどのpodSpecにserviceAccountNameを指定することにより、指定のServiceAccountでPodが動作します。

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      serviceAccountName: my-serviceaccount
      containers:
      - name: nginx
        image: nginx:latest

RoleBinding

RoleBindingはこの例ではServiceAccountRoleを関連づけるリソースで、これらの名前が決まったら適切に参照するだけのものです。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: ServiceAccount
  name: my-serviceaccount
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-and-pod-logs-reader
  apiGroup: rbac.authorization.k8s.io

この例ではServiceAccountが1つずつしかないため単に手間が増えたように見えますが、subjectsリストを任意のタイミングで変更したり、reoleRefが固定されているなど、想定外のセキュリティホールが生じにくくなるように設計されています。

中馬崇尋
Chuma Takahiro