お試しk3s


# 概要
Kubernetesに軽量版があるということなので、触ってみる。Kubernetes本体はインストールも結構難しく、リソースも必要ということなので放置していたので、そもそもKubernetesの知識もない前提。
今回はCentOS7上にk3sをインストールして触ってみる。
[公式](https://github.com/rancher/k3s)

# 環境用意
Windowsマシン上のVirtualBox + VagrantでCentOSを用意する。

```shell-session
# VagrantにてCentOSを作成
2019/03/26 14:02:51|C:\Vagrant>mkdir CentOS7_k3s
2019/03/26 14:03:18|C:\Vagrant>cd CentOS7_k3s
2019/03/26 14:27:37|C:\Vagrant\CentOS7_k3s>vagrant init centos/7
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

2019/03/26 14:28:13|C:\Vagrant\CentOS7_k3s>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos/7'...
==> default: Matching MAC address for NAT networking...
(中略)
# 起動したら、SSHでログインし、SSHDの設定を変更する
# 通常のターミナルソフトから、rootのパスワード認証でログインできるように
2019/03/26 14:32:32|C:\Vagrant\CentOS7_k3s>vagrant ssh
[vagrant@iritokeefd3d1c ~]$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
[vagrant@iritokeefd3d1c ~]$ sudo vi /etc/ssh/sshd_config
[vagrant@iritokeefd3d1c ~]$ sudo diff /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
49c49
< PermitRootLogin yes
---
> #PermitRootLogin yes
79c79
< PasswordAuthentication yes
---
> PasswordAuthentication no
[vagrant@iritokeefd3d1c ~]$
[vagrant@iritokeefd3d1c ~]$ exit
logout
Connection to 127.0.0.1 closed.
```

この後、Vagrantfileに以下を追記してボックスのリロード。`vagrant relaod`

```txt:Vagrantfile
  config.vm.network "forwarded_port", guest: 22, host: 2222
  config.ssh.username = 'root'
  config.ssh.password = 'vagrant'
  config.ssh.insert_key = 'true'
```

これでローカルホスト(127.0.0.1)のポート2222にSSH接続できる状態になった。

# k3sのインストール
[公式QuickStart](https://github.com/rancher/k3s#quick-start)を参考に。
ただし、公式はいきなりk3s serverを実行しているが、実際には

1. 実行権限付与
2. パスを通す

の操作が必要。

```shell-session
[root@iritokeefd3d1c ~]#
# ディレクトリを作ってモジュールをダウンロード
[root@iritokeefd3d1c ~]# mkdir /opt/k3s/
[root@iritokeefd3d1c ~]# cd /opt/k3s/
[root@iritokeefd3d1c k3s]# curl -LJO https://github.com/rancher/k3s/releases/download/v0.2.0/k3s
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   594    0   594    0     0    226      0 --:--:--  0:00:02 --:--:--   226
100 35.9M  100 35.9M    0     0   485k      0  0:01:15  0:01:15 --:--:--  553k
curl: Saved to filename 'k3s'
[root@iritokeefd3d1c k3s]# file k3s
k3s: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# ls -l
total 36852
-rw-r--r--. 1 root root 37735552 Mar 26 06:47 k3s
# 公式はいきなりk3s serverを実行しているが、実際には①実行権限付与、②パスを通す、が必要
[root@iritokeefd3d1c k3s]# chmod +x k3s
[root@iritokeefd3d1c k3s]# export PATH=$PATH:/opt/k3s/
[root@iritokeefd3d1c k3s]# k3s server &
# (中略)
Flag --allow-privileged has been deprecated, will be removed in a future version
INFO[2019-03-26T06:50:39.958073107Z] waiting for node iritokeefd3d1c.corp.emc.com: nodes "iritokeefd3d1c.corp.emc.com" not found
INFO[2019-03-26T06:50:41.963996277Z] waiting for node iritokeefd3d1c.corp.emc.com CIDR not assigned yet
INFO[2019-03-26T06:50:43.969248701Z] waiting for node iritokeefd3d1c.corp.emc.com CIDR not assigned yet
INFO[2019-03-26T06:50:45.976069630Z] waiting for node iritokeefd3d1c.corp.emc.com CIDR not assigned yet
INFO[2019-03-26T06:50:47.977725922Z] waiting for node iritokeefd3d1c.corp.emc.com CIDR not assigned yet
INFO[2019-03-26T06:50:49.981015468Z] waiting for node iritokeefd3d1c.corp.emc.com CIDR not assigned yet
# Enter押さないとプロンプト返らない
[root@iritokeefd3d1c k3s]
[root@iritokeefd3d1c k3s]# k3s kubectl get node
NAME                          STATUS   ROLES    AGE     VERSION
iritokeefd3d1c.corp.emc.com   Ready    <none>   4m12s   v1.13.4-k3s.1
```

# テスト用コンテナのデプロイ
何もわからないので、とりあえず`k3s kubectl run --help`を確認してそこにある例を実行してみる。


```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl run hazelcast --image=hazelcast --port=5701
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/hazelcast created
[root@iritokeefd3d1c k3s]#
# Pod: 通常のDockerでいうコンテナ
[root@iritokeefd3d1c k3s]# k3s kubectl get pod -o wide
NAME                         READY   STATUS             RESTARTS   AGE     IP          NODE                          NOMINATED NODE   READINESS GATES
hazelcast-76c4785db6-zf4qc   0/1     ImagePullBackOff   0          3m12s   10.42.0.4   iritokeefd3d1c.corp.emc.com   <none>           <none>
```

コマンド上はうまくいっているが、正しく起動していない。podの詳細を確認してトラブルシュートするには、describeコマンドを使用する。

```shell-session
# podの詳細確認はdescribe
[root@iritokeefd3d1c k3s]# k3s kubectl describe pods/hazelcast-76c4785db6-zf4qc
Name:               hazelcast-76c4785db6-zf4qc
# (中略)
Containers:
  hazelcast:
    Container ID:
    Image:          hazelcast
    Image ID:
    Port:           5701/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ImagePullBackOff
    Ready:          False
# (中略)
Events:
  Type     Reason     Age                    From                                  Message
  ----     ------     ----                   ----                                  -------
  Normal   Scheduled  6m56s                  default-scheduler                     Successfully assigned default/hazelcast-76c4785db6-zf4qc to iritokeefd3d1c.corp.emc.com
  Normal   Pulling    5m16s (x4 over 6m56s)  kubelet, iritokeefd3d1c.corp.emc.com  pulling image "hazelcast"
  Warning  Failed     5m14s (x4 over 6m53s)  kubelet, iritokeefd3d1c.corp.emc.com  Failed to pull image "hazelcast": rpc error: code = Unknown desc = failed to resolve image "docker.io/library/hazelcast:latest": no available registry endpoint: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
  Warning  Failed     5m14s (x4 over 6m53s)  kubelet, iritokeefd3d1c.corp.emc.com  Error: ErrImagePull
  Normal   BackOff    5m2s (x6 over 6m53s)   kubelet, iritokeefd3d1c.corp.emc.com  Back-off pulling image "hazelcast"
  Warning  Failed     104s (x20 over 6m53s)  kubelet, iritokeefd3d1c.corp.emc.com  Error: ImagePullBackOff
```

イメージがなかったらしい。(もっと早い段階で失敗してほしいが)
hazelcastのdocker hubを見ると、イメージの指定が不足していたので、もう一度。名前をtest-hazelcastに変更して実行。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl run test-hazelcast --image=hazelcast/hazelcast --port=5701
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/test-hazelcast created
[root@iritokeefd3d1c k3s]# k3s kubectl get pod
NAME                             READY   STATUS              RESTARTS   AGE
hazelcast-76c4785db6-nd2zq       0/1     ErrImagePull        0          105s
test-hazelcast-f7489c598-rqs9j   0/1     ContainerCreating   0          9s
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pod -o wide
NAME                             READY   STATUS              RESTARTS   AGE    IP          NODE                          NOMINATED NODE   READINESS GATES
hazelcast-76c4785db6-nd2zq       0/1     ImagePullBackOff    0          116s   10.42.0.5   iritokeefd3d1c.corp.emc.com   <none>           <none>
test-hazelcast-f7489c598-rqs9j   0/1     ContainerCreating   0          20s    <none>      iritokeefd3d1c.corp.emc.com   <none>           <none>
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pod -o wide
NAME                             READY   STATUS             RESTARTS   AGE     IP          NODE                          NOMINATED NODE   READINESS GATES
hazelcast-76c4785db6-nd2zq       0/1     ImagePullBackOff   0          2m23s   10.42.0.5   iritokeefd3d1c.corp.emc.com   <none>           <none>
test-hazelcast-f7489c598-rqs9j   1/1     Running            0          47s     10.42.0.6   iritokeefd3d1c.corp.emc.com   <none>           <none>
[root@iritokeefd3d1c k3s]# ss -ant | grep 5701
[root@iritokeefd3d1c k3s]#
```

今度は正しく起動したが、5701で外部にエクスポートされていない。
またtest-なしのものが残っていることに気が付く。いったん消す。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
NAME                             READY   STATUS             RESTARTS   AGE
hazelcast-76c4785db6-wqxc6       0/1     ImagePullBackOff   0          2m48s
test-hazelcast-f7489c598-j4wx9   1/1     Running            0          36s
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl delete pod hazelcast-76c4785db6-wqxc6
pod "hazelcast-76c4785db6-wqxc6" deleted
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
NAME                             READY   STATUS         RESTARTS   AGE
hazelcast-76c4785db6-lh8sk       0/1     ErrImagePull   0          7s
test-hazelcast-f7489c598-j4wx9   1/1     Running        0          4m36s
```

消しても消えないので、ちゃんと調べたところ、作成したのは実はPodではなく、deploymentという単位で、設定上セルフヒーリングされていた。
すなわち、deployment内のPodの最低数が決まっており、その数以下になると追加される。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl get deployments -o wide
NAME             READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS       IMAGES                SELECTOR
hazelcast        0/1     1            0           26m     hazelcast        hazelcast             run=hazelcast
test-hazelcast   1/1     1            1           8m59s   test-hazelcast   hazelcast/hazelcast   run=test-hazelcast
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl describe deployments test-hazelcast
Name:                   test-hazelcast
Namespace:              default
CreationTimestamp:      Tue, 26 Mar 2019 10:34:32 +0000
Labels:                 run=test-hazelcast
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               run=test-hazelcast
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=test-hazelcast
  Containers:
   test-hazelcast:
    Image:        hazelcast/hazelcast
    Port:         5701/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   test-hazelcast-f7489c598 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  10m   deployment-controller  Scaled up replica set test-hazelcast-f7489c598 to 1
```

いったんdeploymentを全て削除しておく。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl delete deployments test-hazelcast
deployment.extensions "test-hazelcast" deleted
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl delete deployments hazelcast
deployment.extensions "hazelcast" deleted
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
No resources found.
[root@iritokeefd3d1c k3s]# k3s kubectl get deployment
No resources found.
```

まずは再作成。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl run test-hazelcast --image=hazelcast/hazelcast --port=5701
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/test-hazelcast created
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
test-hazelcast-f7489c598-qdsjw   1/1     Running   0          14s
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get deployments
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
test-hazelcast   1/1     1            1           23s
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# ss -ant | grep 5701
```

先と同様にこの状態では外部からアクセスできない。
外部からアクセスできるようにするにはserviceという構造を使用するらしい。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl expose deployment test-hazelcast --port 5701
service/test-hazelcast exposed
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# ss -ant | grep 5701
TIME-WAIT  0      0      10.42.0.1:57018              10.42.0.3:8080
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# ss -ant | grep 5701
TIME-WAIT  0      0      10.42.0.1:57018              10.42.0.3:8080
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get svc
NAME             TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes       ClusterIP   10.43.0.1     <none>        443/TCP    4h17m
test-hazelcast   ClusterIP   10.43.14.35   <none>        5701/TCP   46s
```

serviceを作成すると、確かに5701でエクスポートしているが、ノードのIPではない。
ノードでエクスポートするには、オプションを指定する必要があったらしい。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl expose deployment test-hazelcast --port 5701 --type NodePort --name test-hazelcast-node
service/test-hazelcast-node exposed
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.43.0.1       <none>        443/TCP          4h43m
test-hazelcast        ClusterIP   10.43.14.35     <none>        5701/TCP         26m
test-hazelcast-node   NodePort    10.43.200.137   <none>        5701:31711/TCP   17s

[root@iritokeefd3d1c k3s]# ss -ant | grep 5701
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# ss -ant | grep 31711
LISTEN     0      128         :::31711                   :::*
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# curl http://localhost:31711


ping ^C
[root@iritokeefd3d1c k3s]#
```

このイメージの動作確認方法が不明だが、一応curlコマンドは失敗しない。ssで確認してもIPv6でListenしているように見えるが…、これは正しい挙動らしい。
[こちら](https://qiita.com/fetaro/items/d5164ba8271114d8a0c8)
またそもそも、--portで指定したポートは、外向けに公開されるポートではない…。こちらの指定方法は別途調べる。

# おまけ
そもそも、作成時に、以下のように警告されるが、createコマンドを使用すると、jsonファイルなどの記載を元にサービスなどを作成できるらしい。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl run test-hazelcast --image=hazelcast/hazelcast --port=5701
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
```

helpにはそう書いてあるが、実際はrunと同じ書き方で作成できる。

```shell-session
[root@iritokeefd3d1c k3s]# k3s kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
NAME                             READY   STATUS              RESTARTS   AGE
nginx-5c7588df-6649t             0/1     ContainerCreating   0          12s
test-hazelcast-f7489c598-qdsjw   1/1     Running             0          45m
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
nginx-5c7588df-6649t             1/1     Running   0          34s
test-hazelcast-f7489c598-qdsjw   1/1     Running   0          45m
[root@iritokeefd3d1c k3s]#
[root@iritokeefd3d1c k3s]# k3s kubectl expose deployment nginx --type NodePort --port 80
service/nginx exposed
[root@iritokeefd3d1c k3s]# k3s kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.43.0.1       <none>        443/TCP          4h59m
nginx                 NodePort    10.43.198.228   <none>        80:30917/TCP     8s
test-hazelcast        ClusterIP   10.43.14.35     <none>        5701/TCP         42m
test-hazelcast-node   NodePort    10.43.200.137   <none>        5701:31711/TCP   16m
[root@iritokeefd3d1c k3s]# curl http://10.0.2.15:30917
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@iritokeefd3d1c k3s]#
```

# 今後の課題

- ネットワーク構造が意味不明なので、探究する
- ユースケースを探す