关于 Jimmy Song | 宋净超

Tetrate 布道师,云原生社区 创始人,CNCF Ambassador,云原生技术专家。

RSS 地址: https://jimmysong.io/blog/index.xml

请复制 RSS 到你的阅读器,或快速订阅到 :

Jimmy Song | 宋净超 RSS 预览

香港——内地的一面的镜子

2024-09-06 19:14:52

上个月,因为参加 KubeCon China,我第一次前往香港,这让我有机会近距离审视这颗“东方明珠”。

image
从尖沙咀眺望香港岛

我不记得之前在哪里看到一个说法,说是“香港是中国内地的一面镜子”。香港因其特殊的历史背景、经济发展轨迹以及在回归后的一系列表现等,许多人都在分析研究过程中会将香港的发展情况、社会治理经验教训等与内地进行关联和比较,认为其在某些方面可以为内地提供参考借鉴,就如同镜子一样反映出一些现象和问题的不同侧面及解决路径的可能性等。比如一些研究区域发展和社会治理的专家学者在相关论述中可能就会涉及到类似的观点表达。

香港与内地的不同

香港与内地存在着诸多不同,这些不同不光是表面上的:

维度 香港 内地
政治制度 资本主义制度,行政长官是特别行政区首长。 社会主义制度,人民代表大会制度。
法律体系 英美法系,判例法重要。 大陆法系,以成文法为主。
经济体制 自由市场经济,服务业和金融为主。 社会主义市场经济,公有制为主体,多种所有制发展。
文化方面 中西文化交融,保留大量中华传统文化。 以中华文化为主,地域文化多样。
教育体系 推行“三三四”学制,多语言教学,注重素质教育。 国家指导,地方负责,应试教育为主,统一教材。
医疗体系 公立私立并存,谨慎用药,社区医院为主。 医疗体系多元,大医院资源紧张,用药依据病情。
税收制度 地域来源征税,税种少,税率低。 居民身份征税,税种多,税负较高。
养老保障 强积金制度,雇主和雇员共同供款。 职工和居民基本养老保险,缴费比例不同。
语言使用 粤语为主,英语广泛使用。 普通话为主,各地方言众多。
文字形式 使用繁体中文。 使用简体中文。
生活习惯 饮食清淡,煲汤文化,部分西方生活习惯。 饮食丰富多样,生活习惯因地域文化不同。
消费观念 消费多元化,注重品质,高端品牌接受度高。 消费观念多样化,与经济水平有关。
交通规则 靠左行驶,驾驶位在右侧。 靠右行驶,驾驶位在左侧。
住房情况 土地少,房价高,公屋制度完善。 住房类型多样,房价差异大。
电影分级 有明确的电影分级制度。 无明确电影分级,审查严格。
新闻出版审查 新闻出版较自由,但有监管。 严格的新闻出版审查制度。
网络开放度 互联网相对开放,全球大多数网站可访问。 互联网监管严格,部分国外网站被屏蔽。
护照含金量 可免签或落地签前往约 170 个国家和地区。 可免签或落地签前往约 80 个国家和地区。
计量单位使用 使用英制和公制单位。 主要使用公制单位。
电压和插座类型 220V,英式三插(G 型)。 220V,双孔和三孔插座(A 型、I 型)。
手机支付普及度 现金和信用卡普及,八达通卡使用广泛。 手机支付非常普及,微信支付和支付宝常用。
购物和零售模式 国际品牌与本地品牌并存,夜市和街边小店常见。 大型购物中心、超市、夜市、电商平台多样。
社交习惯 英语使用普遍,西方社交礼仪。 普通话为主,传统社交礼仪。
宗教信仰 多元宗教环境,宗教自由。 宗教信仰有限制,信仰自由受法律保护。
食品安全标准 食品进口和监控严格,国际标准。 标准逐渐完善,偶有问题。
工作时间和假期 每周 44 小时,公共假期多。 每周 40 小时,法定节假日较少。

香港拥挤的交通

香港岛是香港最繁华的地方,面积约 78.10 平方公里,这里集中了大量的商业、办公和住宅区域,吸引了众多人口和车辆,交通压力较大。在香港岛上,有一种极具特色的交通工具——叮当车,它也被称为有轨电车。叮当车全部分布在港岛北部狭长的地带,共有 6 条线路,全都经过港岛繁华热闹的地区,如铜锣湾、跑马地、中环等。它的车身通常为双层,造型古朴,当司机踩到踏脚时,车子会发出“叮当、叮当”的声响,故而得名。

image
香港岛上的叮当车

在香港旺角的街头,人群如潮水般涌动。这里是繁华都市的缩影,喧嚣与热闹交织成一幅独特的画卷。摩肩接踵的人们,怀揣着各自的梦想与故事,在这个充满活力的地方穿梭。时尚的店铺、美味的小吃、璀璨的灯光,共同构成了旺角的魅力。每一个匆忙的脚步,每一张洋溢着笑容的脸庞,都在诉说着这座城市的无限可能。旺角,一个让人感受香港脉搏跳动的地方,永远充满着生机与活力。

image
旺角的夜晚街景

香港岛地形以山地为主,地势较高,自北向南地势渐缓,环岛沿岸曲折,多美景港湾。岛上的主要山峰包括太平山、柏架山、奇力山等,其中太平山是香港岛的最高峰,海拔 554 米。

兰桂坊位于香港岛中西区中环,是一个聚集大小酒吧与餐馆的中高档消费区。它由德己立街、威灵顿街、云咸街、和安里、仁寿里及荣华里构成,宽约 20 米,长约 300 米。20 世纪中期,香港经济腾飞,商业高速发展,夜总会文化开始在香港流行,很多在香港工作或暂居的外国人渴求适合他们品味和要求的娱乐场所,兰桂坊便应运而生。每当夜幕降临,这里便会灯红酒绿,觥筹交错,置身这里让我仿佛置身东南亚,感觉跟泰国很像。

image
兰桂坊周边的街道夜景

本地特色

我在香港 City walk 的时候发现的一些本地特色。

我发现很多建筑使用竹子搭建的脚手架,现在竹子脚手架在大城市中很少见到了。

image
堆放在地上的竹子
image
使用竹子搭建的脚手架

我还在庙街看到算命一条街,还有一家店代客烧香。

image
算命一条街
image
代客拜先人

最后本地的粤菜真的很好吃,我吃了一道炸猪排,外焦里嫩,口水直流。

image
炸猪排

总结

在香港的这次旅行中,我不仅领略了这座城市的繁华与多样性,还感受到了它作为一面“镜子”所带来的思考。香港的独特之处在于它东西方文化的交融、现代与传统的结合,以及其与内地在政治、经济、文化等方面的显著差异。无论是乘坐叮当车穿行在港岛繁华的街道,还是漫步在兰桂坊体验夜生活的丰富多彩,亦或是在街头巷尾发现本地的特色文化,这一切都让我更加理解为什么有人说香港是中国内地的一面镜子。通过这面镜子,我们可以看到一个不同的视角,这不仅让我们更好地理解香港,也能反思内地的许多方面,为未来的社会和经济发展提供更多的借鉴和启示。

KubeCon China 2024 回顾:引领云原生技术的前沿动态

2024-08-27 10:23:48

今年的KubeCon China是首次在香港举办的盛会,持续了三天。作为会议的参与者及一个论坛的主持人,我在这篇文章中将分享会议的精彩内容和对服务网格及网关技术的深入讨论。

image
KubeCon China 现场画面

主题焦点

本次 KubeCon 新增了 AI 与开发者主题,以下是部分重点内容:

  1. 云原生技术在行业中的实际应用:特别是电动汽车和网络安全领域,如 Huawei 和 NIO 的共同探讨云原生技术如何加速电动汽车创新。

  2. Kubernetes 社区的力量:详细讨论了中国 Kubernetes 社区的影响力及其在推动区域云原生活动中的角色。

  3. 开源技术与人工智能的融合:探讨了中国及香港在开源与 AI 技术领域的先进地位及对区域技术创新的推动。

  4. 服务网格与 API 网关的最新进展:包括服务网格的最新技术更新及其与 Kubernetes 调度器的协同工作提高系统吞吐量的策略。

  5. 供应链安全的新策略:关注保障供应链安全的最新动态,特别是 SLSA 合规性的实践指南。

  6. 多集群管理与边缘计算:探讨了在不同架构下进行有效管理与创新的策略。

  7. AI 大模型的推理性能优化:讨论了无服务器架构下的 AI 大模型推理性能优化及相关技术进展。

Istio 与现代 API 网关:探索服务网格的未来

我与来自 Tetrate、阿里云和 Kong Inc.的行业领袖共同参与的圆桌讨论,深入探讨了 Istio 和 API 网关的最新进展及其融合带来的革新。

image
KubeCon China 2024 Istio 和现代 API 网关的圆桌论坛
  1. Istio 的革新:介绍了 Istio 1.123 版本中的 Ambient 模式优化,此模式作为新的架构选择,减少资源消耗同时提升性能。

  2. Ambient 模式与 Sidecar 模式的实用对比

    • 何时选择 Sidecar:需要高度隔离与详尽流量管理时。
    • 何时选择 Ambient:追求极致性能与资源效率时。
  3. Ambient 模式的发展挑战:尽管有诸多优势,Ambient 模式在复杂流量管理与多租户环境中仍面临挑战。

  4. 服务网格优化策略:讨论了服务网格的优化方法,如何提升云应用的性能与效率。

  5. 服务网格与 API 网关的整合:展示了这两大技术如何共同作用,支持更复杂的部署与运维模式。

Istio 的未来展望

徐中虎和何建鹏的分享中,我们了解到了 Istio 未来的可能发展方向:

Sandwich Waypoint

他们着重介绍了 Sandwich Waypoint,这是一种在 Istio 内管理和引导流量的复杂方法,特别是在环境模式下。这种 Waypoint 代理模式旨在通过充当处理、转换和转发客户端和服务器之间流量的中介层来简化和提高流量路由的效率。它利用了双 zTunnel 设置,其中位于通信通道两端的每个 zTunnel 协作封装和解码流量。Waypoint 本身负责执行额外的功能,如流量整形、安全检查和协议转换,从而在没有传统边车开销的情况下丰富服务网格功能。这种方法允许 Istio 保持强大的流量管理和安全功能,同时优化资源利用率并减少延迟。

Sandwich Waypoint 支持:

这是一种 Istio Ambient 模式中捕获七层流量模式,如下图所示。

image
Sandwich Waypoint 捕获流量

Istio Sandwich Waypoint 捕获七层流量的步骤如下:

  1. 通过 zTunnel 终止 HBONE 连接,到达 Waypoint,zTunnel 负责解码 HBONE 协议。
  2. Waypoint 提取目的地地址、源地址等信息用于处理流量及确定转发位置。
  3. Waypoint 扩展或解析传输层封装(TLV)数据,代理支持处理 TLV 以提供更多上下文。
  4. Waypoint 与同位 zTunnel 通信,与服务端 zTunnel 协调确保流量正确转移。
  5. 封装 HBONE,由服务端 zTunnel 发送到最终服务器目的地。实现 Istio 环境中服务的细粒度流量管理和路由并保持与现有网络协议兼容性。

Envoy Gateway 的前沿扩展

赵化冰在 KubeCon 上介绍了 Envoy Gateway 如何通过扩展 Kubernetes Gateway API 来增强功能与灵活性的演讲,涵盖了多种匹配与路由能力的扩展、新的资源和策略模型以及安全策略的细节。

总结

通过本次会议我们了解了 Istio 的 Ambient 模式和 Envoy Gateway 的进展。这些技术的讨论不仅展望了未来趋势,也提供了实用的洞察,助力技术实施与创新。

从黑神话悟空聊起:我心目中的 3A 大作

2024-08-23 14:47:39

随着 8 月 20 日《黑神话:悟空》的正式发售,瞬间点燃了玩家们对 3A 游戏无尽的热情与讨论。在这篇随笔中,我将漫步于记忆的长廊,从孩提时代的掌中世界到今日的次世代主机,细数那些陪伴我的游戏时光,并深入探讨我心目中 3A 大作的独特魅力。

我的游戏养成史

在中国,游戏曾一度被视为教育的绊脚石,是家长眼中的洪水猛兽。然而,正是这些看似微不足道的游戏机,悄然开启了我探索未知世界的奇妙之旅。

掌上游戏机

在我十岁左右,我获得了一个第一台游戏机,一台类似 Gameboy 的掌上游戏机。

image
90 年代的掌上游戏机(图片来自网络,复古游戏机)

这是我最早接触的游戏机,还有我最早接触的游戏《俄罗斯方块》。

游戏机厅

也进过游戏机厅,小学时每年寒暑假前都要写保证书,名叫《暑/寒假公约》,其中一定会有一条——“不去游戏机厅”。我只去过一两次,这些游戏机需要投币。

image
九十年代游戏机厅里的游戏机(图片来自网络)

这类游戏机上常玩的游戏是《街头霸王(Street Fighters)》。

image
FC 游戏:街头霸王

小霸王学习机

小霸王学习机,可以更换卡带,接上电视就能玩,那时候经常用它玩高桥名人的《冒险岛》。

image
小霸王学习机

虽然号称是学习机,但是我没有见过有谁用它来学习的。

image
FC 游戏:冒险岛

网吧

世纪之交的时候,网吧开始兴起,2000 年的时候我才第一次接触电脑,暑期的时候还参加电脑培训,练习过五笔打字,那时候也没学会,光顾着玩游戏了,我记得那时候还使用的是 3.5 英寸软盘,操作系统还是 Windows 98,使用的是笨重的 CRT 显示器。

image
90 年代末 2000 年初的网吧(图片来自网络)

2000 年左右,电脑上的游戏有《红色警戒》、《暴力摩托》、《三角洲部队》、《拳皇》,但是我最喜欢的还是《红色警戒 2》,从 2000 年一直到 2008 年。

image
红色警戒(红警 2)

最开始玩红警的时候年纪还小,是我自己一个人探索着玩,一开始做任务,甚至不知道怎样展开基地车,因为游戏是繁体字,很多我还看不懂。

单机游戏:2000 - 2008

除了红色警戒之外,我玩过的游戏还有《反恐精英》、《半条命》、《暗黑破坏神》、《仙剑奇侠传》、《魔兽争霸》,但这些游戏都不是我的菜,大多也玩不好,我还是钟情于红警,还有它的各种 mod。

网络游戏:2005 - 2008

在开始玩网络游戏之前,从来没有为玩游戏花过钱,因为中国的各种盗版游戏泛滥,网上到处都可以下载到。

在此之后就是网游的时代了,什么《传奇》、《大话西游》,腾讯的各种游戏比如《泡泡堂》、《劲舞团》、《地下城与勇士》、《QQ 飞车》这些我都玩过。

休闲游戏:2009 - 2013

曾经有一段时间,大概 2008 到 2013 年,校友网、QQ 空间上诞生的网页游戏,比如《抢车位》、《开心农场》等火爆一时,很多人定闹钟偷菜,也诞生了一些做网页游戏的网站。

还有一些流行的休闲游戏,比如《植物大战僵尸》也是我特别喜欢的一款游戏。跟它同时期的一些游戏也不错。

手机游戏:2014 - 2023

《开心消消乐》、《原神》、《辐射:避难所》。不过很多流行的手机游戏比如《绝地求生》、《穿越火线》我都没有玩过。

主机游戏:2023 至今

从 2009 年到 2023 年可以说我就没有再接触主机游戏和网游了,平时也很少玩游戏,直到 2023 年 12 月,我获得了我的第一台游戏主机 PS5,情况才发生了改变。

在此之前我曾玩过朋友的任天堂主机,但是并不是很喜欢任天堂主机的游戏,画面质量,游戏类型都不是我喜爱的。

但是从我接触的第一个 PS5 主机游戏《双人成行》开始,我对主机游戏甚至说对电子游戏的看法大大改观了。一起我对大部分游戏都提不起兴趣,感觉那些游戏就是打发打发时间,玩久了就很无聊,但是接下来的几款游戏让我体验到了什么是 3A 大作。

3A 大作

在拥有了 PS5 之后,玩什么游戏就是一个问题了。我订阅了二挡会员,所以起初我下载和玩了一些游戏库里的游戏。

双人成行

《双人成行》这是一个必须两个人配合才能完成的游戏,通过 PS5 的手柄来操控,终于让我体会到玩游戏的快感。这也是我第一次购买的实体游戏,我购买了游戏光盘。

image
双人成行

地平线:西之绝境

《地平线:西之绝境》在 PlayStation 的二挡会员库里,所以我也下载和游玩了这款游戏。这款游戏以废土世界的旧金山为背景,里面有很多奇思妙想的未来机械生物。但是我对它的剧情和部落完全不感兴趣,只是享受其中打斗的乐趣,因为主角可以使用的武器和技能有很多。

image
地平线:西之绝境

对马岛之魂

《对马岛之魂》,故事发生在古代日本的对马岛,虽然景色很美,但是打斗风格及剧情让我提不起兴趣,一个日本人反抗蒙古侵略者的故事,我只玩了几个小时就卸载了游戏。

image
对马岛之魂

蜘蛛侠:Miles Morales

《蜘蛛侠:Miles Morales》,以纽约为背景,化身蜘蛛侠在纽约的城市上空飞来飞去,还有爽快的打斗,确实是一款很刺激的游戏,但是我对漫画人物为主角的游戏也不是特别喜欢,这款游戏的故事也比较简单,很快就通关了。

image
蜘蛛侠:Miles Morales

极地战嚎 6

《极地战嚎 6》,是一个虚构的现代国家 Yara 为背景(实际上是映射古巴)的游击队反抗政府军的故事,这是育碧旗下的游戏,已经出到第六代,有点像罐头游戏,完成主线任务也很快,我喜欢里面的各种枪械和野路子武器,剧情能够发人深省。

image
极地战嚎 6

荒野大镖客 2

《荒野大镖客 2》是以 19 世纪末的美国西部为背景,玩了不到 1 个小时,实在无法带入剧情,对这个的故事和背景也不感兴趣,索性不玩了。

image
荒野大镖客 2

艾尔登法环

我玩过的最后一个 3A 大作是《艾尔登法环》,这是我第一次玩魂系游戏,其中的世界观,复杂的技能点加成,庞大的地图,开放世界都给我造成很大的困惑,尤其是强大的怪物,我一开始玩了几个小时,就死过无数次,被大树守卫很轻易就秒杀,甚至一个普通怪物三两下就把我干掉,我感觉玩这个游戏很痛苦,完全无法体会其中的乐趣,直到我了解可以购买卢恩,将角色升级到满级,然后玩这个游戏就可以轻松很多。

image
艾尔登法环

不过这个游戏偶尔还是会让人感觉很不适,尤其是各种迷宫一样的墓地,阴暗的环境,下水道,恶心的怪物。但是面对那些强大的怪物,当时死亡无数次后将其打败,可以体会到其中的快感,以及游戏庞大的地图,琳琅满目的武器,是我坚持玩下去的动力。

什么是我想要的 3A 游戏

在《黑神话:悟空》诞生之前,并没有一个让我眼前一亮的 3A 大作,它的出现就像一颗闪耀的新星。下面我将谈谈什么是我心目中的 3A 大作。

深入灵魂的叙事篇章

我心目中的 3A 大作,首先必须拥有一段深入人心的故事。它应当如同一部宏大的史诗,让玩家在跌宕起伏的剧情中与角色同悲共喜,体验一段段难忘的旅程。《黑神话:悟空》以其独特的中国神话背景,正是我所期待的那一抹亮色。

视觉与听觉的双重盛宴

高质量的美术与音乐是 3A 大作的另一大亮点。精美的画面、逼真的场景、细腻的角色设计,以及动人心弦的背景音乐和音效,共同构建了一个令人向往的虚拟世界。《黑神话:悟空》的预告片已经展现出了其在这方面的非凡实力。

流畅操作与无限玩法

流畅的操作手感与丰富的游戏玩法是 3A 大作的基石。无论是战斗系统的爽快感、解谜机制的巧妙设计,还是探索元素的无限可能,都应让玩家在享受游戏的过程中感受到无尽的乐趣与挑战。《黑神话:悟空》作为动作冒险游戏,其在这方面的表现无疑值得期待。

文化内涵的深度挖掘

对于国内玩家而言,游戏中融入的文化内涵往往能引发更深的共鸣与认同。《黑神话:悟空》以中国神话为背景,不仅展现了丰富的传统文化元素,更通过游戏这一载体将中华文化的魅力传播至世界各地。

持续的创新与支持

一款优秀的 3A 大作不仅需要在发布时惊艳四座,更需要在后续的开发与运营中保持活力与创新。持续的更新与支持不仅能够为玩家带来新鲜感与惊喜,更是游戏生命力的体现。《黑神话:悟空》作为国产 3A 的佼佼者,其后续的更新与支持同样值得我们期待。

结语

《黑神话:悟空》的发布不仅是对国产游戏的一次重大突破,更是对全球游戏界的一次震撼宣言。它让我看到了国产 3A 大作的无限可能。

image
黑神话:悟空

今天我就购入了《黑神话:悟空》,在游玩一段时间后我会发布新的博客谈谈我的游玩体验。

集成 Envoy Gateway 作为 Istio 服务网格中的入口网关

2024-08-13 13:43:16

Istio 提供了对入口网关的强大而灵活的支持,利用 Envoy 代理在其 sidecar 模式下运行。尽管 Istio 专注于管理集群内服务之间的通信,Envoy Gateway 旨在将应用程序暴露给外部世界,处理用户请求,并支持高级功能,如 OIDC 单点登录。通过结合 Istio 服务网格的功能和 Envoy Gateway 的高级网关功能,可以增强整体应用程序的可访问性和安全性。

下图显示了 Istio 网格中入口网关的流量路径。

image
Istio 入口网关流量路径

下一个图表显示了在引入 Envoy Gateway 后,流量如何从 Istio 网格的边缘流入内部网络。

image
引入 Envoy Gateway 后的流量路径

准备 Envoy Gateway 与 Istio 之间的互操作性

要将 Envoy Gateway 用作 Istio 的入口网关,请考虑以下关键点:

按照 快速启动文档 安装 Envoy Gateway。标记 Envoy Gateway 的命名空间以确保数据平面获得 Istio sidecar 注入:

kubectl label namespace envoy-gateway-system --overwrite=true istio-injection=enabled

配置 Envoy Gateway 的 sidecar 以不拦截进入网关的流量。注入的 sidecar 确保 Envoy Gateway 的组件及其创建的代理被包含在 Istio 网格中,并安装正确的证书以进行安全通信。

spec:
  ports:
  - port: 18000
    appProtocol: tls

应用补丁:

kubectl patch service -n envoy-gateway-system envoy-gateway --type strategic --patch-file control-plane-tls.yaml

配置 Envoy Gateway 不拦截入站流量:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: data-plane-sidecars
  namespace: envoy-gateway-system
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        pod:
          annotations:
            traffic.sidecar.istio.io/includeInboundPorts: ""
  routingType: Service

应用配置:

kubectl apply -f teg-sidecars-no-inbound.yaml

修改 GatewayClass 配置以将 sidecar 配置应用于 Envoy Gateway 数据平面中的所有 EnvoyProxy

spec:
  parametersRef:
    group: gateway.envoyproxy.io
    kind: EnvoyProxy
    namespace: envoy-gateway-system
    name: data-plane-sidecars

应用补丁:

kubectl patch gatewayclass teg --patch-file gtwcls-use-envoyproxy.yaml --type merge

安装 Istio

使用 minimal 配置文件部署 Istio 以避免部署入口网关:

istioctl install --set profile=minimal -y

重启 Envoy Gateway 控制平面

在 Istio 的 sidecar 注入准备好后,重启所有 Envoy Gateway 控制平面的 pod:

for d in envoy-gateway envoy-ratelimit teg-envoy-gateway teg-redis;
	do kubectl rollout restart deployment -n envoy-gateway-system $d;
done

部署测试应用程序

在安装 Istio 后部署测试应用程序,以确保它们也接收到 sidecar 注入:

kubectl create namespace httpbin
kubectl label namespace httpbin --overwrite=true istio-injection=enabled
kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml

配置 Envoy Gateway

现在配置 Envoy Gateway 以处理边缘流量:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: apps
  namespace: httpbin
spec:
  gatewayClassName: teg
  listeners:
  - name: http
    protocol: HTTP
    port: 80

应用配置:

kubectl apply -f apps-gateway.yaml

部署应用网关,包括以下容器:

创建一个 HTTP 路由:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: httpbin
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: apps
  hostnames:
  - "www.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /httpbin/
    filters:
    - type: URLRewrite
      urlRewrite:
        hostname: httpbin.httpbin.svc.cluster.local
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /
    backendRefs:
    - kind: Service
      name: httpbin
      port: 8000

应用路由配置:

kubectl apply -f httpbin-route.yaml

发送测试请求

获取网关的负载平衡器 IP 地址并发送测试请求:

export GATEWAY_URL=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=apps -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
curl -v -H Host:www.example.com http://$GATEWAY_URL/httpbin/get

你应该能看到来自 httpbin 服务的正确响应:

*   Trying 34.41.0.90:80...
* Connected to 34.41.0.90 (34.41.0.90) port 80
> GET /httpbin/get HTTP/1.1
> Host:www.example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< server: envoy
< date: Wed, 31 Jul 2024 08:21:58 GMT
< content-type: application/json
< content-length: 282
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 11
<
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "www.example.com",
    "User-Agent": "curl/8.7.1",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-External-Address": "123.120.227.173"
  },
  "origin": "123.120.227.173",
  "url": "http://www.example.com/get"
}
* Connection #0 to host 34.41.0.90 left intact

启用严格 mTLS

通过应用以下配置启用严格 mTLS:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT

应用配置:

kubectl apply -f strict-mtls.yaml

为网关启用 TLS

创建服务签名的根证书和私钥:

mkdir example_certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt

www.example.com 创建证书和私钥:

openssl req -out example_certs/www.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/www.example.com.key -subj "/CN=www.example.com/O=www organization"
openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/www.example.com.csr -out example_certs/www.example.com.crt

为入口网关创建一个密钥:

kubectl create -n httpbin secret tls httpbin-credential --key=example_certs/www.example.com.key --cert=example_certs/www.example.com.crt

配置入口网关:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: apps
  namespace: httpbin
spec:
  gatewayClassName: teg
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - name: httpbin-credential

应用配置:

kubectl apply -f tls-apps-gateway.yaml

发送测试请求:

curl -v -H Host:www.example.com --resolve "www.example.com:443:$GATEWAY_URL" --cacert example_certs/example.com.crt "https://www.example.com:443/httpbin/get"

你应该可以通过 HTTPS 在网格内访问 httpbin 服务。

结论

通过将 Envoy Gateway 集成为 Istio 服务网格中的入口网关,你可以利用两者的优势:Istio 的强大服务网格能力和 Envoy Gateway 的高级网关功能。这种设置增强了你的应用程序的安全性、可扩展性和灵活性,提供了无缝且安全的用户体验。通过仔细的配置和正确的工具,管理服务网格内外的流量变得更加高效和有效,确保你的应用程序始终可访问并且安全。

Istio 配置安全:如何避免错误配置

2024-08-06 11:03:02

Istio 是一个功能强大的服务网格解决方案,提供零信任安全性、可观测性和高级流量管理等功能,且无需修改代码即可实现。然而,由于配置错误,我们经常会遇到意料之外的行为。本文将介绍几种常见的 Istio 配置错误,解析其背后的原理,并通过示意图展示如何识别和解决这些问题。我们还将介绍 Tetrate 提供的工具——TIS Config Analyzer,这是一种优化 Istio 操作效率和安全性的工具。

配置错误导致的事故案例

以下是两个由于配置错误导致的典型事故案例:

  1. Amazon Web Services 2017 年停机事件:一次简单的输入错误导致了广泛的服务中断,影响了数千个在线服务和应用,突显了即使在成熟的云基础设施中,一个小小的配置错误也会引发严重后果。

  2. GitLab 2017 年数据丢失事故:由于配置错误,GitLab 在进行数据库维护时误删除了大量生产数据。尽管备份机制被配置好,但错误的配置阻止了数据的及时恢复。

这些案例表明,正确的配置管理对于防止服务中断和数据丢失至关重要。

常见的 Istio 配置错误类型

Istio 配置错误主要分为以下几大类:

  1. AuthorizationPolicy(授权策略):命名空间不存在、仅允许 HTTP 方法和完全限定的 gRPC 名称、主机没有匹配的服务注册表条目、字段需要启用 mTLS、未找到服务帐户等。
  2. DestinationRule(目标规则):同一主机子集组合的多个目标规则、主机在服务注册表中没有匹配条目、子集标签在任何匹配主机中未找到等。
  3. Gateway(网关):同一主机端口组合的多个网关、网关选择器在命名空间中未找到匹配的工作负载等。
  4. Port(端口):端口名称必须遵循特定格式、端口的应用协议必须遵循特定格式等。
  5. Service(服务):未找到暴露与服务相同端口的部署等。
  6. VirtualService(虚拟服务):目标权重的路由没有有效的服务、指向不存在网关的虚拟服务等。

常见的 Istio 配置错误示例

在 Istio 的日常使用中,以下是一些最常见的配置错误:

  1. 虚拟服务指向不存在的网关:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: details
      namespace: bookinfo
    spec:
      hosts:
        - details
      gateways:
        - non-existent-gateway
    

    在这种情况下,details 虚拟服务试图通过一个不存在的 non-existent-gateway 进行路由,导致流量管理失败。

  2. 虚拟服务引用不存在的服务子集:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: details
      namespace: bookinfo
    spec:
      hosts:
        - details
    

    如果 details 服务没有定义相应的子集,请求将因无法找到正确的服务实例而被拒绝。

  3. 网关找不到指定的服务器凭证:

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: cert-not-found-gateway
      namespace: bookinfo
    spec:
      selector:
        istio: ingressgateway
      servers:
        - port:
            number: 443
            name: https
            protocol: HTTPS
          tls:
            mode: SIMPLE
            credentialName: "not-exist"
    

    这会导致 TLS 握手失败,因为指定的凭证 not-exist 不存在。

配置验证

为了减少由于配置错误而导致的服务中断风险,配置验证成为了一个不可或缺的步骤。配置验证可以分为以下两种:

推荐的配置验证工具

istioctl validate

istioctl validate 用于验证 Istio 配置文件(如 YAML 文件)的语法和基本结构,确保配置文件符合 Istio API 的规范。它可以在配置应用到集群之前检测出语法错误和格式问题,是一个静态分析工具,通常结合 CI 流程使用,防止无效配置文件应用到集群中。

istioctl analyze

istioctl analyze 是一个强大的诊断工具,用于分析 Istio 集群的运行状态和配置一致性。它不仅检查配置文件的语法,还可以检查集群中实际应用的配置,找出潜在的问题和冲突。istioctl analyze 提供动态分析功能,能够识别集群运行时的配置错误和潜在问题。

istioctl analyze 的配置流程如下:

  1. 收集配置数据:首先,istioctl analyze 收集来自指定源的 Istio 配置数据。这些源可以是活动的 Kubernetes 集群,也可以是本地的配置文件。
  2. 解析和构建模型:工具解析收集的配置数据,构建一个内部表示 Istio 配置的模型。
  3. 应用分析规则:随后,它应用一系列预定义的规则来分析这个模型,检测潜在的配置问题。这些规则涵盖从安全漏洞到性能问题的各种潜在问题。
  4. 生成报告:分析完成后,istioctl analyze 输出一个包含所有发现问题的详细报告。如果没有发现问题,它会通知用户配置看起来没有问题。

下面是 istioctl analyze 的工作流程图:

image
istioctl analyze 的工作流程

Kiali

Kiali 是管理和可视化 Istio 服务网格的重要工具,提供对网格健康状况、性能和配置状态的实时洞察。通过将 Kiali 集成到 Istio 环境中,可以通过以下方式增强配置安全性:

将 Kiali 与 istioctl validateistioctl analyze 等工具结合使用,能确保更为稳健的方法来预防和解决 Istio 配置错误,进而提升服务网格的安全性和效率。

Tetrate 的 TIS 中的 Config Analyzer 工具介绍

为了帮助开发者和运维人员避免常见的配置失误,Tetrate 开发了 TIS Dashboard 中的 Config Analyzer 工具。该工具能够自动验证 Istio 的配置,根据最佳实践分析服务网格的配置问题,并提供优化建议。Config Analyzer 可以自动检测 Istio 服务网格中的配置问题,提供解释及解决方案,支持按需检测配置中的错误。

image
TIS Config Analyzer 可以按需检测配置中的问题

总结

正确配置 Istio 是确保服务网格健康运行的关键。通过了解和避免常见配置错误,以及利用如 Tetrate 的 TIS Config Analyzer 这样的高级工具,您可以确保 Istio 环境的稳定性和安全性。记住,一个小小的配置错误可能导致整个服务网格的故障,因此持续监控和审核配置是非常必要的。

参考

保障 Istio 安全:解决关键安全漏洞及最佳实践

2024-07-25 14:09:37

引言

近期,Wiz 研究团队发布了博客,揭示了 AI 服务中的租户隔离漏洞,引起了广泛关注。该研究详细阐述了多个 AI 服务供应商存在的安全缺陷,特别是 SAP AI Core 平台。通过合法的 AI 训练过程,研究人员能够绕过 Istio 服务网格中的流量劫持,进而横向移动并接管服务,获取客户的私人文件和云环境凭证。这些发现凸显了当今云服务和管理平台在确保隔离和沙盒环境方面面临的挑战。

关于 UID 1337
Istio 选择 UID 1337(leet 的变体)作为 istio-proxy 容器中的用户 ID 是为了便于配置并避免权限冲突。这个数字在技术和游戏文化中象征“精英”(elite),有助于防止与其他常规用户 ID 冲突,确保流量管理操作不受权限问题干扰。

在这个背景下,Istio 作为一个重要的服务网格解决方案,同样面临着类似的安全问题,尤其是在 sidecar 注入和流量管理等关键功能上。这篇博客旨在探讨如何保护 Istio 服务网格的安全,并提供一套全面的缓解措施。我们还将讨论多层安全策略如何有效增强 Istio 的安全性,以应对类似 Wiz 报告中提到的挑战。

概述

Istio 主要用于管理 Kubernetes 中的东西向流量,提供详细的流量管理功能,如请求路由、负载均衡和故障恢复策略。虽然 Istio 提供了流量加密、认证和授权等安全功能,但它本身不应被视为防火墙。为了确保 Istio 网格中的服务安全,除了使用 Istio 自身的安全功能,还需要结合底层网络和基础设施的安全措施,比如 CNI 和安全容器。此外,微分段技术可以用来实现更细粒度的隔离,提高安全性。

不论是 Sidecar 模式还是 Ambient 模式,都是通过劫持应用程序 Pod 的流量到数据平面代理中进行处理和转发的。如果没有成功拦截到应用程序流量或者被仿冒程序冒充了 Istio 而执行操作,就会有安全漏洞出现。

下图展示了通过绕过或仿冒 Istio 系统用户而造成的安全漏洞存在的位置。

image
能够绕过 Istio 中流量劫持的“安全漏洞"

接下来,我们将探讨“安全漏洞”产生的具体情况及应对策略。

绕过 Istio Sidecar 注入

在命名空间级别禁用注入

在 Pod 级别禁用注入

绕过流量重定向到 Istio Sidecar

滥用流量重定向注解

滥用 Pod 的 UID

滥用 Pod 能力(NET_ADMIN、NET_RAW)

绕过入站流量约束

滥用 PeerAuthentication

绕过出站流量约束

滥用 ServiceEntry

滥用 ExternalName 服务

无法控制地更改 Istio Sidecar 配置

滥用 Sidecar 资源

滥用 EnvoyFilter

服务网格应作为分层防御的一部分

服务网格被描述为现有安全模型的一个补充层,通过在传统安全控制之上添加更细粒度的安全策略来增强微服务的安全性。然而,文章强调了服务网格无法独立保障微服务的全面安全,而是应当作为整体安全策略的一部分。

image
微服务安全分层架构

服务网格主要通过在每个服务实例旁部署一个轻量级的代理(sidecar),来管理和控制网络流量。这使得它能够在网络层面上实现精细的流量控制和策略执行,如流量加密、身份认证和授权。尽管服务网格能够提供诸如流量控制、服务发现和断路器等功能,这些功能本质上是对网络流量的管理,无法解决所有安全问题。例如,它不能替代应用层防火墙、入侵检测系统和数据安全等更传统的安全措施。

此外,服务网格依赖于正确的配置和管理,配置不当可能导致安全漏洞。因此,尽管服务网格是现代微服务架构中不可或缺的一部分,它应该与传统的安全措施相结合,共同构成一个全面的、多层次的安全策略框架。参考如何通过服务网格增强微服务的安全性以进一步了解如何加强服务网格的安全。

长期解决方案和社区合作

Istio 社区每年都会进行一次安全审计,见 2021 年2022 年 的安全审计结果。从结果中我们可以看到,Istio 的安全态势有了很大的提升。确保你的 Istio 服务网格符合安全最佳实践。另外,你还需要关注 Istio CVE 公告栏,或者使用如 Tetrate Istio Subscription 这类工具来扫描 Istio 服务网格的各种 CVE,部署符合 FIPS 并经过 FIPS 验证的 Istio 发行版。

结论

服务网格通过在应用程序外部管理控制流,为微服务架构提供了额外的安全层。这允许在不影响应用程序性能的前提下,加强服务之间的通信安全。在部署服务网格时,推荐使用 Istio 的 Egress Gateway 来管理出口流量,结合 Kubernetes 的 NetworkPolicy,确保所有出口流量都必须经过网关,从而防止潜在的数据泄露和其他安全威胁。

参考

乌兰察布之旅:探索火山与失落的村庄

2024-07-23 15:24:08

上个周末,我从北京自驾前往乌兰察布,经历了一段全程 995 公里的旅程。周五晚上,我从北京东四环出发,驶过 295 公里,抵达乌兰察布兴和县,暂住一晚。清晨,我们满怀期待地出发,迎接乌兰哈达火山的壮丽景观。

乌兰哈达火山地质公园是一个免费开放的景区,景区公路和一些配套设施还在建设中。我从北面进入公园,首先到达的是 3 号火山。

当天虽然温度只有 31°C,但紫外线格外强烈。11 点钟,我们开始攀登 3 号火山。烈日当空,紫外线炙热,我穿着防晒服,T 恤已经被汗水浸湿,汗珠如豆粒般大小不断滴落,仿佛在与这片广袤的天地进行一场激烈的对抗。当地的海拔达到了 1600 米,空气清新而稀薄。

乌兰哈达火山地质公园

乌兰哈达火山地质公园位于内蒙古乌兰察布市,这里保存着一片完好的火山群,展现着大自然的鬼斧神工和地质变迁的壮丽画卷。火山群由多座火山组成,其中最著名的 3 号和 6 号火山,被分别称为“北炼丹炉”和“南炼丹炉”。

我们首先攀登了 3 号火山,从山顶俯瞰,火山口清晰可见,周围的火山岩石展现出奇特的地质构造,仿佛在诉说着那段遥远而神秘的历史。随后,我们自驾途径 6 号火山,由于交通堵塞,不得不掉头返回。3 号火山的南面已经被挖得面目全非,只有从北面看才能看出完整的火山形状。

image
内蒙古乌兰察布乌兰哈达火山地质公园,3 号火山(北炼丹炉)
image
内蒙古乌兰察布乌兰哈达火山地质公园,6 号火山(南炼丹炉)

夜晚,我们住在现代化的“蒙古包”里。蒙古包的构造独特,圆形设计不仅抵御风沙,还能保持内部温暖。现代蒙古包则在传统基础上融合了现代元素,提供了更为舒适的居住体验。

image
夜晚住宿在现代「蒙古包」

火山岩石具有独特的地质特征,这些岩石形成于数百万年前火山喷发的熔岩冷却后。它们质地坚硬,颜色多样,从黑色到红色不等。这些岩石不仅是大自然的杰作,也是地质学研究的宝贵材料。

image
火山环境特写

生态保护红线

生态保护红线是为了保护生态系统、维护生态安全而划定的严格保护区域。乌兰察布地区的生态保护红线确保了火山地质公园和周边生态环境的原始风貌得以保存。这片大地上的生态保护红线,像是一道无形的屏障,守护着这片古老而神秘的土地。

image
察哈尔右翼后旗生态保护红线

卓资县,位于乌兰察布的偏远角落。由于经济发展滞后,人口逐年减少,许多村庄因此被废弃。这些废弃的村庄见证了人口迁移和城镇化的历史变迁,仿佛在无声地诉说着一个个时代的故事。

image
卓资县的村庄里羊比人多

上图中上方左二为战国赵长城遗址,公元前 300 年,赵武灵王修建的长城,今复何在?

赵长城,为赵武灵王时所筑,故也称赵武灵王长城。据《史记·匈奴列传》记载:“赵武灵王变俗,胡服,习骑射,北破林胡、楼烦,筑长城,自代并阴山下,至高阙为塞。”

拍摄于乌兰察布市察哈尔右翼后旗四胜路马房沟附近的树林里,成百上千只鸟时而隐藏在树林里,时而飞到远处的山坡上,蔚为壮观。

我们在生态保护红线的地图上采用投飞镖的方式随机造访一个村子,投中了胜利村。几经辗转,我们发现胜利村在手机地图上甚至没有路线指引。最终到达的村子已经不复存在,只留下一些荒废的房子,静静地伫立在这片广袤的土地上。

image
卓资县位于生态保护红线内荒废的房子

总结

这次乌兰察布之旅让我深刻感受到了内蒙古独特的自然景观和人文历史。从壮丽的火山地质公园到失落的乡村,每一处景点都给我留下了深刻的印象。这次旅程不仅让我放松了身心,也让我对生态保护和人口流动有了更多的思考。在这片辽阔的土地上,我看到了自然的壮丽与人类历史的沉浮,内心也随之变得更加丰盈和宁静。

介绍 Tetrate Enterprise Gateway 及与 Istio 集成:云原生应用的全面网关解决方案

2024-07-22 16:43:16

TEG 简介

Tetrate Enterprise Gateway(TEG)是基于 Envoy Gateway (EG) 的企业级解决方案,专门针对 Envoy Proxy 设计,通过 Kubernetes Gateway API 提供更易于消费的 Envoy 代理配置和管理包。TEG 结合了 Kubernetes Gateway API 的特性,支持在 Kubernetes 中轻松暴露服务和应用程序。

TEG 相对于 Envoy Gateway 的主要新增特性包括:

  1. 全局速率限制(Rate Limiting):TEG 支持基于 IP 5-tuple、请求头等进行流量控制,需要通过 Redis 实例管理。
  2. WAF 功能(Web Application Firewall):TEG 提供了与 mod_security 兼容的 WAF 功能,增强了安全防护能力。
  3. OIDC/OAuth2认证:支持在网关级别进行 OIDC/OAuth2 认证,应用程序可以按路由配置认证方式。
  4. 使用 Kubernetes Gateway API:相较于其他 API,Kubernetes Gateway API 的设计更加现代,结合了众多 Ingress 实现的经验,将网关的配置与流量的路由分离,使平台所有者可以管理网关,而应用团队可以掌控流量路由。

TEG 将 Envoy 的高级网络流量处理能力带入 Kubernetes 环境,提供了一种简化的方法来部署和管理负载平衡、API 网关功能、安全控制等,同时支持现代的、开放的应用程序暴露 API,如 Kubernetes Gateway API。这些特性使 TEG 成为一个功能丰富、易于管理的企业级网关解决方案。

TEG 的能力

Tetrate Enterprise Gateway for Envoy (TEG) 构建于 Envoy Gateway 项目之上,提供了一种易于使用和操作的入口,具有先进的按请求流量控制功能、与现有环境的轻松集成,以及一流的可观测性,以理解应用流量和入口健康状况。

易于安装、操作和升级

TEG 从头到尾注重易用性:从首次安装到启用应用团队,从故障排查到执行升级。TEG 的初始安装只需几分钟,你就可以开始使用高级功能,如速率限制、单点登录和金丝雀流量路由。TEG 还简化了运维流程,与你现有的指标、跟踪和日志记录管道相适应,我们还提供了一个完整的、预配置的可观测性堆栈,以评估 EG 产生的数据,并帮助你计划如何将 TEG 集成到你的现有指标堆栈中。

操作性:一流的功能

TEG 由在生产环境中运行大型、关键系统的经验丰富团队构建。TEG 简化了漏洞检查和持续升级过程,与你现有的指标和跟踪提供商轻松集成,并为你现有的 Grafana 部署提供了一套强大的入口可观测性仪表板。

与现有的环境集成

TEG 不仅适用于绿地部署的启动,还可以直接与传统环境以及现代云原生环境集成。它可以帮助你在现有的应用生态系统和你正在构建的云原生目标之间架起桥梁。

引入现有的可观测性堆栈

你的组织可能已经有一个可观测性系统,你的应用和运营团队已经训练有素地使用它。TEG 可以轻松地嵌入到现有的基础设施中,并在你的组织中运行。TEG 将使 Envoy 的丰富指标集导出,让你的应用团队对其应用流量的行为有最佳的洞察,并看到他们所做配置更改的效果。TEG 还为运行它的平台团队提供了仪表板和警报功能,使你能够自信地操作并快速解决发现的问题。

简单的负载平衡

Envoy 非常强大,但要使其启动并运行简单用例可能很难——像 Istio 这样的系统提供 Envoy 入口管理作为更广泛功能套件的一部分,也附带了许多与简单、流畅的操作体验相冲突的额外功能。这就是 Envoy Gateway 存在的原因:使 Envoy 的强大功能易于用于入口用例。

简单的 API 网关

组织中绝大多数 API 网关的使用归结为三件事:认证发起请求的用户;限制用户对服务的访问;在此 API 端点的服务实例之间进行负载平衡。TEG 简化了在传统和云原生环境中完成这三项任务的过程。

TEG 的架构

下图展示的是 TEG 的架构图。

image
TEG 架构图

从架构图中可以看出,Tetrate Enterprise Gateway for Envoy (TEG) 的架构设计包括以下主要组件和流程:

主要组件

  1. Kubernetes Cluster

    • Envoy Gateway:作为控制平面,配置和管理 Envoy 代理,消费 Kubernetes Gateway API 的配置。
    • Metrics Collection:使用 Prometheus 或 OpenTelemetry (OTEL) 作为指标收集点,用于监控 Envoy Proxy 的性能和健康状态。
  2. Envoy Proxy

    • 作为数据平面,直接处理所有进入的流量,支持基于 Kubernetes Gateway API 的配置。
  3. Coraza WAF

    • 作为 TEG 的一部分部署,执行 WAF 规则以保护应用免受恶意请求攻击。
  4. Redis Rate Limit Store

    • 作为全局速率限制的存储解决方案,用于跨所有 Envoy 实例维护统一的速率限制计数。
  5. Your OIDC Server

    • 处理 OAuth2.0 和 OIDC 认证流程,确保只有经过认证的用户可以访问特定的路由和服务。

工作流程

  1. 流量入口

    • 所有外部流量首先通过上游的负载均衡器,然后被路由到 Envoy Proxy。
  2. Envoy Proxy 处理

    • Envoy Proxy 根据 Kubernetes Cluster 中的 Envoy Gateway 的配置处理流量。
    • 配置信息包括路由规则、安全策略(如 WAF 和速率限制)等。
  3. 安全和认证

    • Coraza WAF:在流量到达应用前,根据配置的 WAF 规则进行检查和过滤,提高安全性。
    • OIDC 认证:OIDC Server 处理认证,Envoy Proxy 根据 OIDC Server 的验证结果决定是否允许访问。
  4. 速率限制

    • 使用 Redis 存储进行速率限制,Envoy Proxy 将根据从 Redis 获取的数据执行速率限制策略。
  5. 性能监控

    • Envoy Proxy 的性能和健康状态通过集成的指标收集系统(Prometheus 或 OTEL)进行监控。

配置和管理

这种架构设计利用了 Kubernetes 的灵活性和扩展性,并通过 Envoy 提供了强大的流量管理和安全功能。

部署 TEG

执行下面的命令部署 TEG V0.0.0:

export REGISTRY="oci://docker.io/tetrate"
export CHART_VERSION="v0.0.0-latest"
helm install teg ${REGISTRY}/teg-envoy-gateway-helm \
 --version ${CHART_VERSION} \
 -n envoy-gateway-system --create-namespace

检查部署:

kubectl get pod -n envoy-gateway-system

你将看到下面的结果:

NAMESPACE              NAME                                                       READY   STATUS    RESTARTS        AGE
envoy-gateway-system   envoy-gateway-596dfbcb88-tx7xb                             1/1     Running   0               3m55s
envoy-gateway-system   envoy-ratelimit-674b8c955c-jhlfn                           2/2     Running   2 (3m48s ago)   3m54s
envoy-gateway-system   teg-envoy-gateway-64fd8c8fbb-59b4l                         1/1     Running   0               3m55s
envoy-gateway-system   teg-redis-86bb7d9b9d-27n44                                 1/1     Running   0               3m55s

部署示例应用:

kubectl create namespace httpbin
kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml

部署 Envoy Proxy:

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: dedicated-gateway
  namespace: httpbin
spec:
  gatewayClassName: teg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
EOF

然后你会在 envoy-gateway-system 命名空间下看到一个新的 Envoy 代理。

部署 HTTPRoute,给网关配置路由:

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: httpbin
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: dedicated-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /httpbin/
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - group: ""
          kind: Service
          name: httpbin
          port: 8000
EOF

这个路由配置中有一个 URLRewrite filter,重写 URL 前缀,去掉了 /httpbin/ 部分。

发送流量测试:

export DEDICATED_GATEWAY_IP=$(kubectl get gateway/dedicated-gateway -n httpbin -o jsonpath='{.status.addresses[0].value}')
curl -i http://${DEDICATED_GATEWAY_IP}/httpbin/get
为什么使用 /httpbin/get?

在通过 Tetrate Enterprise Gateway for Envoy (TEG) 暴露 httpbin 应用时,选择 /httpbin/get 作为访问路径的原因主要是为了在同一个 Envoy 网关下能够同时支持多个应用或服务,并能根据不同的路径将流量正确地路由到指定的服务。

这种路径前缀的设置方法允许系统管理员或开发人员为每个服务配置独立的路径前缀,从而通过单一的入口点(即 Envoy 网关)来管理对多个后端服务的访问。这样的配置增加了路由的灵活性,使得在不更改现有服务配置的情况下,轻松地扩展或修改服务的暴露方式。

作为 Istio 的入口网关

Istio 提供了成熟且灵活的入口网关支持,基于与 Tetrate Enterprise Gateway(TEG)相同的 Envoy 代理。Istio 主要专注于处理集群内服务之间的通信。相较之下,TEG 设计用于向外界暴露应用,处理人类用户的请求,并支持如 OIDC 单点登录等高级功能。通过结合 Istio 网格和 TEG 的高级网关功能,两者可以共同使用,以提升整体应用的可访问性和安全性。

以下图示展示了 Istio 网格中入口网关的流量路径。

image
Istio 中入口网关的流量路径

下图展示了在引入 TEG 之后,流量如何从 Istio 网格边缘进入到内部。

image
引入 TEG 后流量从 Istio 网格边缘进入内部的流量路径

将 TEG 集成到 Istio 网格中,通过在 TEG 上配置 sidecar 来颁发证书,同时避免 sidecar 拦截 TEG 中的流量。然后通过 Envoy Gateway 控制入口网关的流量路径。

为 TEG 与 Istio 的互操作做准备

为了使 TEG 作为 Istio 的入口网关,应注意以下关键点:

为 TEG 的命名空间添加标签,以确保数据平面获得 Istio sidecar 的注入。

kubectl label namespace envoy-gateway-system --overwrite=true istio-injection=enabled

我们还需要配置 TEG 的 sidecar,使其不处理进入网关的 Envoy 流量。注入 sidecar 的目的是使 Envoy Gateway 的组件及其创建的代理能够被纳入 Istio 网格,并挂载正确的证书进行安全通信。

spec:
  ports:
  - port: 18000
    appProtocol: tls
kubectl patch service -n envoy-gateway-system envoy-gateway \
     --type strategic --patch-file control-plane-tls.yaml

配置 Envoy Gateway 中的 sidecar 不拦截流量:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: data-plane-sidecars
  namespace: envoy-gateway-system
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        pod:
          annotations:
            traffic.sidecar.istio.io/includeInboundPorts: ""
  routingType: Service
kubectl apply -f teg-sidecars-no-inbound.yaml

修改 GatewayClass 的配置,将上述 sidecar 配置应用到 Envoy Gateway 数据平面的所有 EnvoyProxy 上:

spec:
  parametersRef:
    group: gateway.envoyproxy.io
    kind: EnvoyProxy
    namespace: envoy-gateway-system
    name: data-plane-sidecars
kubectl patch gatewayclass teg --patch-file gtwcls-use-envoyproxy.yaml --type merge

安装 Istio

使用 minimal profile 部署 Istio,从而不部署 Ingress Gateway:

istioctl install --set profile=minimal -y

重启 TEG 控制平面

现在 Istio 的 sidecar 注入已准备就绪,我们将重启所有 TEG 控制平面 Pod,它们将带有 sidecar 重新启动。

for d in envoy-gateway envoy-ratelimit teg-envoy-gateway teg-redis; \
    do kubectl rollout restart deployment -n envoy-gateway-system $d; \
    done

部署测试应用

此步应在安装 Istio 之后进行,以确保它们也获得 sidecar 的注入。

kubectl create namespace httpbin
kubectl label namespace httpbin --overwrite=true istio-injection=enabled
kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml

配置 TEG

现在我们配置 TEG 处理边缘流量。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: apps
  namespace: httpbin
spec:
  gatewayClassName: teg
  listeners:
  - name: http
    protocol: HTTP
    port: 80
kubectl apply -f apps-gateway.yaml

部署应用网关,包含以下容器:

创建 HTTP 路由:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: httpbin
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: apps
  hostnames:
  - "www.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /httpbin/
    filters:
    - type: URLRewrite
      urlRewrite:
        hostname: httpbin.httpbin.svc.cluster.local
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /
    backendRefs:
    - kind: Service
      name: httpbin
      port: 8000
kubectl apply -f httpbin-route.yaml

发送测试请求

获取网关的负载均衡器 IP 地址,并发送测试请求:

export GATEWAY_URL=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=apps -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
curl -v -H Host:www.example.com http://$GATEWAY_URL/httpbin/get

你将看到来自 httpbin 服务的正确响应,如下所示:

*   Trying 34.41.0.90:80...
* Connected to 34.41.0.90 (34.41.0.90) port 80
> GET /httpbin/get HTTP/1.1
> Host:www.example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< server: envoy
< date: Wed, 31 Jul 2024 08:21:58 GMT
< content-type: application/json
< content-length: 282
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 11
<
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "www.example.com",
    "User-Agent": "curl/8.7.1",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-External-Address": "123.120.227.173"
  },
  "origin": "123.120.227.173",
  "url": "http://www.example.com/get"
}
* Connection #0 to host 34.41.0.90 left intact

启用严格的 mTLS

运行下面的命令启用严格的 mTLS:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT

kubectl apply -f strict-mtls.yaml

为网关启用 TLS

创建用于服务签名的根证书和私钥:

mkdir example_certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt

www.example.com 创建证书和私钥:

openssl req -out example_certs/www.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/www.example.com.key -subj "/CN=www.example.com/O=www organization"
openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/www.example.com.csr -out example_certs/www.example.com.crt

为入口网关创建 secret:

kubectl create -n httpbin secret tls httpbin-credential \
  --key=example_certs/www.example.com.key \
  --cert=example_certs/www.example.com.crt

配置入口网关:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: apps
  namespace: httpbin
spec:
  gatewayClassName: teg
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - name: httpbin-credential

kubectl apply -f tls-apps-gateway.yaml

发送测试请求:

curl -v -H Host:www.example.com --resolve "www.example.com:443:$GATEWAY_URL" \
  --cacert example_certs/example.com.crt "https://www.example.com:443/httpbin/get"

你将可以通过 HTTPS 访问网格内的 httpbin 服务。

总结

Tetrate Enterprise Gateway 为企业提供了一种强大的网关解决方案,能够在云原生环境中高效地暴露和管理应用服务。通过其基于 Envoy 的架构和对 Kubernetes Gateway API 的支持,TEG 不仅确保了高性能的流量管理,还大幅简化了网关的部署和维护。无论是面对复杂的安全需求还是高流量的业务场景,TEG 都能提供可靠的支持,帮助企业实现其业务连续性和技术创新。

参考

探索 Envoy 1.31.0:新特性与性能提升全解析

2024-07-20 07:30:55

今天 Envoy Proxy 1.31.0 发布,这是今年继 1.29、1.30 以来发布的第三个大版本。Envoy Proxy 1.31.0 的发布标志着此开源网络代理项目在性能优化和功能增强方面又迈出了重要一步。此版本包括了一系列引人注目的新特性、行为变化和新配置选项,下面我们将逐一解析这些更新,帮助你充分利用 Envoy 的最新能力。

新特性

  1. HTTP/3 “Happy Eyeballs” 特性: HTTP/3的支持现在更为智能,新加入的“happy eyeballs”算法可以在多个 IP 地址族中更快找到最优连接路径,提升连接的可靠性和速度。
  2. Proxy Protocol 类型元数据支持: 在代理协议监听器中,默认现在会填充类型化的元数据,为高级路由和策略实施提供更多的灵活性和精确控制。
  3. Redis 命令支持: Envoy 现在支持所有 Bloom 1.0.0 的 Redis 命令,扩展了与 Redis 交互的能力,尤其适用于需要高级数据结构操作的场景。
Happy Eyeballs

Happy Eyeballs(快乐的眼睛)是一种网络算法,主要用于当一个设备同时支持 IPv4 和 IPv6 时,快速决定应该使用哪种 IP 协议来建立连接。该算法通过几乎同时启动两个连接尝试——一个使用 IPv4,另一个使用 IPv6——并使用哪个首先成功建立的连接,从而减少了连接延迟。

在 HTTP/3 中应用 Happy Eyeballs 特性,尤其是 Envoy 1.31 版本中的实现,可以改进服务在支持多种网络协议的环境中的表现。例如,如果一个服务的 IPv4 连接速度比 IPv6 快,Envoy 会偏好 IPv4,反之亦然。这样做的好处是减少了尝试连接的总时间,提高了用户体验和服务效率。

行为变化

  1. Thread Local 存储变更: SlotImpl 类的行为更新,其析构函数现可在任何线程上被调用,提高了线程局部存储的灵活性。
  2. HTTP/2 和 QUIC 性能提升: 默认启用新的 HTTP/2 编解码器和对 HTTP/3 的优化,包括性能改进和新的连接尝试机制,显著提升了性能和稳定性。

弃用与移除

此版本中,多个旧有的配置和运行时标志被正式弃用和移除,以清理代码库并提升维护效率。这包括一些老旧的 TLS 和 HTTP 配置选项,用户应检查并更新他们的配置以免受到影响。

结论

Envoy 1.31.0 的发布提供了许多值得关注的新特性和改进,不仅增强了其作为现代微服务架构核心组件的地位,也进一步证明了其作为业界领先代理解决方案的能力。无论是在性能提升还是功能拓展方面,Envoy 1.31.0 都为用户带来了实质性的好处。

确保查看完整更新文档,了解所有详细的配置指南和更新说明,以充分利用 Envoy 1.31.0 的潜力。

Envoy 的每次更新都是基于社区的反馈和贡献,我们期待看到你如何利用这些新特性来优化你的应用和服务。如果你有任何问题或需要帮助,欢迎在 Slack 或 GitHub 上与社区交流。

如何参与 Envoy Gateway 社区:贡献或提交代码指南

2024-07-17 13:36:15

Envoy Gateway 是由 Envoy Proxy 社区推动的一个开源 API 网关项目,结合了 Contour、Emissary 等项目力量。这个指南将帮助你理解如何贡献代码和参与社区。

开始之前

了解项目的目标和愿景是非常重要的。Envoy Gateway 旨在作为一个独立或基于 Kubernetes 的应用程序网关,使用 Gateway API 资源来管理 Envoy 代理。

如何参与

1. 沟通协作

在开发前,建议通过GitHubSlack与社区交流。始终创建一个 GitHub Issue 来讨论你的想法。

2. 贡献准则

遵守贡献准则,它包括代码规范和社区行为准则。

3. 提交代码

构建和测试指南

环境准备

代码构建

测试

Lint 检查

镜像操作

部署和调试

Kind 中运行的 Pod 列表

当你完成 Envoy Gateway 和示例应用部署后,运行 kubectl get pod -A 命令,你将看到如下所示的 Pod 列表。

查看 Kind 中运行的 Pod

 NAMESPACE              NAME                                                  READY   STATUS    RESTARTS      AGE
 default                backend-96f75bbf-tcdf7                                1/1     Running   1 (97s ago)   13h
 envoy-gateway-system   envoy-default-eg-e41e7b31-668f754989-wb7xr            2/2     Running   2 (97s ago)   13h
 envoy-gateway-system   envoy-gateway-b457dc69b-l77cr                         1/1     Running   2 (97s ago)   13h
 kube-system            coredns-5dd5756b68-b494d                              1/1     Running   1 (97s ago)   14h
 kube-system            coredns-5dd5756b68-j46bx                              1/1     Running   1 (97s ago)   14h
 kube-system            etcd-envoy-gateway-control-plane                      1/1     Running   1 (97s ago)   14h
 kube-system            kindnet-sq4b4                                         1/1     Running   1 (97s ago)   14h
 kube-system            kube-apiserver-envoy-gateway-control-plane            1/1     Running   1 (97s ago)   14h
 kube-system            kube-controller-manager-envoy-gateway-control-plane   1/1     Running   2 (97s ago)   14h
 kube-system            kube-proxy-4x72s                                      1/1     Running   1 (97s ago)   14h
 kube-system            kube-scheduler-envoy-gateway-control-plane            1/1     Running   2 (97s ago)   14h
 local-path-storage     local-path-provisioner-6f8956fb48-shjcz               1/1     Running   2 (59s ago)   14h
 metallb-system         controller-5c6b6c8447-kjl4n                           1/1     Running   2 (59s ago)   14h
 metallb-system         speaker-6zlrb                                         1/1     Running   1 (97s ago)   14h

调试 Envoy 配置

注意事项

若你在中国大陆的网络环境下构建和推送镜像,需要为 Docker 设置代理,否则你将无法下载一些依赖镜像。你可以将它们下载到本地后再用 kind load 命令加载到 kind 里。需要下载和加载到 kind 里的镜像见下面的代码。

pull-and-load-images-for-kind.sh

#!/bin/bash
echo "Pull the images and load them into the kind cluster..."
docker pull envoy-gateway-control-plane quay.io/metallb/controller:v0.13.10
docker pull envoy-gateway-control-plane quay.io/metallb/speaker:v0.13.10
docker pull envoy-gateway-control-plane docker.io/jimmysong/gateway-dev:435a4dc1
docker pull envoy-gateway-control-plane envoyproxy/envoy:distroless-dev
docker pull envoy-gateway-control-plane gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
 
kind load docker-image -n envoy-gateway --nodes envoy-gateway-control-plane quay.io/metallb/controller:v0.13.10
kind load docker-image -n envoy-gateway --nodes envoy-gateway-control-plane quay.io/metallb/speaker:v0.13.10
kind load docker-image -n envoy-gateway --nodes envoy-gateway-control-plane docker.io/jimmysong/gateway-dev:435a4dc1
kind load docker-image -n envoy-gateway --nodes envoy-gateway-control-plane envoyproxy/envoy:distroless-dev
kind load docker-image -n envoy-gateway --nodes envoy-gateway-control-plane gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e

更多资源

想深入了解如何进行高级测试和贡献,详见 Envoy Gateway 开发文档

加入我们,与全球开发者共同推进 Envoy Gateway 的成长,同时提升你的开发技能和对开源社区的理解。

加入 Envoy Gateway 中文交流群

为了便于中文和中国时区的用户交流,Envoy Gateway 社区成立的微信群,详见通知,该群成立于 2023 年 4 月,目前已有 400 多名成员。你可以联系联系我刘训灼赵化冰等入群。

参考

Fantastic Planet:权力、解放与文明间的微妙平衡 — 深入探索原始星球中知识和自由的力量

2024-07-12 11:51:52

最近我观看了一部名为 Fantastic Planet 的电影,这部电影给了我极大的震撼,令人意想不到的是,这居然是一部上世纪七十年代的作品。

image
Fantastic Planet 电影海报

在这里我想跟你分享一下这部电影,及其引申作品,还有我对这部电影的一些看法。

原始星球中的世界观

《Fantastic Planet》(法语原名“La Planète sauvage”,中文译名“原始星球”)以其独特的世界观和强烈的象征意义吸引了无数观众。这部电影描绘了一个名为 Ygam 的星球,上面居住着智慧而庞大的蓝色生物 Draags 和人类大小的 Oms。Draags 对 Oms 既是宠物又是实验对象,这种关系象征着权力和压迫。电影通过这种超现实的设定,探讨了奴役与反抗、文化冲突与共生的深刻主题。

请看下面的片段。

电影中处处都有一种诡异的氛围,其中的配乐也极具特色。

剧情介绍

《Fantastic Planet》的故事主要围绕一个年轻的 Om(人类),名为 Terr 展开。Terr 是在 Draags 的世界中被当作宠物养大的,但他利用一次偶发的机会逃脱了。当他的“主人”Tiwa 在一次学习过程中分心时,Terr 抓住机会逃离,并最终找到了一群野生的 Oms。电影中,Draags 是智慧而高大的蓝色生物,对 Oms 实施着类似宠物和奴隶的管理。在 Terr 的带领下,他和他的同伴们开始探索 Ygam 星球,学习 Draags 的技术和知识,并最终找到了反抗 Draags 统治的方法。

这部电影的剧情充满转折,不仅展现了 Terr 成长的旅程,还揭示了两种文明之间的冲突与和解,最终迫使 Draags 重新考虑对 Oms 的态度,导致了两个种族之间的和解。

image
Fantastic Planet 电影截图

故事线

电影的情节主要围绕 Terr 的成长和他最终领导 Om 反抗 Draags 的统治展开。故事的主要阶段包括:

  1. 成长与学习:在 Tiwa 的家中,Terr 接触到了 Draags 的学习装置,这些装置通过直接向大脑传递信息的方式教授知识。虽然这些装置主要是为 Draags 设计的,但 Terr 利用它们秘密学习了 Draags 的语言和科技知识。

  2. 逃离与自由:随着对 Draags 文化的理解加深,Terr 意识到自己的奴役地位,决定逃离 Tiwa 的家。他带走了一个重要的学习装置,这成为他和其他 Om 反抗 Draags 的关键工具。

  3. 野生 Om 社区:逃离后,Terr 加入了一个野生 Om 社区,他们居住在 Ygam 星球的荒野中。在那里,Terr 分享了他从 Draags 那里学到的知识,帮助他们提高技术水平,从而更好地抵抗 Draags 的迫害。

  4. 反抗与冲突:随着技术和组织的发展,Terr 和其他 Om 开始更加积极地反抗 Draags。他们策划并执行了多次行动,干扰 Draags 的冥想,最终引发了双方的直接冲突。

  5. 和解与共存:电影的结尾,经过一系列的斗争和破坏,双方达到了一种脆弱的和解。Draags 开始重新考虑对 Oms 的态度,而 Oms 也获得了更多的自由和生存空间。故事以一种暗示未来可能的和平共存的方式结束。

Draags 的弱点

Draags 的主要弱点之一是他们对精神冥想和学习的依赖,这是他们文化的一个核心部分。Draags 通过冥想和精神投射来维持他们的社会结构和知识传承。这种精神活动虽然展示了他们的高度智慧,但也使他们在某种程度上依赖于固定的环境和仪式,一旦这种平衡被打破,他们的社会秩序和个体能力就会受到影响。

Oms 如何打败 Draags

在电影中,Oms 最初是处于被动和受压迫的状态,他们被视为宠物或实验对象。然而,随着故事的发展,Oms 开始积累知识和技能,特别是在 Terr 的领导下,他偷学了 Draags 的知识并分享给其他 Oms。Oms 使用这些知识制造了自己的武器和通讯设备,组织起来进行抵抗。

image
Draags 的冥想仪式

Oms 的转变点是他们学会了干扰 Draags 的冥想仪式。他们发现,通过破坏 Draags 进行精神投射的特定设施,可以直接影响 Draags 的精神和身体健康。最终,Oms 通过一系列策略和战斗,迫使 Draags 重视他们的需求和权利,从而达到了一种新的平衡和相互理解。

电影的寓意和时代背景

《Fantastic Planet》在七十年代的社会政治背景下具有丰富的象征意义。这一时期,世界各地都充斥着社会动荡,包括越南战争、民权运动、以及对传统权威和社会结构的广泛质疑。

  1. 种族和阶级冲突:Draags 和 Oms 之间的关系象征着种族和阶级冲突,反映了现实世界中的压迫和不平等。电影通过展示 Oms 的奋斗和最终的抗争成功,传递了对自由和平等的追求,与世界各地的解放运动和社会变革呼应。
  2. 技术和伦理:Draags 的先进技术和文化并没有使他们对 Oms 的对待更加人道,这引发了关于科技进步与伦理责任之间的关系的讨论。这一主题在当时科技迅速发展的背景下尤为重要,提示观众科技应该如何服务于社会的整体福祉。
  3. 环境意识:电影中对环境和其他物种的描绘也反映了当时日益增长的环保意识。Draags 和 Oms 对环境的不同态度和影响暗示了人类活动对地球生态系统的影响,以及必须采取行动以避免灾难性后果的紧迫感。

结局

在《Fantastic Planet》的结尾,两个种族之间的和解并不是基于完全的和谐或理想化的情感联系,而是基于力量均衡。

和解的保持

电影中的和解通过展示两种文明之间达成的一种平衡来描绘,其中 Oms 通过获得知识和技术,能够在某种程度上与 Draags 站在同一个水平线上。Oms 学会了干扰 Draags 的冥想仪式,显示了他们能够影响 Draags 的生活和幸福。这种能力的证明迫使 Draags 重新评估他们对 Oms 的看法,并接受 Oms 作为平等的存在。因此,双方的和解更多地基于力量平衡和相互依赖,而不仅仅是单方面的宽恕或让步。

核大战的共同毁灭

这种通过显示破坏力来达成和解的方式,在某种程度上类似于冷战时期的“共同毁灭”概念。在核大战策略中,共同毁灭(Mutually Assured Destruction, MAD)是一种阻止核战争的理论,它基于的假设是两个拥有大量核武器的对手如果发动核战争,将导致双方的彻底毁灭。因此,恐惧和自我保护的本能阻止了核战争的发生。

在《Fantastic Planet》中,虽然没有直接的核武器,但 Oms 通过获得足够的知识和技术,以及能够干预 Draags 的生活方式的能力,建立了一种形式的战略平衡。这使得 Draags 必须承认 Oms 的权利和地位,从而防止了进一步的冲突和破坏,确保了两个种族的共存。

这样的和解和平衡展现了一种基于相互尊重和理解的共存方式,同时也提醒了现实世界中力量平衡的脆弱性和维持和平的复杂性。

关于电影及角色名称的解读

这部电影的译名及其中的角色名称也富有深意。

电影的译名与时代背景

《Fantastic Planet》的不同译名映射出不同文化对这部电影的解读。法语原名“La Planète sauvage”带有“野性”的暗示,强调了电影中野生与文明的对比;而英文名“Fantastic Planet”则更强调奇幻元素。中文译名有“原始星球”、“神奇星球”、“奇幻星球”等,结合了这两种元素,既体现了电影的奇异美学,也暗示了其深刻的哲理。这些译名反映了上世纪七十年代的文化背景,当时社会动荡和对权威的质疑正酝酿之中。

角色名称解读

Fantastic Planet 中的角色和名称富有象征意义,每个名字背后都携带着一定的文化或哲学含义,有助于增强电影的主题和故事。

image
Fantastic Planet 中的角色,从左到右,从上到下一次是:年幼的正在玩 Oms 的 Draags、成年的 Oms、年幼的 Tiwa、年幼的 Terr

Draags - 这个名字可能派生自“drag”或“dragoon”,象征着他们的统治地位和力量。Draags 这个名字暗示了他们对 Oms 的支配和冷漠态度。

Oms - 这个名字可能来源于法语单词“homme”,意味“人”。这个名称强调了他们的人性和在 Draags 眼中被视为次等的地位。

Terr - 主角 Terr 的名字来源于“terre”,法语中的“地球”或“土地”。这个名字强调了他作为 Om(类人种族)与自然和地球的紧密联系,同时也体现了他的地位和他的成长旅程。

Tiwa - Terr 的“主人”,一位年轻的 Draag 女性。她的名字可能来源于“twee”,荷兰语中的“二”或表示幼小、可爱的意思,这反映了她相对年轻和她对 Terr 的看待方式,即作为一个宠物或小孩。

精彩的配乐

《Fantastic Planet》(奇幻星球)的配乐是由法国作曲家 Alain Goraguer 创作的,这部音乐成为了电影的一个显著特色,与其独特的视觉风格和深刻的主题完美结合。Goraguer 的音乐风格融合了爵士、电子乐和管弦乐,为电影带来了一种梦幻般的、超现实的氛围。

  1. 电子音乐元素:Goraguer 在音乐中广泛使用了电子合成器,为电影提供了一种前卫的科技感。这种使用在 1970 年代初期是相对新颖的,与电影中的科幻主题和未来主义美学形成了和谐的统一。

  2. 爵士风格的影响:配乐中还融入了爵士音乐的元素,特别是在一些轻松或不安的场景中。这些爵士风格的曲目增加了音乐的动态范围,使观众在情感上更加投入电影的世界。

  3. 管弦乐的运用:电影音乐还包括了传统的管弦乐部分,尤其是在描绘 Draags 的文化和仪式时。这种传统元素与电子和爵士的现代感形成对比,强调了 Draags 社会的复杂性和高度发展。

  4. 节奏和氛围:整个配乐在节奏和氛围上都非常独特,既有悬疑和紧张的片段,也有平静和沉思的片段。这种多样性使得音乐本身几乎成为电影叙事的一个角色。

Alain Goraguer 的配乐为《Fantastic Planet》增添了一层额外的意义和情感深度,使其成为观众和批评家赞誉的对象。这种音乐与电影的结合,为观众提供了一次全面的感官体验,是电影受欢迎的重要因素之一。

导演及其影响

René Laloux 的导演生涯以其独树一帜的视觉风格和深刻的寓意著称。《Fantastic Planet》的视觉设计和故事叙述对许多后来的电影制作人产生了影响,其中包括印度导演 Tarsem Singh。Singh 的作品如《The Cell》(2000 年)和《The Fall》(2006 年)中,同样可以看到对 Laloux 奇幻和超现实风格的致敬。

The Cell 是一部科幻惊悚片,中文译作“入侵脑细胞”,讲述了一个男子突然接到一个被绑架女子的电话,随后展开了一场横跨整个城市的紧张营救行动。

image
《入侵脑细胞》电影截图

The Fall 是一部视觉艺术电影,中文译作“坠入”,通过一个受伤的特技演员在医院里向一个小女孩讲述的五个奇幻英雄的故事,探索了故事讲述的力量和现实与想象的界限。

image
《坠入》电影截图

个人感想

通过 Terr 的经历,电影《Fantastic Planet》深入探讨了知识、自由与自我实现的重要性,并且通过 Terr 这一角色展示了不同文明间的冲突、理解与和解。Terr 不仅仅是反叛的象征,更是连接不同世界、开启和平共存可能性的桥梁。

Oms 如何利用技术和知识战胜 Draags 的过程突显了教育和智慧在社会变革中的核心作用,同时也展现了如何通过团结和策略战胜强大对手的智慧。电影中的和解是一种脆弱的平衡,随时可能因新的冲突而被打破。

观看《Fantastic Planet》是一次视觉与思维的双重震撼,电影中的超现实场景和丰富的社会隐喻促使我深思现实世界中的类似问题。这部作品对权力、压迫及解放的深刻描绘,不仅仅是视觉上的享受,更是对人类社会的深刻反思,提供了宝贵的启示和思考。

多集群 Istio 服务网格的跨集群无缝访问指南

2024-07-11 19:45:20

前言

随着企业信息系统越来越多地采用微服务架构,如何在多集群环境中实现服务的高效、安全地跨集群访问成为了一个重要的挑战。Istio 作为一种流行的服务网格解决方案,提供了丰富的功能来支持跨集群服务的无缝连接。

在部署和使用多集群服务网格时有以下难点:

本文将深入探讨如何在多集群多网格的 Istio 部署中,通过实施 SPIRE 联邦和东西向网关暴露服务的方式,实现跨集群的无缝访问。通过一系列配置和部署示例,本文旨在为读者提供一个清晰的指南,帮助理解和解决多集群服务网格部署中遇到的常见问题和挑战。

Istio 的部署模型

Istio 文档中根据集群、网络、控制平面、网格、信任域及租户等维度划分了多种部署模型,我将其总结并附上适用场景说明如下表所示。

维度 单一配置 多元配置 适用场景说明
集群 一个集群托管所有服务与控制平面。 跨多个集群分布服务,可以共享或分离控制平面。 单集群适用于资源需求较小、管理相对简单的环境;多集群适合于需要高可用性、地理冗余或遵守数据驻留政策的大型组织。
网络 所有服务在单一网络内通信,无需跨网络通信。 服务跨越多个网络,需通过 Istio 网关进行通信。 单网络适用于网络简单、无复杂跨网络通信需求的场景;多网络适合在多云、混合云环境中部署,或需要跨行政边界部署的场景。
控制平面 一个控制平面管理所有服务。 每个控制平面管理一个或多个集群,增强隔离与可用性。 单控制平面适用于小型至中型部署,易于管理;多控制平面适用于大规模部署,需要高度的容错能力和安全隔离。
网格 所有服务在一个连续的服务网格中。 服务网格之间通过联盟进行通信,适用于不同组织或区域。 单网格适用于组织内部密切协作的服务;多网格适合于需要隔离不同业务线或合作伙伴间的服务,或实施强隔离的大型组织。
信任域 所有服务使用同一套密钥和证书体系。 不同信任域使用不同的密钥和证书,需进行信任链交换。 单信任域适用于信任级别统一的环境;多信任域适用于需要严格隔离、满足不同安全级别需求的复杂组织或多方合作场景。
租户 整个网格为单一租户或用户服务。 通过命名空间隔离,支持多个租户在同一网格中运行服务。 单租户适用于所有资源和服务由单一组织管理的场景;多租户适用于云服务提供商或需要在同一物理基础设施上运营多个客户的场景。
Istio 的多维度部署模型及适用场景

选择合适的部署模型需要考虑到实际的业务需求、安全要求、管理复杂度以及成本等因素。在生产环境中,往往是对多种部署模型的组合使用。

下表展示了在实际应用中如何结合不同的部署模型来满足更复杂的业务和技术需求:

混合部署模型 描述 适用场景
多集群 + 多网格 + 多控制平面 不同的集群可以配置成不同的网格,每个网格都有自己的控制平面。通过网格联邦共享服务和策略。 适合大型组织,其中不同的业务单位需要独立运行并管理自己的服务,同时需要一定级别的服务共享和协作。
多信任域联邦 + 命名空间隔离的多租户 不同的网格可以拥有不同的信任域,通过信任域联邦共享密钥和证书。同时在一个网格内部通过命名空间实现租户隔离。 适用于需要强隔离但又要求跨组织或跨业务线协作的环境,如跨国公司或合作伙伴网络。
多集群 + 单网格 + 多控制平面 多个集群共享一个服务网格,但每个集群拥有自己的控制平面来管理本地服务的配置。 适用于需要高可用性和灾难恢复能力的应用,各地区的集群可以独立运行,减少单点故障风险。
多集群 + 多网格 + 单控制平面 多个集群分布在不同的网格中,但所有网格共享一个中心控制平面。 适用于中心化管理的大规模部署,可以减少管理的复杂性,但对控制平面的可用性要求极高。
多信任域 + 多网格 + 命名空间隔离的多租户 各网格拥有独立的信任域,增强安全性和隔离性。在单个网格内使用命名空间来隔离不同的租户。 适用于提供云服务的组织,需要隔离不同客户的数据和服务,同时在不同的法律和合规环境下操作。
Istio 的部署模型组合

这些混合模型提供了高度的灵活性和可扩展性,能够满足各种复杂的部署要求。在选择混合模型时,组织需要考虑到管理复杂性、成本、安全要求以及业务需求,以确定最合适的部署策略。通过适当的规划和设计,Istio 的灵活部署模型可以帮助组织构建出既安全又高效的服务网格架构。在大多数场景下,单信任域的多集群 + 单网格 + 多控制平面已足够满足需要。

本文将聚焦多集群 + 多网格 + 多控制平面 + 多信任域的混合部署模型,这是一种相当复杂的场景,如果你可以完成这种场景的部署,那么其他场景也就不在话下了。

多集群 Istio 服务网格中的 FQDN

网格间的服务要想互相访问,必须了解各自的 FQDN。FQDN 通常由服务名、命名空间和顶级域(如 svc.cluster.local)组成。在 Istio 的多集群或多网格设置中,可以通过不同的机制(如ServiceEntryVirtualServiceGateway 配置)来控制和管理服务的路由和访问,而不是通过修改 FQDN 来实现。

多集群服务网格中的 FQDN 与单集群并没有什么不同,通常遵循以下格式:

<service-name>.<namespace>.svc.cluster.local

也许你会想到通过 meshID 来区分网格?meshID 主要用于区分和管理在同一环境中或跨环境的多个 Istio 网格,meshID 并不用于直接构造服务的 FQDN。

meshID 的主要作用
  • 网格级的遥测数据聚合:区分不同网格的数据,以便在统一平台上进行监控和分析。
  • 网格联邦:在网格之间建立联邦关系,允许网格间共享一些配置和服务。
  • 跨网格的策略实施:识别和应用特定于网格的策略,如安全策略和访问控制。

跨集群的服务注册发现与路由

在 Istio 多网格环境中,东西向网关(East-West Gateway)起着关键作用,它不仅处理网格间的入口和出口流量,还支持服务的发现和连接。当一个集群需要访问另一个集群中的服务时,它通过这个网关路由到目标服务。

下图展示了跨集群的服务注册发现与路由的过程。

在跨集群的 Istio 网格配置中,服务注册、发现和路由的流程是至关重要的,它们确保了不同集群中的服务可以相互发现并通信。以下是跨集群 Istio 网格中服务注册、发现与路由的基本流程:

1. 服务注册

在每个 Kubernetes 集群中,当一个服务被部署时,它的信息会被注册到 Kubernetes 的 API Server。这包括服务的名称、标签、选择器、端口等信息。

2. 同步到 Istiod

Istiod,作为控制平面,负责监控 Kubernetes API Server 的状态变化。每当有新的服务被注册或现有服务被更新时,Istiod 会自动检测到这些变化。Istiod 接着提取必要的服务信息并构建内部的服务和端点的配置。

3. 跨集群服务发现

为了使一个集群中的服务能够发现并通信到另一个集群的服务,Istiod 需要将服务端点信息同步到所有相关集群。这通常通过以下两种方式之一实现:

4. 路由和负载均衡

当服务 A 需要与服务 B 通信时,它的 Envoy 代理首先解析服务 B 的名称获取 IP 地址,即服务 B 所在集群的东西向网关的负载均衡器地址。接着该东西向网关将请求路由到目标服务。Envoy 代理可以根据配置的负载均衡策略(如轮询、最少连接数等),选择最佳的服务实例来发送请求。

5. 流量管理

Istio 提供了丰富的流量管理功能,例如请求路由、故障注入、流量复制等。这些规则在 Istio 的控制平面中定义,并推送到各个 Envoy 代理执行。这样可以在跨集群环境中灵活地控制和优化服务间的通信。

集群间服务的身份识别与认证

当不同集群中运行的服务需要相互通信时,正确的身份认证和授权是确保服务安全的关键。使用 SPIFFE 可以帮助标识和验证服务的身份,但在多集群环境中需要确保这些身份是唯一且可验证的。

为此,我们将设置 SPIRE 联邦来为多集群的服务分配身份并实现跨集群的身份认证:

以下是实现 SPIRE 联邦的步骤说明。

1. 配置 Trust Domain

每个集群都配置为一个单独的 trust domain。这样,每个集群内的服务都将具有基于其所在 trust domain 的唯一 SPIFFE ID。例如,集群 1 的服务可能拥有 ID spiffe://cluster1/ns/default/svc/service1,而集群 2 的相同服务则为 spiffe://cluster2/ns/default/svc/service1

2. 建立 Trust Bundle

在 SPIRE 中配置 trust relationships 以允许不同 trust domain 的节点和工作负载相互验证。这涉及到 trust domain 之间交换和接受彼此的 CA 证书或 JWT keys,确保跨集群通信的安全性。

3. 配置 SPIRE Server 和 Agent

在每个集群中部署 SPIRE Server 和 SPIRE Agent。SPIRE Server 负责管理证书颁发和续签,而 SPIRE Agent 负责将证书和密钥安全地分发给集群内的服务。

Istio 使用 SPIRE 联邦时的工作负载注册兼容性问题
在本文中,我们将在 SPRIE Server 中使用传统的 Kubernetes Workload Registrar 来负责集群中的工作负载注册。从 SPIRE v1.5.4 起弃用了 Kubernetes Workload Registrar,转而是使用 SPIRE Controller Manager 代替,经我测试并不能与 Istio 很好的运行。

4. 使用 Workload API

服务可以通过 SPIRE 的 Workload API 请求和更新其身份证书。这样,服务即使在不同集群中运行,也能持续验证其身份,并安全地与其他服务通信。我们将配置 Istio 网格中的代理共享 SPIRE Agent 中的 Unix Domain Socket,从而访问 Workload API 来管理证书。

5. 自动化证书轮换

我们将使用 cert-manager 作为 SPIRE 的 UpstreamAuthority,配置 SPIRE 自动轮换服务证书和密钥,增强系统的安全性。通过自动化轮换,即使证书被泄露,攻击者也只能在很短的时间内利用这些证书。

通过这些步骤,你可以建立一个跨集群的、安全的服务身份验证框架,使得各个集群的服务能够安全地识别和通信,从而有效地降低安全风险并简化证书管理。这样的配置不仅增强了安全性,还通过分散的信任域提高了系统的可扩展性和灵活性。

部署多集群

下图展示了 Istio 多集群及 SPIRE 联邦的部署模型。

image
多集群网格部署模型

下面我将演示如何在多集群 Istio 网格中实现无缝地跨集群无缝访问。

  1. 在 GKE 中创建两个 Kubernetes 集群,分别命名为 cluster-1cluster-2
  2. 分别在这两个集群中部署 SPIRE 并设置联邦
  3. 分别在两个集群中安装 Istio,注意配置信任域、东西向网关、入口网关、 sidecarInjectorWebhook 挂载 SPIFFE UDS 的 workload-socket,并启用 DNS 代理
  4. 部署测试应用并验证跨集群的无缝访问

我们部署的各组件版本如下:

我将所有命令及步骤说明保存在 Github 上:rootsongjc/istio-multi-cluster,你可以按照该项目中的说明操作。下面是对各主要步骤的说明。

1. 准备 Kubernetes 集群

打开 Google Cloud Shell 或本地终端,并确保你已经安装了 gcloud CLI。使用以下命令创建两个集群:

gcloud container clusters create cluster-1 --zone us-central1-a --num-nodes 3
gcloud container clusters create cluster-2 --zone us-central1-b --num-nodes 3

2. 部署 cert-manager

使用 cert-manager 作为根 CA 为 istiod 和 SPIRE 颁发证书。

./cert-manager/install-cert-manager.sh

3. 部署 SPIRE 联邦

SPIRE 联邦的基本信息如下:

Cluster Alias Trust Domain
cluster-1 foo.com
cluster-2 bar.com

注意:信任域不需要与 DNS 名称一致,但需要与 Istio Operator 配置中的信任域相同。

执行下面的命令部署 SPIRE 联邦:

./spire/install-spire.sh

想了解 Istio 中使用 SPIRE 进行身份管理的详情,请参考使用 cert-manager 和 SPIRE 管理 Istio 中的证书

4. 安装 Istio

我们将使用 IstioOperator 来安装 Istio,其中为每个集群配置了:

执行下面的命令安装 Istio:

istio/install-istio.sh

验证流量联邦

为了验证多集群安装的正确性,我们将在两个集群中分别部署不同版本的 helloworld 应用,然后在 cluster-1 中访问 helloworld 服务,以测试以下跨集群访问场景:

  1. 东西向流量联邦:跨集群的服务冗余
  2. 东西向流量联邦:处理非本地目标服务
  3. 南北向流量联邦:通过远程入口网关访问服务

执行下面的命令在两个集群中部署 helloworld 应用:

./example/deploy-helloword.sh

东西向流量联邦:跨集群的服务冗余

部署完成 helloworld 应用后,从 cluster-1sleep pod 访问 hellowrold 服务:

kubectl exec --context=cluster-1 -n sleep deployment/sleep -c sleep \
	-- sh -c "while :; do curl -sS helloworld.helloworld:5000/hello; sleep 1; done"

下图展示的是该场景下的部署架构及流量路由路径。

image
东西向流量联邦:跨集群的服务冗余

从请求结果既有 helloworld-v1 又有 helloworld-v2 的响应来看,说明跨集群的服务冗余生效了。

验证 DNS

此时,因为 helloworld 服务既存在于本地又在远程集群中,若你在 cluster-1 中查询 helloworld 服务的 DNS 名称:

kubectl exec -it deploy/sleep --context=cluster-1 -n sleep -- nslookup helloworld.helloworld.svc.cluster.local

你将得到 cluster-1 集群中的 helloworld 服务的 ClusterIP。

验证流量路由

接下来我们将通过查看 Envoy 代理配置来验证跨集群的流量路由路径。

cluster-1 中查看 helloworld 服务的端点:

istioctl proxy-config endpoints deployment/sleep.sleep --context=cluster-1 --cluster "outbound|5000||helloworld.helloworld.svc.cluster.local"

你将得到类似下面的输出:

ENDPOINT               STATUS      OUTLIER CHECK     CLUSTER
10.76.3.22:5000        HEALTHY     OK                outbound|5000||helloworld.helloworld.svc.cluster.local
34.136.67.85:15443     HEALTHY     OK                outbound|5000||helloworld.helloworld.svc.cluster.local

这两个端点,一个是 cluster-1 中的 helloworld 服务的端点,另一个是 cluster-2istio-eastwestgateway 服务的负载均衡器地址。Istio 将为跨集群的 TLS 连接设置 SNI,在 cluster-2 中将通过 SNI 区分目标服务。

执行下面的命令,在 cluster-2 中查询前面 SNI 的端点:

istioctl proxy-config endpoints deploy/istio-eastwestgateway.istio-system --context=cluster-2 --cluster "outbound_.5000_._.helloworld.helloworld.svc.cluster.local"

你将得到类似下面的结果:

ENDPOINT           STATUS      OUTLIER CHECK     CLUSTER
10.88.2.4:5000     HEALTHY     OK                outbound_.5000_._.helloworld.helloworld.svc.cluster.local

这个端点就是 helloworld 服务在 cluster-2 集群中的端点。

通过以上步骤,你应该了解了跨集群冗余服务的流量路径。接下来我们将删除 cluster-1 中的 helloworld 服务,不需要对 Istio 做任何配置,就可以自动实现故障转移。

东西向流量联邦:故障转移

执行下面的命令将 cluster-1 中的 helloworld 副本数量缩容为 0:

kubectl -n helloworld scale deploy helloworld-v1 --context=cluster-1 --replicas 0

再次从 cluster-1 中访问 helloworld 服务:

kubectl exec --context=cluster-1 -n sleep deployment/sleep -c sleep \
	-- sh -c "while :; do curl -sS helloworld.helloworld:5000/hello; sleep 1; done"

依然可以获得来自 helloworld-v2 的响应。

现在,直接删除 cluster-1 中的 helloworld 服务:

kubectl delete service helloworld -n helloworld --context=cluster-1

依然可以获得来自 helloworld-v2 的响应,这说明跨集群的故障转移生效了。

下图展示了该场景下的流量路径。

image
东西向流量联邦:故障转移

验证 DNS

此时,因为 helloworld 服务既存在于本地又在远程集群中,若你在 cluster-1 中查询 helloworld 服务的 DNS 名称:

kubectl exec -it deploy/sleep --context=cluster-1 -n sleep -- nslookup helloworld.helloworld.svc.cluster.local

你将得到 cluster-2 集群中东西向网关的地址和 15443 端口。

南北向流量联邦:通过远程入口网关访问服务

通过入口网关访问远程集群中的服务,是最传统的跨集群访问方式,下图展示了该场景下的流量路径。

image
南北向流量联邦:通过远程入口网关访问服务

执行下面的命令在 cluster-2 中创建 Gateway 和 VirtualService:

kubectl apply --context=cluster-2 \
	-f ./examples/helloworld-gateway.yaml -n helloworld

获取 cluster-2 中的入口网关地址:

GATEWAY_URL=$(kubectl -n istio-ingress --context=cluster-2 get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

执行下面的验证可以通过远程入口网关访问服务:

kubectl exec --context="${CTX_CLUSTER1}" -n sleep deployment/sleep -c sleep \
	-- sh -c "while :; do curl -s http://$GATEWAY_URL/hello; sleep 1; done"

你将得到来自 helloworld-v2 的响应。

验证身份

执行下面的命令获取 cluster-1 集群中 sleep pod 中的证书:

istioctl proxy-config secret deployment/sleep -o json --context=cluster-1| jq -r '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode > chain.pem
split -p "-----BEGIN CERTIFICATE-----" chain.pem cert-
openssl x509 -noout -text -in cert-ab
openssl x509 -noout -text -in cert-aa

如果在输出的消息中看到下面的字段,说明身份分配正确:

Subject: C=US, O=SPIFFE

URI:spiffe://foo.com/ns/sample/sa/sleep

查看 SPIRE 中的身份信息:

kubectl --context=cluster-1 exec -i -t -n spire spire-server-0 -c spire-server \
	-- ./bin/spire-server entry show -socketPath /run/spire/sockets/server.sock --spiffeID spiffe://foo.com/ns/sleep/sa/sleep

你将看到类似下面的输出:

Found 1 entry
Entry ID         : 9b09080d-3b67-44c2-a5b8-63c42ee03a3a
SPIFFE ID        : spiffe://foo.com/ns/sleep/sa/sleep
Parent ID        : spiffe://foo.com/k8s-workload-registrar/cluster-1/node/gke-cluster-1-default-pool-18d66649-z1lm
Revision         : 1
X509-SVID TTL    : default
JWT-SVID TTL     : default
Selector         : k8s:node-name:gke-cluster-1-default-pool-18d66649-z1lm
Selector         : k8s:ns:sleep
Selector         : k8s:pod-uid:6800aca8-7627-4a30-ba30-5f9bdb5acdb2
FederatesWith    : bar.com
DNS name         : sleep-86bfc4d596-rgdkf
DNS name         : sleep.sleep.svc

生产环境建议

对于生产环境,建议使用统一网关,通过 Tier-2 架构,在 Tier-1 边缘网关配置全局的流量路由,该边缘网关将把转写的 Istio 配置下发给 Tier-2 集群中的各个入口网关。

下图展示了使用 TSB 部署的 Tier2 架构的 Istio 服务网格,其中使用 SPIRE 联邦。

image
使用 SPIRE、Tier2 架构的 TSB 部署的多集群 Istio 服务网格架构图

我们将这四个 Kubernetes 集群分为 Tier1 集群(tier1)和 Tier2 集群(cp-cluster-1cp-cluster-2cp-cluster-3)。在 T1 中安装 Edge Gateway,而在 T2 中安装 bookinfo 和 httpbin 应用程序。每个集群将拥有独立的信任域,所有这些集群将构成 SPIRE 联邦。

下图展示了用户通过入口网关访问 bookinfo 和 httpbin 服务的流量路由。

image
统一网关架构图

你需要在 Istio 之上创建一个适用于多集群的逻辑抽象层,关于 TSB 中的统一网关的详细信息,请参考 TSB 文档.

总结

本文详细介绍了在 Istio 多集群网格环境中实现服务身份验证、DNS 解析和跨集群流量管理的关键技术和方法。通过精确配置 Istio 和 SPIRE 联邦,我们不仅增强了系统的安全性,还提高了服务间通信的效率和可靠性。遵循这些步骤,你将能够构建一个强大的、可扩展的多集群服务网格,满足现代应用的复杂需求。

参考

探索 Kubernetes Ingress、Gateway API 与 Istio 的演进和转型

2024-07-02 19:40:40

随着 Istio 1.22 版本的发布,Istio API 已正式升级至 v1 版本,同期,Kubernetes Gateway API 也更新至 v1.1 版本。本篇文章旨在深入探索 Ingress API、Istio API 与 Kubernetes Gateway API 之间的联系与区别,并详述它们在现实应用中的选择及迁移策略。

前言

之前,我曾撰写一篇文章,讨论了 为何 Gateway API 是 Kubernetes 与服务网格入口中的未来方向。文章中指出,作为 Kubernetes 的初始入口网关,Ingress 的资源模型由于过于简单,难以满足当下的可编程网络需求。作为其接班人,Gateway API 近年来发展迅速,获得了广泛支持,包括众多新兴的开源网关项目如 Envoy Gateway 也选择基于 Gateway API 开发。此外,一些传统网关项目也开始适配 Gateway API,或通过 ingress2gateway 这样的工具进行迁移。

Gateway API,作为 Kubernetes 入口网关的最新成果,通过角色划分来分离关注点,并支持跨 namespace,更适合多云环境。它整合了入口网关(南北向)与服务网格(东西向,集群内路由)的重叠功能,为云原生时代的统一流量管理提供了新的参考模型。

Ingress API、Gateway API 与 Istio API 都能实现网关功能,它们之间具体有何联系与区别?本文将为你揭晓这一迷题,并提供 Kubernetes 环境中网关的选择和迁移策略。

Kubernetes 中的流量管理

随着微服务架构的广泛应用和日益增长的复杂性,Kubernetes 的流量管理工具也在不断演进以适应各种技术需求。Ingress API、Istio API 与 Kubernetes Gateway API 分别标志着这一演变的不同阶段。

Ingress API 提供了 Kubernetes 的基本流量管理功能,允许用户通过定义简单的路由规则(例如 HTTP 和 HTTPS)来管理外部访问集群内服务的流量。其设计虽简洁,但功能有限,主要适用于规模较小、结构较简单的应用场景。

相比之下,Istio API 作为服务网格的一部分,提供了一系列高级流量管理功能,如流量镜像、金丝雀发布和断路器,适合于需要复杂流量管理的大规模微服务架构。

为了克服 Ingress API 的局限性并集成类似 Istio 的高级功能,Kubernetes Gateway API 因应而生。它不仅在设计上提供了更高的灵活性和扩展性,还通过社区的广泛支持,成为连接传统 Ingress 实现和现代服务网格技术如 Istio 的桥梁,目前主流的开源网关都是基于 Gateway API 或已进行适配。

以下表格概述了这三者的核心特点和推荐使用场景:

API 名称 对象类型 状态 推荐使用场景
Ingress API Ingress 稳定 (Kubernetes v1.19) 适用于小规模和简单的应用场景,主要用于基本的路由配置
Istio API VirtualServiceGateway 稳定 (Istio 1.22) 适用于高度复杂的微服务架构,需细粒度控制和高级流量管理特性的场景
Gateway API HTTPRouteGateway 稳定 (Gateway API v1.1) 适用于新部署或现有部署,需提高灵活性和可扩展性的场景,特别是结合 Istio 使用

Gateway API v1.1 的推出,特别是其在提升与现有 Ingress 配置兼容性方面的改进,为用户提供了一个平稳的迁移途径,使从传统的 Ingress 解决方案向更现代的、功能更全面的 Gateway API 的过渡变得更为顺畅。

从 Ingress 迁移到 Kubernetes Gateway API

若想从 Ingress 迁移到 Gateway API,请按以下步骤操作:

  1. 理解关键差异:与 Ingress 相比,Gateway API 引入了多种新的概念和资源类型,如 GatewayHTTPRouteTLSRoute。这些资源提供了更多的配置选项和灵活性,请参阅 Gateway API 文档以了解其配置。
  2. 配置入口点:创建 Gateway 资源配置,明确定义如何接收外部流量,包括配置协议、端口和 TLS 终端。
  3. 映射旧资源:将现有的 Ingress 资源映射到对应的 Gateway API 资源。例如,Ingress 中的 host 和 path 规则需要转换为 HTTPRoute 中的路由规则。
  4. 测试与部署:在正式迁移之前,在测试环境中验证新的 Gateway API 配置,确保所有流量路由正常,无安全漏洞。

为了简化迁移过程,你可以使用工具如 ingress2gateway,该工具能自动将 Ingress 配置转换为 Gateway API 格式。

实际迁移示例

以下是一个简单的 HTTP 网关配置示例,展示了如何将 Ingress 迁移到 Gateway API。

假设现有一个 Ingress 配置如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

要将其迁移到 Gateway API,首先需要创建一个 Gateway 对象:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-gateway-class
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        kinds
          - kind: HTTPRoute

请确保 gatewayClassName 指向你集群中配置的有效 GatewayClass。GatewayClass 通常由集群管理员设置,是一个为 Gateway 提供配置的资源。

接下来,创建 HTTPRoute 资源来定义路由规则,将流量路由到后端服务:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-httproute
spec:
  parentRefs:
  - name: example-gateway
  hostnames:
  - "example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: "/"
    backendRefs:
    - name: example-service
      port: 80

在此示例中,我们看到:

考虑的挑战

虽然可以将 Ingress 迁移到 Gateway API,并可能同时运行它们,但需要考虑以下挑战和迁移的必要性:

对于现有的 Ingress 和 Istio API 用户,是否需要迁移到 Gateway API 取决于具体情况。以下是一些迁移建议:

对于不同网关对 Gateway API 的支持情况,可以参考 Gateway API 实现项目的一致性报告了解详细信息。

总结

Ingress API、Istio API 和 Kubernetes Gateway API 各具特色,适应不同的应用场景和需求。选择合适的 API,进行合理的规划和管理,可以显著提高系统的灵活性和稳定性。随着 Gateway API 的持续发展和成熟,它将越来越成为未来流量管理的主流选择。

选择合适的网关技术,结合你的具体需求和现有架构,可以更好地管理和优化流量,确保应用的高效和稳定运行。随着技术的进步和社区的发展,Gateway API 提供了一个强大且灵活的框架,使得从传统的 Ingress 迁移到更现代的解决方案变得更为简单和高效。

参考

如何在 Mac 电脑上实现微信多开

2024-06-26 16:55:45

微信是我们在日常生活和工作中不可或缺的通讯工具,许多用户都有在同一台设备上登录多个微信账号的需求。尽管官方客户端不直接支持这一功能,但通过一些简单的技巧,你可以在 Mac 电脑上实现微信的多开功能。

你可能看到过一些介绍如何在 Mac 上实现微信多开的文章或视频,那些技巧大多已经失效,有的可用的也只能在一台电脑上同时登录两个微信,本文将详细介绍如何在 Mac 上同时运行任意多个微信实例。

下面是演示视频。

下面是详细步骤。

步骤一:创建微信的副本

首先,你需要在应用程序文件夹中找到微信应用程序(WeChat.app)并创建启动命令副本:

  1. 打开访达(Finder)后,按下快捷键 CMD + Shift + G
  2. 在弹出的输入框中输入目录 /Applications/WeChat.app/Contents/MacOS
  3. 在新打开的目录中选中 WeChat,鼠标右键选择 创建别名(Make Alias) 即创建了一个启动微信的副本。你也可以通过安装 OPT + CMD 按钮拖动 WeChat 文件到当前或另个目录比如桌面上来创建一个别名(快捷方式)。
image
创建微信副本

步骤二:启动多个微信实例

如果你想同时登录 N 个微信,则依次双击刚创建的微信副本 N + 1 次。比如你想同时登录 3 个微信,那就打开这个副本 4 次。

保持这些窗口在运行状态,你可以将它们最小化,但是不要关闭它们。在这个过程中,你可能会注意到,系统只会打开两个微信登录界面。

步骤三:退出其中一个微信

当两个微信登录界面打开后,手动退出其中一个已经开启的微信。

image
退出其中一个微信

步骤四:触发多开功能

关闭一个微信后,系统会再次打开 N-1 个新的微信窗口。现在你就可以通过这些微信的登录界面登录到不同的微信账户了。

image
在 Mac 上同时登录三个微信

总结

以上方法只需要使用最新的官方版本的微信即可,可以做到任意多开。希望这篇指南能帮助你更高效地使用微信,满足你的多账户管理需求。如有任何问题或需要进一步的帮助,欢迎留言讨论。

首次巴黎之旅:探索城市风情与文化洞察

2024-06-16 06:11:53

2024 年 3 月,一个特别的机会将我带到了法国巴黎——参加 KubeCon EU 2024。这是一场汇集了来自全球的云计算和开源技术爱好者的盛会。利用这次会议的机会,我不仅深入了解了最新的技术趋势,还抓住机会体验了这座城市的历史、文化和日常生活。我的巴黎之行从 3 月 16 日开始,持续到 3 月 24 日,这期间我尽可能多地探索了这座充满魅力的城市。

签证篇章

对于我们中国人来说,无论何时何地,出国的第一步总是签证的申请。尤其是法国申根签证,需要准备众多材料,包括公司证明信、行程单等,但幸好我所在的公司性质让这一切变得相对容易。令人感到略有安慰的是,与申请日本签证相比,法国签证不需要冻结巨额资金或提供庞大的银行存款证明。这次我获得了六个月的签证有效期,这对于我未来的欧洲行计划提供了更多的灵活性和可能性。

到达巴黎

从北京直飞巴黎的旅程总是充满期待。我乘坐的法国航空公司航班,从北京时间凌晨起飞,经过长达 13 小时的旅程后,于巴黎时间早晨 6 点多抵达。归途则选择了在伊斯坦布尔转机,让旅行的回忆更添一分异国情调。

第一印象

戴高乐机场处处可见的中文标牌,字句优雅,显示了法国人对细节的用心。尽管通关时排队等候了近一个小时,但多样化的人流让巴黎的国际化氛围愈发显著。从机场乘坐穿梭地铁时,我体验了三次才成功挤上车,可见人流之多。使用 Bolt 打车服务时,因为语言不通,还得到了一位好心法国人的帮助,他用法语帮我与司机沟通,这让我深感法国人的友好与热心。

在巴黎戴高乐机场随处可见中文标识,很多地方只有英文、法文和中文三种文字的标识。

image
巴黎戴高乐机场

巴黎的生活细节

在巴黎的每一处,都能看到那些独具特色的垃圾桶,它们不仅方便实用,还在安全上做了考虑。例如,一些垃圾桶是为了防爆而设计的,能安全投放玻璃瓶和易拉罐,而另一些仅用透明塑料袋覆盖,也是出于同样的安全考量。这些细节体现了城市管理的精细与周到。

image
巴黎街头的垃圾桶

巴黎的垃圾分类采用彩色编码垃圾桶系统,旨在促进适当的废物处理。垃圾箱有不同的颜色:黄色用于纸张和塑料等可回收物,棕色用于可堆肥食物残渣,白色用于酒瓶等玻璃物品,绿色/灰色用于其他废物。该系统可帮助居民有效地分类垃圾,促进回收利用和适当的废物管理实践。

食在巴黎

尽管西餐中的牛排和糕点让人难以抗拒,我还是更偏爱家乡的味道。在巴黎,我找到了一家名为杨小厨的川菜馆,其牛肉面虽与国内有所不同,但味道可口,价格亲民。此外,巴黎街头的水果与我在网上购买的相比,不仅价格合理,而且味道也极佳,特别是我喜爱的啤梨。

image
巴黎的中餐、西餐及马卡龙

另外在很多地铁口还有街头巷尾也有社区小摊及烘焙店。

image
街头小摊和烘焙店

住在巴黎

巴黎,法国的首都,不仅以其浪漫和历史著称,同时其行政区划也具有独特的结构。巴黎市通常被分为“大巴黎”和“小巴黎”。小巴黎指的是巴黎市内环,即第一到二十区,涵盖了大部分著名的历史地标和文化地区,总面积约为 105 平方公里。而大巴黎则包括小巴黎及其周边的郊区,形成一个更为广泛的都市区。

image
小巴黎地图

下图中环形道路是 Boulevard Périphérique,即巴黎环形高速公路。这条道路环绕着巴黎的 20 个区,这些区域共同构成了所谓的“小巴黎”。

巴黎的 20 个区(arrondissements)按照螺旋状的顺序从市中心向外延伸,包括了市内最核心的商业、居住以及文化区域。这些区域的总面积大约为 105 平方公里(约 40.5 平方英里),从 1 区的市中心向外逐渐扩展至 20 区。

这些区域是巴黎市的行政区划,而“小巴黎”这个名词通常是指的这些内环的区域,即由环形公路所环绕的巴黎市内部区域。因此,图中显示的 20 个区确实组成了“小巴黎”。

相比之下,北京的二环面积约为 62 平方公里,三环面积约为 159 平方公里,小巴黎的面积在二者之间,下图展示了在同等比例尺下的小巴黎和北京三环的地图。

image
小巴黎和北京三环面积对比

我此行住宿的地点位于巴黎的 15 区,这里是巴黎最大的一个区,位于塞纳河左岸(按塞纳河流向)。15 区不仅居住环境宜人,交通便利,而且距离诸如埃菲尔铁塔等著名景点也非常近,步行大约 20 分钟即可到达。我下榻的住所是一栋三层高的联排公寓,底层设有车库和会客厅,而居住区则分布在二楼和三楼,共有五个房间,旁边还有某国的大使馆官邸,增添了一份特别的国际氛围。

行在巴黎

巴黎的道路规划别具一格,道路交错纵横,并非严格的南北走向,加之红绿灯设置在街角,使得初来乍到的人有些不适应。这里的自行车道十分发达,我租了一辆助力自行车,穿行在巴黎的街头巷尾,感受到前所未有的自由与惬意。巴黎的地铁系统复杂多样,但支付方式极为方便,大部分支付都可以通过信用卡完成。

对于游客来说,在小巴黎短距离出行首选方式是自行车。巴黎街头随处可见可供租赁的自行车,你可以下载 App 注册扫码支付后即可使用,注意需要绑定信用卡。有些自行车道是在路的中间,路面上有明确标识自行车道。这些自行车都是助力车,大多维护的比较好,但是也有一些存在故障,需要仔细辨别。另外巴黎的街道较窄,行人也很少遵守红绿灯,可能是因为红绿灯太多了吧。

image
巴黎街头的自行车道

巴黎的地铁票种类繁多,从单次票、日票到周票、月票一应俱全,适应不同游客的需求。然而,许多外地游客在购票环节都会遇到困惑,需要一些时间来熟悉系统。

image
巴黎地铁

巴黎地铁(Métro de Paris)始建于 1900 年,是世界上最早的地铁系统之一。这个广泛的地铁网络包括 16 条线路,覆盖总长度达 225 公里。巴黎地铁不仅连接城市中心和外围区域,还扩展到了一些近郊区域,每年服务数亿乘客,是巴黎公共交通系统的核心部分。因为建造时间比较久远,很多设施都比较老旧,比如车厢陈旧,车厢门要手动打开,运行噪音大,没有电梯等。

医疗体验

在巴黎的第二天,我因饮食不当而开始腹泻,持续了两天后才好转。在这期间,我去了当地的药店买药。药店早上 8 点准时开门,门口总是有人排队等候,这种准时和秩序让我印象深刻。

image
在巴黎购买的止泻药

法国的医疗体系被认为是世界上最好的之一,无论是急诊还是药品购买,都非常便捷。药品的质量和种类也相当丰富,能够满足不同病症的需求。

游在巴黎

在 KubeCon EU 期间,我利用空闲时间游览了几处巴黎的著名景点。埃菲尔铁塔是必须打卡的地方,我登上了二层平台,俯瞰整个巴黎,景色壮观。卢浮宫则是艺术爱好者的天堂,蒙娜丽莎的微笑吸引了无数游客驻足。虽然巴黎圣母院还在维修中,但夜晚的圣母院依旧散发着无尽的魅力。

卢浮宫

卢浮宫(Louvre Museum)是世界上最大和最著名的博物馆之一。它最初建于 12 世纪作为皇宫,直到 1793 年开放为公众博物馆。卢浮宫收藏了超过 38 万件展品,跨越从古代文明到 19 世纪的艺术与历史文物。其中最著名的作品包括《蒙娜丽莎》、《维纳斯的诞生》和《胜利女神像》等。

image
卢浮宫

卢浮宫里人流量最大的地方就是《蒙娜丽莎》,很多人在那里排起了长龙,只为一睹她那神秘的微笑。

万神殿

巴黎万神殿,最初建造为教堂,现作为一个纪念馆,位于法国巴黎的拉丁区。这座建筑最初是为了纪念圣日内瓦瑞,后转变为纪念法国伟大人物的安息之地。建筑风格融合了古典与新古典元素,其宏伟的圆顶和庄严的柱廊使它成为巴黎的一个显著地标。万神殿内部装饰豪华,包括傅科摆锤和许多重要法国历史人物的墓穴。

万神殿内的傅科摆,由法国物理学家利昂·福科于 1851 年设计,以证明地球自转的直接效应。这个简单但引人注目的实验包括一根悬挂的铁球,通过其自由摆动,观察者可以看到摆动平面相对于地面缓慢旋转的现象,这一旋转是地球自转的直接证据。福科摆锤不仅是物理学的一个重要实验,也成为了科学与艺术的结合象征。

image
万神殿内的傅科摆

塞纳河

清晨的塞纳河如诗如画,漫步在河畔,感受到巴黎的静谧与美好。

image
塞纳河

塞纳河是法国的一条主要河流,流经巴黎市中心。河流全长约 777 公里,起源于勃艮第地区的普拉特高原,最终流入英吉利海峡。塞纳河穿过巴黎时,河两岸布满了历史悠久的桥梁和著名的景点,如巴黎圣母院和埃菲尔铁塔。河流不仅是巴黎的重要交通水道,也是旅游和休闲的热门地点,常有游船在此穿梭,提供观光和餐饮服务。

马德莱娜教堂

image
马德莱娜教堂

马德莱娜教堂(Église de la Madeleine)是一座罗马天主教的教堂,以其古典希腊神庙风格著称。这座教堂建于 19 世纪初,外部有 52 根科林斯式柱子环绕。虽然外观极其庄严、类似神庙,但内部装饰华丽,拥有精美的雕刻和壁画。马德莱娜教堂不仅是宗教活动的场所,也常用于举行音乐会,特别是古典音乐演出。

圣心堂

image
圣心堂

圣心堂(Basilique du Sacré-Cœur)位于法国巴黎蒙马特高地,是一座罗马天主教教堂,以其白色圆顶著称。这座教堂建于 1875 年至 1914 年间,是为了纪念普法战争中的法国阵亡将士而兴建的。圣心堂采用了罗曼 - 拜占庭风格的建筑设计,内部装饰华丽,拥有壮观的马赛克和雕塑。它不仅是巴黎的一个重要宗教地点,也因其位于城市之巅,提供了俯瞰巴黎全景的绝佳视角。

除此之外,我还在骑行过程中游览了巴黎圣母院、香榭丽舍大道、爱丽舍宫、小皇宫、凯旋门、协和广场、杜乐丽花园、卢森堡公园等,限于篇幅不在此展开。

关于奥运会

现代奥运会是法国人在巴黎提倡的,可能是法国人对奥运会已经司空见惯,也有可能是为了尽可能不打扰本地人的生活,此次巴黎之行,感受不到任何奥运会将在巴黎召开的气氛。只有一些标志性建筑旁在搭建一些展台可能是为了供奥运会使用,以及一些商店在售卖奥运会纪念品。

评论

最近在中文互联网上,经常看到一些视频介绍巴黎的治安、环境是如何的不堪,比如街道上很多小偷、随地大小便、找不到厕所等。幸运的是我并没有遇到小偷,也没听到同伴有这样的遭遇。但是确实在一些街道尤其是景区周边闻到一些尿骚味,也遭遇了几个流浪汉问我要烟。还有就是卢浮宫里找不到厕所,唯一找到的一个男厕所还在维修中。

image
靠近卢浮宫的街道满是垃圾和尿骚味

总结

巴黎这座城市以其独特的魅力和丰富的文化底蕴给我留下了深刻的印象。这里的人们热情友好,景色美丽动人。虽然在一些游客密集的地方可能会稍显杂乱,但这也是任何旅游城市难以避免的现象。巴黎之行充满了美好的回忆,让人流连忘返,期待未来再次踏上这片浪漫的土地。也希望这篇游记能对初次踏上这篇土地人有所帮助。

如何在 Istio 中集成第三方服务注册表?

2024-06-14 19:14:40

Istio 依赖 Kubernetes 来进行服务发现,这通常意味着必须在 Kubernetes 集群中部署微服务并使用 Kubernetes 服务发现。然而,很多现有的微服务项目还在使用如 Consul、Eureka 这样的第三方服务注册表,本文将探讨如何将这些现有的微服务的注册表与 Istio 集成。

Istio 对非 Kubernetes 服务的支持

Istio 最初只支持 Kubernetes 服务,但随着时间的推移,为了适应更广泛的应用场景,它开始支持像 Consul 这样的第三方服务注册表。通过引入 Mesh Configuration Protocol(MCP),Istio 能够与各种服务发现后端通信,如 Consul,从而管理非 Kubernetes 环境中的服务。在 Istio 1.1 版本中,引入了 ServiceEntry 资源对象,这使得用户可以手动将外部服务添加到 Istio 的服务注册表中,并在 Istio 1.8 中取消了对 Consul 的直接支持,转而通过 ServiceEntry 提供了一种更灵活的方式来集成和管理所有服务,无论它们是否托管在 Kubernetes 上。

Istio 代理配置的高层架构

下图展示了 Istio 代理配置的高层架构,揭示了配置如何从各种源被摄取、转换,并最终服务于 Envoy 代理。

image
Istio 代理配置高层架构

要想详细了解 Istiod 的架构,可以参考 Istio 架构详解

配置摄取过程详解

配置翻译与服务

配置从 ConfigStore 和 ServiceDiscovery 聚合后,由 Config Translator 翻译成适合代理的格式,然后通过 XDS Server 服务于 Envoy 代理。这是将动态配置应用于代理的最终步骤。

第三方注册表同步

为了集成第三方服务注册表,我们可以实现一个 Operator,该 Operator 监视第三方服务注册表并将服务以 ServiceEntry 和 WorkloadEntry 资源形式推送至 Kubernetes API 服务器。以下流程图展示了该同步过程。

image
第三方注册表同步流程图

第三方服务注册表同步的步骤说明

  1. Operator 向第三方服务注册表发起查询请求。
  2. 第三方服务注册表返回当前注册的服务数据。
  3. Operator 将服务数据转换为 Istio 的 ServiceEntry 对象。
  4. Operator 将 ServiceEntry 推送至 Kubernetes API 服务器。
  5. Kubernetes API 服务器将变更通知 Istiod。
  6. Istiod 更新 Envoy Proxies 的配置。
  7. Operator 定期检查第三方服务注册表以监控服务变化,发现变更后更新 ServiceEntry 并重新推送至 Kubernetes API 服务器,完成服务同步。

Istio Registry Sync

Tetrate 开发的 Istio Registry Sync 是一个扩展 Operator,可以作为 TIS 的 add-on 运行。它支持非 Kubernetes 服务注册表(如 AWS Cloud Map 和 Consul)与 Istio 的集成。此工具提供了以下几个使用场景:

总结

通过上述方法,你可以有效地将 Istio 与第三方服务注册表集成,无论是通过开发自定义的 Operator 还是使用现成的 Istio Registry Sync 工具。这样不仅能够保持服务的现代化,还能确保在不同环境之间的高效协同工作。

参考资料

深入解析 Istio 1.22:新特性和实际应用建议

2024-06-11 16:23:50

最近 Istio 1.22 发布包含大量的重大更新,本文将为你分享这个发布带来的新特性及应用建议。

Ambient 模式进入 Beta 阶段

虽然 Ambient 模式现已进入 Beta 阶段,但这并不意味着我们可以完全告别 Sidecar。尽管 Istio 官方宣称 Ambient 模式可以简化操作并显著减少内存和 CPU 使用,但它仍然存在局限性和潜在的复杂性问题。例如,虽然取消了 Sidecar,但需引入新的 ztunnel 和 waypoint 组件,这可能带来新的挑战。关于 Ambient 模式进入 Beta 模式的详细信息请参阅 Istio 官方博客

Ambient 模式带来的新的挑战

关于 Sidecar 模式和 Ambient 模式的对比,详见 Istio Ambient 模式的局限性解析

建议
如果是刚开始使用 Istio,尤其是你只需要为服务自动开启 mTLS 的情况下,当前阶段可以尝试使用 Ambient 模式。但是对于 L7 功能,建议等到 Ambient 模式完全成熟后再考虑生产上使用。

Istio API 升级

Istio Istio 1.22 版本中,关键 API 如流量管理、安全、Telemetry 相关的 API 都已正式升级到 v1 版本。你只需要将原有配置的 API 版本修改为 v1 即可,除此之外不需要任何更改。这些 API 早已成熟,你可以放心的使用 v1 版本,对于对稳定性要求较高的环境,Istio 添加了验证准入策略确保只有 v1 API 和字段可以在 Istio API 中使用。

例如下面的 AuthorizationPolicy 示例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: finance-to-supply-chain
  namespace: finance
spec:
  selector:
    matchLabels:
      app: finance-app
  action: ALLOW
  rules:
  - from:
    - source:
        namespaces: ["finance"]
    to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/supply1", "/api/supply2"]
    when:
    - key: request.headers[:authority]
      values: ["supply-chain-service.supply-chain.svc.cluster.local"]

其他扩展类的 API 如 EnvoyFilterWasmPluginProxyConfig 还未成熟,因此还停留在 alpha 或 beta 阶段。关于 API 升级的更多信息,请参考 v1 API 博客

建议
对于常用功能可以放心使用 v1 API,扩展类 API 尚未稳定为了保证系统稳定性,可以开启验证准入策略。

Gateway API 升级

Gateway API 已更新至版本 1.1.0,现已普遍可用。这一更新扩展了 Istio 的流量管理能力,但需要注意 Istio 原生 API 与 Gateway API 的兼容性问题。在迁移到新 API 时应谨慎,以避免依赖尚未完全成熟的特性。更多详情,请查看 Gateway API v1.1 博客

建议
对于已经稳定使用 Istio API 的现有部署,可以继续使用,尤其是在需要使用到高级功能的场景下。对于新部署优先考虑使用稳定版的 Gateway API,以利用其现代化的流量管理功能。因为二者现存的兼容性问题,不要冒然迁移到 Gateway API,否则得不偿失。

增量 xDS 默认启动

Istio 1.22 版本默认启用了增量 xDS,这是一个优化配置分发的机制。与传统的 State of the World(SotW)模式相比,增量 xDS 仅将变更的配置发送给 Envoy 代理,从而显著减少了网络传输的数据量和控制平面的资源消耗。这一变更尤其适用于配置频繁更新的大规模部署环境,能够提高配置更新的效率和性能。此外,增量 xDS 还有助于在网络环境复杂或配置动态变化的情况下,更高效地管理服务网格的配置更新。

建议
增量 xDS 早在 Istio 的几个版本前就已经开发完成,只是没有默认开启,现在该功能已经稳定,可以放心使用。

更多关于 xDS 的介绍请参考Envoy xDS 及 Istio 中的配置分发流程介绍

AuthorizationPolicy 的路径模板支持通配符

在 Istio 1.22 中,AuthorizationPolicy 新增了对路径模板的支持,极大增强了路径匹配的灵活性和精确性。而在此之前,AuthorizationPolicy 的路径配置并不支持通配符。此功能允许使用基于 Envoy 的 URI 模板匹配来定义 HTTP 请求中的路径。路径可以包括简单的通配符(***)或具名变量,从而精确匹配单个或多个路径组件。例如,路径模板 /foo/{*} 能匹配 /foo/bar 但不匹配 /foo/bar/baz,而 /foo/{**}/ 则可以匹配任何以 /foo/ 开头的路径。这种灵活的路径模板设计,特别适用于动态和复杂的路由规则,进一步加强了 Istio 的安全策略工具箱。

下图展示了 AuthorizationPolicy 的路径匹配的通配符规则。

image
AuthorizationPolicy 的路径匹配通配符规则

了解更多关于路径模板的具体应用和规则,你可以参考 Envoy 的官方文档

提示
AuthorizationPolicy 中的路径匹配终于支持模板了,你不需要再在配置中一个一个地手动加入路径了。

总结

Istio 1.22 版本引入了多项重要更新和改进,尽管某些特性被广泛宣传,但在实际使用中需要进行详细评估和适当的测试。希望本篇博客能帮助你更深入地理解和应用这些新特性,以在实际操作中获得最佳效果。

参考

端午新疆自驾之旅:领略新疆壮美风景

2024-06-10 10:38:16

三年前,我与 Addo 环游了新疆北疆,那次旅行让我久久难忘,尤其是伊犁河谷地带,始终萦绕在心头。这次端午佳节,我决定再赴伊犁,开启一场自驾之旅。

经过精心策划,我从北京出发,途经乌鲁木齐转机,来到美丽的伊宁。在这里,我们租了一辆车,开始了为期一周、总行程 1344 公里的自驾之旅。

航拍视频

在这段视频中,你将看到我在旅途中拍摄的壮丽航拍画面。从广阔的草原到清澈的湖泊,从巍峨的雪山到蜿蜒的公路,这些美景都在视频中得到了完美的呈现。

伊宁喀赞其

我们的第一站是伊宁市的喀赞其民俗村,这是一个充满民族风情的小镇。这里的街道两旁是独具特色的传统民居,五彩斑斓的墙壁和蓝色的大门,仿佛童话世界。喀赞其的生活气息浓厚,街上随处可见当地居民的日常生活场景。

image
伊宁喀赞其

伊犁河

从喀赞其出发,我们前往了伊犁河。伊犁河的河水清澈见底,两岸绿树成荫,广阔的湿地景色宜人。我们在伊犁湿地公园观看了一场壮美的日落,沉醉于大自然的美景中。

image
伊犁河

喀拉峻

第三站是喀拉峻草原。广阔的草原上,牛羊成群,远处的雪山与蓝天白云相映成趣,构成了一幅绝美的自然画卷。这里平均海拔 2000 多米,空气格外清新,每一口呼吸都让人感到无比的舒畅。我在这里露营了一晚,经过了一夜的风雨,第二天雨过天晴日出时,阳光洒在身上暖洋洋的,眺望远处的日照金山。

image
喀拉峻草原

琼库什台

接下来,我们来到了琼库什台。这个哈萨克族的原始村庄虽然多了一些商业气息,但依然保留着原始的魅力。草原和河谷里新开的民宿和饭店让更多游客慕名而来。我们骑马前往后山,体验了最纯粹的自然风光。尤其是夕阳西下时,在山顶看着连绵起伏的草原和远处的雪山交相辉映,相映成趣。

image
琼库什台

夏塔古道

夏塔古道是此次行程中的重要景点。古道曾是丝绸之路上的一部分,沿途高山峡谷景色壮丽。尽管景区尚未开放,我们还是通过无人机航拍领略了这里的冰川河谷。

image
夏塔古道

伊昭公路

伊昭公路被誉为新疆最美的公路之一。沿途风景从高山到草原,从森林到湖泊,变幻多姿。行驶在悬崖峭壁上,不禁感叹开路人的艰辛。

image
伊昭公路

赛里木湖

最后一站是赛里木湖,位于博尔塔拉蒙古自治州。这个高山湖泊的湖水清澈见底,碧蓝如普鲁士蓝,四周环绕着雪山和草原,景色如诗如画。我们在湖边漫步,夜宿赛里木湖西岸,感受这座号称“大西洋的最后一滴眼泪”的静谧与壮丽。

image
赛里木湖

这次新疆伊犁自驾之旅不仅让我领略了壮丽的自然风光,还体验了当地独特的民族文化。通过航拍镜头,我记录下了这一路的美景,制作成了一个视频与大家分享。

美食

伊犁不仅风景如画,美食也令人垂涎。红柳烤肉的鲜香、辣子肉的香辣(当地人将它作为早餐,配合花卷一起吃)、椒麻鸡的麻辣、赛里木湖的高山鲑鱼籽炒饭的鲜香,都是我旅途中难忘的味道。

image
顺时针方向分别为高山鲑鱼籽炒饭、红柳烤肉、辣子肉、椒麻鸡

另外新疆的干果、奶酪和牛肉干也是不错的伴手礼。

总结

这次旅程将成为我人生中一段难忘的回忆。新疆伊犁的美景与魅力,让我深深地爱上了这片土地。如果有机会,我一定会再来这里,探索更多未尽的风景。

希望这篇游记能带给你一些关于新疆伊犁的美好回忆。如果你也有机会去新疆旅行,一定不要错过这些美丽的景点。

Envoy xDS 及 Istio 中的配置分发流程介绍

2024-06-04 16:18:06

在 Istio 项目的早期采用全局状态(State of the World,简称 SotW)的方式推送配置给 Envoy 代理。一旦有一个服务变更,就要将全局配置推送给所有 Sidecar,造成巨大的网络负担及控制平面的性能损耗。Istio 社区从几年前就开始开发增量 xDS 以解决此问题,并在最近几个 Istio 版本中支持了增量 xDS。在最近的 Istio 1.22 发布中,增量 xDS 成为默认开启的功能。本文将为你介绍 xDS、增量 xDS 及 Istio 的配置分发方式。

什么是 xDS?

xDS(Extensible Discovery Service)是一种通信协议,用于在微服务架构中管理服务发现和动态配置。这种机制被广泛用于 Envoy 代理和 Istio 服务网格中,以管理各种类型的资源配置,如路由、服务发现、负载均衡设置等。

xDS 包含哪些发现服务?

xDS 包括以下主要的发现服务,每种服务都负责不同类型的网络资源配置:

  1. LDS(Listener Discovery Service):管理 Envoy 监听器的配置,这些监听器定义了如何接收和处理入站连接。
  2. RDS(Route Discovery Service):提供路由信息,定义了如何根据指定规则将请求路由到不同的服务。
  3. CDS(Cluster Discovery Service):管理集群信息,集群代表一组逻辑上类似的后端服务实例。
  4. EDS(Endpoint Discovery Service):提供具体服务实例的网络地址,这些服务实例组成了 CDS 中定义的集群。
  5. SDS(Secret Discovery Service):管理安全相关的配置,如 TLS 证书和私钥。
  6. VHDS(Virtual Host Discovery Service):为 RDS 提供虚拟主机配置,允许动态更新虚拟主机而不重启连接。
  7. SRDS(Scoped Route Discovery Service):管理路由作用域,提供基于不同条件(如请求头部)的动态路由选择。
  8. RTDS(Runtime Discovery Service):提供运行时配置,这些配置可用于实验性功能或精细调整系统行为。
  9. ECDS(Extension Config Discovery Service):为特定过滤器提供动态配置更新的服务。目前,网络过滤器、HTTP 过滤器和监听器过滤器都支持 ECDS。

这些服务共同支持动态配置的分发和更新,使得基于 Envoy 的应用架构能够实时适应变化,提高可扩展性和灵活性。每种服务的实现可以独立进行,也可以通过聚合方式(如 ADS)进行统一管理。CNCF 也成立了 xDS API 工作组来推动 xDS API 为 L4/L7 数据平面配置提供事实上的标准,类似于 SDN 中 OpenFlow 在 L2/L3/L4 中所扮演的角色。

提示
关于 xDS 协议的详细介绍,如 xDS 协议的 RPC 服务和变体方法,以及 xDS 请求流程,请参考 Envoy 代理文档

xDS 协议的变体

xDS 协议主要包括以下变体:

  1. State of the World (SotW):单独的 gRPC 流为每种资源类型提供完整数据,通常在 Envoy 代理初次启动时使用,也是 Istio 最早使用的 xDS 协议类型。
  2. 增量 xDS(Delta xDS):为每种资源类型提供变化的部分数据,从 2021 年开始开发,在 Istio 1.22 版本中开始默认开启。
  3. 聚合发现服务(ADS):一个 gRPC 流聚合所有资源类型的数据。
  4. 增量 ADS(Delta ADS):一个 gRPC 流聚合所有资源类型的增量数据。

下表概述了 xDS 协议的四种变体,包括对每个变体的解释、使用场景以及优缺点的对比。这些变体为不同的网络环境和服务需求提供了多种选择,可以根据具体情况选择最合适的协议变体以优化服务的性能和资源使用。

变体类型 解释 使用场景 优点 缺点
SotW 每次都发送所有配置数据,不论是否有变化。 适用于配置较少变化的稳定环境。 简单易实现,易于理解和维护。 数据传输量大,不适合频繁更新配置的环境。
Delta xDS 只传输变更的配置数据,而不是全部数据。 适用于配置频繁变化,需要快速响应变更的环境。 减少了不必要的数据传输,提高了效率。 实现复杂,需要客户端和服务端管理配置状态。
ADS 通过单一的 gRPC 流来管理所有配置数据,无需为每种资源类型建立独立的连接。 适用于需要同时管理多种类型资源的复杂服务架构。 减少了网络连接数,简化了资源管理。 对于网络或服务质量差的情况,单点故障可能导致所有配置更新失败。
Delta ADS 结合了 ADS 和增量 xDS 的优点,通过一个 gRPC 流聚合并且只传输变化部分的资源。 适用于既需要管理多种资源类型,又需要频繁更新配置的极其动态的环境。 提供了最大的灵活性和效率,适合大规模和高动态的服务架构。 实现最为复杂,对于配置管理的逻辑要求高,需要精确控制资源的变更和传输。
xDS 协议的四种变体介绍

使用 xDS 协议的服务网格可以更灵活地管理微服务之间的通信和配置,减少了配置变更的延迟,提高了系统的响应速度和可靠性。

在 Istio 中,DiscoveryServer 作为 Envoy 的 xDS API 的实现,负责监听 gRPC 接口并根据 Envoy 的需求动态推送配置。它能够处理各种资源类型的请求,并根据服务的变更实时更新 Envoy 配置。此外,它还支持安全特性,如验证客户端证书,确保只有合法的服务实例可以接收配置数据。

xDS 变体的配置示例

使用 xDS 协议的变体通常涉及在 Envoy 代理或与之类似的服务网格配置中指定 xDS 服务器的详细信息。虽然不同的服务网格和代理服务器的配置细节可能有所不同,下面是一些通用的 YAML 配置示例,说明如何指定 xDS 服务器以及如何使用这些协议变体。

State of the World (SotW)

在 Envoy 的配置中,你可以通过静态资源或通过 API 动态获取资源的方式来使用 SotW。这里是一个简单的 Envoy 配置示例,显示了如何静态定义集群和监听器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static_resources:
  listeners:
    - address:
        socket_address: { address: 0.0.0.0, port_value: 80 }
      filter_chains:
        - filters:
            - name: envoy.http_connection_manager
              config:
                stat_prefix: ingress_http
                codec_type: auto
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route: { cluster: local_service }
                    http_filters:
                      - name: envoy.router
                  clusters:
        - name: local_service
            connect_timeout: 0.25s
            type: STATIC
            lb_policy: ROUND_ROBIN
            hosts: [{ socket_address: { address: 127.0.0.1, port_value: 80 } }]

增量 xDS

增量 xDS 的配置需要在 xDS 服务端支持增量协议,并在客户端配置中指定使用增量 xDS。Envoy 启动配置中需要添加 API 版本来启用增量 xDS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
dynamic_resources:
  cds_config:
    api_config_source:
      api_type: DELTA_GRPC
      grpc_services:
        envoy_grpc:
          cluster_name: xds_cluster
  lds_config:
    api_config_source:
      api_type: DELTA_GRPC
      grpc_services:
        envoy_grpc:
          cluster_name: xds_cluster

聚合发现服务 (ADS)

使用 ADS 时,所有资源类型的配置通过一个单一的 API 端点聚合。这在 Envoy 配置中指定:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
dynamic_resources:
  cds_config:
    ads: {}
  lds_config:
    ads: {}
  ads_config:
    api_type: GRPC
    grpc_services:
      envoy_grpc:
        cluster_name: xds_cluster

增量 ADS

增量 ADS 通过在 ADS 配置中指定增量 API 类型,可以实现更为细粒度的更新:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
dynamic_resources:
  cds_config:
    ads: {}
    resource_api_version: V3
  lds_config:
    ads: {}
    resource_api_version: V3
  ads_config:
    api_type: DELTA_GRPC
    grpc_services:
      envoy_grpc:
        cluster_name: xds_cluster

这些配置示例需要根据你的具体环境和需求进行调整。更多细节和高级配置,你可以参考 Envoy 文档

Istio 如何发送配置给 Envoy sidecar?

得益于 xDS 协议,如 Istio、Envoy Gateway 等可以通过 API 远程动态分发配置到 Envoy 代理。下图展示了 Istio 的配置分发流程(Sidecar 模式)。

image
Istio 的配置分发流程图

Istio 中配置分发的主要流程说明:

  1. 声明式配置:用户通过 YAML 文件或其他配置管理工具定义服务网格的配置。这些配置可以包括路由规则、安全策略、遥测设置等。
  2. Kubernetes:Istio 配置文件被提交到 Kubernetes 集群中,通常是通过 kubectl apply 命令或其他 CI/CD 工具。Kubernetes 接收到配置文件并将其存储在 etcd 数据库中。
  3. Istiod:Istiod 是 Istio 的控制平面组件,负责管理和分发配置。它监听从 Kubernetes API 服务器中传入的事件,获取相关配置变更,并对其进行处理。Istiod 解析配置文件,生成相应的路由规则和策略,并通过 xDS API 将这些配置分发到数据平面(Envoy 代理)。
  4. xDS API:Istiod 使用 xDS API 将配置下发到各个 Envoy 代理中。
  5. Envoy Proxy:Envoy 是 Istio 的数据平面组件,运行在每个服务的旁路(sidecar)容器中,拦截并管理所有入站和出站流量。Envoy 代理通过 xDS API 接收来自 Istiod 的配置,并根据这些配置进行流量管理、策略执行和遥测数据收集。
  6. Pod:每个服务实例运行在一个 Pod 中,Pod 内部包含一个应用容器和一个 Envoy 代理容器。Envoy 代理拦截应用容器的所有网络流量,并根据配置进行处理。

这个配置分发流程确保了 Istio 能够动态管理和配置服务网格中的所有服务实例,提供一致的流量管理和策略执行。

xDS 的发展与 Istio 中的 Delta xDS 实现

起初,xDS 采用了“全局状态”(State of the World,简称 SotW)的设计,这意味着任何一个配置的更改都需要向 Envoy 发送所有配置的完整状态。这种方法在网络和控制平面上造成了巨大的负担,尤其是在大规模服务部署时。

在 2021 年的 EnvoyCon 上,Aditya Prerepa 和 John Howard 分享了 Istio 如何实现 Delta xDS,这是一种增量式的 xDS 实现。与传统的 SotW xDS 相比,Delta xDS 只发送变更的配置,显著减少了需要通过网络发送的配置数据量,从而提高了效率和性能。这种方法特别适用于那些配置频繁变更的环境,因为它只更新变化的部分而不是整个配置。

在实现 Delta xDS 的过程中,Istio 团队面临了多个挑战,包括如何确保配置更新的正确性以及避免潜在的资源泄漏。他们通过采用干运行(Dry-run)模式来并行运行 SotW 和 Delta 生成器,逐步发现并修复了实现中的缺陷。此外,他们还引入了新的 Envoy 类型,如虚拟主机发现服务(Virtual Host Discovery Service),以支持更细粒度的配置分发。

Delta xDS 增量配置

下图展示了 Delta xDS 增量配置的流程。

image
Delta xDS 增量配置流程图

Delta xDS 配置流程如下:

  1. 初始完整配置:控制平面向代理发送初始完整配置,此时使用的是 StoW 模式。
  2. 订阅配置变更:代理从控制平面订阅配置变更。
  3. 检查配置变更:控制平面检查相对于代理已知状态的配置变更。
  4. 计算差异:控制平面计算当前配置与代理持有的前一配置之间的差异(增量)。
  5. 仅发送差异:控制平面仅发送变更的配置(差异)给代理,代理应用这些差异增量更新其配置。

该流程确保只有必要的变更被传输和应用,提高了效率并减少了网络和代理资源的负载。

SotW vs Delta xDS

虽然 Delta xDS 解决了在大规模网络下的配置分发的性能问题,但是 SotW 模式依然有它存在的意义,比如在初次下发配置的情况下。下表对比了 Istio 中的两种配置分发方式:SotW (State of the World) 和 Delta xDS。

对比项 SotW Delta XDS
数据传输量 每次传输完整的配置数据,不管配置是否有变更。 仅传输发生变化的配置数据,减少了数据传输量。
效率 在小型或变更少的环境中效率可接受。 在大型环境或频繁变更的环境中更高效。
复杂性 实现简单,易于理解和维护。 实现较为复杂,需要精细的变更跟踪和管理。
资源消耗 可能因为重复发送大量未变更的数据而增加服务器和网络负载。 更低的资源消耗,因为只处理变更的部分。
实时性 配置更新后立即发送全量配置,实时性高。 只发送变更部分,响应更快,减少处理时间。
适用场景 适合配置变动不频繁的小型至中型部署。 适合配置频繁变更或大规模部署的场景。
Istio 中的全局状态和增量 xDS 配置分发方式对比

这个表格从数据传输量、效率、复杂性、资源消耗、实时性以及适用场景等多个角度对 SotW 和 Delta XDS 进行了对比,有助于在不同的使用环境中做出合适的选择。

总结

在这篇文章中我分享了 xDS 的组成及 Istio 中配置分发的流程,还有 xDS 的两种模式 SotW 和 Delta xDS。随着 Delta xDS 在 Istio 1.22 版本中成为默认配置,这将有助于用户在大规模网络环境下轻松使用 Istio。

参考

如何为你的 Hugo 网站添加即时搜索功能

2024-05-31 10:21:36

最近我用 Fuse 和 Hugo 导出的全站结构化数据(压缩后仅 2MB)做的即时搜索,还有快捷搜索地址 https://jimmysong.io/search/?q=关键词,定制了下结果展示页面,这就是开源的强大之处,任何地方都可以私人订制。

image
搜索结果展示页面

概览

下面我将分享下如何为你的 Hugo 网站添加即时搜索功能。大体步骤如下:

  1. 导出 Hugo 网站的结构化数据
  2. 使用 Fuse 库构建搜索的 JavaScript 代码
  3. 添加前端搜索模板
  4. 自动化更新网站结构化数据
  5. 进一步优化
提示

读者可以参考 hugo-blox-builder 这个项目中的搜索实现,下面是参考的代码:

1. 导出 Hugo 网站的结构化数据

首先,你需要为你的 Hugo 网站创建一个 JSON 文件,它将包含所有页面的必要元数据,如标题、描述、链接等。你可以通过 Hugo 的自定义输出格式来实现这一点。

在你的 Hugo 配置文件(通常是 config.tomlconfig.yaml)中,添加一个自定义输出格式:

[outputs]
home = ["HTML", "RSS", "JSON"]

[outputFormats.JSON]
mediaType = "application/json"
baseName = "index"
isPlainText = false

然后,在你的内容模板中(如 layouts/_default/list.json.json),定义输出的 JSON 结构:

{
  "data": [
    {{ range .Pages }}
    {
      "title": "{{ .Title }}",
      "url": "{{ .Permalink }}",
      "summary": "{{ .Summary }}"
    }
    {{ if not (eq .Next nil) }},{{ end }}
    {{ end }}
  ]
}

这将为你的整个站点生成一个 index.json 文件,其中包含所有页面的基本信息。当然你可能不想导出网站的所有页面,可以通过 Hugo 的语法,可定制化导出的 Section 或者不同类型页面。

2. 使用 Fuse 库构建搜索的 JavaScript 代码

接下来,使用 Fuse.js 库来实现前端的即时搜索功能。首先,你需要在你的网站中包含 Fuse.js 的库文件。你可以从 jsDelivr 等 CDN 加载它:

<script src="https://cdn.jsdelivr.net/npm/fuse.js/dist/fuse.min.js"></script>

然后,在你的 JavaScript 文件中,加载并解析 index.json 文件,并使用 Fuse.js 进行搜索:

fetch('/index.json')
  .then(response => response.json())
  .then(data => {
    const fuse = new Fuse(data.data, {
      keys: ['title', 'summary'],
      includeScore: true
    });

    document.getElementById('search-input').addEventListener('input', function (e) {
      const results = fuse.search(e.target.value);
      displayResults(results);
    });
  });

function displayResults(results) {
  const searchResults = document.getElementById('search-results');
  searchResults.innerHTML = '';
  results.forEach(result => {
    const elem = document.createElement('div');
    elem.innerHTML = `<a href="${result.item.url}">${result.item.title}</a>`;
    searchResults.appendChild(elem);
  });
}

具体实现可以参考 wowchemy-search.js

3. 添加前端搜索模板

在你的网站中添加一个搜索框和结果显示区域:

<input type="text" id="search-input" placeholder="输入搜索词">
<div id="search-results"></div>

另外你还可以添加搜索快捷键,一般是组合键 ⌘/CTRL + K 来快速打开搜索页面。

具体实现可以参考 这个前端模板

4. 自动化更新网站结构化数据

为了保证搜索结果的实时性,可以通过 GitHub Actions 或其他 CI/CD 工具来自动化 Hugo 网站的构建和部署流程,确保 index.json 文件始终是最新的。

创建一个 .github/workflows/hugo_build.yml 文件,定义自动化流程:

name: Build and Deploy
on:
  push:
    branches:
      - main
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - name: Set up Hugo
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: 'latest'
    - name: Build
      run: hugo --minify
    - name: Deploy
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./public

另外如果你的网站支持多语言,可以为每种语言分别生成 index.json 文件,并在不同的语言页面加载对应的索引文件。

5. 进一步优化

通过这些步骤,你可以有效地为你的 Hugo 网站添加一个高效且可定制的即时搜索功能。

总结

本文介绍了如何为 Hugo 网站添加即时搜索功能,并提供了进一步优化搜索功能的建议,包括缓存优化、搜索结果高亮显示和高级搜索选项。这不仅展示了开源技术的强大自定义能力,也使网站用户能更快更准确地找到所需信息。

如何使用 Envoy Gateway 在 API 网关侧基于 OIDC 实现单点登录?

2024-05-24 10:20:20

微服务中常见的认证方式详解这篇博客中我们介绍到了 OAuth 2.0 认证,该身份认证协议有多种实现方式,其中最流行的就是 OpenID Connect(OIDC)认证。OIDC 能够为用户提供身份验证和授权。本文将介绍如何使用 Envoy Gateway 在 API 网关级别实现 OIDC 认证。

Envoy Gateway 支持的认证方式

Envoy Gateway 是一个使用 Envoy 实现的高性能的 API 网关,支持多种认证方式来保护 API 和微服务:

  1. JWT 认证: 使用 JSON Web Tokens(JWT)进行认证。
  2. mTLS(双向 TLS): 使用双向 TLS 确保客户端和服务器之间的安全通信。
  3. HTTP Basic 认证: 使用用户名和密码进行基本认证。
  4. OIDC 认证: 使用 OpenID Connect 协议进行身份验证和授权。
  5. 外部认证:外部认证调用外部 HTTP 或 gRPC 服务来检查传入的 HTTP 请求是否经过认证。

本文重点介绍如何在 Envoy Gateway 中配置和使用 OIDC 认证从而在网关侧实现单点登录。

什么是 OIDC?

OpenID Connect(OIDC)是一个基于 OAuth 2.0 的身份验证协议。它允许客户端通过认证服务器验证用户身份,并获取有关用户的信息。

OIDC 认证流程如下图所示:

image
OIDC 认证流程图

OIDC 为 OAuth 2.0 增加了身份验证层,通过引入 ID Token 和标准化的 UserInfo Endpoint,使 OAuth 2.0 不仅能够用于授权,还可以用于安全地验证用户身份,从而实现单点登录(SSO)和用户身份信息的获取。

为什么要实现单点登录?

单点登录(Single Sign-On, SSO)是一种身份验证方式,它允许用户使用一个账户登录多个独立的应用系统,通过一次身份验证即可无缝访问所有相关应用,减少重复输入用户名和密码的麻烦,从而提升用户体验。SSO 集中管理用户身份和认证,增强了系统安全性,并简化了 IT 管理流程。

对于微服务架构,SSO 尤其重要,因为它在各个微服务之间实现统一的认证和授权,避免了每个服务单独实现身份验证逻辑的需求,减少了用户重复登录的麻烦,并提高了用户体验。集中管理的方式还可以统一应用安全策略,更有效地监控和响应安全事件,提升系统的整体安全性。同时,通过使用标准化的令牌(如 JWT),SSO 简化了微服务之间的身份验证过程,提高了开发效率,让开发人员能够专注于业务逻辑的实现。

示例:使用 Envoy Gateway 和 Auth0 的单点登录

接下来我们将使用 Auth0 作为身份供应商,演示如何使用 Envoy Gateway 在 API 网关端实现单点登录。

你可以在 Bilibili 上查看该示例演示。

基于 Auth0 实现单点登录

首先我们先说明下示例中 Envoy Gateway 基于 Auth0 实现单点登录的详细流程,如下图所示。

image
Envoy Gateway 基于 Auth0 实现单点登录的流程图

步骤说明:

  1. 用户访问网站:用户通过浏览器访问 https://www.example.com
  2. 请求转发:浏览器向 Envoy Gateway 发送 GET 请求。
  3. 检查 ID 令牌:Envoy Gateway 检查用户请求的 cookie 是否包含有效的 ID 令牌。
  4. 重定向到身份提供商:如果没有找到 ID 令牌,Envoy Gateway 将用户重定向到身份提供商(Identity Provider,IdP)的授权端点,在这里是 Auth0,关于 Auth0 如何实现 Login 的详细信息请查看 Auth0 文档
  5. 用户登录:用户在身份提供商的登录页面输入用户名和密码,并提交凭证进行登录。
  6. 获取授权码:用户成功登录后,身份提供商将用户重定向回 Envoy Gateway,并在 URL 中包含授权码。
  7. 交换 ID 令牌:Envoy Gateway 使用授权码向身份提供商请求 ID 令牌。
  8. 设置 Cookie:身份提供商返回 ID 令牌,Envoy Gateway 将其设置为用户的 cookie。
  9. 重定向:Envoy Gateway 将 URL 重定向到 https://www.example.com
  10. 验证 ID 令牌:Envoy Gateway 验证用户请求中的 ID 令牌。
  11. 路由请求:验证通过后,Envoy Gateway 将请求路由到后端应用(App)。

通过上述流程,Envoy Gateway 实现了单点登录功能。用户的 HTTP 请求在没有得到授权的情况下都会被转发单点登录页面。除了 Auth0 以外,Envoy Gateway 还支持多个身份提供商,如 Azure AD、Keycloak、Okta、OneLogin、Salesforce、UAA 等。

下面我们将按照时序图中的流程配置 Auth0 和 Envoy Gateway。

在 Auth0 上创建应用

请参考以下步骤在 Auth0 上设置一个 Regular Web Application:

  1. 访问 Auth0 并注册一个免费账户。
  2. 创建一个新的应用,并选择常规 Web 应用程序。
  3. 在应用设置中,记录或设置以下字段:
    • Domain{DOMAIN}
    • Client ID{CLIENT_ID}
    • Client Secret{CLIENT_SECRET}
    • Allowed Callback URLshttps://www.example.com/oauth2/myapp/callback
    • Allowed Logout URLshttps://www.example.com/myapp/logout

记住上面的 Auth0 字段,我们将用它们来配置 Envoy Gateway 的安全策略。

提示
这里的 Logout URL 不起实际作用,应为在我们的下面示例中的 backend 服务并没有实现 Auth0 的 logout 接口。我们只是按照习惯在此添加该字段,以待未来实现。

下面展示的是 Auth0 的配置页面截图,在设置好用户后并创建普通 Web 应用后,你只需要配置这两个地方。

image
Auth0 配置页面 1
image
Auth0 配置页面 2

以上就是 Auth0 的全部配置,接下来我们将安装和配置 Envoy Gateway。

安装 Envoy Gateway

参考 Envoy Gateway 快速开始在 minikube 上安装 Envoy Gateway:

minikube start --driver=docker --cpus=2 --memory=2g
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.0.1 -n envoy-gateway-system --create-namespace
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.1/quickstart.yaml -n default

参考安全网关,为 Envoy Gateway 配置 TLS:

# 创建根证书和私钥来签署证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt

# 为 www.example.com 创建证书和私钥
openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt

# 将证书/密钥存储在 Secret 中
kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt

更新快速开始中创建的网关,使其包含 443 端口并引用 example-cert Secret 的 HTTPS Listener:

echo '[
  {
    "op": "add",
    "path": "/spec/listeners/-",
    "value": {
      "name": "https",
      "protocol": "HTTPS",
      "port": 443,
      "tls": {
        "mode": "Terminate",
        "certificateRefs": [
          {
            "kind": "Secret",
            "group": "",
            "name": "example-cert"
          }
        ]
      }
    }
  }
]' | kubectl patch gateway eg --type=json --patch-file /dev/stdin

创建 HTTPRoute,为 /myapp 端点增加一条到backend 服务的路由:

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: myapp
spec:
  parentRefs:
  - name: eg
  hostnames: ["www.example.com"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /myapp
    backendRefs:
    - name: backend
      port: 3000
EOF

配置 Envoy Gateway 的 OIDC 认证

创建一个 Kubernetes Secret,用于存储 OAuth Client 的 Client Secret:

kubectl create secret generic auth0-client-secret --from-literal=client-secret=${CLIENT_SECRET}
注意
${CLIENT_SECRET} 替换成你的 Auth0 Client Secret。

创建一个安全策略(SecurityPolicy):

cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  name: oidc-example
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: eg
  oidc:
    provider:
      issuer: "https://${DOMAIN}"
    clientID: "${CLIENT_ID}"
    clientSecret:
      name: "auth0-client-secret"
    redirectURL: "https://www.example.com/myapp/oauth2/callback"
    logoutPath: "/myapp/logout"
EOF

注意事项

在这个示例中我们为 Envoy Gateway 网关设置了 OIDC,修改 targetRef 到 HTTPRoute,也可以为单个路由设置 OIDC。关于 ODIC 的具体配置,请参考 Envoy Gateway API 文档。

验证单点登录:登入

www.example.com 添加到本地的 /etc/hosts 文件中:

echo "127.0.0.1 www.example.com" | sudo tee -a /etc/hosts

配置应用程序的端口转发,以便你可以在本地通过域名访问示例应用:

export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')

sudo kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 443:443

现在在浏览器中访问 https://www.example.com,跳过证书风险提示,页面将跳转到 Auth0 的登录界面,如下图所示,选择使用 Google 账户登录。

image
登录界面

在登录完成后,浏览器将跳转会 https://www.example.com 页面,并展示 HTTP 请求结果,如下面的 JSON 代码所示。

{
  "path": "/",
  "host": "www.example.com",
  "method": "GET",
  "proto": "HTTP/1.1",
  "headers": {
    /*Omit*/
    "Authorization": [
      "Bearer eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtYXdoam15MzhnZzVxeng3dS51cy5hdXRoMC5jb20vIn0..IiH9LnxmnrGAVy-q.eQV_0Ssetw9mmrEaJNLlBowGJNX51awhh67WSejPrksuGU9e9-DcPJQqmR67ONFzTXWR6CFy4Rfgs4btsmEtvCtiNTCgrBHP90ddbOTg_pK31WnsQ7NThyRfGwoogSaAtK6hFrC2pxFaLj0XL7XvSPk-OaTzK1Zh1da1IM1cmWAWiBRc3nQiVWRDrExPo8-i5SawFe0jIcwytVSaRiX5Polyd3cZ7A7nlei-vDLCfj0HVzOO605nF7ED2dBSnZyev1sg14q598f3X2Vfhi2oJlnbiulGZIlpXgGbcPhzAJJxyEe6qpRpNg7Hbk8Ya-i8gUTwwNysrgm3.Zu5kD_6DzSfZPvwemttXYQ"
    ],
    "Cookie": [
      "OauthHMAC-167a6c5=RPdscXEBap0NeSIppJXoxkHt0qvMz4fNHXo2uvgDgIY=; OauthExpires-167a6c5=1716540771; BearerToken-167a6c5=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtYXdoam15MzhnZzVxeng3dS51cy5hdXRoMC5jb20vIn0..IiH9LnxmnrGAVy-q.eQV_0Ssetw9mmrEaJNLlBowGJNX51awhh67WSejPrksuGU9e9-DcPJQqmR67ONFzTXWR6CFy4Rfgs4btsmEtvCtiNTCgrBHP90ddbOTg_pK31WnsQ7NThyRfGwoogSaAtK6hFrC2pxFaLj0XL7XvSPk-OaTzK1Zh1da1IM1cmWAWiBRc3nQiVWRDrExPo8-i5SawFe0jIcwytVSaRiX5Polyd3cZ7A7nlei-vDLCfj0HVzOO605nF7ED2dBSnZyev1sg14q598f3X2Vfhi2oJlnbiulGZIlpXgGbcPhzAJJxyEe6qpRpNg7Hbk8Ya-i8gUTwwNysrgm3.Zu5kD_6DzSfZPvwemttXYQ; IdToken-167a6c5=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFKWkxWbnNrai0tYmhsNlJzVm51OCJ9.eyJpc3MiOiJodHRwczovL2Rldi1hd2hqbXkzOGdnNXF6eDd1LnVzLmF1dGgwLmNvbS8iLCJhdWQiOiJUZzhlNWVoa0xKM2hka3cxTzREMTBQd21QeTcxZHZtdiIsImlhdCI6MTcxNjQ1NDM3MSwiZXhwIjoxNzE2NDkwMzcxLCJzdWIiOiJnb29nbGUtb2F1dGgyfDExMjc0NDc3OTAyMjMzMTA0ODY0MCIsInNpZCI6IjRlSjhDZnZuZjd5Mm1kaE94QXBTY0JiUEhjOS1rZUVLIn0.r9dwIy_HeiO5_I3UlohLkeRES5FGoxqQnwmcA00cA_kdc5mUxgeVopXIhBUjJnTKv7bOUVJvFw21ew4gqVRJfllDyG-s_XfhSW1-lEXmCc2bGYDtOzva6k2S_VRgyMKfG04_DWFuTgO_pLtix28aYq8cGzKJ_VglT_KgRhoktzJu4Js5iCv9JPnydRJmpvRJwX3tDv_Q3mmUSazaLkhOTdiBJFrGlS07qEzJ_iWANZgR8uDNhpXdmlcqpb3MZkkMulr5-jXIgEhBQKpw28tUiSlzh6EpAVuBH9T1w8bUmFRzCc6JPPamJRfflYW5onNgYHDfcU0RpvpsCHRHRAZbdA"
    ],
    /*Omit*/
    "User-Agent": [
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
    ],
    "X-Envoy-Internal": [
      "true"
    ],
    "X-Forwarded-For": [
      "10.244.0.51"
    ],
    "X-Forwarded-Proto": [
      "https"
    ],
    "X-Request-Id": [
      "c1e64057-c5c8-4fb2-a304-25c291eeed32"
    ]
  },
  "namespace": "default",
  "ingress": "",
  "service": "",
  "pod": "backend-55d64d8794-4qvgd"
}

此时通过 Chrome 浏览器的 Inspector - Application - Cookies 查看到 ID Token 如下图所示:

image
在 Chrome Inspector 中查看 ID Token

编写代码 Python 代码,validate_id_token.py,解析 ID Token 并验证其有效性:

import jwt
import requests
from jwt.algorithms import RSAAlgorithm
import argparse
import json
import base64

def base64url_decode(input):
    rem = len(input) % 4
    if rem > 0:
        input += '=' * (4 - rem)
    return base64.urlsafe_b64decode(input)

def get_signing_key(jwk_url, kid):
    jwks = requests.get(jwk_url).json()
    for jwk in jwks['keys']:
        if jwk['kid'] == kid:
            return RSAAlgorithm.from_jwk(jwk)
    raise Exception('Public key not found.')

def validate_token(token, audience, issuer, jwk_url):
    headers = jwt.get_unverified_header(token)
    kid = headers['kid']
    signing_key = get_signing_key(jwk_url, kid)

    decoded_token = jwt.decode(
        token,
        signing_key,
        algorithms=["RS256"],
        audience=audience,
        issuer=issuer
    )
    return decoded_token

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Validate a JWT token.')
    parser.add_argument('token', type=str, help='The JWT token to validate')
    args = parser.parse_args()

    token = args.token

    # 解析 token 的 payload 部分,提取 audience 和 issuer
    header, payload, signature = token.split('.')
    decoded_payload = base64url_decode(payload)
    payload_json = json.loads(decoded_payload)

    audience = payload_json['aud']
    issuer = payload_json['iss']
    jwk_url = f"{issuer}.well-known/jwks.json"

    try:
        decoded = validate_token(token, audience, issuer, jwk_url)
        print("Token is valid. Decoded payload:")
        for key, value in decoded.items():
            print(f"{key}: {value}")
    except Exception as e:
        print(f"Token validation failed: {e}")

安装依赖的包:

pip install pyjwt requests

运行代码:

python validate_id_token.py ${ID_TOKEN}

你将看到类似下面的输出:

Token is valid. Decoded payload:
iss: https://dev-awhjmy38gg5qzx7u.us.auth0.com/
aud: Tg8e5ehkLJ3hdkw1O4D10PwmPy71dvmv
iat: 1716470905
exp: 1716506905
sub: google-oauth2|112744779022331048640
sid: 4W_hQNJJ8ftDL8S3Cozp8GEu2Au4_e9N

通过该 ID Token 的值可以得出:

验证单点登录:登出

由于我们的示例应用中没有实现 Auth0 的 Logout 逻辑,所以我们需要通过 HTTP 请求明确告知 Auth0 要 logout,在浏览器中访问该 URL:

https://${DOMAIN}/v2/logout?client_id=${CLIENT_ID}

请将 ${DOMAIN}${CLIENT_ID 修改为你的 Auth0 应用程序的配置项。关于 Auth0 如何登出 OIDC 端点的详细说明请查看 Auth0 文档

登出后,页面将再次跳转到登录页面,在登录后,页面将重定向到 https://www.example.com

总结

通过以上步骤,你可以在 Envoy Gateway 中实现 OIDC 认证,确保 API 的安全性。这种方法不仅能提供灵活的身份验证机制,还能简化应用程序的身份管理。通过集成 Auth0 等身份提供商,Envoy Gateway 可以轻松实现单点登录,提升用户体验和系统安全性。未来,你可以根据需求进一步配置和优化 Envoy Gateway,充分利用其强大的认证和授权功能,以满足更复杂的安全要求和业务需求。

参考

微服务中常见的认证方式详解

2024-05-22 13:54:49

在现代微服务架构中,安全性是一个至关重要的方面。随着微服务数量的增加,如何确保服务间的安全通信成为了一个挑战。本文将介绍几种常见的微服务认证方式,帮助你在设计和实现微服务系统时选择合适的认证方案。

微服务中常用的认证方式

下表列出了几种微服务中常用的认证方式,并从优点、缺点、适用场景和现实示例等维度进行比较。

认证方式 优点 缺点 运行位置 适用场景 典型用途 现实使用场景
JWT 自包含令牌,减少服务器负担 令牌较大,可能会增加带宽开销 API 网关、服务间 微服务之间无状态通信 用户认证和授权 在微服务架构中,用户认证(如 Auth0、Firebase)
OAuth 2.0 广泛支持,灵活性高 实现复杂,需要额外的交互 API 网关 第三方应用授权 第三方应用访问用户数据 Github OAuth,用于第三方应用访问 Github 数据和 API
mTLS 高安全性,防止中间人攻击 证书管理复杂,性能开销较大 服务间 高安全性要求的通信 安全敏感的服务通信 银行系统中的服务通信
Basic 认证 简单易实现 不安全,容易被拦截 API 网关、服务间 简单的 API 保护 简单的内部服务 Kubernetes API Server 的基本认证
API Key 认证 简单易用 安全性低,容易被滥用 API 网关、服务间 低安全性要求的场景 简单的服务访问控制 各种公共 API,如 OpenAI API

下面我们将详细介绍这几种常见的认证方式。

JWT 认证

JWT(JSON Web Token)最早由 IETF JSON Web Token (JWT) 工作组提出,并在 2015 年作为 RFC 7519 标准正式发布。JWT 的设计目标是提供一种紧凑且自包含的方式,用于在各方之间安全地传递信息。由于其易于使用和无状态的特性,JWT 迅速被广泛采用,成为身份验证和信息交换的标准之一,特别是在微服务和现代 Web 应用中。

下图展示的是 JWT 认证流程。

image
JWT 认证流程

JWT 认证流程说明:

  1. 用户提供凭证
  2. 客户端请求访问令牌
  3. 认证服务器返回 JWT 令牌
  4. 客户端带 JWT 令牌请求资源服务器
  5. 资源服务器验证 JWT

JWT 的格式说明及示例

JWT(JSON Web Token)由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature),分别通过 Base64 编码后用点(.)连接在一起组成。

  1. 头部(Header):头部包含令牌类型和签名算法。

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  2. 载荷(Payload):载荷包含声明(claims),即关于用户或其他数据的断言。

    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    
  3. 签名(Signature):签名由编码后的头部、编码后的载荷以及一个密钥通过头部中指定的算法生成。

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    )
    

下面是一个 JWT 令牌示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

OAuth 2.0

OAuth(Open Authorization)协议最早由 Blaine Cook 和 Chris Messina 在 2006 年提出。最初的目标是为 Twitter 提供一个开放的授权标准。OAuth 1.0 于 2007 年发布,提供了一个允许用户授权第三方应用访问其资源的标准化方式,但由于其复杂的签名机制和其他安全问题,受到了一些限制。

为了克服这些缺点,IETF(Internet Engineering Task Force)成立了 OAuth 工作组,旨在开发一个更简化、更灵活的授权协议。2012 年,OAuth 2.0 正式发布(RFC 6749 和 RFC 6750)。OAuth 2.0 简化了授权流程,增加了多种授权模式,如授权码模式、简化模式、资源所有者密码凭证模式和客户端凭证模式。

OAuth 2.0 迅速成为行业标准,广泛应用于各种网络服务和应用程序,如 Google、Facebook、GitHub 等。在此基础上,出现了多个扩展和补充协议(如 OpenID Connect),进一步增强了 OAuth 2.0 的功能和安全性。

OAuth 2.0 的发展和扩展使其成为现代互联网身份验证和授权的重要基石,提供了灵活和安全的解决方案,满足了不断变化的网络应用需求。

下图展示的是 OAuth 2.0 认证流程。

image
OAuth 2.0 认证流程

OAuth 2.0 认证流程说明:

  1. 用户请求访问资源
  2. 客户端请求认证
  3. 用户登录并授权
  4. 认证服务器返回授权码
  5. 客户端交换授权码获取访问令牌
  6. 客户端带访问令牌请求资源服务器

OAuth 2.0 授权码

在 OAuth 2.0 授权码模式中,授权码是客户端在用户授权后从授权服务器获取的短期凭证,用于交换访问令牌。授权码是一个临时的字符串,可以在授权服务器和客户端之间传递以获得更安全的访问令牌。

OAuth 2.0 扩展

OAuth 2.0 在发展过程中,为了适应不同的场景,发展出了众多的扩展,下表罗列出一些常用的扩展名称、主要功能及适用场景。

扩展名称 主要功能 适用场景
授权码 PKCE 扩展 提高授权码模式的安全性,防止授权码拦截攻击 公共客户端(如移动应用、单页应用)
动态客户端注册协议 允许客户端动态注册和更新客户端信息 自动化和灵活性要求高的系统
Token Introspection 允许资源服务器验证和获取访问令牌的详细信息 需要验证令牌有效性和获取令牌详细信息的场景
Token Revocation 提供令牌撤销的标准接口 提高系统安全性和控制能力
Device Authorization Grant 允许输入受限的设备通过其他设备完成身份验证 智能电视、游戏机等输入能力有限的设备
Mutual TLS Client Authentication 基于双向 TLS 的客户端认证 高安全性要求的应用场景
Resource Indicators 允许客户端在授权请求中指定访问的资源服务器 多资源服务器的支持
Step-up Authentication Challenge Protocol 允许资源服务器按需请求更强的身份验证(如多因素认证) 高风险操作的高级认证

OAuth 2.0 授权流程(以 Github 为例)

GitHub 使用 OAuth 2.0 来授权第三方应用访问用户的 GitHub 数据。OAuth 2.0 令牌在 GitHub 上被称为 “access tokens”,用于验证和授权访问 GitHub API。它提供了一种安全、标准化的方法,允许第三方应用在用户授权的情况下访问 GitHub 资源。通过使用访问令牌,应用程序可以代表用户执行各种操作,如读取用户信息、访问仓库、创建 gists 等。这个过程确保了用户的安全和隐私,同时简化了应用程序的认证和授权流程。

以下是使用 GitHub OAuth 2.0 令牌的详细流程和示例:

  1. 用户授权:用户在第三方应用程序的界面上点击“Login with GitHub”按钮。应用程序将用户重定向到 GitHub 的授权页面。

  2. 获取授权码:用户在 GitHub 授权页面上登录并同意授权,GitHub 会将用户重定向回应用程序,并在 URL 参数中附带一个授权码(authorization code)。

    示例:

    https://yourapp.com/callback?code=AUTHORIZATION_CODE
    
  3. 交换访问令牌:应用程序服务器使用授权码向 GitHub 的授权服务器请求访问令牌。

    请求示例:

    POST https://github.com/login/oauth/access_token
    Content-Type: application/json
    Accept: application/json
    
    {
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "code": "AUTHORIZATION_CODE",
      "redirect_uri": "https://yourapp.com/callback"
    }
    
  4. GitHub 返回访问令牌:GitHub 验证请求并返回访问令牌。

    响应示例:

    {
      "access_token": "YOUR_ACCESS_TOKEN",
      "token_type": "bearer",
      "scope": "repo,gist"
    }
    
  5. 使用访问令牌访问资源:应用程序使用获取的访问令牌访问 GitHub API。

    请求示例:

    curl -H "Authorization: token YOUR_ACCESS_TOKEN" https://api.github.com/user
    

    响应示例:

    {
      "login": "github-user",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/avatar.jpg",
      "name": "Github User",
      "company": "GitHub",
      "blog": "https://example.com",
      "location": "Earth",
      "email": "[email protected]"
    }
    

访问令牌的特点和使用

  1. 权限范围(Scopes):访问令牌的权限范围由用户在授权时指定,可以包括读取用户资料、访问用户仓库、管理 gists 等。例如,在上述示例中,scope 包含 repogist

  2. 有效期和刷新:访问令牌的有效期可以是长期的也可以设置时间范围,直到用户主动撤销。

  3. 安全传输:访问令牌应通过 HTTPS 传输,以确保其不被截获。

mTLS

mTLS(Mutual TLS)是一种在客户端和服务器之间进行双向身份验证的技术,最早起源于 TLS(传输层安全协议),TLS 的前身 SSL(安全套接层)协议于 1995 年由 Netscape 开发。随着互联网安全需求的增加,TLS 逐步发展为一个高度安全的通信标准,而 mTLS 则在此基础上进一步提升了安全性,通过要求双方互相验证身份,广泛应用于金融、医疗等对安全性要求极高的领域。

下图展示的是 mTLS 认证流程。

image
mTLS 认证流程

mTLS 认证流程说明:

  1. 客户端与服务器互相发送证书
  2. 双方验证对方证书
  3. 建立安全连接

更多关于 TLS 和 mTLS 的内容请参考博客 如何理解 Istio 中的 mTLS 流量加密

Basic 认证

Basic 认证是一种最早由 HTTP/1.0 规范(RFC 1945)定义的简单认证机制,它通过将用户名和密码进行 Base64 编码后附加到 HTTP 请求头中进行身份验证。由于实现简单且易于使用,Basic 认证在早期的 Web 应用中被广泛采用。然而,由于其固有的安全性问题(如明文传输容易被截获),它在现代应用中通常与 HTTPS 一起使用,或被更安全的认证方式所替代。

下图展示的是 Basic 认证流程。

image
Basic 认证流程

Basic 认证流程说明:

  1. 用户提供用户名和密码
  2. 客户端带用户名和密码请求资源服务器
  3. 资源服务器验证

Basic 示例

Basic 认证使用 Base64 编码的用户名和密码进行认证。下面是使用 curl 命令进行 Basic 认证请求的示例:

curl -u <username>:<password> https://api.example.com/data

如果用户名为 admin,密码为 password123,请求示例如下:

curl -u admin:password123 https://api.example.com/data

API Key 认证

API Key 认证是一种通过在请求中包含预先分配的唯一密钥来进行身份验证的方法,最早在 2000 年代初随着 Web API 的兴起而流行。API Key 认证由于其简单易用和便于管理的特性,被广泛应用于各种公共和私有 API 中。尽管它的安全性较低,容易被滥用,但在许多场景中仍然是控制访问的一种有效手段,特别是对于不需要高度安全保护的应用。

下图展示的是 API Key 认证流程。

image
API Key 认证流程

API Key 认证流程说明:

  1. 客户端带 API Key 请求资源服务器
  2. 资源服务器验证 API Key

API Key 示例

API Key 是在请求中传递的一个唯一标识符,用于验证客户端身份。API Key 通常通过 HTTP 请求头或 URL 参数传递。

HTTP 请求头中的 API Key 示例:

curl -H "Authorization: ApiKey YOUR_API_KEY" https://api.example.com/data

URL 参数中的 API Key 示例:

curl https://api.example.com/data?api_key=YOUR_API_KEY

API Key 格式通常是一个字符串,包含字母和数字,例如:

1234567890abcdef1234567890abcdef

总结

在微服务架构中选择合适的认证方式至关重要。不同的认证方式在安全性、复杂性和适用场景上各有优劣。本文介绍了 JWT、OAuth 2.0、mTLS、Basic 认证和 API Key 认证五种常见的认证方式,并提供了它们的优缺点和适用场景。此外,其他常见的认证方式如 SAML、LDAP、Kerberos 和 OpenID Connect 也广泛应用于不同的互联网应用场景,特别是在单点登录和跨域认证方面。希望这些信息能帮助你在设计和实现微服务系统时选择最合适的认证方案。

Istio Ambient 模式的局限性解析

2024-05-16 11:28:34

Istio 1.22 版本的发布标志着 Ambient 模式正式进入 beta 阶段,随之发布了一篇标题为 告别 Sidecar:Istio 的 Ambient 模式在 v1.22 中达到 Beta 的博客,声称 Layer 4 和 Layer 7 的功能现已可用于生产环境。其实社区早在一个月前的 KubeCon EU 上就宣布了这一里程碑。这种激动人心的宣传似乎在暗示我们可以彻底抛弃 Sidecar 模式,但事实真是如此吗?

为什么不急于告别 Sidecar 模式?

虽然我对新技术持开放态度,但完全告别 Sidecar 模式可能为时尚早。每种模式都有其特定的应用场景和优缺点。下面,我将详细分享 Ambient 模式相较于 Sidecar 模式的一些限制,帮助大家更好地理解两者之间的差异。

Ambient 模式与 Sidecar 模式的关键区别

流量管理

Ambient 模式的 L7 流量管理支持尚未成熟,尚未达到生产环境的可用水平。相较之下,Sidecar 模式在这方面更为稳定和可靠。

安全性

在 Ambient 模式下,mTLS 被强制在 namespace 级别开启,而 Sidecar 模式则赋予用户更大的灵活性,可以选择是否启用 mTLS。这种灵活性对于某些应用场景尤为重要。

可观测性

对于 L7 层的遥测数据,Ambient 模式能否像 Sidecar 模式一样对每个 pod 进行精确的监控和追踪仍是一个疑问。Sidecar 模式在可观测性方面已被广泛验证,其能力更为成熟。

运维

部署方面,Ambient 模式推荐使用 Helm,仅支持 Kubernetes 平台,而 Sidecar 模式还支持虚拟机和混合云环境。此外,Ambient 模式尚未得到主要云厂商的官方支持。在升级过程中,Ambient 模式的爆炸半径更大,暂不支持金丝雀发布,推荐使用蓝绿部署。对于从 Sidecar 模式向 Ambient 模式的迁移或二者共存,仍缺乏最佳实践。

扩展性

目前对于 Wasm 插件的支持,Ambient 模式仍不明确,而 Sidecar 模式在这方面已经有了较为完善的支持。

其他功能特性

Dual Stack 模式在 Sidecar 模式下虽然仍处于实验阶段,但至少已有一定的实现,而 Ambient 模式是否支持这一特性仍不明朗。

总结

虽然 Istio 1.22 带来了令人兴奋的 Ambient 模式,但在完全告别 Sidecar 模式之前,我们需要慎重考虑这些限制和差异。每种模式都有其独特的优势和适用场景,用户应根据自身需求做出明智的选择。我将继续对 Ambient 模式进行测试和追踪,更多深入解读敬请关注本博客。

Envoy Gateway 概述——使用 Gateway API 的现代 Kubernetes 入口

2024-05-08 11:20:49

在 Kubernetes 环境下选择正确的网络通信工具至关重要。根据Tetrate 的讨论,选择取决于网络通信的类型:南北向流量还是东西向流量。对于主要处理外部请求的服务,Envoy Gateway 是理想选择,它不仅高效管理流量,还能在你向微服务架构过渡时提供无缝集成。

本文将探讨 Envoy Gateway 在 Kubernetes 上部署的优势,及其它与服务网格的关系,展示为何它是暴露服务到公网的理想选择。

Envoy Gateway 及其在服务网格中的角色概述

Envoy Gateway 是一个围绕 Envoy Proxy 构建的 Kubernetes 原生 API 网关,它旨在降低用户采用 Envoy 作为 API 网关的难度,并为供应商建立 API 网关(例如 Tetrate Enterprise Gateway for Envoy)增值产品奠定基础。

Envoy Gateway 不仅是管理南北流量的理想选择,也可作为连接和保护服务网格中服务的关键组件。它还通过提供安全的数据传输、流量路由、负均衡及故障恢复等功能,增强了微服务之间的通信效率和安全性。Envoy Gateway 利用其内置的 Envoy Proxy 技术,可以处理大量的并发连接和复杂的流量管理策略,同时保持较低的延迟和高吞吐量。

此外,Envoy Gateway 与 Kubernetes Gateway API 的紧密集成使得它能够以声明式的方式进行配置和管理,极大简化了服务网格中网关的部署和更新过程。这种集成不仅提升了操作效率,还使得 Envoy Gateway 能够在不增加额外复杂性的前提下,与服务网格如 Istio 这样的解决方案无缝协作。

下图展示了 Envoy Gateway 与服务网格的关系。

image
Envoy Gateway 与服务网格的关系

在 Kubernetes 集群中,Envoy Gateway 负责管理南北向流量,即进出集群的流量,并通过 Kubernetes Gateway API 进行配置,后者定义了服务的路由规格。集群内服务直接连接到 Pods。服务网格部分,由控制平面(如 Istio 或 Linkerd)配置数据平面中的 Envoy Sidecars,这些 Sidecars 负责处理集群内部的东西向流量。在这个系统中,Envoy Gateway 可以与服务网格相互协作,但它们各自独立地管理不同方向的流量。

设想一下,Envoy Gateway 像是一个城市的主要入口(比如海关),所有的数据流,就像各种车辆,都得通过这个大门进出。它就像一个严格的守门员,负责审查、指导,确保每个数据包,就像每个乘客,都能被准确地送到目的地。在 Kubernetes 这座城市中,Envoy Gateway 管理着所有进城的流量,它确保数据流可以安全、高效地进入城市,并被准确地送达给城市内部的服务。

进入城市之后,服务网格就接管了,这就像城市内部的一系列交通网络。服务网格中的 Envoy sidecars 就好比是这座城市内部的出租车或者公交车,负责把数据包从海带到它们在城市内部的具体目的地。Envoy Gateway 负责将外部请求顺利引入,之后服务网格负责在集群内部继续高效地处理这些请求。

Envoy Gateway 对 Kubernetes Gateway API 的支持,可以看作是对我们城市交通信号系统的一个重大升级。这不仅为进入城市的数据流提供了更加清晰和个性化的指引,而且让整个城市的交通运行更加智能化。

Envoy Gateway 的核心功能和优势

Envoy Gateway 提供了几个核心功能,使其成为 API 网关的突出选择:

与 Gateway API 的关系

在 Kubernetes 环境中引入的 Gateway API 为集成和配置 Ingress 网关提供了一种新的强大方法,它与传统的 Ingress 相比具有更高的灵活性和功能性。正如我在 Gateway API:Kubernetes 和服务网格入口中网关的未来 中所讨论的,Gateway API 通过区分角色和提供跨命名空间支持,更适应多云环境,且已被多数 API 网关采用。这种 API 设计支持了 ingress 网关(南北向流量)与服务网格(东西向流量,跨集群路由)的融合,使得 Envoy Gateway 成为 Kubernetes 和服务网格中统一未来的网关解决方案。通过引入 Gateway API,Envoy Gateway 强化了其作为云原生环境中前沿代理的角色,使得用户能够更灵活地管理其流量和策略。

Kubernetes Gateway API 是 Envoy Gateway 的基石,它提供了一种更具表达性、灵活性和以角色为导向的方式来配置 Kubernetes 生态系统中的网关和路由。该 API 提供了如 GatewayClass、Gateway、HTTPRoute 等自定义资源定义(CRD),Envoy Gateway 利用这些资源创建用户友好且一致的配置模型,与 Kubernetes 的原生原则保持一致。

什么是 API Gateway?

API Gateway 是对 API 的全面管理和托管服务。它作为应用程序与后端服务之间的中间层,不仅处理创建、维护、发布、运行和下线等生命周期事件,还承担着更多关键职能。一个完善的 API Gateway 应该提供以下功能来丰富和扩展其基本定义:

  1. 流量控制:API Gateway 应能够处理并控制到后端服务的流量,包括请求路由、负载均衡、熔断机制以及速率限制,以保证后端服务的稳定性和高可用性。
  2. 安全性保障:应具备鉴权、授权和加密功能,能够有效地管理和保护 API 的安全。这涉及到身份验证机制、API 密钥管理、OAuth、JWT、mTLS 等,以确保只有授权的用户和服务能够访问 API。
  3. 监控和分析:提供实时监控和日志记录功能,能够跟踪 API 的使用情况、性能指标、异常检测和分析流量模式,从而优化 API 的性能和响应能力。
  4. 变更管理:支持对 API 变更进行管理,包括版本控制和渐进式部署(如蓝绿部署或金丝雀发布),以无缝过渡新版本且最小化对最终用户的影响。
  5. 请求和响应的转换:允许对传入和传出的 API 调用进行转换,比如从 REST 到 GraphQL 的转换,或是添加、删除和修改请求头和响应头。
  6. 跨域资源共享(CORS)支持:管理和控制跨域请求,允许不同域的前端应用安全地调用后端 API。
  7. 配额和计费:为 API 使用设定配额限制,同时支持计费功能,以适用于商业化的 API 提供。
  8. 用户友好的开发者门户:提供一个面向开发者的门户,使得第三方开发者可以轻松地发现、测试和集成 API。
  9. 协议支持:支持各种网络协议,包括 HTTP/HTTPS、WebSocket、gRPC 等,确保与多种客户端和服务的兼容性。
  10. 插件化和扩展性:允许通过插件或中间件来扩展 API Gateway 的功能,使其可以根据业务需求灵活适配各种中间件服务。
  11. 服务治理:集成服务注册和发现机制,以适应微服务架构下服务的动态性。

综上所述,API Gateway 的角色远远超越了简单的 API 生命周期管理。它是实现微服务架构、确保服务安全性、提高运维效率和优化用户体验的关键组件。通过这些广泛的功能,API Gateway 成为现代云原生应用不可或缺的一部分。

Envoy Gateway 架构概览

Envoy Gateway 的架构设计旨在轻量级和简洁。它包括一个动态配置运行作为数据平面的 Envoy 代理的控制平面。这种关注点的分离确保了网关可以随着流量的增长而扩展,而不影响控制平面的效率。

Envoy Gateway 的架构图如下所示。

image
Envoy Gateway 架构图

在这个架构图的核心是 Envoy Gateway,它是 Envoy 代理的执行实例,负责处理从 Kubernetes 集群进出的所有流量。初始启动时,Envoy Gateway 通过配置文件提供静态配置,建立其操作的基本参数。

Envoy Gateway 配置的动态方面由提供者处理,该提供者定义了网关与 Kubernetes 或其他动态配置输入源的交互。资源监视器负责监视 Kubernetes 资源的更改,特别关注与自定义资源定义(CRD)相关的 CRUD 操作。

随着更改的发生,资源转换器介入将这些外部资源转换为 Envoy Gateway 可以理解的形式。这一转换过程进一步由特定于提供者的基础设施管理器促进,后者负责管理与特定云或基础设施提供商相关的资源,塑造中间表示形式的基础设施,这对于网关的功能至关重要。

然后,该中间表示形式转变为 xDS 中间表示形式,作为 Envoy 理解和执行的最终 xDS 配置的先导。xDS 翻译器承担将这种中间表示形式转换为具体的 xDS 配置的角色。

这些配置由 xDS 服务器交付并执行,该服务器作为服务,根据其收到的 xDS 配置,认真管理 Envoy 实例。Envoy 作为实际运行的代理,最终从 xDS 服务器接收这些配置,解释并实现它们以有效管理流量请求。

最终,所有请求经过 Envoy 的处理后被重定向到了 Envoy Gateway 路由的流量的最终目的地,也就是后端服务。

与其他网关的比较

与 Istio 的入口网关或 NGINX Ingress 等其他流行解决方案相比,Envoy Gateway 凭借其与 Kubernetes 的原生集成以及利用 Envoy 全部潜力的专注,而脱颖而出。下图从多方面对比了目前流行的一些开源的 API 网关。

API 网关 支持的认证和授权策略 支持的服务发现组件 支持的协议 控制平面配置分发方法 支持的插件扩展机制 组织隶属
Envoy Gateway OAuth2, JWT, mTLS, OIDC Kubernetes, EDS HTTP, HTTPS, gRPC xDS 基于 Envoy Filter CNCF
Kuma mTLS, JWT Kubernetes, Consul HTTP, HTTPS, gRPC, TCP REST, gRPC 基于 Lua, Go CNCF
NGINX Ingress RBAC Kubernetes HTTP, HTTPS, TCP, UDP Kubernetes CRD 基于 Nginx 模块 N/A
APISIX OAuth2, JWT, Key Auth, Basic Auth, mTLS, OIDC, LDAP, OpenID 等 Kubernetes, DNS, Consul, Nacos, Eureka HTTP, HTTPS, TCP, UDP, WebSocket REST, CLI, Web UI 基于 Lua, Wasm Apache Software Foundation
Kong OAuth2, JWT, Basic Auth, Key Auth Kubernetes, DNS, Consul HTTP, HTTPS, gRPC, WebSocket REST, gRPC, Web UI 基于 Lua N/A
Emissary Basic Auth Kubernetes HTTP, HTTPS, gRPC Kubernetes CRD 基于 Lua, Go CNCF
开源 API 网关对比

快速开始使用 Envoy Gateway

要快速上手 Envoy Gateway,你可以通过以下简化步骤快速搭建一个本地实验环境。首先,启动一个本地 Kubernetes 集群:

minikube start --driver=docker --cpus=2 --memory=2g

接下来,部署 Gateway API CRD 和 Envoy Gateway 本身:

helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.0.1 -n envoy-gateway-system --create-namespace

然后,安装网关配置并部署一个示例应用:

kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.1/quickstart.yaml -n default

为了暴露 LoadBalancer 服务,这里我们使用端口转发作为示例。你也可以选择使用 minikube tunnel 或安装 MetalLB 作为负载均衡器:

export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &

通过以下命令测试你的 Envoy Gateway 是否正常工作:

curl --verbose --header "Host: www.example.com" http://localhost:8888/get

想了解更多详细的安装和配置步骤,请访问 Envoy Gateway 网站。通过这些步骤,你可以快速开始探索 Envoy Gateway 的功能。

总结

Envoy Gateway 不仅优化了云原生时代的七层网关配置,而且为从边缘网关向服务网格过渡提供了一个平滑的道路。由于服务网格的推广面临一些挑战,如对应用的侵入性和运维团队推动问题,边缘网关则更易于被开发团队接受。Envoy Gateway 采用简化的 Kubernetes Gateway API,提高了流量管理和可观测性的能力。此外,Envoy Gateway 到 Istio 的过渡对于已熟悉 Envoy 功能的团队来说,将是一个自信的技术进步,同时还支持从标准的 Kubernetes Gateway API 到 Istio Ingress Gateway 的无缝切换,或者作为一个定制解决方案继续与 Istio 协作。这些特点使得 Envoy Gateway 成为一个在云原生时代值得投资的网关选择。

请继续关注本系列博客的后续部分,我们将深入探讨如何配置和优化 Envoy Gateway,提供实用指南并展示更广泛的实际应用案例。

KubeCon EU 2024 透明度报告解读

2024-05-07 21:11:49

近日 CNCF 发布了 KubeCon EU 2024 的透明度报告,KubeCon + CloudNativeCon Europe 2024 在巴黎举办,这是有史以来最大规模的一次会议,我也有幸能亲临现场参加,巴黎的美景和会议的氛围让我久久难以忘怀。

image
《KubeCon + CloudNativeCon EU 2024 透明度报告》封面

我们见证了开源和云原生社区的力量,以及它如何推动技术的下一个重大转变 —— 人工智能。在这次会议上,CNCF 宣布成立 AI 工作组,并推出了第一版云原生 AI 白皮书,随后有创建了云原生 AI Landscape

增长与多样性

本次活动迎来了超过 12,000 名参与者,大部分来自欧洲(78%),其中 52% 为首次参会者。来自不同地区的参与者都表现出了对云原生技术的热情。我们还看到了业务运营、开发者和架构师等多样化的职能背景,这突显了云原生技术跨领域的广泛应用。

下表来自不同国家的参会人数 Top 10:

国家 参会人数
法国 1,956
德国 1,879
美国 1,733
英国 816
荷兰 797
瑞士 368
西班牙 355
以色列 312
波兰 303
丹麦 293

创新与交流

活动期间,有 331 场会议和 19 场主题演讲,覆盖了人工智能、应用开发、平台工程等多个热门领域。本届 KubeCon 首次举办了面向研究者的海报会话和项目馆导览,帮助参会者更好地了解各个项目。

社区与包容性

KubeCon 致力于支持多样性、公平性和包容性。活动提供的多样性午餐和 Peer Group Mentoring 等活动,为参与者提供了建立联系和互帮互助的平台。(PS. 会场提供的餐饮实在是让我喜欢不了,尤其是茶的味道,还有硬邦邦的面包)

环保与可持续性

在环保和可持续性方面,主办方选择了具有环保意识的会场,并实施了减少食物浪费和回收废物的措施。这体现了 CNCF 对环境保护的承诺。

展望未来

展望未来,我们期待将 KubeCon 的魔力带到全球更多地区。无论是即将到来的 KubeCon + CloudNativeCon China 2024 还是其他地区的活动,我都非常期待与你相见。我也向 KubeCon China 提交了一个 Panel session,如果能够入选,今年 8 月我们将在香港相见。

结论

KubeCon + CloudNativeCon Europe 2024 不仅是技术的盛会,更是社区力量的展示。如你想了解更多细节,请查看我之前关于 KubeCon + CloudNativeCon Europe 的回顾

我们希望这篇透明性报告能帮助你更好地理解活动的影响力,并激励你参与未来的 KubeCon 活动。

电子书:Kubernetes 网络和 Cilium 网络工程师指南

2024-04-29 09:27:49

亲爱的云原生社区的朋友们,我很高兴向大家推荐 Isovalent 最新推出的电子书《Kubernetes 网络和 Cilium 网络工程师指南(英文原版)》。

image
《Kubernetes 网络和 Cilium 网络工程师指南》电子书封面

作为一名资深的云原生倡导者,我深知 Kubernetes 网络对于网络工程师来说是一个巨大的挑战。但是,随着 Kubernetes 在企业中的广泛应用,学习 Kubernetes 网络知识已经变得非常重要和紧迫。这本电子书正是为了帮助网络工程师们克服这些挑战而诞生的。

这本 56 页的电子书由 Isovalent 的 Senior Staff Technical Marketing Engineer Nico Vibert 撰写,内容涵盖了 Kubernetes 网络的方方面面,包括 Cilium 这个事实上的 Kubernetes 网络层。即使你不是网络工程师,相信你也能轻松理解和学习这本书的内容。

这本电子书就像一本使用说明手册,为网络工程师们提供了一个循序渐进的学习路径。从 Kubernetes 网络的基础知识,到 Cilium 的高级功能,再到实际的部署和运维,应有尽有。相信这本书一定会成为网络工程师学习 Kubernetes 网络的必备资料。

根据这本由 Isovalent 推出的电子书《Kubernetes Networking and Cilium: An Instruction Manual for the Network Engineer》的内容,我为大家总结了以下几点。

本书亮点

  1. 全面介绍了 Kubernetes 网络的基础知识,包括容器网络接口 (CNI)、网络模型等,为网络工程师打下坚实的基础。
  2. 深入探讨了 Cilium 这个事实上的 Kubernetes 网络层,详细讲解了它提供的各种功能,如路由、交换、负载均衡、防火墙、监控等。
  3. 系统介绍了如何在 Kubernetes 中配置和管理网络,包括使用 kubectl 命令行工具、应用 YAML 配置文件等。
  4. 重点阐述了 Cilium 的身份感知安全机制,以及如何使用网络策略进行精细化的网络访问控制。
  5. 讲解了 Kubernetes 中的负载均衡机制,包括 ClusterIP、NodePort 和 Ingress 等服务类型。
  6. 探讨了 Kubernetes 集群跨多个集群的联通方案,以及如何实现跨集群的负载均衡和安全策略。

适读人群

这本电子书主要面向 Kubernetes 网络工程师,帮助他们全面掌握 Kubernetes 网络的方方面面知识。即使不是网络工程师,对云原生技术感兴趣的读者也能从中受益,学习 Kubernetes 网络的基础知识。

中文版

如果你想阅读该书的中文版,请访问这里获取。中文版由 Isovalent 的黄力一翻译。

深入解析 Istio CNI:赋能无侵入式流量管理与强化服务网格安全

2024-04-17 18:54:49

本文将深入探讨 Istio CNI 插件的设计理念、实现方式以及如何通过 Ambient Mode 来解决传统模式中存在的安全和权限问题。本文内容包括:

Istio 网络要求与解决方案概览

Istio 服务网格通过 Sidecar 模式实现应用流量的拦截和管理。该模式通过在应用程序 Pod 中注入 Sidecar Proxy 和 init 容器,并使用 iptables 规则来管理网络流量。详细的部署和操作过程请参见 Istio 中的 Sidecar 注入、透明流量劫持及流量路由过程详解。虽然此方法在多数 Kubernetes 平台上有效,但对高权限的依赖在多租户环境中引发了安全方面的担忧。

Istio-init 的局限性

Istio 在其网络配置初期采用了 istio-init 容器来初始化流量拦截规则,这需要容器具有高级权限来修改网络配置,如 IPTables 规则。虽然这种方法实现了对流量的有效管理,但它也显著提高了权限需求并增加了安全风险。根据 Istio 官方文档istio-init 容器默认被注入到 Istio 网格中的 Pod 里,以便将网络流量劫持到 Istio 的 Sidecar 代理。这一过程需要对部署 Pod 的 Service Account 赋予 NET_ADMIN 容器权限,可能与某些组织的安全政策相悖。

Istio CNI 插件

为响应这一挑战,Istio 社区推出了 Istio CNI 插件,该插件避免了对 init 容器的需求,允许直接在 Kubernetes 的网络层面操作,从而降低权限需求并简化部署流程,但是存在 CNI 兼容性问题。

Ambient 模式的引入

Istio 的 Ambient Mode 是一种创新的无 sidecar 方案,它通过 使用 Geneve 隧道 或 Istio CNI 提高网络的灵活性和安全性。

直到最近 Istio 社区才推出适配任意 CNI 的通用的解决方案。此模式解决了与任意 CNI 的兼容性问题,使 Istio 能够在不影响现有网络策略的前提下,更有效地管理服务间的流量。

NET_ADMIN 权限的安全考虑

在 Kubernetes 和 Docker 等容器化环境中,NET_ADMIN 权限允许容器内的进程执行广泛的网络相关操作。这包括修改 iptables 规则、更改网络接口配置、管理 IP 路由表,以及控制网络相关的内核参数。然而,这种权限的使用引发了安全上的考虑,特别是在权限过度和潜在的攻击面方面。

最佳实践包括

Istio CNI 插件的工作原理

Istio CNI 插件是一个二进制文件,作为代理安装在每个节点的文件系统中。以下流程图说明了 Istio CNI 节点代理的工作原理:

image
Istio CNI 插件的工作原理

解析 Istio Ambient Mode 与 Kubernetes CNI 的冲突

Istio 的 Ambient Mode 是为了适配所有 CNI 而设计的一种模式,它通过 ztunnel 来透明地处理 Pod 内的流量转发,而不影响现有的 CNI 配置。这种模式下,Ambient Mode 通过 ztunnel 管理流量,使其流经 Istio 服务网格,而标准的 CNI 则侧重于为 Pod 提供标准化的网络接入。

CNI 的主要职责是解决 Kubernetes Pod 之间的网络连通性,例如分配 IP 地址和转发数据包。相比之下,Ambient Mode 需要将流量导入 ztunnel,这与 CNI 的网络配置可能存在不兼容,主要问题包括:

为解决这些问题,可以通过将 ztunnel 运行在与 Pod 相同的用户空间中,避免与 CNI 修改过的内核空间的冲突。这样,Pod 可以直接连接到 ztunnel,绕过 CNI 的影响。

下面的时序图描述了 Ambient mode 下的流程:

image
Amibent mode 的运行流程

解决 Istio Ambient Mode 和 Kubernetes CNI 的冲突

为缓解这些冲突,Istio 的 Ambient Mode 避免了对 CNI 修改过的内核空间的依赖:

这些措施帮助 Istio 的 Ambient Mode 在不干扰现有 CNI 插件的情况下,有效管理服务间流量。

Istio Ambient Mode 的流量管理优化

Ambient Mode 在 Istio 中通过 node-local Ztunnel 实现了改进的流量转发机制,允许在 Pod 的网络命名空间中设置侦听套接字,实现从服务网格内部的加密(mTLS)和明文流量的有效重定向。这种方法不仅提高了流量管理的灵活性,还避免了与现有的 CNI 插件之间的潜在冲突。下面是该模式的具体实现流程:

image
Ambient mode 的实现流程

具体步骤如下:

  1. 侦测标记:Istio CNI 节点代理侦测标记为 istio.io/dataplane-mode=ambient 的 Pod。
  2. 触发 CNI 插件:根据 Pod 事件(新启动或现有 Pod 加入网格)触发 CNI 插件,这一步会触发 Istio CNI 节点代理进行流量重定向配置。
  3. 配置重定向规则:在 Pod 的网络命名空间内配置网络重定向规则,以便拦截并重定向至 node-local ztunnel 代理。
  4. 建立侦听套接字:node-local ztunnel 在 Pod 的网络命名空间中创建侦听套接字,实现流量的重定向。
  5. 流量处理:node-local ztunnel 处理网格内的加密(mTLS)和明文流量,确保数据传输的安全性和高效性。

通过这种方法,Istio Ambient Mode 为 Kubernetes 环境中的服务间流量管理提供了一种更为高效和安全的解决方案。

总结

本文全面解析了 Istio CNI 插件的设计理念、实现方式和优势,特别是 Istio CNI 如何解决了传统 istio-init 方法中存在的权限和安全问题。通过这些创新,Istio 在网络安全和操作简便性上取得了重大进步,为 Kubernetes 环境中实施 Istio 提供了更灵活和高效的方法。

深入解读 CNCF 推出的云原生 AI 白皮书

2024-04-16 12:54:49

2024 年 3 月,在 KubeCon EU 期间,云原生计算基金会(CNCF)发布了首份关于云原生人工智能(CNAI)的详细白皮书。这份报告详尽地探讨了将云原生技术与人工智能融合的当前状态、面临的挑战、以及未来的发展方向。本文将对这份白皮书的核心内容进行深入解读。

什么是云原生 AI?

云原生 AI 指的是利用云原生技术原则来构建和部署人工智能应用和工作负载的方法。这包括利用微服务、容器化、声明式 API 和持续集成/持续部署(CI/CD)等云原生技术来增强 AI 应用的可扩展性、可复用性和可操作性。

下图展示了云原生 AI 的架构,图片根据该白皮书重新绘制。

image
云原生 AI 架构

云原生 AI 与云原生技术之间的关系

云原生技术提供了一个灵活、可扩展的平台,使得开发和运行 AI 应用变得更加高效。通过容器化和微服务架构,开发人员可以快速迭代和部署 AI 模型,同时保证系统的高可用性和可扩展性。Kubernetes 和其他云原生工具提供了必要的支持,例如资源调度、自动扩缩容和服务发现等。

白皮书中给出了两个例子说明云原生 AI 与云原生技术的关系,即在云原生基础架构上运行 AI:

云原生 AI 的挑战

尽管云原生技术为 AI 应用提供了坚实的基础,但在将 AI 工作负载与云原生平台整合时,仍然存在一些挑战。这些挑战包括数据准备的复杂性、模型训练的资源需求、以及在多租户环境中保持模型的安全性和隔离性。此外,云原生环境中的资源管理和调度对于大规模 AI 应用尤其关键,需要进一步优化以支持高效的模型训练和推理。

云原生 AI 的发展路径

白皮书中提出了几条云原生 AI 的发展路径,包括改进资源调度算法以更好地支持 AI 负载、开发新的服务网格技术以提高 AI 应用的性能和安全性,以及通过开源项目和社区合作来推动云原生 AI 技术的创新和标准化。

云原生 AI 技术景观图

云原生 AI 涉及到多种技术,从容器和微服务到服务网格和无服务器计算。Kubernetes 是部署和管理 AI 应用的关键平台,而 Istio、Envoy 等服务网格技术则提供了强大的流量管理和安全功能。此外,Prometheus 和 Grafana 等监控工具对于维护 AI 应用的性能和可靠性至关重要。

下面是白皮书中给出的云原生 AI 景观图。

General Orchestration

Distributed Training

ML Serving

CI/CD - Delivery

Data Science

Workload Observability

AutoML

Governance & Policy

Data Architecture

Vector Databases

Model/LLM Observability

总结

最后,笔者梳理了以下关键观点:

有关详情,请下载 云原生 AI 白皮书

深入解读 CNI:容器网络接口

2024-04-15 13:54:49

在容器化环境中,有效管理网络是至关重要的。容器网络接口(CNI)是一个标准,定义了容器应如何配置网络。本文将深入探讨 CNI 的基础知识,并带你了解 CNI 与 CRI 的关系。

什么是 CNI?

CNI(容器网络接口)规范为容器运行时和网络插件之间提供了一个通用的接口,旨在实现容器网络配置的标准化。

CNI 规范包含以下几个核心组成部分:

CNI 规范通过定义这些核心组成部分,确保了不同的容器运行时和网络插件能够以一致的方式进行交互,实现网络配置的自动化和标准化。

CNI 规范的一些要点
  • CNI 是一个插件化的容器化网络解决方案
  • CNI 插件为可执行文件
  • 单个 CNI 插件的职责是单一的
  • CNI 插件是呈链式调用的
  • CNI 规范为一个容器定义一个 Linux 网络命名空间
  • CNI 的网络定义存储为 JSON 格式
  • 网络定义通过 STDIN 输入流传输到插件,这意味着宿主机上不会存储网络配置文件,其他的配置参数通过环境变量传递给插件

CNI 插件根据操作类型,接收相应的网络配置参数,执行网络配置或清理任务,并返回执行结果。这一流程确保了容器网络的动态配置与容器生命周期的同步。

下图展示了 CNI 包含了众多的网络插件。

image
CNI 插件的种类

根据 CNI 规范,一个 CNI 插件负责以某种方式配置容器的网络接口。插件可分为两大类:

CNI 与 CRI 的关系

CNI 和 CRI(容器运行时接口)是 Kubernetes 中两个关键的接口,它们分别处理容器的网络配置和运行时管理。在 Kubernetes 集群中,CRI 调用 CNI 插件来配置或清理容器的网络,这确保了网络配置的过程与容器的创建和销毁过程紧密协调。

下图直观地展示了 CNI 如何与 CRI 协同运行的:

image
CNI 如何与 CRI 协同运行的
  1. Kubelet 到 CRI:Kubelet 指示 CRI 创建已调度的 Pod 的容器。
  2. CRI 到 Pod:容器运行时在 Pod 中启动容器。
  3. Pod 到 CRI:一旦容器运行,它会向容器运行时发出信号。
  4. CRI 到 Kubelet:容器运行时通知 Kubelet 容器已准备就绪。
  5. Kubelet 到 CNI:容器已启动,Kubelet 调用 CNI 为 Pod 设置网络。
  6. CNI 到 Pod:CNI 为 Pod 配置网络,将其连接到必要的网络接口。
  7. Pod 到 CNI:网络配置完成后,Pod 向 CNI 确认网络设置。
  8. CNI 到 Kubelet:CNI 通知 Kubelet Pod 的网络已准备就绪。
  9. Kubelet 到 Pod:现在 Pod 完全可操作,两个容器均已运行且网络已配置。

下图展示了在 Kubernetes 中为 Pod 设置网络所涉及的详细步骤:

image
在 Kubernetes 中为 Pod 设置网络所涉及的详细步骤
  1. Pod 调度:Kubelet 在节点上调度一个 Pod 运行。
  2. 请求网络设置:已调度的 Pod 请求 Kubelet 进行网络设置。
  3. 调用 CNI:Kubelet 调用 CNI 处理 Pod 的网络设置。
  4. 创建网络命名空间:CNI 为 Pod 创建一个网络命名空间,隔离其网络环境。
  5. 分配 IP 地址:CNI 通过其 IP 地址管理(IPAM)插件为 Pod 分配一个 IP 地址。
  6. 设置网络接口:CNI 在 Pod 的网络命名空间内设置必要的网络接口,将其连接到网络。
  7. 网络设置完成:Pod 通知 Kubelet 其网络设置已完成。
  8. 带有网络运行的 Pod:Pod 现在已经运行,并且其网络已配置,可以与 Kubernetes 集群中的其他 Pod 和服务通信。

CNI 工作流程

容器网络接口(CNI)规范定义了容器如何配置网络,其中包括 ADDCHECKDELETEGCVERSION 五种操作。容器运行时通过调用各种 CNI 插件来执行这些操作,从而实现容器网络的动态管理和更新。

image
CNI 工作流程

为了详细说明序列图中描述的每个步骤,涉及 Kubelet、Pod、CNI 插件(包括接口和链式 CNI 插件)、网络设置和 IP 地址管理(IPAM)之间的交互,让我们深入了解这个过程:

  1. 调度 Pod:Kubelet 安排一个 Pod 在节点上运行。这一步启动了 Kubernetes 集群中 Pod 的生命周期。
  2. 请求网络设置:Pod 向 Kubelet 发出网络设置请求。这个请求触发了为 Pod 配置网络的过程,确保它可以在 Kubernetes 集群内进行通信。
  3. 调用 CNI 插件:Kubelet 调用配置的容器网络接口(CNI)插件。CNI 定义了一个标准化的方式,用于容器管理系统在 Linux 容器中配置网络接口。Kubelet 将必要的信息传递给 CNI 插件,以启动网络设置。
  4. 调用接口插件:CNI 框架调用一个接口 CNI 插件,负责为 Pod 设置主要的网络接口。这个插件可能会创建一个新的网络命名空间、连接一对 veth 或执行其他操作,以确保 Pod 具有所需的网络接口。
  5. 设置网络接口:接口 CNI 插件为 Pod 配置网络接口。这个设置包括分配 IP 地址、设置路由和确保接口准备好通信。
  6. 调用链式插件:在设置网络接口之后,接口 CNI 插件或 CNI 框架调用链式 CNI 插件。这些插件执行额外的网络配置任务,比如设置 IP 伪装、配置入口/出口规则或应用网络策略。
  7. 分配 IP 地址:作为链式过程的一部分,链式 CNI 插件中的一个可能涉及 IP 地址管理(IPAM)。IPAM 插件负责为 Pod 分配一个 IP 地址,确保每个 Pod 在集群或命名空间内具有唯一的 IP。
  8. IP 地址已分配:IPAM 插件分配了一个 IP 地址,并将分配信息返回给调用插件。这些信息通常包括 IP 地址本身、子网掩码和可能的网关。
  9. 应用网络策略:链式 CNI 插件将任何指定的网络策略应用于 Pod 的网络接口。这些策略可以规定允许的入口和出口流量,确保根据集群的配置要求进行网络安全和隔离。
  10. 链式配置完成:一旦所有链式插件完成了它们的任务,Pod 的整体网络配置被认为已完成。CNI 框架或链中的最后一个插件向 Kubelet 发送信号,表明网络设置已完成。
  11. 网络设置完成:Kubelet 收到了 Pod 的网络设置完成的确认。此时,Pod 具有完全配置的网络接口,具有 IP 地址、路由规则和应用的网络策略。
  12. 带有网络运行的 Pod:Pod 现在已经运行,并配置了网络。它可以与 Kubernetes 集群中的其他 Pod 通信,根据网络策略访问外部资源,并执行其指定的功能。

以下是针对 CNI 官方示例中的 ADD 操作、CHECK 操作和 DELETE 操作的示例序列图以及详细说明。通过这些操作,容器运行时与 CNI 插件之间进行交互,实现容器网络配置的动态管理和更新。

ADD 操作示例

以下是 ADD 操作的示例序列图以及详细说明:

image
ADD 操作流程
  1. 容器运行时调用 Portmap 插件:容器运行时通过调用 Portmap 插件执行 ADD 操作,配置容器的端口映射。
  2. Portmap 配置完成:Portmap 插件完成端口映射配置,并将结果返回给容器运行时。
  3. 容器运行时调用 Tuning 插件:容器运行时调用 Tuning 插件执行 ADD 操作,配置容器的网络调优参数。
  4. Tuning 配置完成:Tuning 插件完成网络调优参数配置,并将结果返回给容器运行时。
  5. 容器运行时调用 Bridge 插件:容器运行时调用 Bridge 插件执行 ADD 操作,配置容器的网络接口和 IP 地址。
  6. Bridge 插件调用 Host-local 插件:在完成自身配置之前,Bridge 插件调用 Host-local 插件执行 ADD 操作,配置容器的 IP 地址。
  7. IPAM 配置完成:Host-local 插件作为 IP 地址管理(IPAM)的授权方,完成 IP 地址分配,并将结果返回给 Bridge 插件。
  8. Bridge 配置完成:Bridge 插件完成网络接口和 IP 地址配置,并将结果返回给容器运行时。

这些操作确保了在容器启动时,其所需的网络配置能够按照预期进行设置,包括端口映射、网络调优和 IP 地址分配等。

CHECK 操作示例

以下是 CHECK 操作的示例序列图以及详细说明:

image
CHECK 操作流程
  1. 容器运行时调用 Bridge 插件进行检查:容器运行时通过调用 Bridge 插件执行 CHECK 操作,检查容器的网络配置是否符合预期。
  2. Bridge 插件调用 Host-local 插件:Bridge 插件调用 Host-local 插件执行 CHECK 操作,检查 IP 地址分配是否正常。
  3. 返回无错误:Host-local 插件检查 IP 地址分配无异常,并返回无错误给 Bridge 插件。
  4. 返回 0 返回码:Bridge 插件检查网络配置无异常,并返回 0 返回码给容器运行时。
  5. 容器运行时调用 Tuning 插件进行检查:容器运行时调用 Tuning 插件执行 CHECK 操作,检查网络调优参数是否符合预期。
  6. 操作成功:Tuning 插件检查网络调优参数无异常,返回操作成功给容器运行时。

这些操作确保了在容器运行期间,其网络配置和网络调优参数能够按照预期进行检查和验证,以确保网络配置的一致性和正确性。

DELETE 操作示例

以下是 DELETE 操作的示例序列图以及详细说明:

image
DELETE 操作流程
  1. 容器运行时调用 Portmap 插件:容器运行时通过调用 Portmap 插件执行 DELETE 操作,删除容器的端口映射配置。
  2. Portmap 删除完成:Portmap 插件完成端口映射的删除,并将结果返回给容器运行时。
  3. 容器运行时调用 Tuning 插件:容器运行时调用 Tuning 插件执行 DELETE 操作,删除容器的网络调优参数配置。
  4. Tuning 删除完成:Tuning 插件完成网络调优参数的删除,并将结果返回给容器运行时。
  5. 容器运行时调用 Bridge 插件:容器运行时调用 Bridge 插件执行 DELETE 操作,删除容器的网络接口和 IP 地址配置。
  6. Bridge 插件调用 Host-local 插件:在完成自身删除之前,Bridge 插件调用 Host-local 插件执行 DELETE 操作,删除容器的 IP 地址分配。
  7. IPAM 删除完成:Host-local 插件完成 IP 地址分配的删除,并将结果返回给 Bridge 插件。
  8. Bridge 删除完成:Bridge 插件完成网络接口和 IP 地址的删除,并将结果返回给容器运行时。

这些操作确保了在容器停止运行时,其所需的网络配置能够被正确清理和移除,以确保网络资源的有效释放和管理。

通过对 ADD、CHECK 和 DELETE 操作的示例序列图及详细说明,可以清晰地了解容器运行时与 CNI 插件之间的交互过程,以及如何实现容器网络配置的动态管理和更新。

总结

CNI 为容器化环境中的网络管理提供了一种标准化的接口,通过与 CRI 的配合,确保了 Kubernetes 集群中容器的网络配置高效且一致。通过深入理解 CNI,开发者和系统管理员可以更好地管理和优化其容器网络。

参考

TVS:Istio 和 Envoy CVE 扫描解决方案

2024-03-29 12:54:49

本文将介绍 Tetrate 新推出的工具——Tetrate Vulnerability Scanner (TVS),一款针对 Istio 和 Envoy 定制的 CVE 扫描器。在深入了解 TVS 的具体功能前,我们先简要回顾 CVE 的概念及其在软件安全性中的核心作用。

CVE 概览

CVE,即通用漏洞和暴露,是一个公开的漏洞数据库,由 MITRE 公司负责维护。它旨在为软件中的漏洞提供一个标准化的命名体系,包含了漏洞的标识号、详细描述及参考链接。虽然 CVE 本身不提供漏洞的严重性评分,但它为网络安全专家、开发人员和企业提供了一个获取关键安全信息的重要平台。每个 CVE 记录的唯一标识号便于追踪漏洞相关信息,诸如受影响的软件系统、修复措施等。例如,2021 年著名的 Log4j 漏洞(CVE-2021-44228)由于影响广泛,严重程度评级为 10。

CVE 的实用场景

一个典型的 CVE 使用案例是将 CVE 扫描功能集成到 CI/CD 管道中,以自动化安全测试,从而阻止带有已知漏洞的代码合并到代码库并接收警报。这一过程有助于确保应用程序不会使用带有漏洞的包或库,从而提高了软件的安全性。

例如 Github 将 CVE 检测和处理作为供应链安全的关键一环,如果你在 Github 上托管了开源项目,并开启了 Dependabot,每当你的 PR 或 commit 存在漏洞时,你就可能收到类似下面的 CVE 通知:jQuery Cross Site Scripting vulnerability。收到通知后你可以选择容忍该漏洞或者应用 patch。下图展示了 CVE 的处理流程。

image
CVE 的处理流程

TVS 功能介绍

Istio 经常在其官网发布 CVE 通知,例如 ISTIO-SECURITY-2024-001。以前,你必须手动跟踪这些通知,但现在你可以使用 TVS 自动执行 CVE 扫描任务,从而显着减少安全团队的工作量。

目前 TVS 仅提供命令行工具,未来将作为服务集成到 TIS 中。下图展示了 TVS 运行结果。

image
TVS CLI

下图说明了 TVS 的工作流程。

image
TVS 的工作流程示意图
  1. 在 Istio 容器安装后开始。
  2. 收集安装的 Istio 容器的 SHA 摘要。
  3. 将摘要发送到 Tetrate 的 API。
  4. API 检测是否存在 CVE。
    • 如果检测到 CVE,记录 SHA 摘要但不包含任何个人信息,并通知用户。
    • 如果未检测到 CVE,则不需要采取任何行动。
  5. 用户收到通知后,应用补丁或缓解措施。
  6. 流程结束。

所有人都可以免费下载和使用 TVS,不过在执行 CVE 扫描之前你需要先注册,详见 TIS 文档

供应链安全建议

报告指出,现在即使最流行的容器最新版本也有数百个 CVE,下面是为了保证的一些建议:

TVS 的独特价值

TVS 通过其命令行工具提供简便的 CVE 扫描操作,未来还计划在 Kubernetes 和 Tetrate Istio Subscription (TIS) 中集成,以进一步简化 Istio 和 Envoy 的 CVE 管理过程。TIS 提供自 Istio 发布起 14 个月内的 CVE 补丁和向后兼容支持,帮助用户及时获得安全更新,同时保持系统的稳定运行。

TVS 为所有用户免费开放下载使用,使用前需进行简单的注册。更多信息请参阅 TIS 文档

通过采纳 TVS 这一自动化的 CVE 扫描工具,企业能够更有效地识别和处理 Istio 及 Envoy 中的安全漏洞,提升基础设施的安全性,同时减轻安全团队的负担,推动安全管理流程的高效运作。

KubeCon EU 2024 巴黎见闻与回顾

2024-03-27 16:54:49

上周我在巴黎参加了 KubeCon EU 2024,这也是我第一次参加中国以外的 KubeCon。本次大会可谓盛况空前,据说有 1.2 万人参加了会议。本文将为你分享我对本次 KubeCon 的一些观察,主要着重在我关注的服务网格与云原生基础架构领域。

image
Istio Contributor 在 KubeCon EU Istio 展台

Istio、Cilium 及服务网格

Istio 和 Service Mesh 成为了热门讨论的话题,集中展示了在云原生生态系统中这两项技术的最新进展和应用。本次大会涵盖了从基础设施优化、数据本地化、分布式追踪到多集群部署等多个领域,反映了 Service Mesh 技术在实际应用中的广泛关注和持续创新。

数据本地化和全局请求路由

Pigment 的 Arthur Busser 和 Baudouin Herlicq 分享了如何利用 Kubernetes 和 Istio 实现数据本地化的需求。他们介绍了利用 Istio 基于自定义头部进行请求路由的方法,这对于满足如 GDPR 和 CCPA 等法规的数据驻留要求至关重要。

分布式跟踪和可观测性增强

ThousandEyes (part of Cisco) 的 Chris Detsicas 探讨了如何配置 Istio 以使用 OpenTelemetry 实现有效的分布式跟踪,这为微服务生态系统提供了宝贵的可见性,有助于问题诊断和性能优化。

多集群部署和流量管理

China Mobile 的 Haiwen Zhang 和 Yongxi Zhang 介绍了一个简化 Istio 多集群部署的新方法,该方法使用一个全局唯一的 Istio 控制平面,通过主集群的 Apiserver 实现全局服务发现,自动连接多个集群的容器网络,为 Pod 提供直接网络连接。特别强调了 Kosmos 项目,它提供了一种新的解决方案,以简化多集群环境下的服务网格部署和管理。

Google 的 Ameer Abbas 和 John Howard 探讨了如何在基础设施可靠性为 99.9% 的情况下构建出 99.99% 可靠性的服务,并提出了一系列应用架构原型(Archetypes),这些原型可以帮助设计和实现高可靠性的多集群应用程序。

安全和零信任架构

多个议题,如 Microsoft 的 Niranjan Shankar 所介绍的,聚焦于在生产环境中加固 Istio 的重要性和方法。他讨论了利用 Istio 与网络策略、第三方 Kubernetes 工具和云提供的安全服务相结合,构建零信任和深层防御架构的步骤和策略。

Ambient Mesh 的基础设施兼容性及未来

Benjamin Leggett 和 Yuval Kohavi 引入了一种创新的方法,使 Istio 的 Amibent mode 能够支持任意 Kubernetes CNI,详见 Istio 博客。这一进步解决了 Ambient mesh 中 CNI 支持有限的问题,无需重启应用程序 Pod 即可将其纳入 Ambient mode,这对于简化操作和降低基础设施成本具有重要意义。

Istio 社区宣布在即将到来的 Istio 1.22 版本,Ambient 模式将成为 beta,详见 CNCF 博客。多个演讲和讨论聚焦于 Istio Ambient Mesh 的未来,特别是其简化工作负载操作和降低基础设施成本的潜力。Istio Ambient Mesh 的介绍预示了服务网格技术的一个新方向,即无 sidecar 的数据平面架构,提供了更高的性能和更低的资源消耗。

Sidecar-less 服务网格的革新

在 KubeCon EU 2024 上,关于 Sidecar 的讨论主要集中在评估和比较使用 Sidecar 与无 Sidecar(如 Istio 的 Ambient Mesh)服务网格模式的优缺点。特别是 Christian Posta 对 Cilium 和 Istio 在无 sidecar 服务网格实现方面的设计决策和权衡进行了深入分析,突出了这种模式在提高性能、降低资源消耗和简化运维操作方面的潜力。通过分析纽约时报从 Istio 过渡到 Cilium 的案例,进一步证明了无 sidecar 模式在处理复杂、多区域服务网格时的有效性,同时指出了在这一转变过程中的挑战和实施考虑。这些讨论预示着服务网格技术未来可能朝向更加灵活和高效的方向发展,其中无 Sidecar 架构可能成为优化云原生应用性能和资源使用的关键策略。

Cilium 与服务网格的交集

Cilium 在 KubeCon EU 2024 上被广泛讨论,作为一种基于 eBPF 的技术,Cilium 不仅被看作是一个高效的容器网络接口(CNI),而且还展示了其在服务网格领域的强大潜力。通过 Isovalent 和其他组织的演讲,Cilium 被展示为一种能够提供连接、观测和保障服务网格安全的先进解决方案。特别是 Cilium 的无 Sidecar 服务网格实现方式被认为是未来方向,其利用 eBPF 技术在不增加传统 Sidecar 代理负担的情况下实现了微服务的安全通信和精细流量管理。此外,Cilium 在服务网格之外的扩展能力,例如在多云网络和负载平衡方面的应用,凸显了其作为云原生生态系统基础设施核心组件的地位。Cilium 的这些讨论和案例研究证明了其在推动服务网格和云原生技术创新方面的重要作用。

云原生趋势

当前云原生领域的几个主要趋势:

  1. 可持续性和环保意识的增强:例如,Deutsche Bahn 将开发者引入其基础设施绿化过程,强调了在设计和运营云原生解决方案时,越来越多的公司开始考虑环境因素。这反映了一个趋势,即企业在追求技术进步的同时,也在努力减少对环境的影响,通过绿色计算和能效优化来实现可持续的技术生态。

  2. 人工智能与云原生技术的融合:人工智能(AI)正在成为 Kubernetes 和云原生生态系统面临的下一个主要挑战。Nvidia 关于 AI 策略的讨论、CNCF 对 AI 在云原生未来中标准化工作的推动,以及各种关于 AI 和机器学习(ML)集成的工具和平台的更新,都突显了这一点。这一趋势表明,将 AI 和 ML 无缝集成到云原生架构中,不仅可以加速应用开发和部署,还能够提供更加智能和自动化的操作能力。同时 CNCF 还宣布成立 AI WG,并发布了人工智能白皮书

  3. WebAssembly(Wasm)的兴起:Cosmonic 对最新 Wasm 标准的支持,以及 Fermyon 将其开源 Wasm 平台 SpinKube 捐赠给 CNCF,显示了 WebAssembly 在云原生应用开发中日益增长的重要性。Wasm 提供了一种高效、安全的方式来运行在浏览器外的客户端和服务器端代码,这对于构建跨平台、高性能的云原生应用尤为重要。

  4. 云原生观测性的强化:例如,New Relic 在其可观测性平台中添加了原生 Kubernetes 支持,凸显了对云原生应用的监控、日志记录和性能分析需求的增加。随着云原生架构的复杂性增加,企业需要更加强大的工具来保持系统的透明度和健康,从而优化性能和可靠性。

  5. 云原生社区的协作和开源精神的强化:CNCF 成立最终用户技术咨询委员会、Red Hat 与 Docker 合作开发 Testcontainers Cloud 框架等举措,反映了云原生社区致力于促进协作和分享的文化。这种开放的协作精神不仅加速了新技术的发展和采纳,也为云原生生态系统的健康成长提供了坚实的基础。

这些趋势共同描绘了一个多元化、持续创新且日益成熟的云原生技术景观,其中可持续性、AI/ML 集成、WebAssembly、加强的可观测性和社区协作是推动这一领域前进的关键因素。

总结

KubeCon EU 2024 的见闻为我们揭示了云原生技术领域的多个重要进展和未来方向。从服务网格的持续创新到云原生生态系统对环境可持续性的关注,再到人工智能与机器学习技术的深度整合,以及 WebAssembly 在应用开发中的日益重要性,这些趋势共同构成了当前云原生技术的前沿。

特别值得注意的是,Istio 和 Cilium 在服务网格领域的最新动态,展现了无 Sidecar 架构的潜力以及 eBPF 技术在提升性能、安全性和可观测性方面的作用。这些进展不仅为开发者提供了更为高效和灵活的工具,也为云原生应用的设计和运营提出了新的思路。

同时,云原生社区的持续发展和对开源精神的坚持,为技术创新和知识共享提供了坚实的基础。通过强化观测性、推动环境可持续性和促进技术标准化,云原生生态正展现出其深厚的发展潜力和广阔的应用前景。

作为一名观察者和参与者,我深感云原生技术的快速发展给我们带来了前所未有的机遇和挑战。未来,随着技术的不断演进和社区的共同努力,我们有理由相信,云原生技术将在推动数字化转型和创造更加智能、可持续的技术世界方面发挥更大的作用。让我们拭目以待,并积极参与这一令人兴奋的技术旅程。

ICA 认证:Istio 技能认证的最新变化和考试准备指南

2024-03-07 11:27:49

ICA 认证的变化和提醒

即将发生的政策变更:请注意,ICA 认证期限政策将于 2024 年 4 月 1 日 00:00UTC 发生变更。在此日期或之后获得的认证将于满足计划认证要求(包括通过考试)之日起 24 个月后到期。我们鼓励任何有兴趣并准备好的人在政策变更之前安排并参加考试。请在此处查看更多详细信息。

当前的认证有效期是 3 年,4 月 1 日之后通过的认证有效期是 2 年。

Tetrate Academy 背景

Tetrate 运营的 Tetrate Academy 已经有好几年时间,期间推出了 Istio 基础教程、Envoy 基础教程和 CIAT 认证考试,一共有 13000 多人学习了 Tetrate Academy 的课程。去年 9 月 Tetrate 将 CIAT 贡献给了 CNCF,改名为 ICA 考试,至 11 月该认证考试正式上线。

ICA 的考试内容(来自 Linux Foundation)

ICA 的考试内容(来自 Linux Foundation

考试背景

建议与提醒

参考链接

维持请求的透明度:在 Istio 中保留客户端请求的源 IP

2024-01-29 11:27:49

本博文解析了在 Istio 服务网格中服务端获取客户端源 IP 的挑战,并提供了解决方案。将探讨以下问题:

源 IP 保留的重要性

保留客户端源 IP 的主要理由包括:

保留源 IP 的含义

保留源 IP 指的是在请求从客户端发出、经过负载均衡器或反向代理后,避免真实的客户端源 IP 被替换的情况。

以下是源 IP 地址丢失的流程示例:

image
源 IP 地址丢失的流程

上面图只是最常见的一种情况。本文考虑到以下几种情况:

  1. 南北向流量:客户端通过负载均衡器(网关)访问服务端
    1. 只有一层网关
    2. 两层或两层以上网关
  2. 东西向流量:网格内部的服务间访问
  3. 协议:HTTP 和 TCP

如何确认客户端源 IP?

在 Istio 服务网格中,Envoy 代理通常会将客户端 IP 添加到 HTTP 请求的 “X-Forwarded-For” 头部中。以下是确认客户端 IP 的步骤:

  1. 检查 x-forwarded-for 头部:包含请求路径上各代理的 IP 地址。
  2. 选择最后一个 IP:通常,最后一个 IP 是最接近服务器的客户端 IP。
  3. 验证 IP 的可信性:检查代理服务器的信任度。
  4. 使用 x-envoy-external-address:Envoy 可以设置此头部,包含客户端真实 IP。

详情请见 Envoy 文档中对 x-forwarded-for 标头的说明。对于 TCP/IP 连接,可以通过协议字段解析客户端 IP。

测试环境

GKE

Istio

CNI

我们使用了 Cilium CNI,但是没有开启无 kube-proxy 模式。

Node

节点名称 内部 IP 备注
gke-cluster1-default-pool-5e4152ba-t5h3 10.128.0.53
gke-cluster1-default-pool-5e4152ba-ubc9 10.128.0.52
gke-cluster1-default-pool-5e4152ba-yzbg 10.128.0.54 Ingress Gateway Pod 所在节点

执行测试的本地客户端电脑的公网 IP:123.120.247.15

部署测试示例

下图展示了测试方式:

image
测试方式

首先参考 Istio 文档部署 Istio,然后为 default 命名空间开启 sidecar 自动注入:

kubectl label namespace default istio-injection=enabled

在 Istio 中部署 echo-server 应用测试。echo-server 是一个基于 Nginx 的服务器,用于回显客户端发送的请求信息,例如请求头、客户端地址、请求方法等。

kubectl create deployment echo-server --image=registry.k8s.io/echoserver:1.4
kubectl expose deployment echo-server --name=clusterip --port=80 --target-port=8080

创建 Ingress Gateway:

cat>config.yaml<<EOF
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: clusterip-gateway
spec:
  selector:
    istio: ingressgateway # 根据你的环境选择适当的 selector
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "clusterip.jimmysong.io" # 替换成你想要使用的主机名
---
apiVersion:  networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: clusterip-virtualservice
spec:
  hosts:
    - "clusterip.jimmysong.io" # 替换成与 Gateway 中相同的主机名
  gateways:
    - clusterip-gateway # 这里使用 Gateway 的名称
  http:
    - route:
        - destination:
            host: clusterip.default.svc.cluster.local # 替换成你的 Service 的实际主机名
            port:
              number: 80 # Service 的端口
EOF
kubectl apply -f config.yaml

查看 Ingress Gateway 中的 Envoy 日志:

kubectl logs -f deployment/istio-ingressgateway -n istio-system

查看 Sleep Pod 中的 Envoy 日志:

kubectl logs -f deployment/sleep -n default -c istio-proxy

查看 Source IP App 中的 Envoy 日志:

kubectl logs -f deployment/echo-server -n default -c istio-proxy

获取网关公网 IP:

export GATEWAY_IP=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

在本地使用 curl 测试:

curl -H "Host: clusterip.jimmysong.io" $GATEWAY_IP

资源 IP

当部署好测试应用后,你需要获取与以下资源的 IP 地址。在接下来的实验环节中将会用到。

Pod

下面是初始状况下的 Pod IP,随着对 Deployment 的补丁,Pod 会重建,名称和 IP 地址都会变。

Pod 名称 Pod IP
echo-server-6d9f5d97d7-fznrq 10.32.1.205
sleep-9454cc476-2dskx 10.32.3.202
istio-ingressgateway-6c96bdcd74-zh46d 10.32.1.221

Service

Service 名称 Cluster IP External IP
clusterip 10.36.8.86 -
sleep 10.36.14.12 -
istio-ingressgateway 10.36.4.127 35.188.212.88

南北向流量

我们首先考虑客户端位于 Kubernetes 集群外,通过负载均衡器来访问集群内部服务的情况。

测试 1:Cluster 流量策略、iptables 流量劫持

这是通过以上步骤部署完测试应用后的默认情况,也是大家遇到的所谓的源 IP 地址丢失的情况。

curl 测试:

curl -H "Host: clusterip.jimmysong.io" $GATEWAY_IP
查看结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CLIENT VALUES:
client_address=127.0.0.6
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://clusterip.jimmysong.io:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=clusterip.jimmysong.io
user-agent=curl/8.4.0
x-b3-parentspanid=03c124c5f910001a
x-b3-sampled=1
x-b3-spanid=103dc912ec14f3b4
x-b3-traceid=140ffa034822077f03c124c5f910001a
x-envoy-attempt-count=1
x-envoy-internal=true
x-forwarded-client-cert=By=spiffe://cluster.local/ns/default/sa/default;Hash=79253e34e1c28d389e9bfb1a62ffe8944b2c3c369b46bf4a9faf055b55dedb7f;Subject="";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
x-forwarded-for=10.128.0.54
x-forwarded-proto=http
x-request-id=b3c05e22-594e-98da-ab23-da711a8f53ec
BODY:
-no body in request-

你只需要关注 client_addressx-forwarded-for 这两个结果即可。下文的 curl 测试结果中将省略其他信息。

说明

该结果中字段的含义:

  • client_address:通过解析 TCP/IP 协议而获取的客户端 IP 地址,在 Envoy 中称为 remote address。
  • x-forwarded-forx-forwarded-for (XFF) 是一个标准的代理头部,用于指示请求在从客户端到服务器的过程中经过的 IP 地址。一个合规的代理会在代理请求之前将最近客户端的 IP 地址添加到 XFF 列表中。详见 Envoy 文档

从测试结果中我们可以看出,源 IP 地址变成了 Ingress Gateway Pod 所在节点的 IP 地址(10.128.0.54)。

下图展示是两个 Pod 中的数据包流量路径。

image
两个 Pod 中的数据包流量路径

对于这种情况,要想保留源 IP 其实很简单,而且也是 Kubernetes 提供的标准选项。

源 IP 地址是如何丢失的?

下图展示客户端的源 IP 是如何在请求过程中丢失的。

image
客户端的源 IP 是如何在请求过程中丢失的

因为负载均衡器将数据包发送到 Kubernetes 集群中的任意节点,在此过程中会进行 SNAT,导致最终发送到 Server Pod 中的客户端源 IP 丢失。

如何保留客户端源 IP

你可以通过设置 service 中的 externalTrafficPolicy 字段为 Local 控制负载均衡器保留源 IP。

externalTrafficPolicy

externalTrafficPolicy 是一个标准 Service 选项,用于定义传入 Kubernetes 节点的流量是否进行负载均衡以及如何进行负载均衡。Cluster 是默认策略,但 Local 通常用于保留传入集群节点的流量的来源 IP。Local 会在集群节点上有效停用负载均衡,以使本地 Pod 接收的流量看到原始来源 IP 地址。

image
externalTrafficPolicy

也就是说将 externalTrafficPolicy 设置为 Local 就可以让数据包绕过节点上的 kube-proxy,而直达目标 Pod。但是大多数人在 Kubernetes 中创建 Service 时都没有设置 externalTrafficPolicy,所以使用了默认的 Cluster 策略。

既然 Service 采用 Local 外部流量策略可以保留客户端的源 IP 地址,那为什么 Kubernetes 不默认采用呢?

说明
通过 Local 模式暴露服务以获取客户端源 IP 是一种对可靠性的妥协,如果大家有更好的方案欢迎推荐给我。

Kubernetes 默认将 Service 的 externalTrafficPolicy 设置为 Cluster 而非 Local,主要是基于以下考虑:

  1. 负载均衡:确保流量在所有节点之间平均分配,避免单个节点过载。
  2. 高可用性:允许流量被集群中任何节点接收,提高服务的可用性。
  3. 简化配置Cluster 模式降低了网络配置的复杂性。
  4. 性能优化:避免由于保留客户端源 IP 而引起的潜在性能问题。
  5. 通用性:兼容多种网络环境和集群配置,适应更广泛的使用场景。

测试 2:Local 流量策略、iptables 流量劫持

将 Ingress Gateway Service 设置为 Local 外部流量策略:

kubectl patch svc istio-ingressgateway -p '{"spec":{"externalTrafficPolicy":"Local"}}' -n istio-system

Curl 测试:

curl -H "Host: clusterip.jimmysong.io" $GATEWAY_IP
查看结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CLIENT VALUES:
client_address=127.0.0.6
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://clusterip.jimmysong.io:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=clusterip.jimmysong.io
user-agent=curl/8.4.0
x-b3-parentspanid=060c393adb561603
x-b3-sampled=1
x-b3-spanid=8df3e10078cc826b
x-b3-traceid=cf26040ae9536702060c393adb561603
x-envoy-attempt-count=1
x-envoy-external-address=123.120.247.15
x-forwarded-client-cert=By=spiffe://cluster.local/ns/default/sa/default;Hash=79253e34e1c28d389e9bfb1a62ffe8944b2c3c369b46bf4a9faf055b55dedb7f;Subject="";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
x-forwarded-for=123.120.247.15
x-forwarded-proto=http
x-request-id=35bc2123-0971-9a9c-84c1-2aeee233a268
BODY:
-no body in request-

通过 Envoy 日志可以得出现在的数据包路径:

image
数据包路径 1

客户端源 IP 被正确识别为 123.120.247.15

东西向流量

在 Istio 默认配置的情况下,对于东西向流量,服务端也无法获取正确的客户端源 IP。

测试 3:Local 流量策略、tproxy 流量劫持

将 Source IP App 中的流量拦截方式从 iptables 修改为 tproxy

kubectl patch deployment -n default echo-server -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}'

注意:此时 Source IP App 的 Pod 将会重建,新的 Pod 名称是 echo-server-686d564647-r7nlq,IP 地址是 10.32.1.140。

Curl 测试:

kubectl exec -it deployment/sleep -it -- curl clusterip
查看结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CLIENT VALUES:
client_address=10.32.3.202
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://clusterip:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=clusterip
user-agent=curl/8.5.0
x-b3-parentspanid=3c07f3b87cc547dd
x-b3-sampled=1
x-b3-spanid=97844ebdde748bfc
x-b3-traceid=90f57b0fb260dfbf3c07f3b87cc547dd
x-envoy-attempt-count=1
x-forwarded-client-cert=By=spiffe://cluster.local/ns/default/sa/default;Hash=25af59fcf9fbe745eb75a318c47d55059d75914632d2536a43a80d342eaed27c;Subject="";URI=spiffe://cluster.local/ns/default/sa/sleep
x-forwarded-proto=http
x-request-id=e9b27bde-3cf6-9d8b-8f23-1cb0fa35d405
BODY:
-no body in request-

下图展示了数据包路径:

image
数据包路径 2

客户端 IP 被正确识别为 10.32.3.202

测试 4:Local 流量策略、iptables 流量劫持

将 Source IP App 中的流量拦截方式恢复为 redirect:

kubectl patch deployment -n default echo-server -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"REDIRECT"}}}}}'

注意:此时 Source IP App 的 Pod 将会重建,新的 Pod 名称是 echo-server-6d9f5d97d7-bgpk6,IP 地址是 10.32.1.123。

Curl 测试:

kubectl exec -it deployment/sleep -it -- curl clusterip
查看结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CLIENT VALUES:
client_address=127.0.0.6
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://clusterip:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=clusterip
user-agent=curl/8.5.0
x-b3-parentspanid=6123380e58ca0ce7
x-b3-sampled=1
x-b3-spanid=633848c0065ec91e
x-b3-traceid=dbcda8b3673e70a46123380e58ca0ce7
x-envoy-attempt-count=1
x-forwarded-client-cert=By=spiffe://cluster.local/ns/default/sa/default;Hash=25af59fcf9fbe745eb75a318c47d55059d75914632d2536a43a80d342eaed27c;Subject="";URI=spiffe://cluster.local/ns/default/sa/sleep
x-forwarded-proto=http
x-request-id=b05e07e1-08ba-9449-90a9-a4a98277a8c0
BODY:
-no body in request-

下图展示了数据包路径:

image
数据包路径 3

客户端源 IP 被识别为 127.0.0.6

单层代理场景总结

在单层代理的情况下,只需要将 Ingress Gateway 的 Service 的 externalTrafficPolicy 设置为 Local 即可保留客户端源 IP。将目标服务的流量拦截模式修改为 TPROXY 即可以保留东西向请求中的源 IP。

多层代理

如果流量在进入 Istio Mesh 前已经经过的多层代理转发,每次流量经过代理时,代理解析 HTTP 流量并将其自身的 IP 地址追加到 x-forwarded-for 标头中。那么可以使用 numTrustedProxies 配置您信任的代理跳数,请参考 Envoy 文档 了解如何确定 X-Forwarded-For 标头和受信任的客户端地址。

实际上我们很难确定流量在到达 Istio Mesh 时究竟经过了几层代理,但你可以根据 x-forwarded-for 标头了解流量的转发路径。

下图展示了 Envoy 如何根据 x-forwarded-for 标头和 xff_num_trusted_hops(对应 Istio 中的 numTrustedProxies 配置)来确认源 IP 的流程。详见 Envoy 文档

image
多层代理

执行下面的命令为入口网关开启受信代理数量配置:

kubectl patch deployment istio-ingressgateway -n istio-system -p '{"spec":{"template":{"metadata":{"annotations":{"proxy.istio.io/config":"{\"gatewayTopology\":{\"numTrustedProxies\": 2,\"forwardClientCertDetails\":\"SANITIZE_SET\"}}"}}}}}'

当 Istio Gateway 收到这个请求时,它将 X-Envoy-External-Address 头设置为您 curl 命令中 X-Forwarded-For 头中的倒数第二个地址(numTrustedProxies: 2)。根据 Istio 的文档,Gateway 在将其转发到服务端负载之前,会将自己的 IP 附加到 X-Forwarded-For 头中。但实际情况是标头中只有客户端源 IP 和 External Gateway Pod IP。

你可以执行下面的命令取消这个补丁:

kubectl patch deployment istio-ingressgateway -n istio-system -p '{"spec":{"template":{"metadata":{"annotations":{"proxy.istio.io/config":"{}"}}}}}'

TCP 流量

上文所说的使用标头获取客户端源 IP 的方式只适用于 L7 网络,对于 L4 网络的 TCP 流量可以使用 Proxy 协议。

Proxy 协议是一种网络协议,它在 TCP 连接的起始处添加了一个协议头部,用于传递连接过程中的一些元数据,如客户端的真实 IP 地址和端口号。这对于在负载均衡器(LB)后部署的应用程序非常有用,因为负载均衡器通常会更改客户端的原始 IP 地址成 LB 的地址,导致服务端无法知晓客户端的真实 IP。很多代理软件都支持 Proxy Protocol,比如 Envoy 和 HAProxy、NGINX 等。

你可以使用下面的命令为 Ingress Gateway 打上补丁,以支持 Proxy 协议:

kubectl patch deployment istio-ingressgateway -n istio-system -p '{"spec":{"template":{"metadata":{"annotations":{"proxy.istio.io/config":"{\\"gatewayTopology\\":{\\"proxyProtocol\\":{}}}"}}}}}'

注意:不是所有的公有云中的 Kubernetes 中 LoadBalancer 类型的 Service 创建的的负载均衡器都支持该配置。比如 GKE 中就不支持。在 AWS NLB 中开启 Proxy 协议请参考该博客

Envoy 并不建议使用 Proxy 协议,因为它:

关于 Envoy 对 Proxy 协议的支持请参考该文档

应用场景示例

下面是常见的两个源 IP 地址的应用场景。

基于源 IP 地址的访问控制

在 Istio 的入口网关配置基于源 IP 的访问控制策略。这通过设置入口网关的授权策略,根据源 IP 地址实现访问限制。

下图展示了基于源 IP 地址的访问控制流程图。

image
基于源 IP 地址的访问控制流程图

场景假设

假设请求经过三个代理,其 IP 地址分别为 1.1.1.12.2.2.23.3.3.3。在 Ingress Gateway 中,numTrustedProxies 被设置为 2,因此 Istio 信任的源 IP 为 2.2.2.2(即 x-envoy-external-address)。

curl -H "Host: clusterip.jimmysong.io" -H 'X-Forwarded-For: 1.1.1.1,2.2.2.2,3.3.3.3' $GATEWAY_IP

屏蔽特定源 IP

若需屏蔽来自 2.2.2.2 的请求,可以使用以下授权策略:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: DENY
  rules:
    - from:
        - source:
            remoteIpBlocks:
            - "2.2.2.2/24"

使用最终客户端 IP

如果希望识别与 Istio Mesh 直连的客户端 IP(即 x-forwarded-for 中的最后一个 IP,例如 123.120.234.15),则需要用 ipBlocks 配置:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: DENY
  rules:
    - from:
        - source:
            ipBlocks:
            - "123.120.234.15/24"

这种方法通过配置 Istio 的入口网关授权策略,可以有效地实现基于源 IP 的访问控制。它允许管理员根据不同的需求(如屏蔽特定 IP 或信任最终客户端 IP)灵活设定规则,从而增强了服务的安全性和灵活性。

基于源 IP 地址的负载均衡

要在 Istio 中根据源 IP 地址配置负载均衡策略,你需要使用 DestinationRule 资源,并指定 LOAD_BALANCER_POLICY_CONSISTENT_HASH 策略。这种策略允许您根据一致性哈希算法为流量分配目标,可以基于源 IP 地址来实现会话亲和性(session affinity),确保来自同一源 IP 的请求被路由到相同的目标。

源 IP 地址负载均衡示例

下面是一个示例配置,展示了如何使用 DestinationRule 来根据源 IP 地址实现负载均衡:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: example-destination-rule
spec:
  host: example-service
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: x-forwarded-for # 这通常包含源 IP 地址,适用于经过代理或负载均衡器转发的流量。

注意,如果直接连接到 Istio Ingress Gateway 而不经过其他代理,你可能需要根据实际情况调整 httpHeaderName 或使用其他哈希键,例如 useSourceIp,如下所示:

spec:
  trafficPolicy:
    loadBalancer:
      consistentHash:
        useSourceIp: true
注意
  • 使用源 IP 地址作为负载均衡的键时,请确保您理解这可能如何影响流量分布,特别是在源 IP 地址分布不均匀的情况下。
  • 正如上文所述,在某些环境中,原始的源 IP 可能会被网络设备(如负载均衡器或 NAT 设备)修改,需要确保 x-forwarded-for 头或其他相应机制能准确反映原始的客户端 IP。

总结

参考

使用 TIS 增强 Istio:安装与监控指南

2024-01-03 11:27:49

在这篇博客中我将指导你如何安装 TIS 并启用监控插件。

什么是 TIS?

Tetrate Istio Subscription(TIS)是由 Tetrate 提供的企业级、全面支持的产品,提供了经过全面测试且适用于所有主要云平台的 Istio 版本。TIS 基于开源的 Tetrate Istio Distro 项目,增加了对这些构建版本的全面高级支持,并可选提供 FIPS 验证的加密模块。此外,TIS 包含一系列经过测试和支持的 Add-Ons 和 Integrations,使得 Istio 的功能扩展和与常用基础设施工具的集成变得简单安全。

为什么使用 TIS?

TIS 不是 Istio 的一个分支,而是提供针对特定环境进行测试的上游发行版。我们对 Istio 所做的任何增强都会应用于上游。TIS 与普通的 Istio 相比有以下关键优势:

  1. 长期支持:TIS 提供 14 个月的安全更新支持,确保稳定性和安全性。
  2. 商业支持:TIS 有商业支持选项,适用于企业用例,包括合规性需求。
  3. 易于管理:TIS 提供简化的安装和管理过程,减少了操作复杂性。
  4. 多环境适配:TIS 支持不同云环境,满足各种部署需求。
  5. FIPS 验证:提供 FIPS 验证版本,适用于高安全性要求的场景。

想要了解 TIS 的更多信息请访问:https://docs.tetrate.io/istio-subscription/

准备条件

在安装 TIS 及其插件前,你需要准备:

安装 Istio 及 Monitoring addons

首先使用下面的命令查看 TIS 支持的 Istio 版本:

helm search repo tetratelabs/base --versions
NAME            	CHART VERSION  	APP VERSION    	DESCRIPTION
tetratelabs/base	1.20.1+tetrate0	1.20.1-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.20.0+tetrate0	1.20.0-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.19.5+tetrate0	1.19.5-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.19.4+tetrate0	1.19.4-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.19.3+tetrate0	1.19.3-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.18.6+tetrate0	1.18.6-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.18.5+tetrate0	1.18.5-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.18.3+tetrate0	1.18.3-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.17.8+tetrate0	1.17.8-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.17.6+tetrate0	1.17.6-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.16.7+tetrate0	1.16.7-tetrate0	Helm chart for deploying Istio cluster resource...
tetratelabs/base	1.16.6+tetrate0	1.16.6-tetrate0	Helm chart for deploying Istio cluster resource...

我们将安装当前最新的 Istio 1.20.1 版本。

export TIS_USER=<tis_username>
export TIS_PASS=<tis-password>
# Helm chart version
export VERSION=1.20.1+tetrate0
# Image tag
export TAG=1.20.1-tetrate0
kubectl create namespace istio-system

kubectl create secret docker-registry tetrate-tis-creds \
    --docker-server="addon-containers.istio.tetratelabs.com" \
    --docker-username=${TIS_USER} \
    --docker-password=${TIS_PASS} \
    -n istio-system

# Install Istio
helm install istio-base tetratelabs/base -n istio-system \
    --set global.tag=${TAG} \
    --set global.hub="addon-containers.istio.tetratelabs.com" \
    --set "global.imagePullSecrets[0]=tetrate-tis-creds" \
    --version ${VERSION}

helm install istiod tetratelabs/istiod -n istio-system \
    --set global.tag=${TAG} \
    --set global.hub="addon-containers.istio.tetratelabs.com" \
    --set "global.imagePullSecrets[0]=tetrate-tis-creds" \
    --version ${VERSION} \
    --wait

# install ingress Gateway
kubectl create namespace istio-ingress

kubectl create secret docker-registry tetrate-tis-creds \
    --docker-server="addon-containers.istio.tetratelabs.com" \
    --docker-username=${TIS_USER} \
    --docker-password=${TIS_PASS} \
    -n istio-ingress

helm install istio-ingress tetratelabs/istio-ingress -n istio-ingress \
    --set global.tag=${TAG} \
    --set global.hub="addon-containers.istio.tetratelabs.com" \
    --set "global.imagePullSecrets[0]=tetrate-tis-creds" \
    --version ${VERSION} \
    --wait

# Install TIS addon
helm install istio-monitoring-demo tis-addons/istio-monitoring-demo --namespace tis --create-namespace

端口转发 Grafana 服务,然后在本地浏览器中打开 Grafana:http://localhost:3000

kubectl port-forward --namespace tis svc/grafana 3000:3000

注意:请保持该命令持续运行,因为我们在向 Grafana 导入 dashboard 时还需要访问该端口。

安装 Istio Monitoring Addons

使用默认的用户名密码 admin/admin 登录后,在左侧导航栏中选择 Administration - Service accounts,参考 Grafana 文档上的说明创建一个 admin 权限的 Service account。

image
在 Grafana 中创建一个 Service account

记下这个 Token,我们将在下面的操作中用到。

使用 Terraform 向 Grafana 中导入 dashboard:

cat>~/.terraformrc<<EOF
credentials "terraform.cloudsmith.io" {
  token = "tetrate/tis-containers/kuhb8CPZhaOiR3v6"
}
EOF

# Create a terraform module file
cat>istio-monitoring-grafana.tf<<EOF
module "istio_monitoring_grafana" {
  source = "terraform.cloudsmith.io/tis-containers/istio-monitoring-grafana/tetrate"
  version = "v0.2.0"
  gf_url  = "<http://localhost:3000>"
  gf_auth = "<grafana_token>"
}
EOF

# Run the commands
terraform init
terraform plan
terraform apply -auto-approve

恭喜你现在已经成功的向 Grafana 中导入了以下四个 dashboard:

但是现在有些 dashboard 还没有数据,我们需要在网格中制造一些流量。

测试监控

部署 Bookinfo 应用和入口网关:

kubectl create secret docker-registry tetrate-tis-creds \
    --docker-server="addon-containers.istio.tetratelabs.com" \
    --docker-username=${TIS_USER} \
    --docker-password=${TIS_PASS} \
    -n default
kubectl label namespace default istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n default
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml -n default

获取入口网关的 IP 并发送一些流量:

export GATEWAY_IP=$(kubectl -n istio-ingress get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
for i in $(seq 1 100);do curl http://$GATEWAY_IP/productpage ; sleep 3;done

现在访问 Grafana dashboard,你可以看到监控数据了。

image
TIS Workload Dashboard

除此之外,在导入了这些 dashboard 的同时,我们还导入了以下警报规则:

image
导入的警报规则

你也可以在 Grafana 中定义警报规则,比如整合 Telegram 或 Slack 来发送通知。

清理

运行下面的命令清理 Bookinfo 应用和 TIS:

kubectl delete -f samples/bookinfo/platform/kube/bookinfo.yaml -n default
kubectl delete -f samples/bookinfo/networking/bookinfo-gateway.yaml -n default
helm uninstall istio-ingress -n istio-ingress
helm uninstall istio-monitoring-demo -n tis
helm uninstall istiod -n istio-system
helm uninstall istio-base -n istio-system
kubectl delete namespace tis
kubectl delete namespace istio-ingress
kubectl delete namespace istio-system

总结

通过执行这些步骤,您已经使用 TIS 成功地在 Istio 中设置和测试了监视。在 Istio 环境中享受增强监控的见解和优势!

Istio 多集群身份验证与 mTLS 连接解析

2023-12-27 11:27:49

前言

我经常在 Istio 的 GitHub Discussions 上回答网友的问题,最近我遇到了一个关于 Istio 主 - 远程部署的讨论,问题是关于远程集群中网关如何最初验证到外部 Istiod 实例的。这个问题触及到服务网格在多集群配置中的核心安全机制,我认为这值得在社区中进行更深入的分享。

正文

在 Istio 官方的不同网络上安装 Primary-Remote文档中,有一个步骤是将 cluster2 作为 cluster1 的远程集群进行附加。这个过程中会创建一个包含 kubeconfig 配置的 Secret,这个配置文件中含有访问远程集群(cluster2)所需的证书和令牌。

# 这个文件是自动生成的,请不要编辑。
apiVersion: v1
kind: Secret
metadata:
  annotations:
    networking.istio.io/cluster: cluster2
  creationTimestamp: null
  labels:
    istio/multiCluster: "true"
  name: istio-remote-secret-cluster2
  namespace: istio-system
stringData:
  cluster2: |
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: {CERTIFICATE}
        server: {CLUSTER2-APISERVER-ADDRESS}
      name: cluster2
    contexts:
    - context:
        cluster: cluster2
        user: cluster2
      name: cluster2
    current-context: cluster2
    kind: Config
    preferences: {}
    users:
    - name: cluster2
      user:
        token: {TOKEN}    

这个 Secret 的关键作用是让主集群(cluster1)中的 Istio 能够访问远程集群的 API 服务器,从而获得服务信息。此外,远程集群(cluster2)中的 Istiod 服务,通过端点指向主集群中 Istiod 服务的 LoadBalancer IP(端口 15012 和 15017),使得 cluster2 能够通过 Istiod 与主集群进行通信。

因为这两个集群共用一个 CA(由主集群提供),并且远程集群能够访问自己的 API 服务器,所以主集群中的 Istiod 可以验证来自远程集群(cluster2)的请求。下面的序列图清晰地展示了这一过程:

image
Istio 多集群身份验证与 mTLS 连接过程时序图

这一过程是 Istio 多集群配置中的关键一环,确保了服务网格中跨集群通信的安全性。正如我们在这次讨论中看到的,无论是远程网关还是服务都依赖于主集群的 CA 来进行初始的 mTLS 认证,这为整个服务网格的安全通信提供了坚实的基础。

总结

在本篇博客中,我们探讨了在 Istio 主 - 远程部署中,远程集群的网关如何进行初始验证以连接到外部的 Istiod。我们解释了如何通过创建一个含有 kubeconfig 的 Secret 来允许主集群的 Istio 访问远程集群的 API,以及如何通过共享的 CA 和服务账户令牌来确保 mTLS 认证的安全性。这一过程确保了服务网格中的跨集群通信的安全,为理解和实施 Istio 的多集群配置提供了重要的见解。

如何订阅 ChatGPT Plus:只需美区 ID 无需虚拟信用卡

2023-12-06 10:43:27

在上一篇博客中,我向大家介绍了我开发的Istio Advisor Plus GPT。但是,要使用这个工具,需要满足一个前提条件,即您必须已经订阅了 ChatGPT Plus。对于很多中国用户来说,注册 ChatGPT 账户可能已经费了不少力气,但是在订阅 ChatGPT Plus 时可能会遇到一些困难。在这篇文章中,我将指导您如何通过正规渠道、无需使用国外信用卡,也无需虚拟信用卡来成功订阅和续费 ChatGPT Plus。

image
PockytShop 中的礼品卡

答案其实很简单,首先您需要拥有一个美国地区的 Apple ID。然后,您可以前往 https://shop.pockyt.io/ 这个网站购买App Store & iTunes礼品卡,您可以选择礼品卡的金额,范围从 2 美元到 500 美元不等。接下来,您可以使用支付宝进行支付。您也可以直接在您自己的支付宝中将地区设置为美国,然后搜索礼品卡,即可找到购买链接。我为了方便起见,选择在网站上直接购买。购买完成后,您将收到礼品卡代码,登录您的美国地区的 Apple Store 账户后,即可兑换礼品卡。

通过这种方式,您可以轻松订阅 ChatGPT Plus,无需繁琐的操作,同时也避免了使用国外信用卡或虚拟信用卡的麻烦。这是一个简单而有效的方法,让更多人能够享受 ChatGPT Plus 的服务。

Istio 老中医,在线问诊,专治各种疑难杂症

2023-11-25 08:43:27

大家好,今天我要向你们隆重介绍一位特别的“老中医” —— Istio Advisor Plus GPT(以下简称“Istio 老中医”)。不要误会,他不是给人看病的,而是专治您在 Istio 这个“网络世界”中遇到的各种疑难杂症!

Istio 老中医的崭新登场

“老中医”来自于 OpenAI 最近推出的一项革命性技术 —— GPT。这个技术简直是黑科技,能让你不用写一行代码就能创建自定义的 GPT 模型。想象一下,只需几次点击,就能得到专门解答 Istio 问题的智能助手!而且,不久后 GPT Store 就要上线,届时你将能看到更多像“老中医”这样的高手。

我准备了一个视频,展示“老中医”在实战中的表现。例如拿一个 Istio 的 GitHub Issue 问他,看看他会给你开什么样的处方?

你可以在 Github 获取导出 GitHub Issue 的代码。

Istio 老中医的神奇力量

  1. 解释 Istio 概念和特性:从流量管理到安全性,再到可观测性,无所不知,无所不能。

  2. 指导配置:无论您需要怎样的配置建议,“老中医”总有办法。

  3. 诊断和解决问题:遇到棘手的问题?不用怕,“老中医”在此。

  4. 性能优化建议:让您的 Istio 运行得更加流畅,更加高效。

  5. 安全最佳实践:零信任安全原则在此不再是难题。

  6. 可视化表示:用图表展示复杂的网络,让一切变得易懂。

  7. 协助升级:升级 Istio 就像喝水一样简单。

  8. Bug 报告指导:遇到 bug?“老中医”帮您梳理、上报。

  9. 参考相关文档:针对复杂问题,提供深度资料。

  10. 生态系统工具建议:让您在 Istio 生态中如鱼得水。

“老中医”的丰富知识库

  1. Istio 基础:基础知识一应俱全。

  2. Envoy 代理:深入探索 Envoy 的奥秘。

  3. 服务网格概念:掌握服务网格的本质。

  4. Tetrate 文档:了解 Tetrate 的一切。

  5. 零信任安全:安全问题,轻松解决。

  6. SkyWalking 集成:深入了解 APM 系统。

  7. Envoy 网关:流量管理和安全性的高手。

  8. 用例和案例研究:实际应用,一目了然。

“老中医”的智慧回应

  1. TLDR:简洁明了,一目了然。

  2. 查询的解释:提供广泛的上下文。

  3. 详细答案:深入浅出,条理清晰。

  4. 实际示例:实操演示,直观易懂。

  5. 建议的下一步操作:明确指引,方便操作。

  6. 参考资料:海量资源,随手可得。

接受“老中医”的局限性

虽然“老中医”很厉害,但也有局限。比如,要使用它,您需要有 ChatGPT Plus 订阅。而且,当回答太长时,可能需要分多次提问。还有,目前可能存在一些隐私问题,所以建议暂时只用公开数据。

总结

综上所述,Istio 老中医是您在 Istio 世界旅行的必备良伴。无论是丰富的知识库、定制的回应,还是实际的指导,它都能帮您轻松驾驭 Istio 的复杂世界。所以,一起来尝试一下吧,和 Istio 老中医一起探索无限可能!

外部服务别名:ExternalName 与 ServiceEntry 对比

2023-11-10 14:27:49

随着 Kubernetes 不断演进,Istio 功能逐渐在 Kubernetes 中找到对应实现,如 Sidecar 容器Gateway API 以及本文的主题 ExternalName。ExternalName 和 ServiceEntry 都能起到引入 Kubernetes 集群外部服务的作用,但是它们的功能和使用场景也有所区别,本文将为你详细解析。

ExternalName vs ServiceEntry

下表从多个方面对比了 ExternalNameServiceEntry

特性/用例 ExternalName ServiceEntry
流量控制 有限,仅支持 TCP 和 UDP 更灵活,支持 TCP、UDP、HTTP 等多种协议,可以指定端口、TLS 等选项
服务发现 适用于外部服务的简单别名 适用于描述网格内外服务,包括外部和内部服务的详细配置
配置复杂性 简单,适用于基本的服务发现需求 较复杂,适用于需要高级流量控制和详细配置的场景
TLS 支持 有限,较简单 更丰富的 TLS 支持,可以指定证书等详细选项
安全性 较基本,适用于简单的用例 更强大的安全性支持,可以定义 subjectAltNames 等选项
用途 适用于简单的外部服务别名 适用于复杂的流量管理和服务发现需求,尤其是在多协议和复杂网络拓扑中

使用场景

ExternalName 的使用情况:

  1. 简单的服务别名: 外部服务只需一个简单别名,无需复杂流量控制,可选用 ExternalName
  2. 无详细流量控制需求: 不需要对服务流量进行详细控制,只需简单的服务别名访问,选用 ExternalName

ServiceEntry 的使用情况:

  1. 复杂流量控制需求: 需要更复杂的流量控制,如指定协议、端口、TLS 选项等,选择 ServiceEntry
  2. 描述网格内外服务: 需要描述网格内外服务,包括外部和内部服务的详细配置,ServiceEntry 更适合。
  3. 对服务详细属性有要求: 需要为服务定义特殊属性,如 subjectAltNames 等,需使用 ServiceEntry

在 Istio 中使用 ExternalName 可能遇到的问题

在 Istio 1.20 以前,网格内存在 ExternalName 类型的 Service 时,若该 Service 的端口与其他外部服务的端口重叠,流量可能错误路由到该 ExternalName Service。该问题已在 Istio 1.20 版本中解决,详见 Better support ExternalName #37331

总结

在服务网格的选择中,ExternalName 和 ServiceEntry 分别提供了简单的服务别名和更复杂的流量管理与服务发现选项。ExternalName 适用于简单的外部服务别名,而 ServiceEntry 在处理复杂流量控制和网格内外服务时更具优势。在实际应用中,根据具体需求和配置的复杂性权衡,灵活选择合适的机制。随着 Istio 和 Kubernetes 的不断演进,这些功能的使用方式可能会受到影响,因此保持关注相关社区的更新和最佳实践是保持系统健康和高效运行的关键。选择合适的服务网格组件将有助于构建可靠、安全且高度可扩展的微服务架构。

Istio 1.20 有哪些更新?

2023-11-10 06:27:49

Istio 1.20 代表了 Istio 服务网格能力的显著进步,为运维人员和开发人员提供了更好的体验。这个新版本引入了一些关键的功能和更新,将影响到服务网格架构的设计和实施。

Gateway API 支持

Istio 1.20 全面支持 Kubernetes Gateway API,并已正式发布(GA)。这标志着服务网格生态系统的重大进步,为用户提供了一组稳定且丰富的网络 API,与 Kubernetes 的核心服务相一致。Istio 对 Gateway API 的支持是实现更无缝和灵活的流量管理的重要一步,使用户能够利用一致的声明方式定义在 Kubernetes 集群内如何路由流量。如果你想了解更多关于 Gateway API 的信息,可以阅读我的博客 Istio 1.19 有哪些更新:Gateway API 还有更多

增强的 ExternalName 服务支持

在服务发现领域,Istio 1.20 对于ExternalName服务的处理进行了重要更新(见 Better support ExternalName #37331),使得 Istio 的行为更加符合 Kubernetes 的行为。这个变化简化了配置,并使得 Istio 能够更好地处理 DNS,对于依赖于外部终点的服务至关重要。关于 ExternalName 服务的更多信息,你可以参考 Kubernetes 官方文档

ExternalName 和 Istio 中的 ServiceEntry 都可以用于处理服务发现,特别是引入 Kubernetes 集群之外的服务,但有一些关键区别:

其他更新

一致的 Envoy 过滤器排序: 在新版本中,Envoy 过滤器的排序在所有流量方向和协议上变得一致了。这确保了过滤器的统一应用,对于服务网格的可预测行为和安全性至关重要。

网络 Wasm 插件扩展: Istio 继续通过引入新的NETWORK类型扩展网络 Wasm 插件的支持,推动了可扩展性的边界。这个扩展巩固了 Istio 作为服务网格创新领域的领导地位,为用户提供了更多的控制和定制选项。

TCP 元数据交换增强: Istio 1.20 中的两个更新旨在改进 TCP 元数据交换:回退元数据发现过程和控制 ALPN 令牌的能力。这些改进显示了 Istio 对强大高效的网络的承诺。

流量镜像到多个目的地: 新版本扩展了 Istio 的流量镜像功能以支持多个目的地。这个功能对于调试和监控非常宝贵,可以提供关于跨不同服务版本或配置的流量行为的见解。

可插拔的根证书轮换: 加强了安全性,Istio 现在支持可插拔的根证书轮换,增强了服务网格在使用更新的加密凭证时保持服务间信任的能力。

Sidecar 容器中的 StartupProbe: 为了改善启动时间,Istio 在 Sidecar 容器中引入了startupProbe,它可以在初始阶段进行积极的轮询,而不会在整个 Pod 的生命周期中持续存在。

OpenShift 安装增强: 通过去除某些特权要求,Istio 简化了在 OpenShift 上的安装过程,从而降低了 OpenShift 用户的使用门槛。

总结

在 Istio 1.20 中的这些功能和增强将简化运维操作,加强安全性,并提供更具动态和可定制的服务网格体验。随着服务网格领域的不断发展,Istio 的最新版本证明了社区对改进和创新的不懈追求。

Kubernetes Gateway API 如何增强云原生网络

2023-11-09 17:10:49

上周 Kubernetes Gateway API 的正式发布公告标志着 Kubernetes 生态系统内 Gateway 能力的重要里程碑。与此同时,Kubernetes 社区一致认同Backstage是内部开发平台和门户的领先解决方案。Kubernetes Gateway API 和 Backstage 都从一开始就鼓励社区的可扩展性。可以说 API Gateway 的出现为增强 Kubernetes 网络提供了巨大的机会。

Gateway API vs Istio 服务网格

不过也有人对 Gateway API 与 Istio 服务网格的关系存在疑问。对于 Gateway API 和 Istio 服务网格,两者都是为了解决 Kubernetes 网络中的问题。然而,Gateway API 着重于提供一种标准化和简化的方式来配置和部署 Ingress 和 Egress,是一个更加通用的 API。另一方面,Istio 服务网格更关注于服务到服务的通信,提供丰富的流量管理,安全,策略和遥测功能。

Kubernetes Gateway API 的未来

Kubernetes Gateway API 代表了 API Gateway 的关键基础,引入了一种标准,基于角色的,高度适应性的方法来配置和部署 Gateway。Kubernetes Gateway API 相比现有的 Kubernetes Ingress 的显著改进之一是其基于角色的 API 结构。这使得基础设施,平台和应用程序领域的各种角色能够拥有直接与他们的用例相关的 API 的各个方面。Gateway API 的另一个关键特性是其针对可扩展性的设计 - API 专注于核心 Gateway 和路由用例,具有扩展附加能力的可能性,例如安全性,速率限制和转换。

什么是 Backstage?

Backstage 是一个开源的开发者平台,它集成了所有开发者需要的服务,提供了一个统一的视图。这包括版本控制系统、持续集成/持续部署(CI/CD)系统、监控、日志、警报和文档。它旨在让开发者更高效地进行日常任务,而无需在多个工具之间切换,它也可以帮助开发者更好地理解和管理他们的软件。

image
Backstage UI

Backstage 可以应用在多种使用场景中:

Backstage 通过其软件目录用于发现 API,软件模板用于提供带有防护栏的自动 API 上线流程,以及Tech Docs用于提供 API 文档的中心用例,用于围绕 API Gateway 的协作。

Backstage 的目标是简化开发者工作流程,提供一站式的解决方案,它使开发者能够在一个平台上查找他们需要的所有信息,而不是在多个工具间切换。此外,Backstage 可以让开发团队专注于编码,而不是管理工具。它还支持多种插件,可以根据团队的需求进行定制。

关于未来

Backstage 和 Kubernetes Gateway API 已经牢固地将自己建立为云原生 API Gateway 的基础支柱,两个项目都在各自的路线图中充满创新。其中最有趣的领域是 Kubernetes Gateway API 超越其传统的南北入口能力,包括东西服务至服务通信,通过引入GAMMA API。在真实的流量在每个方向上流动的情况下,为南北和东西流量提供单一基础将有助于提高任何容器化应用的安全性,弹性和可观测性。

Istio 1.19 有哪些更新:Gateway API 还有更多

2023-11-09 16:27:49

我很高兴呈现 Istio 的最新版本— Istio 1.19。这篇博客将概述此版本中的更新内容。

Gateway API: 彻底改变服务网格

我们的前一篇博客强调了 Gateway API 将 Kubernetes 和服务网格中的入口网关统一的潜力,为跨命名空间的流量支持打开了大门。有了 Istio 的官方支持,Gateway API 成为了焦点。它不仅用于北 - 南流量(网格的入口和出口),现在还扩展到东 - 西流量的领域,也就是网格内部的流量。

在 Kubernetes 中,服务承担多项职责,从服务发现和 DNS 到工作负载选择、路由和负载均衡。然而,对这些功能的控制一直有限,工作负载选择是显著的例外。Gateway API 改变了这一局面,让你可以控制服务路由。这与 Istio 的 VirtualService 有一些重叠,因为两者都对流量路由有影响。以下是三种情况的简介:

  1. Kubernetes 内部请求:在没有 Istio 的情况下,Kubernetes 的所有内部流量都走服务路由。
  2. 北 - 南流量:通过将 Gateway API 应用到入口网关,流入 Kubernetes 的流量会按照 xRoute(目前支持 HTTPRoute, TCPRoute 和 gRPCRoute)到服务。
  3. 东 - 西流量:在 Istio 内部,当流量进入数据平面时,Gateway API 的 xRoute 接管。它引导流量到原始服务或新的目标服务。
image
图 1:流量路由

Gateway API 与 Istio 的这种动态结合不仅精细化了服务网络,也巩固了 Istio 在 Kubernetes 生态系统中的地位。

服务网格的 Gateway API: 深入探讨

在当前的实验阶段(v0.8.0 版本),服务网格的 Gateway API 引入了一种新的方法来配置 Kubernetes 中的服务网格支持。它直接将单个路由资源(如 HTTPRoute)与服务资源关联起来,简化了配置过程。

以下是一些关键点:

实验阶段:在 v0.8.0 版本中,服务网格的 Gateway API 仍处于实验阶段。建议不要在生产环境中使用。

服务与路由关联:在配置服务网格时,与使用 Gateway 和 GatewayClass 资源不同,单个路由资源直接与服务资源关联。

服务的前端和后端:服务的前端包括其名称和集群 IP,后端由其端点 IP 的集合组成。这种区分使得在网格内进行路由无需引入冗余资源。

路由附加到服务:将路由附加到服务上以将配置应用到指向该服务的任何流量。如果没有附加路由,流量会遵循网格的默认行为。

命名空间关系:

image
图 2:生产者路由和消费者路由

组合路由:在单个命名空间中的同一服务的多个路由,无论是生产者路由还是消费者路由,都将根据 Gateway API 路由合并规则进行合并。这意味着在同一命名空间中为多个消费者定义不同的消费者路由是不可能的。

请求流程:

请记住,在实验阶段,服务网格的 Gateway API 可能会有更多的变化,不建议在生产环境中使用。

但等等,还有更多!我们的旅程并没有结束 - 使用 API 的入口流量支持正快速向通用可用性 (GA) 进发,预计还会有更多动态的发展!

让我们进一步探讨这个版本中的其他增强功能。

Ambient Mesh 增强

Istio 团队一直在不断优化 ambient mesh,这是一种创新的部署模型,提供了一个替代传统 sidecar 方法的选择。如果你还没有探索 ambient,现在是深入了解介绍博客的好时机。

在这次更新中,我们强化了对ServiceEntryWorkloadEntryPeerAuthentication以及 DNS 代理的支持。并且,修复了一些 bug,增强了可靠性,以确保无缝的体验。

请记住,ambient mesh 在这个版本中处于 alpha 阶段。Istio 社区热切期待你的反馈,以推动它向 Beta 阶段前进。

简化虚拟机和多集群体验

简单易用是关键,特别是在处理虚拟机和多集群设置的时候。在这个版本中,我们在WorkloadEntry资源中使地址字段变为可选。这个看似小小的调整将大大简化你的工作流程。

提升安全配置

你现在可以为你的 Istio 入口网关的 TLS 设置配置OPTIONAL_MUTUAL,提供可选的客户端证书验证的灵活性。此外,你可以通过MeshConfig微调你偏好的非 Istio mTLS 流量使用的密码套件。

有了这些更新,Istio 1.19 赋予你在管理你的服务网格时更大的控制、灵活性和安全性。

欢迎你探索这些增强功能,并与 Istio 社区分享你的体验。更多详细信息,请参考官方发布说明

祝你网格愉快!


本博客最初在tetrate.io上发布。

CNCF 与 Tetrate 合作推出 Istio Certificated Associate(ICA)认证

2023-11-08 11:27:49

云计算专业人士,自 Istio Certified Associate (ICA) 认证 旅程开始已经一个月了。这是云原生计算基金会(CNCF)、Linux 基金会培训与认证以及 Tetrate 合作的成果,为微服务管理设立了新的标杆。

Tetrate 是 Istio 项目的关键贡献者,最初创建了 Tetrate 认证的 Istio 管理员(CIAT),为 ICA 认证奠定了基础。自从推出以来,ICA 已成为 Kubernetes 生态系统的重要组成部分,帮助数千人掌握服务网格技术。

认证课程涵盖了诸如安装流量管理安全等基本领域,反映出该领域所需的全面专业知识。在短短时间内,ICA 获得了显著动力,得益于 Tetrate 对云原生领域的愿景和投入。

在 ICA 成立一个月之际,Tetrate 继续通过其 Tetrate Academy 承诺开源教育,提供有关服务网格和 Kubernetes 安全的免费、高质量课程。对于那些打算在生产中部署 Istio 的人来说,Tetrate 提供了Tetrate Istio Distribution (TID),一种安全且得到支持的 Istio 发行版。

如果您还没有加入,现在是时候加入这个不断增长的 Istio 专家社区了。提升您的职业生涯,为云原生技术的演进做出贡献。

什么是 ICA 认证?

ICA 是专为工程师,CI/CD 从业者或任何对 Istio 有特殊兴趣的人设计的专业前认证。

获得认证的 ICA 学员可确认他们对 Istio 原则、术语和最佳实践的基础知识,并展示他们建立 Istio 的能力。

ICA 认证考试展示了考生对 Istio 原则、术语和建立 Istio 的最佳实践的深入理解。

ICA 认证考试内容

ICA 认证考试包括这些一般领域及其在考试中的权重:

详细内容如下:

安装、升级和配置:7%

流量管理:40%

弹性和故障注入:20%

固定工作负载:20%

高级场景:13%

如何获得 ICA 认证?

点击开始您的 ICA 认证吧!

这只是一个开始。让我们期待在服务网格熟练度上达到更多里程碑,由 Tetrate 和 CNCF 引领潮流。

注:ICA 认证提供中文认证考试,证书有效期 3 年。

使用 Argo 项目 Istio 及 SkyWalking 实现 GitOps 和金丝雀部署

2023-10-21 10:18:40

关于本文
本文根据笔者在 KubeCon&CloudNativeCon China 2023 的通话仓活动 IstioCon China 上的分享整理而成,原标题为《如何在 Argo、Istio 和 SkyWalking 中实现 GitOps 和可观测性的完美结合》。

云原生应用的发展导致开发左移,应用迭代频率更高,这就催生了 GitOps 的需求。本文将介绍如何使用 Argo 项目,包括 ArgoCD 和 Argo Rollouts,通过 Istio 实现 GitOps 和金丝雀部署。文中还有一个演示,展示了如何基于 Tetrate Service Express(也适用于 Tetrate Service Bridge)提供的 Istio 环境实现 GitOps。

本文 demo 的部署架构图如图 1 所示。如果您已经熟悉本文介绍的部署策略和 Argo 项目,可以直接跳到 demo 部分

image
图 1:在 TSE/TSB 中使用 Istio 和 Argo 项目实现 GitOps 和金丝雀发布的架构图

部署策略

首先,我想简单介绍一下 Argo Rollouts 支持的两种部署策略,可以实现零停机部署。

蓝绿部署和金丝雀部署的步骤如图 2 所示。

image
Figure 2: Steps of blue-green deployment and canary deployment

蓝绿部署和金丝雀部署的主要区别在于部署方式和变更规模。蓝绿部署是将整个应用部署在新的环境中,然后进行切换,适合大规模的变更,比如整个应用的重大升级。金丝雀部署逐渐引入新版本或功能,适合小规模更改,例如添加或修改单个功能。

从应用场景来看,蓝绿部署适合对高可用、零宕机部署要求较高的系统。在部署大规模变更时,蓝绿部署可以保证稳定性和可靠性,并且可以快速回滚以应对突发情况。金丝雀部署适合需要快速验证新功能或版本的系统。通过逐步引入变更,可以及早发现问题并进行调整,尽量减少对用户的影响。

Kubernetes Deployment 的发布策略

在 Kubernetes 中,Deployment 资源对象是管理应用程序部署和更新的主要工具之一。部署提供了一种声明式方式来定义应用程序的预期状态,并通过控制器的功能实现发布策略。Deployment 的架构如图 3 所示,其中彩色方块代表不同版本的 Pod。

image
图 3:Kubernetes Deployment 架构图

发布策略可以在 Deployment 的 spec 字段中配置。以下是一些常见的发布策略选项:

  1. ReplicaSet 的管理:Deployment 使用 ReplicaSet 来创建和管理应用程序的副本。可以通过设置 spec.replicas 字段来指定所需的副本数量。在发布过程中,Kubernetes 控制器保证新版本 ReplicaSet 的副本数量在创建时逐渐增加,旧版本 ReplicaSet 的副本数量在删除时逐渐减少,实现平滑切换。
  2. 滚动更新策略:部署支持多种滚动更新策略,可以通过设置 spec.strategy.type 字段来选择。常见政策包括:
    • RollingUpdate:默认策略以一定的时间间隔逐渐更新副本。不同时可用的副本数量以及额外可用的副本数量可以通过设置 spec.strategy.rollingUpdate.maxUnavailablespec.strategy.rollingUpdate.maxSurge 字段来控制。
    • ReCreate:该策略在更新过程中首先删除旧版本的所有副本,然后创建新版本的副本。此策略将导致应用程序在更新期间暂时不可用。
  3. 版本控制:Deployment 通过 spec.template.metadata.labels 字段为每个版本的 ReplicaSet 设置标签,以便控制器准确跟踪和管理。这样 ReplicaSet 的多个版本可以共存,并且可以精确控制每个版本的副本数量。

通过使用这些配置选项,Deployment 可以实现不同的发布策略。更新 Deployment 对象的 spec 字段可以触发新版本的发布。Kubernetes 控制器会根据指定的策略自动处理副本的创建、更新和删除,以实现平滑的应用更新和部署策略。

使用 ArgoCD 实施 GitOps

可以使用 Deployment 来手动管理发布策略,但要实现自动化,我们还需要使用 ArgoCD 等 GitOps 工具。

ArgoCD 是一个基于 GitOps 的持续交付工具,用于自动化和管理 Kubernetes 应用程序的部署。它为提高应用程序部署的效率和可靠性提供了一些关键的帮助。

以下是 ArgoCD 为 Kubernetes 应用程序部署提供的一些帮助:

  1. 声明式配置:ArgoCD 使用声明式方式定义应用程序的预期状态,并将应用程序配置存储在 Git 存储库中。通过版本控制和持续集成/持续交付 (CI/CD) 流程,可以轻松跟踪和管理应用程序配置更改。
  2. 持续部署:ArgoCD 可以监控 Git 存储库中的配置变化,并自动将应用程序部署到 Kubernetes 环境。提供可定制的同步策略,自动触发应用部署和更新,实现持续部署。
  3. 状态比较和自动修复:ArgoCD 定期检查应用程序的当前状态并将其与预期状态进行比较。如果发现不一致,它会自动尝试修复并将应用程序恢复到所需状态,以确保预期状态与实际状态的一致性。
  4. 多环境管理:ArgoCD 支持管理多个 Kubernetes 环境,例如开发、测试和生产环境。可以轻松地在不同环境之间部署和同步应用配置,确保一致性和可控性。

与 Deployment 资源对象相比,ArgoCD 提供了更高级的功能和工作流程,补充了原生 Kubernetes 资源对象的功能:

使用 Istio 实现细粒度的流量路由

虽然 ArgoCD 可以实现 GitOps,但它本质上是在 Kubernetes 部署上运行并通过副本数量控制流量路由。为了实现细粒度的流量路由,使用了 Istio 等服务网格。

Istio 通过以下方法实现更细粒度的流量路由和应用发布:

VirtualService:Istio 使用 VirtualService 来定义流量路由规则。通过配置 VirtualService,可以根据请求头、路径、权重等请求属性对流量进行路由和分发,将请求定向到不同的服务实例或版本。

DestinationRule:Istio 的 DestinationRule 用于定义服务版本策略和负载均衡设置。通过指定不同版本服务实例之间不同的流量权重,可以实现金丝雀发布、蓝绿部署等高级应用发布策略。

流量控制和策略:Istio 提供了丰富的流量控制和策略能力,如流量限制、故障注入、超时设置、重试机制等,这些功能帮助应用程序实现更高级别的负载均衡、容错和可靠性要求。

与 ArgoCD 和 Kubernetes Deployment 对象相比,Istio 在应用部署方面提供了以下优势:

细粒度的流量路由控制:Istio 提供了更丰富的流量路由能力,可以根据多种请求属性进行灵活的路由和分发,从而实现更细粒度的流量控制和管理。

高级发布策略支持:Istio 的 DestinationRule 可以指定不同版本服务实例之间的流量权重,支持金丝雀发布、蓝绿部署等高级应用发布策略。这使得应用程序的版本管理和发布更加灵活可控。

强大的流量控制和策略能力:Istio 提供了丰富的流量控制和策略能力,如流量限制、故障注入、超时设置、重试机制等,这些功能帮助应用程序实现更高级别的负载均衡、容错和可靠性要求。

将 Istio 与 Argo Rollouts 相结合,可以充分发挥 Istio 细粒度流量路由的优势。现在让我们一起进行演示。在我们的演示中,我们将使用 TSE 提供的 Kubernetes 和 Istio 环境,使用 ArgoCD 实现 GitOps,并使用 Argo Rollouts 实现金丝雀发布。

Demo

我们的演示中使用的软件版本是:

我们将使用 Istio 的 VirtualService 和 DestinationRule 来实现基于 Subset 的流量分组路由,并使用 ArgoCD Rollouts 进行渐进式发布。

部署 ArgoCD 和 Argo Rollouts

我提前创建了一个 Kubernetes 集群并将其添加到 TSE 中,TSE 会自动为集群安装 Istio 控制平面。我们还需要安装 ArgoCD 和 Argo Rollouts:

# Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Install ArgoCD CLI on macOS
brew install argocd

# Change the service type of argocd-server to LoadBalancer
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

# Get the ArgoCD UI address
ARGOCD_ADDR=$(kubectl get svc argocd-server -n argocd -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

# Login using ArgoCD CLI, see https://argo-cd.readthedocs.io/en/stable/getting_started/#4-login-using-the-cli to get password
argocd login $ARGOCD_ADDR --skip-test-tls --grpc-web --insecure

# Install Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/download/latest/install.yaml

# Install rollouts plugin on macOS
curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.5.0/kubectl-argo-rollouts-darwin-amd64
chmod +x ./kubectl-argo-rollouts-darwin-amd64
sudo mv ./kubectl-argo-rollouts-darwin-amd64 /usr/local/bin/kubectl-argo-rollouts

该功能不适用于 TSE Bridge Mode,因此我们将使用 TSE Direct Mode 来实现渐进式发布。

💡什么是桥接模式和直接模式?
直接模式和桥接模式是 TSE 中控制平面下发配置的两种模式。适用于流量、安全、网关组配置模式。BRIDGED 模式是一种极简模式,允许用户使用 Tetrate 特定的 API 快速配置服务网格中最常用的功能,而 DIRECT 模式为高级用户提供更大的灵活性,允许他们直接使用 Istio API 进行配置。

接下来,部署 Rollouts Dashboard:

git clone https://github.com/argoproj/argo-rollouts.git
kustomize build manifests/dashboard-install|kubectl apply -n argo-rollouts -f -
kubectl port-forward svc/argo-rollouts-dashboard -n argo-rollouts 3100:3100

您现在可以通过 https://localhost:3100/rollouts/ 访问 Rollouts 仪表板。

部署 Bookinfo 应用

我们已经为 Bookinfo 应用程序准备了配置文件(保存在 tse-gitops-demo 存储库中),您也可以将其 fork 到您自己的帐户并将其替换为您自己的存储库。运行以下命令来部署 Bookinfo 应用程序:

argocd app create bookinfo-app --repo https://github.com/tetrateio/tse-gitops-demo.git --path application --dest-server https://kubernetes.default.svc --dest-namespace bookinfo --sync-policy automated

注意:我们在 reviews 部署中将 replicas 设置为 0 ,因为我们将创建 Argo Rollouts 来操纵 reviews 的实例数量服务。如果这里设置为非零正整数,我们将无法实现金丝雀部署。

现在您可以在浏览器中打开 ArgoCD UI,如图 4 所示。

image
图 4:ArgoCD 用户界面

如果您发现应用程序状态不同步,可以运行以下命令或单击 UI 中的 SYNC 按钮。

argocd app sync bookinfo-app

使用 Istio 实施细粒度流量管理

首先,我们使用 Argo CD 创建 Istio 相关的资源对象:

argocd app create bookinfo-tse-conf --repo https://github.com/tetrateio/tse-gitops-demo.git --path argo/tse --dest-server https://kubernetes.default.svc --dest-namespace bookinfo --sync-policy automated --self-heal

# Check the creation status
argocd app get bookinfo-tse-conf

将 Deployment 转换为 Rollout

假设我们要发布新版本的 reviews 服务。为了实现零停机更新,我们将使用金丝雀部署,具体步骤如下:

  1. reviews Deployment 的 replicas 减少为 0;
  2. 创建引用先前在 Bookinfo 应用程序中部署的 reviews Deployment 的 Rollout;
  3. 将流量发送到 reviews 服务以实现自动金丝雀部署进度。

您可以在 GitHub 上查看本演示中使用的 Rollout 和 AnalysisTemplate 配置。运行以下命令来部署 reivews-rollout

argocd app create reviews-rollout --repo https://github.com/tetrateio/tse-gitops-demo.git --path argo/rollout --dest-server https://kubernetes.default.svc --dest-namespace bookinfo --sync-policy automated

注意:我们可以使用 argocd 命令来部署或使用 kubectl apply 。推荐使用 argocd ,因为您可以同时在 ArgoCD UI 和 Argo Rollouts Dashboard 中查看部署状态,并使用 argocd 命令管理部署。

在 Argo Rollouts Dashboard 中查看 reviews 部署的状态,并使用以下命令将流量发送到 reviews 服务一段时间:

export GATEWAY_HOSTNAME=$(kubectl -n bookinfo get service tsb-gateway-bookinfo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
while 1;do curl -H "Host: bookinfo.tetrate.com" http://$GATEWAY_HOSTNAME/api/v1/products/1/reviews;sleep 3;done

您将在输出中看到来自具有不同 rollouts-pod-template-hash 标签的 pod 的响应,这证明金丝雀部署是有效的。大约 10 分钟后,您看到的 Argo Rollouts 仪表板将如图 5 所示。

image
图 5:Argo Rollouts 仪表板

从图 5 中我们可以看到金丝雀部署进展顺利,已经到了第三步。这是因为 reviews 服务的 apdex (应用性能指数)指标正常。您可以使用 Postman 向 SkyWalking 提交 GraphQL 查询来验证这一点,如图 6 所示。

image
图 6:使用 Postman 将 GraphQL 查询提交到 SkyWalking

我们构建的 GraphQL 查询语句如下:

query ReadMetricsValues {
    readMetricsValues(condition: {
    name: "service_apdex", entity: {scope: Service, serviceName: "canary|reviews|bookinfo|cluster-1|-", normal: true}
  }, duration: {
    start: "2023-07-13 0812",
    end: "2023-07-13 0813",
    step: MINUTE
  }) {
        label
        values {
            values {
                id
                value
            }
        }
    }
}

该语句从 UTC 2023-07-13 8:122023 8:13 查询 canary|reviews|bookinfo|cluster-1|- 服务的 apdex 指标,持续两分钟,得到以下结果:

{
    "data": {
        "readMetricsValues": {
            "label": null,
            "values": {
                "values": [
                    {
                        "id": "service_apdex_202307130812_Y2FuYXJ5fHJldmlld3N8Ym9va2luZm98Y2x1c3Rlci0xfC0=.1",
                        "value": 10000
                    },
                    {
                        "id": "service_apdex_202307130813_Y2FuYXJ5fHJldmlld3N8Ym9va2luZm98Y2x1c3Rlci0xfC0=.1",
                        "value": 10000
                    }
                ]
            }
        }
    }
}

apdex 指标的值大于 9900(AnalysisTemplate 的 successCondition 中配置的阈值),因此 Rollouts 会顺利进行。您还可以在 Argo Rollouts Dashboard 上单击“手动升级”来升级它,或运行以下命令:

kubectl argo rollouts promote reviews-rollout -n bookinf

清理

删除已部署的 ArgoCD 应用程序和 Rollout:

argocd app delete -y reviews-rollout
argocd app delete -y bookinfo-tse-conf
argocd app delete -y bookinfo-app

Argo Rollouts 原理

与 Istio 集成时,Argo Rollouts 支持基于 VirtualService 和 Subset 的流量拆分,如图 7 所示。

image
图 7:Argo Rollouts 使用 Istio 进行流量分配

下表提供了这两种流量分段方法的详细比较。

类型 适用场景 资源对象 原则
主机级流量分割 适用于根据主机名访问不同版本的服务; 2 个服务、1 个虚拟服务、1 个部署; Rollout 将 rollouts-pod-template-hash 标签注入到 ReplicaSet 中,并通过更新 Service 中的选择器来选择带有这些标签的 pod;
子集级流量分割 适用于根据标签访问不同的服务; 1 个服务、1 个虚拟服务、1 个目标规则和 1 个转出; Rollout 将 rollouts-pod-template-hash 标签注入到 ReplicaSet 中,并通过更新 DestinationRule 中的选择器来选择具有这些标签的 pod;

本演示中使用基于子集的流量分割,Argo 不断推出:

请访问 Argo Rollouts 文档,了解有关使用 Istio 进行流量管理的详细信息。

总结

本文介绍如何使用 Argo 项目和 Istio 实现 GitOps 和金丝雀部署。首先我们使用 ArgoCD 实现 GitOps,然后使用 Argo Rollout 和 SkyWalking 实现自动化金丝雀发布。从 demo 中我们可以看到 TSE 部署的 Istio 与开源版本完全兼容。TSE 有许多功能值得探索,请访问 Tetrate 网站了解更多信息。

Istio 中的负载均衡详解及多集群路由实践

2023-09-07 20:16:49

编者按
本文介绍了 Istio 中支持的负载均衡类型,然后提出多集群网格负载均衡的解决方案。如果您已经了解 Istio 中负载均衡,可以直接从多集群网格中的负载均衡部分开始阅读。

在之前的博客为什么在使用了 Kubernetes 后你可能还需要 Istio 中提到 Istio 是在 Kubernetes 的基础之上构建起来的,Kubernetes 中的组件 kube-proxy 本身已有负载均衡功能,但是只支持四层流量的负载均衡,而且无法实现服务超时、熔断等高级功能。具体来说,服务网格比起 Kubernetes 新增了以下负载均衡及韧性(Resiliency)特性:

  1. Layer 7 负载均衡:服务网格在应用层(Layer 7)操作和管理流量,可以更细粒度地识别和控制流量。这使得它可以实现更高级的负载均衡策略,如基于 HTTP 请求头、URL 路径、Cookie 等的路由和流量分发。

  2. 动态负载均衡:服务网格通常具备自动负载均衡的能力,可以根据后端服务的实时健康状态和性能指标来动态分发流量。这允许它实现智能负载均衡策略,将流量路由到性能最佳的服务实例。

  3. 故障检测和自动故障转移:服务网格具备高级的故障检测和自动故障转移功能。它可以检测到后端服务实例的故障,并自动将流量从故障实例转移到健康实例,以确保应用程序的可用性。

  4. A/B 测试和金丝雀发布:服务网格允许实施高级部署策略,如 A/B 测试和金丝雀发布。这些策略允许在不同的服务版本之间动态分配流量,并根据结果进行决策。

  5. 熔断和重试:服务网格通常包含熔断和重试机制,以提高应用程序的可用性和稳定性。它可以根据后端服务的性能和可用性情况来自动执行熔断操作,并在必要时重试请求。

  6. 全局流量控制:服务网格提供了集中式的流量控制和策略定义,允许对整个服务网格中的流量进行全局管理。这使得实现统一的安全性、监控和策略成为可能。

  7. 深度集成的监控和追踪:服务网格通常集成了强大的监控和追踪工具,可以提供有关流量性能和可见性的详细信息,帮助进行故障排除和性能优化。

虽然 Kubernetes 提供了基本的负载均衡能力,但服务网格在其之上构建了更高级的负载均衡和流量管理功能,以满足微服务架构中复杂的需求。

客户端负载均衡 vs 服务端负载均衡

客户端负载均衡和服务端负载均衡是两种不同的负载均衡方法,它们在不同的场景和应用中有各自的优势。以下是对它们的解释,适用的场景,实现案例以及相关的开源项目:

客户端负载均衡(Client-Side Load Balancing)

客户端负载均衡的示意图如图 1 所示。

image
图 1:客户端负载均衡

服务端负载均衡(Server-Side Load Balancing)

服务端负载均衡如图 2 所示。

image
图 2:服务端负载均衡

在实际应用中,有时也会将客户端负载均衡和服务端负载均衡结合使用,以满足特定的需求。选择哪种负载均衡方法通常取决于您的架构、部署需求以及性能要求。服务网格(如 Istio)通常使用客户端负载均衡来实现细粒度的流量控制和策略定义,而在云服务提供商中,服务端负载均衡通常用于自动扩展和流量管理。

Istio 如何实现负载均衡

在服务网格(如 Istio)中,客户端负载均衡通常是通过 Envoy 代理实现的。Envoy 是一个高性能的代理服务器,它可以用于构建服务网格的数据平面,用于处理服务之间的通信。客户端负载均衡是一种在服务消费者(客户端)一侧实现的负载均衡策略,它决定了请求应该如何路由到后端服务实例。

单集群单网络 Istio 服务网格的负载均衡如图 3 所示。

image
图 3:单集群单网络的 Istio 服务网格的负载均衡

以下是服务网格中如何实现客户端负载均衡的一般流程:

  1. Sidecar 代理: 在服务网格中,每个部署的服务实例通常都与一个 Sidecar 代理(通常是 Envoy)关联。这个 Sidecar 代理位于服务实例旁边,负责处理该服务实例的入站和出站流量。

  2. 服务注册与发现: 在服务网格中,服务实例的注册和发现通常由服务注册表(Kubernetes 的服务发现机制)处理。这些注册表维护了服务实例的信息,包括它们的网络地址和健康状态。

  3. 客户端负载均衡配置: 在客户端(服务消费者)发送请求时,Sidecar 代理会执行负载均衡策略。这些负载均衡策略通常在服务注册表中获取的服务实例列表上操作。策略可以基于多种因素进行选择,例如权重、健康状态、延迟等。

  4. 请求路由: 根据负载均衡策略,Sidecar 代理将请求路由到选择的后端服务实例。这可以包括使用轮询、加权轮询、最少连接等算法来选择目标实例。

  5. 通信处理: 一旦选择了目标实例,Sidecar 代理将请求转发给该实例,然后将响应传回给客户端。它还可以处理连接管理、故障检测和自动故障转移等任务。

总之,客户端负载均衡是在服务消费者一侧(通常是 Envoy 代理)实现的负载均衡策略,它使服务网格能够有效地分发流量并处理后端服务实例的故障。这种方式使得负载均衡决策在服务消费者的控制下,并允许更精细的流量控制和策略定义。Envoy 代理是实现客户端负载均衡的关键组件之一,它具有丰富的配置选项,可用于满足不同的负载均衡需求。

Istio 中的负载均衡类型

在 Istio 的DestinationRule资源中,loadBalancer部分用于配置负载均衡策略,控制请求如何分发到不同的服务实例或版本,如下图所示。

image
图 4:Istio 中的负载均衡配置参数

从图中我们可以看出,Istio 支持三种类型的负载均衡,分别是:

以下是与负载均衡配置相关的字段的含义:

  1. simple:这个部分定义了一些简单的负载均衡策略选项,其中包括以下选项:
    • ROUND_ROBIN:请求会依次分发到所有可用的后端实例,以轮询的方式。
    • LEAST_CONN:请求将路由到当前连接数最少的后端实例。
    • RANDOM:请求将随机路由到后端实例。
    • PASSTHROUGH:Istio 不会进行负载均衡,而是将请求直接路由到服务的一个实例,适用于特定用例。
  2. consistentHashLB:这个部分允许你配置一致性哈希负载均衡,其中包括以下字段:
    • httpHeaderName:用于哈希计算的 HTTP 标头的名称。
    • httpCookie:用于哈希计算的 HTTP Cookie 的配置,包括名称、路径和生存时间(TTL)。
    • useSourceIp:是否使用请求的源 IP 地址进行哈希计算。
    • httpQueryParameterName:用于哈希计算的 HTTP 查询参数的名称。
    • ringHash:配置环形哈希负载均衡,包括最小环大小(minimumRingSize)。
    • maglev:配置 Maglev 负载均衡,包括表格大小(tableSize)和最小环大小(minimumRingSize)。
  3. localityLbSetting:这个部分用于配置本地性负载均衡设置,其中包括以下字段:
    • distribute:定义了请求的分布,包括起始位置(from)和结束位置(to)。
    • failover:定义了故障切换,包括起始位置(from)和结束位置(to)。
    • failoverPriority:故障切换的优先级设置。
    • enabled:是否启用本地性负载均衡。

这些字段允许你根据你的需求选择适当的负载均衡策略,并配置额外的选项,以确保请求按照所需的方式分发到后端服务实例。不同的策略和配置选项可以满足各种负载均衡需求,如性能、可靠性和流量控制。关于这些字段的详细介绍请见 Istio 文档

如何在 Istio 中为服务设置负载均衡

正如我在如何理解 Istio 中的 VirtualService 和 DestinationRule这篇文章中所说的,VirtualService 主要用于设置路由规则,而服务弹性(负载均衡、超时、重试、熔断等)需要靠它和 DestinationRule 来共同维持。只有同时部署了以上两种资源,负载均衡才能真正生效。

以下是设置负载均衡的一般步骤:

  1. 创建 DestinationRule 资源:首先,你需要创建一个 DestinationRule 资源,该资源定义了服务的流量策略和目标规则。在 DestinationRule 中,你可以指定要设置负载均衡的服务的名称(host)以及负载均衡策略。

    以下是一个 DestinationRule 的示例,其中将流量分发到具有标签 “version: v1” 和 “version: v2” 的两个子集中,并使用 ROUND_ROBIN 负载均衡策略:

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: my-destination-rule
    spec:
      host: my-service.example.com
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
      subsets:
        - name: v1
          labels:
            version: v1
        - name: v2
          labels:
            version: v2
    
  2. 应用 DestinationRule:创建 DestinationRule 后,将其应用于要进行负载均衡的服务。这通常可以通过 Istio 的 VirtualService 资源来完成,通过在 VirtualService 中引用 DestinationRule。

    以下是一个 VirtualService 示例,将流量引导到名为 “my-destination-rule” 的 DestinationRule:

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: my-virtual-service
    spec:
      hosts:
        - my-service.example.com
      http:
        - route:
            - destination:
                host: my-service.example.com
                subset: v1
          weight: 80
        - route:
            - destination:
                host: my-service.example.com
                subset: v2
          weight: 20
    

    在上面的示例中,根据权重配置,80% 的流量将路由到子集 v1,而 20% 的流量将路由到子集 v2。

  3. 应用配置:最后,将 VirtualService 和 DestinationRule 资源应用到你的 Istio 环境中,以确保负载均衡规则生效。

    使用 kubectl 命令将 VirtualService 和 DestinationRule 应用到 Istio 中:

    kubectl apply -f your-service.yaml
    

通过这些步骤,你可以为你的服务设置负载均衡策略,根据需要将流量分发到不同的服务版本或实例,并控制流量的权重。这有助于实现诸如金丝雀发布、A/B 测试和灰度发布等部署策略。请根据你的具体需求和环境调整负载均衡配置。

为什么要分开配置?

在 Istio 中,负载均衡和路由是两个不同的概念,它们通常用于控制服务之间的流量和行为,因此通常分别配置在两个不同的资源对象中:DestinationRule 用于负载均衡,VirtualService 用于路由。这种分离的设计有一些优点:

  1. 模块化和清晰性: 将负载均衡和路由配置分离成两个资源对象可以使配置更加模块化和清晰。这样,您可以更容易地理解和维护这两个方面的配置,而不会使配置对象过于复杂。

  2. 可维护性: 将负载均衡和路由配置分开可以使它们更容易维护和修改,因为它们位于不同的资源对象中。这样,您可以针对不同的需求更改负载均衡策略而不会影响路由规则,反之亦然。

  3. 可重用性: 模块化的配置允许您更容易地重用配置片段。您可以在不同的 DestinationRuleVirtualService 中使用相同的负载均衡策略或路由规则,以提高配置的可重用性。

  4. 精细控制: 分离的配置允许您对每个方面进行更精细的控制。您可以根据需要为每个服务定制不同的路由规则和负载均衡策略,以满足特定的用例和要求。

虽然负载均衡和路由通常是分开配置的,但它们之间仍然存在紧密的关联,因为路由规则决定了请求将如何被路由到后端服务,而负载均衡策略决定了在所选目标服务之间如何分发流量。因此,在 Istio 中,这两个配置对象通常需要协同工作,以实现您的流量管理需求。通过将它们分开配置,使得配置更加清晰和可维护,并允许更灵活地满足不同的需求。

多集群网格中的负载均衡

在微服务领域,Istio 已被证明是管理服务通信的无价之宝。虽然它在单集群场景下表现出色,但多集群设置引入了独特的挑战,特别是在负载均衡方面。接下来我们将揭秘 Istio 中的多集群负载均衡,为您提供解决这一复杂任务的清晰路线图。

两层入口网关:实现多集群通信的关键

在涉及来自不同供应商的集群的多集群设置中,第一步是为每个集群建立一个网关。然而,需要特别注意的关键一点是需要一个唯一的用户访问入口点。尽管可以在同一集群中部署此网关,但通常建议将其放置在一个单独的集群中。

两层入口网格的部署架构如图 4 所示。

image
图 4:两层入口网关

多集群通信所需组件

基于 Istio 创建的多集群网格,通常是多网格多网络模式,为了让网格互通,我们需要添加一个一级(Tier-1)集群,并在每个集群中创建如下组件:

  1. 入口网关:每个网格必须有一个入口网关。
  2. ServiceEntry:用于允许集群发现彼此的端点。
  3. VirtualServices 和 DestinationRules:对于每个集群内部的服务发现和路由至关重要。

实战演示:一个多集群演示

在这个演示中,我将涵盖三个 GKE 上的 Kubernetes 集群,分布在不同的区域,如图 5 所示。当然你也可以使用不同的供应商或者跨供应商。在每个集群中部署了 Istio,为多集群通信奠定了基础。

建立了两层集群:一个专门托管 productpage 服务,另一个包含完整 bookinfo 的服务套件。

image
图 5:演示环境的部署情况

实现多集群路由和负载均衡

为了实现诸如负载均衡和故障转移等高级功能,解决多集群路由问题至关重要。由于一级集群也部署了 Istio,可以将先前讨论的负载均衡技巧应用于此网关。

关键步骤:

  1. 在每个集群中创建入口网关,并获取网关使用的负载均衡器的 IP 地址。

  2. 在每个集群中创建 VirtualServices、DestinationRules 和 ServiceEntries。确保 ServiceEntries 包含每个集群入口网关的入口点。

  3. 为进一步的测试,检索 Tier 1 网关的 IP 地址

    export GATEWAY_IP=$(kubectl -n tier1 get service tier1-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    

    注意:这一步需要在一级集群中操作。

一级集群的网关作为统一网关入口,你可以通过在这个集群中配置 Gateway、VirtualService、DestinationRule 和 ServiceEntry 资源对象,实现多集群的路由,如图 6 所示。

image
图 6:一级集群中的 Istio 资源

在这个演示中我们将实现基于 HTTP header 和 prefix 的多集群的路由,最终的路由路径如图 7 所示。

image
图 7:路由路径

关于操作的细节可以参考 TSB 文档中的统一网关

测试设置

演示继续进行实际测试,使用 curl 命令:

  1. 无需 HTTP 标头的请求 URL。

    curl -Ss "http://bookinfo.tetrate.io/productpage" --resolve "bookinfo.tetrate.io:80:$GATEWAY_IP" -v > index1.html
    
  2. 使用指示首选集群的 HTTP 标头请求 URL。

    curl -Ss "http://bookinfo.tetrate.io/productpage" --resolve "bookinfo.tetrate.io:80:$GATEWAY_IP" -v -H "X-CLUSTER-SELECTOR: gke-jimmy-us-west1-1" > index2.html
    curl -Ss "http://bookinfo.tetrate.io/productpage" --resolve "bookinfo.tetrate.io:80:$GATEWAY_IP" -v -H "X-CLUSTER-SELECTOR: gke-jimmy-us-west1-2" > index3.html
    

通过导出的 HTML 文件验证结果。在浏览器中分别打开 index1.htmlindex2.htmlindex3.html 这三个文件,你将看到页面 1 和页面 2 中都显示 reviews 和 details 服务不可用,只有页面 3 中的所有服务都可访问。

多集群负载均衡

演示成功展示了如何利用 HTTP 标头和路径路由。路由是负载均衡的基础。实现了多集群路由之后,你就可以将来自二级(Tier-2)集群的端点添加到一个 subset 中,从而在 DestinationRule 中实现负载均衡配置。

可以通过将二级集群中的入口网关配置为东西向网关,从而解决 Cluster 1 中的故障转移问题。请参考 Istio 文档

自动化的呼声

尽管 Istio 提供了基于 Envoy 的各种负载均衡类型,但手动在多个集群中创建资源对象容易出错且效率低下。自动化,最好是在 Istio 之上添加一个解释层,是下一个发展阶段。

Tetrate 使用 TSB 解决了这个需求,TSB 与上游的 Istio 兼容,为多集群部署提供了无缝的解决方案。有关更多信息,请访问 Tetrate 网站

总结

精通 Istio 中的多集群负载均衡对于在复杂环境中发挥微服务的全部潜力至关重要。通过谨慎的配置和合适的工具,您可以在集群之间实现强大且可靠的通信,确保您的应用程序无论部署在何处都能顺利运行。对于更精细的负载均衡调整,请考虑探索 EnvoyFilter。感谢您加入我们一起揭秘 Istio 中的多集群负载均衡之旅!

参考

如何使用 GraphQL 和 Postman 查询 SkyWalking 中的数据

2023-07-20 16:27:49

在本文中,我将解释如何使用 GraphQL 与Postman 一起从 SkyWalking 查询数据。它包括获取不记名令牌、构建查询以检索特定服务的负载指标以及使用 GraphQL 自省来查看 SkyWalking GraphQL API 架构的步骤。本文还提供了更多信息的参考。

什么是 GraphQL?

GraphQL 是 Facebook 开发的一种 API 查询语言和运行时。它允许客户端准确指定他们需要的数据并仅接收该数据作为响应,从而为传统 REST API 提供了更高效、更强大、更灵活的替代方案。使用 GraphQL,客户端可以在单个请求中查询多个资源,从而减少与服务器的往返次数并提高性能。

GraphQL 和 REST API 之间有什么区别?

GraphQL 允许客户端仅请求他们需要的数据,而 REST API 要求客户端检索资源中的所有内容,无论他们是否需要。此外,GraphQL 允许客户端在单个请求中查询多个资源,这使其比 REST API 更高效、更简洁。

如何查询 SkyWalking 数据?

SkyWalking 定义了查询阶段的通信协议。SkyWalking 原生 UI 和 CLI 使用此协议从后端持续获取数据,无需担心后端更新。

从 SkyWalking 查询指标有两种方法:

  1. GraphQL API
  2. PromQL API

本文提供了有关如何使用 GraphQL 从 SkyWalking 查询指标的指南。如果你对 PromQL API 感兴趣,可以参阅文章为 Apache SkyWalking 构建 Grafana Dashboard - 原生 PromQL 支持 。继续执行以下步骤需要安装 TSB。如果你没有,但仍想体验使用 GraphQL 在 SkyWalking 中查询数据,你可以使用 SkyWalking 提供的免费演示环境(用户名 / 密码:skywalking/skywalking)。登录演示网站并获取查询令牌。GraphQL 查询的端点地址是 http://demo.skywalking.apache.org/graphql 。构造查询的步骤与下面描述的相同。

观察 TSB 中的 GraphQL 查询

在我们使用 Postman 构建自己的 GraphQL 查询之前,我们首先观察 TSB 如何从 SkyWalking 获取数据。

  1. 打开 Chrome DevTools 并切换到“Network”选项卡。
  2. 访问网站上的Organization - Services 选项卡。

观察网络请求列表并右键单击其中一个 graphql 请求,如下图所示:

image
图 1:Chrome DevTool

你看到的 curl 命令将如下所示。在终端中执行该命令,你将从 SkyWalking 中获取 TSB 管理的服务列表。

curl '<https://saturn.tetrate.work/ui/graphql>' \\
  -H 'Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7,zh-TW;q=0.6' \\
  -H 'Cache-Control: no-cache' \\
  -H 'Client-Timestamp: 1686104776136' \\
  -H 'Connection: keep-alive' \\
  -H 'Content-Type: application/json' \\
  -H 'Cookie: ...' \\
  -H 'Origin: <https://saturn.tetrate.work>' \\
  -H 'Pragma: no-cache' \\
  -H 'Referer: <https://saturn.tetrate.work/mp/services>' \\
  -H 'Request-Id: ...' \\
  -H 'Sec-Fetch-Dest: empty' \\
  -H 'Sec-Fetch-Mode: cors' \\
  -H 'Sec-Fetch-Site: same-origin' \\
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \\
  -H 'X-Bridge-Csrf-Token: IOmJszLAqY3TRIUNhTuGu7vQgnfQY1FtgYFm+l/+Mu4EmVQU5T8EaQ7bngkCv4hQ12ZGids+I21pHMdepE9/qQ==' \\
  -H 'X-Csrf-Token: xTbxZerD3t8N3PaS7nbjKCfxk1Q9dtvvrx4D+IJohHicb0VfB4iAZaP0zh1eXDWctQyCYZWaKLhAYT3M6Drk3A==' \\
  -H 'accept: application/json' \\
  -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"' \\
  -H 'sec-ch-ua-mobile: ?0' \\
  -H 'sec-ch-ua-platform: "macOS"' \\
  --data-raw $'{"query":"query ServiceRegistryListMetrics(...)}' \\
  --compressed

注意: 上例中的某些字段太长,用点 (…) 替换

接下来,我将指导你构建一个查询来检索特定服务的负载指标。

获取 Bearer Token

首先,你需要获取网站的 Bearer Token。登录到 TSB UI,点击右上角的用户按钮,然后点击“Show token information”。在弹出窗口中,你将看到 Bearer Token,如下图所示。

image
图 2:从 TSB UI 获取 Bear Token

注意:Bearer token 的有效期比较短。当它过期时,你需要重新登录 TSB 以获取新的 token。

我们已经预先部署了bookinfo 应用程序并发送了一些测试流量。要在 Postman 客户端中使用 GraphQL 查询reviews的负载指标,请执行以下步骤:

  1. 创建一个新的 GraphQL 请求,并输入请求 URL:$TSB_ADDRESS/graphql
  2. 添加带有值Bearer $TOKENAuthorization
  3. 使用 GraphQL Introspection 查看 SkyWalking GraphQL APIs 的模式。查找并单击readMetricsValues项。你将在右侧看到变量。填写conditionduration项目,如下图所示。
image
图 3:Postman 查询

变量如下:

query ReadMetricsValues {
    readMetricsValues(condition: {
    name: "service_cpm", entity: {scope: Service, serviceName: "reviews", normal: true}
  }, duration: {
    start: "2023-06-05 0625",
    end: "2023-06-05 0627",
    step: MINUTE
  }) {
        label
        values {
            values {
                id
                value
            }
        }
    }
}

单击 Query 按钮以获取结果。它应该类似于以下内容:

{
    "data": {
        "readMetricsValues": {
            "label": null,
            "values": {
                "values": [
                    {
                        "id": "service_cpm_202306050625_cmV2aWV3cw==.1",
                        "value": 0
                    },
                    {
                        "id": "service_cpm_202306050626_cmV2aWV3cw==.1",
                        "value": 0
                    },
                    {
                        "id": "service_cpm_202306050627_cmV2aWV3cw==.1",
                        "value": 0
                    }
                ]
            }
        }
    }
}

以上是使用 SkyWalking Demo 环境测试 GraphQL 查询。TSE 也支持 GraphQL 查询,并且端点地址为$TSB_SERVER/graphql

注意:此处的查询端点与 DevTool 中看到的不同。TSB UI 特定的 GraphQL 查询端点是$TSB_SERVER/ui/graphql

有关 SkyWalking GraphQL 查询协议的详细信息,请参见GitHub

总结

在本文中,我介绍了如何在 Postman 中使用 GraphQL 查询协议查询 SkyWalking 中的数据。你可以根据 SkyWalking 的 GraphQL 模式构建自己的查询条件。TSB / TSE 中也提供了此功能。

Envoy Gateway 0.4.0 发布:自定义 API 扩展

2023-05-16 13:19:28

Envoy Gateway 是一款基于 Envoy 代理和 Kubernetes Gateway API 开发的开源 API 网关,最近发布了 0.4.0 版本。此次发布的版本着重于自定义功能,旨在为最终用户提供更多的用例。在本文中,我们将讨论此版本中可用的新自定义选项及其对用户的重要性。

自定义 Envoy 代理架构

此次版本中最主要的自定义功能之一是配置 EnvoyProxy(Envoy Gateway 定义的 CRD)部署的确切类型。你可以定义 EnvoyProxy 部署的副本数、镜像和资源限制。还可以向 EnvoyProxy 部署和服务添加注解(Annotation)。这使得不同的用例成为可能,例如:

注意
关于 Envoy Gateway 的更多自定义功能请参考 Envoy Gateway 文档。

此外,Envoy Gateway 除了默认的 Kubernetes 单租户模式以外还新增其他部署模式支持,例如多租户,如下图所示。

image
Envoy Gateway 的多租户模式示意图

分别在每个租户的 namespace 部署一个 Envoy Gateway Controller,它们监视 Kubernetes 中的 HTTPRoute 和 Service 资源,并在各自的 namespace 中创建和管理 EnvoyProxy 部署。

自定义 Envoy xDS 引导程序

此版本中的另一个重要自定义功能是自定义 Envoy xDS 引导程序。使用此功能,用户可以提供引导配置,在启动 EnvoyProxy 时配置一些静态资源。例如配置访问日志记录、跟踪和指标以发送到 SkyWalking(可以作为 APM)非常有用。此外,此版本添加了大量 CLI 工具,以帮助验证用户配置。用户可以将 CLI 用作干运行以更改引导程序中的特定字段,如果配置在语法上不正确,则将失败。

扩展控制平面

Envoy Gateway 现在允许供应商和扩展开发人员在 Envoy Gateway 管道的不同阶段添加 gRPC 钩子,以进一步扩展其功能,允许用户做一些事情,比如增强发送给 EnvoyProxy 的 xDS 配置,这在以前是不可能的。

总结

最后,Envoy Gateway 0.4.0 扩展了自定义 API,并为最终用户提供了更多用例。新的自定义功能包括自定义 Envoy 部署、Envoy xDS 引导程序以及扩展控制平面。这些新功能消除了用户创建自己的证书的需要,配置访问日志记录、跟踪和指标,并使供应商能够扩展 XDS 翻译用例。通过此版本的发布,Envoy Gateway 正变得更加用户友好,成为 Istio 的绝佳替代品。

免费的 ChatGPT 浏览器插件工具推荐 | 亲测有效

2023-04-26 13:09:28

ChatGPT 是一个强大的工具,可以根据提示生成文本响应。然而,使用浏览器版本可能会很繁琐和耗时。幸运的是,有几个浏览器扩展可以帮助您更有效地使用 ChatGPT。在本文中,我们将讨论几个我个人测试并推荐的最有用的 ChatGPT 浏览器扩展。这些插件都是完全免费的,不存在订阅或者后期收费选项,大家可以放心使用。

下图展示了安装了插件的 Chrome 浏览器中的 ChatGPT 页面。

image
安装了 Chrome 插件的 ChatGPT 页面

ChatGPT Prompt Genius

GitHub:https://github.com/benf2004/ChatGPT-Prompt-Genius

这个项目是一个多功能的 ChatGPT 浏览器扩展,它可以帮助你发现、分享、导入和使用最好的 ChatGPT 提示。你也可以把你的聊天记录保存在本地,方便以后查看和参考。你可以使用扩展的提示模板功能,轻松地找到并添加提示到你的收藏。你可以在 ChatGPT 页面上搜索、分类和选择提示,找到有创意和有用的方式使用 ChatGPT。还可以添加一些主题,比如短信、温馨的壁炉和黑客。

ChatGPT for Google

在搜索引擎结果中同时显示 ChatGPT 的回答,功能点如下:

你可以在 Chrome 网上应用商店 下载。

KeepChatGPT

GitHub:https://github.com/xcanwin/KeepChatGPT

让我们在使用 ChatGPT 过程中更高效、更顺畅,完美解决 ChatGPT 网络错误,不再频繁地刷新网页,足足省去 10 个多余的步骤。还可以取消后台监管审计。

解决了这几类报错:

  1. NetworkError when attempting to fetch resource.
  2. Something went wrong. If this issue persists please contact us through our help center at help.openai.com .
  3. This content may violate our content policy.
  4. Conversation not found.

TalkBerry

这个 Chrome 扩展的主要内容是让你可以用语音和 ChatGPT 交流,而不需要打字。它的功能有:

这个扩展可以让你更方便地使用 ChatGPT,也可以帮助你学习外语或提高口语能力。它是一个免费和开源的项目,你可以在 Chrome 网上应用商店 下载。

需要注意的是,你无法关闭用语音朗读,除非你卸载掉该扩展。

WebChatGPT

这个免费的扩展程序将相关的网络结果添加到您对 ChatGPT 的提示中,以获得更准确和最新的对话。

当你不想使用时,也可以在 ChatGPT 页面上随时关闭它。你可以在 Chrome 网上应用商店 下载该扩展。

总结

这几个 ChatGPT 浏览器扩展可以帮助您更有效地使用 ChatGPT。无论您需要更便捷的界面、带有有用功能的侧边栏,都有一款扩展可以帮助。我建议尝试每个扩展,以确定哪个最适合您的需求。有了这些工具,您可以改善您的 ChatGPT 体验,快速轻松地生成高质量的文本响应。以后再发现其他更好的插件,笔者会在本文中更新,也欢迎读者朋友们有推荐的插件可以在评论中留言。

Docker 多平台构建指南:构建 WebAssembly 镜像

2023-04-25 19:09:28

Docker 多平台构建是一种用于构建 Docker 镜像以在多种 CPU 架构和操作系统上运行的技术。它可以让用户在一个 Dockerfile 中定义一个通用的构建过程,然后使用 Docker CLI 命令将其构建为多个不同平台的镜像。这些镜像可以在不同的计算机、云平台和容器编排系统上运行,从而为用户提供更广泛的部署选项。

在多平台构建中,用户需要使用 Docker Buildx 插件来构建镜像。Docker Buildx 可以构建并输出多个不同平台的镜像,包括 x86、ARM、IBM Power 等。用户可以使用该插件创建多种平台的构建环境,并使用这些环境构建镜像。

需要注意的是,多平台构建需要在支持多平台的 Docker 主机上进行。在这种主机上,Docker 可以使用 QEMU 等模拟器来模拟其他平台的环境,从而实现构建多种平台的镜像。

什么是 docker buildx?

Docker Buildx 是 Docker 的一个插件,它提供了一种简单、高效的方式来构建和打包 Docker 镜像。它能够在多个平台上构建和输出 Docker 镜像,包括 Linux、Windows、macOS 等,支持 CPU 架构和操作系统等多种参数的设置。

Docker Buildx 在构建镜像时使用了 BuildKit,这是 Docker 官方推出的一个基于 Go 语言实现的高性能构建引擎。BuildKit 提供了更快的构建速度、更小的镜像体积、更好的缓存管理等优势,也可以在 Docker Buildx 之外使用。

使用 Docker Buildx,可以将不同平台上的 Docker 镜像构建合并到一个 manifest 中,使得用户只需要下载一个 manifest,就可以获取多个平台的镜像。这为跨平台开发和分发应用程序提供了很大的便利。

Docker buildx 实现多平台构建的原理

Docker buildx 实现多平台镜像构建的原理是基于 Docker 的多架构支持。Docker 可以在一个主机上运行多个容器,每个容器运行在自己的隔离环境中,相互独立。而 Docker 镜像则是用于创建容器的基础文件系统。

在 Docker 中,不同的 CPU 架构和操作系统可以使用不同的 base image(基础镜像)进行构建。而 Docker buildx 可以自动识别当前主机的架构和操作系统,并选择合适的 base image 进行构建。在构建过程中,Docker buildx 会使用 BuildKit 引擎进行构建,支持多平台的交叉编译和镜像打包。

在构建完成后,Docker buildx 会将不同平台上的镜像打包成一个 manifest 文件,其中包含了所有平台的镜像信息。用户可以通过 Docker CLI 命令或者 Docker registry 接口来操作 manifest 文件,获取不同平台上的镜像。对于不支持多架构的 Docker 版本,可以通过安装 Docker CLI 的 experimental 版本来使用 Docker buildx。

Docker buildx 利用了 Docker 的多架构支持和 BuildKit 引擎,实现了跨平台的 Docker 镜像构建和分发。

Docker BuildKit 引擎简介

BuildKit 是 Docker 官方推出的一个高性能的构建引擎,它可以用于构建 Docker 镜像、构建应用程序以及执行其他构建任务。BuildKit 引擎采用了分布式的架构,可以并行地执行多个构建任务,提高构建效率。

BuildKit 引擎的主要特点包括:

  1. 高性能:BuildKit 引擎采用了高效的缓存管理机制,能够快速地执行增量构建,减少构建时间。同时,它还能够自动优化构建过程,选择最佳的构建路径和策略,进一步提高构建性能。
  2. 多平台支持:BuildKit 引擎支持多种 CPU 架构和操作系统,能够在不同平台上构建和输出 Docker 镜像。在 Docker buildx 中,BuildKit 引擎可以自动识别当前主机的架构和操作系统,并选择合适的构建方案。
  3. 模块化设计:BuildKit 引擎采用了模块化的设计,可以根据需要动态加载和卸载不同的模块。这使得 BuildKit 引擎更加灵活和可扩展,可以支持各种不同的构建任务。
  4. 安全性:BuildKit 引擎采用了安全的构建方式,可以自动执行一系列的安全检查,确保构建过程中不会引入漏洞或其他安全问题。同时,BuildKit 引擎还支持签名和加密等安全功能,保护用户的构建数据和镜像。

Docker buildx 支持哪些平台?

Docker buildx 支持的平台主要包括以下几种:

  1. Linux:包括多种 CPU 架构和操作系统,如 x86_64、ARM、IBM Power、IBM Z 等。
  2. Windows:包括多种 CPU 架构和操作系统,如 x86_64、ARM64 等。
  3. macOS:支持 Intel、Apple M1 架构。

除了以上平台外,Docker buildx 还支持构建和输出多种其他平台的 Docker 镜像,包括 FreeBSD、Solaris 等。用户可以通过指定对应的 platform 参数来构建和输出不同平台的 Docker 镜像,例如:

docker buildx build --platform linux/amd64,linux/arm64 .

这个命令将会构建一个同时支持 x86_64 和 ARM64 架构的 Docker 镜像。用户也可以通过指定不同的 buildx 构建配置来支持更多的平台,例如使用 qemu-user-static 等模拟器来支持其他的 CPU 架构。总之,Docker buildx 的多平台支持非常强大,为跨平台开发和分发应用程序提供了便利。

Docker buildx 引擎的架构与组成

Docker buildx 引擎的架构是一个分布式的构建系统,通过多阶段、多组件的设计,实现了高性能、多平台支持、安全性等优点,为 Docker 镜像构建和应用程序构建提供了强大的支持。它由以下几个主要组成部分组成:

  1. CLI:提供了命令行接口,用户可以通过命令行来执行构建任务、管理构建配置等操作。
  2. BuildKit 引擎:作为 Docker buildx 的构建引擎,它负责执行构建任务,生成 Docker 镜像等。BuildKit 引擎具有高性能、多平台支持、安全性等优点。
  3. 构建器(Builder):构建器是一个 Docker 容器,它包含了构建所需要的环境和工具,可以执行构建任务。在 Docker buildx 中,可以配置多个构建器,以支持多个平台和多个构建环境。
  4. 并行器(Scheduler):并行器是负责协调和管理多个构建器的组件,它可以自动选择最佳的构建器执行构建任务,并将任务分配给合适的构建器。并行器还可以执行构建任务的并行处理,提高构建效率。
  5. 缓存管理器(Cache Manager):缓存管理器是负责管理构建过程中的缓存数据,可以快速执行增量构建,减少构建时间。在 Docker buildx 中,缓存管理器可以自动选择合适的缓存方案,包括本地缓存和远程缓存等。
  6. 输出器(Exporter):输出器负责将构建生成的 Docker 镜像输出到指定的仓库或者本地文件系统中。在 Docker buildx 中,输出器可以自动识别当前平台和目标平台,选择合适的镜像格式和输出路径。

docker buildx 命令的使用

使用 docker buildx 命令可以方便地进行 Docker 镜像的构建和输出。下面是一些常用的 docker buildx 命令及其用法:

查看当前的 buildx 构建器列表

docker buildx ls

创建新的 buildx 构建器

docker buildx create --name mybuilder

切换到指定名称的 buildx 构建器

docker buildx use mybuilder

设置 buildx 构建器的平台支持

docker buildx inspect --bootstrap
docker buildx inspect --platform
docker buildx build --platform linux/amd64,linux/arm64 .

构建 Docker 镜像:

docker buildx build --tag myimage .

输出 Docker 镜像到本地文件系统

docker buildx build --output=type=local,dest=./output .

输出 Docker 镜像到 Docker Hub 或其他远程仓库

docker buildx build --tag myrepo/myimage --push .

删除指定名称的 buildx 构建器

docker buildx rm mybuilder

除了以上命令外,docker buildx 还支持许多其他的参数和选项,例如设置构建缓存、并行处理、构建标签等。用户可以通过查看官方文档或者使用 –help 选项来了解更多详情。

理解 buildx 构建器

在 Docker 中,构建器(Builder)是指一个 Docker 容器,它包含了构建所需要的环境和工具,可以执行构建任务。Docker buildx 构建器是指使用 BuildKit 引擎的多平台构建器,可以通过 Docker CLI 命令进行管理和操作。在使用 Docker buildx 构建器时,用户可以配置多个构建器,以支持多个平台和多个构建环境。

用户可以通过创建、切换、查看和删除构建器,来管理和维护 Docker buildx 的构建环境。构建器的主要作用是提供一个干净、独立的构建环境,避免构建过程中的依赖冲突和环境污染。此外,构建器还可以方便地进行版本管理和共享,以便多个用户或者团队协同构建 Docker 镜像。

Docker buildx 构建器还支持多平台构建,用户可以在同一个构建器中设置多个平台,以便生成跨平台的 Docker 镜像。通过 Docker buildx 构建器,用户可以轻松实现 Docker 镜像的多平台构建,提高构建效率和应用程序的兼容性。

为什么本地看不到 Docker buildx 构建的镜像?

这通常是因为你当前使用的 Docker context 不支持编译出来的镜像架构。例如 Orbstack,虽然它支持编译跨平台的镜像,但是执行 docker buildx 构建出来的镜像不会直接保存在本地的 Docker 镜像仓库中,而是保存在构建器(Builder)的缓存中。这是因为 Docker buildx 采用了分层构建的方式,构建出的每一层镜像都可以被重用,以减少构建时间和磁盘空间的占用。

你应该使用 docker context 命令切换会 Docker 默认的上下文环境再执行构建,这样构建出来的跨平台镜像就可以在本地看见了。

如何将多平台镜像保存到本地?

要将 Docker buildx 构建的多平台镜像保存到本地,可以使用 --output 选项指定输出类型为 type=local,并指定输出目录,例如:

docker buildx build --platform linux/amd64,linux/arm64 --output type=local,dest=./output .

上述命令将构建包含 linux/amd64linux/arm64 两种平台的镜像,并将输出类型设置为本地(type=local),输出目录为 ./output

构建完成后,输出目录中会生成多个子目录,每个子目录分别对应一个平台,其中包含该平台下的镜像文件。

如果只想保存其中一个平台的镜像,可以在 --output 选项中指定要保存的平台,例如:

docker buildx build --platform linux/amd64,linux/arm64 --output type=local,dest=./output/linux/amd64 .

上述命令将只保存 linux/amd64 平台的镜像,输出到 ./output/linux/amd64 目录中。

需要注意的是,--output 选项只支持部分输出类型,如果要将镜像保存到其他类型的输出(例如 tar 包、OCI 存储、Docker registry 等),需要使用其他的输出插件和选项。具体细节可以参考 Docker 官方文档

如何使用构建 Wasm 镜像?

WebAssembly 是一种中间代码格式,需要使用编译器将源代码编译为 WebAssembly 格式的二进制文件,再将其打包成镜像。以下是构建 WebAssembly 镜像的一般步骤:

  1. 编写 WebAssembly 源代码,并使用编译器将其编译为 WebAssembly 格式的二进制文件。例如使用 Rust 编写代码,并使用 Cargo 编译出 .wasm 文件。

  2. 编写 Dockerfile 将 Wasm 二进制文件添加到空镜像中。例如:

    # syntax=docker/dockerfile:1
    FROM scratch
    COPY ./target/wasm32-wasi/debug/hello-wasm.wasm /hello.wasm
    ENTRYPOINT [ "hello.wasm" ]
    
  3. 使用 docker buildx 命令构建镜像,例如 docker buildx build --platform wasi/wasm32 -t jimmysong/hello-wasm . 将在本地构建。若你想将该镜像同时同时推送到 Docker Hub,可以在命令中加上 --push标志。基于 WebAssembly 平台的镜像并上传到 Docker Hub。

注意事项

除了构建多平台镜像、导出和加载镜像外,还有一些 Docker buildx 命令的常用操作及注意事项,包括:

  1. -progress 选项:可以使用 -progress 选项指定构建过程的输出格式,包括 autoplaintty 三种格式。
  2. -no-cache 选项:可以使用 -no-cache 选项禁用构建过程中的缓存机制,强制重新构建镜像。
  3. -push 选项:可以使用 -push 选项将构建的镜像推送到 Docker registry 中。
  4. -tag 选项:可以使用 -tag 选项为构建的镜像指定标签。
  5. -file 选项:可以使用 -file 选项指定 Dockerfile 文件的路径。
  6. -build-arg 选项:可以使用 -build-arg 选项传递构建参数给 Dockerfile 中的指令。
  7. 构建上下文的注意事项:构建上下文指的是 Dockerfile 文件所在的目录,以及构建过程中需要用到的其他文件。在构建过程中需要尽量减少构建上下文的大小,避免构建过程中传输大量不必要的文件。可以使用 .dockerignore 文件排除不需要传输的文件。

需要注意的是,Docker buildx 是一个比较新的命令,不同版本的 Docker Engine 可能会存在差异,因此在使用时需要注意查阅官方文档,并根据实际情况进行操作。

为什么 Docker 要增加 WebAssembly 运行时?

2023-04-07 18:45:40

Docker 发展史:四个重大举措,影响深远! 这篇文章中我提到了 Docker 从一开始引领容器运行时,再到在容器编排这一维度上落后于 Kubernetes。为了在保住容器运行时的统治地位,Docker 公司提出了 OCI 并通过 containerd-wasm-shim 支持更多的 WebAssembly 运行时。

为了解决 Docker 在安全、稳定性、性能及可移植性方面的局限性,Kubernetes 社区开发了具有不同实现和功能的其他容器运行时,并为其制定了容器运行时接口(CRI)规范。目前实现该规范的容器运行时有 containerd、cri-o。还有 katacontainers、gvisor 等未实现 CRI 但是可以通过添加虚拟化层在 Kubernetes 上运行的其他容器运行时。

开放容器倡议 (OCI) 旨在定义容器镜像格式和运行时的行业标准,Docker 捐赠了其运行时 runc 作为该标准的第一个实现。最近,WASM 社区对 OCI 工具链表现出了兴趣,Docker 现在支持 WebAssembly 模块作为其工件之一。现在 Docker Hub 已经支持除了镜像以外的,Helm、Volume 和 WebAssembly 等常用工件。

使用 Docker 构建包含 WebAssembly 模块的镜像,并保存在 Docker Hub 中。通过 containerd-wasm-shim,可以让它们在 Kubernetes 中运行,如下图所示。

image
在 Kubernetes 中运行 WebAssembly 模块

Containerd 是一种符合 CRI(Container Runtime Interface)规范的容器运行时,是由 Docker 公司开源并贡献给 CNCF 的。只要支持 CRI 规范的运行时都可以在 Kubernetes 中运行。

关于以上提到的名词 containerd、CRI、OCI 等的关系介绍,可以参考 Docker,containerd,CRI,CRI-O,OCI,runc 分不清?看这一篇就够了

在 Docker 中运行 WebAssembly 应用相对 Linux 镜像有什么优势?

使用 Docker 运行 WebAssembly 应用相对运行 Linux 镜像有以下优势。

更高的性能

WebAssembly 应用的启动时间更短,因为它不需要启动整个操作系统,而 Linux 容器需要。WebAssembly 模块的冷启动时间比 Docker 容器快 100 倍。WebAssembly 模块的内存占用更小,因为它是一个二进制格式,可以高效地压缩代码和依赖,而 Docker 容器需要打包整个镜像。WebAssembly 模块的大小一般在 1MB 以内,而 Docker 镜像的大小可以达到 100 或 200 MB。

更高的可移植性

WebAssembly 应用是一个架构中立的格式,只要有相应的运行时,就可以在任何底层架构上运行,而不需要考虑不同架构之间的兼容性问题。Docker 容器需要针对不同的架构构建不同的镜像,可能会存在一些潜在的安全风险或漏洞。

更好的安全性和隔离性

WebAssembly 应用可以提供代码级别的安全性,防止恶意代码访问系统资源,具体来说:

因为有以上优势,WebAssembly 在一些场景下比 Docker 容器更有优势,例如边缘计算、云原生应用和微服务。当然,WebAssembly 应用也有一些局限性,比如不支持多线程、垃圾回收和二进制打包等。因此,并不是所有的场景都适合使用 WebAssembly 应用。你可以根据你的具体需求和偏好来选择合适的技术方案。

如何在 Docker 中运行 WebAssembly 应用?

在 Docker 中运行 WebAssembly 应用的方式与普通的 Linux 镜像没有太大的不同,只是在运行时需要指定下平台和运行时。下面的例子来自 Docker 官方文档,以在 Docker Desktop 中为例运行 WebAssembly 应用:

docker run -dp 8080:8080 --name=wasm-example --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm32 michaelirwin244/wasm-example

其中:

目前 Docker 支持四种 WebAssembly 运行时,分别为:

运行时名称 API 名称 开发者 基金会托管
spin io.containerd.spin.v1 Fermyon
SpiderLightning io.containerd.slight.v1 DeisLabs
WasmEdge io.containerd.wasmedge.v1 SecondState CNCF 沙箱项目
Wasmtime io.containerd.wasmtime.v1 Mozilla、Fastly、Intel、Red Hat 等公司 字节码联盟项目

在命令行终端中输入以下命令可以查看 WebAssembly 应用的运行情况:

curl http://localhost:8080/

你将看到如下输出:

Hello world from Rust running with Wasm! Send POST data to /echo to have it echoed back to you

你还可以向/echo端点发送 POST 测试请求:

curl localhost:8080/echo -d '{"message":"Hello"}' -H "Content-type: application/json"

你将看到如下输出:

{"message":"hello"}

总结

本文介绍了 Docker 为什么要增加对 WebAssembly 的支持,以及在 Docker 中运行 WebAssembly 应用的优势和方法。WebAssembly 应用相对于 Linux 镜像有更高的性能、可移植性和安全性,适用于边缘计算、云原生应用和微服务等场景。Docker 支持四种 WebAssembly 运行时,分别为 spin、spiderlightning、WasmEdge 和 wasmtime。在接下来的文章中我将介绍如何开发一个 WebAssembly 应用,敬请期待。

参考

Docker 发展史:四个重大举措,影响深远!

2023-04-06 21:25:40

在 2017 年的容器编排大战中,Docker 公司失败后沉寂了几年,但近年来又开始频繁行动,例如腾退开源组织账号,支持 WebAssembly 等。本文将回顾 Docker 公司发展过程中的四个重大举措,这些措施深深地影响了 Docker 公司的发展,也对 Docker 甚至 Kubernetes 社区产生了深远的影响。

当我们在谈论 Docker 时我们在谈论什么?

首先我们需要先确定 Docker 这个词的含义。当人们在谈论 Docker 时可能指的是:

  1. Docker 公司
  2. Docker 软件栈
  3. Docker 命令行工具
  4. Docker 容器运行时

为什么同一个词会有这么多不同的意思呢?这都是有历史原因的。Docker 软件于 2013 年发布,起初定位为开发者工具。作为最早发布的容器工具,它迅速走红,并成为容器技术的代名词。但它最初只是在单机上运行,有太多耦合的接口设计。后来容器集群出现,才需要用到容器编排调度工具。因为 Kubernetes 具有丰富的功能和扩展性,Docker 公司推出的 Swarm 在这场容器编排大战中败下阵来。归根结底,Docker 面向开发者,而容器运行时则面向机器,只需要对应的接口即可,不需要那么丰富的管理工具。如今,Docker 仍然是最受开发者喜爱的容器工具之一,其 Docker Hub 是全球最大的镜像仓库。

将 Docker 项目改名为 Moby

2017 年 4 月,Docker 公司将 Docker 项目重命名为 Moby,详见 Introducing Moby Project: a new open-source project to advance the software containerization movement

Moby Project 是一个新的开源项目,旨在推动软件容器化运动的发展,帮助生态系统让容器技术走向主流。它提供了一个组件库,一个用于将组件组装成定制的基于容器的系统的框架,以及一个让所有容器爱好者可以实验和交流想法的地方。

Moby Project 和 Docker 的区别和联系是:

支持 Kubernetes 调度

Docker 公司在 2017 年 12 月发布的 Docker 17.12 版本中开始支持 Kubernetes。在此之前,Docker 公司一直在发展自己的容器编排和调度工具 Docker Swarm。然而,Kubernetes 在容器编排和调度方面具有更广泛的支持和社区贡献,已经成为了业界标准。因此,Docker 公司决定将 Kubernetes 集成到 Docker 平台中,以提供更广泛的选择和更好的用户体验。Docker 公司在 Docker Desktop 和 Docker Enterprise 中提供了 Kubernetes 的集成支持,使得 Kubernetes 和 Docker 容器可以更加方便地部署和管理。同时,Docker 公司也开发了一些工具,如 Kompose 和 Docker Compose,使得用户可以将 Docker Compose 配置文件转换为 Kubernetes YAML 文件,以便更加方便地将应用程序从 Docker Swarm 迁移到 Kubernetes。

Kubernetes 不再支持 Docker 运行时

Kubernetes 从 v1.20 起不再支持 Docker 运行时并在 2022 年 4 月发布的 v1.24 中被完全移除,如下图所示。这意味着在 Kubernetes 中只能使用 containerd 或 CRI-O 容器运行时,不过你依然可以使用 Docker 镜像,只是无需使用 docker 命令或 Docker 守护程序。

image
Kubernetes v1.24 正式移除 Docker 运行时

Kubernetes v1.24 正式移除 Docker 运行时

腾退开源组织账号

2023 年 3 月,据 Alex Ellis 的博客 介绍,Docker 公司决定删除一些开源组织的账户和镜像,除非他们升级到付费的团队计划,这对开源社区造成了很大的困扰和不安。很多 Docker 忠实拥护者和贡献者对 Docker 的这一举动表示了不满和失望。

这一事件是这样的:

增加对 WebAssembly 运行时的支持

2022 年 10 月,Docker 公司发布了 Docker+Wasm 技术预览,这是一个特殊的构建,可以让开发者更容易地使用 Docker 运行 Wasm 工作负载。作为这次发布的一部分,Docker 还宣布将加入 Bytecode Alliance 作为一个投票成员。

Wasm 是一种新技术,可让你在沙箱环境中运行 40 多种语言的应用程序代码,包括 Rust,C,C++,JavaScript 和 Golang。最初,Wasm 的用例是在浏览器中运行本地代码,如 Figma,AutoCAD 和 Photoshop 等。现在,一些公司如 Vercel,Fastly,Shopify 和 Cloudflare 等支持使用 Wasm 在边缘和云端运行代码。

Docker+Wasm 技术预览包括:

2023 年 3 月 Docker 公司又发布了 Docker+Wasm 技术预览 2,包括了三个新的 Wasm 运行时引擎:Fermyon 的 spin,Deislabs 的 slight,和 Bytecode Alliance 的 wasmtime。

该版本的主要更新是:

总结

本文介绍了 Docker 发展过程中的四个重大举措:Moby Project、支持 Kubernetes、删除开源组织账号和增加对 WebAssembly 运行时的支持。其中,Moby Project 旨在推动容器技术走向主流,支持 Kubernetes 的举措提供了更广泛的选择和更好的用户体验,删除开源组织账号的举措引起了开源社区的不满和失望,增加对 WebAssembly 运行时的支持的举措则扩展了 Docker 的应用场景。

参考