Open10
おうちKubernetesの構築時メモ
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.version
は2
- `network.ethernets.[NetworkAdapter名(今回はeth0)]
-
dhcp4
はno
-
addresses
は[設定するIP/サブネットマスクのビット数]
-
routes
-
to
はdefault
-
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で設定を確定
Cloudflareを使って自宅のRaspberryPiへSSH
こちらのブログをめちゃめちゃ参考にさせていただきました。
やったこと
- Cloudflareのアカウント作成
- Cloudflareダッシュボードの「Domain Regisration > Register Domains」からドメインを新規取得
- ダッシュボードからZero Trustメニューに進み「Networks > Tunnels」の「Create a tunnel」から新規トンネル作成
- 作成したトンネル設定からコマンドをコピーして、RaspberryPiにcloudflaredをインストール
- UbuntuServerなので、Debianのarm64-bitを選択
- Zero Trustメニューの「Access > Applications」から、作成したトンネルと紐づくApplicationを作成
- 接続元となるクライアントPCにcloudflaredをインストールして、トンネルで設定したドメインに対してSSHログイン
- ブラウザが自動起動するのでcloudflareの認証を実施して設定完了
コンテナランタイムのインストール
Kubernetes公式の手順を元に作業実施。とりあえずcontainerdを入れていく
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
systemd
cgroupドライバーにする
4. runcのcgroupドライバーをinitにsystemdを使っておりcgroupもv2のため、
config.toml
ファイルを編集
plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options
にSystemdCgroup = true
を追記する
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
...
SystemdCgroup = true
設定を変更したらcontainerdを再起動
sudo systemctl restart containerd
メモ:cgroupドライバーについて
- kubeletとコンテナランタイムではcgroupとインターフェースするためにcgroupドライバーを設定する必要がある
- kubeletとコンテナランタイムで使用するcgroupドライバーは同一にする必要がある
-
cgroupfs
またはsystemd
が選べて、kubeletのデフォルトはcgroupfs
になっている - 以下の場合はcgroupドライバーを
systemd
に変更する-
init
システムがsystemd
である場合はcgroupドライバーもsystemd
にすることが推奨-
systemd
はcgroupマネージャーが単一であることを想定しているため、別のcgroupマネージャーが存在しているとリソースを正しくリソースの管理ができず高負荷を招くため
-
- cgroup v2を使用している場合
-
kubeadm, kubelet, kubectlのインストール
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
systemd
に変更
kubeletのcgroupドライバーを/etc/default/kubelet
を編集
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
kubeletを再起動
systemctl daemon-reload
systemctl restart kubelet
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モード)で設定する
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
に変更
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
WorkerNodeをクラスターへ参加させる
Control Plane Nodeにてkubeadm init
した際に出力されたコマンドを各WorkerNodeにて実行
sudo kubeadm join 192.168.130.21:6443 --token <token> \
--discovery-token-ca-cert-hash <hash値>
Podネットワークアドオンをデプロイ
以下を参照しながらCalicoをインストールする
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 init
のpod-network-cidr
で指定した値と同じ値をCALICO_IPV4POOL_CIDR
として設定する
Manifestのapply
kubectl apply -f calico.yaml