このページでは、Kubernetesのワークロードで使用できる、Linuxカーネルに組み込まれたいくつかのセキュリティ機能について説明します。 これらの機能をPodとコンテナに適用する方法については、Podとコンテナにセキュリティコンテキストを設定するを参照してください。 LinuxとKubernetesワークロードの基本については、すでに理解している必要があります。
Kubernetesでワークロードをデプロイする場合は、Podの仕様を使用して、そのワークロードがノード上でrootユーザーとして実行されないように制限します。
PodのsecurityContextを使用すると、Pod内のプロセスに対して特定のLinuxユーザーとグループを定義し、コンテナがrootユーザーとして実行されないように明示的に制限できます。
Podマニフェストにこれらの値を設定すると、コンテナイメージ内の同様の値よりも優先されます。
これは、自分が所有していないイメージを実行する場合に特に便利です。
このページのカーネルセキュリティ機能を設定すると、クラスター内のプロセスが実行できる操作を細かく制御できますが、これらの設定を大規模に管理するのは困難な場合があります。 コンテナを非rootとして実行するか、root権限が必要な場合はユーザー名前空間で実行すると、設定したカーネルセキュリティ機能を強制する必要が生じる可能性を減らせます。
Kubernetesでは、隔離性を強化し、コンテナ化されたワークロードを強化するために、Linuxカーネルの機能を設定して使用できます。 一般的な機能には、次のものがあります。
これらの機能のいずれかの設定を構成するには、ノードに選択したオペレーティングシステムにおいて、その機能がカーネルで有効になっている必要があります。 たとえば、Ubuntu 7.10以降ではAppArmorがデフォルトで有効です。 使用しているOSで特定の機能が有効になっているかどうかを確認するには、OSのドキュメントを参照してください。
Podの仕様のsecurityContextフィールドを使用して、それらのプロセスに適用する制約を定義します。
securityContextフィールドは、特定のLinuxケーパビリティや、UIDとGIDを使用したファイルアクセス権限など、他のセキュリティ設定もサポートしています。
詳細については、Podとコンテナにセキュリティコンテキストを設定するを参照してください。
ワークロードのなかには、ノードのホストマシン上でrootユーザーとして特定の操作を実行するための権限が必要なものがあります。 Linuxでは、利用可能な権限をケーパビリティに分割して分類します。 これにより、プロセスはすべての権限を付与されることなく、特定の操作を実行するために必要な権限を得ることができます。 各ケーパビリティには、プロセスが実行できるシステムコール(syscall)のセットがあります。 seccompを使用すると、これらの個々のsyscallを制限できます。 これはプロセスの権限をサンドボックス化し、ユーザー空間からカーネルに対して実行できる呼び出しを制限するために使用できます。
Kubernetesでは、各ノードでコンテナランタイムを使用してコンテナを実行します。 ランタイムの例には、CRI-O、Docker、containerdがあります。 各ランタイムは、デフォルトではLinuxケーパビリティの一部のみを許可します。 seccompプロファイルを使用すると、許可されるsyscallを個別にさらに制限できます。 コンテナランタイムには通常、デフォルトのseccompプロファイルが含まれています。 Kubernetesでは、ノードに読み込まれたseccompプロファイルをPodとコンテナに自動的に適用できます。
allowPrivilegeEscalation設定もあります。
これをfalseに設定すると、プロセスが新しいケーパビリティを取得することを防ぎ、非特権ユーザーが適用済みのseccompプロファイルをより寛容なプロファイルに変更することを制限します。Kubernetesでseccompを実装する方法については、seccompでコンテナのシステムコールを制限するまたはSeccompのノードリファレンスを参照してください。
seccompの詳細については、LinuxカーネルドキュメントのSeccomp BPFを参照してください。
seccompは低レベルのセキュリティ設定であり、Linux syscallを細かく制御する必要がある場合にのみ自分で設定すべきです。 seccompの使用には、特に大規模な環境では次のリスクがあります。
推奨事項: コンテナランタイムに同梱されているデフォルトのseccompプロファイルを使用してください。 より分離された環境が必要な場合は、gVisorなどのサンドボックスの使用を検討してください。 サンドボックスは、カスタムseccompプロファイルに伴う前述のリスクを解決しますが、ノード上でより多くのコンピュートリソースを必要とし、GPUやその他の特殊なハードウェアとの互換性の問題が発生する可能性があります。
AppArmorやSELinuxなどのLinuxのポリシーベースの強制アクセス制御(MAC)メカニズムを使用して、Kubernetesのワークロードを強化できます。
AppArmorはLinuxカーネルのセキュリティモジュールであり、標準のLinuxユーザーとグループに基づく権限を補完し、プログラムを制限されたリソースのセットに閉じ込めます。 AppArmorは任意のアプリケーションに対して設定でき、潜在的な攻撃対象領域を減らし、より強力な多層防御を提供します。 AppArmorは、Linuxケーパビリティ、ネットワークアクセス、ファイル権限など、特定のプログラムまたはコンテナが必要とするアクセスを許可するように調整されたプロファイルを通じて設定されます。 各プロファイルは、許可されていないリソースへのアクセスをブロックするenforcingモード、または違反の報告のみを行うcomplainモードのいずれかで実行できます。
AppArmorは、コンテナに許可される操作を制限することで、より安全なデプロイを実行するのに役立ちます。 また、システムログを通じてより優れた監査を提供できます。 使用するコンテナランタイムにはデフォルトのAppArmorプロファイルが同梱されている場合もあり、カスタムプロファイルを使用することもできます。
KubernetesでAppArmorを使用する方法については、AppArmdiorでコンテナのリソースアクセスを制限するを参照してください。
SELinuxはLinuxカーネルのセキュリティモジュールであり、プロセスなどの特定のサブジェクトがシステム上のファイルに対して持つアクセスを制限できます。 特定のSELinuxラベルを持つサブジェクトに適用されるセキュリティポリシーを定義します。 SELinuxラベルを持つプロセスがファイルにアクセスしようとすると、SELinuxサーバーはそのプロセスのセキュリティポリシーがアクセスを許可しているかどうかを確認し、認可の判断を行います。
Kubernetesでは、マニフェストのsecurityContextフィールドにSELinuxラベルを設定できます。
指定されたラベルは、それらのプロセスに割り当てられます。
それらのラベルに影響するセキュリティポリシーを設定している場合、ホストOSのカーネルがこれらのポリシーを適用します。
KubernetesでSELinuxを使用する方法については、コンテナにSELinuxラベルを割り当てるを参照してください。
Linuxノード上のオペレーティングシステムには、通常AppArmorまたはSELinuxのどちらか一方が含まれています。 どちらのメカニズムも同様の保護を提供しますが、次のような違いがあります。
次の表では、各セキュリティ制御のユースケースと範囲について説明します。 これらの制御はすべて組み合わせて使用し、より強化されたシステムを構築できます。
| セキュリティ機能 | 説明 | 使用方法 | 例 |
|---|---|---|---|
| seccomp | ユーザー空間内の個々のカーネル呼び出しを制限します。 制限されたsyscallを使用する脆弱性によってシステムが侵害される可能性を減らします。 | Podまたはコンテナ仕様で読み込み済みのseccompプロファイルを指定し、その制約をPod内のプロセスに適用します。 | CVE-2022-0185で使用されたunshare syscallを拒否します。 |
| AppArmor | 特定のリソースへのプログラムのアクセスを制限します。 プログラムの攻撃対象領域を減らします。 監査ログを改善します。 | コンテナ仕様で読み込み済みのAppArmorプロファイルを指定します。 | 読み取り専用のプログラムがシステム内の任意のファイルパスに書き込むことを制限します。 |
| SELinux | ラベルとセキュリティポリシーを使用して、ファイル、アプリケーション、ポート、プロセスなどのリソースへのアクセスを制限します。 | 特定のラベルに対するアクセス制限を指定します。 プロセスにそれらのラベルを付与し、そのラベルに関連するアクセス制限を適用します。 | コンテナが自身のファイルシステム外のファイルにアクセスすることを制限します。 |
seccomp、AppArmor、SELinuxには通常、基本的な保護を提供するデフォルト設定があります。 ワークロードの要件を満たすカスタムプロファイルやポリシーを作成することもできます。 これらのカスタム設定を大規模に管理および配布することは、特に3つの機能すべてを一緒に使用する場合には困難なことがあります。 これらの設定を大規模に管理しやすくするには、Kubernetes Security Profiles Operatorのようなツールを使用してください。
Kubernetesでは、一部の信頼されたコンテナを特権モードで実行するように指定できます。 Pod内の任意のコンテナは、通常はアクセスできないオペレーティングシステムの管理機能を使用するために、特権モードで実行できます。 これはWindowsとLinuxの両方で利用できます。
特権コンテナは、ワークロードで使用する可能性のあるLinuxカーネルの制約の一部を、次のように明示的に上書きします。
Unconfined seccompプロファイルとして実行され、マニフェストで指定したseccompプロファイルを上書きします。unconfined_tドメインとして実行されます。コンテナのsecurityContextフィールドにprivileged: trueフィールドを設定すると、Pod内の任意のコンテナで特権モードを有効にできます。
特権コンテナは、適用されたseccompプロファイル、AppArmorプロファイル、SELinux制約など、他の多くの強化設定を上書きまたは取り消します。
特権コンテナには、不要なものを含むすべてのLinuxケーパビリティが付与されます。
たとえば、特権コンテナ内のrootユーザーは、ノード上でCAP_SYS_ADMINやCAP_NET_ADMINケーパビリティを使用できる場合があり、ランタイムのseccomp設定やその他の制限をバイパスできます。
ほとんどの場合、特権コンテナの使用は避けるべきです。
代わりに、securityContextフィールドのcapabilitiesフィールドを使用して、コンテナに必要な特定のケーパビリティを付与してください。
securityContextでは付与できないケーパビリティがある場合にのみ、特権モードを使用してください。
これは、ネットワークスタックの操作やハードウェアデバイスへのアクセスなど、オペレーティングシステムの管理機能を使用したいコンテナに役立ちます。
Kubernetesバージョン1.26以降では、Podの仕様のセキュリティコンテキストでwindowsOptions.hostProcessフラグを設定することで、Windowsコンテナも同様の特権モードで実行できます。
詳細と手順については、Windows HostProcess Podを作成するを参照してください。
runAsNonRoot: trueを指定して、Linuxワークロードを非rootとして実行してください。さらに、PodマニフェストでhostUsers: falseを設定することで、ユーザー名前空間内でワークロードを実行できます。
これにより、コンテナをユーザー名前空間内ではrootユーザーとして実行し、ノード上のホスト名前空間では非rootユーザーとして実行できます。
これはまだ開発の初期段階にあり、必要なレベルのサポートが得られない可能性があります。
手順については、Podでユーザー名前空間を使用するを参照してください。