Google Container Engine (GKE)を触る


Google Cloud Platformで公開された Google Container Engineを触ってみたいと思います。


## GKE is 何？

GKEはGoogle Compute Engine上にKubernetesのクラスタを作成し、Dockerコンテナを配置可能にしてくれます。

Kubernetes自体はDockerコンテナマネージャに近い役割で、Dockerコンテナの配備、ネットワーキング、死活監視&リスタートなどなどの機能を持っています。

どこまでGoogle側がめんどうみてくれるかはまだドキュメントの範囲では不明ですね...

元々GCEには Container Optimized Imageと呼ばれるKubernetesのコンポーネントの一つKubeletを持ったImageがあったので、それにちかしい物な気もします。

## 試してみる

### Sign Up

GKEはまだAlphaリリースなのでSign Upが必要です。
Sign Upは以下から可能です。

https://docs.google.com/forms/d/10h7vBNZeusl7wwXvTxK3xQLVEi8n4WlII8Z7ZpHIvmY/viewform

よく読んでSign Upして下さい。

### Kubernetesを立ち上げる

#### Container Engine APIを有効化

Sign Upをし、GKEが利用可能になったら
Cloud Consoleの適当なプロジェクトにログインします。

メニューの中から「Container Engine」を選択します。

![gke-menu.png](https://qiita-image-store.s3.amazonaws.com/0/2965/290dfc28-6fcc-103c-7c53-44e0a97b76cb.png "gke-menu.png")


もし以下の様な表示が出た場合は同じくメニューの「API」から`Container Engine API`を有効にして下さい。


![disable-gke.png](https://qiita-image-store.s3.amazonaws.com/0/2965/893b2568-cb39-2edc-c551-bca5fde34217.png "disable-gke.png")


![enable-gke.png](https://qiita-image-store.s3.amazonaws.com/0/2965/e3a5de0a-522a-287a-8956-1d8dabcdc77a.png "enable-gke.png")

#### Clousterの設定(立ち上げ)

APIをONにし、再度「Container Engine」に戻ると以下の様な表示になるので「Create a Cluster」をクリックします。

![createacluster.png](https://qiita-image-store.s3.amazonaws.com/0/2965/d53c4cb5-9b40-91a8-6029-eac8e2849200.png "createacluster.png")


細々した設定を行います。

![gke-setting.png](https://qiita-image-store.s3.amazonaws.com/0/2965/2b45bd2c-b929-83ce-6c88-3feb840b6849.png "gke-setting.png")



大体書いてあるとおりですね。
マシンタイプについては、Kubernetesの公式では、`n1-standard-1`がデフォルトになっています。
それ以上小さいマシンタイプだと正常に動作しない可能性もあるので注意して下さい。
また、Kubernetesは通常1マスタ、nノード構成で動きます。

最小構成(Cluster Sizeを1にしても)でも2VMインスタンス以上立ち上がりますので注意して下さい。

設定が完了したら、「作成」ボタンを押下して、Clusterを立ちあげます。
しばらく待つと以下のようにClusterが立ち上がります。

![clouster-list.png](https://qiita-image-store.s3.amazonaws.com/0/2965/76c6b893-fd76-afb1-e61b-dcf073fcb460.png "clouster-list.png")

![cluster-detail.png](https://qiita-image-store.s3.amazonaws.com/0/2965/7cdf7413-45ee-7952-4e8e-158d95514590.png "cluster-detail.png")

立ち上がっているGCEインスタンスも確認できますね。

#### gcloud preview container コマンドの設定

Clusterの立ち上がりを待っている間に、GKE上のDockerコンテナを操作するためのCLIを落としてきます。

Google Cloud SDKをインストールしていない方はぐぐってインストールして下さい。
インストールが完了したら以下のコマンドで `gcloud preview`コマンドをインストールします。
※インストール済みの方もupdateしたほうがよいでしょう。

```bash
$ gcloud components update preview
```

これで`gcloud preview`コマンドがインストールされます。
今回のGKEに関するコマンド群は`gcloud preview container`コマンドになります。


### KubernetesのWeb UIにログインする

余り知られていませんが、KubernetesにはWeb UI(ただし参照用)があるので、それにログインしてみたいと思います。

まずWeb UIにログインするためのID/PassをGoogle Cloud SDKのCLI経由で取得します。

```bash
$ gcloud preview container clusters list --zone asia-east1-b
clusters:
- clusterApiVersion: 0.4.2
  containerIpv4Cidr: xx.xxx.x.x/16
  creationTimestamp: zzzzzzzzzzzzzzzzzzzz
  description: "\u306F\u3058\u3081\u3066\u306EGKE"
  endpoint: xxx.xxx.xxxx.xx
  masterAuth:
    password: PASSWORDISHERE
    user: xxxx
  name: xxxxxxxxx
  nodeConfig:
    machineType: n1-standard-1
    sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-v20141021
  nodeRoutingPrefixSize: 24
  numNodes: 1
  servicesIpv4Cidr: 10.0.0.0/16
  status: running
  zone: asia-east1-b
```

上のclusters/masterAuth/passwordとclusters/masterAuth/userを保存しておき、以下にアクセスします。

[https://{上記clusters/endpoint}/static/index.html](https://{上記clusters/endpoint}/static/index.html)

すると以下の様なKubernetesのWeb UIが表示されます。
![ kubewebui.png](https://qiita-image-store.s3.amazonaws.com/0/2965/741a0d1b-856d-a46f-e31d-ec1f062c675c.png " kubewebui.png")

まだpods(≒Dockerコンテナ)を起動していないので何も表示されませんね。

### Pods等を立ち上げてみる

次にPods等のkubernetesリソースを立ち上げてみます。
Kubernetesではjsonやyamlで各種設定ファイルを書き、kubernetesのmasterにAPI(CLI)経由でそれを渡します。

サンプルは[KubernetesのRepository](https://github.com/GoogleCloudPlatform/kubernetes/tree/e7922489ac7b9879d4175fb46ba3a9914f4bf1ac/examples)にあるのでそれを使いましょう。

今回はKubernetesのsampleの一つ、[wakthrough](https://github.com/GoogleCloudPlatform/kubernetes/tree/e7922489ac7b9879d4175fb46ba3a9914f4bf1ac/examples/wakthrough)のそれぞれのリソース、pods、service、replicationControllerを立ち上げています。

#### Pods

まずPodsです。
PodsはKubernetesで使われるリソースの一つで、1ホスト上で立ち上がるDocker Container群を表します。(例えば1nginx,1td-agentを1つのpodsとして定義するとか)
上記ディレクトリ内にある`pod-with-http-healthcheck.yaml`を使ってみます。

```yaml:pod-with-http-healthcheck.yaml
kind: Pod
apiVersion: v1beta1
desiredState:
  manifest:
    version: v1beta1
    id: php
    containers:
      - name: nginx
        image: dockerfile/nginx
        ports:
          - containerPort: 80
        # defines the health checking
        livenessProbe:
          # turn on application health checking
          enabled: true
          type: http
          # length of time to wait for a pod to initialize
          # after pod startup, before applying health checking
          initialDelaySeconds: 30
          # an http probe
          httpGet:
            path: /_status/healthz
            port: 8080  


```

上記を作成し以下のコマンドを実行します。

```bash
$ gcloud preview container pods --cluster-name myfirstcluster create myfirstpods --config-file ../kubernetes/examples/walkthrough/pod-with-http-healthcheck.yaml --zone asia-east1-b
ID                                     Image(s)            Host                Labels              Status
----------                             ----------          ----------          ----------          ----------
93b0b023-64a4-11e4-9844-42010af05eba   dockerfile/nginx    <unassigned>                            Waiting

```

しばらく待ってから、以下のコマンドでpodsができていることを確認します。

```bash


$ gcloud preview container pods --cluster-name myfirstcluster list --zone asia-east1-b
ID                                     Image(s)            Host                                                                      Labels              Status
----------                             ----------          ----------                                                                ----------          ----------
93b0b023-64a4-11e4-9844-42010af05eba   dockerfile/nginx    k8s-myfirstcluster-node-1.c.kubernetes-sandbox.internal/130.211.251.206                       Running

```

できてそうですね。
WebUIでも見てみましょう。※自動更新はされないのでF5とか押して画面を更新して下さい！
![KubernetesWebUI-2.png](https://qiita-image-store.s3.amazonaws.com/0/2965/7604d7b6-c664-76e7-2081-405003a9ad9a.png "KubernetesWebUI-2.png")

![KubernetesWebUIDetail.png](https://qiita-image-store.s3.amazonaws.com/0/2965/a717239a-0cf8-2dd7-cd8b-4d2323cb90b3.png "KubernetesWebUIDetail.png")


いい感じで出来てそうですね

Podsを削除する場合は以下のようにします。

```bash
$ gcloud preview container pods --cluster-name myfirstcluster delete 93b0b023-64a4-11e4-9844-42010af05eba --zone asia-east1-b
```

#### ReplicationController

ReplicatoinControllerはKubernetes Cluster全体でのPodsの数を管理するリソースです。
例えばWeb Pods(nginxコンテナ + applicationコンテナ + tg-agentコンテナ)をKubernetes全体でいくつ立ち上げるかを制御できたりします。

これもwalkthrough内のreplication-controller.yamlを使ってみます。

```replication-controller.yaml
id: nginxController
apiVersion: v1beta1
kind: ReplicationController
desiredState:
  replicas: 2
  # replicaSelector identifies the set of Pods that this
  # replicaController is responsible for managing
  replicaSelector:
    name: nginx
  # podTemplate defines the 'cookie cutter' used for creating
  # new pods when necessary
  podTemplate:
    desiredState:
      manifest:
        version: v1beta1
        id: ngix
        containers:
          - name: nginx
            image: dockerfile/nginx
            ports:
              - containerPort: 80
    # Important: these labels need to match the selector above
    # The api server enforces this constraint.
    labels:
      name: nginx

```

※今(2014/11/05)現在のリポジトリに有るファイルだとエラーが出たので上のlabelsを若干修正しています。

これをGoogle Cloud SDK経由で食わせます。

```bash

$ gcloud preview container replicationcontrollers --cluster-name myfirstcluster create --config-file ./examples/walkthrough/replication-controller.yaml --zone asia-east1-b
ID                  Image(s)            Selector            Replicas
----------          ----------          ----------          ----------
nginxController     dockerfile/nginx    name=nginx          2
```


WebUIで確認してみましょう。

![webui-replicationController.png](https://qiita-image-store.s3.amazonaws.com/0/2965/b40700c7-2407-3cb6-bde4-d58a06d12874.png "webui-replicationController.png")


ReplicationControllerを作ったことにより、nginxControllerとnginxのpodsが2つ作成されていますね。

ちなみにKubernetesのCLIを利用するとこのpodsの数をCLIから変更したり、ローリングアップデートしたりできるのですが、どうもGoogle Cloud SDKのやり方は見つからないです...
無いかも？？

削除する場合は以下のようにします。
※実際には後で使うので消しません。

```bash
gcloud preview container replicationcontrollers --cluster-name myfirstcluster delete nginxController --zone asia-east1-b
```


#### Service

ServiceはKubernetes内部で使うネットワークプロキシで、Kubernetes Cluster内のLBとしての役割にもなります。

コレも同じようにwalkthrough内のservice.yamlを使ってみます。

```yaml:service.yaml
kind: Service
apiVersion: v1beta1
id: nginx-example
# the port that this service should serve on
port: 8000
# just like the selector in the replication controller,
# but this time it identifies the set of pods to load balance
# traffic to.
selector:
  name: nginx
# the container on each pod to connect to, can be a name
# (e.g. 'www') or a number (e.g. 80)
containerPort: 80
```

```bash
$ gcloud preview container services --cluster-name myfirstcluster create --config-file ./examples/walkthrough/service.yaml --zone asia-east1-b
ID                  Labels              Selector            Port
----------          ----------          ----------          ----------
nginx-example                           name=nginx          8000

```

ちなみにこれだけだとkubernes内部の通信でしか使えません。
感覚的にはdockerのlink機能などと同じで、それぞれのpodsに対して上記のポートやIP(今はまだ対応していなかった気がしますが)を環境変数として与えてくれます。

外向けのLBを作りたい場合はservice.yamlにて`createExternalLoadBalancer`オプションを使います。

```yaml:service-external.yaml
kind: Service
apiVersion: v1beta1
id: nginx-example
port: 8000
selector:
  name: nginx
containerPort: 80
createExternalLoadBalancer: true
```

```bash
$ gcloud preview container services --cluster-name myfirstcluster create --config-file ./examples/walkthrough/service-external.yaml --zone asia-east1-b
ID                  Labels              Selector            Port
----------          ----------          ----------          ----------
nginx-example2                           name=nginx          8000

```

これで外部向けのLBが作成されました。
実際にはGCEのLoadBalancerが作成されています。
ターゲットグループにも対象のnodeが含まれている状態になります。

![LB.png](https://qiita-image-store.s3.amazonaws.com/0/2965/72fad7f2-019e-89d1-bcd7-2a37db771415.png "LB.png")


これでもろもろ完成です。


## 所感

Kubernetesを触ってた人からすると感覚としては、
GCEに対するKuberntesのOne-Click Deploy + Google Cloud SDKへのkubecfgの統合 + cluster周りのAPI
というイメージがわかりやすいです。

現状だと`kubecfg --proxy`や`kubecfg run`、`kubecfg resize`、`kubecfg rollingupdate`などがCloud SDK側で未サポートっぽいので今後に期待ですね。
※kubecfg経由ではやれると思います。

何にせよ、Kubernetesがちゃんとしたサービス上でも使われてそれがKubernetes側にフィードバックされるのであれば非常に良いですね。