EKSを terraform に移行、作成した際に苦労した話

Terraformのあれこれで苦労した話

みなさんこんにちは、サイオステクノロジーの南です。私は案件で既存のEKSを terraform 側で全て管理できるように移行する作業を行っていたのですが、そこでつまづいたことが多々ありました。そこで今回は、移行するにあたって苦労した点や、解決方法などを書いていきたいと思います

リソース量が他クラウドk8sサービスよりも多い

以下の表ではterraformで管理しているk8sとその周辺リソースの数を、各クラウドごとでまとめたものです。

EKS

AKS

GKE

リソース数

98

58

61

見てもらうとAWS(EKS)が圧倒的に多いことがわかりますね・・

なぜ多くなるかというとEKS(AWS)が持つ以下のリソースをterraformで定義してあげる必要があるからです。

  • IAM
  • サブネット、IPアドレス、iptable などのネットワークに関連するもの

IAM

AWSにはIAMをアタッチすることで、リソースを動かすうえで必要な権限を付与することができます。

これらを運用することでリソースやユーザーがどれくらいアクセスできるかの範囲を調節が可能となりますが、それらの分だけIAMをterraformで定義するためにリソース数が増大しています。

IAMが付与される対象は以下のようなものになります。

EKS cluster

EKS node

Cloud watch

EBS-CSI-driver(eks addon)

auto scaler

具体的なものとして以下にterraformリソースを挙げています

resource "aws_iam_role" "role" {
  name               = "test-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data "aws_iam_policy_document" "policy" {
  statement {
    effect    = "Allow"
    actions   = ["ec2:Describe*"]
    resources = ["*"]
  }
}

resource "aws_iam_policy" "policy" {
  name        = "test-policy"
  description = "A test policy"
  policy      = data.aws_iam_policy_document.policy.json
}

resource "aws_iam_role_policy_attachment" "test-attach" {
  role       = aws_iam_role.role.name
  policy_arn = aws_iam_policy.policy.arn
}

これはEC2に関するIAMですが見ての通りIAMロールとポリシー、IAMロールとポリシーを紐づけるアタッチメントで3つ必要になっています。

今回IAMが付与されていたのは上の5種類なので、合計で15個もリソースが増えることになります。

ネットワーク関連(サブネット、IPアドレスなど)

他k8s(AKS,GKE)などでは基本的にkubernetes周りのresourceをterraformに定義をしてあげるだけで、ネットワーク関連のものまで自動的に作成してくれます。

しかし、EKSでは別で、ネットワークのものもまとめて定義をしないと作成されない仕組みとなっています。

この部分だけでも20個を上回るため、やはりリソース増大に大きく影響している部分と言えます。

EBS CSIドライバーのアドオンを導入しないと、PodのPersistent Volumeがデプロイされない

Persistent Volume(PV)のマウントが必要なサービスをデプロイする際、podがずっとrunningにならないという問題がありました。

今回PVとしてはEBSを使用していたのですが、調べてみるとEBS CSIドライバーを導入しないとEBSをマウントすることができないとAWSが言っており、これに従って解決することができました。

ebs-csi-driverはAWSのストレージであるEBSをEKSで使えるようにするドライバーで、現在はAWS addonの一つであり、terraformのresourceとして定義することができます。

具体的なresourceとしては以下を定義しています。

resource "aws_eks_addon" "ebs_csi_driver" {
  cluster_name = aws_eks_cluster.my_cluster.name
  addon_name   = "ebs-csi-driver"
  addon_version = "1.3.0"  # ご利用のバージョンに適切な値を指定してください
  }

resource "aws_iam_role" "ebs_csi_driver_role" {
  name = "ebs-csi-driver-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "eks.amazonaws.com"
        }
      }
    ]
  })
}

resource "aws_iam_policy" "ebs_csi_driver_policy" {
  name        = "ebs-csi-driver-policy"
  description = "IAM policy for EBS CSI Driver"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ec2:AttachVolume",
          "ec2:CreateSnapshot",
          "ec2:CreateTags",
          "ec2:CreateVolume",
          "ec2:DeleteSnapshot",
          "ec2:DeleteTags",
          "ec2:DeleteVolume",
          "ec2:DescribeInstances",
          "ec2:DescribeSnapshots",
          "ec2:DescribeTags",
          "ec2:DescribeVolumes",
          "ec2:DetachVolume",
          "ec2:ModifyVolume",
          "ec2:Wait",
        ]
        Effect   = "Allow"
        Resource = "*"
      }
    ]
  })
}
resource "aws_iam_role_policy_attachment" "ebs_csi_driver_attachment" {
  policy_arn = aws_iam_policy.ebs_csi_driver_policy.arn
  role       = aws_iam_role.ebs_csi_driver_role.name
}

これらを定義することで解決しました。

特にEBSをpodのストレージとして使いたい方は要注意です。

terraform destroy時にサブネットや、vpcが削除できない

サブネットが削除できない

terraformでEKSを作成、もしくは移行を行ってから削除をする際、EKSのpublic subnetが削除されずにdestroyがエラーになってしまうことがよくありました。

これは、subnetに紐づいているload balancerが削除できていないために起こったエラーであり、terraform側もこれをHashiCorp社のGithubでissueとして報告しています。

サブネット削除問題に関しては、terraformコミッターの作ったmoduleを用いてロードバランサーを削除することで解決しました。

以下にURLとコードを記載します。

terraform-kubernetes-delete-eni

module "remove_eni" {
    source = "github.com/webdog/terraform-kubernetes-delete-eni"
    vpc_id = "your_vpc_id"
    region = "us-east-1"
}

vpcが削除できない

vpcもサブネット同様にdestroy時に削除ができなかったリソースでした。

こちらは、vpcに紐づいている複数のセキュリティグループのインバウンドルールがお互いを依存していることが原因であり、以下を実施することで解決しました。

  • 対象のセキュリティグループをimportする
  • 以下のコードのようにルールを空白にする
resource "aws_security_group" "example_sg" {
  vpc_id = aws_vpc.cluster_vpc.id
  ingress{
    description      = "Allow nodes to communicate with each other (all ports)"
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = []
    ipv6_cidr_blocks = []
  }
}
  • terraform destroyを行って対象リソースが消せることを確認する

まとめ

今回はEKSをterraformに移行、ないし作成でつまづいた点、解決方法などをお伝えしました。また何かこれらに関するネタがあれば書き出していこうと思います。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です