Kubernetesを用いてGoogle Container Engineでコンテナクラスタをデプロイする〜設定ファイル編〜

# はじめに

[前回](http://qiita.com/yusukixs/items/11601607c629295d31a7)の記事では、KubernetesでGoogle Container Engine上でコンテナクラスタを構築する手順についてまとめました。

[Kubernetesを用いてGoogle Container Engineでコンテナクラスタをデプロイする〜入門編〜](http://qiita.com/yusukixs/items/11601607c629295d31a7)

今回は、設定ファイルによる設定手順についてまとめます。
現在稼働しているコンテナクラスタの設定をYAMLファイルにエクスポートします。

# YAMLファイルのエクスポート

## Deployment設定ファイルのエクスポート

```sh
$ kubectl get deployment/nodejs-deploy -o yaml --export > deploy.yaml
```

上記コマンドで `deploy.yaml` というファイルがアウトプットされます。
このファイルを開いてみると、下記のような内容となっています。

```yaml:deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "2"
  creationTimestamp: null
  generation: 1
  labels:
    run: nodejs-deploy
  name: nodejs-deploy
  selfLink: /apis/extensions/v1beta1/namespaces//deployments/nodejs-deploy
spec:
  replicas: 5
  selector:
    matchLabels:
      run: nodejs-deploy
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: nodejs-deploy
    spec:
      containers:
      - command:
        - node
        - app/server.js
        image: asia.gcr.io/kubernetes-demo-172306/nodejs:2.0
        imagePullPolicy: IfNotPresent
        name: nodejs-deploy
        ports:
        - containerPort: 3000
          protocol: TCP
        resources:
          limits:
            cpu: 200m
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status: {}
```

## Service設定ファイルのエクスポート

```sh
$ kubectl get service/nodejs-deploy -o yaml --export > service.yaml
```

上記コマンドで `service.yaml` というファイルがアウトプットされます。
このファイルを開いてみると、下記のような内容となっています。

このままこの設定ファイルを利用するとエラーになるので、
`clusterIP: <unknown>` をコメントアウトしてください。

```yaml:service.yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    run: nodejs-deploy
  name: nodejs-deploy
  selfLink: /api/v1/namespaces//services/nodejs-deploy
spec:
  #clusterIP: <unknown>
  ports:
  - nodePort: 31828
    port: 80
    protocol: TCP
    targetPort: 3000
  selector:
    run: nodejs-deploy
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer: {}
```

# 設定ファイルからのデプロイ

稼働している全てのService, Deploymentを削除して、
アウトプットした設定ファイルから同じ環境を作り直してみましょう。

まずはService, Deploymentの削除です。

```sh
$ kubectl delete deployment,service --all
deployment "nodejs-deploy" deleted
service "nodejs-deploy" deleted

# しばらく待つとPodも削除される
$ kubectl get pod
No resources found.
```

前回の記事で公開していた、`http://ロードバランサーのIPアドレス` にアクセスできなくなっていることを確認してください。

続いて、アウトプットした設定ファイルからDeploymentとServiceを作成します。

```sh
$ kubectl create -f deploy.yaml
deployment "nodejs-deploy" created
$ kubectl create -f service.yaml
service "nodejs-deploy" created

# ロードバランサーに外部IPが紐付いたかを確認
$ kubectl get services
NAME            CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
kubernetes      10.27.240.1     <none>           443/TCP        3d
nodejs-deploy   10.27.245.186   35.xxx.xxx.110   80:31828/TCP   1m
```

`http://<EXTERNAL-IP>` に再びアクセスし、「Hello GKE World！」が表示されることを確認してください。

# 設定ファイルの変更をRolling Updateでデプロイする

では、アプリケーションのソースコードが変更されてPodのコンテナイメージを置き換えるという仮定で、Rolling Updateをしてみます。

`deploy.yaml` を開き、 `image: asia.gcr.io/kubernetes-demo-172306/nodejs:2.0` のタグを `1.0`に変更します。
このタグは前回の記事で作成した、「Hello GKE World!」ではなく「Hello World!」をブラウザに表示するコンテナイメージです。

```yaml:deploy.yaml
# image: asia.gcr.io/kubernetes-demo-172306/nodejs:2.0
image: asia.gcr.io/kubernetes-demo-172306/nodejs:1.0
```

設定ファイルの内容をapplyコマンドで反映させます。

```sh
$ kubectl apply -f deploy.yaml
deployment "nodejs-deploy" configured

# Pod一覧を見るとRolling Updateでコンテナが置き換わっていくのを確認できる
$ kubectl get pod
NAME                             READY     STATUS              RESTARTS   AGE
nodejs-deploy-105340789-bq3fj    1/1       Running             0          4s
nodejs-deploy-105340789-fdzq4    0/1       ContainerCreating   0          1s
nodejs-deploy-105340789-lsctr    1/1       Running             0          12s
nodejs-deploy-105340789-qs20q    1/1       Running             0          12s
nodejs-deploy-105340789-tcr4d    1/1       Running             0          4s
nodejs-deploy-4273761010-c7r2w   0/1       Terminating         0          12m
nodejs-deploy-4273761010-j8m8j   0/1       Terminating         0          12m
```

`http://<EXTERNAL-IP>` に再びアクセスし、「Hello World！」にメッセージが変更されていることを確認してください。

# GKEデモ環境の削除

今回のデモはここまでで終了です。
このまま放置するとGCPで課金されてしまうため、不要な場合は下記コマンドで削除してください。

```sh
$ kubectl delete -f deployment.yaml
$ kubectl delete -f service.yaml
$ gcloud container clusters delete nodejs-cluster
```
# まとめ

私が紹介した方法では、kubectlコマンドでコンテナクラスタを構築し、そのコンテナクラスタからYAMLファイルをアウトプットすることで設定ファイルを作成しました。

もちろん、最初からYAMLファイルで設定ファイルを作成してコンテナクラスタを構築することも可能です。

この設定ファイルをGitリポジトリで管理することで、設定変更によるデプロイもプルリクエストによるレビューをすることができるようになり、多人数の目を通すことで設定ミスなどを防ぐような運用ができるようになります。

更に、GCPではコンテナクラスタの運用を継続的インテグレーションするためのサービス（Container Registry Build Trigger）も準備されています。それを利用すると、GitリポジトリにPUSHされると、コンテナイメージを自動的にビルドしてクラスタにデプロイするということを自動化することができるようになります。

次回は、Container Registry Build Triggerによる継続的インテグレーション手順についてまとめます。