久しぶりに構築したのでそのメモ

今回はmetalLBも入れる

更新日時

目次

  1. 各種データとか
  2. テンプレートdomainの作成
  3. router構築
  4. LB構築
  5. k8s構築(calico, kubeadmのあれこれ)
  6. metal LBデプロイ

各種データとか

  1. version

    • kubeadm/kubelet/kubectl: v1.21
    • HAProxy: v2.0.13
    • MetalLB: v0.10.2
    • bird: v2.0.8
  2. network表

    network備考
    192.168.20.0/24物理ホスト用
    192.168.21.0/24仮想ホスト用
    192.168.22.0/24k8s service用
    10.255.0.0/16pod network用
  3. ホスト表

    nodeip備考
    L3SW192.168.20.1GW
    L3SW192.168.21.1GW
    kvm192.168.20.2全部乗せる仮想基盤(fedora)
    k8s-lb192.168.21.10master node用lb
    k8s-c1192.168.21.11k8s controller node
    k8s-c2192.168.21.12k8s controller node
    k8s-c3192.168.21.13k8s controller node
    k8s-w1192.168.21.14k8s worker node
    k8s-w2192.168.21.15k8s worker node
    k8s-w3192.168.21.16k8s worker node
    k8s-lb1192.168.21.16master node用lb-1号機(予定)
    k8s-lb2192.168.21.17master node用lb-2号機(予定)
    k8s-rt1192.168.21.18bgpしゃべるrouter-1号機(予定)
    k8s-rt2192.168.21.19bgpしゃべるrouter-2号機(予定)
    k8s-rt192.168.21.20bgpしゃべる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

  1. 空のdomainを作る
  2. 適当なUbuntu ISOからubuntuをinstallする
  3. datetime(datetimectl set-timezone Asia/Tokyo), ssh(cat ~/.ssh/authorized_keys)を確認する
    • datetimeがズレているとBGPセッションがESTABLISHEDにならないので注意

Fedora34

  1. 空のdomainを作る
  2. 適当なfedora34 ISOからfedoraをinstallする
  3. datetime(datetimectl set-timezone Asia/Tokyo), ssh(cat ~/.ssh/authorized_keys)を確認する
    • datetimeがズレているとBGPセッションがESTABLISHEDにならないので注意

router構築

metal LBをL3モードで動かすためにBGPを話すrouterを用意する

  1. 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とか)

  2. Fedoraのテンプレートdomainをクローンする

  3. 以下のように作業する

    # 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構築

  1. k8s構築で作ったUbuntu20.04のdomainをLB用に1つクローンする

  2. 以下のように作業する

    # 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
    
  3. stats(http://192.168.21.10:1936)が見えることを確認する

k8s構築

  1. テンプレート用Ubuntu20.04からk8s共通用にdomainを1つcloneする

  2. 以下の共通部分を作業する

    # 既存パッケージの更新
    $ 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
    
  3. 上記のdomainを6つにクローンする

  4. 各domainでIPアドレス/hostnameを設定する

    $ sudo vim /etc/netplan/00-installer-config.yaml
    $ sudo netplan apply
    $ sudo hostnamectl set-hostname k8s-c1
    
  5. controller1号機で初期セットアップを行う

    1. 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
      
    2. 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
      
    3. kube-systemのnamespaceに所属するpodが全てrunningになるまで待つ

      $ kubectl get pods -n kube-system -o wide
      
    4. お手元マシンで動かすように情報を取得しておく

      $ kubectl config view --raw
      
  6. (OPTIONAL)お手元マシンに上記configをmergeする(ここではcontext名をlab1とする)

    # cluster/context/userをmergeする
    $ vim .kube/config
    

metal LBデプロイ

  1. 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
      
  2. kubectl apply -k . --server-sideを実行する

    • kubectl v1.21未満の場合はkustomize build ./ | kubectl apply --server-side -f -(ref)
  3. k8s-rtにログインし以下のコマンドを叩いて全てのBGPセッションがESTABLISHEDになっていることを確認する

    $ sudo birdc
    $ show protocols all
    
  4. 以下のような適当な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>
    
  5. 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
    

参考文献

おわり