spinnaker,gkeで自動デプロイまで設定してみた。

## パイプラインの概要

k8sを導入当初は`kubectl set image`でデプロイをしていましたが、
継続的なデプロイの自動化を試みて、`spinnaker`を導入してみました。

パイプラインは以下です。

<img width="1123" alt="スクリーンショット 2018-12-18 15.13.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/70960/2bab99ad-096f-82c5-7bf2-6c8adb95b310.png">


### Circle CI 
`GitHub Enterprise`から`Circle CI Enterprise`へ

以下、Railsをビルドするための`.circleci/config.yml`

```
version: 2
jobs:
   build:
     working_directory: ~/workspace
     docker:
       - image: circleci/ruby:2.4.1
         environment:
           RAILS_ENV: test
       - image: circleci/mysql:5.7
     steps:
       - checkout
       - run:
            name: submoduleの更新
            command: |
              git submodule update -i
       - restore_cache:
           name: キャッシュ読み込み
           key: tama-bundle-{{ checksum "Gemfile.lock" }}
       - run: bundle install --jobs=4 --path=~/workspace/vendor/bundle
       - save_cache:
           name: キャッシュ作成
           key: tama-bundle-{{ checksum "Gemfile.lock" }}
           paths:
             - ~/workspace/vendor/bundle
       - run:
            name: DB の初期化
            command: |
              mv config/database.ci.yml config/database.yml
              bundle exec rake db:create
       - run:
            name: Rspec
            command: bundle exec rspec spec
       - run:
            name: RuboCop
            command: bundle exec rubocop
   deploy-job:
     docker:
     - image: google/cloud-sdk:171.0.0-alpine
     steps:
     - checkout
     - setup_remote_docker
     - restore_cache:
         keys:
         - v1-{{ .Branch }}
         paths:
         - /caches/app.tar
     - run:
         name: 認証
         command: |
           echo $GCLOUD_SERVICE_KEY > ${HOME}/gcloud-service-key.json
           gcloud config set project $GCLOUD_SERVICE_PROJECT
           gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json
     - run:
         name: gcloud docker build
         command: |
           git remote add google https://source.developers.google.com/p/$GCLOUD_SERVICE_PROJECT/r/hoge-repository
           git config credential.'https://source.developers.google.com'.helper gcloud.sh
           git push --all google
workflows:
  version: 2
  build-and-deploy:
    jobs:
    - build
    - deploy-job:
        requires:
        - build
        filters:
          branches:
            only: master
```
masterブランチの更新時のみ`deploy`が実行され、`Cloud Source Repositories`に`git push`されます。


### Cloud Source Repositories
[Source Repositories](https://cloud.google.com/source-repositories/docs/setting-up-repositories?hl=ja)で`hoge-repository`を作成

### Cloud Build
[Cloud Build](https://cloud.google.com/cloud-build/docs/creating-build-triggers?hl=ja)のトリガーを作成します。

`トリガーを追加`　-> `hoge-repository`を選択 -> `トリガー設定`
リポジトリ、イメージ(Container Registry)、dockerfileなどを設定します。

## Container Registry
`Cloud Build`でビルドされたコンテナは`Container Registry`に配置されます。


ここまででGCPの設定は以上。

## Spinnaker

Spinnakerの環境構築
`GCEのMarketplace`でSpinnakerの簡単に構築できますが、バグが多く、
設定の変更が容易でないので、VMにそのまま入れます。

spinnakerの公式ドキュメントを参考にしました。
https://www.spinnaker.io/setup/quickstart/halyard-gce/

まずGCP VMで立てます。

```
gcloud beta compute --project=hogehoge-gcp \
instances create hogehogespinnaker --zone=asia-northeast1-a \
--machine-type=n1-standard-4 --subnet=huge-subnet \
--network-tier=PREMIUM \
--maintenance-policy=MIGRATE \
--service-account=fugafuga@developer.gserviceaccount.com \
--scopes=https://www.googleapis.com/auth/cloud-platform --tags=spinnaker,http-server \
--image=ubuntu-1404-trusty-v20180818 \
--image-project=ubuntu-os-cloud \
--boot-disk-size=100GB \
--no-boot-disk-auto-delete \
--boot-disk-type=pd-standard \
--boot-disk-device-name=hogehogespinnaker
```

vmにsshして
Spinnakerをセットアップします。

spinnakerのパッケージマネージャーのhalyardを入れます。

```
curl -O https://raw.githubusercontent.com/spinnaker/halyard/master/install/stable/InstallHalyard.sh
sudo bash InstallHalyard.sh
. ~/.bashrc
```

gcpの設定をしてきます。

```
gcloud iam service-accounts create halyard-account \
  --display-name halyard-account

 gcloud projects add-iam-policy-binding hogehoge-gcp \
 --role roles/storage.admin --member serviceAccount:halyard-account@hogehoge-gcp.iam.gserviceaccount.com

gcloud iam service-accounts keys create ~/.gcp/gcs_account.json --iam-account "halyard-account@hogehoge-gcp.iam.gserviceaccount.com"

gcloud iam service-accounts keys create ~/.gcp/gcs_account.json --iam-account spinnaker-account@hogehoge-gcp.iam.gserviceaccount.com

```

halyardの設定をしてきます。

```
# halyard version
hal config version edit --version $(hal version latest -q)

# 一度　bucket locationなしを実行しなければならない。
hal config storage gcs edit --project "hogehoge-gcp" \
  --json-path ~/.gcp/gcs_account.json

hal config storage gcs edit --project "hogehoge-gcp" \
  --bucket-location "asia.gcr.io" \
  --json-path ~/.gcp/gcs_account.json
hal config storage edit --type gcs　

hal config provider docker-registry enable

hal config provider docker-registry account add halyard-gcr-account \
      --address asia.gcr.io \
      --password-file ~/.gcp/gcs_account.json \
      --username _json_key

```

k8sの設定をします。

```

# kube install
sudo curl -L https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl
sudo chmod 755 /usr/local/bin/kubectl
cat <<EOF > ~/switch_cluster.sh
# !/bin/sh
gcloud container clusters get-credentials hoge-gke-cluster --zone asia-northeast1-a --project hogehoge-gcp
EOF



chmod 755 ~/switch_cluster.sh

./switch_cluster.sh

# context確認
kubectl config current-context

# プロバイダー有効化
hal config provider kubernetes enable

# halyardのk8sアカウント作成

hal config provider kubernetes account add halyard-k8s-account \
    --docker-registries halyard-gcr-account \
    --context $(kubectl config current-context)

# v2 対応　デフォルトのv1では機能が少なくすぎて、k8sを使う場合は v2にしましょう。
hal config provider kubernetes account edit halyard-k8s-account \
--provider-version v2 \
--context $(kubectl config current-context)

hal config deploy edit --type distributed --account-name halyard-k8s-account

hal config features edit --artifacts true


# アカウントをセット
hal config deploy edit \
  --account-name halyard-k8s-account \
  --type distributed


# gke credentials set
gcloud config set container/use_client_certificate true
gcloud container clusters get-credentials hoge-gke-cluster --zone asia-northeast1-a --project hogehoge-gcp

# deploy
sudo hal deploy apply

```

これで設定が終わったので
spinnakerを起動します。



```
hal deploy connect
```

ローカルのブラウザで`localhost:9000`を開きます。
**スクリーンショットは後日入れさせていただきます。🙇‍♂️**

`applicationの作成` -> `pipelineの作成` ->  `Configuration`と進み
`Container Registry`に登録したイメージを設定します。

`Add Stage`でデプロイの設定を行います。
今回は
Patch (Manifest) を選択します。

manifest source textで
k8s ymlを少し加工したymlファイルを貼り付けます。

```
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: hoge-repository
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: hoge-repository-app
        role: app
        env: qa
    spec:
      containers:
        - image: "asia.gcr.io/hogehoge-gcp/hoge-repository:latest"
          imagePullPolicy: Always
          name: hoge-repository-app
```

これで全てのパイプラインの設定が完了しました。

`kubectl set image`と同じ挙動で動くはずです。

以上です。