Kube-Soloを使ってPodとService作ってみる

# 概要

Kubernetesをmacローカルで動かすにはVagrantを使った方法もありますが、kube-soloを使ったやり方が簡単そうだったので、ご紹介します。
macへのインストールからnginxコンテナが1つ入ったPodを作成し、Podへ外部から接続するServiceを作成するところまでカバーします。

# 前提
このポストは、Kubernetesとその概念（Node, Pod, Service）やDockerに関しては最低限の理解がある前提で進めます。
基礎的な概念について知りたい方はこちらから学ぶのが良いと思います。

[kubernetes入門コンテンツまとめ](http://qiita.com/techeten/items/73d299611c7ed03f5ca8)

# kube-soloとは

kube-soloとはステータスバーから操作でき、Macローカル上にCoreOSという軽量VMを動かした上でkubernetesの環境を簡単に作成できるツールです。
Docker for macに似ていますね。
corectlというステータスバーツールのラッパーとして作成されているようなので、corectlのインストールも必要です。


# ダウンロード＆インストール
まずはcorectlとkube-soloをそれぞれ下記サイトからdmgイメージを持ってきてインストールします。両方共/Applicationに置いてあげましょう。

- corectl ... https://github.com/TheNewNormal/corectl.app/releases
- kube-solo ... https://github.com/TheNewNormal/kube-solo-osx/releases

インストールが終わったら、アプリケーションフォルダからKube-Soloアイコンをクリックして起動しましょう。前提になっているcorectlもこのタイミングで起動されます。corectlが入っていない場合は警告が出てkube-soloが終了してしまうので、corectlをインストールしましょう。

kube-soloの起動が終わると、corectlとkube-soloのアイコンがそれぞれステータスバーに登場します。
まずはステータスバーのcorectlのアイコンをクリックして、「Server Status:Running」となっていることを確認します。

次に、kube-soloのアイコンから「Up」を選択します。
これでCoreOS上にkubernetesのクラスタが生成されます。
途中でVMのディスクサイズを聞かれますが、今回のデモでは10GBもあれば十分です。

```
Starting k8solo-01 VM ...

Data disk does not exist, it will be created now ...

Please type Data disk size in GBs followed by [ENTER]:
[default is 40]
```

20〜30秒ほど待つと、起動が完了します。

# Podの作成

次にnginxのコンテナが1つだけ入ったPodを作成しましょう。
pod-nginx.ymlというファイルを作成し、下記のように記述します。

```yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    labelName: nginx-label
  name: nginx-pod
spec:
  containers:
    - name: nginx-container
      image: nginx
      ports:
      - containerPort: 80
```

ファイルの中身について解説します。

- apiVersion ... kubernetesのAPIバージョンを指定しています
- kind ... yml内の定義が何を作るのかを指定しています。今回はPod
- metadata ... Podに付加する様々なメタデータ
    - labels ... Podに対して任意のキーバリューセットを定義します。今回はlabelNameを入れてますが、どんなキーバリューでも大丈夫です。ここは後でServiceとの紐付けで使います
    - name ... Podの名前。後で`get pod`等で表示する際の名前になります
- spec ... Podの内容を記述していきます
    - containers ... コンテナの情報
        - name ... コンテナ名
        - image ... イメージ名。この名前でDockerHub等からイメージを取得します
        - ports ... ポートの指定
            - containerPort ... コンテナが外部に晒すポート番号を指定

Podやcontainerについて指定可能な項目などは詳しくはレファレンスに載っています。
- https://kubernetes.io/docs/api-reference/v1.7/#pod-v1-core
- https://kubernetes.io/docs/api-reference/v1.7/#container-v1-core

ファイルが書き終わったらkubectlでPodを作成しましょう。
kubectlはkubernetesの基本的操作をするツールで、kube-soloをインストールすると一緒についてきます

```bash
$ kubectl create -f pod-nginx.yml
pod "nginx-pod" created
```

これでPodが作成されました。
1分ほど待った後にget podすると、立ち上がっていることがわかります

```
$ kubectl get pod
NAME        READY     STATUS    RESTARTS   AGE
nginx-pod   1/1       Running   0          1m
```

次に、describe podsでPodの内容を確認してみましょう。

```
$ kubectl describe pods nginx-pod
Name:		nginx-pod
Namespace:	default
Node:		k8solo-01/192.168.64.2
Start Time:	Mon, 31 Jul 2017 12:11:53 +0900
Labels:		<none>
Annotations:	<none>
Status:		Running
IP:		10.244.7.3
(以下略)
```

k8solo-01/192.168.64.2というCoreOSのNodeで、10.244.7.3というPod内のIPで起動していることがわかります。

ここで下記のようにcurlを飛ばしても、内部のnginxにはアクセスできません

```
$ curl http://192.168.64.2
curl: (7) Failed to connect to 192.168.64.2 port 80: Connection refused
```

これは、nginxはPod内のコンテナとして起動はされているものの、VMの外のネットワークへはまだアクセスできるようになっていないためです。後でServiceを作ってアクセスできるようにしましょう。
ここではksoloというVMへアクセスするツールを使ってVMにssh接続してみます

```
$ ksolo ssh
Last login: Sat Jul 29 02:38:04 UTC 2017 from 192.168.64.1 on pts/0
Container Linux by CoreOS stable (1409.7.0)
Update Strategy: No Reboots
Failed Units: 1
  update-engine-stub.service
core@k8solo-01 ~ $
```

VMに接続できました。ではここで、describeで得られていたPodのIPに向けてcurlを打ちましょう

```
$ curl http://10.244.7.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
(以下略)
```

nginxからWelcomeのHTMLが返ってきました。
nginxは正常に起動していて、VMの内部からはアクセスできるようになっています。
では次にServiceを作成して、VMの外からもnginxにアクセスできるようにしましょう。
VMからはexitで出ておきましょう。

# Serviceの作成

ではServiceの内容を、service-node.ymlに記述していきます。

```
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  selector:
    labelName: nginx-label
  type: NodePort
  ports:
    - protocol: TCP
      targetPort: 80
      port: 80
      nodePort: 31707
      name: http
```

- selector ... どのPodについてのサービスかを指定します。ここでPodの記述に使ったlabelsのキーバリューを参照させます
- type ... どのようにPod内のコンテナを外部に晒すかを指定します。NodePortと指定すると、Nodeの特定ポートを介して公開するようにできます。
- ports
    - protocol ... 公開に利用するプロトコル
    - targetPort ... Dockerコンテナが公開しているポート
    - port ... VM内からPodへ接続するポート
    - nodePort ... Node外部からのアクセスに利用するNodeで公開するポート
    - name ... ポートの名前

ではServiceを作成しましょう。

```
$ kubectl create -f service-node.yml
service "test-service" created
```

ちゃんとできているか中身を見てみます。

```
$ kubectl describe services test-service
Name:			test-service
Namespace:		default
Labels:			<none>
Annotations:		<none>
Selector:		labelName=nginx-label
Type:			NodePort
IP:			10.100.31.29
Port:			http	80/TCP
NodePort:		http	31707/TCP
Endpoints:		10.244.8.3:80
Session Affinity:	None
Events:			<none>
```

できているようです。
では改めてcurlでアクセスしてみましょう。

```
$ curl http://192.168.64.2:31707
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
```

curlを使ってPod内のnginxにアクセスできました。
kube-soloを使うことでmacローカル上でも比較的軽量にkubernetesを試せるので、開発に役立ちそうですね。

# 参考サイト
- [Run Kubernetes on a Mac with Kube Solo](https://deis.com/blog/2016/run-kubernetes-on-a-mac-with-kube-solo/)
- [Kubernetes の学習 (2) ～ Pod の作成](http://qiita.com/Arturias/items/62499b961b5d7375f608#3-%E8%A4%87%E6%95%B0%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92%E5%90%AB%E3%82%80-pod-%E3%81%AE%E4%BD%9C%E6%88%90)
- [kubernetesでjenkinsを立てる
](http://qiita.com/suzukihi724/items/5e16855c3941e629ff70)