EKS環境にてCalicoからVPC CNI pluginにNetworkPolicy Engineを移行した話
始めに
こんにちは!グロービス・デジタルプラットフォーム部門(GDP) SREチームの松井です。
今回は、GDPのプロダクト基盤として運用しているEKS上のKubernetesエコシステムの運用(主にNetworkPolicy関連)に関するお話を書きます。
背景の課題
我々は2020年ごろからEKSをプロダクト基盤として運用を継続しています。 Kubernetesの運用上の明確なメリットとして、成熟したコミュニティの知見が参考になる点や、豊富なエコシステムをOptionとして採用する事が可能な点が考えられます。
しかしながら、EKS(Kubernetes)の運用の宿命として、これらの Kubernetesエコシステムのバージョンアップデートを定期的に行い、最新に追従する事が求められます。これらのバージョンアップ対応はRenovateを活用することで一定程度自動化できていますが、バージョンアップに伴う影響確認等はまだSREによる事後確認を必要としており、一定の工数をかけざるをえません。
我々は運用開始当初からクラスタ内部のネットワークセキュリティ確保を目的として、Calicoを採用する形でNetworkPolicyを有効化していましたが、Calicoのバージョン対応に関しても運用負荷となっていました。
Amazon VPC CNI pluginの機能追加と移行検討
これらのエコシステムコンポーネントの採用当時は、EKSデフォルトのCNI pluginであるAmazon VPC CNI plugin(以下、VPC CNI pluginと表記)単独ではNetworkPolicyを運用できませんでしたが、2023年8月に仕様が変更され、VPC CNI plugin単独でNetworkPolicyが利用可能となりました。日本語解説のブログ記事も出ています。
VPC CNI pluginに統合されることでエコシステムの運用コストが低減できる事ができそうという話が上がり、いずれ移行しようとの話も出ていましたが、別件の検証中に運用中のCalicoの動作不具合が判明した為、これが決め手となり、移行を本格検証していく事になりました。
Calicoからの移行をKubernetesマイナーバージョン1.25以降でサポートされていますが、我々は検討当時1.27にて運用していた為、問題ありませんでした。ただし、先行事例が見当たらない事もあり、入念な事前検証が必要と判断しました。移行検証に際し以下の項目を事前考慮の上、検証を実施しました。
- 有効化設定の選定
- ユースケースを鑑みて必要な設定のみ有効化する
- 検討項目は以下
- イベントロギング
- 動作モード
- Metrics
- NetworkPolicyの仕様が正常に機能するか
- Manifestとして定義されたルール通りにDeny Policy, Allow Policyが正常機能するか
- 移行方式
- Staging/Production環境はEKSクラスターのBlue/Green Deploy
移行検証
移行に際し、移行検証は開発環境で実施の上、移行の事前検証完了後、他の環境の移行はEKS Version Updateと連動してBlue/Green Deployによる切替方式を採用する方針としました。
上記等を参考に、まずは開発環境で有効化を行いました。なお、注意点として、In-Placeでの移行を計画される場合は事前にCalicoの削除対応が必要となります。具体的には以下のような対応が必要です。
-
kind:install
CRの削除# 削除対象の確認 kubectl get installation default -n calico-system # 削除コマンド kubectl delete installation default -n calico-system
-
その他のCRDの削除
# 削除対象の確認 kubectl get crds -oname | grep -e "crd.projectcalico.org" -e "tigera.io" # 対象の削除 kubectl get crds -oname | grep -e "crd.projectcalico.org" -e "tigera.io" | xargs kubectl delete
-
Tigera Operator削除
-
全てのWorker Node Instanceの入れ替え
- Calico削除後も現行Podは正常に稼働し続けますが、新規Podを現行稼働Nodeにデプロイ出来なくなる為、入れ替えは必須になります。Evictionが走る為、本番環境においてはPDBの事前考慮は必須です。
削除後、VPC CNI pluginにて当該機能を有効化する事で利用できます。
我々はこれらのAdd-onをTerraform(eks public module)を利用して管理している為、当該Moduleのパラメータ、及び関連リソースを以下のように変更する事で対応しました。
module "eks" {
source = "terraform-aws-modules/eks/aws"
...
cluster_addons = {
vpc-cni = {
addon_version = "v1.18.2-eksbuild.1"
service_account_role_arn = module.irsa_amazon_vpc_cni.iam_role_arn
configuration_values = jsonencode({
enableNetworkPolicy = "true"
nodeAgent = {
enablePolicyEventLogs = "true"
enableCloudWatchLogs = "true"
healthProbeBindAddr = "8163"
metricsBindAddr = "8162"
}
})
}
}
...
}
# doc: <https://docs.aws.amazon.com/eks/latest/userguide/cni-network-policy.html>
# IRSA用のカスタムポリシー
data "aws_iam_policy_document" "vpc_cni" {
statement {
sid = "CloudwatchlogsForNetworkPolicyLogging"
actions = [
"logs:DescribeLogGroups",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = ["*"]
}
}
resource "aws_iam_policy" "vpc_cni" {
name = "vpc-cni-policy-${local.env}"
policy = data.aws_iam_policy_document.vpc_cni.json
}
これらを有効化する事で、予めVPC CNI pluginのコンポーネントとしてインストール済みのNode Agentコンテナ(aws-network-policy-agent)が機能するようになります。
Node AgentはEKSコントロールプレーン上に存在するNetwork Policy コントローラーから、NetworkPolicyを基に変換されたPolicyEndpoints CRD情報を受け取り、eBPFプログラムによりパケットのフィルタリングを実施するようになります。
考慮ポイント
VPC CNI pluginベースのNetworkPolicyの有効化に伴い、ホワイトペーパーを参考にしながら、主に以下の点を考慮しました。
-
NETWORK_POLICY_ENFORCING_MODE
変数の有効化- 変数
NETWORK_POLICY_ENFORCING_MODE
をstrict
に設定すると、VPC CNI を使用するポッドはデフォルトの拒否ポリシーで起動し、その後ポリシーが設定されます。現状のユースケースに応じて、ここは有効化するか否かの判断が必要になります。
- 変数
-
イベントロギングの有効化
- 参考:https://docs.aws.amazon.com/eks/latest/userguide/network-policies-troubleshooting.html#network-policies-troubleshooting-flowlogs
-
The ability to log network security events (for example connections that are blocked or accepted).
- KubernetesのNetworkPolicyの公式ドキュメントにて、できない事として上記が明示されていますが、VPC CNI pluginの独自実装により、NetworkPolicyのイベントログが取得可能になっています。
- デバッグが容易になる為、これらの機能は有効化を検討し、ロギング有効化する方針で対応しました。
-
healthProbe/Metrics portの重複確認
- 8163/8162 PortをそれぞれDefaultで利用する為、既に他のService Port等で利用されてないか事前に確認の必要があります。
移行前テスト
これらの有効化作業を実施の上、検証環境上にてVPC CNI plugin NetworkPolicyが有効化できました。当該環境上でManifestとして定義されたルール通りにDeny Policy, Allow Policyが正常機能するか検証を実施しました。評価観点としては主に以下となります。
- Egress Ruleが正常機能するか
- Ingress Ruleが全て正常機能するか
- Namespace間の通信制御が正しく機能するか
- Security Group for Podsとの併用において正常機能するか
実践的なユースケースに適合させる為、テスト用のNginx Deployment Manifestを配置し、Destination Namespaceとの通信をPodにShell Loginの上Curl等にて疎通確認するといった事を主に実施しました。
意図した通りに通信出来ているかの確認には先述したVPC CNI pluginのイベントログが非常に役に立ちました。
イベントログをEKS ClusterのCloudwatch Log Groupに出力可能なので、ここで検索/フィルターが実施できます。イベントログは以下の形式です。
Node: ip-xx-xxx-xx-xxx.ap-northeast-1.compute.internal;SIP: xxx.xxx.xxx.xxx;SPORT: xx;DIP: xxx.xxxx.xxx.xxx;DPORT: xxxxx;PROTOCOL: UDP;PolicyVerdict: DENY/ACCEPT
当該ログから対象ノード、Source IP/Port, Destination IP/Port 、ACCEPT/DENY等の情報を入手できます。テスト対象のPod IPと突合する事で正しくNetworkPolicyが機能しているか確認する事が可能です。
ハマッた所
上記のように移行前検証を実施しましたが、かなりの時間を要してしまいました。具体的には以下のような不具合が発現した為、それぞれ調査に時間を要した形です。
同一Manifest内にてIngress/Egressに対し同一CIDRに対するルールを複数定義した場合、一部が正しく適合されないケースがある
テストを実施したところ、NetworkPolicyの設定意図とは異なる通信制御が適用される場合がありました。
該当のNetworkPolicyはDatadog AgentのNetworkPolicyとなりますが、EgressのRuleが一部正しく反映されないというものでした。詳細を追っていくと、こちらのIssueに該当する形でした。
同一Manifest内のrule評価ロジックの不具合に起因するものと確認できた為、暫定対策として別Manifestに反映されないRule定義を追加することで、加算評価されることを利用し、これらの不具合を回避しています。
Namespace間通信にてNetworkPolicy適用時の戻り通信が意図せず許可されない場合がある
Cross Namespace時の通信テストにて、意図しないReturn TrafficのBlockが発生していたので、AWSサポートと連携しながら調査を行いました。 こちらは結論としてはaws-network-policy-agentの不具合であり、VPC CNI plugin version v1.15.3(aws-network-policy-agent v1.0.5)にて修正済みとなっています。
Policy評価時にaws-network-policy-agentにてログがSpamされる
機能面でのテストを一通り終えたあと、ようやく移行対応が完了し、改めてログ出力状況を確認したところ以下のようなログがSpamされている事が発覚しました。
2024-xx-xx xx:xx:xx.xxxxxxxxx +0000 UTC Logger.check error: failed to get caller
こちらも調査を行ったところ、原因としてはaws-network-policy-agentの不具合によるものと判明しました。VPC CNI plugin version v1.18.2以上にアップデートする事で解消されます。機能面では影響は無いものの、Datadogにログ出力していることもあり、これらは運用コストに直結する要素であるため、こちらも対応した形です。
まとめ
移行検証には時間がかかりましたが、既存のNetworkPolicyの設定が全て設定意図通りに動作する形での移行を対応完了する事ができました。対応を完了した事によって、エコシステムの運用負荷を低減させるという当初の課題を解決することができました。
VPC CNI pluginのaws-network-policy-agentがリリースから比較的時間が経っていない機能という事もあり、移行時検証時の不具合調査には苦しみましたが、NetworkPolicyに対する理解を深める良い機会だったと思います。
SREチームではユーザーのために開発速度と安定性を両立するというミッションの元、持続的な改善とイノベーションを意識して日々のタスクに取り組んでいます。今後もこのマインドでプラットフォームの改善に取り組んでいきたいと考えています。
参考
- https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/cni-network-policy.html
- https://aws.amazon.com/jp/blogs/news/amazon-vpc-cni-now-supports-kubernetes-network-policies/
- https://kubernetes.io/docs/concepts/services-networking/network-policies/
- https://github.com/tigera/operator/issues/2031
- https://github.com/aws/amazon-network-policy-controller-k8s/issues/98
- https://github.com/aws/aws-network-policy-agent/issues/100
- https://github.com/aws/aws-network-policy-agent/pull/102
Discussion