この記事はGunosy Advent Calendar 2020の9日目の記事です。
前回の記事は大関さんの「ゼロから始めるEKS事始め(後編)」でした。
EKS関連の内容が続きますが、仕込みじゃありません!
はじめに
広告技術部のjohnmanjiro(@johnmanjiro13)です。普段は広告配信のAPIや管理画面を作っています。
今回は、Launch Templateを使ったManaged Node GroupをTerraform経由で導入した話を紹介します。なかなか詰まる点があったので、参考になれば幸いです。
Managed Node GroupでLaunch Templateを使う
Managed Node GroupはEKSで使用するワーカーノードのプロビジョニングや管理をしてくれます。
リリース当初はLaunch Templateが使えませんでしたが、2020年の8月に使えるようになりました。 これによりユーザーデータ経由でssm-agentをEC2インスタンスに導入することができるなど、かなり便利になりました。
今回はこのLaunch Templateを指定したManaged Node Groupを作成していきます。
Terraformで導入する際の注意点
基本的にはTerraformのドキュメントを読んでいただければ、tfファイルの書き方はだいたいわかると思います。
しかし、実際にterraform applyしてみるとうまくいかなかったということはつきものです。ここでは、Terraformで作成する際の注意点をご紹介します。
いくつかは次のドキュメントに書かれているものと同じ内容です。 docs.aws.amazon.com
Launch Template
Terraformのドキュメントはこちらです。 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template
Launch Templateで指定できないもの
iam_instance_profile
この項目は指定することができません。ノードのIAMはManaged Node Groupのnode_role_arnで指定します。subnet_id (under network_interfaces)
この項目は指定することができません。サブネットはManaged Node Groupのsubnet_idsで指定します。
Launch Templateで指定する必要があるもの
block_device_mappings
ディスクのサイズはLaunch Templateで指定する必要があります。(key_name)
key pairでインスタンスにアクセスする際には必要ですが、ssm-agentを使う場合には不要です。vpc_security_group_ids
セキュリティグループはLaunch Templateで指定する必要があります。余談として、Managed Node Groupはセキュリティグループを一つしか設定できませんが、Launch Templateを使うと複数のセキュリティグループを設定することができます。
User Dataに関する注意点
Launch TemplateにはUser Dataを設定することができます。ただし、このUser DataはEKSが設定するUser Dataとマージして使用されるため、multipart形式で指定する必要があります。
改行などの形式が厳密に決まっているので注意してください。誤った形式のUser Dataが指定された場合、マージされません。
MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="==MYBOUNDARY==" --==MYBOUNDARY== Content-Type: text/x-shellscript; charset="us-ascii" #!/bin/bash set -o xtrace yum install -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm --==MYBOUNDARY==--\
3行目や6行目の改行がない場合はマージされないため、Launch TemplateのUser Dataは反映されません。
また、User Data内でkubeletコマンドを使用することは推奨されていません*1。ラベルをつけたい場合はManaged Node Groupで指定することができます。
Managed Node Group
Terraformのドキュメントはこちらです。 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group
Managed Node Groupで指定できないもの
disk_size
Launch Templateで指定するので、ここでは指定できません。ec2_ssh_key
Launch Templateで指定するので、ここでは指定できません。remote_access_security_group_id
Launch Templateで指定するので、ここでは指定できません。
Managed Node Groupで指定する必要があるもの
node_role_arn
ノードにアタッチするIAMロールを指定します。このロールは、AmazonEKSWorkerNodePolicy
、AmazonEC2ContainerRegistryReadOnly
、AmazonEKS_CNI_Policy
が設定されている必要があります*2。instance profileではなく、通常のロールを指定してください。subnet_ids
Managed Node Groupで使用されるサブネットを指定します。サブネットにはkubernetes.io/cluster/CLUSTER_NAME
タグが付いている必要があります(CLUSTER_NAMEはそれぞれのクラスター名に置き換えてください)*3。
release_versionを指定する際の注意点
release_versionはノードに使用するAMIのバージョンを指定します。指定しておくことで、不意にバージョンアップされることを防ぐことができますが、Managed Node Groupを新規で作成する場合にはその時の最新バージョンしか使用することができません。
labelを指定する際の注意点
Launch Templateの注意点で記載した通り、Managed Node Groupではノードに対してkubernetesのラベルをつけることができますが、kubernetes.io/
を含むラベルは使用することができません。
実際のコード
ここまでで紹介した注意点に気をつけつつ、書いたコードが以下です。IAMなどのコードは省略しています。
locals { node_group_userdata = <<USERDATA MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="==MYBOUNDARY==" --==MYBOUNDARY== Content-Type: text/x-shellscript; charset="us-ascii" #!/bin/bash set -o xtrace yum install -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm --==MYBOUNDARY==--\ USERDATA } resource "aws_launch_template" "eks_node_group" { name_prefix = "eks-node-group" user_data = base64encode(local.node_group_userdata) vpc_security_group_ids = compact([ # security group ids ]) instance_type = "c5.large" } resource "aws_eks_node_group" "eks_node_group" { cluster_name = "eks-cluster" node_group_name = "node_group" node_role_arn = # node role arn subnet_ids = # subnet ids ami_type = "AL2_x86_64" release_version = "1.17.12-20201126" version = "1.7" launch_template { id = aws_launch_template.eks_node_group.id version = aws_launch_template.eks_node_group.latest_version } scaling_config { desired_size = 2 max_size = 20 min_size = 2 } labels = { node_type = "stateful" } depends_on = [aws_launch_template.eks_node_group] }
さいごに
今回はTerraformでLaunch Templateを使ったManaged Node Groupを導入する例をご紹介しました。記載した内容は試行錯誤を繰り返した結果ですが、Terraformで詰まった場合にはaws-sdk-goのコードを読むと細かい仕様が書かれていたりして、解決の糸口になります*4。
少しでも参考になったなら幸いです。
次回はShohei Hidaさんです!お楽しみに!
*1:https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-user-data
*2:https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html#create-worker-node-role
*3:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#subnet_ids
*4:aws providerの裏側ではaws-sdk-goが呼ばれています