OCP4.6目前已经发布。在这个版本OCP中,正式支持OVN-Kubernets。大魏认为这是一个重大进步和提升。进步和提升在哪?灵魂拷问x5一下。
拷问1:OVN-Kubernets对于OCP是否正式可用,优势在哪?
可用!
OpenShift 4.6默认支持两种网络模式:OpenShift SDN和OVN-Kubernetes。下表总结了两种模式当前功能支持:
上图中OVN不支持的egress router的功能,本身在OCP4中也基本不用了。所以说,OVN可以覆盖生产上对OpenShift SDN方面的需求。
关于优势,先说结论:
1. OCP4.6上的OVN-Kubernetes 可以完全替代原有的OpenShift-SDN。
2.OVN-K8S可以设置通过GENEVE实现overlay而不是VxLAN的方式,这样大幅提升了封包解包效率。
3. OVN中的Service实现,不再需要Iptables,而是使用OVN LBs,效率提升。
4.OVN中的NAT,不需要通过Iptables实现,通过OVN LBs实现,效率提升。
拷问2:OVN究竟咋来的。
OVN(即Open Virtual Network)是一款支持虚拟网络抽象的软件系统。OVN在OVS现有功能的基础上原生支持虚拟网络抽象,例如虚拟L2,L3覆盖网络以及完全组。诸如DHCP,DNS的服务也是其关注的内容。说简单点,OVN为OVS提供了一个控制平面:
相比于在OCP上,OVN较早在OpenStack上使用。OVN也是红帽绝对主导的一个开源项目。
OpenStack不是大魏的专攻领域,不展开讨论。
需要注意的是,ovn 跟 openstack 没有必然联系,这俩货没有紧耦合,ovn 跟 openstack 也是通过 plugin/driver 的方式集成在一起的。
拷问3:如何在OCP上使用OVN-Kubernetes ?
两个方法:
1.安装OCP的时候,在install.yaml文件中写明
2.OCP安装后,修改network operator
安装OCP的时候,在install.yaml中增加进行配置:
defaultNetwork:
type: OVNKubernetes
ovnKubernetesConfig:
mtu: 1400
genevePort: 6081
如果OCP已经安装完,请用如下步骤将OpenShift-SDN更换成OVN-Kubernetes(大魏已验证步骤,准确可用):
首先备份现有OVS的配置,输入以下命令:
[root@lb.weixinyucluster ~]# oc get Network.config.openshift.io cluster -o yaml > cluster-openshift-sdn.yaml
启用迁移,通过如下命令修改Cluster Network Operator 配置对象上设置注释:
[root@lb.weixinyucluster ~]# oc annotate Network.operator.openshift.io cluster \
> 'networkoperator.openshift.io/network-migration'=""
network.operator.openshift.io/cluster annotated
更改默认的CNI网络提供商,输入以下命令:
[root@lb.weixinyucluster ~]# oc patch Network.config.openshift.io cluster \
> --type='merge' --patch '{ "spec": { "networkType": "OVNKubernetes" } }'
network.config.openshift.io/cluster patched
要确认迁移已禁用OpenShift SDN默认的CNI网络提供程序并删除了所有OpenShift SDN Pod,openshift-sdn中的pod会自动删除:
[root@lb.weixinyucluster ~]# oc get pod -n openshift-sdn
No resources found in openshift-sdn namespace.
集群中的节点重新引导后,请确认迁移成功,如下命令行输出必须为OVNKubernetes:
[root@lb.weixinyucluster ~]# oc get network.config/cluster -o jsonpath='{.status.networkType}{"\n"}'
OVNKubernetes
确认没有error状态的pod:
[root@lb.weixinyucluster ~]# oc get pods --all-namespaces -o wide --sort-by='{.spec.nodeName}' |grep -i error
从“Cluster Network Operator”配置对象中删除迁移注释,输入以下命令:
[root@lb.weixinyucluster ~]# oc annotate Network.operator.openshift.io cluster \
> networkoperator.openshift.io/network-migration-
network.operator.openshift.io/cluster annotated
删除openshift-sdn ns:
oc delete namespace openshift-sdn
查看OVN组件:
拷问4:GENEVE实现overlay而不是VxLAN的方式,有啥好处?怎么设置GENEVE模式?
首先说,OVN同时支持VxLAN和GENEVE的overlay实现方式。如果想讲OCP设置成GENEVE模式,需要在安装时进行设置(参加拷问3步骤),安装以后,就没法修改了。
Geneve(Generic Network Virtualization Encapsulation,RFC Draft)是NVo3工作组对VxLAN、NvGRE和STT进行总结后提出的一种网络虚拟化技术,希望形成一种通用的封装格式,以便支持数据中心中隧道机制的后续演化。Geneve是于2015年提出的,很多的vSwitch已经对Geneve提供了支持,一些SmartNIC也能够实现Geneve的硬件卸载。
对于Overlay技术,我们最关心的是性能,那么Geneve和VxLAN性能谁高谁低?如果单纯比较Geneve和VxLAN的性能,那和网卡是否支持对这两种技术的offload有关:
某些offload功能实际上并不是VXLAN特有的。例如,通常所说的“ tx-udp_tnl-segmentation”offload同事适用于VXLAN和Geneve。
可以使用ethtool查看NIC是否支持“ tx-udp_tnl-segmentation”。例如,在不支持的主机上:
[root@lb.weixinyucluster ~]# ethtool -k eth0 | grep tnl-segmentation
tx-udp_tnl-segmentation: off [fixed]
关于两者的性能对比,可以参照下文:
https://blog.russellbryant.net/2017/05/30/ovn-geneve-vs-vxlan-does-it-matter/
大魏抽几个图出来,整体上看:Geneve的网络性能高于VxLAN。
结合OVN,我们建议使用Geneve而不是VxLAN。
拷问5:为啥说OVN中的Service实现,不再需要Iptables,而是使用OVN LBs,怎么证明?
本质上说,OCP/K8S中的Iptables,是被kube-proxy引入的!
Kube-proxy,即Kubernetes network proxy。Kube-proxy部署在每个Node节点上,它是实现KubernetesService的通信与负载均衡机制的重要组件; Kube-proxy负责为Pod创建代理服务,从kube-apiserver获取所有Service信息,并根据Service信息创建代理服务,实现Service到Pod的请求路由和转发,从而实现Kubernetes层级的虚拟转发网络。
也就是说,如果用了OVN下图中用红圈圈起来这一坨,就不存在了,换成OVN实现了(ovn不用安装kube-proxy,也就不用再讨论使用用ipvs替换iptables实现svc的问题了!)。
我们分析一下kube-proxy在OpenShift-SDN什么位置:
那么,OCP节点上的kube-proxy是以什么方式运行的呢?
直接从oc get pods --all-namespaces 是grep不出来的。
登录到master节点:
[root@master-0 ~]# ps -ef |grep -i kube-proxy
root 3412213 3412200 0 Jul06 ? 00:04:26 /usr/bin/openshift-sdn-node --proxy-config=/config/kube-proxy-config.yaml --v=2
查到以kube-proxy最终以openshift-sdn-node二进制文件+yaml配置文件实现。但这还不是运行时。
而openshift-sdn-node这个进程,是由名为kubepods-burstable.slice控制的:
[root@master-0 ~]# systemctl status kubepods-burstable.slice |grep -i kube-proxy-config.yaml
│ │ └─3412213 /usr/bin/openshift-sdn-node --proxy-config=/config/kube-proxy-config.yaml --v=2
我们通过systemctl命令查看到这个进程对用的pod和crio如下(后者是container id):
├─kubepods-burstable-pod18c8ff9b_22dc_4cba_8b5a_e81dd4782734.slice
│ ├─crio-143c9806ad2791bb4170c53566ca6bedb99d0efbc53cc98391cac0e82115ee82.scope
│ │ └─3412213 /usr/bin/openshift-sdn-node --proxy-config=/config/kube-proxy-config.yaml --v=2
而kubepods-burstable.slice又是kubepods.slice这个systemd的一部分:
[root@master-0 ~]# systemctl status kubepods.slice |grep -i kubepods-burstable.slice
└─kubepods-burstable.slice
在系统层面通过查看执行二进制文件进程的父进程,也能找到container id:
[root@master-0 ~]# ps -ef |grep -i 3412200
root 2190284 2186215 0 05:56 pts/1 00:00:00 grep --color=auto -i 3412200
root 3412200 1 0 Jul06 ? 00:00:01 /usr/libexec/crio/conmon -s -c 143c9806ad2791bb4170c53566ca6bedb99d0efbc53cc98391cac0e82115ee82 -n k8s_sdn_sdn-9tw2h_openshift-sdn_18c8ff9b-22dc-4cba-8b5a-e81dd4782734_1 -u 143c9806ad2791bb4170c53566ca6bedb99d0efbc53cc98391cac0e82115ee82 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/143c9806ad2791bb4170c53566ca6bedb99d0efbc53cc98391cac0e82115ee82/userdata --persist-dir /var/lib/containers/storage/overlay-containers/143c9806ad2791bb4170c53566ca6bedb99d0efbc53cc98391cac0e82115ee82/userdata -
通过 crictl查看container与pod的对应关系(取container名称的前几位)
[root@master-0 ~]# crictl ps - List containers |grep -i 143c9806ad279
143c9806ad279 04783aad75c195935333357d0bd9fdb9341e51e48fee2c520d5871ee6cd47c8c 26 hours ago Running sdn 1 ace4388462740
也就是说,每个OpenShift节点的kube-proxy,通过sdn pod运行在各自的节点上。
我们查看一个sdn pod的日志,这正好印证了上面推断的正确性(标黄部分),sdn二进制文件读取/config/kube-proxy-config.yaml在节点启动kube-proxy。
[root@lb.weixinyucluster ~]# oc logs -f sdn-rtwdr
I0706 04:17:47.444754 3209083 cmd.go:123] Reading proxy configuration from /config/kube-proxy-config.yaml
I0706 04:17:47.448591 3209083 feature_gate.go:243] feature gates: &{map[]}
I0706 04:17:47.448712 3209083 cmd.go:227] Watching config file /config/kube-proxy-config.yaml for changes
I0706 04:17:47.448789 3209083 cmd.go:227] Watching config file /config/..2020_07_06_04_17_45.051553485/kube-proxy-config.yaml for changes
I0706 04:17:47.538621 3209083 node.go:147] Initializing SDN node of type "redhat/openshift-ovs-networkpolicy" with configured hostname "worker-1" (IP "192.168.91.21")
、
我们将OpenShift-SDN换成OVN以后,sdn pod就都被删除了。OVN的在OCP上的具体实现如下:
查看OVN组件:
我从上图看出,OVN结构分为三部分:ovnkube-master(运行在三个master上)、ovnkube-node(运行在所有OCP节点上)、ovs-node(运行在所有OCP节点上)。OVN的组件是以daemonset.apps的方式部署的:
我们对比OVN的架构图:
我们查看ovnkube-master pod(运行在3个master上)包含的容器,我们看一下,这几个容器,不正是上图的CMD相关组件么?
我们查看ovnkube-node(运行在所有OCP节点上)包含的容器,对应OVN架构图中的ovn controller(下图kube-rbac-proxy是个权限的proxy,不是我们之前的kube-proxy实现。。):
ovs-node(运行在所有OCP节点上),实际上对用ovs的实现:
回到拷问题目,我怎么知道OCP现在用的是OVN LB?好办,通过命令行就能看到:
登录ovnkube-node pod的ovn-controller容器,执行(结果太长太长,只列一部分,我我们可以看到所有OCP节点的域名、和所有pod的IP、应用的路由等信息!):
ovn-nbctl list load-balancer
switch e751ee40-d944-435c-a541-e4b378a404fc (ext_worker-2.weixinyucluster.bluecat.ltd)
port etor-GR_worker-2.weixinyucluster.bluecat.ltd
type: router
addresses: ["52:54:17:8a:f3:00"]
router-port: rtoe-GR_worker-2.weixinyucluster.bluecat.ltd
port br-ex_worker-2.weixinyucluster.bluecat.ltd
type: localnet
addresses: ["unknown"]
switch 7acf5030-9cbe-4b52-97c9-2e9ad9231ed5 (worker-2.weixinyucluster.bluecat.ltd)
port openshift-marketplace_certified-operators-766bcd6f65-6mjvz
addresses: ["0a:58:0a:82:02:07 10.130.2.7"]
port openshift-marketplace_community-operators-7c895d7b67-crzb4
addresses: ["0a:58:0a:82:02:09 10.130.2.9"]
port openshift-monitoring_grafana-5d7b5b575b-qwch2
addresses: ["0a:58:0a:82:02:0c 10.130.2.12"]
port k8s-worker-2.weixinyucluster.bluecat.ltd
addresses: ["a6:69:cf:72:11:13 10.130.2.2"]
port openshift-monitoring_thanos-querier-79d844d9fd-46c77
addresses: ["0a:58:0a:82:02:0a 10.130.2.10"]
port openshift-operators_istio-operator-6cfc889cf-p2pgw
addresses: ["0a:58:0a:82:02:0d 10.130.2.13"]