fbpx

KubernetesをVirtualboxにVagrantとKubeadmでインストールしてみよう #kubernetes #kubeadm #vagrant #virtualbox

この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。

Kubernetesの勉強のためにインストールから始めてみよう! ……と思ったけれど、設定すべきIPアドレスがたくさん出てきてよくわからない……。Kubernetesを勉強したいからインストールするのに、インストールする際に知っておかないといけないKubernetesの知識が多すぎる……」と、いきなり手詰まりになってしまう方も多いかと思います。

ローカルで手軽にKubernetesを構築できるminikubekindなどのツールが存在するので、まずはそちらでKubernetesの勉強をするのもよいでしょう。

本稿では、kubeadmVagrantを使ってVirtualbox上にKubernetesをインストールする際に気をつけるべき点をまとめてみたいと思います。

前提条件

ホストマシンにVagrantとVirtualboxがインストール済みであり、IPアドレスは 192.168.24.201 であるとします。IPアドレスは必要に応じて適宜読み替えてください。

デフォルトで利用されるIPアドレス範囲

まず、Vagrant + Virtualbox + Kubernetesのデフォルトで利用されるIPアドレス範囲を見ておきます。

  • 10.0.2.15/32
  • 172.17.0.0/16
  • 10.96.0.0/12
  • 192.168.0.0/16 (注:Calicoの場合、詳細後述)

これらがホストマシンのIPアドレスにかぶっていると理解の妨げになる上に、何か動作がおかしくなった場合の原因特定が大変になるため、可能な限り変更したいところです。前提条件の通り、本稿におけるホストマシンのIPアドレスは 192.168.24.201192.168.0.0/16 とかぶっているので、その他のものも含めて、以降で各IPアドレス範囲の詳細と変更方法を見ていきましょう。

10.0.2.15/32

10.0.2.15/32 は、Vagrant + Virtualbox でゲストOSのプライマリネットワークインターフェイス(例えばeth0)に付与される、内部ネットワーク用のIPアドレスです。末尾の 15 は変えられないようですが、ネットワーク部 10.0.2.0/24 は変更できます: Configuring the Address of a NAT Network Interface, VBoxManage Customizations

例えば 10.0.3.15/32 に変更するには Vagrantfile で次のようにします。

Vagrant.configure(2) do |config|
# 省略
config.vm.provider "virtualbox" do |v|
v.customize ["modifyvm", :id, "--natnet1", "10.0.3/24"]
end
# 省略
end

なお、この内部ネットワーク用のIPアドレスはプライマリネットワークインターフェイスに必ず付与されます。そのため、プライマリネットワークインターフェイスを自動検知して利用するソフトウェアは動作不良を起こすので、利用するネットワークインターフェイスを手動設定する必要があります。具体例は後述します。

172.17.0.0/16

172.17.0.0/16 はDockerのデフォルトブリッジネットワークで使われるIPアドレス範囲です。もう少し具体的に言うと、ネットワークインターフェイスdocker0のIPアドレス(例えば 172.17.0.1/16)は、このIPアドレス範囲から割り当てられます。

$ ip a show docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:04:c5:cf:b8 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever

docker0のIPアドレスを変更するには、 /etc/docker/daemon.json にて bip キーでIPアドレスを指定し、Dockerを再起動します: Configure the default bridge network

例えば 172.20.0.1/16 に変更するには /etc/docker/daemon.json で次のようにします。

{
"bip": "172.20.0.1/16"
}
$ ip a show docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:04:c5:cf:b8 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.1/16 brd 172.20.255.255 scope global docker0
valid_lft forever preferred_lft forever

余談ですが、bip キーで変更できるのはデフォルトブリッジネットワーク(docker0)のみで、追加ブリッジネットワークは依然として 172.17.0.0/16 から割り当てられることに注意が必要です。

$ for i in $(seq 1 1 5); do docker network create network-$i; done
$ for i in $(docker network ls --filter driver=bridge -q); do docker network inspect --format '{{.Name}} : {{range .IPAM.Config}}{{.Subnet}}{{end}}' $i; done
bridge : 172.20.0.0/16
network-1 : 172.17.0.0/16
network-2 : 172.18.0.0/16
network-3 : 172.19.0.0/16
network-4 : 172.21.0.0/16
network-5 : 172.22.0.0/16

これを避けるには bip キーの代わりに default-address-pools キーを使います。base はブリッジネットワークに割り当てられるIPアドレス範囲で、size は base から切り出されるサブネットマスクになります。例えば、

{
"default-address-pools": [
{
"base": "172.20.0.0/16",
"size": 24
}
]
}

とすると、172.20.0.0/16 すなわち 172.20.0.1 〜 172.20.255.254 がブリッジネットワークに割り当てられるIPアドレス範囲で、

  • 172.20.0.0/24
  • 172.20.1.0/24
  • 172.20.2.0/24
  • (中略)
  • 172.20.253.0/24
  • 172.20.254.0/24
  • 172.20.255.0/24

が各ブリッジネットワーク(最初の 172.20.0.0/24 はdocker0)に割り当てられることになります。

$ for i in $(seq 1 1 5); do docker network create network-$i; done
$ for i in $(docker network ls --filter driver=bridge -q); do docker network inspect --format '{{.Name}} : {{range .IPAM.Config}}{{.Subnet}}{{end}}' $i; done
bridge : 172.20.0.0/24
network-1 : 172.20.1.0/24
network-2 : 172.20.2.0/24
network-3 : 172.20.3.0/24
network-4 : 172.20.4.0/24
network-5 : 172.20.5.0/24

参考: default-address-pools, docker0

10.96.0.0/12

10.96.0.0/12は、kubeadmのデフォルト設定でKubernetesをインストールした場合にServiceという仕組みに用いられるIPアドレス範囲です。
Vagrant + Virtualbox でゲストOSのプライマリネットワークインターフェイス(例えばeth0)に付与される 10.0.2.15/32 と若干まぎらわしいため、変更しておくと理解しやすくなると思います。
Serviceに用いるIPアドレス範囲を変更するには kubeadm initの --service-cidr オプションを使用します。

$ kubeadm init --service-cidr 203.0.113.0/24

192.168.0.0/16

192.168.0.0/16は、 Pod間の通信Calico を用いる場合にデフォルトで使用されるIPアドレス範囲です。
前述の通り、本稿のホストマシンのIPアドレスである 192.168.24.201 を含んでいるため変更しましょう。
Calicoが使用するIPアドレス範囲を変更するには kubeadm initの --pod-network-cidr オプションを使用し、

$ kubeadm init --pod-network-cidr 198.51.100.0/24

さらにCalicoのインストールに利用するYAMLファイルを変更します。これは後述します。

実際のインストール

以上を踏まえて、実際にKubernetesのインストールを行ってみます。

ゲストOSの準備

次のVagrantfileで、ゲストOSのプライマリネットワークインターフェイスのIPアドレスを 10.0.3.15/32 に設定しています(デフォルトは 10.0.2.15/32)。
また、ゲストOSのIPアドレス範囲は、ホストマシンのIPアドレス 192.168.24.201 とややまぎらわしいですが大きな問題となることは少ないため、192.168.123.0/24 としておきます。

Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.box_check_update = false
config.vm.define "master" do |cf|
cf.vm.hostname = "master"
cf.vm.network "private_network", ip: "192.168.123.101"
cf.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.customize ["modifyvm", :id, "--natnet1", "10.0.3/24"]
end
end
config.vm.define "worker" do |cf|
cf.vm.hostname = "worker"
cf.vm.network "private_network", ip: "192.168.123.102"
cf.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.customize ["modifyvm", :id, "--natnet1", "10.0.3/24"]
end
end
end

master と worker の両ゲストOSの /etc/hosts で、両ホストのIPアドレスが 127.0.2.1 となっているところを Vagrantfile で設定したそれぞれのIPアドレスに変更し、お互いに名前解決できるように追記もしておきます(※一部抜粋)。

192.168.123.101 master
192.168.123.102 worker

Dockerのインストールと設定

CRIのインストールに従い、Dockerをインストールします。
/etc/docker/daemon.json の設定には default-address-pools キーの設定を追加し、docker0のIPアドレスを 172.20.0.0/16 に変更します(デフォルトは 172.17.0.0/16)。

{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"default-address-pools": [
{
"base": "172.20.0.0/16",
"size": 24
}
]
}

kubeadmによるKubernetesのインストール

kubeadmを使ってクラスターを構築するに従い、kubeadmでKubernetesをインストールします。

まずはkubeadmのインストールに従い、masterゲストとworkerゲストの両方に kubelet, kubeadm, kubectl をインストールします。

次にkubeadmを使用したクラスターの作成に従い、masterゲストで kubadm init を実行しますが、これには前述の通りオプションが必要になります。

Serviceに用いるIPアドレス範囲は203.0.113.0/24(デフォルトは10.96.0.0/12)とし、Pod間通信のために用いるIPアドレス範囲は198.51.100.0/24(デフォルトは192.168.0.0/16)とします。また、プライマリネットワークインターフェイスを自動検知しないよう --apiserver-advertise-address オプションでmasterゲストのIPアドレス 192.168.123.101 を指定します。

$ sudo kubeadm init --service-cidr 203.0.113.0/24 --pod-network-cidr 198.51.100.0/24 --apiserver-advertise-address 192.168.123.101

正常に完了すれば、次のコマンド群が表示されるので、これをコピー&ペーストしてmasterゲストで実行します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

さらにこのコマンド群の後に kubeadm join というコマンドが表示されるので、これをコピー&ペーストしてworkerゲストで実行します。次は本稿での例で、細かい文字列は異なります。

$ sudo kubeadm join 192.168.123.101:6443 --token wq7k60.igq3l1qr7ehxw7yi \
--discovery-token-ca-cert-hash sha256:ce72112c0048e7e00a9b2a7857fba65ce3a3aeeaf746e364ed1c8fa01aa449cd

さらに kubelet がプライマリネットワークインターフェイスを自動検知しないよう手動で設定します。具体的には /etc/default/kubelet ファイルを作成し、master であれば次を、

KUBELET_EXTRA_ARGS=--node-ip=192.168.123.101

worker であれば次を、

KUBELET_EXTRA_ARGS=--node-ip=192.168.123.102

それぞれ記載し、

$ sudo systemctl daemon-reload
$ sudo systemctl restart kubelet

を実行して kubelet を再起動して設定を読み込ませます。psコマンドでkubeletプロセスを確認し、 --node-ip=192.168.123.10X オプションが付与されていれば成功です。

masterゲストで kubelet get nodes コマンドを実行し、次のようになっていればひとまず kubeadm による Kubernetes のインストールは一段落です。

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane,master 12m v1.22.0
worker NotReady 7m2s v1.22.0

Calicoのインストール

Install Calicoに従い、Pod間通信のためのCalicoをインストールします。すべてmasterゲストで実施します。

まず1つ目のYAMLファイルはそのまま適用します。

$ kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml

2つ目のYAMLには、変更すべきIPアドレス範囲の記載があるため、そのまま適用してはいけません。YAMLファイルをダウンロードし、デフォルトのIPアドレス範囲192.168.0.0/16を198.51.100.0/24に変更します。

$ wget https://docs.projectcalico.org/manifests/custom-resources.yaml
$ cp custom-resources.yaml custom-resources.yaml.orig
$ vi custom-resources.yaml
$ diff -u custom-resources.yaml.orig custom-resources.yaml
--- custom-resources.yaml.orig 2021-08-10 07:22:52.987585977 +0000
+++ custom-resources.yaml 2021-08-10 07:23:44.471585977 +0000
@@ -10,7 +10,7 @@
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
- cidr: 192.168.0.0/16
+ cidr: 198.51.100.0/24
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()

変更したYAMLファイルを適用します。

$ kubectl create -f custom-resources.yaml

少し待ち、次のようにSTATUSがすべてRunningになれば成功です。

$ kubectl get pods -n calico-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-585ff4589d-tvtnw 1/1 Running 0 15m
calico-node-g6jxs 1/1 Running 0 15m
calico-node-vtqwg 1/1 Running 0 15m
calico-typha-57d65ff8f5-4rbnm 1/1 Running 0 15m
calico-typha-57d65ff8f5-k75r8 1/1 Running 0 15m

またこちらのSTATUSもすべてReadyとなっていることも確認しましょう。

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 45m v1.22.0
worker Ready 39m v1.22.0

動作テスト

masterゲスト上でもワークロードを実行できるように次を実行します。

$ kubectl taint nodes --all node-role.kubernetes.io/master-
node/master untainted
error: taint "node-role.kubernetes.io/master" not found

エラーのように見えますが、1行目に「node/master untainted」と出ていれば問題ありません。

デモアプリケーションとしてSock Shopをデプロイします。

$ kubectl create -f https://raw.githubusercontent.com/microservices-demo/microservices-demo/master/deploy/kubernetes/complete-demo.yaml

しばらく待ち、次を実行してSTATUSがすべてRunningになっていたら成功です。

$ kubectl -n sock-shop get pods
NAME READY STATUS RESTARTS AGE
carts-b4d4ffb5c-7h2hq 1/1 Running 0 20m
carts-db-6c6c68b747-27bjb 1/1 Running 0 20m
catalogue-759cc6b86-gq9rc 1/1 Running 0 20m
catalogue-db-96f6f6b4c-qd7df 1/1 Running 0 20m
front-end-5c89db9f57-pf5mn 1/1 Running 0 20m
orders-7664c64d75-hqwxk 1/1 Running 0 20m
orders-db-659949975f-bckt8 1/1 Running 0 20m
payment-7bcdbf45c9-d2g8j 1/1 Running 0 20m
queue-master-5f6d6d4796-7frwb 1/1 Running 0 20m
rabbitmq-5bcbb547d7-52s6p 2/2 Running 0 20m
session-db-7cf97f8d4f-xfvzh 1/1 Running 0 20m
shipping-7f7999ffb7-2xqh8 1/1 Running 0 20m
user-68df64db9c-tcj28 1/1 Running 0 20m
user-db-6df7444fc-gtrz5 1/1 Running 0 20m

ブラウザで http://192.168.123.101:30001 あるいは http://192.168.123.102:30001 にアクセスし、Sock ShopのUIが表示されれば正常に動作しています。

IPアドレス範囲の確認

--pod-network-cidr 198.51.100.0/24 が有効だったかどうかは次で確認できます。

$ kubectl -n sock-shop get pods -o jsonpath='{range .items[*]}{.status.podIP}{"\n"}'
198.51.100.215
198.51.100.207
198.51.100.8
198.51.100.209
198.51.100.9
198.51.100.210
198.51.100.14
198.51.100.212
198.51.100.11
198.51.100.216
198.51.100.13
198.51.100.10
198.51.100.206
198.51.100.12

--service-cidr 203.0.113.0/24 が有効だったかどうかは次で確認できます。

$ kubectl -n sock-shop get svc -o jsonpath='{range .items[*]}{.spec.clusterIP}{"\n"}'
203.0.113.190
203.0.113.234
203.0.113.36
203.0.113.141
203.0.113.12
203.0.113.171
203.0.113.235
203.0.113.53
203.0.113.73
203.0.113.61
203.0.113.254
203.0.113.77
203.0.113.21
203.0.113.227

片付け

次のコマンドでSock Shopを停止・削除します。

$ kubectl delete ns sock-shop
namespace "sock-shop" deleted

まとめ

本稿ではVagrant + VirtualboxでKubernetesをインストールする際に問題となるプライマリネットワークインターフェイスと、Kubernetesで使われるさまざまなIPアドレス範囲とその変更方法、そして実際のkubeadmによるKubernetesのインストールとデモアプリケーションのデプロイについて見てみました。
IPアドレス範囲について把握しておけばKubernetesの学習中に遭遇する疑問やトラブルなどに対処しやすくなり、またVagrant + VirtualboxでKubernetesをインストールできていればクラウド料金等をかけずに手軽に実験することも可能です。
皆様のKubernetesの学習に本稿が役立てば幸いです。

Author

Chef・Docker・Mirantis製品などの技術要素に加えて、会議の進め方・文章の書き方などの業務改善にも取り組んでいます。「Chef活用ガイド」共著のほか、Debian Official Developerもやっています。

Daisuke Higuchiの記事一覧

新規CTA