※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の設定について。
なお、プロビジョニング用スクリプトは以下を参考にさせてもらいました。ありがとうございます。