前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >为OpenStack和K8s集群提供无缝虚拟网络

为OpenStack和K8s集群提供无缝虚拟网络

原创
作者头像
Tungsten Fabric
修改于 2021-01-13 02:03:04
修改于 2021-01-13 02:03:04
1.2K00
代码可运行
举报
运行总次数:0
代码可运行

在数据中心里,同时拥有OpenStack和Kubernetes集群的情况正变得越来越普遍。

一边是由OpenStack管理的虚拟机,另一边是由K8s控制的容器化工作负载。

现实情况下,可能会发生虚拟机和容器需要相互“交谈”的情况。如果是这样,我们需要以某种方式实现两个独立集群之间的通信。

作为两个不同的集群,每个集群都有自己的网络平面。OpenStack可能会依赖OVS,而Kubernetes则会部署某个可用的CNI。

由于每个集群都是独立于其它集群的,因此必须在第三个“元素”上启用通信。这第三个元素可以是IP Fabric。

虚拟机将通过提供商网络退出计算,并在VLAN内的IP Fabric上现身。容器也会做类似的事情。因此,我们可能最终会有两个VLAN,通过配置IP Fabric叶子节点(或spine节点)作为L2/L3 gw来允许它们相互对话。另外,L3 gw的角色可能会被委托给上层设备,比如SDN gw(在这种情况下,IP Fabric叶子节点/spine节点只会是L2 gw)。

这里的一个关键要点是,虚拟/容器化的工作负载成为underlay的一部分,使得服务平面(工作负载)和网络平面(IP Fabric)相互交错。

提供服务也需要在IP Fabric underlay进行配置。我们在探索数据中心使用Tungsten Fabric的优势时,谈到过这个概念,请见下面链接:

https://iosonounrouter.wordpress.com/2020/04/28/which-sdn-solution-is-better-what-i-learned/

同样的考虑在这里也适用,另外我们不仅需要连接虚拟机,还需要连接容器。

我们假设需要部署一个应用程序,其构件既有虚拟机又有容器。这意味着我们需要在OpenStack里部署一些对象,在Kubernetes里部署另外一些对象。从网络的角度来看,我们需要对OpenStack、K8s和IP Fabric进行操作。如果能简化这一点就好了。Tungsten Fabric来了!

TF可以与OpenStack和K8s一起工作(作为CNI)。当然,代码的某些部分是“编排器专用”的。我的意思是,TF一方面需要与Neutron/Nova进行交互,另一方面需要与K8s API和其它K8s组件进行交互。

总之,除了这些,解决方案的核心还是一样的!虚拟网络也还是VRF。工作负载也还是接口!不管我们的接口后面是虚拟机还是容器,对于Tungsten Fabric来说,它只是放到VRF中的一个接口。对于计算节点之间和通向SDN网关的overlay(MPLSoUDP、MPLSoGRE、VXLAN)也是一样的。

因此,让虚拟机与容器进行通信,只是在同一个VRF(虚拟网络)中放置接口的问题。这可以通过让一个实体来“控制”OpenStack和Kubernetes集群的虚拟网络来实现。这个实体就是我们最爱的TF Controller。

我们的数据中心将会是这样的:

如你所见,从配置的角度来看,集群还是有区别的。Kubernetes master控制容器,而OpenStack controller负责Nova虚拟机。

这里的关键变化在于Tungsten Fabric控制器(controller)的存在,它将与OpenStack计算节点和Kubernetes worker节点进行交互(仍然使用XMPP)。这样我们就为集群提供了一个单一的网络平面。

由于TF在overlay层工作,我们不再需要IP Fabric来“看到”虚拟机和容器。工作负载的流量被隐藏在overlay隧道中(无论是在计算节点之间,还是通向SDN网关……就像任何一个TF集群一样)。

拥有一个单一的网络平面还会带来其它优势。例如,TF将负责IP地址分配。假设我们有一个地址为192.168.1.0/24的虚拟网络。如果我们在该VN上创建一个虚拟机,TF将分配地址192.168.1.3。之后,如果我们在Kubernetes中创建一个容器,并将其连接到同一个VN,TF将分配地址192.168.1.4,因为它知道.3已经在使用。如果有两个不同的集群,实现这个功能需要额外的“工具”(例如配置静态分配池或让更高级别的编排器充当IPAM管理器角色)。Tungsten Fabric则简化了这种网络操作。

现在,理论已经说得够多了。让我们来看一个实际的例子!

我在一个虚拟实验室中构建了上述拓扑。为了部署Tungsten Fabric,我使用了Ansible部署器,它允许我们同时配置OpenStack和Kubernetes集群。我不会去详细介绍如何使用Ansible部署器安装TF(这里是一个部署K8s集群的例子);我假设对这个工具有预先的了解。

大家知道,Ansible部署器的核心是instances.yaml文件。下面是我使用的一个文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
###FILE USED TO DESCRIBE THE CONTRAIL CLOUD THAT ANSIBLE DEPLOYER HAS TO BUILD
global_configuration:
  CONTAINER_REGISTRY: hub.juniper.net/contrail
  CONTAINER_REGISTRY_USERNAME: xxx
  CONTAINER_REGISTRY_PASSWORD: yyy
provider_config:
  bms:
    ssh_user: root
    ssh_pwd: Embe1mpls
    ntpserver: 10.102.255.254
    domainsuffix: multiorch.contrail
instances:
  cnt-control:
    provider: bms
    ip: 10.102.240.183
    roles:
      config:
      config_database:
      control:
      webui:
      analytics:
      analytics_database:
      analytics_alarm:
  os-control:
    provider: bms
    ip: 10.102.240.178
    roles:
      openstack:
  os-compute:
    provider: bms
    ip: 10.102.240.171
    roles:
      vrouter:
        VROUTER_GATEWAY: 192.168.200.1
      openstack_compute:
  k8s-master:
   provider: bms
   roles:
      k8s_master:
      kubemanager:
   ip: 10.102.240.174
  k8s-worker:
   provider: bms
   roles:
     vrouter:
       VROUTER_GATEWAY: 192.168.200.1
     k8s_node:
   ip: 10.102.240.172
contrail_configuration:
  CLOUD_ORCHESTRATOR: openstack
  CONTRAIL_CONTAINER_TAG: 2008.121
  CONTRAIL_VERSION: 2008.121
  OPENSTACK_VERSION: queens
  ENCAP_PRIORITY: "VXLAN,MPLSoUDP,MPLSoGRE"
  BGP_ASN: 65100
  CONFIG_NODEMGR__DEFAULTS__minimum_diskGB: 2
  DATABASE_NODEMGR__DEFAULTS__minimum_diskGB: 2
  CONFIG_DATABASE_NODEMGR__DEFAULTS__minimum_diskGB: 2
  KUBERNETES_CLUSTER_PROJECT: {}
  KUBERNETES_API_NODES: 192.168.200.12
  KUBERNETES_API_SERVER: 192.168.200.12
  KUBEMANAGER_NODES: 192.168.200.12
  RABBITMQ_NODE_PORT: 5673
  KEYSTONE_AUTH_URL_VERSION: /v3
  VROUTER_GATEWAY: 192.168.200.1
  CONTROLLER_NODES: 10.102.240.183
  CONTROL_NODES: 192.168.200.10
  JVM_EXTRA_OPTS: "-Xms1g -Xmx2g"
  PHYSICAL_INTERFACE: "ens3f1"
kolla_config:
  kolla_globals:
    enable_haproxy: no
    enable_ironic: no
    enable_swift: no
    enable_barbican: no
  kolla_passwords:
    keystone_admin_password: contrail123
    metadata_secret: meta123

实例部分包括5台服务器

  • openstack controller
  • kubernetes master
  • contrail controller
  • openstack compute
  • kubernetes worker

如果你去看“contrail_configuration”部分,就会注意到我们配置TF是为了与openstack controller(KEYSTONE_AUTH_URL_VERSION)和kubernetes master(KUBERNETES_API_NODES)交互。

一旦所有节点都做好安装准备,从“deployer”节点(可以是contrail controller本身)运行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook -e orchestrator=openstack -i inventory/ playbooks/configure_instances.yml
ansible-playbook -e orchestrator=openstack -i inventory/ playbooks/install_openstack.yml
ansible-playbook -e orchestrator=openstack -i inventory/ playbooks/install_k8s.yml
ansible-playbook -e orchestrator=openstack -i inventory/ playbooks/install_contrail.yml

如果一切顺利的话,我们的集群应该可以运行了。

让我们连接到Tungsten Fabric GUI:

我们看到两个虚拟路由器:os-compute和k8s-worker!

我们看一下控制节点:

只有一个控制器!我们“单一网络平面”的关键概念变成了现实。

接下来,我创建了一个虚拟网络:

  • FQ名称:default-domain:k8s-contrail:seamless
  • CIDR:192.168.1.0/24

启动一个连接到该VN的虚拟机:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nova boot --image cirros2 --flavor cirros --nic net-id=<seamless_uuid> vm
(kolla-toolbox)[ansible@os-control /]$ nova list
+--------------------------------------+------+--------+------------+-------------+------------------------+
| ID                                   | Name | Status | Task State | Power State | Networks               |
+--------------------------------------+------+--------+------------+-------------+------------------------+
| 3cf82185-5261-4b35-87bf-4eaa9de3caaf | vm   | ACTIVE | -          | Running     | seamless=192.168.100.3 |
+--------------------------------------+------+--------+------------+-------------+------------------------+

接下来,创建一个连接到该VN的容器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@k8s-master ~]# cat cn.yaml
---
kind: Namespace
apiVersion: v1
metadata:
  name: seamless
  annotations:
    'opencontrail.org/network' : '{"domain":"default-domain", "project": "k8s-contrail", "name":"seamless"}'
  labels:
    name: seamless
---
apiVersion: v1
kind: Pod
metadata:
  name: cont
  namespace: seamless
spec:
  containers:
  - name: cont
    image: alpine
    command: ["tail"]
    args: ["-f", "/dev/null"]
kubectl apply -f vn.yaml
[root@k8s-master ~]# kubectl get pod -n seamless -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
cont   1/1     Running   0          74s   192.168.100.4   k8s-worker   <none>           <none>
[root@k8s-master ~]# kubectl get -f cn.yaml -o wide
NAME                 STATUS   AGE
namespace/seamless   Active   31m
NAME       READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
pod/cont   1/1     Running   0          31m   192.168.100.4   k8s-worker   <none>           <none>

如你所见,由于192.168.100.3已经被VM占用了,pod被分配了192.168.100.4的IP地址。这也是多个集群使用单一网络平面的优势之一。

让我们从GUI中查看一下路由表:

两个IP都有!我们刚刚把一个虚拟机连接到一个工作负载上……而这对underlay是完全透明的!

让我们再到worker节点,查看一下vRouter代理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(vrouter-agent)[root@k8s-worker /]$ vif --get 3
Vrouter Interface Table
vif0/3      OS: tapeth0-11ccbe NH: 51
            Type:Virtual HWaddr:00:00:5e:00:01:00 IPaddr:192.168.100.4
            Vrf:4 Mcast Vrf:4 Flags:PL3L2DEr QOS:-1 Ref:6
            RX packets:67  bytes:2814 errors:0
            TX packets:87  bytes:3654 errors:0
            Drops:67
(vrouter-agent)[root@k8s-worker /]$ rt --get 192.168.100.3/32 --vrf 4
Match 192.168.100.3/32 in vRouter inet4 table 0/4/unicast
Flags: L=Label Valid, P=Proxy ARP, T=Trap ARP, F=Flood ARP
vRouter inet4 routing table 0/4/unicast
Destination           PPL        Flags        Label         Nexthop    Stitched MAC(Index)
192.168.100.3/32        0           LP         25             39        2:85:bf:53:6b:67(96024)
(vrouter-agent)[root@k8s-worker /]$ nh --get 39
Id:39         Type:Tunnel         Fmly: AF_INET  Rid:0  Ref_cnt:8          Vrf:0
              Flags:Valid, MPLSoUDP, Etree Root,
              Oif:0 Len:14 Data:56 68 a6 6f 05 ff 56 68 a6 6f 06 f7 08 00
              Sip:192.168.200.14 Dip:192.168.200.13

所有的路由信息都在那里!容器可以通过连接Kubernetes worker节点和OpenStack计算节点的MPLSoUPD隧道到达虚拟机。

这样就可以进行通信了吗?还不行!别忘了安全组还在那里!

虚拟机属于一个OpenStack项目(这里是管理项目),而容器属于另一个项目(映射到Kubernetes命名空间)。每个项目都有自己的安全组。默认情况下,安全组只允许来自属于同一安全组的入口流量。由于两个工作负载的接口被分配到不同的安全组,因此它们之间不允许对话!

为了解决这个问题,我们需要对安全组采取行动。

简单的方法是在两个安全组上都允许来自0.0.0.0/0的入口流量(这是容器安全组,但同样也可以在虚拟机安全组上进行):

另外,我们也可以在入口方向允许特定的安全组。

例如,在k8s-seamless-default-sg(容器所属命名空间/项目的安全组)上,我们允许默认安全组(虚拟机所属OpenStack项目的安全组)。

同样地,也可以在分配给虚拟机接口的安全组上进行:

现在,让我们访问容器,并且ping一下虚拟机:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@k8s-worker ~]# docker ps | grep seaml
18c3898a09ac        alpine                                                         "tail -f /dev/null"      9 seconds ago       Up 8 seconds                            k8s_cont_cont_seamless_e4a7ed6d-38e9-11eb-b8fe-5668a66f06f8_0
6bb1c3b40300        k8s.gcr.io/pause:3.1                                           "/pause"                 17 seconds ago      Up 15 seconds                           k8s_POD_cont_seamless_e4a7ed6d-38e9-11eb-b8fe-5668a66f06f8_0
[root@k8s-worker ~]# docker exec -it 18c38 sh
/ # ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:e4:e5:52:ce:38 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.4/24 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 192.168.100.3
PING 192.168.100.3 (192.168.100.3): 56 data bytes
64 bytes from 192.168.100.3: seq=0 ttl=64 time=3.813 ms
64 bytes from 192.168.100.3: seq=1 ttl=64 time=1.802 ms
64 bytes from 192.168.100.3: seq=2 ttl=64 time=2.260 ms
64 bytes from 192.168.100.3: seq=3 ttl=64 time=1.945 ms
^C
--- 192.168.100.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 1.802/2.455/3.813 ms
/ #

就是这样!虚拟机和容器可以互相对话了!

无论你的工作负载是虚拟机还是容器……至少从网络的角度来看,一切都是在Tungsten Fabric的机制下进行的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
十、HikariCP源码分析之ConcurrentBag三
一般我们都是通过 Spring 来使用 HikariCP 的,自己动手启动一个连接池的机会还是少。在 Spring 中使用非常方便,一切都是 Spring 帮我们搞定,我们只管使用,所以需要将连接还回连接池的机会也比较少,也有可能你是间接用过,比如从 HikariCP 中借用的连接,用完之后调用了 close方法,连接其实并没有真正的被关闭,而是还回了连接池,真正的close方法被 HikariCP 重写了。其实这是一个至关重要的方法,如果借用出去的连接,不通过这个方法还回来,会导致内存泄露的。
用户1422411
2022/06/25
4490
九、HikariCP源码分析之ConcurrentBag二
OK,我们继续。这里遍历的 list 变量,是threadList,是当前线程使用过的连接,保存在本地线程的引用。
用户1422411
2022/06/25
4130
【追光者系列】HikariCP 源码分析之 allowPoolSuspension
摘要: 原创出处 https://mp.weixin.qq.com/s/-WGg22lUQU41c_8lx6kyQA 「渣渣王子」欢迎转载,保留摘要,
芋道源码
2018/07/31
1.2K0
基于HiKariCP组件,分析连接池原理
HiKariCP作为SpringBoot2框架的默认连接池,号称是跑的最快的连接池,数据库连接池与之前两篇提到的线程池和对象池,从设计的原理上都是基于池化思想,只是在实现方式上有各自的特点;首先还是看HiKariCP用法的基础案例:
知了一笑
2022/04/18
8630
基于HiKariCP组件,分析连接池原理
【追光者系列】HikariCP源码分析之ConcurrentBag
HikariCP contains a custom lock-free collection called a ConcurrentBag. The idea was borrowed from the C# .NET ConcurrentBag class, but the internal implementation quite different. The ConcurrentBag provides…
用户1655470
2018/07/24
1.3K0
【追光者系列】HikariCP源码分析之ConcurrentBag
读懂HikariCP一百行代码,多线程就是个孙子!
通常,我在看书的时候一般不写代码,因为我的脑袋被设定成单线程的,一旦同时喂给它不同的信息,它就无法处理。
xjjdog
2022/12/22
4970
读懂HikariCP一百行代码,多线程就是个孙子!
干掉Druid,HakariCP 为什么这么快?
Springboot 2.0将 HikariCP 作为默认数据库连接池这一事件之后,HikariCP 作为一个后起之秀出现在大众的视野中。HikariCP 是在日本的程序员开源的,hikari日语意思为“光”,HikariCP 也以速度快的特点受到越来越多人的青睐。
码猿技术专栏
2024/01/29
2800
干掉Druid,HakariCP 为什么这么快?
【追光者系列】HikariCP源码分析之evict、时钟回拨、连接创建生命周期
evict定义在com.zaxxer.hikari.pool.PoolEntry中,evict的汉语意思是驱逐、逐出,用来标记连接池中的连接不可用。
用户1655470
2018/07/24
2.9K0
【追光者系列】HikariCP源码分析之evict、时钟回拨、连接创建生命周期
【源码分析】SpringBoot2中取代Druid的超级连接池:HikariCP之ConcurrentBag
HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池。
Java_老男孩
2020/07/27
1.2K0
【追光者系列】HikariCP源码分析之故障检测那些思考 fail fast &amp; allowPoolSuspension
由于时间原因,本文主要内容参考了 https://segmentfault.com/a/1190000013136251,并结合一些思考做了增注。
用户1655470
2018/07/24
1.4K0
SpringBoot官方为什么采用这个数据库连接池?史上最快?
现在已经有很多公司在使用HikariCP了,HikariCP还成为了SpringBoot默认的连接池,伴随着SpringBoot和微服务,HikariCP 必将迎来广泛的普及。
macrozheng
2021/07/27
9610
SpringBoot官方为什么采用这个数据库连接池?史上最快?
MySQL 连接挂死了!该如何排查?
近期由测试反馈的问题有点多,其中关于系统可靠性测试提出的问题令人感到头疼,一来这类问题有时候属于“偶发”现象,难以在环境上快速复现;二来则是可靠性问题的定位链条有时候变得很长,极端情况下可能要从 A 服务追踪到 Z 服务,或者是从应用代码追溯到硬件层面。
程序员小富
2022/12/10
3.4K0
MySQL 连接挂死了!该如何排查?
十一、HikariCP源码分析之HouseKeeper
HouseKeeper是一个HikariPool的内部类,它实现了Runnable接口,也就是一个线程任务。这个任务是由ScheduledThreadPoolExecutor类型的线程池执行的,也就是说它是一个定时任务。我们在《HikariCP源码分析之初始化分析二》中分析 HikariCP 初始化的时候,遇到了houseKeepingExecutorService的初始化,简单分析了它的初始化过程,但是这个任务是非常重要的,我们要仔细分析一下。
用户1422411
2022/06/25
1.6K0
HikariPool一直报连接不可用
一开始发现测试环境报错,原先配置6现在配置20依然还是很频繁的报错,想看下底层到底如何处理的导致这个问题,到底什么情况。
查拉图斯特拉说
2023/10/25
9890
HikariPool一直报连接不可用
二、HikariCP获取连接流程源码分析二
在上一篇《HikariCP获取连接流程源码分析一》中,我们分析了HikariDataSource的getConnection()方法,而这个方法,其实详细的实现细节都是在HikariPool的getConnection()方法中,我们来分析下HikariPool的getConnection()方法。
用户1422411
2022/06/25
8320
java应用最好的数据源 Hikari?
DBCP是Apache推出的数据库连接池(Database Connection Pool)。
冯杰宁
2019/12/16
2.8K0
java应用最好的数据源 Hikari?
三、HikariCP获取连接流程源码分析三
这里涉及到 HikariCP 的一个设计点,HikariCP的连接不是实时从连接池里剔除的,只是给连接上打个标记而已,都是在获取连接的时候检查是否可用,如果不可用的时候才直接从连接池里删除。如果在 HikariCP的任何地方都可能剔除连接,那么剔除连接的地方会比较多,会很乱,也容易引发 bug。反之,把剔除链接的操作收缩到某几个固定的逻辑中,就比较好管理。
用户1422411
2022/06/25
1.1K0
Java 数据持久化系列之 HikariCP (一)
在上一篇《Java 数据持久化系列之池化技术》中,我们了解了池化技术,并使用 Apache-common-Pool2 实现了一个简单连接池,实验对比了它和 HikariCP、Druid 等数据库连接池的性能数据。在性能方面,HikariCP遥遥领先,而且它还是 Spring Boot 2.0 默认的数据库连接池。下面我们就来了解一下这款明星级开源数据库连接池的实现。
程序员历小冰
2020/04/14
1.2K0
Java 数据持久化系列之 HikariCP (一)
五、HikariCP源码分析之初始化分析二
在上一节,我们说到了pool = fastPathPool = new HikariPool(this);中的new HikariPool(this)。我们来看下代码:
用户1422411
2022/06/25
7000
【追光者系列】HikariCP连接池监控指标实战
业务方关注哪些数据库指标? 首先分享一下自己之前的一段笔记(找不到引用出处了) 系统中多少个线程在进行与数据库有关的工作?其中,而多少个线程正在执行 SQL 语句?这可以让我们评估数据库是不是系统瓶颈。 多少个线程在等待获取数据库连接?获取数据库连接需要的平均时长是多少?数据库连接池是否已经不能满足业务模块需求?如果存在获取数据库连接较慢,如大于 100ms,则可能说明配置的数据库连接数不足,或存在连接泄漏问题。 哪些线程正在执行 SQL 语句?执行了的 SQL 语句是什么?数据库中是否存在系统瓶颈或已经
芋道源码
2018/06/13
6.5K0
推荐阅读
相关推荐
十、HikariCP源码分析之ConcurrentBag三
更多 >
LV.2
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档