GKEでArgoを使ったカナリアリリースを実現する（セットアップ編）

## 概要
KubernetesでGitOpsを実現するツールであるArgo CDとKubernetesでblue/grennデプロイやカナリアリリースを実現するためのデプロイメントコントローラーであるArgo Rolloutsを使用して、カナリアリリースを実現する方法を２回に渡ってご紹介します。
今回はセットアップ編となります。

Arog CDのオフィシャルサイト
https://argoproj.github.io/argo-cd/

## 構成図
![argocd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/4bc0455e-48a9-3b39-4486-82d0b850979b.png)

## 構成要素
* GKE
* GCR ※今回は登場なし
* Cloud Build　※今回は登場なし
* Cloud Load balancer(ingress)
* GitHub
* [argo cd](https://github.com/argoproj/argo-cd)
* [argo rollouts](https://github.com/argoproj/argo-rollouts)

## 前提条件
* Googleアカウントがあること
* GitHubアカウントがあること
* デプロイしたいアプリケーションがあること
 * 今回は例としてオフィシャルサイトが用意している[guestbookのアプリケーション](https://github.com/kubernetes/examples/tree/master/guestbook)をForkし、仮想アプリケーションとして使用
 * 上記リポジトリをForkし、手元にCloneしてある状態であること

## 環境
* macOS Majave
* kubectl Client v1.15.1
* kubectl Server v1.12.8-gke.10
* Google Cloud SDK 259.0.0(gcloudはこれに含まれる）

## 構築の流れ
セットアップ編の大まかな流れがこちらです。

1. 各種クライアントツールをインストール
2. GKEクラスターのセットアッップ
3. Argo CDのインストール
4. Argo CDのセットアップ
5. Argo Rolloutsのインストール
6. Argo Rolloutsのセットアップ

## 手順
### 1. 各種クライアントツールをインストール
ここではセットアップに必要な各種クライアントツールをインストールしていきます。

```shell
$ brew tap argoproj/tap
$ brew install argoproj/tap/argocd
```

### 2. GKEクラスターのセットアップ
ここでは、GKEクラスターをセットアップしていきます。

```shell
# プロジェクトの設定
$ gcloud auth login
$ GCP_PRJ=<your GCP project ID>
$ gcloud config set project $GCP_PRJ

# GKEクラスターの作成
$ GKE_CLUSTER_NAME=<your GKE Cluseter Name>
$ gcloud container clusters create $GKE_CLUSTER_NAME
$ gcloud container clusters get-credentials $GKE_CLUSTER_NAME
$ gcloud container clusters list

# デフォルトで用意されているcluster-adminというClousterroleとuserをバインディング
# cluster-adminは、cluster内の全てのリソースに対し、どんなアクションでも可能な権限
$ APPNAME=<your name> # 任意。今回はアプリケーション名にした。
$ USER_NAME=<your GCP account> # GCPのアカウントに使用しているメールアドレス。
$ kubectl create clusterrolebinding ${APPNAME}-cluster-admin-binding --clusterrole=cluster-admin --user=$USER_NAME
$ kubectl get clusterrolebinding | grep ${APPNAME}
```



### 3. Argo CDのインストール
ここではArgo CDをインストールしていきます。
GKE内にArgo用のServiceやpodを起動させます。

```shell

# Namaspace作成
$ kubectl create ns argocd
$ kubectl get ns

# Argo CDインストール
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
$ kubectl get service -n argocd
$ kubectl get pods -n argocd

# PublicAccessを実現するためにLoadbalancerの作成
$ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
$ kubectl get service argocd-server -n argocd
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
argocd-server   LoadBalancer   10.47.255.158   34.85.104.22   80:32676/TCP,443:31540/TCP   17m

#上記のEXTERNAL-IPをセットしておきます。
$ ARGOCD_SERVER=<EXTERNAL-IP> 
```

上記の`EXTERNAL-IP`で表示されたIPアドレスにブラウザからアクセスします。
<img width="1796" alt="スクリーンショット 2019-08-26 15.27.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/037b92de-3858-8f87-9cf9-09c34175fdf8.png">
次にArgoのログインパスワードを取得します。デフォルトはargocd-serverのpod名となっています。

```
# パスワード取得コマンド
$ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
```
パスワードが取得できたら Username： `admin` と上記で取得したパスワードでログインが可能となります。
次にargocdコマンドでもArgoにログインしておきます。

```
# パスワードは、上述の通り
$ argocd login $ARGOCD_SERVER　
```

なお、Argoのデフォルトパスワードを変更したい場合はこちらのコマンドで可能です。

```
$ argocd account update-password
```

### 4. Argo CDのセットアップ
デプロイ対象のGitHub repositoryを追加していきます。

```shell

$ REPO_URL=<your repository URL> # 今回は例としてForkしたExampleリポジトリのURL(git@github.com:<your account name>/examples.git)を設定
$ SSH_KEY_PATH=<your ssh key path>
$ argocd repo add $REPO_URL --ssh-private-key-path $SSH_KEY_PATH
```

GUIでもリポジトリが追加されていることが確認できます。
<img width="1513" alt="スクリーンショット 2019-08-26 15.51.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/4994065d-74c7-ea39-e615-f34a87b0b736.png">
![スクリーンショット 2019-08-26 15.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/4d30663b-e981-d07f-0d91-400613c79213.png)


続いて管理するkubernetesのclusterの追加します。

```shell

$ K8S_CLUSTER_NAME=`kubectl config get-contexts | grep "*" | awk '{print $3}'`
$ argocd cluster add $K8S_CLUSTER_NAME
```

GUIでもClusterが追加されていることが確認できます。
<img width="1507" alt="スクリーンショット 2019-08-26 16.03.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/b869ed73-cf91-a7bd-2695-99b63246b668.png">
![スクリーンショット 2019-08-26 16.04.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/374f0c2a-1802-e941-12bb-042bb8b8b669.png)

続いて、Argo上にアプリケーションを作成します。

```shell

$ ARGO_SYNC_PATH=guestbook/ # manifestファイルがあるディレクトリを指定します。
$ DEST_SERVER=`argocd cluster list | grep $K8S_CLUSTER_NAME | awk '{print $1}'`

# argo上にアプリケーションを作成。以下、補足説明
#  --repo：同期するGitHubリポジトリ
#  --path：同期するmanifestファイルがあるディレクトリ
#  --dest-server：ArgoのURL
#  --dest-namespace：Argo上Namespace 
#  --revision：同期するブランチ
#  --sync-policy automated：自動同期を有効
#  --auto-prune：同期時にリソースの削除を有効

$ argocd app create $APPNAME \
  --repo $REPO_URL \
  --path $ARGO_SYNC_PATH \
  --dest-server $DEST_SERVER \
  --dest-namespace default \
  --revision master \
  --sync-policy automated \
  --auto-prune
```



ArgoのGUIでもアプリケーションがデプロイされたことが確認できます。
<img width="806" alt="スクリーンショット 2019-08-26 16.55.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/4128bd51-1472-cc05-f3f8-176d8ffc0c0d.png">
<img width="1613" alt="スクリーンショット 2019-08-26 16.56.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/f1b0c33d-5a2d-0717-1f32-32ad9d22f370.png">

これでGKE上にアプリケーションがデプロイされましたが、現状だとPublicに公開していない状態なので仮で`ingress`を作ります。
以下のmanifestファイルを`guestbook/`ディレクトリ以下に作成し、masterブランチでコミットしてPushします。

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: frontend
          servicePort: 80
```

しばらくするとArgoがGitHubと現構成との差分を検知し、同期することでingressが作成されます。
GitOpsですね。
以下のコマンドでingressに付与されたPublicIPAddressが確認できるのでそちらにアクセスします。

```shell
$ kubectl get ingress
NAME          HOSTS   ADDRESS         PORTS   AGE
app-ingress   *       35.190.119.89   80      14m
```

<img width="1021" alt="スクリーンショット 2019-08-27 10.52.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95324/1d647f16-81c0-c734-52af-d439a3d91715.png">

guestbookが確認できました。

### 5. Argo Rolloutsのインストール
つづいて、Argo Rolloutsのインストールします。
Argo CDだけでもデプロイは可能ですが、blue/greenデプロイやカナリアリリースをやろうと思った時に必要となります。

```shell

$ kubectl create ns argo-rollouts
$ kubectl get ns
$ kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml
$ kubectl get service -n argo-rollouts
$ kubectl get pods -n argo-rollouts
```

以上でセットアップ完了となります。
次回、実際にカナリアリリースを実現する方法を書きたいと思います。

---
2019/08/29 続編書きました
[GKEでArgoを使ったカナリアリリースを実現する（完結編）](https://qiita.com/takemotto/items/c4f61a787558df18bf22)

## 参考文献

この記事は以下の情報を参考にして執筆しました。
[EKSでArgo CDのチュートリアルを試してみた](https://dev.classmethod.jp/cloud/aws/eks-argocd-getting-started/)
[GKEでArgoCDを使ってGitOpsしてみた](https://qiita.com/ttr_tkmkb/items/ff4d88f3a91db982b0ab)
[Argo CDによってGKEでGitOpsをする](https://www.1915keke.com/entry/2018/12/15/034843)
[デフォルトで用意されているClusterRole](https://qiita.com/sheepland/items/67a5bb9b19d8686f389d#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%A7%E7%94%A8%E6%84%8F%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8Bclusterrole)