※2020/03/08追記 k8sのセットアップを行うプロビジョニング用スクリプト(scripts/common/00-setup-k8s.sh)については少し変更しています。
前回のhard wayでなんとなくk8sの雰囲気がわかったので、今度はkubeadmを使ってマルチマスターをやってみたいと思います。
ざっとググってみたけど、kubeadmはシングルマスターの記事が多いのと、さらにvagrantになると少しvirtualbox特有のクセみたいなものもあって、なかなかマルチマスターk8s on vagrantな記事はお目にかかりません。であればやってみようというのが今回の目的です。
以下要件。
- ネットワーク構成は基本的にhard wayを踏襲します。
- vagrant上で構築します。お手軽だしオンプレに近い環境つくれると思うので。
- マルチマスター構成、ただしetcdはstacked(さすがにVM台数的に辛い)
- master x 3
- worker x 3
- loadbalancer x 1 ※ master用
- 構築はkubeadmを使います。
- CNIはCalico、といってもflannelとあまりよく違いがわかってないけど、Calicoの仕様によりpodネットワークは192.168.0.0/16になります。
こんな感じ。

Vagrant
レポジトリは以下にあります。最初に少しVagrant部分の説明をします。
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.provider "virtualbox" do |vb|
vb.memory = "512"
end
config.vm.synced_folder "./share", "/Vagrant" , type: "virtualbox"
# must be at the top
config.vm.define "lb-0" do |c|
c.vm.hostname = "lb-0"
c.vm.network "private_network", ip: "10.240.0.40"
c.vm.provision :shell, :path => "scripts/common/00-setup-initial.sh"
c.vm.provision :shell, :path => "scripts/lb/setup-haproxy.sh"
c.vm.provider "virtualbox" do |vb|
vb.memory = "256"
end
end
(0..2).each do |n|
config.vm.define "controller-#{n}" do |c|
c.vm.hostname = "controller-#{n}"
c.vm.network "private_network", ip: "10.240.0.1#{n}"
c.vm.provider "virtualbox" do |v|
v.gui = false
v.cpus = 2
v.memory = 2048
end
c.vm.provision :shell, :path => "scripts/common/00-setup-initial.sh"
c.vm.provision :shell, :path => "scripts/common/00-setup-k8s.sh"
end
end
(0..2).each do |n|
config.vm.define "worker-#{n}" do |c|
c.vm.hostname = "worker-#{n}"
c.vm.network "private_network", ip: "10.240.0.2#{n}"
c.vm.provider "virtualbox" do |v|
v.gui = false
v.cpus = 1
v.memory = 1024
end
c.vm.provision :shell, :path => "scripts/common/00-setup-initial.sh"
c.vm.provision :shell, :path => "scripts/common/00-setup-k8s.sh"
end
end
end
これでloadbalancer x 1、master x 3、worker x 3を構築します。結構リソースは必要です。プロビジョニングでスクリプトをそれぞれ呼んでいます。ちなみにsynced_folderを使っているのは、master間でファイルの受け渡しが発生するためです(sshの設定するのがめんどくさかった)
プロビジョニングで使っているスクリプトの中身はこんな感じです。
scripts/common/00-setup-initial.sh
全台共通で使っています。hostsファイルの設定、SELinuxの停止、firewalldの停止だけです。
#!/bin/bash set -euo pipefail cat <<EOF | sudo tee -a /etc/hosts 10.240.0.10 controller-0 10.240.0.11 controller-1 10.240.0.12 controller-2 10.240.0.20 worker-0 10.240.0.21 worker-1 10.240.0.22 worker-2 EOF # disable SELinux sudo setenforce 0 sudo sed -i -e "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config # disable firewalld sudo systemctl stop firewalld sudo systemctl disable firewalld
scripts/lb/setup-haproxy.sh
loadbalancer用のスクリプトです。haproxyの設定を行っています。これはhard wayのものをそのままにいくつかコメントアウトしただけです。(hard wayはubuntuベース、こちらはcentos)
#!/bin/bash
set -euo pipefail
yum update -y
yum install -y haproxy
grep -q -F 'net.ipv4.ip_nonlocal_bind=1' /etc/sysctl.conf || echo 'net.ipv4.ip_nonlocal_bind=1' >> /etc/sysctl.conf
cat >/etc/haproxy/haproxy.cfg <<EOF
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
#stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
#errorfile 400 /etc/haproxy/errors/400.http
#errorfile 403 /etc/haproxy/errors/403.http
#errorfile 408 /etc/haproxy/errors/408.http
#errorfile 500 /etc/haproxy/errors/500.http
#errorfile 502 /etc/haproxy/errors/502.http
#errorfile 503 /etc/haproxy/errors/503.http
#errorfile 504 /etc/haproxy/errors/504.http
frontend k8s
bind 10.240.0.40:6443
default_backend k8s_backend
backend k8s_backend
balance roundrobin
mode tcp
server controller-0 10.240.0.10:6443 check inter 1000
server controller-1 10.240.0.11:6443 check inter 1000
server controller-2 10.240.0.12:6443 check inter 1000
EOF
systemctl restart haproxy
systemctl enable haproxy
scripts/common/00-setup-k8s.sh
masterとworker用にk8sのコンポーネントのインストールと基本設定を行っています。kubernetesやdockerのバージョンは決め打ちにしています。バージョンコントロールは自分で制御したいので。
#!/bin/bash
set -euo pipefail
KUBERNETES_VERSION=1.17.3
DOCKER_VERSION=19.03.4
CONTAINERD_VERSION=1.2.10
# disable swap off
sudo swapoff -a
sudo sed -i '/ swap /s/^\(.*\)$/#\1/g' /etc/fstab
sudo rm -rf /swapfile
# install kubernetes repository
cat <<EOF | sudo tee -a /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
# install kubeadm, kubelet, kubectl
sudo yum install -y kubelet-${KUBERNETES_VERSION} kubeadm-${KUBERNETES_VERSION} kubectl-${KUBERNETES_VERSION} --disableexcludes=kubernetes
# enable kubelet
sudo systemctl enable --now kubelet
# enable network bridge
cat <<'EOF' | sudo tee -a /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
# install docker
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y --setopt=obsoletes=0 docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION containerd.io-${CONTAINERD_VERSION}
sudo systemctl enable docker && sudo systemctl start docker
sudo usermod -aG docker vagrant
# cgoup
sudo mkdir -p /etc/docker
cat <<'EOF' | sudo tee -a /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
sudo mkdir -p /etc/systemd/system/docker.service.d
# Restart Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
# get private network IP addr and set bind it to kubelet
IPADDR=$(ip a show eth1 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
sudo sed -i "/KUBELET_EXTRA_ARGS=/c\KUBELET_EXTRA_ARGS=--node-ip=$IPADDR" /etc/sysconfig/kubelet
# restart kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
やっていることはざっくりこんな感じ。
- kubernetesを動かすにはswapを無効にする必要があります。単純にfstabコメントアウトするだけではダメで、swapファイル自体も消してます。
- kubernetesのyumレポジトリを追加
- kubeadm, kubelet, kubectlをインストール
- ネットワークブリッジを有効化するためのカーネルパラメータを変更
- dockerをインストール
- dockerでgroupドライバーとしてsystemdを使う設定を追加
- dockerを再起動
- vagrant、というかvirtualboxでは標準でNAT用インタフェースとして10.0.2.15が割り当てられますが、これはホスト間の通信に使えません。kubeletは標準でこれをバインドしようとするので、これを回避するために設定を追加
- kubeletを再起動
Vagrantの起動
master/worker専用のプロビジョニング用ファイルとかもあるんですが、まだ未完成なのでとりあえず進めます。
レポジトリをcloneします。
$ git clone https://github.com/kun432/kubernetes-by-kubeadm-on-vagrant.git $ cd kubernetes-by-kubeadm-on-vagrant
vagrant upでVMを起動します。結構時間がかかります。マシンパワーがないと辛いかもしれません。
$ vagrant up
7台起動していればOKです。
$ vagrant status Current machine states: lb-0 running (virtualbox) controller-0 running (virtualbox) controller-1 running (virtualbox) controller-2 running (virtualbox) worker-0 running (virtualbox) worker-1 running (virtualbox) worker-2 running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run `vagrant status NAME`.
今日はここまで。プロビジョニングしかできていない・・・次回はmaster/workerの設定について。
なお、プロビジョニング用スクリプトは以下を参考にさせてもらいました。ありがとうございます。