フレームワークとしての Kubernetes

このエントリーは [Kubernetes Advent Calendar](http://qiita.com/advent-calendar/2016/kubernetes) 2016の12日目の記事です。
今回は Kubernetes を分散システムのフレームワークとして利用する方法について紹介しようと思います。

# ThirdPartyResource

まずフレームワークとしての利用方法の前にそれを実現するために利用する ThirdPartyResource について簡単に紹介します。
ThirdPartyResource(TPR) は Kubernetes のオブジェクト (Pod, Service, Node等)の一つです。
TPR は Kubernetes API を新しいオブジェクト型で拡張する方法を提供します。
TPR オブジェクトを追加することでユーザ独自の新しいオブジェクト型の API を追加することができます。このユーザ独自の新しいオブジェクト型の API は CRUD の操作と watch をサポートしています。
つまり TPR を利用することでユーザ独自のリソース の WebAPI、データストアを簡単に用意することができます。

# ThirdPartyResource の利用方法

ThirdPartyResource はオブジェクトの一つなので Pod などと同じようにリソースの定義ファイルを用意します。

```tpr.yml
apiVersion: extensions/v1beta1
kind: ThirdPartyResource
metadata:
  name: hello-world.example.com
description: "hello world object"
versions:
- name: v1
```

ファイルができたら TPR を作成します。

```
$ kubectl create -f tpr.yml
thirdpartyresource "hello-world.example.com" created
```

API を叩いてみるとエンドポイントが作成されていることがわかります。

```
$ kubectl proxy &
$ curl http://localhost:8001/apis/example.com
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "example.com",
  "versions": [
    {
      "groupVersion": "example.com/v1",
      "version": "v1"
    }
  ],
  "preferredVersion": {
    "groupVersion": "example.com/v1",
    "version": "v1"
  },
  "serverAddressByClientCIDRs": null
}
$ curl http://localhost:8001/apis/example.com/v1
{
  "kind": "APIResourceList",
  "apiVersion": "v1",
  "groupVersion": "example.com/v1",
  "resources": [
    {
      "name": "helloworlds",
      "namespaced": true,
      "kind": "HelloWorld"
    }
  ]
}
```

# client-go

次にこの作成された TPR の API を利用してアプリケーションを作成します。
アプリケーションを golang で作成する場合は kubernetes のクライアント部分だけが切り離された [client-go](https://github.com/kubernetes/client-go) を利用すると良いと思います。
client-go には Kubernetes へアクセスするために様々なライブラリが用意されており、これを利用することで簡単にアクセスできます。

https://github.com/kubernetes/client-go/tree/master/examples にいくつかサンプルが用意されていますが、TPR を操作する例は以下のようになっています。

```https://github.com/kubernetes/client-go/blob/master/examples/third-party-resources/main.go#L79
	err = tprclient.Get().
		Resource("examples").
		Namespace(api.NamespaceDefault).
		Name("example1").
		Do().Into(&example)
```

```https://github.com/kubernetes/client-go/blob/master/examples/third-party-resources/main.go#L99
	err = tprclient.Post().
		Resource("examples").
		Namespace(api.NamespaceDefault).
		Body(example).
		Do().Into(&result)
```

TPR の場合標準リソースとは異なり専用の client が用意されておらず若干手間がかかりますが、このように TPR を利用することで簡単にデータストアと WebAPIを用意でき、それを利用したライブラリを使って分散システムを構築できます。また、作成したアプリケーションをそのまま Kubernetes 上へデプロイできるので開発者はアプリケーションのロジック部分の開発に集中することできます。

複雑なアプリケーションを作成する場合は　Kubernetes　の ControllerManager で利用されている InformerFramework を利用することもできます。InformerFramework を利用すると Kubernetes Like なリソースを監視してリソースの変更に対して操作を行うようなシステムを比較的簡単に作成することができます。ただ InformerFramework で TPR を利用するには Kubernetes では自動生成されている API Client のコードを用意する必要があり、まだ若干手間がかかります。この方法についてはまた機会があれば紹介します。

# おわりに

Kubernetes の TPR を用いて Kubernetes をフレームワークとして利用する方法を紹介しました。この方法は最近では　CoreOS の Operator など様々なところで利用され始めていて注目を集めています。
TPR は　`kubectl edit`や`kubectl apply`ができない、client の generator がないなどまだまだ多くの課題がありますが、TPR を有効に活用できると Kubernetes の世界も広がるため引き続き動向を追っていきたいと思います。

# 参考

http://kubernetes.io/docs/user-guide/thirdpartyresources/
https://github.com/kubernetes/client-go
https://github.com/coreos/etcd-operator