0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[雑メモ]Cluster Autoscalerデプロイのterraform化

Posted at

Cluster Autoscalerとは

バージョン、プロバイダー

terraform {
  required_version = "~> 1.2.6"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.24.0"
    }
    kubernetes = {
      version = "~> 2.12.1"
    }
    kubectl = {
      source  = "gavinbunney/kubectl"
      version = "1.14.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

provider "kubernetes" {
  host                   = data.aws_eks_cluster.cluster.endpoint
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
  token                  = data.aws_eks_cluster_auth.cluster.token
}

IAM ポリシーとロールを作成する

data "aws_caller_identity" "current" {}

locals {
  eks_cluster_name             = <EKS クラスター名>
  eks_cluster_oidc_issuer_url  = <EKS OpenID Connect プロバイダー URL>
  this_cluster_oidc_issuer_url = replace(local.eks_cluster_oidc_issuer_url, "https://", "")
}

resource "aws_iam_policy" "cluster_autoscaler" {
  name = "cluster-autoscaler-policy"
  policy = templatefile(
    "./cluster-autoscaler-policy.json",
    {
      cluster_name = local.eks_cluster_name
    }
  )
}

data "aws_iam_policy_document" "assume_role_with_oidc" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    principals {
      type        = "Federated"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.this_cluster_oidc_issuer_url}"]
    }
    condition {
      test     = "StringEquals"
      variable = "${local.this_cluster_oidc_issuer_url}:sub"
      values   = ["system:serviceaccount:kube-system:cluster-autoscaler"]
    }
  }
}

resource "aws_iam_role" "cluster_autoscaler" {
  name               = "cluster-autoscaler-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role_with_oidc.json
}

resource "aws_iam_role_policy_attachment" "cluster_autoscaler" {
  role       = aws_iam_role.cluster_autoscaler.name
  policy_arn = aws_iam_policy.cluster_autoscaler.arn
}

cluster-autoscaler-policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/k8s.io/cluster-autoscaler/${cluster_name}": "owned"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeAutoScalingGroups",
                "ec2:DescribeLaunchTemplateVersions",
                "autoscaling:DescribeTags",
                "autoscaling:DescribeLaunchConfigurations"
            ],
            "Resource": "*"
        }
    ]
}

Cluster Autoscalerのデプロイ

data "aws_eks_cluster" "cluster" {
  name = local.eks_cluster_name
}

data "aws_eks_cluster_auth" "cluster" {
  name = local.eks_cluster_name
}

data "kubectl_path_documents" "cluster_autoscaler_manifest" {
  pattern = "./cluster-autoscaler-autodiscover.yaml"
  vars = {
    cluster_name = local.eks_cluster_name
  }
}

resource "kubectl_manifest" "cluster_autoscaler" {
  count     = length(data.kubectl_path_documents.cluster_autoscaler_manifest.documents)
  yaml_body = element(data.kubectl_path_documents.cluster_autoscaler_manifest.documents, count.index)
}

resource "null_resource" "annotate_serviceaccount_cluster_autoscaler" {
  depends_on = [kubectl_manifest.cluster_autoscaler]

  provisioner "local-exec" {
    command = "kubectl annotate serviceaccount cluster-autoscaler -n kube-system eks.amazonaws.com/role-arn=${aws_iam_role.cluster_autoscaler.arn}"
  }
}

resource "null_resource" "patch_deployment_cluster_autoscaler" {
  depends_on = [kubectl_manifest.cluster_autoscaler]

  provisioner "local-exec" {
    command = "kubectl patch deployment cluster-autoscaler -n kube-system -p '{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"cluster-autoscaler.kubernetes.io/safe-to-evict\": \"false\"}}}}}'"
  }
}

resource "null_resource" "set_image_deployment_cluster_autoscaler" {
  depends_on = [kubectl_manifest.cluster_autoscaler]

  provisioner "local-exec" {
    command = "kubectl set image deployment cluster-autoscaler -n kube-system cluster-autoscaler=k8s.gcr.io/autoscaling/cluster-autoscaler:v1.21.1"
  }
}

cluster-autoscaler-autodiscover.yaml

以下URLから取得。 
https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

一部定義を変更。

            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME>

            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/${cluster_name}
            - --balance-similar-node-groups
            - --skip-nodes-with-system-pods=false

参考にしたサイト

https://github.com/gavinbunney/terraform-provider-kubectl/issues/52
https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/data-sources/kubectl_path_documents

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?