作者 Tim Crofts,译者 大愚若智
来源:infoq
为庆祝一年一度的世界IPv6日(始于2011年6月6日),LinkedIn希望用一种别具含义的方式纪念这一天。过去多个月以来,我们忙于在自己的数据中心内启用IPv6,为此我们设计了全新的体系结构,并在网络、系统、工具等方面做好充分的准备,最终于6月6日在一个过渡(Staging)环境中成功启用了IPv6。此番举措是在所有数据中心内实现全功能IPv4/IPv6双堆栈的一个重要里程碑,在顺利实现这一目标后,下一步将彻底弃用IPv4。
在这一系列文章中,我们将介绍从IPv4迁移至IPv6需要考虑的问题,尤其是诸如LinkedIn这样的大型企业在迁移过程中可能遇到的各种挑战。但首先我们想介绍一些有关IPv4和IPv6的基本信息,以及迁移过程中需要考虑的基本原则。
IPv6简史
IPv6的整个发展史与IPv4的发展密不可分。IPv4于1981年被互联网工程任务组(IETF)正式确立,1992年,互联网社区提议对IPv4寻址方案进行扩展。IETF为此创建了一个工作组;1996年,一系列名为请求注解(RFC)的文档正式确立了IPv6(每个文档名称以RFC开头,后跟用于区分不同文档的编号)。
与此同时为了缓解IPv4地址空间即将耗尽的问题,他们为内部私有网络保留了三个公用IPv4地址段(RFC1597)。大部分组织只需要将少量服务暴露到互联网,因此对公用IP空间的需求其实并不大。通过在组织内部使用私有IPv4地址段,进而将对公用IP空间的需求降至最低,即可减少所需IPv4地址的数量。业界通过这种方式将公用IPv4地址空间耗尽的那一天推迟了多年。
1996年,IETF正式颁布了RFC1918文档,该文档是对RFC1597的改进,其中谈到了使用私有或公用地址空间的设备相互通信的不同需求。三年后,1999年发布的RFC2633中提出的网络地址转换(NAT)技术可以自动对来自私有网络的互联网数据包进行转换,将其转发至公用互联网,并将从公用互联网收到的响应转换到私有网络。内部设备可以借助NAT与公用网络中的设备通信,但无法实现反向通信。但是NAT造成了一些新问题。例如当两家公司合并时,由于在合并前使用了相同的私有IPv4地址段,有时可能需要解决内部路由冲突问题。所有私有IPv4流量有时候看起来都像是来自同一个公用IPv4地址,因此作为公用服务供应商,如果阻止某个IPv4地址的通信,可能会影响到数千个设备或用户。
1995年底发布的RFC1883意味着IPv6时代正式开始。IPv6最初只部署在实验室内某些操作系统和路由器中,随后以此为基础构建了一些公用的实验性网络。随着更多RFC陆续发布,解决了越来越多的实现和其他问题后,IPv6网络逐渐达到生产环境中使用的质量要求,但直到2008年2月,互联网编号分配机构(IANA)将IPv6地址加入域名系统(DNS)的根区域后IPv6才算正式登场,随后IETF在同年三月的会议中进行了一次IPv4停用实验。在大概一小时的实验过程中,工程师测试了在不使用IPv4的情况下可以在互联网上执行的操作。此次实验后,很多软件都发布了相应的补丁。
2011年6月6日,Internet Society发起了“世界IPv6日”活动,很多大公司在24小时的活动期间测试了自己网站在IPv6(作为对IPv4的补充)环境下的表现。此次活动一年后的同一天被称作“IPv6发布日”,很多公司在这一天里将自己的网站切换至IPv6并一直沿用至今。LinkedIn的网站在2014年开始正式可以通过IPv6访问。
今天,IPv6流量已经占到全球互联网流量的10%以上,一些国家的占比更高,例如美国已经达到30%以上,比利时超过了50%。一些移动网络已经以IPv6为主,占到流量总数80%以上。Apple也已宣布所有移动应用必须能够支持纯IPv6网络,并使用NAT64(与NAT类似,但用途是将IPv6数据包转换为IPv4格式)访问互联网上依然使用IPv4的部分。Facebook、Akamai以及LinkedIn还分别发现在IPv6环境下端到端使用应用程序(尤其是移动应用程序)的速度也有了很大提升。
IPv4和IPv6的主要差异
IPv4地址包含32位,IPv6地址包含128位。由于地址更“大”,IPv6标头也更大,但其长度是固定的,IPv4标头封包长度是可变的。更重要的是IPv6不再需要校验,一般来说校验工作是在硬件层面或上层实现的。这种设计有助于降低路由器的负载。最后,在IPv6中路由器不需要拆分数据包,如果需要传递的数据包太大,路由器会向发送方发出一个ICMPv6 Packet Too Big(PTB)信息,让发送方以恰当的大小重新发送该数据包。这些改进降低了路由器处理每个数据包时的负荷,进而提高了路由器工作效率。
IPv6的体系结构确保了设备无需集中化服务,即可通过无状态地址自动配置(Stateless Address AutoConfiguration,SLAAC)技术获得自己的IPv6地址。IPv6有两种主要类型:链路范围(Link scope)和全球范围(Global scope)。本地IPv6地址只能在当前网段内使用,全球地址通常来自路由器所宣告的网络,并会结合接口的MAC地址。IPv6中也存在一种集中化的服务:DHCPv6,该服务基于动态主机配置协议(DHCP),但为了与SLAAC共存进行了少量改动。
迁移至IPv6
迁移至IPv6的过程中产生了一种有趣的“22条军规(Catch-22)”:为了顺利迁移必须将最流行的网站迁移至IPv6,但通常来说小规模网站迁移至IPv6的过程要比大型网站的迁移容易得多。IPv6网络上一台服务器可手工配置并快速完成,但大型网站通常包含很多面向IPv4的路由器、负载平衡器、防火墙、监控工具,以及各种设备和软件,这些东西需要进行相应的转变才能用于IPv6。
通过顺利迁移大型网站通常需要的各种特殊设备和软件,世界IPv6日和世界IPv6发布日帮助互联网社区解决了很多问题。路由器、负载平衡器,以及防火墙逐渐应用了各种修复程序,地理位置的分部也逐渐完善。支持IPv6的Web缓存服务越来越多,Packet too big(PTB)信息已经可以由安全筛选器处理,启用IPv6的DNS基础结构可以实现更快速的响应,除此之外还有很多其他改进。
然而将内部网络转换为IPv6则是一个截然不同的故事:这一过程需要很多其他组件相互配合并需要能够伸缩。对于大规模部署,就算RFC1918空间也不足以对所有内部网络需求进行寻址。每个国家的办公室都需要有自己的网络,云平台也需要大量计算机,因此对于大型网络来说,就算10.0.0.0/8也显得不够大,地址空间的重叠也会成为一个麻烦事。使用诸如NAT等解决方案对地址空间进行转换可以缓解此类问题,但这种解决方案也会产生一系列新问题,例如应用程序内嵌入的IP地址,通过伸缩处理更大数量的转换,以及由于引入“NAT防火墙”造成的各种安全问题。
在现实环境中,可以直接关闭路由器的IPv4功能并启用IPv6,但大部分情况下这种做法并不可行。我们认为内部网络进行过渡的最佳策略是首先迁移至双堆栈环境,并通过妥善制定的“淘汰”策略彻底弃用IPv4。这样大家可以有更多时间熟悉IPv6,并将自己的工具、软件,以及流程逐步迁移至IPv6,经过这样的步骤,只有很少一部分流量需要通过IPv4处理。然而这种方式最大的不足在于,为双堆栈环境提供支持不仅更复杂,而且维持两个网络的大量运维工作会拖累新服务的部署速度,如果两种协议未能同步还可能造成新的问题。IP地址的管理也会变成一种复杂的任务,因为IPv4和IPv6地址空间的映射通常还需要很多其他功能,例如ACL的实现、路由汇总、负载平衡器等。
因此有必要面向未来做好准备并尽快着手IPv6的迁移,随后即可按部就班将越来越多的流量顺利迁移至IPv6。由于为两个网络栈提供支持会导致工作复杂度提升将近一倍,一旦迁移至IPv6还需要尽快彻底弃用IPv4。
LinkedIn的IPv6迁移
双堆栈环境可以帮助你循序渐进地将服务器迁移至IPv6。一些应用程序的迁移难度可能略低,例如某些核心UNIX服务的迁移就是一种唾手可得的工作。
6月6日,我们决定开始迁移自己的某个过渡环境,尤其是LinkedIn用于在发布“新”服务前进行测试使用的过渡环境。我们计划为该环境中所有系统添加一个全球IPv6地址,并对尽可能多的核心服务进行迁移,借此提高IPv6网络流量的比例。
我们需要确保此番迁移不会破坏尚未测试的服务,为了实现必要的控制,我们利用了IP双堆栈环境的一些基本特性。例如,我们的大部分软件是通过Java开发的,默认情况下Java应用程序在运行时需要通过一个声明(Declaration)宣告自己在使用IPv6。因此我们无需担心软件突然发现IPv6并自行开始使用该环境。我们还决定不为任何使用全球IPv6地址的计算机的主机名添加AAAA DNS记录,这样使用其他语言发起的连接就不会通过IPv6运行。借此可以确保其他软件、工具,以及实用程序可以像以前一样继续通过IPv4运行,整个环境不受任何干扰。
从那天下午开始,我们在几分钟内为超过1500个系统添加了静态的全球IPv6地址。对于任何此种规模的系统,自动化机制都非常重要,可以帮助我们快速将变更部署给整个系统。在确认通过IPv6正常运行没遇到任何错误后,我们为这些主机增加了AAAA记录,借此这些操作系统将首选使用IPv6而非IPv4。所有这些工作完成后,开始将某些核心基础结构服务(DNS、syslog、SMTP、NTP、集中身份验证等)的流量从IPv4迁移至IPv6。在大概一个小时内,我们通过受控的方式将基础结构内的多个此类服务切换至IPv6网络中。未来几个月里,还将继续将更多基础结构服务迁移至IPv6,同时也将努力让Rest.li等自行开发的软件框架优先选择使用IPv6而非IPv4。
除了上述工作,为了向成员提供服务,我们目前还在建设一个全新数据中心。这个数据中心在设计伊始就充分考虑了IPv4和IPv6双堆栈,此外还包含其他很多先进技术。这个数据中心在LinkedIn内部被称之为Project Altair,之前的很多博客文章中曾经进行过介绍。
借助启用IPv6的过渡环境和生产环境,我们可以将越来越多的内部流量迁移至IPv6。在6月6日的首轮工作成功实现后,对于将其他内部环境迁移至IPv6我们也更加自信。
一旦适应IPv6流量后,该开始考虑弃用IPv4并让数据中心运行在纯IPv6环境下。这个目标并不遥远,我们计划在2017年内全面实现。同时为IPv4和IPv6提供支持意味着需要付出将近两倍的工作量,因此一旦决定采用IPv6,需要确保过渡过程尽可能短。然而很多供应商和软件产品目前并不能全面支持IPv6,为了实现我们最终的迁移目标,还需要针对这种情况采取必要的措施。
LinkedIn内部成立了由“IPv4处理专家”组成的“AAAA团队”。这是一个很赞的技术项目,我们也希望能有更多类似我们这样的组织将自己的数据中心迁移至IPv6,只有通过这种集体合作的方式才能顺利解决妨碍数据中心和云环境全面采用IPv6的遗留问题。请加入我们一起为最终目标贡献自己的力量。
在这一系列文章的第1篇中(以上内容),我们介绍了将内部网络迁移至IPv6的原因。领英(LinkedIn)网站从2014年起即可通过IPv6公开访问,而我们的员工在这之前早已可以通过IPv6访问公众互联网。虽然很早以前我们网络中的大部分组件就已支持IPv6,但直到最近内部数据中心依然运行在IPv4下。本文我们将从网络运维的角度介绍为什么需要创建同时包含IPv4和IPv6的全球网络,以及开始在自己的数据中心内启用双堆栈环境,并期待着有朝一日能彻底弃用IPv4的过程中所面临的挑战。
网络设计:回到未来
除了链路本地(Link-local)地址和现已废除的站点本地(Site-Local)地址等例外情况,所有IPv6地址均已全球可路由。通过IPv4 RFC1918空间我们已经知道使用这种地址的私有网络是不会“泄露”到互联网的。然而在IPv6网络中这一点还无法保障,因为所有全局IPv6空间都是全球可路由的。现在设计数据中心时需要实施更稳健的安全策略,因为流量可能同时源自内部和外部。现在已无法通过某些简单的策略只允许或只拒绝RFC1918地址。
当所有地址都全球可路由时,数据包可能会通过不同路径到达同一个目的地。如果转发路径(Forward path)的设计不够谨慎,可能导致数据包通过一个防火墙出站,通过另一个防火墙返回的情况。防火墙是有状态的,这意味着它们会记住内部计算机与外部计算机之间的连接状态,这样才能自动允许返回的流量通过防火墙。但是跨防火墙分享状态这种做法很难实现,并且可能不够安全。更重要的是,路径中的某些部分可能会通过安全性不那么高的公众互联网传输,而非通过内部网络进行。
使用IPv6时无法轻易通过查看目标IP地址是否包含在RFC1918空间来确定流量是内部还是外部的。内部和外部流量哪怕是虚拟的,也依然需要隔离。为了实现这种隔离,必须重新沿用NAT技术诞生前的网络设计思路。换句话说,我们“回到未来”了。
NAT使得深藏于数据中心内的计算机可以直接访问互联网,从本质上来说这需要建立一对一的NAT连接。我们决定在自己的数据中心内设置一块不公告到互联网的IPv6地址段,这也意味着所有位于这个地址段内的计算机必须通过DMZ中设置的一系列代理或网关访问互联网。为确保整个体系结构尽可能简单,我们不希望内部计算机在无法通过IPv6直接访问互联网的情况下可以通过IPv4直接访问。由于打算实施双堆栈,需要禁用IPv4上的所有NAT。这样内部的所有计算机无论使用IPv4或IPv6,都必须成为多宿主(Multi-homed)计算机。
通过使用边界网关协议(Border Gateway Protocol,BGP),可以将一个路由器所知道的IPv4和IPv6路由通过IPv4或IPv6连接公告给周围其他路由器。由于领英的最终目标是彻底弃用IPv4,我们决定不让公告跨越网络堆栈,我们的IPv6路由公告都将只通过基于IPv6的BGP会话对外公告。
增加新的网络堆栈要求安全性至少要与原本的IPv4环境相当。此时一种方法是使用筛选器拒绝所有IPv6流量并从这里入手。然而一旦设备可以感知IPv6,当它无法通过IPv6到达目的地,并且应用程序无法“优雅”回退至IPv4,或无法及时实现回退时服务可能会中断。因此我们选择了另一种方法。
另一种方法是将现有的访问控制列表(ACL)直接从IPv4转换为IPv6。这种方法的效果到底有多大不同?举例来说,将ICMP筛选器转换为ICMPv6筛选器即可让Ping数据包直接到达目标计算机,但正如这一系列文章的第1篇中提到的,ICMPv6的Packet Too Big(PTB)信息是IPv6独有的,这种信息对通过封装隧道(Encapsulating tunnel)进行的,或使用了巨型帧的通信至关重要。以太网IP数据包通常最大只能达到1,500字节,但隧道技术会将一个数据包封装到另一个数据包内(例如NAT64),而为了通过高速链路实现更快速的传输,可能需要使用巨型帧(超过1,500字节)数据包。为避免遇到难以诊断的网络连接问题,必须确保能够顺利生成、接收和处理PTB信息。由于IPv4(以及其他类似情况)没有PTB的概念,因此不能直接将现有ACL转换为IPv6版本,否则将无法提供对PTB信息进行授权的规则。
最终我们成功实现了通过访问控制列表(ACL)为环境、计算机等提供保护这一目标。在IPv6网络上启用两个设备并创建双堆栈之前,如果不创建与IPv4规则等价的IPv6 ACL规则,设备间的通信可能会中断。
另外我们还使用虚拟IP(VIP)将客户端通过一个IP地址连接到多个服务器。IPv4和IPv6网络中这些VIP的配置略有差异。例如为了正确发送到最终的目标服务器,一些处理VIP的负载平衡器被配置为重写数据包的以太网部分。无论IPv4或IPv6,这个服务器必须能用自己的原生协议处理数据包。因此如果某个VIP是双堆栈的,这意味着该VIP代表的所有计算机都必须是双堆栈的。在负载平衡器的配置中,IPv4和IPv6的VIP配置是两个不同的配置选项,但我们不希望在DNS中为VIP设置不同名称。同理为了避免产生其他技术债,由于最终目标是完全使用纯IPv6环境,我们也不希望使用诸如vipname-v6这样的主机名。因此在DNS端,当服务器可以开始处理IPv6流量后,会给VIP名称增加一条AAAA记录。
通过上述问题我们意识到,为设备创建IPv6地址架构可以帮助我们在并非所有计算机的主机名都有DNS AAAA记录(或反向DNS记录,如果需要的话)时实现很多目的,例如根据不同机器之间的互访需求定义IP规则。
为设备提供怎样的IPv6地址?
我们不想为主机名添加DNS AAAA记录,因为在添加该记录后,到这些服务器的连接将首选使用IPv6。我们必须首先确定所有软件都支持IPv6,随后才能启用双堆栈服务器。
另外我们也不希望将IPv4地址嵌入IPv6地址(例如:2620:abcd:efef::192.168.1.1),原因在于:
上述例子中的地址在接口上将被表示为2620:abcd:efef::c0a8:0101;
IPv4地址空间枯竭的问题还没有成功解决;
弃用IPv4将造成技术债。
为了轻松地将IPv4 ACL转换为IPv6 ACL,我们依然需要能在没有为主机名添加AAAA记录的前提下,通过计算机的IPv4地址知道它的IPv6地址。(ACL决定了哪些计算机获得了授权,可以访问某一特定计算机。)
对于这个问题,我们的解决方案是将每个IPv4网络与IPv6网络配对,并使用IPv4地址最后两个位组(Octest)的十六进制格式作为IPv6地址的最后一个Quibble(IPv6地址用Quibble表示,每个Quibble为4字节/16比特,用冒号分隔)。选择使用最后2个位组的原因在于,这样的话我们一些最小规模的IPv4网络就可以与使用/23掩码的IPv6网络配对(为了放入同一个机柜中,大部分此类网络都是/24或/25规模的)。我们使用了与IP地址管理系统(IPAM)中相同的子网配对选项。通过这种方式,即可针对特定VLAN当前分配的IPv4子网获得IPv6子网。
为了简化ACL、路由聚合,以及内外部网络边界等问题,我们决定为目前和未来的所有数据中心使用一个足够大的IPv6网络。这样做也可以简化内部IPv6流量的识别工作,因为只需要查看地址的来源块(Block)就够了。
为了进一步简化这一系列过程,我们还决定为所有与服务器连接的路由器接口设置fe80::1作为链路本地IPv6地址。在领英的所有数据中心内,服务器始终会使用eth0接口访问默认网关,因此默认网关始终可通过eth0接口的fe80::1地址,即“fe80::1%eth0”的方式访问。不需要使用路由器公告信息即可建立默认网关。我们的所有IPv6地址都是静态的(因为动态IPv6地址需要在DNS中维护),因此客户端总能找到要连接的服务器。由于服务器数量众多,全天时间内会发生多次主要为静态形式的服务器更新。通过将FE80::1作为网关,使用特殊脚本或工具解析路由表即可知道任何网段均已不需要默认网关。对于IPv6地址或默认网关来说,任何动态架构都必须通过持续广播有关网络的信息让系统保持动态的状态。但使用静态状态后,无须确保必须及时将信息广播给服务器和设备就可以让它们维持自己的网络状态。我们的服务器IP就使用了这样的架构。我们的网络设备使用了更传统的架构,其中点对点链路通过更大的地址块组成了一个独特网络,而环回(Loopback)地址则来自专用的IPv6地址空间。
对于服务器,我们使用了静态的IPv4和IPv6 IP地址。我们会使用上文提到的IPAM工具记录所有网络和主机名。这样在供应设备时就可以知道每台主机位于哪个机柜,使用哪个端口连接。IPAM信息会纳入DNS中,这样就不需要使用动态DNS将IP与主机名映射。此外我们的应用程序堆栈会通过发现服务将服务映射为主机名。考虑到这些因素,使用静态IP地址的做法更合理,确保了我们可以控制IP的分配不会改变,并且应用程序堆栈也可以使用持续不变的名称和IP地址对应关系。
与IPv4策略的差异之处在于,无须使用NAT66为代理和其他DMZ功能提供支持,即可通过IPv6访问互联网。DMZ中所有主机将使用多宿主连接在数据中心提供内部IPv6连接,并通过防火墙提供到互联网的外部IPv6连接。
为了支持领英实现纯IPv6数据中心这一最终目标,我们需要确保终端访问控制器访问控制系统(Terminal Access Controller Access Control System,TACACS)、网络时间协议(NTP)、系统日志(Syslog)、简单网络管理协议(SNMP),以及sFlow等其他服务均可支持IPv6源地址,并在功能方面能与IPv4看齐。也就是说应用程序层需要支持IPv6,用于管理所有这些设备的工具也需要支持IPv6。最终所有设备需要能通过纯IPv6网络供应。面对IPv6,零接触供应(Zero Touch Provisioning,ZTP)技术依然有待完善,因为其中还用到大量遗留组件。我们将在这一系列文章的第3篇从较高角度介绍如何让软件或应用程序能够在IPv6网络中正常运转。
致谢
本文撰写过程中得到了AAAA团队下列成员的巨大帮助:
Zaid Ali、Sriram Akella、Andrey Bibik、Donaldo Carvalho、Bo Feng、David Fontaine、Prakash Gopinadham、David Hoa、Sanaldas KB、Henry Ku、Prasanth Kumar、Vikas Kumar、Tommy Lee、Leigh Maddock、Navneet Nagori、Marijana Novakovic、Ved Prakash Pathak、Stephanie Schuller、Chintan Shah、Harish Shetty、Andrew Stracner、Veerabahu Subramanian、Shawn Zandi、Andreas Zaugg、David Paul Zimmerman、Paul Zugnoni。
作者:Tim Crofts,阅读英文原文:IPv6 at LinkedIn Part I, "ChippIn'" Away at IPv4
感谢陈兴璐对本文的审校。