貧者の GKE / 無料枠だけでクラスタを作ろう


**Deprecated: この記事の内容は既に2年以上経過しており、有用なものではなくなっていると考えられます。無料枠だけでクラスタを動かすことができても GKE のシステムコンポーネントの削減には限界があり、実用的ではありません。**

Google Cloud Next '17 で [GCP 無料枠の拡大](https://cloud.google.com/free/)が発表された。
特に注目なのは US リージョンに限るが GCE f1-micro 1インスタンス, 30 GB の HDD が永続で無料なことだろう。 
GKE は5ノードまではマスタの課金はなく、ノードは GCE ノードとして課金されるので、この恩恵が受けられるはずだ。

## 検証環境

Kubernetes 1.5.4
Google Cloud SDK 148.0.1

## 挫折

普通にクラスタを作ろうとすると下記のようなエラーで弾かれる。

```
$ gcloud container clusters create --zone=us-central1-a --machine-type=f1-micro --disk-size=30 --num-nodes=1 free-cluster
ERROR: (gcloud.container.clusters.create) ResponseError: code=400, message=Clusters of f1-micro instances must contain at least 3 nodes. Please make the cluster larger or use a different machine type.
```

f1-micro は3ノード以上にするか、他のマシンタイプを使えと言われてしまう。
f1-micro 3ノードにした場合、2ノード分を支払うことになるが、それでは g1-small や Commited use discounts を受けた `n1-standard-1` に対するメリットが無くなる。

## 解決

とりあえず3ノードで作成してみる。

```
$ gcloud container clusters create --zone=us-central1-a --machine-type=f1-micro --disk-size=30 --num-nodes=3 free-cluster
Creating cluster free-cluster...done.
Created [https://container.googleapis.com/v1/projects/apstndb-sandbox/zones/us-central1-a/clusters/free-cluster].
kubeconfig entry generated for free-cluster.
NAME          ZONE           MASTER_VERSION  MASTER_IP        MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
free-cluster  us-central1-a  1.5.4           130.211.174.186  f1-micro      1.5.4         3          RUNNING
```

ここでおもむろにクラスタサイズを1にリサイズしてみると、通ってしまう。

```
$ gcloud container clusters resize free-cluster --zone=us-central1-a --size=1
Pool [default-pool] for [free-cluster] will be resized to 1.

Do you want to continue (Y/n)?  y

Resizing free-cluster...done.
Updated [https://container.googleapis.com/v1/projects/apstndb-sandbox/zones/us-central1-a/clusters/free-cluster].
```

f1-micro 1ノードのクラスタができた。これならきっと無料になるはずだ。

```
$ gcloud container clusters list
NAME            ZONE               MASTER_VERSION  MASTER_IP        MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
free-cluster    us-central1-a      1.5.4           130.211.174.186  f1-micro      1.5.4         1          RUNNING
```

### 別解

実は、 GKE クラスタのノードプールを削除すると0ノードのクラスタにすることができる。

```
$ gcloud container node-pools delete default-pool --zone=us-central1-a --cluster=free-cluster
The following node pool will be deleted.
[default-pool] in cluster [free-cluster] in zone [us-central1-a]

Do you want to continue (Y/n)?  y

Deleting node pool default-pool...done.
Deleted [https://container.googleapis.com/v1/projects/apstndb-sandbox/zones/us-central1-a/clusters/free-cluster/nodePools/default-pool].

$ gcloud container clusters list free-cluster
NAME            ZONE               MASTER_VERSION  MASTER_IP        MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
free-cluster    us-central1-a      1.5.4           130.211.174.186                1.5.4                    RUNNING
```

3ノード未満の f1-micro のクラスタを作ることができない制限はノードプール作成時にはチェックされない。

```
$ gcloud container node-pools create default-pool --cluster=free-cluster \
    --disk-size=30 --machine-type=f1-micro --num-nodes=1 --zone=us-central1-a
Creating node pool default-pool...done.
Created [https://container.googleapis.com/v1/projects/apstndb-sandbox/zones/us-central1-a/clusters/free-cluster/nodePools/default-pool].
NAME          MACHINE_TYPE  DISK_SIZE_GB  NODE_VERSION
default-pool  f1-micro      30            1.5.4
```

この方法でも f1-micro 1ノードだけのクラスタを作ることができた。

```
% gcloud container clusters list
NAME            ZONE               MASTER_VERSION  MASTER_IP        MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
free-cluster    us-central1-a      1.5.4           130.211.174.186  f1-micro      1.5.4         1          RUNNING
```

## リソース

起動したクラスタに接続し、 Pod を確認してみよう。

```
$ gcloud container clusters get-credentials free-cluster --zone=us-central1-a
Fetching cluster endpoint and auth data.
kubeconfig entry generated for free-cluster.

$ kubectl get pod --all-namespaces
NAMESPACE     NAME                                                                READY     STATUS    RESTARTS   AGE
kube-system   fluentd-cloud-logging-gke-free-cluster-default-pool-fc901d64-db1f   1/1       Running   0          8m
kube-system   heapster-v1.2.0.1-1382115970-dq43k                                  0/2       Pending   0          16m
kube-system   kube-dns-4101612645-tg7t4                                           4/4       Running   0          20m
kube-system   kube-dns-autoscaler-2715466192-5b6r8                                1/1       Running   0          16m
kube-system   kube-proxy-gke-free-cluster-default-pool-fc901d64-db1f              1/1       Running   0          9m
kube-system   kubernetes-dashboard-3543765157-z31pv                               1/1       Running   0          16m
kube-system   l7-default-backend-2234341178-3p94b                                 1/1       Running   0          16m
```

`heapster` Pod が Pending になっている。
原因を `kubectl describe pod` で確認してみよう。

```
$ kubectl describe pod --namespace kube-system heapster-v1.2.0.1-1382115970-dq43k
(省略)
Events:
  FirstSeen     LastSeen        Count   From                    SubObjectPath   Type            Reason                  Message
  ---------     --------        -----   ----                    -------------   --------        ------                  -------
  20m           13m             29      {default-scheduler }                    Warning         FailedScheduling        no nodes available to schedule pods
  12m           1s              47      {default-scheduler }                    Warning         FailedScheduling        pod (heapster-v1.2.0.1-1382115970-dq43k) failed to fit in any node
fit failure summary on nodes : Insufficient memory (1)
  20m   0s      121     {rescheduler }          Normal  PodDoestFitAnyNode      Critical pod kube-system_heapster-v1.2.0.1-1382115970-dq43k doesn't fit on any node.
```

どうやら f1-micro の 0.6 GB のメモリではデフォルトで起動される Pod を全て起動することもできないようだ。

このままでは何も起動できないので、「[GKE でアドオンを削ったクラスタを起動する](http://qiita.com/apstndb/items/1c3f8ea026ed6b27e357)」を参考にどうにか空きを作ることを検討しよう。

## まとめ

- 無料枠の GCE インスタンスだけでも GKE クラスタは作成可能
	- リサイズ
	- ノードプールの削除＆作成
- f1-micro 1ノードではデフォルトの設定で起動される全 Pod の起動は不可能
	- 頑張ってダイエット！