🐈

シン・お家クラウドを構築する【1】- HAなk8sのセットアップ編

2024/04/13に公開

寒い冬も明け、心地よい日差しと爽やかな風、静寂を掻き消すサーバの音に新たな芽吹き。
ファンの爆音にツバメも目を覚ます頃でしょうか
エモいですね~

どうもmurasameです

本日は、新しく届いたサーバのセットアップをする過程でk8sの構成の刷新をしたのでそれについての轍を掲載していこうかなぁと思います。
解説ほぼなしで、手順だけ乗っけていきます。

サーバの紹介

今回セットアップするサーバの紹介を少し、

Node CPU MEM
mackerel Xeon E5-2667 v4 *2 64GB
puffer Xeon E5-2667 v4 *2 64GB
yellowtail Xeon E5-2667 v4 *2 64GB
shark Xeon E5-2667 v4 *2 64GB

全体に 16c/32tで構成されており、メモリは64GBの構成です。

kubernetesの構築

今回構築していくk8sの構成はこんな感じです。

Node Hostname CIDR type CPU / MEM / STO
mackerel k8s2-ha-proxy-1 10.0.1.4/8 LXC 1vCPU / 1GB / SSD 10GB
mackerel k8s2-ha-proxy-2 10.0.1.5/8 LXC 1vCPU / 1GB / SSD 10GB
mackerel k8s2-master-1 10.0.1.1/8 VM 4vCPU / 16GB / SSD 100GB
mackerel k8s2-master-2 10.0.1.2/8 VM 4vCPU / 16GB / SSD 100GB
mackerel k8s2-master-3 10.0.1.3/8 VM 4vCPU / 16GB / SSD 100GB
puffer k8s2-slave-1 10.0.2.1/8 VM 8vCPU*2 / 32GB / SSD 100GB
puffer k8s2-slave-2 10.0.2.2/8 VM 8vCPU*2 / 32GB / SSD 100GB
yellowtail k8s2-slave-3 10.0.3.1/8 VM 8vCPU*2 / 32GB / SSD 100GB
yellowtail k8s2-slave-4 10.0.3.2/8 VM 8vCPU*2 / 32GB / SSD 100GB
shark k8s2-slave-5 10.0.4.1/8 VM 8vCPU*2 / 32GB / SSD 100GB
shark k8s2-slave-6 10.0.4.2/8 VM 8vCPU*2 / 32GB / SSD 100GB

全体的に扱うのはubuntu server 22.04を利用します。
puffer, yellowtail,sharkをVMで2分割してる理由としては、単純にたくさんノードを扱いたかっただけです。

最終的にこんな感じの構成になればいいかなぁと考えてます

参考:高可用性トポロジーのためのオプション

LBの構築

masterが冗長化されているk8sではLBを構築する必要があります。nginxなど利用されることもありますが、今回はHA-Proxyを利用します。
k8s2-ha-proxy-1とk8s2-ha-proxy-2をKeepalibedを利用してVRRPを張りたいと思います。

haproxyの設定

今回etcdはmaster内部のものを利用し、APIserverを冗長化しようと思います。

apt update && apt upgrade -y
apt install haproxy keepalived
cat << _EOF_ >> /etc/haproxy/haproxy.cfg
frontend api
  bind *:6443
  mode tcp
  option tcplog
  default_backend api

backend api
  mode tcp
  option tcplog
  option tcp-check
  balance leastconn
  server master1 10.0.1.1:6443 check
  server master2 10.0.1.2:6443 check backup
  server master3 10.0.1.3:6443 check backup
_EOF_
systemctl restart haproxy.service
systemctl enable haproxy.service

Keepalived

この設定もそれぞれk8s2-ha-proxy-1とk8s2-ha-proxy-2に行ってください

echo "
global_defs {
  notification_email {
  }
  router_id LVS_DEVEL
  vrrp_skip_check_adv_addr
  vrrp_garp_interval 0
  vrrp_gna_interval 0
}

vrrp_script chk_haproxy {
  script "killall -0 haproxy"
  interval 2
  weight 2
}

vrrp_instance haproxy-vip {
  state BACKUP
  priority 100
  interface eth0                       # 適切なネットワークカードを選択してください
  virtual_router_id 60
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  unicast_src_ip 10.0.1.4             # このマシンのアドレス
  unicast_peer {
    10.0.1.5                          # 相手のマシンのアドレス
  }

  virtual_ipaddress {
    10.0.0.100/8                      # VIP
  }

  track_script {
    chk_haproxy
  }
}
" > /etc/keepalived/keepalived.conf

systemctl restart keepalived
systemctl enable keepalived

kubernetes の構築

今回は現状最新の1.29の構築をしていきます。

下準備

masterとslave両方やろう!

sudo apt update && sudo apt upgrade -y
# ipv4のフォワーディング有効に…
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system
# swapの無効化
sudo swapoff -a
sudo vi /etc/fstab

/etc/fstabを

-/swap.img      none    swap    sw      0       0 
+# /swap.img      none    swap    sw      0       0

kubelet , kubeadm , kubectl のインストール

これも両方やろう

sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | 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

参考:kubeadm、kubelet、kubectlのインストール

CRI-Oのセットアップ

これも両方やろう!

sudo su
apt install -y jq
curl https://raw.githubusercontent.com/cri-o/packaging/main/get | bash
sudo systemctl daemon-reload
sudo systemctl enable crio
sudo systemctl start crio

参考:cri-o(GitHub)

masterのセットアップ

ここまで来たらあと少し!

sudo kubeadm init --control-plane-endpoint 10.0.0.100:6443 --pod-network-cidr=10.1.0.0/16 --upload-certs

を実行。ここで注意が、--control-plane-endpoint に設定される値は最初のほうで設定したVIPを指定してください。 --pod-network-cidr=10.1.0.0/16はpod内で扱うネットワークの設定なのでよしなに

#==================================================================================================
# Your Kubernetes control-plane has initialized successfully!

# To start using your cluster, you need to run the following as a regular user:

#   mkdir -p $HOME/.kube
#   sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
#   sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Alternatively, if you are the root user, you can run:

#   export KUBECONFIG=/etc/kubernetes/admin.conf

# You should now deploy a pod network to the cluster.
# Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
#   https://kubernetes.io/docs/concepts/cluster-administration/addons/

# You can now join any number of the control-plane node running the following command on each as root:

#   kubeadm join 10.0.0.100:6443 --token ********* \
#         --discovery-token-ca-cert-hash sha256:********* \
#         --control-plane --certificate-key *********

# Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
# As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
# "kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

# Then you can join any number of worker nodes by running the following on each as root:

# kubeadm join 10.0.0.100:6443 --token ********* \
#         --discovery-token-ca-cert-hash sha256:*********

みたいなのが出るとmasterの初期化成功です。
あとは残りのmasterとworkerをjoinさせれば終了

# master-2, master-3でこっちのコマンド
sudo kubeadm join 10.0.0.100:6443 --token ********* \
--discovery-token-ca-cert-hash sha256:********* \
--control-plane --certificate-key *********

すべてのノードでkubectlが使えるようにセットアップ

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

これでmasterはおしまい!

workerのセットアップ

sudo kubeadm join 10.0.0.100:6443 --token ********* \
        --discovery-token-ca-cert-hash sha256:*********

すべてのセットアップ済のworkerに対してjoinのコマンドを入力すれば完了!

kubectl get nodes
NAME            STATUS   ROLES           AGE   VERSION
k8s2-master-1   Ready    control-plane   56m   v1.29.3
k8s2-master-2   Ready    control-plane   51m   v1.29.3
k8s2-master-3   Ready    control-plane   51m   v1.29.3
k8s2-slave-1    Ready    <none>          16s   v1.29.3
k8s2-slave-2    Ready    <none>          15s   v1.29.3
k8s2-slave-3    Ready    <none>          14s   v1.29.3
k8s2-slave-4    Ready    <none>          14s   v1.29.3
k8s2-slave-5    Ready    <none>          13s   v1.29.3
k8s2-slave-6    Ready    <none>          13s   v1.29.3

こんな感じになってれば準備完了

CNIの準備

今回はcalicoを利用します。(実は失敗だったがまぁいいや)

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
# カスタムリソースのDL
curl https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/custom-resources.yaml -O

custom-resource.yamlの spec.calicoNetwork.ipPools[0].cidrを init時の--pod-network-cidrに修正してください

# This section includes base Calico installation configuration.
# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    # Note: The ipPools section cannot be modified post-install.
    ipPools:
    - blockSize: 26
      cidr: 10.1.0.0/16 # <-ここのアドレスを initした時の--pod-network-cidrに合わせる
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()

---

# This section configures the Calico API server.
# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
  name: default
spec: {}

カスタムリソースのデプロイ

kubectl apply -f custom-resources.yaml
kubectl get pod -n calico-system 
# これですべてのpodがrunningなってたらOK
kubectl get pod -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7cdf75fbc7-z7n6g   1/1     Running   0          6d14h
calico-node-2nqr7                          1/1     Running   0          6d14h
calico-node-7c4kn                          1/1     Running   0          6d14h
calico-node-gj4sq                          1/1     Running   1          6d14h
calico-node-gnzsh                          1/1     Running   0          6d14h
calico-node-ml5qw                          1/1     Running   0          6d14h
calico-node-tmvtf                          1/1     Running   0          6d14h
calico-node-wtw29                          1/1     Running   3          6d14h
calico-node-wz4bn                          1/1     Running   0          6d14h
calico-node-z2cn5                          1/1     Running   0          6d14h
calico-typha-7c56499d7c-6jvbb              1/1     Running   0          6d14h
calico-typha-7c56499d7c-mwrgh              1/1     Running   0          6d14h
calico-typha-7c56499d7c-wmwx2              1/1     Running   0          6d14h
csi-node-driver-4hns7                      2/2     Running   0          6d14h
csi-node-driver-4tjw9                      2/2     Running   0          6d14h
csi-node-driver-6ch9z                      2/2     Running   0          6d14h
csi-node-driver-dbcnv                      2/2     Running   4          6d14h
csi-node-driver-g8xc9                      2/2     Running   2          6d14h
csi-node-driver-nkztd                      2/2     Running   0          6d14h
csi-node-driver-sb7wn                      2/2     Running   0          6d14h
csi-node-driver-sf5f2                      2/2     Running   0          6d14h
csi-node-driver-wjgrn                      2/2     Running   0          6d14h

これ、そこそこ時間がかかるのでゆっくりお茶でもしながら待ちましょう!
すべてが終わったそこのあなた!楽しいk8sライフを楽しみましょう!

MetalLBのセットアップ

自宅鯖勢でもLoadBalancerを活用したい!
そんなあなたにMetalLBを。。。(Calicoミスった。でも動いてるからヨシ!)
calicoだと限定的なサポートになっている…

trictARPの許可

# 変更の確認
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system
# 変更の適用
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system

MetalLBのデプロイ

helm repo add metallb https://metallb.github.io/metallb
kubectl create ns metallb-system
helm install metallb metallb/metallb -n metallb-system

Address Poolの設定

ここで設定した値のレンジがLoadBalancerに割り当てられるIP。
10.0.100.0-10.0.100.100に今回設定したいのでその範囲で設定。

echo "
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default
  namespace: metallb-system
spec:
  addresses:
  - 10.0.100.0-10.0.100.100
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
  - default
" > tee addresspool.yaml
kubectl apply -f addresspool.yaml

動作確認

apiVersion: v1
kind: Pod
metadata:
  name: "nginx"
  labels:
    app: "nginx"
spec:
  containers:
  - name: nginx
    image: "nginx:latest"
    ports:
    - containerPort:  80
      name:  http
  restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: LoadBalancer
  ports:
  - name: nginx
    protocol: TCP
    port: 80
    targetPort: 80

NAME        READY   STATUS    RESTARTS   AGE
pod/nginx   1/1     Running   0          12s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        6d17h
service/nginx        LoadBalancer   10.110.115.132   10.0.100.2    80:31099/TCP   12s

service/nginxに10.0.100.2が割り当てられているのでそこにアクセスしてみよう

nginxが正常にデプロイされてそうですね!

最後に

CNIはfannelとかに変えたほうがいいです。
バージョン変わってできねぇよ!ってなったらコメントとかTwitterで教えてもらえると直します。

Discussion