SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

Azure Kubernetes Service の機密コンテナーの構成について

leave a comment

Azure Kubernetes Service (AKS) では、機密コンテナー (Confidential Container: CC) として、コンテナーを起動することができる機能が、2025/01 時点でプレビューとして提供されています。

AKS では 機密ノードプール という機能も提供されており、こちらについては既に GA しています。

機密ノードプール / 機密コンテナーともに AMD EPYC プロセッサが利用されており、AMD SEV-SNP (SEV: Secure Encrypted Virtualization / SNP: Secure Nested Paging) を使用し、高信頼実行環境 (TEE: Trusted Execution Environment) で VM を実行するものとなるかと思います。

機密ノードプールの場合は、DCasv5 シリーズ、機密コンテナーの場合は、DCas_cc_v5 シリーズが使用され、使用する VM サイズが異なっています。

DCasv5 シリーズはハードウェアベースの VM のメモリ暗号化が行われますが、DCas_cc_v5 シリーズでは「AMD SEV-SNP で保護された子 VM を作成できます。」という特徴があります。

AKS で使用する場合は、VM 上で動作するコンテナーを SEV-SNP で保護された子 VM として起動できる構成となるということになり、機密ノードプールを使用した場合とは異なる構成でコンテナーを起動することになるのかと思います。

機密ノードプール / 機密コンテナーは Azure Confidential Computing の VM (Confidential VM: CVM) が基盤となっていると思いますので、以下の記事も参考にさせていただいています。

 

Confidential Computing で使用可能な VM について

Confidential Computing で使用できる VM サイズは "DC" ファミリ汎用 VM サイズ シリーズ になりますが、投稿時点では大きく分けると次の 3 種類の環境となります。

  1. AMD EPYC (Milan) : AMD SEV-SNP : DCasv5 / DCadsv5 / DCas_cc_v5 / DCads_cc_v5 : 一般提供開始
  2. Intel Xeon (Sapphire Rapids) : Intel TDX : DCesv5 / DCedsv5 : プレビュー
  3. Intel Xeon (Ice Lake) : Intel SGX : DCsv3 / DCdsv3 / DCsv2 : 一般提供開始

機密コンテナーは AMD EPYC の AMD SEV-SNP を使用する構成となっていますので、「1.」の Confidential Computing が対象となり、子 VM の暗号化がポイントとなるため、DCas_cc_v5 / DCads_cc_v5 を使用することになります。

 

機密コンテナーの構成

機密コンテナーの構成については Azure Kubernetes Service (AKS) 上の機密コンテナー (プレビュー) に記載されている内容が基本的な情報となり、コンテナーを次のような構成で起動できるようになります。

上述のドキュメントと 機密コンテナーと既定のポリシーを含んだ AKS クラスターをデプロイする に記載されていますが、機密コンテナーを実行するノードの OS については、Azure Linux を指定する必要があるため、CBL-Mariner が使用されます。

 

機密コンテナーをサポートするノードの展開方法

機密コンテナーをサポートする AKS のノードプールについては、機密コンテナーと既定のポリシーを含んだ AKS クラスターをデプロイする に記載されているとおり「–workload-runtime KataCcIsolation」というオプションを指定することで展開することができ、このオプションを指定して展開したノードについては上記の構成でコンテナーを起動することができます。

 

通常のノード / 機密ノードプールで実行されるコンテナーとの違い

通常の AKS のノードプール / 機密ノードプールでコンテナーを起動した場合は runC + containerd の構成が使用されているかと思います。機密コンテナーの場合は、runC ではなく、Kata Containers + containerd の構成でコンテナーが起動されます。

Kata Containers のドキュメントには次の構成の図が公開されています。

image

通常のノード / 機密ノードプールで起動したコンテナーは runC+containerd となるため右の構成で実行が行われ、ホスト上から直接に指揮できるプロセスとして実行が行われます。

機密コンテナーで起動したコンテナーは左の構成で起動させることができ、通常のコンテナーとは異なりホスト OS 上にプロセスを起動するのではなく、AKS ノード内で Kata Containers により VM を起動し、その中で VM 内でコンテナーを起動するという構成をとることができます。

これにより通常より、よりプロセスを堅牢に分離した形でコンテナーを起動することができるようになります。

Kata Containers がサポートする Hypervisor については、Virtualization in Kata Containers / Hypervisors に記載されていますが、AKS の機密コンテナーについては、Cloud Hypervisor が採用されているようです。

k8s で Kata Containers を動作させる方法については、Run Kata Containers with Kubernetes で記載されていますが、機密コンテナーをサポートするノードプールではこのような設定がデフォルトで行われている状態のノードが起動しています。

機密コンテナーは AMD-SEV-SNP による保護が有効になっている VM が起動するため、k8s で Kata Containers を動作させる設定だけでなく、Cloud Hypervisor 向けに Kata Containers with AMD SEV-SNP VMs (Build Kata Containers Kernel) / Confidential Computing with Kubernetes: SEV Guest Protection for Kata Containers の設定も行われている環境となっているのではないでしょうか。

 

AKS ポッドサンドボックスとの違い

類似の機能としては AKS の ポッドサンドボックス という機能があり、この機能で展開したコンテナーも Kata Containers が使用された環境となります。

しかし、ポッドサンドボックスでは、Kata Containers と AMD SEV-SNP の統合は行われておらず、コンテナー実行時に起動した VM については TEE の構成となっておらず、SNP によるメモリ保護が行われていない状態となっているのかと。

機密コンテナーでは起動した VM は、ポッドサンドボックスと同様に Kata Containers を使用した VM となりますが、Kata Containers with AMD SEV-SNP VMs  の設定が行われていることで、AMD SEV-SNP による TEE として起動し、メモリの暗号化等が行われセキュリティ強度が高いという違いがあるのではないでしょうか。

AKS 機密コンテナーはポッドサンドボックスと異なり、 Kata Containers と AMD SEV-SNP を組み合わせたコンテナーを起動するための設定が一通り行われている AKS ノードを起動できるのが特徴の一つとなるという理解でいます。

k8s で Kata Containers を使用する場合にどのような設定が必要となるかを確認するための環境としても使うことができるかと。(/etc/containerd/config.toml, /opt/confidential-containers/share/defaults/kata-containers/configuration-clh-snp.toml 辺りを参考にするとよいのかと)

AMD SEV-SNPによるネストしたVMの保護 という論文がありますが、L1 VM の中で動作する L2 VM についても暗号化をした状態で実行することができるのが機密コンテナーの特徴の一つとなるのではないでしょうか。

 

機密コンテナーとして Pod を起動するには

機密コンテナーのノードをノードプールとして追加していても、単純に Pod を起動しただけでは通常の runC + containerd の環境として起動が行われています。

Kata Containers が使用された Pod として起動するためには、マニフェストに「runtimeClassName: kata-cc-isolation」を記述する必要があります。(ポッドサンドボックスの場合は「runtimeClassName: kata-mshv-vm-isolation」を指定します)

機密コンテナーを展開している AKS の環境では「RuntimeClass」として「kata-cc-isolation」という設定が追加されています。

apiVersion: v1
items:
- apiVersion: node.k8s.io/v1
  handler: kata-cc
  kind: RuntimeClass
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"node.k8s.io/v1","handler":"kata-cc","kind":"RuntimeClass","metadata":{"annotations":{},"labels":{"addonmanager.kubernetes.io/mode":"Reconcile"},"name":"kata-cc-isolation"},"overhead":{"podFixed":{"memory":"2Gi"}},"scheduling":{"nodeSelector":{"kubernetes.azure.com/kata-cc-isolation":"true"}}}
    creationTimestamp: "2025-01-08T12:00:37Z"
    labels:
      addonmanager.kubernetes.io/mode: Reconcile
    name: kata-cc-isolation
    resourceVersion: "600"
    uid: e8660d66-ff7a-43fe-8af5-dade71046430
  overhead:
    podFixed:
      memory: 2Gi
  scheduling:
    nodeSelector:
      kubernetes.azure.com/kata-cc-isolation: "true"
kind: List
metadata:
  resourceVersion: ""

 

この RuntimeClass を指定して起動した Pod については、Kata Container が使用された環境で起動が行われます。

 

マニフェストファイルのサンプル

使用するマニフェストのサンプルについては、次のドキュメントから確認することができます。

簡単な構成で試したい場合には、Azure Kubernetes Service Confidential Hello World を試すとよいかと。

README の順序でコマンドを実行すれば問題はないのですが、機密コンテナーとして起動する場合には、展開するマニフェストに対して「az confcom katapolicygen」を実行し、YAML にセキュリティポリシーを埋め込んだ状態で apply しないと、次の警告が発生したままとなり、Pod 作成のステータスが「ContainerCreating」から進まないようでした。(katapolicygen は Windows の AZ CLI では実行できないため WSL で実行しました)

Warning  FailedCreatePodSandBox  10s (x4 over 75s)  kubelet            
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create containerd task: 
failed to create shim task: "UpdateInterfaceRequest: internal error query did not produce any values": unknown

 

セキュリティポリシー

上述のエラーは Azure Kubernetes Service での機密コンテナーのセキュリティ ポリシー に関連しているのかと思います。

そのため、エージェントは、バグや悪意の可能性がある API 呼び出しからそれ自体を保護する必要があります。

AKS 機密コンテナーでは、Kata エージェント API の自己保護は、機密ポッドの所有者が指定するセキュリティ ポリシー (Kata "エージェント ポリシー" とも呼ばれます) を使って実装されます。

セキュリティポリシーを設定していないマニフェストによる Pod の展開はできないようです。

上述のサンプルに記載されているように「az confcom katapolicygen -y cc-helloworld.yaml」というように、ポリシーファイルを明示的に指定せず YAML のみを指定した場合「既定のセキュリティポリシー」によりセキュリティポリシーが追加されたマニフェストファイルに更新が行われます。

katapolicygen を実行することで指定した YAML ファイルに「io.katacontainers.config.agent.policy」というポリシーが含まれたアノテーションが追加されます。

このアノテーションがある状態であれば、上述のエラーは発生せずに、Pod を起動することができます。

image

ノードプールに SSH でログインしてプロセスの上表を取得してみると、Cloud Hypervisor が起動していることが確認でき、Kata Containers により、実行環境が分離された Pod が起動されている状態となります。

image

 

セキュリティポリシーのカスタマイズの参考情報

既定のセキュリティポリシーでは次のような設定が含まれています。

default ExecProcessRequest := false

    "ExecProcessRequest": {
      "commands": [],
      "regex": []
    }

 

既定のセキュリティポリシーをその生使った場合は、ExecProcessRequest は許可されていない状態となりますので、「kubectl exec」により、コンテナーにアタッチしようとしてもポリシーで拒否が行われます。

これにより、「with err rpc error: code = PermissionDenied desc = "ExecProcessRequest is blocked by policy: agent_policy:1273」というエラーが発生し、exec によりコンテナーの内部に入ることが制限された状態となります。

セキュリティーポリシーは セキュリティ ポリシーの概要 に記載されていますが Open Policy Agent で使用されている rego ファイルを作成することで対応できるようです。

ポリシーのドキュメントには、業界標準の Rego ポリシー言語を使って、各ポッドに対応するルールとデータが含まれています。 ユーティリティ VM (UVM) 内でのポリシーの適用は、Cloud Native Computing Foundation (CNCF) の段階的なプロジェクトである Open Policy Agent (OPA) を使用して実装されます。

 

Kata Containers 向けのポリシーをカスタマイズする場合は、以下のドキュメントを参考にするとよさそうでした。

既定のセキュリティポリシーではなく、kubectl exec が許可されるカスタムルールファイル (.rego) を作成して「–rules-file-name」で指定することで、機密コンテナーで起動しているコンテナーに対してもアタッチできるようになり、コンテナー内の状態を直接確認することができます。

全てが許可されているルールについては allow-all.rego が参考になり、このルールを使用する場合は次のようなコマンドでポリシーを埋め込めるかと。

apiVersion: v1
kind: Pod
metadata:
  rame: cc-ubuntu-pod
  labels:
    app: ubuntu
spec:
  runtimeClassName: kata-cc-isolation
  containers:
  - name: ubuntu-container
    image: ubuntu:latest
    command: ["tail", "-f", "/dev/null"]
    securityContext:
      privileged: true

このような YAML を作成し、「allow-all.rego」を適用することで「kubectl exec -it cc-ubuntu-pod — /bin/bash」により接続が可能となり、後述の dmesg による確認を行うことができます。

az confcom katapolicygen -y cc-ubuntu.yaml --rules-file-name allow-all.rego

事前にルールファイルを作成しておける場合は、「az confcom katapolicygen」を使用しなくても、「base64 -w 0 <rego ファイル名>」で rego ファイルを BASE64 エンコードして、「io.katacontainers.config.agent.policy」に明示的に追加しておくことでも対応はできるようでした。

 

dmesg の比較

Check for active SNP: で実行されているコンテナーが SNP が有効になっているかを dmesg で確認する方法が紹介されています。

「runtimeClassName: kata-cc-isolation」を指定していないコンテナーについては、機密コンテナーが実行可能なノードで起動しても次の情報となっていました。

image

runtimeClassName を指定したコンテナーでは次のような情報となっており、メモリ暗号化が実行されている情報となっていました。またこの状態で起動していると「/dev/sev-guest」が認識され、snpguest ツールキット の実行も可能となっているようです。

image

 

この辺のセキュリティは SQL Server / SQL Database の Always Encrypted Secure Enclaves を調査する際に少し調べていたことがあるのですが、理解度が浅いことが改めてわかりました…。

Share

Written by Masayuki.Ozawa

1月 8th, 2025 at 11:02 pm

Posted in AKS

Tagged with

Leave a Reply