【ITニュース解説】A Pod with Public IP
2025年09月17日に「Dev.to」が公開したITニュース「A Pod with Public IP」について初心者にもわかりやすく解説しています。
ITニュース概要
EKSではPodに直接パブリックIPを割り当て、専用のセキュリティグループを設定できる。これにより、リアルタイム通信で問題となるNAT越えが不要になり、多くのポートを開放するセキュリティリスクも解消。安全に外部と直接通信できる環境を構築する。
ITニュース解説
システムエンジニアを目指す皆さんにとって、クラウド環境でのアプリケーションデプロイは避けて通れないテーマだ。特に、多数のサービスを効率的に運用できるKubernetesのようなコンテナオーケストレーションシステムは重要となる。今回は、AWSのKubernetesサービスであるEKSで、特定のPodに直接パブリックIPアドレスを割り当て、セキュリティを確保しながら外部との通信を可能にする方法について解説する。
通常、KubernetesのPodは、プライベートIPアドレスを持ち、外部との通信にはロードバランサーやNATゲートウェイなどを介することが一般的だ。しかし、リアルタイム通信を必要とするアプリケーション、例えば電話システムやビデオ会議で使われるRTP(Real-time Transport Protocol)のようなメディアサーバーをEKS上で動かす場合、この一般的な構成では問題が生じることがある。RTPは、通信の両端が直接ネットワークで通信できることを前提としているため、NAT(Network Address Translation)ゲートウェイの背後にあるプライベートサブネットでは、外部からのインバウンドトラフィック(受信トラフィック)がPodに直接到達できないため、リアルタイムストリーミングが困難になるのだ。NATゲートウェイは通常、内部から外部への通信を許可するが、外部から内部への開始される通信はデフォルトでブロックする仕組みになっている。
この問題を解決しようと、安易にEKSのワーカーノード(Podが動作する仮想サーバー)をインターネットに公開し、そのセキュリティグループで必要なポートを全て開けてしまうという方法が考えられるかもしれない。しかし、これは非常に危険な選択だ。RTPは多くの同時ストリーミングを処理するために、非常に広い範囲のポート(数千から数万)を開放する必要がある。これほど多くのポートをセキュリティグループで許可してしまうと、Kubernetesが内部で使用するNodePortなどの他のサービスにも、意図しないアクセスを許してしまうことになる。これは、システムのセキュリティを著しく低下させ、外部からの攻撃に対する脆弱性を高めてしまう。
そこで理想的な解決策として提案されるのが、以下の三つの条件を満たす方法である。一つ目は、Podがインターネットから直接アクセス可能なパブリックな静的IPアドレスを持つこと。二つ目は、Podが他のPodと共有ではない専用のネットワークインターフェースを持つこと。そして三つ目は、そのPod専用のセキュリティグループが適用されることだ。これらの条件が満たされれば、Podは安全かつ信頼性の高い方法で外部と直接通信できるようになる。Podが専用のネットワークインターフェースとセキュリティグループを持つことで、必要なポートのみを開放し、他のPodやノード全体に影響を与えることなく、そのPod固有の通信要件を満たせるようになる。
では、AWS EKS環境でこれをどのように実現するのか、具体的な手順を見ていこう。この実現には、EKSクラスタがAWS VPC-CNIプラグインを使用していること、そして事前にElastic IP(AWSが提供する静的なパブリックIPアドレス)とセキュリティグループが準備されていることが前提となる。AWS VPC-CNIは、EKSクラスタのPodにAWSのVPCネットワークのIPアドレスを直接割り当てるためのプラグインであり、この機能を利用する。
まず第一のステップは、Podに専用のネットワークインターフェースを割り当てる設定を有効にすることだ。これは、EKSクラスタ内でネットワーク管理を担当するaws-nodeというコンポーネント(DaemonSetとして動作する)に対して、環境変数"ENABLE_POD_ENI": "true"を追加することで行われる。この設定により、AWS VPC-CNIは、特定のPodに対して独自のネットワークインターフェースを割り当てることができるようになる。この変更を適用しても、既存のPodや新しく作成される通常のPodの動作には影響はなく、デフォルトでは引き続き共有のネットワークインターフェースを使用する。
次に第二のステップとして、Podに専用のセキュリティグループを割り当てる。AWSはKubernetesの機能を拡張するためにCRD(Custom Resource Definition)という仕組みを提供しており、これを利用する。具体的には、vpcresources.k8s.aws/v1beta1というAPIバージョンで定義されるSecurityGroupPolicyというカスタムリソースを作成する。このSecurityGroupPolicyでは、podSelectorという設定を使って、どのラベルを持つPodにセキュリティグループを適用するかを指定できる。例えば、app: media-serversというラベルを持つPodに対して、事前に用意しておいた特定のセキュリティグループ(sg-e3edxxxxxのようなIDを持つもの)を適用するように設定する。このSecurityGroupPolicyをKubernetesクラスタに適用した後、実際にapp: media-serversというラベルを持つPodを作成すると、そのPodには専用のネットワークインターフェースが割り当てられ、さらに指定したセキュリティグループがそのインターフェースに適用されるようになる。この時点で、PodはプライベートIPアドレスを持ち、専用のセキュリティグループによって通信が制御されている状態になる。PodのIPアドレスはkubectl get pods -n myns -o wideコマンドで確認でき、そのIPアドレスをAWSコンソールのEC2サービスにあるネットワークインターフェースの項目で検索すると、Podに割り当てられた専用のネットワークインターフェースとそのインターフェースに付与されたセキュリティグループを確認できるだろう。
そして最後の第三のステップは、PodにElastic IPを割り当てることだ。これまでの手順でPodは専用のプライベートIPアドレスとセキュリティグループを持つようになったが、まだインターネットから直接アクセス可能なパブリックIPは持っていない。静的なパブリックIPアドレスは、外部のサービスが特定のIPアドレスをホワイトリスト登録して通信する場合などに特に重要となる。AWSコンソールまたはAWS CLIを使用して、新しいElastic IPアドレスを確保するか、既存のものを利用する。その後、このElastic IPアドレスを、Step 2でPodに割り当てられた専用ネットワークインターフェースに関連付ける。この関連付けは、AWS CLIのaws ec2 associate-addressコマンドを使って行うことが可能だ。Elastic IPの割り当てID、PodのプライベートIPアドレス、そしてPodのネットワークインターフェースIDを指定することで、このバインディングを完了させる。このassociate-addressコマンドは、Podが起動するたびに実行されるよう、Podの定義にinit-containerとして組み込むことで、IPアドレスのバインディングを自動化し、Podのライフサイクルにわたって永続的にElastic IPを関連付けた状態を維持できる。
このようにして、Podに専用のネットワークインターフェース、専用のセキュリティグループ、そしてパブリックな静的Elastic IPアドレスを割り当てることで、リアルタイム通信を必要とするアプリケーションでも、セキュリティを犠牲にすることなく、直接外部と安全に通信できる環境を構築することが可能になる。これは、特定の要件を持つアプリケーションをクラウドネイティブ環境で運用する上で、非常に強力で安全な方法と言えるだろう。