Edited at

ラズパイでKubernetesを動かして見たら、驚いた!

More than 1 year has passed since last update.

ラズパイで、Kubernetesが動くという記事を見つけて、自分でも試して見ました。 HyperiotOSというDockerコンテナエンジンが、プレインストールされたラズパイのOSを使って、簡単にできるかと思ったのですが、結構、苦労したので、記録として残しておきたいと思います。 しかし、苦労に見合う大きな発見があり、最後の部分に書いておきました。

IMG_4629.jpg


構成


  • ラズパイ: 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' してルートユーザーで作業します。


/boot/user-data

#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アドレスを設定します。


/etc/network/interface.d/eth0

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行目がコメントになっているので、#を削除して、有効化します。


/etc/ssh/sshd-config

     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 でも、同じ様に簡単に利用できることを意味しているんですね。 コンテナには、ビックリしですね。


参考資料