Group Details Private

Global Moderators

Forum wide moderators

Member List

  • Tungsten Fabric入门宝典丨TF组件的七种“武器”

    作者:Tatsuya Naganawa 译者:TF编译组

    Tungsten Fabric入门宝典系列文章,来自技术大牛倾囊相授的实践经验,由TF中文社区为您编译呈现,旨在帮助新手深入理解TF的运行、安装、集成、调试等全流程。如果您有相关经验或疑问,欢迎与我们互动,并与社区极客们进一步交流。更多TF技术文章,请点击公号底部按钮>学习>文章合集。
    

    df4e62a1-34a3-4d32-a523-4acc382e4a45-image.png
    Tungsten Fabric中有很多不同的组件。接下来我简要描述它们的用法。

    概览

    总体而言,Tungsten Fabric中包含7种角色和(多达)30个微服务,其中角色部分如下:

    • vRouter
    • control
    • config
    • config-database
    • analytics(从TF 5.1开始,可被进一步分为analytics、analytics-snmp和analytics-alarm)
    • analytics-database
    • webui

    尽管组件很多,但在简单的用例中,只需要4种角色:vRouter,control,config,config-database。当然在大多数情况下,webui也是需要的。

    如果你只对Tungsten Fabric的控制平面/数据平面部分感兴趣,也可以省略analytics。只是在这种情况下,某些功能(如v1服务链,haproxy负载均衡器及k8s ingress,SNAT等)将无法正常工作。

    control, vRouter

    Control和vRouter构成了Tungsten Fabric的控制平面和数据平面,因此可以说,这是Tungsten Fabric系统最重要的部分。

    由于control和vRouter都在内部使用MPLS-VPN,因此我建议至少在深入研究它们的细节之前,先略读一下这些材料:

    由于大多数高级功能都在control当中,而vRouter是MPLS所固有的,因此这些资料将有助于弄清它们正在尝试做些什么。

    由于control和vrouter-agent都在内部使用VPNV4 BGP,因此vRouter及其内部VRF将根据extended community属性(也称为路由目标route-target)装载所需的前缀。因此,在vRouter上创建容器或虚拟机时,它可以将VPNV4路由的信号发送给control,并将所有路由映射到其它的vRouter,从而数据平面可以知道自动将报文发送到何处。

    有趣的是,vRouter的虚拟网络可能具有多个默认网关,并且具有相同的IP和相同的MAC!(用Junos的术语来说,与virtual-gateway-address的行为类似。)

    由于不需要VRRP来为每个虚拟网络提供默认网关,因此它消除了瓶颈,并使一切变得完全分布式。

    vRouter还可以为某些功能(例如基于状态的防火墙、NAT、基于流的ECMP等)进行基于流的处理。这是一个重要的区别,因为这种行为会引入一些调整点,例如每秒的连接数和最大流数。(在基于包的系统中,PPS(每秒数据包)和吞吐量(以及某些情况下的延迟)是关键。)如果这些参数对你的系统非常重要,也许你还需要检查这些参数。

    注意:可以选择在“ports”配置中使用“packet-mode”参数禁用此行为。

    config

    Config同样包含几个组件。Config-api为Tungsten Fabric的配置提供了一个API端点,该端点使用了许多组件,例如control、analytics等。

    vRouter不会直接使用它,因为只有需要的数据才会(通过XMPP)由control传递。

    其中,schema-transformer和svc-monitor这两个进程做的事情都很重要,所以让我对其进行详细描述。

    schema-transformer

    这个进程将logical-router、network-policy、service-chain等一些抽象的config参数转换为L3 VPN的语言。它是Tungsten Fabric的核心组件之一,完成了MPLS-VPN不能简单解释的大部分工作。

    例如,logical-router在内部创建一个新的route-target ID,该ID将具有虚拟网络的所有前缀。因此,如果将虚拟网络连接到logical-router,它将接收logical-router所具有的所有路由。该行为在内部使用MPLS-VPN,但route-target配置由schema-transformer控制。

    因此,配置以下面的方式传送到数据平面:

    edit config -> (rabbitmq) -> schema-transformer, which creates new route-target -> (internally edit config) -> (rabbitmq) -> control -> (xmpp) -> vrouter-agent -> (netlink) -> vrouter.ko
    

    Schema-transformer还负责与服务链(service-chain)相关的所有事情。我不会深入研究服务链的所有细节,因为这并没有简单的DC用例(即使AWS VPC当前也不提供类似的服务)。尽管,从内心来说,这是对VRF收到的所有前缀的有趣处理,并且我个人认为值得一读。

    注意:你可以在书中获得所有详细信息。https://mplsinthesdnera.net/

    svc-monitor

    这个进程提供了一些服务,这些服务必须在内部使用外部进程,例如haproxy负载均衡器,基于nova API的v1服务链实例,用于SNAT的iptables MASQUERADE等。

    在内部,vrouter-agent具有一些逻辑来启动haproxy或设置iptables MASQUERADE,当相关服务被定义的时候,svc-monitor将启动这些逻辑。

    Svc-monitor选择一些vRouter来创建这些服务,实例化一些网络功能并对这些元素进行流量处理。在使用analytics-api的输出(analytics/uves/vrouter)中选择一个,然后选点击“Functional”。

    尽管将来的版本可能会改变,但是目前这样的行为是Tungsten Fabric安装时需要analytics的原因之一。

    config-database

    Tungsten Fabric使用多个数据库。大部分数据都保存在Cassandra中,如果发生了更改,将通知RabbitMQ更改的内容以传递到其它组件,例如control、schema-transformer、svc-monitor等。

    ZooKeeper仅用于需要锁定以保持一致性的操作。例如,创建一个端口需要分配一个IP地址,其一致性由ZooKeeper来管理,因此IP地址分配始终是一对一的。

    nodemgr

    我认为到目前为止,大多数重要组件都已涵盖,因此我将介绍其它部分。首先来看一下nodemgr是什么。

    Nodemgr基本上是每个节点状态的源头,因此它检查使用情况、docker ps或CPU的使用情况,并发送analytics UVE NodeStatus。

    该值可能是contrail-status以及其它逻辑(例如analytics-alarm或svc-monitor)的来源,它们在选择vRouter时会检查此值是否为Functional。保持这些Functional的状态,对确保Tungsten Fabric正常运行非常重要。

    如果分配了不同的角色,则此组件的行为会有所不同。因此,它会以不同的行为安装在每个节点上。

    另外,它还会对每个节点进行第一次配置(provision),这意味着要通知config-api该IP已分配了xxx角色。因此,即使不需要analytics功能,该模块也必须存在,至少在第一次启动节点时。

    device-manager

    此过程用于配置physical-router(基于config-database中的对象)。

    在内部,它使用与schema-transformer和svc-monitor相同的逻辑,它们订阅RabbitMQ以查看config是否被更改,当发生更改时,AMQP客户端会启动一些逻辑:

    • 对于schema-transformer,它将更新更多config;
    • 对于svc-monitor,它将在vRouters中添加一些逻辑;
    • 对于device-manager,它将更新physical-router的配置。

    此行为由reaction_map控制,它定义了某些config对象上的某些更改会怎样传递到其它的配置上进行更改。

    例如,当更新bgp-router时,

    'bgp_router': {
               'self': ['bgp_router', 'physical_router'],
               'bgp_router': ['physical_router'],
               'physical_router': [],
              },
    

    基于“self”的定义,它将通过对原始bgp-router对象的引用,传递到bgp-router和physical-router。

    • 对于bgp-router,表示与原始bgp-router所对等(peer)的bgp-router对象

    之后,更新的bgp-router会将其传递到bgp-router对象所在的physical-router。

    'bgp_router': {
               (snip)
               'bgp_router': ['physical_router'],
               (snip)
              },
    

    由于从bgp-router传递事件时,physical-router不会更新任何内容,因此事件在那里停止,并且具有原始bgp-router的physical-router config以及对等(peer)的bgp-router将被更新。

    'physical_router': {
              (snip)
              'bgp_router': [],
              (snip)
    },
    

    当physical-router收到更新的事件时,它将从插件中调用push_conf函数,基于config-database中的对象创建路由config。

    要启用此功能,需要在/etc/contrail/common_config.env中配置此旋钮:DEVICE_MANAGER__DEFAULTS__push_mode = 0。

    以下链接描述了配置过程:
    https://www.juniper.net/documentation/en_US/contrail5.0/topics/concept/using-device-manager-netconf-contrail.html

    analytics

    Tungsten Fabric analytics具有很多功能,但大部分功能都是可选的,因此我会跳过大多数的组件。如果有兴趣,请查阅以下链接以获取SNMP、LLDP、警报等的信息:

    Analytics本身具有有趣的架构,其中涵盖了logs、flows和stats。

    • 据我所知,它们通常涉及不同的系统,例如用于logs/flows的EFK和用于stats的Prometheus。

    如果你需要一个工具,方便地使用所有系统,Tungsten Fabric analytics将是一个很好的选择。

    大多数重要的指标和分析服务都被标记为UVE(用户可见实体),并具有一个URL以提供JSON格式的数据。

    • http://(analytics-ip):8081/analytics/uves 提供了所有可提供的数值。

    如果你需要将Tungsten Fabric与其它监视系统集成在一起,那可能是一个很好的起点。

    analytics-database

    Analytics还使用了多个数据库,例如Redis、Cassandra、Kafka(在内部,它还使用ZooKeeper进行HA选件的部署)。

    如果仅使用analytics,则仅需要Redis数据库,即使在此设置中,大多数webui功能都是可用的。

    • 大多数可视化的功能都使用UVE,因此即使未安装Cassandra也是可用的。

    如果你需要webui的“Query”功能,则需要使用Cassandra,该功能可检索Cassndra数据库中的logs/flows或stats信息。

    Kafka用于将UVE传递到analytics-alarms,因此,如果要使用警报功能,Kafka是必要的。

    webui

    最后,我们来说说webui。基本上,这就只是一个简单的webui,用于查看组件的状态,并配置Tungsten Fabric的参数。

    它使用AJAX行为来更新一些需要对analytics-api进行长时间查询的图形(例如Monitor > Dashboard access),同时由webui-job进程涵盖了异步作业,这一点还挺有趣的。

    Tungsten Fabric入门宝典系列文章——

    1.首次启动和运行指南

    Tungsten Fabric 架构解析系列文章——

    第一篇:TF主要特点和用例
    第二篇:TF怎么运作
    第三篇:详解vRouter体系结构
    第四篇:TF的服务链
    第五篇:vRouter的部署选项
    第六篇:TF如何收集、分析、部署?
    第七篇:TF如何编排
    第八篇:TF支持API一览
    第九篇:TF如何连接到物理网络?
    第十篇:TF基于应用程序的安全策略

    posted in 博客
  • 揭秘LOL背后的IT基础架构丨开发者“打野”工具能做什么?

    作者:Maxfield Stewart(文章来源:Riot Games)译者:TF编译组

    欢迎来到Tungsten Fabric用户案例系列文章,一起发现TF的更多应用场景。“揭秘LOL”系列的主人公是Tungsten Fabric用户Riot Games游戏公司,作为LOL《英雄联盟》的开发和运营商,Riot Games面临全球范围复杂部署的挑战,让我们一起揭秘LOL背后的“英雄们”,看他们是如何运行在线服务的吧。
    

    9fa9ca70-02ce-4b61-bb69-80ce0f3a002b-image.png
    在上一篇文章中,我们讨论了支持服务的生态系统,使我们能够在生产环境中运行微服务。如果说微服务是我们的“核心”,那些工具是“辅助”,那我们的“打野”呢?这就要介绍我们用于集群管理的开发者生态系统了。在过去的文章中,我们已经讨论了一些工具,例如build farm和使用容器来构建容器的策略,这里就不再过多介绍细节了。

    还记得上篇文章那个Web小部件吗?它可以辅助引导工程师们使用工具生态系统:

    023fc51d-3c7f-4f30-afa8-5dfaf6832ebb-image.png

    我们已经介绍了其中的一些应用程序:JFrog的Artifactory,用于图像存储和全局复制;Discovery用于发现服务;Metrics和Jenkins用于自动化和连续交付需求。当然,里面还有更多应用程序可以探索!

    我没时间去覆盖所有内容,但是这个小部件是个不错的起点。现在,我们来看看在生态系统管理的其他关键领域提供帮助的工具。这些工具使我们能够:

    1.检查和可视化全局容器集群上正在运行的内容(Toolbox)
    2.轻松处理复杂的软件网络规则(network.rcluster)
    3.在全球范围内查询我们的服务来弄清楚什么在哪里(Service Discovery)
    4.跟踪构建和部署(Buildtracker)

    这些工具使我们能够处理数十个全球容器集群,并帮助我们管理Riot的规模感。要了解这一点,最好的起点是使用Toolbox。

    可视化管理集群

    下面是我们的容器可视化工具Toolbox的截图。之前我们讨论过Admiral的调度程序。下图是来自调度程序的API数据的直观结果。可以看到我们的全球集群,数一下,有16个集群,以它们的部署区域命名。Riot的集群遍布全球,分布在中国台北、雅加达、迈阿密、阿姆斯特丹,韩国和日本等地。

    c0a97130-d686-415d-b49d-b2305fa6d29f-image.png

    你可以一目了然地看到,我们正在运行超过2,400个各种应用程序的实例,我们称这些为“打包”。这在全球范围内转化为超过5,000个Docker容器。这些打包在过去一两年中都变得很活跃,正如我在Riot开发大量软件之前所说的那样。上面这些甚至不代表Riot运行的所有服务,而只是我们选择在容器中运行的服务。

    Toolbox不仅提供全局视图,我们还可以深入研究任何一个数据中心并查看其中正在运行的数据。

    17fbbcca-9d25-4439-ad82-0e30eaf0a80a-image.png

    我无法在一个屏幕快照中向你展示所有内容,但是通过在阿姆斯特丹的系统的简单视图,我们可以看到正在运行的应用程序数量。在这里,我们可以查看underlay和overlay服务,这些服务旨在简化将计算节点与调度程序和生态系统相集成起来。我们还可以轻松地查看诸如节点分配、打包状况的状态灯,以及哪些应用程序正在向Discovery报告的信息。开发人员和运营人员可以使用它轻松访问全局视图,了解其服务的运行方式。

    可以通过深入研究基本服务,来找到更多的详细信息。让我们看一看我自己拥有和运营的一项服务:Summoner服务。这有助于处理Riot服务(就像Chat和Developer API门户一样的第三方开放的API)的Summoner API流量。

    命名空间和作用域系统决定着我们如何处理应用程序。下图演示了这一点,其中Toolbox按单个应用程序和作用域进行筛选。在这种情况下,我们可以查看应用程序作用域“platform.summonercore”。可以看到该应用程序是如何分发的,包括它如何在AMS1中使用多个部署作用域。比如你可以看到“lolriot.ams1.rusummoner”和“lolriot.ams1.tr1summoner”正在分别支持俄罗斯和土耳其地区的部署。

    2ed14ecc-bef2-49d6-9a7d-64b6e56a9331-image.png

    右边栏包含一些其它信息,例如打包中的容器数量、IP地址、基本状态、日期信息,以及其它详细的信息。用户甚至可以检查容器日志。

    2eb79c1a-6175-411b-b957-881832dc13a6-image.png

    在这张图片中可以看到我最喜欢的功能之一。在加载日志的同时,出现了跳舞的卡特琳娜的gif图。是的伙计们,跳舞的卡特琳娜是我们内部的一个梗,她出现在各种内部工具的加载屏幕中。
    替代文字

    我们在Toolbox中的指标度量系统是一站式的,可提供诸如服务状态和位置的核心服务信息。如果出现问题,此系统使我们能够立即开始分流。用户还可以获取快照,如下图所示:
    f586dcc7-e43f-4395-aa86-b0a64f7a0e76-image.png

    管理复杂的网络规则

    在本系列第一篇文章中,我们讨论了如何使用Tungsten Fabric和JSON配置文件对网络进行基于软件的控制。JSON很酷,但是凝视它足够长的时间,也会使你的眼睛流血。为了帮助我们的工程师,我们构建了一个可视化工具,并选择了非常原始的名称“network.rcluster”。

    0395f583-d466-46a5-9efb-51c5d6d6eab8-image.png

    当你登录时,会看到一排排的小部件,表示我们已在整个集群中全局应用的网络规则。其中的每一个都由JSON配置blob作为支撑。让我们仔细看一下前面提到的Summonercore应用。

    03ee8f82-473a-4a4b-b5a6-5c05ab44e83a-image.png

    乍一看,这并不是什么令人兴奋的东西,只是部署作用域的列表而已。实际上,它是该应用程序作用域的框架。我们可以看到Summoner具有适用于广泛部署作用域的网络规则。考虑到Summoner运行在我们拥有《英雄联盟》的任何一个地方,这是很有道理的。

    我们选择其中一个,就应该能够看到Summoner的访问权限。

    a2cf36bd-e205-4914-b24d-8c61edd41b3c-image.png

    这里有很多条路由。使用这个工具,我们可以检查正在使用中的端口,并查看所有入站和出站连接。再说一遍,这有我们最喜欢的应用程序作用域的框架。如果你有敏锐的眼光,你会发现Summoner被允许与我们的“rtp.collector”通信,该调用会返回到我之前提到的指标。另一个连接是“infrastructurous.discoverous”,这是我们的发现服务。这个特定的屏幕截图来自于QA环境,因此你可以看到一些测试应用程序。

    在全球范围内查询

    运行如此多的软件,其中一个挑战是,有时你无法掌握部署的位置。我们可以使用诸如Toolbox之类的工具,来手动遍历每个集群并筛选应用名称,但是Toolbox仅向我们显示正在运行的打包和容器。许多传统的Riot软件都已部署到物理机上(多么传统),我们也希望能够搜索到那些应用程序。

    这就是查询服务或信息聚合器能派上用场的地方。我们拥有一个创造性的工具,命名为“services.rcluster”,该工具使我们可以指定各种基于上下文的搜索。这是我使用此工具查找刚才看到的所有全球Summoner服务的截图。

    21bd04d9-5a5e-4f2f-8fc9-2f7192df2f7e-image.png

    查询服务与服务发现工具是不同的。相反,它使用基于上下文的搜索来查询没有被发现的服务。例如,当你只记得“platform.summonercore”中的字符串“summoner”时,它可以抓取我们的Admiral调度程序的部署,来匹配字符串并返回到相关命令中。它是以人为本的搜索工具,可以适应人为的缺陷。

    在这里,你也可以看到“位置”列,该列引用了我们命名作用域的部署部分。列中的服务名称是应用程序作用域。

    跟踪构建

    到目前为止,我们已经研究了如何管理生产环境中运行的东西。但大多数软件的生命周期,在它们投入生产之前就已经开始了。当你每年使用超过一百万种软件构建时,如果没有根据时间查看事件的能力,就会遇到麻烦。

    来介绍Buildtracker——这个工具是另一个由API/网络驱动的工具,团队可以选择自动或手动的方式发布和查询数据。当软件从代码转换为服务时,这使他们可以跟踪这个软件。

    807d26d5-8c5d-46e8-be2c-b35aea0cf4fb-image.png

    这是我们第一次公开讨论这个工具,但是使用它已经有大约三、四年的时间了,甚至比我们转向微服务还要早。

    我们构建和扩展了大量的软件,真心不希望团队为跟踪这些构建,去抓取数千行的构建和管道日志。Buildtracker为持续集成系统(或任何自动化/部署系统)提供了一个干净的API,用于添加、标记和查询任何内部版本的变更列表和工件。

    当团队决定构建一个服务时,可以生成微服务构建管道。团队还可以创建自己的构建管道,并使用此API进行跟踪。然后,他们可以在其构建中搜索如下结果:

    a9fb0427-5b50-4146-9314-74fa0089cbc2-image.png

    上图是在Buildtracker工具中我们的配置服务条目的截图。我们为很多个筛选器构建了不同的风格,例如给定的变更列表,构建时间,使用的版本号以及各种标签。这些标记跟踪几种行为,包括构建工件所部署的环境(红色),以及通过的QA事件(灰色)。团队可以使用Buildtracker标签,将各种版本的构建标记为“QA Passed”。然后,他们可以标记仅检索QA Passed构建的步骤,例如部署作业。通过这个过程,团队可以创建受信任的持续交付管道,以确保它们仅部署已通过质量检查的项目。

    即使团队没有完全采用此过程,他们仍然可以通过一目了然的参考信息,来访问有关构建的宝贵历史。

    8b9dd992-772a-4d23-a9a3-6dffe059986d-image.png

    该页面包含到工件存储的路径,到构建作业的链接,以及发生的各种事件的时间表。Buildtracker中的“发布管理”视图使我们能够查看使用此类元数据为团队提供的全部功能:

    d1b70355-e5d4-406a-bbe4-fa6c8ed1015a-image.png

    这张图只是发行团队中用于管理《英雄联盟》发行版本的其中一个存储桶的快照。客户端、游戏服务器、音频包和服务都可以包含在这些列表中。你还可以看到许多标签,它们反映了补丁程序、环境、QA流程等。

    当你构建数百个服务和应用程序时,这样的数据聚合器确实可以帮助你理解流程,并提供一些版本管理控制。

    结论

    我们在文章中介绍的很多生态系统工具,都是自动地为团队工作,另外一些是选择加入的技术,团队可以选择使用它们,或者自己来做。我们的总体策略是,如果工具和技术足够有用,那么团队将使用它们,而不是构建自己的解决方案。这营造了一种灵活、敏捷的氛围,使我们能够专注于为真正渴望或需要它们的团队创建并支持最有价值的工具。例如,一个团队可能使用Service Discovery,但选择在构建时静态配置其应用程序,或者从不存储机密信息,或者使用我们提供的几乎所有内容但构建自己的解决方案来跟踪构建。

    最终,这些工具使每个服务创建者和产品团队都能够充分利用他们所需的功能,将其功能尽快交付给玩家,同时又能保持很高的质量。

    更多“揭秘LOL”系列文章
    揭秘LOL背后的IT基础架构丨踏上部署多样性的征程
    揭秘LOL背后的IT基础设施丨关键角色“调度”
    揭秘LOL背后的IT基础架构丨SDN解锁新基础架构
    揭秘LOL背后的IT基础架构丨基础设施即代码
    揭秘LOL背后的IT基础架构丨微服务生态系统

    posted in 博客
  • Tungsten Fabric入门宝典丨首次启动和运行指南

    作者:Tatsuya Naganawa 译者:TF编译组

    Tungsten Fabric入门宝典系列文章,来自技术大牛倾囊相授的实践经验,由TF中文社区为您编译呈现,旨在帮助新手深入理解TF的运行、安装、集成、调试等全流程。如果您有相关经验或疑问,欢迎与我们互动,并与社区极客们进一步交流。更多TF技术文章,请点击TF中文社区公众号底部按钮>学习>文章合集。

    7f4cb3d0-d84f-44cc-84f7-7e120f791971-image.png

    两年来,我在Tungsten Fabric的旅程中学到了不少知识,接下来,我会用几篇文章来简要介绍一下。

    1为什么要用Tungsten Fabric?

    首先,让我们来看一个重要的问题,SDN/Neutron/CNI都有很多不错的实现案例,为什么还要再尝试另一个呢?据我所知,Tungsten Fabric具有两个关键的差异化特征,这使它变得如此与众不同。

    I. 与ASIC的互操作性

    尽管有很多技术使Linux软件成为生产路由器/交换机的理想选择,但ASIC仍然是这一行业的重要组成部分。为了与它们进行互操作,SDN平台需要使用路由协议,例如BGP或OVSDB。

    许多服务提供商和云服务商使用VRF来终结和分离每个客户的网络连接,这使得路由器和SDN之间的连接变得很复杂。

    • 通常,它们之间可以使用VLAN,但是SDN平台上的终结点可能会成为瓶颈

    • 此外,每个SDN终结点(类似于OpenStack中的网络节点)需要为每个客户进行单独的配置,这使配置更加复杂

    借助MP-BGP这个已经成熟实现的协议,Tungsten Fabric解决了上述问题,该协议允许路由器上的每个VRF将报文直接发送到vRouter,这些vRouter服务于每个客户的应用程序。此功能允许基于控制平面(而不是数据平面),对具有每个客户独立网络的计算节点进行水平扩展,并使其更加直观。

    II. 可扩展性

    由于报文是从路由器直接发送到vRouter的,因此不需要网络节点,这使得Tungsten Fabric在数据平面上具有更大的可扩展性。

    另外,从控制平面的角度来看,Tungsten Fabric具有一个名为“路由目标过滤器(route target filtering)”(https://tools.ietf.org/html/rfc4684)的有意思的功能。

    • 此功能在MP-BGP中很常见,其他路由器也具有这个功能
    • 这个功能意味着,如果vRouter没有该路由目标(route target)的前缀,那么控制平面接收到它时会丢弃前缀

    在云服务中,客户只使用云服务商的数据中心的有限功能,并且不同客户使用不同的路由目标,因此vRouter和控制器不需要知道所有前缀。路由目标过滤功能使这种行为成为可能,并大大减少了每个vRouter以及每个控制器(如果在它们之间使用RR的话)需要考虑的前缀数量,这使得该控制平面更具可扩展性。

    对于私有云或托管云来说,将其与安全策略、网络策略/逻辑路由器(与AWS中的VPC peerling或transit-gateway类似)等其它功能结合在一起,这将是VPC基础架构(类似于AWS/Azure/GCP VPC/vnet)的一个不错的选择,并且使其成为一个非常值得一试的有趣平台。

    2Tungsten Fabric,启动并运行

    在第一次尝试使用Tungsten Fabric时,即使你已经熟悉其他CNI的部署,还是建议使用ansible-deployer(https://github.com/Juniper/contrail-ansible-deployer),因为Tungsten Fabric使用了很多种没有集成在Vanilla Linux中的工具。因此,建议首先尝试可以良好运行的设置,以查看新功能,然后再集成其它系统。

    不幸的是,许多Tungsten Fabric的repos都与rawhide类似,并且在某些情况下已经失去了依赖性。

    因此,我选择了一种组合,是我认为通常都能正常工作并且足够稳定,可以用来尝试大多数功能。

    要尝试此操作,你需要两台服务器,一台用于K8s主服务器,另一台用于K8s节点。K8s主服务器需要至少有2个vCPU、8GB内存和8GB磁盘空间。K8s节点服务器需要1个vCPU、4GB内存和8GB磁盘空间。

    • 我个人通常在AWS的ap-northeast-1区域中使用ami-3185744e(CentOS7.5, login-id: centos),t2.large的规格
    • 由于在我看来,与Tungsten Fabric进行OpenStack和vCenter集成比使用Kubernetes进行集成要复杂得多,因此即使你不需要容器支持,我还是建议首先尝试此设置
    • 安装过程,需要有互联网连接
    ##all the commands are typed at k8s master node
    sudo yum -y remove PyYAML python-requests
    sudo yum -y install git
    sudo easy_install pip
    sudo pip install PyYAML requests ansible==2.7.15
    ssh-keygen
    cd .ssh/
    cat id_rsa.pub >> authorized_keys
    ssh-copy-id root@(k8s node's ip) ## or manually register id_rsa.pub to authorized_keys
    cd
    git clone -b R5.1 http://github.com/Juniper/contrail-ansible-deployer
    cd contrail-ansible-deployer
    vi config/instances.yaml
    (replace contents with this)
    provider_config:
      bms:
       ssh_user: root
       ssh_public_key: /root/.ssh/id_rsa.pub
       ssh_private_key: /root/.ssh/id_rsa
       domainsuffix: local
       ntpserver: 0.centos.pool.ntp.org
    instances:
      bms1:
       provider: bms
       roles:
          config_database:
          config:
          control:
          analytics:
          analytics_database:
          webui:
          k8s_master:
          kubemanager:
       ip: 172.31.14.47 ## k8s master's ip
      bms2:
       provider: bms
       roles:
         vrouter:
         k8s_node:
       ip: 172.31.41.236 ## k8s node's ip
    contrail_configuration:
      CONTRAIL_CONTAINER_TAG: r5.1
      KUBERNETES_CLUSTER_PROJECT: {}
      JVM_EXTRA_OPTS: "-Xms128m -Xmx1g"
    global_configuration:
      CONTAINER_REGISTRY: tungstenfabric
    
    ansible-playbook -e orchestrator=kubernetes -i inventory/ playbooks/configure_instances.yml
     - it takes about 10 minutes
    ansible-playbook -e orchestrator=kubernetes -i inventory/ playbooks/install_k8s.yml
     - it takes about 5 minutes
    ansible-playbook -e orchestrator=kubernetes -i inventory/ playbooks/install_contrail.yml
     - it takes about 20 minutes
    

    需要注意的一点是,使用受支持的内核版本是一项相当严格的要求,因为Tungsten Fabric将自己的内核模块(vrouter.ko)用于其数据平面。我尝试了CentOS7.5、7.6,Ubuntu Xenial,并发现它也运行良好(对于Ubuntu Bionic,需要进行一些修改),但如果是第一次尝试,我建议使用特定的AMI ID,因为由于不能正常工作而进行调试和排错不是一件容易的事。

    如果所有“剧本”(playbooks)都运行良好,可以先输入内容,

    contrail-status
    

    它负责检查一切是否正常。

    [root@ip-172-31-14-47 contrail-ansible-deployer]# contrail-status 
    Pod              Service         Original Name                          State    Status             
                     redis           contrail-external-redis                running  Up 5 minutes       
    analytics        alarm-gen       contrail-analytics-alarm-gen           running  Up 2 minutes       
    analytics        api             contrail-analytics-api                 running  Up 2 minutes       
    analytics        collector       contrail-analytics-collector           running  Up 2 minutes       
    analytics        nodemgr         contrail-nodemgr                       running  Up 2 minutes       
    analytics        query-engine    contrail-analytics-query-engine        running  Up 2 minutes       
    analytics        snmp-collector  contrail-analytics-snmp-collector      running  Up 2 minutes       
    analytics        topology        contrail-analytics-topology            running  Up 2 minutes       
    config           api             contrail-controller-config-api         running  Up 4 minutes       
    config           device-manager  contrail-controller-config-devicemgr   running  Up 3 minutes       
    config           nodemgr         contrail-nodemgr                       running  Up 4 minutes       
    config           schema          contrail-controller-config-schema      running  Up 4 minutes       
    config           svc-monitor     contrail-controller-config-svcmonitor  running  Up 4 minutes       
    config-database  cassandra       contrail-external-cassandra            running  Up 4 minutes       
    config-database  nodemgr         contrail-nodemgr                       running  Up 4 minutes       
    config-database  rabbitmq        contrail-external-rabbitmq             running  Up 4 minutes       
    config-database  zookeeper       contrail-external-zookeeper            running  Up 4 minutes       
    control          control         contrail-controller-control-control    running  Up 3 minutes       
    control          dns             contrail-controller-control-dns        running  Up 3 minutes       
    control          named           contrail-controller-control-named      running  Up 3 minutes       
    control          nodemgr         contrail-nodemgr                       running  Up 3 minutes       
    database         cassandra       contrail-external-cassandra            running  Up 2 minutes       
    database         kafka           contrail-external-kafka                running  Up 2 minutes       
    database         nodemgr         contrail-nodemgr                       running  Up 2 minutes       
    database         zookeeper       contrail-external-zookeeper            running  Up 2 minutes       
    kubernetes       kube-manager    contrail-kubernetes-kube-manager       running  Up About a minute  
    webui            job             contrail-controller-webui-job          running  Up 3 minutes       
    webui            web             contrail-controller-webui-web          running  Up 3 minutes       
    
    WARNING: container with original name 'contrail-external-redis' have Pod or Service empty. Pod: '' / Service: 'redis'. Please pass NODE_TYPE with pod name to container's env
    
    == Contrail control ==
    control: active
    nodemgr: active
    named: active
    dns: active
    
    == Contrail config-database ==
    nodemgr: initializing (Disk for DB is too low. )
    zookeeper: active
    rabbitmq: active
    cassandra: active
    
    == Contrail kubernetes ==
    kube-manager: active
    
    == Contrail database ==
    kafka: active
    nodemgr: initializing (Disk for DB is too low. )
    zookeeper: active
    cassandra: active
    
    == Contrail analytics ==
    snmp-collector: active
    query-engine: active
    api: active
    alarm-gen: active
    nodemgr: active
    collector: active
    topology: active
    
    == Contrail webui ==
    web: active
    job: active
    
    == Contrail config ==
    svc-monitor: active
    nodemgr: active
    device-manager: active
    api: active
    schema: active
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# 
    
    [root@ip-172-31-41-236 ~]# contrail-status 
    Pod      Service  Original Name           State    Status         
    vrouter  agent    contrail-vrouter-agent  running  Up 52 seconds  
    vrouter  nodemgr  contrail-nodemgr        running  Up 52 seconds  
    
    vrouter kernel module is PRESENT
    == Contrail vrouter ==
    nodemgr: active
    agent: active
    
    [root@ip-172-31-41-236 ~]#
    

    这应该表明大多数组件都处于“active”状态,除了以下的:

    nodemgr: initializing (Disk for DB is too low.)
    

    这是可以在demo设置中安全地忽略的问题。

    注意:这基本上表明使用率超过50%,对于Cassandra来说这是一个很重要的问题。

    如果一切正常,则可以尝试使用此命令查看Tungsten Fabric路由表的状态。

    pip install lxml prettytable
    git clone https://github.com/vcheny/contrail-introspect-cli.git
    ##or curl -O https://raw.githubusercontent.com/vcheny/contrail-introspect-cli/master/ist.py
    ./contrail-introspect-cli/ist.py ctr status
    ./contrail-introspect-cli/ist.py ctr nei ## similar to 'show bgp summary'
    ./contrail-introspect-cli/ist.py ctr route summary ## similar to 'show route summary'
    ./contrail-introspect-cli/ist.py ctr route tables ## show routing-tables
    ./contrail-introspect-cli/ist.py ctr route show ## similar to 'show route'
    
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr status
    module_id: contrail-control
    state: Functional
    description
    +-----------+-----------+---------------------+--------+----------------------------------+
    | type      | name      | server_addrs        | status | description                      |
    +-----------+-----------+---------------------+--------+----------------------------------+
    | Collector | n/a       |   172.31.14.47:8086 | Up     | Established                      |
    | Database  | Cassandra |   172.31.14.47:9041 | Up     | Established Cassandra connection |
    | Database  | RabbitMQ  |   172.31.14.47:5673 | Up     | RabbitMQ connection established  |
    +-----------+-----------+---------------------+--------+----------------------------------+
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr nei
    +--------------------------------------+---------------+----------+----------+-----------+-------------+------------+------------+-----------+
    | peer                                 | peer_address  | peer_asn | encoding | peer_type | state       | send_state | flap_count | flap_time |
    +--------------------------------------+---------------+----------+----------+-----------+-------------+------------+------------+-----------+
    | ip-172-31-41-236.ap-                 | 172.31.41.236 | 0        | XMPP     | internal  | Established | in sync    | 0          | n/a       |
    | northeast-1.compute.internal         |               |          |          |           |             |            |            |           |
    +--------------------------------------+---------------+----------+----------+-----------+-------------+------------+------------+-----------+
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr route summary
    +----------------------------------------------------+----------+-------+---------------+-----------------+------------------+
    | name                                               | prefixes | paths | primary_paths | secondary_paths | infeasible_paths |
    +----------------------------------------------------+----------+-------+---------------+-----------------+------------------+
    | default-domain:default-                            | 0        | 0     | 0             | 0               | 0                |
    | project:__link_local__:__link_local__.inet.0       |          |       |               |                 |                  |
    | default-domain:default-project:default-virtual-    | 0        | 0     | 0             | 0               | 0                |
    | network:default-virtual-network.inet.0             |          |       |               |                 |                  |
    | inet.0                                             | 0        | 0     | 0             | 0               | 0                |
    | default-domain:default-project:ip-fabric:ip-       | 3        | 3     | 1             | 2               | 0                |
    | fabric.inet.0                                      |          |       |               |                 |                  |
    | default-domain:k8s-default:k8s-default-pod-network | 3        | 3     | 1             | 2               | 0                |
    | :k8s-default-pod-network.inet.0                    |          |       |               |                 |                  |
    | default-domain:k8s-default:k8s-default-service-    | 3        | 3     | 1             | 2               | 0                |
    | network:k8s-default-service-network.inet.0         |          |       |               |                 |                  |
    +----------------------------------------------------+----------+-------+---------------+-----------------+------------------+
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr route tables
    name: default-domain:default-project:__link_local__:__link_local__.inet.0
    name: default-domain:default-project:default-virtual-network:default-virtual-network.inet.0
    name: inet.0
    name: default-domain:default-project:ip-fabric:ip-fabric.inet.0
    name: default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.inet.0
    name: default-domain:k8s-default:k8s-default-service-network:k8s-default-service-network.inet.0
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr route show
    
    bgp.ermvpn.0: 6 destinations, 6 routes (0 primary, 6 secondary, 0 infeasible)
    
    1-172.31.41.236:1-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:02:26.545449, last_modified: 2019-Apr-13 01:41:18.023211
        [Local|None] age: 0:02:26.548569, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    1-172.31.41.236:2-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:01:09.096721, last_modified: 2019-Apr-13 01:42:35.471939
        [Local|None] age: 0:01:09.100272, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    1-172.31.41.236:3-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:00:41.812247, last_modified: 2019-Apr-13 01:43:02.756413
        [Local|None] age: 0:00:41.816037, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-172.31.41.236:1-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:02:26.544851, last_modified: 2019-Apr-13 01:41:18.023809
        [Local|None] age: 0:02:26.548875, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-172.31.41.236:2-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:01:09.096567, last_modified: 2019-Apr-13 01:42:35.472093
        [Local|None] age: 0:01:09.100828, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-172.31.41.236:3-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:00:41.812032, last_modified: 2019-Apr-13 01:43:02.756628
        [Local|None] age: 0:00:41.816542, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    bgp.evpn.0: 3 destinations, 3 routes (0 primary, 3 secondary, 0 infeasible)
    
    2-172.31.41.236:1-0-0e:92:cc:bd:aa:08,0.0.0.0, age: 0:02:26.545224, last_modified: 2019-Apr-13 01:41:18.023436
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.550028, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'mpls-o-gre', 'udp'], label: 20, AS path: None
    
    2-172.31.41.236:1-0-0e:92:cc:bd:aa:08,172.31.41.236, age: 0:02:26.545271, last_modified: 2019-Apr-13 01:41:18.023389
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.550313, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'mpls-o-gre', 'udp'], label: 20, AS path: None
    
    3-172.31.41.236:1-2-172.31.41.236, age: 0:02:26.545365, last_modified: 2019-Apr-13 01:41:18.023295
        [Local|None] age: 0:02:26.550656, localpref: 100, nh: 172.31.41.236, encap: ['vxlan'], label: 2, AS path: None
    
    bgp.l3vpn.0: 3 destinations, 3 routes (0 primary, 3 secondary, 0 infeasible)
    
    172.31.41.236:1:172.31.41.236/32, age: 0:02:26.545019, last_modified: 2019-Apr-13 01:41:18.023641
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.550608, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp', 'native'], label: 16, AS path: None
    
    172.31.41.236:2:10.47.255.252/32, age: 0:00:41.733374, last_modified: 2019-Apr-13 01:43:02.835286
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.739187, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    172.31.41.236:3:10.96.0.10/32, age: 0:00:41.732905, last_modified: 2019-Apr-13 01:43:02.835755
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.738945, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    bgp.rtarget.0: 7 destinations, 7 routes (7 primary, 0 secondary, 0 infeasible)
    
    64512:target:64512:8000001, age: 0:02:26.592101, last_modified: 2019-Apr-13 01:41:17.976559
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.598445, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:64512:8000002, age: 0:02:26.592073, last_modified: 2019-Apr-13 01:41:17.976587
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.598626, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:64512:8000003, age: 0:02:26.592051, last_modified: 2019-Apr-13 01:41:17.976609
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.598800, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:172.31.14.47:0, age: 0:05:09.194543, last_modified: 2019-Apr-13 01:38:35.374117
        [Local|None] age: 0:05:09.201488, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:172.31.14.47:1, age: 0:02:26.592028, last_modified: 2019-Apr-13 01:41:17.976632
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.599168, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:172.31.14.47:4, age: 0:01:09.099898, last_modified: 2019-Apr-13 01:42:35.468762
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:01:09.107253, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    64512:target:172.31.14.47:5, age: 0:00:41.824049, last_modified: 2019-Apr-13 01:43:02.744611
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.831612, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    default-domain:default-project:ip-fabric:ip-fabric.ermvpn.0: 3 destinations, 3 routes (3 primary, 0 secondary, 0 infeasible)
    
    0-172.31.41.236:1-0.0.0.0,255.255.255.255,0.0.0.0, age: 0:02:26.544896, last_modified: 2019-Apr-13 01:41:18.023764
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.552710, localpref: 100, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 0, AS path: None
    
    1-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:02:26.545544, last_modified: 2019-Apr-13 01:41:18.023116
        [Local|None] age: 0:02:26.553571, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:02:26.544992, last_modified: 2019-Apr-13 01:41:18.023668
        [Local|None] age: 0:02:26.553215, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    default-domain:default-project:ip-fabric:ip-fabric.evpn.0: 4 destinations, 4 routes (4 primary, 0 secondary, 0 infeasible)
    
    2-0:0-0-0e:92:cc:bd:aa:08,0.0.0.0, age: 0:02:26.545298, last_modified: 2019-Apr-13 01:41:18.023362
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.553810, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'mpls-o-gre', 'udp'], label: 20, AS path: None
    
    2-0:0-0-0e:92:cc:bd:aa:08,172.31.41.236, age: 0:02:26.545318, last_modified: 2019-Apr-13 01:41:18.023342
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.554076, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'mpls-o-gre', 'udp'], label: 20, AS path: None
    
    2-172.31.41.236:1-2-ff:ff:ff:ff:ff:ff,0.0.0.0, age: 0:02:26.545486, last_modified: 2019-Apr-13 01:41:18.023174
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.554476, localpref: 100, nh: 172.31.41.236, encap: ['vxlan'], label: 2, AS path: None
    
    3-172.31.41.236:1-2-172.31.41.236, age: 0:02:26.545411, last_modified: 2019-Apr-13 01:41:18.023249
        [Local|None] age: 0:02:26.554614, localpref: 100, nh: 172.31.41.236, encap: ['vxlan'], label: 2, AS path: None
    
    default-domain:default-project:ip-fabric:ip-fabric.inet.0: 3 destinations, 3 routes (1 primary, 2 secondary, 0 infeasible)
    
    10.47.255.252/32, age: 0:00:41.733312, last_modified: 2019-Apr-13 01:43:02.835348
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.742801, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    10.96.0.10/32, age: 0:00:41.732847, last_modified: 2019-Apr-13 01:43:02.835813
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.742561, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    172.31.41.236/32, age: 0:02:26.545051, last_modified: 2019-Apr-13 01:41:18.023609
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.554985, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp', 'native'], label: 16, AS path: None
    
    default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.ermvpn.0: 3 destinations, 3 routes (3 primary, 0 secondary, 0 infeasible)
    
    0-172.31.41.236:2-0.0.0.0,255.255.255.255,0.0.0.0, age: 0:01:09.096823, last_modified: 2019-Apr-13 01:42:35.471837
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:01:09.107020, localpref: 100, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 0, AS path: None
    
    1-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:01:09.096765, last_modified: 2019-Apr-13 01:42:35.471895
        [Local|None] age: 0:01:09.107383, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:01:09.096621, last_modified: 2019-Apr-13 01:42:35.472039
        [Local|None] age: 0:01:09.107473, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.inet.0: 3 destinations, 3 routes (1 primary, 2 secondary, 0 infeasible)
    
    10.47.255.252/32, age: 0:00:41.733411, last_modified: 2019-Apr-13 01:43:02.835249
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.744526, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    10.96.0.10/32, age: 0:00:41.732872, last_modified: 2019-Apr-13 01:43:02.835788
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.744256, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    172.31.41.236/32, age: 0:02:26.544986, last_modified: 2019-Apr-13 01:41:18.023674
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.556602, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp', 'native'], label: 16, AS path: None
    
    default-domain:k8s-default:k8s-default-service-network:k8s-default-service-network.ermvpn.0: 3 destinations, 3 routes (3 primary, 0 secondary, 0 infeasible)
    
    0-172.31.41.236:3-0.0.0.0,255.255.255.255,0.0.0.0, age: 0:00:41.812457, last_modified: 2019-Apr-13 01:43:02.756203
        [XMPP|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.824352, localpref: 100, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 0, AS path: None
    
    1-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:00:41.812393, last_modified: 2019-Apr-13 01:43:02.756267
        [Local|None] age: 0:00:41.824504, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    2-0:0-172.31.14.47,255.255.255.255,0.0.0.0, age: 0:00:41.812099, last_modified: 2019-Apr-13 01:43:02.756561
        [Local|None] age: 0:00:41.824428, localpref: 100, nh: 172.31.14.47, encap: [], label: 0, AS path: None
    
    default-domain:k8s-default:k8s-default-service-network:k8s-default-service-network.inet.0: 3 destinations, 3 routes (1 primary, 2 secondary, 0 infeasible)
    
    10.47.255.252/32, age: 0:00:41.733337, last_modified: 2019-Apr-13 01:43:02.835323
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.745932, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    10.96.0.10/32, age: 0:00:41.732935, last_modified: 2019-Apr-13 01:43:02.835725
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:00:41.745758, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 25, AS path: None
    
    172.31.41.236/32, age: 0:02:26.544959, last_modified: 2019-Apr-13 01:41:18.023701
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:02:26.558031, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp', 'native'], label: 16, AS path: None
    [root@ip-172-31-14-47 contrail-ansible-deployer]#
    

    如果显示类似信息,则说明一切正常,你可以基于K8s yaml创建容器了。

    vi first-containers.yaml
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: cirros-deployment
      labels:
        app: cirros-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: cirros-deployment
      template:
        metadata:
          labels:
            app: cirros-deployment
        spec:
          containers:
          - name: cirros
            image: cirros
            ports:
            - containerPort: 22
    
    kubectl create -f first-containers.yaml
    kubectl get pod -o wide ## check pod name and ip
    kubectl exec -it cirros-deployment-xxxx sh
    ping (another pod's ip)
    
    
    [root@ip-172-31-14-47 ~]# kubectl create -f first-containers.yaml
    deployment "cirros-deployment" created
    [root@ip-172-31-14-47 ~]# 
    [root@ip-172-31-14-47 ~]# kubectl get pod -o wide
    NAME                                 READY     STATUS    RESTARTS   AGE       IP              NODE
    cirros-deployment-54b65ccf48-cr9dd   1/1       Running   0          34s       10.47.255.250   ip-172-31-41-236.ap-northeast-1.compute.internal
    cirros-deployment-54b65ccf48-z9dds   1/1       Running   0          34s       10.47.255.251   ip-172-31-41-236.ap-northeast-1.compute.internal
    [root@ip-172-31-14-47 ~]#
    
    [root@ip-172-31-14-47 ~]# kubectl exec -it cirros-deployment-54b65ccf48-cr9dd sh
    / # 
    / # 
    / # ping 10.47.255.251
    PING 10.47.255.251 (10.47.255.251): 56 data bytes
    64 bytes from 10.47.255.251: seq=0 ttl=63 time=0.572 ms
    64 bytes from 10.47.255.251: seq=1 ttl=63 time=0.086 ms
    ^C
    --- 10.47.255.251 ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max = 0.086/0.329/0.572 ms
    / #
    

    太棒了!这是通过Tungsten Fabric vRouter传输的第一个报文。

    如果运行有问题,也请不要介意。Tungten Fabric的Slack站点可以为你提供帮助。在以下的地址提交你的日志,并尝试寻求帮助来解决该问题。地址:https://tungstenfabric.slack.com
    (编者按:国内用户请关注微信TF中文社区,中文官网:https://tungstenfabric.org.cn/ )

    再次输入“ist.py ctr route show”,你将看到k8s-pod-network包含了来自两个pod以及每个pod的下一跳,与K8s节点的IP相同。

    ./contrail-introspect-cli/ist.py ctr route show (pod ip) ## similar to 'show route (some ip)'
    
    
    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr route show 10.47.255.250
    
    default-domain:default-project:ip-fabric:ip-fabric.inet.0: 5 destinations, 5 routes (1 primary, 4 secondary, 0 infeasible)
    
    10.47.255.250/32, age: 0:03:10.553628, last_modified: 2019-Apr-13 01:46:13.217388
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:03:10.556716, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 37, AS path: None
    
    default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.inet.0: 5 destinations, 5 routes (3 primary, 2 secondary, 0 infeasible)
    
    10.47.255.250/32, age: 0:03:10.553734, last_modified: 2019-Apr-13 01:46:13.217282
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:03:10.557251, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 37, AS path: None
    
    default-domain:k8s-default:k8s-default-service-network:k8s-default-service-network.inet.0: 5 destinations, 5 routes (1 primary, 4 secondary, 0 infeasible)
    
    10.47.255.250/32, age: 0:03:10.553654, last_modified: 2019-Apr-13 01:46:13.217362
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:03:10.557453, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 37, AS path: None
    [root@ip-172-31-14-47 contrail-ansible-deployer]#
    

    请注意,ip-fabric VN和k8s-default-service-network也具有该前缀,因为k8s-pod-network的路由已“泄漏”到那些网络。想要具有某个特定路由表的路由,可以使用-t选项。

    [root@ip-172-31-14-47 contrail-ansible-deployer]# ./contrail-introspect-cli/ist.py ctr route show -t default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.inet.0 10.47.255.251
    
    default-domain:k8s-default:k8s-default-pod-network:k8s-default-pod-network.inet.0: 5 destinations, 5 routes (3 primary, 2 secondary, 0 infeasible)
    
    10.47.255.251/32, age: 0:05:44.533377, last_modified: 2019-Apr-13 01:46:09.193202
        [XMPP (interface)|ip-172-31-41-236.ap-northeast-1.compute.internal] age: 0:05:44.536291, localpref: 200, nh: 172.31.41.236, encap: ['gre', 'udp'], label: 32, AS path: None
    [root@ip-172-31-14-47 contrail-ansible-deployer]#
    

    附录:外部访问

    有人说Tungsten Fabric总是需要好的路由器才能实现外部访问,我认为这里有些误解。

    实际上这是不对的,因为从v4.1开始,Tungsten Fabric开始支持一项称为无网关(gatewayless)的功能,该功能允许容器直接与外界通信(对于带有Calico的类似用例也很有用)。

    要启用此功能,你可以登录Tungsten Fabric WebUI(https://(k8s masters's ip):8143,admin:contrail123)并进入Configure > Networks > k8s-default-pod-network,以切换Advanced Options > IP Fabric Forwarding。

    • 你还需要在该VN和default-domain:default-project:ip-fabric之间设置网络策略,因为如果没有此策略,RPF check将丢弃该报文

    如果ping一下从容器到K8s master的IP,你会发现K8s master从容器接收到一个报文,并向K8s master添加静态路由,ping的运行效果良好。

    • 请注意,如果你使用的是AWS,则需要进行K8s节点的接口设置(EC2 > Network Interfaces > Change Source/Dest Check > Disabled)

    因此,它允许对基于外部访问的网络节点进行类似的设置,该访问基于路由器上的静态路由。

    你还可以选择将IPv4 BGP与无网关(gatewayless)结合使用,因为它可以动态更新每个容器的下一跳,并将报文直接发送到正确的vRouter,从而消除了瓶颈。

    注意:此虚拟网络(virtual-network)也可以用作浮动IP(floating-ip)的来源。

    1.此虚拟网络上设置“Advanced Options”>“External”( 浮动IP池将使用“default”作为名称来创建)

    2.从Kubernetes或OpenStack分配浮动IP(floating-ip)

    • 对于Kubernetes,它将是外部IP的来源,并且需要将此参数指定给kube-manager: KUBERNETES_PUBLIC_FIP_POOL。例如:KUBERNETES_PUBLIC_FIP_POOL={'domain': 'default-domain', 'project': 'default', 'network': 'public-network1', 'name': 'default' }
    • 对于OpenStack,horizon或cli可用于为虚拟机分配浮动IP

    3.你也可以从Tungsten Fabric WebUI直接将浮动IP分配给特定端口(Configure > Ports > edit > floating-ip)

    3接下来的行动

    这可能是你第一次接触Tungsten Fabric,关于看完这篇文章后要怎么做,这里有一些建议。其实,有很多事情可以做,例如高可用性、监视,与其它编排器或路由器/交换机的集成等。

    网络上有很多资源,但是你需要做好选择,我将首先推荐Contrail软件包和教育材料中的一些资源,即便你只会使用开源版本。

    Tungsten Fabric是一个功能强大的平台,具有很多功能,例如安全策略、分析、l3dsr负载平衡器、服务链、BGPaaS等,其中许多功能对于解决现实世界中的问题都是非常棒的。这些链接将包含很多内容以及到其他资源的链接。

    编者按:这里有几个沟通的渠道,如果需要帮助,请尝试使用它们:
    官网社区:https://tungsten.io/community/
    中文官网:https://tungstenfabric.org.cn/
    微信公众号:TF中文社区

    Tungsten Fabric 架构解析系列文章——

    第一篇:TF主要特点和用例
    第二篇:TF怎么运作
    第三篇:详解vRouter体系结构
    第四篇:TF的服务链
    第五篇:vRouter的部署选项
    第六篇:TF如何收集、分析、部署?
    第七篇:TF如何编排
    第八篇:TF支持API一览
    第九篇:TF如何连接到物理网络?
    第十篇:TF基于应用程序的安全策略

    posted in 博客
  • 揭秘LOL背后的IT基础架构丨微服务生态系统

    作者:Maxfield Stewart(文章来源:Riot Games)译者:TF编译组

    欢迎来到Tungsten Fabric用户案例系列文章,一起发现TF的更多应用场景。“揭秘LOL”系列的主人公是Tungsten Fabric用户Riot Games游戏公司,作为LOL《英雄联盟》的开发和运营商,Riot Games面临全球范围复杂部署的挑战,让我们一起揭秘LOL背后的“英雄们”,看他们是如何运行在线服务的吧。
    

    9a5bbc2e-0e25-4dfe-ad9d-d03ebf6d77ee-image.png
    欢迎阅读本系列文章,我叫Maxfield Stewart。本文将深入探讨微服务成为Riot容器平台上实时运行的应用程序的五个关键需求。Riot的每项微服务都必须:

    • 高度便携
    • 在运行时配置
    • 可发现
    • 可知
    • 可检索

    要满足所有这些要求,就需要支持其他服务和工具。有些工具是为“开发人员”构建的,而有些则是为“运营人员”构建的。在Riot,这些职位不只是职务,而是工程师可以在其中进行切换的角色。一个工程师可能会在今天开发一项服务,然后在明天部署它,以推出新的功能。我将深入研究这五个需求以及支持它们的工具,并概述我们的方法。

    如果你准备研究我们的微服务秘密“调味料”的制作方法,请继续阅读!

    高度便携

    Riot在全球范围内拥有庞大的部署范围。我们将服务部署到全球数十个数据中心,每个数据中心都可以托管多个区域。我们希望“一次构建,随地迁移”,这意味着微服务必须具有高度的便携性。

    为了使我们的服务具有便携性,首先要决定对其进行容器化。我们已经详细讨论了容器及其无数的用例,以及诸如Docker之类的有价值的技术,但是将东西放到容器中并不能解决所有的问题。我们仍然必须将这些打包的容器交付到全球的数据中心。

    我们通过利用JFrog的Artifactory的强大功能,托管我们自己的全局复制的Docker注册库来实现此目标。下图显示了构建的容器映像的生产生命周期:

    bd5ecf08-113f-47b4-b9fc-2f9fe5162893-image.png

    我们之前在技术博客中讨论过在Riot构建软件。我们每年的构建次数超过125万。其中一部分,是作为旨在用于生产的Docker映像而构建的微服务。一旦从我们的持续交付过程中发出,它们便被停在内部Docker注册库中。而一旦准备好进行生产,便将其标记为“已升级”并移至复制存储库,复制存储库立即开始将Docker映像散播到我们的数据中心。

    20dc6dc8-cc16-461c-a14c-bb6e6ed9fe33-image.png

    由于这些Docker映像基于可重用的层构建,因此它们可以在几分钟内在世界范围内复制。它们本身很小,变化的范围就像一个bit。你可以从以下链接阅读更多:
    https://docs.docker.com/storage/storagedriver/

    在运行时配置

    目前,在Riot生产环境中运行的容器超过10,000个。任何一项微服务都可能包含多个容器。所有这些运行中的容器,都非常像刚出生的婴儿应用程序,沐浴在它们生产环境的光辉中。它们需要根据这些信息,快速确定自己的位置,以及学习如何进行自我配置。

    在传统的部署系统中,你可能会在应用程序中包含配置有效负载,并使用诸如Chef或Puppet之类的工具,来随着时间的推移保持该配置的收敛性。但是要保持便携性,我们的应用程序必须做到可部署,并且具备在运行时在任何环境中可运行的能力,一切都有条不紊。

    这就是“配置即服务”的用武之地。我们想使用自己的应用程序作用域方案,并且在分析了许多开源解决方案之后,我们意识到,编写自己的配置服务给了我们最大的灵活性。

    事实证明,解决命名方案相对简单。当我们的应用程序启动时,它们知道它们是谁,以及它们在哪里,因为调度程序会通过简单的环境变量注入通知它们。

    让我们看一下我们的作用域方案,它分为两个宏部分:

    94c4fd6e-50a2-4520-9ceb-10a2deee2b80-image.png

    环境作用域分为三部分,应用程序作用域分为两部分,如下所示:

    db894da0-25a8-40dd-a5c5-83fc29dde64c-image.png

    我将使用一个绰号为“MyApp”的简单小工具进行演示。MyApp已部署为可用于第二个Vegas数据中心内的所有Riot服务。它仅由服务器组件组成,可能看起来像这样:

    fe13cab2-572d-421d-a970-570813204133-image.png

    称为“myappprod1”的环境组件很重要。我可能还会将应用程序的QA版本(myappqa1)或开发版本(myappdev1)部署到同一集群中。我甚至还可能运行两个生产版本。作用域方案使我们能够在集群内部创建环境。

    为了使它能够用作配置查找方案,我们必须使用作用域将数据推送到配置服务。例如,如果我想将适用于已部署到“globalriot.las2.myappprod1”的所有应用程序进行数据推送,则可以将配置数据推送到:

    d717f858-51b0-4aa3-8a6d-be4d73702d48-image.png

    当“Myapp”运转起来并标识自己时,它与作用域的前三个部分匹配,并获取通配符的配置数据。如果我想将特定配置应用于特定实例,则可以将该数据推送至:

    f4cd9f90-055d-40f3-892e-d787b3509d87-image.png

    任何以这个完整作用域来标识自己的东西,都将获取数据。数据本身实际上只是一组属性,仅仅是简单的“键/值对”就可以了。这是针对目标作用域的一些数据的示例:

    http.ProxyType=http
    http.ListenPort=80
    http.DomainNames=myapp.somedomain.io

    配置数据也可以实时更新。想象一个速率限制属性是怎样的:

    ratelimit.txsec=1000

    我可以推送新的ratelimit.txsec值,应用程序将在实时检查配置后进行动态调整。这为我们提供了影响live服务的强大功能。曾经有一段时间,修复《英雄联盟》冠军数据,需要重新部署游戏。现在,我们可以将这些数据推送到“服务即配置”中,我们的游戏服务器会在游戏开始时将其提取,并自动应用调整来解决均衡问题、启用/禁用冠军问题等等,所有这些都不会令玩家失望。

    可发现

    如果我们有一个配置服务,它本身仅仅是一个微服务,那么应用程序启动时如何知道在哪里可以找到它?如果一个微服务需要与其它微服务通信,如何找到它们?这就是发现的“先有鸡还是先有蛋的问题”。

    我们的微服务不需要域名。实际上,它们可以任何时间、在集群中的任何位置启动时获得随机IP。我们选择通过发现服务或“单一服务统治所有人”来解决此问题。发现服务位于一个已知的域名中,新服务知道在哪里寻找它。

    77993a41-c093-4759-8b30-09d3502f3b6d-image.png

    当我们第一次踏上这一旅程时,受到了Netflix的Eureka解决方案的启发。实际上,我们的第一个部署就是新的Eureka实例。Eureka非常出色,但是随着时间的流逝,我们开始感到需要一些工具,可以让我们的操作环境具备更加原生的理解。

    新的应用程序启动后,它将查找发现服务,以找出配置服务所在的位置,下面将详细介绍这个过程。在执行下一步之前,应用必须进行自我配置,这一点很重要:在Discovery中注册自己。这使其他服务可以查找和查询新服务,以及了解其服务的合约。这里有一个示例,说明一项指标服务是如何针对QA环境进行报告的:

    4c9dfb7a-0cd8-4709-b91f-d937898629fd-image.png

    一旦应用程序找到发现服务,找到配置服务,并报告了自身,它也就可以继续使用发现服务来查找需要与之通信的其它服务。

    5407d17e-b93b-4267-95b3-3ef73c4a1f11-image.png

    这听起来很简单,但是我们需要牢记一些复杂的情况。例如,如果某个服务关闭,则我们必须注销该服务,否则将冒请求服务的风险(即哪个服务正在侦听什么IP和端口)。如果服务的IP发生更改,我们必须对其进行更新,否则就有将流量路由到错误位置的风险。

    我们通过简单的心跳模式来处理这些情况。在指定的时间内无法回叫的服务被视为M.I.A,将被从发现服务中删除。

    但是,在生产环境中事情可能并没有那么简单。如果数据中心出现严重错误,则系统需要具备基本的意识才能做出适当的反应。如果发现服务注意到其大量注册客户端停止了心跳,则可以断言存在某种大规模的网络或通信故障,并陷入“保留”模式。在保留模式下,发现服务会保留其数据,并立即向运营人员呼叫,从而有助于保护我们免受各种注册风暴或日益流行的“网络故障”的影响。

    cab72898-2650-40c5-820b-b76ea20911ae-image.png

    可知

    Riot的所有微服务都会在已知端点上发出运行状况报告,类似于“健康”,“降级”,“失败”等。即使是简单的报告,也允许我们使用基本的REST调用查询发现服务,并检查所有服务的运行状况。

    但这还不够。如果服务注册失败了怎么办?或者服务因崩溃而注销了该怎么办?如果不在发现服务中,我们如何知道它应该是什么状态(up or down)?

    这就是我们的告警和指标度量系统的来源。

    a8fe4d4f-45ea-4a27-8b01-9766a33e8d32-image.png

    指标度量系统可以查询应用程序的指标有效负载,然后将数据吸收到指标通道中进行检索,再将指标推送到位于每个数据中心的数据收集器。接下来,数据被转发到Elasticsearch存储引擎,在该引擎中注册的watcher协助触发警报。

    应用程序维护出现相关报警的端点。告警服务将其注册,然后通过监视服务监视其指标的状态变更。如果应用程序的状态从“健康”变更为“降级”,并且该应用程序已针对这个状态注册了警报,则告警服务将通知注册的联系点(通过呼叫、电子邮件等方式)。

    指标度量系统如何知道收集器在哪里?通过发现服务!有创造力的开发人员甚至可以通过配置服务,来设置服务发出的度量质保,它们的间隔,或者是服务的警报配置,从而实时更改指标和警报。报警声太吵了吗?你是否注意到总是引起虚假报警的特定警报?将配置更改推送到你的应用程序作用域,并告诉它取消注册警报。

    然后,可以将汇总的指标合并到数据仓库中。在Riot,我们正在将数据移动到一个“实时数据管道”当中,该管道由Elasticsearch支持,并由Riot的数据产品和解决方案团队托管。一旦数据进入管道,我们就可以轻松构建仪表盘了。请记住,所有的应用程序都报告其命名作用域和指标数据,因此我们可以轻松地从特定区域或特定名称的数据中心中,查询某个特定的应用程序的指标。

    afb90d5e-f653-41b9-a0b7-751b9922f801-image.png

    这是我们配置服务中指标的捕获情况。不是每个指标都有,但它是一个很好的示例。你可以看到它的CPU负载(真的很轻),并且每分钟收到大约20,000个请求。这个特定的实例来自我们的阿姆斯特丹数据中心,它的“集群”是“lolriot.ams1.configurous1”(部署作用域),而应用程序是“infrastructurous.configurous”(应用作用域)。

    如果需要,我们可以根据这些指标构建报警。例如,使用“已启用实例计数”,当我们看到实例数量少于预期的“3”个时,可以创建一个报警来呼叫相关人员。

    在发现服务和配置服务中正确注册其应用程序,前期成本是很小的,Riot开发人员可以免费获得这种报告。

    可检索

    到目前为止,我们避开了一个关键问题没谈:安全性。安全地进行通信,是任何高度便携、可动态配置的微服务系统的必要条件。必须锁定用于HTTPS流量或API身份验证令牌的SSL证书。我们希望将这些数据保存在配置服务中,以便可以轻松访问,但是以纯文本格式存储数据肯定不会给自己带来任何好处。那么我们该怎么办?

    如果我们将数据加密并存储在配置服务中,会怎么样?那么一旦找到它,我们将需要一种解密的方法,并且还需要一种方法来确保,检索它的应用程序是唯一具有解密密钥的应用程序。这就进入到我们可操作难题的最后一部分:秘密管理。

    0531356c-b75f-43dd-a1c6-a95655787938-image.png
    https://xkcd.com/538/

    为此,我们选择围绕HashiCorps出色的Vault服务创建服务包装。Vault实际上完成的工作远远超出我们的需求,因为我们实际上只想存储解密的密钥,以便我们的服务可以检索它并解密其数据。因此,我们的服务包装为此基本上只启用了REST端点。

    从理论上讲,使用它是很简单的,开发人员使用应用程序命名作用域,将特定服务的解密密钥放入秘密服务中。我们的容器调度程序Admiral在启动时将密钥注入到应用程序容器中(通过命名作用域查找它们)。一旦应用程序容器具有其解密密钥,它就可以解密从配置服务中检索到的配置属性。服务配置的所有者需要使用加密密钥来加密数据,然后再将其推送到配置存储。

    dec5a868-f01c-44f4-9e6a-badbf0711f4c-image.png

    该流程的详细信息及其工作方式,不在本文的讨论范围之内,但是工作流程至关重要。有了这个系统,服务现在可以实现高度便携、动态配置、自我感知、可知、可发现,同时在必要时还可以处理安全数据位。

    下一步:开发者生态系统

    至此,我们已经讨论了所有服务,就像对生产集群中运行的服务的bot-lane支持一样,但是我们的生态系统还有很多其他服务。毕竟,如果我们的开发人员不能有效地使用它,那么这一切有什么用呢?为了帮助大家利用此系统,我们创建了许多Web和CLI工具。如果刚才谈论的是生产环境的生态系统,那么我们仍然需要讨论开发者生态系统。但这是下一篇文章的故事!现在先留下一些预告。这是来自我们的一个Web应用程序部件的屏幕截图,我们使用它来访问生态系统中的工具,并查看刚刚提供给你的那些数据:

    73e85865-753b-4514-b67a-6a368b917107-image.png

    如果你想知道其中一些工具是什么,敬请期待下一篇文章!

    更多“揭秘LOL”系列文章
    揭秘LOL背后的IT基础架构丨踏上部署多样性的征程
    揭秘LOL背后的IT基础设施丨关键角色“调度”
    揭秘LOL背后的IT基础架构丨SDN解锁新基础架构
    揭秘LOL背后的IT基础架构丨基础设施即代码

    posted in 博客
  • TF Live丨KK/建勋:多云、SDN,还有网工进化论
    一场疫情,改变了所有人的生产与生活,在时代的不确定性面前,我们应该怎么做?
    
    昨晚,第一场【TF Live】如约而至,活动持续了两个多小时,在线人数将近1000人,互动讨论热闹十足。TF中文社区技术代表、瞻博网络全国合作伙伴技术经理张建勋(江湖人称KK),与大家聊了多云网络演变、SDN开放、Tungsten Fabric创新和网工转型等话题,关键词就是一个“变”字,在当下的特殊时期,尤其值得每个人认真思考。
    
    直播活动由SDNLAB和TF中文社区联合举办。
    

    点击下载文档 https://tungstenfabric.org.cn/assets/uploads/files/tf中文社区演讲-sdnlabv1.pdf 查看本文所有相关资料。

    直播活动视频回放https://v.qq.com/x/page/z0936fbc8fo.html

    云卷云舒,SDN应时而变

    时代在变,单一混合云,逐渐演变成了多云的环境。多云是混合云的进步。

    任何企业的IT发展,都不是革命性推倒重来的,而是逐渐累积,就像给你一笔钱理财,你会分散投资一样,IT也是根据自身的能力,根据技术适应场景去做选择。问题来了,不同厂家都有自己的理念、思路和方法,挑战是什么?

    人们发现,SDN不是万能的,很多问题不是SDN能解决的,SDN不要增加问题就不错了。而在硬件SDN上,存在三方面的问题:SDN功能和设备锁定;功能扩展上受制于厂家设备;做NFV和服务链集成时,安全设备引流只能局限在同一厂家。

    换一个思路如何?将虚拟网络层统一,由上层控制器统一管理,下发网络的时候,使用统一的策略,下发到每一个对应服务器的虚拟网络设备上。这里存在一个情况,裸机服务器怎么办?需要由物理交换机承担虚拟交换机的工作。

    如果将每一个服务器上的kernel层,都安装一个虚拟交换机,下面的网络,通过核心层设备+底层设备,跨越了硬件的交换机,underlay承载的工作就会非常简单,只负责物理设备,只负责IP Fabric服务器之间IP流量的互传,而不用去关心硬件的交换机究竟是什么产品。这种设计思路,在目前主流厂家中很常见,尤其是在公有云环境中。

    无论是国外的主流公有云,还是国内的几家,他们的SDN和硬件交换机都是解耦的。SDN应该要做的事情,就是让虚拟机能够在不同的平台运行,业务之间自动的打通。不关心上层是什么平台,K8s也好,Openstack或VMware也好,就单纯为业务创建网络。

    我理解现在的SDN就是tradeoff,其实就是平衡,而平衡就是混合,软件SDN的方式,目前在性能上是可以满足需求的,如果一定要追求更高性能,也可以在裸机上实现。

    未来将会如何?

    首先,未来SDN一定是开放解耦的架构,从全部硬件SDN,变为部分硬件+部分软件。SDN的功能,应该像真正的公有云环境中SDN的功能一样,和硬件交换机是一个松散的关系,解耦的逻辑。

    第二,硬件交换机本身,也会有硬件和软件的解耦,也就是白盒化的进一步升级。

    第三,在企业云的设计中,最重要的还是IT管理,可能催生出来的机会就是CMP,统一的云化管理,而这个平台一定是定制化的,是和业务紧密挂钩的。无论是集成业务商,还是企业自己建设平台,定制化云管平台都是实现IT转型的很好方式。

    [QA环节]

    Q:内部云平台可以统一管理,但是多云呢?怎么管理到阿里云、腾讯云和内部统一,怎么统一下发策略?

    A:以AWS为例,私有云和公有云在设计的时候,地址的管理是很难统一的,针对地址或网段的管理,我们在K8s环境下和AWS有个互联互通的测试。我们可以把阿里云的平台,理解成自留地资源,安装了相应的环境和平台,把其中网络的部分理解成underlay,虚拟网络的部分交给Tungsten Fabric来做,其实就是overlay的方式。在AWS、Azure上,都可以采用这样的方式。K8s的集群是可以跨越不同点的。

    (演示Tungsten Fabric的多平台访问demo)
    可以看到,在K8s、OpenStack、BMS多个平台上,是可以通过开源的软件,实现统一网络管理的,不管虚拟机也好,docker也好,它们可以在一个网里面,也可以在不同的网,根据你自己的需求而定,我们的策略是基于标签tag的,做了一个网络访问策略,是SDN overlay的网络策略,不用去考虑在什么平台下,一旦部署策略,策略就是基于逻辑,基于归属的。

    简单策略,跨越复杂部署

    Tungsten Fabric就是一个面向未来的SDN解决方案,想要实现的是:多云的部署方式+统一的策略。

    Tungsten Fabric是一个SDN产品,支持统一策略、服务链管理、安全策略等。原来的名字是OpenContrail,2013年正式开源,2017年加入到Linux Foundation,2018年更名为Tungsten Fabric。

    在Tungsten Fabric的体系架构里,下层就是IP Fabric,由虚拟交换机对应下层每一个虚机之间的通讯,上层有一对儿TF控制器,对上层是汇合对接不同的云平台/编排系统,同时将网络信息以虚拟化的方式下发。至于裸机服务器,则通过Netconf的方式实现TOR的配置。

    Tungsten Fabric是一个非常成熟的开源产品,是一个“共生”的开源——它是商业化产品开源出来的,而不是开源产品商业化,在成熟度上是经过验证的。

    通过这几年版本的迭代,Tungsten Fabric已经比较成熟了,很多硬件SDN没有的功能,也能支持得很好,集成度也比较高,特别适合技术创新,拿来作为自己云平台的网络管理部分,解决云网里面“网”的逻辑,使用起来也是统一的,并且可以解除一些产品的锁定。

    我们有自己的TF中文社区,希望降低大家学习网络新知的难度,了解并熟悉Tungsten Fabric这个开源SDN的产品,能够很快上手,真正运用起来,帮助到自己的企业和行业。

    对于公有云的连接和管理,我的想法是这样的,还是从需求出发。因为公有云本身有自己的网络环境和地址管理,因此这种管理本身和私有云平台可能就会产生兼容性的问题,所以如果从统一管理的角度来说,统一成同一个网络并不是特别的现实,至少我目前没有合适的想法。

    真是要实现可能有如下几个模式:

    第一个,就是做一个打通和互联,不存在“大二层”的需求,那么就是老样子,IPSec 网关和路由打通,这是现在比较普遍的方式。当然,你买了公有云的专线,另当别论。

    第二个,在网络中先把地址规划做好,比如VPC的网络地址分配不冲突,不可能统一分配,但是至少做好管理,然后安装一个支持大二层比如EVPN功能的GW,假定是Juniper的VMX,那么这时可以实现VMX和Contrail(同Tungsten Fabric)的EVPN互通,用EVPN对的方式打通所谓的“二层”,某种程度上来说,相当于两个二层的缝合,而这时公有云的虚机的网关不再是VPC原有的网关,而是我们做的VMX,这个也是可能实现的。

    第三个,还有一个是CEM里面的multicloud gw,这个只能在K8s平台下是OK的。

    Multicloud gateway (MC-GW) node interconnects different Virtual Private Cloud (VPC)/Virtual Networks (VNets) in cloud. Additionally, MC-GW extends on-premise resources to cloud.

    链接如下:
    https://www.juniper.net/documentation/en_US/contrail19/topics/task/installation/deploy-multicloud-contrail-command.html

    [QA环节]

    Q:Tungsten Fabric与NSX到底有啥区别?
    A:在技术实现的理念上完全一样,都是使用server overlay的方式。在实现的方式上,除了一个花钱一个不花钱以外,NSX实现一定是在VMware平台,Tungsten Fabric实现是多平台的。在和VMware的互通上方式,需要有技术选择,第一个是全网使用VMware只做IP Fabric,但是可以和vCenter建立关系;第二个是将vRouter安装到每一个虚拟机下面做网关。实际上,对于VMware客户其实已经是选择了私有化方案,不会选择其他平台。不同的实现场景,解决不同的问题。

    Q:大量BGP路由收敛的话,收敛时间是否会成为一个问题?
    A:从实践和测试的角度来说,为什么会选择BGP或者说EVPN,就是因为它整个的效率是一个平衡的效率,这是协议的设计上决定的,不管是量大还是量小,选择的都是比较成熟的协议。BGP是行业里收敛和变化最稳定的一个,和传统的IGP路由协议不一样(附注:旨在说明不存在路由算法),跟OpenFlow方式也不一样,它是一个比较朴素的分布式部署的方式,通过RR的方式,每个vRouter看到的邻居其实是两个RR,,采用按需更新的方式,在这种情况下,收敛性方面不是问题。

    Q:vRouter万一挂了怎么办?
    A:是否足够稳定,要看运行环境是什么样的。目前的实践来看,vRouter挂的情况比较少。问题在于,当做到生产环境的时候,需要考虑整个服务器的硬件匹配,操作系统的匹配,包括KVM版本、kernel版本、K8s版本等的匹配。同时,TF本身也会有vRouter的检测,会去看它的状态,在troubleshooting的时候,也会做相应检查,另外我们可以通过控制器对它进行重启和重置。在这一点上,我对Juniper自身路由协议和路由处理方面的代码还是有信心的。

    IT快跑,网工如何转型?

    从多云的角度来说,还是面临着各种情况,做云的过程中难免面临技术争议,包括技术选择的问题和困境。企业IT有两种模式或形态——稳态和敏态,本身是由由稳态走向敏态,不断更新,不断变化的。

    用户为什么选择云,其实也是市场的原因,市场对他们的要求提高了,比如制造业、餐饮、服装等行业,他们在进行业务变革的时候,速度会很快,倒逼着IT变化也很快。

    这里就有一个值得大家思考的问题,我们网络从业者、网工,在这个不断变化的时代,应该怎么做?

    两年前,我就听到说,网工已经成立了落后生产力的代表。因为我们总是在满足业务的需求,而不是积极的响应,很有可能业务会因为网络的原因不能实现敏捷,需要我们反思的是,负责服务器的,负责数据库的,负责网络的,当我们真正去做IT的时候,最好的方式是大家坐下来,确定统一的业务目标,统一的技术方向,这样才能把IT做得更稳妥,任何一个冒尖或者落后,都会带来问题。

    未来,我们要更多了解业务,了解云是怎么设计的,让网络发挥最大的能力。我们要去看企业进行数据中心管理时的样子,要了解他们选择了什么云平台,为什么选择这个平台,还要看在做什么业务,为什么做这个业务,以及数据库、应用结构等。一旦有了云的设计,业务和IT的挂钩,就会越来越紧密,应用研发和网络的关系也越来越紧密。

    云肯定是未来方向,但在选择上有不少困境。Tungsten Fabric是可以帮助企业实现技术把控的一种很好的手段,在熟悉了这个工具之后,在网络的自主可控上,可以进行各种扩展,使用起来更加方便。

    疫情期间,这段时间每个人都在思考,IT的发展怎么样?我相信,没有冬天不会过去,没有春天不会到来。

    [QA环节]

    Q:传统网工该如何转型?要学习的好多好复杂,不知如何学起?
    A:网工是不是被边缘化了?传统知识不能满足现在的需求,这是必然的。IT行业是不断变化的行业,门槛不断降低,网络设备价格不断降低,每个10G端口的成本不断下降,但并没有降低人的要求和素质。网络是IT必不可少的部分,如果不了解生成树、VLAN、基础知识,没办法更深的内容,EVPN,VXLAN,Segment Routing,都是要学习的内容。技术基础的持续学习是第一位的。

    第二,与其说转型,不如叫升级,增加一些看问题的视角。云对网络的变化有很多要求,但不同企业和行业对云的认识差异还非常大,这里有很多内容网工可以投入进去,一些技术因为时间精力背景的原因不能深入,但至少要有全局的认识。

    第三,提高自己自动化的水平,如果仅仅做CLI的,只是一个工人,要让自己通过一些手段方法,把数据可视化,把经验的东西程式化,转化成工具。看Google或Facebook,他们的网工,每个人手里都有几把武器,检测网络的时候,人家编个脚本就上去了,但这种自动化编程,不是搞数据库,就是先学现卖,拿来主义。如果你想有一些进步的话,看看其他老网工在做些什么。

    第四,网络安全是未来的一个趋势,针对安全的服务大有可为。

    大家可能知道,疫情期间能看到很多行业受到影响,但是我发现疫情期间打印机卖的特别火,因为很多“神兽”在家,有打印的需求,因此我猜再开学的时候,学校周边的打印店就不好开了。所以说,真正“搞垮”你的不一定是同行。同样道理,我们为什么要去学自动化?传统企业服务可能永远用不到这个知识,就是要应对不确定性的变化,做好充分的准备,不拘泥一个厂商,而是根据看待行业本身的需要去寻找自身的优势和劣势,迎接变革的到来。

    彩蛋

    Tungsten Fabric最新版本v2003版,将于近期发布!敬请关注TF中文社区,并加入我们的社群,与行业大牛一起讨论学习,未来社区还将探索更多在线活动玩法,敬请期待。

    posted in 新闻
  • TF Q&A丨只在此网中,云深不知处

    1147a668-d288-4eac-8923-40754005c9b7-image.png
    3fb74991-815d-44c2-ae19-3cb516bd6fdb-image.png
    8a76a91c-2ca0-4522-8ad1-7f062d76b4d2-image.png
    4e90ebb7-0d56-4e3f-a8e9-f41050a31399-image.png
    26097d58-29c6-43b6-8b71-2624a530e258-image.png
    e01a967a-f20f-4f25-be7f-636457a0acdd-image.png
    5fced781-04ff-418f-bc84-872dc4e96776-image.png
    0ff0f59e-4807-488f-8fee-73721164875c-image.png
    fcbead3d-1da2-4c38-8b46-b338c10df43d-image.png

    来了来了!TF中文社区线上直播活动“TF Live”即刻启动~ TF中文社区技术代表、瞻博网络中国区合作伙伴技术经理张建勋,将在首次直播活动中,和您一起聊聊如何面对这个多云架构时代。本期活动,由TF中文社区与SDNLAB合作举办——

    0a66cc06-ee21-466c-9f72-17f0ceb54258-image.png

    参与方式:长按识别图片二维码,添加SDNLAB君为好友,回复“直播”即可。

    如果你对本次直播内容有一些想要深入了解的或者想要沟通交流的部分,欢迎与我们联系,我们的嘉宾将在直播过程中挑选部分问题进行解答~

    752f4e1b-9a46-46fa-9878-7c94956c1dfe-image.png

    posted in 博客
  • TF Live首期预告:多云时代,聊聊SDN开源架构

    来了来了!TF中文社区线上直播活动“TF Live”即刻启动~ TF中文社区技术代表、瞻博网络中国区合作伙伴技术经理张建勋,将在首次直播活动中,和您一起聊聊如何面对这个多云架构时代。本期活动,由TF中文社区与SDNLAB合作举办——

    在企业未来的数字化转型过程中,如何利用开源架构产品,帮助客户实现在多云环境下的SDN网络架构设计,实现异构云平台网络的统一调度和自动化管理。我们将讨论以下问题:

    • 为什么SDN变得越来越不灵活了?

    • 网络硬件设备到底该怎么选?硬件SDN行不行?

    • 我的云管平台为什么不好用?

    • 在OpenStack环境下部署的策略,能否在其他的环境下同时生效?

    • 行业有自主可控的要求,怎么实现?二次开发如何不跑偏?

    • Tungsten Fabric架构是什么样?解析最新技术细节。

    6e266809-fdcc-40a5-8a18-d943e0544916-image.png

    参与方式:长按识别图片二维码,添加SDNLAB君为好友,回复“直播”即可。

    如果你对本次直播内容有一些想要深入了解的或者想要沟通交流的部分,欢迎与我们联系,我们的嘉宾将在直播过程中挑选部分问题进行解答~

    a4101ce1-9127-46ec-856c-ec4023d26d81-image.png

    4beb3569-c2fb-4b03-844d-11d1fd379341-image.png

    posted in 新闻
  • Tungsten Fabric与K8s集成指南丨创建隔离命名空间

    作者:吴明秘

    Hi!欢迎来到Tungsten Fabric与Kubernetes集成指南系列,本文介绍如何创建隔离的命令空间,并对其网络连通性进行验证。
    Tungsten Fabric与K8s集成指南系列文章,由TF中文社区为您呈现,旨在帮助大家了解Tungsten Fabric与K8s集成的基础知识。大家在相关部署中有什么经验,或者遇到的问题,欢迎与我们联系。
    

    K8s与Tungsten Fabric集成后有四种配置模式,分别为:默认模式、自定义隔离模式、命名空间隔离模式、嵌套模式。

    默认模式:Tungsten Fabric创建一个由所有命名空间共享的虚拟网络,并从中分配service和pod的IP地址,在Kubernetes集群中产生的所有命名空间中的所有pod都能够彼此通信。

    自定义隔离模式:管理员和应用程序开发人员可以添加注释("opencontrail.org/network: ")来指定虚拟网络。在这个虚拟网络中,一个命令空间中的一个或所有pod将在这个虚拟网络中被启动。如果该注释是在pod上配置的,那么pod将在该网络中启动;如果注释是在命名空间中配置的,那么命名空间中的所有pod都将在该网络中启动。

    命名空间隔离模式:集群管理员可以在创建新的命令空间时,添加注释("opencontrail.org/isolation : true")以启用命令空间隔离。因此,该命名空间中的服务不能从其他命名空间访问,除非明确定义了安全组或网络策略以允许访问,或者启动注释("opencontrail.org/isolation.service : false")单独允许该命名空间的service可以被其他命令空间的pod访问。

    嵌套模式:Tungsten Fabric支持与基于OpenStack虚拟机部署的Kubernetes集群集成。Tungsten Fabric提供了一个可折叠的控制和数据平面,一个TF控制平面和一个网络堆栈管理和服务同时在OpenStack和Kubernetes两个集群中。有了统一的控制和数据平面,可以无缝地交互和配置这些集群,不需要单独为每个集群部署TF。

    在本系列的第二篇文章中,创建的命名空间为默认模式,而创建的网络是自定义模式的虚拟网络,在本章节中将会创建隔离的命令空间,并验证其网络连通性。

    创建隔离命名空间

    在此将会创建一个隔离的命名空间,名为isolated-ns,具体配置文件如下:

    16d71fab-9781-4d2f-97c0-14b02bbc4736-image.png

    执行kubectl的创建命令之后,对应的命名空间随即被创建。

    0e1a3085-e47e-4d7f-a4c7-76ae101f8e59-image.png

    而在TF上也会有对应的policy和虚拟网络被创建出来,分别为:

    TF policy: k8s-isolated-ns-pod-service-np
    

    这条TF policy的作用,是允许附加了该条策略的虚拟网络能够访问命令空间isolated-ns中的service clusterip。

    TF network: k8s-isolated-ns-pod-network , k8s-isolated-ns-service-network
    

    这两个网络分别使用了命名空间default里面的IPAM,所以在这个命令空间isolated-ns中默认创建出来的pod和service所分配的IP所属的IP池,与命名空间default中的一样,即pod(10.32.0.0/12)和service(10.96.0.0/12)。

    6d03b15d-a9ec-4d74-b8a8-244153d2e663-image.png

    5e4fd31b-afb6-481a-bfc4-9dbbfd483253-image.png

    验证与非隔离命令空间的网络连通性

    接下来在隔离的命令空间isolated-ns中创建pod和service,验证isolated-ns与其他命令空间的连通性。

    首先在default和isolated-ns两个命令空间中分别创建两个pod和一个service。

    246181db-638f-4683-8642-e678754a103e-image.png

    6579f2dc-63eb-45d9-8cf4-cc14c777ba98-image.png

    所以目前的资源为:

    2个命名空间:default,isolated-ns

    2个service:nginx-default (10.105.147.31),nginx-isolated (10.97.162.157)

    4个pod:
    nginx-default-test01 (10.47.255.251)
    nginx-default-test02 (10.47.255.250)
    nginx-isolated-test01 (10.47.255.249)
    nginx-isolated-test02 (10.47.255.247)

    网络连通性验证流程:

    1、从命名空间default中的pod nginx-default-test01去ping其他三个pod,结果是pod nginx-default-test01只能连通同一命名空间中pod,而无法连通隔离命名空间中的pod。

    f6136e16-800b-49eb-96d0-e47644994cf3-image.png

    2、 从命名空间isolated-ns中的pod nginx-isolated-test01去ping其他三个pod,结果是pod nginx-isolated-test01只能连通同一命名空间中pod,而无法连通其他命名空间中的pod。

    b34d5b84-148b-470e-8b09-772c266c65fd-image.png

    3、从命名空间default中的pod nginx-default-test01去curl分别在两个命令空间中的service,结果是pod nginx-default-test01只能请求default和kube-system这些非隔离命名空间中的service,而无法请求隔离命名空间中的service。

    584796d0-0cb9-4515-bfd0-df33816ba1f5-image.png

    4、从命名空间isolated-ns中的pod nginx-isolated-test01去curl分别在两个命令空间中的service,结果是pod nginx-isolated-test01只能请求default和kube-system这些非隔离命名空间中的service,而无法请求隔离命名空间中的service,即便该service在自己所在的命名空间。

    b71f5f90-86fa-4847-9173-f3451a656ee6-image.png

    所有验证结果综合起来就是,非隔离命名空间和隔离命名空间之后建的pod默认无法互访——即便在相同的IPAM中,并且非隔离命名的service可以被任何pod访问,而隔离命名空间的service默认无法被访问。

    现在需要添加TF policy让pod之间,pod和service之间能够连通。

    对于pod之间的访问,需要添加如下TF policy,该条policy是连接两个网络,k8s-default-pod-network与k8s-isolated-ns-pod-network。

    7dd4fc86-4b2b-4d43-9c57-c23a0355f78e-image.png

    创建完成,分别将这条Policy附加到隔离命名空间和非隔离命令空间的pod网络上,k8s-default-pod-network与k8s-isolated-ns-pod-network。

    13eabf1b-077e-4627-b4ee-8adcc74f7e2c-image.png

    f6c2434a-35a4-4497-bc38-fd6892ecf777-image.png

    此时再进行pod之间的网络连接验证,结果是两个命名空间的pod之间已经能够通信。

    c8a49adb-d6df-458a-a99b-d85c13c09e2b-image.png

    对于pod与service之间的访问,需要添加如下TF policy,该条policy是允许指定网络能够访问isolated-ns的service。

    3b11012b-3cf4-4b45-a144-e79425d3ba36-image.png

    创建完成后,再将这条Policy附加到隔离命名空间和非隔离命令空间的pod网络上,k8s-default-pod-network与k8s-isolated-ns-pod-network,以及隔离命名空间的service网络k8s-isolated-ns-service-network上。

    b6effdc4-faca-41d5-8e56-55c6c447713b-image.png

    31950198-a7de-47eb-bb0b-30b39edbcbd0-image.png

    8011fdce-7836-47df-9d99-238bb18c6784-image.png

    此时再进行pod与service之间的网络连接验证,结果是两个命名空间的pod都可以访问到隔离命名空间中的service。

    1966b355-fac0-4b32-9e9c-3545e0ae697b-image.png

    在隔离命名空间和非隔离命名空间的流量全通之后,还可以通过安全策略去做进一步的流量控制。

    (作者来自深圳市天源景云科技有限公司)

    “Tungsten Fabric+K8s集成指南”系列文章——

    第一篇:部署准备与初始状态
    第二篇:创建虚拟网络
    第三篇:创建安全策略

    “Tungsten Fabric+K8s轻松上手”系列文章——
    第一篇:TF Carbide 评估指南--准备篇
    第二篇:通过Kubernetes的服务进行基本应用程序连接
    第三篇:通过Kubernetes Ingress进行高级外部应用程序连接
    第四篇:通过Kubernetes命名空间实现初步的应用程序隔离
    第五篇:通过Kubernetes网络策略进行应用程序微分段

    posted in 博客
  • TF中文社区技术委员会第五次线上会议--邀您参加

    我们将召开第五次线上会议。

    为了大家更好地参与到技术委员会会议,我们对开会时间做了线上投票,现调整为每两周周三下午15:00-16:00。

    因本次分享内容需要一些时间准备,开会推迟一天。我们将于3月12日(星期四)下午15:00 - 16:00召开第五次线上会议。

    参与方式:https://zoom.com.cn/j/5486946411
    (进入ZOOM会议室需要下载安装包,请提前下载)

    本次会议的主要议题是:
    杨雨分享--K8S与TF集成之Ingress实现

    会议制度说明:频率为每两周一次(每两周周三下午15:00 - 16:00)

    Tungsten Fabric项目是一个开源项目协议,它基于标准协议开发,并且提供网络虚拟化和网络安全所必需的所有组件。项目的组件包括:SDN控制器,虚拟路由器,分析引擎,北向API的发布,硬件集成功能,云编排软件和广泛的REST API。

    posted in 新闻
  • 揭秘LOL背后的IT基础架构丨基础设施即代码

    作者:Doug Lardo和David Press(文章来源:Riot Games)译者:TF编译组

    欢迎来到Tungsten Fabric用户案例系列文章,一起发现TF的更多应用场景。“揭秘LOL”系列的主人公是Tungsten Fabric用户Riot Games游戏公司,作为LOL《英雄联盟》的开发和运营商,Riot Games面临全球范围复杂部署的挑战,让我们一起揭秘LOL背后的“英雄们”,看他们是如何运行在线服务的吧。
    

    044bd186-b6da-4da0-886f-52f121100771-image.png

    在上一篇文章中,我们讨论了Riot针对全球应用程序部署的解决方案rCluster所涉及的网络的一些内容。具体来说,我们讨论了overlay网络的概念,OpenContrail(编者按:已更名为Tungsten Fabric,下文中出现OpenContrail之处,均以Tungsten Fabric代替)的实现,以及Tungsten Fabric解决方案如何与Docker配合使用。

    本文将在此基础上深入探讨其他主题:基础架构即代码、负载均衡和故障转移测试。如果你对如何以及为什么建立这些工具、基础架构和流程感到好奇,那么本文正适合你。

    基础架构即代码

    通过Tungsten Fabric提供用于配置网络的API,我们现在有机会自动化应用程序的网络需求。在Riot,我们将持续交付作为发布应用程序的最佳实践。这意味着每一次提交给master的代码都是潜在可释放的。

    为了达到这个状态,应用程序必须经过严格的测试自动化,并具有完全自动化的构建和部署流程。一旦出现问题,这些部署也应该是可重复且可逆的。这种方法的复杂性之一,是应用程序的功能性不仅在于其代码上,还在于环境方面,包括它所依赖的网络功能。

    为了使构建和部署具有可重复性,应对应用程序及其环境的每个部分进行版本控制和审核,以便知道谁更改了内容。这意味着不仅要在源代码管理中拥有应用程序代码的每个版本,并且还描述了其环境并将其版本化。

    为启用此工作流,我们构建了一个系统,以简单的JSON数据模型(我们称为网络蓝图)描述应用程序的网络功能。然后,我们创建了一个周期性工作,从源代码管理中提取这些蓝图文件,然后将其转换为Tungsten Fabric上的API调用以实施适当的策略。使用此数据模型,应用程序开发人员可以定义需求,例如一个应用程序与其它应用程序进行交谈的能力。开发人员不必担心IP寻址或通常只有网络工程师才能真正理解的任何细节。

    应用程序开发人员拥有自己的网络蓝图。现在,更改它们就像给其蓝图文件发出pull请求,并使对方将其合并到master一样容易。通过启用这样的自主服务工作流,我们的网络更改不再受限于少数专业网络工程师。现在,唯一的瓶颈是工程师编辑JSON文件并单击“提交”的速度。

    6acb4cfe-a080-4386-8a61-c39aa0524c70-image.png

    该系统使我们能够快速、轻松地打开必要的网络访问权限,这是安全策略的关键要素所在。在Riot,玩家的安全性至关重要,因此我们将安全性融入到了基础架构当中。我们安全策略的两个主要支柱是最低特权和纵深防御。

    最低特权,意味着Riot网络上的任何参与者都只能访问完成其工作所需的最少资源集。参与者可能是人,也可能是后端服务。通过执行此原则,我们极大地限制了潜在入侵的影响范围。

    深度防御,意味着我们在基础架构的多个位置执行安全策略。如果攻击者破坏或绕过我们的执行点之一,他们将始终碰到更多可抗衡的东西。例如,公共Web服务器被禁止从网络访问支付系统,并且该系统还维护自己的一组防御措施,比如第7层防火墙和入侵检测系统。

    c183f5f1-61c0-4971-bef6-8b7b2c234c0b-image.png

    Tungsten Fabric通过其vRouter在每个主机上添加一个执行点来帮助我们。通过基础设施即代码JSON描述文件来使用其API ,我们始终可以为应用程序之间的通信提供最新的、版本化的,并且易于审核的网络策略。我们创建了可以扫描网络规则的工具,以发现违反政策和访问权限过大的情况。速度、最佳安全实践,以及审核能力的结合,构成了一个强大的安全系统,这并不会妨碍开发人员,相反,它使开发人员能够快速、轻松地做正确的事情。

    负载均衡

    为了满足应用程序不断增长的需求,我们将DNS、等价多路径(ECMP)和传统的基于TCP的负载均衡器(例如HAProxy或NGINX)相结合,以提供功能丰富且高度可用的负载均衡解决方案。

    在Internet上,我们使用DNS将负载分散到多个全局IP地址上。玩家可以查找“riotplzmoarkatskins.riotgames.com”这样的记录(不是真实的,但也许应该是真实的),并且我们的服务器可以使用多个IP地址进行答复,这些IP地址将响应DNS查询。一半的玩家可能会收到一个列表,其中服务器A的位置位于顶部,而另一半玩家将看到服务器B的位置位于顶部。如果其中一台服务器关闭,客户端将自动尝试另一台服务器,因此没有人会看到服务的中断。

    在网络内部,我们有许多服务器都配置为应答服务器A的IP地址。通过应答这个地址的能力,每个服务器都向网络发布通告,同时网络将每个服务器视为可能的目的地。收到新的玩家连接后,我们将在交换机中执行哈希计算,以确定性地计算出哪个服务器接收了流量。哈希基于数据包头中的IP地址和TCP端口值的组合。

    如果其中一台服务器“休假”了,我们将尝试使用一种称为“一致性哈希”的技术,最大程度地减少影响,以确保只有使用故障服务器的玩家受到影响。大多数情况下,客户会通过自动重新启动新连接来无缝处理此问题,受影响的玩家甚至不会注意到。收到新的连接后,我们已经检测到并删除了发生故障的服务器,因此不会浪费时间尝试向其发送流量。

    对于我们的大多数系统,我们会自动启动一个新实例,一旦它准备好接收流量,系统就会将其重新添加到循环中。我们认为它非常“漂亮”。负载均衡的最后一层,是通过传统的基于TCP或HTTP的负载均衡器(例如HAproxy或NGINX)执行的。

    04b5f34d-fc8b-430e-92d6-5d6c82b11e65-image.png

    当请求来自ECMP层时,它们可能会遇到许多负载均衡的实例。这些负载均衡实例监视每个真实的Web服务器,并确保服务器运行状况良好,在适当的时间内做出响应,准备接收新的连接等。如果满足所有这些条件,则服务器会收到请求,并且答复将一直返回到玩家。

    这一层通常是我们进行blue-green部署和智能运行状况检查的地方,例如“/index.html加载的响应代码为200吗?”

    编者按:Bule-green部署是一种负载均衡健康检查的部署方法,请见链接:https://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/

    此外,我们可以执行诸如“canary部署”,每10台服务器中的一台获得最新版本的网页,而其他9台服务器仍使用旧版本。我们会密切监视新版本,以确保不会出现任何问题,如果进展顺利,我们会将10台服务器中的两台移至新版本,依此类推。如果情况不佳,就回退到上一个已知的稳定版本,并找出解决问题的方法。我们随后将添加测试以更早地发现这些问题,以便不会两次犯相同的错误。这使我们能够不断改进服务,同时最大程度地降低生产风险。

    通过所有层的协同工作(DNS、ECMP和传统的TCP或第7层负载均衡),我们为开发人员和玩家提供了功能丰富、性能稳定,且具有可扩展性的解决方案,使我们能够尽可能快地将服务器安装在机架中。

    故障切换测试

    高可用系统最重要的部分之一,就是当发生故障时,该系统能够进行故障转移。当我们刚开始构建数据中心时,通过让工程师拉出一些电缆,并在这里和那里重新启动一些服务器,来模拟这些问题。但是,一旦数据中心启动并为玩家提供服务,这个过程将变得很困难,前后不一致,并且根本无法接受。这鼓励我们构建一些东西,然后再也不要碰它。我们绝对发现了重要问题,并避免了此过程的中断,但是还需要认真改进。

    首先,我们在过渡环境中构建了按比例缩小版本的数据中心。它足够完整,可以准确无误。例如,在过渡环境中,我们有两个机架,每个机架有五台服务器。而生产系统在两个维度上都大得多,不过我们的问题可以通过更小、更便宜的设置来解决。

    在这种过渡环境中,我们将测试所有更改,然后再将其交付生产。我们的自动化部署将在这里变更,对于每一个变更,我们都会对其执行快速的基本测试,以防止我们做完全愚蠢的事情。这消除了我们对于自动化系统变得有知觉,进行了上千次失控改变并最终融化了整个星球的一份担忧(编者按:本句的原文特别文艺——This removes the fear of our automated systems becoming sentient, making a thousand runaway changes, and eventually melting the whole planet,实际上就是想表达,我们不会过度的依赖自动化系统,因为担心自动化系统会放大细微的错误而将业务毁于一旦)。相对于生产环境,我们更喜欢在过渡环境中捕获这些类型的错误。

    除了基本检查之外,我们还进行了更为复杂和破坏性的测试,这些测试破坏了重要组件并迫使系统在降级状态下运行。尽管四个子系统中只有三个子系统可以运行,但我们知道可以忍受这种损失,并且我们有时间在不影响玩家的情况下修复系统。

    全套测试更加耗时,更具破坏性(我们宁愿中断系统并立即开始学习,而不是在生产中学习),并且比基本测试还要复杂,因此我们运行全套故障转移测试的频率并不高。

    我们让每个链接都失效,重新启动内核,重新启动TOR交换机,禁用SDN控制器,以及我们能想到的其他任何方法。然后,我们测量系统进行故障转移所需的时间,并确保一切仍在平稳运行。

    如果事情发生了变化,我们可以查看自上次运行代码以来对代码所做的更改,并在将更改交付生产之前,弄清楚我们可能已更改的内容。如果我们在生产中遇到无法预见的问题,而故障切换测试中没有发现该问题,我们会将该测试快速添加到套件中,以确保不再发生类似情况。我们的目标始终是尽早发现问题,越早发现问题,就可以越快地解决它。当我们以这种方式工作时,不仅可以快速前进,而且更加自信。

    结论

    在上一篇文章中,介绍了数据中心网络的核心概念和实现,这次我们介绍了如何实现基础架构即代码,以及安全策略、负载均衡和故障转移测试。“变化是唯一不变的东西”,可能是将这些问题结合在一起的最好主题。基础设施是活着的、有呼吸的,并且在不断进化的“动物”。我们需要在它生长的时候提供资源,需要在它生病时做出反应,需要在全球范围内尽快完成所有工作。拥抱这一现实,意味着确保我们的工具、流程和范例能够对动态环境做出反应。所有这些使我们相信,现在是开发生产基础架构的绝佳时机。

    和往常一样,非常欢迎与我们取得联系,说出你的问题和评论。

    更多“揭秘LOL”系列文章
    揭秘LOL背后的IT基础架构丨踏上部署多样性的征程
    揭秘LOL背后的IT基础设施丨关键角色“调度”
    揭秘LOL背后的IT基础架构丨SDN解锁新基础架构

    posted in 博客