本文发表时间已超过一年。较早的文章可能包含过时内容。请确认页面中的信息自发布以来没有发生变化。

创建运行 Kubernetes 的 Raspberry Pi 集群,安装篇 (第 2 部分)

在比利时 Devoxx 和摩洛哥 Devoxx 大会上,我和 Ray Tsang (Arjen Wassink) 展示了我们在 Quintor 构建的、运行 HypriotOS、Docker 和 Kubernetes 的 Raspberry Pi 集群。虽然我们的演讲收到了许多赞扬,但最常见的问题是关于如何自己构建一个 Pi 集群!我们将分两部分来做这件事。 第一部分介绍了集群的购物清单,第二部分将向您展示如何启动并运行 kubernetes...

现在您的 Raspberry Pi 集群已经全部搭建好了,是时候在上面运行一些软件了。正如之前的博客中所述,本教程基于适用于 ARM 处理器的 Hypriot Linux 发行版。主要原因是其内置的 Docker 支持。本教程中我使用的是 这个版本的 Hypriot,因此如果您在使用其他版本的 Hypriot 时遇到问题,请考虑使用我提供的版本。

第一步是确保每个 Pi 都运行着 Hypriot,如果还没有,请查看它们的 入门指南。同时将集群交换机连接到网络,以便可以访问 Internet,并且每个 Pi 可以通过 DHCP 获取 IP 地址。由于我们将运行多个 Pi,为每个 Pi 设置唯一的 hostname 会比较方便。我将我的 Pi 改名为 rpi-master, rpi-node-1, rpi-node-2 等,以方便我自己使用。请注意,在 Hypriot 上,hostname 是通过编辑 /boot/occidentalis.txt 文件设置的,而不是 /etc/hostname。您也可以使用 Hypriot flash 工具设置 hostname。

在 Pi 上运行软件最重要的一点是 ARM 发行版的可用性。感谢 Brendan BurnsGoogle Cloud Registry 中提供了适用于 ARM 的 Kubernetes 组件。这太好了。第二个障碍是如何安装 Kubernetes。有两种方法:直接安装在系统上,或者安装在 Docker 容器中。虽然容器支持处于实验阶段,但我选择使用它,因为它使安装 Kubernetes 变得更容易。Kubernetes 需要在节点上运行多个进程(etcd、flannel、kubectl 等),这些进程应按特定顺序启动。为了简化这一点,提供了 systemd 服务,以正确的方式启动必要的进程。systemd 服务还可以确保节点(重新)启动时 Kubernetes 会启动。为了使安装非常简单,我为 master 节点和 worker 节点创建了一个简单的安装脚本。所有脚本都可以在 GitHub 上找到。现在就开始吧!

安装 Kubernetes master 节点

首先,我们将在 master 节点上安装 Kubernetes,然后将 worker 节点添加到集群中。这基本上归结为获取 git 仓库内容并执行安装脚本。

$ curl -L -o k8s-on-rpi.zip https://github.com/awassink/k8s-on-rpi/archive/master.zip

$ apt-get update

$ apt-get install unzip

$ unzip k8s-on-rpi.zip

$ k8s-on-rpi-master/install-k8s-master.sh

安装脚本将安装五个服务:

  • docker-bootstrap.service - 这是一个单独的 Docker daemon,用于运行 etcd 和 flannel,因为 flannel 需要在标准 Docker daemon (docker.service) 之前运行,以便进行网络配置。
  • k8s-etcd.service - 这是用于存储 flannel 和 kubelet 数据的 etcd 服务。
  • k8s-flannel.service - 这是 flannel 进程,用于在集群所有节点上提供 Overlay 网络。
  • docker.service - 这是标准的 Docker daemon,但使用 flannel 作为网络桥。它将运行所有 Docker 容器。
  • k8s-master.service - 这是 kubernetes master 服务,提供集群功能。

此安装过程的基本细节也记录在 Kubernetes 的 入门指南 中。请查阅该指南以更深入地了解多节点 Kubernetes 集群的搭建方法。

让我们检查一下是否一切正常。必须有两个 Docker daemon 进程正在运行。

$ ps -ef|grep docker
root       302     1  0 04:37 ?        00:00:14 /usr/bin/docker daemon -H unix:///var/run/docker-bootstrap.sock -p /var/run/docker-bootstrap.pid --storage-driver=overlay --storage-opt dm.basesize=10G --iptables=false --ip-masq=false --bridge=none --graph=/var/lib/docker-bootstrap

root       722     1 11 04:38 ?        00:16:11 /usr/bin/docker -d -bip=10.0.97.1/24 -mtu=1472 -H fd:// --storage-driver=overlay -D

etcd 和 flannel 容器必须正在运行。

$ docker -H unix:///var/run/docker-bootstrap.sock ps

CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS               NAMES

4855cc1450ff        andrewpsuedonym/flanneld     "flanneld --etcd-endp"   2 hours ago         Up 2 hours                              k8s-flannel

ef410b986cb3        andrewpsuedonym/etcd:2.1.1   "/bin/etcd --addr=127"   2 hours ago         Up 2 hours                              k8s-etcd


The hyperkube kubelet, apiserver, scheduler, controller and proxy must be up.

$ docker ps

CONTAINER ID        IMAGE                                           COMMAND                  CREATED             STATUS              PORTS               NAMES

a17784253dd2        gcr.io/google\_containers/hyperkube-arm:v1.1.2   "/hyperkube controller"   2 hours ago         Up 2 hours                              k8s\_controller-manager.7042038a\_k8s-master-127.0.0.1\_default\_43160049df5e3b1c5ec7bcf23d4b97d0\_2174a7c3

a0fb6a169094        gcr.io/google\_containers/hyperkube-arm:v1.1.2   "/hyperkube scheduler"   2 hours ago         Up 2 hours                              k8s\_scheduler.d905fc61\_k8s-master-127.0.0.1\_default\_43160049df5e3b1c5ec7bcf23d4b97d0\_511945f8

d93a94a66d33        gcr.io/google\_containers/hyperkube-arm:v1.1.2   "/hyperkube apiserver"   2 hours ago         Up 2 hours                              k8s\_apiserver.f4ad1bfa\_k8s-master-127.0.0.1\_default\_43160049df5e3b1c5ec7bcf23d4b97d0\_b5b4936d

db034473b334        gcr.io/google\_containers/hyperkube-arm:v1.1.2   "/hyperkube kubelet -"   2 hours ago         Up 2 hours                              k8s-master

f017f405ff4b        gcr.io/google\_containers/hyperkube-arm:v1.1.2   "/hyperkube proxy --m"   2 hours ago         Up 2 hours                              k8s-master-proxy

在集群上部署第一个 pod 和 service

确认正常后,我们就可以使用 kubectl 访问 Kubernetes 集群的 master 节点了。适用于 ARM 的 kubectl 可以从 googleapis storage 下载。kubectl get nodes 命令显示哪些集群节点已注册及其状态。master 节点被命名为 127.0.0.1。

$ curl -fsSL -o /usr/bin/kubectl https://dl.k8s.io/release/v1.1.2/bin/linux/arm/kubectl

$ kubectl get nodes

NAME              LABELS                                   STATUS    AGE

127.0.0.1         kubernetes.io/hostname=127.0.0.1         Ready      1h


An easy way to test the cluster is by running a busybox docker image for ARM. kubectl run can be used to run the image as a container in a pod. kubectl get pods shows the pods that are registered with its status.

$ kubectl run busybox --image=hypriot/rpi-busybox-httpd

$ kubectl get pods -o wide

NAME                   READY     STATUS    RESTARTS   AGE       NODE

busybox-fry54          1/1       Running   1          1h        127.0.0.1

k8s-master-127.0.0.1   3/3       Running   6          1h        127.0.0.1

现在 pod 正在运行,但应用还无法从外部访问。通过创建 service 可以实现这一点。cluster IP-address 是 service 在集群内部可用的 IP 地址。使用 master 节点的 IP 地址作为 external IP,service 就可以在集群外部访问了(例如在我这里是 http://192.168.192.161)。

$ kubectl expose rc busybox --port=90 --target-port=80 --external-ip=\<ip-address-master-node\>

$ kubectl get svc

NAME         CLUSTER\_IP   EXTERNAL\_IP       PORT(S)   SELECTOR      AGE

busybox      10.0.0.87    192.168.192.161   90/TCP    run=busybox   1h

kubernetes   10.0.0.1     \<none\>            443/TCP   \<none\>        2h

$ curl http://10.0.0.87:90/
\<html\>

\<head\>\<title\>Pi armed with Docker by Hypriot\</title\>

  \<body style="width: 100%; background-color: black;"\>

    \<div id="main" style="margin: 100px auto 0 auto; width: 800px;"\>

      \<img src="pi\_armed\_with\_docker.jpg" alt="pi armed with docker" style="width: 800px"\>

    \</div\>

  \</body\>

\</html\>

安装 Kubernetes worker 节点

下一步是在每个 worker 节点上安装 Kubernetes 并将其添加到集群。这基本上也是获取 git 仓库内容并执行安装脚本。不过,在此安装过程中,需要预先复制 k8s.conf 文件并编辑,使其包含 master 节点的 IP 地址。

$ curl -L -o k8s-on-rpi.zip https://github.com/awassink/k8s-on-rpi/archive/master.zip

$ apt-get update

$ apt-get install unzip

$ unzip k8s-on-rpi.zip

$ mkdir /etc/kubernetes

$ cp k8s-on-rpi-master/rootfs/etc/kubernetes/k8s.conf /etc/kubernetes/k8s.conf

将 /etc/kubernetes/k8s.conf 中的 IP 地址更改为 master 节点的 IP 地址

$ k8s-on-rpi-master/install-k8s-worker.sh

安装脚本将安装四个服务。这些服务与 master 节点上的服务非常相似,但区别在于没有运行 etcd 服务,并且 kubelet 服务被配置为 worker 节点。

worker 节点上的所有服务都启动并运行后,我们就可以在 master 节点上检查该节点是否已添加到集群中。

$ kubectl get nodes

NAME              LABELS                                   STATUS    AGE

127.0.0.1         kubernetes.io/hostname=127.0.0.1         Ready     2h

192.168.192.160   kubernetes.io/hostname=192.168.192.160   Ready     1h

$ kubectl scale --replicas=2 rc/busybox

$ kubectl get pods -o wide

NAME                   READY     STATUS    RESTARTS   AGE       NODE

busybox-fry54          1/1       Running   1          1h        127.0.0.1

busybox-j2slu          1/1       Running   0          1h        192.168.192.160

k8s-master-127.0.0.1   3/3       Running   6          2h        127.0.0.1

尽情享受您的 Kubernetes 集群吧!

恭喜!您的 Kubernetes Raspberry Pi 集群现在已经运行起来了,您可以开始体验 Kubernetes 并学习它。查阅 Kubernetes 用户指南,了解您可以做什么。也不要忘记偶尔像 Ray 和我一样拔掉一些电源线 :-)