乐趣区

6000个边缘Kubernetes节点驱动城市80万次智能停车,如何成为可能?

城市的街道因为汽车数量的增长越来越繁忙,对于驾车一族而言,在热门区域寻找停车场更是无比头痛的事情。然而与此同时,其实也许很多办公楼、住宅楼、酒店和公共车库中仍有许多付费停车的资源未被充分利用。
ParkBee 就是这样一家为城市提供智能停车解决方案的公司。ParkBee 平台上显示着每位车主定位附近的可使用的停车场,停车价格、停车位的空余情况等都是实时更新。ParkBee“打开”了城市中的所有停车场,解决了停车难题,既节约车主时间,又帮助停车场最大限度创收。
ParkBee 近期开始尝试在边缘位置进行容器部署。因为 ParkBee 的整体业务的一个重要部分就是大量的停车场,与 ParkBee 合作的停车场有 6000 多家,截至目前我们已服务于 80 万次停车服务。我们必须确保每一个停车场的容器都能按预期工作,因此部署包含业务逻辑的应用程序至关重要。
ParkBee 目前使用 Kops 部署 Kubernetes,公有云选择的是 AWS。虽然这种方法适用于我们的基于云的服务,但对于我们的边缘部署而言,事情却并不是那么简单。我们的理想目标是:在 ParkBee 合作的每一个停车场上都有一个 Kubernetes 集群,集群中包含停车点位置的边缘 Kubernetes 节点以及 AWS 中的 Kubernetes 主节点。
半个月前,Rancher Labs 发布了 K3s——一个被认为是史上最轻量的 Kubernetes 发行版。K3s 的设计初衷就是为了能让像树莓派一样的低资源计算平台更容易安装和维护 Kubernetes。
本质上讲,K3s 有望成为一个轻量级的、易于使用、只使用一个二进制文件的 Kubernetes provisioner。K3s 的发布公告里写到它的主要功能包括:

生产级 Kubernetes:K3s 是一个符合标准的、已获 CNCF 官方认证的 Kubernetes 发行版。
一个没有主机依赖的二进制文件:在任何设备上安装 Kubernetes 所需的一切都包含在这一个 40MB 的二进制文件当中,不需要像 KuberSpray、KubeADM 或者 RKE 这样的外部安装程序。只需要一个命令,用户就可以配置或者升级单节点 K3s 集群。
一条命令,向集群添加节点:若想向集群添加其他节点,管理员只需在新节点上运行一条命令,指向原始服务器,通过安全 token 传递即可。
自动生成证书:集群启动时,在 Kubernetes 主服务器和节点之间建立 TLS 所需的所有证书都会被自动创建,还会自动创建服务账号的加密密钥。

准备工作
在这篇文章中,我将使用 K3s 的第一个版本 v0.1.0。如果你想要按照我的文章来尝试一样的操作,你需要准备:

Raspberry Pi 3 B+ 型号,带有闪存了 Raspbian Stretch Lite 的 microSD 卡。
本地网络:为了方便起见,我将在家里使用自己的局域网。
在你的笔记本电脑本地安装的 Vagrant:也可以使用 Docker for Mac,不过本质上来说,K3s 二进制文件还是为了 Linux、arm64 和 armhf 架构而构建的。

Vagrant
如果您正在使用 Vagrant,则可以在 test 目录中使用以下内容创建一个 Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANT_API = 2

Vagrant.configure(VAGRANT_API) do |config|
config.vm.box = “bento/ubuntu-18.04”
config.vm.box_check_update = false
config.vm.network “forwarded_port”, guest: 6443, host: 6443, host_ip: “0.0.0.0”

config.vm.provider “virtualbox” do |vb|
vb.cpus = 1
vb.gui = true
vb.memory = “2048”
vb.name = “k3s-master”
end

config.vm.provision :docker

config.vm.provision “shell”, inline: <<-SHELL
sudo modprobe vxlan
curl -sfL https://get.k3s.io | sh –
hostnamectl set-hostname k3s-master
SHELL
end

至此,你将安装好了 Docker 以及 K3s 二进制文件。安装脚本也可以方便地将 kubectl 二进制文件符号链接到 K3s,因为它是内置的。
防火墙
小提示:Raspberry Pi 需要连接到 LAN 中的本地计算机。在 macOS 中,确保转到设置 => 安全和隐私 => 防火墙,然后单击“关闭”按钮。

对于 Windows,您可以参考 Lifewire 关于在 Windows 中关闭防火墙的文章:
https://www.lifewire.com/how-…
运行 K3s 主节点
我们将先使用 Vagrant 机器作为 K3s 主节点; 一旦它开始正常工作,我们将尝试将 Raspberry Pi 连接到本地 LAN 上的 K3s 主节点。
与任何 Vagrant 机器一样,只需运行 vagrant up,一切就开始启动了。Vagrant 将运行 K3s 自动安装脚本,打开本地计算机上的 6443 端口,以便 K3s 节点加入,并创建稍后所需的连接令牌。
首先,验证主节点安装是否成功:
root@k3s-master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-master Ready <none> 4m51s v1.13.3-k3s.6
默认情况下,K3s 安装脚本不会将 k3s-master 标记为主节点;但因为我们已经预先安装好了 kubectl 二进制文件,我们现在可以解决这个问题:
root@k3s-master:~# kubectl label node k3s-master kubernetes.io/role=master
node/k3s-master labeled
root@k3s-master:~# kubectl label node k3s-master node-role.kubernetes.io/master=””
node/k3s-master labeled
K3s 安装也不会污染 NoSchedule 的主节点。在此次测试中,我们希望确保 Raspberry Pi 能够接收测试部署,因此使用以下方法污染主节点:
root@k3s-master:~# kubectl taint nodes k3s-master node-role.kubernetes.io/master=effect:NoSchedule
node/k3s-master tainted
接下来,我们需要 token,来将 K3s 节点连接到新主节点。该 k3s server 命令应该已经为您创建了这个 /var/lib/rancher/k3s/server/node-token。运行以下命令:
root@k3s-master:~# cat /var/lib/rancher/k3s/server/node-token
<some-long-node-token>
在 Raspberry Pi 上运行 K3s 节点
首先,我们需要为树莓派准备一些初始步骤。首先,使用以下命令来禁用 swap:
dphys-swapfile swapoff && \
dphys-swapfile uninstall && \
update-rc.d dphys-swapfile remove
然后,将以下文本附加到 /boot/cmdline.txt 的第一行:
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory
然后,reboot 树莓派。返回时,重新登录,然后运行以下命令下载 k3s 二进制文件。
curl -fSL “https://github.com/rancher/k3s/releases/download/v0.1.0/k3s-armhf” \
-o /usr/local/bin/k3s && \
chmod +x /usr/local/bin/k3s
因为 K3s 已经不使用 containerd 了,因此我们无需安装 Docker,但最好还是验证一下是不是所有 pod 都在正常运行。通过运行以下命令可以快速安装 Docker:
curl -fsSL https://get.docker.com | sh – && \
usermod -aG docker pi
获取从主服务器创建的 token,并将其导出为环境变量:
export NODE_TOKEN=”<some-long-node-token>”
最后,运行 k3s agent 命令以启动代理程序,然后加入主节点。在我的这次使用中,192.168.0.10 是我网络中本地笔记本电脑上运行的 Vagrant 机器的地址。记得务必使用适当的地址替换该值。
k3s agent \
–docker \
–server https://192.168.0.10:6443 \
–token ${NODE_TOKEN} \
> /root/logs.txt 2>&1 &
与 K3s 主节点类似,这次安装不会使用正确的节点标签标记 Raspberry Pi。在 k3s-master 上,在 Raspberry Pi 加入集群后运行以下命令:
root@k3s-master:~# kubectl label node raspberrypi kubernetes.io/role=node
node/raspberrypi labeled
root@k3s-master:~# kubectl label node raspberrypi node-role.kubernetes.io/node=””
node/raspberrypi labeled
如果 Raspberry Pi 成功加入,则在主服务器上运行该命令时应该会看到类似以下内容:
root@k3s-master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
raspberrypi Ready node 2m v1.13.3-k3s.6
k3s-master Ready master 20m v1.13.3-k3s.6
部署一个测试 NGINX 容器
为了确保 K3s 集群能真正正常工作,我们可以部署一个测试 NGINX pod 和 NodePort 服务,以确保 Raspberry Pi 创建了 pod,并成功打开了端口。
在 K3s 主 Vagrant 机器上,使用以下内容在 /root/nginx-test.yaml 上创建一个文件:

apiVersion: v1
kind: Service
metadata:
name: nginx-unprivileged-test
namespace: default
spec:
type: NodePort
selector:
app: nginx-unprivileged-test
ports:
– protocol: TCP
nodePort: 30123
port: 8080
name: http
targetPort: 8080

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-unprivileged-test
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: nginx-unprivileged-test
spec:
containers:
– image: nginxinc/nginx-unprivileged
name: nginx-unprivileged-test
ports:
– containerPort: 8080
name: http
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 3
然后最终将其部署到集群:
root@k3s-master:~# kubectl apply -f /root/nginx-test.yaml
service/nginx-unprivileged-test created
deployment.extensions/nginx-unprivileged-test created
因为这是一项 NodePort 服务,K3s 将在 Raspberry Pi 上打开一个端口 30123。在我的本地网络上,Raspberry Pi 位于 192.168.0.43。
结 语
在我使用 K3s 的过程中注意到了一些事项,在此想要提醒:

在部署 NGINX 测试容器时,我最初使用了 Docker Hub 中的常规 nginx:latest 镜像。但是,似乎 K3s 还不支持低于 1024 的端口。在默认情况下,nginx 镜像会尝试在容器内打开端口 80,而这会导致一些问题。
本文中提到过,通常 Kubernetes 发行版中都包含 label 和 taint,但 K3s 暂时没有完全实现这一点。

K3s 将极大地促进 Kubernetes 在边缘计算场景的使用,对这一点我充分相信。

退出移动版