TerraformのEKS published moduleを使ってEKSクラスターを作成する
今回はTerraform Registryにある以下Published Moduleを使ってEKSクラスターを作成したいと思います。
Terraformとprovidersの設定
terraform { required_version = "= 0.14.7" required_providers { aws = { source = "hashicorp/aws" version = "3.30.0" } } } provider "aws" { region = "ap-northeast-1" }
Terraform version 0.13以降の書き方ですね。
VPC作成
eksctlはクラスターを稼働させるVPCまで併せて作成してくれました。が、このeksモジュールはそこまではやってくれず、引数で既存VPCの情報を渡す必要があるようです。というわけで先にVPCを作成します。
以下のTerraform RegistryにあるVPCのPublished Moduleを利用します。
data "aws_availability_zones" "available" { state = "available" } module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "2.77.0" name = "eks-module-test-vpc" cidr = "10.0.0.0/16" azs = data.aws_availability_zones.available.names private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] enable_nat_gateway = true }
以下リソースが作成されます。
$ terraform state list module.vpc.aws_eip.nat[0] module.vpc.aws_eip.nat[1] module.vpc.aws_eip.nat[2] module.vpc.aws_internet_gateway.this[0] module.vpc.aws_nat_gateway.this[0] module.vpc.aws_nat_gateway.this[1] module.vpc.aws_nat_gateway.this[2] module.vpc.aws_route.private_nat_gateway[0] module.vpc.aws_route.private_nat_gateway[1] module.vpc.aws_route.private_nat_gateway[2] module.vpc.aws_route.public_internet_gateway[0] module.vpc.aws_route_table.private[0] module.vpc.aws_route_table.private[1] module.vpc.aws_route_table.private[2] module.vpc.aws_route_table.public[0] module.vpc.aws_route_table_association.private[0] module.vpc.aws_route_table_association.private[1] module.vpc.aws_route_table_association.private[2] module.vpc.aws_route_table_association.public[0] module.vpc.aws_route_table_association.public[1] module.vpc.aws_route_table_association.public[2] module.vpc.aws_subnet.private[0] module.vpc.aws_subnet.private[1] module.vpc.aws_subnet.private[2] module.vpc.aws_subnet.public[0] module.vpc.aws_subnet.public[1] module.vpc.aws_subnet.public[2] module.vpc.aws_vpc.this[0]
Local Moduleを作る
後の検証で使いたいので、EKSクラスターを作成する部分はChild Module化します。そのModuleの中で前述のEKSのPublished Moduleを使いたいと思います。
$ tree . (略) ├── modules │ └── k8s_cluster │ ├── eks.tf │ ├── providers.tf │ ├── target_group.tf │ └── variables.tf (略)
providers
provider "kubernetes" { host = data.aws_eks_cluster.cluster.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) exec { api_version = "client.authentication.k8s.io/v1alpha1" command = "aws" args = [ "eks", "get-token", "--cluster-name", data.aws_eks_cluster.cluster.name ] } } data "aws_eks_cluster" "cluster" { name = module.main.cluster_id }
EKS published moduleが必要とするprividerには、kubernetes providerも含まれます。作成したEKSクラスター内にaws-auth ConfigMapリソースを作成する際に使われます。EKSクラスターへの接続情報が必要ですので、その情報をkuberetes providerのブロックに記述しています。記述内容は以下を参考にしました。
variables
variable "cluster_name" { type = string } variable "k8s_version" { type = string } variable "vpc_id" { type = string } variable "subnet_ids" { type = list(string) }
eks
module "main" { source = "terraform-aws-modules/eks/aws" version = "14.0.0" cluster_name = var.cluster_name cluster_version = var.k8s_version subnets = var.subnet_ids vpc_id = var.vpc_id worker_groups = [{ root_volume_type = "gp2" target_group_arns = [aws_alb_target_group.tg.arn] }] }
- workerのroot volume typeのデフォルト値はgp3です。以下エラーが出たためgp2に変更しています。
Worker Node GroupのAutoScaling Groupはこの書き方だと起動設定から作成されるのですが、どうやら起動設定だと現在root_volume_typeにgp3を指定することができないようです。
Error: Error creating launch configuration: ValidationError: gp3 is invalid. Valid volume types are standard, io1, gp2, st1 and sc1.
- Worker Node GroupのAutoScaling Groupに紐づくTarget Groupを指定しています。こちらは今後の検証で利用する予定です。
target group
前述のとおりWorker Node GroupのAutoScaling Groupに紐づくTarget Groupです。
resource "aws_alb_target_group" "tg" { name = "${var.cluster_name}-tg" port = 30080 protocol = "HTTP" vpc_id = var.vpc_id }
確認
ここまでのコードの状態でterraform init
してterraform apply
します。
以下リソースが作成できました。
$ terraform state list data.aws_availability_zones.available module.blue.data.aws_eks_cluster.cluster module.blue.aws_alb_target_group.tg module.vpc.aws_eip.nat[0] module.vpc.aws_eip.nat[1] module.vpc.aws_eip.nat[2] module.vpc.aws_internet_gateway.this[0] module.vpc.aws_nat_gateway.this[0] module.vpc.aws_nat_gateway.this[1] module.vpc.aws_nat_gateway.this[2] module.vpc.aws_route.private_nat_gateway[0] module.vpc.aws_route.private_nat_gateway[1] module.vpc.aws_route.private_nat_gateway[2] module.vpc.aws_route.public_internet_gateway[0] module.vpc.aws_route_table.private[0] module.vpc.aws_route_table.private[1] module.vpc.aws_route_table.private[2] module.vpc.aws_route_table.public[0] module.vpc.aws_route_table_association.private[0] module.vpc.aws_route_table_association.private[1] module.vpc.aws_route_table_association.private[2] module.vpc.aws_route_table_association.public[0] module.vpc.aws_route_table_association.public[1] module.vpc.aws_route_table_association.public[2] module.vpc.aws_subnet.private[0] module.vpc.aws_subnet.private[1] module.vpc.aws_subnet.private[2] module.vpc.aws_subnet.public[0] module.vpc.aws_subnet.public[1] module.vpc.aws_subnet.public[2] module.vpc.aws_vpc.this[0] module.blue.module.main.data.aws_ami.eks_worker module.blue.module.main.data.aws_ami.eks_worker_windows module.blue.module.main.data.aws_caller_identity.current module.blue.module.main.data.aws_iam_policy_document.cluster_assume_role_policy module.blue.module.main.data.aws_iam_policy_document.cluster_elb_sl_role_creation[0] module.blue.module.main.data.aws_iam_policy_document.workers_assume_role_policy module.blue.module.main.data.aws_partition.current module.blue.module.main.data.template_file.userdata[0] module.blue.module.main.aws_autoscaling_group.workers[0] module.blue.module.main.aws_eks_cluster.this[0] module.blue.module.main.aws_iam_instance_profile.workers[0] module.blue.module.main.aws_iam_policy.cluster_elb_sl_role_creation[0] module.blue.module.main.aws_iam_role.cluster[0] module.blue.module.main.aws_iam_role.workers[0] module.blue.module.main.aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy[0] module.blue.module.main.aws_iam_role_policy_attachment.cluster_AmazonEKSServicePolicy[0] module.blue.module.main.aws_iam_role_policy_attachment.cluster_AmazonEKSVPCResourceControllerPolicy[0] module.blue.module.main.aws_iam_role_policy_attachment.cluster_elb_sl_role_creation[0] module.blue.module.main.aws_iam_role_policy_attachment.workers_AmazonEC2ContainerRegistryReadOnly[0] module.blue.module.main.aws_iam_role_policy_attachment.workers_AmazonEKSWorkerNodePolicy[0] module.blue.module.main.aws_iam_role_policy_attachment.workers_AmazonEKS_CNI_Policy[0] module.blue.module.main.aws_launch_configuration.workers[0] module.blue.module.main.aws_security_group.cluster[0] module.blue.module.main.aws_security_group.workers[0] module.blue.module.main.aws_security_group_rule.cluster_egress_internet[0] module.blue.module.main.aws_security_group_rule.cluster_https_worker_ingress[0] module.blue.module.main.aws_security_group_rule.workers_egress_internet[0] module.blue.module.main.aws_security_group_rule.workers_ingress_cluster[0] module.blue.module.main.aws_security_group_rule.workers_ingress_cluster_https[0] module.blue.module.main.aws_security_group_rule.workers_ingress_self[0] module.blue.module.main.kubernetes_config_map.aws_auth[0] module.blue.module.main.local_file.kubeconfig[0] module.blue.module.main.null_resource.wait_for_cluster[0] module.blue.module.main.random_pet.workers[0]
クラスター内リソースも確認します。
このモジュールは引数write_kubeconfig
をtrue(デフォルト値)にすればコンテキストファイルを作成してくれますが、ちょっと扱いづらいので、別途AWS CLIを使って書きます。
$ aws eks update-kubeconfig --name blue-with-module Updated context arn:aws:eks:ap-northeast-1:123456789012:cluster/blue-with-module in /Users/kazue.masaki/.kube/config $ kubectl config use-context arn:aws:eks:ap-northeast-1:123456789012:cluster/blue-with-module Switched to context "arn:aws:eks:ap-northeast-1:123456789012:cluster/blue-with-module".
クラスター内リソースも確認できました。
$ kubectl get all -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/aws-node-54h7s 1/1 Running 0 30h kube-system pod/coredns-59847d77c8-n9gb6 1/1 Running 0 30h kube-system pod/coredns-59847d77c8-p6dzd 1/1 Running 0 30h kube-system pod/kube-proxy-xdrmg 1/1 Running 0 30h NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 30h kube-system service/kube-dns ClusterIP 172.20.0.10 <none> 53/UDP,53/TCP 30h NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/aws-node 1 1 1 1 1 <none> 30h kube-system daemonset.apps/kube-proxy 1 1 1 1 1 <none> 30h NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/coredns 2/2 2 2 30h NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/coredns-59847d77c8 2 2 2 30h
起動設定→起動テンプレート
前述のとおり、Worker Node GroupのAutoScaling Groupは起動設定から作成されました。これを起動テンプレートからに変えたいと思います。やり方は簡単で、worker_groups
をworker_groups_launch_template
に変えるだけです。
module "main" { source = "terraform-aws-modules/eks/aws" version = "14.0.0" cluster_name = var.cluster_name cluster_version = var.k8s_version subnets = var.subnet_ids vpc_id = var.vpc_id - worker_groups = [{ + worker_groups_launch_template = [{ root_volume_type = "gp2" target_group_arns = [aws_alb_target_group.tg.arn] }] }
起動テンプレートだとroot_volume_typeにgp3を使うこともできます。
module "main" { source = "terraform-aws-modules/eks/aws" version = "14.0.0" cluster_name = var.cluster_name cluster_version = var.k8s_version subnets = var.subnet_ids vpc_id = var.vpc_id worker_groups_launch_template = [{ - root_volume_type = "gp2" # デフォルトのgp3を使う target_group_arns = [aws_alb_target_group.tg.arn] }] }
セルフマネージド型ノード → マネージド型ノードグループ
worker_groups
及びworker_groups_launch_template
はセルフマネージド型ノードのプロビジョニングに使われるものでした。今回は特にセルフマネージド型ノードにする必要性がなかったので、マネージド型ノードグループに変更します。
node_groups
引数を使います。使い方詳細は以下ページにあります。
module "main" { source = "terraform-aws-modules/eks/aws" version = "14.0.0" cluster_name = var.cluster_name cluster_version = var.k8s_version subnets = var.subnet_ids vpc_id = var.vpc_id - worker_groups_launch_template = [{ - target_group_arns = [aws_alb_target_group.tg.arn] - }] + node_groups = { + example = { + target_group_arns = [aws_alb_target_group.tg.arn] + subnets = var.private_subnet_ids + } + } }
variable "cluster_name" { type = string } variable "k8s_version" { type = string } variable "vpc_id" { type = string } variable "subnet_ids" { type = list(string) } +variable "private_subnet_ids" { + type = list(string) +}
module "blue" { source = "./modules/k8s_cluster" cluster_name = "blue-with-module" k8s_version = "1.19" subnet_ids = concat(module.vpc.private_subnets, module.vpc.public_subnets) + private_subnet_ids = module.vpc.private_subnets vpc_id = module.vpc.vpc_id }