Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

TerraformでLaunch Templateを使ったManaged Node Groupを導入する

この記事はGunosy Advent Calendar 2020の9日目の記事です。

前回の記事は大関さんの「ゼロから始めるEKS事始め(後編)」でした。

EKS関連の内容が続きますが、仕込みじゃありません!

tech.gunosy.io

はじめに

広告技術部の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インスタンスに導入することができるなど、かなり便利になりました。

aws.amazon.com

今回はこの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ロールを指定します。このロールは、AmazonEKSWorkerNodePolicyAmazonEC2ContainerRegistryReadOnlyAmazonEKS_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さんです!お楽しみに!