Day10-kubernetes资源限制、多账户控制、网络实现方式
20211031作业:
1.kubernetes pod、container与namespace资源限制
1.1.kubernetes中资源限制概括
CPU 以核心为单位;
memory 以字节为单位;
requests 为kubernetes scheduler执行pod调度时node节点至少需要拥有的资源;
limits 为pod运行成功后最多可以使用的资源上限;
1.2.kubernetes对单个容器的CPU及memory实现资源限制
官方文档https://kubernetes.io/zh/docs/tasks/configure-pod-container/assign-memory-resource/
case1-pod-memory-limit.yml
#apiVersion: extensions/v1beta1 apiVersion: apps/v1 kind: Deployment metadata: name: limit-test-deployment namespace: magedu spec: replicas: 1 selector: matchLabels: #rs or deployment app: limit-test-pod # matchExpressions: # - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]} template: metadata: labels: app: limit-test-pod spec: containers: - name: limit-test-container image: lorel/docker-stress-ng resources: limits: memory: "200Mi" cpu: 200m requests: memory: "100Mi" #command: ["stress"] args: ["--vm", "2", "--vm-bytes", "256M"] #nodeSelector: # env: group1
case2-pod-memory-and-cpu-limit.yml
#apiVersion: extensions/v1beta1 apiVersion: apps/v1 kind: Deployment metadata: name: limit-test-deployment namespace: magedu spec: replicas: 1 selector: matchLabels: #rs or deployment app: limit-test-pod # matchExpressions: # - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]} template: metadata: labels: app: limit-test-pod spec: containers: - name: limit-test-container image: lorel/docker-stress-ng resources: limits: cpu: "1.2" memory: "512Mi" requests: memory: "100Mi" cpu: "500m" #command: ["stress"] args: ["--vm", "2", "--vm-bytes", "256M"] #nodeSelector: # env: group1
1.3.kubernetes对单个pod的CPU及memory实现资源限制
Limit Range是对具体某个Pod或容器的资源使用进行限制
官方资料https://kubernetes.io/zh/docs/concepts/policy/limit-range/
- 限制namespace中每个Pod或容器的最小与最大计算资源
- 限制namespace中每个Pod或容器计算资源request、limit之间的比例
- 限制namespace中每个存储卷声明(PersistentVolumeClaim)可使用的最小与最大存储空间
- 设置namespace中容器默认计算资源的request、limit,并在运行时自动注入到容器中
case3-LimitRange.yaml
apiVersion: v1 kind: LimitRange metadata: name: limitrange-magedu namespace: magedu spec: limits: - type: Container #限制的资源类型 max: cpu: "2" #限制单个容器的最大CPU memory: "2Gi" #限制单个容器的最大内存 min: cpu: "500m" #限制单个容器的最小CPU memory: "512Mi" #限制单个容器的最小内存 default: cpu: "500m" #默认单个容器的CPU限制 memory: "512Mi" #默认单个容器的内存限制 defaultRequest: cpu: "500m" #默认单个容器的CPU创建请求 memory: "512Mi" #默认单个容器的内存创建请求 maxLimitRequestRatio: cpu: 2 #限制CPU limit/request比值最大为2 memory: 2 #限制内存limit/request比值最大为1.5 - type: Pod max: cpu: "4" #限制单个Pod的最大CPU memory: "4Gi" #限制单个Pod最大内存 - type: PersistentVolumeClaim max: storage: 50Gi #限制PVC最大的requests.storage min: storage: 30Gi #限制PVC最小的requests.storage
case4-pod-RequestRatio-limit.yaml
kind: Deployment apiVersion: apps/v1 metadata: labels: app: magedu-wordpress-deployment-label name: magedu-wordpress-deployment namespace: magedu spec: replicas: 1 selector: matchLabels: app: magedu-wordpress-selector template: metadata: labels: app: magedu-wordpress-selector spec: containers: - name: magedu-wordpress-nginx-container image: nginx:1.16.1 imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: cpu: 2 memory: 3Gi requests: cpu: 2 memory: 1.5Gi - name: magedu-wordpress-php-container image: php:5.6-fpm-alpine imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: cpu: 1 #cpu: 2 memory: 1Gi requests: cpu: 500m memory: 512Mi --- kind: Service apiVersion: v1 metadata: labels: app: magedu-wordpress-service-label name: magedu-wordpress-service namespace: magedu spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: 8080 nodePort: 30063 selector: app: magedu-wordpress-selector
case5-pod-cpu-limit.yaml
kind: Deployment apiVersion: apps/v1 metadata: labels: app: magedu-wordpress-deployment-label name: magedu-wordpress-deployment namespace: magedu spec: replicas: 1 selector: matchLabels: app: magedu-wordpress-selector template: metadata: labels: app: magedu-wordpress-selector spec: containers: - name: magedu-wordpress-nginx-container image: nginx:1.16.1 imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: cpu: 1 memory: 1Gi requests: cpu: 500m memory: 512Mi - name: magedu-wordpress-php-container image: php:5.6-fpm-alpine imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: #cpu: 2.8 cpu: 2 memory: 1Gi requests: cpu: 1.5 memory: 512Mi --- kind: Service apiVersion: v1 metadata: labels: app: magedu-wordpress-service-label name: magedu-wordpress-service namespace: magedu spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: 8080 nodePort: 30033 selector: app: magedu-wordpress-selector
ff
1.4.kubernetes对整个namespace的CPU及memory实现资源限制
kubernetes对整个namespace的CPU及memory实现资源限制
官方资料https://kubernetes.io/zh/docs/concepts/policy/resource-quotas/
- 限定某个对象类型(如Pod、service)可创建对象的总数;
- 限定某个对象类型可消耗的计算资源(CPU、内存)与存储资源(存储卷声明)总数
case3-LimitRange.yaml
apiVersion: v1 kind: LimitRange metadata: name: limitrange-magedu namespace: magedu spec: limits: - type: Container #限制的资源类型 max: cpu: "2" #限制单个容器的最大CPU memory: "2Gi" #限制单个容器的最大内存 min: cpu: "500m" #限制单个容器的最小CPU memory: "512Mi" #限制单个容器的最小内存 default: cpu: "500m" #默认单个容器的CPU限制 memory: "512Mi" #默认单个容器的内存限制 defaultRequest: cpu: "500m" #默认单个容器的CPU创建请求 memory: "512Mi" #默认单个容器的内存创建请求 maxLimitRequestRatio: cpu: 2 #限制CPU limit/request比值最大为2 memory: 2 #限制内存limit/request比值最大为1.5 - type: Pod max: cpu: "4" #限制单个Pod的最大CPU memory: "4Gi" #限制单个Pod最大内存 - type: PersistentVolumeClaim max: storage: 50Gi #限制PVC最大的requests.storage min: storage: 30Gi #限制PVC最小的requests.storage
case6-ResourceQuota-magedu.yaml
apiVersion: v1 kind: ResourceQuota metadata: name: quota-magedu namespace: magedu spec: hard: requests.cpu: "46" limits.cpu: "46" requests.memory: 120Gi limits.memory: 120Gi requests.nvidia.com/gpu: 4 pods: "20" services: "20"
case7-namespace-pod-limit-test.yaml
kind: Deployment apiVersion: apps/v1 metadata: labels: app: magedu-nginx-deployment-label name: magedu-nginx-deployment namespace: magedu spec: replicas: 5 selector: matchLabels: app: magedu-nginx-selector template: metadata: labels: app: magedu-nginx-selector spec: containers: - name: magedu-nginx-container image: nginx:1.16.1 imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: cpu: 1 memory: 1Gi requests: cpu: 500m memory: 512Mi --- kind: Service apiVersion: v1 metadata: labels: app: magedu-nginx-service-label name: magedu-nginx-service namespace: magedu spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: 80 #nodePort: 30033 selector: app: magedu-nginx-selector
case8-namespace-cpu-limit-test.yaml
kind: Deployment apiVersion: apps/v1 metadata: labels: app: magedu-nginx-deployment-label name: magedu-nginx-deployment namespace: magedu spec: replicas: 2 selector: matchLabels: app: magedu-nginx-selector template: metadata: labels: app: magedu-nginx-selector spec: containers: - name: magedu-nginx-container image: nginx:1.16.1 imagePullPolicy: Always ports: - containerPort: 80 protocol: TCP name: http env: - name: "password" value: "123456" - name: "age" value: "18" resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 512Mi --- kind: Service apiVersion: v1 metadata: labels: app: magedu-nginx-service-label name: magedu-nginx-service namespace: magedu spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: 80 nodePort: 50033 selector: app: magedu-nginx-selector
ff
2.kubernetes 多账户实现案例
ff
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/ #使用RBAC鉴权 RBAC是基于角色的访问控制(Role-Based Access Control) https://kubernetes.io/zh/docs/reference/access-authn-authz/authorization/ #鉴权概述 1.1:在指定namespace创建账户: # kubectl create serviceaccount magedu -n magedu serviceaccount/magedu created 1.2:创建role规则: # kubectl apply -f magedu-role.yaml role.rbac.authorization.k8s.io/magedu-role created # cat magedu-role.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: magedu name: magedu-role rules: - apiGroups: ["*"] resources: ["pods","pods/exec"] verbs: ["*"] ##RO-Role #verbs: ["get", "watch", "list"] - apiGroups: ["extensions", "apps/v1"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] ##RO-Role #verbs: ["get", "watch", "list"] 1.3:将规则与账户进行绑定: # kubectl apply -f magedu-role-bind.yaml rolebinding.rbac.authorization.k8s.io/role-bind-magedu created # cat magedu-role-bind.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: role-bind-magedu namespace: magedu subjects: - kind: ServiceAccount name: magedu namespace: magedu roleRef: kind: Role name: magedu-role apiGroup: rbac.authorization.k8s.io 1.4:获取token名称: # kubectl get secret -n magedu | grep magedu magedu-token-8d897 kubernetes.io/service-account-token 3 5m45s 1.5:使用base加密: # kubectl get secret magedu-token-8d897 -o jsonpath={.data.token} -n magedu |base64 -d eyJhbGciOiJSUzI1NiIsImtpZCI6IlYwMDNHdWJwTmtoaTJUMFRPTVlwV3RiVWFWczJYRHJCNkFkMGRtQWFqRTgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtYWdlZHUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoibWFnZWR1LXRva2VuLThkODk3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Im1hZ2VkdSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBlZmNiNGI0LWM3YTUtNGJkZS1iZjk4LTFiNTkwNThjOTFjNiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptYWdlZHU6bWFnZWR1In0.SJHLgshKcGtIf-ycivn_4SWVRdWw4SuWymBVaA8YJXHPd5PYnwERVNtfUPX88nv-wXkCuZY7fIjGYkoYj6AJEhSPoG15fcmUPaojYeyjkQYghan3CBsZR8C12buSB6t5zCCt22GdG_ScZymxLU7n3Z0PhOzTLzgpXRs1Poqz4DOYylqZyLmW_BPgoNhtQYKlBH6OFzDe8v3JytnaaJUObVZCRxtI6x4iKLt2Evhs8XKfczqqesgoo61qTqtbU4jzlXuHeW7cUMhWoipUc-BkEdV6OtKWOetecxu5uB-44eTRHa1FBjnRMv9SEGj0hxTJCQ08ZNlP0Kc01JZlKXBGdQroot@k8s-master1:~/role/magedu-RBAC# 1.6:登录dashboard测试: pods "magedu-tomcat-app1-deployment-798fc69b75-rc7l5" is forbidden: User "system:serviceaccount:magedu:magedu" cannot create resource "pods/exec" in API group "" in the namespace "magedu" 二:基于kube-config文件登录: 2.1:创建csr文件: # cat magedu-csr.json { "CN": "China", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } 2.2:签发证书: # ln -sv /etc/kubeasz/bin/cfssl* /usr/bin/ # cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem -ca-key=/etc/kubernetes/ssl/ca-key.pem -config=/etc/kubeasz/clusters/k8s-01/ssl/ca-config.json -profile=kubernetes user1-csr.json | cfssljson -bare user1 # ls magedu* magedu-csr.json magedu-key.pem magedu-role-bind.yaml magedu-role.yaml magedu.csr magedu.pem 2.3:生成普通用户kubeconfig文件: # kubectl config set-cluster cluster1 --certificate-authority=/etc/kubernetes/ssl/ca.pem --embed-certs=true --server=https://172.31.7.188:6443 --kubeconfig=user1.kubeconfig #--embed-certs=true为嵌入证书信息 2.4:设置客户端认证参数: # cp *.pem /etc/kubernetes/ssl/ # kubectl config set-credentials user1 \ --client-certificate=/etc/kubernetes/ssl/user1.pem \ --client-key=/etc/kubernetes/ssl/user1-key.pem \ --embed-certs=true \ --kubeconfig=user1.kubeconfig 2.5:设置上下文参数(多集群使用上下文区分) https://kubernetes.io/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig/ # kubectl config set-context cluster1 \ --cluster=cluster1 \ --user=user1 \ --namespace=magedu \ --kubeconfig=user1.kubeconfig 2.5: 设置默认上下文 # kubectl config use-context cluster1 --kubeconfig=user1.kubeconfig 2.7:获取token: # kubectl get secrets -n magedu | grep magedu # kubectl describe secrets magedu-token-8d897 -n magedu token: eyJhbGciOiJSUzI1NiIsImtpZCI6IlYwMDNHdWJwTmtoaTJUMFRPTVlwV3RiVWFWczJYRHJCNkFkMGRtQWFqRTgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtYWdlZHUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoibWFnZWR1LXRva2VuLThkODk3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Im1hZ2VkdSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBlZmNiNGI0LWM3YTUtNGJkZS1iZjk4LTFiNTkwNThjOTFjNiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptYWdlZHU6bWFnZWR1In0.SJHLgshKcGtIf-ycivn_4SWVRdWw4SuWymBVaA8YJXHPd5PYnwERVNtfUPX88nv-wXkCuZY7fIjGYkoYj6AJEhSPoG15fcmUPaojYeyjkQYghan3CBsZR8C12buSB6t5zCCt22GdG_ScZymxLU7n3Z0PhOzTLzgpXRs1Poqz4DOYylqZyLmW_BPgoNhtQYKlBH6OFzDe8v3JytnaaJUObVZCRxtI6x4iKLt2Evhs8XKfczqqesgoo61qTqtbU4jzlXuHeW7cUMhWoipUc-BkEdV6OtKWOetecxu5uB-44eTRHa1FBjnRMv9SEGj0hxTJCQ08ZNlP0Kc01JZlKXBGdQ 2.8:将token写入用户kube-config文件: 3.9:dashboard登录测试: https://172.31.7.111:30002/#/login
3.整理kubernetes中的网络实现方式
实现同一个pod中的不同容器通信(LNMP) 实现pod与pod同主机与跨主机的容器通信(微服务) pod和服务之间的通信(nginx通过调用tomcat) pod与k8s之外的网络通信 外部到pod(客户端的请求) pod到外部(响应报文、调用支付接口)
集群中网络系统https://kubernetes.io/zh/docs/concepts/cluster-administration/networking/
K8S中的网络主要涉及到pod的各种访问需求,如同一pod的内部(单容器或者多容器)通信、Pod A与Pod B通信、从外部网络访问 Pod、以及从Pod访问外部网络。
K8S的网络基于第三方插件实现,但是定义了一些插件兼容规范,该规范有CoreOS和Google联合定制,叫做CNI(Container Network Interface)。
https://kubernetes.io/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/ #CNI简介
https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md #CNI版本
目前常用的CNI网络插件有calico和flannel;(公有云上使用flannel居多)
Overlay:
Calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做为一个路由器(router),各节点通过BGP(Border Gateway Protocol)边界网关协议学习并在node节点生成路由规则,从而将不同node节点上的pod连接起来进行通信。
Flannel由CoreOS开源的针对K8S的网络服务,借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段,Flannel目前有三种方式实例UDP/VXLAN/host-gw。
3.1 网络通信方式
3.1.1 二层通信
基于目标mac地址通信,不可跨局域网通信,通常是由交换机实现报文转发。
macvlan是Linux kernel支持的特性,macvlan类似于宿主机网卡子接口,但相比网卡子接口来说,macvlan接口拥有自己独立的mac地址,因此使用macvlan接口可以允许更多的二层操作,macvlan有四种模式:
private mode:private模式下,同一父接口下的子接口之间彼此隔离,不能通信,从外部也无法访问。 vepa mode(Virtual Ethernet Port Aggerator虚拟以太网端口聚合器):vepa模式下,子接口之间的通信流量需要导致外部支持802.1Qbg/VPEA功能的交换机上(可以是物理的或虚拟的),经由外部交换机转发,再绕回来。 bridge mode:bridge模式下,模拟的是Linux bridge的功能,但比bridge要好的一点是每个接口的MAC地址是已知的,不用学习,所以这种模式下,子接口之间就是直接可以通信的。 passthru mode(直通模式):passtru模式,只允许单个子接口连接父接口。 source mode:这种模式,只接收源mac为指定的mac地址的报文。
3.1.2 三层通信
基于目标IP通信,也叫做IP交换机技术,解决了跨局域网、跨网络通信,通常是由路由器、防火墙、三层交换机等。
3.1.3 网桥(bridge)
安装完docker之后会默认生成一个docker的网桥设备,网桥设备通过mac地址转发报文到各个容器,如果容器要访问当前宿主机以外的容器或者网络,则会使用宿主机的路由功能进行源地址转换。
3.1.4 VLAN
VLAN(virtual Local Area Network)即虚拟局域网,是将一个物理(交换机)的网络在逻辑上划分成多个广播域的通信技术,VLAN内的主机间可以直接通信,而VLAN网络外的主机需要通过三层网络设备转发才可以通信,因此一个vlan可以将服务器的广播报文限制在一个VLAN内,从而降低单个网络环境中的广播报文,vlan采用12位标识vlan ID,即一个交换机设备最多为2^12=4096个vlan。
802.1Q标准的以太网帧格式增加了802.1Q字段,该字段包含了Type、PRI、CFI和VID 4个部分,各个部分的含义如下:
Type:长度为2 bytes,表示帧类型,802.1Q tag帧中Type字段取固定值0x8100,如果不支持802.1Q的设备收到802.1Q帧,则将其丢弃。 PRI:priority字段,长度为3 bit,表示 以太网帧的优先级,取值范围是0~7,数值越大,优先级越高。当交换机/路由器发生传输拥塞时,优先发送优先级高的数据帧。 CFI:Canonical Format Indicator,长度为1bit,表示MAC地址是否是经典格式。CFI为0说明是经典格式,CFI为1表示为非经典格式。该字段用于区分以太网帧、FDDI帧和令牌环网帧,在以太网帧中,CFI取值为0 VID:VLAN ID,长度为12 bit,取值范围是0~4095,其中0和4095是保留值,不能给用户使用。
这里需要关注的是VID字段,该字段唯一标识了一个VLAN,12bit长度的VID可以表示4096个不同的值,除去两个保留值,一个以太网最多可以划分为4094个VLAN。
3.1.5 Overlay网络简介
叠加网络或者覆盖网络,在物理网络的基础之上叠加实现新的虚拟网络,即可使网络中的容器可以相互通信。
Overlay网络实现方式:
VxLAN:VxLAN全称是Visual eXtensible Local Area Network(虚拟扩展本地局域网),主要由Cisco推出,vxlan是一个VLAN的扩展协议,是由IETF定义的NVO3(Network Virtualization over Layer 3)标准技术之一,VXLAN的特点是将L2的以太帧封装到UDP报文(即L2 over L4)中,并在L3网络中传输,即使用MAC in UDP的方法对报文进行重新封装,VxLAN本质上是一种overlay的隧道封装技术,它将L2的以太网帧封装成L4的UDP数据包,然后在L3的网络中传输,效果就像L2的以太网帧在一个广播域中传输一样,实际上L2的以太网帧跨越了L3网络传输,但是却不受L3网络的限制,vxlan采用24位标识vlan ID号,因此可以支持2^24=1677216个vlan,其可扩展性比vlan强大的多,可以技术大规模数据中心的网络需求。
VTEP(VXLAN Tunnel Endpoint vxlan隧道端点),VTEP是VXLAN网络的边缘设备,是VXLAN隧道的起点和终点,VXLAN对用户原始数据帧的封装和解封装均在VTEP上进行,用于VXLAN报文的封装和解封装,VTEP与物理网络相连,分配的地址为物理网IP地址,VXLAN报文中源IP地址为本节点的VTEP地址,VXLAN报文中目的IP地址为对端节点的VTEP地址,一对VTEP地址就对应着一个VXLAN隧道,服务器上的虚拟交换机(隧道flannel.1就是VTEP),比如一个虚拟机网络中的多个vxlan就需要多个VTEP对不同网络的报文进行封装与解封装。
VNI(VXLAN Network Identifier):VXLAN网络标识VNI类似VLAN ID,用于区分VXLAN段,不同VXLAN段的虚拟机不能直接二层相互通信,一个VNI表示一个租户,即使多个终端用户属于同一个VNI,也表示一个租户。
NVGRE:Network Virtualization using Generic Routing Encapsulation,主要支持者是Mircrosoft,与VXLAN不同的是,NVGRE没有采用标准传输协议(TCP/UDP),而是借助通用路由封装协助(GRE),NVGRE使用GRE头部的低24位作为租户网络标识符(TNI),与VXLAN一样可以支持1777216个vlan。
由于MAC-to-UDP封装,vxlan在原来的帧当中引入了50字节的overhead。
参考资料 VXLAN概述:思科Nexus 9000系列交换机,https://blog.csdn.net/xtydtc/article/details/117445671 Neutron VxLAN + Linux Bridge 环境中的网络 MTU,https://www.cnblogs.com/sammyliu/p/5079898.html (VLAN overhead 50字节和GRE overhead 24字节) VTEP节点和VTEP网关,https://www.cnblogs.com/mrwuzs/p/8012022.html Vxlan为何采用UDP封装,而不是TCP或者IP?https://www.cnblogs.com/dier-gaohe/p/14435879.html (UDP头部只占用8个字节,使用UDP封装开销比较小。)
步骤 | 操作/封包 | 协议 | 长度 | MTU |
1 | ping -s 1422 | ICMP | 1430 = 1422 + 8 (ICMP header) | |
2 | L3 | IP | 1450 = 1430 + 20 (IP header) | VxLAN Interface 的 MTU |
3 | L2 | Ethernet | 1464 = 1450 + 14 (Ethernet header) | |
4 | VxLAN | UDP | 1480 = 1464 + 8 (VxLAN header) + 8 (UDP header) | |
5 | L3 | IP | 1500 = 1480 + 20 (IP header) | 物理网卡的(IP)MTU,它不包括 Ethernet header 的长度 |
6 | L2 | Ethernet | 1514 = 1500 + 14 (Ethernet header) | 最大可传输帧大小 |
3.1.6 underlay简介
Underlay网络就是传统IT基础设施网络,由交换机和路由器等设备组成,借助以太网协议、路由协议和VLAN协议等驱动,它还是Overlay网络的底层网络,为Overlay网络提供数据通过通信服务。容器网络中的Underlay网络是借助驱动程序将宿主机的底层网络接口直接暴露给容器使用的一种网络构建技术,较为常见的解决方案有MAC VLAN、IP VLAN和直接路由等。
Bridge模式: 桥接模式。
MAC VLAN模式:支持在同一个以太网接口上虚拟出多个网络接口(子接口),每个虚拟接口都拥有唯一的MAC地址并可配置网卡子接口IP.
IP VLAN:类似于MACVLAN,它同样创建新的虚拟网络接口并为每个接口分配唯一的IP地址,不同之外在于,每个虚拟接口将共享使用物理接口的MAC地址,从而不再违反防止MAC欺骗的交换机的安全策略,且不要在物理接口上启用混杂模式。
3.2 VXLAN通信过程
https://support.huawei.com/enterprise/zh/doc/EDOC1100087027
VXLAN网络中的通信过程。对于处于同一个VXLAN的两台虚拟终端,其通信过程可以概括为如下的步骤:
① 发送方向接收方发送数据帧,帧中包含了发送方和接收方的虚拟MAC地址。 ② 发送方连接的VTEP节点收到了数据帧,通过查找发送方所在的VXLAN以及接收方所连接的VTEP节点,将该报文添加VXLAN首部、外部UDP首部、外部IP首部后,发送给目的VTEP节点。 ③ 报文经过物理网络传输到达目的VTEP节点。 ④ 目的VTEP节点接收到报文后,拆除报文的外部IP首部和外部UDP首部,检查报文的VNI以及内部数据帧的目的MAC地址,确认接收方与本VTEP节点相连后,拆除VXLAN首部,将内部数据帧交付给接收方。 ⑤ 接收方收到数据帧,传输完成。
VXLAN网关节点适用于这样一种应用场景:当一台处于VXLAN网络中的终端要和一台处于非VXLAN网络中的节点进行通信时,由于VXLAN网络中的终端使用的都是虚拟网络地址,而非VXLAN中的设备使用的是实际的物理地址,此时,VXLAN网关将起到地址转换的作用,通信时,临时将VXLAN终端的虚拟地址转换为物理地址,然后再与外网进行通信。地址转换的方式可基于NAT机制。
3.3 Docker对网络的支持
Docker跨主机通信方案总结:
Bridge网络,docker0就是默认的桥接网络;
Docker网络驱动:
Overlay:基于VXLAN、NVGRE等封装技术实现overlay叠加网络;
Macvlan:基于Docker宿主机物理网卡的不同子接口实现多个虚拟vlan,一个子接口就是一个虚拟vlan,容器通过宿主机的路由功能和外网保持通信。
3.4 Docker多主机通信之macvlan
macvlan是Linux kernel支持的特性,macvlan类似于宿主机网卡子接口,但相比网卡子接口来说,macvlan接口拥有自己独立的mac地址,因此使用macvlan接口可以允许更多的二层操作,macvlan有四种模式:Private、VEPA、Passthru、bridge。
3.4.1 Private私有模式
在Private模式下,同一个宿主机下的容器不能通信,即使通过交换机再把数据报文转发回来也不行。
# docker network create -d macvlan --subnet=172.31.0.0/21 --gateway=172.31.7.254 -o parent=eth0 -o macvlan_mode=private s209_macvlan_private # docker network ls
# docker run -it --rm --net=s209_macvlan_private --name=container4 --ip=172.31.5.222 centos:7.7.1908 /bin/bash # docker run -it --rm --net=s209_macvlan_private --name=container5 --ip=172.31.5.223 centos:7.7.1908 /bin/bash 测试两个容器连通性 #验证private模式macvlan模型 # docker network inspect s209_macvlan_private
3.4.2 VEP模式
虚拟以太端口汇聚器(Virtual Ethernet Port Aggregator,简称VEPA),在这种模式下,macvlan内的容器不能直接接收在同一个物理网卡的容器的请求数据包,但是可以经过交换机的(端口回流)再转发回来可以实现通信。
# docker network create -d macvlan --subnet=172.31.0.0/21 --gateway=172.31.7.254 -o parent=eth0 -o macvlan_mode=vepa s209_macvlan_vepa # docker network ls
# docker run -it --rm --net=s209_macvlan_vepa --name=container1 --ip=172.31.6.222 centos:7.8.2003 /bin/bash # docker run -it --rm --net=s209_macvlan_vepa --name=container2 --ip=172.31.6.223 centos:7.8.2003 /bin/bash 测试两个容器连通性 #验证private模式macvlan模型 # docker network inspect s209_macvlan_vepa
3.4.3 passthru直通模式
Passthru模式下该macvlan只能创建一个容器,当运行一个容器后再创建其它容器则会报错。
# docker network create -d macvlan --subnet=172.31.0.0/21 --gateway=172.31.7.254 -o parent=eth0 -o macvlan_mode=passthru s209_macvlan_passthru # docker network ls
# docker run -it --rm --net=s209_macvlan_passthru --name=container1 centos:7.8.2003 /bin/bash # docker run -it --rm --net=s209_macvlan_passthru --name=container2 centos:7.8.2003 /bin/bash
3.4.4 bridge模式
在bridge这种模式下,使用同一个宿主机网络的macvlan容器可以直接通信。
# docker network create -d macvlan --subnet=172.31.0.0/21 --gateway=172.31.7.254 -o parent=eth0 -o macvlan_mode=bridge s209_macvlan_bridge # docker network ls # docker run -it --rm --net=s209_macvlan_bridge --ip=172.31.6.201 --name=container1 centos:7.8.2003 /bin/bash # docker run -it --rm --net=s209_macvlan_bridge --ip=172.31.6.202 --name=container2 centos:7.8.2003 /bin/bash # docker network inspect s209_macvlan_bridge
注:在部分服务器需要开启网卡混杂模式,混杂模式(Promiscuous Mode)是指一台服务器能够接收所有经过它的数据流,而不论其目的地址是否是当前服务器。
3.4.5 设置一个服务器如果多个macvlan
(1)将服务器对应的交换机接口设置为trunk模式;
# interface fastEthernet0/1 # switch mode trunk
(2)Linux服务器添加网卡子接口
# ifconfig eth0:1 172.31.2.202 netmask 255.255.248.0
(3)在Linux网卡子接口添加新的macvlan;
# docker network create -d macvlan --subnet=172.31.0.0/21 --gateway=172.31.7.254 -o parent=eth0.1 -o macvlan_mode=private s209_macvlan_private
3.5 Docker多主机通信之overlay
3.5.1 calico
官网https://www.projectcalico.org/
Calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做为一个路由器(router),各节点通过BGP(Border Gateway Protocol)边界网关协议学习并在node节点生成路由规则,从而将不同node节点上的pod连接起来进行通信。
BGP是一个去中心化的协议,它通过自动学习和维护路由表实现网络的可用性,但是并不是所有的网络都支持BGP,另外为了跨网络实现更大规模的网络管理,calico还支持IP-in-IP的叠加模型,简称IPIP,IPIP可以实现跨不同网段建立路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置文件设置是否启用IPIP,在公司内部如果k8s的node节点没有跨越网段建议关闭IPIP。
IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各Node上创建一个名为"tunl0"的虚拟网络接口。 BGP模式则直接使用物理机作为虚拟路由器(vRouter),不再创建额外的tunnel。
Calico核心组件:
Felix:calico的agent,运行在每一台node节点上,其主要是维护路由规则、汇报当前节点状态以确保pod的跨主机通信。 BGP Client:每台node都运行,其主要负责监听node节点上由felix生成的路由信息,然后通过BGP协议广播至其他剩余的node节点,从而相互学习路由实现pod通信。 Route Reflector:集中式的路由反射器,calico v3.3开始支持,当Calico BGP客户端将路由从其FIB(Forward Infomation database转发信息库)通告到Route Reflector时,Route Reflector会将这些路由通告给部署集群中的其他节点,Route Reflector专门用于管理BGP网络路由规则,不会产生pod数据通信。 注:calico默认工作模式是BGP的node-to-node mesh,如果要将使用Route Reflector需要进行相关配置。 https://docs.projectcalico.org/networking/bgp https://docs.projectcalico.org/reference/architecture/overview
https://docs.projectcalico.org/getting-started/kubernetes/
3.5.2 Flannel
官网https://coreos.com/flannel/docs/latest/
文档https://coreos.com/flannel/docs/latest/
由CoreOS开源的针对k8s的网络服务,其目的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段。
Flannel网络模型(后端),Flannel目前有三各方式实现:UDP、VXLAN、host-gw。
UDP:早期版本的Flannel使用UDP封装完成报文的跨越主机转发,其安全性及性能略有不足。 VXLAN:Linux内核在2012年义的v3.7.0之后加入了VXLAN的协议支持,因此新版本的Flannel也有UDP转换为VXLAN,VXLAN本质上是一种tunnel(隧道)协议,用来基于3层网络实现虚拟的2层网络,目前flannel的网络模型已经是基于VXLAN的叠加(覆盖)网络,目前推荐使用vxlan作为其网络模型。 Host-gw:也就是Host GateWay,通过在node节点上创建到达各目标容器地址的路由表而完成报文的转发,因此这种方式要求各node节点本身必须处于同一个局域网(二层网络)中,因此不适用于网络变动频繁或比较大型的网络环境,但是其性能较好。
Flannel组件解释:
Cni0:网桥设备,每创建一个pod都会创建一对veth pair,其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡),Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上,Cni0设备获得的ip地址是该节点分配到的网段的第一个地址。 Flannel1.1:overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。
Flannel的系统文件及目录:
# find / -name flannel /run/flannel /usr/bin/flannel /var/lib/cni/flannel
flannel pod状态(需要在部署k8s的时候使用Flannel作为网络插件)
# kubectl get pods -n kube-system
查看当前node主机IP地址范围
# cat /run/flannel/subnet.env
查看当前node主机的cni信息;
# cat /var/lib/cni/flannel/aaaaaaaaaaxxxxxddfsdfsdfsdfdsf
overlay
flannel
calico
underlay
macvlan
bridge