仕事でEKS on Fargateの環境に対してManaged Node Groupを追加で作成する必要があってその一環でVPCから作ってみようとなったのでその備忘録でTerraformとeksctlを使用してEKS環境を作成していきます。
筆者のバージョン環境は以下の通りです
MacOS 10.15.4 $ terraform version Terraform v0.12.25 $ eksctl version 0.22.0
事前にAWSアカウントの作成とIAMの作成を実施しておいてください。
自身のプロファイル情報を先に設定しておいて切り替えておいてください
export AWS_PROFILE=<your profile>
VPCの作成
最初にTerraformを使用してVPCを作成していくのですが作成が必要なリソースとしてVPCとNode Groupに割り当てるIAM Roleの作成。
本来はEC2Nodeに対してsshするなどの必要性もありキーペアの管理をなどをする必要が出てくるのですが今回は作成のみなので割愛させていただきます。
今回は test-vpc
という名前でVPCの作成をします
terraformのディレクトリ構造はこのようになっています
terraform └── workspaces ├── accounts │ ├── iam.tf │ ├── providers.tf │ ├── terraform.tfstate │ └── yaml_files │ └── managed_node_group_assume_role_policy.yaml └── networks ├── providers.tf ├── terraform.tfstate ├── variable.tf └── vpc.tf
vpcの作成に必要なリソースはnetworksの配下にあるのでディレクトリをnetworksまで移動しましょう
cd terraform/workspaces/network
VPCの作成ですがTerraform registoryのVPCを使用して作成していきます
コードはこのようにしています
vpc.tf
module "vpc" { source = "terraform-aws-modules/vpc/aws" name = "test-vpc" cidr = var.vpc_cidr azs = var.azs vpc_tags = { "kubernetes.io/cluster/${var.cluster}" = "shared" } #public_subnets public_subnets = var.public_subnet public_subnet_tags = { "kubernetes.io/role/elb" = 1 "kubernetes.io/cluster/${var.cluster}" = "shared" } #pirvate_subent private_subnets = var.private_subnet private_subnet_tags = { "kubernetes.io/role/internal-elb" = 1 "kubernetes.io/cluster/${var.cluster}" = "shared" } enable_nat_gateway = true single_nat_gateway = false one_nat_gateway_per_az = false enable_vpn_gateway = true enable_dns_hostnames = true }
所々 var
を使用していますがこれはvariable.tfを作成して設定します
cidr設計は適当なので実際に実行する際は設計をしっかりおこないましょう。
variable.tf
variable "vpc_cidr" { default = "10.10.0.0/16" } variable "azs" { default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"] } variable "public_subnet" { default = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] } variable "private_subnet" { default = ["10.10.4.0/24", "10.10.5.0/24", "10.10.6.0/24"] } variable "cluster" { default = "test-cluster" }
terraformを実行していきます
terraform init terraform plan
問題なければapplyをしましょう
このリソースの作成は少し時間がかかります
terraform apply Apply complete! Resources: 29 added, 0 changed, 0 destroyed.
AWSのコンソールを確認して作成されているか確認しましょう。
IAM Roleの作成
次にIAM Roleの作成になります
accountsのディレクトリ配下に移動して説明していきます
cd terraform/workspaces/accounts
IAM Roleの作成を行なっていきますManaged Node Groupを作成する際にはワーカーノードのロール以下のポリシーがアタッチされている必要があります
AmazonEKSWorkerNodePolicy AmazonEKS_CNI_Policy AmazonEC2ContainerRegistryReadOnly
iam.tf
resource "aws_iam_role" "eks_managed_node_group" { name = "eks-managed-node-group-role" description = "managed node group iam role" assume_role_policy = jsonencode(yamldecode(file("${path.module}/yaml_files/managed_node_group_assume_role_policy.yaml"))) } resource "aws_iam_role_policy_attachment" "eks_worker_node_policy" { role = aws_iam_role.eks_managed_node_group.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" } resource "aws_iam_role_policy_attachment" "eks_cni_policy" { role = aws_iam_role.eks_managed_node_group.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" } resource "aws_iam_role_policy_attachment" "ec2_container_registry_read_only" { role = aws_iam_role.eks_managed_node_group.name policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" }
IAM Roleのassume roleですがyamlファイルを作成して参照します
Version: "2012-10-17" Statement: - Action: "sts:AssumeRole" Effect: "Allow" Principal: Service: "ec2.amazonaws.com"
これでVPC同様実行していきます
terraform init terraform plan terraform apply
マネジメントコンソール上に eks-managed-node-group-role
というロールができていると思います。
このロールを確認してポリシーがアタッチされているか確認しておきましょう。
これでリソースの準備ができたのでEKSを作成していきましょう。
EKS Clusterの作成
eksctl側のディレクトリ構成はこのようになっています
. ├── eksctl │ ├── cluster.yaml │ ├── fargateprofile.yaml │ └── managed-node-group.yaml
EKSのClusterを作成していきます
cluster.yaml
--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: test-cluster region: ap-northeast-1 version: "1.15" tags: env: test iam: withOIDC: true vpc: subnets: public: ap-northeast-1a: { id: 作成されたsubnetのid } ap-northeast-1c: { id: 作成されたsubnetのid } ap-northeast-1d: { id: 作成されたsubnetのid } private: ap-northeast-1a: { id: 作成されたsubnetのid } ap-northeast-1c: { id: 作成されたsubnetのid } ap-northeast-1d: { id: 作成されたsubnetのid } cloudWatch: clusterLogging: enableTypes: ["*"]
これでeksctlコマンドを使用していきます
eksctl create cluster -f eksctl/cluster.yaml
EKS Clusterの作成はめちゃくちゃ重いです。。。 コーヒーでも飲んでtwitterでもして時間を潰してください
作成されたらManaged Node Groupを作成していきます
managed-node-group.yaml
--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: test-cluster region: ap-northeast-1 version: "1.15" tags: env: test managedNodeGroups: - name: test-managed-ng desiredCapacity: 2 minSize: 2 maxSize: 4 instanceType: t3.large volumeSize: 20 ssh: allow: true privateNetworking: true iam: instanceRoleARN: 作成したIAM Roleを付与
eksctl create nodegroup -f eksctl/managed-node-group.yaml
無事作成されたらFargateも作成しましょう
fargateprofile.yaml
--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: test-cluster region: ap-northeast-1 version: "1.15" tags: env: test fargateProfiles: - name: fp-default selectors: - namespace: default - namespace: kube-system subnets: - プライベートサブネット1aの値 - プライベートサブネット1cの値 - プライベートサブネット1dの値
適用します
eksctl create fargateprofile -f eksctl/fargateprofile.yaml
これでFargateも作成されたと思います。
kubectl get nodeでnodeが作成されているか確認してみましょう。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION fargate-ip-10-10-5-19.ap-northeast-1.compute.internal Ready <none> 40s v1.15.10-eks-094994 fargate-ip-10-10-5-83.ap-northeast-1.compute.internal Ready <none> 51s v1.15.10-eks-094994 ip-10-10-4-18.ap-northeast-1.compute.internal Ready <none> 8m42s v1.15.11-eks-af3caf ip-10-10-5-230.ap-northeast-1.compute.internal Ready <none> 8m45s v1.15.11-eks-af3caf ip-10-10-6-25.ap-northeast-1.compute.internal Ready <none> 8m46s v1.15.11-eks-af3caf
これでFargateとManaged Node Groupの作成ができました。
今回は構築するだけですので用がなければ最後は作成したリソースの削除をしましょう
eksctl delete cluster -f eksctl/cluster.yaml
terraform destroy
これで以上です。 思ったよりも作るだけなら簡単に作成することができました。 実際にはalbのリソースのIRSAの作成なども対象になるのですが今回は割愛します。
実際これらのことはeksctlコマンドで全部作成自体は可能なのですがIaCで管理することによって明示的に確認できるのでメリットはでかいなと思いました。 eksctlでリソースの作成をする際にupdateがリソースの更新ではなくてクラスタ自体のアップデートになってしまうので注意が必要です。
なのでクラスタの設定とNode GroupやFargateを別で管理しておくことによって管理のしやすさが高まるかなあと個人的には思っています。 長くなりましたが見ていただきありがとうございました。
他にこのような方法がいいというものがありましたらご指摘・意見をいただけると嬉しいです。