0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RockyLinux 9 on PowerPC への Kubernetes 導入

Last updated at Posted at 2024-12-29

目的

K8s cluster構築には kubeadm を用いるが、以下要件がある。

  • 次のいずれかが動作しているマシンが必要です
    • Ubuntu 16.04+
    • Debian 9+
    • CentOS 7
    • Red Hat Enterprise Linux (RHEL) 7
    • Fedora 25+
    • HypriotOS v1.0.1+
    • Container Linux (tested with 1800.6.0)
  • 1台あたり2GB以上のメモリ(2GBの場合、アプリ用のスペースはほとんどありません)
  • 2コア以上のCPU
  • クラスター内のすべてのマシン間で通信可能なネットワーク(パブリックネットワークでもプライベートネットワークでも構いません)
  • ユニークなhostname、MACアドレス、とproduct_uuidが各ノードに必要です。詳細はここを参照してください。
  • マシン内の特定のポートが開いていること。詳細はここを参照してください。
  • Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。

CentOS 後継の RockyLinux は 8以上からがリリースされており、且つ PowerPC系(ここではPower9(ppc64le)を対象とする)のサポートは RockyLinux 9 以上が必要。

kubeadm標準ではサポート対象外だが、導入した際の手順・注意事項などをここに記す。

事前準備

RockyLinux 9特有のことは無い。

swap off

一時的には以下のようにする。

$ sudo swapoff -a

恒久的には /etc/fstab 上の swap マウント箇所をコメントアウトすればよい。

$ vi /etc/fstab

# xxxxx      none                    swap    defaults        0 0

swap off になっているかは以下で確認できる。

$ cat /proc/swaps

空っぽなら swap off 状態になっている。

port有効化

以下のポートを有効にしておく必要がある。
https://kubernetes.io/ja/docs/reference/networking/ports-and-protocols/

  • コントロールプレーン
プロトコル 通信の向き ポート範囲 目的 使用者
TCP Inbound 6443 Kubernetes API
TCP Inbound 2379-2380 etcd server
TCP Inbound 10250 Kubelet API
TCP Inbound 10259 kube-scheduler 自身
TCP Inbound 10257 kube-controller-manager 自身
  • ワーカーノード
プロトコル 通信の向き ポート範囲 目的 使用者
TCP Inbound 10250 Kubelet API 自身, コントロールプレーン
TCP Inbound 30000-32767 NodePort Services† 全て

control-plane にする場合は以下でポートを有効にする。

$ sudo firewall-cmd --zone=public --add-port 6443/tcp --add-port 2379-2380/tcp --add-port 10250/tcp  --add-port 10259/tcp  --add-port 10257/tcp  --add-port 30000-32767/tcp --permanent
$ sudo firewall-cmd --reload

Installing a container runtime

Enable IPv4 packet forwarding

# sysctl params required by setup, params persist across reboots
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

# Apply sysctl params without reboot
$ sudo sysctl --system

Disable IPv6

$ cat <<EOF | sudo tee /etc/sysctl.d/disable_ipv6.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
EOF

# Apply sysctl params without reboot
$ sudo sysctl --system

build and install cri-dockerd

docker を使うため、cri-dockerd をインストールする。

https://github.com/Mirantis/cri-dockerd/releases
に対応するパッケージがあるが、PowerPC用のものが提供されてないのでビルドするしかない。

$ git clone https://github.com/Mirantis/cri-dockerd
$ cd cri-dockerd
$ git checkout v0.3.13
$ make cri-dockerd

https://mirantis.github.io/cri-dockerd/usage/install-manually/
に従ってcri-dockerd サービスを設定する。

$ sudo install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
$ sudo install packaging/systemd/* /etc/systemd/system
$ sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now cri-docker.socket
$ sudo systemctl start cri-docker.socket

install kubeadm, kubelet, kubectl

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
に従って行う。

add kubernatis yum repository

# This overwrites any existing configuration in /etc/yum.repos.d/kubernetes.repo
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

install kubelet, kubeadm and kubectl

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

(Optional) Enable the kubelet service before running kubeadm:

sudo systemctl enable --now kubelet

Configuring a cgroup driver

https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/
によれば 'systemd' driver を推奨するとあり、かつ 1.22 以降では 'systemd' driverがデフォルトになっているとあるため、何もしない。

Creating a cluster

Network setup

各ノードに以下要件を満たしていること。

  • default route が設定されていること
  • ノード間で唯一のIPで通信しあえること

Initializing control-plane node

initialize control-plane single node

kubeadm で初期化実行。

  • control-plane-endpoint に DNSラウンドロビンアドレスを指定 (→ k8s-cluster とする)
  • cri-socket には cri-docker を指定
  • pod-network-cidr は 10.244.0.0/16 とする
    • service-cluster-ip-range のデフォルトが 10.96.0.0/12 のためoverlapしないようにする
    • network add-in に flannel を選択したが、そのデフォルト値が 10.244.0.0/16 となっており、変更しても何故か反映されない(多分、flannel のバグ)ため、デフォルト値に従う。
  • HA availability のために upload-certs を指定
$ sudo -E kubeadm init \
   --control-plane-endpoint k8s-cluster \
   --cri-socket unix:///var/run/cri-dockerd.sock \
   --pod-network-cidr 10.244.0.0/16 \
   --upload-certs

以下のようなメッセージが出ればクラスタ構築成功。

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/

失敗した場合、いくつかのコンテナが動作した状態になっているので、'kubeadm reset' を実行して一旦リセットする。
cri-socket の指定も忘れずに。

$ sudo -E kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock

add control-plane node

`kubeadm init --upload-certs' とした場合、以下のようなメッセージが出る。

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

  kubeadm join k8s-cluster:6443 --token XXXXXXXXXXXXXXXXXXX \
        --discovery-token-ca-cert-hash sha256:YYYYYYYYYYYYYYYYYYYYYY \
        --control-plane --certificate-key ZZZZZZZZZZZZZZZZZZ

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 k8s-cluster:6443 --token XXXXXXXXXXXXXXXXXXXX \
        --discovery-token-ca-cert-hash sha256:YYYYYYYYYYYYYYYYYYYYYY 

要するに、認証鍵が 2h間有効になっているため、その間に control-plane node を kubeadm join で追加せよ、といこと。

2h 過ぎた場合は、鍵を再生成するよう kubeadm init phase upload-certs --upload-certs を実行すればよい。

$ sudo kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
ZZZZZZZZZZZZZZZZZZZZ

ノード追加用トークンの再生成は以下。

$ kubeadm token create --print-join-command
kubeadm join k8s-cluster:6443 --token XXXXXXXXXXXXXXXX --discovery-token-ca-cert-hash sha256:YYYYYYYYYYYYYYYYYYYYYY 

追加ノードを control-plane にしたい場合は鍵再生成結果を --certificate-key に指定する。
cri-docker 指定も忘れずに。

$ sudo kubeadm join k8s-cluster:6443 \
  --token XXXXXXXXXXXXXXXXX --discovery-token-ca-cert-hash sha256:YYYYYYYYYYYYYYYYYYYY \
  --certificate-key  ZZZZZZZZZZZZZZZZZZZZZ \
  --cri-socket unix:///var/run/cri-dockerd.sock \
  --control-plane

add worker node to cluster

control-plane でないworkerノードを追加する場合は --control-plane の部分を抜けばよい。

$ sudo kubeadm join k8s-cluster:6443 \
  --token XXXXXXXXXXXXXXXXX --discovery-token-ca-cert-hash sha256:YYYYYYYYYYYYYYYYYYYY \
  --certificate-key  ZZZZZZZZZZZZZZZZZZZZZ \
  --cri-socket unix:///var/run/cri-dockerd.sock

delete node

ノードの削除方法は以下のように drain して関連daemonsets を消してから delete node する。

$ kubectl drain [node-name] --ignore-daemonsets --delete-emptydir-data
$ kubectl delete node [node-name]

docker credential情報を使用する

docker loginしたときの認証情報をk8sにも適用したいとき。

$ kubectl create secret generic regcred \
    --from-file=.dockerconfigjson=$HOME/.docker/config.json \
    --type=kubernetes.io/dockerconfigjson

匿名で使う場合は pull 回数に制限があるため、認証することで回避

Installing a Pod network add-on

k8s pod 内のネットワークをどのように管理するかのポリシー的なアルゴリズムを入れる必要がある。

から選べるとあるが、PowerPCの場合は Flannel 一択

Flannel

マニフェストを適用すればインストールできる。

$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

flannelのデフォルト設定では CIDR 割当範囲が 10.244.0.0/16 となっているが、変更するには yaml ファイルをダウンロードしてから編集して適用する

$ wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
$ vi kube-flannel.yml
...
  net-conf.json: |
    {
      "Network": "192.168.49.0/24",
      "Backend": {
        "Type": "vxlan"
      }
    }
...

## 編集したflannelを適用。
$ kubectl apply -f kube-flannel.yml

firewall configuration

flannel はバックエンドとして VXLAN を用いるが、特定の UDPポートをノード間の通信に使用する。
https://github.com/flannel-io/flannel/blob/master/Documentation/backends.md

Linuxの場合は 8472/UDP を用いるため、各ノードで許可しておく。

$ sudo firewall-cmd --permanent --zone=public --add-port=8472/udp
$ sudo firewall-cmd --reload

Calico

一般的には Calico の利用率が高いらしいが、残念ながら PowerPC 系には対応していない。

具体的には calico/node-driver-registrarというコンテナ が platform linux/ppc64le を提供しているにも関わらず "exec format error" で動かない。

なんじゃそりゃー (ノ`Д´)ノ彡┻━┻


(後日談)
どうやら PowerPC 未対応なのは release-3.27 以前の模様。
現在 3.29 までがリリースされているが、3.28 以降であれば exec format error にならないため動きそう。

が、今更に移行する気は無いので保留。

local-path dynamic volume provisioner

local path はdynamic provisioning に対応していないため、都度割り当てる必要がある。

Local volumes do not support dynamic provisioning in Kubernetes 1.30; however a StorageClass should still be created to delay volume binding until a Pod is actually scheduled to the appropriate node. This is specified by the WaitForFirstConsumer volume binding mode.

local path の dynamic provisioning の対応例に以下のものがある。
https://github.com/rancher/local-path-provisioner

だが、残念ながら PowerPC系には対応していない。
PowerPCを除外して適用するには以下のようにする。

$ wget https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.26/deploy/local-path-storage.yaml
$ vi local-path-storage.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: local-path-provisioner
  namespace: local-path-storage
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: "kubernetes.io/arch"
                  operator: In
                  values: ["amd64", "arm64"]

...

firewall backend の変更

istioやflannelではPod間の通信制御に iptables を使用するが、RHEL9 では iptables が deprecated になり nftables に移行した。

ipset and iptables-nft have been deprecated
The ipset and iptables-nft packages have been deprecated in RHEL. The iptables-nft package contains different tools such as iptables, ip6tables, ebtables and arptables. These tools will no longer receive new features and using them for new deployments is not recommended. As a replacement, prefer using the nft command-line tool provided by the nftables package. Existing setups should migrate to nft if possible.

この仕様変更により、RockyLinux 9 では pod間の通信ができなくなってしまっている。

本来なら K8s がiptablesでなく nftables に対応してほしいところだが、従来の iptables で制御することを許可すれば当座はしのげる。

バックエンドを iptables に変更

/etc/firewalld/firewalld.conf:

#FirewallBackend=nftables
FirewallBackend=iptables

以下で適用。

$ sudo systemctl restart firewalld
$ sudo firewall-cmd --reload

iptables rule順序変更

backend を iptables に変更しても、iptables チェインが以下のようになる場合がある。

$ sudo iptables -L FORWARD --line-number

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    KUBE-PROXY-FIREWALL  all  --  anywhere             anywhere             ctstate NEW /* kubernetes load balancer firewall */
2    KUBE-FORWARD  all  --  anywhere             anywhere             /* kubernetes forwarding rules */
3    KUBE-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes service portals */

...

17   FORWARD_direct  all  --  anywhere             anywhere            
18   FORWARD_ZONES  all  --  anywhere             anywhere            
19   DROP       all  --  anywhere             anywhere             ctstate INVALID
20   REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited
21   FLANNEL-FWD  all  --  anywhere             anywhere             /* flanneld forward */

21番目にある FLANNEL-FWD ルールが REJECT より後にあるため、当該ノードへの通信が遮断されてしまう。
このルールを上に上げる必要があるが、FORWARD_ZONES内の FWD_public ルール内でREJECTしているため、それより上にする必要がある。

$ sudo iptables -L FORWARD_ZONES --line-number
# Warning: iptables-legacy tables present, use iptables-legacy to see them
Chain FORWARD_ZONES (1 references)
num  target     prot opt source               destination         
1    FWD_docker  all  --  anywhere             anywhere            [goto] 
2    FWD_docker  all  --  anywhere             anywhere            [goto] 
3    FWD_public  all  --  anywhere             anywhere            [goto] 
4    FWD_public  all  --  anywhere             anywhere            [goto] 
5    FWD_public  all  --  anywhere             anywhere            [goto] 
6    FWD_public  all  --  anywhere             anywhere            [goto] 

$ sudo iptables -L FWD_public --line-number
# Warning: iptables-legacy tables present, use iptables-legacy to see them
Chain FWD_public (4 references)
num  target     prot opt source               destination         
1    FORWARD_POLICIES_pre  all  --  anywhere             anywhere            
2    FWD_public_pre  all  --  anywhere             anywhere            
3    FWD_public_log  all  --  anywhere             anywhere            
4    FWD_public_deny  all  --  anywhere             anywhere            
5    FWD_public_allow  all  --  anywhere             anywhere            
6    FWD_public_post  all  --  anywhere             anywhere            
7    FORWARD_POLICIES_post  all  --  anywhere             anywhere            
8    REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

上記例では FORWARD チェイン内 18番目に FORWARD_ZONES があるため、FLANNEL-FWD ルールをそれより上になるようにすればよい。

### FLANNEL-FWD ルール を No.18 に挿入
$ sudo iptables -I FORWARD 18 -j FLANNEL-FWD

当然ながら、iptables ルールが更新されるとルールも刷新されるため、この対処は "都度" 必要になる。

### iptables が更新される
$ sudo firewall-cmd --reload

そもそも RHEL9 では前述のとおり iptables による制御は deprecated のため暫定的であるべきである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?