Kustomize + CodePipeline + CodeBuildでEKSに継続的デプロイしてみた

118件のシェア(ちょっぴり話題の記事)

こんにちは、かたいなかです。

Kubernetesを仕事で触っていて、CodePipeline/CodeBuildとKustomizeを組み合わせての継続的デプロイを検証する機会があったので備忘録として記事にまとめてみます。

Kustomizeとは

KustomizeはkubernetesのYAMLファイルをパッケージングするツールです。ベースの構成をもとにSTG/PRDなどの環境ごとに変えたい設定などを上書きすることができます。Kustomizeで生成されたYAMLを、kubectl applyする形で使用します。将来的にkubectlへの統合が前提に開発されているそうです。

今回はこのKustomizeをCodePipeline/CodeBuildと組み合わせて使用し、継続的デプロイできるようにしていきます。

パイプラインの構築

今回は以下の図のようなパイプラインを組んでいきます。

前提条件

以下の状態を前提に進めていきます

  • EKSのクラスタおよびワーカーノードがすでに作成されていること

  • デプロイの対象となるリポジトリには以下のようにベースの設定と環境ごとのオーバレイが用意された状態となっていること

    .
      base/
        kustomization.yaml
        deployment.yaml
        ...(省略)...
      overlays/
        production/
          kustmization.yaml
          ...(省略)...
        staging/
          kustomization.yaml
          ...(省略)...
    

    詳細はこちらの今回の記事のコードをご覧ください。 リポジトリはKustomizeのSpringBootのサンプルを少し修正したものです。

CodeBuild環境用イメージの準備

以下のようなDockerfileでCodeBuild環境用のイメージを作成します。

FROM alpine:3.8

# install AWS CLI
ENV AWS_CLI_VERSION 1.16.26
RUN apk --update --no-cache add \
        python \
        py-pip \
        groff \
        less \
        mailcap \
        && \
    pip install --upgrade awscli==${AWS_CLI_VERSION} && \
    apk -v --purge del py-pip

# install kubectl
ENV KUBECTL_VERSION 1.11.3
RUN wget -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
    chmod +x /usr/local/bin/kubectl

# install Kustomize
ENV KUSTOMIZE_VERSION 1.0.8
RUN wget -O /usr/local/bin/kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_linux_amd64 && \
    chmod +x /usr/local/bin/kustomize

# install AWS IAM Authenticator
ENV AWS_IAM_AUTHENTICATOR_RELEASE_DATE 2018-07-26
ENV AWS_IAM_AUTHENTICATOR_VERSION 1.10.3
RUN wget -O /usr/local/bin/aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERSION}/${AWS_IAM_AUTHENTICATOR_RELEASE_DATE}/bin/linux/amd64/aws-iam-authenticator && \
    chmod +x /usr/local/bin/aws-iam-authenticator

AWS CLIkubectlKustomizeAWS IAM Authenticatorをalpineにインストールしてイメージを作成しています。

上のDockerfileを元にイメージをビルドして、EKSのクラスタがあるリージョンのECRのリポジトリにプッシュしておきます。

$ $(aws ecr get-login --no-include-email --region <EKSクラスタのあるリージョン名>)
$ docker build -t <ECRリポジトリのURI>:latest .
$ docker push <ECRリポジトリのURI>:latest

ECRのリポジトリではCodeBuildからのPullを許可するため、以下のポリシードキュメントでアクセス権限を設定しておきます。

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "allowCodeBuildPullImage",
            "Effect": "Allow",
            "Principal": {
                "Service": "codebuild.amazonaws.com"
            },
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability"
            ]
        }
    ]
}

ビルド定義の準備

CodeBuildでの処理の内容を指定するbuildspec.ymlをリポジトリのルートに設置します。

version: 0.2

phases:
  pre_build:
    commands:
      - aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME}
  build:
    commands:
      - kustomize build overlays/${KUSTOMIZE_OVERLAY} | kubectl apply -f -

AWS CLIでkubeconfigを生成し、kubectlでクラスタに接続できるようにし、KustomizeでYAMLファイルを作成されたYAMLをkubectl applyしています。

また、クラスタ名やオーバレイの指定は環境変数で行うようにしています。

ロールの準備

CodeBuildでkubeconfigを生成するため、CodeBuildのサービスロールとして以下のようなポリシーがアタッチされたものを作成します

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": "eks:DescribeCluster",
            "Resource": "arn:aws:eks:*:*:cluster/*"
        }
    ]
}

aws-authConfigMapにCodeBuildのサービスロールの設定を追加

EKSクラスタ内のaws-authというConfigMapを編集し、CodeBuildのサービスロールとKubenetes内のユーザを紐付け、デプロイを行うための権限を与えます。

以下のコマンドを実行し、

$ kubectl edit -n kube-system configmap/aws-auth

ハイライトされている部分を追加します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: <ARN of instance role (not instance profile)>
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
    - rolearn: <CodeBuildのサービスロールのARN>
      username: codebuild
      groups:
        - system:masters

Pipelineの構築

ここまででパイプラインを組むための準備が終わったので実際に以下の図のようなパイプラインを組んでいきます。

CodePipelineの作成画面から順番に設定していきます。

パイプライン名の設定

まずはパイプライン名を指定します。

ソースの設定

ソースの設定画面では、GitHubをソースプロバイダとして選択し、デプロイの対象となるリポジトリとブランチを指定します。

ビルドの設定

ビルドの設定画面では、CodeBuildをビルドプロバイダとして選択し、新しいビルドプロジェクトを作成していきます。

環境の設定では、CodeBuildの環境用のイメージをプッシュしておいたECRのリポジトリを指定します。

buildspec.yml内で使用している環境変数を設定します。ここではクラスタ名とkustomizeでどのoverlayを使用するかを指定しています。

デプロイの設定

今回はビルドの設定の中でデプロイの設定を行うように設定したので、デプロイなしを選択します。

CodePipeline のサービスロールの設定

ロールの作成ボタンから作成できるものをそのまま使用します。

ここまででパイプラインの設定内容でパイプラインを作成します

デプロイ実行!!!

パイプラインが作成されたら自動的にデプロイが実行されます。

実行が成功した後、kubectlでも確認してみると

$ kubectl get pods
NAME                             READY   STATUS             RESTARTS   AGE
staging-sbdemo-58bb5458d-qshc5   0/1     Running            0          1d

デプロイされたPodが表示され、正しくデプロイが実行されたのがわかります。

まとめ

今回は、Kustomize+CodePipelineを使用したデプロイの自動化の方法を備忘録としてまとめてみました。

今回、ブログを書くためKustomizeを調査した際に、リソースに共通したラベルを設定したり、nameにプレフィックスを付与したりなど、設定値の上書き以外にも便利な機能があることを知ったので、別途そのあたりもブログ化したいと思っています。

参考資料