Contents
はじめに – 本記事の目的と対象読者
Kubernetes の NetworkPolicy を用いれば、Pod 同士や外部サービスへの通信を細かく制御できますが、対応した CNI プラグインが正しく導入されていなければポリシーは無効化されたままです。本ハンズオンでは、2026 年時点で AWS EKS が公式に推奨する Amazon VPC CNI(CNI アドオン) と Calico の両方をセットアップし、実際に NetworkPolicy を作成・適用・検証する手順を体験します。対象は本番環境で EKS を運用中の DevOps エンジニア・SRE です。
本記事を最後まで読めば、最小構成だけでなく外部 egress の制御やベストプラクティス も含めた実践的なネットワークセキュリティ設計ができるようになります。
前提条件と環境設定
このセクションでは、ハンズオンを安全に開始するために最低限必要な EKS バージョン・IAM 権限・CLI ツール を整理します。前もって準備しておくことで、途中で手戻りが発生しないようにします。
対象となる EKS クラスタのバージョン要件
2026 年 3 月時点の公式ドキュメントによれば、Amazon VPC CNI ポリシー と Calico v3.27 以降 は EKS v1.28 以上 のクラスターで安定動作が保証されています。バージョンが古い場合は、まず eksctl upgrade cluster で最新のマイナーバージョンへ更新してください。
必要な IAM 権限と CLI ツール
| 項目 | 推奨設定・理由 |
|---|---|
| IAM ロール | 以下の最小権限が付与されたロールを使用します。json<br>{<br> "Version": "2012-10-17",<br> "Statement": [<br> { "Effect":"Allow", "Action":[ "eks:DescribeCluster" ], "Resource":"*" },<br> { "Effect":"Allow", "Action":[ "ec2:DescribeNetworkInterfaces","ec2:CreateNetworkInterface","ec2:DeleteNetworkInterface","ec2:AssignPrivateIpAddresses","ec2:UnassignPrivateIpAddresses" ], "Resource":"*" },<br> { "Effect":"Allow", "Action":[ "iam:PassRole" ], "Resource":"arn:aws:iam::*:role/eks-nodegroup-role" }<br> ]<br>}<br>※実際のクラスター構成に合わせてリソース ARN を絞り込みます。 |
| aws-cli | バージョン 2.14 以上を推奨(aws --versionで確認)。最新機能とセキュリティ修正が含まれています。 |
| kubectl | クラスタの API バージョンに合わせた kubectl(例: v1.28.x)。バイナリは公式サイトからダウンロードしてください。 |
| eksctl | 最新リリース(2026‑02 時点で 0.156.0)がインストールされていることを確認します。 |
|
1 2 3 4 5 6 7 |
# macOS の例:Homebrew で最新ツールをインストール brew install awscli eksctl kubectl # AWS 認証情報の設定(プロファイル名は任意) aws configure set profile.my-eks-profile.region ap-northeast-1 aws configure set profile.my-eks-profile.output json |
テストクラスター作成例
|
1 2 3 4 5 6 7 8 9 10 |
eksctl create cluster \ --name np-demo \ --version 1.28 \ --region ap-northeast-1 \ --nodegroup-name standard-workers \ --node-type t3.medium \ --nodes 3 \ --managed aws eks update-kubeconfig --name np-demo --region ap-northeast-1 |
CNI プラグインの導入
NetworkPolicy が機能するためには、CNI プラグイン側が ポリシーコントローラー を提供している必要があります。本節では Calico と Amazon VPC CNI + Amazon VPC CNI ポリシー の 2 種類を導入し、それぞれのバージョン要件と設定ポイントを解説します。
Calico のインストールと基本設定
Calico はオープンソースのネットワークプラグインで、デフォルトで NetworkPolicy をサポートします。以下は公式マニフェスト(2026‑02 更新版)を利用した手順です。
- 最新マニフェスト取得
bash
curl -L -o calico.yaml https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/calico.yaml - ConfigMap のカスタマイズ(インラインで
networkPolicyを有効化)
yaml
# 省略せずに貼り付ける例
apiVersion: v1
kind: ConfigMap
metadata:
name: calico-config
namespace: kube-system
data:
typha_service_name: "calico-typha"
cni_network_config: |
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "__KUBERNETES_NODE_NAME__",
"ipam": {
"type": "host-local"
},
"policy": {
"type": "k8s"
}
} - マニフェスト適用
bash
kubectl apply -f calico.yaml
ポイント:Calico が提供する
calicoctlコマンドで IPIP トンネルや BGP の有無を確認できます。EKS の VPC CNI と併用したい場合は、IPIP を無効化しBGP設定だけ残すのが一般的です。
Amazon VPC CNI + Amazon VPC CNI ポリシー(CNI アドオン)の有効化
AWS が提供する公式手順は変遷があります。2026 年 2 月時点で ENABLE_POD_ENI フラグは非推奨とされ、代わりに環境変数 AWS_VPC_K8S_CNI_ENABLE_POD_ENI=true を使用します。最新情報は必ず公式リファレンス(EKS CNI Add-on Docs)で確認してください。
- CNI アドオン本体のインストール(v1.15 以降が必要)
bash
eksctl utils install-aws-vpc-cni \
--cluster np-demo \
--region ap-northeast-1 \
--approve - Pod ENI 機能の有効化(非推奨フラグは使用しない)
bash
kubectl set env daemonset/aws-node -n kube-system AWS_VPC_K8S_CNI_ENABLE_POD_ENI=true - NetworkPolicy 用 webhook のデプロイ(ポリシーコントローラー)
bash
eksctl utils install-aws-vpc-cni-policy \
--cluster np-demo \
--region ap-northeast-1
バージョン要件:
aws-nodeコンテナはv1.15.0以上、amazon-vpc-cni-policyはv0.3.0以上が必要です。kubectl get daemonset aws-node -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'で実際のイメージタグを確認し、公式リリースノートと照らし合わせましょう。
最小構成の NetworkPolicy 作成・適用
このセクションでは デフォルト deny を前提に、特定ラベルを持つフロントエンド Pod だけがバックエンド Pod の HTTP(ポート 80)へアクセスできる最小構成を作ります。まずは YAML サンプルを確認し、その後デプロイ手順と検証方法を示します。
NetworkPolicy YAML のサンプル
以下のマニフェストは app=backend ラベルが付与された Pod を対象に、role=frontend ラベルを持つ Pod からの TCP/80 のみ許可し、それ以外の ingress とすべての egress(ただし CIDR 制限で例示)をブロックします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-backend namespace: default spec: podSelector: matchLabels: app: backend # バックエンド対象 Pod policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: role: frontend # フロントエンドからのアクセスを許可 ports: - protocol: TCP port: 80 egress: - to: - ipBlock: cidr: 10.0.0.0/8 # 同一 VPC 内のリソースへの outbound を許可 |
ポイント:
policyTypesにIngressとEgressの両方を明示することで、意図しない egress がデフォルトで許可されることを防ぎます。実運用では外部サービス(例: S3)だけに絞った CIDR を指定してください。
デプロイ手順と確認コマンド
- ファイル保存
bash
cat > allow-frontend-to-backend.yaml <<'EOF'
(上記 YAML を貼り付け)
EOF - 適用
bash
kubectl apply -f allow-frontend-to-backend.yaml - 作成結果の検証
bash
# ネームスペースと名前を指定して詳細表示
kubectl get networkpolicy allow-frontend-to-backend -n default -o yaml
# ポリシーが対象 Pod に正しくマッチしているか確認
kubectl describe networkpolicy allow-frontend-to-backend -n default
典型的なユースケースとベストプラクティス
最小構成だけでなく、実務でよく求められる 外部サービスへの egress 制御 や 名前空間単位の分離 を例示します。これにより、ポリシー設計の全体像が把握できるようになります。
ユースケース 1:外部 S3 バケットへの限定的 egress
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-s3 namespace: prod spec: podSelector: {} # 全 Pod が対象 policyTypes: - Egress egress: - to: - ipBlock: cidr: 52.216.0.0/15 # ap-northeast-1 の S3 エンドポイント範囲(例) ports: - protocol: TCP port: 443 # HTTPS 通信のみ許可 |
ベストプラクティス:外部への egress は「最小 CIDR」かつ「HTTPS のみ」に絞り、不要なポートはすべて遮断します。定期的に AWS IP 範囲リスト(
https://ip-ranges.amazonaws.com/ip-ranges.json)を取得し、CI パイプラインで自動更新することが推奨されます。
ユースケース 2:名前空間ごとの完全分離
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-cross-namespace namespace: dev spec: podSelector: {} # dev 名前空間のすべての Pod が対象 policyTypes: - Ingress - Egress ingress: - from: - podSelector: {} # 同一名前空間内からのみ許可 egress: - to: - podSelector: {} # 同一名前空間内へだけ outbound を許可 |
ポイント:
podSelector: {}は「すべての Pod」を意味します。上記ポリシーはdev名前空間以外からのアクセスを完全に遮断し、同一名前空間内部でのみ通信可能にします。
ベストプラクティス集
| 項目 | 推奨内容 |
|---|---|
| デフォルト deny | クラスター作成直後に NetworkPolicy を 1 件だけ作り、全トラフィックを遮断した状態で運用開始する。 |
| ラベル命名規則 | app, role, environment のようなキーはチーム横断で統一し、ドキュメント化しておく。 |
| ポリシーのコード管理 | policy.yaml を Git リポジトリに保存し、PR 時に kubeval や conftest で静的検証を走らせる。 |
| CI/CD テスト | kubectl exec による egress/ingress の自動テストスクリプト(例: network-policy-test.sh)をパイプラインに組み込み、変更時の回帰テストを実施する。 |
| 監査ログ | Amazon VPC Flow Logs と EKS audit logs を統合し、ポリシー違反や不審な通信があった場合にアラートを上げる仕組みを構築する。 |
テスト手順と結果検証
実際に作成した NetworkPolicy が期待通りに機能しているか確認します。ここでは ラベルがポリシーと一致する Pod と 不一致の Pod を用意し、curl と nc(netcat)で通信成功/失敗を判定します。
テスト用 Pod のデプロイ(ラベル整合性に注意)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# フロントエンド側(role=frontend, app=frontend) kubectl run frontend-pod \ --image=busybox \ --restart=Never \ --labels="app=frontend,role=frontend" \ -it --rm -- sh # バックエンド側(app=backend)※ポリシーの対象 kubectl run backend-pod \ --image=nginx \ --port=80 \ --labels="app=backend" \ --restart=Never \ -d # ラベルが一致しないテスト用 Pod(role=unknown) kubectl run other-pod \ --image=busybox \ --restart=Never \ --labels="app=unknown,role=unknown" \ -it --rm -- sh |
重要:
frontend-podのラベルrole=frontendがポリシーのfrom.podSelector.matchLabels.role=frontendと完全に一致している必要があります。以前の記事でrole: frontと記載した場合は動作しません。
通信テストコマンド
| テスト | コマンド | 期待結果 |
|---|---|---|
| 許可された ingress(成功) | curl -s http://backend-pod.default.svc.cluster.local:80 && echo "OK" |
HTML が返り、OK と表示される |
| 拒否された ingress(失敗) | nc -zv backend-pod.default.svc.cluster.local 80 |
Connection timed out または Network unreachable エラーが出る |
| 許可された egress(例:S3) | curl https://s3.ap-northeast-1.amazonaws.com/ |
正常に応答し、ステータスコード 200 が返る(ポリシーで許可した場合) |
| 拒否された egress(例:外部 API) | curl https://api.ipify.org |
タイムアウトまたは接続エラーが発生 |
期待結果の表形式まとめ
| テスト元 Pod | ラベル | 宛先ラベル | ポート | 結果 |
|---|---|---|---|---|
frontend-pod |
role=frontend |
app=backend |
80 (TCP) | 成功(ポリシーにマッチ) |
other-pod |
role=unknown |
app=backend |
80 | 失敗(ラベル不一致) |
frontend-pod |
role=frontend |
app=backend |
443 | 失敗(ポリシーで未定義) |
frontend-pod |
role=frontend |
外部 S3 CIDR | 443 | 成功(egress ポリシーで許可) |
frontend-pod |
role=frontend |
任意外部 API | 80 | 失敗(egress がブロック) |
トラブルシューティングとベストプラクティス
NetworkPolicy が期待通りに動作しないケースは多く、原因の切り分けが重要です。ここでは代表的な問題シナリオと具体的なデバッグ手順を示します。
CNI が NetworkPolicy をサポートしていない場合
- CNI バージョン確認
bash
kubectl get daemonset -n kube-system aws-node -o jsonpath='{.spec.template.spec.containers[0].image}'
# 例: amazon/k8s-cni:v1.15.2 - 公式対応表のチェック(AWS Docs → “CNI version compatibility”)
- 未対応の場合は、以下いずれかを実施:
・Calico へ切り替える
・aws-node のイメージを最新 (v1.16以上) にアップグレード
ポリシーがマッチしない典型的な原因
| 原因 | 確認ポイント | 解決策 |
|---|---|---|
| ラベルのタイプミス | kubectl get pods -n default --show-labels で実際のラベルを確認 |
YAML の matchLabels キー・値を正確に合わせる |
| Namespace 指定ミス | metadata.namespace が期待通りか確認 |
正しい Namespace に再作成、もしくは --namespace オプションで適用 |
| PolicyTypes が抜けている | kubectl describe networkpolicy <name> で Policy Types: をチェック |
必要に応じて Ingress / Egress を明示的に列挙 |
| Webhook が起動していない | kubectl logs -n kube-system daemonset/aws-node にエラーが無いか確認 |
環境変数 AWS_VPC_K8S_CNI_ENABLE_POD_ENI の設定漏れや、Pod ENI 機能が有効化されているか再度適用 |
ログ取得例
|
1 2 |
kubectl logs -l k8s-app=aws-node -n kube-system --tail=200 | grep -i "networkpolicy" |
ヒント:
NetworkPolicy webhook not readyと表示されたら、DaemonSet のロールアウトが完了していない可能性があります。kubectl rollout status daemonset/aws-node -n kube-systemで進捗を確認してください。
ベストプラクティス再掲
- 最小権限の IAM:上記 JSON ポリシーをベースに、使用するリソースだけ許可範囲を絞る。
- バージョンロック:
eksctl utils install-aws-vpc-cniの際は--versionフラグで明示的にイメージタグを指定し、予期せぬ自動アップデートを防止する。 - CI でのポリシー検証:
conftestと OPA ポリシーで「必ずpolicyTypesに Egress が含まれる」等の社内ルールをコード化し、プルリクエスト時に自動チェック。 - 監査と可視化:Amazon VPC Flow Logs + CloudWatch Logs Insights で “DENIED” イベントを検索し、ポリシー違反が頻出する領域を特定して改善策を検討。
まとめと次のステップ
この記事では以下のことを実践できました。
- EKS クラスタに Calico と Amazon VPC CNI + ポリシーアドオン を導入し、NetworkPolicy が有効になる基盤を構築。
- 最小構成の NetworkPolicy(デフォルト deny+特定ラベル許可)を作成・適用し、
kubectl execとcurl/netcatで通信テストを実施。 - 外部 egress 制御や名前空間分離 といった典型的ユースケースと、IAM 最小権限・CNI バージョン要件 を明示したベストプラクティスを提示。
- トラブルシューティング手順(ログ取得、バージョン確認、ラベル整合性)と CI/CD でのポリシー検証 の流れを整理。
次に挑戦すべきこと
| 項目 | 推奨アクション |
|---|---|
| 環境ごとのポリシー分離 | dev / staging / prod 用の Namespace 別 NetworkPolicy をコード化し、GitOps で自動デプロイ。 |
| PodSecurityPolicy と併用 | Pod の権限昇格やホストネットワーク使用を制限する PSP(または PSA)と組み合わせ、全体的なセキュリティポスチャーを強化。 |
| ポリシーのコードレビュー自動化 | OPA + Conftest で「必ず Egress が明示されている」等の社内ルールを定義し、CI に組み込む。 |
| 可観測性の高度化 | CloudWatch Logs Insights のダッシュボードで「NetworkPolicy Denied」件数をモニタリングし、アラートを設定。 |
| 最新情報のウォッチ | ENABLE_POD_ENI フラグが非推奨になる可能性があるため、AWS のリリースノートや EKS ドキュメントを月次で確認する仕組みを作る。 |
これらを順次導入すれば、Kubernetes クラスターのネットワークレイヤーは 最小権限・可観測性・自動テスト が整った堅牢な状態になります。ぜひ本ハンズオンで得た知見を実際のプロダクション環境に展開し、継続的な改善サイクルへとつなげてください。