今更ながらのVagrantの勉強を兼ね、vagrant up
でKubernetesクラスターを簡単に起動するためのVagrantfile
を作成したのでメモ。
参考資料
- Multi Node Kubernetes Cluster with Vagrant, VirtualBox and Kubeadm
- Kubernetes v1.10 クラスタをVagrantで構築したメモ
- Get Docker CE for Ubuntu
- Get Docker CE for CentOS
- Creating a single master cluster with kubeadm
Vagrantfile
Masterはシングルで複数NodeのKubernetesクラスターを作成する。
注意すべき点は以下。
- 各VMはNAT用に
10.0.2.15
という同じIP持っており、apiserverがそちらにバインドされてしまうため、kubeadm init
で--apiserver-advertise-address
などを引数に設定 - 同じくkubeletも
10.0.2.15
にバインドされてしまうため、kubeletの引数に--nodeip
を指定する必要があり、そのためkubeletサービスのSystemdユニット定義から参照される/etc/default/kubelet
(Ubuntu)または/etc/sysconfig/kubelet
(CentOS)を修正する - Masterノード上で生成した
kubeadm join
コマンドを、各Nodeはscpで取得して実行
(追記)以下に記載のものからKubernetesのバージョンアップへの対応などちょいちょい変更をしています。
Ubuntu
ネットワークプラグインはFlannelを使ってみる。
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
$configureBox = <<-SHELL
# パッケージ更新
apt-get update
apt-get upgrade -y
# Dockerの前提パッケージ
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Dockerのレポジトリ追加
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Dockerのインストール
apt-get update
apt-get install -y docker-ce=$(apt-cache madison docker-ce | grep 17.03 | head -1 | awk '{print $3}')
apt-mark hold docker-ce
# vagrantユーザーをdockerグループに追加
usermod -aG docker vagrant
# Flannelの場合に必要
# デフォルトが1なのでコメントアウト
# echo net.bridge.bridge-nf-call-iptables = 1 >> /etc/sysctl.conf
# sysctl -p
# スワップを無効化する
# スワップ領域がないのでコメントアウト
# swapoff -a
# プロビジョニングで実行する場合はバックスラッシュのエスケープが必要なことに注意
# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# sed -i '/ swap / s/^\\(.*\\)$/#\\1/g' /etc/fstab
# Kubernetesの前提パッケージ
# apt-get update
# apt-get install -y apt-transport-https curl
# Kubernetesのレポジトリ追加
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
# kubeadm、kubelet、kubectlのインストール
apt-get update
# apt-get install -y kubelet=1.12.2-00 kubeadm=1.12.2-00 kubectl=1.12.2-00
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
# プライベートネットワークのNICのIPアドレスを変数に格納
IPADDR=$(ip a show enp0s8 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
# kubeletがプライベートネットワークのNICにバインドするように設定
sed -i "/KUBELET_EXTRA_ARGS=/c\KUBELET_EXTRA_ARGS=--node-ip=$IPADDR" /etc/default/kubelet
# kubeletを再起動
systemctl daemon-reload
systemctl restart kubelet
SHELL
$configureMaster = <<-SHELL
echo "This is master"
# プライベートネットワークのNICのIPアドレスを変数に格納
IPADDR=$(ip a show enp0s8 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
# ホスト名を変数に格納
HOSTNAME=$(hostname -s)
# kubeadm initの実行
# Flannelの場合
kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --node-name $HOSTNAME --pod-network-cidr=10.244.0.0/16
# Calicoの場合
# kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --node-name $HOSTNAME --pod-network-cidr=192.168.0.0/16
# vagrantユーザーがkubectlを実行できるようにする
sudo --user=vagrant mkdir -p /home/vagrant/.kube
cp -i /etc/kubernetes/admin.conf /home/vagrant/.kube/config
chown $(id -u vagrant):$(id -g vagrant) /home/vagrant/.kube/config
# Flannelのインストール
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
# Calicoのインストール
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
# kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
# kubectl joinコマンドを保存する
kubeadm token create --print-join-command > /etc/kubeadm_join_cmd.sh
chmod +x /etc/kubeadm_join_cmd.sh
# sshでのパスワード認証を許可する
sed -i "/^[^#]*PasswordAuthentication[[:space:]]no/c\PasswordAuthentication yes" /etc/ssh/sshd_config
systemctl restart sshd
SHELL
$configureNode = <<-SHELL
echo "This is worker"
apt-get install -y sshpass
sshpass -p "vagrant" scp -o StrictHostKeyChecking=no vagrant@192.168.33.11:/etc/kubeadm_join_cmd.sh .
# sshpass -p "vagrant" scp -o StrictHostKeyChecking=no vagrant@172.16.33.11:/etc/kubeadm_join_cmd.sh .
sh ./kubeadm_join_cmd.sh
SHELL
Vagrant.configure(2) do |config|
(1..3).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"
# ネットワークを指定
# pod-network-cidrと重ならないように注意
private_ip = "192.168.33.#{i+10}"
# private_ip = "172.16.33.#{i+10}"
s.vm.network "private_network", ip: private_ip
# ノードのスペックを指定
s.vm.provider "virtualbox" do |v|
v.gui = false
if i == 1 then
v.cpus = 2
v.memory = 1024
else
v.cpus = 1
v.memory = 1024
end
end
# 共通のプロビジョニング
s.vm.provision "shell", inline: $configureBox
if i == 1 then
# Masterのプロビジョニング
s.vm.provision "shell", inline: $configureMaster
else
# Nodeのプロビジョニング
s.vm.provision "shell", inline: $configureNode
end
end
end
end
CentOS
こちらはネットワークプラグインはCalicoを使ってみる。CalicoのPodネットワーク192.168.0.0/16
と重ならないようにするため、VirtualBoxのプライベートネットワークは172.16.33.0/24
を使用する。
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
$configureBox = <<-SHELL
# パッケージ更新
yum update -y
# Dockerの前提パッケージ
yum install -y yum-utils device-mapper-persistent-data lvm2
# Dockerのレポジトリ追加
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# Dockerのインストール
VERSION=$(yum list docker-ce --showduplicates | sort -r | grep 17.03 | head -1 | awk '{print $2}')
yum install -y --setopt=obsoletes=0 docker-ce-$VERSION docker-ce-selinux-$VERSION
systemctl enable docker && systemctl start docker
# vagrantユーザーをdockerグループに追加
usermod -aG docker vagrant
# スワップを無効化する
swapoff -a
# プロビジョニングで実行する場合はバックスラッシュのエスケープが必要なことに注意
# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
sed -i '/ swap / s/^\\(.*\\)$/#\\1/g' /etc/fstab
# Kubernetesのレポジトリ追加
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
# SELinuxを無効化
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# kubeadm、kubelet、kubectlのインストール
# yum install -y kubelet-1.12.2-0 kubeadm-1.12.2-0 kubectl-1.12.2-0 --disableexcludes=kubernetes
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
# プライベートネットワークのNICのIPアドレスを変数に格納
IPADDR=$(ip a show eth1 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
# kubeletがプライベートネットワークのNICにバインドするように設定
sed -i "/KUBELET_EXTRA_ARGS=/c\KUBELET_EXTRA_ARGS=--node-ip=$IPADDR" /etc/sysconfig/kubelet
# kubeletを再起動
systemctl daemon-reload
systemctl restart kubelet
SHELL
$configureMaster = <<-SHELL
echo "This is master"
# プライベートネットワークのNICのIPアドレスを変数に格納
IPADDR=$(ip a show eth1 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
# ホスト名を変数に格納
HOSTNAME=$(hostname -s)
# kubeadm initの実行
# Flannel
# kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --node-name $HOSTNAME --pod-network-cidr=10.244.0.0/16
# Calico
kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --node-name $HOSTNAME --pod-network-cidr=192.168.0.0/16
# vagrantユーザーがkubectlを実行できるようにする
sudo --user=vagrant mkdir -p /home/vagrant/.kube
cp -i /etc/kubernetes/admin.conf /home/vagrant/.kube/config
chown $(id -u vagrant):$(id -g vagrant) /home/vagrant/.kube/config
# Flannelのインストール
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
# Calicoのインストール
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
# kubectl joinコマンドを保存する
kubeadm token create --print-join-command > /etc/kubeadm_join_cmd.sh
chmod +x /etc/kubeadm_join_cmd.sh
# sshでのパスワード認証を許可する
sed -i "/^[^#]*PasswordAuthentication[[:space:]]no/c\PasswordAuthentication yes" /etc/ssh/sshd_config
systemctl restart sshd
SHELL
$configureNode = <<-SHELL
echo "This is worker"
yum install -y sshpass
# sshpass -p "vagrant" scp -o StrictHostKeyChecking=no vagrant@192.168.33.11:/etc/kubeadm_join_cmd.sh .
sshpass -p "vagrant" scp -o StrictHostKeyChecking=no vagrant@172.16.33.11:/etc/kubeadm_join_cmd.sh .
sh ./kubeadm_join_cmd.sh
SHELL
Vagrant.configure(2) do |config|
(1..3).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 = "centos/7"
# ネットワークを指定
# pod-network-cidrと重ならないように注意
# private_ip = "192.168.33.#{i+10}"
private_ip = "172.16.33.#{i+10}"
s.vm.network "private_network", ip: private_ip
# ノードのスペックを指定
s.vm.provider "virtualbox" do |v|
v.gui = false
if i == 1 then
v.cpus = 2
v.memory = 1024
else
v.cpus = 1
v.memory = 1024
end
end
# 共通のプロビジョニング
s.vm.provision "shell", inline: $configureBox
if i == 1 then
# Masterのプロビジョニング
s.vm.provision "shell", inline: $configureMaster
else
# Nodeのプロビジョニング
s.vm.provision "shell", inline: $configureNode
end
end
end
end
動作確認
Ubuntu
$ vagrant up
Bringing machine 'master' up with 'virtualbox' provider...
Bringing machine 'node1' up with 'virtualbox' provider...
Bringing machine 'node2' up with 'virtualbox' provider...
==> master: Importing base box 'ubuntu/xenial64'...
==> master: Matching MAC address for NAT networking...
(省略)
node2: Run 'kubectl get nodes' on the master to see this node join the cluster.
sotoiwa@sotonombp:~/workspace/vagrant-k8s-ubuntu
$ vagrant ssh master
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-140-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
0 packages can be updated.
0 updates are security updates.
New release '18.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
*** System restart required ***
vagrant@master:~$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready master 3m34s v1.13.0 192.168.33.11 <none> Ubuntu 16.04.5 LTS 4.4.0-140-generic docker://17.3.3
node1 Ready <none> 2m3s v1.13.0 192.168.33.12 <none> Ubuntu 16.04.5 LTS 4.4.0-140-generic docker://17.3.3
node2 Ready <none> 37s v1.13.0 192.168.33.13 <none> Ubuntu 16.04.5 LTS 4.4.0-140-generic docker://17.3.3
vagrant@master:~$ kubectl get po --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-86c58d9df4-mkg9w 1/1 Running 0 3m26s 10.244.0.2 master <none> <none>
kube-system coredns-86c58d9df4-rkzfp 1/1 Running 0 3m26s 10.244.0.3 master <none> <none>
kube-system etcd-master 1/1 Running 0 2m39s 192.168.33.11 master <none> <none>
kube-system kube-apiserver-master 1/1 Running 0 2m41s 192.168.33.11 master <none> <none>
kube-system kube-controller-manager-master 1/1 Running 0 2m24s 192.168.33.11 master <none> <none>
kube-system kube-flannel-ds-amd64-27mm7 1/1 Running 0 48s 192.168.33.13 node2 <none> <none>
kube-system kube-flannel-ds-amd64-l8tj7 1/1 Running 0 2m14s 192.168.33.12 node1 <none> <none>
kube-system kube-flannel-ds-amd64-q6bhm 1/1 Running 0 3m26s 192.168.33.11 master <none> <none>
kube-system kube-proxy-bqpx8 1/1 Running 0 48s 192.168.33.13 node2 <none> <none>
kube-system kube-proxy-dltht 1/1 Running 0 3m26s 192.168.33.11 master <none> <none>
kube-system kube-proxy-gg6sl 1/1 Running 0 2m14s 192.168.33.12 node1 <none> <none>
kube-system kube-scheduler-master 1/1 Running 0 2m48s 192.168.33.11 master <none> <none>
vagrant@master:~$
CentOS
$ vagrant up
Bringing machine 'master' up with 'virtualbox' provider...
Bringing machine 'node1' up with 'virtualbox' provider...
Bringing machine 'node2' up with 'virtualbox' provider...
==> master: Importing base box 'centos/7'...
==> master: Matching MAC address for NAT networking...
(省略)
node2: Run 'kubectl get nodes' on the master to see this node join the cluster.
sotoiwa@sotonombp:~/workspace/vagrant-k8s-centos
$ vagrant ssh master
[vagrant@master ~]$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready master 10m v1.13.0 172.16.33.11 <none> CentOS Linux 7 (Core) 3.10.0-862.14.4.el7.x86_64 docker://17.3.3
node1 Ready <none> 7m v1.13.0 172.16.33.12 <none> CentOS Linux 7 (Core) 3.10.0-862.14.4.el7.x86_64 docker://17.3.3
node2 Ready <none> 3m51s v1.13.0 172.16.33.13 <none> CentOS Linux 7 (Core) 3.10.0-862.14.4.el7.x86_64 docker://17.3.3
[vagrant@master ~]$ kubectl get po --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system calico-node-24jkl 2/2 Running 0 7m7s 172.16.33.12 node1 <none> <none>
kube-system calico-node-dnjbb 2/2 Running 0 4m4s 172.16.33.13 node2 <none> <none>
kube-system calico-node-hhscc 2/2 Running 0 10m 172.16.33.11 master <none> <none>
kube-system coredns-86c58d9df4-hlmpt 1/1 Running 0 10m 192.168.0.2 master <none> <none>
kube-system coredns-86c58d9df4-phbjg 1/1 Running 0 10m 192.168.0.3 master <none> <none>
kube-system etcd-master 1/1 Running 0 9m30s 172.16.33.11 master <none> <none>
kube-system kube-apiserver-master 1/1 Running 0 9m2s 172.16.33.11 master <none> <none>
kube-system kube-controller-manager-master 1/1 Running 3 9m4s 172.16.33.11 master <none> <none>
kube-system kube-proxy-cmc72 1/1 Running 0 7m7s 172.16.33.12 node1 <none> <none>
kube-system kube-proxy-h5z7t 1/1 Running 0 4m4s 172.16.33.13 node2 <none> <none>
kube-system kube-proxy-kbgm5 1/1 Running 0 10m 172.16.33.11 master <none> <none>
kube-system kube-scheduler-master 1/1 Running 3 9m30s 172.16.33.11 master <none> <none>
[vagrant@master ~]$