久しぶりに構築したのでそのメモ
今回はmetalLBも入れる
更新日時
- 2021/04/28 初版
- 2021/07/01 k8sをv1.21.2に, 色々ラリっていたのを修正
目次
- 各種データとか
- テンプレートdomainの作成
- router構築
- LB構築
- k8s構築(calico, kubeadmのあれこれ)
- metal LBデプロイ
各種データとか
version
- kubeadm/kubelet/kubectl: v1.21
- HAProxy: v2.0.13
- MetalLB: v0.10.2
- bird: v2.0.8
network表
network 備考 192.168.20.0/24
物理ホスト用 192.168.21.0/24
仮想ホスト用 192.168.22.0/24
k8s service用 10.255.0.0/16
pod network用 ホスト表
node ip 備考 L3SW
192.168.20.1
GW L3SW
192.168.21.1
GW kvm
192.168.20.2
全部乗せる仮想基盤(fedora) k8s-lb
192.168.21.10
master node用lb k8s-c1
192.168.21.11
k8s controller node k8s-c2
192.168.21.12
k8s controller node k8s-c3
192.168.21.13
k8s controller node k8s-w1
192.168.21.14
k8s worker node k8s-w2
192.168.21.15
k8s worker node k8s-w3
192.168.21.16
k8s worker node k8s-lb1
192.168.21.16
master node用lb-1号機(予定) k8s-lb2
192.168.21.17
master node用lb-2号機(予定) k8s-rt1
192.168.21.18
bgpしゃべるrouter-1号機(予定) k8s-rt2
192.168.21.19
bgpしゃべるrouter-2号機(予定) k8s-rt
192.168.21.20
bgpしゃべるrouter ただし、
k8s-lb1
,k8s-lb2
,k8s-rt1
,k8s-rt2
は予定(時間あればVRRPでLBとrouterを冗長化したい)kvm
,k8s-rt
のみfedora34, 他はubuntu20.04他
- CRIプラグイン: container.io(選定理由は特に無い)
- CNIプラグイン: Calico(選定理由は特に無い(L3って良いよね))
- LB: HAProxy(選定理由は特に無い(慣れてるので))
- router: bird(選定理由は特に無い(configがシンプルなの良いよね))
- frrは諦めた
- AS番号: 65000(router側), 65001(metal LB側)
テンプレートdomainの作成
Ubuntu20.04
- 空のdomainを作る
- 適当なUbuntu ISOからubuntuをinstallする
- datetime(
datetimectl set-timezone Asia/Tokyo
), ssh(cat ~/.ssh/authorized_keys
)を確認する- datetimeがズレているとBGPセッションがESTABLISHEDにならないので注意
Fedora34
- 空のdomainを作る
- 適当なfedora34 ISOからfedoraをinstallする
- datetime(
datetimectl set-timezone Asia/Tokyo
), ssh(cat ~/.ssh/authorized_keys
)を確認する- datetimeがズレているとBGPセッションがESTABLISHEDにならないので注意
router構築
metal LBをL3モードで動かすためにBGPを話すrouterを用意する
Gateway(今回の場合L3SW)にログインして
192.168.22.0/24
のgatewayを192.168.21.20
にするstatic routeを追加する(Cisco IOSならip route 192.168.22.0 255.255.255.0 192.168.21.20
とか)Fedoraのテンプレートdomainをクローンする
以下のように作業する
# IPアドレス/hostnameを設定する $ nmcli c m enp1s0.21 ipv4.method manual ipv4.address 192.168.21.20/24 ipv4.gateway 192.168.21.1 $ nmcli c d enp1s0.21 && nmcli c u enp1s0.21 $ sudo hostnamectl set-hostname k8s-rt # カーネルパラメータを変更する $ cat <<EOF | sudo tee /etc/sysctl.d/00-bird.conf net.ipv4.ip_forward = 1 EOF $ sudo sysctl --system # BGPをfirewallで通すようにする $ sudo firewall-cmd --add-service=bgp --zone=public $ sudo firewall-cmd --add-service=bgp --zone=public --permanent # birdをinstallする $ sudo dnf install bird # configを投入する $ sudo cp /etc/bird.conf /etc/bird.conf.old $ cat <<EOF | sudo tee /etc/bird.cfg log syslog all; router id 192.168.21.20; define my_asn = 65000; define my_addr = 192.168.21.20; protocol device { } protocol direct { disabled; # Disable by default ipv4; # Connect to default IPv4 table ipv6; # ... and to default IPv6 table } protocol kernel { persist; merge paths; # ECMP ipv4 { # Connect protocol to IPv4 table by channel export all; # Export to protocol. default is export none }; } protocol kernel { ipv6 { export all; }; } protocol static { ipv4; # Again, IPv4 channel with default options route 0.0.0.0/0 via 192.168.21.1; } template bgp metal_lb{ description "Metal LB"; local as 65000; hold time 90; # Default is 240 password "secret"; # Password used for MD5 authentication ipv4 { # regular IPv4 unicast (1/1) import all; export where source ~ [ RTS_STATIC, RTS_BGP ]; }; ipv6 { # regular IPv6 unicast (2/1) import all; export filter { # The same as 'where' expression above if source ~ [ RTS_STATIC, RTS_BGP ] then accept; else reject; }; }; } protocol bgp lb101 from metal_lb { neighbor 192.168.21.11 as 65001; } protocol bgp lb102 from metal_lb { neighbor 192.168.21.12 as 65001; } protocol bgp lb103 from metal_lb { neighbor 192.168.21.13 as 65001; } protocol bgp lb104 from metal_lb { neighbor 192.168.21.14 as 65001; } protocol bgp lb105 from metal_lb { neighbor 192.168.21.15 as 65001; } protocol bgp lb106 from metal_lb { neighbor 192.168.21.16 as 65001; } EOF # birdcを有効化する $ sudo systemctl enable --now bird # birdcを再読込する $ sudo bird $ configure $ exit
LB構築
k8s構築で作ったUbuntu20.04のdomainをLB用に1つクローンする
以下のように作業する
# IPアドレス/hostnameを設定する $ sudo vim /etc/netplan/00-installer-config.yaml $ sudo netplan apply $ sudo hostnamectl set-hostname k8s-c1 # HAProxyのインストール $ sudo apt install haproxy # configの設定 $ sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old $ cat <<EOF | sudo tee /etc/haproxy/haproxy.cfg global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats timeout 30s user haproxy group haproxy daemon defaults log global mode tcp option tcplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend k8s_frontend bind 192.168.21.10:6443 default_backend k8s_backend backend k8s_backend balance roundrobin mode tcp server k8s-c1 192.168.21.11:6443 check inter 1000 server k8s-c2 192.168.21.12:6443 check inter 1000 server k8s-c3 192.168.21.13:6443 check inter 1000 listen stats bind *:1936 mode http stats enable stats refresh 15s stats show-legends stats show-node stats uri / EOF $ sudo vim /etc/haproxy/haproxy.cfg # カーネルパラメータを変更する $ cat <<EOF | sudo tee /etc/sysctl.d/00-haproxy.conf net.ipv4.ip_nonlocal_bind = 1 EOF $ sudo sysctl --system # HAProxyを有効化する $ sudo systemctl enable --now haproxy
stats(
http://192.168.21.10:1936
)が見えることを確認する
k8s構築
テンプレート用Ubuntu20.04からk8s共通用にdomainを1つcloneする
以下の共通部分を作業する
# 既存パッケージの更新 $ sudo apt update $ sudo apt upgrade $ sudo apt clean $ sudo apt autoremove # swapを切る $ sudo swapoff -a # fstabからswapを無効にする $ sudo vim /etc/fstab # 余計なdaemonを止める $ sudo systemctl disable --now snapd.service snapd.socket unattended-upgrades.service $ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF # kernel moduleを読み込む $ sudo modprobe overlay $ sudo modprobe br_netfilter # k8s稼働に必要なカーネルパラメータを変更する $ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF $ sudo sysctl --system # container.ioを入れる $ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt update $ sudo apt install containerd.io $ sudo mkdir -p /etc/containerd # configの作成と反映 $ containerd config default | sudo tee /etc/containerd/config.toml $ sudo systemctl restart containerd # kubelet, kubeadm, kubectlを入れる $ sudo apt-get update $ sudo apt-get install -y apt-transport-https ca-certificates curl $ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg $ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list $ sudo apt update $ sudo apt install -y kubelet kubeadm kubectl # バージョンを固定する $ sudo apt-mark hold kubelet kubeadm kubectl # 止める $ sudo systemctl poweroff
上記のdomainを6つにクローンする
各domainでIPアドレス/hostnameを設定する
$ sudo vim /etc/netplan/00-installer-config.yaml $ sudo netplan apply $ sudo hostnamectl set-hostname k8s-c1
controller1号機で初期セットアップを行う
kubeadm initを行う
$ sudo kubeadm init --control-plane-endpoint="192.168.21.10:6443" --apiserver-advertise-address="192.168.21.11" --kubernetes-version="v1.21.2" --pod-network-cidr="10.255.0.0/16" --upload-certs | sudo tee -a /etc/kubernetes/kubeadm-init.result
calicoを入れる
$ wget https://docs.projectcalico.org/manifests/calico.yaml # L3672あたりのCALICO_IPV4POOL_CIDRのコメント化を解除し10.255.0.0/16を入れる(--pod-network-cidrで指定した値と同じやつ) $ vim calico.yaml $ kubectl apply -f calico.yaml
kube-systemのnamespaceに所属するpodが全てrunningになるまで待つ
$ kubectl get pods -n kube-system -o wide
お手元マシンで動かすように情報を取得しておく
$ kubectl config view --raw
(OPTIONAL)お手元マシンに上記configをmergeする(ここではcontext名を
lab1
とする)# cluster/context/userをmergeする $ vim .kube/config
metal LBデプロイ
kubeadm(contextの向き先は
lab1
)が使える環境で以下のファイルを作成するkustomization.yml
namespace: metallb-system resources: - github.com/metallb/metallb//manifests?ref=v0.10.2 - configmap.yml
configmap.yml
--- apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | peers: - peer-address: 192.168.21.20 peer-asn: 65000 my-asn: 65001 password: "secret" address-pools: - name: default protocol: bgp addresses: - 192.168.22.0/24 avoid-buggy-ips: true
kubectl apply -k . --server-side
を実行する- kubectl v1.21未満の場合は
kustomize build ./ | kubectl apply --server-side -f -
(ref)
- kubectl v1.21未満の場合は
k8s-rt
にログインし以下のコマンドを叩いて全てのBGPセッションがESTABLISHEDになっていることを確認する$ sudo birdc $ show protocols all
以下のような適当なdeploymentを用意し疎通するか確認する
--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: strm/helloworld-http ports: - name: http containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - name: http port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
$ kubectl apply -f nginx.yaml --server-side # EXTERNAL-IPが付与されていれば成功 $ kubectl get svc nginx $ curl <EXTERNAL-IP>
k8s-rt
でECMPになっていることを確認する$ ip route ... 192.168.22.1 proto bird metric 32 nexthop via 192.168.21.11 dev enp1s0.21 weight 1 nexthop via 192.168.21.12 dev enp1s0.21 weight 1 nexthop via 192.168.21.13 dev enp1s0.21 weight 1 nexthop via 192.168.21.14 dev enp1s0.21 weight 1 nexthop via 192.168.21.15 dev enp1s0.21 weight 1 nexthop via 192.168.21.16 dev enp1s0.21 weight 1
参考文献
- Kubernetes Documentation
- HAProxy Configuration Manual
- BIRD User's Guide
- MetalLB Documentation
- FRRouting, OpenBGPd and BIRD
- 各routing daemonの比較はこれが分かりやすい(今思えばgobgpでも良かったかも)
- ルーティングソフトウェア BIRD の使いかた - Cybozu Inside Out | サイボウズエンジニアのブログ
おわり