こんにちは!今日は、Kubernetesセキュリティの基本であり核心であるService Account(サービスアカウント)について深く掘り下げていきたいと思います。
単に「Podに権限を与えるときに使うものじゃないの?」と思っていた方は、今日の投稿を通じて、より深い内容を持ち帰ることができるでしょう。特に、最近のKubernetesバージョンで標準となったProjected VolumeとBound Tokenの概念は、セキュリティの観点から非常に重要なので、必ず理解しておきましょう。
10分だけ投資して、Kubernetes認証構造の核心をマスターしてください! 🚀

1. Service Account (SA): Podのための身分証 🪪
私たちが会社の建物に入る際に社員証をかざすように、Kubernetesクラスター内部でPod内のアプリケーションがAPIサーバーと通信するには身分証が必要です。これがService Accountです。
👤 User Account vs. 🤖 Service Account
- User Account: 人間(Human)のためのアカウントです。(管理者、開発者など)。主にグローバルに管理され、AWS IAMやGoogleアカウントなどの外部システムと連携します。
- Service Account: プロセス(Bot)のためのアカウントです。Namespaceに依存する点が最も大きな特徴です。
Podを作成する際に別途指定しない場合、Kubernetesは自動的にそのNamespaceのdefaultサービスアカウントを割り当てます。
2. 過去の方法: 「永遠に腐らない鍵」(Legacy) 🗝️
以前(Legacy)の方法では、サービスアカウントを作成すると自動的にSecret(シークレット)リソースが作成されました。そして、このシークレットの中には有効期限のない(No Expiration)トークンが入っていました。
この方法には致命的な欠点がありました。
- セキュリティ脆弱性: トークンが一度盗まれると、管理者が手動で失効させるまでハッカーが永遠に使用できてしまいます。
- 管理の不便さ: トークンを交換(Rotation)するには、シークレットを削除して再作成するという面倒な作業が必要でした。
そのため、KubernetesコミュニティはProjected Volumeという新しい技術を導入しました。
3. 現在の標準: Projected Volumeと「生きているトークン」 ✨
最新のKubernetesでは、トークンは静的なSecretに保存されません。代わりにProjected Volumeを利用して、Podが作成されるその瞬間にAPIサーバーから「一時トークン」を発行してもらい、Podに注入します。
📽️ なぜ「Projected(投影された)」という名前なのですか?
一般的なボリュームマウントが単一のストレージを接続するのに対し、Projected Volumeは複数のソース(Source)を一つのディレクトリに集めて(投影して)見せる技術だからです。
通常、次の3つの情報が1つのフォルダ(/var/run/secrets/kubernetes.io/serviceaccount)に混在して表示されます。
- serviceAccountToken: 認証のためのJWTトークン
- configMap (kube-root-ca.crt): APIサーバー信頼のための証明書
- downwardAPI: PodのNamespace情報
4. コア技術: Bound Service Account Token 🔗
Projected Volumeを通じて注入されるトークンはBound Tokenと呼ばれます。どこかに強力に「묶여(Bound)」いるからです。この概念がセキュリティの核心です。
① Time Bound(時間制限) ⏳
このトークンには有効期間があります(デフォルトは1時間)。
- Legacy: 有効期限なし。
- Modern:
expirationSecondsが設定されています。
② Object Bound(Podへの依存) 📦
このトークンは、発行された特定のPod(Pod UID)と運命を共にします。
- Podが削除されると、トークンも即座に無効化されます。
- 攻撃者がトークンをコピーして別のPodで使おうとしても、トークン内部の情報と実行環境が一致しない場合、拒否される可能性があります。
③ Audience Bound(使用目的の制限) 🎯
トークンに aud(Audience)フィールドを設定できます。
- 「このトークンはAWS認証用だ」として発行された場合、このトークンでKubernetes APIサーバーをハッキングしようとしても、「あれ?君はAWS用じゃないか?」と拒否されます。
- Istioのようなサービスメッシュは、この機能を積極的に活用してサービス間の認証を行います。
5. YAMLファイルを覗いてみよう 📝
皆さんのPod YAMLファイルの一番下を見ると、kubeletが自動的に追加した次のような設定が見られます。
YAML
volumes:
- name: kube-api-access-xxxxx
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607 # 👈 1時間後に失効!
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
この設定のおかげで、Pod内部のアプリケーションは /var/run/secrets/kubernetes.io/serviceaccount/token ファイルを読み込んで、安全に通信できるのです。
6. トークンが期限切れになったらアプリは死ぬの?(Token Rotation) 🔄
「1時間後に期限切れになるなら、私のサービスも1時間後に停止するの?」
いいえ!心配しないでください。
Kubeletが非常に勤勉に動いています。
- トークンの有効期限が近づくと、Kubeletは自動的にAPIサーバーに新しいトークンをリクエストします。
- そして、Pod内部にマウントされたtokenファイルを新しいトークン値で上書き(Update)します。
- アプリケーション(ほとんどのK8sクライアントライブラリ)は、定期的にファイルを再読み込みしてトークンを更新します。
⚠️ 注意点: アプリケーションを直接開発する場合、トークンファイルを最初に読み込んだら終わりではなく、定期的に再読み込みするロジック(Reload)を実装する必要があります。(Goクライアントなど標準ライブラリは既に実装されています。)
7. まとめ 🎁
今日の内容を3行で要約してみましょう。
- Service Accountは、PodがKubernetes APIと対話するための身分証です。
- セキュリティのため、Projected Volume方式を使用し、寿命が短く自動更新されるトークン(Bound Token)を使用します。
- このトークンはPodと運命を共にし、特定のPodに묶られて(Bound)いるため、盗まれてもリスクが低いです。
これで、kubectl get pod -o yaml を実行したときに出てくる複雑なprojected構文も怖くないですよね?これは、皆さんのクラスターを安全に守るためのKubernetesの細やかな配慮なのです。 🛡️
今日も安全で楽しいKubernetesライフをお過ごしください!
コメントを残す