TerraformでEKSを作成する

Terraform で EKS を作成してみたのでメモとして残しておきます。 サンプルは GitHub に置いてます。README 通りに進めればデプロイできます。不備があれば Issue や PR もらえると喜びます。

github.com

なぜeksctlじゃないのか

github.com

ざっと理由を挙げると以下です。

  • EKS Cluster に関連しない AWS リソースの管理が複雑となる
    • EKS Cluster 群は eksctl で、それ以外はマネコンや AWS CLI、Terraform とかとなると運用辛そう
  • 細かいパラメータの指定ができない
    • Security Group のルールとか Launch Templete のパラメータとか

誤っているとかあればブコメTwitter で教えてください。 念の為に書いておくと、僕は eksctl を dis るつもりは全く無く、なんなら今でも検証用途でサクッと EKS Cluster 作りたい時は eksctl でやっています。 プロダクションで eksctl 使ってるよって人がいればどういう運用をしているのか聞いてみたいです。

Managed Node Groupを利用しない

Managed Node Group は便利ですが、様々な制約があります。( 2020/06/07 現在

docs.aws.amazon.com

全ては網羅していませんが、代表的なものを挙げると以下です。

  • UserData がカスタムできない 1
  • Spot Instance が利用できない 2
  • Launch Template が指定できない 3

特に UserData がカスタムできない点が痛いです。Docker や kubelet の Config を修正することができないほか、 kubelet を起動する際に --register-with-taints オプションで Taints を割り当てることもできません。 Unmanaged Node Group の場合は UserData で bootstrap.sh の引数として --register-with-taints を渡すことが可能です。

その他の Issue については aws/containers-roadmap に挙がっていますので、これ欲しい!という機能があれば Issue を立てるか既存の Issue に +1 しましょう!

工夫したところとか

template_fileData Sourceの利用

Terraform の template_file Data Source を利用して Woker node の UserData を指定しました。

www.terraform.io

Worker node を作成した EKS Cluster に参加させる際に /etc/eks/bootstrap.sh の引数で EKS Cluster 名を指定する必要があり、そこで template_file を利用することで、ShellScript に EKS Cluster 名をハードコードせずとも動的に指定することが可能です。便利。

EKS最適化AMIのAMI IDをSSM Parameter Storeから取得

EKS 最適化 AMI の AMI ID は SSM Parameter Store に存在します。

docs.aws.amazon.com

以下の様に Data Source で SSM Parameter Store の情報を取得し、value を利用することが可能です。便利。

data "aws_ssm_parameter" "eks_optimized_ami_id" {
  name = "/aws/service/eks/optimized-ami/1.16/amazon-linux-2/recommended/image_id"
}

resource "aws_launch_template" "eks_worker_node_template" {
  .
  .
  .
  image_id = data.aws_ssm_parameter.eks_optimized_ami_id.value
  .
  .
  .
}

www.terraform.io

ハマったとことか

殆どドキュメントに記載されている内容です。

docs.aws.amazon.com

Worker nodeが認識されない

$ kubectl get nodes
No resources found in default namespace.

様々な問題が考えられますが、僕の場合は Security Group に問題がありました。 Terraform で Cluster 用の Security Group を作成していましたが、aws_eks_cluster Resource で security_group_ids を指定していなかったことが原因でした。 下記の様に security_group_ids を指定することで、EKS 上では Additional security groups として認識されます。

vpc_config {
  security_group_ids = [ aws_security_group.eks-cluster-sg-01.id ]
  subnet_ids         = [
    aws_subnet.public-a-01.id,
    aws_subnet.public-b-01.id,
    aws_subnet.protected-a-01.id,
    aws_subnet.protected-b-01.id
  ]
}

Additional security groups は EKS Cluster 作成後は更新できないため、注意しましょう。( 僕は Cluster 再作成しました...

aws-auth configMap のデプロイ漏れ

aws-auth configMap のデプロイし忘れで Worker node が認識されませんでした。

docs.aws.amazon.com

API server endpoint accessの設定不備

kubectlなどでローカルマシンから EKS の API server endpoint に対してリクエストを行う場合、接続元 IP アドレスを制限することが可能です。

docs.aws.amazon.com

ドキュメントにも記載されていますが、IP 制限を行う場合は API server endpoint access の設定で Private からも許可する設定を行うか、Worker node がインターネットへ出る時の Public IP も Public access source whitelist に追加する必要があります。つまり、下記の設定だと Worker node と EKS Cluster の Control Plane ( kube-apiserver ) 間の通信ができません。

f:id:enokawaa:20200606185601p:plain

なので僕は下記の様に設定しました。これで Worker node と Control Plane 間の通信が可能となりました。

f:id:enokawaa:20200606190914p:plain

次は

ALB Ingress Controllerについて書こうかと思います。

github.com