一回EKSのFargateを試してみようと思っていたので、新年早々やってみた。せっかくなのでEKS+FargateプロファイルをTerraformから作成する。他の事例だとeksctlから構築するパターンが多いようだが、最近Terraformいじってるし、eksctl嫌いなもんで。(削除時にハマったこともあり)
その前に Fargateのことをよく分かっていなかったので基本項目をあげておく。以下は2022年1月現在の仕様・制約事項。
- 「面倒なEC2の管理が不要!」と大っぴらに言われているが、Fargateでも最低限のノードグループは必要。
- Fargate Pod用のノードが起動するサブネットはプライベートサブネットであること。
- 2.のPodがコントロールプレーンと通信するためVPC外へ出る必要がある。NATゲートウェイ/プロキシ/VPCエンドポイントいずれかの方式で外部への通信経路を確保する。
- Fargateプロファイルを設定する。(大雑把に言うとここでFargateが動作する環境を定義する)
- FargateにおけるPodとノードの関係は常に1:1となる。(1ノードに複数のPodは起動できない)
- Fargate Pod専用のIAMロールが必要。(4.で指定)
- Fargateと通常のEKSワーカーノードの共存が可能。
実は 1.については知らなかったので、EKSクラスタ起動してFargateプロファイル設定すればPodが起動できるもんだと思っていた。EC2がいらないってウソやんけ…。当初その辺りで躓いたのだが、余計な失敗ネタは置いといて成功パターンを書いておく。
で、Terraformのコード載せる前に基本前提について。上記の制約があることから、最小限以下の構成を用意しておく。それらもTerraformで作るのであればそれでもいいが、自分はさすがに面倒見切れないので既存のアイテムを流用した。VPCはすでにある想定で:
- AZにまたがったパブリックサブネット
- AZにまたがったプライベートサブネット
- NATゲートウェイ(2.のサブネットが外部と通信するため)
- ①EKSクラスタ ②ノードグループ ③Fargate Pod用の各IAMロール
- ノードグループリモートアクセス用のセキュリティグループ
- EKSクラスタ用のセキュリティグループ
- ノードグループ用のssh key
Fargateだろうが何だろうが、これらの前提アイテムは別途構築しなければならないのである。「eksctlならよしなに作ってくれるから楽!」とか言ってても、PoCならともかく実運用時にeksctlでお任せ構築なんてあり得ないのである。夢は見させてくれないのである。
IAMロールについて
①クラスタ②ノード用ロールは既存のを使用した。ちなみにそれぞれ必要なポリシーは、①はAmazonEKSClusterPolicy、②はAmazonEKSWorkerNodePolicy、AmazonEC2ContainerRegistryReadOnlyとなる。②については、PoC時は最小限の権限でよいが本来Podが必要とするサービスの権限をすべてポリシーに追加する。
参考
Amazon EKS クラスター の IAM ロール
Amazon EKS ノード の IAM ロール
Fargate Pod用ロールはCLIから新規作成した。信頼ポリシー用JSONを用意してコマンド実行。
eks-fargate-pods-policy.json(信頼ポリシー用JSON)
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"Service": "eks-fargate-pods.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
}
# ロール作成
$ aws iam create-role \
--role-name AmazonEKSFargatePodExecutionRole \
--assume-role-policy-document file://eks-fargate-pods-policy.json
# ロールにポリシーをアタッチ
aws iam attach-role-policy \
--role-name AmazonEKSFargatePodExecutionRole\
--policy-arn "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy"
Teraraformコード
以降、Terraformコード。今回、前提条件となるネットワーク環境、IAMロール等はTerraform外で作成済みのアイテムを指定している。
eks.tf
#############################################
# EKS Cluster
#############################################
resource "aws_eks_cluster" "eks-cluster" {
name = "eks-test-cluster"
role_arn = var.cluster-role
vpc_config {
subnet_ids = [var.public-a, var.public-c]
security_group_ids = [var.cluster-sg]
}
}
output "endpoint" {
value = aws_eks_cluster.eks-cluster.endpoint
}
output "kubeconfig-certificate-authority-data" {
value = aws_eks_cluster.eks-cluster.certificate_authority[0].data
}
#############################################
# EKS Node Group
#############################################
resource "aws_eks_node_group" "eks-node" {
cluster_name = aws_eks_cluster.eks-cluster.name
node_group_name = "eks-test-node"
node_role_arn = var.node-role
subnet_ids = [var.private-a, var.private-c]
ami_type = "AL2_x86_64"
instance_types = ["t3.small"]
labels = {
type = "fargate-test"
}
remote_access {
ec2_ssh_key = var.keyname
source_security_group_ids = [var.remote-sg]
}
scaling_config {
desired_size = 2
max_size = 2
min_size = 2
}
}
#############################################
# EKS Fargate Profile
#############################################
resource "aws_eks_fargate_profile" "fargate-test" {
cluster_name = aws_eks_cluster.eks-cluster.name
fargate_profile_name = "test-profile"
pod_execution_role_arn = var.pod-role
subnet_ids = [var.private-a, var.private-c]
selector {
namespace = "fargate-test"
}
}
以下、変数参照先のvariables.tf。最近のTerraform PoCではtfvarsを使っていたが、今回は単純なケースなのでこれ一本で行く。
variables.tf
#############################
# public subnet-a
#############################
variable "public-a" {
default = "subnet-xxxxxxxxxxxxxxxxx"
}
#############################
# public subnet-c
#############################
variable "public-c" {
default = "subnet-yyyyyyyyyyyyyyyyy"
}
#############################
# private subnet-a
#############################
variable "private-a" {
default = "subnet-wwwwwwwwwwwwwwwww"
}
#############################
# private subnet-c
#############################
variable "private-c" {
default = "subnet-zzzzzzzzzzzzzzzzz"
}
#############################
# cluster security group
#############################
variable "cluster-sg" {
default = "sg-xxxxxxxxxxxxxxxxx"
}
#############################
# eks node security group
#############################
variable "remote-sg" {
default = "sg-xxxxxxxxxxxxxxxxx"
}
#############################
# cluster IAM role
#############################
variable "cluster-role" {
default = "arn:aws:iam::012345678910:role/eks-cluster-role"
}
#############################
# node IAM role
#############################
variable "node-role" {
default = "arn:aws:iam::012345678910:role/eks-node-group-role"
}
#############################
# pod IAM role
#############################
variable "pod-role" {
default = "arn:aws:iam::012345678910:role/AmazonEKSFargatePodExecutionRole"
}
#############################
# eks node key
#############################
variable "keyname" {
default = "eks-workeernode-key"
}
この状態で terraform apply したところ、十数分後にEKSクラスタ/ノードグループ/Fargateプロファイルの作成が完了した。
最後のFargate Profile -> [Pod selectors]は、Fargate上で実行させたいPodの条件が設定されている。上記の場合Namespaceに[fargate-test]を指定しているため、Kubernetes上のfargate-testネームスペースにおいてFarget Podが実行されるようになる。
ではようやく、Fargate Podを起動してみる。…といきたいが、長くなるので次回に持ち越し。
参考
Getting started with AWS Fargate using Amazon EKS
【AWS】 EKS on Fargate のクラスタを構築してみる
EKS on Fargateの特徴、通常のEKSとの違いは何か?(第1回)
Amazon Fargate for Amazon EKSを試してみた #reinvent
なんとなく「Fargate for EKS」が分かった気になる? ~ いろいろなギモンを調べてみた ~ #reinvent
続きは以下。
EKS FargateクラスタをTerraformで作成する(2)