みなさんこんにちは、サイオステクノロジーの南です。私は案件で既存の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に移行、ないし作成でつまづいた点、解決方法などをお伝えしました。また何かこれらに関するネタがあれば書き出していこうと思います。