最近做开源需要部署k8s环境,但k8s本身是一个相当前沿的项目而且架构仍然在改变,所以网上的教程会有很多旧版本的坑,加之官方文档比较晦涩难懂,这篇博客旨在给对k8s感兴趣/有需求的同学提供参考。
这篇博客面向环境搭建,你不会学到太多K8S具体内容和工作原理,但你能知道自己一条命令下去做了什么,如何从log中获取有用信息并贴出一些官方文档链接,能拥有一个包含一个master节点以及一个work节点的正常运行的集群,
前置需求
-
了解image、container、pod等概念
-
基础指令:容器运行时工具基本用法
-
能耐心读容器日志
-
能耐心读大量文档
Part1 K8S 简介
1.你为什么需要K8S
容器是打包和运行应用程序的好方式。在生产环境中, 你需要管理运行着应用程序的容器,并确保服务不会下线。 例如,如果一个容器发生故障,则你需要启动另一个容器。 如果此行为交由给系统处理,是不是会更容易一些?
这就是 Kubernetes 要来做的事情! Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移你的应用、提供部署模式等。
2.K8S架构简介
容器运行时接口(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部署可选方案:
- 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增量学习解析
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的人可以在此基础上继续产出。