GeekFactory

int128.hatenablog.com

EKSのGitLab RunnerでTerraformをCI/CDする

AWS EKSでGitLab Runnerを実行して,GitLab RunnerでTerraformを実行する方法を紹介します.

以下の流れで作業を行います.

  1. EKS workerにAssumeRoleのIAMポリシーをアタッチする.
  2. stable/kube2iamをデプロイする.
  3. GitLab RunnerのIAMロールを作成する.
  4. GitLab Runner Helm Chartをデプロイする.
  5. リポジトリ.gitlab-ci.yml を追加して,ビルドを実行する.

ここでは以下のツールを利用している前提とします.

  • GitLab
  • Terraform
  • helmfile

EKS workerのIAMポリシーの追加

kube2iamがAssumeRoleを実行できるように,EKS workerインスタンスにIAMポリシーをアタッチします. Terraformのeksモジュールを利用している場合は以下を追加します.

resource "aws_iam_policy" "worker_kube2iam" {
  name        = "hello-eks-worker-kube2iam"
  description = "kube2iam on EKS workers"
  policy      = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "sts:AssumeRole"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

module "eks" {
  workers_additional_policies = [
    aws_iam_policy.worker_kube2iam.arn
  ]
}

kube2iamのデプロイ

stable/kube2iamKubernetesにデプロイします. helmfileを利用している場合は以下を追加します.

releases:
  # https://github.com/helm/charts/tree/master/stable/kube2iam
  - name: kube2iam
    namespace: kube-system
    chart: stable/kube2iam
    values:
      - host:
          iptables: true
          interface: eni+
        extraArgs:
          # https://github.com/jtblin/kube2iam#base-arn-auto-discovery
          auto-discover-base-arn: ""
        rbac:
          create: true

GitLab RunnerのIAMロールの作成

GitLab RunnerのPodにアタッチするIAMロールを作成します. ここではコードを簡単にするためPowerUserAccessポリシーをアタッチしていますが,実際にはGitLab Runner専用のIAMポリシーを書く方がよいでしょう.

data "aws_iam_policy_document" "kube2iam_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
    principals {
      type        = "AWS"
      identifiers = [module.eks.worker_iam_role_arn]
    }
  }
}

resource "aws_iam_role" "gitlab_runner_terraform" {
  name               = "hello-gitlab-runner-terraform"
  assume_role_policy = data.aws_iam_policy_document.kube2iam_assume_role.json
}

resource "aws_iam_role_policy_attachment" "gitlab_runner_terraform" {
  role       = aws_iam_role.gitlab_runner_terraform.name
  policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess"
}

kube2iamが正常に動作しているか,以下のコマンドを実行して確認します.

kubectl run aws -i --rm --image fstab/aws-cli --restart=Never \
  --overrides '{"metadata":{"annotations":{"iam.amazonaws.com/role":"hello-gitlab-runner-terraform"}}}' \
  -- /home/aws/aws/env/bin/aws s3 ls

S3バケットの一覧が表示されたら成功です.権限不足もしくはクレデンシャルが見つからないというエラーが表示された場合はkube2iamのログを確認してください.

GitLab Runnerのデプロイ

GitLab Runner Helm Chartをデプロイします.

releases:
  - name: gitlab-runner-terraform
    namespace: gitlab
    chart: gitlab/gitlab-runner
    values:
      - gitlabUrl: {{ .Environment.Values.gitlabURL }}
        runnerRegistrationToken: {{ .Environment.Values.gitlabRunnerRegistrationToken }}
        rbac:
          create: true
        runners:
          tags: "terraform"
          podAnnotations:
            # Switch to the role for Terraform
            iam.amazonaws.com/role: hello-gitlab-runner-terraform

上記ではterraformというタグが付いているビルドのみ受け入れるように設定しています.

.gitlab-ci.ymlの追加

リポジトリ.gitlab-ci.yml を追加して,ビルドを実行します.

image:
  name: hashicorp/terraform:light
  entrypoint:
    - /usr/bin/env

cache:
  paths:
    - .terraform

before_script:
  - terraform --version
  - terraform init

stages:
  - validate
  - build
  - deploy

validate:
  stage: validate
  script:
    - terraform validate
  tags:
    - terraform

plan:
  stage: build
  script:
    - terraform plan -out=plan.tfplan
  artifacts:
    name: plan
    paths:
      - plan.tfplan
  tags:
    - terraform

apply:
  stage: deploy
  script:
    - terraform apply -input=false plan.tfplan
  dependencies:
    - plan
  when: manual
  only:
    - master
  tags:
    - terraform