Tungsten Fabric从4.0版本起,就开始支持用于将Kubernetes自动化平台与TF的集成的容器网络接口(CNI)。本文就来介绍基于CNI的TF K8s集成部署。
什么是Kubernetes
Kubernetes也称为K8s,是一个开放源代码平台,用于跨主机集群自动执行应用程序容器的部署、扩展和运行,从而提供以容器为中心的基础架构。它提供了跨公共云和私有云的可移植平台。Kubernetes支持应用程序的部署、扩展和自动修复。
Kubernetes支持可用于大多数基本网络连接的容器网络接口(CNI)的可插入框架,包括容器Pod寻址、网络隔离、基于策略的安全性、网关、SNAT、负载均衡器,以及Kubernetes编排的服务链功能。Tungsten Fabric自4.0版本起即可支持Kubernetes的CNI功能。
Kubernetes提供了一个扁平的网络模型,其中所有容器Pod都可以彼此通信。添加了网络策略功能,以提供Pod之间的安全性。与Kubernetes集成的Tungsten Fabric则添加了其它网络功能,包括多租户、网络隔离、具有网络策略的微分段和负载均衡等。
表1列出了Kubernetes概念与Tungsten Fabric资源之间的映射。
表1:Kubernetes到Tungsten Fabric的映射
Kubernetes | Tungsten Fabric资源 |
---|---|
Namespace命名空间 | 共享或单个项目 |
Pod | 虚拟机,接口,实例IP |
Service | 基于ECMP的原生负载均衡器 |
Ingress | 基于HAProxy的用于URL路由的L7负载均衡器, |
Network policy网络策略 | 基于命名空间和Pod选择器的安全组 |
什么是Kubernetes Pod?
Kubernetes pod是一组单个或多个容器(例如Docker容器),这些容器共享的存储和如何运行容器的配置选项。Pod始终位于同一位置,在同一时间编排,并在共享的上下文中运行。Pod的共享上下文是一组Linux命名空间、cgroup和其它隔离方面。在Pod的相关环境中,每个应用程序可能会有进一步的子隔离。
你可以在以下位置找到有关Kubernetes的更多信息:
http://kubernetes.io/docs/whatisk8s/
TF K8s的四种配置模式
可以在Kubernetes中以几种不同的模式配置Tungsten Fabric,本节介绍的几种配置模式包括:
·默认模式
·命名空间隔离模式
·自定义隔离模式
·嵌套模式
默认模式
在Kubernetes中,所有Pod可以与所有其它Pod通信,而无需使用网络地址转换(NAT)。这也是TF Kubernetes集群的默认模式。在默认模式下,Tungsten Fabric创建一个由所有命名空间共享的虚拟网络,从该命名空间分配服务和Pod IP地址。
Kubernetes集群中产生的所有命名空间中的所有Pod都可以相互通信。所有Pod的IP地址都是从TF Kubernetes管理器中配置的Pod子网分配的。
注意:
在kube-system命名空间中生成的系统Pod不在Kubernetes集群中运行;它们以underlay的方式运行,并且这些pod的网络也不是由TF处理的。
命名空间隔离模式
除了Kubernetes授权使用的默认网络模型外,Tungsten Fabric还支持其他自定义网络模型,这些模型为Kubernetes集群的用户提供了许多丰富的Tungsten Fabric功能。其中一种这样的功能,就是Kubernetes命名空间的网络隔离。
对于命名空间隔离模式,集群管理员可以配置命名空间注释以打开隔离。在该模式下,除非明确定义了安全组或网络策略以允许访问,否则无法从其它命名空间访问该命名空间中的服务。
可以通过注释Kubernetes命名空间元数据,来将Kubernetes命名空间配置为隔离的:
opencontrail.org/isolation : true
命名空间隔离为Pod提供了网络隔离,因为隔离的命名空间中的Pod无法访问集群中其它命名空间中的Pod。
命名空间隔离还为Pod提供服务的隔离。如果任何Kubernetes服务是由隔离命名空间中的Pod实现的,则这些Pod仅可通过Kubernetes service-ip到达同一命名空间中的Pod。
为了使服务仍然可以访问其它命名空间,可以通过在命名空间上标记以下注释来禁用服务隔离:
opencontrail.org/isolation.service : false
禁用服务隔离,可以使服务访问其它命名空间中的Pod,但是隔离的命名空间中的Pod仍然无法访问其它命名空间中的Pod。
对于Pod和服务隔离都被标记为“已隔离”的命名空间,具有以下网络行为:
·在隔离的命名空间中创建的所有Pod彼此之间都具有网络可达性。
·Kubernetes集群中其它命名空间中的pod无法到达隔离命名空间中的pod。
·在隔离命名空间中创建的pod可以到达非隔离命名空间中的pod。
·隔离命名空间中的Pod可以访问Kubernetes集群中任何命名空间中的非隔离服务。
·来自其它命名空间的Pod无法到达隔离命名空间中的服务。
被标记为“已隔离”,且服务隔离被禁用、pod隔离被启用的命名空间,具有以下网络行为:
·在隔离的命名空间中创建的所有Pod彼此之间都具有网络可达性。
·Kubernetes集群中其它命名空间中的pod无法到达隔离命名空间中的pod。
·在隔离命名空间中创建的pod可以到达其它命名空间中的pod。
·隔离命名空间中的Pod可以访问Kubernetes集群中任何命名空间中的非隔离服务。
·来自其它命名空间的Pod可以到达隔离命名空间中的服务。
自定义隔离模式
管理员和应用程序开发人员可以添加注释,以指定要在其中配置一个或多个Pod的虚拟网络。用于指定此自定义虚拟网络的注释为:
"opencontrail.org/network: <fq_network_name>"
如果在Pod规范上配置了此注释,则会在该网络中启动Pod。如果在命名空间规范中配置了注释,则将在提供的网络中启动命名空间中的所有Pod。
注意:
在Pod或命名空间规范中配置虚拟网络之前,必须使用Tungsten Fabric VNC API或Tungsten Fabric-UI创建虚拟网络。
嵌套模式
Tungsten Fabric支持在OpenStack集群内部配置Kubernetes集群。虽然这种集群的嵌套本身并不是独一无二的,但Tungsten Fabric提供了一个折叠式的控制和数据平面,在这个平面中,一个TF控制平面和一个网络栈同时管理和服务OpenStack和Kubernetes集群。通过统一的控制和数据平面,这些集群的互通和配置是无缝的,并且没有复制和重叠的现象,使其成为非常有效的选项。
在嵌套模式下,一个OpenStack集群的虚拟机中预配置了一个Kubernetes集群。Kubernetes集群的CNI插件和TF-kubernetes管理器,直接与管理OpenStack集群的Tungsten Fabric组件交互。
在嵌套模式部署中,所有Kubernetes特性、功能和规格都可以被支持。嵌套部署允许其与底层的OpenStack集群在同一平面上运行,从而扩展了Kubernetes的边界和局限性。
想要了解更多的信息,请查看以下链接:
https://www.juniper.net/documentation/en_US/contrail20/topics/task/installation/provisioning-k8s-cluster.html
Kubernetes服务
Kubernetes服务是一种抽象概念,它定义了逻辑上的Pod集以及用于访问Pod的策略。根据服务定义中的LabelSelector字段选择实现服务的Pod集。在Tungsten Fabric中,Kubernetes服务被实现为原生于ECMP的负载均衡器。
TF Kubernetes集成支持以下ServiceType:
·“clusterIP”:这是默认模式。选择此ServiceType可使服务通过集群网络访问。
·“LoadBalancer”:将ServiceType指定为“LoadBalancer”可以从外部访问该服务。为“LoadBalancer”_Service_分配了CluserIP和ExternalIP地址。此ServiceType假定用户已使用浮动IP池配置了公共网络。
TF Kubernetes服务集成支持TCP和UDP协议。另外,服务可以暴露多个端口,而这些端口都与targetPort不同。例如:
代码语言:javascript复制kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
Kubernetes用户可以为LoadBalancer和clusterIP ServiceTypes指定spec.clusterIP和spec.externalIPs。
如果ServiceType为LoadBalancer,并且用户未指定spec.externalIP,那么conutil-kube-manager将从公共池中分配一个浮动IP,并将其关联到ExternalIP地址。
Ingress
Kubernetes服务可以通过多种方式在外部公开或在集群外部暴露。
有关从外部公开Kubernetes服务的所有方法的列表,请参见链接:
https://kubernetes.io/docs/concepts/services-networking/ingress/#alternatives
Ingress就是这样一种方法。Ingress提供7层负载均衡,而其它方法提供4层负载均衡。Tungsten Fabric支持基于http的单一服务入口、简单扇出入口,和基于命名的虚拟主机入口。
TF K8s解决方案的七大元素
Tungsten Fabric Kubernetes解决方案包括以下元素:
·TF Kubernetes Manager
·Kubernetes服务的ECMP负载均衡器
·用于Kubernetes Ingress的HAProxy 负载均衡器
·Kubernetes网络策略的安全组
·Kubernetes对安全策略的支持
·域名服务器(DNS)
·支持的Kubernetes注释
接下来请它们一一登场。
TF Kubernetes Manager
TF Kubernetes的实施需要侦听Kubernetes API消息,并在Tungsten Fabric API数据库中创建相应的资源。
在Docker容器中运行一个新的模块——conilil-kube-manager,以侦听来自Kubernetes API服务器的消息。
Kubernetes服务的ECMP负载均衡器
Kubernetes中的每个服务都由一个负载均衡器对象表示。Kubernetes分配的服务IP用作负载均衡器的VIP。正在侦听的服务端口上会创建侦听器。每个Pod都被添加为侦听器池的成员。Consilute-kube-manager会侦听基于服务标签或Pod标签的任何更改,并使用添加、更新或删除的Pod更新成员池列表。
服务的负载均衡是基于ECMP的4层原生、非代理的负载均衡。instance-ip(service-ip)链接到服务中每个Pod的端口。这将在Tungsten Fabric中创建一个ECMP下一跳,并且流量直接从源pod进行负载均衡。
用于Kubernetes Ingress的HAProxy 负载均衡器
Kubernetes Ingress是通过Tungsten Fabric中的HAProxy负载均衡器功能实现的。只要在Kubernetes中配置了入口,contrail-kube-manager就会在contrail-controller中创建负载均衡器对象。TF服务监视器将侦听负载均衡器对象,并根据主备模式下的入口规范规则以适当的配置启动HAProxy。
有关负载均衡器的更多信息,请参见:
https://www.juniper.net/documentation/en_US/contrail20/topics/task/configuration/lbaas-contrail3-F5.html
Kubernetes网络策略的安全组
Kubernetes网络策略是有关如何允许Pod组彼此通信,以及与其它网络端点进行通信的规范。NetworkPolicy资源使用标签来选择Pod,并定义允许列表规则,该规则除了对给定命名空间的隔离策略所允许的内容外,还允许对选定Pod的访问。
有关Kubernetes网络策略的更多信息,请参阅:
https://kubernetes.io/docs/concepts/services-networking/networkpolicies/
Contil-kube-manager侦听Kubernetes网络策略事件以创建、更新和删除,并将Kubernetes网络策略转换为应用于虚拟机接口(VMI)的Tungsten Fabric安全组对象。当添加和删除pod和标签时,VMI会动态更新。
Kubernetes对安全策略的支持
在Kubernetes环境中创建的网络策略,是通过使用Tungsten Fabric安全策略框架来实现的。Kubernetes环境中的标签(labels)在Tungsten Fabric中作为标签(tags)公开。从Tungsten Fabric 5.0版开始,你可以为Kubernetes环境定义标签。Tungsten Fabric安全策略使用这些标签来实现指定的Kubernetes策略。你可以在UI中定义标签或以JSON格式上传配置。新定义的标签可用于在TF Security中创建和实施策略。
域名服务器(DNS)
Kubernetes使用SkyDNS实施DNS,SkyDNS是一个小型DNS应用程序,可响应来自Pod的DNS请求以解析服务名称。SkyDNS在Kubernetes中作为pod运行。
支持的Kubernetes注释
当前,Tungsten Fabric支持以下Kubernetes注释:
代码语言:javascript复制'opencontrail.org/network': '{"domain":"default-domain", "project": "k8s-contrail", "name":"deu"}'
'opencontrail.org/isolation': 'true'
'opencontrail.org/fip-pool': '{"domain": "default-domain", "project": "k8s-default", "network": "k8s-default-svc-public", "name": "default"}'
有关更多详细信息,请参阅:
https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/.
验证Kubernetes的CNI配置
你可以使用下面的验证步骤,来查看和验证针对Kubernetes的Tungsten Fabric容器网络接口(CNI)的配置。
查看Pod名称和IP地址
使用以下命令查看分配给Pod的IP地址。
代码语言:javascript复制[root@device ~]# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
default client-1 1/1 Running 0 19d 10.47.25.247 k8s-minion-1-3
default client-2 1/1 Running 0 19d 10.47.25.246 k8s-minion-1-1
default client-x 1/1 Running 0 19d 10.84.21.272 k8s-minion-1-1
验证Pod的可达性
执行以下步骤,以验证各个pod是否可以相互到达。
1.确定pod的IP地址和名称。
代码语言:javascript复制[root@device ~]# kubectl get pods --all-namespaces -o wide
NAME READY STATUS RESTARTS AGE IP NODE
example1-36xpr 1/1 Running 0 43s 10.47.25.251 b3s37
example2-pldp1 1/1 Running 0 39s 10.47.25.250 b3s37
2.从源Pod去ping目标Pod,以验证Pod是否可达。
代码语言:javascript复制root@device ~]# kubectl exec -it example1-36xpr ping 10.47.25.250
PING 10.47.25.250 (10.47.25.250): 56 data bytes
64 bytes from 10.47.25.250: icmp_seq=0 ttl=63 time=1.510 ms
64 bytes from 10.47.25.250: icmp_seq=1 ttl=63 time=0.094 ms
验证隔离命名空间的Pod是否为不可访问
执行以下步骤,以验证非隔离命名空间中的pod是否无法访问隔离命名空间中的pod。
1.确定隔离命名空间中Pod的IP地址和名称。
代码语言:javascript复制[root@device ~]# kubectl get pod -n test-isolated-ns -o wide
NAME READY STATUS RESTARTS AGE IP NODE
example3-bvqx5 1/1 Running 0 1h 10.47.25.249 b3s37
2.确定非隔离命名空间中的Pod的IP地址。
代码语言:javascript复制[root@device ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
example1-36xpr 1/1 Running 0 15h
example2-pldp1 1/1 Running 0 15h
3.从非隔离命名空间中的Pod去ping隔离命名空间中的Pod的IP地址。
代码语言:javascript复制[root@device ~]# kubectl exec -it example1-36xpr ping 10.47.25.249
--- 10.47.255.249 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
验证非隔离命名空间的Pod是否为可以访问
执行以下步骤,以验证非隔离命名空间中的Pod是否可以访问非隔离命名空间中的Pod。
1.确定非隔离命名空间中Pod的IP地址。
代码语言:javascript复制[root@device ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
example1-36xpr 1/1 Running 0 15h 10.47.25.251 b3s37
example2-pldp1 1/1 Running 0 15h 10.47.25.250 b3s37
2.确定隔离命名空间中的Pod的IP地址和名称。
代码语言:javascript复制[root@device ~]# kubectl get pod -n test-isolated-ns -o wide
NAME READY STATUS RESTARTS AGE IP NODE
example3-bvqx5 1/1 Running 0 1h 10.47.25.249 b3s37
3.从隔离命名空间中的pod去ping非隔离命名空间中pod的IP地址。
代码语言:javascript复制[root@device ~]# kubectl exec -it example3-bvqx5 -n test-isolated-ns ping 10.47.25.251
PING 10.47.25.251 (10.47.25.251): 56 data bytes
64 bytes from 10.47.25.251: icmp_seq=0 ttl=63 time=1.467 ms
64 bytes from 10.47.25.251: icmp_seq=1 ttl=63 time=0.137 ms
^C--- 10.47.25.251 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.137/0.802/1.467/0.665 ms
验证命名空间是否隔离
命名空间注释用于打开Kubernetes命名空间中的隔离。在隔离的Kubernetes命名空间中,命名空间元数据使用opencontrail.org/isolation : true
标注进行注释。
使用以下命令查看命名空间上的注释。
代码语言:javascript复制[root@a7s16 ~]#
kubectl describe namespace test-isolated-ns
Name: test-isolated-ns
Labels: <none>
Annotations: opencontrail.org/isolation : true Namespace is isolated
Status: Active