Kubernetes基礎 #7 - アクセスコントロール

Last Edited: 6/3/2025

このブログ記事では、Kubernetesにおけるアクセスコントロールについて紹介します。

DevOps

これまで、私たちは単独の管理者/開発者としてアプリケーションを開発し、Kubernetesクラスターを設定してきました。 しかし、より大規模で現実的なクラスターでは、他の開発者と協力し、自動化ツールを使用する必要があります。 これにより、適切なアクセス制御なしでは、他の開発者やツールがクラスター内の無関係なシークレット、データベース、 決済サービスにアクセスする機会が生じてしまいます。そのため、この記事では、Kubernetesにおけるアクセス制御の基本について説明します。

ユーザー認証

アクセス制御は、認証と認可という2つのプロセスで構成されます。認証はユーザーの身元を確認するプロセスであり、 認可は確認されたユーザーに付与されるアクセスに関するルールを適用するプロセスです。 サービスに対するユーザーの認証は実装する必要があり、SSL、JSON Web Tokens(JWT)、 OpenID Connect(OIDC)(Microsoft、Salesforce、GoogleなどでサポートされているOAuth2)など、 ユーザー認証を設定する方法は複数あります。

ネットワーク #4 - HTTP & HTTPSでは、 サーバーの身元を確認する文脈でTLS(SSLの後継)の基本について説明しました。 この仕組みをユーザーの身元確認に適用することができます。 ユーザーが自分の証明書と鍵からCertificate Signing Request(CSR)を発行し(OpenSSLによる)、 管理者がCertificate Authority(CA)として証明書に署名し、サービスがCAの鍵で署名された証明書を検証して信頼と接続を確立します。 Kubernetesはcertificates.k8s.io/v1というAPIを提供しており、これによりユーザーは十分な情報を含むYAMLファイルを適用することで簡単にCSRを作成できます。

管理者はget csrでCSRを確認し、describeで詳細を確認し、certificate approveで証明書に署名し、 kubeconfigファイルを使用して特定のユーザー名と発行された証明書でユーザーをAPIサーバーに登録できます。 その後、ユーザーはset-credentialsを使用して認証情報を提供し、新しいコンテキストに切り替えて自分自身を認証できます。 APIサーバーは認証のためにOIDCプロバイダーからJWTトークンを受信するように設定することもできます(これはよりスムーズで推奨されます)が、詳細はこの記事の範囲外です。

ロールベースアクセス制御(RBAC)

ユーザーの認可を実装する方法は様々ありますが、ユーザーまたはグループに特定のアクセス権限を持つロールを割り当てるロールベースアクセス制御(RBAC)(PostgreSQLでも使用されています)は、一般的に使用される方法です。 Kubernetesでは、まず特定のアクセス権限を持つRoleを定義し、次にRoleBindingを定義することでそのロールをユーザーに割り当てることができます。 ロールは名前空間のリソースに適応され、APIグループ(v1のようなコアAPIグループやその他の名前付きAPIグループ)、リソース(pods、services、deployments)、 および動詞(get、watch、list、create、update、delete等)を使用して定義できます。

pod-readonly.yaml
## Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-readonly
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
## Role Binding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: pod-readonly
subjects:
  - kind: User
    name: example-user
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-readonly
  apiGroup: rbac.authorization.k8s.io

ロールは名前空間スコープであるため、名前空間やノード間のリソースに関するルールを指定することはできません。 そのため、これらのルールを指定できるClusterRoleClusterRoleBindingと呼ばれる別のオブジェクトセットがあります。 いくつかのプリセットクラスターロールとクラスターロールバインディングがあり、ルールを集約することでカスタマイズできますが、 詳細は残念ながらこの記事の範囲外です。

サービスアカウント

これまでユーザー(開発者)の認証と認可について説明してきましたが、ビルドツール、監視、ログサービスなども安全な方法でクラスターのリソースに干渉する必要があります。 これらの非人間サービスに対してKubernetesでは、サービスアカウントと呼ばれる抽象化を提供し、認証と認可を実装します。 監視サービス用の新しいサービスアカウント(各名前空間に定義されているデフォルトのサービスアカウントとは別に)を以下のように作成できます。

monitor-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata: 
  name: monitor-sa
  namespace: default
---
apiVersion: v1
kind: Secret
metadata:
  name: monitor-sa-secret
  annotations:
    kubernetes.io/service-account.name: monitor-sa
type: kubernetes.io/service-account-token

後半部分では、サービスアカウントを認証するための長期間有効なAPIトークンを作成しています。監視サービスに対応するPodは、specの下にサービスアカウント名を含め、 シークレットをボリュームとしてマウントしてmonitor-saサービスアカウントとして認証できます。 また、Podがプライベートリポジトリからコンテナイメージを読み込むことを意図したimagePullSecretも認証に使用できます。 imagePullSecretは以下のように作成できます。

kubectl create secret docker-registry myregistrykey --docker-server=<registry name> \
        --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \
        --docker-email=DUMMY_DOCKER_EMAIL

その後、Pod仕様ではimagePullSecretsフィールドの下に作成されたキーの名前を含めることで、プライベートイメージをプルできます。 同じシークレットは、monitor-sa.yamlのトップレベルのimagePullSecretsフィールドの下にキーの名前を含めることで、 サービスアカウントの認証にも使用できます。サービスアカウントを認証した後、通常のユーザーの認可と同様に、RBACを使用してロールを割り当て、それらをサービスアカウントにバインドできます。

結論

この記事では、ユーザー認証、ロールベースアクセス制御、サービスアカウントの基本について説明ました。 これらは管理者が安全なクラスターを設定し、開発者が適切なアクセス制御が設定されたクラスターで作業するために重要な基本概念です。 しかし、将来説明予定の概念やツールによって、APIサーバー上で直接設定する必要性を部分的に排除できるため、多くの詳細はこの記事では省略されています。 詳細に興味がある場合は、以下に引用されている公式Kubernetesドキュメントをご確認ください。

リソース