研究開発部 Architectグループ ML PlatformチームのKAZYこと新井です。
名古屋にある中部支店に所属しています。
バージョン更新の負荷を減らすためにEKSにセキュリティーグループを追加した話を紹介します。
なお、本記事は【R&D DevOps通信】という連載記事のひとつです。
目次
背景
研究開発部へのEKS導入
2022年に研究開発部ではアプリケーション基盤としてEKS(Circuitと呼んでいます)を導入しました。
Kubernetesは日々開発が進んでおり、新しいバージョンが続々とリリースされています。
Amazon EKSでは、新しいKubernetesのバージョンが最初に利用可能になってから14か月間サポートされます*1。
Amazon EKS Kubernetes のバージョン - Amazon EKS
Amazon EKSユーザは定期的にKubernetesのバージョン更新をすることになります。
私達のチームでは、この度はじめてのクラスタのバージョン更新を迎えます。
Blue/Greenデプロイによるクラスタのバージョン更新
CircuitではBlue/Greenデプロイでクラスタのバージョン更新を行います。
この方法では、新しいバージョンのクラスタに、既存のクラスタと同様のシステムを作成し、トラフィック移行をします*2。
既存のクラスタを更新するよりも、新しいクラスタを作成する方が手間やコストはありますが、ロールバックや検証が容易で、更新をより安全に行えるメリットがあります。
Blue/GreenデプロイをするためにCircuitではアプリケーションの負荷分散にIngressリソースは使わず、TargetGroupBindingリソースを使いターゲットグループの向き先を変えるだけでクラスタ間のトラフィック移行ができるようにしています。
以下の記事が詳しいです。
TargetGroupBinding を使って AWS EKS で Kubernetes を無停止かつ DNS 切り替え無しでバージョンアップしました – PSYENCE:MEDIA
以下の記事を読むとさらに理解が深まると思います。
より安全なEKS cluster update方法を模索する
宣言的 Blue/Green デプロイで EKS バージョンライフサイクルに立ち向かう話|グロービス・デジタル・プラットフォーム
クラスタごとに作られるクラスタセキュリティーグループ
EKSにはクラスタセキュリティーグループ(以降クラスタSG)というものがあります。クラスタSGはクラスタ作成とともに自動作成されます。
そしてeks-cluster-sg-<クラスタ名>-<uniqueID>
という名前を持ちます。
クラスタSGはコントロールプレーンに割り当てられているセキュリティーグループです。FargateノードやEC2ノードもデフォルトではこちらに割り当てられています。
Amazon EKS セキュリティグループの要件および考慮事項 - Amazon EKS
SecrurityGroupPolicyでPodごとのアクセス制限
CircuitではSecrurityGroupPolicyリソースを使って、Pod単位でのアクセス制限をしています。
SecrurityGroupPolicyを使うためには紐付けるセキュリティーグループで満たすべき条件があります。
CircuitではEC2とFargateのノードがクラスタ内で動作しているため以下のようになります。
EC2ノード/Fargateノード共通
- PodからCoreDNSのPodへのTCP/UDP 53番ポートでの通信
- 名前解決を含む通信を避けることができれば塞がっていてもPodは起動するが、実用上不便です
- ノードに適用されたセキュリティーグループからのインバウンド通信
- probeを利用している場合は塞がっているとPodが正常に起動しない
- コントロールプレーンからkubelet に対する TCP:10250 通信
- 塞がっていてもPodは起動するが、kubectl exec/logsなどが使えなくなるため、実用上不便です
- EC2ノードにクラスタSGがノードにアタッチされている場合は意識しなくても通信ができる
EC2ノードのみ
- Podごとにネットワークインターフェースがある
- Amazon VPC CNI plugin for Kubernetesで実現ができる
Fargateノードのみ
- Podからコントロールプレーン(kube-apiserver)へのTCP:443 通信
- 塞がっているとFargateノードをプロビジョニングできずPodが起動しない
通信的な観点ではFargateノードのPodからコントロールプレーン(apiserver)への通信が必須で、その他は運用方法に合わせて決めます。
チュートリアル: Pods のセキュリティグループ - Amazon EKS
解決したい課題
クラスタのバージョン更新のたびにSecurityGroupPolicyを書き換えたくない
ドキュメントには、SecurityGroupPolicyを使用するための簡単な方法が書かれており、クラスタSGをセキュリティーグループの1つとして指定することが提案されています。Circuitでも同様の方法を採用していました。
そのため、Circuit内で使用するSecurityGroupPolicyリソースのマニフェストは、クラスタSGとPod固有のセキュリティーグループを組み合わせています。
apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy ︙略 securityGroups: groupIds: - クラスタSG - Pod独自のSG
この構成では、新しいクラスタを作成するたびにマニフェストを更新する必要があります。 クラスタSGはクラスタごとに作成されるためです。
apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy ︙略 securityGroups: groupIds: - クラスタSG ←クラスタが変わる毎に変更が必要 - Pod独自のSG
この書き換え作業が今回の課題です。無くしたいです。
解決策
追加のセキュリティーグループをSecurityGroupPolicyに紐付ける
EKSにセキュリティーグループを追加して解決しました。
追加のセキュリティーグループ
EKSでは、クラスタSG以外にも、追加のセキュリティーグループがあります。独自に作成したセキュリティーグループを追加することができます。
コンソール上ではネットワーキングタブの中央辺りのクラスタセキュリティーグループの下にあります。
追加のセキュリティーグループはクラスタSGと同様にコントロールプレーンに割り当てられています。
TerraformでEKSにセキュリティーグループを追加する
CircuitはTerraformのaws_eks_clusterリソースでEKSクラスタを作成しているため、vpc_configのsecurity_group_idsにセキュリティーグループを追加しました。
resource "aws_eks_cluster" "eks_circuit" { ︙略 vpc_config { ︙略 security_group_ids = ["sg-XXXXXX"] # 追加のセキュリティーグループ } ︙略 }
追加のセキュリティーグループの設定
以下のルールを全てのSecrutiyGroupPolicyにアタッチして運用することを前提に設定しました。この設定により、EC2/Fargateのノードを気にすることなくPod単位のアクセス制限が運用できます。
- 443ポートへのコントロールプレーン通信
- Fargateノードのプロビジョニングを可能にするためです
- TCP/UDP53ポートへのCoreDNS通信
SecurityGroupPolicyを書き換える
SecurityGroupPolicyのリソースに設定しているクラスタSGを、新しく作成したSGに書き換えて完成です。
apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy ︙略 securityGroups: groupIds: - 追加のセキュリティーグループ ← クラスタが変わっても書き換える必要なし - Pod独自のSG
これにより、次回以降のクラスタ更新では、セキュリティーグループの書き換えが不要になりました。
おわりに
クラスタSG、CoreDNS、VPC CNI、kubelet の動作について学ぶことができ、私にとって良い課題でした。
引き続き勉強します。
余談
Pod毎にセキュリティーグループをつけて、Liveness probe/Readiness probeを使用するためには、AmazonVPC CNIの設定でTCP Early Demux も無効にする必要があることに気がつかず結構ハマりました。
チュートリアル: Pods のセキュリティグループ - Amazon EKS
求人
私の所属するML Platformチームを含む、研究開発部Architectグループでは一緒に働く仲間を募集しています。