アドミッションコントローラでKubernetesのセキュリティを強化するには?
すでにKubernetesを使っている方なら、RBACやネットワークポリシーなどの基本的なセキュリティ機能の使い方をご存じかもしれません。
しかし場合によっては、さらに細かい設定やポリシー機能が必要です。クラスターへの参加を許可する前に、追加のチェックを実行してリソースを検証しなければならないこともあるでしょう。
そこで使えるのが Kubernetes アドミッションコントローラです。拡張性に優れたソリューションで、他よりもはるかに高度なセキュリティチェックを実行可能。高度な分析機能やコンプライアンス機能を提供する外部のセキュリティツールと Kubernetes を接続する際にも中心的な役割を果たします。
この記事では、Kubernetes アドミッションコントローラの役割と仕組みについて説明したうえで、アドミッションコントローラを使ってセキュリティを強化する場合の一般的な方法をわかりやすくご紹介します。
関 連 記 事
Kubernetesとは? | Kubernetesセキュリティ の基礎 | Kubernetesアーキテクチャの 設計方法 |
AWSのEKS (Elastic Kubernetes Service) | Kubernetesの クラスターとは? | Kubernetes のノードとは? |
KubernetesのPodとは? | KubernetesのHelmとは? | クラウドセキュリティと ランタイムインサイト |
Kubernetes アドミッションコントローラとは
Kuberneteにおけるアドミッションコントローラとは、Kubernetes APIサーバーへのリクエストを評価し、そのリクエストを許可するかどうかを決定するコードです。
この評価は、APIサーバーがリクエストを認証して権限を付与したあと、リクエストが許可され、実行される前に行われます。
APIサーバーが有効なリクエストであると判断した場合でも(判断は、設定したRBAC RoleやClusterRoleに基づきおこなわれる)、アドミッションコントローラはそのリクエストを評価し、独自のルールに基づいて受け入れるかどうかを決定します。
関連記事:5分でKubernetesのアドミッションコントローラーについて学ぶ
アドミッションコントローラのメリット
アドミッションコントローラは、Kubernetes のセキュリティ戦略の一環として、いくつかの重要なメリットをもたらします。
- リクエストのダブルチェック: アドミッションコントローラは、RBAC ポリシーの設定ミスなどのために RBAC の制御をすり抜ける可能性のある無効なリクエストに対して、第 2 の防御線として機能します。
- ルールの柔軟性: アドミッションコントローラは、RBAC では構成できない(少なくとも簡単にはできない)パラメータに基づいてリクエストを評価し、ルールを適用できます。RBAC は ID とアクションのみに基づいてルールを定義するため、この点は重要です。アドミッションコントローラは、リソースのリクエストを制限したり、特権コンテナでコマンドを実行できないようにしたりするなど、さらに細かい設定が可能です。
- サードパーティの統合: アドミッションコントローラの中には、Webhook を使用できるものがあります。Webhook を使用すると、サードパーティのセキュリティシステムでアクションをトリガできます。つまり、アドミッションコントローラは外部のセキュリティツールを Kubernetes API で直接実行することなく、これらのツールを Kubernetes に統合する手段を提供します。これはおそらく、アドミッションコントローラの最も強力な機能と言えるでしょう。
アドミッションコントローラの使用方法
ここでは、Kubernetes でアドミッションコントローラを使う方法を、手順を追って説明します。
クラスターでのアドミッションコントローラの有効化
Kubernetes でアドミッションコントローラを使用するには、最初にクラスターの kube-apiserver.yaml ファイル(ほとんどの場合、Kubernetes のマスターまたはマスターノードの /etc/kubernetes/manifests/ ディレクトリに格納されます)で、アドミッションコントローラ機能が有効になっていることを確認する必要があります。
–enable-admission-plugins フラグが存在する場合、アドミッションコントローラはそのクラスターに対して有効になっています。
特定のアドミッションコントローラの選択
–enable-admission-plugins フラグのあとに、次のようにコンマ区切りリストが続いていることがあります。
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,TaintNodesByCondition
,Priority,DefaultTolerationSeconds,DefaultStorageClass,StorageObjectInUseProtection
,PersistentVolumeClaimResize,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,RuntimeClass
,ResourceQuota
このリストは、クラスターに対して有効になっている具体的なアドミッションコントローラを示しています。Kubernetes のドキュメントでは、利用できるすべてのアドミッションコントローラについて詳しく説明しています。
–enable-admission-plugins フラグが存在し、あとに続くリストがない場合、Kubernetes はアドミッションコントローラのデフォルトのセットを有効にします。Kubernetes の現在のバージョンでは次のようになります。
- NamespaceLifecycle
- LimitRanger
- ServiceAccount
- TaintNodesByCondition
- Priority
- DefaultTolerationSeconds
- DefaultStorageClass
- StorageObjectInUseProtection
- PersistentVolumeClaimResize
- RuntimeClass
- CertificateApproval
- CertificateSigning
- CertificateSubjectRestriction
- DefaultIngressClass
- MutatingAdmissionWebhook
- ValidatingAdmissionWebhook
- ResourceQuota
つまり、デフォルトのアドミッションコントローラを使用することも、有効にするアドミッションコントローラを明示的に定義することもできます。
アドミッションコントローラの無効化
必要に応じて、kube-apiserver.yaml ファイル内の –disable-admission-plugins=… フラグを使用してアドミッションコントローラを明示的に無効にすることができます。
このフラグはコントローラのデフォルトのセットを使用しており、そのセット内の特定のコントローラを無効にしたい場合に便利です。
アクティブなアドミッションコントローラの確認
クラスター内で有効になっているアドミッションコントローラがわからない場合は、以下のコマンドを実行すると一覧表示できます。
kube-apiserver -h | grep enable-admission-plugins
Kubernetes は、クラスター内で有効にしたアドミッションコントローラを自動的に適用します。(RBAC などのように)追加のポリシーファイルを作成する必要はありません。
ただし、アドミッションコントローラによっては、構成の詳細を指定する必要があります。たとえば、API サーバーで受け入れるリクエストの数を制限する EventRateLimit コントローラを使用するには、YAML 形式の構成ファイルを作成し、–admission-control-config-file フラグを使用して API サーバーにそれを指示する必要があります。
構成ファイルは次のようになります。
apiVersion: eventratelimit.admission.k8s.io/v1alpha1
kind: Configuration
limits:
- type: Namespace
qps: 50
burst: 100
cacheSize: 2000
- type: User
qps: 10
burst: 50
Code language: PHP (php)
このファイルだと、qps は 1 秒あたりのクエリ数(queries per second)を表します。burst は qps で設定した制限を適用する前に API サーバーが受け入れるクエリ数を定義するものです。つまり、qps が 50 で burst が 100 の場合、サーバーは 50 の qps 制限を適用し始める前に、クエリを 100 個まで受け入れることを意味します。この制限は、特定の種類のリソース(上記の例では namespace とユーザー)に対して定義されます。
具体的なアドミッションコントローラの構成に関する詳細は、Kubernetes のドキュメントを参照してください。
Webhook を使う時のカスタムアドミッションコントローラ作成方法
さまざまな組み込みアドミッションコントローラを適切に構成すれば、クラスターセキュリティのさまざまな面を大幅に強化できます。
しかし、前述のとおり、アドミッションコントローラの最も強力な機能は、Webhook を使用して外部のセキュリティツールと統合できることです。
たとえば、ImagePolicyWebhook コントローラを使用すれば、リモートサーバーに接続できます。そのためには、最初に kube-apiserver.yaml で ImagePolicyWebhook が有効になっていることを確認する必要があります。
次に、リモートサーバーへの接続に使用する ImagePolicyWebhook の構成の詳細を記載したファイル(admission-config.yaml)を作成します。次のコマンドで API サーバーにこのファイルを指定します。
kube-apiserver --admission-control-config-file=admission-config.yaml
admission-config.yaml ファイル自体には、次のような記述が含まれています。
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ImagePolicyWebhook
configuration:
imagePolicy:
kubeConfigFile: <path-to-kubeconfig-file>
allowTTL: 50
denyTTL: 50
retryBackoff: 500
defaultAllow: true
Code language: HTML, XML (xml)
また、リモートサーバーを構成する、次のような別の kubeconfig ファイルも必要です。
# clusters refers to the remote service.
clusters:
- name: name-of-remote-imagepolicy-service
cluster:
certificate-authority: /path/to/ca.pem # CA for verifying the remote service.
server: https://images.example.com/policy # URL of remote service to query. Must use 'https'.
# users refers to the API server's webhook configuration.
users:
- name: name-of-api-server
user:
client-certificate: /path/to/cert.pem # cert for the webhook admission controller to use
client-key: /path/to/key.pem # key matching the cert
Code language: PHP (php)
正しく構成すれば、Kubernetes API サーバーが許可の判断を行う際に、(上記で定義したリモートサーバーのような)リモートサービスに接続できるようになります。繰り返しますが、このアプローチの利点は、使用したいポリシーエンジンを Kubernetes API サーバー自体に組み込むことなく、アドミッションルールを外部で定義できることです(率直に言えば、API サーバーの構成はそれ自体で十分複雑であるためです)。
つまり、少なくとも現在の Kubernetes の基準では、Kubernetes アドミッションコントローラは、クラスターに他のセキュリティ層を追加するための強力かつ比較的使いやすいリソースと言えます。どのアドミッションコントローラを有効にするかはワークロードによって異なり、Webhook を使用してカスタムコントローラを定義する必要があるかどうかも、アドミッションコントローラによって異なります。
しかし、少なくとも、どの種類の本番ワークロードにも使用する Kubernetes クラスターについては、最低限デフォルトのアドミッションコントローラを有効にしておく必要があるでしょう。
まとめ
Kubernetesにおけるアドミッションコントローラは、セキュリティの保護に役立てることができます。
あくまでオプション機能であり、基本的な RBAC やネットワークポリシーで十分にセキュリティを確保できるシンプルな構成であれば必要ないかもしれません。しかし、複雑で大規模なクラスターを保護するのであれば、非常に有効なリソースなります。