Mirai Translate TECH BLOG

株式会社みらい翻訳のテックブログ

EKS の aws-loadbalancer-controller のインストールを terraform 化する

こんにちは。みらい翻訳 SRE チームの jeff です。

前回の記事で EKS に aws-loadbalancer-controller を導入するところまで書きました。 今回はこれをインストールしやすいように terraform 化するまでを書きたいと思います。

記事の内容について

今回書くのは aws-loadbalancer-controller 自体の terraform 化と、EKS on Fargate を前提として coredns を Fargate で動かせるようにする設定変更を terraform で行えるようにする部分の2点を書いていきます。

尚、すでに EKS クラスターと VPC は構築している前提になりますのでご了承ください。

参考

今回の件を terraform 化するにあたり EKS の Workshop が非常に参考になりました。

tf-eks-workshop.workshop.aws

よろしければ合わせて参照ください。

早速試してみる

aws-loadbalancer-controller

terraform のコードは以下です。

provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}

resource "helm_release" "aws-load-balancer-controller" {
  name       = "aws-load-balancer-controller"
  depends_on = [null_resource.service-account]

  repository = "https://aws.github.io/eks-charts"
  chart      = "aws-load-balancer-controller"
  namespace  = "kube-system"

  set {
    name  = "clusterName"
    value = var.cluster-name
  }

  set {
    name  = "serviceAccount.create"
    value = false
  }

  set {
    name  = "serviceAccount.name"
    value = "aws-load-balancer-controller"
  }

  set {
    name  = "image.repository"
    value = format("602401143452.dkr.ecr.%s.amazonaws.com/amazon/aws-load-balancer-controller", var.region)
  }

  set {
    name  = "image.tag"
    value = var.image-tag
  }

  set {
    name  = "region"
    value = var.region
  }

  set {
    name  = "vpcId"
    value = var.vpc-id
  }
}

resource "null_resource" "service-account" {
  triggers = {
    always_run = timestamp()
  }

  provisioner "local-exec" {
    on_failure  = fail
    interpreter = ["/bin/bash", "-c"]
    when        = create
    command     = <<EOT
            service_account_iam_role=$(echo ${var.service-account-iam-role})
            echo "$service_account_iam_role"
            ./create_service_account.sh $service_account_iam_role
            echo "done"
        EOT
  }
}

内容について

provider
provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}

内部的に helm でインストールするので provider で helm を指定します。 また、インストールするコンテキストを指定する必要があるため kubernetes の config_path を設定します(ここは環境変数KUBE_CONFIG_PATH を指定しても構いません)。

registry.terraform.io

helm_release リソース

基本的には AWS ドキュメントのインストール方法に書いてある helm でのコマンドインストールで指定する内容を resource の中で指定していきます。

depends_on = [null_resource.service-account]

サービスアカウントを先に作る必要があるため depends_on を指定します。 サービスアカウントについては後述します。

repository = "https://aws.github.io/eks-charts"
chart      = "aws-load-balancer-controller"

インストールするリポジトリと chart を指定します。

  set {
    name  = "clusterName"
    value = var.cluster-name
  }

  set {
    name  = "serviceAccount.create"
    value = false
  }

  set {
    name  = "serviceAccount.name"
    value = "aws-load-balancer-controller"
  }

・・・

helm コマンドでインストールするときに --set で指定するパラメーターを set で指定していきます。

スクリプト実行

上で触れましたが、helm インストールする前に service-account を作成する必要があります(helm リソースの depends_on で実行順を制御しています)。 null_resource でサービスアカウントの作成を行います。

null_resource は、このリソース自体は何もしませんが triggers で任意のタイミングで呼び出すことができて provisoner で処理を行うことができます。

  provisioner "local-exec" {
    on_failure  = fail
    interpreter = ["/bin/bash", "-c"]
    when        = create
    command     = <<EOT
            echo "create service account"
            kubectl apply -f aws-load-balancer-controller-service-account.yaml
            echo "done"
        EOT
  }

今回は apply のタイミングでこのリソースを呼び出して local-exec プロビジョナーから kubectl で service-account を作成しています。

yaml の中身は以下のようになっています。

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: {iam role arn}

これで aws-loadbalancer-controller を terraform から作れるようになりました!

coredns

続いて coredns を Fargate 対応する設定を terraform から行えるようにします。 マニュアルにあるように、 Fargate で coredns の pod を動かせるようにするにはアノテーションの変更が必要になります。それを terraform で行えるようにします(リンクにある Farage プロファイルは作成済みとします)。

docs.aws.amazon.com

コードは以下になります。

resource "null_resource" "delete-ec2-annotation" {
  triggers = {
    always_run = timestamp()
  }

  provisioner "local-exec" {
    on_failure  = fail
    interpreter = ["/bin/bash", "-c"]
    when        = create
    command     = <<EOT
            kubectl patch deployment coredns \
              -n kube-system \
              --type json \
              -p='[{"op": "remove", "path": "/spec/template/metadata/annotations/eks.amazonaws.com~1compute-type"}]'
            echo "done"
        EOT
  }
}

先ほどと同じく null_resource でトリガーを設定してアノテーションを変更するコマンドを実行させます。 これで coredns も起動できるようになったかと思います。

終わりに

今回は手で構築していた部分を terraform 化するところを書きました。 環境構築をコード化すると再現性が出るので安心感と効率化に繋がって良いですね! 今後も IaC 化は進めていきたいと思います。

みらい翻訳ではSREを募集しています

EKS の構築・運用に興味がある方、その他運用改善など SRE に興味がある方を募集しております。 ご興味がおありの方は下記のリンクからご応募・お問い合わせをお待ちしております。

miraitranslate.com