Amazon Web Services ブログ

Amazon VPC CNI による Kubernetes NetworkPolicy のサポート

イントロダクション

本日、Amazon VPC Container Networking Interface (CNI) プラグインでの Kubernetes NetworkPolicy のネイティブサポートを発表できることを嬉しく思います。Kubernetes クラスター内の Pod ネットワーキングとネットワークポリシーの両方を実装するために、Amazon VPC CNI を利用できます。NetworkPolicy のネイティブなサポートは、私達のコンテナロードマップにおいて、最も要望の多かった機能の 1 つでした。

デフォルトでは、Kubernetes は全ての Pod が制限なく相互に通信することを許可しています。Kubernetes の NetworkPolicy は、Pod 間のトラフィックフローのルールを定義し、強制できます。仮想ファイヤウォールとして機能し、クラスターをセグメント化し、保護します。これは、Pod の Label、Namespace、IP アドレス、IP ブロック (CIDR レンジ)、ポート番号などのさまざまな基準に基づいた受信および送信ネットワークトラフィックのルールを指定することでおこなわれます。今までは、お客様はサードパーティのネットワークポリシープラグインを使用して、NetworkPolicy を実装し、それによってしばしば運用と管理のオーバーヘッドが生じていました。Amazon VPC CNI の統合された機能によって、クラスターの構成とデプロイがシンプルになりました。トラフィックフローを制限することで、スケーリングの課題を心配することなく、より強力なセキュリティ体制を実現できます。

Amazon VPC CNI の NetworkPolicy のネイティブなサポートにより、AWS 上で Kubernetes を実行する場合に、機密性の高いワークロードを隔離し、認可されていないアクセスから保護するポリシーを作成できます。このきめ細やかなコントロールレベルにより、許可された Pod のみが相互に通信できる最小権限の原則を実装できます。NetworkPolicy は Amazon Elastic Computer Cloud (Amazon EC2) セキュリティグループ (SG) やネットワークアクセスコントロールリスト (NACL) などの、Amazon VPC によって提供されるセキュリティ機能を拡張する、多層防御のメカニズムを提供します。

Amazon Elastic Kubernetes Service (Amazon EKS) は、アップストリームの Kubernetes NetworkPolicy を完全にサポートしているため、互換性と Kubernetes 標準への準拠が保証されます。これは、Amazon EKS クラスターにおける NetworkPolicy API の全ての機能を使用できることを意味しています。アップストリームの API によってサポートされるさまざまな識別子を使って柔軟にポリシーを定義できます。これにより、Pod 間の通信を定義することが可能になり、クラスター内のセキュリティと分離が強化されます。

動作の仕組み

Kubernetes の NetworkPolicy が最初に導入された時、広く採用されていたデフォルトの実装は iptables でした。iptables はネットワークポリシーの強制には効果的であることが証明されましたが、特に Kubernetes クラスターのサイズが拡大する時に、いくつかの制約がありました。数多くの iptables ルールを管理することが課題になる可能性があります。また、各パケットでルールを順番に評価することで、ルール数の増加によって、パフォーマンスの問題が生じる可能性もあります。

これらの課題に対処し、パフォーマンスを改善するために、Amazon EKS は extended Berkeley Packet Filter (eBPF) を用いて NetworkPolicy を実装するという高度なアプローチを採用しました。このテクノロジーは NetworkPolicy の代替実装として、近年大きな支持を集めています。eBPF は iptables と比較してより効率的なパケットフィルタリングを提供し、全体的なパフォーマンスが向上する可能性を秘めています。これは、カーネル自体の中でカスタムコードを直接実行できるようにすることによって実現されます。

NetworkPolicy の実装を円滑に進めるために、Amazon EKS ではシームレスに連携する 3 つの主要なコンポーネントを導入しています。

  • Network Policy コントローラー: Amazon EKS は、最新バージョンの Amazon VPC CNI と共に、Network Policy コントローラーのローンチを発表しました。現在、コントローラーは一般公開されています。新しい Amazon EKS クラスターを作成すると、機能が有効になった際に Network Policy コントローラーが Kubernetes のコントロールプレーンに自動的にインストールされます。クラスター内の NetworkPolicy の作成をアクティブに監視し、ポリシーエンドポイントを調整します。その後コントローラーは、ポリシーエンドポイントを通じて Pod の情報を公開することによって、ノード上で eBPF プログラムを作成または更新するよう、Node Agent に指示します。Network Policy コントローラーは、Pod のプロビジョニングと並行して、Pod のポリシーを設定します。それまで新しい Pod には、デフォルトの許可ポリシーが設定されます。既にあるポリシーに対して調整されるまで、新しい Pod への送受信トラフィックは全て許可されます。セルフマネージド型 Kubernetes クラスターの NetworkPolicy を効率的に管理するには、Network Policy コントローラーをデプロイする必要があります。この点については、この記事のウォークスルーのセクションで、セルフマネージド型クラスターに関する詳しい情報と重要な考慮事項を確認することができます。
  • Node Agent: Amazon VPC CNI の最新バージョンでは、クラスター内の全てのノードに CNI バイナリと ipamd プラグインと共に、Node Agent もインストールされます。Node Agent は VPC CNI にバンドルされ、aws-node DaemonSet 配下でコンテナとして実行されます。NetworkPolicy がクラスターに適用されると、Node Agent はコントローラーからポリシーエンドポイントを受け取ります。Node Agent は eBPF プログラムの管理において重要な役割を果たし、シームレスな NetworkPolicy への道を開きます。
  • eBPF SDK (Software Development Kit): Amazon VPC CNI はサポートと運用を助けるために、ノード上の eBPF プログラムと対話するための直感的なインタフェースを提供する SDK を含んでいます。この SDK により、eBPF 実行時における、ランタイムのインストロペクション、トレース、分析が可能になり、接続性の問題の特定と解決に役立ちます。

本日より、v1.25 以降の新しい Amazon EKS (IPv4 および IPv6) で NetworkPolicy がサポートされます。Amazon EKS は、既存の全てのクラスターを、対応する Kubernetes マイナーバージョン用の最新の Amazon EKS プラットフォームバージョンに自動的にアップグレードします。まもなく、この機能をサポートするプラットフォームバージョンをリリース予定です。そのプラットフォームバージョンへの自動アップグレードがおこなわれた後に、NetworkPolicy が適用可能になります。

クラスターで NetworkPolicy を有効化するには、クラスターが Amazon VPC CNI 1.14.0 以降のバージョンを実行していることを確認します。新しいクラスターを作成する際には、Amazon VPC CNI 1.14.0 以降のバージョンを指定することができます。Amazon VPC CNI 1.14.0 で作成されていないクラスターについては、Amazon VPC CNI を更新してください。既存のクラスターのプラットフォームバージョンの更新が完了したら、VPC CNI をサポートされているバージョンに更新してください。

ローンチ時点では、NetworkPolicy は Kernel バージョン 5.10 以降を使った Amazon EKS-optimized Amazon Linux AMIAmazon EKS-optimized Bottlerocket AMIAmazon EKS-optimized Ubuntu Linux AMI でサポートされています。Kernel バージョン 5.10 以降を使って構築された Amazon EKS-optimized AMI は、eBPF ファイルシステム /sys/fs/bpf を自動的にマウントします。これは、ノードに NetworkPolicy を適用するために必要です。既存のクラスターにおいては、Amazon EKS プラットフォームバージョンが更新された時に、最新の Amazon EKS-optimized AMI に更新することを推奨します。カーネルバージョン 5.10 またはそれより下のバージョンを使用するノードの場合、eBPF ファイルシステムをマウントする手順について、Amazon EKS ユーザーガイドを参照してください。eBPF システムサポートを使用して独自のカスタム AMI を作成する方法については「Amazon EKS-optimized Amazon Linux AMI ビルドスクリプト」を確認してください。

始め方

NetworkPolicy の機能は Kubernetes マイナーバージョン 1.25 以降を実行しているクラスターでサポートされていますが、ローンチ時点ではデフォルトで無効になっています。クラスターを作成する際に、Amazon VPC CNI の設定パラメータを使用してクラスターの NetworkPolicy を有効化できます。

Amazon VPC CNI が IP アドレスを管理するには、AWS Identity and Access Management (AWS IAM) による許可が必要になります。Amazon EKS では、AmazonEKS_CNI_Policy 管理ポリシーで定義されたアクセス権限を使用して、別の AWS IAM ロールを作成し、IRSA (AWS IAM roles for service acount) を使用してそのロールを VPC CNI に関連付けることを推奨しています。IRSA は OpenID Connect (OIDC) エンドポイントを必要とするため、クラスター作成の一部として IAM OIDC プロバイダーを作成します。詳細については「サービスアカウントの IAM ロールを使用する Amazon VPC CNI plugin for Kubernetes の設定」を参照してください。

以下の設定をコピーして cluster.yaml という名前のファイルに保存します。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: network-policy-demo
  version: "1.27"
  region: us-west-2

iam:
  withOIDC: true

vpc:
  clusterEndpoints:
    publicAccess: true
    privateAccess: true

addons:
  - name: vpc-cni
    version: 1.14.0
    attachPolicyARNs: #optional
    - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy 
    configurationValues: |-
      enableNetworkPolicy: "true"
  - name: coredns
  - name: kube-proxy

managedNodeGroups:
  - name: x86-al2-on-demand
    amiFamily: AmazonLinux2
    instanceTypes: [ "m6i.xlarge", "m6a.xlarge" ]
    minSize: 0
    desiredCapacity: 2
    maxSize: 6
    privateNetworking: true
    disableIMDSv1: true
    volumeSize: 100
    volumeType: gp3
    volumeEncrypted: true
    tags:
      team: "eks"
eksctl create cluster -f cluster.yaml
Bash

クラスターの作成が完了するのを待って、Amazon VPC CNI が Node Agent を実行するようになったかどうかを確認します。

kubectl get ds -n kube-system aws-node -o jsonpath='{.spec.template.spec.containers[*].name}{"\n"}'

出力:

aws-node aws-eks-nodeagent
Apache Configuration

eBPF SDK を使用する

Amazon VPC CNI の最新バージョンには、ノード上の eBPF プログラムとやり取りするためのインタフェースを提供する SDK が付属しています。SDK は aws-node がノードにデプロイされる時にインストールされます。SDK バイナリはノードの /opt/cni/bin ディレクトリ配下にインストールされています。接続性の問題を特定したい場合は、SDK の使用を検討してください。ノード上の Pod のために eBPF プログラムが作成されていることを確認します。これを確認するには AWS System Manager (AWS SSM) を使用して、Amazon EC2 コンソールからノードに接続します。

ローンチ時には、SDK は eBPF プログラムやマップの検査など、基本的な機能をサポートしています。特定の利用リクエストがある場合は、こちらの GitHub Issue から教えてください。SDK の使用方法については、ユーザーガイドを御覧ください。

sudo /opt/cni/bin/aws-eks-na-cli ebpf progs
Apache Configuration

サンプルアプリケーションのデプロイ

次に、demo-app というサンプル NGINX アプリケーションと、default Namespace にシンプルなクライアントアプリケーションをデプロイします。さらに、another-ns という default Namespace ではない Namespace に別のクライアントアプリケーションを作成します。

git clone https://github.com/aws-samples/eks-network-policy-examples.git
cd eks-network-policy-examples
kubectl apply -f advanced/manifests/
Apache Configuration

全ての Pod が Running 状態になるまで待ちます。

kubectl get pods --all-namespaces --watch
Apache Configuration

NetworkPolicy を実装する

デフォルトでは、Kubernetes は全ての Pod が他の全ての Pod と自由に通信することを許可しています。Kubernetes の NetworkPolicy が Pod に適用されていない場合は、Pod に出入りする全てのトラフィックが許可されます。

アクセスを確認し、全ての送受信トラフィックを許可する

別のターミナルを使用して、前のステップでデプロイしたクライアントの Pod からの接続を確認できます。

kubectl exec -it client-one -- curl demo-app
Apache Configuration

API 呼び出しが成功したことを示す応答が表示されます。

全てのトラフィックを拒否する

demo-app アプリケーションのために、全 Namespace に渡って全てのトラフィックを拒否するポリシーを適用することで、分離をおこないましょう。

kubectl apply -f advanced/policies/01-deny-all-ingress.yaml
Apache Configuration

NetworkPolicy では全ての Pod を選択したため、demo-app への受信トラフィックはすべて拒否されます。

kubectl exec -it client-one -- curl demo-app
Apache Configuration

前のコマンドはタイムアウトになります。

curl: (28) Connection timed out after 3001 milliseconds<br />command terminated with exit code 28

同じ Namespace からの受信を許可する

次のステップでは、同じ Namespace 内で、client-one から demo-app への受信トラフィックを許可します。

kubectl apply -f advanced/policies/03-allow-ingress-from-samens-client-one.yaml
Apache Configuration

NGINX のウェルカムページの HTML が返されるはずです。

kubectl exec -it client-one -- curl --max-time 3 demo-app
Apache Configuration

another-ns Namespace からの受信を許可する

次に、別の Namesapce からのトラフィックを許可します。

kubectl apply -f advanced/policies/04-allow-ingress-from-xns.yaml

これにより、別の Namespace のクライアントから demo-app にアクセスできるようになり、ウェルカムメッセージが返されるはずです。

kubectl exec -it -n another-ns another-client-one -- curl --max-time 3 demo-app.default

送信トラフィックを拒否する

default Namespace の client-one Pod からの全ての送信の分離を適用します。

kubectl apply -f advanced/policies/06-deny-egress-from-client-one.yaml
Apache Configuration

DNS Lookup を含め、client-one からの全ての送信トラフィックが拒否されていることがわかります。

kubectl exec -it client-one -- nslookup demo-app
Apache Configuration

送信トラフィックを許可する

DNS トラフィックも含め、複数のポートと Namespace からの送信を許可しましょう。

kubectl apply -f advanced/policies/08-allow-egress-to-demo-app.yaml
Apache Configuration

DNS と demo-app への送信トラフィックを許可する必要があります。

kubectl exec -it client-one -- curl --max-time 3 demo-app
Apache Configuration

重要な考慮事項

NetworkPolicy と Security Groups for Pods

IPv4 モードの Amazon VPC CNI は、Security Groups for Pods と呼ばれる強力な機能があります。この機能により、Amazon EC2 セキュリティグループを使用して、ノードにデプロイされた Pod との間のインバウンドおよびアウトバウンドのネットワークトラフィックを管理するルールを定義できます。Security Groups for Pods と NetworkPolicy を組み合わせて活用することで、セキュリティ体制を強化できます。NetworkPolicy が有効になっている場合、Security Groups for Pods は多層防御戦略の追加のレイヤーとして機能します。NetworkPolicy を使うと、クラスター内のネットワークトラフィックの流れをきめ細かく制御できます。一方で、Security Groups for Pods は Amazon のセマンティックコントロールを活用し Amazon RDS データベースなどの Virtual Private Cloud (VPC) 内のリソースとの通信を管理することで保護を強化します。Amazon EKS では、Pod 間のネットワーク通信を制限する NetworkPolicy を採用することを強く推奨しています。これにより、攻撃対象領域が減少し、潜在的な脆弱性を最小限に抑えられます。NetworkPolicy とセキュリティグループの仕様に関する詳細のガイダンスについては、Amazon EKS ベストプラクティスを参照してください。

NetworkPolicy とサードパーティ CNI プラグイン

Amazon VPC CNI は、Kubernetes NetworkPolicy API を使って定義されたネットワークポリシーをサポートするようになりました。Pod ネットワーキング用のサードパーティ CNI プラグインを実行しているクラスターは、NetworkPolicy の機能を有効化するために、Amazon VPC CNI に移行しなければならないと注意しておくことが重要です。

この記事を書いている時点では、Amazon VPC CNI はサードパーティのネットワークポリシープラグインの Amazon VPC CNI へのインプレースでの移行をサポートしていません。移行を円滑に進めるために、Amazon EKS では Amazon VPC CNI の NetworkPolicy サポートを有効化する前に、既存のサードパーティネットワークポリシー API を Kubernetes NetworkPolicy API に変換することを推奨しています。本番環境に変更を適用する前に、移行したポリシーを別のテスト用クラスターでテストすることを推奨します。これによって、Pod 間通信の振る舞いにおける潜在的な問題や不一致を特定して対処できます。

一貫性を保ち、予期せぬ Pod の通信の振る舞いを回避するために、単一のネットワークポリシープラグインのみを実行することを推奨します。Amazon VPC CNI の最新バージョンにアップグレードする前に、既存のサードパーティのネットワークポリシー CNI プラグインを削除することが重要です。さらに、ワーカーノードを入れ替えることで、iptables や eBPF プログラムなど、ノードに残っている変更を排除できます。Amazon VPC CNI の NetworkPolicy サポートに移行するための詳細な手順については、こちらのドキュメントを参照してください。このオープンソースリポジトリで提供されるスクリプトを使用して、サードパーティのネットワークポリシーを Kubernetes NetworkPolicy アーティファクトに変換できます。これらのリソースは Amazon EKS よって公式にサポートされておらず、ベストエフォートになります。リソースは、Amazon VPC CNI NetworkPolicy サポートへの移行を成功させるために、移行プロセスを合理化および簡素化することを目的としています。

セルフマネージド型 Kubernetes クラスター

Amazon VPC CNI の最新バージョンでは、AWS 上のセルフマネージド型 Kubernetes に NetworkPolicy を適用できるようになりました。Amazon VPC CNI の更新に加えて、セルフマネージド型 Kubernetes クラスターに Amazon NetworkPolicy コントローラーをインストールして、NetworkPolicy を有効化します。GitHub リポジトリに記載されている手順にしたがって、NetworkPolicy コントローラーをデプロイします。現在、Amazon VPC CNI と Network Policy コントローラーはサードパーティの NetworkPolicy プラグインとカスタム NetworkPolicy オブジェクトのインプレースでの移行をサポートしていないことに注意することが重要です。そのため、上記の手順に従って Amazon VPC CNI NetworkPolicy に移行するようにしてください。

クリーンアップ

将来のコストを避けるため、この演習用に作成した Amazon EKS クラスターを含む全てのリソースを削除してください。このアクションは、クラスターを削除するだけではなく、ノードグループも削除します。

eksctl delete cluster -f cluster.yaml
Apache Configuration

まとめ

この記事では、Kubernetes NetworkPolicy が Amazon EKS でも利用できるようになったことをお伝えしました。これは、ロードマップで最も要望の多かった機能の 1 つに対応したものです。また、サードパーティのネットワークポリシープラグインを管理しなくても、きめ細やかな通信制御を実施し、ワークロードを分離し、AWS Kubernetes クラスター全体のセキュリティを強化する方法を示しました。

NetworkPolicy の領域を詳しく調べる時に、Amazon EKS ではアプリケーションの特定のセキュリティ要件を念頭に置き、新たな脅威に備えるために定期的にポリシーを見直して更新することを推奨しています。綿密な計画と実装をおこなうことで、Kubernetes NetworkPolicy のポテンシャルを最大限に活用して、アプリケーションとデータを不正なアクセスから保護できます。推奨事項や追加の考慮事項については、Amazon EKS ベストプラクティスガイドをご覧ください。

Amazon VPC CNI のインストール手順については、Amazon EKS ユーザーガイドを参照してください。Amazon VPC CNI プラグインに関するフィードバックは、GitHub でホストされている AWS コンテナロードマップに Issue を開くか、コメントを残すことで提示できます。今後も機能を進化させ、eBPF テクノロジーを活用して Amazon VPC CNI 内でモニタリングやオブザーバビリティの機能を提供する追加の方法を模索していきますので、ご期待ください。

翻訳はソリューションアーキテクトの後藤が担当しました。原文はこちらです。