LoginSignup
7

More than 3 years have passed since last update.

Kubernetesアドオンのインストールを自動化しよう

Last updated at Posted at 2020-12-09

AWS EKS + Kubernetesアドオンのインストールを自動化

image.png

はじめに

今回はKubernetesアドオンのインストールの自動化の取り組みを共有したいと思います。

AWS EKSでしか試してはいないのですが、この基本的な仕組みは他のクラウド(Azure AKSやGCP GKEなど)でも応用はできるかなと思います。

なぜKubernetesアドオンのインストールを自動化するの?

AWS EKSの場合、EKS構築後に必要なアドオンを追加で導入する必要があります。要件にあわせたアドオンを選べるメリットがありますが、別途導入や設定作業を行う必要になります。
また、EKSのIAM Roles for Service Accounts(IRSA)を利用し、Roleとサービスアカウントと連携する設定は、手順が複雑で設定ミスや設定漏れも起こりやすいかと思います。

私の場合、何度も繰返しEKSの構築することがあり、また誰でも同じ環境をいつでも構築できるようにしたいという思いがあって、アドオンの導入も含めたEKSのインストールの自動化に挑戦してきました。

何のツールを使って自動化するか?

自動で構築できるツールはたくさんありますが、私は以下の条件でツールを選びました。

ツールの選定条件

なるべく誰でも使いやすい、また変更しやすいなどのメンテナンス性を重視しました。

  1. 利用するツールの種類をなるべく少なくして、学習コストを低くしたい
  2. どのクラウドプラットフォームでも同じツールで構築できるように統一したい

選定したツール

TerraformとHelmを連携させ、EKS構築だけでなくアドオンの導入までの全てを自動構築します。
helmやkubectlをshellから実行させる方法もありますが、変更時の冪等性を考慮し、この組み合わせだけで完結するように構成しました。

  • Terraform
    • EKSのようなKubernetesのマネージドサービスの部分だけでなく、RDSなどの構築もできる
    • どのクラウドプラットフォームでも共通で使える
  • Helm
    • 多くのアドオンのインストール定義「Chart」が用意されていて、網羅性が高い(全部あるわけではない)
    • Terraformと連携させるとEKS構築も含めて一度に全部自動構築できる

TerraformとHelmを連携されるには

TerraformからHelmを連携させるには、TerraformのHelm Providerを利用します。

Terraform Helm Providerの基本的な利用方法

Kubernetesアドオンを導入するTerraformの定義は以下のような感じです。
これだけ覚えればOKなので理解しやすいと思います。

resource "Helm_release" "(Terraformの定義で管理される名前)" {
  name       = "(Helmで管理される名前)"
  repository = "(Helm リポジトリのURL)"
  chart      = "(Helm Chart名)"
  namespace  = "(導入先のNamespace)"
  version    = "(Helm Chartのバージョン)"

  # 導入パラメーター
  set {
    name  = "(設定項目名)"
    value = "(設定値)"
  }

  set {
    name  = "(設定項目名)"
    value = "(設定値)"
  }
}

Helm Providerを利用するために事前にインストールしておくモジュール

  • Terraform
  • Helmコマンド
  • kubectlコマンド

EKS構築&k8sアドオン導入のサンプル定義

GitHubにサンプル一式を公開しましたので、必要であればこちらも参照してください。

このサンプルでは、VPCとEKSを構築し、その後のKubernetesアドオンの導入までを一気に実行できます。

Helm Providerの設定

Helm ProviderからKubernetesクラスターへ接続する設定方法はいくつかあります。Terraformで構築されたEKS構築とスムーズに連携させるには、構築されたEKSのTerraformの値を直接連携させたほうが楽です。

providers.tf
provider "Helm" {
  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
  }
  version = "~> 1.3.2"
}

k8sアドオンの導入設定をしてみよう

ここでは、Cluster Autoscalerのアドオンを例にして説明を行います。
Cluster Autoscalerはクラウドと連携しNode数の設定値を増減させるためにIAMの権限と連携する必要があります。

(1) Helm Chartを探してみよう

  1. Helm ChartのHubページへいく
    Artifact Hub
    https://artifacthub.io/
    image.png

  2. HubでChartを検索してみる
    「cluster autoscaler」で検索してみると、該当するChartが表示されます。
    image.png

  3. 利用するChartを選ぶ
    今回はORGがKubernetesのChartを選びました。

導入方法や設定パタメータは詳細情報のページに記載されています。
image.png

(2) IAM Roles for Service Accounts(IRSA)の設定

Cluster Autoscalerのアドオンを実行するには、IAM Roleとの連携が必要です。
(IAM Roleとの連携が不要なアドオンの場合は、この手順は不要です。)

この後の説明するためにIRSAの仕組みをおさらいします。

EKS(Kubernetes)からクラウドのリソースを操作するには、クラウドのリソースを操作する権限を与える必要があります。EC2(Node)に権限を与えても動作できますが、その場合EC2(Node)上で稼働するすべてのPodにクラウドリソースを操作する権限を与えることになり、セキュリティ上好ましくありません。
そこで、IAM RoleとKubernetesのサービスアカウントを連携させて、そのサービスアカウントが指定されたPodのみにその権限を与えるようにします。

ざっくりとイメージにすると以下のような感じです。
image.png

IAM Roleとサービスアカウントを連携するには、IAM Roleとアドオンが利用するサービスアカウントの設定値を合わせる必要があります。

IRSA構築の設定

IRSA用のIAM Role構築の定義を簡単に記述する為に、Terraform Moduleとして提供されているものを使用しました。

oidc_fully_qualified_subjectsには、アドオンが使用するサービスアカウントの名前を記述します。
この名称とアドオンが使用するサービスアカウント名は一致させなくてはいけません。

k8saddon_aws_iam_sa_role
module "iam_role_sa_cluster_autoscaler" {
  source                        = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
  version                       = "~> v2.14.0"
  create_role                   = true
  role_name                     = "${module.eks.cluster_id}_cluster-autoscaler"
  provider_url                  = replace(module.eks.cluster_oidc_issuer_url, "https://", "")
  role_policy_arns              = [aws_iam_policy.cluster_autoscaler.arn]
  oidc_fully_qualified_subjects = ["system:serviceaccount:kube-system:cluster-autoscaler-aws-cluster-autoscaler"]
}

resource "aws_iam_policy" "cluster_autoscaler" {
  name_prefix = "${module.eks.cluster_id}_cluster-autoscaler"
  description = "EKS cluster-autoscaler policy for cluster ${module.eks.cluster_id}"
  policy      = file("./policy_json/cluster_autoscaler.json")
}

IAM Roleのポリシーは、Terraform内のjsonファイルに記述して、aws_iam_policyリソースの定義内で読み込ませてに構築を行います。アドオンのバージョンを変更すると、ポリシーの内容も変更になる可能性があるので合わせて変更するよう気をつけておきます。

cluster_autoscaler.json
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "autoscaling:DescribeAutoScalingGroups",
          "autoscaling:DescribeAutoScalingInstances",
          "autoscaling:DescribeLaunchConfigurations",
          "autoscaling:DescribeTags",
          "autoscaling:SetDesiredCapacity",
          "autoscaling:TerminateInstanceInAutoScalingGroup"
        ],
        "Resource": "*"
      }
    ]
}

(3) Helmの記述方法

Helm Chartのインストール

まず最初にHelm Chartを管理しているリポジトリとChartの情報を取得します。
右上の「INSTALL」のボタンを押すと情報が表示されます。

image.png

表示されたインストールコマンドに含まれるリポジトリのURLとChartの名称を取得します。

image.png

Terraform側の定義に反映した完成イメージは以下のようになります。

k8saddon_Helm.tf
resource "helm_release" "cluster-autoscaler" {
  name       = "cluster-autoscaler"
  repository = "https://kubernetes.github.io/autoscaler"
  chart      = "cluster-autoscaler"
  namespace  = "kube-system"
  version    = var.param.k8saddon.cluster_autoscaler.version
  set {
    name  = "autoDiscovery.clusterName"
    value = data.aws_eks_cluster.cluster.id
  }
  set {
    name  = "awsRegion"
    value = var.param.region
  }
  set {
    name  = "rbac.serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = module.iam_role_sa_cluster_autoscaler.this_iam_role_arn
  }
}

setには、アドオンの導入に必要な設定パラメータをセットします。アドオンの説明をみて項目名と値をセットします。

IRSA用の設定追加

また、IRSAと連携させるためには、サービスアカウントのAnnotationへIAM RoleのARNを登録するようにsetの設定を追加する必要があります。

IRSAと連携するサービスアカウントのAnnotationには以下のようにセットします。

Key Value
eks.amazonaws.com/role-arn arn:aws:iam::(アカウントID):role/(Role名)

アドオンの詳細説明にどのようにセットすればよいかが明記されています。
setに記述するnameの表記はアドオンによって異なっていますが、name名や説明をみればおおよそ判断できるとおもいます。

  • Cluster-AutoscalerのValues一覧より抜粋
    image.png

Terraformへの記述方法は以下になります。
valueがObject型になっていますが、以下のようにnameにAnnotationのKeyを連結させた文字列にすればOKです。(Object型の正式な記述方法があると思うのですが、わからなかったのでこの方法で対応しました。)

記述例
  set {
    name  = "rbac.serviceAccountAnnotations.eks\\.amazonaws\\.com/role-arn"
    value = module.iam_role_sa_cluster_autoscaler.this_iam_role_arn
  }

実行してみよう

アドオンの定義をふくめて記述ができたら、実行してみます。
実行終了するまで約15分ほど時間がかかりますが、無事AWS EKSからアドオンの導入までを自動で構築できました。
image.png

IRSAの設定ができているかの確認方法

IAM RoleとサービスアカウントのIRSA連携部分では、それぞれが同じ値になっているかを確認してみましょう。

  • IAM Role側
    image.png

  • サービスアカウント側
    image.png

まとめ

このような方法で、Kubernetesのアドオンのインストールまでを自動化することができ、いつでもすぐに同じEKSの環境を構築できるようになりました。

Helmをつかったアドオンの自動化でいろいろハマったことや注意事項があったので、最後に共有します。

Helmを使った自動化の課題点

  • すべてのアドオンのChartがあるわけではないので、Chartがないアドオンは今まで通り手動での導入が必要になる。
  • 2020年11月にHelmのStableリポジトリが廃止になったため、どのChartが安心して使える”鉄板”なのかがわかりにくくなってしまった。
  • Terraform実行中に「Helmリポジトリを更新しなさい」というエラーが発生することがあり、発生した場合はhelm repo updateを実行してTerraformの再実行が必要になる。

以上になります。
説明不足の点があるかもしれませんが、もし同じようなことを考えている方の参考になれば幸いです。
ありがとうございました。

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
7