仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

JujuでCalicoを使ったKubernetes環境を構築する(後編)

前編はこちらです。

tech.virtualtech.jp

前編ではKubernetes MasterとWorkerの2台構成の環境を作りました。後編ではまずWorkerノードを増やしてみます。 Jujuでアプリケーションを構築した場合、ノードを追加してスケールするのは簡単にできます。

前編と同様、Juju CloudとしてMAASを使った場合を例とします。

スケールの拡大(ノードの追加)

ノードを増やすにはGUIで行う方法と、コマンドラインで行う方法があります。 次のようなコマンドを実行するだけです。

一行目では、MAASのノードに「node2」というタグを振ったノードを新たなJuju machineとして追加しています。 juju add-machineコマンドを実行するとMAAS API経由で該当のノードの電源を入れて、Ubuntuをデプロイします。鍵認証でログインできるようにするため、公開鍵を該当のノードに転送します(~/.local/share/juju/ssh/にあるキーペアを利用します)。

二行目では、Juju Machine 2にkubernetes-workerを2つ目のユニットとして 追加しています。

すでにあるユニットを拡大するにはjuju deployコマンドではなく、juju add-unitコマンドを実行します。 実行するまえにJuju Machine番号を確認しておいてください。

% juju add-machine --constraints "arch=amd64 tags=node2"
% juju machines
Machine  State    DNS            Inst id  Series  AZ       Message
0        started  172.17.28.110  cnep3s   xenial  default  Deployed
1        started  172.17.28.104  6gchhg   xenial  default  Deployed
2        started  172.17.28.105  e3ye8t   xenial  default  Deployed

% juju add-unit kubernetes-worker --to 2

デプロイの状況はjuju debug-logコマンドやjuju statusコマンドを確認します。 デプロイが完了すると、Kubernetes Dashboardに新たなノードとして追加されます。

f:id:virtualtech:20180615163358p:plain

ラベルの確認

Kubernetesというよりクラウド全般はどこのノードでコンテナーないし仮想マシンが動いているかは意識する必要はありません。 外部からアクセスする手段があれば、なんとかなるからです。

今回はあえてコンテナーを動かすホストを固定して、ホストまたぎのPod間通信を確認するためにKubernetes Workerノードに定義されたラベルを確認します。これらのラベルはいくつかビルトインのものが定義されます。任意のラベルを設定することもできます。

次のようなコマンドでKubernetesノードのラベルを確認します。 kubernetes.io/hostnameがノードの識別に使えそうであることがわかります。

% kubectl get no --show-labels
NAME         STATUS    ROLES     AGE       VERSION   LABELS
110gen9      Ready     <none>    1d        v1.10.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,cuda=true,gpu=true,juju-application=kubernetes-worker,kubernetes.io/hostname=110gen9
bl460cg7n6   Ready     <none>    12m       v1.10.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,juju-application=kubernetes-worker,kubernetes.io/hostname=bl460cg7n6

Pod作成のためのYAMLの準備

各WorkerノードにPodを作るため、nodeSelectorを使います。次のようなYAMLを用意します。 前編で作ったYAMLにnodeSelectorを追加しただけのYAMLです。

% cat pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
    - name: ubuntu
      image: ytooyama/ubuntu-redis:latest
      tty: true

  nodeSelector:
    kubernetes.io/hostname: 110gen9

% cat pod2.yml
apiVersion: v1
kind: Pod
metadata:
  name: ubuntu2
spec:
  containers:
    - name: ubuntu2
      image: ytooyama/ubuntu-redis:latest
      tty: true

  nodeSelector:
    kubernetes.io/hostname: bl460cg7n6

Podの起動

Podを起動してみます。

% kubectl create -f pod1.yml
% kubectl create -f pod2.yml

IPアドレスを確認してみます。 別々のネットワークのIPアドレスを取得していることがわかります。

% kubectl exec -it ubuntu -- busybox ip a|grep eth0
3: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    inet 192.168.44.36/32 scope global eth0
% kubectl exec -it ubuntu2 -- busybox ip a|grep eth0
3: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    inet 192.168.129.131/32 scope global eth0

pingとtracerouteによる疎通確認

ubuntuのPodからubuntu2にPingを飛ばしてみます。 パケロスする事なく、Pingが通りました。

% kubectl exec -it ubuntu -- busybox ping -c1 192.168.129.131
PING 192.168.129.131 (192.168.129.131): 56 data bytes
64 bytes from 192.168.129.131: seq=0 ttl=62 time=0.503 ms

--- 192.168.129.131 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.503/0.503/0.503 ms

簡易的ながら、経路をtracerouteで追ってみました。

% kubectl exec -it ubuntu -- busybox ip a|grep eth0
3: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    inet 192.168.44.36/32 scope global eth0

% kubectl exec -it ubuntu -- busybox traceroute -I 192.168.129.131
traceroute to 192.168.129.131 (192.168.129.131), 30 hops max, 46 byte packets
 1  110gen9.maas (172.17.28.104)  0.010 ms  0.006 ms  0.004 ms
 2  bl460cg7n6.maas (172.17.28.105)  0.286 ms  0.291 ms  0.220 ms
 3  192.168.129.131 (192.168.129.131)  0.278 ms  0.252 ms  0.214 ms

このことから、ubuntuコンテナーのIPアドレス(192.168.44.36)からコンテナーが起動しているKubernetes-workerノード0のホスト(172.17.28.104)から、Kubernetes-workerノード1のホスト(172.17.28.105)を経由して、ubuntu2コンテナーのIPアドレス(192.168.129.131)に到達していることがわかります。

iperf3を使ったベンチマーク

iperf3を使ってスループット値を計測してみます。 まずはiperf3のインストールから。

% kubectl exec -it ubuntu -- apt update -qq
% kubectl exec -it ubuntu -- apt install iperf3 -y -qq

% kubectl exec -it ubuntu2 -- apt update -qq
% kubectl exec -it ubuntu2 -- apt install iperf3 -y -qq

ubuntu2コンテナーをサーバーにして、ubuntuコンテナーから計測するため、次のようにコマンドを実行します。 計測を実行すると、ubuntu2の方にも出力がされますが、今回は省略します。

サーバーは1GbEで接続されています。これだけスループットがでれば良いでしょう。 リトライは発生していますが、TCP/IPによる通信なので特に問題はありません。

% kubectl exec -it ubuntu2 -- iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
...

% kubectl exec -it ubuntu -- iperf3 -c 192.168.129.134
Connecting to host 192.168.129.134, port 5201
[  4] local 192.168.44.37 port 40694 connected to 192.168.129.134 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec   114 MBytes   960 Mbits/sec   10   2.28 MBytes
[  4]   1.00-2.00   sec   111 MBytes   933 Mbits/sec    0   2.48 MBytes
[  4]   2.00-3.00   sec   112 MBytes   944 Mbits/sec   11   1.28 MBytes
[  4]   3.00-4.00   sec   111 MBytes   933 Mbits/sec    8    529 KBytes
[  4]   4.00-5.00   sec   112 MBytes   944 Mbits/sec    0    676 KBytes
[  4]   5.00-6.00   sec   111 MBytes   933 Mbits/sec    6    592 KBytes
[  4]   6.00-7.00   sec   111 MBytes   933 Mbits/sec    2    721 KBytes
[  4]   7.00-8.00   sec   111 MBytes   933 Mbits/sec    9    611 KBytes
[  4]   8.00-9.00   sec   112 MBytes   943 Mbits/sec    0    738 KBytes
[  4]   9.00-10.00  sec   111 MBytes   933 Mbits/sec    0    847 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  1.09 GBytes   939 Mbits/sec   46             sender
[  4]   0.00-10.00  sec  1.09 GBytes   937 Mbits/sec                  receiver

iperf Done.

iptablesを確認してみる

また次のように実行すると、Workerノードのiptablesにforwardingのルールが記述されていることがわかります。 grepコマンドを外せば全体のルールを確認できます。

% juju status calico
...
Unit                  Workload  Agent  Machine  Public address  Ports           Message
easyrsa/0*            active    idle   0        172.17.28.110                   Certificate Authority connected.
kubernetes-master/0*  active    idle   0        172.17.28.110   6443/tcp        Kubernetes master running.
  calico/0*           active    idle            172.17.28.110                   Calico is active
kubernetes-worker/0*  active    idle   1        172.17.28.104   80/tcp,443/tcp  Kubernetes worker running.
  calico/1            active    idle            172.17.28.104                   Calico is active
kubernetes-worker/1   active    idle   2        172.17.28.105   80/tcp,443/tcp  Kubernetes worker running.
  calico/2            active    idle            172.17.28.105                   Calico is active

% juju ssh calico/0 sudo iptables -L|grep 192.168.
Connection to 172.17.28.110 closed.

% juju ssh calico/1 sudo iptables -L|grep 192.168.
ACCEPT     all  --  192.168.0.0/16       anywhere             /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             192.168.0.0/16       /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED
Connection to 172.17.28.104 closed.

% juju ssh calico/2 sudo iptables -L|grep 192.168.
ACCEPT     all  --  192.168.0.0/16       anywhere             /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             192.168.0.0/16       /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED
Connection to 172.17.28.105 closed.

Jujuを使えばKubernetesをお試しする環境がすぐに作れます。 標準的に使われるFlannel構成のほか、Calicoを使った構成も簡単です。

以上、「JujuでCalicoを使ったKubernetes環境を構築する」の話題でした。