KubeEdge-Sedna搭建指南--从零开始部署边云协同应用

最近做开源需要部署k8s环境,但k8s本身是一个相当前沿的项目而且架构仍然在改变,所以网上的教程会有很多旧版本的坑,加之官方文档比较晦涩难懂,这篇博客旨在给对k8s感兴趣/有需求的同学提供参考。

这篇博客面向环境搭建,你不会学到太多K8S具体内容和工作原理,但你能知道自己一条命令下去做了什么,如何从log中获取有用信息并贴出一些官方文档链接,能拥有一个包含一个master节点以及一个work节点的正常运行的集群,

前置需求

  • 了解image、container、pod等概念

  • 基础指令:容器运行时工具基本用法

  • 能耐心读容器日志

  • 能耐心读大量文档

Part1 K8S 简介

1.你为什么需要K8S

容器是打包和运行应用程序的好方式。在生产环境中, 你需要管理运行着应用程序的容器,并确保服务不会下线。 例如,如果一个容器发生故障,则你需要启动另一个容器。 如果此行为交由给系统处理,是不是会更容易一些?

这就是 Kubernetes 要来做的事情! Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移你的应用、提供部署模式等。

2.K8S架构简介

Kubernetes 的组件

容器运行时接口(CRI) : 一组与kubelet集成的容器运行时API

容器运行时(Container Runtimes):负责运行容器的软件。 我们需要着重关心的是容器的CNI插件、配置文件、CRI套接字、Cgroup驱动、systemd服务以及沙箱镜像(sandbox_image)版本

Cgroup驱动程序(Cgroup drivers):一组具有可选资源隔离、审计和限制的Linux进程,我们需要惯性的是cgroupfs驱动还是systemd驱动

集群CNI插件:实现 Kubernetes 的网络模型, 建议看最简单的flannel

Part2 K8S集群

1. OS相关配置

关闭防火墙

service iptables stop
systemctl stop firewalld.service
ufw disable
iptables -F

关闭swap分区

swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

iptable相关配置

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 应用 sysctl 参数而不重新启动
sudo sysctl --system

2.相关软件

此处容器运行时我选择了containerd, 如果用docker请注意k8s三件套版本,官方会在之后停止对docker的支持

安装containerd及其cni插件,参考

修改config.toml配置时重点注意:

  • cgroup 配置为systemd
  • pause镜像的名称以及版本
  • 参考
apt install containerd -y
systemctl start containerd
mkdir -p /etc/containerd/
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

安装containerd需要的cni :https://github.com/containerd/containerd/blob/main/docs/getting-started.md#step-3-installing-cni-plugins

systemctl restart containerd

安装k8s三件套,版本统一为1.22.13-00

  • kubeadm 用于初始化(init)和重置(reset)集群

  • kubectl 用于控制和监控集群资源

  • kubelet是节点需要的sysytemed服务

apt install -y apt-transport-https  gnupg gnupg2 gnupg1 curl lsb-release
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet=1.22.13-00 kubeadm=1.22.13-00 kubectl=1.22.13-00
# 启动kubelet
systemctl enable kubelet && systemctl start kubelet

3.下拉镜像

国内源下拉镜像并打上标签,将命名空间设置为k8s.io,这是使用kubeadm初始化集群时找镜像的命名空间。

kubeadm config images pull --kubernetes-version=v1.22.13 --image-repository=registry.aliyuncs.com/google_containers --cri-socket unix:///run/containerd/containerd.sock

ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.22.13 k8s.gcr.io/kube-apiserver:v1.22.13
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.22.13 k8s.gcr.io/kube-controller-manager:v1.22.13
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.22.13 k8s.gcr.io/kube-scheduler:v1.22.13
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-proxy:v1.22.13 k8s.gcr.io/kube-proxy:v1.22.13
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/pause:3.5 k8s.gcr.io/pause:3.5
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/etcd:3.5.0-0 k8s.gcr.io/etcd:3.5.0-0 
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/coredns:v1.8.4 k8s.gcr.io/coredns:v1.8.4

此处注意pause镜像的版本要与containerd配置文件中的镜像版本相同

pause镜像用于创建sandbox也就是k8s中的pod

4.kubeadm搭建集群

sudo kubeadm init \
      --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
      --service-cidr=10.96.0.0/12       \
      --pod-network-cidr 10.244.0.0/16
	  --cri-socket unix:///run/containerd/containerd.sock


mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

--image-repository : 指定镜像仓库

--service-cidr=10.96.0.0/12 : 服务的网段

什么是服务

--pod-network-cidr 10.244.0.0/16 :给集群的pod划分网段,该网段是后续cni插件flannel的默认网段。这里划分的网段不能跟你宿主机的网段有重叠

什么是pod

--cri-socket unix:///run/containerd/containerd.sock : 如果你的宿主机上同时存在多个容器运行时,比如docker 和 containerd, 需要指定容器运行时接口(cri)所使用的socket

记住这里会输出kubeadm join 的指令

5.kubeadm join

在其他节点重复重复1-3步,然后kubeadm join

6.集群cni

选择flannel作为集群cni

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

7. 重置

如果你部署出了问题需要重置边/云节点,

  • 首先: 边端都执行kubeadm reset

  • 删除网卡,清空路由表并重启systemd服务

rm -rf /etc/cni/net.d && rm -rf /home/lj1ang/.kube/config file && rm -rf  $HOME/.kube/config
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm --clear
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig edgemesh0 down
ip link delete cni0
ip link delete flannel.1
ip link delete edgemesh0
systemctl restart kubelet
systemctl restart containerd

至此,会有两个ready的集群,其中每个节点都是ready状态,每个pod都是running状态

其中有一些目录/网卡是后续kubeedge和edgemesh创建的

Part3 Kubeedge 二进制部署

kubeedge官方文档

kubeedge部署可选方案:

  • keadm:这个是官方开发的工具,这个方案需要你能解决各种网络问题或者自己能把crd放在合适的位置
  • 二进制部署:通过cloudcore 和 edgecore完成

我选择了二进制部署 ,首先不用管网络问题和各种资源的位置,其次后续在部署edgemesh的时候也要对cloudcore和edgecore的配置文件动刀子

1. 创建CRD

kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/devices/devices_v1alpha2_device.yaml
kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/devices/devices_v1alpha2_devicemodel.yaml
kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/reliablesyncs/cluster_objectsync_v1alpha1.yaml
kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/reliablesyncs/objectsync_v1alpha1.yaml
kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/router/router_v1_ruleEndpoint.yaml
kubectl apply -f https://raw.githubusercontent.com/kubeedge/kubeedge/master/build/crds/router/router_v1_rule.yaml

2. 准备配置文件

github下载kuebedge编译出来的的最新版本,云端进入cloudcore所在目录,边端进入edgecore所在目录,

我这里用的是v1.11.1

cloudcore --defaultconfig > cloudcore.yaml

此处分有两个选项--minconfig--defaultconfig, 不建议选择--minconfig, 不然后续配置不够用。

edgecore --minconfig > edgecore.yaml

配置修改

  • cloudcore 所用配置

    • kubeAPIConfig.kubeConfig
    • advertiseAddress
  • edgecore 所用配置

    • modules.edgehub.websocket.server

    • modules.edgehub.quic.server

    • modules.edgehub.httpServer

    • token: 在云端通过kubectl get secret -nkubeedge tokensecret -o=jsonpath='{.data.tokendata}' | base64 -d 获得

    • 安装mosquitto, 边端需要1883端口进行mqtt通信,这里可能要配置mosquitto 的systemd, 这里请参看自己所用linux发行版的文档

    • 自动注册modules.edged.registerNode: true

    • CRI 相关内容: kubeedge默认的cri是docker, 我们使用containerd作为容器运行时

      remoteRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
      remoteImageEndpoint: unix:///var/run/containerd/containerd.sock
      runtimeRequestTimeout: 2
      podSandboxImage: k8s.gcr.io/pause:3.2
      runtimeType: remote
      

      以及 modules.edged.cgroupDriver: systemd

3.运行

云端

./cloudcore --config cloudcore.yaml

边端

./edgedcore --config edgecore.yaml

4. 重置

如果你出错需要重新部署整个集群,请参考上面 Part2 第7小节

至此,你应该会拥有一个正常运行edgecore和cloudcore的集群。集群里每个pod都处于running状态,但边端目前应该会有目标同步出错的问题(1.11.1版本kubeedge),但能正常运行`

Part4 部署edgemesh

官方文档

1.安装edgemesh

edgemesh分为edgemesh-server和edgemesh-agent

我建议采用手动安装 ,这样出了问题更能知道在拿出了问题。

安装部分没有太多需要介绍的内容,完全参考手动安装教程就可以了,要注意的是master可以让master节点也跑edgemesh-aget, 需要的操作是

kubectl taint node lenovo node-role.kubernetes.io/master-

什么是污点(taint)
k8s默认pod不被调度到master节点上, 上免得操作是驱逐master节点的taint使一个edgemesh-agent可以被调度到master节点上


这里重点介绍一下测试用例为sedna做准备

2.测试用例

sedna需要边云通信,请确保用edgemesh能跑通跨边云通信测试用例

Part5 部署Sedna

1.安装

部署文档

直接参考部署文档做。

2. sedna troubleshooting

报错:边端lc 无法连接云端gm
分析: 通常如果edgemesh的跨边云通信跑通了不会出现这样的问题。

建议查看各个容器的log, 尝试重新部署,

我之前是没用kubeadm把边缘节点加入集群。

报错: 云端lc pod没起来
查看senda的部署脚本内容,我通过去掉master 的taint解决了这个问题

Part6 Senda增量学习解析

refer:
官方文档
增量学习demo

1.sedna是如何做增量学习的?

当我们正确部署sedna增量学习demo的pod时:

  • 边端起一个infer-worker,同时边端lc监控数据集的数量
  • 当数据集的数量满足trigger条件时,边端lc通知云端gm创建训练pod,在边端调度train-worker
  • train-worker完成训练后,起eval-worker测试推理和训练的权值文件的准确率,看是否要替代用于推理的权值文件。

2. 如何客制化增量学习demo

需要自己定制的部分:

  • 数据集,estimator, 定制train.py, infer.py,eval.py
  • 自己打镜像
  • 修改参考的yaml

Part6 Troubleshooting

问题1:kubeadm init 超时
解决方案:通常是镜像拉不下来,这里可以通过查看containerd和kubelet的log看到没能拉去下来 的镜像,通过下拉阿里云的镜像仓库并打上对应的标签可以解决

问题2:pause镜像版本不匹配
解决方案:pause镜像是创建pod的基础,需要保证yaml中描述的pause镜像仓库名称,版本正确

问题3:启用edgecore的时候报错1883端口连接异常
解决方案:1883端口被用于边端的mqtt服务。需要在边端开启mqtt并且作为systemd服务启动

问题4:edgemesh不能实现跨云边通信
解决方案: 没有在部署kubeedge的时候将边端节点join到集群

问题5:边端节点由于token等原因没有正常启动,需要重置
解决方案:1.删除相关目录 2. 重新启动edgecore

问题6:边端lc无法连接到云端gm
解决方案:测试edgemesh能否实现跨云边通信,参考问题4

问题7:sedna的lc pod在云端无法正常运行
解决方案:将master节点作为云端节点时,默认不运行pod,可以通过删除其master的taint解决该问题

问题8:demo开发过程中容器内环境变量值错误
解决方案:1.进入容器内通过echo查看环境变量的值 2. 在云端describe pod 查看环境变量

目前k8s和kubeedge社区的项目仍然在频繁地更新迭代,这篇blog在不久的将来肯定会有不足的地方,希望阅读这篇blog的人可以在此基础上继续产出。

1 个赞

补充一点对于sedna的介绍

Senda可以干嘛?

得益于KubeEdge提供的边云协同能力,Sedna可以实现跨边云的协同训练和协同推理能力,如联合推理、增量学习。
说人话就是可以在云端部署一个带有某种学习范式(例如增量学习)的应用到边端。云端主要做监管和部署等工作,而边端主要做训练和推理等工作。

可以选用的深度学习框架

  • TensorFlow
  • Pytorch
  • Mindspore(pr review中)
  • TinyMS(未来会支持)

Debug

在正确配置环境变量的情况下,sedna的example目录下的各个demo是可以本地跑通的,更方便调试。