Kubernetes 网络插件

庆云2年前技术文章403

Kubernetes 自身并不提供网络解决方案,允许托管使用第三方的网络解决方案。

  • flannel

  • calico

  • canel

  • kube-router

  • ......


各种 CNI 插件的解决方案:

  • 虚拟网桥(bridge)

  • 多路复用(MacVLAN)
    直接使用物理网卡,基于物理网卡中的 MacVLAN 机制进行跨节点之间通信

  • 硬件交换(SR-IOV)
    单根 IO 虚拟化,虚拟出多个网卡


虚拟网桥能实现更多的控制能力,但是网络传输中的性能开销较大。


3.1 Flannel


Flannel 是一个可以用于 Kubernetes 的 overlay 网络提供者,是一种简单易用的方式来配置专为 Kubernetes 设计的第 3 层网络结构。


Flannel 在每台主机上运行一个名为 flanneld 的小型的单个二进制代理,并负责从一个更大的预配置地址空间中为每个主机分配子网租约。Flannel 使用 Kubernetes API 或 etcd 直接存储网络配置、分配的子网和任何辅助数据(例如主机的公共 IP)。数据包使用多种后端机制之一进行转发,包括 VXLAN 和各种云集成。


网络插件能够实现辅助设置 Pod and Pod 之间是否能够互相访问的网络策略,而 Flannel 专注于网络。对于网络策略,可以使用 Calico 等其他项目。


kubernetes 加载 CNI 插件:/etc/cni/net.d/10-flannel.conflist


# 10-flannel.conflist
{
	"name": "cbr0",
	"plugins": [
		{
			"type": "flannel",
			"delegate": {
				"hairpinMode": true,
				"isDefaultGateway": true
			}
		},
		"type": "portmap",
		"capabilities": {
			"portMappings": true
		}
	]
}


Flannel 默认使用 VxLAN 的方式来作为后端网络传输机制。当然支持多种后端。


  • VxLAN

    • 原生 VxLAN

    • Directrouting

    • 节点在同一个三层网络之中使用 Host Gateway,不在同一个三层网络之中使用原生 VxLAN

  • Host Gateway
    要求各节点必须工作在同一个三层网络之中

  • UDP


Flannel 可以部署为系统守护进程, 被 kubelet 所调用,有 kubelet 存在的节点都必须部署 flannel。kubelet 存在是为了创建 Pod,Pod 需要网络,网络是由 kubelet 调用 flannel 或其他网络插件来为 Pod 的网络做设计的 。


Flannel 可以部署为普通 Pod,也可以部署为系统守护进程(共享节点网络名称空间的 Pod)


kubeadm 部署的集群,默认 flannel 托管运行在 kubernetes 集群之上。


"查看 flannel"
$ kubectl get daemonset -n kube-system | grep flannel
$ kubectl get pod -n kube-system | grep flannel

"查看 flannel 配置"
$ kubectl get configmap -n kube-system | grep flannel
$ kubectl get configmap kube-flannel-cfg -n kube-system -o json
......
Network: 10.244.0.0/16  # pod network segment
SubnetLen:              # 将Network切分子网供各节点使用时,使用多长的掩码进行切分,默认为24位
SubnetMin:              # 10.244.10.0/24
SubnetMax:              # 10.244.100.0/24
Backend:                # backend type
......


3.1.1 Directrouting


在两个 Node 节点上分别部署 Pod,分别在两个终端登陆两个 Pod 中相互 Ping。在两个 Node 节点之上做 tcpdump 抓包分析:


$ tcpdump -i cni0 -nn icmp               # 有数据: pod ip --- pod ip
$ tcpdump -i flannel.1 -nn               # 有数据: pod ip --- pod ip
$ tcpdump -i ens32 -nn host 172.20.0.67  # 有数据: node ip --- node ip


结果分析:报文 --- cni0进来 --- flannel.1(封装 VxLAN 报文)出去 --- 借助 ens32 发出去。


配置 flannel 使用 Directrouting(VxLAN)做为后端网络传输机制:


# 更改配置文件
$ kubectl edit comfigmap kube-flannel-cfg -n kube-system
......
net-conf.json |
  {
	  "Network": "10.244.0.0/16",
	  "Backend": {
		  "Type": "vxlan",
		  "Directrouting": true
	  }
  }
...... 

# 查看规则
$ ip route show
......
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink  # 看到的是:flannel(没生效)
...... 
 
# 卸载flannel,更改flannel的yaml部署文件,重新部署flannel!!!

# 查看规则
$ ip route show
......
10.244.1.0/24 via 172.20.0.70 dev ens32            # 看到的是:ens32
...... 

# 抓包分析:直接使用物理网卡通信,相当于桥接模式
$ tcpdump -i ens32 -nn icmp


3.1.2 host-gw


host-gw 要求各 Node 节点必须在同一个网段。


# 更改flannel配置文件,部署
......
net-conf.json |
  {
	  "Network": "10.244.0.0/16",
	  "Backend": {
		  "Type": "host-gw"
	  }
  }
......


3.2 Calico


官网:https://projectcalico.docs.tigera.io/about/about-calico


Github:https://github.com/projectcalico/calico


Calico 是一个开源网络和网络安全解决方案,适用于容器、虚拟机和基于本地主机的工作负载。Calico 支持广泛的平台,包括 Kubernetes、OpenShift、Mirantis Kubernetes Engine (MKE)、OpenStack 和裸机服务。


Calico 即支持地址分配,又支持网络策略。可以在实现地址转发的方式当中可以基于 BGP 协议实现二层转发。


3.2.1 NetworkPolicy


3.2.1.1 Ingress


拒绝所有:


# ingressDenyAll-devNamespace.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: dev
spec:
  podSelector: {}  # 选择namespace中所有pod
  # ingress:
  # - {}             # 定义Ingress规则,{}代表所有,允许所有入栈流量
  policyTypes:
  - Ingress        # 没有定义Ingress规则表示不允许任何人访问


$ kubectl create ns dev
$ kubectl apply -f ingressDenyAll-devNamespace.yaml
$ kubectl get NetworkPolicy -n dev
NAME               POD-SELECTOR   AGE
deny-all-ingress   <none>         47s


创建测试 Pod(dev namespace):


# pod-devNamespace.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-dev-ns
  namespace: dev
spec:
  containers:
  - name: myapp
    image: zhangyyhub/myapp:v1.0


# create pod
$ kubectl apply -f pod-devNamespace.yaml
pod/pod-dev-ns created

$ kubectl get pods -n dev -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
pod-dev-ns   1/1     Running   0          59s   10.244.235.137   worker1   <none>           <none>

# can not access
$ curl 10.244.235.137 

# create pod
$ kubectl create ns prod
namespace/prod created

$ cat pod-prodNamespace.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-prod-ns
  namespace: prod
spec:
  containers:
  - name: myapp
    image: zhangyyhub/myapp:v1.0

$ kubectl apply -f pod-prodNamespace.yaml 
pod/pod-dev-ns created

$ kubectl get pods -n prod -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
pod-prod-ns   1/1     Running   0          11s   10.244.235.254   k8s-master   <none>           <none>

"access is successful"
$ curl 10.244.235.254
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>


放行 Ingress 流量:放行 dev namespace 中入栈流量,允许访问 label app=myapp pod。


"add label"
$ kubectl label pods pod-dev-ns app=myapp -n dev
pod/pod-dev-ns labeled
$ kubectl get pods pod-dev-ns --show-labels -n dev
NAME         READY   STATUS    RESTARTS   AGE   LABELS
pod-dev-ns   1/1     Running   0          39m   app=myapp


# ingressAllowMyapp-devNamespace.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-myapp-ingress
  namespace: dev
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Ingress
  ingress:
    - from:
        - ipBlock:
            cidr: 0.0.0.0/0         # 放行
            except:
              - 172.16.107.104/32   # 排除
      ports:
        - protocol: TCP
          port: 80                  # 允许访问80端口


$ kubectl apply -f ingressAllowMyapp-devNamespace.yaml
networkpolicy.networking.k8s.io/allow-myapp-ingress created

$ kubectl get NetworkPolicy -n dev
NAME                  POD-SELECTOR   AGE
allow-myapp-ingress   app=myapp      50s
deny-all-ingress      <none>         94m

$ curl 10.244.235.137
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>


3.2.1.2 Egress


拒绝所有:


# egressDenyAll-prodNamespace.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: prod
spec:
  podSelector: {}  # 选择namespace中所有pod
  # egress:
  # - {}             # 定义egress规则,{}代表所有,允许所有流量出栈
  policyTypes:
  - Egress         # 没有定义Egress规则表示不允许任何流量出栈


$ kubectl apply -f egressDenyAll-prodNamespace.yaml
networkpolicy.networking.k8s.io/deny-all-egress created

$ kubectl get NetworkPolicy -n prod
NAME              POD-SELECTOR   AGE
deny-all-egress   <none>         49s

$ kubectl get pods -n prod         
NAME          READY   STATUS    RESTARTS   AGE
pod-prod-ns   1/1     Running   0          109m

"拒绝所有出栈流量"
$ kubectl exec -it pod-prod-ns -n prod -- /bin/sh
/ # ping www.baidu.com
ping: bad address 'www.baidu.com'


相关文章

磁盘分盘脚本分享

磁盘分区脚本名称:mg_fdisk.sh#!/bin/bashif [ "$#" -ne 1 ]; then  echo "请传入磁盘参数"  exit 1fidisk=$1# 检查磁盘是否存在if...

nginx分发算法

nginx分发算法

一、分发算法介绍如何将用户请求按照一定的规律分发给业务服务器。主要分为Nginx集群默认算法和基于请求头分发算法。二、nginx集群默认算法nginx的upstream 目前支持4种方式的分配轮询(默...

Kubernetes源码解读(二)--DeltaFIFO源码分析

Kubernetes源码解读(二)--DeltaFIFO源码分析

1、Queue接口与DeltaFIFO的实现1.1、Queue和Store接口接口和结构体先相关代码类似 workqueue 里的队列概念,这里也有一个队列,Queue 接口定义在 client-go...

oracle安装gi执行root.sh报错:PRCR-1079 : Failed to start resource ora.cvu

1、具体报错如下:安装gi执行root.sh报错:PRCC-1014 : LISTENER_SCAN1 was already runningPRCR-1004 : Resource ora.LIST...

 Ranger-hive插件部署

Ranger-hive插件部署

解压插件tar -zxf ranger-metastore-plugin.tar.gz -C /opt修改配置vim /opt/ranger-metastore-plugin/install.prop...

CDP实操--动态启停服务

以yarn nodemanager 为例获取role yarn nodemanager:curl -u admin:admin 'http://172.16.106.151:7180/api/v1/c...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。