OVN on Kubernetes

1.Kubernetes的CNI

Kubernetes的CNI有很多实现,诸如Flannel,calico,Canal,Weave等,各有优势。比如Flannel功能简单,不支持网络策略,但是性能稳定。Calico功能全面,性能(理论)高,支持灵活的网络策略,但灵活的另一面就是复杂。下面主要介绍下kubernetes网络的另一种实现OVN。

2.什么是OVN

OVN(Open Virtual Network)是OpenvSwitch项目组为OpenvSwitch开发SDN控制器。OVS可以无缝迁移到OVN。

OVN的组成

  • CMS(云管理系统):负责元数据(逻辑网络配置数据)的输入
  • OVN数据库:负责存储配置数据
  • 虚拟机管理程序(hypervisors)
  • 网关

OVN的架构

ovn.png

OVN的流程和组件职责

CMS书逻辑配置的输入端,plugin 将来源的数据信息转化并存储到NorthboundDB(格式信息logical switch,logical router,logical port和ACL),ovn-northd监听NorthboundDB的变化,并将数据在此转化存储到Southbound DB,其数据包括物理网络数据,逻辑网络数据以及物理网络和逻辑网络的绑定关系数据。

ovn-controller通过连接ovsdb-server ,监控、读取、管理OpenvSwitch的配置信息,将本机的物理网络数据上报给Southbound DB。

ovsdb-server保存了整个OVS的配置信息(包括接口,流表和VLAN)的数据库

3.OVN在kubernetes上的实现

OVN 替代了什么

原有的CNI插件,kube-proxy,iptables

#不需要
--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin \

OVN 的优势

可以实现定义的网络规则,实在kubernetes和Openstack等互通,减少其他组建的以来,支持更大的规模

OVN 的部署方式

  • kubernetes的安装

  • OVS编译安装

[root@node1 soft]# wget https://www.openvswitch.org/releases/openvswitch-2.5.8.tar.gz
[root@node1 soft]#  mkdir - p  $HOME/rpmbuild/SOURCES
[root@node1 soft]#  cp openvswitch-2.5.8.tar.gz $HOME/rpmbuild/SOURCES
[root@node1 soft]#  cd  $HOME/rpmbuild/SOURCES
[root@node1 SOURCES]#  tar xzf openvswitch-2.5.8.tar.gz 
[root@node1 SOURCES]# cd openvswitch-2.5.8
[root@node1 SOURCES]# yum install -y rpm-build 
[root@node1 SOURCES]# rpmbuild -bb rhel/openvswitch.spec
[root@node1 soft]# rpm -ivh openvswitch-2.5.8-1.x86_64.rpm
  • OVN的安装
    到https://github.com/ovn-org/ovn-kubernetes下载dist文件即可
#该步骤主要是根据你的配置和 /dist/templates 下的模板文件生成部署文件
#有乱码问题请执行: sed -i "s/\r//" daemonset.sh
[root@node1 images]# ./daemonset.sh --image=ovnkube/ovn-daemonset-u:latest \
--net-cidr=10.1.0.0/16 --svc-cidr=172.16.1.0/24      \
--gateway-mode="local"    \
--k8s-apiserver=https://192.168.56.104:6443
image: ovnkube/ovn-daemonset-u:latest
imagePullPolicy: IfNotPresent
ovn_gateway_mode: local
ovn_gateway_opts: 
ovn_db_vip_image: docker.io/ovnkube/ovndb-vip-u:latest
ovn_db_replicas: 3
ovn_db_vip: 
net_cidr: 10.1.0.0/16
svc_cidr: 172.16.1.0/24
k8s_apiserver: https://192.168.56.104:6443
#生成的文件位于/dist/yaml下
[root@node1 dist]# ll yaml/
total 44
-rw-r--r-- 1 root root  4367 Jul 31 21:15 ovnkube-db-vip.yaml
-rw-r--r-- 1 root root  5147 Jul 31 21:15 ovnkube-db.yaml
-rw-r--r-- 1 root root  9104 Jul 31 21:15 ovnkube-master.yaml
-rw-r--r-- 1 root root 10936 Jul 31 21:15 ovnkube-node.yaml
-rw-r--r-- 1 root root  2612 Jul 31 21:15 ovn-setup.yaml

各个文件说明如下
#ovnkube/ovn-daemonset-u:latest镜像中包含DB,northd,master以及node节点的ovsdb-server,ovs-switchd和ovn-controller
ovn-setup.yaml        : 为ovn在kubernetes中创建namespace, service accounts, ovnkube-db headless service, configmap, and policies,其中ConfigMap中包含初始化时指定的 cidr信息和apiserver信息。
ovnkube-db.yaml       :包含OVN中用于存储网络配置信息的北向DB(对应架构中NorthboundDB)和南向DB(对应架构中Southbound DB),两个DB位于一个POD但独立于两个容器,以Deployment方式运行
ovnkube-db-vip.yaml   :和ovnkube-db.yaml 是同一个只是增加VIP,做集群
ovnkube-master.yaml   :对应架构中的ovn-northd,以及ovnkube-master,以Deployment方式运行
ovnkube-node.yaml     :对应OVN架构中的ovsdb-server,ovs-switchd和ovn-controller,以DaemonSet方式运行于所有node几点
开始部署(环境有限以最简部署为主)
#1.namespace等资源创建
[root@node1 dist]# kubectl create -f yaml/ovn-setup.yaml 
namespace/ovn-kubernetes created
serviceaccount/ovn created
clusterrole.rbac.authorization.k8s.io/system:ovn-reader created
clusterrolebinding.rbac.authorization.k8s.io/ovn-reader created
clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-0 created
service/ovnkube-db created
configmap/ovn-config created
#2.ovn-db部署
[root@node1 dist]# kubectl create -f yaml/ovnkube-db.yaml              
deployment.apps/ovnkube-db created
[root@node1 dist]# kubectl get pod -n ovn-kubernetes
NAME                          READY   STATUS    RESTARTS   AGE
ovnkube-db-56cc76545d-hbtlk   0/2     Pending   0          50s
#查看运行状况,没有对应标签
[root@node1 dist]# kubectl  -n ovn-kubernetes describe pod ovnkube-db-56cc76545d-hbtlk
Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  68s (x2 over 68s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match node selector.
#开始打标签,具体需要的表到yaml中查看
[root@node1 ~]# kubectl get node
NAME    STATUS   ROLES    AGE    VERSION
node1   Ready       138m   v1.15.1
node2   Ready       123m   v1.15.1
[root@node1 ~]# kubectl label node node1 node-role.kubernetes.io/master="" 
node/node1 labeled
[root@node1 ~]# kubectl describe node node1
Name:               node1
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node1
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
.....
#再次部署DB(内部有ovn中有不少问题,见后面QA)
[root@node1 yaml]# kubectl create -f ovnkube-db.yaml
[root@node1 yaml]# kubectl  -n ovn-kubernetes get pod
NAME                          READY   STATUS    RESTARTS   AGE
ovnkube-db-79f656485c-dkr87   2/2     Running   0          54s
#部署Master
[root@node1 yaml]# kubectl create -f ovnkube-master.yaml
[root@node1 yaml]# kubectl  -n ovn-kubernetes get pod
NAME                              READY   STATUS    RESTARTS   AGE
ovnkube-db-79f656485c-dkr87       2/2     Running   0          5m49s
ovnkube-master-7b4bb48cd5-rgl95   2/2     Running   0          19s
#部署Node
[root@node1 yaml]# kubectl create -f ovnkube-node.yaml 
[root@node1 ~]# kubectl -n ovn-kubernetes get pod 
NAME                              READY   STATUS             RESTARTS   AGE
ovnkube-db-79f656485c-dkr87       2/2     Running            2          2d5h
ovnkube-master-7b4bb48cd5-rgl95   2/2     Running            15         2d5h
ovnkube-node-lsrwz                2/3     Running            2          12h
ovnkube-node-zv276                3/3     Running            2          12h

节点网络分配 TODO

QA

Q : Failed create pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for pod "ovnkube-db-56cc76545d-j8jgb": Error response from daemon: OCI runtime create failed: systemd cgroup flag passed, but systemd support for managing cgroups is not available: unknown

A  : 由于之前cgroup-driver采用的systemd,此处问题是不支持systemd引起的, 
       修改docker中daemon.json
        {
          "exec-opts": ["native.cgroupdriver=systemd"]
        }
       以及kubelet中的--cgroup-driver=cgroupfs 

Q : error: error validating "STDIN": error validating data: ValidationError(Endpoints.subsets[0].addresses[0]): missing required field "ip" in io.k8s.api.core.v1.EndpointAddress; if you choose to ignore these errors, turn validation off with --validate=false
Failed to create endpoint with host for ovnkube-db service

A  : 原因是ovnkube.sh中 获取主机IP失败导致,修改源码编译
      ovn_db_host=$(getent ahosts $(hostname) | head -1 | awk '{ print $1 }')

Q : Interface table in Open_vSwitch database lacks mtu_request column

A  :   
#查看日志 ,显示表Interface 中没有字段mtu_request
[root@node1 ~]# cat /var/log/ovn-kubernetes/ovnkube.log
time="2019-08-02T12:25:52Z" level=debug msg="exec(4): /usr/bin/ovs-vsctl --timeout=15 -- --may-exist add-port br-int k8s-node1 -- set interface k8s-node1 type=internal mtu_request=1400 external-ids:iface-id=k8s-node1"
time="2019-08-02T12:25:52Z" level=debug msg="exec(4): stdout: \"\""
time="2019-08-02T12:25:52Z" level=debug msg="exec(4): stderr: \"2019-08-02T12:25:52Z|00002|ovsdb_idl|WARN|Interface table in Open_vSwitch database lacks mtu_request column (database needs upgrade?)\\n2019-08-02T12:25:52Z|00003|ovsdb_idl|WARN|Interface table in Open_vSwitch database lacks mtu_request column (database needs upgrade?)\\n2019-08-02T12:25:52Z|00004|ovsdb_idl|WARN|transaction error: {\\\"details\\\":\\\"No column mtu_request in table Interface.\\\",\\\"error\\\":\\\"unknown column\\\",\\\"syntax\\\":\\\"{\\\\\\\"external_ids\\\\\\\":[\\\\\\\"map\\\\\\\",[[\\\\\\\"iface-id\\\\\\\",\\\\\\\"k8s-node1\\\\\\\"]]],\\\\\\\"mtu_request\\\\\\\":1400,\\\\\\\"name\\\\\\\":\\\\\\\"k8s-node1\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"internal\\\\\\\"}\\\"}\\novs-vsctl: transaction error: {\\\"details\\\":\\\"No column mtu_request in table Interface.\\\",\\\"error\\\":\\\"unknown column\\\",\\\"syntax\\\":\\\"{\\\\\\\"external_ids\\\\\\\":[\\\\\\\"map\\\\\\\",[[\\\\\\\"iface-id\\\\\\\",\\\\\\\"k8s-node1\\\\\\\"]]],\\\\\\\"mtu_request\\\\\\\":1400,\\\\\\\"name\\\\\\\":\\\\\\\"k8s-node1\\\\\\\",\\\\\\\"type\\\\\\\":\\\\\\\"internal\\\\\\\"}\\\"}\\n\""
# 表字段查看
[root@node1 ~]# ovs-vsctl list  interface
_uuid               : ceea4af1-bcad-416d-91f1-4bf1a7e36b8a
admin_state         : down
bfd                 : {}
bfd_status          : {}
cfm_fault           : []
cfm_fault_status    : []
cfm_flap_count      : []
cfm_health          : []
cfm_mpid            : []
cfm_remote_mpids    : []
cfm_remote_opstate  : []
duplex              : []
error               : []
external_ids        : {}
ifindex             : 18
ingress_policing_burst: 0
ingress_policing_rate: 0
lacp_current        : []
link_resets         : 0
link_speed          : []
link_state          : down
lldp                : {}
mac                 : []
mac_in_use          : "82:62:bb:12:16:4f"
mtu                 : 1400 //名称不是mtu_request,或者已改名
name                : br-int
ofport              : 65534
ofport_request      : []
options             : {}
other_config        : {}
#查看源代码中的标志位是mtu_request,原因可能是OVS和OVN版本不匹配
[root@node1 addon]# vim management-port.go
229         stdout, stderr, err = util.RunOVSVsctl("--", "--may-exist", "add-port",
230                 "br-int", interfaceName, "--", "set", "interface", interfaceName,
231                 "type=internal", "mtu_request="+fmt.Sprintf("%d", config.Default.MTU),
232                 "external-ids:iface-id=k8s-"+nodeName)

你可能感兴趣的:(OVN on Kubernetes)