作者:马伟,青云科技容器顾问,云原生爱好者,目前专注于云原生技能,云原生领域技能栈触及 Kubernetes、KubeSphere、KubeKey 等。
边际核算在广泛制造业、工业、零售和金融等职业,跟着云原生运用的兴起,不可变基础设施和快速的运用交给等特性很适用于边际核算场景。因而在 Kubernetes 上运用边际核算结构是近年很火热的一个方向。本篇会介绍下边际核算的场景和架构,并以一个 Demo 示例展示怎么运转一个边际运用到边际节点上。
边际核算痛点和场景
首先,边际核算是云核算的延伸,云核算按需和资源池化的特性能够满意资源利用率的提高和核算资源的集中供应,但边际测的运用场景决议不可能什么运用都丢到数据中心里。比方
- 低推迟处理。车联网场景假如要进行数据共享和指令下发需求极低推迟的通讯保证和核算处理速度。
- 本地处理数据。有些数据较敏感不能什么都传到云端(如用户照片、密码)
- 离线自治。许多边端设备纷歧定有牢靠的衔接坚持和云端的通讯。如农业、地舆科学的传感器。
因而关于边际节点和边际设备来说,需求统一办理和本地核算的才能,来完成云端担任总体决议计划,边端担任本地履行的作用。这样处理的优点便是数据处理效率高、减少云边带宽、下降运营本钱,却又不短少云端的资产办理、调度监控、安全管控。
了解边际核算意义后,就有提问了,已然边际核算和云核算都是一种概念,必然商场上有许多边际核算的产品和规范,为什么要在 Kubernetes 上运用边际核算呢?
这个我个人了解是双向奔赴的,kubernetes 本身比较合适基础架构规范化和运用交给,能够协助云端统一办理边际节点和边际设备,也合适于规范运用的云端下发,生态丰富且开源敞开的可观测系统也合适于不同的企业用管数据中心的办法完成边端可观测性。而 Kubernetes 也需求边际核算将自己的才能得到更多的延伸,去完成更多的渠道才能和渠道规范,究竟云-网-边-端是当代云核算需求涵盖的每个方向~
常见边际核算结构
关于产品选型来说,云原生领域最便利的便是翻开 landscape 了。咱们来看看 Automation&Configuration 这栏:
咱们常见的有三种,如 KubeEdge、OpenYurt 和 SuperEdge。本篇先拿 KubeEdge 这个孵化项目共享下。
KubeEdge 架构
KubeEdge 分为云端和边端。云端中心组件 CloudCore 和边端中心组件 EdgeCore 联合完成边际核算结构的许多功用,如云边通讯、设备办理、离线自治等。还有一些辅助组件如 EdgeMesh 完成边端通讯和服务治理,Sedna 供给边端 AI 结构等。
而到详细的 CloudCore 和 EdgeCore 的组成,可从下图详细学习架构规划:
云端
CloudCore 由 CloudHub 和 EdgeController、DeviceController 组成。
- CloudHub。首要观察云边改变,读写 Edge 音讯,缓存数据后经过 WebSocket/QUIC(K8s 的 listwatch 机制太耗资源)发送给 EdgeHub,还要把和 Edge 通讯得到的一些音讯发送给 Controller。
- EdgeController。作为 ApiServer 和 EdgeCore 的桥梁,办理常用的装备、Pod、缓存等事情,把 EdgeCore 订阅到的 Pod 的许多事情信息同步状况到 ApiServer。也把 ApiServer 的 ADD/UPDATE/DELETE 等事情同步到 EdgeCore。
- DeviceController。经过 EdgeCore DeviceTwin 同步设备更新,总体进程是 Mapper—>MQTT—>EventBus—>DeviceTwin->EdgeHub->CloudHub—>Deviceontroller->APIServer。另一方面便是云端创立的 Device,下发到边端得到元数据进行设备端更新。
边端
- EdgeHub。云边通讯边端,同步资源更新。
- EventBus。发送 / 接纳 MQTT 音讯
- MetaManager。在 SQLlite 存储数据,是 Edged 和 EdgeHub 的音讯处理器。
- Edged。边端裁剪版 kubelet。办理 Pod、configmap、volume 等资源的生命周期。还包括一个 StatusManager 和 MetaClient 组件。前者每 10s 将本地数据库存储的状况信息上传至云,后者作为 client 和本地迷你 Etcd(MetaManager)交互,如读取云端下发的 ConfigMap、Secret,写 Node、Pod Status。
- DeviceTwin。存储设备特色和状况,创立 Edge 设备和节点联系,同步设备特色到云。
- ServiceBus: 接纳云上服务恳求和边际运用进行 http 交互
装置布置
装置 Cloudcore
KubeSphere 现已集成了 KubeEdge,可供给边际节点纳管、运用下发、日志监控等功用。接下来将在 KubeSphere 上演示边际核算 Demo。
KubeSphere 上启用 KubeEdge,修正 clusterconfiguration,设置 edgeruntime enabled 为 true,kubeedge enabled 为 true,设置 advertiseAddress IP 为“master_ip”
设置完成后,在集群办理-> 节点中会出现“边际节点”:
此刻检查 kubeedge 命名空间下的作业负载和装备,能够熟悉下布置架构。
CloudCore 作为一个 Deployment 运转,IptablesManager 会协助处理云边通道的 Iptables 规矩下发。
检查 CloudCore 挂载的 ConfigMap 和 Secret,ConfigMap 首要挂载 cloudcore.yaml 装备文件到 /etc/kubeedge/config, 可灵活修正 CloudCore Modules 装备。Secret 挂载 CloudCore 和 EdgeCore 需求用到的一些 TLS 证书。
增加边际节点
进入 KubeSphere Console,导航到节点-> 边际节点,增加边际节点:
填写边际节点的姓名和边际节点的 IP,生成边际节点装备命令,粘贴到边际节点履行:
因为咱们运用的 cloudcore 的服务是经过 NodePort 暴露出来的,所以在边际节点注册 Cloudcore 时,需求运用 NodeIP:NodePort 方式,此处将 10000-10004 替换为 30000-30004 端口。
install MQTT service successfully.
kubeedge-v1.9.2-linux-amd64.tar.gz checksum:
checksum_kubeedge-v1.9.2-linux-amd64.tar.gz.txt content:
[Run as service] start to download service file for edgecore
[Run as service] success to download service file for edgecore
kubeedge-v1.9.2-linux-amd64/
kubeedge-v1.9.2-linux-amd64/edge/
kubeedge-v1.9.2-linux-amd64/edge/edgecore
kubeedge-v1.9.2-linux-amd64/version
kubeedge-v1.9.2-linux-amd64/cloud/
kubeedge-v1.9.2-linux-amd64/cloud/csidriver/
kubeedge-v1.9.2-linux-amd64/cloud/csidriver/csidriver
kubeedge-v1.9.2-linux-amd64/cloud/admission/
kubeedge-v1.9.2-linux-amd64/cloud/admission/admission
kubeedge-v1.9.2-linux-amd64/cloud/cloudcore/
kubeedge-v1.9.2-linux-amd64/cloud/cloudcore/cloudcore
kubeedge-v1.9.2-linux-amd64/cloud/iptablesmanager/
kubeedge-v1.9.2-linux-amd64/cloud/iptablesmanager/iptablesmanager
KubeEdge edgecore is running, For logs visit: journalctl -u edgecore.service -b
检查 KubeSphere 控制台的边际节点,现已能够看到边际节点注册上来:
运用 kubectl 检查节点状况:
Metrics& 日志
此刻咱们发现节点的 CPU 内存信息无法统计,需求敞开 KubeSphere Metrics_Server 并在 Edge 端敞开 EdgeStream:
修正 cc,敞开 metrics-server:
修正边际节点 /etc/kubeedge/config/edgecore.yaml 文件,搜索 edgeStream,将 false 更改为 true:
edgeStream:
enable: true
handshakeTimeout: 30
readDeadline: 15
server: 192.168.100.7:30004
tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt
tlsTunnelCertFile: /etc/kubeedge/certs/server.crt
tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key
writeDeadline: 15
此处 server 字段设置端口为 30004,因为咱们运用 NodePort 端口和云端通讯
重启 edgecore.service:
$ systemctl restart edgecore.service
检查节点监控信息:
咱们上面章节中现已在 edgecore 敞开 edgestream,完成了云端搜集 Edge 节点的 Metrics 功用,这个操作一起也完成了边端日志检查的才能。
一般来说,当咱们 kubectl logs pod -n namespace 后,kubectl 会恳求 kube-apiserver 查询 pod 是否存在以及 pod 里是否含有多个容器,再检索 Pod 所在的 Node 的 Kubelet Server 信息。这个信息一般能够经过 kubectl describe 或 get node 查到:
$ kubectl get node ks2 -oyaml
addresses:
- address: 192.168.100.7
type: InternalIP
- address: ks2
type: Hostname
daemonEndpoints:
kubeletEndpoint:
Port: 10250
kubectl get node edge-node-1 -oayml
addresses:
- address: 192.168.100.6
type: InternalIP
- address: edge-node-1
type: Hostname
daemonEndpoints:
kubeletEndpoint:
Port: 10352
InternalIP+kubeletEndpoint 组成 kubelet server 的地址,kubectl logs 就能够恳求这个地址得到相关日志信息。但关于边际端来说,大多数状况这个 internalIP 云端是无法拜访的。
此刻就需求 CloudCore 的 CloudStream 和 EdgeCore 的 EdgeStream 树立一个云边通道,在 CloudCore 和 EdgeCore 树立云边 WebSocket 通讯后,将恳求的 Edge kubelet server 的日志信息能经过通道回来给云端。这个通道需求两边敞开 CloudStream 和 EdgeStream,并经过 TLS 证书进行验证。
边际端在上面现已敞开 EdgeStream,云端布置 CloudCore 后会主动敞开。
检查云端挂载的 CloudCore.yaml 装备文件:
当然,云边通道只能将日志从音讯回来,详细回来到 CloudCore 的 CloudStream,还需设置一个 NAT 规矩:
$ iptables -t nat -A OUTPUT -p tcp --dport 10350(edge kubelet 端口)-j NAT --to $ClOUDCOREIPS:10003
这个操作现已让主动布置的 iptables-manager 完成了~
$ iptables -t nat -L
Chain TUNNEL-PORT (2 references)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:10351 to:10.20.253.88:10003
DNAT tcp -- anywhere anywhere tcp dpt:10352 to:10.20.253.127:10003
进入边际节点,检查容器组,咱们能够看到有几个 daemonset 有强忍受度,调度到了边际节点,因为边际端许多状况存在不稳定通讯,不合适运转 Calico 这种 CNI 组件,更多运用 EdgeMesh 进行云边通讯和服务发现,咱们能够手动 Patch Pod 以防止非边际节点调度至作业节点:
#!/bin/bash
NoShedulePatchJson='{"spec":{"template":{"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node-role.kubernetes.io/edge","operator":"DoesNotExist"}]}]}}}}}}}'
ns="kube-system"
DaemonSets=("nodelocaldns" "kube-proxy" "calico-node")
length=${#DaemonSets[@]}
for((i=0;i<length;i++));
do
ds=${DaemonSets[$i]}
echo "Patching resources:DaemonSet/${ds}" in ns:"$ns",
kubectl -n $ns patch DaemonSet/${ds} --type merge --patch "$NoShedulePatchJson"
sleep 1
done
进入节点终端(KS3.3 以上可用),运转脚本
sh-4.2# ./bash.sh
Patching resources:DaemonSet/nodelocaldns in ns:kube-system,
daemonset.apps/nodelocaldns patched
Patching resources:DaemonSet/kube-proxy in ns:kube-system,
daemonset.apps/kube-proxy patched
Patching resources:DaemonSet/calico-node in ns:kube-system,
daemonset.apps/calico-node patched
检查边际节点容器组:
运转运用
已然边际节点注册进来了,咱们来运转个运用吧。
进入项目-运用负载,创立一个 Deployment 作业负载:
设置资源约束
选择节点分配:
创立后会显现节点存在污点无法调度,需求加上 toleration:
修正 nginx-edge 运用的 yaml,增加对 edge 的 toleration:
增加污点忍受后,Pod 运转成功:
设置一个 NodePort Service,拜访 Nginx 服务:
此刻能够发现拜访是不通的,因为云端无法拜访边际端的 Pod 网络,检查边际 nginx-edge 的 ip:
bash-5.1# kubectl get pod -n demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-9c99b5774-vvsfq 1/1 Running 4 (12h ago) 4d11h 10.20.253.123 ks2 <none> <none>
nginx-edge-68c66d6bf9-k9l6n 1/1 Running 0 7m55s 172.17.0.2 edge-node-1 <none> <none>
ssh 到边际节点,拜访 172.17.0.2:
$ curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
可见 Nginx Pod 服务是正常的,这个 IP 地址分配也很熟悉,172.17.0.0/16,这不是 docker bridge 网段嘛,检查下边际节点 docker0 地址:
$ ip ad
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:1a:fa:b2:cb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:1aff:fefa:b2cb/64 scope link
valid_lft forever preferred_lft forever
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6c296a4dc16 nginx "/docker-entrypoint.…" 7 minutes ago Up 6 minutes k8s_container-zpnv7r _nginx-edge-68c66d6bf9-k9l6n_demo_99d01b2c-9ca7-4d56-a475-ab1b6838a35d_0
4e72f538703c kubeedge/pause:3.1 "/pause" 11 minutes ago Up 11 minutes k8s_POD_nginx-edge-6 8c66d6bf9-k9l6n_demo_99d01b2c-9ca7-4d56-a475-ab1b6838a35d_0
咱们能够看到 nginx-edge 这个容器还是以 Pod 方式运转的,经过 pause 容器共享网络命名空间,只不过它没有运用集群的 PodCIDR 分配,而是运用 docker bridge 网络。因而在没有 coredns 和 kube-proxy 的服务发现和云边容器网络互通的条件下,边端的 Pod Service 是无法拜访的。这很契合边云特色,边际端更多是私网,且无法被云端拜访,这种单向通讯的特色需求有其他方式的网络促成云边的通讯和服务拜访,比方树立地道。
云边服务互访
KubeEdge 社区有个 EdgeMesh 的项目。在边际核算机的场景下,网络拓扑结构更加杂乱。不同区域的边际节点往往不能互联,而运用之间又需求业务流量互通。EdgeMesh 即可满意边际节点之间流量互通的要求。按照官方 Github 介绍,EdgeMesh 作为 KubeEdge 集群的数据平面组件,为运用程序供给简略的服务发现和流量代理功用,然后屏蔽了边际场景中的杂乱网络结构。
因而 EdgeMesh 首要完成两个终极方针:
- 用户能够在不同的网络中拜访边到边、边到云、云到边的运用
- 布置 EdgeMesh 相当于布置了 CoreDNS+Kube-Proxy+CNI
布置 EdgeMesh
布置有些前置条件,比方敞开 Edge Kube-API Endpoint: 敞开 cloudcore dynamicController:
$ vim /etc/kubeedge/config/cloudcore.yaml
modules:
...
dynamicController:
enable: true
敞开 Edge metaServer:
$ vim /etc/kubeedge/config/edgecore.yaml
modules:
...
edgeMesh:
enable: false
...
metaManager:
metaServer:
enable: true
增加 edgemesh commonconfig 信息:
$ vim /etc/kubeedge/config/edgecore.yaml
modules:
...
edged:
clusterDNS: 169.254.96.16
clusterDomain: cluster.local
...
重启 cloudcore 和 edgecore 后,可在 edge 端验证是否能恳求 kube-API:
[root@i-pfcctw6w ~]# curl 127.0.0.1:10550/api/v1/services
{"apiVersion":"v1","items":[{"apiVersion":"v1","kind":"Service","metadata":{"creationTimestamp":"2023-01-04T13:09:51Z","labe ls":{"component":"apiserver","provider":"kubernetes","service.edgemesh.kubeedge.io/service-proxy-name":""}
EdgeMesh Helm Chart 已收入 KubeSphere 运用商铺,咱们翻开运用商铺直接布置即可。 进入 kubeedge 项目,将 EdgeMesh 布置到此项目中。 此刻需求修正运用设置的 server.nodeName,server.advertiseAddress。 履行装置,装置成功后检查 edgemesh-server 和 edgemesh-agent 运转状况:
测验边端服务拜访:
运用示例运用 github.com/kubeedge/ed… hostname 运用及服务: 测验从云端的 Pod 拜访边际 Service:
测验云边互访:
布置 github.com/kubeedge/ed… 的 cloudzone 和 edgezone 运用: 云端 busybox 拜访边端运用: 边端 busybox 拜访云端运用:
$ docker exec -it 5a94e3e34adb sh
/ # cat /etc/resolv.conf
nameserver 169.254.96.16
search edgezone.svc.ks2 svc.ks2 ks2 sh1.qingcloud.com
options ndots:5
/ # telnet tcp-echo-cloud-svc.cloudzone 2701
Welcome, you are connected to node ks2.
Running on Pod tcp-echo-cloud-6d687d88c4-tllst.
In namespace cloudzone.
With IP address 10.20.253.177.
Service default.
边际设备数据拜访
布置一个模拟温度数据获取的 App:
apiVersion: apps/v1
kind: Deployment
metadata:
name: temperature-mapper
labels:
app: temperature
spec:
replicas: 1
selector:
matchLabels:
app: temperature
template:
metadata:
labels:
app: temperature
spec:
hostNetwork: true
tolerations:
- key: "node-role.kubernetes.io/edge"
operator: "Exists"
effect: "NoSchedule"
nodeSelector:
kubernetes.io/hostname: "edge-node-1"
containers:
- name: temperature
image: lammw12/temperature-mapper:edge
imagePullPolicy: IfNotPresent
securityContext:
privileged: true
创立 DeviceModel:
apiVersion: devices.kubeedge.io/v1alpha2
kind: Device
metadata:
name: temperature
labels:
description: 'temperature'
manufacturer: 'test'
spec:
deviceModelRef:
name: temperature-model
nodeSelector:
nodeSelectorTerms:
- matchExpressions:
- key: ''
operator: In
values:
- edge-centos
status:
twins:
- propertyName: temperature-status
desired:
metadata:
type: string
value: ''
创立 Device:
apiVersion: devices.kubeedge.io/v1alpha2
kind: Device
metadata:
name: temperature
labels:
description: 'temperature'
manufacturer: 'test'
spec:
deviceModelRef:
name: temperature-model
nodeSelector:
nodeSelectorTerms:
- matchExpressions:
- key: ''
operator: In
values:
- edge-node-1
status:
twins:
- propertyName: temperature-status
desired:
metadata:
type: string
value: ''
KubeEdge 经过 Kubernetes 的 CRD,增加了 DeviceModel 和 Device 两个资源,分别来描绘设备元信息和设备实例信息,DeviceController 担任边际设备办理,在云和边之间传递这些信息。用户能够经过 Kubernetes API 从云中创立、更新和删去设备元数据,也能够经过 CRD API 控制设备特色的预期 (desired) 状况,从云端对设备进行 CRUD 操作。 DeviceModel 描绘了设备特色,例如 “温度” 或 “压力”, 相似一个可重复运用的模板,运用它能够创立和办理许多设备。 一个 Device 实例代表一个实际的设备对象。它就像 device model 的实例化,引用了 model 中界说的特色。 kubectl apply 上述资源。 检查运转的 temperature 运用: 检查 temperature 运用日志: 运用 kubectl 检查 device 状况:
[root@ks2 examples]# kubectl get device temperature -oyaml
status:
twins:
- desired:
metadata:
type: string
value: ""
propertyName: temperature-status
reported:
metadata:
timestamp: "1673256318955"
type: string
value: 70C
yaml 中的 device status 包括两份数据,一个是云端期望设置的状况数据(‘desired’),一个是边际端上报的状况数据(‘reported’)。云端的 DeviceController 经过 Kubernetes API 监听 device 设备的创立事情,会主动创立一个新的 configmap,存储该 device 的 status 等特色信息,并保存到 ectd 中。EdgeController 将 configmap 同步到边际节点,因而边际节点的运用也能够获取设备的特色信息。‘desired’值将初始化到边际节点数据库以及边际设备中,因而即便边际节点重启,也能主动恢复到之前的状况。当然这个‘desired’值也会跟着云端用户对设备的 CRUD 而更改。
镜像预热
在实际运用中,边际节点和设备是大规模且网络环境不够稳定的,云端下发边际运用到多个节点后,可能镜像拉取花费的时刻很受办理员困扰。这与容器化快速大规模交给运用和业务上线 / 扩容 / 晋级的期望背道而驰。 因而镜像预热的才能是大规模边际节点场景中不可或缺的,咱们能够借助镜像预热工具完成边际节点上的镜像提早拉取,加快运用布置的速度。开源社区有一个 OpenKruise 的项目,能够完成此需求。 OpenKruise 为每个 Node 驻扎一个 Daemonset,经过与 CRI 交互来绕过 kubelet 完成拉取镜像的才能。比方,界说一个 NodeImage CR,界说每个节点需求预热什么镜像,然后 kruise-daemon 就能够按照 NodeImage 来履行镜像的拉取使命: 关于大规模边际节点场景,能够经过 ImagePullJob 筛选节点后进行批量预热,一个 ImagePullJob 创立后,会被 kruise-manager 中的 imagepulljob-controller 接纳到并处理,将其分解并写入到一切匹配节点的 NodeImage 中,以此来完成规模化的预热。
apiVersion: apps.kruise.io/v1alpha1
kind: ImagePullJob
metadata:
name: job-with-always
spec:
image: nginx:1.9.1 # [required] 完整的镜像名 name:tag
parallelism: 10 # [optional] 最大并发拉取的节点梳理, 默以为 1
selector: # [optional] 指定节点的 姓名列表 或 标签选择器 (只能设置其中一种)
names:
- node-1
- node-2
matchLabels:
node-type: xxx
# podSelector: # [optional] 经过 podSelector 匹配Pod,在这些 Pod 所在节点上拉取镜像, 与 selector 不能一起设置.
# matchLabels:
# pod-label: xxx
# matchExpressions:
# - key: pod-label
# operator: In
# values:
# - xxx
completionPolicy:
type: Always # [optional] 默以为 Always
activeDeadlineSeconds: 1200 # [optional] 无默许值, 只对 Alway 类型生效
ttlSecondsAfterFinished: 300 # [optional] 无默许值, 只对 Alway 类型生效
pullPolicy: # [optional] 默许 backoffLimit=3, timeoutSeconds=600
backoffLimit: 3
timeoutSeconds: 300
以上便是本次共享的全部内容,首要方针为把 KubeSphere 的边际核算用起来,那么这把剑舞到什么程度,还要持续打磨技能+专业服务。
本文由博客一文多发渠道 OpenWrite 发布!