本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

创建一个运行 Kubernetes 的树莓派集群,安装(第 2 部分)

在比利时 Devoxx 和摩洛哥 Devoxx 大会上,Ray Tsang 和我(Arjen Wassink)展示了我们在 Quintor 搭建的运行 HypriotOS、Docker 和 Kubernetes 的树莓派集群。尽管我们的演讲收到了很多赞扬,但最常见的问题是如何自己构建一个 Pi 集群!我们将分两部分完成这个任务。第一部分介绍了集群的采购清单,第二部分将向您展示如何让 Kubernetes 运行起来。

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

第一步是确保每个 Pi 都运行 Hypriot,如果还没有,请查阅他们的入门指南。另外,将集群交换机连接到网络,以便提供互联网访问,并通过 DHCP 为每个 Pi 分配 IP 地址。由于我们将运行多个 Pi,为每个 Pi 分配一个唯一的主机名会很实用。为了方便起见,我将我的 Pi 重命名为 rpi-master、rpi-node-1、rpi-node-2 等。请注意,在 Hypriot 上,主机名是通过编辑 /boot/occidentalis.txt 文件设置的,而不是 /etc/hostname。您也可以使用 Hypriot 刷机工具设置主机名。

在树莓派上运行软件最重要的方面是 ARM 发行版的可用性。感谢 Brendan Burns,Google Cloud Registry 中提供了适用于 ARM 的 Kubernetes 组件。这太棒了。第二个难点是如何安装 Kubernetes。有两种方法:直接在系统上安装或在 Docker 容器中安装。尽管容器支持仍处于实验阶段,但我选择使用它,因为它能让 Kubernetes 的安装变得更简单。Kubernetes 要求在节点上运行多个进程(etcd、flannel、kubectl 等),这些进程应按特定顺序启动。为了简化这一点,我们提供了 systemd 服务来以正确的方式启动必要的进程。systemd 服务还确保在节点(重新)启动时 Kubernetes 能够启动。为了使安装变得非常简单,我为主节点和工作节点创建了一个简单的安装脚本。所有内容都可以在 GitHub 上找到。那么,现在就开始吧!

安装 Kubernetes 主节点

首先我们将在主节点上安装 Kubernetes,稍后将工作节点添加到集群中。这基本上归结为获取 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 守护进程,用于运行 etcd 和 flannel,因为 flannel 需要在标准 Docker 守护进程 (docker.service) 之前运行,以便进行网络配置。
  • k8s-etcd.service - 这是用于存储 flannel 和 kubelet 数据的 etcd 服务。
  • k8s-flannel.service - 这是 flannel 进程,在集群中的所有节点上提供一个叠加网络。
  • docker.service - 这是标准的 Docker 守护进程,但以 flannel 作为网络桥接。它将运行所有 Docker 容器。
  • k8s-master.service - 这是 Kubernetes 主服务,提供集群功能。

此安装过程的基本细节也在 Kubernetes 的入门指南中有所记载。请查阅以更深入地了解如何设置多节点 Kubernetes 集群。

让我们检查一切是否正常运行。必须运行两个 docker 守护进程。

$ 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 和服务

如果一切顺利,我们就可以使用 kubectl 访问 Kubernetes 集群的主节点了。ARM 版的 Kubectl 可以从 googleapis 存储下载。`kubectl get nodes` 显示已注册的集群节点及其状态。主节点被命名为 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 正在运行,但应用程序无法通用访问。这可以通过创建服务来实现。集群 IP 地址是服务在集群内部可用的 IP 地址。使用主节点的 IP 地址作为外部 IP,服务就可以在集群外部访问(例如,在我的情况下为 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 工作节点

下一步是在每个工作节点上安装 Kubernetes 并将其添加到集群中。这基本上也归结为获取 git 仓库内容并执行安装脚本。尽管在此安装中,需要预先复制 k8s.conf 文件并进行编辑,使其包含主节点的 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 地址更改为与主节点匹配

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

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

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

$ 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 树莓派集群现在已经运行起来了,您可以开始使用 Kubernetes 并进行学习。查阅 Kubernetes 用户指南以了解您可以做的所有事情。别忘了偶尔拔掉一些插头,就像 Ray 和我那样 :-)