LoginSignup
9
6

More than 3 years have passed since last update.

CodeBuildでEKSへBuild&Deploy

Last updated at Posted at 2020-02-27

はじめに

AWS CodeBuildを用いてDocker build および EKSヘのデプロイを行うサンプルです。
GitHub Enterprise(GHI)へのPushをトリガーにCodeBuildをkickしてみます。

※当初は、CodePiplelineでGHEへのPushトリガーを受けようと考えていたのですが、CodePipelineはGHEに対応していないらしく、CodeBuildのみでまかなうことにしました。

前提

  • Date : 2020/2 時点
  • EKS Kubernetes version: 1.14
  • ImageリポジトリはECRを利用し、かつセットアップ済み (ECRの設定は本記事には記載しない)
  • EKSはセットアップ済み(EKSの設定は本記事に記載しない)
  • GHEへアプリケーションソースコードおよびDockerfileを格納済み(すでに存在する前提)
  • リポジトリ直下に、Dockerfileが格納されている(docker buildで利用)
  • リリース対象のEKS(K8s)リソースは、Deploymentを想定

GHEのPersonal access tokenの作成

GHEの右上個人メニューからSeeting -> Developer settingsと遷移し、Personal access tokensタブから作成します。
scopeはrepoのみ選択すれば問題ありません。
作成されたトークンは控えておきましょう(再表示できません)。
image.png

CodeBuildプロジェクトの作成

マネジメントコンソールから、ビルドプロジェクトを作成します。
※なお、設定値に言及がない場合は、デフォルト値を採用しています。

プロジェクトの設定セクションは任意に入力してください。

送信元セクションでは、ソースプロバイダにGitHub Enterpriseを選択し、先ほど取得したPersonal access tokenを入力します。
image.png
トークンの保存後、リポジトリのURLを入力します。
image.png

ウェブフックイベントセクションでは、再構築にチェックを入れ、イベントタイプにはプッシュを選択します。
image.png

環境セクションは下図の通り入力します。
イメージ内でDockerを起動するため、特権付与にチェックを入れます。
ロール名は任意の名称を入力してください。
image.png

環境セクションの追加設定で、下図の環境変数を設定します。
この環境変数は、後続に記載するbuildspec.yamlで利用します。
image.png

IAMポリシー&ロールの編集

CodeBuildプロジェクト作成時に作成したサービスロールに、ECRおよびEKSへのアクセスを許可するポリシーを作成します。

policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:CompleteLayerUpload",
                "ecr:GetAuthorizationToken",
                "ecr:UploadLayerPart",
                "ecr:InitiateLayerUpload",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "eks:DescribeCluster",
            "Resource": "arn:aws:eks:*:*:cluster/*"
        }
    ]
}

ポリシー作成後、サービスロールにアタッチします(スクショは割愛)。

IAM RoleとEKS RBACとの紐付け

外部からEKSのK8sリソースにアクセスする場合、IAMロールとKubernetesのユーザー/グループを紐づける必要があります(先達の投稿がよくまとまっていると思います)。

「aws-auth」というEKS固有のConfigMapを編集し、CodeBuild用サービスロールをK8sのsystem:mastersグループに紐付けます。
※system:mastersというグループは、いわゆるadmin的な権限を持つデフォで存在するグループです。

aws-auth
$ kubectl edit cm aws-auth -n kube-system

apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::xxxx:role/xxxx
      username: system:node:{{EC2PrivateDNSName}}
##add from
    - rolearn: arn:aws:iam::xxxxx:role/codebuild-hoge-service-role
      username: codebuild 
      groups:
      - system:masters 
##add to
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: aws-auth
  selfLink: /api/v1/namespaces/kube-system/configmaps/aws-auth  

ここで、注意点です。
rolearnには、パスを含めてはいけません。

○: arn:aws:iam::xxxxx:role/codebuild-hoge-service-role
×: arn:aws:iam::xxxxx:role/service-role/codebuild-hoge-service-role

マネジメントコンソールに表示されるarnにはパスが含まれるのですが、これをコピペするとロールが正しく認識されず、you must login みたいなエラーになりました。

buildspec.yaml

buildspec.yamlの内容は以下の通りです。
簡単に処理内容を書くと、dockerを起動して、buildして、pushして、k8sのdeploymentをrolloutすることでPodを再作成し、イメージの変更を反映させています。
このファイルをGHEリポジトリの直下に配置します。

buildspec.yaml
version: 0.2 

phases: 
  install:
    runtime-versions:
        docker: 18
    commands:
      # install kubectl
      - wget -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl
      - chmod +x /usr/local/bin/kubectl
  pre_build:
    commands:
    - echo "Logging in to Amazon ECR...."
    - aws --version
    - $(aws ecr get-login --no-include-email --region $CI_REGION)
    - echo "the repo/version now is ${REPO_URL}:${LATEST_VERSION}"

    - echo "Creating folders for pid files"
    - mkdir shared
    - mkdir shared/pids
    - mkdir shared/sockets
  build: 
    commands: 
    - echo "Build started on `date`"
    - echo "Building the Docker image.. ${REPO_URL}:${LATEST_VERSION}"

    # dokcer build & push
    - docker build -t tempimage:latest .
    - docker tag tempimage:latest ${REPO_URL}:${LATEST_VERSION}
    - echo "dokcer build completed on `date`" 
    - echo "pushing to repo ${REPO_URL}:${LATEST_VERSION}"
    - docker push ${REPO_URL}:${LATEST_VERSION}
  post_build: 
    commands: 
    - echo "Build completed on `date`"
    # rollout kubernetes(eks) deployment
    - echo "rollout eks deployment = ${K8S_DEPLOY_NAME} @ ${EKS_CLUSTER_NAME}"
    - aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME} --verbose
    - kubectl rollout restart deployments/${K8S_DEPLOY_NAME} -n ${K8S_NAMESPACE}

CodeBuildにWebHookを追加

以下のコマンドでCodeBuildにWebHookを追加します。
--project-nameオプションは、CodeBuildプロジェクト名を設定します。

create-webhook

$ aws codebuild create-webhook --project-name hoge
{
    "webhook": {
        "payloadUrl": "https://codebuild.ap-northeast-1.amazonaws.com/webhooks?t=eyJlbmNyeXB...<省略>",
        "secret": "5ZUJKd8wA...<省略>",
        "lastModifiedSecret": 1595395732.558
    }
}    

GHEにWebhook URLを登録

GHEリポジトリのSettings画面からWebHookを追加します。
ここで、Payload URLとSecretには、先の手順コマンドで取得したURLとSecretを入力します。

image.png

以上で手順は終了です。
GHEリポジトリに変更をpushすることで自動的にBuild&Deployが開始されるはずです。

9
6
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
9
6