Raspberry Pi 4 で簡単にx86対応Kubernetesクラスタを作ろう
はじめに
サイバーエージェントの7days インフラ向け 開発型インターン ONLINEに参加しました。
色々と新しい学びがありましたが躓いたことなどもあったので、自分なりに簡単にクラスタを作れる手順をまとめました。
構築手順
OSセットアップ
今回利用したOSはubuntu20.04です。sshが接続できるような状態にします。
以下の作業をすべての端末で行ってください。
アップデート
以下のコマンドを実行しシステムを更新します。
sudo apt update
sudo apt upgrade -y
E: Unable to lock the administration directory /var/lib/dpkg/lock?
上記のようなメッセージが出る場合は自動更新が動いているのでしばらく放置しましょう。
ホストネームの設定
同じ端末が複数あるとどの端末を操作しているかわからなくなるので、名前をつけましょう。
とりあえず各端末を以下のようにします。
- rpi4-node1
- rpi4-node2
- rpi4-node3
sudo hostnamectl set-hostname rpi4-node1
上記コマンド実行後に再度ログインすればホストネームは変更されています。
IPアドレスの固定
Ubuntu 20.04 LTSで固定IPアドレスの設定のようにすればアドレスを固定にできます。
本例では以下のようになっています。
- rpi4-node1 192.168.1.21
- rpi4-node2 192.168.1.22
- rpi4-node3 192.168.1.23
- デフォルトゲートウェイ 192.168.1.1
rpi4-node1であれば以下のようなファイルを「/etc/netplan/99_config.yaml」に作成します。
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: false
dhcp6: false
addresses: [192.168.1.21/24]
gateway4: 192.168.1.1
nameservers:
addresses: [192.168.1.1, 8.8.8.8, 8.8.4.4]
その後以下のコマンドで設定を適応します。
この際sshが切れる場合があるので、変更後のIPアドレスに再接続してください。
sudo netplan apply
魔法の設定
以下のコマンドを実行すると、memoryが0となっています。これを1にする必要があります。
ubuntu@rpi4-node1:~$ cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 10 1 1
cpu 3 1 1
cpuacct 3 1 1
blkio 4 1 1
memory 0 48 0
devices 2 40 1
freezer 6 2 1
net_cls 5 1 1
perf_event 8 1 1
net_prio 5 1 1
pids 9 45 1
rdma 7 1 1
「/boot/firmware/cmdline.txt」を以下のように編集してください。
ビフォー
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc
アフター
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_enable=memory
x86エミュレータの設定
以下のコマンドを貼り付け実行してください。
wget https://raw.githubusercontent.com/penM000/qemu-binfmt-setup/main/qemu-binfmt-setup.sh
chmod +x ./qemu-binfmt-setup.sh
./qemu-binfmt-setup.sh
rm ./qemu-binfmt-setup.sh
上記ではqemu 4.2が入りますが、割とコアダンプが多発するので以下のように無理やり新しいバージョンを入れることを推奨します。
qemu 5.0
wget http://ports.ubuntu.com/pool/universe/q/qemu/qemu-user-static_5.0-5ubuntu9_arm64.deb
sudo dpkg -i qemu-user-static_5.0-5ubuntu9_arm64.deb
rm qemu-user-static_5.0-5ubuntu9_arm64.deb
qemu 5.1
wget http://ftp.jp.debian.org/debian/pool/main/q/qemu/qemu-user-static_5.1+dfsg-4+b1_arm64.deb
sudo dpkg -i qemu-user-static_5.1+dfsg-4+b1_arm64.deb
rm qemu-user-static_5.1+dfsg-4+b1_arm64.deb
再起動
このタイミングで一旦再起動します。
sudo reboot
microk8sのインストール
以下のコマンドでインストールします。
sudo snap install microk8s --classic --channel=1.19/stable
kubectlの別名を設定します。
sudo snap alias microk8s.kubectl kubectl
sudo 無しで利用できるようにします。次回ログインで適応されます。
sudo usermod -a -G microk8s ubuntu
sudo chown -f -R ubuntu ~/.kube
正しくインストールできれば以下のような表示になります。
sudo microk8s.status
microk8s is running
high-availability: no
datastore master nodes: 127.0.0.1:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # Configure high availability on the current node
disabled:
dashboard # The Kubernetes dashboard
dns # CoreDNS
helm # Helm 2 - the package manager for Kubernetes
helm3 # Helm 3 - Kubernetes package manager
host-access # Allow Pods connecting to Host services smoothly
ingress # Ingress controller for external access
metallb # Loadbalancer for your Kubernetes cluster
metrics-server # K8s Metrics Server for API access to service metrics
rbac # Role-Based Access Control for authorisation
registry # Private image registry exposed on localhost:32000
storage # Storage class; allocates storage from host directory
以下のような表示になる場合は「魔法の設定」を行っていない可能性があります。
また、起動直後は処理中の場合があります。
sudo microk8s.status
microk8s is not running. Use microk8s inspect for a deeper inspection.
クラスタの作成
下記作業は、すべてのノードでmicrok8sが利用可能なものとして進行します。
rpi4-node1で以下のコマンドを実行します。すると以下のような情報が出るのでこれをrpi4-node2で実行します。
joinにはsudoが必要です。
ubuntu@rpi4-node1:~$ microk8s add-node
From the node you wish to join to this cluster, run the following:
microk8s join 192.168.1.21:25000/1d40b640b06cf019f1f4b47bf2a8e42e
ubuntu@rpi4-node1:~$ sudo microk8s join 192.168.1.21:25000/1d40b640b06cf019f1f4b47bf2a8e42e
Contacting cluster at 192.168.1.21
Waiting for this node to finish joining the cluster. ..
戻ってきたら再度rpi4-node1でコマンドを実行し、同様にして、rpi4-node3で実行します。
ubuntu@rpi4-node1:~$ microk8s add-node
From the node you wish to join to this cluster, run the following:
microk8s join 192.168.1.21:25000/373ed6c9036180b5906348a8657e78c5
ubuntu@rpi4-node3:~$ sudo microk8s join 192.168.1.21:25000/373ed6c9036180b5906348a8657e78c5
Contacting cluster at 192.168.1.21
Waiting for this node to finish joining the cluster. ..
すべて参加できると以下のように3台がマスターノードで認識されます。
ubuntu@rpi4-node1:~$ microk8s.status
microk8s is running
high-availability: yes
datastore master nodes: 192.168.1.21:19001 192.168.1.23:19001 192.168.1.22:19001
datastore standby nodes: none
もし以下のように参加できない場合は参加できないノードで「sudo microk8s.leave」などをでリセットしてから再度参加しましょう。
ubuntu@rpi4-node1:~$ microk8s.status
microk8s is running
high-availability: no
datastore master nodes: 192.168.1.21:19001 192.168.1.23:19001
datastore standby nodes: none
Kubernetes設定
上記でKubernetesクラスターが完成しました。
ここからは実際に使えるようにKubernetesの設定を行います。
helm有効化
ubuntu@rpi4-node1:~$ sudo microk8s.enable helm3
sudo snap alias microk8s.helm3 helm
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
DNS有効化
以下のコマンドでポッドがDNSを利用できるようになります
ubuntu@rpi4-node1:~$ sudo microk8s.enable dns
ubuntu@rpi4-node1:~$ kubectl run test --image busybox:1.28 --restart Never -it --rm -- nslookup google.com
Server: 10.152.183.10
Address 1: 10.152.183.10 kube-dns.kube-system.svc.cluster.local
Name: google.com
Address 1: 2404:6800:4004:808::200e nrt20s08-in-x0e.1e100.net
Address 2: 172.217.175.238 nrt12s29-in-f14.1e100.net
pod "test" deleted
MetalLB有効化
以下のコマンドでMetalLBが利用できます
アドレス範囲は192.168.1.30~192.168.1.40とします。
ubuntu@rpi4-node1:~$ sudo microk8s.enable metallb
Enabling MetalLB
Enter each IP address range delimited by comma (e.g. '10.64.140.43-10.64.140.49,192.168.0.105-192.168.0.111'): 192.168.1.30-192.168.1.40
ダッシュボード有効化
以下のコマンドでダッシュボードが利用できます。
ubuntu@rpi4-node1:~$ sudo microk8s.enable dashboard
ダッシュボードを8443ポートで見れるようにします。
ubuntu@rpi4-node1:~$ kubectl expose deployment kubernetes-dashboard --name=kubernetes-dashboard-lb --port 8443 --target-port=8443 --type LoadBalancer -n kube-system
以下のコマンドでhttps://192.168.1.30:8443にアクセスすれば良いことがわかります。
ubuntu@rpi4-node1:~$ kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.152.183.10 <none> 53/UDP,53/TCP,9153/TCP 9m24s
metrics-server ClusterIP 10.152.183.225 <none> 443/TCP 2m15s
kubernetes-dashboard ClusterIP 10.152.183.105 <none> 443/TCP 2m6s
dashboard-metrics-scraper ClusterIP 10.152.183.178 <none> 8000/TCP 2m5s
kubernetes-dashboard-lb LoadBalancer 10.152.183.118 192.168.1.30 8443:31650/TCP 27s
アクセスするとトークンを求められます。以下のコマンドでトークンを取得する事ができます。
ubuntu@rpi4-node1:~$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep default-token | a
wk '{print $1}')
Name: default-token-gqfr7
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 650450a4-16f4-42e7-9092-11e77d6e91dd
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1103 bytes
namespace: 11 bytes
token: eyJhbGciOiJ
Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
以下のようにすべて起動するまで待ちましょう。
ubuntu@rpi4-node1:~$ kubectl get pods -n argocd
NAME READY STATUS RESTARTS AGE
argocd-redis-cccbb8f7-lz59z 1/1 Running 0 65s
argocd-application-controller-5bb5bf665c-qnk8b 1/1 Running 0 65s
argocd-repo-server-8fbdb95bf-zm2g2 1/1 Running 0 65s
argocd-dex-server-5559ccbb9f-rgcw2 1/1 Running 1 65s
argocd-server-5bc896856-56sjp 1/1 Running 0 64s
以下のようにpodが受付状態になっていますが、外からアクセスできないのでこれをできるようにします。
ubuntu@rpi4-node1:~$ kubectl get svc -n argocd
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-dex-server ClusterIP 10.152.183.238 <none> 5556/TCP,5557/TCP,5558/TCP 3m16s
argocd-metrics ClusterIP 10.152.183.169 <none> 8082/TCP 3m16s
argocd-redis ClusterIP 10.152.183.107 <none> 6379/TCP 3m16s
argocd-repo-server ClusterIP 10.152.183.193 <none> 8081/TCP,8084/TCP 3m16s
argocd-server-metrics ClusterIP 10.152.183.83 <none> 8083/TCP 3m16s
argocd-server ClusterIP 10.152.183.114 <none> 80/TCP,443/TCP 3m16s
上記でロードバランサが使えるようになったので変更します。
ubuntu@rpi4-node1:~$ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
service/argocd-server patched
ubuntu@rpi4-node1:~$ kubectl get svc -n argocd
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-dex-server ClusterIP 10.152.183.238 <none> 5556/TCP,5557/TCP,5558/TCP 4m25s
argocd-metrics ClusterIP 10.152.183.169 <none> 8082/TCP 4m25s
argocd-redis ClusterIP 10.152.183.107 <none> 6379/TCP 4m25s
argocd-repo-server ClusterIP 10.152.183.193 <none> 8081/TCP,8084/TCP 4m25s
argocd-server-metrics ClusterIP 10.152.183.83 <none> 8083/TCP 4m25s
argocd-server LoadBalancer 10.152.183.114 192.168.1.31 80:31148/TCP,443:30112/TCP 4m25s
192.168.1.31にアクセスするとページが見れます。
ユーザー名はadminで、パスワードは以下のコマンドを実行することで得ることができます。

ubuntu@rpi4-node1:~$ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
argocd-server-5bc896856-56sjp

project: default
source:
repoURL: 'https://github.com/argoproj/argocd-example-apps.git'
path: guestbook
targetRevision: HEAD
destination:
server: 'https://kubernetes.default.svc'
namespace: default




コマンドも以下のようにすれば動きます。
wget https://github.com/argoproj/argo-cd/releases/download/v1.7.8/argocd-linux-amd64
chmod +x argocd-linux-amd64
./argocd-linux-amd64
argocd controls a Argo CD server
Usage:
argocd [flags]
argocd [command]
Available Commands:
account Manage account settings
app Manage applications
cert Manage repository certificates and SSH known hosts entries
cluster Manage cluster credentials
completion output shell completion code for the specified shell (bash or zsh)
context Switch between contexts
gpg Manage GPG keys used for signature verification
help Help about any command
login Log in to Argo CD
logout Log out from Argo CD
proj Manage projects
relogin Refresh an expired authenticate token
repo Manage repository connection parameters
repocreds Manage repository connection parameters
version Print version information
Flags:
--auth-token string Authentication token
--client-crt string Client certificate file
--client-crt-key string Client certificate key file
--config string Path to Argo CD config (default "/home/ubuntu/.argocd/config")
--grpc-web Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2.
--grpc-web-root-path string Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2. Set web root.
-H, --header strings Sets additional header to all requests made by Argo CD CLI. (Can be repeated multiple times to add multiple headers, also supports comma separated headers)
-h, --help help for argocd
--insecure Skip server certificate and domain verification
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--plaintext Disable TLS
--port-forward Connect to a random argocd-server port using port forwarding
--port-forward-namespace string Namespace name which should be used for port forwarding
--server string Argo CD server address
--server-crt string Server certificate file
Use "argocd [command] --help" for more information about a command.
kube-ops-view
kubectl create namespace kube-ops-view

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kube-ops-view
spec:
destination:
name: ''
namespace: kube-ops-view
server: 'https://kubernetes.default.svc'
source:
path: deploy
repoURL: 'https://codeberg.org/hjacobs/kube-ops-view.git'
targetRevision: HEAD
project: default





kubectl port-forward service/kube-ops-view 8080:80 --address 0.0.0.0 -n kube-ops-view

Weave Scope
kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '\n')"
kubectl port-forward -n weave "$(kubectl get -n weave pod --selector=weave-scope-component=app -o jsonpath='{.items..metadata.name}')" 4040 --address 0.0.0.0

prometheus
kubectl create namespace prometheus
helm install prometheus stable/prometheus-operator --namespace prometheus
kubectl port-forward service/prometheus-grafana 3000:80 --address 0.0.0.0 -n prometheus
ユーザ: admin
パスワード: prom-operator

まとめ
CPUがarmであるので、x86のイメージが動かないという問題から、イメージのビルドをしなければならないという問題がありましたが、これである程度はビルドしなくても動かせることがわかりました。でもやっぱり、コアダンプする時はするのでその場合はarm向けのビルドを行わなければいけなさそうです。
ディスカッション
コメント一覧
まだ、コメントがありません