k8s : DockerコンテナをKubernetes EngineにデプロイしてAppを起動する

###概要
Dockerコンテナに格納されているAppをGKEのKubernetes Engineで稼働させることを目標とします。
稼働させるAppについては、GCP公式の[hello-app](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/hello-app)を利用します。リクエストに対して「Hello, World!」というメッセージで応答します（port80）

####事前準備
- Google Cloud PlatformのKubernetes Engineで任意のプロジェクトを作成してください。
- プロジェクトに対する課金を有効にしてください。→[プロジェクトの請求設定の変更](https://support.google.com/cloud/answer/6293499#enable-billing)

<img width="1044" alt="スクリーンショット 2018-08-13 1.15.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/122901/fbfe5061-2c29-757e-360a-8dde8fefb78e.png">

- 基本的なgcloud, kubectlコマンドなどの初期設定については公式か[k8s : GKEによるKubernetesセットアップ(クラスタ作成まで)〜無料枠〜](https://qiita.com/i35_267/items/d0ecd5d483e7e7fae32c)を参照してください。

--- 

#### ステップ 1: コンテナ イメージを作成する.
Kubernetes Engine は、Docker イメージをアプリケーション デプロイメント形式として受け入れます。まずはDockerイメージを作成します。

**Git clone**
[hello-app](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/hello-app)をcloneします。

```bash

$ git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Cloning into 'kubernetes-engine-samples'...
remote: Counting objects: 436, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 436 (delta 0), reused 1 (delta 0), pack-reused 431
Receiving objects: 100% (436/436), 385.01 KiB | 332.00 KiB/s, done.
Resolving deltas: 100% (180/180), done.
$ cd kubernetes-engine-samples/hello-app
```

**環境変数設定**

```bash
$ export PROJECT_ID="$(gcloud config get-value project -q)"
Your active configuration is: [cloudshell-29771]
$ echo $PROJECT_ID
kubernetes-test-213018
```

**コンテナイメージを作成し、アップロード用のタグを付ける**
このコマンドは Dockerに対し、現在のディレクトリで Dockerfile を使用してイメージを作成し、gcr.io/my-project/hello-app:v1 などの名前を使用してタグ付けするように指示します。

```bash
$ docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
Sending build context to Docker daemon  9.728kB
Step 1/7 : FROM golang:1.8-alpine
1.8-alpine: Pulling from library/golang
550fe1bea624: Pull complete
cbc8da23026a: Pull complete

~中略~

Successfully built c0b949436195
Successfully tagged gcr.io/kubernetes-test-213018/hello-app:v1
```

```bash:コンテナイメージ確認
$ docker images
REPOSITORY                                TAG                 IMAGE ID            CREATED              SIZE
gcr.io/kubernetes-test-213018/hello-app   v1                  c0b949436195        About a minute ago   10.3MB
<none>                                    <none>              c6c64569411f        About a minute ago   263MB
alpine                                    latest              11cd0b38bc3c        5 weeks ago          4.41MB
golang                                    1.8-alpine          4cb86d3661bf        6 months ago         257MB

$ docker ps -a //プロセスはまだない。
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

#### ステップ 2: コンテナイメージをCONTAINER REGISTRYへアップロードする
コンテナのイメージを[CONTAINER REGISTRY](https://cloud.google.com/container-registry/)へアップロードします。

**アップロード**

```bash
$ gcloud docker -- push gcr.io/${PROJECT_ID}/hello-app:v1
WARNING: `gcloud docker` will not be supported for Docker client versions above 18.03.
As an alternative, use `gcloud auth configure-docker` to configure `docker` to
use `gcloud` as a credential helper, then use `docker` as you would for non-GCR
registries, e.g. `docker pull gcr.io/project-id/my-image`. Add
`--verbosity=error` to silence this warning: `gcloud docker
--verbosity=error -- pull gcr.io/project-id/my-image`.
See: https://cloud.google.com/container-registry/docs/support/deprecation-notices#gcloud-docker
The push refers to repository [gcr.io/kubernetes-test-213018/hello-app]
29c39384924b: Pushed

~中略~
```

#### ステップ 3: コンテナをローカルに実行する（オプション）
では、ローカル(コンソール上)で実行してport8080でアクセスしてみましょう。

```bash
$ docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-app:v1
2018/08/12 16:43:49 Server listening on port 8080
2018/08/12 16:44:25 Serving request: /
2018/08/12 16:44:25 Serving request: /favicon.ico

```
確認方法としては、 Cloud Shellで実行している場合は『ウェブでプレビュー』で見てみましょう。
<img width="1276" alt="スクリーンショット 2018-08-13 1.44.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/122901/7bd239a9-f850-f430-81b7-31031153ef14.png">

<img width="218" alt="スクリーンショット 2018-08-13 1.47.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/122901/3c9cfafd-5538-cebd-4831-93b8d9d85132.png">

curlでの確認でも問題ありません。

```bash
$ curl http://localhost:8080
Hello, world!
Version: 1.0.0
Hostname: f871bced7ec5
```
これでローカルでのApp検証は確認できました。ではデプロイを行っていきましょう。

#### ステップ 4: コンテナクラスタを作成する
クラスタ作成については下記の手順で行います。
参考 : [k8s : GKEによるKubernetesセットアップ(クラスタ作成まで)〜無料枠〜](https://qiita.com/i35_267/items/d0ecd5d483e7e7fae32c)

```
$gcloud config set project [プロジェクト名]
$gcloud config set compute/zone [ゾーン名]
$gcloud config set compute/region [リージョン名]
$gcloud config list
```
今回は下記のような感じで作成してみます。
[プロジェクト名] : kubernetes-test
[リージョン名] : us-west1-a
[ゾーン名] : us-west1

```bash
// プロジェクト
$ gcloud config set project kubernetes-test-213018

// ゾーン
$ gcloud config set compute/zone us-west1

// リージョン
$ gcloud config set compute/region us-west1-a

// 確認
$ gcloud config list
[compute]
region = us-west1-a
zone = us-west1
[core]
account = xxxxxx
disable_usage_reporting = False
pass_credentials_to_gsutil = false
project =  kubernetes-test-213018

Your active configuration is: [default]
```

```bash
$ gcloud compute instances list
NAME                                         ZONE        MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP     STATUS
gke-test-cluster-default-pool-ea04ffe6-tptm  us-west1-a  f1-micro      true         10.138.0.2   35.233.147.83   RUNNING
gke-test-cluster-default-pool-ea04ffe6-wmfz  us-west1-a  f1-micro      true         10.138.0.3   35.233.215.176  RUNNING
gke-test-cluster-default-pool-ea04ffe6-xwgq  us-west1-a  f1-micro      true         10.138.0.4   35.227.149.76   RUNNING
```

#### ステップ 5: アプリケーションをデプロイする
Kubernetes Engine クラスタにアプリケーションをデプロイして管理するには、Kubernetes クラスタ管理システムと通信する必要があります。

**Tips**
・Kubernetes上で可動するApp単位を[Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/)といいます。
・`kubectl run` コマンドを実行すると、Kubernetes がクラスタに hello-web という名前の[Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) を作成します。Deployment は、レプリカと呼ばれるアプリケーションの複数のコピーを管理し、クラスタ内の個々のノード上で実行するようにスケジューリングします。今回の場合、Deployment ではアプリケーションの 1 つのポッドのみが実行されます。
引用 : https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app

**Listen PORT**

```bash
$ kubectl run hello-web --image=gcr.io/${PROJECT_ID}/hello-app:v1 --port 8080
deployment "hello-web" created
```

**Pods確認**

```bash
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
hello-web-6f5854c4f4-c8kt8   1/1       Running   0          35s
```

#### ステップ 6: アプリケーションをインターネットに公開する
Kubernetes Engine 上で実行するコンテナは、外部 IP アドレスを持たないため、インターネットからアクセスできません。アプリケーションをインターネットからのトラフィックに明示的に公開する必要がある場合は、次のコマンドを実行します。

```bash
$ kubectl expose deployment hello-web --type=LoadBalancer --port 80 --target-port 8080
service "hello-web" exposed

$ kubectl get service
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
hello-web    LoadBalancer   10.59.246.168   35.233.225.41   80:32667/TCP   4m
```

**アクセス確認**

```bash
$ curl http://35.233.225.41:80
Hello, world!
Version: 1.0.0
Hostname: hello-web-6f5854c4f4-c8kt8
```
無事、アクセスできました！ 

これで無事公開が終わりましたが、Tips的にscaleについて言及します。

**現状のレプリカ数について確認**

```bash
$ kubectl get deployment hello-web
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-web   1         1         1            1           8m
```

これを3つにします。`kubectl scale deployment {app_name} --replicas=3`を実行します。

```bash
$ kubectl scale deployment hello-web --replicas=3
deployment "hello-web" scaled
i35_267_m@kubernetes-test-213018:~/kubernetes-engine-samples/hello-app$ kubectl get deployment hello-web
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-web   3         3         3            2           9m
```

という風になります。

また、このままだと課金されるのでクリーンアップ作業をします。

```bash
$ kubectl delete service hello-web
service "hello-web" deleted
$ gcloud compute forwarding-rules list
NAME                              REGION    IP_ADDRESS     IP_PROTOCOL  TARGET
a84f4475b9e5111e89f1442010a8a001  us-west1  35.233.225.41  TCP          us-west1/targetPools/a84f4475b9e5111e89f1442010a8a001
$ gcloud container clusters delete test-cluster
ERROR: (gcloud.container.clusters.delete) One of [--zone, --region] must be supplied: Please specify location..
$ gcloud container clusters delete test-cluster --zone us-west1-a
The following clusters will be deleted.
 - [test-cluster] in [us-west1-a]
Do you want to continue (Y/n)?  y
Deleting cluster test-cluster...done.
```

以上です。