共计 13151 个字符,预计需要花费 33 分钟才能阅读完成。
作者 | 唐炳昌
起源 | 阿里巴巴云原生公众号
随着边缘计算的疾速倒退,越来越多的数据须要到网络的边缘侧进行存储、解决和剖析,边缘的设施和利用呈爆发式增长。如何高效的治理边缘侧的资源和利用是业界面临的一个次要问题。以后,采纳云原生的办法,将云计算的能力下沉到边缘并在云端做对立调度、管控的云边端一体化架构失去了业界的宽泛认可。
2020 年 5 月,阿里巴巴开源首个 Kubernetes 无侵入的边缘计算云原生我的项目 OpenYurt,并于同年 9 月份进入 CNCF SandBox。OpenYurt 针对边缘场景中网络不稳固、云边运维艰难等问题,对原生 Kubernetes 无侵入地加强,重点提供了边缘节点自治、云边运维通道、边缘单元化的能力。
如图 1 所示,本文通过在云端部署 Kubernetes 集群的管制面,并将树莓派接入集群来搭建云管边场景。基于这个环境演示 OpenYurt 的外围能力,带大家疾速上手 OpenYurt。
图 1 原生 Kubernetes 集群
环境筹备
1. 根底环境介绍
在云端,购买 ENS 节点(ENS 节点具备公网 IP,不便通过公网对外裸露服务)来部署原生 K8s 集群的管控组件。其中零碎采纳 ubuntu18.04、hostname 为 master-node、docker 版本为 19.03.5。
在边缘,如图 2 所示,将树莓派 4 与本地的路由器连贯,组成边缘私网环境,路由器通过 4G 网卡拜访互联网。其中树莓派 4 预装零碎为 ubuntu18.04、hostname 为 edge-node、docker 版本为 19.03.5。
图 2 边缘环境实体图
2. 原生 K8s 集群搭建
本文演示环境基于社区 1.16.6 版本的 K8s 集群,并采纳社区提供的 kubeadm 工具来搭建集群,具体操作如下:
- 在云端节点和树莓派上别离执行如下命令装置 Kubernetes 组件。
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt install -y kubelet=1.16.6-00 kubeadm=1.16.6-00 kubectl=1.16.6-00
- 应用 kubeadm 初始化云端节点(在云端节点上执行如下命令),部署过程中采纳阿里云的镜像仓库,为了反对树莓派的接入,该仓库的镜像做了 manifest 列表,可能反对 amd64/arm64 两种不同的 CPU 架构。
# master-node
kubeadm init --image-repository=registry.cn-hangzhou.aliyuncs.com/edge-kubernetes --kubernetes-version=v1.16.6 --pod-network-cidr=10.244.0.0/16
根据初始化实现之后的提醒,拷贝 config 文件到 $HOME/.kube 中:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
- 树莓派接入云端集群根据第二步中初始化实现当前输入的节点接入信息,在树莓派上执行接入命令。
kubeadm join 183.195.233.42:6443 --token XXXX \
--discovery-token-ca-cert-hash XXXX
- 增加 cni 配置(云端管控节点和树莓派都须要配置),本文搭建的集群应用主机网络。创立 cni 配置文件 /etc/cni/net.d/0-loopback.conf,并将如下内容拷贝到该文件中。
{
"cniVersion": "0.3.0",
"name": "lo",
"type": "loopback"
}
- 在 master 节点上查看部署成果。
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
edge-node Ready <none> 74s v1.16.6 192.168.0.100 <none> Ubuntu 18.04.4 LTS 4.19.105-v8-28 docker://19.3.5
master-node Ready master 2m5s v1.16.6 183.195.233.42 <none> Ubuntu 18.04.2 LTS 4.15.0-52-generic docker://19.3.5
- 删除 CoreDNS(本文 Demo 中 CoreDNS 不须要应用),并将 master 节点的 taints 去掉(不便后续部署 OpenYurt 组件)。
kubectl delete deployment coredns -n kube-system
kubectl taint node master-node node-role.kubernetes.io/master-
原生 K8s 集群在边缘场景中的问题
基于上述环境,咱们来测试一下原生 K8s 在云管边架构中对云边运维的反对和对云边网络断开时的反馈。首先,咱们从云端部署一个测试利用 nginx,在 master 节点上执行 kubectl apply -f nginx.yaml,具体的部署 yaml 如下。
留神:nodeSelector 抉择 edge-node 节点,主机网络配置为 true,并配置 pod 的容忍工夫为 5s(默认 5min, 此处配置便于演示 pod 驱赶)。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 5
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 5
nodeSelector:
kubernetes.io/hostname: edge-node
containers:
- name: nginx
image: nginx
hostNetwork: true
查看部署后果:
root@master-node:~# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 11s 192.168.0.100 edge-node <none> <none>
1. 测试罕用的集群运维指令,包含 logs、exec、port-forward。
在 master 节点上运维边缘节点利用,执行 logs/exec/port-forward 等指令,查看后果。
root@master-node:~# kubectl logs nginx
Error from server: Get https://192.168.0.100:10250/containerLogs/default/nginx/nginx: dial tcp 192.168.0.100:10250: connect: connection refused
root@master-node:~# kubectl exec -it nginx sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Error from server: error dialing backend: dial tcp 192.168.0.100:10250: connect: connection refused
root@master-node:~# kubectl port-forward pod/nginx 8888:80
error: error upgrading connection: error dialing backend: dial tcp 192.168.0.100:10250: connect: connection refused
从执行后果看,原生的 k8s 在云管边的场景中,无奈提供从云端运维边缘利用的能力。这是因为边缘节点部署在用户的私网环境,从云端无奈通过边缘节点的 IP 地址间接拜访边缘节点。
2. 测试边缘断网时对业务的影响
边缘节点与云端管控通过公网连贯,常常会呈现网络不稳固,云端断连的状况。这里咱们将做两个断网相干的测试:
- 断网 1 分钟 -> 复原网络
- 断网 1 分钟 -> 重启边缘节点 -> 复原网络
察看两个测试过程中节点和 Pod 的状态变动。本文 Demo 中的断网形式是将路由器的公网连贯断开。
1)断网 1 分钟 -> 复原网络
断开网络,大概 40s 后,节点变成 NotReady(失常节点 10s 钟上报一次心跳,当 4 次没有上报心跳时,管控组件认为节点异样)。
root@master-node:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
edge-node NotReady <none> 5m13s v1.16.6
master-node Ready master 6m4s v1.16.6
持续期待 5s 之后(失常节点变为 NotReady 之后,5m 才开始驱赶 pod,此处为了测试成果,将 pod 的容忍工夫配成了 5s),利用 pod 被驱赶,状态变为 Terminating。
root@master-node:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Terminating 0 3m45s
将网络复原,察看节点及 pod 变动。
root@master-node:~# kubectl get pods
No resources found in default namespace.
网络复原后,节点状态变成 ready,业务 pod 被革除,这是因为边缘节点的 Kubelet 获取到业务 Pod 的 Terminating 状态,对业务 Pod 做删除操作,并返回删除胜利,云端也做了相应的清理。至此,业务 Pod 因为云边网络的不稳固而被驱赶,然而在断网期间,边缘节点其实是能够失常工作的。
从新创立利用 nginx,用于上面测试。
root@master-node:~# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 4s 192.168.0.100 edge-node <none> <none>
2)断网 1 分钟 -> 重启边缘节点 -> 复原网络
接下来,咱们测试在断网的状况下,边缘节点的重启对业务的影响。断网 1 分钟之后,Node 和 Pod 状态同下面测试后果,Node 变为 NotReady,Pod 的状态变为 Terminating。此时,切换到公有网络环境,登录到树莓派上,将树莓派重启,重启实现后期待大概 1 分钟,察看重启前后节点上的容器列表。
重启前边缘节点容器列表(此时云边端开,尽管在云端获取的 pod 是 Terminating 状态,然而边缘并未 Watch 到 Terminating 的操作,所以边缘的利用还失常运行)。
root@edge-node:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9671cbf28ca6 e86f991e5d10 "/docker-entrypoint.…" About a minute ago Up About a minute k8s_nginx_nginx_default_efdf11c6-a41c-4b95-8ac8-45e02c9e1f4d_0
6272a46f93ef registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 2 minutes ago Up About a minute k8s_POD_nginx_default_efdf11c6-a41c-4b95-8ac8-45e02c9e1f4d_0
698bb024c3db f9ea384ddb34 "/usr/local/bin/kube…" 8 minutes ago Up 8 minutes k8s_kube-proxy_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_0
31952700c95b registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 8 minutes ago Up 8 minutes k8s_POD_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_0
重启后节点容器列表,断网重启后,kubelet 无奈从云端获取 Pod 信息,不会重建 Pod。
root@edge-node:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@edge-node:~#
从重启前后的比照看,边缘节点在断网重启之后,节点上的 Pod 全副无奈复原。这就会导致在云边断网时,一旦节点重启,利用将无奈工作。
将网络复原,察看节点及 pod 变动,同下面测试后果,网络复原后,节点变为 Ready,业务 Pod 被革除。
root@master-node:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
edge-node Ready <none> 11m v1.16.6
master-node Ready master 12m v1.16.6
root@master-node:~# kubectl get pods
No resources found in default namespace.
接下来,再次部署业务 nginx,测试 OpenYurt 集群对云边运维的反对和对云边断网时的反馈。
root@master-node:~# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 12s 192.168.0.100 edge-node <none> <none>
原生 K8s 集群一键转换为 OpenYurt 集群
探索了原生 Kubernetes 在云边一体化架构中的有余之后,咱们来看下 OpenYurt 集群是否能满足这种场景。当初,咱们利用 OpenYurt 社区提供的集群转换工具 yurtctl,来将原生 K8s 集群转换成 OpenYurt 集群。在 master 节点上执行如下命令,该命令指定了组件的镜像以及云端节点,并指定装置云边运维通道 yurt-tunnel。
yurtctl convert --yurt-controller-manager-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurt-controller-manager:v0.2.1 --yurt-tunnel-agent-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurt-tunnel-agent:v0.2.1 --yurt-tunnel-server-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurt-tunnel-server:v0.2.1 --yurtctl-servant-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurtctl-servant:v0.2.1 --yurthub-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurthub:v0.2.1 --cloud-nodes=master-node --deploy-yurttunnel
转换大略须要 2min,转换实现之后,察看业务 pod 的状态,能够看到转换过程中对业务 pod 无影响(也能够在转换过程中在新的终端应用 kubectl get pod -w 察看业务 pod 的状态)。
root@master-node:~# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 2m4s 192.168.0.100 edge-node <none> <none>
执行实现之后的组件散布如图 3 所示,其中橙色局部是 OpenYurt 相干的组件,蓝色局部是原生 K8s 组件。相应地,咱们察看云端节点和边缘节点的 pod。
图 3 OpenYurt 集群组件分布图
云端节点 yurt 相干的 pod:yurt-controller-manager 和 yurt-tunnel-server。
root@master-node:~# kubectl get pods --all-namespaces -owide | grep master | grep yurt
kube-system yurt-controller-manager-7d9db5bf85-6542h 1/1 Running 0 103s 183.195.233.42 master-node <none> <none>
kube-system yurt-tunnel-server-65784dfdf-pl5bn 1/1 Running 0 103s 183.195.233.42 master-node <none> <none>
边缘节点新增 yurt 相干的 pod: yurt-hub(static pod)和 yurt-tunnel-agent。
root@master-node:~# kubectl get pods --all-namespaces -owide | grep edge | grep yurt
kube-system yurt-hub-edge-node 1/1 Running 0 117s 192.168.0.100 edge-node <none> <none>
kube-system yurt-tunnel-agent-7l8nv 1/1 Running 0 2m 192.168.0.100 edge-node <none> <none>
测试 OpenYurt 集群在边缘场景中的能力
1. 测试 logs/exec/port-forward 等运维指令,查看后果
root@master-node:~# kubectl logs nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
root@master-node:~# kubectl exec -it nginx sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# ls
bin dev docker-entrypoint.sh home media opt root sbin sys usr
boot docker-entrypoint.d etc lib mnt proc run srv tmp var
# exit
root@master-node:~# kubectl port-forward pod/nginx 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Handling connection for 8888
测试 port-forward 时,在 master 节点上执行 curl 127.0.0.1:8888,能够拜访 nginx 服务。
从演示后果看,OpenYurt 可能很好地反对罕用的云边运维指令。
2. 测试边缘断网时对业务的影响
同样咱们反复原生 K8s 中断网的两个测试,在测试之前咱们先为边缘节点 edge-node 开启自治。在 OpenYurt 集群中,边缘节点的自治是通过一个 annotation 来标识的。
root@master-node:~# kubectl annotate node edge-node node.beta.alibabacloud.com/autonomy=true
node/edge-node annotated
1)断网 1 分钟 -> 网络复原
同样,将路由器公网断开,察看 Node 和 Pod 的状态。大概过了 40s,节点的状态变成 NotReady,而大概过 1min 当前,Pod 的状态始终是 Running,并不会被驱赶。
root@master-node:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
edge-node NotReady <none> 24m v1.16.6
master-node Ready master 25m v1.16.6
root@master-node:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 5m7s
复原网络,察看 Node 和 Pod 的状态,Node 状态变为 Ready,Pod 放弃 Running。可见云边网络不稳固时,对边缘节点的业务 Pod 无影响。
root@master-node:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
edge-node Ready <none> 25m v1.16.6
master-node Ready master 26m v1.16.6
root@master-node:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 6m30s
2)断网 1 分钟 -> 重启边缘节点 -> 复原网络
接下来,咱们测试在断网的状况下,边缘节点的重启对业务的影响。断网 1 分钟之后,Node 和 Pod 状态同下面测试后果,Node 变为 NotReady,Pod 放弃 Running。同样,咱们登录到树莓派上,将树莓派重启,察看重启前后节点上的容器列表。
重启前边缘节点容器列表:
root@edge-node:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38727ec9270c 70bf6668c7eb "yurthub --v=2 --ser…" 7 minutes ago Up 7 minutes k8s_yurt-hub_yurt-hub-edge-node_kube-system_d75d122e752b90d436a71af44c0a53be_0
c403ace1d4ff registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 7 minutes ago Up 7 minutes k8s_POD_yurt-hub-edge-node_kube-system_d75d122e752b90d436a71af44c0a53be_0
de0d693e9e74 473ae979be68 "yurt-tunnel-agent -…" 7 minutes ago Up 7 minutes k8s_yurt-tunnel-agent_yurt-tunnel-agent-7l8nv_kube-system_75d28494-f577-43fa-9cac-6681a1215498_0
a0763f143f74 registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 7 minutes ago Up 7 minutes k8s_POD_yurt-tunnel-agent-7l8nv_kube-system_75d28494-f577-43fa-9cac-6681a1215498_0
80c247714402 e86f991e5d10 "/docker-entrypoint.…" 7 minutes ago Up 7 minutes k8s_nginx_nginx_default_b45baaac-eebc-466b-9199-2ca5c1ede9fd_0
01f7770cb0f7 registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 7 minutes ago Up 7 minutes k8s_POD_nginx_default_b45baaac-eebc-466b-9199-2ca5c1ede9fd_0
7e65f83090f6 f9ea384ddb34 "/usr/local/bin/kube…" 17 minutes ago Up 17 minutes k8s_kube-proxy_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_1
c1ed142fc75b registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 17 minutes ago Up 17 minutes k8s_POD_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_1
重启后边缘节点容器列表:
root@edge-node:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0c66b87066a0 473ae979be68 "yurt-tunnel-agent -…" 12 seconds ago Up 11 seconds k8s_yurt-tunnel-agent_yurt-tunnel-agent-7l8nv_kube-system_75d28494-f577-43fa-9cac-6681a1215498_2
a4fb3e4e8c8f e86f991e5d10 "/docker-entrypoint.…" 58 seconds ago Up 56 seconds k8s_nginx_nginx_default_b45baaac-eebc-466b-9199-2ca5c1ede9fd_1
fce730d64b32 f9ea384ddb34 "/usr/local/bin/kube…" 58 seconds ago Up 57 seconds k8s_kube-proxy_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_2
c78166ea563f registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 59 seconds ago Up 57 seconds k8s_POD_yurt-tunnel-agent-7l8nv_kube-system_75d28494-f577-43fa-9cac-6681a1215498_1
799ad14bcd3b registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 59 seconds ago Up 57 seconds k8s_POD_nginx_default_b45baaac-eebc-466b-9199-2ca5c1ede9fd_1
627673da6a85 registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" 59 seconds ago Up 58 seconds k8s_POD_kube-proxy-rjws7_kube-system_51576be4-2b6d-434d-b50b-b88e2d436fef_2
04da705e4120 70bf6668c7eb "yurthub --v=2 --ser…" About a minute ago Up About a minute k8s_yurt-hub_yurt-hub-edge-node_kube-system_d75d122e752b90d436a71af44c0a53be_1
260057d935ee registry.cn-hangzhou.aliyuncs.com/edge-kubernetes/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_yurt-hub-edge-node_kube-system_d75d122e752b90d436a71af44c0a53be_1
从重启前后的比照看,边缘节点在断网重启之后,节点上的 pod 能失常拉起,OpenYurt 的节点自治能力能够在断网下保障业务的稳固运行。
复原网络,节点 Ready,察看业务 pod 的状态,网络复原后,业务 pod 状态放弃 running,有一次重启记录,合乎预期。
root@master-node:~# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 1 11m 192.168.0.100 edge-node <none> <none>
最初,咱们利用 yurtctl 的能力将 OpenYurt 集群,转换为原生 K8s 集群。同样,能够察看转换过程中对现有业务不会有影响。
yurtctl revert --yurtctl-servant-image=registry.cn-hangzhou.aliyuncs.com/openyurt/yurtctl-servant:v0.2.1
OpenYurt 作为阿里首个边缘云原生开源我的项目,基于商业化产品 ACK@Edge,在团体外部经验了长时间的打磨。曾经利用在 CDN、IoT、盒马、ENS、菜鸟物流等泛滥场景。针对边缘场景,该我的项目保持放弃原生 K8s 的个性,以 Addon 的模式提供了边缘节点自治、云边端一体化运维通道等能力。最近在社区同学的一起致力下又开源了边缘单元化治理能力,同时后续还会持续开源更多的边缘治理能力,欢送大家积极参与奉献。钉钉搜寻群号:31993519,即可进群交换。