Help us understand the problem. What is going on with this article?

k3sをVagrantで構築する(3台構成)

More than 1 year has passed since last update.

はじめに

k3sという軽量なKubernetes環境があるということで、Vagrantで構築してみました。
Vagrantで構築する場合、ネットワーク設定(flannel)で注意点があるため記録を残します。

構成

以下のように、3台のUbuntu 16.04マシンをそれぞれ、master, node1, node2として構成し、Node間はプライベートネットワークで接続します。

image.png

flannelのVXLANインターフェースが適切に設定されない問題

こちらのissueの通りですが、そのままインストールするとNode間の通信ができません。

k3sで使われているCNIのflannelはVXLANトンネルを利用してNode間通信を行います。その時に利用するVXLANの出入口となるNICがデフォルトではNodeの一番最初のNICとなります。

Vagrantの場合、必ずNAT用のNICが最初に作成されてしまうため、デフォルトではNAT用のインターフェースが選択されてしまい都合が良くありません。
kubeadm等で構築する場合は、flanneldの実行引数--ifaceで明示的に指定可能ですが、k3sではflannelが組み込まれているため指定ができません。

そのため、今回はk3sでは--no-flannelフラグを付けてflannelインストールをスキップし、別途flannelをインストールしました。

なお、k3sの実行オプションとして--flannel-ifaceを付けるPRもあるため、取り込まれたらk3sのflannelを利用しても設定できるようになります。

--2019/4/26追記

マージされていました。

Master Nodeへk3sをインストール

公式のインストーラーを用いて以下のように設定します。INSTALL_K3S_EXECの環境変数を用いてオプションを渡してあげます。

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--no-flannel --node-ip=192.168.33.11" sh -

/var/lib/rancher/k3s/server/node-tokenにNode追加用のトークンが払い出されていますので、メモしておきます。

Node1,2を追加

先ほどメモしたトークンを用いてNode1, 2をagentとして追加します。以下はNode1用です。

export K3S_TOKEN=<トークン>
export K3S_URL=https://192.168.33.11:6443
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--no-flannel --node-ip=192.168.33.12" sh -

CNIプラグインのインストール

すべてのNodeにおいて、CNIプラグインを配置しておく必要があるため、あらかじめ公式のリリースページよりcni-plugins-xxxx.tgzをインストールし、/opt/cni/binに展開しておきます。

flannelをインストール

flannel自身のデプロイはkubectlを使って行います。

公式のマニフェストファイルをダウンロードして、以下のように修正します。

ポイントは以下の2点です。

  • flanneldのDaemonSetで起動オプションに--ifaceを追加
    • 以下の例はamd64用のDaemonSetに設定しましたが、環境にあわせて適切に設定してください。
  • CNI設定のConfigMapを環境にあわせて設定
    • k3sのデフォルトにあわせて10.42.0.0/16で設定しました。
--- kube-flannel.yaml.org       2019-03-21 09:28:45.427370300 +0000
+++ kube-flannel.yaml   2019-03-20 14:37:30.155241900 +0000
@@ -124,7 +124,7 @@
     }
   net-conf.json: |
     {
-      "Network": "10.244.0.0/16",
+      "Network": "10.42.0.0/16",
       "Backend": {
         "Type": "vxlan"
       }
@@ -174,6 +174,7 @@
         args:
         - --ip-masq
         - --kube-subnet-mgr
+        - --iface=enp0s8
         resources:
           requests:
             cpu: "100m"

修正したファイルをkubectlで適用します。

vagrant@master:~$ kubectl apply -f kube-flannel.yaml

確認

以上で構築は完了しました。VXLANインターフェースの設定やNode間通信が問題ないかを確認します。

VXLANインターフェース

vagrant@master:~$ ip -d a show flannel.1
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
    link/ether 6a:02:aa:4b:49:0d brd ff:ff:ff:ff:ff:ff promiscuity 0
    vxlan id 1 local 192.168.33.11 dev enp0s8 srcport 0 0 dstport 8472 nolearning ageing 300
    inet 10.42.0.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::6802:aaff:fe4b:490d/64 scope link
       valid_lft forever preferred_lft forever

プライベートのインターフェースが設定されています。

Node間通信

NginxのDeploymentを適当に作成しておきます。

vagrant@master:~$ kubectl run --image=nginx --replicas=5 nginx
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/nginx created
vagrant@master:~$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx-7cdbd8cdc9-824qd   1/1     Running   0          25s   10.42.1.12   node1    <none>           <none>
nginx-7cdbd8cdc9-9sct7   1/1     Running   0          25s   10.42.2.11   node2    <none>           <none>
nginx-7cdbd8cdc9-bxfhb   1/1     Running   0          25s   10.42.2.12   node2    <none>           <none>
nginx-7cdbd8cdc9-csd4p   1/1     Running   0          25s   10.42.1.13   node1    <none>           <none>
nginx-7cdbd8cdc9-wcn9s   1/1     Running   0          25s   10.42.0.13   master   <none>           <none>
  • Master -> Pods の通信
vagrant@master:~$ ping 10.42.1.12 -c 1
PING 10.42.1.12 (10.42.1.12) 56(84) bytes of data.
64 bytes from 10.42.1.12: icmp_seq=1 ttl=63 time=0.425 ms

--- 10.42.1.12 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.425/0.425/0.425/0.000 ms

vagrant@master:~$ ping 10.42.2.11 -c 1
PING 10.42.2.11 (10.42.2.11) 56(84) bytes of data.
64 bytes from 10.42.2.11: icmp_seq=1 ttl=63 time=0.802 ms

--- 10.42.2.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.802/0.802/0.802/0.000 ms
  • Pod -> Pods の通信
vagrant@master:~$ kubectl run --generator=run-pod/v1 -it test --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # ping 10.42.0.13 -c 1
PING 10.42.0.13 (10.42.0.13): 56 data bytes
64 bytes from 10.42.0.13: seq=0 ttl=64 time=0.075 ms

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

/ # ping 10.42.1.12 -c 1
PING 10.42.1.12 (10.42.1.12): 56 data bytes
64 bytes from 10.42.1.12: seq=0 ttl=62 time=0.484 ms

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

/ # ping 10.42.2.11 -c 1
PING 10.42.2.11 (10.42.2.11): 56 data bytes
64 bytes from 10.42.2.11: seq=0 ttl=62 time=0.433 ms

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

すべて通信できることが確認できました。

Vagrantfile

最後に、すべてをまとめたVagrantファイルを以下に置いておきます。
kube-flannel.yamlは修正済みのものがすでにVagrantfileと同じフォルダに置かれているものとします。

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

$configureCommon = <<-SHELL

  # apt-get update
  # apt-get upgrade -y

  ## cni pluginsを展開
  mkdir -p /opt/cni/bin
  curl -sSL https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-amd64-v0.7.5.tgz | tar xzf - -C /opt/cni/bin

SHELL

$configureMaster = <<-SHELL

  # プライベートネットワークのNICのIPアドレスを変数に格納
  IPADDR=$(ip a show enp0s8 | grep "inet " | awk '{print $2}' | cut -d / -f1)

  ## k3sのデプロイ flannelをOFF プライベートIPをkubeletのIPとするように指定
  ## ここで、flannelをOFFにしているのは、現在ではVxLANの送出IFの指定ができず、Vagrant環境の場合、NATインターフェースが選択されてしまうため都合が悪い
  ## k3sのFlannelはあきらめて、flannelは別途構築する
  curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--no-flannel --node-ip=${IPADDR}" sh -

  ## flannelのデプロイ
  kubectl apply -f /vagrant/kube-flannel.yaml

  ## agent登録用のトークンを共有フォルダに配置
  cp /var/lib/rancher/k3s/server/node-token /vagrant/token

SHELL

$configureNode = <<-SHELL

  export K3S_TOKEN=$(cat /vagrant/token)
  export K3S_URL=https://192.168.33.11:6443
  # プライベートネットワークのNICのIPアドレスを変数に格納
  IPADDR=$(ip a show enp0s8 | grep "inet " | awk '{print $2}' | cut -d / -f1)

  ## k3sのデプロイ flannelをOFF プライベートIPをkubeletのIPとするように指定
  curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--no-flannel --node-ip=${IPADDR}" sh -

SHELL

Vagrant.configure(2) do |config|

  node_num = 3

  (1..node_num).each do |i|

    if i == 1 then
      vm_name = "master"
    else
      vm_name = "node#{i-1}"
    end

    config.vm.define vm_name do |s|

      # ホスト名
      s.vm.hostname = vm_name
      # ノードのベースOSを指定
      s.vm.box = "ubuntu/xenial64"
      # ネットワークを指定
      private_ip = "192.168.33.#{i+10}"
      s.vm.network "private_network", ip: private_ip

      # 共通
      s.vm.provision "shell", inline: $configureCommon

      if i == 1 then
        # For Master
        s.vm.provision "shell", inline: $configureMaster
      else
        # For Nodes
        s.vm.provision "shell", inline: $configureNode
      end

    end
  end
end
omatsu32
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away