Tungsten Fabric SDN — 与 Kubernetes 的资源映射

Posted 范桂飓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tungsten Fabric SDN — 与 Kubernetes 的资源映射相关的知识,希望对你有一定的参考价值。

目录

文章目录

Kubernetes to Contrail Object Mapping

contrail-kube-manager 会 Watch 这些 K8s resource 的变更,并转发到 TF API 请求。

K8s Namespace mapping to TF Shared or single project(multi-tenancy,多租户增强)

K8s Namespace 可以映射到 TF Shared Project 或 TF Single Project。

  1. K8s Namespace mapping to TF Shared Project(TF Single Tenant,单租户集成模式):TF 对应 K8s Cluster 只有一个 Tenant。K8s Namespace 映射为 TF VN。

  2. K8s Namespace mapping to TF Single Project(TF Multi Tenant,多租户集成模式):TF 对应 K8s Cluster 有多个 Tenants。K8s Namespace 映射为 TF Project。

K8s Namespace mapping to TF Shared Project

可以通过修改 kube-manager 的配置文件 /etc/contrail/contrail-kubernetes.conf 中的配置项 [KUBERNETES].cluster_project 来指定实施 “单租户集成模式”。例如:

[KUBERNETES]
cluster_project = 'domain': 'default-domain', 'project': 'kubernetes'
...

单租户集成模式中,所有的 non-Isolated network 都会共享默认的 cluster-network VN VRF;所有的 Isolated network 都具有独立的 VN VRF。

K8s Namespace mapping to TF Single Project

默认的,contrail-ansible-deployer 会实施 “多租户集成模式”。初始状态下,存在 5 个 TF Projects 对应 5 个 K8s Namespaces。之后再新建一个 K8s Namespace 就会同时创建一个 TF Project。

每个对应 K8s Namespace 的 TF Project 下都包含了 2 个 VNs:k8s-vn_name-service-network 和 k8s-vn_name-pod-network,并且绑定了相应的 IPAM 和 Network Policies。分别用于 Pod 和 Service 资源。

默认情况下,除了 k8s-vn_name-pod-network 之外,其他的 VN 是无法连接到 k8s-vn_name-service-network 的,这由 TF Network Policy 来进行控制。

k8s-default Project 存放了大量可以被 Shared 的资源,例如:IPAM、Network Policy、Security group 等等。

  • 3 个 TF IPAM:k8s-pod-ipam、k8s-service-ipam 和 k8s-ip-fabric-ipam,分别作为 K8s Pods、Services、Underlay(IP Fabric)的 Subnet IP Pool。
  • 3 条 Network Policies:k8s-default-service-np、k8s-default-ip-fabric-np 和 k8s-default-pod-service-np。
    • k8s-default-service-np 允许指定的 VN 可以访问 K8s service VN。
    • k8s-default-pod-service-np 允许指定的 Pod VN 可以访问 K8s service VN。
    • k8s-default-ip-fabric-np 允许指定的 VN 可以访问 K8s underlay(IP Fabric)VN。
  • 1 条 Security Group:允许 Pod VIF 的所有 Ingress/Egress 流量。

K8s Pod mapping to TF VRF Virtual Interface IP(network isolation,网络隔离增强)

创建一个 K8s Pod 就会在相应的 TF VN 中创建一个 VIF,并挂载到 Pod 所处的 Linux Network Namespace。

Kubernetes 的基本网络模型是一个扁平的网络(Flat networking),通过 K8s Network policy 来提供 Pod-to-Pod 的安全访问控制。但 K8s Flat networking 并没有实现真正的多租户隔离,这意味着任何 Namespace 中的 Pod 都可以与任何 Other Namespace 中的 Pods 进行通信。换句话说,如果 Target Pod 的 Domain Name 或 IP address 已知,则无法阻止从一个 Namespace 中的 Pod 到 Other Namespace 中的 Pods 的通信。

可见,Kubernetes 的基本网络模型并不适用于对安全隔离性要求高的场景。针对这一需求,TF 除了为 K8s 提供 CNI 标准强制要求的 Flat Networking(Non-Isolated 网络模型)之外,还为 K8s 提供了 Network isolation 网络增强功能。

Default Mode(Non-Isolated Namespaces)

为了保持 K8s 基本的 Flat Networking(扁平网络)模型,TF 默认提供了 Non-Isolated Namespaces(非隔离命名空间)模式。

TF 为 K8s Cluster 预配置了 2 个 Default VN(虚拟网络):k8s-default-pod-network 和 k8s-default-service-network。它们分别为所有 Non-Isolated Namespaces 中的 Pods 或 Services 提供网络。使得所有的 Non-Isolated Namespaces 中的 Pods 或 Services 处于一个扁平的网络中的(包括 Default Namespace),可以跨越不同的 Namespace 互联互通。

从 TF 的角度看,这些 Non-Isolated Namespaces 对应的 Projects 共享了 2 个 Public VRF:

  • k8s-default-pod-network: the pod virtual network/VRF table, with the default subnet 10.32.0.0/12
  • k8s-default-service-network: the service virtual network /VRF table, with a default subnet 10.96.0.0/12

也就是说,当你新建一个(默认)Non-Isolated Namespace 时,TF 会自动为该 Project 授权这 2 个 Default VN/VRF。

NOTE:无论是 Non-Isolated Namespace 还是 Isolated Namespace 中,每个 TF virtual network 都具有独立的 VRF,所以两个不同的 virtual network 需要互通时,依旧需要配置相应的 Network Policy。例如:k8s-default-pod-network 和 k8s-default-service-network 之间就是通过 Network Policy 来实现互通的。

NOTE:kube-system namespace 是一个特殊的 underlay 网络,不在 K8s Cluster 范围内,也就是说不属于 TF 管理。

Isolation Mode(Isolated Namespaces)

Isolated Namespace 拥有独立隔离的 Pod 和 Service VN/VRF。也就是说:

  1. Isolated Namespace 中的 Pod 只能与同一个 Namespace 中的其他 Pods 互通,无法访问 other Namespaces 中的 Pods,但可以访问 non-Isolated Namespaces 中的 Services。创建一个 Isolated Namespace 如下。
apiVersion: v1
kind: Namespace 
metadata:
  annotations: 
    "opencontrail.org/isolation" : "true"  # The value of true indicates this is an isolated namespace.
  name: ns-isolated
  1. Isolated Namespace 中的 Service(k8s service-ip)只能与同一个 Namespace 中的其他 Pods 互通,other Namespace 中的 Pods 无法访问 Isolated Namespace 中的 Service。根据需求,如果 Isolated Namespace 中的 Service 需要被 other Namespace 中的 Pods 访问到,则可以配置 disabling service isolation。此时 other Namespace 的 Pods 可以范围该 Service,同时 Isolated Namespace 中的 Pods 依旧是隔离的。
apiVersion: v1
kind: Namespace 
metadata:
  annotations: 
    "opencontrail.org/isolation" : "true"  # The value of true indicates this is an isolated namespace.
    "opencontrail.org/isolation.service": "false"
  name: ns-isolated

从 YAML 可以看出,contrail-kube-manager 对 K8s resources 进行了扩展。新建一个 Namespace 时,contrail-kube-manager 会 Watch K8s API Server 并读取到 opencontrail.org/isolation 注释,然后根据 Namespace 的隔离类型来进行相应的处理。当 isolation 为 true,TF 就会使用相应的 VRF 来创建该 Namespace 映射的 Project。

举例说明:假设现在具有 3 个 Namespace: default、ns-non-isolated、ns-isolated,并在每个 Namespace 中创建了 VN vn-left-1。那么你将会看见以下 VNs/VRFs,它们的隔离关系如图所示。

  • default-domain:k8s-default:k8s-default-pod-network

  • default-domain:k8s-default:k8s-default-service-network

  • default-domain:k8s-default:k8s-vn-left-1-pod-network

  • default-domain:k8s-ns-non-isolated:k8s-vn-left-1-pod-network

  • default-domain:k8s-ns-isolated:k8s-ns-isolated-pod-network

  • default-domain:k8s-ns-isolated:k8s-ns-isolated-service-network

  • default-domain:k8s-ns-isolated:k8s-vn-left-1-pod-network

NOTE:Isolated Namespaces Mode 下,如果两个 Namespaces 需要互通时,则可以对 Namespace 下属的 VN 配置相应的 Network Policy。

Custom Isolation Mode

该模式中,用户可以通过修改 Application YAML annotations 来自定义自己的 Namespace 中所使用的 Virtual Network。例如:

annotations: 
    "opencontrail.org/network" : '"domain":"default-domain", "project": "k8s-default", "name":"k8s-blue-net-pod-network"'

  1. 如果该 annotations 配置 Pod YAML 上,则指定 Pod 启动在指定 Namespace 的 Virtual network 上。
  2. 如果该 annotations 配置 Namespace YAML 上,则该 Namespace 中的所有 Pods 都启动在 Virtual network 上。

操作示例:验证路由隔离是否有效

  1. 新建 non-Isolated Namespace
$ cat ns-non-isolated.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: ns-non-isolated
  1. 新建 Isolated Namespace
$ cat ns-isolated.yaml

apiVersion: v1
kind: Namespace
metadata:
  annotations:
    "opencontrail.org/isolation": "true"
  name: ns-isolated
  1. 创建 Pods
$ kubectl apply -f pod-busybox.yaml -n default
$ kubectl apply -f pod-busybox.yaml -n ns-non-isolated
$ kubectl apply -f pod-busybox.yaml -n ns-isolated

$ kubectl get pods -A -o wide | grep busybox
default           busybox                                 1/1     Running   0          39s     10.47.255.248   worker02
ns-isolated       busybox                                 1/1     Running   0          3m38s   10.47.255.250   worker02
ns-non-isolated   busybox                                 1/1     Running   0          2m5s    10.47.255.249   worker01
  1. 对比验证 Pods 之间的网络隔离性
# 验证 Isolated 和 non-Isolated 之间的隔离性
kubectl exec -it -n ns-isolated busybox -- ping 10.47.255.249

# 验证 Default 和 Isolated 之间的隔离性
kubectl exec -it -n default busybox -- ping 10.47.255.250

# 验证 Default 和 non-Isolated 之间的隔离性
kubectl exec -it -n default busybox -- ping 10.47.255.249

K8s Service mapping to TF ECMP-based native LoadBalancer(load-balancing,负载均衡增强)

K8s Service 支持以下 4 种模式,还支持使用 ExternalIP。

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. ExternalName

而 TF 则主要支持了其中必要的 2 种模式,以及 ExternalIP。

  1. TF ClusterIP
  2. TF LoadBalancer

TF ClusterIP Service

TF ClusterIP Service 通过 ECMP 和 NAT 技术,实现了在 Service 和 Pods 之间进行 L4 负载均衡转发。

TF Native Load Balancer

新建一个 K8s ClusterIP Service 时,TF 会从同步新建一个 TF Load Balancer,LB Provider Type 为 Native,底层实现为 vRouter ECMP。所以也称为 TF Native Load Balancer。

并且 TF 还会从相应的 Service VN 的 Subnet Pool 分配一个 IP 作为 LB VIP,也就是 ClusterIP。

TF Floating IP NAT

在有了 TF Native LB VIP 作为 Front-end IP 之后,还需要将流量转发到 Backend IPs(Pods),TF 使用 NAT 技术来实现这一功能,而不是引入一个重型的 HAProxy-like 负载均衡器。

同时,由于 TF Floating IP 本身就具有 NAT 的功能特性,所以就可以直接使用 TF Floating IP 来完成这项工作。

另外,由于 ClusterIP Service 只能在 K8s Cluster Internal 被访问,所以针对 ClusterIP Service 的 FIP 实际上是一个 Inter-FIP。直接从相应的 Service VN 中的 FIP Pool 分配的,而不需要从 Public VN 中分配。

使用示例

  1. 创建 ClusterIP Service。
$ cat nginx-deployment-clusterip-service.yaml

---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment-clusterip-service
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 1 pods matching the template
  template: # create pods using pod definition in this template
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deployment-clusterip-service
  namespace: default
  labels:
    app: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
    

$ kubectl get pods -A -o wide | grep nginx
default           nginx-56db997f77-9qxwd                  1/1     Running   0          15m    10.47.255.246   worker01 
default           nginx-56db997f77-thpxd                  1/1     Running   0          15m    10.47.255.247   worker02 


$ kubectl describe service -n default nginx
Name:              nginx
Namespace:         default
Labels:            app=nginx
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     "apiVersion":"v1","kind":"Service","metadata":"annotations":,"labels":"app":"nginx","name":"nginx","namespace":"default","spec":"p...
Selector:          app=nginx
Type:              ClusterIP
IP:                10.97.137.130
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.47.255.246:80,10.47.255.247:80
Session Affinity:  None
Events:            <none>
  1. 查看 ClusterIP Service 对应的 TF LB。

  2. 查看 TF LB 在 vRouter 上的 ECMP Routes。

  3. 查看 ClusterIP 的 FIP。

TF Loadbalancer Service

TF Loadbalancer Service 的实现方式是在 TF ClusterIP Service(Native LB + Inter-FIP NAT)的基础之上,再叠加了一个 External FIP NAT。因为 Loadbalancer Service 相对于 ClusterIP Sercice 而言,是提供给 External Network 访问的。

  • ClusterIP Service as a Cluster Internal LB VIP
  • Loadbalancer Service as a Cluster External Floating VIP

可见,对于 Loadbalancer Service 而言拥有 3 个关键 IP:

  1. TF Native LB IP:从 Service VN Subnet Pool 分配,作为内部 L3-4 负载均衡 VIP。
  2. Inter-FIP:从 Service VN FIP Pool 分配,作为内部 L3-4 NAT Front-end IP。
  3. Ext-FIP:从 Public VN FIP Pool(Namespace FIP Pool 或 Global FIP Pool)分配,作为外部 L3-4 NAT Front-end IP。

相对的,Loadbalancer Service 中也存在着 2 种类型的 ECMP:

  1. Internal ECMP:Cluster IP 和 Pod IPs 之间的 ECMP
  2. External ECMP:External VIP 和 Cluster IPs(跨节点)之间的 ECMP。

使用示例

  • 新建 Loadbalancer Service
$ vi service-web-lb.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-web-lb
  spec:
    ports:
    - port: 8888
    targetPort: 80 selector:
  app: webserver
  type: LoadBalancer

NodePort Service(kube-proxy iptables NAT)

NodePort Service 依赖原生的 kube-proxy iptables NAT 技术来实现,在 TF 的场景中,通常没必要使用到。

使用示例

  • 创建 Nginx Deployment NodePort Service。
$ cat nginx-deployment-nodeport-service.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-nodeport-service
  labels:
    name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deployment-nodeport-service
  labels:
    name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
      name: http
  selector:
    name: nginx
    

$ kubectl get pods -A -o wide | grep nodeport
default           nginx-deployment-nodeport-service-69f7cb4f44-pjm9r   1/1     Running   0          30s     10.47.255.247   worker02


$ kubectl describe service -n default nginx-deployment-nodeport-service
Name:                     nginx-deployment-nodeport-service
Namespace:                default
Labels:                   name=nginx
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            "apiVersion":"v1","kind":"Service","metadata":"annotations":,"labels":"name":"nginx","name":"nginx-deployment-nodeport-service","nam...
Selector:                 name=nginx
Type:                     NodePort
IP:                       10.98.140.244
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30080/TCP
Endpoints:                10.47.255.247:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>


# worker02
$ curl http://172.27.10.75:30080
  • 查看 Service 对应的 LB。
  • 查看 ClusterIP 的 FIP。

K8s Ingress mapping to TF HAProxy L7 LoadBalancer(外部网络接入增强)

TF 提供了基于 HAProxy 的 Ingress 实现,创建 K8s Ingress 就会创建一个 TF HAProxy LoadBalancer。

其中,由 contrail-svc-monitor 执行具体的 LBaaS 任务。contrail-svc-monitor 作为 TF 内部组件(e.g. Config Node)与外部组件(e.g. Loadbalancer Provider、OpenStack API)之间进行交互的桥梁。

K8s Network Policy mapping to TF Security group(micro-segmentation)

TF Security Group 可以通过限制 Protocol、Ports 等参数来管理任意 Pods 之间、以及 Pod 与 Service 之间的访问控制,当新建一个 K8s Network Policy 就会创建一个 TF Security Group。

TF Security Group 会被转化为具体的 TF Firewall Rules。

以上是关于Tungsten Fabric SDN — 与 Kubernetes 的资源映射的主要内容,如果未能解决你的问题,请参考以下文章

Tungsten Fabric SDN — 网络协议

Tungsten Fabric SDN — 软件项目编译与打包

Tungsten Fabric SDN — 与 Kubernetes 的集成部署(CN)

Tungsten Fabric SDN — 服务链

Tungsten Fabric SDN — 与 Bare Metal 的集成架构

Tungsten Fabric SDN — 与 Bare Metal 的集成架构