サービスアカウント

KubernetesのServicesAccountオブジェクトについて学びます。

このページではKubernetesのServiceAccountオブジェクトについて説明し、どのようにサービスアカウントが機能するか、使用例、制限、代替手段、追加のガイダンスとなるリソースへのリンクを紹介します。

サービスアカウントとは?

サービスアカウントは、Kubernetesにおいて、Kubernetesクラスター内で固有のアイデンティティを提供する人間以外のアカウントの一種です。 アプリケーションPod、システムコンポーネント、およびクラスター内外のエンティティは、特定のServiceAccountの認証情報を使用してそのServiceAccountとして識別できます。 このアイデンティティは、APIサーバーへの認証やアイデンティティベースのセキュリティポリシーの実装など、さまざまな状況で役立ちます。

サービスアカウントは、APIサーバー内のServiceAccountオブジェクトとして存在します。 サービスアカウントには次の特性があります:

  • Namespaced: 各サービスアカウントはKubernetesのnamespaceにバインドされます。 各namespaceは作成時にdefault ServiceAccountを取得します。

  • Lightweight: サービスアカウントはクラスター内に存在し、Kubernetes APIで定義されています。 特定のタスクを有効にするためにサービスアカウントを素早く作成できます。

  • Portable: 複雑なコンテナ化されたワークロードの構成バンドルには、システムのコンポーネントのサービスアカウント定義が含まれる場合があります。 サービスアカウントの軽量性と名前空間内のアイデンティティは、構成をポータブルにします。

サービスアカウントは、クラスター内の認証された人間のユーザーであるユーザーアカウントとは異なります。 デフォルトでは、KubernetesのAPIサーバーにユーザーアカウントは存在しません。代わりに、APIサーバーはユーザーのアイデンティティを不透明なデータとして扱います。 複数の方法を使用して、ユーザーアカウントとして認証できます。 一部のKubernetesディストリビューションでは、APIサーバーでユーザーアカウントを表すカスタム拡張APIが追加されることがあります。

サービスアカウントとユーザーの比較
説明ServiceAccountユーザーまたはグループ
ロケーションKubernetes API (ServiceAccountオブジェクト)外部
アクセス制御Kubernetes RBACまたはその他の認可メカニズムKubernetes RBACまたはその他のアイデンティティおよびアクセス管理メカニズム
使用目的ワークロード、自動化人間

デフォルトのサービスアカウント

クラスターを作成すると、Kubernetesはクラスター内の各Namespaceに対してdefaultという名前のServiceAccountオブジェクトを自動的に作成します。 各Namespaceのdefaultサービスアカウントは、ロールベースのアクセス制御(RBAC)が有効になっている場合、Kubernetesがすべての認証されたプリンシパルに付与するデフォルトのAPI検出権限以外の権限をデフォルトで取得しません。 Namespace内のdefault ServiceAccountオブジェクトを削除すると、コントロールプレーンが新しいServiceAccountオブジェクトを作成します。

NamespaceにPodをデプロイし、Podに手動でServiceAccountを割り当てない場合、KubernetesはそのNamespaceのdefault ServiceAccountをPodに割り当てます。

Kubernetesサービスアカウントの使用例

一般的なガイドラインとして、次のシナリオでサービスアカウントを使用できます:

  • PodがKubernetes APIサーバーと通信する必要がある場合、例えば次のような場合です:
    • Secretに保存されている機密情報への読み取り専用アクセスを提供します。
    • Namespaceをまたいだアクセスを許可します。例えば、example NamespaceのPodがkube-node-lease NamespaceのLeaseオブジェクトを読み取り、一覧、監視することを許可します。
  • Podが外部のサービスと通信する必要がある場合。例えば、ワークロードのPodには商用クラウドAPIのアイデンティティが必要であり、商用プロバイダーは適切な信頼関係の構成を許可する場合です。
  • imagePullSecretを使用してプライベートイメージレジストリに認証する場合。
  • 外部サービスがKubernetes APIサーバーと通信する必要がある場合。例えば、CI/CDパイプラインの一部としてクラスターに認証する必要がある場合です。
  • クラスター内でサードパーティのセキュリティソフトウェアを使用する場合。さまざまなPodのServiceAccountアイデンティティを使用してこれらのPodを異なるコンテキストにグループ化します。

サービスアカウントの使用方法

Kubernetesサービスアカウントを使用するには、次の手順を実行します:

  1. kubectlなどのKubernetesクライアントを使用してServiceAccountオブジェクトを作成するか、オブジェクトを定義するマニフェストを使用します。

  2. RBACなどの認可メカニズムを使用してServiceAccountオブジェクトに権限を付与します。

  3. Podの作成時にServiceAccountオブジェクトをPodに割り当てます。

    外部サービスからのアイデンティティを使用している場合は、ServiceAccountトークンを取得し、そのサービスから使用します。

詳細な手順については、PodにServiceAccountを割り当てるを参照してください。

ServiceAccountに権限を付与する

各ServiceAccountに必要な最小限の権限を付与するために、Kubernetesビルトインのロールベースのアクセス制御(RBAC)メカニズムを使用できます。 ServiceAccountにアクセスを付与するロールを作成し、そのロールをServiceAccountにバインドします。 RBACを使用すると、ServiceAccountの権限が最小限になるように定義できます。 PodがそのServiceAccountを使用している場合、そのPodは正しく機能するために必要な権限以上の権限を取得しません。

詳細な手順については、ServiceAccount権限を参照してください。

ServiceAccountを使用したNamespace間のアクセス

RBACを使用して、クラスターの異なるNamespaceにあるリソースに対して別のNamespaceのServiceAccountがアクションを実行できるようにすることができます。 例えば、dev NamespaceにサービスアカウントとPodがあり、そのPodがmaintenance Namespaceで実行されているJobを見る必要がある場合を考えてみましょう。 Jobオブジェクトをリストする権限を付与するRoleオブジェクトを作成できます。 次に、そのRoleをmaintenance NamespaceのServiceAccountオブジェクトにバインドするRoleBindingオブジェクトを作成します。 そうすることで、dev NamespaceのPodは、そのServiceAccountを使用してmaintenance NamespaceのJobオブジェクトをリストできます。

PodにServiceAccountを割り当てる

ServiceAccountをPodに割り当てるには、Podの仕様にあるspec.serviceAccountNameフィールドを設定します。 Kubernetesは、そのServiceAccountの認証情報をPodに自動的に提供します。 v1.22以降では、KubernetesはTokenRequest APIを使用して有効期間が短く自動的にローテーションされるトークンを取得し、そのトークンを投影ボリュームとしてPodにマウントします。

デフォルトではKubernetesは、ServiceAccountがdefault ServiceAccountか指定したカスタムServiceAccountであるかに関わらず、PodにそのServiceAccountの認証情報を提供します。

Kubernetesが指定されたServiceAccountまたはdefault ServiceAccountの認証情報を自動的に注入しないようにするには、Podの使用にあるautomountServiceAccountTokenフィールドをfalseに設定します。

1.22より前のバージョンでは、Kubernetesは有効期間の長い静的なトークンをSecretとしてPodに提供します。

ServiceAccount認証情報の手動取得

ServiceAccountを標準以外の場所にマウントするための認証情報、またはAPIサーバー以外の対象向けの認証情報が必要な場合は、次のいずれかの方法を使用します:

  • TokenRequest API (推奨): 独自のアプリケーションコードから短期間のサービスアカウントトークンをリクエストします。 トークンは自動的に期限切れになり、期限切れ時にローテーションできます。 Kubernetesに対応していないレガシーアプリケーションがある場場合、同じPod内のサイドカーコンテナを使用してこれらのトークンを取得し、アプリケーションワークロードで使用できるようにすることができます。
  • トークン投影ボリューム (推奨): Kubernetes v1.20以降では、Podの仕様を使用して、kubeletにサービスアカウントトークンを投影ボリュームとしてPodに追加するように指示します。 投影トークンは自動的に期限切れになり、kubeletはトークンが期限切れになる前にトークンをローテーションします。
  • サービスアカウントトークンシークレット(Kubernetes v1.24からv1.26ではデフォルトで有効) (非推奨): サービスアカウントトークンをKubernetes SecretとしてPodにマウントできます。 これらのトークンは期限切れになることも、ローテーションされることもありません。 v1.24以前のバージョンでは、サービスアカウントごとに永続的なトークンが自動的に作成されていました。 この方法は、静的で有効期間の長い認証情報に関するリスクがあるため、特に大規模な環境では推奨されなくなりました。 LegacyServiceAccountTokenNoAutoGenerationフィーチャーゲートにより、Kubernetesが指定されたServiceAccountに対してこれらのトークンを自動的に作成するのを防止できました。 このフィーチャーゲートはGAステータスに昇格したため、v1.27では削除されました。 無期限のサービスアカウントトークンを手動で作成することは引き続き可能ですが、セキュリティ上の影響を考慮する必要があります。

シークレットへのアクセスを制限する

Kubernetesは、ServiceAccountに追加できるkubernetes.io/enforce-mountable-secretsというアノテーションを提供しています。 このアノテーションを適用すると、ServiceAccountのシークレットは指定された種類のリソースにのみマウントできるため、クラスターのセキュリティ体制が強化されます。

マニフェストを使用してServiceAccountにアノテーションを追加できます:

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubernetes.io/enforce-mountable-secrets: "true"
  name: my-serviceaccount
  namespace: my-namespace

このアノテーションが"true"に設定されている場合、Kubernetesコントロールプレーンは、このServiceAccountのSecretが特定のマウント制限の対象であることを確認します。

  1. Pod内のボリュームとしてマウントされる各Secretのな雨は、PodのServiceAccountのsecretsフィールドに表示される必要があります。
  2. Pod内のenvFromを使用して参照される各Secretの名前は、PodのServiceAccountのsecretsフィールドに表示される必要があります。
  3. Pod内のimagePullSecretsを使用して参照される各Secretの名前は、PodのServiceAccountのsecretsフィールドに表示される必要があります。

これらの制限を理解して適用することで、クラスター管理者はより厳格なセキュリティプロファイルを維持し、適切なリソースのみがシークレットにアクセスできるようにします。

サービスアカウント認証情報の認証

ServiceAccountは、Kubernetes APIサーバーおよび信頼関係が存在する他のシステムに対して、署名されたJSON Web Tokens (JWTs) を使用して認証を行います。 トークンの発行方法(TokenRequestを使用して時間制限付きで発行されるか、Secretを使用して従来のメカニズムで発行されるか)に応じて、ServiceAccountトークンには有効期限、オーディエンス、トークンが有効になる時間などが含まれる場合があります。 ServiceAccountとして機能しているクライアントがKubernetes APIサーバーと通信しようとすると、クライアントはHTTPリクエストにAuthorization: Bearer <token>ヘッダーを含めます。 APIサーバーは、次のようにしてBearerトークンの有効性を確認します:

  1. トークンの署名を確認します。
  2. トークンが期限切れかどうかを確認します。
  3. トークン要求内のオブジェクト参照が現在有効かどうかを確認します。
  4. トークンが現在有効かどうかを確認します。
  5. オーディエンス要求を確認します。

TokenRequest APIは、ServiceAccountに バインドされたトークン を生成します。 このバインディングは、そのServiceAccountとして機能しているクライアント(Podなど)のライフタイムにリンクされています バインドされたPodのサービスアカウントトークンのJWTスキーマとペイロードの例については、トークンボリューム投影を参照してください。

TokenRequest APIを使用して発行されたトークンの場合、APIサーバーは、そのオブジェクトの ユニークID と一致する、ServiceAccountを使用している特定のオブジェクト参照がまだ存在するかどうかも確認します。 PodにSecretとしてマウントされているレガシートークンの場合、APIサーバーはトークンをSecretと照合します。

認証プロセスの詳細については、認証を参照してください。

独自のコードでサービスアカウントの認証情報を認証する

Kubernetesサービスアカウントの認証情報の検証が必要なサービスがある場合、次の方法を使用できます:

Kubernetesプロジェクトでは、TokenReview APIの使用を推奨しており、この方法ではSecret、ServiceAccount、Pod、NodeなどのAPIオブジェクトにバインドされたトークンが削除されると、そのトークンが無効になります。 例えば、投影されたServiceAccountトークンを含むPodを削除すると、クラスターはただちにそのトークンを無効にし、TokenReviewはただちに失敗します。 代わりにOIDC認証を使用する場合、トークンが有効期限のタイムスタンプに達するまで、クライアントはトークンを有効なものとして扱い続けます。

アプリケーションでは、受け入れるオーディエンスを常に定義し、トークンのオーディエンスがアプリケーションが期待するオーディエンスと一致するかどうかを確認する必要があります。 これにより、トークンのスコープが最小限に抑えられ、アプリケーション内でのみ使用でき、他の場所では使用できないようになります。

代替案

次の項目

このページの項目は、Kubernetesが必要とする機能を提供するサードパーティー製品またはプロジェクトです。Kubernetesプロジェクトの作者は、それらのサードパーティー製品またはプロジェクトに責任を負いません。詳しくは、CNCFウェブサイトのガイドラインをご覧ください。第三者のリンクを追加するような変更を提案する前に、コンテンツガイドを読むべきです。