LoginSignup
30
22

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-06-23

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

参考資料

30
22
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
30
22