TerraformでAWS EKSを構築する

皆さん、こんにちは。技術開発グループのn-ozawanです。
連日の雨から一転、暑い日が続きますね。観測史上、5月の最高気温は39.5度で、北海道で記録されたそうです。

本題です。
AWSでKubernetesによるコンテナ環境を構築するには、EKSというサービスを利用します。今回はそのEKSをTerraformで構築して、Fargateで動作させるやり方をお話ししたいと思います。

EKSの構築

EKS (Amazon Elastic Kubernetes Service) は、コンテナオーケストレーションであるKubernetesの実行環境です。コンテナの実行環境にはECS (Amazon Elastic Container Service) もありますが、その違いはコンテナのオーケストレーションをAWSで行うのか、Kubernetesで行うのかの差になります。

ロールの作成

初めにEKSに付与するロールを作成します。EKSを構築するには必ずロールを指定する必要があります。

# IAM Role
resource "aws_iam_role" "eks_cluster" {
  name = "eks-role"
  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# Policy
resource "aws_iam_role_policy_attachment" "eks_cluster_AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.eks_cluster.name
}

最初にIAMロールを作成します。ロールはAssumeRoleで、これはEKSが必要な時に、一時的に権限を付与してくれるロール、という意味です。詳細な説明は省きますが、assume_role_policyの内容は、そのような意味だと思ってください。

次に、先ほど作成したロールにAmazonEKSClusterPolicyポリシーをアタッチしてあげています。これによりロールに権限がアタッチされたことになります。

以上でEKSの構築に必要なロールが出来ました。

EKSの構築

続いてEKSを構築しましょう。

variable "public_subnet_ids" {
  description = "Public Subnet のID"
  type = list(string)
}

resource "aws_eks_cluster" "main" {
  name     = "eks-cluster"
  role_arn = aws_iam_role.eks_cluster.arn

  vpc_config {
    subnet_ids = var.public_subnet_ids    # 2つ以上のSubnet IDを指定
  }

  depends_on = [
    aws_iam_role_policy_attachment.eks_cluster_AmazonEKSClusterPolicy
  ]
}

nameはEKSクラスタの名前です。任意につけてOKです。role_arnには先ほど作成したIAM ロールのARNを指定します。

vpc_config.subnet_idsにはEKSクラスタを配置するPublic SubnetのIDを指定します。EKSは2つ以上のAZ (アベイラビリティーゾーン) を跨いで配置する必要があります。var.public_subnet_idsの型はlist(string)であり、2つ以上のSubnet IDを受け取る文字列型の配列です。

depends_onには、ロールにポリシーをアタッチしたらEKSを構築するように指定しています。Terraformに限らず構築する順番は大事ですよね。これにより、ポリシーがアタッチされていないロールでEKSを構築する、という状況を無くします。

Fargate

KubernetesのPodをFargateで動かせるようにします。Fargateはいわゆるサーバーレスで、KubernetesのPodが起動するタイミングで、AWSが自動的に仮想環境を充ててくれます。これにより事前にEC2インスタンスなどの仮想環境を用意する必要がなくなります。

EKSでFargateを有効にするには、Fargate Profileというリソースを作成します。このFargate ProfileにもIAMロールを作成する必要があります。

# Role
resource "aws_iam_role" "eks-fargate-profile" {
  name = "fargate-profile-role"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks-fargate-pods.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# Policy
resource "aws_iam_role_policy_attachment" "eks_cluster_AmazonEKSFargatePodExecutionRolePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy"
  role       = aws_iam_role.eks-fargate-profile.name
}

# variable
variable "private_subnet_ids" {
  description = "Private Subnet のID"
  type = list(string)
}

# Fargate Profile
resource "aws_eks_fargate_profile" "main" {
  cluster_name           = aws_eks_cluster.main.name
  fargate_profile_name   = "main"
  pod_execution_role_arn = aws_iam_role.eks-fargate-profile.arn
  subnet_ids             = var.private_subnet_ids

  selector {
    namespace = "default"
  }

  depends_on = [
    aws_iam_role_policy_attachment.eks_cluster_AmazonEKSFargatePodExecutionRolePolicy,
  ]
}

IAMロールとポリシーのついては先ほどとほぼ同じなので説明は省きます。

aws_eks_fargate_profilecluster_nameには、Fargate Profileを適用するEKSクラスタの名前を指定します。上記の例では先ほど作成したEKSクラスタの名前を指定しています。fargate_profile_nameにはFargate Profileの名前を、pod_execution_role_arnには作成したロールのARNを指定します。

subnet_idsにはFargateが動作するPrivate SubnetのIDを指定します。var.private_subnet_idsの型はlist(string)であり、2つ以上のSubnet IDを受け取る文字列型の配列です。

selector.namespaceにはFargateで動作させるPODを指定します。上記の例ではKubernetesのnamespaceで、defaultに属しているPODは、すべてFargateで動作することを示しています。

おわりに

今日はTerraformでEKSを構築する場合のお話をしました。実はこれだけではまだ足りません。実際に構築してみると、AWSのコンソール画面からは、EKSクラスタは構築されていることが確認できるものの、その中身が見れない状態になっています。それはEKSクラスタ自身が、AWSにログインしているユーザー(rootユーザーも含む)に対して参照を許していないからです。

次回はその辺の解決方法をお話ししたいと思います。ではまた。

Recommendおすすめブログ