【GKE】CircleCI を使ってGKEへ自動デプロイ


# CircleCIとGKE
今回は、CircleCIを使ってGKEに自動デプロイする実装を業務で行ったので、備忘録として記載しておきます。
間違いなどあれば、ご指摘お願いいたします。

## 記事の全体像
本記事の流れは下記になります。

- CircleCIの復習
- GKEへのデプロイ
- 今後やりたいこと
- デバッグ方法


## CircleCI 復習
下記記事を読めば大体わかります。
[いまさらだけどCircleCIに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)

記事読む際は、最低限下記4つを意識して読めば良いと思います。

- jobs
- job_name
- steps
- workflow


## GKEへのデプロイ
では一旦CircleCIのざっとした復習をしたので、次にGKEへのデプロイについて見ていきたいと思います。
まずGKEにデプロイするためには、以下を満たす必要があります。

1. サービスアカウントを使っての認証
2. Google Cloud SDKのインストール(gcloud上にkubectlをインストールするため)
3. gcloudコマンドでのプロジェクト設定
4. Docker imageをBuildし、GCRにPush
5. KuberntesのDeploymentの更新(imageの箇所)

[GKE+CircleCI 2.0で継続的デプロイ可能なアプリケーションをシュッと作る](https://medium.com/eureka-engineering/gke-circleci-2-0%E3%81%A7%E7%B6%99%E7%B6%9A%E7%9A%84%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E5%8F%AF%E8%83%BD%E3%81%AA%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%82%B7%E3%83%A5%E3%83%83%E3%81%A8%E4%BD%9C%E3%82%8B-fc42bef34761)
[Circle CIでGKEにデプロイ](https://mitaka.club/posts/use_circleci/)

アウトプットは下記のようになります。

```yaml

deploy:
    docker:
      - image: google/cloud-sdk
    steps:
      - checkout
      - setup_remote_docker:
          version: 18.06.0-ce
      - run:
          name: GCP Authenticate
          command: |
            echo $GKE_SERVICE_KEY > gcloud-service-key.json
            gcloud auth activate-service-account --key-file gcloud-service-key.json
            gcloud auth configure-docker
      - run:
          name: gcloud install & setting
          command: |
            curl -s https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-196.0.0-linux-x86_64.tar.gz | tar xz
            source ./google-cloud-sdk/path.bash.inc
            gcloud components install kubectl
            gcloud config set project $GKE_PROJECT
            gcloud config set compute/zone $GKE_COMPUTE_ZONE
            gcloud container clusters get-credentials $GKE_CLUSTER_NAME
      - run:
          name: Build the image
          command: |
            docker build -t $GKE_GCR_REPO:${CIRCLE_SHA1} .
      - run:
          name: Push the image
          command: |
            docker push $GKE_GCR_REPO:${CIRCLE_SHA1}
      - run:
          name: Deploy
          command: |
            kubectl set image deployment/デプロイメントのファイル名 recloc-sha256=$STG_GKE_GCR_REPO:${CIRCLE_SHA1}

workflows:
  version: 2
  deploy_production:
    jobs:
      - deploy:
          filters:
            branches:
              only:
                - master
```


### サービスアカウントを使っての認証
#### サービスアカウント作成
GCPのIAMから作成し、下記2つ権限の付与します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148392/2357247b-6589-b5d3-e2ca-69282fbe4d0c.png)

「ストレージ管理者」GCRにアクセスするために必要で、
「Kubernetes Engine 管理者」は、クラスタ情報を得るため、「kubectl set image」コマンドを実行するために必要です。

#### circleCIの環境変数にサービスアカウントを定義
サービスアカウントを定義した後は、jsonの形式でダウンロードします。
ダウンロードしたものは、CircleCIで環境変数として定義します。(上記の実装で言う所の$GKE_SERVICE_KEY)

`echo $GKE_SERVICE_KEY > gcloud-service-key.json`
CircleCIで定義した環境変数を `gcloud-service-key.json`に入力しています。

`gcloud auth activate-service-account --key-file gcloud-service-key.json`
作成したjsonファイルで認証を行います

`gcloud auth configure-docker`
Docker認証ヘルパーを通します。

**Docker認証ヘルパー[補足]**
dockerコマンドを使って、GCRに対してpullしたり、pushするのは認証が必要になります。
いくつか方法があるが、下記のようにDcoker認証ヘルパーを使用する場合は、google sdkのバージョンが18.03以降である必要があります。

>警告: Docker 認証ヘルパーは、バージョン 18.03 以降でのみ使用してください。以前のバージョンの Docker クライアントのバグにより、認証ヘルパーが構成されていると、docker build の性能が大幅に低下します。

[認証方法](https://cloud.google.com/container-registry/docs/advanced-authentication?hl=ja#gcloud_as_a_docker_credential_helper)


### Google Cloud SDKのインストール
`Google Cloud SDK`は、`gcloud`に`kubectl`をインストールするために、使用します。
この設定で、`kubectl`コマンドがGCP上で使用することができるようになります。
この設定後、`kubectl get deployment` or `kubectl get pod`などのコマンドで、意図するクラスタの情報が取れているか確認することができます。

### gcloudコマンドでのプロジェクト設定
どこのプロジェクトのどのクラスタに対して、Kubernetesのマニフェストファイルを更新するか定義します。
下記3つを設定します。

```
# 使用するプロジェクトを設定
gcloud config set project [プロジェクト名]
# Zoneを設定
gcloud config set compute/zone [zon名]
# 指定したプロジェクト内のクラスタを設定
gcloud container clusters get-credentials [クラスタ名]
```

### Imageのbuild, push
GCPの設定が終わったので、次にPushするイメージを作成していきます。
$GKE_GCR_REPOには、`gcr.io/{プロジェクト名}/{フォルダ名}`が入っています。

`${CIRCLE_SHA1}`は、CircleCIが定義している環境変数で、値としては、最後のコミットのハッシュ値が入っています。
[定義済み環境変数](https://circleci.com/docs/ja/2.0/env-vars/#%E5%AE%9A%E7%BE%A9%E6%B8%88%E3%81%BF%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)

```
docker build -t $GKE_GCR_REPO:${CIRCLE_SHA1} .
docker push $GKE_GCR_REPO:${CIRCLE_SHA1}
```

### Deploymentの更新(imageの箇所)
`kubectl set image`コマンドを使ってimageを更新をします。

他の方法として`kubectl patch`コマンドがありますが、ごちゃごちゃしていないので、`set image`コマンドの方が個人的には好んで使っています。

[Kubernetes道場 23日目 - kubectlを網羅する](https://cstoku.dev/posts/2018/k8sdojo-23/)

ここまでで自動デプロイは完成しているはず！！

### Workflow

最後にworkflowに関してです。
これは、文章で説明してしまうと、
**deployのjobはmasterブランチでしか動作しませんよ**という定義を行なっています。
例えば、masterにマージされたタイミングでステージング環境に対して自動デプロイしたいというときにしようできると思います。

```yaml
workflows:
  version: 2
  deploy_production:
    jobs:
      - deploy:
          filters:
            branches:
              only:
                - master

```


## 今後やりたいこと
### Orbsを使ってCircleCIからGKEにデプロイ
CircleCIの実装でも Orbsを使用することで、GKEにでデプロイできるようです。
[Orb Source](https://circleci.com/orbs/registry/orb/circleci/gcp-cli)

### 高度なデプロイ
巷ではGitOpsが流行っていますが、`spinnaker`を使ったグリーンデプロイくらいまで実装したいと思う。


## デバッグ方法
後少し便利なので、デバッグ方法についても記載しておきます。
CircleCIでデバッグする方法について記載します。

### 文法チェック
`circleci config validate`

下記のように返って来れば問題ありません。
`Config file at .circleci/config.yml is valid.`

### 実行をローカルでチェック
`circleci local execute`

下記のように`job`を指定することもできます。
`circleci local execute --job build`
※認証周りのテストはローカルでは十っこうできないため、スキップする必要があります。
ここのベストプラクティスがあれば教えて欲しいです！

[まさかPushデバッグしてないよね？ よく使うCircleCIのデバッグ方法](https://blog.vtryo.me/entry/circleci-debug-method)
[CircleCI のデバッグ方法3つ](https://qiita.com/mokuo/items/1f6e35abe3845c82253b)