Open10

おうちKubernetesの構築時メモ

imamoto_hikaruimamoto_hikaru

Ubuntu serverの初期設定メモ

事前準備

  • microSDにRaspberryPi OSをDL
  • microSDとSSDをRaspberryPiに接続

Raspberry Pi OSでの作業

  • RaspberryPi ImagerでUbuntu Server 24.04.1 LTSをダウンロード
    • Timezone: Asia/Tokyo, Keyboard: us
    • User/PWを設定
    • SSH有効化
  • ファイルマネージャーのsystem-boot/media/ユーザー名/system-boot/config.txtcを編集して以下を追記
dtparam=pciex1(またはdtparam=nvme)
dtparam=pciex1_gen=3
  • RaspberryPi OSをシャットダウン
  • microSDを抜いてから再度起動する

Ubuntuでやった作業

ホスト名変更

  • hostnamectlコマンドで任意のホスト名に変更
hostnamectl set-hostname rasp001

net-toolsインストール

sudo apt update
sudo apt install net-tools

(必要であれば)日本語化

sudo apt -y install language-pack-ja-base language-pack-ja
localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
source /etc/default/locale
echo $LANG

現在のネットワーク設定を確認

# 現在のIP、サブネットマスク、ネットワークアダプタ名等を確認
# IP: 192.168.129.135
# SubnetMask: 255.255.240.0
# Broadcast address: 192.168.143.255
# Network Adapter: eth0
# 使用可能範囲: 192.168.128.1~192.168.143.254
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 2c:cf:67:5e:f3:29 brd ff:ff:ff:ff:ff:ff
    inet 192.168.129.135/20 metric 100 brd 192.168.143.255 scope global dynamic eth0
       valid_lft 42281sec preferred_lft 42281sec
    inet6 fde6:c499:c32a:f283:2ecf:67ff:fe5e:f329/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 1781sec preferred_lft 1781sec
    inet6 fe80::2ecf:67ff:fe5e:f329/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 2c:cf:67:5e:f3:2a brd ff:ff:ff:ff:ff:ff

# デフォルトゲートウェイ(192.168.128.2)を確認
$ route -n
カーネルIP経路テーブル
受信先サイト    ゲートウェイ    ネットマスク   フラグ Metric Ref 使用数 インタフェース
0.0.0.0         192.168.128.2   0.0.0.0         UG    100    0        0 eth0
61.215.192.144  192.168.128.2   255.255.255.255 UGH   100    0        0 eth0
192.168.128.0   0.0.0.0         255.255.240.0   U     100    0        0 eth0
192.168.128.2   0.0.0.0         255.255.255.255 UH    100    0        0 eth0
210.250.61.20   192.168.128.2   255.255.255.255 UGH   100    0        0 eth0
219.127.220.16  192.168.128.2   255.255.255.255 UGH   100    0        0 eth0

(必要であれば)静的IPを設定(Ethernet利用)

  • /etc/netplan/51-manual.yamlをパーミッション600で作成して以下の通り編集
    • network.version2
    • `network.ethernets.[NetworkAdapter名(今回はeth0)]
      • dhcp4no
      • addresses[設定するIP/サブネットマスクのビット数]
      • routes
        • todefault
        • viaはデフォルトゲートウェイ(今回は192.168.128.2)
      • nameservers.addresses[8.8.8.8,8.8.8.4]
network:
    version: 2
    ethernets:
        eth0:
            dhcp4: no
            addresses: [192.168.130.1/20]
            routes:
                - to: default
                  via: 192.168.128.2
            nameservers:
                addresses: [8.8.8.8,8.8.8.4]
  • yamlファイルを作成したらsudo netplan tryでエラーが出ないことを確認してreturnで設定を確定
imamoto_hikaruimamoto_hikaru

Cloudflareを使って自宅のRaspberryPiへSSH

こちらのブログをめちゃめちゃ参考にさせていただきました。
https://zenn.dev/jij_inc/articles/659fe35813b940

やったこと

  1. Cloudflareのアカウント作成
  2. Cloudflareダッシュボードの「Domain Regisration > Register Domains」からドメインを新規取得
  3. ダッシュボードからZero Trustメニューに進み「Networks > Tunnels」の「Create a tunnel」から新規トンネル作成
  4. 作成したトンネル設定からコマンドをコピーして、RaspberryPiにcloudflaredをインストール
    • UbuntuServerなので、Debianのarm64-bitを選択
  5. Zero Trustメニューの「Access > Applications」から、作成したトンネルと紐づくApplicationを作成
  6. 接続元となるクライアントPCにcloudflaredをインストールして、トンネルで設定したドメインに対してSSHログイン
  7. ブラウザが自動起動するのでcloudflareの認証を実施して設定完了
imamoto_hikaruimamoto_hikaru

コンテナランタイムのインストール

Kubernetes公式の手順を元に作業実施。とりあえずcontainerdを入れていく
https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/

1.IPv4フォワーディングを有効化し、iptablesからブリッジされたトラフィックを見えるようにする

以下のコマンドを実行

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

確認

# 各モジュールが読み込まれていることを確認
lsmod | grep br_netfilter
lsmod | grep overlay

# 各カーネルパラメータが1に設定されていることを確認
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

2. containerd, runcのインストール

こちらを参考にインストール。Docker配布のcontainerdもあるが、今回は公式のバイナリファイルからインストールする

# containerdのインストール
wget https://github.com/containerd/containerd/releases/download/v2.0.1/containerd-2.0.1-linux-arm64.tar.gz
sudo tar Cxzvf /usr/local containerd-2.0.1-linux-arm64.tar.gz

# systemd
wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo mv containerd.service /lib/systemd/system/containerd.service
systemctl daemon-reload
systemctl enable --now containerd

# runcのインストール
wget https://github.com/opencontainers/runc/releases/download/v1.2.3/runc.arm64
sudo install -m 755 runc.arm64 /usr/local/sbin/runc

3. containerdのデフォルト設定ファイルを作成

mkdir /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

4. runcのcgroupドライバーをsystemdcgroupドライバーにする

initにsystemdを使っておりcgroupもv2のため、
config.tomlファイルを編集
plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.optionsSystemdCgroup = trueを追記する

[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
  ...
  SystemdCgroup = true

設定を変更したらcontainerdを再起動

sudo systemctl restart containerd
imamoto_hikaruimamoto_hikaru

メモ:cgroupドライバーについて

  • kubeletとコンテナランタイムではcgroupとインターフェースするためにcgroupドライバーを設定する必要がある
  • kubeletとコンテナランタイムで使用するcgroupドライバーは同一にする必要がある
  • cgroupfsまたはsystemdが選べて、kubeletのデフォルトはcgroupfsになっている
  • 以下の場合はcgroupドライバーをsystemdに変更する
    • initシステムがsystemdである場合はcgroupドライバーもsystemdにすることが推奨
      • systemdはcgroupマネージャーが単一であることを想定しているため、別のcgroupマネージャーが存在しているとリソースを正しくリソースの管理ができず高負荷を招くため
    • cgroup v2を使用している場合
imamoto_hikaruimamoto_hikaru

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

https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/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.32/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
imamoto_hikaruimamoto_hikaru

kubeadmを使ったクラスター構築

こちらの手順を参考に実施
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

コントロールプレーンノードで必要なimageをpullできるか確認

sudo kubeadm config images pull

結果

[config/images] Pulled registry.k8s.io/kube-apiserver:v1.32.0
[config/images] Pulled registry.k8s.io/kube-controller-manager:v1.32.0
[config/images] Pulled registry.k8s.io/kube-scheduler:v1.32.0
[config/images] Pulled registry.k8s.io/kube-proxy:v1.32.0
[config/images] Pulled registry.k8s.io/coredns/coredns:v1.11.3
[config/images] Pulled registry.k8s.io/pause:3.10
[config/images] Pulled registry.k8s.io/etcd:3.5.16-0

コントロールプレーン向けのVIP設定

kube-vipを使ってstatic pod(ARPモード)で設定する
https://kube-vip.io/docs/installation/static/

kube-vip向け環境変数設定

# コントロールプレーン用VIPを設定(利用できるIPであればOK)
export VIP=192.168.130.21
# インターフェース名を設定(`ip a`で確認可能)
export INTERFACE=eth0
#kube-vipのバージョンを指定。以下は最新バージョンを取得している
KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")

kube-vip用のaliasコマンドを作成

# コンテナランタイムがcontainerdの場合
alias kube-vip="ctr image pull ghcr.io/kube-vip/kube-vip:$KVVERSION; ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip"

# コンテナランタイムがDockerの場合
alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:$KVVERSION"

kube-vip用マニフェスト作成

kube-vip manifest pod \
    --interface $INTERFACE \
    --address $VIP \
    --controlplane \
    --services \
    --arp \
    --leaderElection | tee /etc/kubernetes/manifests/kube-vip.yaml

作成されたマニフェストを一時的に編集する。
こちらのIssue commentを参考に、super-admin.confを指定

クラスター初期化

kubeadm initで初期化

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

kube-vipの設定値をもとに戻す

super-admin.confからadmin.confに変更

imamoto_hikaruimamoto_hikaru

kubectlをrootユーザー以外でも実行できるようにする

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

WorkerNodeをクラスターへ参加させる

Control Plane Nodeにてkubeadm initした際に出力されたコマンドを各WorkerNodeにて実行

sudo kubeadm join 192.168.130.21:6443 --token <token> \
        --discovery-token-ca-cert-hash <hash値>
imamoto_hikaruimamoto_hikaru

Podネットワークアドオンをデプロイ

以下を参照しながらCalicoをインストールする
https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises

Operatorのデプロイ

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/tigera-operator.yaml

namespace/tigera-operator created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpfilters.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/caliconodestatuses.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipreservations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/tiers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/adminnetworkpolicies.policy.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/apiservers.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/imagesets.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/installations.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/tigerastatuses.operator.tigera.io created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created

CRDデプロイ

# Manifestダウンロード
curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/custom-resources.yaml -O

# CRD作成
kubectl create -f custom-resources.yaml

installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created

Networkingリソースをデプロイ

Manifestのダウンロード

curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/calico.yaml -O

Manifestの値を変更

kubeadm initpod-network-cidrで指定した値と同じ値をCALICO_IPV4POOL_CIDRとして設定する

Manifestのapply

kubectl apply -f calico.yaml