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 AMI、Amazon EKS-optimized Bottlerocket AMI、 Amazon 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 という名前のファイルに保存します。
クラスターの作成が完了するのを待って、Amazon VPC CNI が Node Agent を実行するようになったかどうかを確認します。
出力:
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 の使用方法については、ユーザーガイドを御覧ください。
サンプルアプリケーションのデプロイ
次に、demo-app というサンプル NGINX アプリケーションと、default Namespace にシンプルなクライアントアプリケーションをデプロイします。さらに、another-ns という default Namespace ではない Namespace に別のクライアントアプリケーションを作成します。
全ての Pod が Running 状態になるまで待ちます。
NetworkPolicy を実装する
デフォルトでは、Kubernetes は全ての Pod が他の全ての Pod と自由に通信することを許可しています。Kubernetes の NetworkPolicy が Pod に適用されていない場合は、Pod に出入りする全てのトラフィックが許可されます。
アクセスを確認し、全ての送受信トラフィックを許可する
別のターミナルを使用して、前のステップでデプロイしたクライアントの Pod からの接続を確認できます。
API 呼び出しが成功したことを示す応答が表示されます。
全てのトラフィックを拒否する
demo-app アプリケーションのために、全 Namespace に渡って全てのトラフィックを拒否するポリシーを適用することで、分離をおこないましょう。
NetworkPolicy では全ての Pod を選択したため、demo-app への受信トラフィックはすべて拒否されます。
前のコマンドはタイムアウトになります。
同じ Namespace からの受信を許可する
次のステップでは、同じ Namespace 内で、client-one から demo-app への受信トラフィックを許可します。
NGINX のウェルカムページの HTML が返されるはずです。
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 からの全ての送信の分離を適用します。
DNS Lookup を含め、client-one からの全ての送信トラフィックが拒否されていることがわかります。