ラズパイで、Kubernetesが動くという記事を見つけて、自分でも試して見ました。 HyperiotOSというDockerコンテナエンジンが、プレインストールされたラズパイのOSを使って、簡単にできるかと思ったのですが、結構、苦労したので、記録として残しておきたいと思います。 しかし、苦労に見合う大きな発見があり、最後の部分に書いておきました。
構成
- ラズパイ: Raspberry Pi 3 Model B V1.2 x4
- ラズパイのOS: HyperiotOS Version 1.7.1 https://blog.hypriot.com/, Docker-CE 17.10
- K8s: バージョン 1.8.14
- ポッドネットワーク: Flannel 0.9.1
Hyperiot OSのSDカードの作成
HyperiotOSのダウンロードページ で、hypriotos-rpi-v1.7.1.img.zip をクリックして、ダウンロードします。 それから、MacOSを利用したSDカード作成のガイドを参考にして、SDカードを作成します。
IPアドレスとホスト名の設定
作成したSDカードをセットして、モニターとキーボードを接続して、ラズパイを起動したら、/boot/user-dataを編集して、ホスト名を設定します。
ログインは、HyperiotOS ユーザーIDとパスワードは、FAQに書いてあります。 ログインできたら、'sudo -s' してルートユーザーで作業します。
#cloud-config
# vim: syntax=yaml
#
# The current version of cloud-init in the Hypriot rpi-64 is 0.7.9
# When dealing with cloud-init, it is SUPER important to know the version
# I have wasted many hours creating servers to find out the module I was trying to use wasn't in the cloud-init version I had
# Documentation: http://cloudinit.readthedocs.io/en/0.7.9/index.html
# Set your hostname here, the manage_etc_hosts will update the hosts file entries as well
hostname: master1 <--- ホスト名をセット
manage_etc_hosts: true
# You could modify this for your own user information
users:
以下省略
デフォルトでは、DHCPでIPアドレスを取得する設定なのですが、k8sクラスタを構成するために、エディタで/etc/network/interface.d/eth0を編集して、静的なIPアドレスを設定します。
allow-hotplug eth0
iface eth0 inet static
address 192.168.1.201
netmask 255.255.255.0
gateway 192.168.1.1
nameserver 192.168.1.1
以上の設定が完了したら、rebootコマンドで再起動します。
認証鍵の設定
sshでパスワード無しでログインできる様に、公開鍵を設定して、ログインできる様にします。
pirate でログインして、エディタでauthorized_keysに公開鍵を設定ます。 sshの鍵生成方法は、https://webkaru.net/linux/ssh-keygen-command/ を参考にすると良いと思います。
$ mkdir .ssh
$ vi authorized_keys
それから、ルートになって、sshd設定ファイルを編集します。 33行目がコメントになっているので、#を削除して、有効化します。
26 # Authentication:
27 LoginGraceTime 120
28 PermitRootLogin without-password
29 StrictModes yes
30
31 RSAAuthentication yes
32 PubkeyAuthentication yes
33 AuthorizedKeysFile %h/.ssh/authorized_keys
34
設定が有効になる様に、以下でsshdを再起動して、設定を有効化します。
sudo systemctl restart ssh.service
Kubernetesのインストール
Kuberentesのバイナリが登録されたリポジトリを追加して、aptパッケージ・マネージャーでインストールできる様にします。
apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
ARMプロセッサ用にビルドされたKubernetesは、どれでも利用できるという訳ではなさそうです。 筆者が試したところ、1.9.0 以降では、apiserverが安定に動作せず、利用できませんでした。原因を詳しく調べていませんが、apiserverが起動して、1分くらい経過したところで、コンテナが止まってしまいます。 そして、停止と起動を繰り返すといった症状がおきました。
- 1.10.5 apiserver NG
- 1.9.8 apiserver NG
- 1.9.0 apiserver NG
- 1.8.14 apiserver OK
- 1.8.0 apiserver OK
- 1.7.16 apiserver OK
とりあえず、動作する 1.8.14 を利用する事にして、セットアップを進めます。 次のコマンドで、バージョンを指定して、インストールします。
# apt-get update
# apt-get install kubelet=1.8.14-00 kubeadm=1.8.14-00 kubectl=1.8.14-00 kubernetes-cni=0.5.1-00
利用可能なバージョン確認するには、apt-cache madison kubeadm
を利用します。
もし、インストールしたバージョンが不安定だったり、問題があったら、次のコマンドで、アンインストールして、他のバージョンを試すことができます。
apt-get remvoe --purge kubelet=1.8.14-00 kubeadm=1.8.14-00 kubectl=1.8.14-00 kubernetes-cni=0.5.1-00
設定の修正とマスターの初期化
インストールが終わったら、次のファイルを編集します。
vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
修正部分は、KUBELET_DNS_ARGSのdnsのアドレスです。 Flannel のポッド・ネットワークは、固定アドレスなので、合わせて修正して、--cluster-dns=10.244.0.10 とします。
5 Environment="KUBELET_DNS_ARGS=--cluster-dns=10.244.0.10 --cluster-domain=cluster.local"
終わったら、kubeletを再起動して、設定を反映させます。
systemctl daemon-reload && systemctl restart kubelet
次のコマンドで、マスターノードの初期化を実行します。
kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.1.201 --service-cidr=10.244.0.0/16
もし、間違えたり、途中で、問題が発生して、最初からやり直したい場合は、以下の様にリセットできます。リセット後に、前述のkubeadm init
から、やり直し事ができます。
kubeadm reset
このリセットは、マスターを初期化で、動作を開始した Dockerコンテナを終了と削除、設定を消去するものです。 マスターだけでなく、ノードでも利用する事ができます。
kubectlの実行環境作成
マスターの設定が完了したら、次の表な表示が出ますから、ルートをexitして、一般ユーザーになって、下記のmkdir からの3行を実行して、kubectl が動作する様にします。
$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.1.201 --service-cidr=10.244.0.0/16
<途中省略>
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run (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
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
http://kubernetes.io/docs/admin/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join --token 9d3ca7.4b675998b35c75bc 192.168.1.201:6443 --discovery-token-ca-cert-hash sha256:c2530cd4440c04a9b463d046ef27f6a6edf30b304aad8b196cee90a12c32d47e
設定が完了したら、kubectl get node
を実行して、以下の様に表示されたら、成功です。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
master1 NotReady master 2m v1.8.14
上記の様に、設定直後は、NotReadyの状態ですが、ポッド・ネットワークを設定することで、Readyの状態へ変わります。
ポッド・ネットワークの作成
最後に、ノードを跨って構成するポッド・ネットワークを設定します。 Flannelは、デーモン・セットとして、稼働するので、YAMLを使って設定します。
curl -O https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
ダウンロードしたYAMLファイルを編集します。変更箇所は、以下の3箇所で、amd64 を armに修正します。
$ diff kube-flannel.yml kube-flannel-arm.yml
88c88
< beta.kubernetes.io/arch: amd64
---
> beta.kubernetes.io/arch: arm
96c96
< image: quay.io/coreos/flannel:v0.9.1-amd64
---
> image: quay.io/coreos/flannel:v0.9.1-arm
110c110
< image: quay.io/coreos/flannel:v0.9.1-amd64
---
> image: quay.io/coreos/flannel:v0.9.1-arm
ファイルを修正したら、次の様に適用します。
kubectl apply -f kube-flannel-arm.yml
コマンドを実行して、1〜2分で、ネットワークが立ち上がり、マスターが Ready状態になります。
$ kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
etcd-master1 1/1 Running 0 2m
kube-apiserver-master1 1/1 Running 1 2m
kube-controller-manager-master1 1/1 Running 0 45s
kube-dns-66ffd5c588-4r78m 2/3 Running 0 1m
kube-flannel-ds-52827 1/1 Running 0 25s
kube-proxy-rvpn6 1/1 Running 0 1m
kube-scheduler-master1 1/1 Running 0 2m
HypriotOS/armv7: pirate@master1 in ~
$ kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready master 3m v1.8.14
これで、マスタの設定が完了しました。
ノードの追加
コンテナの実行環境であるノードは、マスターと同じ様に、下記の作業を実施した後に、マスターの初期化が完了した時に表示される kubeadm join --token ...
を実行して、クラスタに追加します。
- /boot/user-data を編集して、ホスト名を設定 node1,node2...
- /etc/network/interface.d/eth0 を変数して、静的IPアドレスを付与
- ssh鍵の設定
- apt-get update && apt-get install kubelet=1.8.14-00 kubeadm=1.8.14-00 kubectl=1.8.14-00 kubernetes-cni=0.5.1-00 でインストール
- vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf の--cluster-dns=10.244.0.10 の変更
- systemctl daemon-reload && systemctl restart kubelet
上記の設定が終わったら、kubeadm init ...
の完了時の表示をコピペして、各ノードで実行します。
kubeadm join --token 9d3ca7.4b675998b35c75bc 192.168.1.201:6443 --discovery-token-ca-cert-hash sha256:c2530cd4440c04a9b463d046ef27f6a6edf30b304aad8b196cee90a12c32d47e
これが完了すると、マスターで確認できる様になります。デーモンセットは、自動的に展開されるので、追加したノードは順次 Ready状態になります。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready master 7m v1.8.14
node1 Ready <none> 49s v1.8.14
node2 Ready <none> 39s v1.8.14
node3 NotReady <none> 17s v1.8.14
kuebctl の .kube/configへの追加
マスタの.kube/configから、clustersの-cluster, contextsの-context, usersの-name の3箇所のデータをピックアップして、管理者クライアントの.kube/configへ追加する事で、kubectl config get-contexts
でリストを表示して、kubectl config set-context rasp-k8s
で表示できる様になります。
clusters:
- cluster:
certificate-authority-data: XXXX
server: https://192.168.1.201:6443
name: rasp-k8s
<省略>
contexts:
- context:
cluster: rasp-k8s
namespace: default
user: rasp-admin
name: rasp-k8s
<省略>
users:
- name: rasp-admin
user:
client-certificate-data: XXXX
client-key-data: XXXX
デプロイなど
IAサーバーやクラウドで利用しているYAMLファイルを適用して見ます。 armプロセッサ用のコンテナでなければ、起動しないはずですが、指定をしなくても nginxのコンテナが起動しました。
imac:k8s_l2_pod maho$ cat pod-nginx.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.15
imac:k8s_l2_pod maho$ kubectl apply -f pod-nginx.yml
pod "nginx" created
imac:k8s_l2_pod maho$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 38s
imac:k8s_l2_pod maho$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 1m
確かに起動しています。
imac:~ maho$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 4m 10.244.3.2 node3
次に、対話型のシェルのポッドを起動して見ます。
imac:k8s_l2_pod maho$ kubectl run -it ubuntu --rm --restart=Never --image=ubuntu -- bash
もう一つターミナルを開いて、動作状態を確認します。 armプロセッサ上ですが、普通にコンテナが上がってきました。
imac:~ maho$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 14m 10.244.3.2 node3
ubuntu 1/1 Running 0 8s 10.244.2.11 node2
ubuntu対話型シェルから、nginxサーバへアクセスして、動作を確認して見ます。下記の様に問題なく、利用できます。
root@ubuntu:/# apt-get update && apt-get install -y curl
<省略>
root@ubuntu:/# curl http://10.244.3.2/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<以下省略>
どっか間違えて、IAサーバーのパブリッククラウドへデプロイを掛けたのでしょうか?心配になってきたので、CPUの情報を確かめてみます。 しかし、確かに、ARMです。 INTEL CPUとバイナリ互換ではないので、ARM用に作られたコンテナがあるという事ですね。
root@ubuntu:/proc# cat cpuinfo
processor : 0
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 1
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 2
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 3
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
Hardware : BCM2709
Revision : a32082
Serial : 0000000006a75704
参照先によると、DockerHubのオフィシャルのコンテナ・イメージは、AMD64以外のアーキテクチャのCPUへも移植され、利用できる様になっていました。
これは、使い慣れないCPUアーキテクチャのマシンでも、DockerコンテナとKuberentesを利用する事で、敷居が下がり、利用しやすくなったと言えると思います。 メインフレームとかPOWER System でも、同じ様に簡単に利用できることを意味しているんですね。 コンテナには、ビックリしですね。
参考資料
- Kubernetes 1.8 のドキュメント https://v1-8.docs.kubernetes.io/docs/setup/independent/install-kubeadm/
- Setup Kubernetes on a Raspberry Pi Cluster easily the official way! https://blog.hypriot.com/post/setup-kubernetes-raspberry-pi-cluster/
- Installing kubeadm https://v1-8.docs.kubernetes.io/docs/setup/independent/install-kubeadm/
- https://github.com/coreos/flannel
- https://github.com/docker-library/official-images#architectures-other-than-amd64