mirror of https://github.com/istio/istio.io.git
7332 lines
671 KiB
XML
7332 lines
671 KiB
XML
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Istio Blog</title><description>Connect, secure, control, and observe services.</description><link>/v1.12</link><image><url>/v1.12/favicons/android-192x192.png</url><link>/v1.12</link></image><category>Service mesh</category><item><title>中国首次 Istio meetup 圆满结束!</title><description>
|
||
<p>2021 年 7 月 10 号 Istio 社区在中国的首场 meetup 在北京圆满结束.这次活动受到了中国 Istio 开发者的热烈欢迎:有 292 人报名了本次活动,大约有 140 人现场参与了本次活动,在线观看直播的人数在高峰时段达到 2000 多人.现场的与会者们也做了热烈的面对面的讨论,性能提升,数据平面的升级,跨集群管理是很多开发者关注的问题.</p>
|
||
<h2 id="presentations">演讲资料</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>议题</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><a href="./IstioMeetupChina-服务网格热升级技术分享.pdf">《服务网格数据平面热升级技术分享》史泽寰-阿里云</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="./IstioMeetupChina-EnvoyPrincipleIntroductionAndOnlineProblemPit.pdf">《Envoy 原理介绍及线上问题采坑》张伟-华为云容器网格数据面技术专家</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="./IstioMeetupChina-AccelerateServiceMeshNetworkwithebpf.pdf">《使用 eBPF 加速 Istio/Envoy 网络》钟露瑶-Intel云计算软件工程师</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="./IstioMeetupChina-Full-stackServicemesh-howAerakihelpsyoumanageanyLayer7trafficinIstio.pdf">《全栈服务网格- <code>Aeraki</code>助你在 Istio 中管理任意七层流量》赵化冰-腾讯云高级工程师</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="./IstioMeetupChina-服务网格安全-理解IstioCNI.pdf">《服务网络安全-理解<code>IstioCNI</code>》张之晗-Tetrate</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>感谢来自中国的 Istio 社区成员的工作举办这次活动,感谢来自 Istio 社区的 Maria Cruz 和 Craig Box 的大力支持!</p></description><pubDate>Thu, 15 Jul 2021 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2021/istiomeetups-china-report/</link><author>Iris Ding (Intel), Maria Cruz (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2021/istiomeetups-china-report/</guid><category>community</category><category>meetup</category></item><item><title>中国首次 Istio meetup 来了!</title><description>
|
||
<p>随着云原生技术在国内的普及,Istio 近两年在中国也越来越受到开发者的广泛应用,几乎所有中国的 CSP 都在基于 Istio 创建和运行他们的 Service Mesh 产品。自从 2021 年 2 月举办的第一届 IstioCon 技术峰会广受开发者们欢迎,开发者们也表达了强烈的诉求,希望能看到和参与更多的 Istio 技术 Meetup,有更多的技术爱好者一起来共同分享交流。</p>
|
||
<p>为此 Istio 社区联动了信通院、阿里云、华为云、英特尔、腾讯云、Tetrate 六位合作伙伴共同主办国内首届 Istio Meetup China,并邀请了多位业内专家和大家一起分享全面的 Istio 技术实践。干货实在,席位有限,先到先得。请通过此<a href="https://www.huodongxing.com/event/7604616393700?td=3381727549788">链接</a>报名.</p>
|
||
<p><strong>活动时间</strong>:2021 年 7 月 10 日 13:00-17:30</p>
|
||
<p><strong>活动地点</strong>:北京市海淀区花园北路52号中国信息通信研究院 科研楼二层工业互联网展厅(正对北门的黄色大楼)</p>
|
||
<h2 id="agenda">日程安排</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>时间 (中国本地时间 GMT+8)</th>
|
||
<th>议题</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>13:30 - 13:50</td>
|
||
<td>活动签到</td>
|
||
</tr>
|
||
<tr>
|
||
<td>13:50 - 14:00</td>
|
||
<td>欢迎致辞 - Craig Box (Istio steering committee member), 丁少君 (Iris Ding) (Intel 云计算软件工程师)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>14:00 - 14:30</td>
|
||
<td>《服务网格技术能力要求》标准解读 信通院 云计算部工程师 尹夏梦雪</td>
|
||
</tr>
|
||
<tr>
|
||
<td>14:30 - 15:00</td>
|
||
<td>《服务网格数据平面热升级技术分享》 史泽寰 阿里云</td>
|
||
</tr>
|
||
<tr>
|
||
<td>15:00 - 15:30</td>
|
||
<td>《Envoy 原理介绍及线上问题采坑》 张伟:华为云容器网格数据面技术专家</td>
|
||
</tr>
|
||
<tr>
|
||
<td>15:30 - 15:45</td>
|
||
<td>茶歇交流</td>
|
||
</tr>
|
||
<tr>
|
||
<td>15:45 - 16:15</td>
|
||
<td>《使用 eBPF 加速 Istio/Envoy 网络》 钟露瑶 Intel 云计算软件工程师</td>
|
||
</tr>
|
||
<tr>
|
||
<td>16:15 - 16:45</td>
|
||
<td>《全栈服务网格 - <code>Aeraki</code> 助你在 Istio 中管理任意七层流量》 赵化冰 腾讯云高级工程师</td>
|
||
</tr>
|
||
<tr>
|
||
<td>16:45 - 17:15</td>
|
||
<td>《服务网络安全:理解 Istio CNI》 张之晗 Tetrate</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>感谢来自中国的 Istio 社区成员的工作和支持来举办这次活动,热烈期待您的参与!</p></description><pubDate>Tue, 06 Jul 2021 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2021/istiomeetups-china/</link><author>Iris Ding (Intel), Maria Cruz (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2021/istiomeetups-china/</guid><category>community</category><category>meetup</category></item><item><title>加入我们,参加 2021 年的第一届 IstioCon!</title><description><p>IstioCon 2021 将是 Istio(业界<a href="https://www.cncf.io/wp-content/uploads/2020/11/CNCF_Survey_Report_2020.pdf">最流行的服务网格</a>)的开幕会议。在成立的第一年, IstioCon 将实现 100% 虚拟化,将全球各地的社区成员与 Istio 的生态系统联系起来。该会议将于 2 月底举行。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:40.3125%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/istiocon-2021/istioconlogo.jpg" title="">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/istiocon-2021/istioconlogo.jpg" alt="IstioCon logo" />
|
||
</a>
|
||
</div>
|
||
<figcaption></figcaption>
|
||
</figure>
|
||
<p>与 IstioCon 有关的所有信息都将在<a href="https://events.istio.io/">会议网站</a>上发布。IstioCon 提供了一个展示在生产中运行 Istio 的经验教训和在 Istio 社区动手积累经验的机会,并将邀请来自整个 Istio 生态系统的维护者参加。目前,我们鼓励 Istio 用户,开发人员,合作伙伴和倡导者<a href="https://sessionize.com/istiocon-2021/">通过会议的 CFP 门户提交会议建议</a>。会议提供了一系列主题演讲、技术演讲、简短演讲、研讨会和路线图会议。 从以下形式中选择提交一个会话提案到 IstioCon:</p>
|
||
<ul>
|
||
<li><strong>演讲:</strong> 演讲时间 40 分钟,最多 2 人</li>
|
||
<li><strong>座谈会:</strong> 3 至 5 名发言者讨论 40 分钟</li>
|
||
<li><strong>研讨会:</strong> 160 分钟(2 小时 40 分钟),由 1-4 名演讲者进行深入的亲身演示</li>
|
||
<li><strong>简短演讲:</strong> 10 分钟演讲,限 1 人</li>
|
||
</ul>
|
||
<p>这个由社区主导的活动还准备了两个小时的社交时间来减轻 Istio 社区、供应商和维护人员的负担。参加活动是免费的,并且只要参加者登记就能参加。</p>
|
||
<p>请持续关注了解更多关于本次会议的信息,我们希望您能参加 2021 年的第一届 IstioCon!</p></description><pubDate>Tue, 08 Dec 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/istiocon-2021/</link><author>Istio 指导委员会</author><guid isPermaLink="true">/v1.12/zh/blog/2020/istiocon-2021/</guid><category>IstioCon</category><category>Istio</category><category>conference</category></item><item><title>处理 Docker Hub 速率限制</title><description>
|
||
<p>从 2020 年 11 月 20 日开始,Docker Hub 在镜像拉取中引入了<a href="https://www.docker.com/increase-rate-limits">速率限制</a>。</p>
|
||
<p>因为 Istio 使用 <a href="https://hub.docker.com/u/istio">Docker Hub</a> 作为默认镜像仓库,所以在大型集群上使用可能会由于超出速率限制导致 Pod 无法启动。这对 Istio 来说有很大问题,因为通常 Istio 的 sidecar 镜像与集群中的大多数 Pod 是一起启动的。</p>
|
||
<h2 id="mitigation">防范</h2>
|
||
<p>Istio 允许您指定一个自定义 docker 镜像仓库,可用于从您的私有仓库中获取容器镜像。在安装时通过 <code>--set hub=&lt;some-custom-registry&gt;</code> 来配置。</p>
|
||
<p>Istio 在 <a href="https://gcr.io/istio-release">Google 容器仓库</a> 提供了官方镜像。可以通过 <code>--set hub=gcr.io/istio-release</code> 来配置。这适用于 Istio 1.5 及以上版本。</p>
|
||
<p>或者,您可以将 Istio 官方镜像拷贝到您自己的镜像仓库中。根据您的使用场景,如果您的集群运行在特定镜像仓库的环境中(例如,在 AWS 上,您可能希望将镜像映射到 Amazon ECR),或者您对安全性有严格的要求(对公共仓库的访问受限制),则此操作特别有用。您可以使用以下脚本完成此操作:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ SOURCE_HUB=istio
|
||
$ DEST_HUB=my-registry # Replace this with the destination hub
|
||
$ IMAGES=( install-cni operator pilot proxyv2 ) # Images to mirror.
|
||
$ VERSIONS=( 1.7.5 1.8.0 ) # Versions to copy
|
||
$ VARIANTS=( &#34;&#34; &#34;-distroless&#34; ) # Variants to copy
|
||
$ for image in $IMAGES; do
|
||
$ for version in $VERSIONS; do
|
||
$ for variant in $VARIANTS; do
|
||
$ name=$image:$version$variant
|
||
$ docker pull $SOURCE_HUB/$name
|
||
$ docker tag $SOURCE_HUB/$name $DEST_HUB/$name
|
||
$ docker push $DEST_HUB/$name
|
||
$ docker rmi $SOURCE_HUB/$name
|
||
$ docker rmi $DEST_HUB/$name
|
||
$ done
|
||
$ done
|
||
$ done
|
||
</code></pre></description><pubDate>Mon, 07 Dec 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/docker-rate-limit/</link><author>John Howard (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/docker-rate-limit/</guid><category>docker</category></item><item><title>2020 年指导委员会选举结果</title><description><p>上个月,我们<a href="../steering-changes/">宣布了对指导委员会章程的修订</a>,向更多贡献者和社区成员开放了治理角色。指导委员会现在由 9 个按比例分配的贡献席位和 4 个选举的社区席位组成。</p>
|
||
<p>我们已经结束了社区席位的<a href="https://github.com/istio/community/tree/master/steering/elections/2020">就职选举</a>,并且我们很高兴欢迎以下新成员加入委员会:</p>
|
||
<ul>
|
||
<li><a href="https://github.com/istio/community/blob/master/steering/elections/2020/nrjpoddar.md">Neeraj Poddar</a> (Aspen Mesh)</li>
|
||
<li><a href="https://github.com/istio/community/blob/master/steering/elections/2020/zackbutcher.md">Zack Butcher</a> (Tetrate)</li>
|
||
<li><a href="https://github.com/istio/community/blob/master/steering/elections/2020/ceposta.md">Christian Posta</a> (Solo.io)</li>
|
||
<li><a href="https://github.com/istio/community/blob/master/steering/elections/2020/hzxuzhonghu.md">Zhonghu Xu</a> (Huawei)</li>
|
||
</ul>
|
||
<p>他们加入了谷歌、IBM/Red Hat 和 Salesforce 的贡献席位持有者。现在我们有来自 7 个组织的指导代表,反映了我们的贡献者生态系统的广度。</p>
|
||
<p>感谢每一个参与选举过程的人。下一次选举将在 2021 年 7 月举行。</p></description><pubDate>Tue, 29 Sep 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/steering-election-results/</link><author>Istio 指导委员会</author><guid isPermaLink="true">/v1.12/zh/blog/2020/steering-election-results/</guid><category>istio</category><category>steering</category><category>governance</category><category>community</category><category>election</category></item><item><title>在网格外部署多个控制平面</title><description>
|
||
<h2 id="overview">概览</h2>
|
||
<p>根据与不同的服务网格用户和供应商合作的经验,我们认为典型的服务网格有 3 个关键角色:</p>
|
||
<ul>
|
||
<li><p>网格操作员,管理服务网格控制平面的安装和升级。</p></li>
|
||
<li><p>网格管理员,通常被称为平台所有者,他拥有服务网格平台,并定义了服务所有者采用服务网格的总体策略和实现。</p></li>
|
||
<li><p>网格用户,通常称为服务所有者,在网格中拥有一个或多个服务。</p></li>
|
||
</ul>
|
||
<p>在 1.7 版本之前,Istio 要求控制平面在网格的一个<span class="term" data-title="Primary Cluster" data-body="&lt;p&gt;主集群是具有&lt;a href=&#34;/zh/docs/reference/glossary/#control-plane&#34;&gt;控制平面&lt;/a&gt;
|
||
的&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;集群&lt;/a&gt;。
|
||
一个网格可以有一个以上的主集群,以用于 HA 或需要低延迟的场景。
|
||
主集群可以充当&lt;a href=&#34;/zh/docs/reference/glossary/#remote-cluster&#34;&gt;从集群&lt;/a&gt;的控制平面。&lt;/p&gt;
|
||
">主要集群</span>中运行,导致网格操作员和网格管理员之间没有分离。 Istio 1.7 引入了一个新的<span class="term" data-title="External Control Plane" data-body="&lt;p&gt;External Control Plane 是从外部管理运行在自己的&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;Cluster&lt;/a&gt;或者其他基础设施中的网格工作负载的&lt;a href=&#34;/zh/docs/reference/glossary/#control-plane&#34;&gt;Control Plane&lt;/a&gt;。Control Plane 可以部署在一个 Cluster 中,尽管不能部署在它所控制的网格的一部分 Cluster 中。它的目的是将 Control Plane 与网格的 Data Plane 完全分离。&lt;/p&gt;
|
||
">外部控制平面</span>部署模型,该模型允许网格操作人员在单独的外部集群上安装和管理网格控制平面。这种部署模型允许网格操作员和网格管理员之间的明确分离。Istio 网格操作员现在可以为网格管理员运行 Istio 控制平面,而网格管理员仍然可以控制控制平面的配置,而不必担心安装或管理控制平面。这个模型对网格用户是透明的。</p>
|
||
<h2 id="external-control-plane-deployment-model">外部控制平面部署模型</h2>
|
||
<p>使用<a href="/v1.12/zh/docs/setup/install/istioctl/#install-istio-using-the-default-profile">默认安装配置文件</a>安装 Istio 后,您将在单个集群中安装一个 Istiod 控制平面,如下图所示:</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:40.78842240615207%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/new-deployment-model/single-cluster.svg" title="单集群中的 Istio 网格">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/new-deployment-model/single-cluster.svg" alt="单集群中的 Istio 网格" />
|
||
</a>
|
||
</div>
|
||
<figcaption>单集群中的 Istio 网格</figcaption>
|
||
</figure>
|
||
<p>使用 Istio 1.7 中的新部署模型,可以在外部集群上运行 Istiod,与网格服务分离,如下图所示。外部控制平面集群由网格操作员拥有,而网格管理员拥有运行部署在网格中的服务的集群。网格管理员无法访问外部控制平面集群。网格操作人员可以遵循<a href="https://github.com/istio/istio/wiki/External-Istiod-single-cluster-steps">外部 istiod 单集群逐步指南</a>来进一步探索这方面的内容。(注意:在 Istio 维护者之间的一些内部讨论中,这个模型以前被称为“中心 istiod”。)</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:47.926329500847174%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/new-deployment-model/single-cluster-external-Istiod.svg" title="外部带有 Istiod 的单群集 Istio 网格">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/new-deployment-model/single-cluster-external-Istiod.svg" alt="外部带有 Istiod 的单群集 Istio 网格" />
|
||
</a>
|
||
</div>
|
||
<figcaption>外部控制平面集群中带有 Istiod 的单个群集 Istio 网格</figcaption>
|
||
</figure>
|
||
<p>网格管理员可以将服务网格扩展到多个集群,这些集群由运行在外部集群中的相同 Istiod 管理。 在这种情况下,没有一个网格集群是<span class="term" data-title="Primary Cluster" data-body="&lt;p&gt;主集群是具有&lt;a href=&#34;/zh/docs/reference/glossary/#control-plane&#34;&gt;控制平面&lt;/a&gt;
|
||
的&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;集群&lt;/a&gt;。
|
||
一个网格可以有一个以上的主集群,以用于 HA 或需要低延迟的场景。
|
||
主集群可以充当&lt;a href=&#34;/zh/docs/reference/glossary/#remote-cluster&#34;&gt;从集群&lt;/a&gt;的控制平面。&lt;/p&gt;
|
||
">主要集群</span>。它们都是<span class="term" data-title="Remote Cluster" data-body="&lt;p&gt;从集群是一个连接到集群外部
|
||
&lt;a href=&#34;/zh/docs/reference/glossary/#control-plane&#34;&gt;控制平面&lt;/a&gt;
|
||
的&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;集群&lt;/a&gt;。
|
||
从集群可以连接到
|
||
&lt;a href=&#34;/zh/docs/reference/glossary/#primary-cluster&#34;&gt;主集群&lt;/a&gt;
|
||
的控制平面,或连接到一个
|
||
&lt;a href=&#34;/zh/docs/reference/glossary/#external-control-plane&#34;&gt;外部控制平面&lt;/a&gt;。&lt;/p&gt;
|
||
">远程集群</span>。但是,除了运行服务外,其中一个还充当 Istio 配置集群。外部控制平面从 <code>config cluster</code> 读取 Istio 配置,而 Istiod 将配置推送到在配置集群和其他远程集群中运行的数据平面,如下图所示。</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:44.93126790115233%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/new-deployment-model/multiple-clusters-external-Istiod.svg" title="外部带有 Istiod 的多集群 Istio 网格">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/new-deployment-model/multiple-clusters-external-Istiod.svg" alt="外部带有 Istiod 的多集群 Istio 网格" />
|
||
</a>
|
||
</div>
|
||
<figcaption>外部控制平面集群中具有 Istiod 的多集群 Istio 网格</figcaption>
|
||
</figure>
|
||
<p>网格操作员可以进一步扩展这种部署模型,从运行多个 Istio 控制平面的外部集群管理多个 Istio 控制平面:</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:45.55366354432676%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/new-deployment-model/multiple-external-Istiods.svg" title="外部带有 Istiod 的多个单集群 Istio 网格">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/new-deployment-model/multiple-external-Istiods.svg" alt="外部带有 Istiod 的单集群 Istio 网格" />
|
||
</a>
|
||
</div>
|
||
<figcaption>外部控制平面集群中具有多个 Istiod 控制平面的多个单集群</figcaption>
|
||
</figure>
|
||
<p>在这种情况下,每个 Istiod 管理自己的远程集群。网格操作人员甚至可以在外部控制平面集群中安装自己的 Istio 网格,并配置 <code>istio-ingress</code> 网关,将通信从远程集群路由到相应的 Istiod 控制平面。 想要了解更多,请查看<a href="https://github.com/istio/istio/wiki/External-Istiod-single-cluster-steps#deploy-istio-mesh-on-external-control-plane-cluster-to-manage-traffic-to-istiod-deployments">这些步骤</a>。</p>
|
||
<h2 id="conclusion">结论</h2>
|
||
<p>外部控制平面部署模型使 Istio 控制平面能够由具有 Istio 操作专长的网格操作人员运行和管理,并在服务网格控制和数据平面之间提供了清晰的分离。 网格操作人员可以在自己的集群或其他环境中运行控制平面,将控制平面作为服务提供给网格管理员。网格操作人员可以在单个集群中运行多个 Istiod 控制平面,部署自己的 Istio 网格,并使用 <code>istio-ingress</code> 网关来控制对这些 Istiod 控制平面的访问。通过本文提供的示例,网格操作人员可以探索不同的实现选择并选择最适合自己的方法。</p>
|
||
<p>这种新模型允许网格管理员只关注网格配置而不操作控制平面,从而降低了网格管理员的复杂性。网格管理员可以继续配置网格范围的设置和 Istio 资源,而不需要访问任何外部控制平面集群。网格用户可以继续与服务网格交互,而无需进行任何更改。</p></description><pubDate>Thu, 27 Aug 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/new-deployment-model/</link><author>Lin Sun (IBM), Iris Ding (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/new-deployment-model/</guid><category>istiod</category><category>deployment model</category><category>install</category><category>deploy</category><category>1.7</category></item><item><title>介绍新的 Istio 指导委员会</title><description>
|
||
<p>今天,Istio 项目很高兴地宣布了其指导章程的新修订,它将向更多的贡献者和社区成员开放治理角色。这次修订巩固了我们对开放治理的承诺,确保围绕项目的社区总是能够引导其方向,并且没有一家公司对项目拥有多数表决权的控制。</p>
|
||
<p>Istio 指导委员会监督项目的行政方面,并制定营销方向。从项目初期开始,谷歌和 IBM 这两家公司的创始人和最大的贡献者就开始了他们的创业之路,并明确表示会增加其他席位。今天,我们很高兴能够实现这一承诺,用新的宪章来奖励贡献和社区。</p>
|
||
<p>新指导委员会由 13 个席位组成:9 个按比例分配的<strong>贡献席位</strong>及 4 个选举的<strong>社区席位</strong>。</p>
|
||
<h2 id="contribution-seats">贡献席位</h2>
|
||
<p>项目的方向是由参与项目的人确定的。我们设计了委员会来反映这一点,根据过去 12 个月对 Istio 的贡献,将 9 个席位分配给 Istio。Kubernetes 的口号是“砍柴挑水”,我们同样希望奖励那些用贡献推动项目增长的公司。</p>
|
||
<p>今年,我们选择使用<strong>合并 pull requests</strong> 作为我们的<a href="https://github.com/istio/community/blob/master/steering/CONTRIBUTION-FORMULA.md">代理比例贡献</a>。我们知道,任何衡量贡献的方法都不是完美的,因此,我们每年将明确地重新考虑这个规则。(在此期间其他给出了相同结果的方法我们也会考虑,包括提交、评论和操作。)</p>
|
||
<p>为了确保公司的多样性,总会有至少三家公司代表在贡献席位。</p>
|
||
<h2 id="community-seats">社区席位</h2>
|
||
<p>Istio 社区有许多出色的贡献者,包括开发人员、SREs 和网格管理员,他们为大大小小的公司工作。我们想要确保在代表和选择方面都有他们的声音。</p>
|
||
<p>我们增加了 4 个席位给来自 4 个不同机构的代表,他们在贡献席位分配中没有代表。这些席位将由 Istio 社区在<a href="https://github.com/istio/community/tree/master/steering/elections">年度选举</a>中投票选出。</p>
|
||
<p>所有<a href="https://github.com/istio/community/blob/master/ROLES.md#member">项目成员</a>均可参选;过去 12 个月活跃的 Istio 成员都有资格投票。</p>
|
||
<h2 id="corporate-diversification-is-the-goal">公司多元化是目标</h2>
|
||
<p>我们的目标是让 Istio 的治理反映出多样化的贡献者。谷歌和 IBM/Red Hat 都将拥有比以前更少的席位,新模型旨在确保至少有 7 个不同组织的代表。</p>
|
||
<p>我们还想明确的是,没有一个供应商拥有对 Istio 项目多数投票控制权,不管他们的贡献有多大。我们已经对公司可以拥有的席位数量实施了限制,这样他们既不能一致赢得投票,也不能否决委员会其他成员的决定。</p>
|
||
<h2 id="committee-and-election">2020 年委员会和选举</h2>
|
||
<p>根据我们的<a href="https://docs.google.com/spreadsheets/d/1Dt-h9s8G7Wyt4r16ZVqcmdWXDuCaPC0kPS21BuAfCL8/edit#gid=0">席位分配流程</a>,今年谷歌将分配 5 个席位,IBM/Red Hat 将分配 3 个席位。作为过去 12 个月 Istio 的第三大贡献者,我们很高兴地宣布 Salesforce 赢得了一个贡献席位。</p>
|
||
<p>第一次<a href="https://github.com/istio/community/tree/master/steering/elections/2020">社区席位选举</a>今日开始。成员有两周时间提名自己,投票将于 9 月 14 日至 27 日进行。你可以在 GitHub 上的 <code>istio/community</code> 知识库中了解有关选举的所有信息。我们也将在太平洋地区本周四 10:00 举办一个特别的<a href="http://bit.ly/istiocommunitymeet">社区会议</a>,讨论选举的变化和过程。我们希望在那里见到你!</p></description><pubDate>Mon, 24 Aug 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/steering-changes/</link><author>Istio 指导委员会</author><guid isPermaLink="true">/v1.12/zh/blog/2020/steering-changes/</guid><category>istio</category><category>steering</category><category>governance</category><category>community</category><category>election</category></item><item><title>在 Istio 中使用 MOSN:另一个数据平面</title><description>
|
||
<p>MOSN(Modular Open Smart Network)是用 GoLang 编写的网络代理服务器。它是 <a href="https://www.antfin.com/">蚂蚁集团</a> 为 Sidecar、API Gateway、云原生 Ingress、Layer 4 或 Layer 7 负载均衡器等场景构建的。随着时间的推移,我们添加了额外的功能,例如多协议框架,多进程插件机制,DSL 和对 <a href="https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol">xDS API</a> 的支持。支持 xDS 意味着我们现在可以将 MOSN 用作 Istio 的数据平面。Istio 项目不支持此配置。如需帮助,请参阅下面的<a href="#了解更多">了解更多</a>。</p>
|
||
<h2 id="背景">背景</h2>
|
||
<p>在 Service Mesh 领域,使用 Istio 作为控制平面已成为主流。由于 Istio 的数据面默认是基于 Envoy 构建的,因此它使用了 Envoy 的数据平面 API(统称为 xDS API)。这些 API 已与 Envoy 分开并进行了标准化,因此,通过在 MOSN 中实现它们,我们就可以使用 MOSN 替代 Envoy。Istio 的第三方数据平面集成可以通过以下三个步骤实现:</p>
|
||
<ul>
|
||
<li>实现 xDS 协议,对齐数据面相关服务治理能力;</li>
|
||
<li>使用 Istio 的脚本并设置相关 <code>SIDECAR</code> 等参数构建 <code>proxyv2</code> 镜像;</li>
|
||
<li>通过 istioctl 工具并设置 proxy 相关配置指定具体的数据面;</li>
|
||
</ul>
|
||
<h2 id="mosn-架构">MOSN 架构</h2>
|
||
<p>MOSN 是一个分层的体系结构,其系统分为 NET/IO、Protocol、Stream、Proxy 四层,如下图所示:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:45.77056778679027%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/mosn-proxy/mosn-arch.png" title="MOSN 架构图">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/mosn-proxy/mosn-arch.png" alt="MOSN 架构图" />
|
||
</a>
|
||
</div>
|
||
<figcaption>MOSN 架构图</figcaption>
|
||
</figure>
|
||
<ul>
|
||
<li>NET/IO 作为网络层,监测连接和数据包的到来,同时作为 listener filter 和 network filter 的挂载点;</li>
|
||
<li>Protocol 作为多协议引擎层,对数据包进行检测,并使用对应协议做 decode/encode 处理;</li>
|
||
<li>Stream 对 decode 的数据包做二次封装为 stream,作为 stream filter 的挂载点;</li>
|
||
<li>Proxy 作为 MOSN 的转发框架,对封装的 stream 做 proxy 处理;</li>
|
||
</ul>
|
||
<h2 id="为什么要使用-mosn">为什么要使用 MOSN ?</h2>
|
||
<p>蚂蚁集团在进行 Mesh 改造前,已经预料到作为下一代蚂蚁集团的基础架构,Mesh 化势必带来革命性的变革以及演进成本,我们有非常宏大的蓝图:准备将原有的网络和中间件方面的各种能力重新沉淀和打磨,打造成为未来新一代架构的底层平台,承载各种服务通讯的职责。</p>
|
||
<p>这是一个需要多年时间打造,满足未来五年乃至十年需求的长期规划项目,合作共建团队跨业务、SRE、中间件、基础架构等部门。我们必须有一个具备灵活扩展、高性能、满足长期演进的网络代理转发平面。Nginx、Envoy 在网络代理领域有非常长期的能力积累和活跃的社区,我们也同时借鉴了 Nginx、Envoy 等其他优秀的开源网络代理,同时在研发效率、灵活扩展等方面进行了加强,同时整个 Mesh 改造涉及到非常多的部门和研发人员,必须考虑到跨团队合作的落地成本,所以我们基于 GoLang 自研了云原生场景下的新型网络代理 MOSN。对于 GoLang 的性能,我们前期也做了充分的调研和测试,满足蚂蚁集团业务对性能的要求。</p>
|
||
<p>同时我们从社区用户方面收到了很多的反馈和需求,大家有同样的需求以及思考,所以我们结合社区与自身的实际情况,从满足社区以及用户角度出发进行了 MOSN 的研发工作,我们认为开源的竞争主要是标准与规范的竞争,我们需要基于开源标准做最适合自身的实现选择。</p>
|
||
<h2 id="mosn-和-istio-默认的-proxy-的不同点是什么">MOSN 和 Istio 默认的 Proxy 的不同点是什么?</h2>
|
||
<h3 id="语言栈的不同">语言栈的不同</h3>
|
||
<p>MOSN 使用 GoLang 语言编写,GoLang 语言在生产效率,内存安全上有比较强的保障,同时 GoLang 在云原生时代有广泛的库生态系统,性能在 Mesh 场景下我们评估以及实践是可以接受的。另外 MOSN 对于使用 GoLang、Java 等语言的公司和个人的心智成本更低。</p>
|
||
<h3 id="核心能力的差异化">核心能力的差异化</h3>
|
||
<ul>
|
||
<li>MOSN 支持多协议框架,用户可以比较容易的接入私有协议,具有统一的路由框架;</li>
|
||
<li>多进程的插件机制,可以通过插件框架很方便的扩展独立 MOSN 进程的插件,做一些其他管理,旁路等的功能模块扩展;</li>
|
||
<li>具备中国密码合规的传输层国密算法支持;</li>
|
||
</ul>
|
||
<h3 id="mosn-的不足">MOSN 的不足</h3>
|
||
<ul>
|
||
<li>由于 MOSN 是用 GoLang 编写的,因此它的性能不如 Istio 的默认代理(默认代理使用的是 C++ 语言),但是在服务网格场景中该性能是可以接受的并且可以使用;</li>
|
||
<li>与 Istio 默认代理相比,不完全支持某些功能,例如 WASM、HTTP3、Lua 等。但是,这些功能在 MOSN 的 <a href="https://docs.google.com/spreadsheets/d/1fALompY9nKZNImOuxQw23xtMD-5rCBrXWziJZkj76bo/edit?usp=sharing">roadmap</a> 计划之中,我们的目标是和 Istio 完全兼容;</li>
|
||
</ul>
|
||
<h2 id="mosn-结合-istio">MOSN 结合 Istio</h2>
|
||
<p>下面介绍如何将 MOSN 设置为 Istio 的数据平面。</p>
|
||
<h2 id="安装-istio">安装 Istio</h2>
|
||
<p>您可以在 <a href="https://github.com/istio/istio/releases/tag/1.5.2">Istio release</a> 页面下载与您操作系统匹配的压缩文件,该文件中包含:安装文件、示例和 istioctl 命令行工具。使用如下命令来下载 Istio(本文示例使用的是 Istio 1.5.2):</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export ISTIO_VERSION=1.5.2 &amp;&amp; curl -L https://istio.io/downloadIstio | sh -
|
||
</code></pre>
|
||
<p>下载的 Istio 包名为 <code>istio-1.5.2</code>,包含:</p>
|
||
<ul>
|
||
<li><code>install/kubernetesi</code>:包含 Kubernetes 相关的 YAML 安装文件;</li>
|
||
<li><code>examples/</code>:包含示例应用程序;</li>
|
||
<li><code>bin/</code>:包含 istioctl 的客户端文件;</li>
|
||
</ul>
|
||
<p>切换到 Istio 包所在目录:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cd istio-$ISTIO_VERSION/
|
||
</code></pre>
|
||
<p>使用如下命令将 istioctl 客户端路径加入 $PATH 中:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export PATH=$PATH:$(pwd)/bin
|
||
</code></pre>
|
||
<p>截止目前,我们已经可以通过 istioctl 命令行工具来灵活的自定义 Istio 控制平面和数据平面配置参数。</p>
|
||
<h2 id="设置-mosn-作为-istio-的-sidecar">设置 MOSN 作为 Istio 的 Sidecar</h2>
|
||
<p>通过 istioctl 命令的参数指定 MOSN 作为 Istio 中的数据面:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl manifest apply --set .values.global.proxy.image=&#34;mosnio/proxyv2:1.5.2-mosn&#34; --set meshConfig.defaultConfig.binaryPath=&#34;/usr/local/bin/mosn&#34;
|
||
</code></pre>
|
||
<p>检查 Istio 相关 pod 服务是否部署成功:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get svc -n istio-system
|
||
</code></pre>
|
||
<p>如果服务状态 STATUS 为 Running,则表示 Istio 已经成功安装,后面就可以部署 Bookinfo 示例了。</p>
|
||
<h2 id="bookinfo-示例">Bookinfo 示例</h2>
|
||
<p>可以通过 <a href="https://katacoda.com/mosn/courses/istio/mosn-with-istio">MOSN with Istio</a> 的教程来进行 Bookinfo 示例的演示操作,另外在该教程中您也可以找到更多关于使用 MOSN 和 Istio 的说明。</p>
|
||
<h2 id="展望">展望</h2>
|
||
<p>接下来,MOSN 不仅会持续兼容适配新版本的 Istio 的功能,而且还将在以下几个方面进行发展:</p>
|
||
<ul>
|
||
<li>作为微服务运行时,使得面向 MOSN 编程的服务更轻、更小、更快;</li>
|
||
<li>可编程,如支持 WASM;</li>
|
||
<li>更多场景 mesh 化方案支持,缓存/消息/区块链 mesh 化等;</li>
|
||
</ul>
|
||
<p>MOSN 是一个开源项目,社区中的任何人都可以使用,参与和改进。我们希望您能加入我们!可以通过<a href="https://github.com/mosn/community">这里</a>介绍的几种方式了解 MOSN 正在做的事情并参与其中。</p>
|
||
<h2 id="了解更多">了解更多</h2>
|
||
<ul>
|
||
<li><a href="https://mosn.io">MOSN 官方博客</a></li>
|
||
<li><a href="https://mosn.io/en/docs/community/">MOSN 开源社区</a></li>
|
||
<li><a href="https://katacoda.com/mosn">MOSN 教程</a></li>
|
||
</ul></description><pubDate>Wed, 29 Jul 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/mosn-proxy/</link><author>王发康 (mosn.io)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/mosn-proxy/</guid><category>mosn</category><category>sidecar</category><category>proxy</category></item><item><title>开放和中立:将我们的商标转移到 Open Usage Commons</title><description>
|
||
<p>从<a href="/v1.12/zh/news/releases/0.x/announcing-0.1/">第一天</a>开始,Istio 项目就相信成为贡献者运行、开放、透明和对所有人可用的重要性。本着这种精神,谷歌很高兴地宣布,它将把项目商标的所有权转让给新的组织 Open Usage Commons。</p>
|
||
<p>Istio 是一个开源项目,在 Apache 2.0 许可下发布。这意味着人们可以复制、修改、分发、制作、使用和销售源代码。在 Apache 2.0 许可下,人们唯一没有的自由就是使用 Istio 这个名称,或者它的标识,这可能会使消费者感到困惑。</p>
|
||
<p>作为该项目的创始人之一,谷歌目前是 Istio 商标的所有者。虽然根据许可证使用软件的任何人都可以使用这些商标,但是历史所有权给谁可以使用这个名称以及如何使用造成了一些混乱和不确定性,而且这种混乱有时会成为社区发展的障碍。因此今天,作为 Istio 对开放的持续承诺的一部分,谷歌宣布 Istio 商标将被转让给一个新的组织(Open Usage Commons)来提供对商标中立、独立的监督。</p>
|
||
<h2 id="a-neutral-home-for-Istio-trademarks">Istio 商标的中立之家</h2>
|
||
<p>Open Usage Commons 是一个新的组织,它专注于以一种与<a href="https://opensource.org/osd">开源定义</a>一致的方式为开源项目商标提供管理和指导。对于项目而言,特别是像 Istio 这样具有健壮生态系统的项目,确保根据许可证使用该软件的任何人都可以使用该商标是很重要的。该商标允许维护者发展社区,并使用该名称来实现这一目标。它还允许生态系统合作伙伴在项目之上创建服务,并且允许开发人员创建引用项目的工具和集成。维护人员、生态系统合作伙伴和开发人员都必须对他们在 Istio 的长期投资有信心。谷歌认为将 Istio 商标纳入 Open Usage Commons 是明确说明和提供这种信心的正确方式。</p>
|
||
<p>Open Usage Commons 将与 Istio 指导委员会合作,生成商标使用指南。这里不会立即更改 Istio 使用指南,如果您目前正在按照现有的品牌指南使用 Istio 标记,您可以继续这样做。</p>
|
||
<p>你可以在 <a href="https://openusage.org/faq">openusage.org</a> 上了解更多关于<a href="https://openusage.org">开源项目 IP 和开放使用公共资源</a>的信息。</p>
|
||
<h2 id="a-continued-commitment-to-open">持续承诺开放</h2>
|
||
<p>Open Usage Commons 专注于项目商标;它不涉及开放项目的其他方面,比如谁得到决策投票的规则。与早期的许多项目一样,Istio 的委员会也是由创始公司创立的小团队组成的。但是 Istio 已经成长和成熟(去年 Istio 是 <a href="https://octoverse.github.com/#fastest-growing-oss-projects-by-contributors">GitHub 中增长最快的开源项目的第 4 名!</a>),并且是时候开始 Istio 治理的下一次演变了。</p>
|
||
<p>最近,<a href="https://aspenmesh.io/helping-istio-sail/">我们很荣幸地任命 Neeraj Poddar,Aspen Mesh 的联合创始人兼首席架构师</a>为技术监督委员会,该委员会负责项目的所有技术决策。Neeraj 是该项目的长期贡献者,并担任工作组领导。<a href="https://github.com/istio/community/blob/master/TECH-OVERSIGHT-COMMITTEE.md#committee-members">TOC 现在由</a> 4 个不同公司的 7 个成员组成——Tetrate,IBM,谷歌和现在的 Aspen Mesh。</p>
|
||
<p>我们的社区目前正在讨论如何管理监督市场和社区活动的指导委员会,来反映不断扩大的社区和生态系统。如果你对这种新的治理方式有想法,请访问正在进行积极讨论的 <a href="https://github.com/istio/community/pull/361">GitHub 上的 pull request</a>。</p>
|
||
<p>在过去的 12 个月里,Istio 已经有了来自 <a href="https://istio.teststats.cncf.io/d/5/companies-table?var-period_name=Last%20year&amp;var-metric=commits">100 多个组织</a>的提交,目前有<a href="http://eng.istio.io/maintainers">来自 14 个不同公司的 70 名维护者</a>。这种趋势正是项目创始人所希望的贡献者多样性,培养这种多样性仍然是首要任务。谷歌对 Istio 的未来感到兴奋,并希望您能成为其中的一员。</p></description><pubDate>Wed, 08 Jul 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/open-usage/</link><author>Sean Suchter (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/open-usage/</guid><category>trademark</category><category>governance</category><category>steering</category></item><item><title>重做我们的插件集成</title><description>
|
||
<p>从 Istio 1.6 开始,我们引入了一种与遥测插件集成的新方法,例如 Grafana,Prometheus,Zipkin,Jaeger 和 Kiali。</p>
|
||
<p>在以前的版本中,这些附加软件是作为 Istio 安装的一部分捆绑在一起的。这使用户可以快速开始使用 Istio,无需进行任何复杂的配置即可安装和集成这些插件。但是,它带来一些问题:</p>
|
||
<ul>
|
||
<li>Istio 插件安装不是最新的或不如上游安装方法功能丰富。用户错过了这些应用程序提供的一些很棒的功能,例如:
|
||
<ul>
|
||
<li>持久化存储</li>
|
||
<li>Prometheus 的 <code>Alertmanager</code> 功能</li>
|
||
<li>高级安全设置</li>
|
||
</ul></li>
|
||
<li>与使用这些特性的现有部署集成比预想的更具挑战性。</li>
|
||
</ul>
|
||
<h2 id="changes">修改</h2>
|
||
<p>为了解决这些问题,我们做了一些修改:</p>
|
||
<ul>
|
||
<li><p>增加一个新的<a href="/v1.12/zh/docs/ops/integrations/">集成</a>文档部分,解释 Istio 可以集成哪些应用程序,如何使用它们,以及最佳实践。</p></li>
|
||
<li><p>减少设置遥测插件所需的配置数量</p>
|
||
<ul>
|
||
<li><p>Grafana 仪表盘现在<a href="/v1.12/zh/docs/ops/integrations/grafana/#import-from-grafana-com">发布到 <code>grafana.com</code></a>。</p></li>
|
||
<li><p>Prometheus 现在可以移除所有的 Istio Pod <a href="/v1.12/zh/docs/ops/integrations/prometheus/#option-2-metrics-merging">使用标准的 <code>prometheus.io</code> 注解</a>。这允许大多数 Prometheus 部署在没有任何特殊配置的情况下使用 Istio。</p></li>
|
||
</ul></li>
|
||
<li><p>通过 <code>istioctl</code> 和操作面板删除绑定的插件安装。Istio 不会安装不是由 Istio 项目交付的组件。因此,Istio 将停止发送与插件相关的安装工件。但是,Istio 将在必要时保证版本兼容性。用户有责任使用相应项目提供的官方<a href="/v1.12/zh/docs/ops/integrations/">集成</a>文档和工件来安装这些组件。对于 demo 演示,用户可以通过 <a href="https://github.com/istio/istio/tree/release-1.12/samples/addons"><code>samples/addons/</code> 目录</a>部署简单的 YAML 文件。</p></li>
|
||
</ul>
|
||
<p>我们希望这些修改使用户能够充分利用这些附加组件,从而充分体验 Istio 可以提供的功能。</p>
|
||
<h2 id="timeline">时间线</h2>
|
||
<ul>
|
||
<li>Istio 1.6: 遥测插件的新演示部署 demo 可以在 <code>samples/addons/</code> 目录下找到。</li>
|
||
<li>Istio 1.7: 建议使用上游安装方法或新的示例部署。 不推荐使用 <code>istioctl</code> 进行安装。</li>
|
||
<li>Istio 1.8: 删除了 <code>istioctl</code> 对插件的安装。</li>
|
||
</ul></description><pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/addon-rework/</link><author>John Howard (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/addon-rework/</guid><category>telemetry</category><category>addons</category><category>integrations</category><category>grafana</category><category>prometheus</category></item><item><title>介绍工作负载条目</title><description>
|
||
<h2 id="introducing-workload-entries-bridging-Kubernetes-and-VMs">工作负载条目简介:桥接 Kubernetes 和 VM</h2>
|
||
<p>从历史上看,Istio 为在 Kubernetes 上运行的工作负载提供了很好的体验,但对于其他类型的工作负载,如虚拟机(VM)和裸机,则不太顺利。这些差距包括无法在 VM 上以声明方式指定 Sidecar 的属性,无法正确响应工作负载的生命周期变化(例如,从启动到未准备就绪,或健康检查),以及在工作负载迁移到 Kubernetes 时繁琐的 DNS 解决方法,仅此而已。</p>
|
||
<p>Istio 1.6 在如何管理非 Kubernetes 工作负载方面引入了一些变化,其驱动力是希望在容器之外的用例中更容易获得 Istio 的好处,比如在 Kubernetes 之外的平台上运行传统数据库,或者在不重写现有应用的情况下采用 Istio 的功能。</p>
|
||
<h3 id="background">背景</h3>
|
||
<p>在 Istio 1.6 之前,非容器化工作负载可以简单地配置为 <code>ServiceEntry</code> 中的一个IP地址,这意味着它们只作为服务的一部分存在。Istio 缺乏对这些非容器化工作负载的一流抽象,类似于 Kubernetes 将 Pod 视为计算的基本单位&ndash;一个命名对象,作为与工作负载相关的所有事物的集合点&ndash;名称、标签、安全属性、生命周期状态事件等。输入 <code>WorkloadEntry</code>。</p>
|
||
<p>考虑下面的 <code>ServiceEntry</code>,描述一个由几十个有 IP 地址的虚拟机实现的服务:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: svc1
|
||
spec:
|
||
hosts:
|
||
- svc1.internal.com
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
resolution: STATIC
|
||
endpoints:
|
||
- address: 1.1.1.1
|
||
- address: 2.2.2.2
|
||
....
|
||
</code></pre>
|
||
<p>如果您想以主动-主动的方式将这个服务迁移到 Kubernetes 中&ndash;即启动一堆 Pod,通过 Istio 双向 TLS(mTLS)将一部分流量发送到 Pod,并将其余的流量发送到没有 Sidecar 的 VM 上&ndash;您会怎么做?您需要使用 Kubernetes 服务、虚拟服务和目标规则的组合来实现这一行为。现在,假设您决定将 Sidecar 逐一添加到这些 VM 上,这样您就希望只有到有 Sidecar 的 VM 的流量才会使用 Istio mTLS。如果任何其他服务条目碰巧在其地址中包括相同的 VM,事情就开始变得非常复杂和容易出错。</p>
|
||
<p>这些复杂情况的主要来源是 Istio 缺乏对非容器化工作负载的一流定义,其工作负载的属性可以独立于其所属的服务来描述。</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:75%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/workload-entry/workload-entry-first-example.svg" title="The Internal of Service Entries Pointing to Workload Entries">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/workload-entry/workload-entry-first-example.svg" alt="Service Entries Pointing to Workload Entries" />
|
||
</a>
|
||
</div>
|
||
<figcaption>The Internal of Service Entries Pointing to Workload Entries</figcaption>
|
||
</figure>
|
||
<h3 id="workload-entry-a-non-Kubernetes-endpoint">工作负载条目</h3>
|
||
<p><code>WorkloadEntry</code> 是专门为解决这个问题而创建的。<code>WorkloadEntry</code> 允许您描述非 Pod 端点,这些端点应该仍然是网格的一部分,并将其与 Pod 同等对待。从这里开始,一切都变得简单了,比如在工作负载之间启用 <code>MUTUAL_TLS</code>,无论它们是否是容器化的。</p>
|
||
<p>要创建一个 <a href="/v1.12/zh/docs/reference/config/networking/workload-entry/"><code>WorkloadEntry</code></a> 并将其附加到一个 <a href="/v1.12/zh/docs/reference/config/networking/service-entry/"><code>ServiceEntry</code></a>上,您可以这样做:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: WorkloadEntry
|
||
metadata:
|
||
name: vm1
|
||
namespace: ns1
|
||
spec:
|
||
address: 1.1.1.1
|
||
labels:
|
||
app: foo
|
||
instance-id: vm-78ad2
|
||
class: vm
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: svc1
|
||
namespace: ns1
|
||
spec:
|
||
hosts:
|
||
- svc1.internal.com
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
resolution: STATIC
|
||
workloadSelector:
|
||
labels:
|
||
app: foo
|
||
</code></pre>
|
||
<p>这将创建一个带有一组标签和地址的新 <code>WorkloadEntry</code>,以及使用 <code>WorkloadSelector</code> 来选择所有带有所需标签的端点的 <code>ServiceEntry</code>,在这种情况下包括为 VM 创建的 <code>WorkloadEntry</code>。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:75%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/workload-entry/workload-entry-final.svg" title="The Internal of Service Entries Pointing to Workload Entries">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/workload-entry/workload-entry-final.svg" alt="Service Entries Pointing to Workload Entries" />
|
||
</a>
|
||
</div>
|
||
<figcaption>The Internal of Service Entries Pointing to Workload Entries</figcaption>
|
||
</figure>
|
||
<p>注意 <code>ServiceEntry</code> 可以同时引用 Pod 和 <code>WorkloadEntry</code>,使用相同的选择器。现在 Istio 可以对 VM 和 Pod 进行相同的处理,而不是将它们分开。</p>
|
||
<p>如果要将一些工作负载迁移到 Kubernetes,且选择保留大量的 VM,则 <code>WorkloadSelector</code> 可以同时选择 Pod 和 VM,Istio 会自动在它们之间进行负载平衡。1.6 的变化还意味着 <code>WorkloadSelector</code> 可以在 Pod 和 VM 之间同步配置,并且无需手动要求以重复的策略(例如mTLS和授权)将两个基础结构作为目标。Istio 1.6 版本为 Istio 的未来发展提供了一个伟大的起点。能够像描述 Pod 那样描述网状结构之外的东西,会带来更多的好处,比如改善启动体验。然而,这些好处仅仅是副作用。核心的好处是您现在可以让 VM 和 Pod 共存,而不需要任何配置来将两者连接起来。</p></description><pubDate>Thu, 21 May 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/workload-entry/</link><author>Cynthia Coan (Tetrate), Shriram Rajagopalan (Tetrate), Tia Louden (Tetrate), John Howard (Google), Sven Mawson (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/workload-entry/</guid><category>vm</category><category>workloadentry</category><category>migration</category><category>1.6</category><category>baremetal</category><category>serviceentry</category><category>discovery</category></item><item><title>使用金丝雀控制平面部署安全升级 Istio</title><description>
|
||
<p>金丝雀部署是 Istio 的核心特性。用户依靠 Istio 的流量管理特性安全地控制新版本应用程序的推出,同时利用 Istio 丰富的遥测技术来比较金丝雀的性能。然而,当涉及到升级 Istio 时,没有一种简单的方法来监测升级,而且由于升级的就地性质,发现的问题或更改会立即影响整个网格。</p>
|
||
<p>Istio 1.6 将支持一种新的升级模式来安全部署 Istio 的新版本。在这个新模型中,代理将与它们使用的特定控制平面相关联。这允许新版本以较小的风险部署到集群—直到用户明确选择连接新版本时,才会有代理连接到新版本。这允许将工作负载逐步迁移到新的控制平面,当监控到更改时使用 Istio 遥测技术来调查任何问题,就像对工作负载使用 <code>VirtualService</code> 一样。每个独立的控制平面被称为一个“修订”,并有一个 <code>istio.io/rev</code> 标签。</p>
|
||
<h2 id="understanding-upgrades">升级过程解读</h2>
|
||
<p>升级 Istio 是一个复杂的过程。在两个版本之间的过渡期间(对于大型集群来说可能需要很长时间),代理和控制平面之间存在版本差异。在旧模型中,新旧控制平面使用相同的服务,流量在两个平面之间随机分布,不向用户提供控制。然而,在新的模型中,不存在跨版本通信。看看升级是如何变化的:</p>
|
||
<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vR2R_Nd1XsjriBfwbqmcBc8KtdP4McDqNpp8S5v6woq28FnsW-kATBrKtLEG9k61DuBwTgFKLWyAxuK/embed?start=false&loop=true&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
|
||
<h2 id="configuring">配置</h2>
|
||
<p>控制平面的选择是基于 sidecar 注入 webhook。每个控制平面都配置为选择名称空间匹配 <code>istio.io/rev</code> 标签的对象。然后,升级过程将 Pod 配置为连接到指定修订版的控制平面。与当前模型不同,这意味着给定的代理在生命周期内连接到同一修订版控制平面。这避免了当代理切换时它所连接的控制平面可能出现的细微问题。</p>
|
||
<p>当使用修订版时,新的 <code>istio.io/rev</code> 标签将替换 <code>istio-injection=enabled</code> 标签。例如,如果我们有一个名为金丝雀的修订,我们将使用 istio.io/rev=canary 标签标记要使用该修订的名称空间。有关更多信息请参见<a href="/v1.12/zh/docs/setup/upgrade">升级指南</a>。</p></description><pubDate>Tue, 19 May 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/multiple-control-planes/</link><author>John Howard (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/multiple-control-planes/</guid><category>install</category><category>upgrade</category><category>revision</category><category>control plane</category></item><item><title>扩展和改进 WebAssemblyHub 给 Envoy 和 Istio 赋能 WebAssembly</title><description>
|
||
<p><a href="https://www.solo.io/blog/an-extended-and-improved-webassembly-hub-to-helps-bring-the-power-of-webassembly-to-envoy-and-istio/"><em>最初发布在 Solo.io 博客上</em></a></p>
|
||
<p>随着组织采用诸如 Istio 之类的基于 Envoy 的基础架构来帮助解决微服务通信方面的挑战,他们不可避免地发现自己需要自定义基础架构的一些部分来匹配它们组织的约束。<a href="https://webassembly.org/">WebAssembly(Wasm)</a>已经成为一种安全,安全且动态的平台扩展环境。</p>
|
||
<p>在最近的 <a href="/v1.12/zh/blog/2020/wasm-announce/">Istio 1.5 公告</a>中,Istio 项目为将 WebAssembly 带入流行的 Envoy 代理奠定了基础。<a href="https://solo.io">Solo.io</a> 与谷歌和 Istio 社区合作来简化对 Envoy 和 Istio 创建,共享和部署 WebAssembly 扩展的整体体验。不久之前,谷歌和其他公司为容器奠定了基础,而 Docker 建立了良好的用户体验使其具有可消费性。同样,通过在 Istio 上为 WebAssembly 构建最佳用户体验,这一努力使 Wasm 可消费。</p>
|
||
<p>早在 2019 年 12 月,随着 WebAssembly Hub 的发布,Solo.io 开始努力为 WebAssembly 提供良好的开发人员体验。WebAssembly Hub 允许开发人员非常快速地启动 C++ 中的新 WebAssembly 项目(我们正在扩展此语言选择,请参见下文),在 Docker 中使用 Bazel 进行构建,并将其推送到 OCI 兼容仓库中。从那里,operators 必须拉出模块,然后自己配置 Envoy 代理才能从磁盘加载它。<a href="https://docs.solo.io/gloo/latest/">基于 Envoy 构建的 API 网关 Gloo</a> 中的 Beta 支持让您可以声明式地动态地加载模块,Solo.io 团队希望为您带来同样的轻松体验以及其他基于 Envoy 的框架(例如 Istio)的安全体验。</p>
|
||
<p>这个领域的创新引起了人们的极大兴趣,Solo.io 团队一直在努力提高 WebAssembly Hub 的功能及其支持的工作流程。Solo.io 激动地宣布与 Istio 1.5 结合,对 WebAssembly Hub 进行了新的增强,这些改进增强了 Envoy 在 WebAssembly 上的生产能力,改善了开发人员的体验,并简化了在 Istio 中将 Wasm 与 Envoy 结合使用的过程。</p>
|
||
<h2 id="evolving-toward-production">逐步走向生产</h2>
|
||
<p>Envoy 社区正在努力将 Wasm 支持引入上游项目(现在它位于一个有效的开发分支中),Istio 宣布 Wasm 支持 Alpha 功能。在 <a href="https://www.solo.io/blog/announcing-gloo-1-0-a-production-ready-envoy-based-api-gateway/">Gloo 1.0 中,我们还宣布了</a>支持 Wasm。 什么是 Gloo?Gloo 是一种现代的 API 网关和入口控制器(基于 Envoy 代理构建),支持路由和保护传入流量到传统的单体架构,微服务/Kubernetes 和无服务功能。开发和运营团队能够调整和控制从外部终端用户/客户端到后端应用程序服务的流量模式。Gloo 是 Kubernetes 和 Istio 的本地入口网关。</p>
|
||
<p>尽管每个项目的成熟度都很高,但是作为社区,我们可以做些事情来改善生产支持的基础。</p>
|
||
<p>第一个领域是标准化 Envoy 的 WebAssembly 扩展的外观。Solo.io,谷歌和 Istio 社区已定义了一个开放规范,用于将 WebAssembly 模块捆绑和分发为 OCI 镜像。该规范为分发包括 Envoy 扩展名在内的任何类型的 Wasm 模块提供了一个强大的模型。</p>
|
||
<p>这是向社区开放的-<a href="https://github.com/solo-io/wasm-image-spec">加入我们的行列</a></p>
|
||
<p>下一个领域是改善部署 Wasm 扩展到基于 Envoy 的框架运行的生产环境的体验。在 Kubernetes 生态中,使用声明性的基于 CRD 的配置来管理集群配置被认为是生产中的最佳实践。新的 <a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/wasme_operator/">WebAssembly Hub Operator</a> 添加了一个声明式的 CRD,该 CRD 可自动将 Wasm 筛选器部署和配置到在 Kubernetes 集群中运行的 Envoy 代理。Operator 使 GitOps 工作流程和集群自动化能够管理 Wasm 筛选器,而无需人工干预或命令性的工作流程。我们将在即将发布的博客文章中提供有关 Operator 的更多信息。</p>
|
||
<p>最后,Wasm 扩展的开发人员与部署它们的团队之间的交互需要某种基于角色访问,组织管理和设施来共享,发现和使用这些扩展。WebAssembly Hub 添加了团队管理功能,例如权限,组织,用户管理,共享等。</p>
|
||
<h2 id="improving-the-developer-experience">改善开发人员体验</h2>
|
||
<p>由于开发人员希望以更多的语言和运行时间为目标,所以体验必须保持尽可能简单和高效。多语言支持和运行时 ABI(应用程序二进制接口)目标应在工具中自动处理。</p>
|
||
<p>Wasm 的好处之一是能够用多种语言编写模块。Solo.io 与谷歌之间的合作为用 C++,Rust 和 AssemblyScript 编写的 Envoy 过滤器提供了开箱即用的支持。我们将继续增加对更多语言的支持。</p>
|
||
<p>Wasm 扩展使用部署它们的 Envoy 代理内的应用程序二进制接口(ABI)。WebAssembly Hub 在 Envoy,Istio 和 Gloo 之间提供了强大的 ABI 版本保证,可以防止不可预测的行为和错误。您只需关心编写您的扩展代码。</p>
|
||
<p>最后,像 Docker 一样,WebAssembly Hub 将 Wasm 扩展存储和分发为 OCI 镜像。这使得推,拉和运行 Wasm 扩展像 Docker 容器一样容易。Wasm 扩展镜像经过版本控制和加密保护,从而可以像在生产环境中一样安全地在本地运行扩展。这样,当他们下拉和部署镜像时,您就可以构建和推送镜像以及信任镜像来源。</p>
|
||
<h2 id="web-assembly-hub-with-Istio">Istio 集成 WebAssembly Hub</h2>
|
||
<p>WebAssembly Hub 现在完全自动化了将 Wasm 扩展部署到安装在 Kubernetes 中的 Istio(以及其他基于 Envoy 的框架,例如 <a href="https://docs.solo.io/gloo/latest/">Gloo API Gateway</a>) 的过程。借助此部署功能,WebAssembly Hub 使 operator 或终端用户无需在 Istio 服务网格中手动配置 Envoy 代理即可使用其 WebAssembly 模块。</p>
|
||
<p>观看以下视频,了解 WebAssembly 和 Istio 入门的简便性:</p>
|
||
<ul>
|
||
<li><a href="https://www.youtube.com/watch?v=-XPTGXEpUp8">第 1 部分</a></li>
|
||
<li><a href="https://youtu.be/vuJKRnjh1b8">第 2 部分</a></li>
|
||
</ul>
|
||
<h2 id="get-started">开始使用</h2>
|
||
<p>我们希望 WebAssembly Hub 将成为社区共享,发现和分发 Wasm 扩展的聚会场所。通过提供良好的用户体验,我们希望使 Wasm 的开发,安装和运行变得更轻松,更有意义。加入我们的<a href="https://webassemblyhub.io">WebAssembly Hub</a>,共享您的扩展名和<a href="https://slack.solo.io">想法</a>,并且加入<a href="https://solo.zoom.us/webinar/register/WN_i8MiDTIpRxqX-BjnXbj9Xw">即将举行的网络研讨会</a>。</p></description><pubDate>Wed, 25 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/wasmhub-istio/</link><author>Idit Levine (Solo.io)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/wasmhub-istio/</guid><category>wasm</category><category>extensibility</category><category>alpha</category><category>performance</category><category>operator</category></item><item><title>为没有 sidecar 的应用程序提供证书和密钥</title><description><div>
|
||
<aside class="callout warning">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-warning"/></svg>
|
||
</div>
|
||
<div class="content">以下信息描述了一个实验性功能,仅用于评估。</div>
|
||
</aside>
|
||
</div>
|
||
<p>Istio sidecars 获取使用 secret 发现服务的证书。服务网格中的服务可能不需要(或不想要) Envoy sidecar 来处理其流量。在这种情况下,如果服务想要连接到其他 TLS 或共同 TLS 安全的服务,它将需要自己获得证书。</p>
|
||
<p>对于不需要 sidecar 来管理其流量的服务,sidecar 仍然可以被部署只为了通过来自 CA 的 CSR 流量提供私钥和证书,然后通过一个挂载到 <code>tmpfs</code> 中的文件来共享服务证书。我们使用 Prometheus 作为示例应用程序来配置使用此机制的证书。</p>
|
||
<p>在示例应用程序(即 Prometheus)中,通过设置标识 <code>.Values.prometheus.provisionPrometheusCert</code> 为 <code>true</code>(该标识在 Istio 安装中默认设置为 true)将 sidecar 添加到 Prometheus 部署。然后,这个部署的 sidecar 将请求与 Prometheus 共享一个证书。</p>
|
||
<p>为示例应用程序提供的密钥和证书都挂载在 <code>/etc/istio-certs/</code> 目录中。运行以下命令,我们可以列出为应用程序提供的密钥和证书:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it `kubectl get pod -l app=prometheus -n istio-system -o jsonpath=&#39;{.items[0].metadata.name}&#39;` -c prometheus -n istio-system -- ls -la /etc/istio-certs/
|
||
</code></pre>
|
||
<p>上面命令的输出应该包含非空的密钥和证书文件,如下所示:</p>
|
||
<pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >-rwxr-xr-x 1 root root 2209 Feb 25 13:06 cert-chain.pem
|
||
-rwxr-xr-x 1 root root 1679 Feb 25 13:06 key.pem
|
||
-rwxr-xr-x 1 root root 1054 Feb 25 13:06 root-cert.pem
|
||
</code></pre>
|
||
<p>如果您想使用此机制来为您自己的应用程序提供证书,请查看我们的 <a href="https://github.com/istio/istio/blob/release-1.12/manifests/charts/istio-telemetry/prometheus/templates/deployment.yaml">Prometheus 示例应用程序</a>,并简单地遵循相同的模式。</p></description><pubDate>Wed, 25 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/proxy-cert/</link><author>Lei Tang (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/proxy-cert/</guid><category>certificate</category><category>sidecar</category></item><item><title>介绍 istiod:简化控制平面</title><description>
|
||
<p>当服务需要由不同的团队交付,或者单独部署及扩展的价值高于编排的成本时,微服务是一种很好的模式。我们定期与在现实世界中运行 Istio 的客户和团队进行交流,他们告诉我们,对于 Istio 控制平面而言,情况并非如此。因此,在 Istio 1.5 中,我们更改了 Istio 的打包方式,将控制平面功能合并为一个被称为 <strong>istiod</strong> 的二进制文件。</p>
|
||
<h2 id="history-of-the-Istio-control-plane">Istio 控制平面的历史</h2>
|
||
<p>Istio 实现了一种已在 Google 和 IBM 使用多年的模式,该模式后来被称为“服务网格”。通过代理服务器将客户端和服务端进程配对,它们可以充当应用程序感知的 <em>数据平面</em> ,而不仅仅是在主机间传输数据包或通过网络传输脉冲信号。</p>
|
||
<p>这种模式有利于全世界的工程师通过 <em>微服务</em> 达成共识:通过轻量级协议连接细粒度、松散耦合的服务。通用的跨平台和跨语言标准(例如 HTTP 和 gRPC )取代专有传输方式,且各种语言都有相关的库,使得不同的团队能够以最适合的语言编写整个体系架构的不同部分。此外,每个服务可以根据需要独立扩展。对这样的网络实施安全性、可观察性和流量控制的愿景推动了 Istio 的普及。</p>
|
||
<p>Istio 的 <em>控制平面</em> 本身就是一种现代的云原生应用程序。因此,它从一开始就作为一组微服务而构建。诸如服务发现(Pilot),配置(Galley),证书生成(Citadel)和可扩展性(Mixer)等各个 Istio 组件都被编写并部署为单独的微服务。这些组件需要安全地进行通信并易于观察,这为 Istio 提供了“吃自己的狗粮”的机会(或“喝自己的香槟”,更法语化的比喻!)。</p>
|
||
<h2 id="the-cost-of-complexity">复杂性的代价</h2>
|
||
<p>优秀的团队会回顾他们的选择,并借助事后回顾重新审视当时的选择。通常,当团队接受微服务及其固有的复杂性时,他们会在其他方面寻求改进以证明其取舍的正确性。让我们看一下此视角下的 Istio 控制平面。</p>
|
||
<ul>
|
||
<li><p><strong>微服务使您能够使用不同的语言编写。</strong> 数据平面( Envoy 代理)是用 C++ 编写的,并且此边界受益于 xDS API 的清晰隔离设计。此外,所有 Istio 控制平面组件都是用 Go 编写的。我们为适当的工作选择了适当的语言:高性能的 C++ 用于代理,而在考虑易于访问和快速开发的其他所有场景都会使用 Go。</p></li>
|
||
<li><p><strong>微服务使您能够允许不同的团队分别管理服务。</strong> 在绝大多数 Istio 安装过程中,所有组件都是由单个团队或个人安装和操作的。Istio 的组件划分与构建它的开发团队的划分是一致的,如果 Istio 的组件是由其开发团队作为托管服务交付,那么这样看起来似乎是很合理的,但事实并非如此!虽然这使得组件开发团队的工作变得更简单,但这对数量更多的普通用户的易用性产生了巨大影响。</p></li>
|
||
<li><p><strong>微服务使您能够解耦版本,并在不同时间发布不同的组件。</strong> 控制平面的所有组件从始至终均在同一版本中发布。我们从未测试或支持运行(例如)Citadel 和 Pilot 的不同版本。</p></li>
|
||
<li><p><strong>微服务使您能够独立扩展组件。</strong> 在 Istio 1.5 中,控制平面的开销主要决于一个功能:Envoy xDS API(对数据平面进行编程)。每个其他的功能都有边际成本,这意味着在可单独伸缩的微服务中拥有这些功能的价值很小。</p></li>
|
||
<li><p><strong>微服务使您能够维护安全边界。</strong> 将应用程序分为不同的微服务的另一个很好的理由是,它们是否具有不同的安全角色。诸如 sidecar 注入器,Envoy 引导程序,Citadel 和 Pilot 之类的多个 Istio 微服务拥有几乎等同的更改代理配置的权限。因此,利用其中的任何服务都将造成几乎同等的损害。部署 Istio 时,默认情况下,所有组件都安装在同一 Kubernetes 命名空间中,从而提供了有限的安全隔离。</p></li>
|
||
</ul>
|
||
<h2 id="the-benefit-of-consolidation-introducing-istiod">合并的好处:引入 istiod</h2>
|
||
<p>在确定微服务的许多常见好处并不适用于 Istio 控制平面之后,我们决定将它们统一为一个二进制文件:<strong>istiod</strong>( &rsquo;d&rsquo; 代表 <a href="https://en.wikipedia.org/wiki/Daemon_%28computing%29">daemon</a>)。</p>
|
||
<p>让我们看一下新打包方式的好处:</p>
|
||
<ul>
|
||
<li><p><strong>安装变得更加容易。</strong> 所需的 Kubernetes deployment 和相关配置更少,因此 Istio 的配置选项和参数集大大减少了。在最简单的情况下,<strong><em>您只需启动单个 Pod,就可以启用一个包含了所有功能的 Istio 控制平面。</em></strong></p></li>
|
||
<li><p><strong>配置变得更加容易。</strong> Istio 目前拥有的许多配置选项都是编排控制平面组件的方法,因此不再需要。您也不再需要更改群集范围内的 <code>PodSecurityPolicy</code> 来部署Istio。</p></li>
|
||
<li><p><strong>使用虚拟机变得更加容易。</strong> 要将工作负载添加到网格中,现在只需要安装一个代理和已生成的证书即可。该代理仅连接单个后台服务。</p></li>
|
||
<li><p><strong>维护变得更加容易。</strong> 安装、升级和删除 Istio 不再需要复杂的版本依赖关系和启动顺序。例如:要升级控制平面,您只需要在现有控制平面边上启动一个新的 istiod 版本,对其进行金丝雀部署,然后将所有流量移至该平面即可。</p></li>
|
||
<li><p><strong>伸缩变得更加容易。</strong> 现在只有一个需要伸缩的组件。</p></li>
|
||
<li><p><strong>调试变得更加容易。</strong> 更少的组件意味着更少的跨组件环境调试。</p></li>
|
||
<li><p><strong>启动时间减少。</strong> 在以预定义的顺序启动时,组件不再需要彼此等待。</p></li>
|
||
<li><p><strong>资源使用率下降,响应能力上升。</strong> 组件之间的通信将得到保证,并且不受 gRPC 报文大小限制。缓存可以被安全的共享,从而减少了资源占用。</p></li>
|
||
</ul>
|
||
<p>istiod 将先前由 Pilot,Galley,Citadel 和 sidecar 注入器执行的功能统一为一个二进制文件。</p>
|
||
<p>单独的组件 istio-agent 通过将配置和密钥安全地传递给 Envoy 代理,来帮助每个 sidecar 连接到网格。严格来说,尽管该代理仍然是控制平面的一部分,但它是按 per-pod(每 pod ) 运行的。通过将以前作为 DaemonSet 运行的 per-node(每节点) 功能移动到 per-pod(每 pod )代理中,我们进一步简化了操作。</p>
|
||
<h2 id="extra-for-experts">专家说明</h2>
|
||
<p>在某些情况下,您可能仍然想要独立运行 Istio 组件或替换某些组件。</p>
|
||
<p>一些用户可能想在网格外部使用证书颁发机构(CA),我们有<a href="/v1.12/zh/docs/tasks/security/plugin-ca-cert/">如何执行此操作的文档</a>。如果您使用其他工具进行证书设置,则可以使用它代替内置 CA。</p>
|
||
<h2 id="moving-forward">进阶</h2>
|
||
<p>本质上,istiod 只是打包和优化方面的改变。它与单独的组件基于相同的代码和 API 契约构建,并且仍由我们全面的测试套件覆盖。这使我们有信心将其设置为 Istio 1.5 中的默认设置。该服务现在称为 <code>istiod</code> - 在升级过程完成时,您会看到一个用于现有代理的 <code>istio-pilot</code>。</p>
|
||
<p>虽然迁移到 istiod 似乎是一个巨大的变化,并且对于 <strong>管理</strong> 和 <strong>维护</strong> 网格的人员来说是一个巨大的改进,但它不会让 <strong>使用</strong> Istio 的日常生活变得有何不同。istiod 不会更改用于配置网格的任何 API,因此您现有的进程不会有什么变化。</p>
|
||
<p>这是否意味着微服务对于所有工作负载和架构设计都是错误的?当然不是。它们只是工具箱里的工具,当它们适合您组织的真实情况时,可以发挥最佳的作用。恰恰相反,此变更(引入 istiod )表明了 Istio 项目愿意根据用户的反馈进行更改,并为了所有用户持续专注于简化操作。微服务的大小必须合适,而我们相信我们已经为 Istio 找到了合适的大小。</p></description><pubDate>Thu, 19 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/istiod/</link><author>Craig Box (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/istiod/</guid><category>istiod</category><category>control plane</category><category>operator</category></item><item><title>在 Istio 中进行 WebAssembly 声明式部署</title><description>
|
||
<p>正如 <a href="/v1.12/zh/blog/2020/tradewinds-2020/">Istio 2020——为了商用</a>以及最近的 <a href="/v1.12/zh/news/releases/1.5.x/announcing-1.5/">Istio 1.5 发布公告</a>中指出的那样,WebAssembly (Wasm) 现在是用于扩展 Istio 服务代理( Envoy 代理)功能的(alpha)选项。使用 Wasm,用户可以建立对新协议、自定义指标、日志和其他过滤器的支持。我们的社区(<a href="https://solo.io">Solo.io</a>) 与 Google 紧密合作,专注于提升为 Istio 构建、交流和部署 Wasm 扩展的用户体验。我们发布了 <a href="https://webassemblyhub.io">WebAssembly Hub</a> 和<a href="https://docs.solo.io/web-assembly-hub/latest/installation/">相关工具</a>,以便在使用 Wasm 时可以获得“类似 docker ”的体验。</p>
|
||
<h2 id="background">背景</h2>
|
||
<p>借助 WebAssembly Hub 工具,我们可以使用 <code>wasme</code> CLI 轻松为 Envoy 创建一个 Wasm 项目,将其推送到存储库,然后将其提取或部署到 Istio。例如,要使用 <code>wasme</code> 将 Wasm 扩展部署到 Istio,我们可以运行以下命令:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ wasme deploy istio webassemblyhub.io/ceposta/demo-add-header:v0.2 \
|
||
--id=myfilter \
|
||
--namespace=bookinfo \
|
||
--config &#39;tomorrow&#39;
|
||
</code></pre>
|
||
<p>这会将 <code>demo-add-header</code> 扩展添加到在 <code>bookinfo</code> 命名空间中运行的所有工作负载中。我们可以通过使用 <code>--labels</code> 参数来更精细地控制哪些工作负载获得扩展:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ wasme deploy istio webassemblyhub.io/ceposta/demo-add-header:v0.2 \
|
||
--id=myfilter \
|
||
--namespace=bookinfo \
|
||
--config &#39;tomorrow&#39; \
|
||
--labels app=details
|
||
</code></pre>
|
||
<p>这比手动创建 <code>EnvoyFilter</code> 资源并尝试将 Wasm 模块发送到每个 pod(您的目标工作负载的一部分)要容易得多。不管怎么说,这是与 Istio 进行交互的非常必要的方法。就像用户通常不直接在生产环境中使用 <code>kubectl</code> ,而是喜欢声明式的、基于资源的工作流一样,我们也希望对 Istio 代理进行自定义。</p>
|
||
<h2 id="a-declarative-approach">声明式方法</h2>
|
||
<p>WebAssembly Hub 工具还包括<a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/wasme_operator/">用于将 Wasm 扩展部署到 Istio 工作负载的 operator</a>。<a href="https://kubernetes.io/zh/docs/concepts/extend-kubernetes/operator/">operator</a>允许用户使用声明式的格式定义其 WebAssembly 扩展,并将其交给 operator 以修正部署状态。例如,我们使用 <code>FilterDeployment</code> 资源来定义需要扩展的镜像和工作负载:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: wasme.io/v1
|
||
kind: FilterDeployment
|
||
metadata:
|
||
name: bookinfo-custom-filter
|
||
namespace: bookinfo
|
||
spec:
|
||
deployment:
|
||
istio:
|
||
kind: Deployment
|
||
labels:
|
||
app: details
|
||
filter:
|
||
config: &#39;world&#39;
|
||
image: webassemblyhub.io/ceposta/demo-add-header:v0.2
|
||
</code></pre>
|
||
<p>然后,我们可以获取这个 <code>FilterDeployment</code> 文档,并使用其余的 Istio 资源对其进行版本控制。您可能想知道在 Istio 已经具有 <code>EnvoyFilter</code> 资源的情况下,为什么还需要这个自定义资源来配置 Istio 的服务代理以使用 Wasm 扩展。</p>
|
||
<p>让我们来看看所有这一切在幕后的工作原理。</p>
|
||
<h2 id="how-it-works">工作原理</h2>
|
||
<p>在后台,operator 正在做一些有助于将 Wasm 扩展部署和配置到 Istio 服务代理( Envoy 代理)中的事情。</p>
|
||
<ul>
|
||
<li>设置 Wasm 扩展的本地缓存</li>
|
||
<li>将所需的 Wasm 扩展提取到本地缓存中</li>
|
||
<li>将 <code>wasm-cache</code> 挂载到适当的工作负载中</li>
|
||
<li>使用 <code>EnvoyFilter</code> CRD 配置 Envoy 以使用 Wasm 过滤器</li>
|
||
</ul>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:42.663891779396465%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/deploy-wasm-declarative/how-it-works.png" title="理解 wasme operator 的工作原理">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/deploy-wasm-declarative/how-it-works.png" alt="wasme operator 工作原理" />
|
||
</a>
|
||
</div>
|
||
<figcaption>理解 wasme operator 的工作原理</figcaption>
|
||
</figure>
|
||
<p>目前,Wasm 镜像需要发布到一个 registry 中,以便 operator 能够正确缓存它。缓存 pod 作为 DaemonSet 运行在每个节点上,以便可以将缓存挂载到 Envoy 容器中。它并不是最理想的机制,我们正在对其进行改进。理想情况下,我们无需处理任何挂载,而是可以直接通过 HTTP 将模块流式传输到代理,因此请随时关注更新(应在接下来的几天内完成)。使用 <code>sidecar.istio.io/userVolume</code> 和 <code>sidecar.istio.io/userVolumeMount</code> 注释后,挂载将会建立。有关其工作原理的更多信息,请参见<a href="/v1.12/zh/docs/reference/config/annotations/">有关 Istio 资源注释的文档</a>。</p>
|
||
<p>一旦 Wasm 模块被正确缓存并挂载入工作负载的服务代理中,operator 即可配置 <code>EnvoyFilter</code> 资源。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: EnvoyFilter
|
||
metadata:
|
||
name: details-v1-myfilter
|
||
namespace: bookinfo
|
||
spec:
|
||
configPatches:
|
||
- applyTo: HTTP_FILTER
|
||
match:
|
||
context: SIDECAR_INBOUND
|
||
listener:
|
||
filterChain:
|
||
filter:
|
||
name: envoy.http_connection_manager
|
||
subFilter:
|
||
name: envoy.router
|
||
patch:
|
||
operation: INSERT_BEFORE
|
||
value:
|
||
config:
|
||
config:
|
||
configuration: tomorrow
|
||
name: myfilter
|
||
rootId: add_header
|
||
vmConfig:
|
||
code:
|
||
local:
|
||
filename: /var/local/lib/wasme-cache/44bf95b368e78fafb663020b43cf099b23fc6032814653f2f47e4d20643e7267
|
||
runtime: envoy.wasm.runtime.v8
|
||
vmId: myfilter
|
||
name: envoy.filters.http.wasm
|
||
workloadSelector:
|
||
labels:
|
||
app: details
|
||
version: v1
|
||
</code></pre>
|
||
<p>您可以看到 <code>EnvoyFilter</code> 资源配置了代理以添加 <code>envoy.filter.http.wasm</code> 过滤器并从 <code>wasme-cache</code> 加载 Wasm 模块。</p>
|
||
<p>一旦将 Wasm 扩展加载到 Istio 服务代理,它将使用您引入的任意自定义代码来扩展代理的功能。</p>
|
||
<h2 id="next-steps">下一步</h2>
|
||
<p>在此博客中,我们探讨了将 Wasm 扩展安装到 Istio 工作负载中的选项。在 Istio 上开始使用 WebAssembly 的最简单方法是使用 <code>wasme</code> 工具<a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/getting_started/">创建一个新的 Wasm 项目</a>,可使用 C++,AssemblyScript [或即将推出的 Rust!]。例如,要设置 C++ Wasm 模块,可以运行:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ wasme init ./filter --language cpp --platform istio --platform-version 1.5.x
|
||
</code></pre>
|
||
<p>如果没有额外的参数,则 <code>wasme init</code> 将进入交互模式,引导您选择正确的值。</p>
|
||
<p>查看 <a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/getting_started/">WebAssembly Hub wasme 工具</a>,以在 Istio 上开始使用 Wasm。</p>
|
||
<h2 id="learn-more">了解更多</h2>
|
||
<ul>
|
||
<li><p><a href="/v1.12/zh/blog/2020/wasm-announce/">重新定义代理的扩展性</a></p></li>
|
||
<li><p>WebAssembly SF talk (video): <a href="https://www.youtube.com/watch?v=OIUPf8m7CGA">网络代理的扩展</a>, by John Plevyak</p></li>
|
||
<li><p><a href="https://www.solo.io/blog/an-extended-and-improved-webassembly-hub-to-helps-bring-the-power-of-webassembly-to-envoy-and-istio/">Solo 博客</a></p></li>
|
||
<li><p><a href="https://github.com/proxy-wasm/spec">Proxy-Wasm ABI 规范</a></p></li>
|
||
<li><p><a href="https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/blob/master/docs/wasm_filter.md">Proxy-Wasm C++ SDK</a> 以及 <a href="https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/blob/master/docs/wasm_filter.md">开发者文档</a></p></li>
|
||
<li><p><a href="https://github.com/proxy-wasm/proxy-wasm-rust-sdk">Proxy-Wasm Rust SDK</a></p></li>
|
||
<li><p><a href="https://github.com/solo-io/proxy-runtime">Proxy-Wasm AssemblyScript SDK</a></p></li>
|
||
<li><p><a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/">教程</a></p></li>
|
||
<li><p><a href="https://www.youtube.com/channel/UCuketWAG3WqYjjxtQ9Q8ApQ">Solo.io 的 Youtube 频道</a>里的视频</p></li>
|
||
</ul></description><pubDate>Mon, 16 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/deploy-wasm-declarative/</link><author>Christian Posta (Solo.io)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/deploy-wasm-declarative/</guid><category>wasm</category><category>extensibility</category><category>alpha</category><category>operator</category></item><item><title>重新定义代理的扩展性:Envoy 和 Istio 引入 WebAssembly</title><description>
|
||
<p>自 2016 年使用 <a href="https://www.envoyproxy.io/">Envoy</a> 以后,Istio 项目一直想提供一个平台,在此平台上可以构建丰富的扩展,以满足用户多样化的需求。有很多要向服务网格的数据平面增加功能的理由 &mdash; 比如:支持更新的协议,与专有安全控件集成,或是通过自定义度量来增强可观察性。</p>
|
||
<p>在过去的一年半中,我们在 Google 的团队一直在努力用 <a href="https://webassembly.org/">WebAssembly</a> 来为 Envoy 代理添加动态扩展。今天我们很高兴与大家分享这项工作,并推出<a href="https://github.com/proxy-wasm/spec">针对代理的 WebAssembly (Wasm)</a> (Proxy-Wasm):包括一个会标准化的 ABI,SDK,以及它的第一个重点实现:新的,低延迟的 <a href="/v1.12/zh/docs/reference/config/telemetry">Istio 遥测系统</a>。</p>
|
||
<p>我们还与社区紧密合作,以确保为用户提供良好的开发者体验,帮助他们快速上手。Google 团队一直与 <a href="https://solo.io">Solo.io</a> 团队紧密合作,Solo 他们已经建立了 <a href="https://webassemblyhub.io/">WebAssembly Hub</a> 服务,用于构建,共享,发现和部署 Wasm 扩展。有了 WebAssembly Hub,Wasm 扩展就会像容器一样易于管理,安装和运行。</p>
|
||
<p>这个项目现在发布了 Alpha 版本,仍然还有很多<a href="#next-steps">工作要做</a>,但是我们很高兴将其交提供给开发者,以便他们可以开始尝试由此带来的巨大可能性。</p>
|
||
<h2 id="background">背景</h2>
|
||
<p>可扩展需求一直都是 Istio 和 Envoy 项目的基本原则,但是两个项目采用了不同的实现方式。Istio 项目的做法是启用一个通用的进程外扩展模型,叫做 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/">Mixer</a>,以此带来轻量级的开发者体验,而 Envoy 则专注于代理内<a href="https://www.envoyproxy.io/docs/envoy/latest/extending/extending">扩展</a>。</p>
|
||
<p>每种方法都各有利弊。Istio 模型导致明显的资源效率低下,从而影响了尾部延迟和资源利用率。该模型在根本上来说是有局限性的 - 例如,它永远不会支持实现<a href="https://blog.envoyproxy.io/how-to-write-envoy-filters-like-a-ninja-part-1-d166e5abec09">自定义协议处理</a>。</p>
|
||
<p>Envoy 模型强化了单体构建过程,并要求使用 C++ 编写扩展,从而限制了开发者的生态。给集群发布新的扩展需要下发新的二进制文件并滚动重启,这可能很难协调,并有可能会导致停机。这也促使了开发者向 Envoy 上游提交他们的扩展,而这些扩展仅由一小部分生产环境使用,更多仅仅是为了利用其发布机制。</p>
|
||
<p>随着时间的流逝,Istio 的一些对性能最敏感的功能已合进了上游的 Envoy - 例如<a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/rbac_filter">流量检查策略</a>和例如<a href="/v1.12/zh/docs/reference/config/telemetry/metrics/">遥测上报</a>。尽管如此,我们一直想把扩展汇聚在一个技术栈上,从而减少两者之间犹豫的权衡:这使 Envoy 版本与其扩展生态系统脱钩,使开发者能够使用他们选择的语言进行工作,并使 Istio 可靠地推出新功能而不必有停机风险。</p>
|
||
<h2 id="what-is-WebAssembly">什么是 WebAssembly</h2>
|
||
<p><a href="https://webassembly.org/">WebAssembly</a>(Wasm)是一种由<a href="https://github.com/appcypher/awesome-wasm-langs">多种语言</a>编写的,可移植的字节码格式,它能以以接近本机的速度执行。其最初的<a href="https://webassembly.org/docs/high-level-goals/">设计目标</a>与上述挑战很相符,并且在其背后得到了相当大的行业支持。Wasm 是在所有主流浏览器中可以本地运行的第四种标准语言(继 HTML,CSS 和 JavaScript 之后),于 2019 年 12 月成为 <a href="https://www.w3.org/TR/wasm-core-1/">W3C 正式建议</a>。这使我们有信心对其进行战略下注。</p>
|
||
<p>尽管 WebAssembly 最初是作为客户端技术而诞生,但它在服务器上用也有很多优势。运行时是内存安全的,并且以沙盒方式运行以确保安全。它有一个很大的工具生态系统,用于以文本或二进制格式编译和调试 Wasm。<a href="https://www.w3.org/">W3C</a> 和 <a href="https://bytecodealliance.org/">BytecodeAlliance</a> 已成为其它服务器端工作的活跃中心。比如,Wasm 社区正在 W3C 中标准化 <a href="https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/">&ldquo;WebAssembly 系统接口 Interface&rdquo; (WASI)</a>,并通过一个示例实现,它为 Wasm “程序” 提供了一个类似 OS 的抽象。</p>
|
||
<h2 id="bringing-WebAssembly-to-Envoy">把 WebAssembly 引入 Envoy</h2>
|
||
<p><a href="https://github.com/envoyproxy/envoy/issues/4272">在过去的 18 个月中</a>,我们一直与 Envoy 社区合作把 Wasm 的扩展引入 Envoy,并将其贡献到上游。我们很高兴地宣布,此特性在 <a href="/v1.12/zh/news/releases/1.5.x/announcing-1.5/">Istio 1.5</a> 自带的 Envoy 中以 Alpha 版本可用了,其源代码在 <a href="https://github.com/envoyproxy/envoy-wasm/"><code>envoy-wasm</code></a> 开发分支中,并且正在努力将其合并到 Envoy 主干上。该实现使用了 Google 高性能 <a href="https://v8.dev/">V8 引擎</a>中内置的 WebAssembly 运行时。</p>
|
||
<p>除了构建底层的运行时,我们还构建了:</p>
|
||
<ul>
|
||
<li>把 Wasm 嵌入代理的通用应用程序二进制接口(ABI),这意味着编译后的扩展将可以在不同版本的 Envoy 中工作,甚至其它代理也可以,当然当然,其它代理得实现 ABI。</li>
|
||
<li>用 <a href="https://github.com/proxy-wasm/proxy-wasm-cpp-sdk">C++</a>,
|
||
<a href="https://github.com/proxy-wasm/proxy-wasm-rust-sdk">Rust</a> 和 <a href="https://github.com/solo-io/proxy-runtime">AssemblyScript</a> 可以方便进行扩展开发的 SDK,后续还有很多语言支持</li>
|
||
<li>全面的<a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/">示例和说明</a>介绍如何在 Istio 和独立的 Envoy 中部署</li>
|
||
<li>允许使用其它 Wasm 运行时的抽象,包括把本地把扩展直接编译进 Envoy 中 “null” 运行时,这对于测试和调试非常有用</li>
|
||
</ul>
|
||
<p>使用 Wasm 扩展 Envoy 带来了几个主要好处:</p>
|
||
<ul>
|
||
<li>敏捷性:可以用 Istio 控制平面在运行时下发和重载扩展。这就可以快速的进行扩展开发→ 测试→ 发布周期,而无需重启 Envoy。</li>
|
||
<li>发布库:一旦完成合并到主树中之后,Istio 和其它程序将能够使用 Envoy 的发布库,而不是自己构建。这也方便 Envoy 社区迁移某些内置扩展到这个模型,从而减少他们的工作。</li>
|
||
<li>可靠性和隔离性:扩展部署在具有资源限制的沙箱中,这意味着它们现在可以崩溃或泄漏内存,但不会让整个 Envoy 挂掉。CPU 和内存使用率也可以受到限制。</li>
|
||
<li>安全性:沙盒具有一个明确定义的 API,用于和 Envoy 通信,因此扩展只能访问和修改链接或者请求中有限数量的属性。此外,由于 Envoy 协调整个交互,因此它可以隐藏或清除扩展中的敏感信息(例如,HTTP 头中的 “Authorization”和“Cookie”,或者客户端的 IP 地址)。</li>
|
||
<li>灵活性:<a href="https://github.com/appcypher/awesome-wasm-langs">可以将超过 30 种编程语言编译为 WebAssembly</a>,可以让各种技术背景的开发人员都可以用他们选择的语言来编写 Envoy 扩展,比如:C++,Go,Rust,Java,TypeScript 等。</li>
|
||
</ul>
|
||
<p>“看到 Envoy 上支持了 WASM,我感到非常兴奋;这是 Envoy 可扩展的未来。Envoy 的 WASM 支持与社区驱动的 hub 相结合,将在服务网格和 API 网关用例中开启出令人难以置信的网络创新。我迫不及待地想看到社区构建是如何向前发展的。” – Envoy 创造者 Matt Klein。</p>
|
||
<p>有关实现的技术细节,请关注即将在 <a href="https://blog.envoyproxy.io/">Envoy 博客</a>上发的文章。</p>
|
||
<p>主机环境和扩展之间的 <a href="https://github.com/proxy-wasm">Proxy-Wasm</a> 接口有意设计为代理无感知的。我们已将其内置到了 Envoy 中,但它是为其它代理供应商设计的。我们希望看为 Istio 和 Envoy 编写的扩展也可以在其它基础设施中运行。很快就会有更多相关的设计和实现了。</p>
|
||
<h2 id="building-on-WebAssembly-in-Istio">Istio 中的 WebAssembly 构建</h2>
|
||
<p>为了显著提高性能,Istio 在 1.5 的发布中,把它的几个扩展内置到了 Envoy 中。在执行此工作时,我们把这些同样的扩展可以作为 Proxy-Wasm 模块进行编译和运行,测试确保其行为没有异常。考虑到我们认为 Wasm 支持还是 Alpha 版本,我们还没有完全准备好将这个设置设为默认设置;然而,在我们的通用实现和主机环境还是给了我们不少信心,至少 ABI 和 SDK 已经开发完成了。</p>
|
||
<p>我们还是要小心地确保 Istio 控制平面及其 <a href="/v1.12/zh/docs/reference/config/networking/envoy-filter/">Envoy 配置 API</a> 已经可以支持 Wasm。我们有一些示例来展示几种常见的定制,例如定制头解码或程序中路由,这是用户的常见要求。当将这个支持发展到 Beta 版本时,将会看到 Istio 中使用 Wasm 最佳实践的文档。</p>
|
||
<p>最后,我们正在与许多编写了 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/adapters/">Mixer 适配器</a>的供应商合作,帮助他们迁移到 Wasm — 如果这是前行的最佳方式。Mixer 将在未来的版本中转为社区项目,它将仍可用于老系统。</p>
|
||
<h2 id="developer-experience">开发者体验</h2>
|
||
<p>没有出色的开发者体验,再强大的工具也毫无用处。Solo.io <a href="https://www.solo.io/blog/an-extended-and-improved-webassembly-hub-to-helps-bring-the-power-of-webassembly-to-envoy-and-istio/">最近宣布</a>发布 <a href="https://webassemblyhub.io/">WebAssembly Hub</a>,这是一套为 Envoy 和 Istio 做的,用于构建,部署,共享和发现 Envoy Proxy Wasm 扩展的工具和仓库。</p>
|
||
<p>WebAssembly Hub 把为开发和部署 Wasm 扩展所需的许多步骤都完全自动化了。使用 WebAssembly Hub 工具,用户可以轻松地把任何受支持语言开发的代码编译为 Wasm 扩展。可以将这些扩展上传到 Hub 仓库,并且用单个命令就将其在 Istio 中部署和删除。</p>
|
||
<p>在后台,Hub 处理了很多细节问题,例如:引入正确的工具链、ABI 版本验证、权限控制等等。该工作流程还通过自动化扩展部署,消除了跨 Istio 服务代理的配置更改带来的麻烦。此工具帮助用户和操作员避免由于配置错误或版本不匹配而导致的意外行为。</p>
|
||
<p>WebAssembly Hub 工具提供了功能强大的 CLI 和优雅且易于使用的图形用户界面。WebAssembly Hub 的一个重要目标是简化围绕构建 Wasm 模块的体验,并为开发者提供共享和发现有用扩展的协作场所。</p>
|
||
<p>请查看<a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/">入门指南</a>,以创建您的第一个 Proxy-Wasm 扩展。</p>
|
||
<h2 id="next-steps">下一步</h2>
|
||
<p>除了努力发布 Beta 版,我们还致力于确保围绕 Proxy-Wasm 有一个持久的社区。ABI 需要最终确定,而将其转变为标准的工作将会在适当的标准机构内获得更广泛的反馈后完成。完成向 Envoy 主干提供上游支持的工作仍在进行中。我们还在为工具和 WebAssembly Hub 寻找合适的社区。</p>
|
||
<h2 id="learn-more">了解更多</h2>
|
||
<ul>
|
||
<li>WebAssembly SF talk (视频) : <a href="https://www.youtube.com/watch?v=OIUPf8m7CGA">网络代理扩展</a>, by John Plevyak</li>
|
||
<li><a href="https://www.solo.io/blog/an-extended-and-improved-webassembly-hub-to-helps-bring-the-power-of-webassembly-to-envoy-and-istio/">Solo 博客</a></li>
|
||
<li><a href="https://github.com/proxy-wasm/spec">Proxy-Wasm ABI 说明</a></li>
|
||
<li><a href="https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/blob/master/docs/wasm_filter.md">Proxy-Wasm C++ SDK</a> 和其<a href="https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/blob/master/docs/wasm_filter.md">开发者文档</a></li>
|
||
<li><a href="https://github.com/proxy-wasm/proxy-wasm-rust-sdk">Proxy-Wasm Rust SDK</a></li>
|
||
<li><a href="https://github.com/solo-io/proxy-runtime">Proxy-Wasm AssemblyScript SDK</a></li>
|
||
<li><a href="https://docs.solo.io/web-assembly-hub/latest/tutorial_code/">指南</a></li>
|
||
<li><a href="https://www.youtube.com/channel/UCuketWAG3WqYjjxtQ9Q8ApQ">Solo.io Youtube 频道</a>上的视频</li>
|
||
</ul></description><pubDate>Thu, 05 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/wasm-announce/</link><author>Craig Box, Mandar Jog, John Plevyak, Louis Ryan, Piotr Sikora (Google), Yuval Kohavi, Scott Weiss (Solo.io)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/wasm-announce/</guid><category>wasm</category><category>extensibility</category><category>alpha</category><category>performance</category><category>operator</category></item><item><title>Istio 2020——为了商用</title><description>
|
||
<p>Istio 解决了人们在运行微服务时遇到的实际问题。甚至<a href="https://kubernetespodcast.com/episode/016-descartes-labs/">早期的预发行版本</a>就已经可以帮助用户诊断其体系架构中的延迟,提高服务的可靠性以及透明地保护防火墙后的流量。</p>
|
||
<p>去年,Istio 项目成长巨大。经过 9 个月的酝酿,在 2019 年第一季度发行 1.1 之前,我们设定了一个季度发布节奏的目标。我们知道,持续且可预测地交付非常重要。我们计划连续三个季度发布三个版本,并且我们为实现了这一目标感到自豪。</p>
|
||
<p>过去一年,我们改进了构建和测试基础架构,从而提高了质量并简化了发布周期。我们将用户体验提高了一倍,添加了许多命令使网格的操作和调试变得更加简单。我们还看到为 Istio 做出贡献的开发人员和公司数量急剧增长,最终,我们成为了 <a href="https://octoverse.github.com/#fastest-growing-oss-projects-by-contributors">GitHub 增长最快的十大项目中排名第 4 名</a>!</p>
|
||
<p>2020 年,Istio 有宏伟的目标,并且我们正在努力中。与此同时,我们坚信良好的基础设施应该“无聊”。在生产中使用 Istio 应该是无缝的体验;性能不应该成为问题,升级应该是非事件性的,复杂的任务应自动化。随着我们对更强大的可扩展性的投入,我们认为 Istio 在专注于现在成就的同时,可以加快服务网格领域的创新步伐。以下是我们在 2020 年主要工作的详情。</p>
|
||
<h2 id="sleeker-smoother-and-faster">更快、更简单</h2>
|
||
<p>从第一天起,Istio 就通过 Mixer 组件提供了可扩展性支持。Mixer 是一个平台,允许使用自定义<a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#adapters">适配器</a>充当数据平面与策略及遥测后端之间的中介。Mixer 必定会增加请求的开销,因为它必须扩展到进程之外。因此,我们正在向一种可以直接在代理中进行扩展的模型转变。</p>
|
||
<p>Istio 的<a href="/v1.12/zh/docs/concepts/security/#authentication-policies">认证</a>和<a href="/v1.12/zh/docs/concepts/security/#authorization">授权</a>策略已经涵盖了 Mixer 用于策略执行的大多数用例,这些策略使您可以直接在代理中控制 workload 到 workload 以及终端用户到 workload 的授权。常见的监控用例也已经转移到代理中,我们<a href="/v1.12/zh/docs/ops/configuration/telemetry/in-proxy-service-telemetry/">引入了代理内支持</a>,以便将遥测发送到 Prometheus 和 Stackdriver。</p>
|
||
<p>我们的基准测试表明,新的遥测模型可显著减少延迟,并可提供行业领先的性能,同时降低 50% 的延迟和 CPU 消耗。</p>
|
||
<h2 id="a-new-model-for-Istio-extensibility">新的 Istio 可扩展性模型</h2>
|
||
<p>新的 Mixer 模型使用 Envoy 中的扩展来提供更多功能。Istio 社区正在领导 Envoy 的 <a href="https://webassembly.org/">WebAssembly</a>(Wasm)运行时的实现,Wasm 让我们可以使用<a href="https://github.com/appcypher/awesome-wasm-langs">超过 20 种的语言</a>来开发模块化、沙盒化的扩展。可以在代理继续提供流量的同时动态加载、重载扩展。Wasm 扩展程序还可以通过 Mixer 无法做到的方式来扩展平台。它们可以充当自定义协议处理程序,并在通过 Envoy 时转换有效负载,简而言之,它们可以执行与 Envoy 中内置的模块相同的操作。</p>
|
||
<p>我们正在与 Envoy 社区一起研究发现和分发这些扩展的方法。我们希望使 WebAssembly 扩展像容器一样易于安装和运行。我们的许多合作伙伴已经编写了 Mixer 适配器,并与我们一起将其移植到 Wasm。如何编写自己的扩展并进行自定义集成?我们正在开发相关的指南和代码实验室。</p>
|
||
<p>更换扩展模型后,我们还可以删除数十个 CRD。与 Istio 集成的每个软件都不再需要唯一 CRD。</p>
|
||
<p>通过 <code>preview</code> 配置文件安装 Istio 1.5 不会再安装 Mixer。安全起见,如果您是从以前的版本升级,或通过 <code>default</code> 配置文件安装,我们仍会保留 Mixer。当使用 Prometheus 或 Stackdriver 进行度量时,建议您尝试新模式并查看性能提高了多少。</p>
|
||
<p>如果有需要,您可以保持安装并启用 Mixer。最终,Mixer 将成为 Istio 单独的发行组件,成为 <a href="https://github.com/istio-ecosystem/">istio-ecosystem</a> 的一部分。</p>
|
||
<h2 id="fewer-moving-parts">减少移动部分</h2>
|
||
<p>我们还将简化其余控制平面的 deployment。为此,我们将几个控制平面组件合并为一个组件:Istiod。该二进制文件包括 Pilot、Citadel、Galley 和 Sidecar 注入器的功能。这种方法从许多方面改善了 Istio 的安装和管理,降低了安装和配置的复杂性、维护工作量以及问题诊断时间,同时提高了响应速度。
|
||
关于 Istiod 的更多内容请查看 <a href="https://blog.christianposta.com/microservices/istio-as-an-example-of-when-not-to-do-microservices/">Christian Posta 的这篇博客</a>。</p>
|
||
<p>我们将 Istiod 作为 1.5 中所有配置文件的默认配置。</p>
|
||
<p>为了减少每个节点的占用空间,我们放弃了用于分发证书的节点代理,并将其功能迁移至已经在每个 Pod 中运行的 istio-agent 中。从图片来看,我们正在从这里:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:75%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/tradewinds-2020/architecture-pre-istiod.svg" title="Istio 目前的架构">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/tradewinds-2020/architecture-pre-istiod.svg" alt="基于 Pilot、Mixer、Citadel、Sidecar 注入器的 Istio 架构" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 目前的架构</figcaption>
|
||
</figure>
|
||
<p>迁移到这里:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:75%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/tradewinds-2020/architecture-post-istiod.svg" title="Istio 2020 年的架构">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/tradewinds-2020/architecture-post-istiod.svg" alt="基于 Istiod 的 Istio 架构" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 2020 年的架构</figcaption>
|
||
</figure>
|
||
<p>2020 年,我们将继续专注于普及,实现默认 <code>零配置</code> 的目标,该默认设置不需要您更改应用程序的任何配置即可使用 Istio 的大多数功能。</p>
|
||
<h2 id="improved-lifecycle-management">改进生命周期管理</h2>
|
||
<p>为了改进 Istio 的生命周期管理,我们使用了基于 <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/">operator</a> 的安装方式。这里介绍 <strong><a href="/v1.12/zh/docs/setup/install/istioctl/">Istio Operator CRD 的两种安装模式</a></strong>:</p>
|
||
<ul>
|
||
<li>人为触发:使用 istioctl 将设置应用至集群。</li>
|
||
<li>机器触发:使用一个控制器,实时观察 CRD 的改动并使其生效。</li>
|
||
</ul>
|
||
<p>在 2020 年,升级 Istio 也将变得更加容易。我们将添加对 Istio 控制平面新版本的&rdquo;金丝雀&rdquo;支持,这使您可以同时运行现有版本的和新版本,并将数据平面逐渐切换至新版本。</p>
|
||
<h2 id="secure-by-default">默认安全</h2>
|
||
<p>Istio 已经为强大的服务安全性提供了基础:可靠的 workload 身份、强大的访问策略、全面的审核日志记录。我们正在为这些功能提供稳定的 API;许多 Alpha API 都将在 1.5 版中过渡为 Beta 版,我们希望到 2020 年底它们都将成为 v1 版本。要了解有关 API 状态的更多信息,请参见我们的<a href="/v1.12/zh/about/feature-stages/#istio-features">功能页面</a>。</p>
|
||
<p>默认情况下,网络流量也变得更加安全。继许多用户可以在评估时启用它之后,<a href="/v1.12/zh/docs/tasks/security/authentication/auto-mtls/">自动双向 TLS</a> 已成为 Istio 1.5 中的推荐做法。</p>
|
||
<p>此外,我们将让 Istio 所需的权限更少,并简化其依赖性,从而使 Istio 成为更强大的系统。在以前,您必须使用 Kubernetes Secrets 将证书安装到 Envoy,这些证书作为文件挂载至每个代理中。而现在,通过<a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret">密钥发现服务(SDS)</a> ,我们可以安全地分发这些证书,而不必担心它们会被计算机上的其他 workload 拦截。该模式将成为 1.5 中的默认模式。</p>
|
||
<p>摆脱节点代理,不仅简化了部署,而且消除了对整个集群范围内 <code>PodSecurityPolicy</code> 的要求,从而进一步改善了集群的安全性。</p>
|
||
<h2 id="other-features">其它功能</h2>
|
||
<p>这是 Istio 在 2020 年一些值得期待的、令人兴奋的事情:</p>
|
||
<ul>
|
||
<li>与更多托管的 Kubernetes 环境集成,目前已有 15 个供应商提供了 Istio 服务网格,这些公司包括:Google、IBM、Red Hat、VMware、Alibaba 以及 Huawei。</li>
|
||
<li>更多的关注 <code>istioctl</code> 及其帮助诊断问题的能力。</li>
|
||
<li>将基于 VM 的 workload 更好地集成到网格中。</li>
|
||
<li>继续努力使多群集和多网络网格更易于配置、维护和运行。</li>
|
||
<li>与更多的服务发现系统集成,包括 Functions-as-a-Service。</li>
|
||
<li>实现新的 <a href="https://kubernetes-sigs.github.io/service-apis/">Kubernetes service API</a>(目前正在开发中)。</li>
|
||
<li><a href="https://github.com/istio/enhancements/">增强存储库</a>,以便开发追踪功能。</li>
|
||
<li>让没有 Kubernetes 的 Istio 可以更轻松地运行!</li>
|
||
</ul>
|
||
<p>从大海到<a href="https://www.youtube.com/watch?v=YjZ4AZ7hRM0">天空</a>,Istio 期待您的加入!</p></description><pubDate>Tue, 03 Mar 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/tradewinds-2020/</link><author>Istio Team</author><guid isPermaLink="true">/v1.12/zh/blog/2020/tradewinds-2020/</guid><category>roadmap</category><category>security</category><category>performance</category><category>operator</category></item><item><title>移除跨 Pod Unix Domain Socket</title><description><p>在 Istio 1.5 之前,执行秘密发现服务(SDS)期间,SDS 客户端和 SDS 服务器通过跨 Pod Unix Domain Socket(UDS)进行通信,该法需要 Kubernetes Pod 安全策略提供保护。</p>
|
||
<p>在 Istio 1.5 中,Pilot Agent、Envoy 和 Citadel Agent 将运行在同一个容器中(体系结构如下图所示)。为了防止攻击者窃听 Envoy(SDS 客户端)和 Citadel Agent(SDS 服务器)之间的跨 Pod UDS,Istio 1.5 将 Pilot Agent 和 Citadel Agent 合并为一个 Istio Agent,并将 Envoy 和 Citadel Agent 之间的 UDS 变为 Istio Agent 专用的(私有的)。Istio Agent 容器被部署为应用服务容器的 Sidecar。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:80.39622513132818%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/istio-agent/istio_agent.svg" title="Istio Agent 的体系结构">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/istio-agent/istio_agent.svg" alt="Istio Agent 的体系结构" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio Agent 的体系结构</figcaption>
|
||
</figure></description><pubDate>Thu, 20 Feb 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/istio-agent/</link><author>Lei Tang (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/istio-agent/</guid><category>security</category><category>secret discovery service</category><category>unix domain socket</category></item><item><title>使用 Admiral 管理 Istio 多集群的配置和服务发现</title><description>
|
||
<p>在 Intuit 公司,我们看到了博客<a href="/v1.12/zh/blog/2019/isolated-clusters/">用于隔离和边界保护的多网格部署</a>,其中提到的某些问题与我们有关系。我们意识到,即使我们想要配置单网格多集群,而不是博客中描述的多个网格联邦,我们的环境中也会遇到相同的非统一命名问题。这篇博客介绍了我们如何使用 <a href="https://github.com/istio-ecosystem/admiral">Admiral</a> 解决这些问题,该项目是 GitHub 组织 <code>istio-ecosystem</code> 下的一个开源项目。</p>
|
||
<h2 id="background">背景</h2>
|
||
<p>使用 Istio,我们意识到多集群的配置很复杂,并且随着时间的推移很难维护。结果就是,出于可伸缩性和其他操作可行性的考虑,我们选择了<a href="/v1.12/zh/docs/setup/install/multicluster/gateways/#deploy-the-Istio-control-plane-in-each-cluster">具有控制平面副本集的多集群 Istio 服务网格</a>中描述的模型。遵循此模型,在大范围使用 Istio 服务网格之前,我们必须解决这些关键需求:</p>
|
||
<ul>
|
||
<li>如<a href="/v1.12/zh/blog/2019/isolated-clusters/#features-of-multi-mesh-deployments">多网格部署的功能</a>中所描述的,创建与命名空间分离的服务 DNS。</li>
|
||
<li>跨集群的服务发现。</li>
|
||
<li>支持双活以及 HA/DR 部署。我们还必须通过在分散的集群中的全局唯一命名空间中部署服务来支持这些关键的弹性模式。</li>
|
||
</ul>
|
||
<p>我们拥有超过 160 个的 Kubernetes 集群以及跨集群的全局唯一命名空间。基于这样的配置,我们可以根据命名空间名称,将相同的服务 workload 部署到不同区域中。
|
||
结果是,我们根据<a href="/v1.12/zh/blog/2019/multicluster-version-routing">多集群网格中的分版本路由</a>中的路由策略,示例中的 <code>foo.namespace.global</code> 无法跨集群工作。我们需要通过全局唯一的、可发现的 service DNS,该 DNS 可以解析多个集群中的服务实例,每个实例都可以使用其唯一 Kubernetes FQDN 进行寻址/运行。
|
||
例如,如果 <code>foo</code> 以不同的名称,同时运行在两个 Kubernetes 集群中,则 <code>foo.global</code> 应该同时解析为 <code>foo.uswest2.svc.cluster.local</code> 和 <code>foo.useast2.svc.cluster.local</code>。并且,我们的服务需要其他具有不同解析度和全局路由属性的 DNS 名称。例如,<code>foo.global</code> 应首先在本地解析,然后使用拓扑路由,将其路由到远程实例,而<code>foo-west.global</code> 和 <code>foo-east.global</code>(用于测试的名称)始终应解析到相应地区。</p>
|
||
<h2 id="contextual-configuration">上下文配置</h2>
|
||
<p>经过进一步的调查,很明显,配置需要根据上下文来确定:每个集群都需要根据其场景定制配置。</p>
|
||
<p>例如,我们有一个被订单和报告消费的支付服务。支付服务在 <code>us-east</code>(集群 3)和 <code>us-west</code>(集群 2)之间进行了 HA/DR 部署。支付服务部署在两个区域不同名的命名空间中。订单服务作为支付方式,部署在 <code>us-west</code> 另一个集群中(集群 1)。报告服务与 <code>us-west</code> 中的支付服务部署在同一集群中(集群 2)。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60.81558869142712%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/multi-cluster-mesh-automation/Istio_mesh_example.svg" title="Istio 中的 workload 跨集群通信">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/multi-cluster-mesh-automation/Istio_mesh_example.svg" alt="Istio 多集群调用 workload 的示例" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 中的 workload 跨集群通信</figcaption>
|
||
</figure>
|
||
<p>当集群 1 和集群 2 中的其它服务想要使用支付服务时,下面的 Istio <code>ServiceEntry</code> yaml 说明了其需要使用的上下文配置:</p>
|
||
<p>集群 1 Service Entry</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: payments.global-se
|
||
spec:
|
||
addresses:
|
||
- 240.0.0.10
|
||
endpoints:
|
||
- address: ef394f...us-east-2.elb.amazonaws.com
|
||
locality: us-east-2
|
||
ports:
|
||
http: 15443
|
||
- address: ad38bc...us-west-2.elb.amazonaws.com
|
||
locality: us-west-2
|
||
ports:
|
||
http: 15443
|
||
hosts:
|
||
- payments.global
|
||
location: MESH_INTERNAL
|
||
ports:
|
||
- name: http
|
||
number: 80
|
||
protocol: http
|
||
resolution: DNS
|
||
</code></pre>
|
||
<p>集群 2 Service Entry</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: payments.global-se
|
||
spec:
|
||
addresses:
|
||
- 240.0.0.10
|
||
endpoints:
|
||
- address: ef39xf...us-east-2.elb.amazonaws.com
|
||
locality: us-east-2
|
||
ports:
|
||
http: 15443
|
||
- address: payments.default.svc.cluster.local
|
||
locality: us-west-2
|
||
ports:
|
||
http: 80
|
||
hosts:
|
||
- payments.global
|
||
location: MESH_INTERNAL
|
||
ports:
|
||
- name: http
|
||
number: 80
|
||
protocol: http
|
||
resolution: DNS
|
||
</code></pre>
|
||
<p>从集群 2 中报告服务的角度来看,支付 <code>ServiceEntry</code>(Istio CRD)应将 <code>us-west</code> 指向本地 Kubernetes FQDN,将 <code>us-east</code> 指向集群 3 的 <code>istio-ingressgateway</code>(负载均衡器)。从集群 1 中订单服务的角度来看,支付 <code>ServiceEntry</code> 应将 <code>us-west</code> 指向集群 2 的 <code>istio-ingressgateway</code> 以及将 <code>us-east</code> 指向集群 3 的 <code>istio-ingressgateway</code>。</p>
|
||
<p>但是,还有更复杂的情况:如果 <code>us-west</code> 的支付服务想进行计划维护,现在要将流量转移到 <code>us-east</code> 的支付服务,此时该怎么办?这要求支付服务更改其所有客户集群中的 Istio 配置。如果没有自动化,这几乎不可能。</p>
|
||
<h2 id="admiral-to-the-rescue-admiral-is-that-automation">Admiral 的方案:Admiral 自动化</h2>
|
||
<p>Admiral 是一个 Istio 控制平面的控制器。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:69.43866943866944%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2020/multi-cluster-mesh-automation/Istio_mesh_example_with_admiral.svg" title="Istio 和 Admiral 上的跨集群 workload 通信">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2020/multi-cluster-mesh-automation/Istio_mesh_example_with_admiral.svg" alt="使用 Admiral 在 Istio 多集群中调用 workload 的示例" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 和 Admiral 上的跨集群 workload 通信</figcaption>
|
||
</figure>
|
||
<p>Admiral 基于服务唯一标识符,为跨多个集群的 Istio 网格提供自动化配置,使其像单个网格一样工作,该标识符将多个集群上运行的 workload 和服务进行关联。它还为跨集群的 Istio 配置提供了自动同步功能。这同时减轻了开发人员和网格运维人员的负担,并有助于集群的扩展。</p>
|
||
<h2 id="admiral-crd">Admiral CRD</h2>
|
||
<h3 id="global-traffic-routing">全局流量路由</h3>
|
||
<p>基于 Admiral 的全局流量策略 CRD,支付服务可以更新区域流量权重,而 Admiral 可以在使用支付服务的所有集群中更新 Istio 配置。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: admiral.io/v1alpha1
|
||
kind: GlobalTrafficPolicy
|
||
metadata:
|
||
name: payments-gtp
|
||
spec:
|
||
selector:
|
||
identity: payments
|
||
policy:
|
||
- dns: default.payments.global
|
||
lbType: 1
|
||
target:
|
||
- region: us-west-2/*
|
||
weight: 10
|
||
- region: us-east-2/*
|
||
weight: 90
|
||
</code></pre>
|
||
<p>在上面的示例中,支付服务 90% 的流量被路由到 <code>us-east</code> 地区。该全局流量配置会自动转换为 Istio 配置,并在上下文中映射到 Kubernetes 集群中,从而为网格中的支付服务客户端启用多集群全局路由。</p>
|
||
<p>全局流量路由依赖于 Istio 每个可用服务的本地负载均衡,这需要使用 Istio 1.5 或更高版本。</p>
|
||
<h3 id="dependency">Dependency</h3>
|
||
<p>Admiral <code>Dependency</code> CRD 允许我们基于服务标识符指定服务的依赖关系。这优化了 Admiral 配置的传递,仅向运行服务的依赖客户端的必需集群传递生成的配置(而无需将其传递到所有集群)。Admiral 还会在客户端 workload 的命名空间中配置 <code>并/或</code> 更新 Sidecar Istio CRD,以将 Istio 配置限制为仅依赖于它。我们使用记录在其他地方的 service-to-service 授权信息来生成此 <code>Dependency</code> 记录,以供 Admiral 使用。</p>
|
||
<p>订单服务依赖关系的示例:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: admiral.io/v1alpha1
|
||
kind: Dependency
|
||
metadata:
|
||
name: dependency
|
||
namespace: admiral
|
||
spec:
|
||
source: orders
|
||
identityLabel: identity
|
||
destinations:
|
||
- payments
|
||
</code></pre>
|
||
<p><code>Dependency</code> 是可选的,没有服务的依赖关系,只是会导致该服务的 Istio 配置被推送到全部的集群。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>Admiral 提供了新的全局流量路由和唯一服务命名功能,致力于解决由<a href="/v1.12/zh/docs/setup/install/multicluster/gateways/#deploy-the-Istio-control-plane-in-each-cluster">具有控制平面副本集的多集群部署</a>带来的挑战。它消除了集群之间手动配置同步的需求,并为每个集群生成上下文配置。这样或许就可以操作由许多 Kubernetes 集群组成的服务网格了。</p>
|
||
<p>我们认为 Istio/Service Mesh 社区将从这种方法中受益,因此我们开源了 <a href="https://github.com/istio-ecosystem/admiral">Admiral</a>,我们很高兴收到您的反馈和支持!</p></description><pubDate>Sun, 05 Jan 2020 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2020/multi-cluster-mesh-automation/</link><author>Anil Attuluri (Intuit), Jason Webb (Intuit)</author><guid isPermaLink="true">/v1.12/zh/blog/2020/multi-cluster-mesh-automation/</guid><category>traffic-management</category><category>automation</category><category>configuration</category><category>multicluster</category><category>multi-mesh</category><category>gateway</category><category>federated</category><category>globalidentifer</category></item><item><title>安全管理 Webhook</title><description><p><code>Istio</code> 有两个 <code>Webhook</code>,分别是 <code>Galley</code> 和 <code>Sidecar Injector</code>。<code>Galley</code> 负责验证 <code>Kubernetes</code> 资源,<code>Sidecar Injector</code> 负责将 <code>Sidecar</code> 容器注入 <code>Istio</code>中。</p>
|
||
<p>默认情况下,<code>Galley</code> 和 <code>Sidecar Injector</code> 管理它们自己 <code>Webhook</code> 的配置。如果出现漏洞(例如,缓冲区溢出)它们便会受到威胁,可能会带来一些安全隐患。所以,配置 <code>Webhook</code> 是一项权限很高的操作,因为 <code>Webhook</code> 会监控和更改所有 <code>Kubernetes</code> 资源。</p>
|
||
<p>在以下示例中,攻击者破坏了 <code>Galley</code> 并修改了 <code>Galley</code> 的 <code>Webhook</code> 配置,以便于窃听所有 <code>Kubernetes</code> 机密(攻击者对 <code>clientConfig</code> 进行了修改,将 <code>Secret</code> 资源改变为攻击者自己所拥有的服务)。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:44.37367303609342%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/webhook/example_attack.png" title="攻击示例">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/webhook/example_attack.png" alt="攻击示例" />
|
||
</a>
|
||
</div>
|
||
<figcaption>攻击示例</figcaption>
|
||
</figure>
|
||
<p>为了防止这种攻击,<code>Istio</code> 1.4 引入了一项新功能,可以使用 <code>istioctl</code> 更安全地管理 <code>Webhook</code>:</p>
|
||
<ol>
|
||
<li><p><code>istioctl</code> 替代 <code>Galley</code> 和 <code>Sidecar Injector</code> 去管理 <code>Webhook</code> 配置。<code>Galley</code> 和 <code>Sidecar Injector</code> 已经被解除特殊权限,因此即便受到侵入,它们也无法更改 <code>Webhook</code> 的配置。</p></li>
|
||
<li><p>在配置 <code>Webhook</code> 前,<code>istioctl</code> 将验证 <code>Webhook</code> 服务器是否已启动和该 <code>Webhook</code> 服务器使用的证书链是否有效。这样可以减少在服务器就绪之前或服务器证书失效时可能发生的错误。</p></li>
|
||
</ol>
|
||
<p>要尝试此新功能,请参阅 <a href="https://archive.istio.io/v1.4/docs/tasks/security/webhook">Istio Webhook 管理内容</a>。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/webhook/</link><author>Lei Tang (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/webhook/</guid><category>security</category><category>kubernetes</category><category>webhook</category></item><item><title>istioctl analyze 介绍</title><description>
|
||
<p>Istio 1.4 引入了一个实验性的新工具,可以帮助分析和调试正在运行 Istio 的集群。</p>
|
||
<p><a href="/v1.12/zh/docs/reference/commands/istioctl/#istioctl-experimental-analyze"><code>istioctl analyze</code></a> 是一个诊断工具,来发现 Istio 配置的潜在问题,以及提供一些改进配置的意见。它可以针对一个正在运行的集群或者是一堆本地配置文件。还可以是这两种方式的组合,让您在对集群应用更改之前发现问题。</p>
|
||
<p>开始之前,先看看这里的<a href="/v1.12/zh/docs/ops/diagnostic-tools/istioctl-analyze/">文档</a>。</p>
|
||
<h2 id="designed-to-be-approachable-for-novice-users">专为新手用户设计</h2>
|
||
<p>我们遵循的其中一个关键设计目标就是要非常容易使用,就是不需要传复杂参数而让命令又很有用。</p>
|
||
<p>实际中,下面是这个工具要应对的一些场景:</p>
|
||
<ul>
|
||
<li><em>“集群有问题,但是不知该从何入手”</em></li>
|
||
<li><em>“运行起来没问题,但是不知道是否还有优化空间”</em></li>
|
||
</ul>
|
||
<p>从这个意义上讲,它与某些更高级的诊断工具有很大的不同,后者适合以下场景(以 <code>istioctl proxy-config</code> 为例):</p>
|
||
<ul>
|
||
<li><em>“列出指定 Pod 的 Envoy 配置,来看看有没有问题”</em></li>
|
||
</ul>
|
||
<p>这对高级调试非常有用,但是这需要非常多的经验,您才能知道需要运行这条命令,以及在哪个 Pod 上运行。</p>
|
||
<p>因此,用一句话来说明 <code>analyze</code> 就是:尽管运行!它非常安全,不用考虑,可能会有帮助,最坏的情况就是浪费您一分钟!</p>
|
||
<h2 id="improving-this-tool-over-time">这个工具在不断改进中</h2>
|
||
<p>在 Istio 1.4 中,<code>analyze</code> 有一组很好分析器,可以检测很多常见的问题。但这只是开始,我们计划在后期每个版本中不断增加和优化分析器。</p>
|
||
<p>事实上,我们欢迎 Istio 用户提建议。特别是遇到您认为可以用配置分析器检测的情况时,而 <code>analyze</code> 没有正确标出来,请告诉我们。最好的方式就是<a href="https://github.com/istio/istio/issues">在 GitHub 上建 Issue</a>。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/introducing-istioctl-analyze/</link><author>David Ebbo (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/introducing-istioctl-analyze/</guid><category>debugging</category><category>istioctl</category><category>configuration</category></item><item><title>Istio v1beta1 授权策略概述</title><description>
|
||
<p>Istio 1.4 引入了 <a href="/v1.12/zh/docs/reference/config/security/authorization-policy/"><code>v1beta1</code> 授权策略</a>,这是对
|
||
以前 <code>v1alpha1</code> 的基于角色的访问控制(RBAC)策略的重要更新。包括以下改进:</p>
|
||
<ul>
|
||
<li>符合 Istio 配置模型。</li>
|
||
<li>通过简化 API 改善用户体验。</li>
|
||
<li>支持更多用例(例如,Ingress/Egress 网关支持),而不会增加复杂性。</li>
|
||
</ul>
|
||
<p>该 <code>v1beta1</code> 策略不向后兼容,需要一次转换。Istio 提供了一个工具来自动执行此过程。
|
||
Istio 1.6 以后将不再支持先前的配置资源 <code>ClusterRbacConfig</code>、<code>ServiceRole</code> 和 <code>ServiceRoleBinding</code>。</p>
|
||
<p>本文描述了新的 <code>v1beta1</code> 授权策略模型、设计目标和从 <code>v1alpha1</code> RBAC 策略的迁移。
|
||
有关 <code>v1beta1</code> 授权策略的详细说明,请参见 <a href="/v1.12/zh/docs/concepts/security/#authorization">authorization concept</a> 页面。</p>
|
||
<p>我们欢迎您在 <a href="https://discuss.istio.io/c/security">discuss.istio.io</a> 上反馈有关 <code>v1beta1</code> 授权策略的相关信息。</p>
|
||
<h2 id="background">背景</h2>
|
||
<p>迄今为止,Istio 提供了 RBAC 策略,以便使用 <code>ClusterRbacConfig</code>、<code>ServiceRole</code> 和 <code>ServiceRoleBinding</code> 配置资源
|
||
对 <span class="term" data-title="Service" data-body="&lt;p&gt;使用&lt;a href=&#34;/zh/docs/reference/glossary/#service-name&#34;&gt;服务名称&lt;/a&gt;标识一组具有关联行为的服务&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;服务网格&lt;/a&gt;,并使用这些名称应用 Istio 策略(例如负载均衡和路由)。
|
||
服务通常由一个或多个&lt;a href=&#34;/zh/docs/reference/glossary/#service-endpoint&#34;&gt;服务 Endpoint&lt;/a&gt; 实现,并且或许包含多个&lt;a href=&#34;/zh/docs/reference/glossary/#service-version&#34;&gt;服务版本&lt;/a&gt;。&lt;/p&gt;
|
||
">服务</span> 实施访问控制。使用此 API,用户可以在网格级别、命名空间级别和服务级别强
|
||
制实施访问控制。与其他 RBAC 策略一样,Istio RBAC 使用相同的角色和绑定概念来授予身份权限。</p>
|
||
<p>尽管 Istio RBAC 一直稳定可靠的工作着,但我们还是发现了许多改进空间。</p>
|
||
<p>例如,用户错误地假定访问控制实施发生在服务级别,因为 <code>ServiceRole</code> 使用服务指定在何处应用策略,但是,策略实际上应用于
|
||
<span class="term" data-title="Workload" data-body="&lt;p&gt;&lt;a href=&#34;/zh/docs/reference/glossary/#operator&#34;&gt;operators&lt;/a&gt; 部署的二进制文件,用于提供服务网格应用的一些功能。
|
||
工作负载有自己的名称,命名空间,和唯一的 id。
|
||
这些属性可以通过下面的&lt;a href=&#34;/zh/docs/reference/glossary/#attribute&#34;&gt;属性&lt;/a&gt;被策略配置和遥测配置使用:&lt;/p&gt;
|
||
&lt;ul&gt;
|
||
&lt;li&gt;&lt;code&gt;source.workload.name&lt;/code&gt;, &lt;code&gt;source.workload.namespace&lt;/code&gt;, &lt;code&gt;source.workload.uid&lt;/code&gt;&lt;/li&gt;
|
||
&lt;li&gt;&lt;code&gt;destination.workload.name&lt;/code&gt;, &lt;code&gt;destination.workload.namespace&lt;/code&gt;, &lt;code&gt;destination.workload.uid&lt;/code&gt;&lt;/li&gt;
|
||
&lt;/ul&gt;
|
||
&lt;p&gt;在 Kubernetes 环境中,一个工作负载通常对应一个 Kubernetes deployment,
|
||
并且一个&lt;a href=&#34;/zh/docs/reference/glossary/#workload-instance&#34;&gt;工作负载实例&lt;/a&gt;对应一个独立的被 deployment 管理的 &lt;a href=&#34;/zh/docs/reference/glossary/#pod&#34;&gt;pod&lt;/a&gt;。&lt;/p&gt;
|
||
">工作负载</span>,该服务仅用于查找相应的工作负载。当多个服务引用相同的工作负载时,
|
||
这种细微差别非常重要。如果两个服务引用相同的工作负载,则服务 A 的 <code>ServiceRole</code> 也会影响服务 B,这可能会导致混淆和不
|
||
正确的配置。</p>
|
||
<p>另一个示例是,由于需要深入了解三个相关资源,用户很难维护和管理 Istio RBAC 配置。</p>
|
||
<h2 id="design-goals">设计目标</h2>
|
||
<p>新的 <code>v1beta1</code> 授权策略具有几个设计目标:</p>
|
||
<ul>
|
||
<li><p>与 <a href="https://goo.gl/x3STjD">Istio 配置模型</a>保持一致,以便更清楚地了解策略目标。
|
||
配置模型提供统一的配置层次结构、解决方案和目标选择。</p></li>
|
||
<li><p>通过简化 API 改善用户体验。管理一个包含所有访问控制规范的 CRD(自定义资源定义)比管理多个 CRD 更容易。</p></li>
|
||
<li><p>支持更多用例,而不会增加复杂性。例如,允许在 Ingress/Egress 网关上应用策略,以对进出网格的流量实施访问控制。</p></li>
|
||
</ul>
|
||
<h2 id="authorization-policy"><code>AuthorizationPolicy</code></h2>
|
||
<p>通过 <a href="/v1.12/zh/docs/reference/config/security/authorization-policy/"><code>AuthorizationPolicy</code> 自定义资源</a>启用对工作
|
||
负载的访问控制。本节介绍 <code>v1beta1</code> 授权策略中的变化。</p>
|
||
<p><code>AuthorizationPolicy</code> 包括 <code>selector</code> 和一个 <code>rule</code> 列表。<code>selector</code> 指定应用策略的工作负载,<code>rule</code> 列表指定工作
|
||
负载的详细访问控制规则。</p>
|
||
<p><code>rule</code> 是累加的,这意味着如果任何 <code>rule</code> 允许请求,则请求将被允许。每个 <code>rule</code> 都包含 <code>from</code>、<code>to</code> 和 <code>when</code> 的定义,
|
||
其指定了允许<strong>谁</strong>在哪些<strong>条件</strong>下执行哪些<strong>操作</strong>。</p>
|
||
<p><code>selector</code> 将替换 <code>ClusterRbacConfig</code> 和 <code>ServiceRole</code> 中的 <code>services</code> 字段提供的功能。
|
||
<code>rule</code> 将替换 <code>ServiceRoleBinding</code> 和 <code>ServiceRole</code> 中的其他字段。</p>
|
||
<h3 id="example">示例</h3>
|
||
<p>以下授权策略适用于 <code>foo</code> 命名空间中含有 <code>app: httpbin</code> 和 <code>version: v1</code> 标签的工作负载:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
selector:
|
||
matchLabels:
|
||
app: httpbin
|
||
version: v1
|
||
rules:
|
||
- from:
|
||
- source:
|
||
principals: [&#34;cluster.local/ns/default/sa/sleep&#34;]
|
||
to:
|
||
- operation:
|
||
methods: [&#34;GET&#34;]
|
||
when:
|
||
- key: request.headers[version]
|
||
values: [&#34;v1&#34;, &#34;v2&#34;]
|
||
</code></pre>
|
||
<p>当来自 <code>cluster.local/ns/default/sa/sleep</code> 的请求头中包含值为 <code>v1</code> 或 <code>v2</code> 的 <code>version</code> 字段时,
|
||
该策略将允许其通过 <code>GET</code> 请求访问工作负载。默认情况下,任何与策略不匹配的请求都将被拒绝。</p>
|
||
<p>假设 <code>httpbin</code> 服务定义为:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
selector:
|
||
app: httpbin
|
||
version: v1
|
||
ports:
|
||
# omitted
|
||
</code></pre>
|
||
<p>如果要在 <code>v1alpha1</code> 中实现相同的目的,您需要配置三个资源:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ClusterRbacConfig
|
||
metadata:
|
||
name: default
|
||
spec:
|
||
mode: &#39;ON_WITH_INCLUSION&#39;
|
||
inclusion:
|
||
services: [&#34;httpbin.foo.svc.cluster.local&#34;]
|
||
---
|
||
apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRole
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
rules:
|
||
- services: [&#34;httpbin.foo.svc.cluster.local&#34;]
|
||
methods: [&#34;GET&#34;]
|
||
constraints:
|
||
- key: request.headers[version]
|
||
values: [&#34;v1&#34;, &#34;v2&#34;]
|
||
---
|
||
apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
subjects:
|
||
- user: &#34;cluster.local/ns/default/sa/sleep&#34;
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;httpbin&#34;
|
||
</code></pre>
|
||
<h3 id="workload-selector">工作负载选择器</h3>
|
||
<p><code>v1beta1</code> 授权策略中的一个主要更改是,它现在使用工作负载选择器指定应该在何处应用策略。
|
||
这与 <code>Gateway</code>、<code>Sidecar</code> 和 <code>EnvoyFilter</code> 配置中使用的工作负载选择器相同。</p>
|
||
<p>工作负载选择器显式的表明,策略是在工作负载(而不是服务)上应用和强制执行的。
|
||
如果策略适用于由多个不同服务使用的工作负载,则同一策略将影响所有不同服务的流量。</p>
|
||
<p>只需将 <code>selector</code> 留空,即可将策略应用于命名空间中的所有工作负载。以下策略适用于命名空间 <code>bar</code> 中的所有工作负载:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: policy
|
||
namespace: bar
|
||
spec:
|
||
rules:
|
||
# omitted
|
||
</code></pre>
|
||
<h3 id="root-namespace">根命名空间</h3>
|
||
<p>根命名空间中的策略应用于网格中每个命名空间中的所有工作负载。
|
||
根命名空间可在 <a href="/v1.12/zh/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig"><code>MeshConfig</code></a> 中配置,
|
||
其默认值为 <code>istio-system</code>。</p>
|
||
<p>例如,您在 <code>istio-system</code> 命名空间中安装了 Istio,并在 <code>default</code> 和 <code>bookinfo</code> 命名空间中部署了工作负载。
|
||
把根命名空间从默认值更改为 <code>istio-config</code> 后,以下策略将应用于每个命名空间中的工作负载,
|
||
包括 <code>default</code>、<code>bookinfo</code> 和 <code>istio-system</code>:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: policy
|
||
namespace: istio-config
|
||
spec:
|
||
rules:
|
||
# omitted
|
||
</code></pre>
|
||
<h3 id="ingress-egress-gateway-support">Ingress/Egress 网关支持</h3>
|
||
<p><code>v1beta1</code> 授权策略也可以应用于 ingress/egress 网关,以对进入或离开网格的流量实施访问控制,
|
||
您只需更改 <code>selector</code> 即可选择入口或出口工作负载。</p>
|
||
<p>以下策略适用于具有 <code>app: istio-ingressgateway</code> 标签的工作负载:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: ingress
|
||
namespace: istio-system
|
||
spec:
|
||
selector:
|
||
matchLabels:
|
||
app: istio-ingressgateway
|
||
rules:
|
||
# omitted
|
||
</code></pre>
|
||
<p>请注意,授权策略仅适用于与策略相同的命名空间中的工作负载,除非在根命名空间中应用该策略:</p>
|
||
<ul>
|
||
<li><p>如果不更改根命名空间的默认值(即 <code>istio-system</code>),上述策略将应用于<strong>每个</strong>命名空间中
|
||
含有 <code>app: istio-ingressgateway</code> 标签的工作负载。</p></li>
|
||
<li><p>如果将根命名空间更改为其他值,则上述策略将<strong>仅适用</strong>于 <code>istio-system</code> 命名空间中
|
||
含有 <code>app: istio-ingressgateway</code> 标签的工作负载。</p></li>
|
||
</ul>
|
||
<h3 id="comparison">比较</h3>
|
||
<p>下表突出显示了旧的 <code>v1alpha1</code> RBAC 策略和新的 <code>v1beta1</code> 授权策略之间的主要区别。</p>
|
||
<h4 id="feature">特性</h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>特性</th>
|
||
<th><code>v1alpha1</code> RBAC 策略</th>
|
||
<th><code>v1beta1</code> 授权策略</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>API 稳定性</td>
|
||
<td><code>alpha</code>:<strong>不</strong> 向后兼容</td>
|
||
<td><code>beta</code>:<strong>确保</strong>向后兼容</td>
|
||
</tr>
|
||
<tr>
|
||
<td>CRD 数量</td>
|
||
<td>三个:<code>ClusterRbacConfig</code>、<code>ServiceRole</code> 和 <code>ServiceRoleBinding</code></td>
|
||
<td>一个:<code>AuthorizationPolicy</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>策略目标</td>
|
||
<td><strong>service</strong></td>
|
||
<td><strong>workload</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td>默认拒绝行为</td>
|
||
<td>通过<strong>显式</strong>的配置 <code>ClusterRbacConfig</code> 启用</td>
|
||
<td><strong>隐式</strong>的通过 <code>AuthorizationPolicy</code> 启用</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Ingress/Egress 网关支持</td>
|
||
<td>不支持</td>
|
||
<td>支持</td>
|
||
</tr>
|
||
<tr>
|
||
<td>策略中的 <code>&quot;*&quot;</code> 值</td>
|
||
<td>匹配所有内容(空和非空)</td>
|
||
<td>仅匹配非空内容</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>下表显示了 <code>v1alpha1</code> 和 <code>v1beta1</code> API 之间的关系。</p>
|
||
<h4 id="clusterrbacconfig"><code>ClusterRbacConfig</code></h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th><code>ClusterRbacConfig.Mode</code></th>
|
||
<th><code>AuthorizationPolicy</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>OFF</code></td>
|
||
<td>未应用策略</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ON</code></td>
|
||
<td>在根命名空间中应用的全部拒绝策略</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ON_WITH_INCLUSION</code></td>
|
||
<td>策略应用于 <code>ClusterRbacConfig</code> 中包含的命名空间或工作负载</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ON_WITH_EXCLUSION</code></td>
|
||
<td>策略应用于 <code>ClusterRbacConfig</code> 中包含的命名空间或工作负载</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="servicerole"><code>ServiceRole</code></h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th><code>ServiceRole</code></th>
|
||
<th><code>AuthorizationPolicy</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>services</code></td>
|
||
<td><code>selector</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>paths</code></td>
|
||
<td><code>to</code> 字段下的 <code>paths</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>methods</code></td>
|
||
<td><code>to</code> 字段下的 <code>methods</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>destination.ip</code></td>
|
||
<td>不支持</td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>destination.port</code></td>
|
||
<td><code>to</code> 字段下的 <code>ports</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>destination.labels</code></td>
|
||
<td><code>selector</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>destination.namespace</code></td>
|
||
<td>替换为策略的命名空间,即元数据中的 <code>namespace</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>destination.user</code></td>
|
||
<td>不支持</td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>experimental.envoy.filters</code></td>
|
||
<td><code>when</code> 字段下的 <code>experimental.envoy.filters</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>在约束中的 <code>request.headers</code></td>
|
||
<td><code>when</code> 字段下的 <code>request.headers</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h4 id="servicerolebinding"><code>ServiceRoleBinding</code></h4>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th><code>ServiceRoleBinding</code></th>
|
||
<th><code>AuthorizationPolicy</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>user</code></td>
|
||
<td><code>from</code> 字段下的 <code>principals</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>group</code></td>
|
||
<td><code>to</code> 字段下的 <code>paths</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>source.ip</code> 属性</td>
|
||
<td><code>from</code> 字段下的 <code>ipBlocks</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>source.namespace</code> 属性</td>
|
||
<td><code>from</code> 字段下的 <code>namespaces</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>source.principal</code> 属性</td>
|
||
<td><code>from</code> 字段下的 <code>principals</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>request.headers</code> 属性</td>
|
||
<td><code>when</code> 字段下的 <code>request.headers</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>request.auth.principal</code> 属性</td>
|
||
<td><code>from</code> 字段下的 <code>requestPrincipals</code> 或 <code>when</code> 字段下的 <code>request.auth.principal</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>request.auth.audiences</code> 属性</td>
|
||
<td><code>when</code> 字段下的 <code>request.auth.audiences</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>request.auth.presenter</code> 属性</td>
|
||
<td><code>when</code> 字段下的 <code>request.auth.presenter</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>request.auth.claims</code> 属性</td>
|
||
<td><code>when</code> 字段下的 <code>request.auth.claims</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>除了所有差异之外,与 <code>v1alpha1</code> 类似,<code>v1beta1</code> 策略也由 Envoy 引擎强制执行,并支持同样的身份验证(双向 TLS 或 JWT)、条件和其他基元(如 IP、端口等)。</p>
|
||
<h2 id="future-of-the-v1alpha1-policy">未来的 <code>v1alpha1</code> 策略</h2>
|
||
<p><code>v1alpha1</code> RBAC 策略(<code>ClusterRbacConfig</code>、<code>ServiceRole</code> 和 <code>ServiceRoleBinding</code>)将被 <code>v1beta1</code> 授权策略替代并弃用。</p>
|
||
<p>Istio 1.4 继续支持 <code>v1alpha1</code> RBAC 策略,以便使您有足够的时间完成迁移。</p>
|
||
<h2 id="migration-from-the-v1alpha1-policy">从 <code>v1alpha1</code> 策略迁移</h2>
|
||
<p>对于给定的工作负载,Istio 仅支持两个版本之一:</p>
|
||
<ul>
|
||
<li>如果仅为工作负载配置 <code>v1beta1</code> 策略,则 <code>v1beta1</code> 策略生效。</li>
|
||
<li>如果仅为工作负载配置 <code>v1alpha1</code> 策略,则 <code>v1alpha1</code> 策略生效。</li>
|
||
<li>如果同时为工作负载配置 <code>v1beta1</code> 和 <code>v1alpha1</code> 策略,则仅 <code>v1beta1</code> 策略生效,<code>v1alpha1</code> 策略将被忽略。</li>
|
||
</ul>
|
||
<h3 id="general-guideline">一般准则</h3>
|
||
<div>
|
||
<aside class="callout warning">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-warning"/></svg>
|
||
</div>
|
||
<div class="content">迁移时,对给定工作负载使用 <code>v1beta1</code> 策略时,请确保新的 <code>v1beta1</code> 策略涵盖应用于工作负载的所有现有 <code>v1alpha1</code> 策略,
|
||
因为在应用 <code>v1beta1</code> 后,将忽略应用于工作负载的 <code>v1alpha1</code> 策略。</div>
|
||
</aside>
|
||
</div>
|
||
<p>迁移到 <code>v1beta1</code> 策略的典型流程是首先检查 <code>ClusterRbacConfig</code>,以确定哪些命名空间或服务启用了 RBAC。</p>
|
||
<p>对于启用了 RBAC 的每个服务:</p>
|
||
<ol>
|
||
<li>从服务定义中获取工作负载选择器。</li>
|
||
<li>使用工作负载选择器创建一个 <code>v1beta1</code> 策略。</li>
|
||
<li>根据应用与服务的每个 <code>ServiceRole</code> 和 <code>ServiceRoleBinding</code> 更新 <code>v1beta1</code> 策略。</li>
|
||
<li>应用该 <code>v1beta1</code> 策略并监视流量,以确保该策略按预期工作。</li>
|
||
<li>对启用了 RBAC 的下一个服务重复该过程。</li>
|
||
</ol>
|
||
<p>对于启用了 RBAC 的每个命名空间:</p>
|
||
<ol>
|
||
<li>把拒绝所有流量的 <code>v1beta1</code> 策略应用到给定的命名空间。</li>
|
||
</ol>
|
||
<h3 id="migration-example">迁移示例</h3>
|
||
<p>假设在 <code>foo</code> 命名空间中您有以下 <code>v1alpha1</code> 策略用于 <code>httpbin</code> 服务:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ClusterRbacConfig
|
||
metadata:
|
||
name: default
|
||
spec:
|
||
mode: &#39;ON_WITH_INCLUSION&#39;
|
||
inclusion:
|
||
namespaces: [&#34;foo&#34;]
|
||
---
|
||
apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRole
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
rules:
|
||
- services: [&#34;httpbin.foo.svc.cluster.local&#34;]
|
||
methods: [&#34;GET&#34;]
|
||
---
|
||
apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
subjects:
|
||
- user: &#34;cluster.local/ns/default/sa/sleep&#34;
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;httpbin&#34;
|
||
</code></pre>
|
||
<p>以下述方式将上面的策略迁移到 <code>v1beta1</code>:</p>
|
||
<ol>
|
||
<li><p>假设 <code>httpbin</code> 服务具有以下工作负载选择器:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >selector:
|
||
app: httpbin
|
||
version: v1
|
||
</code></pre></li>
|
||
<li><p>通过工作负载创建 <code>v1beta1</code> 策略:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
selector:
|
||
matchLabels:
|
||
app: httpbin
|
||
version: v1
|
||
</code></pre></li>
|
||
<li><p>根据服务所应用的 <code>ServiceRole</code> 和 <code>ServiceRoleBinding</code> 更新 <code>v1beta1</code> 策略:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: httpbin
|
||
namespace: foo
|
||
spec:
|
||
selector:
|
||
matchLabels:
|
||
app: httpbin
|
||
version: v1
|
||
rules:
|
||
- from:
|
||
- source:
|
||
principals: [&#34;cluster.local/ns/default/sa/sleep&#34;]
|
||
to:
|
||
- operation:
|
||
methods: [&#34;GET&#34;]
|
||
</code></pre></li>
|
||
<li><p>应用 <code>v1beta1</code> 策略并监视流量,以确保该策略按预期工作。</p></li>
|
||
<li><p>应用下面的 <code>v1beta1</code> 策略,该策略拒绝所有到达 <code>foo</code> 命名空间的流量,因为命名空间 <code>foo</code> 启用了 RBAC:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: security.istio.io/v1beta1
|
||
kind: AuthorizationPolicy
|
||
metadata:
|
||
name: deny-all
|
||
namespace: foo
|
||
spec:
|
||
{}
|
||
</code></pre></li>
|
||
</ol>
|
||
<p>确保 <code>v1beta1</code> 策略按预期工作,然后可以从集群中删除 <code>v1alpha1</code> 策略。</p>
|
||
<h3 id="automation-of-the-migration">自动化迁移</h3>
|
||
<p>为了帮助简化迁移,可通 <code>istioctl experimental authz convert</code> 转换命令自动将 <code>v1alpha1</code> 策略
|
||
转换为 <code>v1beta1</code> 策略。</p>
|
||
<p>迁移时您可以考虑该命令,但它在 Istio 1.4 中是实验性的,并且截至此博客文章发布,其还不能够完整支持 v1alpha1 的全部语义。</p>
|
||
<p>支持完整 v1alpha1 语义的命令预计在 Istio 1.4 之后的修补程序版本中发布。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/v1beta1-authorization-policy/</link><author>Yangmin Zhu (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/v1beta1-authorization-policy/</guid><category>security</category><category>RBAC</category><category>access control</category><category>authorization</category></item><item><title>Istio Operator 简介</title><description>
|
||
<p>Kubernetes <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/">operator</a> 提供了一种将人类运维知识编码到软件中的模式,是一种简化软件基础结构组件管理的流行方法。Istio 是自动 operator 的理想选择,因为它的管理具有挑战性。</p>
|
||
<p>到目前为止,<a href="https://github.com/helm/helm">Helm</a> 一直是安装和升级 Istio 的主要工具。Istio 1.4 引入了一种新的<a href="/v1.12/zh/docs/setup/install/istioctl/">使用istioctl安装</a>方法。这种新的安装方法建立在 Helm 的优势之上,并添加了以下内容:</p>
|
||
<ul>
|
||
<li>用户只需要安装一个工具:<code>istioctl</code></li>
|
||
<li>验证所有 API 字段</li>
|
||
<li>不在 API 中的小型定制不需要更改 chart 或 API</li>
|
||
<li>版本特定的升级 hook 可以很容易和稳健地实现</li>
|
||
</ul>
|
||
<p><a href="/v1.12/zh/docs/setup/install/helm/">Helm 安装</a>方法正在弃用中。从 Istio 1.4 升级到一个默认没有安装 Helm 的版本也会被一个新的 <a href="/v1.12/zh/docs/setup/upgrade/istioctl-upgrade/">istioctl 升级特性</a>所取代。</p>
|
||
<p>新的 <code>istioctl</code> 安装命令使用一个<a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">自定义资源</a>来配置安装。自定义资源是新的 Istio operator 实现的一部分,该实现旨在简化安装、升级和复杂的 Istio 配置更改等常见管理任务。安装和升级的验证和检查与工具紧密集成,以防止常见错误并简化故障排除。</p>
|
||
<h2 id="the-Operator-API">Operator API</h2>
|
||
<p>每个 operator 实现都需要一个<a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions">自定义资源定义(CRD)</a> 来定义它的自定义资源,即它的 API。Istio 的 operator API 由 <a href="/v1.12/zh/docs/reference/config/istio.operator.v1alpha12.pb/"><code>IstioControlPlane</code> CRD</a> 定义,它是由一个 <a href="https://github.com/istio/operator/blob/release-1.4/pkg/apis/istio/v1alpha2/istiocontrolplane_types.proto"><code>IstioControlPlane</code> 原型</a>生成的。API 支持所有 Istio 当前的<a href="/v1.12/zh/docs/setup/additional-setup/config-profiles/">配置文件</a> ,通过使用一个字段来选择 profile。例如,下面的 <code>IstioControlPlane</code> 资源使用 <code>demo</code> profile 配置 Istio:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: install.istio.io/v1alpha2
|
||
kind: IstioControlPlane
|
||
metadata:
|
||
namespace: istio-operator
|
||
name: example-istiocontrolplane
|
||
spec:
|
||
profile: demo
|
||
</code></pre>
|
||
<p>然后可以使用其他设置来自定义配置。例如,禁用遥测:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: install.istio.io/v1alpha2
|
||
kind: IstioControlPlane
|
||
metadata:
|
||
namespace: istio-operator
|
||
name: example-istiocontrolplane
|
||
spec:
|
||
profile: demo
|
||
telemetry:
|
||
enabled: false
|
||
</code></pre>
|
||
<h2 id="install-with-Istio">通过istioctl安装</h2>
|
||
<p>使用 Istio operator API 的推荐方法是通过一组新的 <code>istioctl</code> 命令。例如,要在集群中安装 Istio:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl manifest apply -f &lt;your-istiocontrolplane-customresource&gt;
|
||
</code></pre>
|
||
<p>通过编辑配置文件并再次执行 <code>istioctl manifest apply</code> 来更改安装配置。</p>
|
||
<p>升级到新版本的 Istio:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl x upgrade -f &lt;your-istiocontrolplane-config-changes&gt;
|
||
</code></pre>
|
||
<p>除了在 <code>IstioControlPlane</code> 资源中指定完整的配置外,<code>istioctl</code> 命令还可以使用 <code>--set</code> 标志传递单独的设置:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl manifest apply --set telemetry.enabled=false
|
||
</code></pre>
|
||
<p>还有许多其他 <code>istioctl</code> 命令,例如,它们可以帮助您列出、显示和比较配置 profile 和 manifest。</p>
|
||
<p>更多信息请参考 Istio <a href="/v1.12/zh/docs/setup/install/istioctl">安装说明</a>。</p>
|
||
<h2 id="Istio-controller-alpha">Istio Controller (alpha)</h2>
|
||
<p>Operator 实现使用 Kubernetes controller 来持续监控它们的自定义资源并应用相应的配置更改。Istio controller 监控一个 <code>IstioControlPlane</code> 资源,并通过更新相应集群中的 Istio 安装配置来响应更改。</p>
|
||
<p>在 1.4 版中,Istio controller 处于开发的 alpha 阶段,没有完全集成到 <code>istioctl</code> 中。但是,可以使用 <code>kubectl</code> 命令来做<a href="/v1.12/zh/docs/setup/install/standalone-operator/">实验</a>。例如,要将 controller 和默认版本的 Istio 安装到集群中,请运行以下命令:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f https://&lt;repo URL&gt;/operator.yaml
|
||
$ kubectl apply -f https://&lt;repo URL&gt;/default-cr.yaml
|
||
</code></pre>
|
||
<p>然后你可以对 Istio 的安装配置进行修改:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl edit istiocontrolplane example-istiocontrolplane -n istio-system
|
||
</code></pre>
|
||
<p>一旦资源更新,controller 将检测到这些变化,并相应地更新 Istio 安装。</p>
|
||
<p>Operator controller 和 <code>istioctl</code> 命令共享相同的实现。重要的区别在于其执行上下文。对于 <code>istioctl</code>,操作在管理用户的命令执行和安全上下文中运行。对于 controller,集群中的一个 pod 在其安全上下文中运行代码。在这两种情况下,都根据一个 schema 来验证配置,并执行相同的正确性检查。</p>
|
||
<h2 id="migration-from-helm">从 Helm 迁移</h2>
|
||
<p>为了方便从使用 Helm 过渡,<code>istioctl</code> 和 controller 支持对 Helm 安装 API 的透传访问。</p>
|
||
<p>您可以使用 <code>istioctl --set</code> 来传递 Helm 配置选项,方法是将字符串 <code>values.</code> 放在配置选项前面。例如,对于这个 Helm 命令:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm template ... --set global.mtls.enabled=true
|
||
</code></pre>
|
||
<p>您可以使用 <code>istioctl</code> 这个命令:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl manifest generate ... --set values.global.mtls.enabled=true
|
||
</code></pre>
|
||
<p>你也可以在一个 <code>IstioControlPlane</code> 自定义资源中设置 Helm 配置值。参见<a href="/v1.12/zh/docs/setup/install/istioctl/#customize-Istio-settings-using-the-helm-API">使用 Helm 自定义 Istio 设置</a>。</p>
|
||
<p>另一个可以帮助从 Helm 迁移的特性是这个 alpha 命令:<a href="/v1.12/zh/docs/reference/commands/istioctl/#istioctl-manifest-migrate">istioctl manifest migrate</a>。此命令可用于将 Helm <code>values.yaml</code> 文件自动转换为相应的 <code>IstioControlPlane</code> 配置。</p>
|
||
<h2 id="implementation">实现</h2>
|
||
<p>已经创建了几个框架,通过为部分或所有组件生成存根来帮助实现 operator。Istio operator 是在 <a href="https://github.com/kubernetes-sigs/kubebuilder">kubebuilder</a> 和 <a href="https://github.com/operator-framework">operator framework</a> 的帮助下创建的。Istio 的安装现在使用 proto 来描述 API,这样就可以通过 schema 对执行运行时进行验证。</p>
|
||
<p>有关实现的更多信息可以在 <a href="https://github.com/istio/operator">Istio operator 仓库</a>中的 README 和 ARCHITECTURE 文档中找到。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>从 Istio 1.4 开始,Helm 安装将被新的 <code>istioctl</code> 命令所取代,该命令使用新的 operator 自定义资源定义,<code>IstioControlPlane</code>,作为配置 API。一个 alpha controller 也被提供用于 operator 的早期实验。</p>
|
||
<p>新的 <code>istioctl</code> 命令和 operator controller 都会验证配置 schema,并执行安装更改或升级的一系列检查。这些检查与工具紧密集成,以防止常见错误并简化故障排除。</p>
|
||
<p>Istio 维护者们期望这种新方法能够改善安装和升级期间的用户体验,更好地稳定安装 API,帮助用户更好地管理和监控他们的 Istio 安装。</p>
|
||
<p>我们欢迎您在 <a href="https://discuss.istio.io/">discuss.istio.io</a> 上对新的安装方法提出反馈。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/introducing-istio-operator/</link><author>Martin Ostrowski (Google), Frank Budinsky (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/introducing-istio-operator/</guid><category>install</category><category>configuration</category><category>istioctl</category><category>operator</category></item><item><title>Istio client-go 发布公告</title><description>
|
||
<p>我们很高兴地宣布 <a href="https://github.com/istio/client-go">Istio client go</a> 的第一个版本发布了,该存储库使开发人员能够在 <code>Kubernetes</code> 环境中访问 <code>Istio API</code> 。在此存储库中的 <code>Kubernetes</code> 程序和客户端使开发人员可以轻松地为所有 <code>Istio</code> 客户端自定义的资源 <code>(CRDs)</code> 创建,读取,更新和删除 <code>(CRUD)</code>。</p>
|
||
<p>这是许多 Istio 用户强烈要求的功能,从 <a href="https://github.com/aspenmesh/istio-client-go">Aspen Mesh</a>
|
||
和 <a href="https://github.com/knative/pkg">Knative project</a> 项目对客户端产生的功能请求中可以明显地看出这一点。如果您正在使用上述客户端之一,则可以像如下这样轻松地切换到 <a href="https://github.com/istio/client-go">Istio client go</a>:</p>
|
||
<pre><code class='language-go' data-expandlinks='true' data-repo='istio' >import (
|
||
...
|
||
- versionedclient &#34;github.com/aspenmesh/istio-client-go/pkg/client/clientset/versioned&#34;
|
||
+ versionedclient &#34;istio.io/client-go/pkg/clientset/versioned&#34;
|
||
)
|
||
</code></pre>
|
||
<p>由于生成的客户端在功能上是等效的,因此使用新的 <code>istio-client-go</code> 也不会有什么问题。</p>
|
||
<h2 id="how-to-use-client-go">如何使用客户端</h2>
|
||
<p><a href="https://github.com/istio/client-go">Istio client go</a> 存储库遵循与 <a href="https://github.com/istio/api">Istio API</a> 存储库 相同的分支策略,因为客户端存储库取决于 <code>API</code> 定义。如果要使用稳定的客户端,则可以在 <a href="https://github.com/istio/client-go">client go</a> 存储库中使用发行版分支或标记的版本。使用客户端与使用 <a href="https://github.com/kubernetes/client-go">Kubernetes client go</a> 非常相似,这是一个使用客户端列出命名空间中所有 <a href="/v1.12/zh/docs/reference/config/networking/virtual-service">Istio
|
||
virtual services</a> 的简单示例:</p>
|
||
<pre><code class='language-go' data-expandlinks='true' data-repo='istio' >package main
|
||
import (
|
||
&#34;log&#34;
|
||
&#34;os&#34;
|
||
metav1 &#34;k8s.io/apimachinery/pkg/apis/meta/v1&#34;
|
||
&#34;k8s.io/client-go/tools/clientcmd&#34;
|
||
versionedclient &#34;istio.io/client-go/pkg/clientset/versioned&#34;
|
||
)
|
||
func main() {
|
||
kubeconfig := os.Getenv(&#34;KUBECONFIG&#34;)
|
||
namespace := os.Getenv(&#34;NAMESPACE&#34;)
|
||
if len(kubeconfig) == 0 || len(namespace) == 0 {
|
||
log.Fatalf(&#34;Environment variables KUBECONFIG and NAMESPACE need to be set&#34;)
|
||
}
|
||
restConfig, err := clientcmd.BuildConfigFromFlags(&#34;&#34;, kubeconfig)
|
||
if err != nil {
|
||
log.Fatalf(&#34;Failed to create k8s rest client: %s&#34;, err)
|
||
}
|
||
ic, err := versionedclient.NewForConfig(restConfig)
|
||
if err != nil {
|
||
log.Fatalf(&#34;Failed to create istio client: %s&#34;, err)
|
||
}
|
||
// Print all VirtualServices
|
||
vsList, err := ic.NetworkingV1alpha3().VirtualServices(namespace).List(metav1.ListOptions{})
|
||
if err != nil {
|
||
log.Fatalf(&#34;Failed to get VirtualService in %s namespace: %s&#34;, namespace, err)
|
||
}
|
||
for i := range vsList.Items {
|
||
vs := vsList.Items[i]
|
||
log.Printf(&#34;Index: %d VirtualService Hosts: %+v\n&#34;, i, vs.Spec.GetHosts())
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>您可以在<a href="https://github.com/istio/client-go/blob/release-1.12/cmd/example/client.go">这里</a>找到更详尽的示例。</p>
|
||
<h2 id="useful-tools-created-for-generating-Istio-client-go">为生成 Istio client go 而创建的工具</h2>
|
||
<p>如果您想知道为什么花费大量时间也很难生成此客户端,本小节将对此进行说明。在 <code>Istio</code> 中,我们使用 <a href="https://developers.google.com/protocol-buffers">protobuf</a> 规范编写 <code>API</code>,然后使用 <code>protobuf</code> 工具链将其转换为 <code>Go</code> 定义。如果尝试从 <code>protobuf</code> 的 <code>API</code> 生成 <code>Kubernetes</code> 客户端,可能会面临三个主要的挑战:</p>
|
||
<ul>
|
||
<li><p><strong>创建 Kubernetes 装饰器类型</strong> - Kubernetes <a href="https://github.com/kubernetes/code-generator/tree/master/cmd/client-gen">客户端生成库</a>
|
||
仅适用于遵循 <code>Kubernetes</code> 对象规范的 <code>Go</code> 对象,例如:<a href="https://github.com/istio/client-go/blob/release-1.12/pkg/apis/authentication/v1alpha1/types.gen.go">Authentication Policy Kubernetes Wrappers</a>。这意味着对于需要程序访问的每个 API,您都需要创建这些装饰器。此外,每个 <code>CRD</code> 组,版本和种类都需要大量的样板,需要用客户端代码生成。为了自动化该过程,我们创建了一个 <a href="https://github.com/istio/tools/tree/master/cmd/kubetype-gen">Kubernetes type
|
||
generator</a> 工具,可以基于注释去自动创建 <code>Kubernetes</code>类型。该工具的注释和各种可用选项在 <a href="https://github.com/istio/tools/blob/master/cmd/kubetype-gen/README.md">README</a> 中进行了说明。请注意,如果您使用 <code>protobuf</code> 工具生成 <code>Go</code> 类型,则需要将这些注释添加到 <code>proto</code> 文件中,以便注释出现在生成的 <code>Go</code> 文件中,然后供该工具使用。</p></li>
|
||
<li><p><strong>生成 deep copy 方法</strong> - 在 <code>Kubernetes</code> 客户端机制中,如果您想对从客户端集返回的任何对象进行修改,则需要创建该对象的副本以防止直接修改缓存中的对象。为了不直接修改缓存中的对象,我们一般是在所有嵌套类型上创建一个 <code>deep copy</code> 方法。我们开发了一个 <a href="https://github.com/istio/tools/tree/master/cmd/protoc-gen-deepcopy">protoc deep copy
|
||
generator</a> 工具 ,该工具是一个 <code>protoc</code> 插件,可以使用 <a href="https://godoc.org/github.com/golang/protobuf/proto#Clone">Proto
|
||
Clone</a> 库上的注释自动创建 <code>deepcopy</code> 方法。这是一个生成了 <code>deepcopy</code> 方法的<a href="https://github.com/istio/api/blob/release-1.12/authentication/v1alpha1/policy_deepcopy.gen.go">示例</a>。</p></li>
|
||
<li><p><strong>类型和 JSON 的互相转换</strong> - 对于从 <code>proto</code> 定义生成的类型,使用默认的 <code>Go JSON</code> 编码器或解码器通常会出现问题,因为像 <code>protobuf</code> 的 <code>oneof</code> 这类字段需要进行特殊处理。另外,名称中带有下划线的任何 <code>Proto</code> 字段都可以序列化或反序列化为不同的字段名称,具体取决于编码器/解码器,因为 <code>Go</code> 结构体的标记方式<a href="https://github.com/istio/istio/issues/17600">不同</a>。始终建议使用 <code>protobuf</code> 原语对 <code>JSON</code> 进行序列化或反序列化,而不是依赖默认的 <code>Go</code> 库。我们创建了一个 <a href="https://github.com/istio/tools/tree/master/cmd/protoc-gen-jsonshim">protoc JSON shim</a> 工具,它是一个 <code>protoc</code> 插件,可以为从 <code>Proto</code> 定义所有 <code>Go</code> 类型自动创建的 <code>Marshalers</code> 或 <code>Unmarshalers</code>。这是用此工具生成代码的一个<a href="https://github.com/istio/api/blob/release-1.12/authentication/v1alpha1/policy_json.gen.go">示例</a>。</p></li>
|
||
</ul>
|
||
<p>我们希望新发布的客户端使用户能够为 <code>Istio API</code> 创建更多的 <code>integrations</code> 和 <code>controllers</code>,并且开发人员可以使用上述工具从 <code>Proto API</code> 生成 <code>Kubernetes</code> 客户端。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/announcing-istio-client-go/</link><author>Neeraj Poddar (Aspen Mesh)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/announcing-istio-client-go/</guid><category>client-go</category><category>tools</category><category>crd</category></item><item><title>DNS 证书管理</title><description><p>默认情况下, <code>Istio</code> 的 <code>DNS</code> 证书是由 <code>Citadel</code> 来管理的。<code>Citadel</code> 是一个功能强大的组件,不仅维护自己的私有签名密钥,而且充当证书颁发机构(CA)。</p>
|
||
<p>在 <code>Istio</code> 的 1.4 版本中,我们引入了一项新功能,可以安全地配置和管理由 <code>Kubernetes CA</code> 签名的 <code>DNS</code> 证书,它具有以下优点。</p>
|
||
<ul>
|
||
<li><p>轻量级 <code>DNS</code> 证书管理,不依赖于 <code>Citadel</code>。</p></li>
|
||
<li><p>与 <code>Citadel</code> 不同的是,此功能不维护私有签名密钥,从而增强了安全性。</p></li>
|
||
<li><p>简化了向 <code>TLS</code> 客户端分发根证书。客户不再需要等待 <code>Citadel</code> 生成和分发其 <code>CA</code> 证书。</p></li>
|
||
</ul>
|
||
<p>下图显示了在 <code>Istio</code> 中配置和管理 <code>DNS</code> 证书的体系结构。<code>Chiron</code> 是在 <code>Istio</code> 中配置和管理 <code>DNS</code> 证书的组件。</p>
|
||
<figure style="width:50%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:82.13367609254499%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/dns-cert/architecture.png" title="在 Istio 中配置和管理 DNS 证书的架构">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/dns-cert/architecture.png" alt="在 Istio 中配置和管理 DNS 证书的架构" />
|
||
</a>
|
||
</div>
|
||
<figcaption>在 Istio 中配置和管理 DNS 证书的架构</figcaption>
|
||
</figure>
|
||
<p>要尝试此新功能,请参阅 <a href="/v1.12/zh/docs/tasks/security/cert-management/dns-cert">DNS 证书管理内容</a>。</p></description><pubDate>Thu, 14 Nov 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/dns-cert/</link><author>Lei Tang (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/dns-cert/</guid><category>security</category><category>kubernetes</category><category>certificates</category><category>DNS</category></item><item><title>把 Istio 作为外部服务的代理</title><description>
|
||
<p>在网格内如何配置一个入口网关来把内部服务暴露出去,让外部可以访问,在这两篇文章中有介绍<a href="/v1.12/zh/docs/tasks/traffic-management/ingress/ingress-control/">控制入口流量</a>和<a href="/v1.12/zh/docs/tasks/traffic-management/ingress/ingress-sni-passthrough/">无 TLS 终止的入口网关</a>。这些服务可以是 HTTP 或者 HTTPS。如果是 HTTPS,网关会透传流量,而不终止 TLS。</p>
|
||
<p>这篇博客介绍如何使用 Istio 的入口网关机制来访问外部服务,而不是网格内应用。这样,Istio 整个作为一个代理服务,具有可观测性、流量管理和策略执行的附加价值。</p>
|
||
<p>这篇博客也展示了如何配置访问一个外部的 HTTP 和 HTTPS 服务,分别是 <code>httpbin.org</code> 和 <code>edition.cnn.com</code>。</p>
|
||
<h2 id="configure-an-ingress-gateway">配置一个入口网关</h2>
|
||
<ol>
|
||
<li><p>定义一个入口网关,在 <code>servers:</code> 配置中配置 <code>80</code> 和 <code>443</code> 端口。
|
||
在对端口 <code>443</code> 的配置终确定 <code>tls:</code> 的 <code>mode:</code> 配置为 <code>PASSTHROUGH</code>,这配置网关直接透传流量而且不终止 TLS。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: proxy
|
||
spec:
|
||
selector:
|
||
istio: ingressgateway # use istio default ingress gateway
|
||
servers:
|
||
- port:
|
||
number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
hosts:
|
||
- httpbin.org
|
||
- port:
|
||
number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
tls:
|
||
mode: PASSTHROUGH
|
||
hosts:
|
||
- edition.cnn.com
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>为 <code>httpbin.org</code> 和 <code>edition.cnn.com</code> 创建服务入口,让他们可以通过入口网关访问:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: httpbin-ext
|
||
spec:
|
||
hosts:
|
||
- httpbin.org
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
resolution: DNS
|
||
location: MESH_EXTERNAL
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: cnn
|
||
spec:
|
||
hosts:
|
||
- edition.cnn.com
|
||
ports:
|
||
- number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
resolution: DNS
|
||
location: MESH_EXTERNAL
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>创建一个服务入口,并且为 <code>localhost</code> 服务配置目的规则。在下一步中,需要这个服务入口作为网格内部应用流量到外部服务的目的地,从而隔断来自网格内部的流量。在此例中把 Istio 用作外部应用和外部服务间的代理。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: localhost
|
||
spec:
|
||
hosts:
|
||
- localhost.local
|
||
location: MESH_EXTERNAL
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
- number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
resolution: STATIC
|
||
endpoints:
|
||
- address: 127.0.0.1
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: localhost
|
||
spec:
|
||
host: localhost.local
|
||
trafficPolicy:
|
||
tls:
|
||
mode: DISABLE
|
||
sni: localhost.local
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>为每个外部服务创建一个虚拟服务并配置路由规则。两个虚拟服务的 <code>gateways:</code> 和 <code>match:</code> 配置中有针对 HTTP 和 HTTPS 流量相关的 <code>proxy</code> 网关配置。</p>
|
||
<p>注意 <code>route:</code> 配置中的 <code>mesh</code> 网关配置,这个网关代表网格内的应用程序。<code>mesh</code> 网关中的 <code>route:</code> 配置表示如何将流量转向 <code>localhost.local</code> 服务,从而有效地阻隔了流量。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: httpbin
|
||
spec:
|
||
hosts:
|
||
- httpbin.org
|
||
gateways:
|
||
- proxy
|
||
- mesh
|
||
http:
|
||
- match:
|
||
- gateways:
|
||
- proxy
|
||
port: 80
|
||
uri:
|
||
prefix: /status
|
||
route:
|
||
- destination:
|
||
host: httpbin.org
|
||
port:
|
||
number: 80
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: 80
|
||
route:
|
||
- destination:
|
||
host: localhost.local
|
||
port:
|
||
number: 80
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: cnn
|
||
spec:
|
||
hosts:
|
||
- edition.cnn.com
|
||
gateways:
|
||
- proxy
|
||
- mesh
|
||
tls:
|
||
- match:
|
||
- gateways:
|
||
- proxy
|
||
port: 443
|
||
sni_hosts:
|
||
- edition.cnn.com
|
||
route:
|
||
- destination:
|
||
host: edition.cnn.com
|
||
port:
|
||
number: 443
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: 443
|
||
sni_hosts:
|
||
- edition.cnn.com
|
||
route:
|
||
- destination:
|
||
host: localhost.local
|
||
port:
|
||
number: 443
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging">启用 Envoy 的访问日志</a>。</p></li>
|
||
<li><p>根据<a href="/v1.12/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-i-p-and-ports">确定入口网关的 IP 和端口</a>中的命令,设置 <code>SECURE_INGRESS_PORT</code> 和 <code>INGRESS_HOST</code> 两个环境变量。</p></li>
|
||
<li><p>在上一步中分别把 IP 和端口存储到了环境变量 <code>$INGRESS_HOST</code> 和 <code>$INGRESS_PORT</code> 中,现在可以用这个 IP 和端口访问 <code>httbin.org</code> 服务。访问 <code>httpbin.org</code> 服务的 <code>/status/418</code> 路径,会返回 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418">418 我是一个茶壶</a>的 HTTP 状态码。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl $INGRESS_HOST:$INGRESS_PORT/status/418 -Hhost:httpbin.org
|
||
-=[ teapot ]=-
|
||
_...._
|
||
.&#39; _ _ `.
|
||
| .&#34;` ^ `&#34;. _,
|
||
\_;`&#34;---&#34;`|//
|
||
| ;/
|
||
\_ _/
|
||
`&#34;&#34;&#34;`
|
||
</code></pre></li>
|
||
<li><p>如果 Istio 入口网关部署在 <code>istio-system</code> 名字空间下,使用下面的命令打印网关日志。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs -l istio=ingressgateway -c istio-proxy -n istio-system | grep &#39;httpbin.org&#39;
|
||
</code></pre></li>
|
||
<li><p>检索日志找到类似如下内容:</p>
|
||
<pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >[2019-01-31T14:40:18.645Z] &#34;GET /status/418 HTTP/1.1&#34; 418 - 0 135 187 186 &#34;10.127.220.75&#34; &#34;curl/7.54.0&#34; &#34;28255618-6ca5-9d91-9634-c562694a3625&#34; &#34;httpbin.org&#34; &#34;34.232.181.106:80&#34; outbound|80||httpbin.org - 172.30.230.33:80 10.127.220.75:52077 -
|
||
</code></pre></li>
|
||
<li><p>通过入口网关访问 <code>edition.cnn.com</code> 服务:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl -s --resolve edition.cnn.com:$SECURE_INGRESS_PORT:$INGRESS_HOST https://edition.cnn.com:$SECURE_INGRESS_PORT | grep -o &#34;&lt;title&gt;.*&lt;/title&gt;&#34;
|
||
&lt;title&gt;CNN International - Breaking News, US News, World News and Video&lt;/title&gt;
|
||
</code></pre></li>
|
||
<li><p>如果 Istio 入口网关部署在 <code>istio-system</code> 名字空间下,使用下面的命令打印网关日志。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs -l istio=ingressgateway -c istio-proxy -n istio-system | grep &#39;edition.cnn.com&#39;
|
||
</code></pre></li>
|
||
<li><p>检索日志找到类似如下内容:</p>
|
||
<pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >[2019-01-31T13:40:11.076Z] &#34;- - -&#34; 0 - 589 17798 1644 - &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;172.217.31.132:443&#34; outbound|443||edition.cnn.com 172.30.230.33:54508 172.30.230.33:443 10.127.220.75:49467 edition.cnn.com
|
||
</code></pre></li>
|
||
</ol>
|
||
<h2 id="cleanup">清除</h2>
|
||
<p>删除网关、虚拟服务和服务入口:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete gateway proxy
|
||
$ kubectl delete virtualservice cnn httpbin
|
||
$ kubectl delete serviceentry cnn httpbin-ext localhost
|
||
$ kubectl delete destinationrule localhost
|
||
</code></pre></description><pubDate>Tue, 15 Oct 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/proxy/</link><author>Vadim Eisenberg (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/proxy/</guid><category>traffic-management</category><category>ingress</category><category>https</category><category>http</category></item><item><title>用于隔离和边界保护的多网格部署</title><description>
|
||
<p>各种合规性标准要求保护敏感数据环境。下表列出了一些重要的标准及其保护的敏感数据的类型:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>标准</th>
|
||
<th>敏感数据类型</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><a href="https://www.pcisecuritystandards.org/pci_security">PCI DSS</a></td>
|
||
<td>支付卡数据</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.fedramp.gov">FedRAMP</a></td>
|
||
<td>联邦信息,数据和元数据</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="http://www.gpo.gov/fdsys/search/pagedetails.action?granuleId=CRPT-104hrpt736&amp;packageId=CRPT-104hrpt736">HIPAA</a></td>
|
||
<td>个人健康数据</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://gdpr-info.eu">GDPR</a></td>
|
||
<td>个人资料</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><a href="https://www.pcisecuritystandards.org/pci_security">PCI DSS</a>,例如,建议将持卡人数据环境放置在和系统其它部分不同的网络上。它还需要使用 <a href="https://en.wikipedia.org/wiki/DMZ_(computing)">DMZ</a>,并在公网和 DMZ 之间以及 DMZ 和内部网络之间设置防火墙。</p>
|
||
<p>将敏感数据环境与其他信息系统隔离可以减少合规性检查的范围并提高敏感数据的安全性。缩小范围可降低合规性检查失败的风险,并降低合规性成本,因为根据合规性要求,要检查和保护的组件较少。</p>
|
||
<p>通过将处理数据的应用程序各部分分离到单独的服务网格中(最好也是在单独的网络上),然后将具有不同合规性要求的网格连接到 <span class="term" data-title="Multi-Mesh" data-body="&lt;p&gt;Multi-mesh 是由两个或多个&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;服务网格&lt;/a&gt;组成的部署模型。
|
||
每个网格都有独立的命名管理和身份管理,但是您可以通过&lt;a href=&#34;/zh/docs/reference/glossary/#mesh-federation&#34;&gt;网格联邦&lt;/a&gt;来暴露
|
||
网格之间的服务, 最终构成一个多网格部署。&lt;/p&gt;
|
||
">多网格</span> 部署中,可以实现敏感数据的隔离。连接网间应用程序的过程称为 <span class="term" data-title="Mesh Federation" data-body="&lt;p&gt;网格联邦是在网格之间公开服务的一种行为,并且能跨越网格边界进行通信。每一个网格或许会公开其一部分的服务,使一个或多个其他网格使用此公开的服务。
|
||
您可以使用网格联邦来启用网格之间的通信,可参阅&lt;a href=&#34;/zh/docs/ops/deployment/deployment-models/#multiple-meshes&#34;&gt;多个网格部署&lt;/a&gt;。&lt;/p&gt;
|
||
">网格联邦</span>。</p>
|
||
<p>请注意,使用网格联邦来创建多网格部署与创建 <span class="term" data-title="Multicluster" data-body="&lt;p&gt;Multicluster 是一种部署模型,由具有多个&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;集群&lt;/a&gt;的&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;网格&lt;/a&gt;组成。&lt;/p&gt;
|
||
">多集群</span> 部署非常不同,后者定义了一个由跨多个群集的服务组成的单个服务网格。与多网格不同,多群集部署不适用于需要隔离和边界保护的应用程序。</p>
|
||
<p>在此博客文章中,我描述了隔离和边界保护的要求,并概述了多网格部署的原理。最后,我介绍了 Istio 当前在网格联邦支持和自动化工作的状态。</p>
|
||
<h2 id="isolation-and-boundary-protection">隔离和边界保护</h2>
|
||
<p>隔离和边界保护机制在 <a href="http://dx.doi.org/10.6028/NIST.SP.800-53r4">NIST 特殊出版物 800-53,修订 4,联邦信息系统和组织的安全和隐私控制</a>,_附录 F,安全控制目录,SC-7 边界保护中进行了说明_。</p>
|
||
<p>特别是 <em>边界保护,隔离信息系统组件</em> 控制增强:</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content">组织可以隔离执行不同任务和/或业务功能的信息系统组件。这种隔离限制了系统组件之间未经授权的信息流,并且还提供了为所选组件部署更高级别的保护的机会。使用边界保护机制将系统组件分开提供了增强对单个组件的保护并更有效地控制这些组件之间的信息流的能力。这种类型的增强保护可限制网络攻击和错误带来的潜在危害。提供的分离程度取决于所选的机制。边界保护机制包括,路由器、网关和防火墙等,将系统组件分离为物理上分离的网络或子网;跨域设备将子网分离;虚拟化技术;以及使用不同的加密密钥对系统组件之间的信息流进行加密。</div>
|
||
</aside>
|
||
</div>
|
||
<p>各种合规性标准隔离建议,用于处理组织其余部分的敏感数据的环境。<a href="https://www.pcisecuritystandards.org/pci_security/">支付卡行业(PCI)数据安全标准</a>建议为 <em>持卡人数据</em> 环境实现网络隔离,并要求将此环境与 <a href="https://en.wikipedia.org/wiki/DMZ_(computing)">DMZ</a> 隔离。<a href="https://www.fedramp.gov/assets/resources/documents/CSP_A_FedRAMP_Authorization_Boundary_Guidance.pdf">FedRAMP 边界授权指南</a>描述了联邦信息和数据的 _授权边界_,而 <a href="https://doi.org/10.6028/NIST.SP.800-37r2">NIST 特别出版物 800-37,修订版 2,信息系统和组织的风险管理框架:用于安全性和隐私的系统生命周期方法</a> <em>附录 G,授权边界注意事项</em> 建议保护这样的边界:</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content">将系统划分为子系统(即分而治之)有助于针对性地应用控制措施,以实现足够的安全性,保护个人隐私和具有成本效益的风险管理流程。将复杂的系统划分为子系统也支持域分离和网络分段的重要安全概念,这在处理高价值资产时可能非常重要。将系统划分为子系统时,组织可以选择制定单独的子系统安全和隐私计划,也可以选择在相同的安全和隐私计划中处理系统和子系统。
|
||
信息安全和隐私体系结构在将复杂系统划分为子系统的过程中起着关键作用。这包括在子系统之间的内部边界监视和控制通信,以及选择,分配和实施满足或超过组成子系统的安全性和隐私要求的控件。</div>
|
||
</aside>
|
||
</div>
|
||
<p>边界保护意味着:</p>
|
||
<ul>
|
||
<li>在边界(防火墙,网关等)上设置访问控制机制</li>
|
||
<li>监视边界处的出/入流量</li>
|
||
<li>默认情况下,所有访问控制机制都必须为 <em>deny-all</em></li>
|
||
<li>不要通过边界暴露私有 IP 地址</li>
|
||
<li>不要让边界外的组件影响边界内的安全性</li>
|
||
</ul>
|
||
<p>多网格部署有助于将系统划分为具有不同安全性和合规性要求的子系统,有助于边界保护。您将每个子系统放入单独的服务网格中,最好放在单独的网络中。使用网关连接 Istio 网格。网关在每个网格的边界监视和控制跨网格流量。</p>
|
||
<h2 id="features-of-multi-mesh-deployments">多网格部署的特性</h2>
|
||
<ul>
|
||
<li><strong>非统一命名</strong>。一个网格 <code>accounts</code> 命名空间中的 <code>withdraw</code> 服务可能与其他网格 <code>accounts</code> 命名空间中的 <code>withdraw</code> 服务具有不同的功能和 API。这种情况可能发生在没有统一命名空间和服务命名策略的组织中,或者当网格属于不同组织时。</li>
|
||
<li><strong>默认不暴露任何内容</strong>。默认情况下,网格中没有任何暴露的服务,网格所有者必须明确指定要暴露的服务。</li>
|
||
<li><strong>边界保护</strong>。流量的访问控制必须在入口网关上执行,这将阻止未经允许的流量进入网格。该要求实现了<a href="https://en.wikipedia.org/wiki/Defense_in_depth_(computing)">纵深防御原则</a>,并且是某些合规性标准的一部分,例如<a href="https://www.pcisecuritystandards.org/pci_security/">支付卡行业(PCI)数据安全标准</a>。</li>
|
||
<li><strong>可能不存在共同信任</strong>。由于某些安全要求或由于网格所有者最初未计划网格联邦,可能会出现一个网格中的 Istio sidecar 不信任其他网格中的 Citadel 证书的情况。</li>
|
||
</ul>
|
||
<p>必需通过 <strong>默认不暴露任何内容</strong> 和 <strong>边界保护</strong> 来促进合规性并提高安全性。连接不同组织的网格,或者组织不能执行统一命名,或者不能建立网格之间的公共信任,<strong>非统一命名</strong> 和 <strong>可能不存在共同信任</strong> 也是必需的。</p>
|
||
<p>您可能要使用的一个可选功能是 <code>服务位置透传</code>:使用服务的请求使用本地服务名称将请求发送到远程网格中的公开服务。消费服务忽略了以下事实:某些目的地位于远程网格中,而某些目的地是本地服务。访问使用本地服务名称是统一的,例如在 Kubernetes 中是 <code>reviews.default.svc.cluster.local</code>。<strong>服务位置透传</strong> 在您希望能够更改使用的服务的位置的情况下很有用,例如,某些服务从私有云迁移到公共云而无需更改应用程序代码的情况。</p>
|
||
<h2 id="the-current-mesh-federation-work">网格联邦目前的工作</h2>
|
||
<p>尽管您现在已经可以使用标准 Istio 配置完成网格联邦,但是它需要编写大量 YAML 文件模板,并且容易出错。我们正在努力使网格联邦过程自动化。同时,您可以查看这些<a href="https://github.com/istio-ecosystem/multi-mesh-examples">多网格部署示例</a>,以了解生成的联邦可能包括的内容。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>在此博客中,我描述了使用 Istio 多网格部署对敏感数据环境进行隔离和边界保护的要求。概述了 Istio 多网格部署的原理,并报告了 Istio 中有关网格联邦的最新工作。</p>
|
||
<p>我很高兴在 <a href="https://discuss.istio.io">discuss.istio.io</a> 听到您对 <span class="term" data-title="Multi-Mesh" data-body="&lt;p&gt;Multi-mesh 是由两个或多个&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;服务网格&lt;/a&gt;组成的部署模型。
|
||
每个网格都有独立的命名管理和身份管理,但是您可以通过&lt;a href=&#34;/zh/docs/reference/glossary/#mesh-federation&#34;&gt;网格联邦&lt;/a&gt;来暴露
|
||
网格之间的服务, 最终构成一个多网格部署。&lt;/p&gt;
|
||
">多网格</span> 和 <span class="term" data-title="Multicluster" data-body="&lt;p&gt;Multicluster 是一种部署模型,由具有多个&lt;a href=&#34;/zh/docs/reference/glossary/#cluster&#34;&gt;集群&lt;/a&gt;的&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;网格&lt;/a&gt;组成。&lt;/p&gt;
|
||
">多集群</span> 的意见。</p></description><pubDate>Wed, 02 Oct 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/isolated-clusters/</link><author>Vadim Eisenberg (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/isolated-clusters/</guid><category>traffic-management</category><category>multicluster</category><category>security</category><category>gateway</category><category>tls</category></item><item><title>监控被阻止的和透传的外部服务流量</title><description>
|
||
<p>了解,控制和保护外部服务访问权限是你能够从 Istio 这样的服务网格中获得的主要好处之一。
|
||
从安全和操作的角度来看,监控哪些外部服务流量被阻止是非常重要的;因为如果程序试图与不合适的服务进行通信,它们可能会出现错误配置或安全漏洞。
|
||
同样,如果你现在有允许任何外部服务访问的策略,那么你可以根据对流量的监控,逐步地添加明确的 Istio 配置来限制访问并提高集群的安全性。
|
||
在任何情况下,通过遥测了解这种流量都非常有帮助,因为你可以根据它来创建警报和仪表板,并更好地了解安全状况。
|
||
这是 Istio 的生产用户强烈要求的功能,我们很高兴在版本 1.3 中添加了对此功能的支持。</p>
|
||
<p>为了实现此功能,Istio 的<a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/metrics">默认监控指标</a>增加了显式标签,以捕获被阻止和透传的外部服务流量。
|
||
这篇博客将介绍如何使用这些增强指标来监视所有外部服务流量。</p>
|
||
<p>Istio 控制平面使用了预定义集群 BlackHoleCluster 和 Passthrough 来配置 sidecar 代理,它们的作用分别是阻止和通过所有流量。
|
||
为了了解这些集群,让我们先从外部和内部服务在 Istio 服务网格的意义开始。</p>
|
||
<h2 id="external-and-internal-services">外部和内部服务</h2>
|
||
<p>内部服务被定义为平台中的一部分,并被视为在网格中。对于内部服务,默认情况下,Istio 控制平面为 sidecars 提供所有必需的配置。
|
||
例如,在 Kubernetes 集群中,Istio 会为所有 Kubernetes 服务配置 sidecar,以保留所有能够与其他服务通信的服务的默认 Kubernetes 行为。</p>
|
||
<p>外部服务是不属于平台的服务,即不在网格内的服务。
|
||
对于外部服务,Istio 提供了两个选项,一个是阻止所有外部服务访问(通过将 <code>global.outboundTrafficPolicy.mode</code> 设置
|
||
为 <code>REGISTRY_ONLY</code> 启用), 另一个是允许所有对外部服务的访问(通过将 <code>global.outboundTrafficPolicy.mode</code> 设置为 <code>ALLOW_ANY</code> 启用)。
|
||
从 Istio 1.3 开始,此设置的默认选项是允许所有外部服务访问。此选项可以通过<a href="/v1.12/zh/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-OutboundTrafficPolicy-Mode">网格配置</a>进行配置。</p>
|
||
<p>这就是使用 BlackHole 和 Passthrough 集群的地方。</p>
|
||
<h2 id="what-are-black-hole-and-pass-through-clusters">什么是 BlackHole 和 Passthrough 集群?</h2>
|
||
<ul>
|
||
<li><strong>BlackHoleCluster</strong> - 当将 <code>global.outboundTrafficPolicy.mode</code> 设置为 <code>REGISTRY_ONLY</code> 时,BlackHoleCluster 是
|
||
在 Envoy 配置中创建的虚拟集群。在这种模式下,除非为每个服务显式添加了
|
||
<a href="/v1.12/zh/docs/reference/config/networking/service-entry">service entries</a>,否则
|
||
所有到外部服务的流量都会被阻止。为了实现此目的,
|
||
将使用了 <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#original-destination">original destination</a> 且在 <code>0.0.0.0:15001</code> 的默认虚拟出站监听器设置为以 BlackHoleCluster 为静态集群的 TCP 代理。
|
||
BlackHoleCluster 的配置如下所示:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;name&#34;: &#34;BlackHoleCluster&#34;,
|
||
&#34;type&#34;: &#34;STATIC&#34;,
|
||
&#34;connectTimeout&#34;: &#34;10s&#34;
|
||
}
|
||
</code></pre>
|
||
<p>如你所见,这个集群是静态的且没有任何的 endpoints,所以所有的流量都会被丢弃。
|
||
此外,Istio 会为平台服务的每个端口/协议组合创建唯一的监听器,如果对同一端口上的外部服务发出了请求,则监听器将会取代虚拟监听器。
|
||
在这种情况下,Envoy 中每个虚拟路由的路由配置都会被扩展,以添加 BlackHoleCluster,如下所示:</p>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;name&#34;: &#34;block_all&#34;,
|
||
&#34;domains&#34;: [
|
||
&#34;*&#34;
|
||
],
|
||
&#34;routes&#34;: [
|
||
{
|
||
&#34;match&#34;: {
|
||
&#34;prefix&#34;: &#34;/&#34;
|
||
},
|
||
&#34;directResponse&#34;: {
|
||
&#34;status&#34;: 502
|
||
}
|
||
}
|
||
]
|
||
}
|
||
</code></pre>
|
||
<p>该路由被设置为响应码是 502 的<a href="https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-route-direct-response">直接响应</a>,这意味着如果没有其他路由匹配,则 Envoy 代理将直接返回 502 HTTP 状态代码。</p>
|
||
<ul>
|
||
<li><strong>PassthroughCluster</strong> - 当将 <code>global.outboundTrafficPolicy.mode</code> 设置为 <code>ALLOW_ANY</code> 时,
|
||
PassthroughCluster 是在 Envoy 配置中创建的虚拟集群。在此模式下,允许流向外部服务的所有流量。
|
||
为了实现此目的,将使用 <code>SO_ORIGINAL_DST</code> 且监听 <code>0.0.0.0:15001</code> 的默认虚拟出站监听器设置为 TCP 代理,并将 PassthroughCluster 作为静态集群。
|
||
PassthroughCluster 的配置如下所示:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;name&#34;: &#34;PassthroughCluster&#34;,
|
||
&#34;type&#34;: &#34;ORIGINAL_DST&#34;,
|
||
&#34;connectTimeout&#34;: &#34;10s&#34;,
|
||
&#34;lbPolicy&#34;: &#34;ORIGINAL_DST_LB&#34;,
|
||
&#34;circuitBreakers&#34;: {
|
||
&#34;thresholds&#34;: [
|
||
{
|
||
&#34;maxConnections&#34;: 102400,
|
||
&#34;maxRetries&#34;: 1024
|
||
}
|
||
]
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>该集群使用<a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#original-destination">原始目标负载均衡策略</a>,
|
||
该策略将 Envoy 配置为将流量发送到原始目标,即透传。</p>
|
||
<p>与 BlackHoleCluster 类似,对于每个基于端口/协议的监听器,虚拟路由配置都会添加 PassthroughCluster 以作为默认路由:</p>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;name&#34;: &#34;allow_any&#34;,
|
||
&#34;domains&#34;: [
|
||
&#34;*&#34;
|
||
],
|
||
&#34;routes&#34;: [
|
||
{
|
||
&#34;match&#34;: {
|
||
&#34;prefix&#34;: &#34;/&#34;
|
||
},
|
||
&#34;route&#34;: {
|
||
&#34;cluster&#34;: &#34;PassthroughCluster&#34;
|
||
}
|
||
}
|
||
]
|
||
}
|
||
</code></pre>
|
||
<p>在 Istio 1.3 之前,没有流量报告,即使流量报告到达这些群集,也没有报告明确的标签设置,从而导致流经网格的流量缺乏可见性。</p>
|
||
<p>下一节将介绍如何利用此增强功能,因为发出的指标和标签取决于是否命中了虚拟出站或显式端口/协议监听器。</p>
|
||
<h2 id="using-the-augmented-metrics">使用增强指标</h2>
|
||
<p>要捕获两种情况(BlackHole 或 Passthrough)中的所有外部服务流量,你将需要监控 <code>istio_requests_total</code> 和 <code>istio_tcp_connections_closed_total</code> 指标。
|
||
根据 Envoy 监听器的类型,即被调用的 TCP 代理或 HTTP 代理,将增加相应的指标。</p>
|
||
<p>此外,如果使用 TCP 代理监听器以查看被 BlackHole 阻止或被 Passthrough 透传的外部服务的 IP 地址,
|
||
则需要将 <code>destination_ip</code> 标签添加到 <code>istio_tcp_connections_closed_total</code> 指标。
|
||
在这种情况下,不会捕获外部服务的主机名。默认情况下不添加此标签,但是可以通过扩展 Istio 配置以生成属性和 Prometheus 处理程序,轻松地添加此标签。
|
||
如果你有许多服务的 IP 地址不稳定,则应注意时序的基数爆炸。</p>
|
||
<h3 id="pass-through-cluster-metrics">PassthroughCluster 指标</h3>
|
||
<p>本节将说明基于被 Envoy 调用的监听器类型的指标和发出的标签。</p>
|
||
<ul>
|
||
<li>HTTP 代理监听器: 当外部服务的端口与集群中定义的服务端口之一相同时,就会触发这种情况。
|
||
在这种情况下,当命中 PassthroughCluster 时,指标 <code>istio_requests_total</code> 会增加类似以下内容:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;metric&#34;: {
|
||
&#34;__name__&#34;: &#34;istio_requests_total&#34;,
|
||
&#34;connection_security_policy&#34;: &#34;unknown&#34;,
|
||
&#34;destination_app&#34;: &#34;unknown&#34;,
|
||
&#34;destination_principal&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service&#34;: &#34;httpbin.org&#34;,
|
||
&#34;destination_service_name&#34;: &#34;PassthroughCluster&#34;,
|
||
&#34;destination_service_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;destination_version&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;instance&#34;: &#34;100.96.2.183:42422&#34;,
|
||
&#34;job&#34;: &#34;istio-mesh&#34;,
|
||
&#34;permissive_response_code&#34;: &#34;none&#34;,
|
||
&#34;permissive_response_policyid&#34;: &#34;none&#34;,
|
||
&#34;reporter&#34;: &#34;source&#34;,
|
||
&#34;request_protocol&#34;: &#34;http&#34;,
|
||
&#34;response_code&#34;: &#34;200&#34;,
|
||
&#34;response_flags&#34;: &#34;-&#34;,
|
||
&#34;source_app&#34;: &#34;sleep&#34;,
|
||
&#34;source_principal&#34;: &#34;unknown&#34;,
|
||
&#34;source_version&#34;: &#34;unknown&#34;,
|
||
&#34;source_workload&#34;: &#34;sleep&#34;,
|
||
&#34;source_workload_namespace&#34;: &#34;default&#34;
|
||
},
|
||
&#34;value&#34;: [
|
||
1567033080.282,
|
||
&#34;1&#34;
|
||
]
|
||
}
|
||
</code></pre>
|
||
<p>请注意,标签 <code>destination_service_name</code> 设置为 PassthroughCluster,以表明已命中该集群,而 <code>destination_service</code> 设置为外部服务的主机。</p>
|
||
<ul>
|
||
<li>TCP 代理虚拟监听器 - 如果外部服务端口未映射到集群中任何基于 HTTP 的服务端口,则将调用此监听器,
|
||
并且会增加指标 <code>istio_tcp_connections_closed_total</code>:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;status&#34;: &#34;success&#34;,
|
||
&#34;data&#34;: {
|
||
&#34;resultType&#34;: &#34;vector&#34;,
|
||
&#34;result&#34;: [
|
||
{
|
||
&#34;metric&#34;: {
|
||
&#34;__name__&#34;: &#34;istio_tcp_connections_closed_total&#34;,
|
||
&#34;connection_security_policy&#34;: &#34;unknown&#34;,
|
||
&#34;destination_app&#34;: &#34;unknown&#34;,
|
||
&#34;destination_ip&#34;: &#34;52.22.188.80&#34;,
|
||
&#34;destination_principal&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service_name&#34;: &#34;PassthroughCluster&#34;,
|
||
&#34;destination_service_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;destination_version&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;instance&#34;: &#34;100.96.2.183:42422&#34;,
|
||
&#34;job&#34;: &#34;istio-mesh&#34;,
|
||
&#34;reporter&#34;: &#34;source&#34;,
|
||
&#34;response_flags&#34;: &#34;-&#34;,
|
||
&#34;source_app&#34;: &#34;sleep&#34;,
|
||
&#34;source_principal&#34;: &#34;unknown&#34;,
|
||
&#34;source_version&#34;: &#34;unknown&#34;,
|
||
&#34;source_workload&#34;: &#34;sleep&#34;,
|
||
&#34;source_workload_namespace&#34;: &#34;default&#34;
|
||
},
|
||
&#34;value&#34;: [
|
||
1567033761.879,
|
||
&#34;1&#34;
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>在这种情况下,<code>destination_service_name</code> 设置为 PassthroughCluster,而 <code>destination_ip</code> 设置为外部服务的 IP 地址。
|
||
标签 <code>destination_ip</code> 可用于执行反向 DNS 查找并获取外部服务的主机名。
|
||
在通过该集群时,还将更新其他与 TCP 相关的指标,例如 <code>istio_tcp_connections_opened_total</code>,
|
||
<code>istio_tcp_received_bytes_total</code> 和 <code>istio_tcp_sent_bytes_total</code>。</p>
|
||
<h3 id="black-hole-cluster-metrics">BlackHoleCluster 指标</h3>
|
||
<p>与 PassthroughCluster 类似,本节将说明基于被 Envoy 调用的监听器类型的指标和发出的标签。</p>
|
||
<ul>
|
||
<li>HTTP 代理监听器: 这种情况发生在外部服务的端口与群集中定义的服务端口之一相同时。
|
||
在这种情况下,如果命中了 BlackHoleCluster,标签 <code>istio_requests_total</code> 会增加类似以下的内容:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;metric&#34;: {
|
||
&#34;__name__&#34;: &#34;istio_requests_total&#34;,
|
||
&#34;connection_security_policy&#34;: &#34;unknown&#34;,
|
||
&#34;destination_app&#34;: &#34;unknown&#34;,
|
||
&#34;destination_principal&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service&#34;: &#34;httpbin.org&#34;,
|
||
&#34;destination_service_name&#34;: &#34;BlackHoleCluster&#34;,
|
||
&#34;destination_service_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;destination_version&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;instance&#34;: &#34;100.96.2.183:42422&#34;,
|
||
&#34;job&#34;: &#34;istio-mesh&#34;,
|
||
&#34;permissive_response_code&#34;: &#34;none&#34;,
|
||
&#34;permissive_response_policyid&#34;: &#34;none&#34;,
|
||
&#34;reporter&#34;: &#34;source&#34;,
|
||
&#34;request_protocol&#34;: &#34;http&#34;,
|
||
&#34;response_code&#34;: &#34;502&#34;,
|
||
&#34;response_flags&#34;: &#34;-&#34;,
|
||
&#34;source_app&#34;: &#34;sleep&#34;,
|
||
&#34;source_principal&#34;: &#34;unknown&#34;,
|
||
&#34;source_version&#34;: &#34;unknown&#34;,
|
||
&#34;source_workload&#34;: &#34;sleep&#34;,
|
||
&#34;source_workload_namespace&#34;: &#34;default&#34;
|
||
},
|
||
&#34;value&#34;: [
|
||
1567034251.717,
|
||
&#34;1&#34;
|
||
]
|
||
}
|
||
</code></pre>
|
||
<p>请注意,标签 <code>destination_service_name</code> 设置为 BlackHoleCluster,而 <code>destination_service</code> 设置为外部服务的主机名。
|
||
在这种情况下,响应码应始终为 502。</p>
|
||
<ul>
|
||
<li>TCP 代理虚拟监听器 - 如果外部服务端口未映射到集群中任何基于 HTTP 的服务端口,则会调用此监听器,
|
||
并增加指标 <code>istio_tcp_connections_closed_total</code>:</li>
|
||
</ul>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;metric&#34;: {
|
||
&#34;__name__&#34;: &#34;istio_tcp_connections_closed_total&#34;,
|
||
&#34;connection_security_policy&#34;: &#34;unknown&#34;,
|
||
&#34;destination_app&#34;: &#34;unknown&#34;,
|
||
&#34;destination_ip&#34;: &#34;52.22.188.80&#34;,
|
||
&#34;destination_principal&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service&#34;: &#34;unknown&#34;,
|
||
&#34;destination_service_name&#34;: &#34;BlackHoleCluster&#34;,
|
||
&#34;destination_service_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;destination_version&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload&#34;: &#34;unknown&#34;,
|
||
&#34;destination_workload_namespace&#34;: &#34;unknown&#34;,
|
||
&#34;instance&#34;: &#34;100.96.2.183:42422&#34;,
|
||
&#34;job&#34;: &#34;istio-mesh&#34;,
|
||
&#34;reporter&#34;: &#34;source&#34;,
|
||
&#34;response_flags&#34;: &#34;-&#34;,
|
||
&#34;source_app&#34;: &#34;sleep&#34;,
|
||
&#34;source_principal&#34;: &#34;unknown&#34;,
|
||
&#34;source_version&#34;: &#34;unknown&#34;,
|
||
&#34;source_workload&#34;: &#34;sleep&#34;,
|
||
&#34;source_workload_namespace&#34;: &#34;default&#34;
|
||
},
|
||
&#34;value&#34;: [
|
||
1567034481.03,
|
||
&#34;1&#34;
|
||
]
|
||
}
|
||
</code></pre>
|
||
<p>请注意,标签 <code>destination_ip</code> 表示外部服务的 IP 地址,而 <code>destination_service_name</code> 设置为 BlackHoleCluster,表示此流量已被网格阻止。
|
||
有趣的是,对于 BlackHole 集群,由于未建立任何连接,因此其他与 TCP 相关的指标(例如 <code>istio_tcp_connections_opened_total</code>)不会增加。</p>
|
||
<p>监控这些指标可以帮助管理员轻松了解其集群中的应用程序接收的所有外部服务。</p></description><pubDate>Sat, 28 Sep 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/monitoring-external-service-traffic/</link><author>Neeraj Poddar (Aspen Mesh)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/monitoring-external-service-traffic/</guid><category>monitoring</category><category>blackhole</category><category>passthrough</category></item><item><title>适用于 Knative 的 Mixer 适配器</title><description>
|
||
<p>这篇文章演示了如何使用 <a href="/v1.12/zh/faq/mixer/">Mixer</a> 把应用逻辑放进 Istio。它描述了一个用简单的代码实现了 Knative scale-from-zero 逻辑的 Mixer 适配器,该适配器和原有实现的性能相差无几。</p>
|
||
<h2 id="Knative-serving">Knative Serving</h2>
|
||
<p><a href="https://knative.dev/docs/serving/">Knative Serving</a> 基于 <a href="https://kubernetes.io/">Kubernetes</a> 来支持 Serverless 应用的部署和服务(Serving)。一个 Serverless 平台的核心功能就是 scale-to-zero,该功能可减少非活动工作负载的资源使用量和成本。当空闲应用收到新请求时,需要一种新的机制来 scale-from-zero。</p>
|
||
<p>下图表示当前 Knative scale-from-zero 的架构。</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:76.29350893697084%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/knative-activator-adapter/knative-activator.png" title="Knative scale-from-zero">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/knative-activator-adapter/knative-activator.png" alt="Knative scale-from-zero" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Knative scale-from-zero</figcaption>
|
||
</figure>
|
||
<p>通过配置 Istio 中的 <code>VirtualServices</code> 和 <code>DestinationRules</code> 可以将空闲应用的流量重定向到 <strong>Activator</strong> 组件。当 <strong>Activator</strong> 接受新请求的是时候,它:</p>
|
||
<ol>
|
||
<li>缓存进来的请求</li>
|
||
<li>触发 <strong>Autoscaler</strong></li>
|
||
<li>在应用扩容了之后把请求重定向到该应用,包括重试和负载均衡(如果需要的话)</li>
|
||
</ol>
|
||
<p>一旦应用启动并再次运行,Knative 就会把请求路由到正在运行的应用上(之前请求是路由到 <strong>Activator</strong> 的)。</p>
|
||
<h2 id="mixer-adapter">Mixer 适配器</h2>
|
||
<p><a href="/v1.12/zh/faq/mixer/">Mixer</a> 在 Istio 组件和基础设施后端之间提供了一个丰富的中介层。它是独立于 <a href="https://www.envoyproxy.io/">Envoy</a> 的组件,并且具有简单的可扩展性模型,该扩展模型使 Istio 可以与大部分后端进行交互。Mixer 本质上比 Envoy 更容易扩展。</p>
|
||
<p>Mixer 是一个属性处理引擎,它使用面向操作员(operator-supplied)的配置通过可插拔(Pluggable)的适配器将 Istio 代理的请求属性映射到对基础设施后端系统的调用。适配器使 <strong>Mixer</strong> 暴露单个统一的 API,与使用中的基础设施后端无关。运行时使用的适配器是由操作员配置决定的,适配器可以轻松扩展以适应新的或定制的基础设施后端。</p>
|
||
<p>为了实现 Knative scale-from-zero,我们使用 Mixer <a href="https://github.com/istio/istio/wiki/Mixer-Out-Of-Process-Adapter-Dev-Guide">进程外适配器</a>来调用 Autoscaler。Mixer 的进程外适配器使开发人员可以使用任何编程语言,并以独立程序的形式构建和维护您的扩展程序,而无需构建 Istio 代理。</p>
|
||
<p>下图表示使用 <strong>Mixer</strong> 适配器的 Knative 设计。</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:76.29350893697084%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/knative-activator-adapter/knative-mixer-adapter.png" title="Knative scale-from-zero">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/knative-activator-adapter/knative-mixer-adapter.png" alt="Knative scale-from-zero" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Knative scale-from-zero</figcaption>
|
||
</figure>
|
||
<p>在这种设计中,无需像 Knative 原有的设置中那样为空闲应用程序更改到 <strong>Activator</strong> 的路由。当由 Istio 代理(Ingress 网关)收到对空闲应用程序的新请求时,它将通知 Mixer,包括所有相关的元数据信息。然后 Mixer 调用您的适配器,该适配器使用 Knative 原有的协议触发 Knative Autoscaler。</p>
|
||
<div>
|
||
<aside class="callout idea">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-idea"/></svg>
|
||
</div>
|
||
<div class="content">通过使用这种设计,您不需要处理缓存,重试和负载平衡的问题,因为 Istio 代理已经处理了这些问题。</div>
|
||
</aside>
|
||
</div>
|
||
<p>Istio 的 Mixer 适配器模式使得我们可以用更简单的方式实现原本复杂并且基于网络的应用逻辑,如 <a href="https://github.com/zachidan/istio-kactivator">Knative 适配器</a>中所示。</p>
|
||
<p>当适配器从 <strong>Mixer</strong> 接收到消息时,它会使用 Knative 协议直接向 <strong>Autoscaler</strong> 发送一个 <code>StatMessage</code>。Istio 代理将 <strong>Autoscaler</strong> 所需的元数据信息(<code>namespace</code> 和 <code>service name</code>)传输到 <strong>Mixer</strong>,再从那里传输到适配器。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>我将 Knative 原有的参考架构的冷启动(cold-start)时间与新的 Istio Mixer 适配器参考架构进行了比较。结果显示它们的冷启动时间很接近。使用 Mixer 适配器的实现更加简单。无需处理基于底层网络的机制,因为这些机制是由 Envoy 处理的。</p>
|
||
<p>下一步是把这个 Mixer 适配器放到一个特定的 Envoy(Envoy-Specific)过滤器中,该过滤器是在 Ingress 网关内运行。这将进一步改善响应时间(不再调用 <strong>Mixer</strong> 和适配器),并消除对 Istio Mixer 的依赖。</p></description><pubDate>Wed, 18 Sep 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/knative-activator-adapter/</link><author>Idan Zach (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/knative-activator-adapter/</guid><category>mixer</category><category>adapter</category><category>knative</category><category>scale-from-zero</category></item><item><title>APP 身份和访问适配器</title><description>
|
||
<p>如果在 Kubernetes 以容器化的方式运行应用,就可以使用 App 身份和访问适配器获得抽象级别的安全性,而无需更改代码或重新部署。</p>
|
||
<p>无论您的运行环境是单云提供商,还是多个云提供商的组合或者遵循混合云的方式,集中式身份管理都可以帮助您维护现有基础设施并避免被云供应商绑定。</p>
|
||
<p>有了 <a href="https://github.com/ibm-cloud-security/app-identity-and-access-adapter">App 身份和访问适配器</a>,就可以使用以下 OAuth2/OIDC 提供商:IBM Cloud App ID、Auth0、Okta、Ping Identity、AWS Cognito、Azure AD B2 等。身份和授权策略可以以高效的方式应用在所有环境(包括前端和后端应用程序),而无需修改代码或重新部署。</p>
|
||
<h2 id="understanding-Istio-and-the-adapter">了解 Istio 和其适配器</h2>
|
||
<p><a href="/v1.12/zh/docs/concepts/what-is-istio/">Istio</a> 是一个开源的服务网格,它对分布式应用来说是一个透明层,它可以和 Kubernetes 无缝集成。为了降低布署复杂性 Istio 提供了对整个服务网格的行为洞察和操作控制。详见 <a href="/v1.12/zh/docs/ops/deployment/architecture/">Istio 架构</a>。</p>
|
||
<p>Istio 使用 [Envoy sidecar 代理] 来调整服务网格中所有 Pod 的入站和出站流量。Istio 从 Envoy sidecar 中提取遥测数据,并将其发送到负责收集遥测数据和执行策略的 Istio 组件 Mixer。</p>
|
||
<p>APP 身份和访问适配器通过分析针对服务网格上各种访问控制策略的遥测数据(属性)扩展 Mixer 的功能。访问控制策略可以关联到具体的 Kubernetes 服务,并且可以微调到特定的服务端点。关于策略和遥测信息的详情请看 Istio 的文档。</p>
|
||
<p>当 <a href="https://github.com/ibm-cloud-security/app-identity-and-access-adapter">App 身份和访问适配器</a>结合到 Istio 中后,为多云架构提供可扩展的、集成身份和访问解决方案,而且不需要修改任何应用程序代码。</p>
|
||
<h2 id="installation">安装</h2>
|
||
<p>可以直接使用 <code>github.com</code> 仓库中的 Helm 来安装 APP 身份和访问适配器。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm repo add appidentityandaccessadapter https://raw.githubusercontent.com/ibm-cloud-security/app-identity-and-access-adapter/master/helm/appidentityandaccessadapter
|
||
$ helm install --name appidentityandaccessadapter appidentityandaccessadapter/appidentityandaccessadapter
|
||
</code></pre>
|
||
<p>另外,可以从 <code>github.com</code> 仓库 clone 下来,在本地用 Helm chart 进行安装。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ git clone git@github.com:ibm-cloud-security/app-identity-and-access-adapter.git
|
||
$ helm install ./helm/appidentityandaccessadapter --name appidentityandaccessadapter.
|
||
</code></pre>
|
||
<h2 id="protecting-web-applications">保护 web 应用程序</h2>
|
||
<p>Web 应用程序通常是由 OpenID Connect (OIDC) 工作流保护,也被叫做 <code>authorization_code</code>。当检测到未经认证或未经授权的用户时,它们会自动重定向到所选择的身份服务并展示认证页面。身份验证完成后,浏览器将重定向回适配器拦截的隐式 <code>/oidc/callback</code> 端点。此时,适配器从身份服务获取访问和身份令牌,然后将用户重定向回 Web 应用程序中最初请求的 URL。</p>
|
||
<p>身份状态和令牌是由适配器维护管理的。适配器处理的每个请求会包含访问和身份令牌的认证头,其格式是:<code>Authorization: Bearer &lt;access_token&gt; &lt;id_token&gt;</code>。</p>
|
||
<p>开发者可以根据读取令牌(token)信息调整应用程序的用户体验,比如显示用户名,根据用户角色适配用户界面等。</p>
|
||
<p>为了终止经过身份验证的会话并且清除令牌(即用户注销),只需将浏览器重定向到受保护服务下的 <code>/oidc/logout</code> 端点即可。例如,从 <code>https://example.com/myapp</code> 中将应用程序重定向到 <code>https://example.com/myapp/oidc/logout</code>。</p>
|
||
<p>无论何时访问令牌过期了,系统都会通过刷新令牌自动获取一个新的访问和身份令牌,而无需重新进行身份验证。如果已配置的身份认证提供商返回一个刷新令牌,适配器会将其持久保存,用于老令牌过期时,重新获取新的访问和身份令牌。</p>
|
||
<h3 id="applying-web-application-protection">应用 web 应用程序保护</h3>
|
||
<p>保护 web 应用程序需要创建 2 种类型的资源 - <code>OidcConfig</code> 资源用于定义各种 OIDC 服务提供商,<code>Policy</code> 资源用于定义 web 应用保护策略。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;security.cloud.ibm.com/v1&#34;
|
||
kind: OidcConfig
|
||
metadata:
|
||
name: my-oidc-provider-config
|
||
namespace: sample-namespace
|
||
spec:
|
||
discoveryUrl: &lt;discovery-url-from-oidc-provider&gt;
|
||
clientId: &lt;client-id-from-oidc-provider&gt;
|
||
clientSecretRef:
|
||
name: &lt;kubernetes-secret-name&gt;
|
||
key: &lt;kubernetes-secret-key&gt;
|
||
</code></pre>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;security.cloud.ibm.com/v1&#34;
|
||
kind: Policy
|
||
metadata:
|
||
name: my-sample-web-policy
|
||
namespace: sample-namespace
|
||
spec:
|
||
targets:
|
||
- serviceName: &lt;kubernetes-service-name-to-protect&gt;
|
||
paths:
|
||
- prefix: /webapp
|
||
method: ALL
|
||
policies:
|
||
- policyType: oidc
|
||
config: my-oidc-provider-config
|
||
rules: // optional
|
||
- claim: iss
|
||
match: ALL
|
||
source: access_token
|
||
values:
|
||
- &lt;expected-issuer-id&gt;
|
||
- claim: scope
|
||
match: ALL
|
||
source: access_token
|
||
values:
|
||
- openid
|
||
</code></pre>
|
||
<p><a href="https://github.com/ibm-cloud-security/app-identity-and-access-adapter">阅读更多关于如何保护 web 应用程序</a>。</p>
|
||
<h2 id="protecting-backend-application-and-APIs">保护后端应用程序和 API</h2>
|
||
<p>后端应用程序和 API 的保护是使用 Bearer Token 工作流,对特定的策略验证传入的令牌。Bearer Token 授权流程需要在请求中包含 <code>Authorization</code> 头,这个头以 JWT 格式包含了有效的访问令牌。需要的头结构是:<code>Authorization: Bearer {access_token}</code>。如果令牌验证成功请求会被发往被请求的服务。如果令牌验证失败会给客户端返回 HTTP 401 以及访问这个 API 所需要的权限列表。</p>
|
||
<h3 id="applying-backend-application-and-APIs-protection">应用后端程序和 API 保护</h3>
|
||
<p>保护后端程序和 API 需要创建 2 种类型的资源 - <code>JwtConfig</code> 用于定义各种 JWT 服务提供者,<code>Policy</code> 用于定义后端应用保护策略。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;security.cloud.ibm.com/v1&#34;
|
||
kind: JwtConfig
|
||
metadata:
|
||
name: my-jwt-config
|
||
namespace: sample-namespace
|
||
spec:
|
||
jwksUrl: &lt;the-jwks-url&gt;
|
||
</code></pre>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;security.cloud.ibm.com/v1&#34;
|
||
kind: Policy
|
||
metadata:
|
||
name: my-sample-backend-policy
|
||
namespace: sample-namespace
|
||
spec:
|
||
targets:
|
||
- serviceName: &lt;kubernetes-service-name-to-protect&gt;
|
||
paths:
|
||
- prefix: /api/files
|
||
method: ALL
|
||
policies:
|
||
- policyType: jwt
|
||
config: my-oidc-provider-config
|
||
rules: // optional
|
||
- claim: iss
|
||
match: ALL
|
||
source: access_token
|
||
values:
|
||
- &lt;expected-issuer-id&gt;
|
||
- claim: scope
|
||
match: ALL
|
||
source: access_token
|
||
values:
|
||
- files.read
|
||
- files.write
|
||
</code></pre>
|
||
<p><a href="https://github.com/ibm-cloud-security/app-identity-and-access-adapter">阅读更多如何保护后端应用程序</a>。</p>
|
||
<h2 id="known-limitations">已知的局限性</h2>
|
||
<p>在写这篇博客的时候,有 2 个关于 APP 身份和访问适配器的已知局限性问题:</p>
|
||
<ul>
|
||
<li><p>如果在 Web 应用程序上启用 APP 身份和访问适配器,只能创建 1 个适配器的副本。由于 Envoy 代理处理 HTTP 头的方式,Mixer 有可能给 Envoy 返回多个 <code>Set-Cookie</code> 头。因此,不能设置 Web 应用程序想要设置的所有 cookie。这个问题最近在 Envoy 和 Mixer 的开发上被讨论,计划在后期适配器的版本中解决。<strong>注意这个问题只影响 Web 应用程序,并不会以任何方式影响后端 APP 和 API</strong>。</p></li>
|
||
<li><p>作为一般最佳实践,集群内通信应该永远考虑使用双向 TLS 通信。现在 Mixer 与 APP 身份和访问适配器之间的通信通道并没有使用双端 TLS 通信。未来计划根据 <a href="https://github.com/istio/istio/wiki/Mixer-Out-of-Process-Adapter-Walkthrough#step-7-encrypt-connection-between-mixer-and-grpc-adapter">Mixer 适配器开发指引</a>实现解决这个问题。</p></li>
|
||
</ul>
|
||
<h2 id="summary">总结</h2>
|
||
<p>当多云部署实施时,随着环境的发展和多样性,安全也会变得复杂起来。当云提供商提供协议和工具来确保其产品的安全性,开发团队仍然要负责应用程序级别的安全,比如基于 OAuth2 的 API 访问控制,通过流量加密防御中间人攻击以及为服务访问控制提供双向 TLS。但是在多云环境中,这会变得复杂,因为可能要为分别为每个服务定义它的安全策略。有了适当的安全协议,这些外部和内部的威胁就可以减轻了。</p>
|
||
<p>开发团队花时间让服务能够移植到不同的云提供商,在同等情况下,安全应该更灵活而不依赖基础设施。</p>
|
||
<p>Istio 和 APP 身份和访问适配器可以加固 Kubernetes app 的安全性,并且无关编程语言和框架,不需要修改任何一行代码并重新部署。使用这种方式保证了 app 的最大可移植性,并且可以在多个环境中方便的去执行相同的安全策略。</p>
|
||
<p>可以在<a href="https://www.ibm.com/cloud/blog/using-istio-to-secure-your-multicloud-kubernetes-applications-with-zero-code-change">发布博客</a>上阅读更多关于 APP 身份和访问适配器的信息。</p></description><pubDate>Wed, 18 Sep 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/app-identity-and-access-adapter/</link><author>Anton Aleksandrov (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/app-identity-and-access-adapter/</guid><category>security</category><category>oidc</category><category>jwt</category><category>policies</category></item><item><title>Istio 1.3 Secret 服务发现的更改</title><description><p>在 Istio 1.3 中,我们正在利用 Kubernetes 的改进功能来更安全地为工作负载实例颁发证书。</p>
|
||
<p>当 Citadel 代理向 Citadel 发送证书签名请求以获取工作负载实例的证书时,它包含了 Kubernetes API 服务器颁发的代表工作负载实例的服务帐户的 JWT。如果 Citadel 可以对 JWT 进行身份验证,则提取为工作负载实例颁发证书所需的服务帐户名。</p>
|
||
<p>在 Kubernetes 1.12 之前,Kubernetes API 服务器的 JWT 存在以下问题:</p>
|
||
<ol>
|
||
<li>令牌没有重要字段来限制其使用范围,例如 <code>aud</code> 或 <code>exp</code>。有关更多信息,请参见<a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/auth/bound-service-account-tokens.md">绑定服务令牌</a>。</li>
|
||
<li>令牌安装在所有 Pod 上,无法退出。请参见<a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/svcacct-token-volume-source.md">服务帐户令牌数量</a>了解其机制。</li>
|
||
</ol>
|
||
<p>Kubernetes 1.12 引入了 <code>可信任</code> JWT 来解决这些问题。但是,直到 <a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.13.md">Kubernetes 1.13</a> 才支持 <code>aud</code> 字段与 API 服务器受众具有不同的值。为了更好地保护网格,Istio 1.3 仅支持 <code>可信任</code> JWT,并且在启用 SDS 时要求 <code>aud</code> 字段的值为 <code>istio-ca</code>。在启用 SDS 的情况下将 Istio 部署升级到 1.3 之前,请验证您是否使用了 Kubernetes 1.13 或更高版本。</p>
|
||
<p>根据您选择的平台进行以下考虑:</p>
|
||
<ul>
|
||
<li><strong>GKE:</strong> 至少将群集版本升级到 1.13。</li>
|
||
<li><strong>本地 Kubernetes</strong> 和 <strong>私有 GKE:</strong> 将<a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection">额外配置</a>添加到您的 Kubernetes。您也可以参考 <a href="https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/">API 服务页面</a>以获取最新的标志名称。</li>
|
||
<li>对于其他平台,请与您的提供商联系。如果您的提供商不支持可信任 JWT,则您将需要使用文件挂载的方式来传播 Istio 1.3 中的工作负载密钥和证书。</li>
|
||
</ul></description><pubDate>Tue, 10 Sep 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/trustworthy-jwt-sds/</link><author>Phillip Quy Le (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/trustworthy-jwt-sds/</guid><category>security</category><category>PKI</category><category>certificate</category><category>nodeagent</category><category>sds</category></item><item><title>Istio API 的演变</title><description>
|
||
<p>使团队能开发出最适合他们特定组织或者工作负载的抽象层,是 Istio 的一个主要目标,过去是,将来也是。Istio 为服务与服务之间网络通信提供了健壮有力的模块。从 <a href="/v1.12/zh/news/releases/0.x/announcing-0.1">Istio 0.1</a> 开始,Istio 小组一直在从生产用户那里了解他们如何将自己的架构、工作负载和约束映射到 Istio 的功能,并且一直在持续优化 Istio API 来让它们更好地为用户服务。</p>
|
||
<h2 id="evolving-Istio-APIs">Istio API 的演变</h2>
|
||
<p>Istio API 进化的下一步重心是在 Istio 用户的角色上。一个安全管理员应该能够与在逻辑上分组并且简化 Istio 网格中安全操作的 API 进行交互;服务操作人员和流量管理操作也是如此。</p>
|
||
<p>更进一步,使我们有机会为每个角色的初级、中级、高级用例提供改进的体验。有许多常见的用例,可以通过显而易见的默认的设置和一个需要极少配置甚至不需要配置的更好定义的初始体验来解决。对于中级用例,Istio 小组希望利用环境中的上下文提示来为你提供一个更简便的配置体验。最后,对于更高级的使用场景,我们的目标是<a href="https://www.quora.com/What-is-the-origin-of-the-phrase-make-the-easy-things-easy-and-the-hard-things-possible">让简单的事简单困难的事成为可能</a>。</p>
|
||
<p>为了提供这些以角色为中心的抽象,无论如何,在这些抽象之下的 API 必须要能够描述 Istio 的所有功能。从历史上看,Istio 的 API 设计遵循的路径与其他基础性平台的 API 相似。Istio 遵循下列设计原则:</p>
|
||
<ol>
|
||
<li>Istio API 应该寻求:
|
||
<ul>
|
||
<li>正确地表示他们映射到的基础资源</li>
|
||
<li>不应该隐藏任何基础资源的有用功能</li>
|
||
</ul></li>
|
||
<li>Istio API 也应该是<a href="https://en.wikipedia.org/wiki/Composability">可组合的</a>,因此终端用户能以适合其自身需求的方式组合基础 API。</li>
|
||
<li>Istio API 也应该是灵活的:在一个组织内部,应该有可能对基础资源有不同的表现形式,并且对每个团队都有意义。</li>
|
||
</ol>
|
||
<p>在接下来的几个版本中,我们将分享我们的进展,我们将加强 Istio API 与 Istio 用户角色之间的一致性。</p>
|
||
<h2 id="composability-and-abstractions">可组合性和抽象</h2>
|
||
<p>Istio 和 Kubernetes 经常一起使用,但 Istio 更像是 Kubernetes 的附加组件 – Kubernetes 更接近于一个平台。Istio 旨在提供基础架构,并在强大的服务网格中展现您所需的功能。例如,有一些使用 Kubernetes 作为基础的 platform-as-a-service 产品,并基于 Kubernetes 的可组合性向应用开发人员提供 API 的子集。</p>
|
||
<p>Kubernetes 可组合性的一个具体示例是部署应用时有一系列的对象需要配置。根据我们的统计,至少有 10 个对象需要被配置:<code>Namespace</code>、<code>Service</code>、<code>Ingress</code>、<code>Deployment</code>、<code>HorizontalPodAutoscaler</code>、<code>Secret</code>、<code>ConfigMap</code>、<code>RBAC</code>、<code>PodDisruptionBudget</code> 和 <code>NetworkPolicy</code>。</p>
|
||
<p>听起来很复杂,但不是每个人都要和这些概念打交道。不同的团队有不同的职责,比如集群、网络、或者安全管理团队,并且许多配置提供合理的默认值。云原生平台和部署工具的一个巨大的优势是可以利用少量的信息来为你配置这些对象以隐藏这种复杂性。</p>
|
||
<p>可以在 <a href="https://cloud.google.com/load-balancing/docs/https/">Google Cloud HTTP(S) Load Balancer</a> (GCLB) 找到网络空间可组合性的另一个例子。要正确使用 GCLB 的一个实例,需要创建和配置 6 个不同的基础对象。这样的设计是我们操作分布式系统 20 年经验的一个结果,并且<a href="https://www.youtube.com/watch?v=J5HJ1y6PeyE">为什么每一个对象和其他对象相互独立是有原因的</a>。但你通过 Google Cloud 控制台创建一个实例的步骤是被简化过的。我们提供越多的通用的面向终端用户/以角色为中心的配置,以后你们配置的通用设置越少。最终,基础 API 的目标是在不牺牲功能的情况下提供最大的灵活性。</p>
|
||
<p><a href="http://knative.dev">Knative</a> 是一个创建、运行并且操作无服务器工作负载的平台,它提供了一个以角色为中心的现实世界绝佳的示例,更高层次的 API。<a href="https://knative.dev/docs/serving/">Knative Serving</a>,Knative 的一个组件,基于 Kubernetes 和 Istio 服务于无服务器应用和功能,为应用开发人员管理服务的路由和修订提供了一个稳定的工作流。由于采用这种稳定的方式,Knative Serving 将 Istio 的 <a href="/v1.12/zh/docs/reference/config/networking/virtual-service/"><code>VirtualService</code></a> 和 <a href="/v1.12/zh/docs/reference/config/networking/destination-rule/"><code>DestinationRule</code></a> 资源,抽象成一个简化的支持修订和流量路由的<a href="https://github.com/knative/docs/blob/master/docs/serving/spec/knative-api-specification-1.0.md#route">路由</a>对象,将与应用开发人员最紧密相关的 Istio 网络 API 的一个子集暴露出来。</p>
|
||
<p>随着 Istio 的成熟,我们还看到生产用户在 Istio 的基础 API 之上开发了针对特定工作负载和组织的抽象层。</p>
|
||
<p>AutoTrader UK 提供了一个基于 Istio 定制平台的我们最喜欢的例子。在<a href="https://kubernetespodcast.com/episode/052-autotrader/">来自 Google 的 Kubernetes Podcast 的一个采访</a>中,Russel Warman 和 Karl Stoney 描述了他们基于 Kubernetes 的交付平台,和<a href="https://karlstoney.com/2018/07/07/managing-your-costs-on-kubernetes/">用 Prometheus 和 Grafana 搭建的成本 Dashboard</a>。他们毫不费力地添加了配置项使网络达到他们的开发人员希望配置成的样子,并且现在它管理着的 Istio 的对象让这一切成为可能。在企业和云原生公司中构建了无数其他的平台:一些旨在替换公司特定的自定义脚本的网络,而另一些旨在成为通用的公共工具。随着越来越多的公司开始公开谈论他们的工具,我们将把他们的故事带到此博客。</p>
|
||
<h2 id="what’s-coming-next">接下来会发生什么</h2>
|
||
<p>我们正在为即将发布的版本进行一些改进,其中包括:</p>
|
||
<ul>
|
||
<li>通过 Istio operator 安装配置文件用来设置 ingress 和 egress 标准模式</li>
|
||
<li>自动推断容器端口和遥测协议</li>
|
||
<li>默认情况下支持路由所有流量,以逐步限制路由</li>
|
||
<li>添加单个全局标志以启用双向 TLS 并加密所有 Pod 间通信</li>
|
||
</ul>
|
||
<p>噢,如果由于某种原因,你通过安装的 CRD 列表来判断工具箱,在 Istio 1.2 中我们将数字 54 减少到 23。为什么?事实证明,如果您有很多功能,则需要一种方法来配置所有功能。通过对安装程序的改进,您现在可以使用与适配器配合使用的<a href="/v1.12/zh/docs/setup/additional-setup/config-profiles/">配置</a>安装 Istio。</p>
|
||
<p>在所有的服务网格中,作为扩展,Istio 寻求将复杂的基础性操作自动化,比如网络和安全。这意味着总有些 API 是复杂的,但是 Istio 始终致力于解决操作者的需求,同时继续演变 API 以提供强大的构建块并通过以角色为中心的抽象来优先满足灵活性。</p>
|
||
<p>我们迫不及待地希望你加入我们的<a href="/v1.12/zh/get-involved/">社区</a>,看看你会使用 Istio 构建出什么美妙的产品!</p></description><pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/evolving-istios-apis/</link><author>Louis Ryan (Google), Sandeep Parikh (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/evolving-istios-apis/</guid><category>apis</category><category>composability</category><category>evolution</category></item><item><title>Istio 中安全管控出口流量,第三部分</title><description>
|
||
<p>欢迎来看在 Istio 对出口流量进行安全管控系列文章的第 3 部分。
|
||
在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-1/">这个系列文章的第一部分</a>,我提出了出口流量相关攻击和我们针对出口流量进行安全管控收集的要求点。
|
||
在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/">这个系列文章的第二部分</a>,我展示了 Istio 的对安全出口流量方案,并且展示了使用 Istio 如何来阻止攻击。</p>
|
||
<p>在这一期中,我对 Istio 出口流量安全管控方案和其它的方案进行了对比,比如使用 Kubernetes 网络策略和已有的出口代理和防火墙。最后我讲述了 Istio 中安全管控出口流量的性能因素。</p>
|
||
<h2 id="alternative-solutions-for-egress-traffic-control">出口流量管控的其它解决方案</h2>
|
||
<p>首先,我们回想一下我们之前收集的<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-1/#requirements-for-egress-traffic-control">出口流量管控要求</a>:</p>
|
||
<ol>
|
||
<li>用 <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">SNI</a> 或者用 <a href="/v1.12/zh/docs/reference/glossary/#tls-origination">TLS 源</a>来支持 <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS</a>。</li>
|
||
<li><strong>监控</strong> SNI 和每个出口访问的 workload 源。</li>
|
||
<li>定义和执行 <strong>每个集群的策略</strong>。</li>
|
||
<li>定义和执行 <strong>每个源的策略</strong>,Kubernetes 可感知。</li>
|
||
<li><strong>阻止篡改</strong>。</li>
|
||
<li>对应用程序来说流量管控是 <strong>透明的</strong>。</li>
|
||
</ol>
|
||
<p>接下来,将会介绍两种出口流量管控的备选方案:Kubernetes 网络策略和出口代理与防火墙。展示了上述要求中哪些是它们满足的,更重要的是那些要求是它们不能满足的。</p>
|
||
<p>Kubernetes 通过<a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">网络策略</a>提供了一个流量管控的原生方案,特别是对出口流量管控。使用这些网络策略,集群运维人员可以配置那个 pod 可以访问指定的外部服务。
|
||
集群运维人员可以通过 pod 标签、命名空间标签或者 IP 范围来识别 pod。集群运维人员可以使用 IP 范围来明确外部服务,但是不能使用像 <code>cnn.com</code> 这样的域名来指定外部服务。因为 <strong>Kubernetes 网络策略对 DNS 无感知</strong>。
|
||
网络策略可以满足第一个要求,因为它可以管控任何 TCP 流量。网络策略只能部分满足第三和第四点要求,因为集群运维人员可以针对每个集群或者每个 pod 制定策略,但是运维人员无法用域名来标示外部服务。
|
||
只有当攻击者无法从恶意容器进入 Kubernetes 节点并干扰该节点内策略的执行时,网络策略才满足第五个要求。
|
||
最近,网络策略满足了第六点要求:运维人员不需要修改代码或者容器环境。总之,我们能说 Kubernetes 网络策略提供了透明的、Kubernetes 可感知的出口流量管控,但不是 DNS 可感知的。</p>
|
||
<p>第二种是比 Kubernetes 早的备选方案。使用 <strong>DNS 可感知的出口代理或者防火墙</strong> 允许配置应用程序将流量定向到代理并使用某些代理协议,例如:<a href="https://en.wikipedia.org/wiki/SOCKS">SOCKS</a>。
|
||
因为运维人员必须配置应用程序,这个解决方案不是透明的。而且运维人员使用 pod 标签或者 pod 服务账号来配置代理,因为出口代理是不知道它们的。因此 <strong>出口网关不是 Kubernetes 可感知的</strong> 并且不能满足第四点要求,因为如果 Kubernetes 组件指定源,出口代理不能通过源执行策略。
|
||
总结一下,出口代理能满足第一、二、三和五的要求,但是不能满足第四和六的要求,因为它们不能对应用程序透明并且不能被 Kubernetes 感知。</p>
|
||
<h2 id="advantages-of-Istio-egress-traffic-control">Istio 出口流量管控的优势</h2>
|
||
<p>Istio 出口流量管控是 <strong>DNS 可感知的</strong>:你可以基于 URL 或者泛域名(像 <code>*.ibm.com</code>)来定义策略。从这个点上说,Istio 的方案比不能 DNS 感知的 Kubernetes 网络策略方案要好。</p>
|
||
<p>Istio 出口流量管控对 TLS 流量是 <strong>透明的</strong>,因为 Istio 是透明的:不需要改变应用程序或者配置容器。
|
||
对于有 TLS 源的 HTTP 流量,你必须配置网格中的应用程序配置使用 HTTP,不能使用 HTTPS。</p>
|
||
<p>Istio 出口流量管控是 <strong>Kubernetes 可感知的</strong>:出口流量源的身份是基于 Kubernetes 服务账号的。Istio 出口流量管控比现有的 DNS 感知的代理或者防火墙要好,因为它们都是不透明的,也不是 Kubernetes 可感知的。</p>
|
||
<p>Istio 出口流量管控是 <strong>安全的</strong>:它基于 Istio 的强身份认证,当使用<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#additional-security-considerations">附加安全措施</a>时,Istio 的流量管控具有防篡改功能。</p>
|
||
<p>另外,Istio 的出口流量管控提供了以下的优势:</p>
|
||
<ul>
|
||
<li>对入口、出口和集群内流量用同一种语言定义访问策略。对所有类型的流量只需要学习一种策略和配置语言。</li>
|
||
<li>集成了 Istio 策略的出口流量管控功能和可观测性适配器,开箱即用。</li>
|
||
<li>用于外部监控或者访问管控系统的 Istio 适配器只需要编写一次,就可以把他们应用在所有类型的流量上:入口,出口和集群内。</li>
|
||
<li>对出口流量使用 Istio <a href="/v1.12/zh/docs/concepts/traffic-management/">流量管理特性</a>:负载均衡,被动和主动的健康检查,熔断,超时,重试,故障注入等等。</li>
|
||
</ul>
|
||
<p>我们将具有上述优点的系统称为 <strong>Istio 可感知</strong>。</p>
|
||
<p>下表总结了 Istio 和备选方案提供的出口流量管控特性:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th></th>
|
||
<th>Istio 出口流量管控</th>
|
||
<th>Kubernetes 网络策略</th>
|
||
<th>现有出口代理或防火墙</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>DNS 可感知</td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#cancel"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Kubernetes 可感知</td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#cancel"/></svg></td>
|
||
</tr>
|
||
<tr>
|
||
<td>透明</td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#cancel"/></svg></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Istio 可感知</td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#checkmark"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#cancel"/></svg></td>
|
||
<td><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#cancel"/></svg></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="performance-considerations">性能因素</h2>
|
||
<p>使用 Istio 管控出口流量有一个代价:增加对外部服务调用的延时和集群 pod 的 CPU 使用率。
|
||
流量穿过了两层代理:</p>
|
||
<ul>
|
||
<li>应用程序的 sidecar 代理</li>
|
||
<li>出口网关的代理</li>
|
||
</ul>
|
||
<p>如果你使用<a href="/v1.12/zh/docs/tasks/traffic-management/egress/wildcard-egress-hosts/">泛域名 TLS 出口流量</a>,你必须在应用程序和外部服务之间增加<a href="/v1.12/zh/docs/tasks/traffic-management/egress/wildcard-egress-hosts/#wildcard-configuration-for-arbitrary-domains">附加代理</a>。因为出口网关代理和需要使用通配符配置任意域的代理之间的流量是在 pod 的本地网络,那部分流量不应该对延迟有显著影响。</p>
|
||
<p>请参阅为管控出口流量设置不同 Istio 配置的<a href="/v1.12/zh/blog/2019/egress-performance/">性能评估</a>。我鼓励你在决定是否能够承担你用例的性能开销之前,仔细评估你自己的应用程序和外部服务的不同配置。你应该权衡所需的安全级别与性能要求,并比较所有备选方案的性能开销。</p>
|
||
<p>让我来分享我对使用 Istio 管控出口流量后带来性能开销的想法:
|
||
访问外部服务已经有比较高的延时和增加的开销,由于集群内的 2 个或者 3 个代理很可能相比之下没有那么重要。
|
||
毕竟,采用微服务架构的应用程序可以在微服务之间有多次调用的链路。因此,在出口网关上增加 1 个或者 2 个代理不应该有很大的影响。</p>
|
||
<p>此外,我们继续在优化减少 Istio 的性能开销。
|
||
可能的优化措施包括:</p>
|
||
<ul>
|
||
<li>扩展 Envoy,让它来处理泛域名:这可以消除上面场景中应用程序和外部服务的代理。</li>
|
||
<li>如果流量已加密,那么就只使用双边 TLS 进行身份验证而不加密 TLS 流量。</li>
|
||
</ul>
|
||
<h2 id="summary">总结</h2>
|
||
<p>希望读完这个系列的文章,可以说服你认同,对于集群安全来说管控出口流量是非常重要的。
|
||
更希望,我可以说服你认同 Istio 对安全的管控出口流量是一个非常有用的工具,并且 Istio 比其它备选方案有很多优势。
|
||
Istio 是我所知的唯一解决方案,它可以让你:</p>
|
||
<ul>
|
||
<li>以安全和透明的方式管控出口流量</li>
|
||
<li>用域名明确外部服务</li>
|
||
<li>使用 Kubernetes 组件来明确流量源</li>
|
||
</ul>
|
||
<p>以我之见,如果你在寻找你的第一个 Istio 应用场景,安全管控出口流量是一个非常好的选择。在这个场景中,Istio 甚至在你使用它所有其它功能之前就已经为你提供了一些优势:
|
||
<a href="/v1.12/zh/docs/tasks/traffic-management/">流量管理</a>,<a href="/v1.12/zh/docs/tasks/security/">安全性</a>,<a href="/v1.12/zh/docs/tasks/policy-enforcement/">策略</a>和<a href="/v1.12/zh/docs/tasks/observability/">可观测性</a>,上面的功能都可以用在在集群内的微服务之间的流量上。</p>
|
||
<p>所以,如果你还没有机会使用 Istio,那就在你集群上<a href="/v1.12/zh/docs/setup/install/">安装 Istio</a> 并且检查<a href="/v1.12/zh/docs/tasks/traffic-management/egress/">出口流量管控任务</a>再执行其它 <a href="/v1.12/zh/docs/tasks/">Istio 特性</a>的任务。我们也想收到你的反馈,请在 <a href="https://discuss.istio.io">discuss.istio.io</a> 加入我们。</p></description><pubDate>Mon, 22 Jul 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-3/</link><author>Vadim Eisenberg (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-3/</guid><category>traffic-management</category><category>egress</category><category>security</category><category>gateway</category><category>tls</category></item><item><title>Istio 中的安全管控出口流量,第二部分</title><description>
|
||
<p>欢迎来看 Istio 对出口流量进行安全管控系列文章的第 2 部分。
|
||
在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-1/">这个系列文章的第一部分</a>, 我提出了出口流量相关攻击和针对出口流量进行安全管控我们收集的要求点。
|
||
在这一期中,我会讲述对出口流量进行安全管控的 Istio 方式,并且展示 Istio 如何帮你阻止攻击。</p>
|
||
<h2 id="secure-control-of-egress-traffic-in-Istio">Istio 中的出口流量安全管控</h2>
|
||
<p>为了在 Istio 中实施出口流量的安全管控,你必须<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#egress-gateway-for-https-traffic">通过出口网关将 TLS 流量发送到外部服务</a>。
|
||
或者可以<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#egress-gateway-for-http-traffic">通过出口网关发送 HTTP 流量</a>,并且<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/#perform-TLS-origination-with-an-egress-gateway">让出口网关来发起执行 TLS</a>。</p>
|
||
<p>两种选择各有利弊,你应该根据你的具体场景进行选择。选择的关键取决于你的应用程序是否能发送不加密的 HTTP 请求和你团队的安全策略是否允许发送不加密的 HTTP 请求。
|
||
例如,如果你的应用程序使用了某些客户端库,用这些库来对流量进行加密,但是它无法取消加密,你就不能使用发送不加密 HTTP 流量的选项。万一你团队的安全策略无法让你<strong>在 pod 内</strong>发送不加密的 HTTP 请求也是一样的(pod 外的流量由 Istio 来加密)。</p>
|
||
<p>如果应用程序发送 HTTP 请求,并且由出口网关发起执行 TLS,你就可以监控 HTTP 信息,像 HTTP 方法、HTTP 头和 URL 路径。也可以根据上面说的 HTTP 信息来<a href="/v1.12/zh/blog/2018/egress-monitoring-access-control">定义策略</a>。如果是由应用程序发起执行 TLS,你就可以对源 pod 的 TLS 流量的 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress_sni_monitoring_and_policies/">SNI 和服务账号进行监控</a>,并且基于 SNI 和服务账号定义策略。</p>
|
||
<p>你必须确保你集群到外部的流量不能绕过出口网关。Istio 不能给你确保这一点,所以你必需使用一些<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#additional-security-considerations">附加的安全机制</a>,比如 <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">Kubernetes 网络策略</a>或者 L3 防火墙。看一个 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#apply-Kubernetes-network-policies">Kubernetes 网络策略配置</a>的例子。
|
||
根据<a href="https://en.wikipedia.org/wiki/Defense_in_depth_(computing)">纵深防御</a>的概念,为同一个目标使用的安全机制越多越安全。</p>
|
||
<p>你也必需也要确保 Istio 控制平面和出口网关不能被破坏。你的集群里面可能有成百上千的应用程序 pod,而只有十几个 Istio 控制平面 pod 和网关。
|
||
你可以也应该聚焦在保护控制平面 pod 和网关,因为这比较容易(需要保护的 pod 数量很少),并且这对集群的安全性是最关键的。
|
||
如果攻击者破坏了控制平面和出口网关,他们可以违反任何策略。</p>
|
||
<p>根据环境的不同,你可能有多种工具来保护控制平面 pod。合理的安全策略如下:</p>
|
||
<ul>
|
||
<li>把运行控制平面 pod 的节点和应用程序节点隔离开。</li>
|
||
<li>把控制平面的 pod 运行在它们自己独立的命名空间中。</li>
|
||
<li>启用 Kubernetes 的 RBAC 和网络策略来保护控制平面的 pod。</li>
|
||
<li>监控控制平面 pod 要比监控应用程序 pod 更紧密。</li>
|
||
</ul>
|
||
<p>一旦你通过出口网关引导了出口流量,并且应用了附加的安全机制,就可以进行安全的监控和施加对流量的安全策略。</p>
|
||
<p>下图展示了 Istio 的安全架构,用 L3 防火墙进行了加强,L3 防火墙就是<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#additional-security-considerations">附加安全机制</a>的一部分,它应该在 Istio 的外面。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:54.89557965057057%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/SecurityArchitectureWithL3Firewalls.svg" title="带有出口网关和 L3 防火钱的 Istio 安全架构">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/SecurityArchitectureWithL3Firewalls.svg" alt="带有出口网关和 L3 防火钱的 Istio 安全架构" />
|
||
</a>
|
||
</div>
|
||
<figcaption>带有出口网关和 L3 防火钱的 Istio 安全架构</figcaption>
|
||
</figure>
|
||
<p>可以简单的配置 L3 防火墙,使它只允许通过 Istio 入口网关来的流量,并且只允许通过 Istio 出口网关出去的流量。网关的 Istio 代理执行策略,并且和在网格中其它所有代理一样上报检测信息。</p>
|
||
<p>现在我们来测试一下可能的攻击,并且我会给你们展示 Istio 中的出口流量安全管控是怎么阻止攻击的。</p>
|
||
<h2 id="preventing-possible-attacks">阻止可能的攻击</h2>
|
||
<p>参考以下出口流量的安全策略:</p>
|
||
<ul>
|
||
<li>允许应用程序 <strong>A</strong> 访问 <code>*.ibm.com</code>,这包含了所有外部服务中匹配 <code>*.ibm.com</code> 的 URL。</li>
|
||
<li>允许应用程序 <strong>B</strong> 访问 <code>mongo1.composedb.com</code>。</li>
|
||
<li>监控所有的出口流量。</li>
|
||
</ul>
|
||
<p>假设攻击者有以下目标:</p>
|
||
<ul>
|
||
<li>从你的集群中访问 <code>*.ibm.com</code>。</li>
|
||
<li>从你的集群中访问 <code>*.ibm.com</code>,并且不被监控到。攻击者不想他的流量被监控到,如果被监控到你将会发觉这个禁止的访问。</li>
|
||
<li>从你的集群中访问 <code>mongo1.composedb.com</code>。</li>
|
||
</ul>
|
||
<p>现在假设攻击者设法在攻破应用程序 <strong>A</strong> 的其中一个 pod,并且试图使用这个被攻破的 pod 来执行被禁止的访问。攻击者可能试试运气直接访问外部服务。你会对这个直接的尝试做出如下反应:</p>
|
||
<ul>
|
||
<li>最开始,是没有办法阻止被攻破的 应用程序 <strong>A</strong> 去访问 <code>*.ibm.com</code>,因为被攻破的 pod 很难和原来的 pod 区分开。</li>
|
||
<li>幸运的是,你可以监控所有对外部服务的访问,检测可疑流量,并且阻止攻击者获得对 <code>*.ibm.com</code> 的无监控访问。例如,你可以用异常检测工具检测出口流量的日志。</li>
|
||
<li>阻止攻击者从集群中访问 <code>mongo1.composedb.com</code>,Istio 会正确的检测流量的源,如这个例子中应用程序 <strong>A</strong>,根据上面提到的安全策略验证它是不是被允许访问 <code>mongo1.composedb.com</code>。</li>
|
||
</ul>
|
||
<p>直接攻击失败的话,恶意攻击者可能会使用高级攻击方式:</p>
|
||
<ul>
|
||
<li><strong>绕过容器的 sidecar 代理</strong> 就可能直接访问任何外部服务,而且没有了 sidecar 的策略执行和上报。这种攻击可以通过 Kubernetes 网络策略或者 L3 防火墙来阻止,因为它们可以让出网格的流量只通过出口网关。</li>
|
||
<li><strong>破坏出口网关</strong> 就可以强制它发送假信息给监控系统或禁止执行安全策略。这种攻击可以通过在出口网关 pod 上应用特殊的安全策略。</li>
|
||
<li><strong>冒充应用程序 B</strong>,因为允许应用程序 <strong>B</strong> 访问 <code>mongo1.composedb.com</code>。幸运的是,这种攻击可以用 Istio 的<a href="/v1.12/zh/docs/concepts/security/#istio-identity">强身份认证支持</a>来阻止。</li>
|
||
</ul>
|
||
<p>据我们所见,所有禁止的访问都可以阻止,或者至少可以监控到,在以后可以被阻止。
|
||
如果看到当前设计中涉及出口流量或安全漏洞的其它攻击,我们将很高兴<a href="https://discus.istio.io">听到它</a>。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>希望我能说服你:Istio 在阻止相关出口流量攻击上是一个非常高效的工具。在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-3/">这个系列文章的下一部分</a>,我对 Istio 出口流量安全管控方案和其它的方案进行了对比,比如 <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">Kubernetes 网络策略</a>和已有的出口代理/防火墙。</p></description><pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/</link><author>Vadim Eisenberg (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/</guid><category>traffic-management</category><category>egress</category><category>security</category><category>gateway</category><category>tls</category></item><item><title>最佳实践:Service Mesh 基准性能测试</title><description>
|
||
<p>服务网格为应用部署增加了很多功能,包括<a href="/v1.12/zh/docs/concepts/what-is-istio/#traffic-management">流量策略</a>、<a href="/v1.12/zh/docs/concepts/what-is-istio/#observability">可观察性</a>和<a href="/v1.12/zh/docs/concepts/what-is-istio/#security">安全通信</a>。但是,无论是时间(增加的延迟)还是资源(CPU 周期),向环境中添加服务网格都是有代价的。要就服务网格是否适合您的情况做出明智的决定,评估应用与服务网格一起部署时的性能非常重要。</p>
|
||
<p>今年早些时候,我们发布了关于 Istio 1.1 性能改进的<a href="/v1.12/zh/blog/2019/istio1.1_perf/">博客</a>。在发布 <a href="/v1.12/zh/news/releases/1.2.x/announcing-1.2">Istio 1.2</a> 之后,我们希望提供指导和工具,以帮助您在可用于生产的 Kubernetes 环境中对 Istio 的数据平面性能进行基准测试。</p>
|
||
<p>总体而言,我们发现 Istio <a href="/v1.12/zh/docs/ops/deployment/architecture/#envoy">sidecar 代理</a>的延迟取决于并发连接数。以每秒 1000 个请求(RPS)的速度,通过 16 个连接,Istio 延迟在 50% 时增加 <strong>3 毫秒</strong>,在 99% 时增加 <strong>10 毫秒</strong>。</p>
|
||
<p>在 <a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark">Istio Tools 仓库</a>中,您将找到用于测量 Istio 数据平面性能的脚本和说明,以及有关如何使用另一服务网格实现 <a href="https://linkerd.io">Linkerd</a> 运行脚本的其他说明。在我们详细介绍性能测试框架的每个步骤的一些最佳实践时,请<a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark#setup">遵循</a>。</p>
|
||
<h2 id="1-use-a-production-ready-Istio-installation">1. 使用生产就绪的 Istio 安装</h2>
|
||
<p>为了准确地大规模度量服务网格的性能,使用<a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/istio-install#istio-setup">适当大小的</a> Kubernetes 集群很重要。我们使用三个工作节点进行测试,每个工作节点至少具有 4 vCPU 和 15 GB 的内存。</p>
|
||
<p>然后,在该群集上使用可用于生产的 Istio <strong>安装配置文件</strong> 很重要。这使我们能够实现面向性能的设置,例如控制平面 pod 自动伸缩,并确保资源限制适用于繁重的流量负荷。<a href="/v1.12/zh/docs/setup/install/helm/#安装步骤">默认</a> Istio 安装适用于大多数基准测试用例。为了进行广泛的性能基准测试,并提供数千种注入代理的服务,我们还提供了<a href="https://github.com/istio/tools/blob/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/istio-install/values.yaml">调整后的 Istio 安装</a>,可为 Istio 控制平面分配额外的内存和 CPU。</p>
|
||
<p><svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#exclamation-mark"/></svg> Istio 的 <a href="/v1.12/zh/docs/setup/getting-started/">demo 安装</a>不适合进行性能测试,因为它被设计为部署在小型试用群集中,并且具有完整的跟踪和访问日志,可显示 Istio 的功能。</p>
|
||
<h2 id="2-focus-on-the-data-plane">2. 专注于数据平面</h2>
|
||
<p>我们的基准测试脚本专注于评估 Istio 数据平面:<span class="term" data-title="Envoy" data-body="&lt;p&gt;Envoy 是在 Istio 里使用的高性能代理,用于为所有&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;服务网格&lt;/a&gt;里的&lt;a href=&#34;/zh/docs/reference/glossary/#service&#34;&gt;服务&lt;/a&gt;调度进出的流量。
|
||
&lt;a href=&#34;https://envoyproxy.github.io/envoy/&#34;&gt;了解更多关于 Envoy&lt;/a&gt;。&lt;/p&gt;
|
||
">Envoy</span> 代理,可在应用容器之间进行流量调度。为什么要关注数据平面?因为在大规模使用大量应用容器时,数据平面的 <strong>内存</strong> 和 <strong>CPU</strong> 使用率很快就会超过 Istio 控制平面。让我们看一个具体的例子:</p>
|
||
<p>假设您运行了 2,000 个注入 Envoy 的 pod,每个 pod 每秒处理 1,000 个请求。每个代理使用 50 MB 的内存,并且要配置所有这些代理,Pilot 使用 1 vCPU 和 1.5 GB 的内存。所有的资源中,Istio 数据平面(所有 Envoy 代理的总和)使用了 100 GB 的内存,而 Pilot 只使用了 1.5 GB。</p>
|
||
<p>考虑到 <strong>延迟</strong>,关注数据平面性能也很重要。这是因为大多数应用的请求会通过 Istio 数据平面,而不是通过控制平面。但是,有两个例外:</p>
|
||
<ol>
|
||
<li><strong>遥测报告:</strong> 每个代理将原始遥测数据发送到 <span class="term" data-title="Mixer" data-body="&lt;p&gt;Mixer 是 Istio 里的一个组件,它负责增强&lt;a href=&#34;/zh/docs/reference/glossary/#service-mesh&#34;&gt;服务网格&lt;/a&gt;里的访问控制和使用策略。它还负责收集来自 &lt;a href=&#34;/zh/docs/reference/glossary/#envoy&#34;&gt;envoy&lt;/a&gt; 和其他服务的遥测数据。
|
||
&lt;a href=&#34;/zh/docs/reference/config/policy-and-telemetry&#34;&gt;了解更多关于 Mixer&lt;/a&gt;。&lt;/p&gt;
|
||
">Mixer</span>,Mixer 将其处理为度量,跟踪和其他遥测。原始遥测数据类似于访问日志,因此要付出一定的代价。访问日志处理会消耗 CPU,并使工作线程无法处理下一个工作单元。在更高的吞吐量场景下,下一个工作单元更有可能在队列中等待被工作者接走。这可能导致 Envoy 的长尾延迟(99%)。</li>
|
||
<li><strong>自定义策略检查:</strong> 当使用<a href="/v1.12/zh/docs/concepts/observability/">自定义 Istio 策略适配器</a>时,策略检查位于请求路径上。这意味着数据路径上的请求 header 和 metadata 将被发送到控制平面(Mixer),从而导致更高的请求延迟。<strong>注意:</strong> 这些策略检查<a href="/v1.12/zh/docs/reference/config/installation-options/#global-options">默认情况下处于禁用状态</a>,因为最常见的策略用例(<a href="/v1.12/zh/docs/reference/config/security/istio.rbac.v1alpha1">RBAC</a>)完全由 Envoy 代理执行。</li>
|
||
</ol>
|
||
<p>当 <a href="https://docs.google.com/document/d/1QKmtem5jU_2F3Lh5SqLp0IuPb80_70J7aJEYu4_gS-s">Mixer V2</a> 将所有策略和遥测功能直接移到代理中时,这两个例外都会在将来的 Istio 版本中消失。</p>
|
||
<p>接下来,在大规模测试 Istio 的数据平面性能时,不仅要以每秒递增的请求进行测试,而且还要以越来越多的 <strong>并发</strong> 连接进行测试,这一点很重要。这是因为现实世界中的高吞吐量流量来自多个客户端。我们<a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark#run-performance-tests">提供了脚本</a>允许您以递增的 RPS 对任意数量的并发连接执行相同的负载测试。</p>
|
||
<p>最后,我们的测试环境可以测量两个 pod 之间少量的请求。客户端 pod 是 <a href="http://fortio.org/">Fortio</a>,它将流量发送到服务端 pod。</p>
|
||
<p>为什么只用两个 pod 测试?因为增加吞吐量(RPS)和连接(线程)对 Envoy 的性能的影响比增加服务注册表的总大小(或 Kubernetes 集群中 Pod 和服务的总数)更大。当服务注册表的大小增加时,Envoy 必须跟踪更多的端点,并且每个请求的查找时间确实增加了,但是增加了一个很小的常数。如果您有许多服务,并且此常数成为延迟问题,则 Istio 提供 <a href="/v1.12/zh/docs/reference/config/networking/sidecar/">Sidecar 资源</a>,它使您可以限制每个 Envoy 知道的服务。</p>
|
||
<h2 id="3-measure-with-and-without-proxies">3. 有/无 度量的代理</h2>
|
||
<p>尽管 Istio 的许多特性,例如<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS 身份验证</a>,都依赖于应用 pod 的 Envoy 代理,但是您可以<a href="/v1.12/zh/docs/setup/additional-setup/sidecar-injection/#disabling-or-updating-the-webhook">选择性地禁用</a>一些网格服务的 sidecar 代理注入。在扩展 Istio 以进行生产时,您可能需要将 sidecar 代理增量添加到工作负载中。</p>
|
||
<p>为此,测试脚本提供了<a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark#run-performance-tests">三种不同模式</a>。当请求同时通过客户端和服务器代理(<code>both</code>)、仅通过服务器代理(<code>serveronly</code>)和都不通过代理(<code>baseline</code>)时,这些模式将分析 Istio 的性能。</p>
|
||
<p>您还可以在性能测试期间禁用 <a href="/v1.12/zh/docs/concepts/observability/">Mixer</a> 以停止 Istio 的遥测,这将得到与 Mixer V2 工作完成时我们期望的性能相符的结果。Istio 还支持 <a href="https://github.com/istio/istio/wiki/Envoy-native-telemetry">Envoy 本地遥测</a>,其功能类似于禁用 Istio 的遥测。</p>
|
||
<h2 id="Istio-1-2-performance">Istio 1.2 性能</h2>
|
||
<p>让我们看看如何使用该测试环境来分析 Istio 1.2 数据平面的性能。我们还提供了运行 <a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark/linkerd">Linkerd 数据平面的相同性能测试</a>的说明。Linkerd 目前仅支持延迟基准测试。</p>
|
||
<p>为了衡量 Istio sidecar 的代理延迟,我们考虑在 50%、90% 和 99% 时不断增加并发连接数量,从而保持了请求吞吐量(RPS)不变。</p>
|
||
<p>我们发现,通过 16 个并发连接和 1000 RPS,当请求同时通过客户端和服务器代理传输时,Istio 会在基线(P50)上增加 <strong>3ms</strong>。(从绿色线 <code>both</code> 中减去粉红色线 <code>base</code>)在 64 个并发连接上,Istio 在基线上增加了 <strong>12ms</strong>,但是禁用 Mixer(<code>nomixer_both</code>)后,Istio 仅增加了 <strong>7ms</strong>。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/performance-best-practices/latency_p50.png" title="Istio sidecar 代理, 50% 时的延迟">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/performance-best-practices/latency_p50.png" alt="Istio sidecar 代理, 50% 时的延迟" />
|
||
</a>
|
||
</div>
|
||
<figcaption></figcaption>
|
||
</figure>
|
||
<p>在 90% 时,有 16 个并发连接,Istio 增加 <strong>6ms</strong>;在 64 个连接的情况下,Istio 增加了 <strong>20ms</strong>。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/performance-best-practices/latency_p90.png" title="Istio sidecar 代理, 90% 时的延迟">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/performance-best-practices/latency_p90.png" alt="Istio sidecar 代理, 90% 时的延迟" />
|
||
</a>
|
||
</div>
|
||
<figcaption></figcaption>
|
||
</figure>
|
||
<p>最后,在具有 16 个连接的 99% 时,Istio 在基线之上增加了 <strong>10ms</strong>。在 64 个连接处,Istio 使用 Mixer 增加 <strong>25ms</strong>,不使用 Mixer 则增加 <strong>10ms</strong>。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/performance-best-practices/latency_p99.png" title="Istio sidecar 代理, 99% 时的延迟">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/performance-best-practices/latency_p99.png" alt="Istio sidecar 代理, 99% 时的延迟" />
|
||
</a>
|
||
</div>
|
||
<figcaption></figcaption>
|
||
</figure>
|
||
<p>对于 CPU 使用率,我们以不断增加的请求吞吐量(RPS)和恒定数量的并发连接进行了测量。我们发现启用了 Mixer 的 Envoy 在 3000 RPS 时的最大 CPU 使用率是 <strong>1.2 vCPU</strong>。在 1000 RPS 时,一个 Envoy 大约使用了 50% 的 CPU。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/performance-best-practices/cpu_max.png" title="Istio sidecar 代理,最大 CPU 使用率">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/performance-best-practices/cpu_max.png" alt="Istio sidecar 代理,最大 CPU 使用率" />
|
||
</a>
|
||
</div>
|
||
<figcaption></figcaption>
|
||
</figure>
|
||
<h2 id="summary">总结</h2>
|
||
<p>在对 Istio 的性能进行基准测试的过程中,我们吸取了一些重要的经验教训:</p>
|
||
<ul>
|
||
<li>使用模仿生产的环境。</li>
|
||
<li>专注于数据平面流量。</li>
|
||
<li>基于基准进行测量。</li>
|
||
<li>增加并发连接以及总吞吐量。</li>
|
||
</ul>
|
||
<p>对于在 16 个连接上具有 1000 RPS 的网格,Istio 1.2 仅在 50% 的基础上增加了 <strong>3 毫秒</strong> 的基准延迟。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">Istio 的性能取决于您的具体设置和流量负载情况。由于存在这种差异,请确保您的测试设置能够准确反映您的生产工作负载。要试用基准测试脚本,请转到 <a href="https://github.com/istio/tools/tree/3ac7ab40db8a0d595b71f47b8ba246763ecd6213/perf/benchmark">Istio Tools 库</a>。</div>
|
||
</aside>
|
||
</div>
|
||
<p>另外,请查阅 <a href="/v1.12/zh/docs/ops/deployment/performance-and-scalability">Istio 性能和可伸缩性指南</a>获取最新的性能数据。感谢您的阅读,祝您基准测试愉快!</p></description><pubDate>Tue, 09 Jul 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/performance-best-practices/</link><author>Megan O'Keefe (Google), John Howard (Google), Mandar Jog (Google)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/performance-best-practices/</guid><category>performance</category><category>scalability</category><category>scale</category><category>benchmarks</category></item><item><title>延长 Istio 自签名根证书的有效期</title><description><p>Istio 自签名证书的默认有效期为 1 年。如果您正在使用 Istio 自签名证书,您需要在到期前安排定期根转换。根证书到期可能会导致整个群集意外中断。此问题会影响使用 1.0.7 和 1.1.7 以下版本创建的新集群。</p>
|
||
<p>有关如何判断证书年龄和如何执行轮换的信息,请参见<a href="https://istio.io/v1.7/docs/ops/configuration/security/root-transition/">延长 Istio 自签名证书的有效期</a>。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">我们强烈建议您每年轮换根密钥和根证书作为最佳安全实践。我们将尽快发出有关根密钥/证书轮换的说明。</div>
|
||
</aside>
|
||
</div></description><pubDate>Fri, 07 Jun 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/root-transition/</link><author>Oliver Liu</author><guid isPermaLink="true">/v1.12/zh/blog/2019/root-transition/</guid><category>security</category><category>PKI</category><category>certificate</category><category>Citadel</category></item><item><title>Istio 中的安全管控出口流量,第一部分</title><description>
|
||
<p>这是我计划发布的关于 Istio 中出口流量安全管控系列文章中的第一部分。在这一期,会阐述为什么集群需要应用出口流量管控,要防止的出口流量相关的攻击有哪些,以及出口流量管控系统的要求有哪些。
|
||
一旦同意集群的出口流量应该被管控,那么就会出现下面的问题:出口流量安全管控系统需要什么?针对这些要求的最佳解决方案是什么?(捣乱分子:以我之见 Istio 是最佳解决方案)
|
||
下一期将阐述 <a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/">Istio 中实现出口流量的安全管控</a>,并和其它方案进行对比。</p>
|
||
<p>对于服务网格来说入口流量才是最重要的安全问题。一定要防止入侵者通过入口 API 渗透集群。既然这么说,流出服务网格的安全同样非常重要。一旦集群被攻破,你必须要有预案,尽可能的减少损害,并且要阻止攻击者使用集群对集群外的服务和已有系统进行进一步攻击。要达到这么目标,需要出口流量的安全管控。</p>
|
||
<p>合规要求是要实施出口流量安全管控的另外一个原因。例如,<a href="https://www.pcisecuritystandards.org/pci_security/">支付卡行业 (PCI) 数据安全标准</a>进出流量都必须限制在必要的范围之内:</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content"><em>1.2.1 将入口和出口流量限制为持卡人数据环境所必需的流量,并明确拒绝所有其他流量。</em></div>
|
||
</aside>
|
||
</div>
|
||
<p>特别是对出口流量:</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content"><em>1.3.4 不允许持卡人数据环境没有授权的出站流量进入互联网。持卡人数据环境流出的所有流量应该做评估,以保证流量符合既定的授权规则。应该检查链接上的流量并限制只允许认证过的通信(例如:通过限制源/目的的地址/端口,包括限制传输内容)。</em></div>
|
||
</aside>
|
||
</div>
|
||
<p>我们从涉及出口流量的攻击开始。</p>
|
||
<h2 id="the-attacks">流量攻击</h2>
|
||
<p>在还没有被攻击的时候 IT 部门就必须要假设会被攻击,并且它的部分基础设施可能已经损坏或者未来会出现损坏。一旦攻击者能渗透集群中的应用程序,他们就可以继续攻击外部服务了:已有系统,外部 web 服务和数据库。攻击者可能想偷取应用程序的数据并且发送到他们的外部服务上。攻击者的恶意程序会访问攻击者的服务器来下载更新。攻击者可能使用集群中的 pod 执行 DDOS 攻击或者闯入外部系统。即便您<a href="https://en.wikipedia.org/wiki/There_are_known_knowns">不知道</a>攻击的所有可能类型,你还是想减少任何攻击的可能性,无论是已知还是未知的攻击。</p>
|
||
<p>外部攻击者通过应用程序的缺陷从服务网格外部访问到应用程序的容器进行攻击,但是攻击者同样也可能来自内部,比如:组织内部的恶意 DevOps 人员。</p>
|
||
<p>为了防止以上所说的攻击,必须应用一些出口流量管控策略。我们在下一节介绍出口流量管控。</p>
|
||
<h2 id="the-solution-secure-control-of-egress-traffic">出口流量安全管控解决方案</h2>
|
||
<p>出口流量安全管控的意思是监控出口流量并且针对出口流量应用所有的安全策略。
|
||
监控出口流量,可以对它进行分析(可能是离线的),即便你无法实时阻止攻击,也要检测攻击事件。
|
||
另外一个减少攻击可能性的方法是遵循<a href="https://en.wikipedia.org/wiki/Need_to_know#In_computer_technology]">需要知道</a>的原则进行指定限制访问策略。</p>
|
||
<p>现在来看看已经收集到的出口流量管控要求。</p>
|
||
<h2 id="requirements-for-egress-traffic-control">出口流量管控要求</h2>
|
||
<p>我的同事(在 IBM)和我从一些客户那里收集了一些出口流量安全管控的要求,并把它们和 <a href="https://docs.google.com/document/d/1-Cq_Y-yuyNklvdnaZF9Qngl3xe0NnArT7Xt_Wno9beg">Kubernetes 网络特定兴趣小组的出口流量管控要求</a>做了整合。</p>
|
||
<p>Istio 1.1 满足所有的收集要求:</p>
|
||
<ol>
|
||
<li><p>使用 <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">SNI</a> 支持 <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS</a> 或者用 Istio 支持 <a href="/v1.12/zh/docs/reference/glossary/#tls-origination">TLS 源</a></p></li>
|
||
<li><p><strong>监视器</strong> SNI 和每个出口访问的源 workload。</p></li>
|
||
<li><p>定义和执行 <strong>每个集群的策略</strong>,比如:</p>
|
||
<ul>
|
||
<li><p>集群中所有应用程序可能访问 <code>service1.foo.com</code> (指定的主机)</p></li>
|
||
<li><p>集群中所有的应用程序可能访问 <code>*.bar.com</code> (泛域名) 下的任何主机</p></li>
|
||
</ul>
|
||
<p>必须阻止所有未明确的访问。</p></li>
|
||
<li><p>定义和执行<strong>每个源的策略</strong>,_Kubernetes 可感知_:</p>
|
||
<ul>
|
||
<li><p>应用 <code>A</code> 可能访问 <code>*.foo.com</code>。</p></li>
|
||
<li><p>应用 <code>B</code> 可能访问 <code>*.bar.com</code>。</p></li>
|
||
</ul>
|
||
<p>必须阻止其他访问,尤其是应用 <code>A</code> 到 <code>service1.bar.com</code> 的访问。</p></li>
|
||
<li><p>**防篡改*。万一有一个应用的 pod 被破坏了,要防止受损的 pod 逃离监控,防止发送假信息给监控系统,防止破坏出口策略。</p></li>
|
||
<li><p>有这点就更好:流量管控对应用程序要<strong>透明</strong>。</p></li>
|
||
</ol>
|
||
<p>对每个要求我来详细介绍以下。第一个要求指出,必须支持对外服务访问只能使用 TLS。在看到所有出集群的流量都必须加密后,这个要求就出现了。这意味着要么是应用程序执行 TLS,要么是 Istio 必须为应用程序执行 TLS。
|
||
注意如果应用程序执行了 TLS,Istio 代理是无法看到原始的流量的,只能看到加密后的,所以代理只能看到 TLS 协议。对代理来说它不关心原始协议是 HTTP 还是 MongoDB ,所有的 Istio 代理只能看到 TLS 流量。</p>
|
||
<p>第二个要求指出:必须监控 SNI 和流量源。监控是防止攻击的第一步。即使攻击者可以从集群内访问外部服务,如果监控了访问请求,就会有机会发现可疑流量并且采取纠正措施。</p>
|
||
<p>注意如果是应用程序发起的 TLS,Istio 的 sidecar 代理就只能看到 TCP 流量和包含 SNI 的 TLS 握手。源 pod 的标签可以识别出流量来源,但是 pod 的服务账号或者其它源识标识符也可以用来识别流量。我们把出口流量管控系统的这个特性叫做 _Kubernetes 可感知_:这个系统必须理解 Kubernetes 组件,比如 pod 和服务账号。如果这个系统不是 Kubernetes 可感知的,那它只能监控 IP 地址,并把它作为源的标示。</p>
|
||
<p>第三个要求指出:Istio 运维人员必须能为整个集群所有的出口流量定规策略。策略指出集群中的 pod 可能会访问哪些外部服务。外部服务可以通过服务的<a href="https://en.wikipedia.org/wiki/Fully_qualified_domain_name">全域名</a> (比如 <code>www.ibm.com</code>)或者泛域名(比如:<code>*.ibm.com</code>)进行标示。只有指定的外部服务可以访问,其它所有的出口流量都要被阻止。</p>
|
||
<p>这个要求是为了阻止攻击者访问恶意站点而提出的,比如下载更新/操作他们的恶意软件。同样也想去限制攻击者可以访问和攻击的外部站点的数量。只允许集群内应用程序需要访问的外部站点并且阻止其它所拥有的服务访问,这样减少了<a href="https://en.wikipedia.org/wiki/Attack_surface">攻击面</a>。当外部服务有了它们自己的安全机制,你想使用<a href="https://en.wikipedia.org/wiki/Defense_in_depth_(computing)">纵深防御</a>并且使用多个安全层:除了外部系统的安全层外,集群内还有一个安全层。</p>
|
||
<p>这个要求意味着外部服务必须能用域名来标示。我们把出口管控系统的这个特性叫做 DNS 感知。如果系统不是 DNS 可感知的,外部服务必须用 IP 地址标示。
|
||
使用 IP 地址不方便而且经常不灵活,因为服务的 IP 地址会变的。有时候服务的所有 IP 地址甚至都不知道,比如:<a href="https://en.wikipedia.org/wiki/Content_delivery_network">CDN</a>。</p>
|
||
<p>第四个要求指出:出口流量的源都必须添加策略,以高效扩展第三个要求。策略能明确那个源可以访问那个外部服务,并且就像第二个要求一样源必须要标示,例如:通过源 pod 的标签或者通过 pod 的服务账号。
|
||
这意味这策略的执行也必须是 Kubernetes 可感知的。如果策略执行不是 Kubernetes 可感知的,策略必须通过 pod 的 IP 来标示流量的源头,使用 pod 的 IP 是不方便的,特别是 pod 启动和销毁,而它们的 IP 是不固定的。</p>
|
||
<p>第五个要求指出:即使集群被攻破并且攻击者管控了一些 pod,他们也必须不能欺骗监控或者违反出口管控系统的策略。我们才能说这样的系统提供了出口流量的安全管控。</p>
|
||
<p>第六个要求指出:提供的流量管控服务要不能改变应用程序容器,特别是不能修改应用程序代码和不能修改容器环境。我们把这样的做法称为透明出口流量管控。</p>
|
||
<p>在下一篇文章中,我将展示 Istio 作为出口流量管控系统的示例,由此说明它可以满足所有这些要求,特别是它的透明性、DNS 感知能力和 Kubernetes 感知能力。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>希望您确信对于集群安全来说出口流量管控是非常重要的。在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-2/">这个系列文章的第二部分</a>我讲述了使用 Istio 实现出口流量安全管控的方法。在<a href="/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-3/">这个系列文章的第三部分</a>我和其它方案进行了对比,比如 <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">Kubernetes 网络策略</a>以及已有的其它出口代理/防火墙方案。</p></description><pubDate>Wed, 22 May 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-1/</link><author>Vadim Eisenberg (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/egress-traffic-control-in-istio-part-1/</guid><category>traffic-management</category><category>egress</category><category>security</category></item><item><title>为性能而设计的 Istio 1.1</title><description>
|
||
<p>构建一个超大规模的基于微服务的云环境一直令人非常兴奋,但却难于管理。随之而来的是 2014 年的 Kubernetes(容器编排引擎),接着是 2017 年的 Istio(容器服务管理),这两个开源项目让开发者无需在管理上耗费太多时间即可扩展基于容器的应用程序。</p>
|
||
<p>现在,Istio 1.1 新的增强功能带来了改进的应用性能和服务管理效率,以便扩大规模。相比于 Istio 1.0,使用我们的示例商业航班预订程序的模拟显示出了如下改进。</p>
|
||
<p>我们看到大量的应用程序性能提升:</p>
|
||
<ul>
|
||
<li>应用程序平均延迟降低 30%</li>
|
||
<li>在大型网格中服务启动时间快 40%</li>
|
||
</ul>
|
||
<p>同样还有服务管理效率的显著提升:</p>
|
||
<ul>
|
||
<li>在大型网格中,Pilot 的 CPU 使用率降低了 90%</li>
|
||
<li>在大型网格中,Pilot 的内存使用率降低了 50%</li>
|
||
</ul>
|
||
<p>使用 Istio 1.1,企业会对一致性和可控的应用程序扩展能力更加自信 —— 即使在超大规模的云环境中也无所畏惧。</p>
|
||
<p>祝贺那些来自世界各地的为此次版本发布做出贡献的 Istio 专家。我们对这些结果无比高兴。</p>
|
||
<h2 id="istio-1-1-性能增强-istio-1-1-performance-enhancements">Istio 1.1 性能增强{Istio-1-1-performance-enhancements}</h2>
|
||
<p>作为 Istio Performance and Scalability (性能和可伸缩)工作组的成员,我们进行了广泛的性能评估。我们与其他 Istio 贡献者合作,为 Istio 1.1 引入了许多旨在提高性能的新特性。1.1 中一些显著的性能增强包括:</p>
|
||
<ul>
|
||
<li>Envoy 生成统计数据的默认集合显著减少</li>
|
||
<li>为 Mixer 工作负载添加了减载特性</li>
|
||
<li>改进了 Envoy 和 Mixer 之间的协议</li>
|
||
<li>隔离命名空间以减少操作开销</li>
|
||
<li>可配置的并发工作线程,可以提高整体吞吐量</li>
|
||
<li>为限制遥测数据的可配置过滤器</li>
|
||
<li>解除同步瓶颈</li>
|
||
</ul>
|
||
<h2 id="持续的代码质量和性能验证-continuous-code-quality-and-performance-verification">持续的代码质量和性能验证{continuous-code-quality-and-performance-verification}</h2>
|
||
<p>回归巡检促进了 Istio 性能和质量的不断提高,在幕后帮助 Istio 开发者识别并修正代码错误。每天的构建都会经过以客户为中心的性能基准 <a href="https://github.com/blueperf/">BluePerf</a> 的性能检测。测试结果会展示在 <a href="https://ibmcloud-perf.istio.io/regpatrol/">Istio 社区门户网站</a>。评估了各种应用配置以帮助洞悉 Istio 组件的性能。</p>
|
||
<p>另一个用于评估 Istio 构建性能的工具是 <a href="https://fortio.org/">Fortio</a>,它提供了一个综合的端到端的压力测试基准。</p>
|
||
<h2 id="概要-summary">概要{summary}</h2>
|
||
<p>Istio 1.1 旨在提高性能和可扩展性。Istio Performance and Scalability (性能和可扩展性)工作组实现了自 1.0 以来显著的性能改进。
|
||
Istio 1.1 提供的新特性和功能优化,提高了服务网格对企业工作负载的支撑能力。Istio 1.1 性能和调优指南记录了性能模拟,提供了调整和容量规划指导,并包含了调优客户用例的最佳实践。</p>
|
||
<h2 id="有用的链接-useful-links">有用的链接{useful-links}</h2>
|
||
<ul>
|
||
<li><a href="https://www.youtube.com/watch?time_continue=349&amp;v=G4F5aRFEXnU">Istio 服务网格性能 (34:30)</a>, 作者:Surya Duggirala, Laurent Demailly 和 Fawad Khaliq 于 KubeCon Europe 2018</li>
|
||
<li><a href="https://discuss.istio.io/c/performance-and-scalability">Istio 性能和可扩展性讨论专题</a></li>
|
||
</ul>
|
||
<h2 id="免责声明-disclaimer">免责声明{disclaimer}</h2>
|
||
<p>这里展示的性能数据是在一个可控的隔离环境中产生的。在其他环境中获得的实际结果可能存在较大差异。无法保证在其他地方获得相同或类似的结果。</p></description><pubDate>Tue, 19 Mar 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/istio1.1_perf/</link><author>Surya V Duggirala (IBM), Mandar Jog (Google), Jose Nativio (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/istio1.1_perf/</guid><category>performance</category><category>scalability</category><category>scale</category><category>benchmarks</category></item><item><title>多集群服务网格中的分版本路由</title><description>
|
||
<p>如果花一点时间对 Istio 进行了解,你可能会注意到,大量的功能都可以在单一的 Kubernetes 集群中,用简单的<a href="/v1.12/zh/docs/tasks">任务</a>和<a href="/v1.12/zh/docs/examples/">示例</a>所表达的方式来运行。但是真实世界中的云计算和基于微服务的应用往往不是这么简单的,会需要在不止一个地点分布运行,用户难免会产生怀疑,生产环境中是否还能这样运行?</p>
|
||
<p>幸运的是,Istio 提供了多种服务网格的配置方式,应用能够用近乎透明的方式加入一个跨越多个集群运行的服务网格之中,也就是<a href="/v1.12/zh/docs/ops/deployment/deployment-models/#multiple-clusters">多集群服务网格</a> 。最简单的设置多集群网格的方式,就是使用<a href="/v1.12/zh/docs/ops/deployment/deployment-models/#control-plane-models">多控制平面拓扑</a> ,这种方式不需要特别的网络依赖。在这种条件下,每个 Kubernetes 集群都有自己的控制平面,但是每个控制平面都是同步的,并接受统一的管理。</p>
|
||
<p>本文中,我们会在多控制平面拓扑形式的多集群网格中尝试一下 Istio 的<a href="/v1.12/zh/docs/concepts/traffic-management/">流量管理</a>功能。我们会展示如何配置 Istio 路由规则,在多集群服务网格中部署 <a href="https://github.com/istio/istio/tree/release-1.12/samples/bookinfo">Bookinfo 示例</a>,<code>reviews</code> 服务的 <code>v1</code> 版本运行在一个集群上,而 <code>v2</code> 和 <code>v3</code> 运行在另一个集群上,并完成远程服务调用。</p>
|
||
<h2 id="setup-clusters">集群部署</h2>
|
||
<p>首先需要部署两个 Kubernetes 集群,并各自运行一个做了轻度定制的 Istio。</p>
|
||
<ul>
|
||
<li><p>依照<a href="/v1.12/zh/docs/setup/install/multicluster/gateways/">使用 Gateway 连接多个集群</a>中提到的步骤设置一个多集群环境。</p></li>
|
||
<li><p><code>kubectl</code> 命令可以使用 <code>--context</code> 参数访问两个集群。
|
||
使用下面的命令列出所有 <code>context</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl config get-contexts
|
||
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
|
||
* cluster1 cluster1 user@foo.com default
|
||
cluster2 cluster2 user@foo.com default
|
||
</code></pre></li>
|
||
<li><p>将配置文件中的 <code>context</code> 名称赋值给两个环境变量:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export CTX_CLUSTER1=&lt;cluster1 context name&gt;
|
||
$ export CTX_CLUSTER2=&lt;cluster2 context name&gt;
|
||
</code></pre></li>
|
||
</ul>
|
||
<h2 id="deploy-in-cluster-1">在 <code>cluster1</code> 中部署 <code>bookinfo</code> 的 <code>v1</code> 版本</h2>
|
||
<p>在 <code>cluster1</code> 中运行 <code>productpage</code> 和 <code>details</code> 服务,以及 <code>reviews</code> 服务的 <code>v1</code> 版本。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl label --context=$CTX_CLUSTER1 namespace default istio-injection=enabled
|
||
$ kubectl apply --context=$CTX_CLUSTER1 -f - &lt;&lt;EOF
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: productpage
|
||
labels:
|
||
app: productpage
|
||
spec:
|
||
ports:
|
||
- port: 9080
|
||
name: http
|
||
selector:
|
||
app: productpage
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: productpage-v1
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: productpage
|
||
version: v1
|
||
spec:
|
||
containers:
|
||
- name: productpage
|
||
image: istio/examples-bookinfo-productpage-v1:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
---
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: details
|
||
labels:
|
||
app: details
|
||
spec:
|
||
ports:
|
||
- port: 9080
|
||
name: http
|
||
selector:
|
||
app: details
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: details-v1
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: details
|
||
version: v1
|
||
spec:
|
||
containers:
|
||
- name: details
|
||
image: istio/examples-bookinfo-details-v1:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
---
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: reviews
|
||
labels:
|
||
app: reviews
|
||
spec:
|
||
ports:
|
||
- port: 9080
|
||
name: http
|
||
selector:
|
||
app: reviews
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: reviews-v1
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: reviews
|
||
version: v1
|
||
spec:
|
||
containers:
|
||
- name: reviews
|
||
image: istio/examples-bookinfo-reviews-v1:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
EOF
|
||
</code></pre>
|
||
<h2 id="deploy-in-cluster-2">在 <code>cluster2</code> 中部署 <code>bookinfo</code> 的 <code>v2</code> 和 <code>v3</code></h2>
|
||
<p>在 <code>cluster2</code> 中运行 <code>ratings</code> 服务以及 <code>reviews</code> 服务的 <code>v2</code> 和 <code>v3</code> 版本:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl label --context=$CTX_CLUSTER2 namespace default istio-injection=enabled
|
||
$ kubectl apply --context=$CTX_CLUSTER2 -f - &lt;&lt;EOF
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: ratings
|
||
labels:
|
||
app: ratings
|
||
spec:
|
||
ports:
|
||
- port: 9080
|
||
name: http
|
||
selector:
|
||
app: ratings
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: ratings-v1
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: ratings
|
||
version: v1
|
||
spec:
|
||
containers:
|
||
- name: ratings
|
||
image: istio/examples-bookinfo-ratings-v1:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
---
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: reviews
|
||
labels:
|
||
app: reviews
|
||
spec:
|
||
ports:
|
||
- port: 9080
|
||
name: http
|
||
selector:
|
||
app: reviews
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: reviews-v2
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: reviews
|
||
version: v2
|
||
spec:
|
||
containers:
|
||
- name: reviews
|
||
image: istio/examples-bookinfo-reviews-v2:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: reviews-v3
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: reviews
|
||
version: v3
|
||
spec:
|
||
containers:
|
||
- name: reviews
|
||
image: istio/examples-bookinfo-reviews-v3:1.10.0
|
||
imagePullPolicy: IfNotPresent
|
||
ports:
|
||
- containerPort: 9080
|
||
EOF
|
||
</code></pre>
|
||
<h2 id="access-the-application">访问 <code>bookinfo</code> 应用</h2>
|
||
<p>和平常一样,我们需要使用一个 Istio gateway 来访问 <code>bookinfo</code> 应用。</p>
|
||
<ul>
|
||
<li><p>在 <code>cluster1</code> 中创建 <code>bookinfo</code> 的网关:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/bookinfo-gateway.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply --context=$CTX_CLUSTER1 -f @samples/bookinfo/networking/bookinfo-gateway.yaml@
|
||
</code></pre></div></li>
|
||
<li><p>遵循 <a href="/v1.12/zh/docs/examples/bookinfo/#determine-the-ingress-IP-and-port">Bookinfo 示例应用</a>中的步骤,确定 Ingress 的 IP 和端口,用浏览器打开 <code>http://$GATEWAY_URL/productpage</code>。</p></li>
|
||
</ul>
|
||
<p>这里会看到 <code>productpage</code>,其中包含了 <code>reviews</code> 的内容,但是没有出现 <code>ratings</code>,这是因为只有 <code>reviews</code> 服务的 <code>v1</code> 版本运行在 <code>cluster1</code> 上,我们还没有配置到 <code>cluster2</code> 的访问。</p>
|
||
<h2 id="在-cluster1-上为远端的-reviews-服务创建-serviceentry-以及-destinationrule">在 <code>cluster1</code> 上为远端的 <code>reviews</code> 服务创建 <code>ServiceEntry</code> 以及 <code>DestinationRule</code></h2>
|
||
<p>根据<a href="/v1.12/zh/docs/setup/install/multicluster/gateways/#setup-DNS">配置指南</a>中的介绍,远程服务可以用一个 <code>.global</code> 的 DNS 名称进行访问。在我们的案例中,就是 <code>reviews.default.global</code>,所以我们需要为这个主机创建 <code>ServiceEntry</code> 和 <code>DestinationRule</code>。<code>ServiceEntry</code> 会使用 <code>cluster2</code> 网关作为端点地址来访问服务。可以使用网关的 DNS 名称或者公共 IP:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export CLUSTER2_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER2 svc --selector=app=istio-ingressgateway \
|
||
-n istio-system -o jsonpath=&#34;{.items[0].status.loadBalancer.ingress[0].ip}&#34;)
|
||
</code></pre>
|
||
<p>用下面的命令来创建 <code>ServiceEntry</code> 和 <code>DestinationRule</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply --context=$CTX_CLUSTER1 -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: reviews-default
|
||
spec:
|
||
hosts:
|
||
- reviews.default.global
|
||
location: MESH_INTERNAL
|
||
ports:
|
||
- name: http1
|
||
number: 9080
|
||
protocol: http
|
||
resolution: DNS
|
||
addresses:
|
||
- 240.0.0.3
|
||
endpoints:
|
||
- address: ${CLUSTER2_GW_ADDR}
|
||
labels:
|
||
cluster: cluster2
|
||
ports:
|
||
http1: 15443 # 不要修改端口值
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: reviews-global
|
||
spec:
|
||
host: reviews.default.global
|
||
trafficPolicy:
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
subsets:
|
||
- name: v2
|
||
labels:
|
||
cluster: cluster2
|
||
- name: v3
|
||
labels:
|
||
cluster: cluster2
|
||
EOF
|
||
</code></pre>
|
||
<p><code>ServiceEntry</code> 的地址 <code>240.0.0.3</code> 可以是任意的未分配 IP。在 <code>240.0.0.0/4</code> 的范围里面进行选择是个不错的主意。阅读<a href="/v1.12/zh/docs/setup/install/multicluster/gateways/#configure-the-example-services">通过网关进行连接的多集群</a>一文,能够获得更多相关信息。</p>
|
||
<p>注意 <code>DestinationRule</code> 中的 <code>subset</code> 的标签,<code>cluster: cluster2</code> 对应的是 <code>cluster2</code> 网关。一旦流量到达目标集群,就会由本地目的 <code>DestinationRule</code> 来鉴别实际的 Pod 标签(<code>version: v1</code> 或者 <code>version: v2</code>)</p>
|
||
<h2 id="在所有集群上为本地-reviews-服务创建-destinationrule">在所有集群上为本地 <code>reviews</code> 服务创建 <code>DestinationRule</code></h2>
|
||
<p>技术上来说,我们只需要为每个集群定义本地的 <code>subset</code> 即可(<code>cluster1</code> 中的 <code>v1</code>,<code>cluster2</code> 中的 <code>v2</code> 和 <code>v3</code>),但是定义一个用不到的并未部署的版本也没什么大碍,为了清晰一点,我们会在两个集群上都创建全部三个 <code>subset</code>。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply --context=$CTX_CLUSTER1 -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
host: reviews.default.svc.cluster.local
|
||
trafficPolicy:
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
subsets:
|
||
- name: v1
|
||
labels:
|
||
version: v1
|
||
- name: v2
|
||
labels:
|
||
version: v2
|
||
- name: v3
|
||
labels:
|
||
version: v3
|
||
EOF
|
||
</code></pre>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply --context=$CTX_CLUSTER2 -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
host: reviews.default.svc.cluster.local
|
||
trafficPolicy:
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
subsets:
|
||
- name: v1
|
||
labels:
|
||
version: v1
|
||
- name: v2
|
||
labels:
|
||
version: v2
|
||
- name: v3
|
||
labels:
|
||
version: v3
|
||
EOF
|
||
</code></pre>
|
||
<h2 id="create-a-destination-rule-on-both-clusters-for-the-local-reviews-service">创建 <code>VirtualService</code> 来路由 <code>reviews</code> 服务的流量</h2>
|
||
<p>目前所有调用 <code>reviews</code> 服务的流量都会进入本地的 <code>reviews</code> Pod,也就是 <code>v1</code>,如果查看一下远吗,会发现 <code>productpage</code> 的实现只是简单的对 <code>http://reviews:9080</code> (也就是 <code>reviews.default.svc.cluster.local</code>)发起了请求,也就是本地版本。对应的远程服务名称为 <code>reviews.default.global</code>,所以需要用路由规则来把请求转发到远端集群。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">注意如果所有版本的 <code>reviews</code> 服务都在远端,也就是说本地没有 <code>reviews</code> 服务,那么 DNS 就会把 <code>reviews</code> 直接解析到 <code>reviews.default.global</code>,在本文的环境里,无需定义任何路由规则就可以发起对远端集群的请求。</div>
|
||
</aside>
|
||
</div>
|
||
<p>创建下列的 <code>VirtualService</code>,把 <code>jason</code> 的流量转发给运行在 <code>cluster2</code> 上的 <code>v2</code> 和 <code>v3</code> 版本的 <code>reviews</code>,两个版本各负责一半流量。其他用户的流量还是会发给 <code>v1</code> 版本的 <code>reviews</code>。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply --context=$CTX_CLUSTER1 -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
hosts:
|
||
- reviews.default.svc.cluster.local
|
||
http:
|
||
- match:
|
||
- headers:
|
||
end-user:
|
||
exact: jason
|
||
route:
|
||
- destination:
|
||
host: reviews.default.global
|
||
subset: v2
|
||
weight: 50
|
||
- destination:
|
||
host: reviews.default.global
|
||
subset: v3
|
||
weight: 50
|
||
- route:
|
||
- destination:
|
||
host: reviews.default.svc.cluster.local
|
||
subset: v1
|
||
EOF
|
||
</code></pre>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">这种平均分配的规则并不实际,只是一种用于演示远端服务多版本之间流量分配的方便手段。</div>
|
||
</aside>
|
||
</div>
|
||
<p>回到浏览器,用 <code>jason</code> 的身份登录。刷新页面几次,会看到星形图标在红黑两色之间切换(<code>v2</code> 和 <code>v3</code>)。如果登出,就只会看到没有 <code>ratings</code> 的 <code>reviews</code> 服务了。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>本文中,我们看到在多控制平面拓扑的多集群网格中,如何使用 Istio 路由规则进行跨集群的流量分配。
|
||
这里我们手工配置了 <code>.global</code> 的 <code>ServiceEntry</code> 以及 <code>DestinationRule</code>,用于进行对远端集群中 <code>reviews</code> 服务的访问。实际上如果我们想要的话,可以让任何服务都在远端或本地运行,当然需要为远端服务配置 <code>.global</code> 的相关资源。幸运的是,这个过程可以自动化,并且可能在 Istio 的未来版本中实现。</p></description><pubDate>Thu, 07 Feb 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/multicluster-version-routing/</link><author>Frank Budinsky (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/multicluster-version-routing/</guid><category>traffic-management</category><category>multicluster</category></item><item><title>博客策略更新!</title><description><p>欢迎来到 Istio 博客!</p>
|
||
<p>为了让您更方便的在我们的网站上发表博客,我们<a href="/v1.12/zh/docs/releases/contribute/add-content/#content-types">更新了内容类型指南</a>。</p>
|
||
<p>这次更新的目标是对内容进行更方便的分享和搜索。</p>
|
||
<p>我们希望更简单地共享 Istio 方面的最新信息,<a href="/v1.12/zh/blog">Istio 博客</a>是一个好的出发点。</p>
|
||
<p>如果您认为您的内容符合下面三个分类中的一个,我们非常欢迎将其提交到 Istio 博客之中。</p>
|
||
<ul>
|
||
<li>文章中详细介绍了您在使用和配置 Istio 中的经验。如果分享了一种新的观点或体验,那就更好了。</li>
|
||
<li>文章中着重介绍了 Istio 的功能。</li>
|
||
<li>文章中详细讲解了使用 Istio 完成一个任务或者满足特定用例需求的相关内容。</li>
|
||
</ul>
|
||
<p>仅需<a href="/v1.12/zh/docs/releases/contribute/github/">提交一个 PR</a> 就可以发表您的博客,如果需要,可以<a href="/v1.12/zh/docs/releases/contribute/review">申请评审</a>。</p>
|
||
<p>我们期待能够很快就能在博客上看到您的 Istio 体验!</p></description><pubDate>Tue, 05 Feb 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/sail-the-blog/</link><author>Rigs Caballero, Google</author><guid isPermaLink="true">/v1.12/zh/blog/2019/sail-the-blog/</guid><category>community</category><category>blog</category><category>contribution</category><category>guide</category><category>guideline</category><category>event</category></item><item><title>揭开 Istio Sidecar 注入模型的神秘面纱</title><description>
|
||
<p>Istio 服务网格体系结构的简单概述总是从控制平面和数据平面开始。</p>
|
||
<p>从 <a href="/v1.12/zh/docs/ops/deployment/architecture/">Istio 的文档</a> :</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content"><p>Istio 服务网格在逻辑上分为数据平面和控制平面。</p>
|
||
<p>数据平面由一组部署为 sidecar 的智能代理(Envoy)组成。这些代理与 Mixer、通用策略和遥测中心协调并控制微服务之间的所有网络通信。</p>
|
||
<p>控制平面管理并配置从代理到路由的流量。此外,控制平面配置 Mixer 以执行策略和收集遥测数据。</p>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
<figure style="width:40%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:80%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/data-plane-setup/arch-2.svg" title="Istio Architecture">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/data-plane-setup/arch-2.svg" alt="基于 Istio 的应用程序的总体架构。" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio Architecture</figcaption>
|
||
</figure>
|
||
<p>重要的是要理解向应用程序 pod 中注入边车是自动进行的,尽管也可以手动注入。流量从应用服务流向 sidecar,而开发人员无需关心它。一旦将应用程序连接到 Istio 服务网格,开发者便可以开始使用并获得服务网格中的所有效益。但是,数据平面管道是如何发生的,以及无缝迁移工作的真正要求是什么?在本文中,我们将深入研究 Sidecar 注入模型的细节,以非常清楚地理解 Sidecar 注入的工作原理。</p>
|
||
<h2 id="sidecar-injection">Sidecar 注入</h2>
|
||
<p>简单来说,Sidecar 注入会将额外容器的配置添加到 Pod 模板中。Istio 服务网格目前所需的容器有:</p>
|
||
<p><code>istio-init</code>
|
||
<a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/">init 容器</a>用于设置 iptables 规则,以便将入站/出站流量通过 sidecar 代理。初始化容器与应用程序容器在以下方面有所不同:</p>
|
||
<ul>
|
||
<li>它在启动应用容器之前运行,并一直运行直至完成。</li>
|
||
<li>如果有多个初始化容器,则每个容器都应在启动下一个容器之前成功完成。</li>
|
||
</ul>
|
||
<p>因此,您可以看到,对于不需要成为实际应用容器一部分的设置或初始化作业来说,这种容器是多么的完美。在这种情况下,<code>istio-init</code> 就是这样做并设置了 <code>iptables</code> 规则。</p>
|
||
<p><code>istio-proxy</code>
|
||
这个容器是真正的 sidecar 代理(基于 Envoy)。</p>
|
||
<h3 id="manual-injection">手动注入</h3>
|
||
<p>在手动注入方法中,可以使用 <a href="/v1.12/zh/docs/reference/commands/istioctl"><code>istioctl</code></a> 修改容器模板并添加前面提到的两个容器的配置。不论是手动注入还是自动注入,Istio 都从 <code>istio-sidecar-injector</code> 和的 <code>istio</code> 两个 Configmap 对象中获取配置。</p>
|
||
<p>我们先来看看 <code>istio-sidecar-injector</code> Configmap 的配置,了解一下其中的内容。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-outputis='yaml' data-repo='istio' >$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath=&#39;{.data.config}&#39;
|
||
以下代码片段来自 output:
|
||
policy: enabled
|
||
template: |-
|
||
initContainers:
|
||
- name: istio-init
|
||
image: docker.io/istio/proxy_init:1.0.2
|
||
args:
|
||
- &#34;-p&#34;
|
||
- [[ .MeshConfig.ProxyListenPort ]]
|
||
- &#34;-u&#34;
|
||
- 1337
|
||
.....
|
||
imagePullPolicy: IfNotPresent
|
||
securityContext:
|
||
capabilities:
|
||
add:
|
||
- NET_ADMIN
|
||
restartPolicy: Always
|
||
containers:
|
||
- name: istio-proxy
|
||
image: [[ if (isset .ObjectMeta.Annotations &#34;sidecar.istio.io/proxyImage&#34;) -]]
|
||
&#34;[[ index .ObjectMeta.Annotations &#34;sidecar.istio.io/proxyImage&#34; ]]&#34;
|
||
[[ else -]]
|
||
docker.io/istio/proxyv2:1.0.2
|
||
[[ end -]]
|
||
args:
|
||
- proxy
|
||
- sidecar
|
||
.....
|
||
env:
|
||
.....
|
||
- name: ISTIO_META_INTERCEPTION_MODE
|
||
value: [[ or (index .ObjectMeta.Annotations &#34;sidecar.istio.io/interceptionMode&#34;) .ProxyConfig.InterceptionMode.String ]]
|
||
imagePullPolicy: IfNotPresent
|
||
securityContext:
|
||
readOnlyRootFilesystem: true
|
||
[[ if eq (or (index .ObjectMeta.Annotations &#34;sidecar.istio.io/interceptionMode&#34;) .ProxyConfig.InterceptionMode.String) &#34;TPROXY&#34; -]]
|
||
capabilities:
|
||
add:
|
||
- NET_ADMIN
|
||
restartPolicy: Always
|
||
.....
|
||
</code></pre>
|
||
<p>如您所见,configmap 包含了 <code>istio-init</code> 初始化容器和 <code>istio-proxy</code> 代理容器的配置。该配置包括容器镜像的名称以及拦截模式,权限要求等参数。</p>
|
||
<p>从安全的角度来看,重要的是要注意 <code>istio-init</code> 需要 <code>NET_ADMIN</code> 权限来修改 pod 命名空间中的 <code>iptables</code>,如果 <code>istio-proxy</code> 是 <code>TPROXY</code> 模式,也需要这一权限。由于该仅限于 pod 的命名空间,因此应该没有问题。但是,我们注意到最近的 open-shift 版本可能会出现一些问题,因此需要一种解决方法。本文结尾处提到了一个这样的选择。</p>
|
||
<p>要修改当前的 Pod 模板以进行 sidecar 注入,您可以:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl kube-inject -f demo-red.yaml | kubectl apply -f -
|
||
</code></pre>
|
||
<p>或者</p>
|
||
<p>要使用修改后的 Configmap 或本地 Configmap:</p>
|
||
<ul>
|
||
<li><p>从 configmap 创建 <code>inject-config.yaml</code> 和 <code>mesh-config.yaml</code></p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath=&#39;{.data.config}&#39; &gt; inject-config.yaml
|
||
$ kubectl -n istio-system get configmap istio -o=jsonpath=&#39;{.data.mesh}&#39; &gt; mesh-config.yaml
|
||
</code></pre></li>
|
||
<li><p>修改现有的 pod 模板,在这个例子中是,<code>demo-red.yaml</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ istioctl kube-inject --injectConfigFile inject-config.yaml --meshConfigFile mesh-config.yaml --filename demo-red.yaml --output demo-red-injected.yaml
|
||
</code></pre></li>
|
||
<li><p>提交 <code>demo-red-injected.yaml</code></p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f demo-red-injected.yaml
|
||
</code></pre></li>
|
||
</ul>
|
||
<p>如上所示,我们使用 <code>sidecar-injector</code> 和网格配置创建了一个新模板,然后使用 <code>kubectl</code> 应用该新模板。如果我们查看注入后的 YAML 文件,它具有 Istio 特定容器的配置,如上所述。一旦我们应用注入后的 YAML 文件,我们将看到两个容器正在运行。其中一个是实际的应用程序容器,另一个是 <code>istio-proxy</code> sidecar。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods | grep demo-red
|
||
demo-red-pod-8b5df99cc-pgnl7 2/2 Running 0 3d
|
||
</code></pre>
|
||
<p>这里没有 3 个 Pod,因为 <code>istio-init</code> 容器是一个 init 类型的容器,它在完成应做的操作后退出,其用于在 pod 中设置 <code>iptable</code> 规则。为了确认 init 容器已退出,让我们看一下 <code>kubectl describe</code> 的输出:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-outputis='yaml' data-repo='istio' >$ kubectl describe pod demo-red-pod-8b5df99cc-pgnl7
|
||
以下代码片段来自 output:
|
||
Name: demo-red-pod-8b5df99cc-pgnl7
|
||
Namespace: default
|
||
.....
|
||
Labels: app=demo-red
|
||
pod-template-hash=8b5df99cc
|
||
version=version-red
|
||
Annotations: sidecar.istio.io/status={&#34;version&#34;:&#34;3c0b8d11844e85232bc77ad85365487638ee3134c91edda28def191c086dc23e&#34;,&#34;initContainers&#34;:[&#34;istio-init&#34;],&#34;containers&#34;:[&#34;istio-proxy&#34;],&#34;volumes&#34;:[&#34;istio-envoy&#34;,&#34;istio-certs...
|
||
Status: Running
|
||
IP: 10.32.0.6
|
||
Controlled By: ReplicaSet/demo-red-pod-8b5df99cc
|
||
Init Containers:
|
||
istio-init:
|
||
Container ID: docker://bef731eae1eb3b6c9d926cacb497bb39a7d9796db49cd14a63014fc1a177d95b
|
||
Image: docker.io/istio/proxy_init:1.0.2
|
||
Image ID: docker-pullable://docker.io/istio/proxy_init@sha256:e16a0746f46cd45a9f63c27b9e09daff5432e33a2d80c8cc0956d7d63e2f9185
|
||
.....
|
||
State: Terminated
|
||
Reason: Completed
|
||
.....
|
||
Ready: True
|
||
Containers:
|
||
demo-red:
|
||
Container ID: docker://8cd9957955ff7e534376eb6f28b56462099af6dfb8b9bc37aaf06e516175495e
|
||
Image: chugtum/blue-green-image:v3
|
||
Image ID: docker-pullable://docker.io/chugtum/blue-green-image@sha256:274756dbc215a6b2bd089c10de24fcece296f4c940067ac1a9b4aea67cf815db
|
||
State: Running
|
||
Started: Sun, 09 Dec 2018 18:12:31 -0800
|
||
Ready: True
|
||
istio-proxy:
|
||
Container ID: docker://ca5d690be8cd6557419cc19ec4e76163c14aed2336eaad7ebf17dd46ca188b4a
|
||
Image: docker.io/istio/proxyv2:1.0.2
|
||
Image ID: docker-pullable://docker.io/istio/proxyv2@sha256:54e206530ba6ca9b3820254454e01b7592e9f986d27a5640b6c03704b3b68332
|
||
Args:
|
||
proxy
|
||
sidecar
|
||
.....
|
||
State: Running
|
||
Started: Sun, 09 Dec 2018 18:12:31 -0800
|
||
Ready: True
|
||
.....
|
||
</code></pre>
|
||
<p>从输出中可以看出,<code>istio-init</code> 容器的 <code>State</code> 为 <code>Terminated</code>,而 <code>Reason</code> 是 <code>Completed</code>。只有两个容器是运行的,主应用程序 <code>demo-red</code> 容器和 <code>istio-proxy</code> 容器。</p>
|
||
<h3 id="automatic-injection">自动注入</h3>
|
||
<p>在大多数情况下,您不想在每次部署应用程序时都使用 <a href="/v1.12/zh/docs/reference/commands/istioctl"><code>istioctl</code></a> 命令手动注入边车,而是希望 Istio 自动将 sidecar 注入到您的 pod 中。这是推荐的方法,要使自动注入生效,您只需要用 <code>istio-injection=enabled</code> 标记想部署应用程序的命名空间。</p>
|
||
<p>贴上标签后,Istio 会自动为您在该命名空间中部署的所有 pod 注入 sidecar。下面的例子里,<code>istio-dev</code> 命名空间中部署的 pod 被自动注入了 sidecar:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get namespaces --show-labels
|
||
NAME STATUS AGE LABELS
|
||
default Active 40d &lt;none&gt;
|
||
istio-dev Active 19d istio-injection=enabled
|
||
istio-system Active 24d &lt;none&gt;
|
||
kube-public Active 40d &lt;none&gt;
|
||
kube-system Active 40d &lt;none&gt;
|
||
</code></pre>
|
||
<p>但它是如何工作的呢?要深入了解这一点,我们需要理解 Kubernetes 准入控制器。</p>
|
||
<p><a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/">来自 Kubernetes 文档:</a></p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">准入控制器是一段代码,用于在对象持久化之前但请求已经过身份验证和授权之后,拦截对 Kubernetes API 服务器的请求。您可以定义两种类型的 Admission Webhook:Validating 和 Mutating。Validating 类型的 Webhook 可以根据自定义的准入策略决定是否拒绝请求;Mutating 类型的 Webhook 可以根据自定义配置来对请求进行编辑。</div>
|
||
</aside>
|
||
</div>
|
||
<p>对于 sidecar 自动注入,Istio 依赖于 <code>Mutating Admission Webhook</code>。让我们来看看 <code>istio-sidecar-injector</code> 中的配置详情。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-outputis='yaml' data-repo='istio' >$ kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml
|
||
以下代码片段来自 output:
|
||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||
kind: MutatingWebhookConfiguration
|
||
metadata:
|
||
annotations:
|
||
kubectl.kubernetes.io/last-applied-configuration: |
|
||
{&#34;apiVersion&#34;:&#34;admissionregistration.k8s.io/v1beta1&#34;,&#34;kind&#34;:&#34;MutatingWebhookConfiguration&#34;,&#34;metadata&#34;:{&#34;annotations&#34;:{},&#34;labels&#34;:{&#34;app&#34;:&#34;istio-sidecar-injector&#34;,&#34;chart&#34;:&#34;sidecarInjectorWebhook-1.0.1&#34;,&#34;heritage&#34;:&#34;Tiller&#34;,&#34;release&#34;:&#34;istio-remote&#34;},&#34;name&#34;:&#34;istio-sidecar-injector&#34;,&#34;namespace&#34;:&#34;&#34;},&#34;webhooks&#34;:[{&#34;clientConfig&#34;:{&#34;caBundle&#34;:&#34;&#34;,&#34;service&#34;:{&#34;name&#34;:&#34;istio-sidecar-injector&#34;,&#34;namespace&#34;:&#34;istio-system&#34;,&#34;path&#34;:&#34;/inject&#34;}},&#34;failurePolicy&#34;:&#34;Fail&#34;,&#34;name&#34;:&#34;sidecar-injector.istio.io&#34;,&#34;namespaceSelector&#34;:{&#34;matchLabels&#34;:{&#34;istio-injection&#34;:&#34;enabled&#34;}},&#34;rules&#34;:[{&#34;apiGroups&#34;:[&#34;&#34;],&#34;apiVersions&#34;:[&#34;v1&#34;],&#34;operations&#34;:[&#34;CREATE&#34;],&#34;resources&#34;:[&#34;pods&#34;]}]}]}
|
||
creationTimestamp: 2018-12-10T08:40:15Z
|
||
generation: 2
|
||
labels:
|
||
app: istio-sidecar-injector
|
||
chart: sidecarInjectorWebhook-1.0.1
|
||
heritage: Tiller
|
||
release: istio-remote
|
||
name: istio-sidecar-injector
|
||
.....
|
||
webhooks:
|
||
- clientConfig:
|
||
service:
|
||
name: istio-sidecar-injector
|
||
namespace: istio-system
|
||
path: /inject
|
||
name: sidecar-injector.istio.io
|
||
namespaceSelector:
|
||
matchLabels:
|
||
istio-injection: enabled
|
||
rules:
|
||
- apiGroups:
|
||
- &#34;&#34;
|
||
apiVersions:
|
||
- v1
|
||
operations:
|
||
- CREATE
|
||
resources:
|
||
- pods
|
||
</code></pre>
|
||
<p>在这里,您可以看到与标签 <code>istio-injection:enabled</code> 相匹配的 webhook <code>namespaceSelector</code> 标签。在这种情况下,您还会看到在创建容器时要完成的操作和资源。当 <code>apiserver</code> 接收到与其中一个规则匹配的请求时,<code>apiserver</code> 会根据 <code>clientconfig</code> 配置中指定的 <code>name: istio-sidecar-injector</code> 键值对,向 webhook 服务发送准入审查请求。我们应该能够看到该服务正在 <code>istio-system</code> 命名空间中运行。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get svc --namespace=istio-system | grep sidecar-injector
|
||
istio-sidecar-injector ClusterIP 10.102.70.184 &lt;none&gt; 443/TCP 24d
|
||
</code></pre>
|
||
<p>最终,该配置与手动注入中的配置几乎相同。只是它是在 pod 创建过程中自动完成的,因此您不会看到部署中的更改。您需要使用 <code>kubectl describe</code> 来查看 sidecar 代理和 init 代理。</p>
|
||
<p>sidecar 自动注入不仅取决于 webhook 的 <code>namespaceSelector</code> 机制,还取决于默认注入策略和每个 pod 自身注解。</p>
|
||
<p>如果你再次查看 <code>istio-sidecar-injector</code> ConfigMap,它将定义默认的注入策略。在这个示例中,它是默认启用的。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-outputis='yaml' data-repo='istio' >$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath=&#39;{.data.config}&#39;
|
||
以下代码片段来自 output:
|
||
policy: enabled
|
||
template: |-
|
||
initContainers:
|
||
- name: istio-init
|
||
image: &#34;gcr.io/istio-release/proxy_init:1.0.2&#34;
|
||
args:
|
||
- &#34;-p&#34;
|
||
- [[ .MeshConfig.ProxyListenPort ]]
|
||
</code></pre>
|
||
<p>您还可以在 pod 模板中使用注解 <code>sidecar.istio.io/inject</code> 覆盖默认策略。以下示例展示如何为 <code>Deployment</code> 中的 pod 禁用 sidecar 自动注入。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: ignored
|
||
spec:
|
||
template:
|
||
metadata:
|
||
annotations:
|
||
sidecar.istio.io/inject: &#34;false&#34;
|
||
spec:
|
||
containers:
|
||
- name: ignored
|
||
image: tutum/curl
|
||
command: [&#34;/bin/sleep&#34;,&#34;infinity&#34;]
|
||
</code></pre>
|
||
<p>此示例显示了许多变量,这取决于是否在命名空间、ConfigMap 和 pod 中控制 sidecar 自动注入,它们是:</p>
|
||
<ul>
|
||
<li>webhook <code>namespaceSelector</code>(<code>istio-injection: enabled</code>)</li>
|
||
<li>默认策略(在 ConfigMap <code>istio-sidecar-injector</code> 中配置)</li>
|
||
<li>每个 pod 的重载注解(<code>sidecar.istio.io/inject</code>)</li>
|
||
</ul>
|
||
<p><a href="/v1.12/zh/docs/ops/common-problems/injection/">注入状态表</a>根据上述变量的值清晰显示了最终注入状态。</p>
|
||
<h2 id="traffic-flow-from-application-container-to-sidecar-proxy">从应用容器到 Sidecar 代理的流量</h2>
|
||
<p>既然我们已经清楚了如何将 sidecar 容器和 init 容器注入到应用清单中,那么 sidecar 代理如何捕获容器之间的入站和出站流量?我们曾简要提到过,这是通过在 pod 命名空间中设置 <code>iptable</code> 规则来完成的,而规则又是由 <code>istio-init</code> 容器完成的。现在,是时候验证命名空间中实际更新的内容了。</p>
|
||
<p>让我们进入上一节中部署的应用程序 pod 命名空间,并查看已配置的 iptables。我们将展示一个使用 <code>nsenter</code> 的例子。或者,您也可以通过特权模式进入容器并查看相同的信息。对于无法访问节点的人来说,使用 <code>exec</code> 进入 sidecar 并运行 <code>iptables</code> 更实用。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ docker inspect b8de099d3510 --format &#39;{{ .State.Pid }}&#39;
|
||
4125
|
||
</code></pre>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ nsenter -t 4215 -n iptables -t nat -S
|
||
-P PREROUTING ACCEPT
|
||
-P INPUT ACCEPT
|
||
-P OUTPUT ACCEPT
|
||
-P POSTROUTING ACCEPT
|
||
-N ISTIO_INBOUND
|
||
-N ISTIO_IN_REDIRECT
|
||
-N ISTIO_OUTPUT
|
||
-N ISTIO_REDIRECT
|
||
-A PREROUTING -p tcp -j ISTIO_INBOUND
|
||
-A OUTPUT -p tcp -j ISTIO_OUTPUT
|
||
-A ISTIO_INBOUND -p tcp -m tcp --dport 80 -j ISTIO_IN_REDIRECT
|
||
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15001
|
||
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -j ISTIO_REDIRECT
|
||
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
|
||
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
|
||
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
|
||
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
|
||
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
|
||
</code></pre>
|
||
<p>上面的输出清楚地表明,端口 80 的所有入站流量(即我们的 <code>red-demo</code> 应用正在监听的端口)现在已被 <code>REDIRECTED</code> 到端口 15001,即 <code>istio-proxy</code> 的端口,一个 Envoy 代理正在监听的端口。对于出站流量也是如此。</p>
|
||
<p>本文已经快结束了。我们希望本文有助于您弄清 Istio 是如何将 Sidecar 代理注入到现有部署中以及 Istio 是如何将流量路由到代理。</p>
|
||
<div>
|
||
<aside class="callout idea">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-idea"/></svg>
|
||
</div>
|
||
<div class="content">更新:现在似乎可以选择使用新的 CNI 来代替 <code>istio-init</code>,其移除了对 init 容器和相关特权的要求。<a href="https://github.com/istio/cni"><code>istio-cni</code></a> 插件设置了 pod 的网络来满足此要求,以代替 Istio 当前通过 <code>istio-init</code> 注入 pod 的方法。</div>
|
||
</aside>
|
||
</div></description><pubDate>Thu, 31 Jan 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/data-plane-setup/</link><author>Manish Chugtu</author><guid isPermaLink="true">/v1.12/zh/blog/2019/data-plane-setup/</guid><category>kubernetes</category><category>sidecar-injection</category><category>traffic-management</category></item><item><title>Egress 网关性能测试</title><description>
|
||
<p>为了从网格中访问外部服务(本例中使用的是 MongoDB),需要加入 Egress 网关,本次测试的主要目的就是调查这一行为对性能和资源使用造成的影响。在博客<a href="/v1.12/zh/blog/2018/egress-mongo/">使用外部 MongoDB 服务</a>中介绍了为外部 MongoDB 配置 Egress 网关的具体步骤。</p>
|
||
<p>本次测试中使用的应用是 Acmeair 的 Java 版,这个应用会模拟一个航空订票系统。在 Istio 的每日构建中会使用该应用来进行性能的回归测试,但是在回归测试过程中,这些应用会使用自己的 Sidecar 来访问外部的 MongoDB,而不是 Egress 网关。</p>
|
||
<p>下图描述了目前的 Istio 回归测试过程中,Acmeair 应用的运行方式:</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:62.69230769230769%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/acmeair_regpatrol3.png" title="在 Istio 性能回归测试环境中的 Acmeair 基准测试">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/acmeair_regpatrol3.png" alt="在 Istio 性能回归测试环境中的 Acmeair 基准测试" />
|
||
</a>
|
||
</div>
|
||
<figcaption>在 Istio 性能回归测试环境中的 Acmeair 基准测试</figcaption>
|
||
</figure>
|
||
<p>还有一个差别就是,这一应用和外部数据库使用的是明文的 MongoDB 协议。本文中的第一个变化就是将应用到外部 MongoDB 之间的连接升级为 TLS 模式,以体现更贴近实际情况的场景。</p>
|
||
<p>下面会讲到一些从网格中访问外部数据库的具体案例。</p>
|
||
<h2 id="egress-traffic-cases">Egress 流量案例</h2>
|
||
<h3 id="case-1-bypassing-the-sidecar">案例 1:绕过 Sidecar</h3>
|
||
<p>在这个案例中,Sidecar 对应用和外部数据库之间的通信不做拦截。这一配置是通过初始化容器中的 <code>-x</code> 参数来完成的,将其内容设置为 MongoDB 的 CIDR 即可。这种做法导致 Sidecar 忽略流入/流出指定 IP 地址的流量。举例来说:</p>
|
||
<pre><code> - -x
|
||
- &#34;169.47.232.211/32&#34;</code></pre>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:76.45536869340232%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/case1_sidecar_bypass3.png" title="绕过 Sidecar 和外部 MongoDB 进行通信">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/case1_sidecar_bypass3.png" alt="绕过 Sidecar 和外部 MongoDB 进行通信" />
|
||
</a>
|
||
</div>
|
||
<figcaption>绕过 Sidecar 和外部 MongoDB 进行通信</figcaption>
|
||
</figure>
|
||
<h3 id="case-2-through-the-sidecar-with-service-entry">案例 2:使用 Service Entry,通过 Sidecar 完成访问</h3>
|
||
<p>在 Sidecar 已经注入到应用 Pod 之后,这种方式是缺省(访问外部服务)的方式。所有的流量都被 Sidecar 拦截,然后根据配置好的规则路由到目的地,这里所说的目的地也包含了外部服务。下面为 MongoDB 配置一个 <code>ServiceEntry</code>。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:74.41253263707573%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/case2_sidecar_passthru3.png" title="Sidecar 拦截对外部 MongoDB 的流量">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/case2_sidecar_passthru3.png" alt="Sidecar 拦截对外部 MongoDB 的流量" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Sidecar 拦截对外部 MongoDB 的流量</figcaption>
|
||
</figure>
|
||
<h3 id="case-3-egress-gateway">案例 3: Egress 网关</h3>
|
||
<p>配置 Egress 网关以及配套的 Destination Rule 和 Virtual Service,用于访问 MongoDB。所有进出外部数据库的流量都从 Egress 网关(Envoy)通过。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:62.309368191721134%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/case3_egressgw3.png" title="使用 Egress 网关访问 MongoDB">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/case3_egressgw3.png" alt="使用 Egress 网关访问 MongoDB" />
|
||
</a>
|
||
</div>
|
||
<figcaption>使用 Egress 网关访问 MongoDB</figcaption>
|
||
</figure>
|
||
<h3 id="case-4-mutual-TLS-between-sidecars-and-the-egress-gateway">案例 4:在 Sidecar 和 Egress 网关之间的双向 TLS</h3>
|
||
<p>这种方式中,在 Sidecar 和 网关之中多出了一个安全层,所以会影响性能。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:63.968957871396896%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/case4_egressgw_mtls3.png" title="在 Sidecar 和 Egress 网关之间启用双向 TLS">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/case4_egressgw_mtls3.png" alt="在 Sidecar 和 Egress 网关之间启用双向 TLS" />
|
||
</a>
|
||
</div>
|
||
<figcaption>在 Sidecar 和 Egress 网关之间启用双向 TLS</figcaption>
|
||
</figure>
|
||
<h3 id="case-5-egress-gateway-with-SNI-proxy">案例 5:带有 SNI Proxy 的 Egress 网关</h3>
|
||
<p>这个场景中,因为 Envoy 目前存在的一些限制,需要另一个代理来访问通配符域名。这里创建了一个 Nginx 代理,在 Egress 网关 Pod 中作为 Sidecar 来使用。</p>
|
||
<figure style="width:70%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:65.2762119503946%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/case5_egressgw_sni_proxy3.png" title="带有 SNI Proxy 的 Egress 网关">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/case5_egressgw_sni_proxy3.png" alt="带有 SNI Proxy 的 Egress 网关" />
|
||
</a>
|
||
</div>
|
||
<figcaption>带有 SNI Proxy 的 Egress 网关</figcaption>
|
||
</figure>
|
||
<h2 id="environment">环境</h2>
|
||
<ul>
|
||
<li>Istio 版本:1.0.2</li>
|
||
<li><code>K8s</code> 版本:<code>1.10.5_1517</code></li>
|
||
<li>Acmeair 应用:4 个服务(每个服务一个实例),跨服务事务,外部 MongoDB,平均载荷:620 字节。</li>
|
||
</ul>
|
||
<h2 id="results">结果</h2>
|
||
<p>使用 <code>Jmeter</code> 来生成负载,负载包含了一组持续五分钟的访问,每个阶段都会逐步提高客户端数量来发出 http 请求。客户端数量为:1、5、10、20、30、40、50 和 60。</p>
|
||
<h3 id="throughput">吞吐量</h3>
|
||
<p>下图展示了不同案例中的吞吐量:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:54.29638854296388%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/throughput3.png" title="不同案例中的吞吐量">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/throughput3.png" alt="不同案例中的吞吐量" />
|
||
</a>
|
||
</div>
|
||
<figcaption>不同案例中的吞吐量</figcaption>
|
||
</figure>
|
||
<p>如图可见,在应用和外部数据库中加入 Sidecar 和 Egress 网关并没有对性能产生太大影响;但是启用双向 TLS、又加入 SNI 代理之后,吞吐量分别下降了 10% 和 24%。</p>
|
||
<h3 id="response-time">响应时间</h3>
|
||
<p>在 20 客户端的情况下,我们对不同请求的平均响应时间也进行了记录。下图展示了各个案例中平均、中位数、90%、95% 以及 99% 百分位的响应时间。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:48.76783398184176%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/response_times3.png" title="不同配置中的响应时间">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/response_times3.png" alt="不同配置中的响应时间" />
|
||
</a>
|
||
</div>
|
||
<figcaption>不同配置中的响应时间</figcaption>
|
||
</figure>
|
||
<p>跟吞吐量类似,前面三个案例的响应时间没有很大区别,但是双向 TLS 和 额外的代理造成了明显的延迟。</p>
|
||
<h3 id="CPU-utilization">CPU 用量</h3>
|
||
<p>运行过程中还搜集了所有 Istio 组件以及 Sidecar 的 CPU 使用情况。为了公平起见,用吞吐量对 Istio 的 CPU 用量进行了归一化。下图中展示了这一结果:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:53.96174863387978%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2019/egress-performance/cpu_usage3.png" title="使用 TPS 进行归一化的 CPU 用量">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2019/egress-performance/cpu_usage3.png" alt="使用 TPS 进行归一化的 CPU 用量" />
|
||
</a>
|
||
</div>
|
||
<figcaption>使用 TPS 进行归一化的 CPU 用量</figcaption>
|
||
</figure>
|
||
<p>经过归一化处理之后的 CPU 用量数据表明,Istio 在使用 Egress 网关 + SNI 代理的情况下,消耗了更多的 CPU。</p>
|
||
<h2 id="conclusion">结论</h2>
|
||
<p>在这一系列的测试之中,我们用不同的方式来访问一个启用了 TLS 的 MongoDB 来进行性能对比。Egress 网关的引用没有对性能和 CPU 消耗的显著影响。但是启用了 Sidecar 和 Egress 网关之间的双向 TLS 或者为通配符域名使用了额外的 SNI 代理之后,会看到性能降级的现象。</p></description><pubDate>Thu, 31 Jan 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/egress-performance/</link><author>Jose Nativio, IBM</author><guid isPermaLink="true">/v1.12/zh/blog/2019/egress-performance/</guid><category>performance</category><category>traffic-management</category><category>egress</category><category>mongo</category></item><item><title>使用 AppSwitch 进行 Sidestepping 依赖性排序</title><description>
|
||
<p>我们正在经历一个有趣事情,对应用程序进行拆分和重组。虽然微服务需要把单体应用分解为多个微型服务,但服务网格会把这些服务连结为一个应用程序。因此,微服务是逻辑上分离而又不是相互独立的。它们通常是紧密相互依赖的,而拆分单体应用的同时会引入了许多新的问题,例如服务之间需要双向认证等。而 Istio 恰巧能解决大多数问题。</p>
|
||
<h2 id="dependency-ordering-problem">依赖性排序问题</h2>
|
||
<p>依赖性排序的问题是由于应用程序拆分而导致的问题且 Istio 也尚未解决 - 确保应用程序整体快速正确地的顺序启动应用程序的各个服务。在单体应用程序中,内置所有组件,组件之间的依赖顺序由内部锁机制强制执行。但是,如果单个服务分散在服务网格的集群中,则启动服务需要首先检查它所依赖的服务是否已启动且可用。</p>
|
||
<p>依赖性排序由于存在许多相互关联的问题而具有欺骗性。对单个服务进行排序需要具有服务的依赖关系图,以便它们可以从叶节点开始返回到根节点。由于相互依赖性随着应用程序的行为而发展,因此构建这样的图并随时保持更新并不容易。即使以某种方式提供依赖图,强制执行排序本身并不容易。简单地按指定的顺序启动服务显然是行不通的。服务可能已启动但尚未准备好提供服务。例如 docker-compose 中的 depends-on 标签就存在这样的问题。</p>
|
||
<p>除了在服务启动之间引入足够长的睡眠之外,还有一个常见的模式是,在启动服务之前检查被依赖的服务是否已经准备就绪。在 Kubernetes 中,可以用在 Pod 的 Init 容器中加入等待脚本的方式来完成。但是,这意味着整个应用程序将被暂停,直到所有的依赖服务都准备就绪。有时,应用程序会在启动第一次出站连接之前花几分钟时间初始化自己。不允许服务启动会增加应用程序整体启动时间的大量开销。此外,等待 init 容器的策略不适用于同一 pod 中的多个服务相互依赖的情况。</p>
|
||
<h3 id="example-scenario-IBM-WebSphere">示例场景:IBM WebSphere ND</h3>
|
||
<p>IBM WebSphere ND 是一个常见的应用程序中间件,通过对它的观察,能够更好地理解这种问题。它本身就是一个相当复杂的框架,由一个名为 Deployment manager(<code>dmgr</code>)的中央组件组成,它管理一组节点实例。它使用 UDP 协商节点之间的集群成员资格,并要求部署管理器在任何节点实例出现并加入集群之前已启动并可运行。</p>
|
||
<p>为什么我们在现代云原生环境中讨论传统应用程序?事实证明,通过使它们能够在 Kubernetes 和 Istio 平台上运行,可以获得显著的收益。从本质上讲,它是现代化之旅的一部分,它允许在同一现代平台上运行传统应用程序和全新的现代应用程序,以促进两者之间的互操作。实际上,WebSphere ND 是一个要求很高的应用程序。它期望具有特定网络接口属性的一致网络环境等。AppSwitch 可以满足这些要求。本博客的将重点关注依赖顺序需求以及 AppSwitch 在这方面的解决方法。</p>
|
||
<p>在 Kubernetes 集群上简单地部署 <code>dmgr</code> 和节点实例作为 pod 是行不通的。<code>dmgr</code> 和节点实例碰巧有一个很长的初始化过程,可能需要几分钟。如果他们被同时部署,那么应用程序通常会处于一个有趣的状态。当一个节点实例出现并发现缺少 <code>dmgr</code> 时,它将需要一个备用启动路径。相反,如果它立即退出,Kubernetes 崩溃循环将接管,也许应用程序会出现。但即使在这种情况下,事实证明及时启动并不能得到保证。</p>
|
||
<p>一个 <code>dmgr</code> 及其节点实例是 WebSphere ND 的基本部署配置。构建在生产环境中运行的 WebSphere ND 之上的 IBM Business Process Manager 等应用程序包括其他一些服务。在这些配置中,可能存在一系列相互依赖关系。根据节点实例托管的应用程序,它们之间也可能存在排序要求。使用较长的服务初始化时间和崩溃循环重启,应用程序几乎没有机会在任何合理的时间内启动。</p>
|
||
<h3 id="sidecar-dependency-in-Istio">Istio 中的 Sidecar 依赖</h3>
|
||
<p>Istio 本身受依赖性排序问题版本的影响。由于在 Istio 下运行的服务的连接通过其 sidecar 代理重定向,因此在应用程序服务及其 sidecar 之间创建了隐式依赖关系。除非 sidecar 完全正常运行,否则所有来自服务的请求都将被丢弃。</p>
|
||
<h2 id="dependency-ordering-with-AppSwitch">使用 AppSwitch 进行依赖性排序</h2>
|
||
<p>那么我们如何解决这些问题呢?一种方法是将其推迟到应用程序并说它们应该“表现良好”并实施适当的逻辑以使自己免受启动顺序问题的影响。但是,许多应用程序(尤其是传统应用程序)如果错误则会超时或死锁。即使对于新的应用程序,为每个服务实现一个关闭逻辑也是最大的额外负担,最好避免。服务网格需要围绕这些问题提供足够的支持。毕竟,将常见模式分解为底层框架实际上是服务网格的重点。</p>
|
||
<p><a href="http://appswitch.io">AppSwitch</a> 明确地解决了依赖性排序。它位于应用程序在集群中的客户端和服务之间的网络交互的控制路径上,并且通过进行 <code>connect</code> 调用以及当特定服务通过使 <code>listen</code> 准备好接受连接时,准确地知道服务何时成为客户端。调用它的 <em>service router</em> 组件在集群中传播有关这些事件的信息,并仲裁客户端和服务器之间的交互。AppSwitch 就是以这种简单有效的方式实现负载均衡和隔离等功能的。利用应用程序的网络控制路径的相同战略位置,可以想象这些服务所做的“连接”和“监听”调用可以以更精细的粒度排列,而不是按照依赖关系图对整个服务进行粗略排序。这将有效地解决多级依赖问题和加速应用程序启动。</p>
|
||
<p>但这仍然需要一个依赖图。存在许多产品和工具来帮助发现服务依赖性。但它们通常基于对网络流量的被动监控,并且无法预先为任意应用程序提供信息。由于加密和隧道导致的网络级混淆也使它们不可靠。发现和指定依赖项的负担最终落在应用程序的开发人员或操作员身上。实际上,甚至一致性检查依赖性规范本身也非常复杂,相对来说,能够避免使用依赖图的任何方法都会更加理想。</p>
|
||
<p>依赖图的要点是知道哪些客户端依赖于特定服务,以便让客户端能够等待被依赖服务准备就绪。但具体客户真的重要吗?归根结底,一个服务的所有客户端,都是依赖这个服务的。AppSwitch 正是利用这一点来解决依赖问题。事实上,这完全避免了依赖性排序。可以同时调度应用程序中的所有服务,而无需考虑启动顺序。它们之间的相互依赖性会根据各个请求和响应的粒度自动完成,从而实现快速,正确的应用程序启动。</p>
|
||
<h3 id="AppSwitch-model-and-constructs">AppSwitch 模型和构造</h3>
|
||
<p>既然我们对 AppSwitch 的高级方法有了概念性的理解,那么让我们来看看所涉及的结构。但首先要对使用模型进行快速总结。尽管它是针对不同的上下文编写的,但在此主题上查看我之前的 <a href="/v1.12/zh/blog/2018/delayering-istio/">blog</a> 也很有用。为了完整起见,我还要注意 AppSwitch 不会打扰非网络依赖。例如,两个服务可能使用 IPC 机制或通过共享文件系统进行交互。像这样的深层联系的流程通常是同一服务的一部分,并且不需要主动地对应用程序的正常执行进行干预。</p>
|
||
<p>AppSwitch 的核心能够使用 BSD Socket API 及其相关的其它调用(例如 <code>fcntl</code> 和 ioctl)来完成对 Socket 的处理。它的实现细节很有意思,但是为了防止偏离本文的主题,这里仅对其独特的关键属性进行一个总结。
|
||
(1)速度很快。它使用 <code>seccomp</code> 过滤和二进制检测的组合来积极地限制应用程序正常执行的干预。AppSwitch 特别适用于服务网格和应用程序网络用例,因为它实现了这些功能,而无需实际触摸数据。相反,网络级方法会导致每个数据包的成本。看看这个<a href="/v1.12/zh/blog/2018/delayering-istio/">博客</a>进行一些性能测量。
|
||
(2)它不需要任何内核支持,内核模块或补丁,可以在标准的发行版内核上运行
|
||
(3)它可以作为普通用户运行(非 root)。事实上,该机制甚至可以通过删除对网络容器的根要求来运行<a href="https://linuxpiter.com/en/materials/2478">非 root 的 Docker 守护进程</a>
|
||
(4)它可以不加更改的用于任何类型的应用程序上,适用于任何类型的应用程序 - 从 WebSphere ND 和 SAP 到自定义 C 应用程序,再到静态链接的 <code>Golang</code> 应用程序。Linux/x86 是仅有的运行需求。</p>
|
||
<h3 id="decoupling-services-from-their-references">将服务与其引用分离</h3>
|
||
<p>AppSwitch 建立在应用程序应与其引用分离的基本前提之上。传统上,应用程序的标识源自它们运行的 主机的标识。但是,应用程序和主机是需要独立引用的非常不同的对象。本<a href="https://arxiv.org/abs/1711.02294">主题</a>介绍了围绕此主题的详细讨论以及 AppSwitch 的概念基础。</p>
|
||
<p>实现服务对象及其身份之间解耦的中央 AppSwitch 构造是 _service reference_(简称 <em>reference</em> )。AppSwitch 基于上面概述的 API 检测机制实现服务引用。服务引用由 IP:端口对(以及可选的 DNS 名称)和标签选择器组成,标签选择器选择引用所代表的服务以及此引用所适用的客户端。引用支持一些关键属性。(1)它的名称可以独立于它所引用的对象的名称。也就是说,服务可能正在侦听 IP 和端口,但是引用允许在用户选择的任何其他 IP 和端口上达到该服务。这使 AppSwitch 能够运行从源环境中捕获的传统应用程序,通过静态 IP 配置在 Kubernetes 上运行,为其提供必要的 IP 地址和端口,而不管目标网络环境如何。(2)即使目标服务的位置发生变化,它也保持不变。引用自动重定向自身,因为其标签选择器现在解析为新的服务实例(3)对于此讨论最重要的是,在目标服务的启动过程中,引用就已经生效了。</p>
|
||
<p>为了便于发现可通过服务引用访问的服务,AppSwitch 提供了一个 _auto-curated 服务注册表_。根据 AppSwitch 跟踪的网络 API,当服务进出群集时,注册表会自动保持最新。注册表中的每个条目都包含相应服务绑定的 IP 和端口。除此之外,它还包括一组标签,指示此服务所属的应用程序,应用程序在创建服务时通过 Socket API 传递的 IP 和端口,AppSwitch 实际绑定基础主机上的服务的 IP 和端口此外,在 AppSwitch 下创建的应用程序带有一组用户传递的标签,用于描述应用程序以及一些默认系统标签,指示创建应用程序的用户和运行应用程序的主机等。这些标签都可以在服务引用所携带的标签选择器中表示。通过创建服务引用,可以使客户端访问注册表中的服务。然后,客户端将能够以引用的名称(IP:端口)访问服务。现在让我们来看看 AppSwitch 如何在目标服务尚在启动的过程中就让服务引用开始生效的。</p>
|
||
<h3 id="non-blocking-requests">非阻塞请求</h3>
|
||
<p>AppSwitch 利用 BSD Socket API 的语义,确保服务引用从客户的角度看起来是有效的,因为相应的服务出现了。当客户端对一个尚未启动的服务发起阻塞式连接调用时,AppSwitch 会阻止该调用一段时间等待目标服务变为活动状态。由于已知目标服务是应用程序的一部分并且预计很快就会出现,因此客户端会被阻塞,而不是收到 ECONNREFUSED 之类的返回信息导致启动失败。如果服务没有及时出现,则会向应用程序返回一个错误,以便像 Kubernetes 崩溃循环这样的框架级机制可以启动。</p>
|
||
<p>如果客户端请求被标记为非阻塞,则 AppSwitch 通过返回 <code>EAGAIN</code> 来处理该请求以通知应用程序重试而不是放弃。再次,这与 Socket API 的语义一致,并防止由于启动竞争而导致的失败。AppSwitch 通过对 BSD Socket API 的支持,将重试逻辑内置到应用程序之中,从而透明的为应用提供了依赖排序支持。</p>
|
||
<h3 id="application-timeouts">应用程序超时</h3>
|
||
<p>如果应用程序基于其自己的内部计时器超时怎么办?说实话,如果需要,AppSwitch 还可以伪造应用程序对时间的感知,但这种做法不仅越界,而且并无必要。应用程序决定并知道它应该等待多长时间,这对 AppSwitch 来说是不合适的。应用程序超过保守时长,如果目标服务仍未及时出现,则不太可能是依赖性排序问题。一定是出现了其它问题,AppSwitch 不应掩盖这些问题。</p>
|
||
<h3 id="wildcard-service-references-for-sidecar-dependency">为 Sidecar 提供服务引用的通配符支持</h3>
|
||
<p>服务引用可用于解决前面提到的 Istio sidecar 依赖性问题。AppSwitch 用 IP:端口的方式来描述对服务的引用,这种描述中是可以使用通配符的。也就是说,服务引用描述中可以用 IP 掩码的形式来表达要捕捉的 IP 地址的范围。如果服务引用的标签选择器指向 sidecar 服务,则应用此服务引用的任何应用程序的所有传出连接将被透明地重定向到 sidecar。当然,在 Sidecar 启动过程中,服务引用仍然是有效的。</p>
|
||
<p>使用 sidecar 依赖性排序的服务引用也隐式地将应用程序的连接重定向到 sidecar ,而不需要 iptables 和随之而来的权限问题。基本上它就像应用程序直接连接到 sidecar 而不是目标目的地一样工作,让 sidecar 负责做什么。AppSwitch 将使用 sidecar 可以在将连接传递到应用程序之前解码的代理协议将关于原始目的地等的元数据插入到连接的数据流中。其中一些细节已在<a href="/v1.12/zh/blog/2018/delayering-istio/">此处</a>进行了讨论。出站连接是这样处理的,那么入站连接呢?由于所有服务及其 sidecar 都在 AppSwitch 下运行,因此来自远程节点的任何传入连接都将被重定向到各自的远程 sidecar 。所以传入连接没有什么特别处理。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>依赖顺序是一个讨厌的问题。这主要是由于无法访问有关服务间交互的细粒度应用程序级事件。解决这个问题通常需要应用程序来实现自己的内部逻辑。但 AppSwitch 使这些内部应用程序事件无需更改应用程序即可进行检测。然后,AppSwitch 利用对 BSD Socket API 的普遍支持来回避排序依赖关系的要求。</p>
|
||
<h2 id="acknowledgements">致谢</h2>
|
||
<p>感谢 Eric Herness 和团队对 IBM WebSphere 和 BPM 产品的见解和支持,我们将它们应用到现代化 Kubernetes 平台,还要感谢 Mandar Jog,Martin Taillefer 和 Shriram Rajagopalan 对于此博客早期草稿的评审。</p></description><pubDate>Mon, 14 Jan 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/appswitch/</link><author>Dinesh Subhraveti (AppOrbit and Columbia University)</author><guid isPermaLink="true">/v1.12/zh/blog/2019/appswitch/</guid><category>appswitch</category><category>performance</category></item><item><title>使用 cert-manager 部署一个自定义 Ingress 网关</title><description>
|
||
<p>本文介绍了手工创建自定义 Ingress <a href="/v1.12/zh/docs/reference/config/networking/gateway/">Gateway</a> 的过程,其中使用 cert-manager 完成了证书的自动管理。</p>
|
||
<p>自定义 Ingress 网关在使用不同负载均衡器来隔离通信的情况下很有帮助。</p>
|
||
<h2 id="before-you-begin">开始之前</h2>
|
||
<ul>
|
||
<li>根据<a href="/v1.12/zh/docs/setup/">安装指南</a>完成 Istio 的部署。</li>
|
||
<li>用 Helm <a href="https://github.com/helm/charts/tree/master/stable/cert-manager#installing-the-chart">Chart</a> 部署 <code>cert-manager</code>。</li>
|
||
<li>我们会使用 <code>demo.mydemo.com</code> 进行演示,因此您的 DNS 解析要能够解析这个域名。</li>
|
||
</ul>
|
||
<h2 id="configuring-the-custom-ingress-gateway">配置自定义 Ingress 网关</h2>
|
||
<ol>
|
||
<li><p>用下面的 <code>helm</code> 命令检查 <a href="https://github.com/helm/charts/tree/master/stable/cert-manager">cert-manager</a> 是否已经完成部署:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm ls
|
||
</code></pre>
|
||
<p>该命令的输出大概如下所示,其中的 <code>cert-manager</code> 的 <code>STATUS</code> 字段应该是 <code>DEPLOYED</code></p>
|
||
<pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||
istio 1 Thu Oct 11 13:34:24 2018 DEPLOYED istio-1.0.X 1.0.X istio-system
|
||
cert 1 Wed Oct 24 14:08:36 2018 DEPLOYED cert-manager-v0.6.0-dev.2 v0.6.0-dev.2 istio-system
|
||
</code></pre></li>
|
||
<li><p>要创建集群的证书签发者,可以使用如下的配置:</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">用自己的配置修改集群的<a href="https://cert-manager.readthedocs.io/en/latest/reference/issuers.html">证书签发者</a>。例子中使用的是 <code>route53</code>。</div>
|
||
</aside>
|
||
</div>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: certmanager.k8s.io/v1alpha1
|
||
kind: ClusterIssuer
|
||
metadata:
|
||
name: letsencrypt-demo
|
||
namespace: kube-system
|
||
spec:
|
||
acme:
|
||
# ACME 服务器地址
|
||
server: https://acme-v02.api.letsencrypt.org/directory
|
||
# ACME 注册的 Email 地址
|
||
email: &lt;REDACTED&gt;
|
||
# Secret 的名字,用于保存 ACME 账号的私钥
|
||
privateKeySecretRef:
|
||
name: letsencrypt-demo
|
||
dns01:
|
||
# 这里定义了一个列表,包含了 DNS-01 的相关内容,用于应对 DNS Challenge。
|
||
providers:
|
||
- name: your-dns
|
||
route53:
|
||
accessKeyID: &lt;REDACTED&gt;
|
||
region: eu-central-1
|
||
secretAccessKeySecretRef:
|
||
name: prod-route53-credentials-secret
|
||
key: secret-access-key
|
||
</code></pre></li>
|
||
<li><p>如果使用的是 <code>route53</code> <a href="https://cert-manager.readthedocs.io/en/latest/tasks/acme/configuring-dns01/route53.html">Provider</a>,必须提供一个 Secret 来进行 DNS 的 ACME 验证。可以使用下面的配置来创建需要的 Secret:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: prod-route53-credentials-secret
|
||
type: Opaque
|
||
data:
|
||
secret-access-key: &lt;REDACTED BASE64&gt;
|
||
</code></pre></li>
|
||
<li><p>创建自己的证书:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: certmanager.k8s.io/v1alpha1
|
||
kind: Certificate
|
||
metadata:
|
||
name: demo-certificate
|
||
namespace: istio-system
|
||
spec:
|
||
acme:
|
||
config:
|
||
- dns01:
|
||
provider: your-dns
|
||
domains:
|
||
- &#39;*.mydemo.com&#39;
|
||
commonName: &#39;*.mydemo.com&#39;
|
||
dnsNames:
|
||
- &#39;*.mydemo.com&#39;
|
||
issuerRef:
|
||
kind: ClusterIssuer
|
||
name: letsencrypt-demo
|
||
secretName: istio-customingressgateway-certs
|
||
</code></pre>
|
||
<p>记录一下 <code>secretName</code> 的值,后面会使用它。</p></li>
|
||
<li><p>要进行自动扩容,可以新建一个 HPA 对象:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: autoscaling/v1
|
||
kind: HorizontalPodAutoscaler
|
||
metadata:
|
||
name: my-ingressgateway
|
||
namespace: istio-system
|
||
spec:
|
||
maxReplicas: 5
|
||
minReplicas: 1
|
||
scaleTargetRef:
|
||
apiVersion: apps/v1beta1
|
||
kind: Deployment
|
||
name: my-ingressgateway
|
||
targetCPUUtilizationPercentage: 80
|
||
status:
|
||
currentCPUUtilizationPercentage: 0
|
||
currentReplicas: 1
|
||
desiredReplicas: 1
|
||
</code></pre></li>
|
||
<li><p>使用<a href="/v1.12/zh/blog/2019/custom-ingress-gateway/deployment-custom-ingress.yaml">附件 YAML 中的定义</a>进行部署。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">其中类似 <code>aws-load-balancer-type</code> 这样的注解,只对 AWS 生效。</div>
|
||
</aside>
|
||
</div>
|
||
</li>
|
||
<li><p>创建您的服务:</p>
|
||
<div>
|
||
<aside class="callout warning">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-warning"/></svg>
|
||
</div>
|
||
<div class="content"><code>NodePort</code> 需要是一个可用端口。</div>
|
||
</aside>
|
||
</div>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: my-ingressgateway
|
||
annotations:
|
||
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
||
labels:
|
||
app: my-ingressgateway
|
||
istio: my-ingressgateway
|
||
spec:
|
||
type: LoadBalancer
|
||
selector:
|
||
app: my-ingressgateway
|
||
istio: my-ingressgateway
|
||
ports:
|
||
-
|
||
name: http2
|
||
nodePort: 32380
|
||
port: 80
|
||
targetPort: 80
|
||
-
|
||
name: https
|
||
nodePort: 32390
|
||
port: 443
|
||
-
|
||
name: tcp
|
||
nodePort: 32400
|
||
port: 31400
|
||
</code></pre></li>
|
||
<li><p>创建您的自定义 Ingress 网关配置对象:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
annotations:
|
||
name: istio-custom-gateway
|
||
namespace: default
|
||
spec:
|
||
selector:
|
||
istio: my-ingressgateway
|
||
servers:
|
||
- hosts:
|
||
- &#39;*.mydemo.com&#39;
|
||
port:
|
||
name: http
|
||
number: 80
|
||
protocol: HTTP
|
||
tls:
|
||
httpsRedirect: true
|
||
- hosts:
|
||
- &#39;*.mydemo.com&#39;
|
||
port:
|
||
name: https
|
||
number: 443
|
||
protocol: HTTPS
|
||
tls:
|
||
mode: SIMPLE
|
||
privateKey: /etc/istio/ingressgateway-certs/tls.key
|
||
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
|
||
</code></pre></li>
|
||
<li><p>使用 <code>VirtualService</code> 连接 <code>istio-custom-gateway</code>:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: my-virtualservice
|
||
spec:
|
||
hosts:
|
||
- &#34;demo.mydemo.com&#34;
|
||
gateways:
|
||
- istio-custom-gateway
|
||
http:
|
||
- route:
|
||
- destination:
|
||
host: my-demoapp
|
||
</code></pre></li>
|
||
<li><p>服务器返回了正确的证书,并成功完成验证(<code>SSL certificate verify ok</code>):</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl -v `https://demo.mydemo.com`
|
||
Server certificate:
|
||
SSL certificate verify ok.
|
||
</code></pre></li>
|
||
</ol>
|
||
<p><strong>恭喜您!</strong> 现在您可以使用自定义的 <code>istio-custom-gateway</code> <a href="/v1.12/zh/docs/reference/config/networking/gateway/">网关</a>对象了。</p></description><pubDate>Thu, 10 Jan 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/custom-ingress-gateway/</link><author>Julien Senon</author><guid isPermaLink="true">/v1.12/zh/blog/2019/custom-ingress-gateway/</guid><category>ingress</category><category>traffic-management</category></item><item><title>Istio 论坛成立</title><description><p>我们在 Istio 论坛中一直努力寻找合适的方法,让用户与论坛的其他成员进行互动、交流,寻求其他用户的帮助,以及与该项目的开发者进行沟通。</p>
|
||
<p>我们尝试了几种不同的途径,但是每种途径都有一些不足。RocketChat 是我们最近的工作,但是缺少某些功能(例如,线程方面),意味着它不再适合围绕任何单一问题进行讨论。这也给一些用户带来了困惑:什么时候应该向 <code>istio-users@googlegroups.com</code> 发送电子邮件,什么时候又该使用 RocketChat?</p>
|
||
<p>我们认为我们已经在单一的平台上找到了正确平衡功能,因此我们很高兴地宣布 <a href="https://discuss.istio.io">discuss.istio.io</a> 论坛成立。这是一个功能全面的论坛,我们将从这里开始对 Istio 进行讨论沟通,它允许您提出问题并获得主题回复!真正的好处是,您可以使用您的 GitHub 身份进行这些操作。</p>
|
||
<p>如果您喜欢使用电子邮件,那么您可以将其配置为用电子邮件去发送,就像 Google Groups 一样。</p>
|
||
<p>我们会将 Google Groups 标记为“只读”,以便保留其原始内容,但是请您将其它问题发送到 <a href="https://discuss.istio.io">discuss.istio.io</a>。如果在您的小组中有任何未解决的问题或讨论,请结束讨论。</p></description><pubDate>Thu, 10 Jan 2019 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2019/announcing-discuss.istio.io/</link><author/><guid isPermaLink="true">/v1.12/zh/blog/2019/announcing-discuss.istio.io/</guid></item><item><title>增量式应用 Istio 第一部分,流量管理</title><description>
|
||
<p>流量管理是 Istio 提供的重要优势之一。Istio 流量管理的核心是在将通信流量和基础设施的伸缩进行解耦。如果没有 Istio 这样的服务网格,这种流量控制方式是不可能实现的。</p>
|
||
<p>例如,您希望执行一次<a href="https://martinfowler.com/bliki/CanaryRelease.html">金丝雀发布</a>。当使用 Istio 时,您可以指定 service 的 <strong>v1</strong> 版本接收 90% 的传入流量,而该 service <strong>v2</strong> 版本仅接收 10%。如果使用标准的 Kubernetes deployment,实现此目的的唯一方法是手动控制每个版本的可用 Pod 数量,例如使 9 个 Pod 运行 v1 版本,使 1 个 Pod 运行 v2 版本。这种类型的手动控制难以实现,并且随着时间的推移可能无法扩展。有关更多信息,请查看<a href="/v1.12/zh/blog/2017/0.1-canary/">使用 Istio 进行金丝雀发布</a>。</p>
|
||
<p>部署现有 service 的更新时存在同样的问题。虽然您可以使用 Kubernetes 更新 deployment,但它需要将 v1 Pod 替换为 v2 Pod。使用 Istio,您可以部署 service 的 v2 版本,并使用内置流量管理机制在网络层面将流量转移到更新后的 service,然后删除 v1 版本的 Pod。</p>
|
||
<p>除了金丝雀发布和一般流量转移之外,Istio 还使您能够实现动态请求路由(基于 HTTP header)、故障恢复、重试、断路器和故障注入。有关更多信息,请查看<a href="/v1.12/zh/docs/concepts/traffic-management/">流量管理文档</a>。</p>
|
||
<p>这篇文章介绍的技术重点突出了一种特别有用的方法,可以逐步实现 Istio(在这种情况下,只有流量管理功能),而无需单独更新每个 Pod。</p>
|
||
<h2 id="setup-why-implement-Istio-traffic-management-features">设置:为什么要实施 Istio 流量管理功能?</h2>
|
||
<p>当然,第一个问题是:为什么要这样做?</p>
|
||
<p>如果你是众多拥有大量团队和大型集群的组织中的一员,那么答案是很清楚的。假设 A 团队正在开始使用 Istio,并希望在 service A 上开始一些金丝雀发布,但是 B 团队还没有开始使用 Istio,所以他们没有部署 sidecar。</p>
|
||
<p>使用 Istio,A 团队仍然可以让 service B 通过 Istio 的 ingress gateway 调用 service A 来实现他们的金丝雀发布。</p>
|
||
<h2 id="background-traffic-routing-in-an-Istio-mesh">背景:Istio 网格中的流量路由</h2>
|
||
<p>但是,如何在不更新每个应用程序的 Pod 的情况下,使用 Istio 的流量管理功能来包含 Istio sidecar?在回答这个问题之前,让我们以高层视角,快速地看看流量如何进入 Istio 网格以及如何被路由。</p>
|
||
<p>Pod 包含一个 sidecar 代理,该代理作为 Istio 网格的一部分,负责协调 Pod 的所有入站和出站流量。在 Istio 网格中,Pilot 负责将高级路由规则转换为配置并将它们传播到 sidecar 代理。这意味着当服务彼此通信时,它们的路由决策是由客户端确定的。</p>
|
||
<p>假设您有 service A 和 service B 两个服务,他们是 Istio 网格的一部分。当 A 想要与 B 通信时,Pod A 的 sidecar 代理负责将流量引导到 service B。例如,如果你希望到 service B v1 版本和 v2 版本之间的流量按 <sup>50</sup>&frasl;<sub>50</sub> 分割,流量将按如下方式流动:</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:42.66666666666667%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/incremental-traffic-management/fifty-fifty.png" title="50/50 流量分割">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/incremental-traffic-management/fifty-fifty.png" alt="50/50 流量分割" />
|
||
</a>
|
||
</div>
|
||
<figcaption>50/50 流量分割</figcaption>
|
||
</figure>
|
||
<p>如果 service A 和 B 不是 Istio 网格的一部分,则没有 sidecar 代理知道如何将流量路由到 service B 的不同版本。在这种情况下,您需要使用另一种方法来使 service A 到 service B 的流量遵循您设置的 <sup>50</sup>&frasl;<sub>50</sub> 规则。</p>
|
||
<p>幸运的是,标准的 Istio 部署已经包含了一个 <a href="/v1.12/zh/docs/concepts/traffic-management/#gateways">Gateway</a>,它专门处理 Istio 网格之外的入口流量。此 Gateway 用于允许通过外部负载均衡器进入的集群外部入口流量;或来自 Kubernetes 集群,但在服务网格之外的入口流量。网关可以进行配置,对没有 Sidecar 支持的入口流量进行代理,引导流量进入相应的 Pod。这种方法允许您利用 Istio 的流量管理功能,其代价是通过入口网关的流量将产生额外的跃点。</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:54.83870967741935%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/incremental-traffic-management/fifty-fifty-ingress-gateway.png" title="使用 Ingress Gateway 的 50/50 流量分割">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/incremental-traffic-management/fifty-fifty-ingress-gateway.png" alt="使用 Ingress Gateway 的 50/50 流量分割" />
|
||
</a>
|
||
</div>
|
||
<figcaption>使用 Ingress Gateway 的 50/50 流量分割</figcaption>
|
||
</figure>
|
||
<h2 id="in-action-traffic-routing-with-Istio">实践:Istio 流量路由</h2>
|
||
<p>一种实践的简单方法是首先按照<a href="/v1.12/zh/docs/setup/platform-setup/">平台设置</a>说明设置 Kubernetes 环境,然后使用 <a href="/v1.12/zh/docs/setup/install/helm/">Helm</a> 安装仅包含流量管理组件(ingress gateway、egress gateway、Pilot)的 Istio。下面的示例使用 <a href="https://cloud.google.com/gke">Google Kubernetes Engine</a>。</p>
|
||
<p>首先,安装并配置 <a href="/v1.12/zh/docs/setup/platform-setup/gke/">GKE</a>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ gcloud container clusters create istio-inc --zone us-central1-f
|
||
$ gcloud container clusters get-credentials istio-inc
|
||
$ kubectl create clusterrolebinding cluster-admin-binding \
|
||
--clusterrole=cluster-admin \
|
||
--user=$(gcloud config get-value core/account)
|
||
</code></pre>
|
||
<p>然后,<a href="https://helm.sh/docs/intro/install/">安装 Helm</a> 并<a href="/v1.12/zh/docs/setup/install/helm/">生成 Istio 最小配置安装</a> &ndash; 只有流量管理组件:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm template install/kubernetes/helm/istio \
|
||
--name istio \
|
||
--namespace istio-system \
|
||
--set security.enabled=false \
|
||
--set galley.enabled=false \
|
||
--set sidecarInjectorWebhook.enabled=false \
|
||
--set mixer.enabled=false \
|
||
--set prometheus.enabled=false \
|
||
--set pilot.sidecar=false &gt; istio-minimal.yaml
|
||
</code></pre>
|
||
<p>然后创建 <code>istio-system</code> namespace 并部署 Istio:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl create namespace istio-system
|
||
$ kubectl apply -f istio-minimal.yaml
|
||
</code></pre>
|
||
<p>然后,在没有 Istio sidecar 容器的前提下部署 Bookinfo 示例:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo.yaml@
|
||
</code></pre></div>
|
||
<p>现在,配置一个新的 Gateway 允许从 Istio 网格外部访问 reviews service;一个新的 <code>VirtualService</code> 用于平均分配到 reviews service v1 和 v2 版本的流量;以及一系列新的、将目标子集与服务版本相匹配的 <code>DestinationRule</code> 资源:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: reviews-gateway
|
||
spec:
|
||
selector:
|
||
istio: ingressgateway # 使用 istio 默认控制器
|
||
servers:
|
||
- port:
|
||
number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
hosts:
|
||
- &#34;*&#34;
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
hosts:
|
||
- &#34;*&#34;
|
||
gateways:
|
||
- reviews-gateway
|
||
http:
|
||
- match:
|
||
- uri:
|
||
prefix: /reviews
|
||
route:
|
||
- destination:
|
||
host: reviews
|
||
subset: v1
|
||
weight: 50
|
||
- destination:
|
||
host: reviews
|
||
subset: v2
|
||
weight: 50
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
host: reviews
|
||
subsets:
|
||
- name: v1
|
||
labels:
|
||
version: v1
|
||
- name: v2
|
||
labels:
|
||
version: v2
|
||
- name: v3
|
||
labels:
|
||
version: v3
|
||
EOF
|
||
</code></pre>
|
||
<p>最后,使用 <code>curl</code> 部署一个用于测试的 Pod(没有 Istio sidecar 容器):</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/sleep/sleep.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/sleep/sleep.yaml@
|
||
</code></pre></div>
|
||
<h2 id="testing-your-deployment">测试您的部署</h2>
|
||
<p>现在就可以通过 Sleep pod 使用 curl 命令来测试不同的行为了。</p>
|
||
<p>第一个示例是使用标准 Kubernetes service DNS 行为向 reviews service 发出请求(<strong>注意</strong>:下面的示例中使用了 <a href="https://stedolan.github.io/jq/"><code>jq</code></a> 来过滤 <code>curl</code> 的输出):</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export SLEEP_POD=$(kubectl get pod -l app=sleep \
|
||
-o jsonpath={.items..metadata.name})
|
||
$ for i in `seq 3`; do \
|
||
kubectl exec -it $SLEEP_POD curl http://reviews:9080/reviews/0 | \
|
||
jq &#39;.reviews|.[]|.rating?&#39;; \
|
||
done
|
||
</code></pre>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;stars&#34;: 5,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
{
|
||
&#34;stars&#34;: 4,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
null
|
||
null
|
||
{
|
||
&#34;stars&#34;: 5,
|
||
&#34;color&#34;: &#34;red&#34;
|
||
}
|
||
{
|
||
&#34;stars&#34;: 4,
|
||
&#34;color&#34;: &#34;red&#34;
|
||
}
|
||
</code></pre>
|
||
<p>请注意我们是如何从 reviews service 的所有三个版本获得响应(<code>null</code> 来自 reviews v1 版本,它没有评级数据)并且流量没有在 v1 和 v2 版本间平均拆分。这是预期的行为,因为 <code>curl</code> 命令在 reviews service 所有三个版本之间进行 Kubernetes service 负载均衡。为了以 <sup>50</sup>&frasl;<sub>50</sub> 的流量拆分形式访问 reviews,我们需要通过 ingress Gateway 访问 service:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ for i in `seq 4`; do \
|
||
kubectl exec -it $SLEEP_POD curl http://istio-ingressgateway.istio-system/reviews/0 | \
|
||
jq &#39;.reviews|.[]|.rating?&#39;; \
|
||
done
|
||
</code></pre>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;stars&#34;: 5,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
{
|
||
&#34;stars&#34;: 4,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
null
|
||
null
|
||
{
|
||
&#34;stars&#34;: 5,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
{
|
||
&#34;stars&#34;: 4,
|
||
&#34;color&#34;: &#34;black&#34;
|
||
}
|
||
null
|
||
null
|
||
</code></pre>
|
||
<p>任务完成!这篇文章展示了如何部署仅包含流量管理组件(Pilot、ingress Gateway)的 Istio 的最小安装,然后使用这些组件将流量定向到特定版本的 reviews service。由于不是必须通过部署 Istio sidecar 代理来获得这些功能,因此几乎没有给现有工作负载或应用程序造成中断。</p>
|
||
<p>这篇文章展示了如何利用 Istio 及内置的 ingress Gateway(以及一些 <code>VirtualService</code> 和 <code>DestinationRule</code> 资源),轻松实现集群外部入口流量和集群内部服务到服务的流量管理。这种技术是增量式应用 Istio 的一个很好的例子,在 Pod 由不同团队拥有,或部署到不同命名空间的现实案例中尤其有用。</p></description><pubDate>Wed, 21 Nov 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/incremental-traffic-management/</link><author>Sandeep Parikh</author><guid isPermaLink="true">/v1.12/zh/blog/2018/incremental-traffic-management/</guid><category>traffic-management</category><category>gateway</category></item><item><title>使用外部 MongoDB 服务</title><description>
|
||
<p>在<a href="/v1.12/zh/blog/2018/egress-tcp/">使用外部 TCP 服务</a>博文中,我描述了网格内的 Istio 应用程序如何通过 TCP 使用外部服务。在本文中,我将演示如何使用外部 MongoDB
|
||
服务。您将使用 <a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>,它的书籍评级数据保存在 MongoDB 数据库中。您会将此数据库部署在集群外部,并配置 <code>ratings</code>
|
||
微服务使用它。您将学习控制到外部 MongoDB 服务流量的多种选择及其利弊。</p>
|
||
<h2 id="Bookinfo-with-external-ratings-database">使用外部 ratings 数据库的 Bookinfo</h2>
|
||
<p>首先,在您的 Kubernetes 集群外部建立一个 MongoDB 数据库实例以保存书籍评级数据。然后修改 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo 示例应用程序</a>使用该数据库。</p>
|
||
<h3 id="setting-up-the-ratings-database">建立 ratings 数据库</h3>
|
||
<p>在这个任务中您将建立一个 <a href="https://www.mongodb.com">MongoDB</a> 实例。您可以使用任何 MongoDB 实例;我使用 <a href="https://www.ibm.com/cloud/compose/mongodb">Compose for MongoDB</a>。</p>
|
||
<ol>
|
||
<li><p>为 <code>admin</code> 用户的密码设置一个环境变量。为了避免密码被保存在 Bash 历史记录中,在运行命令之后,请立即使用 <a href="https://www.gnu.org/software/bash/manual/html_node/Bash-History-Builtins.html#Bash-History-Builtins">history -d</a> 将其从历史记录中删除。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export MONGO_ADMIN_PASSWORD=&lt;your MongoDB admin password&gt;
|
||
</code></pre></li>
|
||
<li><p>为需要创建的新用户(即 <code>bookinfo</code>)的密码设置环境变量,并使用 <a href="https://www.gnu.org/software/bash/manual/html_node/Bash-History-Builtins.html#Bash-History-Builtins">history -d</a> 将其从历史记录中删除。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export BOOKINFO_PASSWORD=&lt;password&gt;
|
||
</code></pre></li>
|
||
<li><p>为您的 MongoDB 服务设置环境变量 <code>MONGODB_HOST</code> 和 <code>MONGODB_PORT</code>。</p></li>
|
||
<li><p>创建 <code>bookinfo</code> 用户:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | mongo --ssl --sslAllowInvalidCertificates $MONGODB_HOST:$MONGODB_PORT -u admin -p $MONGO_ADMIN_PASSWORD --authenticationDatabase admin
|
||
use test
|
||
db.createUser(
|
||
{
|
||
user: &#34;bookinfo&#34;,
|
||
pwd: &#34;$BOOKINFO_PASSWORD&#34;,
|
||
roles: [ &#34;read&#34;]
|
||
}
|
||
);
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>创建一个 <em>collection</em> 来保存评级数据。以下命令将两个评级都设置为 <code>1</code>,以便在 Bookinfo <em>ratings</em> service 使用数据库时提供视觉验证(默认 Bookinfo <em>ratings</em>
|
||
为 <code>4</code> 和 <code>5</code>)</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | mongo --ssl --sslAllowInvalidCertificates $MONGODB_HOST:$MONGODB_PORT -u admin -p $MONGO_ADMIN_PASSWORD --authenticationDatabase admin
|
||
use test
|
||
db.createCollection(&#34;ratings&#34;);
|
||
db.ratings.insert(
|
||
[{rating: 1},
|
||
{rating: 1}]
|
||
);
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>检查 <code>bookinfo</code> 用户是否可以获取评级数据:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | mongo --ssl --sslAllowInvalidCertificates $MONGODB_HOST:$MONGODB_PORT -u bookinfo -p $BOOKINFO_PASSWORD --authenticationDatabase test
|
||
use test
|
||
db.ratings.find({});
|
||
EOF
|
||
</code></pre></li>
|
||
</ol>
|
||
<p>输出应该类似于:</p>
|
||
<pre><code><pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >MongoDB server version: 3.4.10
|
||
switched to db test
|
||
{ &#34;_id&#34; : ObjectId(&#34;5b7c29efd7596e65b6ed2572&#34;), &#34;rating&#34; : 1 }
|
||
{ &#34;_id&#34; : ObjectId(&#34;5b7c29efd7596e65b6ed2573&#34;), &#34;rating&#34; : 1 }
|
||
bye
|
||
</code></pre></code></pre>
|
||
<h3 id="Initial-setting-of-Bookinfo-application">Bookinfo 应用程序的初始设置</h3>
|
||
<p>为了演示使用外部数据库的场景,请首先运行一个<a href="/v1.12/zh/docs/setup/getting-started/">安装了 Istio</a> 的 Kubernetes 集群。然后部署
|
||
<a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>并<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">应用默认 destination rules</a> 和<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-control/#change-to-the-blocking-by-default-policy">改变 Istio 到 blocking-egress-by-default 策略</a>。</p>
|
||
<p>此应用程序从 <code>ratings</code> 微服务获取书籍评级(1 到 5 的数字)。评级以星标形式显示每条评论。<code>ratings</code> 微服务有几个版本。在下一小节中,请部署使用 <a href="https://www.mongodb.com">MongoDB</a>
|
||
作为 ratings 数据库的版本。</p>
|
||
<p>本博文中的示例命令适用于 Istio 1.0。</p>
|
||
<p>作为提醒,这是 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo 示例应用程序</a>的端到端架构。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.086918235567985%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/docs/examples/bookinfo/withistio.svg" title="The original Bookinfo application">
|
||
<img class="element-to-stretch" src="/v1.12/zh/docs/examples/bookinfo/withistio.svg" alt="The original Bookinfo application" />
|
||
</a>
|
||
</div>
|
||
<figcaption>The original Bookinfo application</figcaption>
|
||
</figure>
|
||
<h3 id="use-the-external-database-in-Bookinfo-application">在 Bookinfo 应用程序中使用外部数据库</h3>
|
||
<ol>
|
||
<li><p>部署使用 MongoDB 数据库的 <em>ratings</em> 微服务(_ratings v2_):</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml@
|
||
serviceaccount &#34;bookinfo-ratings-v2&#34; created
|
||
deployment &#34;ratings-v2&#34; created
|
||
</code></pre></div></li>
|
||
<li><p>为你的 MongoDB 设置 <code>MONGO_DB_URL</code> 环境变量:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl set env deployment/ratings-v2 &#34;MONGO_DB_URL=mongodb://bookinfo:$BOOKINFO_PASSWORD@$MONGODB_HOST:$MONGODB_PORT/test?authSource=test&amp;ssl=true&#34;
|
||
deployment.extensions/ratings-v2 env updated
|
||
</code></pre></li>
|
||
<li><p>将所有到 <em>reviews</em> service 的流量路由到它的 <em>v3</em> 版本,以确保 <em>reviews</em> service 总是调用 <em>ratings</em> service。此外,将所有到 <code>ratings</code> service
|
||
的流量路由到使用外部数据库的 _ratings v2_。</p></li>
|
||
</ol>
|
||
<p>通过添加两个 <a href="/v1.12/zh/docs/reference/config/networking/virtual-service/">virtual services</a> 来为以上两个 services 指定路由。这些 virtual service
|
||
在 Istio 发布包中 <code>samples/bookinfo/networking/virtual-service-ratings-mongodb.yaml</code> 有指定 。
|
||
<strong><em>重要:</em></strong> 请确保在运行以下命令之前<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">应用了默认的 destination rules</a>。</p>
|
||
<pre><code><div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-ratings-db.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/networking/virtual-service-ratings-db.yaml@
|
||
</code></pre></div></code></pre>
|
||
<p>更新的架构如下所示。请注意,网格内的蓝色箭头标记对应于我们添加的 virtual service。根据 virtual service,流量将被发送到 <code>reviews v3</code> 和 <code>ratings v2</code>。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.314858206480224%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-mongo/bookinfo-ratings-v2-mongodb-external.svg" title="The Bookinfo application with ratings v2 and an external MongoDB database">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-mongo/bookinfo-ratings-v2-mongodb-external.svg" alt="The Bookinfo application with ratings v2 and an external MongoDB database" />
|
||
</a>
|
||
</div>
|
||
<figcaption>The Bookinfo application with ratings v2 and an external MongoDB database</figcaption>
|
||
</figure>
|
||
<p>请注意,MongoDB 数据库位于 Istio 服务网格之外,或者更确切地说是在 Kubernetes 集群之外。服务网格的边界使用虚线标记。</p>
|
||
<h3 id="access-the-webpage">访问网页</h3>
|
||
<p><a href="/v1.12/zh/docs/examples/bookinfo/#determine-the-ingress-IP-and-port">确认 ingress IP 和端口之后</a>,访问应用程序的网页。</p>
|
||
<p>由于您尚未配置 egress 流量控制,所以 Istio 会阻止到 MongoDB 服务的访问。这就是为什么您当前不能看到评级的星标,只能看到 <em>&ldquo;Ratings service is currently unavailable&rdquo;</em> 的信息:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:36.18705035971223%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-mongo/errorFetchingBookRating.png" title="The Ratings service error messages">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-mongo/errorFetchingBookRating.png" alt="The Ratings service error messages" />
|
||
</a>
|
||
</div>
|
||
<figcaption>The Ratings service error messages</figcaption>
|
||
</figure>
|
||
<p>在以下部分中,您将使用不同的 Istio egress 控制选项,配置对外部 MongoDB 服务的访问。</p>
|
||
<h2 id="egress-control-for-TCP">TCP 的 egress 控制</h2>
|
||
<p>由于 <a href="https://zh/docs.mongodb.com/manual/reference/mongodb-wire-protocol/">MongoDB 协议</a>运行在 TCP 之上,您可以像控制到<a href="/v1.12/zh/blog/2018/egress-tcp/">其余 TCP 服务</a>的流量一样控制到 MongoDB 的 egress 流量。为了控制 TCP 流量,您必须指定一个 <a href="https://tools.ietf.org/html/rfc2317">CIDR</a> 表示的 IP 块,该 IP 块包含 MongoDB 的地址。需要注意的是,有时候 MongoDB 主机的 IP 并不稳定或无法事先得知。</p>
|
||
<p>在 MongoDB IP 不稳定的情况下,可以以 <a href="#egress-control-for-TLS">TLS 方式控制</a> egress 流量,或绕过 Istio sidecar <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-control/#direct-access-to-external-services">直接</a>路由流量。</p>
|
||
<p>获取 MongoDB 数据库实例的 IP 地址。一种选择是使用 <a href="https://linux.die.net/man/1/host">host</a> 命令。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export MONGODB_IP=$(host $MONGODB_HOST | grep &#34; has address &#34; | cut -d&#34; &#34; -f4)
|
||
</code></pre>
|
||
<h3 id="control-TCP-egress-traffic-without-a-gateway">在没有 gateway 的情况下控制 TCP egress 流量</h3>
|
||
<p>如果您不用通过 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#use-case">egress gateway</a> 定向流量,例如不要求所有流量都通过 gateway 流出网格时,请遵循以下部分的说明。或者,如果您确实希望通过 egress gateway 定向流量,请继续阅读<a href="#direct-tcp-egress-traffic-through-an-egress-gateway">通过 egress gateway 定向 TCP egress 流量</a>。</p>
|
||
<ol>
|
||
<li><p>定义一个网格外 TCP service entry:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
hosts:
|
||
- my-mongo.tcp.svc
|
||
addresses:
|
||
- $MONGODB_IP/32
|
||
ports:
|
||
- number: $MONGODB_PORT
|
||
name: tcp
|
||
protocol: TCP
|
||
location: MESH_EXTERNAL
|
||
resolution: STATIC
|
||
endpoints:
|
||
- address: $MONGODB_IP
|
||
EOF
|
||
</code></pre></li>
|
||
</ol>
|
||
<p>请注意,protocol 被指定为 <code>TCP</code> 而不是 <code>MONGO</code>,因为如果 <a href="https://zh/docs.mongodb.com/manual/tutorial/configure-ssl/">MongoDB 协议运行在 TLS 之上时</a>,流量可以加密。如果加密了流量,该加密的 MongoDB 协议就不能被 Istio 代理解析。</p>
|
||
<p>如果您知道使用的是未加密的 MongoDB 协议,可以指定 protocol 为 <code>MONGO</code>,从而使 Istio 代理产生 <a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/mongo_proxy_filter#statistics">MongoDB 相关的统计数据</a>。还要注意,当指定 protocol <code>TCP</code> 时,配置不是特定于 MongoDB 的,对于其余使用基于 TCP 协议的数据库同样适用。</p>
|
||
<ol>
|
||
<li><p>刷新应用程序的网页。应用程序现在应该显示评级数据而非错误:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:36.69064748201439%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-mongo/externalDBRatings.png" title="Book Ratings Displayed Correctly">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-mongo/externalDBRatings.png" alt="Book Ratings Displayed Correctly" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Book Ratings Displayed Correctly</figcaption>
|
||
</figure></li>
|
||
</ol>
|
||
<p>请注意,和预期的一样,您会看到两个显示评论的一星评级。您将评级设置为一星,以作为外部数据库确实被使用了的视觉证据。</p>
|
||
<ol>
|
||
<li>如果要通过出口网关引导流量,请继续下一节。否则,请执行 <a href="#cleanup-of-TCP-egress-traffic-control">cleanup</a>.</li>
|
||
</ol>
|
||
<h3 id="direct-TCP-egress-traffic-through-an-egress-gateway">通过 egress gateway 定向 TCP Egress 流量</h3>
|
||
<p>在本节中,您将处理通过 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#use-case">egress gateway</a> 定向流量的情况。Sidecar 代理通过匹配 MongoDB 主机的 IP 地址(一个 32 位长度的 CIDR 块),将 TCP 连接从 MongoDB 客户端路由到 egress gateway。Egress gateway 按照其 hostname,转发流量到 MongoDB 主机。</p>
|
||
<ol>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#deploy-Istio-egress-gateway">部署 Istio egress gateway</a>.</p></li>
|
||
<li><p>如果您未执行<a href="#control-TCP-egress-traffic-without-a-gateway">上一节</a>中的步骤,则立即执行这些步骤。</p></li>
|
||
<li><p>您可能希望启用 sidecar 代理和 MongoDB 客户端之间以及 egress gateway 的 <span class="term" data-title="Mutual TLS Authentication" data-body="&lt;p&gt;双向 TLS 通过内置身份和凭证管理,提供强大的服务到服务身份验证。
|
||
&lt;a href=&#34;/zh/docs/concepts/security/#mutual-TLS-authentication&#34;&gt;了解更多关于双向 TLS 身份验证&lt;/a&gt;。&lt;/p&gt;
|
||
">mutual TLS Authentication</span>,以使 egress gateway 监控来源 pod 的身份并基于该 identity 启用 Mixer 策略。启用双向 TLS 时同样对流量进行了加密。
|
||
如果你不想开启双向 TLS,参考 <a href="#mutual-TLS-between-the-sidecar-proxies-and-the-egress-gateway">Mutual TLS between the sidecar proxies and the egress gateway</a> 小节
|
||
否则,请继续以下部分。</p></li>
|
||
</ol>
|
||
<h4 id="configure-TCP-traffic-from-sidecars-to-the-egress-gateway">配置从 sidecar 到 egress gateway 的 TCP 流量</h4>
|
||
<ol>
|
||
<li><p>定义 <code>EGRESS_GATEWAY_MONGODB_PORT</code> 环境变量来保存用于通过 egress gateway 定向流量的端口,例如 <code>7777</code>。必须选择没有被网格中其余 service 使用的端口。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export EGRESS_GATEWAY_MONGODB_PORT=7777
|
||
</code></pre></li>
|
||
<li><p>添加选择的端口到 <code>istio-egressgateway</code> service。您需要使用和安装 Istio 时一样的端口,特别是必须指定前面配置 <code>istio-egressgateway</code> 的所有端口。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm template install/kubernetes/helm/istio/ --name istio-egressgateway --namespace istio-system -x charts/gateways/templates/deployment.yaml -x charts/gateways/templates/service.yaml --set gateways.istio-ingressgateway.enabled=false --set gateways.istio-egressgateway.enabled=true --set gateways.istio-egressgateway.ports[0].port=80 --set gateways.istio-egressgateway.ports[0].name=http --set gateways.istio-egressgateway.ports[1].port=443 --set gateways.istio-egressgateway.ports[1].name=https --set gateways.istio-egressgateway.ports[2].port=$EGRESS_GATEWAY_MONGODB_PORT --set gateways.istio-egressgateway.ports[2].name=mongo | kubectl apply -f -
|
||
</code></pre></li>
|
||
<li><p>检查 <code>istio-egressgateway</code> service 确实有选择的端口:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get svc istio-egressgateway -n istio-system
|
||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||
istio-egressgateway ClusterIP 172.21.202.204 &lt;none&gt; 80/TCP,443/TCP,7777/TCP 34d
|
||
</code></pre></li>
|
||
<li><p>为 <code>istio-egressgateway</code> 服务 关闭双向 TLS 认证</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: authentication.istio.io/v1alpha1
|
||
kind: Policy
|
||
metadata:
|
||
name: istio-egressgateway
|
||
namespace: istio-system
|
||
spec:
|
||
targets:
|
||
- name: istio-egressgateway
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>为您的 MongoDB service 创建一个 egress <code>Gateway</code>、一个 destination rules 和 virtual services,以定向流量到 egress gateway,并从 egress gateway 发送到外部服务。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: istio-egressgateway
|
||
spec:
|
||
selector:
|
||
istio: egressgateway
|
||
servers:
|
||
- port:
|
||
number: $EGRESS_GATEWAY_MONGODB_PORT
|
||
name: tcp
|
||
protocol: TCP
|
||
hosts:
|
||
- my-mongo.tcp.svc
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: egressgateway-for-mongo
|
||
spec:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subsets:
|
||
- name: mongo
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
host: my-mongo.tcp.svc
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-mongo-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- my-mongo.tcp.svc
|
||
gateways:
|
||
- mesh
|
||
- istio-egressgateway
|
||
tcp:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
destinationSubnets:
|
||
- $MONGODB_IP/32
|
||
port: $MONGODB_PORT
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: mongo
|
||
port:
|
||
number: $EGRESS_GATEWAY_MONGODB_PORT
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: $EGRESS_GATEWAY_MONGODB_PORT
|
||
route:
|
||
- destination:
|
||
host: my-mongo.tcp.svc
|
||
port:
|
||
number: $MONGODB_PORT
|
||
weight: 100
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p><a href="#verify-that-egress-traffic-is-directed-through-the-egress-gateway">验证 TCP egress 流量是否被定向到 egress gateway</a>.</p></li>
|
||
</ol>
|
||
<h4 id="mutual-TLS-between-the-sidecar-proxies-and-the-egress-gateway">Sidecar 代理和 egress gateway 之间的双向 TLS</h4>
|
||
<ol>
|
||
<li><p>删除前面小节中的配置:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete gateway istio-egressgateway --ignore-not-found=true
|
||
$ kubectl delete virtualservice direct-mongo-through-egress-gateway --ignore-not-found=true
|
||
$ kubectl delete destinationrule egressgateway-for-mongo mongo --ignore-not-found=true
|
||
$ kubectl delete policy istio-egressgateway -n istio-system --ignore-not-found=true
|
||
</code></pre></li>
|
||
<li><p>Enforce mutual TLS authentication for the <code>istio-egressgateway</code> service:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: authentication.istio.io/v1alpha1
|
||
kind: Policy
|
||
metadata:
|
||
name: istio-egressgateway
|
||
namespace: istio-system
|
||
spec:
|
||
targets:
|
||
- name: istio-egressgateway
|
||
peers:
|
||
- mtls: {}
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>为您的 MongoDB service 创建一个 egress <code>Gateway</code>、一个 destination rules 和 virtual services,以定向流量到 egress gateway,并从 egress gateway 发送到外部服务。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: istio-egressgateway
|
||
spec:
|
||
selector:
|
||
istio: egressgateway
|
||
servers:
|
||
- port:
|
||
number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
hosts:
|
||
- my-mongo.tcp.svc
|
||
tls:
|
||
mode: MUTUAL
|
||
serverCertificate: /etc/certs/cert-chain.pem
|
||
privateKey: /etc/certs/key.pem
|
||
caCertificates: /etc/certs/root-cert.pem
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: egressgateway-for-mongo
|
||
spec:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subsets:
|
||
- name: mongo
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: ROUND_ROBIN
|
||
portLevelSettings:
|
||
- port:
|
||
number: 443
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
sni: my-mongo.tcp.svc
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
host: my-mongo.tcp.svc
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-mongo-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- my-mongo.tcp.svc
|
||
gateways:
|
||
- mesh
|
||
- istio-egressgateway
|
||
tcp:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
destinationSubnets:
|
||
- $MONGODB_IP/32
|
||
port: $MONGODB_PORT
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: mongo
|
||
port:
|
||
number: 443
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: 443
|
||
route:
|
||
- destination:
|
||
host: my-mongo.tcp.svc
|
||
port:
|
||
number: $MONGODB_PORT
|
||
weight: 100
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>继续下一节。</p></li>
|
||
</ol>
|
||
<h4 id="verify-that-egress-traffic-is-directed-through-the-egress-gateway">验证 TCP egress 流量是否通过 egress gateway 定向</h4>
|
||
<ol>
|
||
<li><p>再次刷新应用程序的网页,并验证等级是否仍正确显示。</p></li>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging">开启 Envoy 访问日志</a></p></li>
|
||
<li><p>检查 egress gateway 的 Envoy 的统计数据,找到对应请求 MongoDB service 的 counter。如果 Istio 步骤在 <code>istio-system</code> namespace 中,打印 counter 的命令为:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs -l istio=egressgateway -n istio-system
|
||
[2019-04-14T06:12:07.636Z] &#34;- - -&#34; 0 - &#34;-&#34; 1591 4393 94 - &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;&lt;Your MongoDB IP&gt;:&lt;your MongoDB port&gt;&#34; outbound|&lt;your MongoDB port&gt;||my-mongo.tcp.svc 172.30.146.119:59924 172.30.146.119:443 172.30.230.1:59206 -
|
||
</code></pre></li>
|
||
</ol>
|
||
<h3 id="cleanup-of-TCP-egress-traffic-control">清理通过 egress gateway 定向 TCP egress 流量的配置</h3>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry mongo
|
||
$ kubectl delete gateway istio-egressgateway --ignore-not-found=true
|
||
$ kubectl delete virtualservice direct-mongo-through-egress-gateway --ignore-not-found=true
|
||
$ kubectl delete destinationrule egressgateway-for-mongo mongo --ignore-not-found=true
|
||
$ kubectl delete policy istio-egressgateway -n istio-system --ignore-not-found=true
|
||
</code></pre>
|
||
<h2 id="egress-control-for-TLS">TLS egress 控制</h2>
|
||
<p>在现实生活中,绝大多数到外部服务的通信都必须被加密,而 <a href="https://zh/docs.mongodb.com/manual/tutorial/configure-ssl/">MongoDB 协议在 TLS 之上运行</a>。
|
||
并且,TLS 客户端经常发送<a href="https://en.wikipedia.org/wiki/Server_Name_Indication">服务器名称指示</a>,SNI,作为握手的一部分。
|
||
如果您的 MongoDB 服务器运行 TLS 且 MongoDB 客户端发送 SNI 作为握手的一部分,您就可以像任何其余带有 SNI 的 TLS 流量一样控制 MongoDB egress 流量。
|
||
您不需要指定 MongoDB 服务器的 IP 地址,而只需指定他们的主机名称,这样会更加方便,因为您无需依赖 IP 地址的稳定性。
|
||
您还可以指定通配符为主机名的前缀,例如允许从 <code>*.com</code> 域访问任意服务器。</p>
|
||
<p>要想检查您的 MongoDB 服务器是否支持 TLS,请运行:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ openssl s_client -connect $MONGODB_HOST:$MONGODB_PORT -servername $MONGODB_HOST
|
||
</code></pre>
|
||
<p>如果上述命令打印了一个服务器返回的证书,说明该服务器支持 TLS。如果没有,您就需要像前面小节描述的一样在 TCP 层面控制 MongoDB egress 流量。</p>
|
||
<h3 id="control-TLS-egress-traffic-without-a-gateway">无 gateway 情况下控制 TLS egress 流量</h3>
|
||
<p>如果您<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#use-case">不需要 egress gateway</a>,请遵循本小节中的说明。
|
||
如果您需要通过 egress gateway 定向流量,请继续阅读<a href="#direct-tcp-egress-traffic-through-an-egress-gateway">通过 egress gateway 定向 TCP Egress 流量</a>。</p>
|
||
<ol>
|
||
<li><p>为 MongoDB service 创建一个 <code>ServiceEntry</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
ports:
|
||
- number: $MONGODB_PORT
|
||
name: tls
|
||
protocol: TLS
|
||
resolution: DNS
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>刷新应用程序的网页。应用程序应该正确显示评级数据。</p></li>
|
||
</ol>
|
||
<h4 id="cleanup-of-the-egress-configuration-for-TLS">清理 TLS 的 egress 配置</h4>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry mongo
|
||
</code></pre>
|
||
<h3 id="direct-tcp-egress-traffic-through-an-egress-gateway">通过 egress gateway 定向 TLS Egress 流量</h3>
|
||
<p>在本小节中,您将处理通过 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#use-case">egress gateway</a> 定向流量的情况。
|
||
Sidecar 代理通过匹配 MongoDB 主机的 SNI,将 TLS 连接从 MongoDB 客户端路由到 egress gateway。
|
||
Egress gateway 再将流量转发到 MongoDB 主机。请注意,sidecar 代理会将目的端口重写为 443。
|
||
Egress gateway 在 443 端口上接受 MongoDB 流量,按照 SNI 匹配 MongoDB 主机,并再次将端口重写为 MongoDB 服务器的端口。</p>
|
||
<ol>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#deploy-Istio-egress-gateway">部署 Istio egress gateway</a>.</p></li>
|
||
<li><p>为 MongoDB service 创建一个 <code>ServiceEntry</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
ports:
|
||
- number: $MONGODB_PORT
|
||
name: tls
|
||
protocol: TLS
|
||
- number: 443
|
||
name: tls-port-for-egress-gateway
|
||
protocol: TLS
|
||
resolution: DNS
|
||
location: MESH_EXTERNAL
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>刷新应用程序的网页并验证评级数据是否显示正常。</p></li>
|
||
<li><p>为您的 MongoDB service 创建一个 egress <code>Gateway</code>、一个 destination rules 和 virtual services,以将流量定向到 egress gateway,并从 egress gateway 发送到外部服务。</p></li>
|
||
</ol>
|
||
<p>如果您希望启用 sidecar 代理和应用程序 pod 以及 egress gateway 之间的<a href="/v1.12/zh/docs/tasks/security/authentication/authn-policy/#auto-mutual-TLS">双向 TLS 认证</a>,可以使用下面的命令。(您可能希望启用双向 TLS 以使 egress gateway 监控来源 pod 的身份并基于该 identity 启用 Mixer 策略。)</p>
|
||
<pre><code>
|
||
<div id="tabset-zh-blog-2018-egress-mongo-1" role="tablist" class="tabset ">
|
||
<div class="tab-strip" data-category-name="mtls" ><button aria-selected="true" data-category-value="enabled"
|
||
aria-controls="tabset-zh-blog-2018-egress-mongo-1-0-panel" id="tabset-zh-blog-2018-egress-mongo-1-0-tab" role="tab"><span>mutual TLS enabled</span>
|
||
</button><button tabindex="-1" data-category-value="disabled"
|
||
aria-controls="tabset-zh-blog-2018-egress-mongo-1-1-panel" id="tabset-zh-blog-2018-egress-mongo-1-1-tab" role="tab"><span>mutual TLS disabled</span>
|
||
</button></div>
|
||
<div class="tab-content"><div id="tabset-zh-blog-2018-egress-mongo-1-0-panel" role="tabpanel" tabindex="0" aria-labelledby="tabset-zh-blog-2018-egress-mongo-1-0-tab">
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: istio-egressgateway
|
||
spec:
|
||
selector:
|
||
istio: egressgateway
|
||
servers:
|
||
- port:
|
||
number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
tls:
|
||
mode: MUTUAL
|
||
serverCertificate: /etc/certs/cert-chain.pem
|
||
privateKey: /etc/certs/key.pem
|
||
caCertificates: /etc/certs/root-cert.pem
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: egressgateway-for-mongo
|
||
spec:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subsets:
|
||
- name: mongo
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: ROUND_ROBIN
|
||
portLevelSettings:
|
||
- port:
|
||
number: 443
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
sni: $MONGODB_HOST
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-mongo-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
gateways:
|
||
- mesh
|
||
- istio-egressgateway
|
||
tls:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: $MONGODB_PORT
|
||
sni_hosts:
|
||
- $MONGODB_HOST
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: mongo
|
||
port:
|
||
number: 443
|
||
tcp:
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: 443
|
||
route:
|
||
- destination:
|
||
host: $MONGODB_HOST
|
||
port:
|
||
number: $MONGODB_PORT
|
||
weight: 100
|
||
EOF
|
||
</code></pre>
|
||
</div><div hidden id="tabset-zh-blog-2018-egress-mongo-1-1-panel" role="tabpanel" tabindex="0" aria-labelledby="tabset-zh-blog-2018-egress-mongo-1-1-tab">
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: istio-egressgateway
|
||
spec:
|
||
selector:
|
||
istio: egressgateway
|
||
servers:
|
||
- port:
|
||
number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
tls:
|
||
mode: PASSTHROUGH
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: egressgateway-for-mongo
|
||
spec:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subsets:
|
||
- name: mongo
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-mongo-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- $MONGODB_HOST
|
||
gateways:
|
||
- mesh
|
||
- istio-egressgateway
|
||
tls:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: $MONGODB_PORT
|
||
sni_hosts:
|
||
- $MONGODB_HOST
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: mongo
|
||
port:
|
||
number: 443
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: 443
|
||
sni_hosts:
|
||
- $MONGODB_HOST
|
||
route:
|
||
- destination:
|
||
host: $MONGODB_HOST
|
||
port:
|
||
number: $MONGODB_PORT
|
||
weight: 100
|
||
EOF
|
||
</code></pre>
|
||
</div></div>
|
||
</div>
|
||
</code></pre>
|
||
<ol>
|
||
<li><a href="#verify-that-egress-traffic-is-directed-through-the-egress-gateway">验证 TCP egress 流量是否通过 egress gateway 定向</a></li>
|
||
</ol>
|
||
<h4 id="cleanup-directing-TLS-Egress-traffic-through-an-egress-gateway">清除通过 egress gateway 定向 TLS Egress 流量的配置</h4>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry mongo
|
||
$ kubectl delete gateway istio-egressgateway
|
||
$ kubectl delete virtualservice direct-mongo-through-egress-gateway
|
||
$ kubectl delete destinationrule egressgateway-for-mongo
|
||
</code></pre>
|
||
<h3 id="enable-MongoDB-TLS-egress-traffic-to-arbitrary-wildcarded-domains">启用到任意通配符域名的 MongoDB TLS egress 流量</h3>
|
||
<p>有时,您希望将 egress 流量配置为来自同一域的多个主机名,例如到 <code>*.&lt;your company domain&gt;.com</code> 中的所有 MongoDB service。
|
||
您不希望创建多个配置项,而是一个用于公司中所有 MongoDB service 的通用配置项。
|
||
要想通过一个配置来控制到所有相同域中的外部服务的访问,您需要使用 <em>通配符</em> 主机。</p>
|
||
<p>在本节中,您将为通配符域名配置 egress gateway。我在 <code>composedb.com</code> 处使用了 MongoDB instance,
|
||
因此为 <code>*.com</code> 配置出口流量对我有效(我也可以使用<code>*.composedb.com</code>)。
|
||
您可以根据 MongoDB 主机选择通配符域名。</p>
|
||
<p>要为通配符域名配置 egress gateway 流量,
|
||
您需要使用<a href="/v1.12/zh/docs/tasks/traffic-management/egress/wildcard-egress-hosts/#wildcard-configuration-for-arbitrary-domains">一个额外的 SNI 代理</a>来部署一个自定义的 egress gateway。由于 Envoy(Istio egress gateway 使用的标准代理)目前的限制,这是必须的。</p>
|
||
<h4 id="prepare-a-new-egress-gateway-with-an-SNI-proxy">准备一个 SNI 代理使用新的 egress gateway</h4>
|
||
<p>在本节中,除了标准的 Istio Envoy 代理之外,您还将部署具有 SNI 代理的 egress gateway。您可以使用任何能够根据任意未预先配置的 SNI 值路由流量的 SNI 代理;我们使用 <a href="http://nginx.org">Nginx</a> 来实现这一功能。</p>
|
||
<ol>
|
||
<li><p>为 Nginx SNI 代理创建配置文件。如果需要,您可以编辑该文件以指定其他 Nginx 设置。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF &gt; ./sni-proxy.conf
|
||
user www-data;
|
||
events {
|
||
}
|
||
stream {
|
||
log_format log_stream &#39;\$remote_addr [\$time_local] \$protocol [\$ssl_preread_server_name]&#39;
|
||
&#39;\$status \$bytes_sent \$bytes_received \$session_time&#39;;
|
||
access_log /var/log/nginx/access.log log_stream;
|
||
error_log /var/log/nginx/error.log;
|
||
# tcp forward proxy by SNI
|
||
server {
|
||
resolver 8.8.8.8 ipv6=off;
|
||
listen 127.0.0.1:$MONGODB_PORT;
|
||
proxy_pass \$ssl_preread_server_name:$MONGODB_PORT;
|
||
ssl_preread on;
|
||
}
|
||
}
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>创建一个 Kubernetes <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/">ConfigMap</a> 来保存 Nginx SNI 代理的配置:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl create configmap egress-sni-proxy-configmap -n istio-system --from-file=nginx.conf=./sni-proxy.conf
|
||
</code></pre></li>
|
||
<li><p>下面的命令将产生用于编辑和部署的 <code>istio-egressgateway-with-sni-proxy.yaml</code> 文件。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | helm template install/kubernetes/helm/istio/ --name istio-egressgateway-with-sni-proxy --namespace istio-system -x charts/gateways/templates/deployment.yaml -x charts/gateways/templates/service.yaml -x charts/gateways/templates/serviceaccount.yaml -x charts/gateways/templates/autoscale.yaml -x charts/gateways/templates/role.yaml -x charts/gateways/templates/rolebindings.yaml --set global.mtls.enabled=true --set global.istioNamespace=istio-system -f - &gt; ./istio-egressgateway-with-sni-proxy.yaml
|
||
gateways:
|
||
enabled: true
|
||
istio-ingressgateway:
|
||
enabled: false
|
||
istio-egressgateway:
|
||
enabled: false
|
||
istio-egressgateway-with-sni-proxy:
|
||
enabled: true
|
||
labels:
|
||
app: istio-egressgateway-with-sni-proxy
|
||
istio: egressgateway-with-sni-proxy
|
||
replicaCount: 1
|
||
autoscaleMin: 1
|
||
autoscaleMax: 5
|
||
cpu:
|
||
targetAverageUtilization: 80
|
||
serviceAnnotations: {}
|
||
type: ClusterIP
|
||
ports:
|
||
- port: 443
|
||
name: https
|
||
secretVolumes:
|
||
- name: egressgateway-certs
|
||
secretName: istio-egressgateway-certs
|
||
mountPath: /etc/istio/egressgateway-certs
|
||
- name: egressgateway-ca-certs
|
||
secretName: istio-egressgateway-ca-certs
|
||
mountPath: /etc/istio/egressgateway-ca-certs
|
||
configVolumes:
|
||
- name: sni-proxy-config
|
||
configMapName: egress-sni-proxy-configmap
|
||
additionalContainers:
|
||
- name: sni-proxy
|
||
image: nginx
|
||
volumeMounts:
|
||
- name: sni-proxy-config
|
||
mountPath: /etc/nginx
|
||
readOnly: true
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>部署新的 egress gateway:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f ./istio-egressgateway-with-sni-proxy.yaml
|
||
serviceaccount &#34;istio-egressgateway-with-sni-proxy-service-account&#34; created
|
||
role &#34;istio-egressgateway-with-sni-proxy-istio-system&#34; created
|
||
rolebinding &#34;istio-egressgateway-with-sni-proxy-istio-system&#34; created
|
||
service &#34;istio-egressgateway-with-sni-proxy&#34; created
|
||
deployment &#34;istio-egressgateway-with-sni-proxy&#34; created
|
||
horizontalpodautoscaler &#34;istio-egressgateway-with-sni-proxy&#34; created
|
||
</code></pre></li>
|
||
<li><p>验证新 egress gateway 是否工作正常。请注意 pod 有两个容器(一个是 Envoy 代理,另一个是 SNI 代理)。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pod -l istio=egressgateway-with-sni-proxy -n istio-system
|
||
NAME READY STATUS RESTARTS AGE
|
||
istio-egressgateway-with-sni-proxy-79f6744569-pf9t2 2/2 Running 0 17s
|
||
</code></pre></li>
|
||
<li><p>创建一个使用静态地址 127.0.0.1 (<code>localhost</code>) 的 service entry,并对定向到新 service entry 的流量禁用双向 TLS:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: sni-proxy
|
||
spec:
|
||
hosts:
|
||
- sni-proxy.local
|
||
location: MESH_EXTERNAL
|
||
ports:
|
||
- number: $MONGODB_PORT
|
||
name: tcp
|
||
protocol: TCP
|
||
resolution: STATIC
|
||
endpoints:
|
||
- address: 127.0.0.1
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: disable-mtls-for-sni-proxy
|
||
spec:
|
||
host: sni-proxy.local
|
||
trafficPolicy:
|
||
tls:
|
||
mode: DISABLE
|
||
EOF
|
||
</code></pre></li>
|
||
</ol>
|
||
<h4 id="configure-access-to-com-using-the-new-egress-gateway">使用新 egress gateway 配置到 <code>*.com</code> 的访问</h4>
|
||
<ol>
|
||
<li><p>为 <code>*.com</code> 定义一个 <code>ServiceEntry</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl create -f -
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: mongo
|
||
spec:
|
||
hosts:
|
||
- &#34;*.com&#34;
|
||
ports:
|
||
- number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
- number: $MONGODB_PORT
|
||
name: tls-mongodb
|
||
protocol: TLS
|
||
location: MESH_EXTERNAL
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>为 *.com 创建一个 egress Gateway,使用 443 端口和 TLS 协议。创建一个 destination rule 来为 gateway 设置 <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">SNI</a>。
|
||
以及为 Envoy 过滤器,以防止恶意应用程序篡改 SNI (过滤器验证这个应用程序发布的 SNI 与报告给 Mixer 的 SNI 是否相同)</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: istio-egressgateway-with-sni-proxy
|
||
spec:
|
||
selector:
|
||
istio: egressgateway-with-sni-proxy
|
||
servers:
|
||
- port:
|
||
number: 443
|
||
name: tls
|
||
protocol: TLS
|
||
hosts:
|
||
- &#34;*.com&#34;
|
||
tls:
|
||
mode: MUTUAL
|
||
serverCertificate: /etc/certs/cert-chain.pem
|
||
privateKey: /etc/certs/key.pem
|
||
caCertificates: /etc/certs/root-cert.pem
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: mtls-for-egress-gateway
|
||
spec:
|
||
host: istio-egressgateway-with-sni-proxy.istio-system.svc.cluster.local
|
||
subsets:
|
||
- name: mongo
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: ROUND_ROBIN
|
||
portLevelSettings:
|
||
- port:
|
||
number: 443
|
||
tls:
|
||
mode: ISTIO_MUTUAL
|
||
---
|
||
# The following filter is used to forward the original SNI (sent by the application) as the SNI of the mutual TLS
|
||
# connection.
|
||
# The forwarded SNI will be reported to Mixer so that policies will be enforced based on the original SNI value.
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: EnvoyFilter
|
||
metadata:
|
||
name: forward-downstream-sni
|
||
spec:
|
||
filters:
|
||
- listenerMatch:
|
||
portNumber: $MONGODB_PORT
|
||
listenerType: SIDECAR_OUTBOUND
|
||
filterName: forward_downstream_sni
|
||
filterType: NETWORK
|
||
filterConfig: {}
|
||
---
|
||
# The following filter verifies that the SNI of the mutual TLS connection (the SNI reported to Mixer) is
|
||
# identical to the original SNI issued by the application (the SNI used for routing by the SNI proxy).
|
||
# The filter prevents Mixer from being deceived by a malicious application: routing to one SNI while
|
||
# reporting some other value of SNI. If the original SNI does not match the SNI of the mutual TLS connection, the
|
||
# filter will block the connection to the external service.
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: EnvoyFilter
|
||
metadata:
|
||
name: egress-gateway-sni-verifier
|
||
spec:
|
||
workloadLabels:
|
||
app: istio-egressgateway-with-sni-proxy
|
||
filters:
|
||
- listenerMatch:
|
||
portNumber: 443
|
||
listenerType: GATEWAY
|
||
filterName: sni_verifier
|
||
filterType: NETWORK
|
||
filterConfig: {}
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>将目的为 <em>*.com</em> 的流量路由到 egress gateway,并从 egress gateway 路由到 SNI 代理.</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-mongo-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- &#34;*.com&#34;
|
||
gateways:
|
||
- mesh
|
||
- istio-egressgateway-with-sni-proxy
|
||
tls:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: $MONGODB_PORT
|
||
sni_hosts:
|
||
- &#34;*.com&#34;
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway-with-sni-proxy.istio-system.svc.cluster.local
|
||
subset: mongo
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
tcp:
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway-with-sni-proxy
|
||
port: 443
|
||
route:
|
||
- destination:
|
||
host: sni-proxy.local
|
||
port:
|
||
number: $MONGODB_PORT
|
||
weight: 100
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>再次刷新应用程序的网页,验证评级数据仍然显示正确。</p></li>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging">开启 Envoy 访问日志</a></p></li>
|
||
<li><p>检查 egress gateway 的 Envoy 的日志。如果 Istio 部署在 <code>istio-system</code> namespace 中,打印日志的的命令为:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs -l istio=egressgateway-with-sni-proxy -c istio-proxy -n istio-system
|
||
</code></pre>
|
||
<p>You should see lines similar to the following:</p>
|
||
<pre><code class='language-plain' data-expandlinks='true' data-repo='istio' >[2019-01-02T17:22:04.602Z] &#34;- - -&#34; 0 - 768 1863 88 - &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;127.0.0.1:28543&#34; outbound|28543||sni-proxy.local 127.0.0.1:49976 172.30.146.115:443 172.30.146.118:58510 &lt;your MongoDB host&gt;
|
||
[2019-01-02T17:22:04.713Z] &#34;- - -&#34; 0 - 1534 2590 85 - &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;-&#34; &#34;127.0.0.1:28543&#34; outbound|28543||sni-proxy.local 127.0.0.1:49988 172.30.146.115:443 172.30.146.118:58522 &lt;your MongoDB host&gt;
|
||
</code></pre></li>
|
||
<li><p>检查 SNI 代理的日志。如果 Istio 部署在 <code>istio-system</code> namespace 中,打印日志的命令为:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs -l istio=egressgateway-with-sni-proxy -n istio-system -c sni-proxy
|
||
127.0.0.1 [23/Aug/2018:03:28:18 +0000] TCP [&lt;your MongoDB host&gt;]200 1863 482 0.089
|
||
127.0.0.1 [23/Aug/2018:03:28:18 +0000] TCP [&lt;your MongoDB host&gt;]200 2590 1248 0.095
|
||
</code></pre></li>
|
||
</ol>
|
||
<h4 id="understanding-what-happened">理解原理</h4>
|
||
<p>在本节中,您使用通配符域名为您的 MongoDB 主机配置了 egress 流量。对于单个 MongoDB 主机使用通配符域名没有任何好处(可以指定确切的主机名),
|
||
而当集群中的应用程序需要访问多个匹配某个通配符域名的 MongoDB 主机时可能有用。
|
||
例如,如果应用程序需要访问 <code>mongodb1.composedb.com</code>、<code>mongodb2.composedb.com</code> 和 <code>mongodb3.composedb.com</code> 时,
|
||
egress 流量可以使用针对泛域名 <code>*.composedb.com</code> 的单个配置实现。</p>
|
||
<p>当配置一个应用使用另一个主机名匹配本小节中的通配符域名的 MongoDB 实例时,不需要额外的 Istio 配置。
|
||
我将这留作一个练习,让读者自行验证。</p>
|
||
<h4 id="cleanup-of-configuration-for-MongoDB-TLS-egress-traffic-to-arbitrary-wildcarded-domains">清理到任意通配符域名的 MongoDB TLS egress 流量的配置</h4>
|
||
<ol>
|
||
<li><p>删除针对 <code>*.com</code> 的配置项:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry mongo
|
||
$ kubectl delete gateway istio-egressgateway-with-sni-proxy
|
||
$ kubectl delete virtualservice direct-mongo-through-egress-gateway
|
||
$ kubectl delete destinationrule mtls-for-egress-gateway
|
||
$ kubectl delete envoyfilter forward-downstream-sni egress-gateway-sni-verifier
|
||
</code></pre></li>
|
||
<li><p>删除 <code>egressgateway-with-sni-proxy</code> <code>Deployment</code> 的配置项:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry sni-proxy
|
||
$ kubectl delete destinationrule disable-mtls-for-sni-proxy
|
||
$ kubectl delete -f ./istio-egressgateway-with-sni-proxy.yaml
|
||
$ kubectl delete configmap egress-sni-proxy-configmap -n istio-system
|
||
</code></pre></li>
|
||
<li><p>删除您创建的配置文件:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ rm ./istio-egressgateway-with-sni-proxy.yaml
|
||
$ rm ./nginx-sni-proxy.conf
|
||
</code></pre></li>
|
||
</ol>
|
||
<h2 id="cleanup">清理</h2>
|
||
<ol>
|
||
<li><p>删除<code>bookinfo</code>用户:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | mongo --ssl --sslAllowInvalidCertificates $MONGODB_HOST:$MONGODB_PORT -u admin -p $MONGO_ADMIN_PASSWORD --authenticationDatabase admin
|
||
use test
|
||
db.dropUser(&#34;bookinfo&#34;);
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>删除 <code>ratings</code> 集合:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | mongo --ssl --sslAllowInvalidCertificates $MONGODB_HOST:$MONGODB_PORT -u admin -p $MONGO_ADMIN_PASSWORD --authenticationDatabase admin
|
||
use test
|
||
db.ratings.drop();
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>取消您使用的环境变量:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ unset MONGO_ADMIN_PASSWORD BOOKINFO_PASSWORD MONGODB_HOST MONGODB_PORT MONGODB_IP
|
||
</code></pre></li>
|
||
<li><p>删除 virtual services:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-ratings-db.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete -f @samples/bookinfo/networking/virtual-service-ratings-db.yaml@
|
||
Deleted config: virtual-service/default/reviews
|
||
Deleted config: virtual-service/default/ratings
|
||
</code></pre></div></li>
|
||
<li><p>删除 <code>ratings v2-mongodb</code> deployment:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml@
|
||
deployment &#34;ratings-v2&#34; deleted
|
||
</code></pre></div></li>
|
||
</ol>
|
||
<h2 id="conclusion">总结</h2>
|
||
<p>在这篇博文中,我演示了 MongoDB egress 流量控制的各种选项。您可以在 TCP 或 TLS 层面上控制 MongoDB egress 流量。
|
||
根据您的组织的安全需求,在 TCP 和 TLS 场景下您都可以将流量从 sidecar 代理定向到外部 MongoDB 主机
|
||
,或者通过一个 egress gateway 进行转发。在后面一种场景中,您还可以决定是否禁用 sidecar 代理到 egress gateway 的双向 TLS 认证。
|
||
如果您想要通过指定类似 <code>*.com</code> 的通配符域名来从 TLS 层面控制 MongoDB 的 egress 流量,并且通过 egress gateway 定向流量时,
|
||
您必须部署一个使用 SNI 代理的自定义 egress gateway。</p>
|
||
<p>请注意,本博客文章中描述的 MongoDB 配置和注意事项与 TCP/TLS 之上的其他非 HTTP 协议相同。</p></description><pubDate>Fri, 16 Nov 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/egress-mongo/</link><author>Vadim Eisenberg</author><guid isPermaLink="true">/v1.12/zh/blog/2018/egress-mongo/</guid><category>traffic-management</category><category>egress</category><category>tcp</category><category>mongo</category></item><item><title>Istio 在 Twitch 上全天直播</title><description>
|
||
<p>为了庆祝 Istio 1.0 版本的发布并向更广泛的受众推广该软件,8 月 17 日 Istio 社区在 Twitch 举办了一天的实况直播。</p>
|
||
<h2 id="what-is-twitch">Twitch 是什么?</h2>
|
||
<p><a href="https://twitch.tv/">Twitch</a> 是一个流行的视频游戏直播流媒体平台,最近也看到了大量的编码内容出现。IBM 的倡导者一直在那里进行现场编码和演示,这是很有趣的事情。虽然大多数都是和游戏有关的内容,但是也有<a href="https://www.twitch.tv/communities/programming">不断发展的社区</a>在该网站上分享和观看编程内容。</p>
|
||
<h2 id="what-does-this-have-to-do-with-Istio">它用 Istio 做了什么?</h2>
|
||
<p>Istio 在平台上发布的全天的内容,希望可以给观众讲解如何将深度技术内容、初级内容和业务线内容做良好融合。我们有开发人员、用户和布道者来分享示例和故事。期待现场编码,QA 和一些惊喜。我们有来自 IBM、Google、Datadog、Pivotal 和更多的明星嘉宾。</p>
|
||
<h2 id="recordings">如何观看</h2>
|
||
<p>可点击<a href="https://www.youtube.com/playlist?list=PLzpeuWUENMK0V3dwpx5gPJun-SLG0USqU">这里</a>进行观看。</p>
|
||
<h2 id="schedule">安排</h2>
|
||
<p>任何时候都是 <code>PDT</code>。</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>时间</th>
|
||
<th>演讲者</th>
|
||
<th>所属单位</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>10:00 - 10:30</td>
|
||
<td><code>Spencer Krum + Lisa-Marie Namphy</code></td>
|
||
<td><code>IBM / Portworx</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>10:30 - 11:00</td>
|
||
<td><code>Lin Sun / Spencer Krum / Sven Mawson</code></td>
|
||
<td><code>IBM / Google</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>11:00 - 11:10</td>
|
||
<td><code>Lin Sun / Spencer Krum</code></td>
|
||
<td><code>IBM</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>11:10 - 11:30</td>
|
||
<td><code>Jason Yee / Ilan Rabinovich</code></td>
|
||
<td><code>Datadog</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>11:30 - 11:50</td>
|
||
<td><code>April Nassl</code></td>
|
||
<td><code>Google</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>11:50 - 12:10</td>
|
||
<td><code>Spike Curtis</code></td>
|
||
<td><code>Tigera</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>12:10 - 12:30</td>
|
||
<td><code>Shannon Coen</code></td>
|
||
<td><code>Pivotal</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>12:30 - 1:00</td>
|
||
<td><code>Matt Klein</code></td>
|
||
<td><code>Lyft</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>1:00 - 1:20</td>
|
||
<td><code>Zach Jory</code></td>
|
||
<td><code>F5/Aspen Mesh</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>1:20 - 1:40</td>
|
||
<td><code>Dan Ciruli</code></td>
|
||
<td><code>Google</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>1:40 - 2:00</td>
|
||
<td><code>Isaiah Snell-Feikema</code> / <code>Greg Hanson</code></td>
|
||
<td><code>IBM</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>2:00 - 2:20</td>
|
||
<td><code>Zach Butcher</code></td>
|
||
<td><code>Tetrate</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>2:20 - 2:40</td>
|
||
<td><code>Ray Hudaihed</code></td>
|
||
<td><code>American Airlines</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>2:40 - 3:00</td>
|
||
<td><code>Christian Posta</code></td>
|
||
<td><code>Red Hat</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>3:00 - 3:20</td>
|
||
<td><code>Google/IBM China</code></td>
|
||
<td><code>Google / IBM</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>3:20 - 3:40</td>
|
||
<td><code>Colby Dyess</code></td>
|
||
<td><code>Tuffin</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>3:40 - 4:00</td>
|
||
<td><code>Rohit Agarwalla</code></td>
|
||
<td><code>Cisco</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table></description><pubDate>Fri, 03 Aug 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/istio-twitch-stream/</link><author>Spencer Krum, IBM</author><guid isPermaLink="true">/v1.12/zh/blog/2018/istio-twitch-stream/</guid></item><item><title>Istio 是惠普 FitStation 平台的改变者</title><description><p>惠普的 FitStation 团队坚信,未来的 Kubernetes、BPF 和服务网络是云基础设施的下一个标准。我们也很高兴看到 Istio 即将推出其官方的 Istio 1.0 版本 - 这要归功于 2017 年 5 月从 Google、IBM 和 Lyft 开始的联合合作。</p>
|
||
<p>在 FitStation 大规模和渐进式云平台的开发过程中,Istio 、Cilium 和 Kubernetes 的技术提供了大量机会,使我们的系统更加健壮和易于扩展。Istio 在创建可靠和动态的网络通信方面改变了游戏规则。</p>
|
||
<p><a href="http://www.fitstation.com">由惠普提供支持的 FitStation</a> 是一个技术平台,可捕获 3D 生物识别数据,设计个性化鞋类,完美贴合个人足部尺寸和形状以及步态轮廓。它使用 3D 扫描,压力感应,3D 打印和可变密度注塑成型来制造独特的鞋类。Brooks、Steitz Secura 或 Superfeet 等鞋类品牌正在连接 FitStation,以打造下一代高性能运动鞋,专业鞋和医用鞋。</p>
|
||
<p>FitStation 建立在对用户生物识别数据的最终安全性和隐私承诺的基础上。Istio 是我们在云中实现数据传输的基石。通过在基础架构级别管理这些方面,我们专注于解决业务问题,而不是花时间在安全服务通信的单独实现上。使用 Istio 可以大大降低维护大量库和服务的复杂性,从而提供安全的通信服务。</p>
|
||
<p>作为使用 Istio 1.0 的额外好处,我们获得了网络可见性,指标和开箱即用的追踪。这极大地改善了我们开发和 DevOps 团队的的决策和响应质量。团队深入了解包括新应用程序和传统应用程序在内的整个平台的网络通信。Cilium 与 Envoy 的整合,让 Istio 服务网格网络通信能力的性能取得了显著提升,同时还提供了内核驱动的细粒度 L7 网络安全层。这归功于 Cilium 为 Istio 提供的 BPF 功能。我们认为未来将推动 Linux 的内核安全。</p>
|
||
<p>跟随 Istio 的成长一直非常令人兴奋。我们已经能够看到不同开发版本的性能和稳定性的明显改进。版本 0.7 和 0.8 之间的改进使我们的团队对 1.0 版本感到满意,我们可以说 Istio 现在已经准备好用于实际生产。</p>
|
||
<p>我们期待着 Istio、Envoy、Cilium 和 CNCF 充满希望的路线图。</p></description><pubDate>Tue, 31 Jul 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/hp/</link><author>Steven Ceuppens, Chief Software Architect @ HP FitStation, Open Source Advocate & Contributor</author><guid isPermaLink="true">/v1.12/zh/blog/2018/hp/</guid></item><item><title>使用 AppSwitch 精简 Istio 层次</title><description>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content">计算机科学中的所有问题,都可以用另一个层来解决,除了层数太多的问题。—— David Wheeler</div>
|
||
</aside>
|
||
</div>
|
||
<p>Sidecar proxy 模式成就了很多奇迹。Sidecar 身处微服务的数据路径之中,能够精确的了解到应用程序的意图。它在应用程序级别而非网络层级别对流量进行监控和协议的检测,从而实现了深度的可见性、访问控制以及流量管理能力。</p>
|
||
<p>如果我们仔细观察,在执行应用流量的高级分析之前,数据必须通过许多中间层。这些层中的大部分都是基础设施的一部分,是数据传输的管道。这样一来,就增加了数据通信的延迟,也提高了整个系统的复杂性。</p>
|
||
<p>多年以来,在网络数据路径层内实现积极的细粒度优化方面,已经有了很多集体努力。每次迭代可能都节省了几个毫秒。但这些层本身的必要性却无人质疑。</p>
|
||
<h2 id="do-not-optimize-layers-remove-them">优化层还是删除层</h2>
|
||
<p>在我看来,在对某些东西进行优化之前,应该先行考虑的是这个方面的需求是否可以取消。我最初的操作系统级虚拟化工作目标(broken link: <code>https://apporbit.com/a-brief-history-of-containers-from-reality-to-hype/</code>),就是移除虚拟机(broken link: <code>https://apporbit.com/a-brief-history-of-containers-from-reality-to-hype/</code>),用 Linux 容器直接在主机操作系统上运行应用,从而免除中间层的困扰。很长一段时间里,业界都在努力的对虚拟机进行优化,这是一场错误的战斗,真正应该做的是删除附加层。</p>
|
||
<p>在微服务以及网络的连接方面,历史再次重演。网络已经经历了物理服务器十年前所经历的变化。新引进层和结构正被深入集成到了协议栈甚至是晶片之中,却没有人认真考虑替代的可能。也许移除这些附加层才是更好的办法。</p>
|
||
<p>这个问题我已经思考了一段时间,我相信网络栈应该可以借鉴容器的做法,能够从基础上简化应用端点跨越复杂中间层进行连接的过程。我从容器的原始工作中总结的原则,也被应用到了创建 <a href="http://appswitch.io">AppSwitch</a> 的过程之中。容器所提供的接口可以直接被应用拿来消费,AppSwitch 会直接插入到应用程序所用的定义良好的网络 API 之中,并跳过所有中间层,直接将应用程序的客户端连接到适当的服务器上。这才是网络的应有之意。</p>
|
||
<p>在详细说明 AppSwitch 如何从 Istio 栈中清理无用层次之前,首先介绍一下产品架构。更多内容请移步浏览<a href="https://appswitch.readthedocs.io/en/latest/">产品文档页面</a>。</p>
|
||
<h2 id="appswitch">AppSwitch</h2>
|
||
<p>和容器运行时相比,AppSwitch 由客户端和一个守护进程组成,二者通过 HTTP 协议的 REST API 进行通信。客户端和守护进程构建为一个自包含的二进制文件 <code>ax</code>。客户端透明的注入 s 应用程序,并追踪网络相关的系统调用,随后通知守护进程。例如一个应用进行了 <code>connect(2)</code> 系统调用,目标是一个 Kubernetes 服务的 IP。AppSwitch 客户端拦截这一调用并令其失效,然后把这一事件及其参数和上下文环境告知守护进程。守护进程会处理系统调用,例如代表应用程序直接连接到上游服务器的 Pod IP。</p>
|
||
<p>值得注意的一点是,AppSwitch 的客户端和服务器之间不做任何数据转发。它们中间会通过 Unix socket 交换文件描述符,从而避免数据拷贝。另外客户端也不是独立进程,而是运行在应用本身的上下文之中的,因此应用和 AppSwitch 之间也不存在数据拷贝的操作。</p>
|
||
<h2 id="Delayering-the-stack">删减堆栈层</h2>
|
||
<p>现在我们大概知道了 AppSwitch 的功能,接下来看看它从标准服务网格中优化掉的层。</p>
|
||
<h3 id="network-devirtualization">网络的去虚拟化</h3>
|
||
<p>Kubernetes 为运行其上的微服务应用提供了简单的设计优良的网络结构。然而为了支持这些设计,也为下层网络强加了特定的<a href="https://kubernetes.io/docs/concepts/cluster-administration/networking/">需求</a>。要符合这些需求并不简单。通常会通过另加一层的方式来满足要求。典型方案就是在下层网络和 Kubernetes 之间加入叠加层。应用产生的流量会在源头进行封包,在目的地进行解包,这一过程消耗的不仅是网络资源,还包括 CPU。</p>
|
||
<p>AppSwitch 会通过和平台之间的接触,来决定应用程序的可见范围。它会为应用程序提供一个关于下层网络的虚拟视图,这一视图类似于叠加层,但是不会在数据路径中引入额外的处理工作。和容器的情况类似,容器内部看起来也像是一个虚拟机,但是其基础实现不会干扰低级中断之类的高发事件的控制过程。</p>
|
||
<p>AppSwitch 能注入到标准的 Kubernetes 清单文件之中(和 Istio 注入类似),这样应用的网络就直接被 AppSwitch 控制,跳过任何的网络叠加过程。稍后介绍更多细节。</p>
|
||
<h3 id="artifacts-of-container-networking">容器网络的组件</h3>
|
||
<p>将网络从主机扩展到容器是一个<a href="https://kubernetes.io/blog/2016/01/why-kubernetes-doesnt-use-libnetwork/">巨大挑战</a>。新的网络层应运而生。容器中的进程只是主机上的一个进程。然而应用所期待的网络抽象和容器网络命名空间之间存在一个<a href="http://appswitch.io/blog/kubernetes_istio_and_network_function_devirtualization_with_appswitch/">错位</a>,进程无法直接访问主机网络。应用程序眼里的网络是 Socket 或者 Session,而网络命名空间暴露的是设备抽象。一旦进入网络命名空间,进程会失去所有连接。为此发明了 <code>veth-pair</code> 之类的工具用来弥合这一鸿沟。数据现在必须从主机接口进入虚拟交换机,然后通过 <code>veth-pair</code> 才能进入容器网络空间里面的虚拟网络接口。</p>
|
||
<p>AppSwitch 能够有效的移除连接两端的虚拟交换机和 <code>veth-pair</code> 层。运行在主机上的守护进程所用的主机网络既然已经就绪,就无需再使用网桥方式把主机网络桥接到容器了。主机上创建的 Socket 文件描述符被传递给运行在 Pod 网络命名空间中的应用程序。应用收到 FD 之后,控制路径的所有工作都已就绪,就可以使用 FD 进行实际 IO 了。</p>
|
||
<h3 id="skip-TCP-IP-for-colocated-endpoints">跳过共生端点的 TCP/IP</h3>
|
||
<p>TCP/IP 几乎是所有通信过程的媒介。如果恰好应用端点处于同一主机,还有必要继续使用 TCP/IP 么?毕竟 TCP/IP 会完成很多工作,并且非常复杂。Unix Socket 是为主机内通信设计的,AppSwitch 可以透明的将共生端点之间的通信切换到 Unix Socket 上。</p>
|
||
<p>应用所监听的每个 Socket,AppSwitch 都会管理两个监听 Socket,一个对应 TCP,一个对应 Unix。当客户端尝试连接到的服务器恰好在同一主机,AppSwitch 守护进程就会选择连接到服务器的 Unix 监听 Socket 上。连接两端的 Unix Socket 被传递给相应的应用程序之中。返回完成的连接 FD 之后,应用会把它当做简单的字节管道。协议真的不重要。有个应用偶尔会做一些协议相关的调用,例如 <code>getsockname(2)</code>,AppSwitch 会自行处理。它会提供一致的响应,保证程序持续运行。</p>
|
||
<h3 id="data-pushing-proxy">数据推送代理</h3>
|
||
<p>我们一直在讨论移除层的问题,再回头看看代理层自身的需求。有时候代理服务器可能退化成为普通的数据推送装置:</p>
|
||
<ul>
|
||
<li>可能不需要协议解码。</li>
|
||
<li>协议可能不被代理支持。</li>
|
||
<li>通信过程是加密的,代理无法访问其中的 Header。</li>
|
||
<li>应用(Redis、Memcached 等)对延迟非常敏感,无法忍受中间代理服务器的花销。</li>
|
||
</ul>
|
||
<p>这些情况下,代理服务器和低层的管道层并无区别。实际上,代理无法对这种情况作出合适的优化,这种延迟可能会更高。</p>
|
||
<p>举例说明,看看下图的应用。其中包含了一个 Python 应用以及一组 Memcached。根据连接时间进行路由,选择了一个 Memcached 作为上游服务器。速度是这里的首要考量。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:38.63965267727931%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/delayering-istio/memcached.png" title="延迟敏感的应用场景">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/delayering-istio/memcached.png" alt="无代理的数据路径" />
|
||
</a>
|
||
</div>
|
||
<figcaption>延迟敏感的应用场景</figcaption>
|
||
</figure>
|
||
<p>浏览图中的数据流,Python 应用发起了到 Memcached IP 的连接。该连接被重定向到客户端的 Sidecar。Sidecar 把连接路由到一个 Memcached 服务器,并在两个 Socket 之间复制数据——一端是应用,一端是 Memcached。同样的事情也发生在服务端的 Sidecar 和 Memcached 之间。这一场景之下,代理服务器的角色只是无聊的在两个 Socket 之间传送字节流,同时还给端到端连接造成了大量延迟。</p>
|
||
<p>想象一下,如果应用跳过两个代理,直接连接到 Memcached。数据会在应用和 Memcached 服务之间直接流动。AppSwitch 在 Python 应用发起 <code>connect(2)</code> 系统调用时会透明地对系统调用的目标地址进行调整。</p>
|
||
<h3 id="proxyless-protocol-decoding">无代理的协议解码</h3>
|
||
<p>这一节要谈的事情有点奇怪。在前面我们看到,在无需了解流量内容的情况下,可以跳过代理服务器。但是其它场景呢?也是可以的。</p>
|
||
<p>在典型的微服务通信场景中,Header 中会有很多有用的信息。Header 之后会是信息本体或者负载,这些构成通信的主体。这里代理服务器再一次退行成为数据推送器。AppSwitch 为这些用例提供了一个花招,用于跳过代理服务器。</p>
|
||
<p>虽说 AppSwitch 并非代理,它会对应用端点之间的连接进行仲裁,还能访问对应 Socket 的文件描述符。通常 AppSwitch 简单的把这些 FD 传给应用。但是它也可以使用 <code>recvfrom(2)</code> 系统调用的 <code>MSG_PEEK</code> 选项查看连接上收到的初始消息。这样 AppSwitch 就能在不从 Socket 缓冲区中取出信息的情况下获取流量的内容。当 AppSwitch 将 FD 发给应用并退出数据路径之后,应用程序才会对连接进行真正的读取。AppSwitch 使用这一技术,对应用级的流量进行深层分析,在不进入数据路径的前提下,实现下面将要谈到的复杂网络功能。</p>
|
||
<h3 id="zero-cost-load-balancer-firewall-and-network-analyzer">零损耗的负载均衡器、防火墙和网络分析器</h3>
|
||
<p>负载均衡器和防火墙这样的典型网络功能,通常的实现方式都是引入一个中间层,介入到数据/包之中。Kubernetes 的负载均衡器(<code>kube-proxy</code>)实现利用 iptables 完成对数据包流的探测,Istio 也在代理层中实现了同样的功能。但是如果目标只是根据策略来对连接进行重定向或者丢弃,那么在整个连接过程中都介入到数据通路上是不必要的。AppSwitch 能够更有效的处理这些任务,只要简单的在 API 层面处理控制路径即可。AppSwitch 和应用紧密结合,因此还能够获取更多的应用信息,例如堆栈动态和堆利用情况、服务就绪时间以及活动连接属性等,这些信息可以为监控和分析提供更大发的操作空间。</p>
|
||
<p>更进一步,AppSwitch 还能够利用从 Socket 缓冲区获取的协议数据,完成七层负载均衡和防火墙功能。它能够利用从 Pilot 获取的策略信息,合成协议数据和各种其它信号,从而实现高效的路由和访问控制能力。实际上,无需对应用程序自身或配置做出任何变动,AppSwitch 也可以“诱导”应用连接到正确的后端服务器。看起来好像应用程序本身就具备了策略和流量管理能力。</p>
|
||
<p>实际上还存在一种可能的黑魔法就是,无需进入数据路径,也能够对应用的数据流进行修改,后面我会专门撰文描述这一功能。目前如果有对应用协议流量进行修改的需要,AppSwitch 当前的实现是使用一个代理,AppSwitch 使用一种高度优化的机制来完成代理任务,下一节将继续说明。</p>
|
||
<h3 id="traffic-redirection">流量重定向</h3>
|
||
<p>Sidecar 代理要获知应用的协议流量,首先需要接入连接。利用包过滤层改写包,让数据包进入对应的 Sidecar,从而完成对应用程序进入和发出连接的重定向任务。要实现重定向规则,就意味着要编写大量规则,这是很繁琐的工作。Sidecar 捕获的目标子网发生变化时,规则的应用和更新也是很昂贵的操作。</p>
|
||
<p>虽说 Linux 社区正在解决一些性能问题,但是还有特权相关的问题:不论何时策略发生变化,iptables 的规则都要随之更新。当前架构下,所有特权操作都是在初始化容器中执行,初始化容器只会在应用启动时执行一次,然后这一特权就会被删除;更新 iptables 规则需要 root 权限,所以如果不重新启动应用,则无法再次执行更新。</p>
|
||
<p>AppSwitch 提供了无需 root 特权就能重定向应用连接的方法。这样一个无特权应用也能够连接任何主机。应用程序的所有者无需额外权限,就可以修改应用的 <code>connect(2)</code> 调用时的主机地址。</p>
|
||
<h4 id="socket-delegation">Socket 委托</h4>
|
||
<p>接下来看看 AppSwitch 如何在不使用 iptables 的情况下进行连接重定向。想象一下,应用程序能够以某种方式主动传递它用于与 Sidecar 通信的 Socket 文件描述符的话,就不需要 iptables 了。AppSwitch 提供了一种称为 <strong>Socket 委托</strong>的机制用于完成这一任务。这个功能让 Sidecar 在不更改应用程序的情况下,透明的访问应用程序用于通信的 Socket 文件描述符的副本。</p>
|
||
<p>举个例子,在我们的 Python 示例应用中用于完成这一目标的几个步骤。</p>
|
||
<ol>
|
||
<li>应用初始化一个到 memcached 服务 IP 的连接请求。</li>
|
||
<li>客户端发出的连接请求被转发给守护进程。</li>
|
||
<li>守护进程创建一对预连接的 Unix socket(用 <code>socketpair(2)</code> 系统调用)。</li>
|
||
<li>发送 Socket 对中的一端给应用,应用会用这个 FD 进行读写。它还要确保应用始终视其为合法 Socket,以便于侵入所有对连接属性的查询。</li>
|
||
<li>另外一端会通过一个不同的用于开放守护进程 API 的 Unix Socket 发送给 Sidecar。原始目的之类的信息也会由相同的接口进行传输。</li>
|
||
</ol>
|
||
<figure style="width:50%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:22.442748091603054%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/delayering-istio/socket-delegation.png" title="基于 Socket 委托的连接重定向">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/delayering-istio/socket-delegation.png" alt="Socket 委托协议" />
|
||
</a>
|
||
</div>
|
||
<figcaption>基于 Socket 委托的连接重定向</figcaption>
|
||
</figure>
|
||
<p>应用和 Sidecar 连接之后,接下来的事情就很普通了。Sidecar 初始化一个到上游服务器的连接,并在从守护进程接收到的 Socket 和连接到上游服务器的 Socket 之间充当数据代理。这里的主要区别在于,Sidecar 得到的连接不是通过 <code>accept(2)</code> 系统调用而来的,而是由守护进程的 Unix socket 来的。Sidecar 不再通过监听来自应用的 <code>accept(2)</code> 通道,而是连接到 AppSwitch 守护进程的 REST 端点获取到的 Socket。</p>
|
||
<p>为了完整叙述,再说说服务端发生的事情:</p>
|
||
<ol>
|
||
<li>应用接收到一个连接。</li>
|
||
<li>AppSwitch 守护进程代应用程序接受这个连接。</li>
|
||
<li>用 <code>socketpair(2)</code> 系统调用创建一对预连接的 Unix Socket。</li>
|
||
<li>Socket 对的一端通过 <code>accept(2)</code> 系统调用返回给应用。</li>
|
||
<li>Socket 对的另外一端会和守护进程以应用程序身份接收的 Socket 一起发送给 Sidecar。</li>
|
||
<li>Sidecar 会解开这两个 Socket FD - 一个 Unix Socket FD 连接到应用,另一个 TCP Socket FD 连接到远程客户端。</li>
|
||
<li>Sidecar 会读取守护进程提供的关于远程客户端的元数据,并执行正常操作。</li>
|
||
</ol>
|
||
<h4 id="sidecar-aware-applications">Sidecar 感知的应用</h4>
|
||
<p>Socket 委托功能对于知晓 Sidecar 存在并希望利用其能力的应用非常有用。应用程序可以通过相同的功能,把 Socket 传递给 Sidecar,委托其进行网络交互。一定程度上,AppSwitch 透明的把每个应用都转换成为了 Sidecar 感知应用。</p>
|
||
<h2 id="how-does-it-all-come-together">如何整合这些功能?</h2>
|
||
<p>退一步看,Istio 把应用程序的连接问题转嫁给 Sidecar,由 Sidecar 代表应用执行这些功能。AppSwitch 对这些服务网格进行了简化和优化,绕过了中间层,仅在确实需要时才调用代理。</p>
|
||
<p>接下来讲讲 AppSwitch 可以如何初步集成到 Istio 之中。这不是设计文档,其中涉及到的可能的集成方式并没有经过完全的验证,一些细节还没能解决。这里的尝试是一个大致的将两个系统组合在一起的概要。在这一方案中 AppSwitch 作为一个类似垫片的东西出现在 Istio(应该是网格内应用——译者注)和真正的代理之间。它会作为一个快速通路,用绕过 Sidecar 代理的方式更高效的运作。对于需要使用代理的场合,也会通过移除层的方式缩短数据路径。这篇<a href="http://appswitch.io/blog/kubernetes_istio_and_network_function_devirtualization_with_appswitch/">博客</a>中记录了更多这方面的细节。</p>
|
||
<h3 id="appswitch-client-injection">AppSwitch 的客户端注入</h3>
|
||
<p>和 Istio 的 sidecar-injector 类似,AppSwitch 提供了一个 <code>ax-injector</code> 工具用来把 AppSwitch 客户端注入到标准的 Kubernetes 清单文件中。被注入的客户端会透明的监测应用,并把应用程序生成的控制路径上的网络 API 事件报告给 AppSwitch 守护进程。</p>
|
||
<p>如果使用了 AppSwitch CNI 插件,还可能仅使用标准 Kubernetes 清单文件,无需注入。这种情况下,CNI 插件会在获得初始化回调时完成必要的注入任务。注入器有以下优点:</p>
|
||
<ol>
|
||
<li>可以在 GKE 这样的的严格受控的环境中工作。</li>
|
||
<li>可以轻松的扩展到其它平台,例如 Mesos。</li>
|
||
<li>同一个集群中可以同时运行标准应用以及启用 AppSwitch 支持的应用。</li>
|
||
</ol>
|
||
<h3 id="appswitch-daemonset">AppSwitch <code>DaemonSet</code></h3>
|
||
<p>AppSwitch 守护进程可以配置成 <code>DaemonSet</code> 的运行方式,也可以作为直接注入应用程序清单的扩展。两种方式下都能够处理来自受支持应用的网络事件。</p>
|
||
<h3 id="agent-for-policy-acquisition">用于获取策略的 Agent</h3>
|
||
<p>这一组件用来将 Istio 的配置和策略转达给 AppSwitch。它实现了 xDS API,用来监听 Pilot,并调用对应的 AppSwitch API,来完成守护进程的程控。例如可以把 <code>istioctl</code> 制定的负载均衡策略翻译成等效的 AppSwitch 能力。</p>
|
||
<h3 id="platform-adapter-for-appswitch-auto-curated-service-registry">AppSwitch 服务注册表的平台适配器</h3>
|
||
<p>AppSwitch 是存在于应用网络 API 的控制路径上的,因此也就具备了访问集群上服务拓扑的能力。AppSwitch 用服务注册表的形式公布信息,这个注册表会随着应用和服务的变化来自动的进行同步更新。Kubernetes 之外的平台适配器,例如 Eureka,会为 Istio 提供上游服务的详细信息。这虽然并非必要,但更有助于上面提到的 AppSwitch Agent 关联从 Pilot 接收到的端点信息。</p>
|
||
<h3 id="proxy-integration-and-chaining">代理集成和链路</h3>
|
||
<p>通过前面讨论过的 Socket 委托机制,能够将需要深度扫描和应用程序流量突变的连接传递给外部代理。这一过程使用了一个扩展的<a href="https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt">代理服务器协议</a>。在简单的代理协议参数之外,加入了其它的元数据(包括从 Socket 缓冲区中获取的协议 Header)以及活跃的 Socket FD(代表应用的连接),转发给代理服务器。</p>
|
||
<p>代理服务器取得元数据之后会进行处理决策。可能接受连接执行代理任务,也可能重定向给 AppSwitch 从而把连接送入快速通道,当然,还有可能直接丢弃连接。</p>
|
||
<p>这个机制中有一点比较有趣,当代理从 AppSwitch 接收一个 Socket 的时候,它可以把这个委托转交给其它代理。实际上 AppSwitch 目前就是这么做的。它会用一个简单的内置代理来检查元数据,然后决定在内部处理连接,还是交出去给外部代理(Envoy)。这种机制可以扩展为插件链条,每个环节都
|
||
在其中查找特定签名,链条最后一节完成真正的代理工作。</p>
|
||
<h2 id="it-is-not-just-about-performance">不仅仅是性能</h2>
|
||
<p>从数据路径上移除中间层,不仅仅意味着性能的提高。性能提高是好事,但这仅仅是一个副产品。在 API 级别上,有更多的重要提升。</p>
|
||
<h3 id="automatic-application-onboarding-and-policy-authoring">应用接入和策略生成的自动化</h3>
|
||
<p>在微服务和服务网格之前,流量管理由负载均衡器完成,而访问控制则由防火墙完成。通过 IP 地址和 相对静态的 DNS 名称来鉴别应用。实际上这仍然是当前大多数环境的现状。这样的环境将从服务网格中受益匪浅。相对于新功能的开发来说,转型难度并不高,但是需要对整个基础设施进行重新思考和重新实现,这就需要投入了。目前多数策略和配置存在于负载均衡和防火墙中,现存的上下文需要有一个可扩展的路径来完成到服务网格模型的过渡。</p>
|
||
<p>AppSwitch 能够大大简化接入流程。它可以把应用程序源环境投射到目标环境。如果传统应用的配置文件包含了硬编码的 IP 地址或者 DNS 名称,通常是难于迁移的。AppSwitch 可以协助捕获这些应用及其配置,在无需更改的情况下将其接入服务网格。</p>
|
||
<h3 id="broader-application-and-protocol-support">更大范围的应用和协议支持</h3>
|
||
<p>众所周知,HTTP 是的现代应用程序领域的主导协议,但是一旦涉及传统应用和环境,我们会遇到各种协议和传输方式。有时候连 UDP 的支持都是必要选项,例如 IBM 的 WebSphere 就广泛的依赖 UDP,多数多媒体应用也在使用 UDP 媒体流。当然,DNS 可能是最多使用的 UDP 应用。AppSwitch 在 API 级别为 UDP 提供了和 TCP 非常相似的支持,它检测到 UDP 连接之后,会透明的在快速路径中进行处理,而不是委托给代理。</p>
|
||
<h3 id="client-IP-preservation-and-end-to-end-principle">保留客户端 IP 以及端到端原则</h3>
|
||
<p>和保留源网络环境的机制类似,同样也可以保留服务器视角的客户端 IP 地址。在 Sidecar 的干扰下,连接通常是来自于 Sidecar 而非客户端,这样服务端应用看到的对端地址就被替换为代理服务器的 IP。AppSwitch 能让服务器看到客户端的真实地址,进行正确的记录,并且能够通过该地址进行准确的决策。另外 AppSwitch 保留了<a href="https://en.wikipedia.org/wiki/End-to-end_principle">端到端原则</a>,中间层的存在会打破这一规则,并对真正的底层上下文造成混淆。</p>
|
||
<h3 id="enhanced-application-signal-with-access-to-encrypted-headers">访问加密 Header 以增强应用信号</h3>
|
||
<p>加密流量会阻止服务网格对流量的分析。API 级别的介入提供了一种可行的解决方法。AppSwitch 目前的实现能够在系统调用层面获得对应用网络 API 的访问。然而还有进一步的可能,在应用尚未加密或者已经加密的高级 API 边界上对应用程序施加影响。最终的视角上,应用生成明文数据,在发出之前的某个时间点进行加密。既然 AppSwitch 运行在应用的内存上下文中,因此就可能在更高层的数据中获取到明文。当然要完成这种功能,应用需要进行明确定义并且适合介入。同时这一功能还要访问应用二进制文件的符号表。目前 AppSwitch 还没有实现这一功能。</p>
|
||
<h2 id="so-what-is-the-net">所以收益如何?</h2>
|
||
<p>AppSwitch 从标准服务网格中移除了一组层次和操作。到底会对性能造成什么影响?</p>
|
||
<p>我们做了一些初级的实验,来对前面提到的 AppSwitch 集成方式在提高性能方面的优化进行定性。这个实验运行在 GKE 上,对应的软件系统包括 Fortio 0.11.0、Istio 0.8.0 以及 AppSwitch 0.4.0-2。在无代理测试中,AppSwitch 守护进程以 <code>DaemonSet</code> 的形式运行在 Kubernetes 集群中,并给 Fortio Pod 注入了 AppSwitch 客户端。这是仅有的两个步骤。这个测试的目的是衡量 100 并发连接的情况下,GRPC 的延迟情况。</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:54.66034755134282%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/delayering-istio/perf.png" title="有无 AppSwitch 的对比。">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/delayering-istio/perf.png" alt="性能对比" />
|
||
</a>
|
||
</div>
|
||
<figcaption>有无 AppSwitch 的对比。</figcaption>
|
||
</figure>
|
||
<p>初步显示,p50 延迟在有无 AppSwitch 的情况下有高达 18 倍的差距(3.99 毫秒 vs 72.96 毫秒)。如果禁用了日志和 Mixer,差距会缩减为 8 倍。很明显,这一差距就是因为数据路径上的多余层造成的。客户端和服务器分属两台不同主机,因此 Unix Socket 优化在这一场景上没有触发,有理由相信,如果客户端和服务器恰好在同一节点上,延迟会进一步缩小。究其根本,在 Kubernetes 上各自 Pod 中运行的服务器和客户端是通过 GKE 网络上的 TCP Socket 直接连接的——没有隧道、网桥或者代理。</p>
|
||
<h2 id="net-net">Net Net</h2>
|
||
<p>从 David Wheeler 的引言开始说到,另起一层并非解决层次过多问题的方案。我的博客中经常提到,目前的网络栈已经层次太多,应该精简,但是 AppSwitch 是不是又加了一层?</p>
|
||
<p>是的,AppSwitch 的确是另外一层。然而它的存在,能够移除更多层。这样一来,就把新的服务网格层和传统的网络层无缝的结合在一起。AppSwitch 不但抵消了 Sidecar 的成本,并且随着 Istio 1.0 的到来,还提供了一个从现有应用及其网络环境过度到服务网格世界的桥梁。</p>
|
||
<p>可能 Wheeler 的引言可以换个说法:</p>
|
||
<div>
|
||
<aside class="callout quote">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-quote"/></svg>
|
||
</div>
|
||
<div class="content">计算机科学中的所有问题,都可以用另一个层来解决,<strong>即使</strong>是层数太多的问题。</div>
|
||
</aside>
|
||
</div>
|
||
<h2 id="acknowledgements">感谢</h2>
|
||
<p>感谢 Mandar Jog(Google)进行了多次沟通,讨论 AppSwitch 对 Istio 的存在价值。同时也要感谢对本文稿件进行 Review 的几位朋友(以字母排序):</p>
|
||
<ul>
|
||
<li>Frank Budinsky (IBM)</li>
|
||
<li>Lin Sun (IBM)</li>
|
||
<li>Shriram Rajagopalan (VMware)</li>
|
||
</ul></description><pubDate>Mon, 30 Jul 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/delayering-istio/</link><author>Dinesh Subhraveti (AppOrbit and Columbia University)</author><guid isPermaLink="true">/v1.12/zh/blog/2018/delayering-istio/</guid><category>appswitch</category><category>performance</category></item><item><title>基于 Istio 授权的 Micro-Segmentation</title><description>
|
||
<p>Micro-Segmentation 是一种安全技术,可在云部署中创建安全区域,并允许各组织将工作负载彼此隔离以单独保护它们。
|
||
<a href="/v1.12/zh/docs/concepts/security/#authorization">Istio 的授权功能</a>也称为 Istio 基于角色的访问控制,为 Istio 网格中的服务提供
|
||
Micro-Segmentation。它的特点是:</p>
|
||
<ul>
|
||
<li>不同粒度级别的授权,包括命名空间级别、服务级别和方法级别。</li>
|
||
<li>服务间和最终用户到服务授权。</li>
|
||
<li>高性能,因为它在 Envoy 上本地执行。</li>
|
||
<li>基于角色的语义,使其易于使用。</li>
|
||
<li>灵活性高,因为它允许用户使用<a href="/v1.12/zh/docs/reference/config/security/constraints-and-properties">组合属性</a>定义条件。</li>
|
||
</ul>
|
||
<p>在这篇博客文章中,您将了解主要授权功能以及如何在不同情况下使用它们。</p>
|
||
<h2 id="characteristics">特点</h2>
|
||
<h3 id="RPC-level-authorization">RPC 级别授权</h3>
|
||
<p>授权在各个 RPC 级别执行。具体来说,它控制“谁可以访问我的 <code>bookstore</code> 服务”,或者“谁可以在我的 <code>bookstore</code> 服务中访问
|
||
<code>getBook</code> 方法 ”。它不是为了控制对于应用程序具体资源实例的访问而设计的,例如访问“存储桶 X ”或访问“第二层架上的第 3 本书”。目前这种应用特定的访问控制逻辑需要由应用程序本身处理。</p>
|
||
<h3 id="role-based-access-control-with-conditions">具有条件的基于角色的访问控制</h3>
|
||
<p>授权是<a href="https://en.wikipedia.org/wiki/Role-based_access_control">基于角色的访问控制(RBAC)</a> 系统,
|
||
将此与<a href="https://en.wikipedia.org/wiki/Attribute-based_access_control">基于属性的访问控制(ABAC)</a> 系统对比。
|
||
与 ABAC 相比,RBAC 具有以下优势:</p>
|
||
<ul>
|
||
<li><p><strong>角色允许对属性进行分组。</strong> 角色是权限组,用于指定允许的操作在系统上执行。用户根据组织内的角色进行分组。
|
||
您可以针对不同的情况定义角色并重用他们。</p></li>
|
||
<li><p><strong>关于谁有权访问,更容易理解和推理。</strong> RBAC 概念自然地映射到业务概念。例如,数据库管理员可能拥有对数据库后端服务的所有访问权限,
|
||
而 Web 客户端可能只能查看数据库后端服务前端服务。</p></li>
|
||
<li><p><strong>它减少了无意的错误。</strong> RBAC 策略使得复杂的安全更改变得更加容易。你不会有在多个位置重复配置,以后在需要进行更改时忘记更新其中一些配置。</p></li>
|
||
</ul>
|
||
<p>另一方面,Istio 的授权系统不是传统的 RBAC 系统。它还允许用户使用定义<strong>条件</strong><a href="/v1.12/zh/docs/reference/config/security/constraints-and-properties">属性组合</a>。这给了 Istio 表达复杂的访问控制策略的灵活性。实际上,<strong>Istio 授权采用“RBAC + 条件”模型,具有 RBAC 系统的所有优点,并支持通常是 ABAC 系统提供的灵活性。</strong>你会在下面看到一些<a href="#examples">示例</a>。</p>
|
||
<h3 id="high-performance">高性能</h3>
|
||
<p>由于其简单的语义,Istio 授权直接在 Envoy 本地执行。在运行时,授权决策完全在 Envoy 过滤器内部完成,不依赖于任何外部模块。
|
||
这允许 Istio 授权实现高性能和可用性。</p>
|
||
<h3 id="work-with-without-primary-identities">使用/不使用主要标识</h3>
|
||
<p>与任何其他 RBAC 系统一样,Istio 授权具有身份识别功能。在 Istio 授权政策中,有一个主要的
|
||
身份称为 <code>user</code>,代表客户的主体。</p>
|
||
<p>除主要标识外,您还可以自己定义标识。例如,您可以将客户端标识指定为“用户 <code>Alice</code> 从 <code>Bookstore</code> 前端服务调用”,在这种情况下,
|
||
你有一个调用服务(<code>Bookstore frontend</code>)和最终用户(<code>Alice</code>)的组合身份。</p>
|
||
<p>要提高安全性,您应该启用<a href="/v1.12/zh/docs/concepts/security/#authentication">认证功能</a>, 并在授权策略中使用经过验证的身份。但是,
|
||
使用授权不强迫一定要有身份验证。Istio 授权可以使用或不使用身份。如果您正在使用遗留系统,您可能没有网格的双向 TLS 或 JWT 身份验证
|
||
设置。在这种情况下,识别客户端的唯一方法是,例如,通过 IP。您仍然可以使用 Istio 授权来控制允许哪些 IP 地址或 IP 范围访问您的服务。</p>
|
||
<h2 id="examples">示例</h2>
|
||
<p><a href="/v1.12/zh/docs/tasks/security/authorization/authz-http">授权任务</a>通过 <a href="/v1.12/zh/docs/examples/bookinfo">Bookinfo 应用</a>向您展示如何使用 Istio 的授权功能来控制命名空间级别
|
||
和服务级别的访问。在本节中,您将看到更多使用 Istio 授权进行权限细分的示例。</p>
|
||
<h3 id="namespace-level-segmentation-via-rbac-conditions">通过 RBAC + 条件进行命名空间级别细分</h3>
|
||
<p>假设你在 <code>frontend</code> 和 <code>backend</code> 命名空间中有服务。您想要允许所有在 <code>frontend</code> 命名空间中的服务访问 <code>backend</code> 命名空间中标记
|
||
为 <code>external</code> 的所有服务。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRole
|
||
metadata:
|
||
name: external-api-caller
|
||
namespace: backend
|
||
spec:
|
||
rules:
|
||
- services: [&#34;*&#34;]
|
||
methods: [&#34;*”]
|
||
constraints:
|
||
- key: &#34;destination.labels[visibility]”
|
||
values: [&#34;external&#34;]
|
||
---
|
||
apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: external-api-caller
|
||
namespace: backend
|
||
spec:
|
||
subjects:
|
||
- properties:
|
||
source.namespace: &#34;frontend”
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;external-api-caller&#34;
|
||
</code></pre>
|
||
<p>上面的 <code>ServiceRole</code> 和 <code>ServiceRoleBinding</code> 表示“允许<em>谁</em> 在 <em>什么条件</em> (RBAC + 条件)下执行<em>什么</em> ”。其中:</p>
|
||
<ul>
|
||
<li><strong>“谁”</strong> 是 <code>frontend</code> 命名空间中的服务。</li>
|
||
<li><strong>“什么”</strong> 是在 <code>backend</code> 命名空间中调用服务。</li>
|
||
<li><strong>“条件”</strong> 是具有值 <code>external</code> 的目标服务的 <code>visibility</code> 标签。</li>
|
||
</ul>
|
||
<h3 id="service-method-level-isolation-with-without-primary-identities">具有/不具有主要身份的服务/方法级别隔离</h3>
|
||
<p>这是演示另一个服务/方法级别的细粒度访问控制的示例。第一步是定义一个 <code>book-reader</code> <code>ServiceRole</code>,它允许对 <code>bookstore</code> 服务中的 <code>/books/*</code> 资源进行 READ 访问。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRole
|
||
metadata:
|
||
name: book-reader
|
||
namespace: default
|
||
spec:
|
||
rules:
|
||
- services: [&#34;bookstore.default.svc.cluster.local&#34;]
|
||
paths: [&#34;/books/*”]
|
||
methods: [&#34;GET”]
|
||
</code></pre>
|
||
<h4 id="using-authenticated-client-identities">使用经过身份验证的客户端身份</h4>
|
||
<p>假设你想把这个 <code>book-reader</code> 角色授予你的 <code>bookstore-frontend</code> 服务。如果您已启用
|
||
您的网格的<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS 身份验证</a>, 您可以使用服务帐户,以识别您的 <code>bookstore-frontend</code> 服务。授予 <code>book-reader</code> 角色到 <code>bookstore-frontend</code> 服务可以通过创建一个 <code>ServiceRoleBinding</code> 来完成,如下所示:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: book-reader
|
||
namespace: default
|
||
spec:
|
||
subjects:
|
||
- user: &#34;cluster.local/ns/default/sa/bookstore-frontend”
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;book-reader&#34;
|
||
</code></pre>
|
||
<p>您可能希望通过添加“仅属于 <code>qualified-reviewer</code> 组的用户的条件来进一步限制此操作允许阅读书籍“。<code>qualified-reviewer</code> 组是经过身份验证的最终用户身份 <a href="/v1.12/zh/docs/concepts/security/#authorization">JWT 身份验证</a>。在这种情况下,客户端服务标识(<code>bookstore-frontend</code>)和最终用户身份(<code>qualified-reviewer</code>)的组合将用于授权策略。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: book-reader
|
||
namespace: default
|
||
spec:
|
||
subjects:
|
||
- user: &#34;cluster.local/ns/default/sa/bookstore-frontend”
|
||
properties:
|
||
request.auth.claims[group]: &#34;qualified-reviewer”
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;book-reader&#34;
|
||
</code></pre>
|
||
<h4 id="client-does-not-have-identity">无身份客户</h4>
|
||
<p>强烈建议在授权策略中使用经过身份验证的身份以确保安全性。但是,如果你有一个如果遗留系统不支持身份验证,您可能没有经过身份验证的身份验证。即使没有经过身份验证的身份,您仍然可以使用 Istio 授权来保护您的服务。以下示例表明您可以在授权策略中指定允许的源 IP 范围。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;rbac.istio.io/v1alpha1&#34;
|
||
kind: ServiceRoleBinding
|
||
metadata:
|
||
name: book-reader
|
||
namespace: default
|
||
spec:
|
||
subjects:
|
||
- properties:
|
||
source.ip: 10.20.0.0/9
|
||
roleRef:
|
||
kind: ServiceRole
|
||
name: &#34;book-reader&#34;
|
||
</code></pre>
|
||
<h2 id="summary">概要</h2>
|
||
<p>Istio 在命名空间级别,服务级别和方法级别粒度上提供授权功能。它采用“ RBAC + 条件”模型,使其成为易于使用和理解的 RBAC 系统,同时提供 ABAC 系统级别的灵活性。由于 Istio 授权在 Envoy 上本地运行,它有很高的性能。Istio 授权既可以与 <a href="/v1.12/zh/docs/concepts/security/#authentication">Istio 认证功能</a>一起提供最佳的安全性,也可以用于为没有身份验证的旧系统提供访问控制。</p></description><pubDate>Fri, 20 Jul 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/istio-authorization/</link><author>Limin Wang</author><guid isPermaLink="true">/v1.12/zh/blog/2018/istio-authorization/</guid><category>authorization</category><category>rbac</category><category>security</category></item><item><title>通过 Stackdriver 将日志导出到 BigQuery、GCS、Pub/Sub</title><description>
|
||
<p>这篇文章展示了如何将 Istio 日志指向 <a href="https://cloud.google.com/stackdriver/"><code>Stackdriver</code></a> 并将这些日志导出到各种配置的接收器,例如 <a href="https://cloud.google.com/bigquery/"><code>BigQuery</code></a>、<a href="https://cloud.google.com/storage/"><code>Google Cloud Storage(GCS)</code></a> 或 <a href="https://cloud.google.com/pubsub/"><code>Cloud Pub/Sub</code></a>。在这篇文章的最后,可以从喜欢的地方(如 BigQuery、GCS 或 Cloud Pub/Sub)对 Istio 数据进行分析。</p>
|
||
<p><a href="/v1.12/zh/docs/examples/bookinfo/"><code>Bookinfo</code></a> 示例应用程序在整个任务中用作示例应用程序。</p>
|
||
<h2 id="before-you-begin">开始之前</h2>
|
||
<p>在集群中 <a href="/v1.12/zh/docs/setup/"><code>安装 Istio</code></a> 并部署应用程序。</p>
|
||
<h2 id="configuring-Istio-to-export-logs">配置 Istio 导出日志</h2>
|
||
<p>Istio 使用 <code>logentry</code> <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/templates/logentry"><code>模板</code></a> 导出日志。这里指定了可用于分析的所有变量。它包含源服务、目标服务、<code>auth</code> 指标(即将实现&hellip;&hellip;)等信息。以下是示意图:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:75%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/export-logs-through-stackdriver/istio-analytics-using-stackdriver.png" title="导出日志到 Stackdriver 进行分析的图释">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/export-logs-through-stackdriver/istio-analytics-using-stackdriver.png" alt="导出日志到 Stackdriver 进行分析的图释" />
|
||
</a>
|
||
</div>
|
||
<figcaption>导出日志到 Stackdriver 进行分析的图释</figcaption>
|
||
</figure>
|
||
<p>Istio 支持将日志导出到 Stackdriver,而 Stackdriver 又可以配置为将日志导出到喜欢的接收器,如 BigQuery、Pub/Sub 或 GCS。请按照以下步骤设置喜欢的接收器,首先导出日志,然后在 Istio 中使用 Stackdriver。</p>
|
||
<h3 id="setting-up-various-log-sinks">设置各种日志接收器</h3>
|
||
<p>所有接收器的通用设置:</p>
|
||
<ol>
|
||
<li>为项目启用 <a href="https://cloud.google.com/monitoring/api/enable-api"><code>Stackdriver Monitoring API</code></a> 。</li>
|
||
<li>确保配置的接收器的 <code>principalEmail</code> 具有对项目写入的权限和日志管理员角色的权限。</li>
|
||
<li>确保已设置 <code>GOOGLE_APPLICATION_CREDENTIALS</code> 环境变量。请按照 <a href="https://cloud.google.com/docs/authentication/getting-started"><code>此处</code></a> 的说明进行设置。</li>
|
||
</ol>
|
||
<h4 id="big-query">BigQuery</h4>
|
||
<ol>
|
||
<li><a href="https://cloud.google.com/bigquery/docs/datasets"><code>创建 BigQuery 数据集</code></a> 作为日志导出的目标。</li>
|
||
<li>记录数据集的 ID。这里需要设置 Stackdriver 处理程序。它的格式为 <code>bigquery.googleapis.com/projects/[PROJECT_ID]/datasets/[DATASET_ID]</code></li>
|
||
<li>给 <a href="https://cloud.google.com/logging/docs/api/tasks/exporting-logs#writing_to_the_destination"><code>接收器授权</code></a>:cloud-logs@system.gserviceaccount.com。它具有 IAM 中的 BigQuery Data Editor 的角色。</li>
|
||
<li>如果使用 <a href="/v1.12/zh/docs/setup/platform-setup/gke/"><code>Google Kubernetes Engine</code></a>,请确保在集群上启用了 <code>bigquery</code> <a href="https://cloud.google.com/sdk/gcloud/reference/container/clusters/create"><code>Scope</code></a>。</li>
|
||
</ol>
|
||
<h4 id="google-cloud-storage">Google Cloud Storage (GCS)</h4>
|
||
<ol>
|
||
<li><a href="https://cloud.google.com/storage/docs/creating-buckets"><code>创建 GCS 存储桶</code></a>,希望导出日志到 GCS 中。</li>
|
||
<li>记录存储桶的 ID。这里需要配置 Stackdriver。它的形式为 <code>storage.googleapis.com/[BUCKET_ID]</code>。</li>
|
||
<li>给 <a href="https://cloud.google.com/logging/docs/api/tasks/exporting-logs#writing_to_the_destination"><code>接收器授权</code></a>:<code>cloud-logs @ system.gserviceaccount.com</code>。它具有 IAM 中的 Storage Object Creator 的角色。</li>
|
||
</ol>
|
||
<h4 id="google-cloud-pub-sub">Google Cloud Pub/Sub</h4>
|
||
<ol>
|
||
<li><a href="https://cloud.google.com/pubsub/docs/admin"><code>创建主题</code></a>,希望导出日志到 Google Cloud Pub/Sub 中。</li>
|
||
<li>记录主题的 ID。这里需要配置 Stackdriver。它的形式为<code>pubsub.googleapis.com/projects/[PROJECT_ID]/topics/[TOPIC_ID]</code>。</li>
|
||
<li>给 <a href="https://cloud.google.com/logging/docs/api/tasks/exporting-logs#writing_to_the_destination"><code>接收器授权</code></a>:<code>cloud-logs @ system.gserviceaccount.com</code>。它具有 IAM 中的 Pub/Sub Publisher 角色。</li>
|
||
<li>如果使用 <a href="/v1.12/zh/docs/setup/platform-setup/gke/"><code>Google Kubernetes Engine</code></a>,请确保在集群中启动了 <code>pubsub</code> <a href="https://cloud.google.com/sdk/gcloud/reference/container/clusters/create"><code>Scope</code></a>。</li>
|
||
</ol>
|
||
<h3 id="setting-up-stack-driver">设置 Stackdriver</h3>
|
||
<p>必须创建 Stackdriver 处理程序,将数据导出到 Stackdriver。Stackdriver 处理程序的配置在 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/adapters/stackdriver/"><code>此处</code></a> 描述。</p>
|
||
<ol>
|
||
<li><p>保存如下的 yaml 文件为 <code>stackdriver.yaml</code> 。并替换 <code>&lt;project_id&gt;,
|
||
&lt;sink_id&gt;, &lt;sink_destination&gt;, &lt;log_filter&gt;</code> 为相应的值。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: stackdriver
|
||
metadata:
|
||
name: handler
|
||
namespace: istio-system
|
||
spec:
|
||
# 设置 pushInterval 值。默认值是每分钟一次,不设置使用默认值。
|
||
# pushInterval: 1m
|
||
# 必须设置 Stacldriver 适配器 project_id 的值。
|
||
project_id: &#34;&lt;project_id&gt;&#34;
|
||
# apiCredentials 和 apiKey 必须设置之一;首选方法是`appCredentials`,它对应于 Google 应用程序默认凭据。
|
||
# 如果没有提供,我们使用默认应用凭据。
|
||
# appCredentials:
|
||
# apiKey:
|
||
# serviceAccountPath:
|
||
# 描述如何将 Istio 日志映射到 Stackdriver。
|
||
logInfo:
|
||
accesslog.logentry.istio-system:
|
||
payloadTemplate: &#39;{{or (.sourceIp) &#34;-&#34;}} - {{or (.sourceUser) &#34;-&#34;}} [{{or (.timestamp.Format &#34;02/Jan/2006:15:04:05 -0700&#34;) &#34;-&#34;}}] &#34;{{or (.method) &#34;-&#34;}} {{or (.url) &#34;-&#34;}} {{or (.protocol) &#34;-&#34;}}&#34; {{or (.responseCode) &#34;-&#34;}} {{or (.responseSize) &#34;-&#34;}}&#39;
|
||
httpMapping:
|
||
url: url
|
||
status: responseCode
|
||
requestSize: requestSize
|
||
responseSize: responseSize
|
||
latency: latency
|
||
localIp: sourceIp
|
||
remoteIp: destinationIp
|
||
method: method
|
||
userAgent: userAgent
|
||
referer: referer
|
||
labelNames:
|
||
- sourceIp
|
||
- destinationIp
|
||
- sourceService
|
||
- sourceUser
|
||
- sourceNamespace
|
||
- destinationIp
|
||
- destinationService
|
||
- destinationNamespace
|
||
- apiClaims
|
||
- apiKey
|
||
- protocol
|
||
- method
|
||
- url
|
||
- responseCode
|
||
- responseSize
|
||
- requestSize
|
||
- latency
|
||
- connectionMtls
|
||
- userAgent
|
||
- responseTimestamp
|
||
- receivedBytes
|
||
- sentBytes
|
||
- referer
|
||
sinkInfo:
|
||
id: &#39;&lt;sink_id&gt;&#39;
|
||
destination: &#39;&lt;sink_destination&gt;&#39;
|
||
filter: &#39;&lt;log_filter&gt;&#39;
|
||
---
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: stackdriver
|
||
namespace: istio-system
|
||
spec:
|
||
match: &#34;true&#34; # 缺省 match 为 true
|
||
actions:
|
||
- handler: handler.stackdriver
|
||
instances:
|
||
- accesslog.logentry
|
||
---
|
||
</code></pre></li>
|
||
<li><p>创建配置</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f stackdriver.yaml
|
||
stackdriver &#34;handler&#34; created
|
||
rule &#34;stackdriver&#34; created
|
||
logentry &#34;stackdriverglobalmr&#34; created
|
||
metric &#34;stackdriverrequestcount&#34; created
|
||
metric &#34;stackdriverrequestduration&#34; created
|
||
metric &#34;stackdriverrequestsize&#34; created
|
||
metric &#34;stackdriverresponsesize&#34; created
|
||
</code></pre></li>
|
||
<li><p>访问示例应用程序。
|
||
对于 <code>Bookinfo</code> 示例,请使用浏览器访问 <code>http://$GATEWAY_URL/productpage</code> 或发出以下命令:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl http://$GATEWAY_URL/productpage
|
||
</code></pre></li>
|
||
<li><p>验证日志是否正在通过 Stackdriver 流向配置的接收器。</p></li>
|
||
</ol>
|
||
<ul>
|
||
<li>Stackdriver:导航到项目的 <a href="https://pantheon.corp.google.com/logs/viewer"><code>Stackdriver Logs Viewer</code></a>,查看 “GKE Container” -&gt; “Cluster Name” -&gt; “Namespace Id”,查看 Istio 访问日志。</li>
|
||
<li>BigQuery:导航到项目的 <a href="https://bigquery.cloud.google.com/"><code>BigQuery Interface</code></a>,在接收器的数据集中找到一个前缀为 <code>accesslog_logentry_istio</code> 的表。</li>
|
||
<li>GCS:导航到项目的 <a href="https://pantheon.corp.google.com/storage/browser/"><code>Storage Brower</code></a>,在接收器的桶中找到一个名为 <code>accesslog.logentry.istio-system</code> 的桶。</li>
|
||
<li>Pub/Sub:导航到项目的 <a href="https://pantheon.corp.google.com/cloudpubsub/topicList"><code>Pub/Sub 主题列表</code></a>,在接收器的主题中找到 <code>accesslog</code> 主题。</li>
|
||
</ul>
|
||
<h2 id="understanding-what-happened">了解发生了什么</h2>
|
||
<p>上面的 <code>Stackdriver.yaml</code> 文件配置了 Istio 将访问日志发送到 Stackdriver,然后添加了一个接收器配置,将日志导出。具体如下:</p>
|
||
<ol>
|
||
<li><p>添加一个 <code>stackdriver</code> 类型的处理程序:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: stackdriver
|
||
metadata:
|
||
name: handler
|
||
namespace: &lt;your defined namespace&gt;
|
||
</code></pre></li>
|
||
<li><p>在 <code>spec</code> 上增加 <code>logInfo</code></p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >spec:
|
||
logInfo: accesslog.logentry.istio-system:
|
||
labelNames:
|
||
- sourceIp
|
||
- destinationIp
|
||
...
|
||
...
|
||
sinkInfo:
|
||
id: &#39;&lt;sink_id&gt;&#39;
|
||
destination: &#39;&lt;sink_destination&gt;&#39;
|
||
filter: &#39;&lt;log_filter&gt;&#39;
|
||
</code></pre></li>
|
||
</ol>
|
||
<p>在上面的配置中,sinkInfo 包含有关日志导出到所需接收器的信息。有关如何填写不同接收器的更多信息,请参阅 <a href="https://cloud.google.com/logging/docs/export/#sink-terms"><code>此处</code></a>。
|
||
|
||
1. 为 Stackdriver 添加规则</p>
|
||
<pre><code><pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: stackdriver
|
||
namespace: istio-system spec:
|
||
match: &#34;true&#34; # 缺省 match 为 true
|
||
actions:
|
||
- handler: handler.stackdriver
|
||
instances:
|
||
- accesslog.logentry
|
||
</code></pre></code></pre>
|
||
<h2 id="cleanup">清理</h2>
|
||
<ul>
|
||
<li><p>删除新的 Stackdriver 配置:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete -f stackdriver.yaml
|
||
</code></pre></li>
|
||
<li><p>如果不打算任何后续任务,请参阅 <a href="/v1.12/zh/docs/examples/bookinfo/#cleanup"><code>Bookinfo cleanup</code></a> 指令关闭应用程序。</p></li>
|
||
</ul>
|
||
<h2 id="availability-of-logs-in-export-sinks">日志导出的可用性</h2>
|
||
<p>导出到 BigQuery 只需几分钟(可以认为是瞬间完成的),不过 GCS 要延迟 2 至 12 小时,而 Pub/Sub 则几乎没有延迟。</p></description><pubDate>Mon, 09 Jul 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/export-logs-through-stackdriver/</link><author>Nupur Garg and Douglas Reid</author><guid isPermaLink="true">/v1.12/zh/blog/2018/export-logs-through-stackdriver/</guid></item><item><title>HTTP Egress 流量监控和访问策略</title><description>
|
||
<p>虽然 Istio 的主要关注点是管理服务网格内微服务之间的流量,但它也可以管理 ingress (从外部进入网格) 和 egress (从网格向外) 的流量。Istio 可以统一执行访问策略,并为网格内部、ingress 和 egress 流量聚合遥测数据。</p>
|
||
<p>在这篇博客文章中,将向您展示如何使用 Istio 进行 HTTP Egress 流量监控和访问策略。</p>
|
||
<h2 id="use-case">用例</h2>
|
||
<p>考虑一个运行处理 <em>cnn.com</em> 内容的应用程序的组织。应用程序被解耦为部署在 Istio 服务网格中的微服务。应用程序访问 <em>cnn.com</em> 的各种话题页面:<a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a>,<a href="https://edition.cnn.com/sport">edition.cnn.com/sport</a> 和 <a href="https://edition.cnn.com/health">edition.cnn.com/health</a>。该组织<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/">配置了访问 edition.cnn.com 的权限</a>,一切都正常运行。然而,在某一时刻,本组织决定移除政治话题。实际上,这意味着禁止访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> ,只允许访问 <a href="https://edition.cnn.com/sport">edition.cnn.com/sport</a> 和 <a href="https://edition.cnn.com/health">edition.cnn.com/health</a> 。该组织将根据具体情况,向个别应用程序和特定用户授予访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 的权限。</p>
|
||
<p>为了实现这一目标,组织的运维人员监控对外部服务的访问,并分析 Istio 日志,以验证没有向 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 发送未经授权的请求。他们还配置了 Istio 来防止自动访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 。</p>
|
||
<p>本组织决心防止对新策略的任何篡改,决定设置一些机制以防止恶意应用程序访问禁止的话题。</p>
|
||
<h2 id="related-tasks-and-examples">相关工作和示例</h2>
|
||
<ul>
|
||
<li><a href="/v1.12/zh/docs/tasks/traffic-management/egress/">Control Egress 流量</a>任务演示了网格内的应用程序如何访问外部(Kubernetes 集群之外) HTTP 和 HTTPS 服务。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/">配置 Egress 网关</a>示例描述了如何配置 Istio 来通过一个称为 <em>出口网关</em> 的专用网关服务来引导出口流量。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/">带 TLS 发起的 Egress 网关</a>示例演示了如何允许应用程序向需要 HTTPS 的外部服务器发送 HTTP 请求,同时通过 Egress Gateway 引导流量。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/observability/metrics/collecting-metrics/">收集指标</a>任务描述如何为网格中的服务配置指标。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/observability/metrics/using-istio-dashboard/">Grafana 的可视化指标</a>描述了用于监控网格流量的 Istio 仪表板。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/policy-enforcement/denial-and-list/">基本访问控制</a>任务显示如何控制对网格内服务的访问。</li>
|
||
<li><a href="/v1.12/zh/docs/tasks/policy-enforcement/denial-and-list/">拒绝和白/黑名单</a>任务显示如何使用黑名单或白名单检查器配置访问策略。</li>
|
||
</ul>
|
||
<p>与上面的遥测和安全任务相反,这篇博客文章描述了 Istio 的监控和访问策略,专门应用于 egress 流量。</p>
|
||
<h2 id="before-you-begin">开始之前</h2>
|
||
<p>按照<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/">带 TLS 发起的 Egress 网关</a>中的步骤,<strong>启用了双向 TLS 身份验证</strong>,而不需要<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination//#cleanup">清除</a>步骤。完成该示例后,您可以从安装了 <code>curl</code> 的网格中容器访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a>。本文假设 <code>SOURCE_POD</code> 环境变量包含源 pod 的名称,容器的名称为 <code>sleep</code>。</p>
|
||
<h2 id="configure-monitoring-and-access-policies">配置监控和访问策略</h2>
|
||
<p>由于您希望以 <em>安全方式</em> 完成您的任务,您应该通过 <em>egress 网关</em> 引导流量,正如<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/">带 TLS 发起的 Egress 网关</a>任务中所描述的那样。这里的 <em>安全方式</em> 意味着您希望防止恶意应用程序绕过 Istio 监控和策略强制。</p>
|
||
<p>根据我们的场景,组织执行了<a href="#before-you-begin">开始之前</a>部分中的命令,启用 HTTP 流量到 <em>edition.cnn.com</em> ,并将该流量配置为通过 egress 网关。egress 网关执行 TLS 发起到 <em>edition.cnn.com</em> ,因此流量在网格中被加密。此时,组织已经准备好配置 Istio 来监控和应用 <em>edition.cnn.com</em> 流量的访问策略。</p>
|
||
<h3 id="logging">日志</h3>
|
||
<p>配置 Istio 以记录对 <em>*.cnn.com</em> 的访问。创建一个 <code>logentry</code> 和两个 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/adapters/stdio/">stdio</a> <code>handlers</code>,一个用于记录禁止访问(<em>error</em> 日志级别),另一个用于记录对 <em>*.cnn.com</em> 的所有访问(<em>info</em> 日志级别)。然后创建规则将 <code>logentry</code> 实例定向到 <code>handlers</code>。一个规则指导访问 <em>*.cnn.com/politics</em> 为日志禁止访问处理程序, 另一个规则指导日志条目的处理程序,输出每个访问 <em>*.cnn.com</em> 作为 <em>info</em> 的日志级别。要了解 Istio <code>logentries</code>、<code>rules</code> 和 <code>handlers</code>,请参见 <a href="/v1.12/zh/blog/2017/adapter-model/">Istio 适配器模型</a>。下图显示了涉及的实体和它们之间的依赖关系:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:46.46700562636976%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-monitoring-access-control/egress-adapters-monitoring.svg" title="用于 egress 监视和访问策略的实例、规则和处理程序">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-monitoring-access-control/egress-adapters-monitoring.svg" alt="用于 egress 监视和访问策略的实例、规则和处理程序" />
|
||
</a>
|
||
</div>
|
||
<figcaption>用于 egress 监视和访问策略的实例、规则和处理程序</figcaption>
|
||
</figure>
|
||
<ol>
|
||
<li><p>创建 <code>logentry</code>、<code>rules</code> 和 <code>handlers</code>。注意您指定了 <code>context.reporter.uid</code> 作为
|
||
<code>kubernetes://istio-egressgateway</code> 在规则中只能从 egress 网关获取日志信息。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
# Log entry for egress access
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: logentry
|
||
metadata:
|
||
name: egress-access
|
||
namespace: istio-system
|
||
spec:
|
||
severity: &#39;&#34;info&#34;&#39;
|
||
timestamp: request.time
|
||
variables:
|
||
destination: request.host | &#34;unknown&#34;
|
||
path: request.path | &#34;unknown&#34;
|
||
responseCode: response.code | 0
|
||
responseSize: response.size | 0
|
||
reporterUID: context.reporter.uid | &#34;unknown&#34;
|
||
sourcePrincipal: source.principal | &#34;unknown&#34;
|
||
monitored_resource_type: &#39;&#34;UNSPECIFIED&#34;&#39;
|
||
---
|
||
# Handler for error egress access entries
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: stdio
|
||
metadata:
|
||
name: egress-error-logger
|
||
namespace: istio-system
|
||
spec:
|
||
severity_levels:
|
||
info: 2 # output log level as error
|
||
outputAsJson: true
|
||
---
|
||
# Rule to handle access to *.cnn.com/politics
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: handle-politics
|
||
namespace: istio-system
|
||
spec:
|
||
match: request.host.endsWith(&#34;cnn.com&#34;) &amp;&amp; request.path.startsWith(&#34;/politics&#34;) &amp;&amp; context.reporter.uid.startsWith(&#34;kubernetes://istio-egressgateway&#34;)
|
||
actions:
|
||
- handler: egress-error-logger.stdio
|
||
instances:
|
||
- egress-access.logentry
|
||
---
|
||
# Handler for info egress access entries
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: stdio
|
||
metadata:
|
||
name: egress-access-logger
|
||
namespace: istio-system
|
||
spec:
|
||
severity_levels:
|
||
info: 0 # output log level as info
|
||
outputAsJson: true
|
||
---
|
||
# Rule to handle access to *.cnn.com
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: handle-cnn-access
|
||
namespace: istio-system
|
||
spec:
|
||
match: request.host.endsWith(&#34;.cnn.com&#34;) &amp;&amp; context.reporter.uid.startsWith(&#34;kubernetes://istio-egressgateway&#34;)
|
||
actions:
|
||
- handler: egress-access-logger.stdio
|
||
instances:
|
||
- egress-access.logentry
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>发送三个 HTTP 请求到 <em>cnn.com</em> 、<a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a>、<a href="https://edition.cnn.com/sport">edition.cnn.com/sport</a> 和 <a href="https://edition.cnn.com/health">edition.cnn.com/health</a>。
|
||
三个请求都应该返回 <em>200 OK</em> 。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD -c sleep -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
200
|
||
200
|
||
200
|
||
</code></pre></li>
|
||
<li><p>查询 Mixer 日志,查看请求信息出现在日志中:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep egress-access | grep cnn | tail -4
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:43:24.611462Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:1883355,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:43:24.886316Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/sport&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2094561,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:43:25.369663Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/health&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2157009,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;error&#34;,&#34;time&#34;:&#34;2019-01-29T07:43:24.611462Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:1883355,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
</code></pre>
|
||
<p>您将看到与您的三个请求相关的四个日志条目。三个关于访问 <em>edition.cnn.com</em> 的 <em>info</em> 信息和一个关于访问 <em>edition.cnn.com/politics</em> 的 <em>error</em> 信息。服务网格 operators 可以查看所有访问实例,还可以搜索日志中表示禁止访问的 <em>error</em> 日志。这是在自动地阻塞禁止访问之前可以应用的第一个安全措施,即将所有禁止访问实例记录为错误。在某些设置中,这可能是一个足够的安全措施。</p>
|
||
<p>注意以下属性:</p>
|
||
<ul>
|
||
<li><code>destination</code>、<code>path</code>、<code>responseCode</code> 和 <code>responseSize</code> 与请求的 HTTP 参数相关</li>
|
||
<li><code>sourcePrincipal</code>:<code>cluster.local/ns/default/sa/sleep</code> —— 表示 <code>default</code> 命名空间中的 <code>sleep</code> 服务帐户的字符串</li>
|
||
<li><code>reporterUID</code>: <code>kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system</code> —— 报告 pod 的 UID,在本例中为 <code>istio-egressgateway-747b6764b8-44rrh</code>,位于 <code>istio-system</code> 命名空间中</li>
|
||
</ul></li>
|
||
</ol>
|
||
<h3 id="access-control-by-routing">路由访问控制</h3>
|
||
<p>启用对 <em>edition.cnn.com</em> 的访问进行日志记录之后,自动执行访问策略,即只允许访问 <em>/health</em> 和 <em>/sport</em> URL 路径。这样一个简单的策略控制可以通过 Istio 路由实现。</p>
|
||
<ol>
|
||
<li><p>为 <em>edition.cnn.com</em> 重定义 <code>VirtualService</code> :</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-cnn-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- edition.cnn.com
|
||
gateways:
|
||
- istio-egressgateway
|
||
- mesh
|
||
http:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: 80
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: cnn
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: 443
|
||
uri:
|
||
regex: &#34;/health|/sport&#34;
|
||
route:
|
||
- destination:
|
||
host: edition.cnn.com
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
EOF
|
||
</code></pre>
|
||
<p>注意,您通过 <code>url</code> 添加添加了一个 <code>match</code>,该条件检查 URL 路径是 <em>/health</em> 还是 <em>/sport</em> 。还要注意,此条件已添加到 <code>VirtualService</code> 的 <code>istio-egressgateway</code> 部分,因为就安全性而言,egress 网关是一个经过加固的组件(请参阅 <a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#additional-security-considerations">egress 网关安全性注意事项</a>)。您一定不希望您的任何策略被篡改。</p></li>
|
||
<li><p>发送之前的三个 HTTP 请求到 <em>cnn.com</em> :</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD -c sleep -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
404
|
||
200
|
||
200
|
||
</code></pre>
|
||
<p>向 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 发送请求会返回 <em>404 Not Found</em> ,然而向
|
||
<a href="https://edition.cnn.com/sport">edition.cnn.com/sport</a> 和
|
||
<a href="https://edition.cnn.com/health">edition.cnn.com/health</a> 发送请求,会像我们预想的那样返回 <em>200 OK</em> 。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">您可能需要等待几秒钟,等待 <code>VirtualService</code> 的更新传播到 egress 网关。</div>
|
||
</aside>
|
||
</div>
|
||
</li>
|
||
<li><p>查询 Mixer 日志,可以看到关于请求的信息再次出现在日志中:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep egress-access | grep cnn | tail -4
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:55:59.686082Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:404,&#34;responseSize&#34;:0,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:55:59.697565Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/sport&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2094561,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T07:56:00.264498Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/health&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2157009,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
{&#34;level&#34;:&#34;error&#34;,&#34;time&#34;:&#34;2019-01-29T07:55:59.686082Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:404,&#34;responseSize&#34;:0,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/sleep&#34;}
|
||
</code></pre>
|
||
<p>你依然会得到关于访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 的信息和错误消息,然而这次 <code>responseCode</code> 会像我们预想的那样返回 <code>404</code> 。</p></li>
|
||
</ol>
|
||
<p>虽然在这个简单的例子中使用 Istio 路由实现访问控制是可行的,但是在更复杂的例子中就不够了。例如,组织可能希望在某些条件下允许访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a>,因此需要比仅通过 URL 路径过滤更复杂的策略逻辑。您可能想要应用 Istio Mixer 适配器,例如允许/禁止 URL 路径的<a href="/v1.12/zh/docs/tasks/policy-enforcement/denial-and-list/#attribute-based-whitelists-or-blacklists">白名单或黑名单</a>。策略规则允许指定复杂的条件,用丰富的表达式语言指定,其中包括与和或逻辑运算符。这些规则可用于日志记录和策略检查。更高级的用户可能希望应用基于 <a href="/v1.12/zh/docs/concepts/security/#authorization">Istio 角色访问控制</a>。</p>
|
||
<p>另一方面是与远程访问策略系统的集成。如果在我们的用例中组织操作一些<a href="https://en.wikipedia.org/wiki/Identity_management">标识和访问管理</a>系统,您可能希望配置 Istio 来使用来自这样一个系统的访问策略信息。您可以通过应用 <a href="/v1.12/zh/blog/2017/adapter-model/">Istio Mixer 适配器</a>来实现这种集成。</p>
|
||
<p>现在您移除在本节中使用的路由取消访问控制,在下一节将向您演示通过 Mixer 策略检查实现访问控制。</p>
|
||
<ol>
|
||
<li><p>用之前<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway-tls-origination/#perform-TLS-origination-with-an-egress-gateway">配置 Egress 网关</a>示例中的版本替换 <em>edition.cnn.com</em> 的 <code>VirtualService</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: direct-cnn-through-egress-gateway
|
||
spec:
|
||
hosts:
|
||
- edition.cnn.com
|
||
gateways:
|
||
- istio-egressgateway
|
||
- mesh
|
||
http:
|
||
- match:
|
||
- gateways:
|
||
- mesh
|
||
port: 80
|
||
route:
|
||
- destination:
|
||
host: istio-egressgateway.istio-system.svc.cluster.local
|
||
subset: cnn
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
- match:
|
||
- gateways:
|
||
- istio-egressgateway
|
||
port: 443
|
||
route:
|
||
- destination:
|
||
host: edition.cnn.com
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>发送之前的三个 HTTP 请求到 <em>cnn.com</em> ,这一次您应该会收到三个 <em>200 OK</em> 的响应:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD -c sleep -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
200
|
||
200
|
||
200
|
||
</code></pre></li>
|
||
</ol>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">您可能需要等待几秒钟,等待 <code>VirtualService</code> 的更新传播到 egress 网关。</div>
|
||
</aside>
|
||
</div>
|
||
<h3 id="access-control-by-Mixer-policy-checks">Mixer 策略检查访问控制</h3>
|
||
<p>在该步骤中,您使用 Mixer <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/adapters/list/"><code>Listchecker</code> 适配器</a>,它是一种白名单。您可以使用请求的 URL 路径定义一个 <code>listentry</code>,并使用一个 <code>listchecker</code> 由 <code>overrides</code> 字段指定的允许 URL 路径的静态列表检查 <code>listentry</code>。对于<a href="https://en.wikipedia.org/wiki/Identity_management">外部标识和访问管理</a>系统,请使用 <code>providerurl</code> 字段。实例、规则和处理程序的更新图如下所示。注意,您重用相同的策略规则 <code>handle-cn-access</code> 来进行日志记录和访问策略检查。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:52.79420593027812%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-monitoring-access-control/egress-adapters-monitoring-policy.svg" title="用于 egress 监视和访问策略的实例、规则和处理程序">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-monitoring-access-control/egress-adapters-monitoring-policy.svg" alt="用于 egress 监视和访问策略的实例、规则和处理程序" />
|
||
</a>
|
||
</div>
|
||
<figcaption>用于 egress 监视和访问策略的实例、规则和处理程序</figcaption>
|
||
</figure>
|
||
<ol>
|
||
<li><p>定义 <code>path-checker</code> 和 <code>request-path</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl create -f -
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: listchecker
|
||
metadata:
|
||
name: path-checker
|
||
namespace: istio-system
|
||
spec:
|
||
overrides: [&#34;/health&#34;, &#34;/sport&#34;] # overrides provide a static list
|
||
blacklist: false
|
||
---
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: listentry
|
||
metadata:
|
||
name: request-path
|
||
namespace: istio-system
|
||
spec:
|
||
value: request.path
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>修改 <code>handle-cnn-access</code> 策略规则并发送 <code>request-path</code> 实例到 <code>path-checker</code>:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
# Rule handle egress access to cnn.com
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: handle-cnn-access
|
||
namespace: istio-system
|
||
spec:
|
||
match: request.host.endsWith(&#34;.cnn.com&#34;) &amp;&amp; context.reporter.uid.startsWith(&#34;kubernetes://istio-egressgateway&#34;)
|
||
actions:
|
||
- handler: egress-access-logger.stdio
|
||
instances:
|
||
- egress-access.logentry
|
||
- handler: path-checker.listchecker
|
||
instances:
|
||
- request-path.listentry
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>执行常规测试,将 HTTP 请求发送到 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a>,<a href="https://edition.cnn.com/sport">edition.cnn.com/sport</a> 和 <a href="https://edition.cnn.com/health">edition.cnn.com/health</a>。正如所料,对 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 的请求返回 <em>403</em> (禁止)。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD -c sleep -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
403
|
||
200
|
||
200
|
||
</code></pre></li>
|
||
</ol>
|
||
<h3 id="access-control-by-Mixer-policy-checks-part-2">Mixer 策略检查访问控制,第二部分</h3>
|
||
<p>在我们用例中的组织设法配置日志和访问控制之后,它决定扩展它的访问策略,允许具有特殊<a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/">服务帐户</a>的应用程序访问 <em>cnn.com</em> 的任何主题,而不受监控。您将看到如何在 Istio 中配置此需求。</p>
|
||
<ol>
|
||
<li><p>使用 <code>politics</code> 服务账户开启 <a href="https://github.com/istio/istio/tree/release-1.12/samples/sleep">sleep</a> 示例程序。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ sed &#39;s/: sleep/: politics/g&#39; samples/sleep/sleep.yaml | kubectl create -f -
|
||
serviceaccount &#34;politics&#34; created
|
||
service &#34;politics&#34; created
|
||
deployment &#34;politics&#34; created
|
||
</code></pre></li>
|
||
<li><p>定义 <code>SOURCE_POD_POLITICS</code> shell 变量来保存带有 <code>politics</code> 服务帐户的源 pod 的名称,以便向外部服务发送请求。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export SOURCE_POD_POLITICS=$(kubectl get pod -l app=politics -o jsonpath={.items..metadata.name})
|
||
</code></pre></li>
|
||
<li><p>执行常规测试,这次从 <code>SOURCE_POD_POLITICS</code> 发送三个 HTTP 请求。对 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 的请求返回 <em>403</em> ,因为您没有为 <em>politics</em> 命名空间配置异常。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD_POLITICS -c politics -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
403
|
||
200
|
||
200
|
||
</code></pre></li>
|
||
<li><p>查询 Mixer 日志,可以看到来自 <em>politics</em> 命名空间的请求信息出现在日志中:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep egress-access | grep cnn | tail -4
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T08:04:42.559812Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:403,&#34;responseSize&#34;:84,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/politics&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T08:04:42.568424Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/sport&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2094561,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/politics&#34;}
|
||
{&#34;level&#34;:&#34;error&#34;,&#34;time&#34;:&#34;2019-01-29T08:04:42.559812Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/politics&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:403,&#34;responseSize&#34;:84,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/politics&#34;}
|
||
{&#34;level&#34;:&#34;info&#34;,&#34;time&#34;:&#34;2019-01-29T08:04:42.615641Z&#34;,&#34;instance&#34;:&#34;egress-access.logentry.istio-system&#34;,&#34;destination&#34;:&#34;edition.cnn.com&#34;,&#34;path&#34;:&#34;/health&#34;,&#34;reporterUID&#34;:&#34;kubernetes://istio-egressgateway-747b6764b8-44rrh.istio-system&#34;,&#34;responseCode&#34;:200,&#34;responseSize&#34;:2157009,&#34;sourcePrincipal&#34;:&#34;cluster.local/ns/default/sa/politics&#34;}
|
||
</code></pre>
|
||
<p>注意 <code>sourcePrincipal</code> 是 <code>cluster.local/ns/default/sa/politics</code>,表示 <code>default</code> 命名空间中的 <code>politics</code> 服务帐户。</p></li>
|
||
<li><p>重新定义 <code>handle-cn-access</code> 和 <code>handl-politics</code> 策略规则,使 <em>politics</em> 命名空间中的应用程序免受监控和策略强制。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat &lt;&lt;EOF | kubectl apply -f -
|
||
# Rule to handle access to *.cnn.com/politics
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: handle-politics
|
||
namespace: istio-system
|
||
spec:
|
||
match: request.host.endsWith(&#34;cnn.com&#34;) &amp;&amp; context.reporter.uid.startsWith(&#34;kubernetes://istio-egressgateway&#34;) &amp;&amp; request.path.startsWith(&#34;/politics&#34;) &amp;&amp; source.principal != &#34;cluster.local/ns/default/sa/politics&#34;
|
||
actions:
|
||
- handler: egress-error-logger.stdio
|
||
instances:
|
||
- egress-access.logentry
|
||
---
|
||
# Rule handle egress access to cnn.com
|
||
apiVersion: &#34;config.istio.io/v1alpha2&#34;
|
||
kind: rule
|
||
metadata:
|
||
name: handle-cnn-access
|
||
namespace: istio-system
|
||
spec:
|
||
match: request.host.endsWith(&#34;.cnn.com&#34;) &amp;&amp; context.reporter.uid.startsWith(&#34;kubernetes://istio-egressgateway&#34;) &amp;&amp; source.principal != &#34;cluster.local/ns/default/sa/politics&#34;
|
||
actions:
|
||
- handler: egress-access-logger.stdio
|
||
instances:
|
||
- egress-access.logentry
|
||
- handler: path-checker.listchecker
|
||
instances:
|
||
- request-path.listentry
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>从 <code>SOURCE_POD</code> 中执行常规测试:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD -c sleep -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
403
|
||
200
|
||
200
|
||
</code></pre>
|
||
<p>由于 <code>SOURCE_POD</code> 没有 <code>politics</code> 服务帐户,所以像以前一样访问 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 会被禁止。</p></li>
|
||
<li><p>从 <code>SOURCE_POD_POLITICS</code> 中执行之前的测试:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl exec -it $SOURCE_POD_POLITICS -c politics -- sh -c &#39;curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &#34;%{http_code}\n&#34; http://edition.cnn.com/health&#39;
|
||
200
|
||
200
|
||
200
|
||
</code></pre>
|
||
<p>访问 <em>edition.cnn.com</em> 的所有话题都是被允许的。</p></li>
|
||
<li><p>检查 Mixer 日志,查看是否有更多使用 <code>sourcePrincipal</code> 请求,能够匹配 <code>cluster.local/ns/default/sa/politics</code> 的内容出现在日志中。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -n istio-system logs -l istio-mixer-type=telemetry -c mixer | grep egress-access | grep cnn | tail -4
|
||
</code></pre></li>
|
||
</ol>
|
||
<h2 id="comparison-with-HTTPS-egress-traffic-control">与 HTTPS egress 流量控制进行比较</h2>
|
||
<p>在这个用例中,应用程序使用 HTTP 和 Istio Egress 网关为它们执行 TLS 初始化。或者,应用程序可以通过向 <em>edition.cnn.com</em> 发出 HTTPS 请求来发起 TLS 本身。在本节中,我们将描述这两种方法及其优缺点。</p>
|
||
<p>在 HTTP 方法中,请求在本地主机上不加密地发送,由 Istio sidecar 代理拦截并转发到 egress 网关。由于您将 Istio 配置为在 sidecar 代理和 egress 网关之间使用相互的 TLS,因此流量会使 pod 加密。egress 网关解密流量,检查 URL 路径、HTTP 方法和报头,报告遥测数据并执行策略检查。如果请求没有被某些策略检查阻止,那么 egress 网关将执行 TLS 发起到外部目的地(在我们的示例中是 <em>cnn.com</em> ),因此请求将再次加密并发送到外部目的地。下图演示了这种方法的流程。网关内的 HTTP 协议根据解密后网关看到的协议来指定协议。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:64.81718469808756%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-monitoring-access-control/http-to-gateway.svg" title="HTTP egress 流量通过 egress 网关">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-monitoring-access-control/http-to-gateway.svg" alt="HTTP egress 流量通过 egress 网关" />
|
||
</a>
|
||
</div>
|
||
<figcaption>HTTP egress 流量通过 egress 网关</figcaption>
|
||
</figure>
|
||
<p>这种方法的缺点是请求在 pod 中发送时没有加密,这可能违反某些组织的安全策略。此外,一些 SDK 具有硬编码的外部服务 URL,包括协议,因此不可能发送 HTTP 请求。这种方法的优点是能够检查 HTTP 方法、头和 URL 路径,并基于它们应用策略。</p>
|
||
<p>在 HTTPS 方法中,从应用程序到外部目的地的请求是端到端加密的。下图演示了这种方法的流程。网关中的 HTTPS 协议指定网关所看到的协议。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:64.81718469808756%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-monitoring-access-control/https-to-gateway.svg" title="HTTPS egress 流量通过 egress 网关">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-monitoring-access-control/https-to-gateway.svg" alt="HTTPS egress 流量通过 egress 网关" />
|
||
</a>
|
||
</div>
|
||
<figcaption>HTTPS egress 流量通过 egress 网关</figcaption>
|
||
</figure>
|
||
<p>从安全的角度来看,端到端 HTTPS 被认为是一种更好的方法。然而,由于流量是加密的,Istio 代理和出口网关只能看到源和目标 IP 以及目标的 <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">SNI</a>。由于您将 Istio 配置为在 sidecar 代理和 egress 网关之间使用相互的 TLS ,所以<a href="/v1.12/zh/docs/concepts/security/#istio-identity">源标识</a>也是已知的。网关无法检查 URL 路径、HTTP 方法和请求的头,因此无法基于 HTTP 信息进行监控和策略。在我们的用例中,组织将能够允许访问 <em>edition.cnn.com</em> 并指定允许哪些应用程序访问 <em>edition.cnn.com</em> 。但是,将不可能允许或阻止对 <em>edition.cnn.com</em> 的特定 URL 路径的访问。使用 HTTPS 方法既不能阻止对 <a href="https://edition.cnn.com/politics">edition.cnn.com/politics</a> 的访问,也不能监控此类访问。</p>
|
||
<p>我们认为,每个组织都应充分考虑这两种方法的优缺点,并选择最适合其需要的方法。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>在这篇博客文章中,我们展示了如何将 Istio 的不同监控和策略机制应用于 HTTP egress 流量。可以通过配置日志适配器来实现监控。访问策略可以通过配置 <code>VirtualServices</code> 或配置各种策略检查适配器来实现。向您演示了一个只允许特定 URL 路径的简单策略。还向您展示了一个更复杂的策略,通过对具有特定服务帐户的应用程序进行豁免,扩展了简单策略。最后,比较了 HTTP-with-TLS-origination egress 流量与 HTTPS egress 流量,以及通过 Istio 进行控制的可能性。</p>
|
||
<h2 id="cleanup">清理</h2>
|
||
<ol>
|
||
<li><p>执行<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/">配置 Egress 网关</a>示例的<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-gateway/#cleanup">清理</a>部分中的说明。</p></li>
|
||
<li><p>删除日志和策略检查配置:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete logentry egress-access -n istio-system
|
||
$ kubectl delete stdio egress-error-logger -n istio-system
|
||
$ kubectl delete stdio egress-access-logger -n istio-system
|
||
$ kubectl delete rule handle-politics -n istio-system
|
||
$ kubectl delete rule handle-cnn-access -n istio-system
|
||
$ kubectl delete -n istio-system listchecker path-checker
|
||
$ kubectl delete -n istio-system listentry request-path
|
||
</code></pre></li>
|
||
<li><p>删除 <em>politics</em> 源 pod:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ sed &#39;s/: sleep/: politics/g&#39; samples/sleep/sleep.yaml | kubectl delete -f -
|
||
serviceaccount &#34;politics&#34; deleted
|
||
service &#34;politics&#34; deleted
|
||
deployment &#34;politics&#34; deleted
|
||
</code></pre></li>
|
||
</ol></description><pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/egress-monitoring-access-control/</link><author>Vadim Eisenberg and Ronen Schaffer (IBM)</author><guid isPermaLink="true">/v1.12/zh/blog/2018/egress-monitoring-access-control/</guid><category>egress</category><category>traffic-management</category><category>access-control</category><category>monitoring</category></item><item><title>Istio v1aplha3 路由 API 介绍</title><description>
|
||
<p>到目前为止,Istio 提供了一个简单的 API 来进行流量管理,该 API 包括了四种资源:<code>RouteRule</code>,<code>DestinationPolicy</code>,<code>EgressRule</code> 和 (Kubernetes 的)<code>Ingress</code>。借助此 API,用户可以轻松管理 Istio 服务网格中的流量。该 API 允许用户将请求路由到特定版本的服务,为弹性测试注入延迟和失败,添加超时和断路器等,所有这些功能都不必更改应用程序本身的代码。</p>
|
||
<p>虽然目前 API 的功能已被证明是 Istio 非常引人注目的一部分,但用户的反馈也表明,这个 API 确实有一些缺点,尤其是在使用它来管理包含数千个服务的非常大的应用程序,以及使用 HTTP 以外的协议时。此外,使用 Kubernetes Ingress 资源来配置外部流量的方式已被证明不能满足需求。</p>
|
||
<p>为了解决上述缺陷和其他的一些问题,Istio 引入了新的流量管理 API v1alpha3,新版本的 API 将完全取代之前的 API。尽管 v1alpha3 和之前的模型在本质上是基本相同的,但它并不向后兼容的,基于旧 API 的模型需要进行手动转换。</p>
|
||
<p>为了证明该非兼容升级的必要性,v1alpha3 API 经历了漫长而艰苦的社区评估过程,以希望新的 API 能够大幅改进,并经得起时间考验。在本文中,我们将介绍新的配置模型,并试图解释影响这次变化的一些动机和设计原则。</p>
|
||
<h2 id="design-principles">设计原则</h2>
|
||
<p>路由模型的重构过程中遵循了一些关键的设计原则:</p>
|
||
<ul>
|
||
<li>除支持声明式(意图)配置外,也支持显式指定模型依赖的基础设施。例如,除了配置入口网关(的功能特性)之外,负责实现 入口网关功能的组件(Controller)也可以在模型指定。</li>
|
||
<li>编写模型时应该&rdquo;生产者导向”和&rdquo;以 Host 为中心”,而不是通过组合多个规则来编写模型。例如,所有与特定 Host 关联的规则被配置在一起,而不是单独配置。</li>
|
||
<li>将路由与路由后行为清晰分开。</li>
|
||
</ul>
|
||
<h2 id="configuration-resources-in-v1alpha3">v1alpha3 中的配置资源</h2>
|
||
<p>在一个典型的网格中,通常有一个或多个用于终结外部 TLS 链接,将流量引入网格的负载均衡器(我们称之为 gateway)。然后流量通过边车网关(sidecar gateway)流经内部服务。应用程序使用外部服务的情况也很常见(例如访问 Google Maps API),一些情况下,这些外部服务可能被直接调用;但在某些部署中,网格中所有访问外部服务的流量可能被要求强制通过专用的出口网关(Egress gateway)。下图描绘了网关在网格中的使用情况。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:35.204472660409245%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/v1alpha3-routing/gateways.svg" title="Istio 服务网格中的网关">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/v1alpha3-routing/gateways.svg" alt="Role of gateways in the mesh" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 服务网格中的网关</figcaption>
|
||
</figure>
|
||
<p>考虑到上述因素,<code>v1alpha3</code>引入了以下这些新的配置资源来控制进入网格,网格内部和离开网格的流量路由。</p>
|
||
<ol>
|
||
<li><code>Gateway</code></li>
|
||
<li><code>VirtualService</code></li>
|
||
<li><code>DestinationRule</code></li>
|
||
<li><code>ServiceEntry</code></li>
|
||
</ol>
|
||
<p><code>VirtualService</code>,<code>DestinationRule</code> 和 <code>ServiceEntry</code> 分别替换了原 API 中的 <code>RouteRule</code>,<code>DestinationPolicy</code> 和 <code>EgressRule</code>。<code>Gateway</code> 是一个独立于平台的抽象,用于对流入专用中间设备的流量进行建模。</p>
|
||
<p>下图描述了跨多个配置资源的控制流程。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:41.164966727369595%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/v1alpha3-routing/virtualservices-destrules.svg" title="不同 v1alpha3 元素之间的关系">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/v1alpha3-routing/virtualservices-destrules.svg" alt="不同 v1alpha3 元素之间的关系" />
|
||
</a>
|
||
</div>
|
||
<figcaption>不同 v1alpha3 元素之间的关系</figcaption>
|
||
</figure>
|
||
<h3 id="gateway"><code>Gateway</code></h3>
|
||
<p><a href="/v1.12/zh/docs/reference/config/networking/gateway/"><code>Gateway</code></a> 用于为 HTTP / TCP 流量配置负载均衡器,并不管该负载均衡器将在哪里运行。网格中可以存在任意数量的 Gateway,并且多个不同的 Gateway 实现可以共存。实际上,通过在配置中指定一组工作负载(Pod)标签,可以将 Gateway 配置绑定到特定的工作负载,从而允许用户通过编写简单的 Gateway Controller 来重用现成的网络设备。</p>
|
||
<p>对于入口流量管理,您可能会问:<em>为什么不直接使用 Kubernetes Ingress API</em> ?原因是 Ingress API 无法表达 Istio 的路由需求。Ingress 试图在不同的 HTTP 代理之间取一个公共的交集,因此只能支持最基本的 HTTP 路由,最终导致需要将代理的其他高级功能放入到注解(annotation)中,而注解的方式在多个代理之间是不兼容的,无法移植。</p>
|
||
<p>Istio <code>Gateway</code> 通过将 L4-L6 配置与 L7 配置分离的方式克服了 <code>Ingress</code> 的这些缺点。<code>Gateway</code> 只用于配置 L4-L6 功能(例如,对外公开的端口,TLS 配置),所有主流的 L7 代理均以统一的方式实现了这些功能。然后,通过在 <code>Gateway</code> 上绑定 <code>VirtualService</code> 的方式,可以使用标准的 Istio 规则来控制进入 <code>Gateway</code> 的 HTTP 和 TCP 流量。</p>
|
||
<p>例如,下面这个简单的 <code>Gateway</code> 配置了一个 Load Balancer,以允许访问 host <code>bookinfo.com</code> 的 https 外部流量进入网格中:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: Gateway
|
||
metadata:
|
||
name: bookinfo-gateway
|
||
spec:
|
||
servers:
|
||
- port:
|
||
number: 443
|
||
name: https
|
||
protocol: HTTPS
|
||
hosts:
|
||
- bookinfo.com
|
||
tls:
|
||
mode: SIMPLE
|
||
serverCertificate: /tmp/tls.crt
|
||
privateKey: /tmp/tls.key
|
||
</code></pre>
|
||
<p>要为进入上面的 Gateway 的流量配置相应的路由,必须为同一个 host 定义一个 <code>VirtualService</code>(在下一节中描述),并使用配置中的 <code>gateways</code> 字段绑定到前面定义的 <code>Gateway</code> 上:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: bookinfo
|
||
spec:
|
||
hosts:
|
||
- bookinfo.com
|
||
gateways:
|
||
- bookinfo-gateway # &lt;---- bind to gateway
|
||
http:
|
||
- match:
|
||
- uri:
|
||
prefix: /reviews
|
||
route:
|
||
...
|
||
</code></pre>
|
||
<p><code>Gateway</code> 可以用于建模边缘代理或纯粹的内部代理,如第一张图所示。无论在哪个位置,所有网关都可以用相同的方式进行配置和控制。</p>
|
||
<h3 id="virtualservice"><code>VirtualService</code></h3>
|
||
<p>用一种叫做 &ldquo;Virtual services” 的东西代替路由规则可能看起来有点奇怪,但对于它配置的内容而言,这事实上是一个更好的名称,特别是在重新设计 API 以解决先前模型的可扩展性问题之后。</p>
|
||
<p>实际上,发生的变化是:在之前的模型中,需要用一组相互独立的配置规则来为特定的目的服务设置路由规则,并通过 precedence 字段来控制这些规则的顺序;在新的 API 中,则直接对(虚拟)服务进行配置,该虚拟服务的所有规则以一个有序列表的方式配置在对应的 <a href="/v1.12/zh/docs/reference/config/networking/virtual-service/"><code>VirtualService</code></a> 资源中。</p>
|
||
<p>例如,之前在 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo</a> 应用程序的 <code>reviews</code> 服务中有两个 <code>RouteRule</code> 资源,如下所示:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: config.istio.io/v1alpha2
|
||
kind: RouteRule
|
||
metadata:
|
||
name: reviews-default
|
||
spec:
|
||
destination:
|
||
name: reviews
|
||
precedence: 1
|
||
route:
|
||
- labels:
|
||
version: v1
|
||
---
|
||
apiVersion: config.istio.io/v1alpha2
|
||
kind: RouteRule
|
||
metadata:
|
||
name: reviews-test-v2
|
||
spec:
|
||
destination:
|
||
name: reviews
|
||
precedence: 2
|
||
match:
|
||
request:
|
||
headers:
|
||
cookie:
|
||
regex: &#34;^(.*?;)?(user=jason)(;.*)?$&#34;
|
||
route:
|
||
- labels:
|
||
version: v2
|
||
</code></pre>
|
||
<p>在 <code>v1alpha3</code>,可以在单个 <code>VirtualService</code> 资源中提供相同的配置:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
hosts:
|
||
- reviews
|
||
http:
|
||
- match:
|
||
- headers:
|
||
cookie:
|
||
regex: &#34;^(.*?;)?(user=jason)(;.*)?$&#34;
|
||
route:
|
||
- destination:
|
||
host: reviews
|
||
subset: v2
|
||
- route:
|
||
- destination:
|
||
host: reviews
|
||
subset: v1
|
||
</code></pre>
|
||
<p>正如你所看到的,和 <code>reviews</code> 服务相关的两个规则集中写在了一个地方。这个改变乍一看可能觉得并没有什么特别的优势,然而,如果仔细观察这个新模型,会发现它和之前的 API 之间存在着根本的差异,这使得 <code>v1alpha3</code> 功能更加强大。</p>
|
||
<p>首先,请注意 <code>VirtualService</code> 的目标服务是使用 <code>hosts</code> 字段(实际上是重复字段)指定的,然后再在每个路由的 <code>destination</code> 字段中指定。这是与以前模型的重要区别。</p>
|
||
<p><code>VirtualService</code> 描述了一个或多个用户可寻址目标到网格内实际工作负载之间的映射。在上面的示例中,这两个地址是相同的,但实际上用户可寻址目标可以是任何用于定位服务的,具有可选通配符前缀或 CIDR 前缀的 DNS 名称。
|
||
这对于应用从单体架构到微服务架构的迁移过程特别有用,单体应用被拆分为多个独立的微服务后,采用 <code>VirtualService</code> 可以继续把多个微服务对外暴露为同一个目标地址,而不需要服务消费者进行修改以适应该变化。</p>
|
||
<p>例如,以下规则允许服务消费者访问 Bookinfo 应用程序的 reviews 和 ratings 服务,就好像它们是 <code>http://bookinfo.com/</code>(虚拟)服务的一部分:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: bookinfo
|
||
spec:
|
||
hosts:
|
||
- bookinfo.com
|
||
http:
|
||
- match:
|
||
- uri:
|
||
prefix: /reviews
|
||
route:
|
||
- destination:
|
||
host: reviews
|
||
- match:
|
||
- uri:
|
||
prefix: /ratings
|
||
route:
|
||
- destination:
|
||
host: ratings
|
||
...
|
||
</code></pre>
|
||
<p>实际上在 <code>VirtualService</code> 中 hosts 部分设置只是虚拟的目的地, 因此不一定是已在网格中注册的服务。这允许用户为在网格内没有可路由条目的虚拟主机的流量进行建模。通过将 <code>VirtualService</code> 绑定到同一 Host 的 <code>Gateway</code> 配置(如前一节所述 ),可向网格外部暴露这些 Host。</p>
|
||
<p>除了这个重大的重构之外,<code>VirtualService</code> 还包括其他一些重要的改变:</p>
|
||
<ol>
|
||
<li><p>可以在 <code>VirtualService</code> 配置中表示多个匹配条件,从而减少对冗余的规则设置。</p></li>
|
||
<li><p>每个服务版本都有一个名称(称为服务子集)。属于某个子集的一组 Pod/VM 在 <code>DestinationRule</code> 定义,具体定义参见下节。</p></li>
|
||
<li><p>通过使用带通配符前缀的 DNS 来指定 <code>VirtualService</code> 的 host,可以创建单个规则以作用于所有匹配的服务。例如,在 Kubernetes 中,在 <code>VirtualService</code> 中使用 <code>*.foo.svc.cluster.local</code> 作为 host , 可以对 <code>foo</code> 命名空间中的所有服务应用相同的重写规则。</p></li>
|
||
</ol>
|
||
<h3 id="destinationrule"><code>DestinationRule</code></h3>
|
||
<p><a href="/v1.12/zh/docs/reference/config/networking/destination-rule/"><code>DestinationRule</code></a> 配置将流量转发到服务时应用的策略集。这些策略应由服务提供者撰写,用于描述断路器,负载均衡设置,TLS 设置等。
|
||
除了下述改变外,<code>DestinationRule</code> 与其前身 <code>DestinationPolicy</code> 大致相同。</p>
|
||
<ol>
|
||
<li><code>DestinationRule</code> 的 <code>host</code> 可以包含通配符前缀,以允许单个规则应用于多个服务。</li>
|
||
<li><code>DestinationRule</code> 定义了目的 host 的子集 <code>subsets</code> (例如:命名版本)。这些 subset 用于 <code>VirtualService</code> 的路由规则设置中,可以将流量导向服务的某些特定版本。通过这种方式为版本命名后,可以在不同的 virtual service 中明确地引用这些命名版本的 subset,简化 Istio 代理发出的统计数据,并可以将 subset 编码到 SNI 头中。
|
||
为 reviews 服务配置策略和 subsets 的 <code>DestinationRule</code> 可能如下所示:</li>
|
||
</ol>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: reviews
|
||
spec:
|
||
host: reviews
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: RANDOM
|
||
subsets:
|
||
- name: v1
|
||
labels:
|
||
version: v1
|
||
- name: v2
|
||
labels:
|
||
version: v2
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: ROUND_ROBIN
|
||
- name: v3
|
||
labels:
|
||
version: v3
|
||
</code></pre>
|
||
<p>注意,与 <code>DestinationPolicy</code> 不同的是,可在单个 <code>DestinationRule</code> 中指定多个策略(例如上面实例中的缺省策略和 v2 版本特定的策略)。</p>
|
||
<h3 id="serviceentry"><code>ServiceEntry</code></h3>
|
||
<p><a href="/v1.12/zh/docs/reference/config/networking/service-entry/"><code>ServiceEntry</code></a> 用于将附加条目添加到 Istio 内部维护的服务注册表中。
|
||
它最常用于对访问网格外部依赖的流量进行建模,例如访问 Web 上的 API 或遗留基础设施中的服务。</p>
|
||
<p>所有以前使用 <code>EgressRule</code> 进行配置的内容都可以通过 <code>ServiceEntry</code> 轻松完成。例如,可以使用类似这样的配置来允许从网格内部访问一个简单的外部服务:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: foo-ext
|
||
spec:
|
||
hosts:
|
||
- foo.com
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
</code></pre>
|
||
<p>也就是说,<code>ServiceEntry</code> 比它的前身具有更多的功能。首先,<code>ServiceEntry</code> 不限于外部服务配置,它可以有两种类型:网格内部或网格外部。网格内部条目只是用于向网格显式添加服务,添加的服务与其他内部服务一样。采用网格内部条目,可以把原本未被网格管理的基础设施也纳入到网格中(例如,把虚机中的服务添加到基于 Kubernetes 的服务网格中)。网格外部条目则代表了网格外部的服务。对于这些外部服务来说,双向 TLS 身份验证是禁用的,并且策略是在客户端执行的,而不是在像内部服务请求一样在服务器端执行策略。</p>
|
||
<p>由于 <code>ServiceEntry</code> 配置只是将服务添加到网格内部的服务注册表中,因此它可以像注册表中的任何其他服务一样, 与 <code>VirtualService</code> 和/或 <code>DestinationRule</code> 一起使用。例如,以下 <code>DestinationRule</code> 可用于启动外部服务的 双向 TLS 连接:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: foo-ext
|
||
spec:
|
||
name: foo.com
|
||
trafficPolicy:
|
||
tls:
|
||
mode: MUTUAL
|
||
clientCertificate: /etc/certs/myclientcert.pem
|
||
privateKey: /etc/certs/client_private_key.pem
|
||
caCertificates: /etc/certs/rootcacerts.pem
|
||
</code></pre>
|
||
<p>除了扩展通用性以外,<code>ServiceEntry</code> 还提供了其他一些有关 <code>EgressRule</code> 改进,其中包括:</p>
|
||
<ol>
|
||
<li>一个 <code>ServiceEntry</code> 可以配置多个服务端点,这在之前需要采用多个 <code>EgressRules</code> 来实现。</li>
|
||
<li>现在可以配置服务端点的解析模式(<code>NONE</code>,<code>STATIC</code> 或 <code>DNS</code>)。</li>
|
||
<li>此外,我们正在努力解决另一个难题:目前需要通过纯文本端口访问安全的外部服务(例如 <code>http://google.com:443</code>)。该问题将会在未来几周内得到解决,届时将允许从应用程序直接访问 <code>https://google.com</code>。请继续关注解决此限制的 Istio 补丁版本(0.8.x)。</li>
|
||
</ol>
|
||
<h2 id="creating-and-deleting-v1alpha3-route-rules">创建和删除 v1alpha3 路由规则</h2>
|
||
<p>由于一个特定目的地的所有路由规则现在都存储在单个 <code>VirtualService</code> 资源的一个有序列表中,因此为该目的地添加新的规则不需要再创建新的 <code>RouteRule</code>,而是通过更新该目的地的 <code>VirtualService</code> 资源来实现。</p>
|
||
<p>旧的路由规则:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f my-second-rule-for-destination-abc.yaml
|
||
</code></pre>
|
||
<p><code>v1alpha3</code> 路由规则:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f my-updated-rules-for-destination-abc.yaml
|
||
</code></pre>
|
||
<p>通过使用<code>kubectl apply</code>更新现有资源,也可以删除特定目的地的最后一个路径规则。</p>
|
||
<p>在添加或删除引用服务版本的路由时,需要在该服务相应的 <code>DestinationRule</code> 更新 <code>subsets</code> 。正如你可能猜到的,这也是使用 <code>kubectl apply</code> 完成的。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>Istio <code>v1alpha3</code> 路由 API 具有比其前身更多的功能,但不幸的是新的 API 并不向后兼容,旧的模型升级需要一次手动转换。Istio 0.9 以后将不再支持 <code>RouteRule</code>,<code>DesintationPolicy</code> 和 <code>EgressRule</code> 这些以前的配置资源 。Kubernetes 用户可以继续使用 <code>Ingress</code> 配置边缘负载均衡器来实现基本的路由。但是,高级路由功能(例如,跨两个版本的流量分割)则需要使 <code>用 Gateway</code> ,这是一种功能更强大,Istio 推荐的 <code>Ingress</code> 替代品。</p>
|
||
<h2 id="acknowledgments">致谢</h2>
|
||
<p>感谢以下人员为新版本的路由模型重构和实现工作做出的贡献(按字母顺序)</p>
|
||
<ul>
|
||
<li>Frank Budinsky (IBM)</li>
|
||
<li>Zack Butcher (Google)</li>
|
||
<li>Greg Hanson (IBM)</li>
|
||
<li>Costin Manolache (Google)</li>
|
||
<li>Martin Ostrowski (Google)</li>
|
||
<li>Shriram Rajagopalan (VMware)</li>
|
||
<li>Louis Ryan (Google)</li>
|
||
<li>Isaiah Snell-Feikema (IBM)</li>
|
||
<li>Kuat Yessenov (Google)</li>
|
||
</ul></description><pubDate>Wed, 25 Apr 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/v1alpha3-routing/</link><author>Frank Budinsky (IBM) and Shriram Rajagopalan (VMware)</author><guid isPermaLink="true">/v1.12/zh/blog/2018/v1alpha3-routing/</guid><category>traffic-management</category></item><item><title>使用 AWS NLB 配置 Istio Ingress</title><description>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">本文已于 2019 年 1 月 16 日更新,其中包含一些使用警告。</div>
|
||
</aside>
|
||
</div>
|
||
<p>本文提供了使用 <a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html">AWS 网络负载均衡器</a>配置 Ingress Istio 的说明。</p>
|
||
<p>可以使用网络负载均衡器 (NLB) 来代替传统的负载均衡器。您可以查看不同的 AWS <code>负载均衡器</code> 之间的<a href="https://aws.amazon.com/elasticloadbalancing/details/#Product_comparisons">比较</a>以获取更多的解释。</p>
|
||
<h2 id="prerequisites">先行条件</h2>
|
||
<p>以下说明需要 Kubernetes <strong>1.9.0 或更高版本</strong> 的集群。</p>
|
||
<div>
|
||
<aside class="callout warning">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-warning"/></svg>
|
||
</div>
|
||
<div class="content"><p>在 Kubernetes上 使用 AWS <code>nlb</code> 是一个 Alpha 功能,不建议用于生产环境的集群。</p>
|
||
<p>由于 <a href="https://github.com/kubernetes/kubernetes/issues/69264">Kubernetes Bug #6926</a>中的问题,AWS <code>nlb</code> 的使用不支持在同一区域创建两个或多个运行 Istio 的 Kubernetes 集群。</p>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
<h2 id="iam-policy">IAM Policy</h2>
|
||
<p>您需要在主角色上应用策略,以便能够配置网络负载均衡器。</p>
|
||
<ol>
|
||
<li><p>在 AWS <code>iam</code> 控制台中,点击策略并单击“创建新策略”:</p>
|
||
<p>{&lt; image width=&ldquo;80%&rdquo; link=&ldquo;./createpolicystart.png&rdquo; caption=&ldquo;Create a new policy&rdquo; &gt;}}</p></li>
|
||
<li><p>选择 <code>json</code>:</p>
|
||
<p>{<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:50.63492063492063%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/aws-nlb/createpolicyjson.png" title="Select json">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/aws-nlb/createpolicyjson.png" alt="Select json" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Select json</figcaption>
|
||
</figure></p></li>
|
||
<li><p>拷贝以下内容:</p>
|
||
<pre><code class='language-json' data-expandlinks='true' data-repo='istio' >{
|
||
&#34;Version&#34;: &#34;2012-10-17&#34;,
|
||
&#34;Statement&#34;: [
|
||
{
|
||
&#34;Sid&#34;: &#34;kopsK8sNLBMasterPermsRestrictive&#34;,
|
||
&#34;Effect&#34;: &#34;Allow&#34;,
|
||
&#34;Action&#34;: [
|
||
&#34;ec2:DescribeVpcs&#34;,
|
||
&#34;elasticloadbalancing:AddTags&#34;,
|
||
&#34;elasticloadbalancing:CreateListener&#34;,
|
||
&#34;elasticloadbalancing:CreateTargetGroup&#34;,
|
||
&#34;elasticloadbalancing:DeleteListener&#34;,
|
||
&#34;elasticloadbalancing:DeleteTargetGroup&#34;,
|
||
&#34;elasticloadbalancing:DescribeListeners&#34;,
|
||
&#34;elasticloadbalancing:DescribeLoadBalancerPolicies&#34;,
|
||
&#34;elasticloadbalancing:DescribeTargetGroups&#34;,
|
||
&#34;elasticloadbalancing:DescribeTargetHealth&#34;,
|
||
&#34;elasticloadbalancing:ModifyListener&#34;,
|
||
&#34;elasticloadbalancing:ModifyTargetGroup&#34;,
|
||
&#34;elasticloadbalancing:RegisterTargets&#34;,
|
||
&#34;elasticloadbalancing:SetLoadBalancerPoliciesOfListener&#34;
|
||
],
|
||
&#34;Resource&#34;: [
|
||
&#34;*&#34;
|
||
]
|
||
},
|
||
{
|
||
&#34;Effect&#34;: &#34;Allow&#34;,
|
||
&#34;Action&#34;: [
|
||
&#34;ec2:DescribeVpcs&#34;,
|
||
&#34;ec2:DescribeRegions&#34;
|
||
],
|
||
&#34;Resource&#34;: &#34;*&#34;
|
||
}
|
||
]
|
||
}
|
||
</code></pre></li>
|
||
<li><p>点击审核策略,填写所有字段,接着点击创建策略:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:60.08097165991902%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/aws-nlb/create_policy.png" title="Validate policy">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/aws-nlb/create_policy.png" alt="Validate policy" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Validate policy</figcaption>
|
||
</figure></li>
|
||
<li><p>点击角色,选择您的主角色节点,然后点击附加策略:</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:30.328324986087924%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/aws-nlb/roles_summary.png" title="Attach policy">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/aws-nlb/roles_summary.png" alt="Attach policy" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Attach policy</figcaption>
|
||
</figure></li>
|
||
<li><p>现在,您的策略就已经附加到了主节点。</p></li>
|
||
</ol>
|
||
<h2 id="generate-the-Istio-manifest">重写 Istio Ingress 服务</h2>
|
||
<p>要使用 AWS <code>nlb</code> 负载平衡器,必须在 Istio 安装中添加一个 AWS 特定的注释。 这些说明解释了如何添加注释。</p>
|
||
<p>将其保存为文件 <code>override.yaml</code>:
|
||
您需要使用以下内容来重写 <code>istio-ingress</code> 服务:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >gateways:
|
||
istio-ingressgateway:
|
||
serviceAnnotations:
|
||
service.beta.kubernetes.io/aws-load-balancer-type: &#34;nlb&#34;
|
||
</code></pre>
|
||
<p>使用 Helm 生成清单:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ helm template install/kubernetes/helm/istio --namespace istio -f override.yaml &gt; $HOME/istio.yaml
|
||
</code></pre></description><pubDate>Fri, 20 Apr 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/aws-nlb/</link><author>Julien SENON</author><guid isPermaLink="true">/v1.12/zh/blog/2018/aws-nlb/</guid><category>ingress</category><category>traffic-management</category><category>aws</category></item><item><title>Istio 的软性多租户支持</title><description>
|
||
<p>多租户是一个在各种环境和各种应用中都得到了广泛应用的概念,但是不同环境中,为每租户提供的具体实现和功能性都是有差异的。<a href="https://github.com/kubernetes/community/blob/master/wg-multitenancy/README.md">Kubernetes 多租户工作组</a>致力于在 Kubernetes 中定义多租户用例和功能。然而根据他们的工作进展来看,恶意容器和负载对于其他租户的 Pod 和内核资源的访问无法做到完全控制,因此只有&rdquo;软性多租户”支持是可行的。</p>
|
||
<h2 id="soft-multi-tenancy">软性多租户</h2>
|
||
<p>文中提到的&rdquo;软性多租户”的定义指的是单一 Kubernetes 控制平面和多个 Istio 控制平面以及多个服务网格相结合;每个租户都有自己的一个控制平面和一个服务网格。集群管理员对所有 Istio 控制面都有控制和监控的能力,而租户管理员仅能得到指定 Istio 的控制权。使用 Kubernetes 的命名空间和 RBAC 来完成不同租户的隔离。</p>
|
||
<p>这种模式的一个用例就是企业内部共享的基础设施中,虽然预计不会发生恶意行为,但租户之间的清晰隔离仍然是很有必要的。</p>
|
||
<p>本文最后会对 Istio 未来的多租户模型进行一些描述。</p>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">这里仅就在有限多租户环境中部署 Istio 做一些概要描述。当官方多租户支持实现之后,会在<a href="/v1.12/zh/docs/">文档</a>中具体阐述。</div>
|
||
</aside>
|
||
</div>
|
||
<h2 id="deployment">部署</h2>
|
||
<h3 id="multiple-Istio-control-planes">多个 Istio 控制面</h3>
|
||
<p>要部署多个 Istio 控制面,首先要在 Istio 清单文件中对所有的 <code>namespace</code> 引用进行替换。以 <code>istio.yaml</code> 为例:如果需要两个租户级的 Istio 控制面,那么第一个租户可以使用 <code>istio.yaml</code> 中的缺省命名空间也就是 <code>istio-system</code>;而第二个租户就要生成一个新的 yaml 文件,并在其中使用不同的命名空间。例如使用下面的命令创建一个使用 <code>istio-system1</code> 命名空间的 yaml 文件:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ cat istio.yaml | sed s/istio-system/istio-system1/g &gt; istio-system1.yaml
|
||
</code></pre>
|
||
<p><code>istio.yaml</code> 文件包含了 Istio 控制面的部署细节,包含组成控制面的 Pod(Mixer、Pilot、Ingress 以及 CA)。部署这两个控制面 yaml 文件:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f install/kubernetes/istio.yaml
|
||
$ kubectl apply -f install/kubernetes/istio-system1.yaml
|
||
</code></pre>
|
||
<p>会在两个命名空间生成两个 Istio 控制面</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods --all-namespaces
|
||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||
istio-system istio-ca-ffbb75c6f-98w6x 1/1 Running 0 15d
|
||
istio-system istio-ingress-68d65fc5c6-dnvfl 1/1 Running 0 15d
|
||
istio-system istio-mixer-5b9f8dffb5-8875r 3/3 Running 0 15d
|
||
istio-system istio-pilot-678fc976c8-b8tv6 2/2 Running 0 15d
|
||
istio-system1 istio-ca-5f496fdbcd-lqhlk 1/1 Running 0 15d
|
||
istio-system1 istio-ingress-68d65fc5c6-2vldg 1/1 Running 0 15d
|
||
istio-system1 istio-mixer-7d4f7b9968-66z44 3/3 Running 0 15d
|
||
istio-system1 istio-pilot-5bb6b7669c-779vb 2/2 Running 0 15d
|
||
</code></pre>
|
||
<p>如果需要 Istio <a href="/v1.12/zh/docs/setup/additional-setup/sidecar-injection/">Sidecar 注入组件</a>以及<a href="/v1.12/zh/docs/tasks/observability/">遥测组件</a>,也需要根据租户的命名空间定义,修改所需的 yaml 文件。</p>
|
||
<p>需要由集群管理员、而不是租户自己的管理员来加载这两组 yaml 文件。另外,要把租户管理员的操作权限限制在各自的命名空间内,还需要额外的 RBAC 配置。</p>
|
||
<h3 id="split-common-and-namespace-specific-resources">区分通用资源和命名空间资源</h3>
|
||
<p>Istio 仓库中的清单文件中会创建两种资源,一种是能够被所有 Istio 控制面访问的通用资源,另一种是每个控制平面一份的专属资源。上面所说的在 yaml 文件中替换 <code>istio-system</code> 命名空间的方法自然是很简单的,更好的一种方法就是把 yaml 文件拆分为两块,一块是所有租户共享的通用部分;另一块就是租户自有的部分。根据 <a href="https://kubernetes.io/docs/concepts/api-extension/custom-resources/#customresourcedefinitions">CRD 资源定义(Custom Resource Definitions)</a> 中的说法,角色和角色绑定资源需要从 Istio 文件中进行剥离。另外,清单文件中提供的角色和角色绑定的定义可能不适合多租户环境,还需要进一步的细化和定制。</p>
|
||
<h3 id="Kubernetes-rbac-for-Istio-control-plane-resources">Istio 控制面的 Kubernetes RBAC 设置</h3>
|
||
<p>租户管理员应该被限制在单独的 Istio 命名空间中,要完成这个限制,集群管理员需要创建一个清单,其中至少要包含一个 <code>Role</code> 和 <code>RoleBinding</code> 的定义,类似下面的文件所示。例子中定义了一个租户管理员,命名为 *sales-admin*,他被限制在命名空间 <code>istio-system1</code> 之中。完整的清单中可能要在 <code>Role</code> 中包含更多的 <code>apiGroups</code> 条目,来定义租户管理员的资源访问能力。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >kind: Role
|
||
apiVersion: rbac.authorization.k8s.io/v1
|
||
metadata:
|
||
namespace: istio-system1
|
||
name: ns-access-for-sales-admin-istio-system1
|
||
rules:
|
||
- apiGroups: [&#34;&#34;] # &#34;&#34; 代表核心 API 资源组
|
||
resources: [&#34;*&#34;]
|
||
verbs: [&#34;*&#34;]
|
||
---
|
||
kind: RoleBinding
|
||
apiVersion: rbac.authorization.k8s.io/v1
|
||
metadata:
|
||
name: access-all-istio-system1
|
||
namespace: istio-system1
|
||
subjects:
|
||
- kind: User
|
||
name: sales-admin
|
||
apiGroup: rbac.authorization.k8s.io
|
||
roleRef:
|
||
kind: Role
|
||
name: ns-access-for-sales-admin-istio-system1
|
||
apiGroup: rbac.authorization.k8s.io
|
||
</code></pre>
|
||
<h3 id="watching-specific-namespaces-for-service-discovery">关注特定命名空间进行服务发现</h3>
|
||
<p>除了创建 RBAC 规则来限制租户管理员只能访问指定 Istio 控制平面之外,Istio 清单还需要为 Istio Pilot 指定一个用于应用程序的命名空间,以便生成 xDS 缓存。Pilot 组件提供了命令行参数 <code>--appNamespace, ns-1</code> 可以完成这一任务。<em>ns-1</em> 就是租户用来部署自己应用的命名空间。<code>istio-system1.yaml</code> 中包含的相关代码大致如下:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: istio-pilot
|
||
namespace: istio-system1
|
||
annotations:
|
||
sidecar.istio.io/inject: &#34;false&#34;
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
istio: pilot
|
||
spec:
|
||
serviceAccountName: istio-pilot-service-account
|
||
containers:
|
||
- name: discovery
|
||
image: docker.io/&lt;user ID&gt;/pilot:&lt;tag&gt;
|
||
imagePullPolicy: IfNotPresent
|
||
args: [&#34;discovery&#34;, &#34;-v&#34;, &#34;2&#34;, &#34;--admission-service&#34;, &#34;istio-pilot&#34;, &#34;--appNamespace&#34;, &#34;ns-1&#34;]
|
||
ports:
|
||
- containerPort: 8080
|
||
- containerPort: 443
|
||
</code></pre>
|
||
<h3 id="deploying-the-tenant-application-in-a-namespace">在特定命名空间中部署租户应用</h3>
|
||
<p>现在集群管理员已经给租户创建了命名空间(<code>istio-system1</code>),并且对 Istio Pilot 的服务发现进行了配置,要求它关注应用的命名空间(<code>ns-1</code>),创建应用的 yaml 文件,将其部署到租户的专属命名空间中:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Namespace
|
||
metadata:
|
||
name: ns-1
|
||
</code></pre>
|
||
<p>然后把每个资源的命名空间都指定到 <code>ns-1</code>,例如:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: details
|
||
labels:
|
||
app: details
|
||
namespace: ns-1
|
||
</code></pre>
|
||
<p>虽然没有展示出来,但是应用的命名空间也应该有 RBAC 设置,用来对特定资源进行访问控制。集群管理员和租户管理员都有权完成这种 RBAC 限制。</p>
|
||
<h3 id="using-in-a-multi-tenant-environment">在多租户环境中使用 <code>istioctl</code></h3>
|
||
<p>定义<a href="https://archive.istio.io/v0.7/docs/reference/config/istio.routing.v1alpha1/#RouteRule">路由规则</a>或者<a href="https://archive.istio.io/v0.7/docs/reference/config/istio.routing.v1alpha1/#DestinationPolicy">目标策略</a>时,要确认 <code>istioctl</code> 命令是针对专有的 Istio 控制面所在的命名空间运行的。另外规则自身的定义也要限制在租户的命名空间里,这样才能保证规则在租户自己的网格中生效。<em>-i</em> 选项用来在 Istio 控制面所属的命名空间中创建(get 和 describe 也一样)规则。<em>-n</em> 参数会限制规则的所在范围是租户的网格,取值就是租户应用所在的命名空间。如果 yaml 文件中的资源已经指定了范围,<em>-n</em> 参数会被跳过。</p>
|
||
<p>例如下面的命令会创建到 <code>istio-system1</code> 命名空间的路由规则:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl –i istio-system1 apply -n ns-1 -f route_rule_v2.yaml
|
||
</code></pre>
|
||
<p>用下面的命令可以查看:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl -i istio-system1 -n ns-1 get routerule
|
||
NAME KIND NAMESPACE
|
||
details-Default RouteRule.v1alpha2.config.istio.io ns-1
|
||
productpage-default RouteRule.v1alpha2.config.istio.io ns-1
|
||
ratings-default RouteRule.v1alpha2.config.istio.io ns-1
|
||
reviews-default RouteRule.v1alpha2.config.istio.io ns-1
|
||
</code></pre>
|
||
<p><a href="/v1.12/zh/blog/2018/soft-multitenancy/#multiple-Istio-control-planes">Multiple Istio control planes</a> 中讲述了更多多租户环境下 <code>命名空间</code> 的相关问题。</p>
|
||
<h3 id="test-results">测试结果</h3>
|
||
<p>根据前文的介绍,一个集群管理员能够创建一个受限于 RBAC 和命名空间的环境,租户管理员能在其中进行部署。</p>
|
||
<p>完成部署后,租户管理员就可以访问指定的 Istio 控制平面的 Pod 了。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods -n istio-system
|
||
NAME READY STATUS RESTARTS AGE
|
||
grafana-78d649479f-8pqk9 1/1 Running 0 1d
|
||
istio-ca-ffbb75c6f-98w6x 1/1 Running 0 1d
|
||
istio-ingress-68d65fc5c6-dnvfl 1/1 Running 0 1d
|
||
istio-mixer-5b9f8dffb5-8875r 3/3 Running 0 1d
|
||
istio-pilot-678fc976c8-b8tv6 2/2 Running 0 1d
|
||
istio-sidecar-injector-7587bd559d-5tgk6 1/1 Running 0 1d
|
||
prometheus-cf8456855-hdcq7 1/1 Running 0 1d
|
||
</code></pre>
|
||
<p>然而无法访问全部命名空间的 Pod:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods --all-namespaces
|
||
Error from server (Forbidden): pods is forbidden: User &#34;dev-admin&#34; cannot list pods at the cluster scope
|
||
</code></pre>
|
||
<p>访问其他租户的命名空间也是不可以的:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods -n istio-system1
|
||
Error from server (Forbidden): pods is forbidden: User &#34;dev-admin&#34; cannot list pods in the namespace &#34;istio-system1&#34;
|
||
</code></pre>
|
||
<p>租户管理员能够在租户指定的应用命名空间中进行应用部署。例如可以修改一下 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo</a> 的 yaml 然后部署到租户的命名空间 <em>ns-0</em> 中,然后租户管理员就可以在这一命名空间中列出 Pod 了:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods -n ns-0
|
||
NAME READY STATUS RESTARTS AGE
|
||
details-v1-64b86cd49-b7rkr 2/2 Running 0 1d
|
||
productpage-v1-84f77f8747-rf2mt 2/2 Running 0 1d
|
||
ratings-v1-5f46655b57-5b4c5 2/2 Running 0 1d
|
||
reviews-v1-ff6bdb95b-pm5lb 2/2 Running 0 1d
|
||
reviews-v2-5799558d68-b989t 2/2 Running 0 1d
|
||
reviews-v3-58ff7d665b-lw5j9 2/2 Running 0 1d
|
||
</code></pre>
|
||
<p>同样也是不能访问其他租户的应用程序命名空间:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods -n ns-1
|
||
Error from server (Forbidden): pods is forbidden: User &#34;dev-admin&#34; cannot list pods in the namespace &#34;ns-1&#34;
|
||
</code></pre>
|
||
<p>如果部署了<a href="/v1.12/zh/docs/tasks/observability/">遥测组件</a>, 例如
|
||
<a href="/v1.12/zh/docs/tasks/observability/metrics/querying-metrics/">Prometheus</a>(限制在 Istio 的 <code>namespace</code>),其中获得的统计结果展示的也只是租户应用命名空间的私有数据。</p>
|
||
<h2 id="conclusion">结语</h2>
|
||
<p>上面的一些尝试表明 Istio 有足够的能力和安全性,符合少量多租户的用例需求。另外也很明显的,Istio 和 Kubernetes <strong>无法</strong>提供足够的能力和安全性来满足其他的用例,尤其是在租户之间要求完全的安全性和隔离的要求的用例。只有等容器技术(例如 Kubernetes )能够提供更好的安全模型以及隔离能力,我们才能进一步的增强这方面的支持,Istio 的支持并不是很重要。</p>
|
||
<h2 id="issues">问题</h2>
|
||
<ul>
|
||
<li>一个租户(例如,<code>istio-system</code> 命名空间)的 CA(Certificate Authority) 和 Mixer 的 Pod 中产生的 Log 包含了另一个租户(例如,<code>istio-system1</code> 命名空间)的控制面的 <code>info</code> 信息。</li>
|
||
</ul>
|
||
<h2 id="challenges-with-other-multi-tenancy-models">其他多租户模型的挑战</h2>
|
||
<p>还有其他值得考虑的多租户部署模型:</p>
|
||
<ol>
|
||
<li><p>一个网格中运行多个应用程序,每个租户一个应用。集群管理员能控制和监控网格范围内的所有应用,租户管理员只能控制一个特定应用。</p></li>
|
||
<li><p>单独的 Istio 控制平面控制多个网格,每个租户一个网格。集群管理员控制和监控整个 Istio 控制面以及所有网格,租户管理员只能控制特定的网格。</p></li>
|
||
<li><p>一个云环境(集群控制),多个 Kubernetes 控制面(租户控制)</p></li>
|
||
</ol>
|
||
<p>这些选项,有的需要改写代码才能支持,有的无法满足用户要求。</p>
|
||
<p>目前的 Istio 能力不适合第一种方案,这是因为其 RBAC 能力无法覆盖这种租户操作。另外在当前的网格模型中,Istio 的配置信息需要传递给 Envoy 代理服务器,多个租户在同一网格内共存的做法非常不安全。</p>
|
||
<p>再看看第二个方式,目前的 Istio 假设每个 Istio 控制面对应一个网格。要支持这种模型需要大量改写。这种情况需要更好的对资源的范围限制进行调整,同时根据命名空间进行安全限制,此外还需要调整 Istio 的 RBAC 模型。这种模式未来可能会支持,但目前来说是不可能的。</p>
|
||
<p>第三个方式对多数案例都是不合适的,毕竟多数集群管理员倾向于将同一个 Kubernetes 控制面作为 <a href="https://en.wikipedia.org/wiki/Platform_as_a_service">PaaS</a> 提供给他们的租户。</p>
|
||
<h2 id="future-work">未来</h2>
|
||
<p>很明显,单一 Istio 控制面控制多个网格可能是下一个功能。还有可能就是在同一个网格中支持多个租户,并提供某种程度的隔离和安全保障。要完成这样的能力,就需要像 Kubernetes 中对命名空间的的操作那样,在一个单独的控制平面中进行分区,社区中发出了<a href="https://docs.google.com/document/d/14Hb07gSrfVt5KX9qNi7FzzGwB_6WBpAnDpPG6QEEd9Q">这篇文档</a>来定义其他的用例,以及要支持这些用例所需要的 Istio 功能。</p>
|
||
<h2 id="references">参考</h2>
|
||
<ul>
|
||
<li>视频:<a href="https://www.youtube.com/watch?v=ahwCkJGItkU">用 RBAC 和命名空间支持的多租户功能及安全模型</a>, <a href="https://schd.ws/hosted_files/kccncna17/21/Multi-tenancy%20Support%20%26%20Security%20Modeling%20with%20RBAC%20and%20Namespaces.pdf">幻灯片</a>.</li>
|
||
<li><code>Kubecon</code> 讨论,关于对“协同软性多租户”的支持 <a href="https://www.youtube.com/watch?v=YRR-kZub0cA">Building for Trust: How to Secure Your Kubernetes</a>.</li>
|
||
<li>Kubernetes <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/">RBAC 文档</a>以及<a href="https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/">命名空间文档</a>.</li>
|
||
<li><code>Kubecon</code> 幻灯片 <a href="https://schd.ws/hosted_files/kccncna17/a9/kubecon-multitenancy.pdf">Multi-tenancy Deep Dive</a>.</li>
|
||
<li>Google 文档 <a href="https://docs.google.com/document/d/15w1_fesSUZHv-vwjiYa9vN_uyc--PySRoLKTuDhimjc">Multi-tenancy models for Kubernetes</a>. (需要授权)</li>
|
||
<li>Cloud Foundry 提出的文档:<a href="https://docs.google.com/document/d/14Hb07gSrfVt5KX9qNi7FzzGwB_6WBpAnDpPG6QEEd9Q">Multi-cloud and Multi-tenancy</a></li>
|
||
<li><a href="https://docs.google.com/document/d/12F183NIRAwj2hprx-a-51ByLeNqbJxK16X06vwH5OWE">Istio Auto Multi-Tenancy 101</a></li>
|
||
</ul></description><pubDate>Thu, 19 Apr 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/soft-multitenancy/</link><author>John Joyce 和 Rich Curran</author><guid isPermaLink="true">/v1.12/zh/blog/2018/soft-multitenancy/</guid><category>tenancy</category></item><item><title>用于在生产环境进行测试的 Istio 流量镜像功能</title><description><p>在非生产/测试环境中,尝试穷举一个服务所有可能的测试用例组合是个令人望而生畏的任务,在某些情况下,您会发现编写这些用例的所有工作都与实际生产用例不匹配,理想情况下,我们可以使用实时生产用例和流量来帮助说明我们可能在更人为的测试环境中错过的所测试服务的所有功能区域。</p>
|
||
<p>Istio 可以在这里提供帮助。随着 <a href="/v1.12/zh/news/releases/0.x/announcing-0.5">Istio 0.5</a> 的发布,Istio 可以镜像流量来帮助测试您的服务,您可以编写类似于以下内容的路由规则来启用流量镜像:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: config.istio.io/v1alpha2
|
||
kind: RouteRule
|
||
metadata:
|
||
name: mirror-traffic-to-httbin-v2
|
||
spec:
|
||
destination:
|
||
name: httpbin
|
||
precedence: 11
|
||
route:
|
||
- labels:
|
||
version: v1
|
||
weight: 100
|
||
- labels:
|
||
version: v2
|
||
weight: 0
|
||
mirror:
|
||
name: httpbin
|
||
labels:
|
||
version: v2
|
||
</code></pre>
|
||
<p>这里有几点需要注意:</p>
|
||
<ul>
|
||
<li>当流量镜像到不同的服务时,会发生在请求的关键路径之外</li>
|
||
<li>忽略对任何镜像流量的响应;流量被视为“即发即忘”</li>
|
||
<li>必须创建一个权重为 0 的路由,让 Istio 据此通知 Envoy 创建对应的集群定义;<a href="https://github.com/istio/istio/issues/3270">这应该在未来的版本中解决</a>。</li>
|
||
</ul>
|
||
<p>访问<a href="/v1.12/zh/docs/tasks/traffic-management/mirroring/">镜像任务</a>了解有关镜像的更多信息,并查看更多信息<a href="https://dzone.com/articles/traffic-shadowing-with-istio-reducing-the-risk-of">在我的博客上综合处理这种情况</a>。</p></description><pubDate>Thu, 08 Feb 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/traffic-mirroring/</link><author>Christian Posta</author><guid isPermaLink="true">/v1.12/zh/blog/2018/traffic-mirroring/</guid><category>traffic-management</category><category>mirroring</category></item><item><title>使用外部 TCP 服务</title><description>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">这篇博客在 2018 年 7 月 23 日有修改,修改的内容使用了新的 <a href="/v1.12/zh/blog/2018/v1alpha3-routing/">v1alpha3 流量管理 API</a>。如果你想使用旧版本 API,请参考<a href="https://archive.istio.io/v0.7/blog/2018/egress-tcp.html">这个文档</a>。</div>
|
||
</aside>
|
||
</div>
|
||
<p>在我之前的博客文章<a href="/v1.12/zh/blog/2018/egress-https/">使用外部 Web 服务</a>中,我描述了如何通过 HTTPS 在网格 Istio 应用程序中使用外部服务,在这篇文章中,我演示了通过 TCP 使用外部服务。你会用到 <a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>,这是将书籍评级数据保存在 MySQL 数据库中的版本。你会在集群外部署此数据库并配置 <em>ratings</em> 服务以使用它,你还会定义<a href="/v1.12/zh/docs/reference/config/networking/service-entry/">服务 Entry</a> 以允许网格内应用程序访问外部数据库。</p>
|
||
<h2 id="Bookinfo-sample-application-with-external-ratings-database">Bookinfo 示例应用程序与外部评级数据库</h2>
|
||
<p>首先,在 Kubernetes 集群之外设置了一个 MySQL 数据库实例来保存 Bookinfo 评级数据,然后修改 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo 示例应用程序</a>以使用这个数据库。</p>
|
||
<h3 id="setting-up-the-database-for-ratings-data">为评级数据设置数据库</h3>
|
||
<p>为此,你设置了 <a href="https://www.mysql.com">MySQL</a> 的实例,你可以使用任何 MySQL 实例; 我使用 <a href="https://www.ibm.com/cloud/compose/mysql">Compose for MySQL</a>,我使用 <code>mysqlsh</code>(<a href="https://dev.mysql.com/doc/mysql-shell/en/">MySQL Shell</a>)作为 MySQL 客户端来提供评级数据。</p>
|
||
<ol>
|
||
<li><p>设置 <code>MYSQL_DB_HOST</code> 和 <code>MYSQL_DB_PORT</code> 环境变量。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export MYSQL_DB_HOST=&lt;你的 MySQL host&gt;
|
||
$ export MYSQL_DB_PORT=&lt;你的 MySQL port&gt;
|
||
</code></pre>
|
||
<p>如果你使用的是本地数据库,使用的是默认 MYSQL port,那 <code>host</code> 和 <code>port</code> 分别是 <code>localhost</code> 和 <code>3306</code>。</p></li>
|
||
<li><p>初始化数据库时,如果出现提示,执行下面的命令输入密码。这个命令通过 <code>admin</code> 数据库用户凭证来执行。这个 <code>admin</code> 用户是通过 <a href="https://www.ibm.com/cloud/compose/mysql">Compose for Mysql</a> 创建数据库时默认存在的。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl -s https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/src/mysql/mysqldb-init.sql | mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT
|
||
</code></pre>
|
||
<p><em><strong>或者</strong></em></p>
|
||
<p>使用 <code>mysql</code> 客户端和本地 MySQL 数据库时,运行:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ curl -s https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/src/mysql/mysqldb-init.sql | mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT
|
||
</code></pre></li>
|
||
<li><p>创建一个名为 <code>bookinfo</code> 的用户,并在 <code>test.ratings</code> 表上授予它 <em>SELECT</em> 权限:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;CREATE USER &#39;bookinfo&#39; IDENTIFIED BY &#39;&lt;password you choose&gt;&#39;; GRANT SELECT ON test.ratings to &#39;bookinfo&#39;;&#34;
|
||
</code></pre>
|
||
<p><em><strong>或者</strong></em></p>
|
||
<p>对于 <code>mysql</code> 和本地数据库,命令是:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;CREATE USER &#39;bookinfo&#39; IDENTIFIED BY &#39;&lt;password you choose&gt;&#39;; GRANT SELECT ON test.ratings to &#39;bookinfo&#39;;&#34;
|
||
</code></pre>
|
||
<p>在这里,你会应用<a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">最小特权原则</a>,这意味着不在 Bookinfo 应用程序中使用 <code>admin</code> 用户。相反,你为应用程序 Bookinfo 创建了一个最小权限的特殊用户 <code>bookinfo</code>,在这种情况下,<code>bookinfo</code> 用户只对单个表具有 <code>SELECT</code> 特权。</p>
|
||
<p>在运行命令创建用户之后,你可能会想通过检查最后一个命令的编号并运行 <code>history -d &lt;创建用户的命令编号&gt;</code> 来清理我的 bash 历史记录。你可能不希望新用户的密码存储在 bash 历史记录中,如果你使用了 <code>mysql</code> 命令行工具,记得要删除 <code>~/.mysql_history</code> 文件中的最后一个命令。在 <a href="https://dev.mysql.com/doc/refman/5.5/en/create-user.html">MySQL 文档</a>中阅读有关新创建用户的密码保护的更多信息。</p></li>
|
||
<li><p>检查创建的评级,看看一切都按预期工作:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysqlsh --sql --ssl-mode=REQUIRED -u bookinfo -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;select * from test.ratings;&#34;
|
||
Enter password:
|
||
+----------+--------+
|
||
| ReviewID | Rating |
|
||
+----------+--------+
|
||
| 1 | 5 |
|
||
| 2 | 4 |
|
||
+----------+--------+
|
||
</code></pre>
|
||
<p><em><strong>或者</strong></em></p>
|
||
<p>对于 <code>mysql</code> 和本地数据库:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysql -u bookinfo -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;select * from test.ratings;&#34;
|
||
Enter password:
|
||
+----------+--------+
|
||
| ReviewID | Rating |
|
||
+----------+--------+
|
||
| 1 | 5 |
|
||
| 2 | 4 |
|
||
+----------+--------+
|
||
</code></pre></li>
|
||
<li><p>暂时将评级设置为<code>1</code>,以便在 Bookinfo <em>ratings</em> 服务使用我们的数据库时提供可视线索:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;update test.ratings set rating=1; select * from test.ratings;&#34;
|
||
Enter password:
|
||
Rows matched: 2 Changed: 2 Warnings: 0
|
||
+----------+--------+
|
||
| ReviewID | Rating |
|
||
+----------+--------+
|
||
| 1 | 1 |
|
||
| 2 | 1 |
|
||
+----------+--------+
|
||
</code></pre>
|
||
<p><em><strong>或</strong></em></p>
|
||
<p>对于<code>mysql</code>和本地数据库:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;update test.ratings set rating=1; select * from test.ratings;&#34;
|
||
Enter password:
|
||
+----------+--------+
|
||
| ReviewID | Rating |
|
||
+----------+--------+
|
||
| 1 | 1 |
|
||
| 2 | 1 |
|
||
+----------+--------+
|
||
</code></pre>
|
||
<p>在最后一个命令中使用了 <code>admin</code> 用户(和 <code>root</code> 用于本地数据库),因为 <code>bookinfo</code> 用户在 <code>test.ratings</code> 表上没有 <code>UPDATE</code> 权限。</p></li>
|
||
</ol>
|
||
<p>现在你已经可以去部署使用外部数据库的 Bookinfo 应用程序版本了。</p>
|
||
<h3 id="initial-setting-of-Bookinfo-application">Bookinfo 应用程序的初始设置</h3>
|
||
<p>为了演示使用外部数据库的场景,你首先使用安装了 <a href="/v1.12/zh/docs/setup/getting-started/">Istio</a> 的 Kubernetes 集群,然后部署 <a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>、<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">应用默认的 destination rule</a> 并<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-control/#change-to-the-blocking-by-default-policy">将 Istio 默认策略修改为禁止 Egress</a>。</p>
|
||
<p>此应用程序使用 <code>ratings</code> 微服务来获取书籍评级,评分在 1 到 5 之间。评级显示为每个评论的星号,有几个版本的 <code>ratings</code> 微服务。有些人使用 <a href="https://www.mongodb.com">MongoDB</a>,有些使用 <a href="https://www.mysql.com">MySQL</a> 作为他们的数据库。</p>
|
||
<p>这篇博客例子里的命令是以 Istio 0.8 以上版本为基础的,无论启用或不启用<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS</a>。</p>
|
||
<p>提醒一下,这是 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo 示例应用程序</a>中应用程序的原始整体架构图。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.086918235567985%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/docs/examples/bookinfo/withistio.svg" title="原始的 Bookinfo 应用程序">
|
||
<img class="element-to-stretch" src="/v1.12/zh/docs/examples/bookinfo/withistio.svg" alt="原始的 Bookinfo 应用程序" />
|
||
</a>
|
||
</div>
|
||
<figcaption>原始的 Bookinfo 应用程序</figcaption>
|
||
</figure>
|
||
<h3 id="use-the-database-for-ratings-data-in-Bookinfo-application">将数据库用于 Bookinfo 应用程序中的评级数据</h3>
|
||
<ol>
|
||
<li><p>修改使用 MySQL 数据库的 <em>ratings</em> 服务版本的 <code>deployment spec</code>,以使用你的数据库实例。该 <code>spec</code> 位于 Istio 发行档案的 <a href="https://github.com/istio/istio/blob/release-1.12/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml"><code>samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml</code></a> 中。编辑以下几行:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >- name: MYSQL_DB_HOST
|
||
value: mysqldb
|
||
- name: MYSQL_DB_PORT
|
||
value: &#34;3306&#34;
|
||
- name: MYSQL_DB_USER
|
||
value: root
|
||
- name: MYSQL_DB_PASSWORD
|
||
value: password
|
||
</code></pre>
|
||
<p>替换上面代码段中的值,指定数据库主机,端口,用户和密码,请注意,在 Kubernetes 中使用容器环境变量中密码的正确方法是 <a href="https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables">使用 secret</a>,仅对于此示例任务,你可能会在 deployment spec 中直接配置明文的密码,<strong>切记!不要在真实环境中这样做</strong>!我想你们应该也知道,<code>&quot;password&quot;</code> 这个值也不应该用作密码。</p></li>
|
||
<li><p>应用修改后的 <code>spec</code> 来部署使用外部数据库的 <em>ratings</em> 服务,<em>v2-mysql</em> 的版本。</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml@
|
||
deployment &#34;ratings-v2-mysql&#34; created
|
||
</code></pre></div></li>
|
||
<li><p>将发往 <em>reviews</em> 服务的所有流量路由到 <em>v3</em> 版本,这样做是为了确保 <em>reviews</em> 服务始终调用 <em>ratings</em> 服务,此外,将发往 <em>ratings</em> 服务的所有流量路由到使用外部数据库的 _ratings v2-mysql_。</p>
|
||
<p>通过添加两个<a href="/v1.12/zh/docs/reference/config/networking/virtual-service/">虚拟服务(virtual service)</a>,可以为上述两种服务指定路由。这些虚拟服务在 Istio 发行档案的 <code>samples/bookinfo/networking/virtual-service-ratings-mysql.yaml</code> 中指定。
|
||
<strong><em>注意:</em></strong> 确保你在完成了<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">添加默认目标路由</a>才执行下面的命令。</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-ratings-mysql.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/networking/virtual-service-ratings-mysql.yaml@
|
||
</code></pre></div></li>
|
||
</ol>
|
||
<p>更新的架构如下所示,请注意,网格内的蓝色箭头标记根据我们添加的虚拟服务配置的流量,根据虚拟服务的定义,流量将发送到 <em>reviews v3</em> 和 <em>ratings v2-mysql</em> 。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.314858206480224%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-tcp/bookinfo-ratings-v2-mysql-external.svg" title="Bookinfo 应用程序,其评级为 v2-mysql,外部为 MySQL 数据库">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-tcp/bookinfo-ratings-v2-mysql-external.svg" alt="Bookinfo 应用程序,其评级为 v2-mysql,外部为 MySQL 数据库" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Bookinfo 应用程序,其评级为 v2-mysql,外部为 MySQL 数据库</figcaption>
|
||
</figure>
|
||
<p>请注意,MySQL 数据库位于 Istio 服务网格之外,或者更准确地说是在 Kubernetes 集群之外,服务网格的边界由虚线标记。</p>
|
||
<h3 id="access-the-webpage">访问网页</h3>
|
||
<p>在<a href="/v1.12/zh/docs/examples/bookinfo/#determine-the-ingress-IP-and-port">确定入口 IP 和端口</a>之后,访问应用程序的网页。</p>
|
||
<p>你会发现问题,在每次审核下方都会显示消息 <em>&ldquo;Ratings service is currently unavailable”</em> 而不是评级星标。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:36.18705035971223%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-tcp/errorFetchingBookRating.png" title="Ratings 服务的错误信息">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-tcp/errorFetchingBookRating.png" alt="Ratings 服务的错误信息" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Ratings 服务的错误信息</figcaption>
|
||
</figure>
|
||
<p>与<a href="/v1.12/zh/blog/2018/egress-https/">使用外部 Web 服务</a>一样,你会体验到<strong>优雅的服务降级</strong>,这很好,虽然 <em>ratings</em> 服务中有错误,但是应用程序并没有因此而崩溃,应用程序的网页正确显示了书籍信息,详细信息和评论,只是没有评级星。</p>
|
||
<p>你遇到的问题与<a href="/v1.12/zh/blog/2018/egress-https/">使用外部 Web 服务</a>中的问题相同,即 Kubernetes 集群外的所有流量(TCP 和 HTTP)都被 sidecar 代理默认阻止,要为 TCP 启用此类流量,必须定义 TCP 的网格外部服务入口。</p>
|
||
<h3 id="mesh-external-service-entry-for-an-external-MySQL-instance">外部 MySQL 实例的网格外部服务入口</h3>
|
||
<p>&ldquo;TCP 网格外部服务入口&rdquo;功能可以解决上面的问题。</p>
|
||
<ol>
|
||
<li><p>获取你的 MySQL 数据库事例的 IP 地址,作为参考,你可以通过 <a href="https://linux.die.net/man/1/host">host</a> 命令实现:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ export MYSQL_DB_IP=$(host $MYSQL_DB_HOST | grep &#34; has address &#34; | cut -d&#34; &#34; -f4)
|
||
</code></pre>
|
||
<p>如果是本地数据库,设置 <code>MYSQL_DB_IP</code> 环境变量为你的本机 IP,保证这个环境变量能被集群访问到。</p></li>
|
||
<li><p>定义一个网格外部服务入口:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: mysql-external
|
||
spec:
|
||
hosts:
|
||
- $MYSQL_DB_HOST
|
||
addresses:
|
||
- $MYSQL_DB_IP/32
|
||
ports:
|
||
- name: tcp
|
||
number: $MYSQL_DB_PORT
|
||
protocol: tcp
|
||
location: MESH_EXTERNAL
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>检查你刚刚新增的服务入口,确保它的值是正确的</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get serviceentry mysql-external -o yaml
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
...
|
||
</code></pre></li>
|
||
</ol>
|
||
<p>请注意,对于 TCP 服务入口,将 <code>tcp</code> 指定为入口 &ldquo;port&rdquo; 的 &ldquo;protocol&rdquo; 的值,另请注意,要在 &ldquo;addresses&rdquo; 列表里面指定外部服务的 IP 地址,作为一个 <code>32</code> 为后缀的 <a href="https://tools.ietf.org/html/rfc2317">CIDR</a> 块。</p>
|
||
<p><a href="#service-entries-for-tcp-traffic">下面</a>我将详细讨论 TCP 服务入口。现在先来验证我们添加的出口规则是否解决了问题。访问网页看看评星是否回来了。</p>
|
||
<p>有效!访问应用程序的网页会显示评级而不会出现错误:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:36.69064748201439%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-tcp/externalMySQLRatings.png" title="Book Ratings 显示正常">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-tcp/externalMySQLRatings.png" alt="Book Ratings 显示正常" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Book Ratings 显示正常</figcaption>
|
||
</figure>
|
||
<p>请注意,正如预期的那样,你会看到两个显示评论的一星评级。将评级更改为一颗星,为我们提供了一个视觉线索,确实使用了我们的外部数据库。</p>
|
||
<p>与 HTTP/HTTPS 的服务入口一样,你可以动态地使用 <code>kubectl</code> 删除和创建 TCP 的服务入口。</p>
|
||
<h2 id="motivation-for-egress-TCP-traffic-control">出口 TCP 流量控制的动机</h2>
|
||
<p>一些网内 Istio 应用程序必须访问外部服务,例如遗留系统,在许多情况下,不通过 HTTP 或 HTTPS 协议执行访问,使用其他 TCP 协议,例如 <a href="https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/">MongoDB Wire 协议</a>和 <a href="https://dev.mysql.com/doc/internals/en/client-server-protocol.html">MySQL 客户端/服务器协议</a>等特定于数据库的协议,与外部数据库通信。</p>
|
||
<p>接下来我会再说说 TCP 流量的服务入口。</p>
|
||
<h2 id="service-entries-for-tcp-traffic">TCP 流量的服务入口</h2>
|
||
<p>启用到特定端口的 TCP 流量的服务入口必须指定 <code>TCP</code> 作为端口的协议,此外,对于 <a href="https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/">MongoDB Wire 协议</a>,协议可以指定为 <code>MONGO</code>,而不是 <code>TCP</code>。</p>
|
||
<p>对于服务入口配置的 <code>addresses</code> 字段,必须使用 <a href="https://tools.ietf.org/html/rfc2317">CIDR</a> 表示法中的 IP 块。注意在 TCP 服务入口配置中,<code>host</code> 字段会被忽略。</p>
|
||
<p>要通过其主机名启用到外部服务的 TCP 流量,必须指定主机名的所有 IP,每个 IP 必须由 CIDR 块指定。</p>
|
||
<p>请注意,外部服务的所有 IP 并不总是已知。要往外发送 TCP 流量,只能配置为被应用程序使用的 IP。</p>
|
||
<p>另请注意,外部服务的 IP 并不总是静态的,例如在 <a href="https://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> 的情况下,有时 IP 在大多数情况下是静态的,但可以不时地更改,例如由于基础设施的变化。在这些情况下,如果已知可能 IP 的范围,则应通过 CIDR 块指定范围。如果不知道可能的 IP 的范围,则不能使用 TCP 服务入口,并且<a href="/v1.12/zh/docs/tasks/traffic-management/egress/egress-control/#direct-access-to-external-services">必须直接调用外部服务</a>,绕过 sidecar 代理。</p>
|
||
<h2 id="relation-to-virtual-machines-support">与网格扩展的关系</h2>
|
||
<p>请注意,本文中描述的场景与<a href="/v1.12/zh/docs/examples/virtual-machines/bookinfo/">集成虚拟机</a>示例中描述的网格扩展场景不同。在这种情况下,MySQL 实例在与 Istio 服务网格集成的外部(集群外)机器(裸机或 VM)上运行 ,MySQL 服务成为网格的一等公民,具有 Istio 的所有有益功能,除此之外,服务可以通过本地集群域名寻址,例如通过 <code>mysqldb.vm.svc.cluster.local</code>,并且可以通过<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS 身份验证</a>保护与它的通信,无需创建服务入口来访问此服务; 但是,该服务必须在 Istio 注侧,要启用此类集成,必须在计算机上安装 Istio 组件(<em>Envoy proxy</em> ,<em>node-agent</em> ,<code>_istio-agent_</code> ),并且必须可以从中访问 Istio 控制平面(<em>Pilot</em> ,<em>Mixer</em> ,<em>Citadel</em> )。有关详细信息,请参阅 <a href="/v1.12/zh/docs/examples/virtual-machines/">Istio VM 相关</a>。</p>
|
||
<p>在这个的示例中,MySQL 实例可以在任何计算机上运行,也可以由云提供商作为服务进行配置,无需集成机器
|
||
与 Istio ,无需从机器访问 Istio 控制平面,在使用 MySQL 作为服务的情况下,运行 MySQL 的计算机可能无法访问,并且可能无法在其上安装必需的组件。在这个的例子中,MySQL 实例可以通过其全局域名进行寻址,如果消费应用程序希望使用该域名,这可能是有益的,当在消费应用程序的部署配置中无法更改预期的域名时,这尤其重要。</p>
|
||
<h2 id="cleanup">清理</h2>
|
||
<ol>
|
||
<li><p>删除 <code>test</code> 数据库和 <code>bookinfo</code> 用户:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;drop database test; drop user bookinfo;&#34;
|
||
</code></pre>
|
||
<p><em><strong>或者</strong></em></p>
|
||
<p>对于<code>mysql</code>和本地数据库:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;drop database test; drop user bookinfo;&#34;
|
||
</code></pre></li>
|
||
<li><p>删除虚拟服务:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-ratings-mysql.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete -f @samples/bookinfo/networking/virtual-service-ratings-mysql.yaml@
|
||
Deleted config: virtual-service/default/reviews
|
||
Deleted config: virtual-service/default/ratings
|
||
</code></pre></div></li>
|
||
<li><p>取消部署 <em>ratings v2-mysql</em> :</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml@
|
||
deployment &#34;ratings-v2-mysql&#34; deleted
|
||
</code></pre></div></li>
|
||
<li><p>删除服务入口:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry mysql-external -n default
|
||
Deleted config: serviceentry mysql-external
|
||
</code></pre></li>
|
||
</ol>
|
||
<h2 id="conclusion">结论</h2>
|
||
<p>在这篇博文中,我演示了 Istio 服务网格中的微服务如何通过 TCP 使用外部服务,默认情况下,Istio 会阻止所有流量(TCP 和 HTTP)到集群外的主机,要为 TCP 启用此类流量,必须为服务网格创建 TCP 网格外部服务入口。</p></description><pubDate>Tue, 06 Feb 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/egress-tcp/</link><author>Vadim Eisenberg</author><guid isPermaLink="true">/v1.12/zh/blog/2018/egress-tcp/</guid><category>traffic-management</category><category>egress</category><category>tcp</category></item><item><title>使用外部 Web 服务</title><description>
|
||
<p>在许多情况下,在 <em>service mesh</em> 中的微服务序并不是应用程序的全部,有时,
|
||
网格内部的微服务需要使用在服务网格外部的遗留系统提供的功能,虽然我们希望逐步将这些系统迁移到服务网格中。
|
||
但是在迁移这些系统之前,必须让服务网格内的应用程序能访问它们。还有其他情况,
|
||
应用程序使用外部组织提供的 Web 服务,通常是通过万维网提供的服务。</p>
|
||
<p>在这篇博客文章中,我修改了 <a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>让它可以
|
||
从外部 Web 服务(<a href="https://developers.google.com/books/docs/v1/getting_started">Google Books APIs</a> )获取图书详细信息。
|
||
我将展示如何使用 <em>mesh-external service entries</em> 在 Istio 中启用外部 HTTPS 流量。最后,
|
||
我解释了当前与 Istio 出口流量控制相关的问题。</p>
|
||
<h2 id="initial-setting">初始设定</h2>
|
||
<p>为了演示使用外部 Web 服务的场景,我首先使用安装了 <a href="/v1.12/zh/docs/setup/getting-started/">Istio</a> 的
|
||
Kubernetes 集群, 然后我部署 <a href="/v1.12/zh/docs/examples/bookinfo/">Istio Bookinfo 示例应用程序</a>,
|
||
此应用程序使用 <em>details</em> 微服务来获取书籍详细信息,例如页数和发布者, 原始 <em>details</em> 微服务提供书籍
|
||
详细信息,无需咨询任何外部服务。</p>
|
||
<p>此博客文章中的示例命令适用于 Istio 1.0+,无论启用或不启用<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS</a>。
|
||
Bookinfo 配置文件位于 Istio 发行存档的 <code>samples/bookinfo</code> 目录中。</p>
|
||
<p>以下是原始 <a href="/v1.12/zh/docs/examples/bookinfo/">Bookinfo 示例应用程序</a>中应用程序端到端体系结构的副本。</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.086918235567985%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/docs/examples/bookinfo/withistio.svg" title="原 Bookinfo 应用程序">
|
||
<img class="element-to-stretch" src="/v1.12/zh/docs/examples/bookinfo/withistio.svg" alt="原 Bookinfo 应用程序" />
|
||
</a>
|
||
</div>
|
||
<figcaption>原 Bookinfo 应用程序</figcaption>
|
||
</figure>
|
||
<p>执行<a href="/v1.12/zh/docs/examples/bookinfo/#deploying-the-application">部署应用程序</a>、<a href="/v1.12/zh/docs/examples/bookinfo/#confirm-the-app-is-accessible-from-outside-the-cluster">确认应用正在运行</a>,以及
|
||
<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">应用默认目标规则</a>中的步骤部分。</p>
|
||
<h3 id="Bookinfo-with-https-access-to-a-google-books-web-service">Bookinfo 使用 HTTPS 访问 Google 图书网络服务</h3>
|
||
<p>让我们添加一个新版本的 <em>details</em> 微服务,_v2_,从 <a href="https://developers.google.com/books/docs/v1/getting_started">Google Books APIs</a> 中获取图书详细信息。
|
||
它设定了服务容器的 <code>DO_NOT_ENCRYPT</code> 环境变量为 <code>false</code>。此设置将指示已部署服务使用 HTTPS(而不是 HTTP )来访问外部服务。</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-details-v2.yaml@ --dry-run -o yaml | kubectl set env --local -f - &#39;DO_NOT_ENCRYPT=false&#39; -o yaml | kubectl apply -f -
|
||
</code></pre></div>
|
||
<p>现在,应用程序的更新架构如下所示:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:65.1654485092242%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-https/bookinfo-details-v2.svg" title="Bookinfo 的 details V2 应用程序">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-https/bookinfo-details-v2.svg" alt="Bookinfo 的 details V2 应用程序" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Bookinfo 的 details V2 应用程序</figcaption>
|
||
</figure>
|
||
<p>请注意,Google Book 服务位于 Istio 服务网格之外,其边界由虚线标记。</p>
|
||
<p>现在让我们将指向 <em>details</em> 微服务的所有流量定向到 _details v2_:</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/networking/virtual-service-details-v2.yaml@
|
||
</code></pre></div>
|
||
<p>请注意,<code>VirtualService</code> 依赖于您在<a href="/v1.12/zh/docs/examples/bookinfo/#apply-default-destination-rules">应用默认目标规则</a>部分中创建的目标规则。</p>
|
||
<p>在<a href="/v1.12/zh/docs/examples/bookinfo/#determine-the-ingress-IP-and-port">确定 ingress 的 IP 和端口</a>之后,
|
||
让我们访问应用程序的网页。</p>
|
||
<p>糟糕&hellip; 页面显示 _Error fetching product details_,而不是书籍详细信息:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:36.18649965205289%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-https/errorFetchingBookDetails.png" title="获取产品详细信息的错误消息">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-https/errorFetchingBookDetails.png" alt="获取产品详细信息的错误消息" />
|
||
</a>
|
||
</div>
|
||
<figcaption>获取产品详细信息的错误消息</figcaption>
|
||
</figure>
|
||
<p>好消息是我们的应用程序没有崩溃, 通过良好的微服务设计,我们没有让<strong>故障扩散</strong>。在我们的例子中,
|
||
失败的 <em>details</em> 微服务不会导致 <code>productpage</code> 微服务失败, 尽管 <em>details</em> 微服务失败,
|
||
仍然提供了应用程序的大多数功能, 我们有<strong>优雅的服务降级</strong>:正如您所看到的,评论和评级正确显示,
|
||
应用程序仍然有用。</p>
|
||
<p>那可能出了什么问题?啊&hellip;&hellip; 答案是我忘了启用从网格内部到外部服务的流量,在本例中是 Google Book Web 服务。
|
||
默认情况下,Istio sidecar 代理(<a href="https://www.envoyproxy.io">Envoy proxies</a>)
|
||
<strong>阻止到集群外目的地的所有流量</strong>, 要启用此类流量,我们必须定义 <a href="/v1.12/zh/docs/reference/config/networking/service-entry/">mesh-external service entry</a>。</p>
|
||
<h3 id="enable-https-access-to-a-google-books-web-service">启用对 Google Books 网络服务的 HTTPS 访问</h3>
|
||
<p>不用担心,让我们定义<strong>网格外部 <code>ServiceEntry</code></strong> 并修复我们的应用程序。您还必须定义 <em>virtual
|
||
service</em> 使用 <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">SNI</a> 对外部服务执行路由。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: googleapis
|
||
spec:
|
||
hosts:
|
||
- www.googleapis.com
|
||
ports:
|
||
- number: 443
|
||
name: https
|
||
protocol: HTTPS
|
||
location: MESH_EXTERNAL
|
||
resolution: DNS
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: googleapis
|
||
spec:
|
||
hosts:
|
||
- www.googleapis.com
|
||
tls:
|
||
- match:
|
||
- port: 443
|
||
sni_hosts:
|
||
- www.googleapis.com
|
||
route:
|
||
- destination:
|
||
host: www.googleapis.com
|
||
port:
|
||
number: 443
|
||
weight: 100
|
||
EOF
|
||
</code></pre>
|
||
<p>现在访问应用程序的网页会显示书籍详细信息而不会出现错误:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:34.82831114225648%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-https/externalBookDetails.png" title="正确显示书籍详细信息">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-https/externalBookDetails.png" alt="正确显示书籍详细信息" />
|
||
</a>
|
||
</div>
|
||
<figcaption>正确显示书籍详细信息</figcaption>
|
||
</figure>
|
||
<p>您可以查询您的 <code>ServiceEntry</code> :</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get serviceentries
|
||
NAME AGE
|
||
googleapis 8m
|
||
</code></pre>
|
||
<p>您可以删除您的 <code>ServiceEntry</code> :</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry googleapis
|
||
serviceentry &#34;googleapis&#34; deleted
|
||
</code></pre>
|
||
<p>并在输出中看到删除了 <code>ServiceEntry</code>。</p>
|
||
<p>删除 <code>ServiceEntry</code> 后访问网页会产生我们之前遇到的相同错误,即 <em>Error fetching product details</em>,
|
||
正如我们所看到的,与许多其他 Istio 配置一样,<code>ServiceEntry</code> 是<strong>动态定义</strong>的 , Istio 运算符可以动态决定
|
||
它们允许微服务访问哪些域, 他们可以动态启用和禁用外部域的流量,而无需重新部署微服务。</p>
|
||
<h3 id="cleanup-of-https-access-to-a-google-books-web-service">清除对 Google 图书网络服务的 HTTPS 访问权限</h3>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml'>Zip</a><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry googleapis
|
||
$ kubectl delete virtualservice googleapis
|
||
$ kubectl delete -f @samples/bookinfo/networking/virtual-service-details-v2.yaml@
|
||
$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo-details-v2.yaml@
|
||
</code></pre></div>
|
||
<h2 id="TLS-origination-by-Istio">由 Istio 发起的 TLS</h2>
|
||
<p>这个故事有一个警告。假设您要监视您的微服务使用 <a href="https://developers.google.com/apis-explorer/">Google API</a> 的哪个特定集
|
||
(<a href="https://developers.google.com/books/docs/v1/getting_started">书籍</a>,<a href="https://developers.google.com/calendar/">日历</a>,<a href="https://developers.google.com/tasks/">任务</a>等)
|
||
假设您要强制执行仅允许使用<a href="https://developers.google.com/books/docs/v1/getting_started">图书 API</a> 的策略。
|
||
假设您要监控您的微服务访问的标识符。对于这些监视和策略任务,您需要知道 URL 路径。
|
||
考虑例如 URL <a href="https://www.googleapis.com/books/v1/volumes?q=isbn:0486424618"><code>www.googleapis.com/books/v1/volumes?q=isbn:0486424618</code></a>。
|
||
在该网址中,路径段指定了<a href="https://developers.google.com/books/docs/v1/getting_started">图书 API</a>
|
||
<code>/books</code> 和路径段的 <a href="https://en.wikipedia.org/wiki/International_Standard_Book_Number">ISBN</a> 代码
|
||
<code>/volumes?q=isbn:0486424618</code>。但是,在 HTTPS 中,所有 HTTP 详细信息(主机名,路径,标头等)都是加密的
|
||
sidecar 代理的这种监督和策略执行是无法实现的。Istio 只能通过 <a href="https://tools.ietf.org/html/rfc3546#section-3.1">SNI</a>(_Server Name Indication_)得知加密请求中的主机名称,在这里就是 <code>www.googleapis.com</code>。</p>
|
||
<p>为了允许 Istio 基于域执行出口请求的过滤,微服务必须发出 HTTP 请求, 然后,Istio 打开到目标的 HTTPS 连接(执行 TLS 发起),
|
||
根据微服务是在 Istio 服务网格内部还是外部运行,
|
||
微服务的代码必须以不同方式编写或以不同方式配置, 这与<a href="/v1.12/zh/docs/ops/deployment/architecture/#design-goals">最大化透明度</a>
|
||
的 Istio 设计目标相矛盾, 有时我们需要妥协&hellip;&hellip;</p>
|
||
<p>下图显示了如何执行外部服务的 HTTPS 流量, 在顶部,Istio 服务网格外部的微服务发送常规 HTTPS 请求,
|
||
端到端加密, 在底部,Istio 服务网格内的相同微服务必须在 pod 内发送未加密的 HTTP 请求,
|
||
这些请求被 sidecar Envoy 代理拦截 , sidecar 代理执行 TLS 发起,因此 pod 和外部服务之间的流量被加密。</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:95.1355088590701%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2018/egress-https/https_from_the_app.svg" title="对外发起 HTTPS 流量的两种方式:微服务自行发起,或由 Sidecar 代理发起">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2018/egress-https/https_from_the_app.svg" alt="对外发起 HTTPS 流量的两种方式:微服务自行发起,或由 Sidecar 代理发起" />
|
||
</a>
|
||
</div>
|
||
<figcaption>对外发起 HTTPS 流量的两种方式:微服务自行发起,或由 Sidecar 代理发起</figcaption>
|
||
</figure>
|
||
<p>以下是我们如何在 <a href="https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/src/details/details.rb">Bookinfo 的 details 微服务代码</a>
|
||
中使用 Ruby <a href="https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html">net/http 模块</a>:</p>
|
||
<pre><code class='language-ruby' data-expandlinks='true' data-repo='istio' >uri = URI.parse(&#39;https://www.googleapis.com/books/v1/volumes?q=isbn:&#39; + isbn)
|
||
http = Net::HTTP.new(uri.host, ENV[&#39;DO_NOT_ENCRYPT&#39;] === &#39;true&#39; ? 80:443)
|
||
...
|
||
unless ENV[&#39;DO_NOT_ENCRYPT&#39;] === &#39;true&#39; then
|
||
http.use_ssl = true
|
||
end
|
||
</code></pre>
|
||
<p>当定义 <code>WITH_ISTIO</code> 环境变量时,在没有 SSL(普通 HTTP )的情况下请求会通过 80 端口执行。</p>
|
||
<p>我们将 <a href="https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml">details v2 的部署配置文件</a> 的环境变量 <code>DO_NOT_ENCRYPT</code> 设置为 _&ldquo;true&rdquo;_。
|
||
<code>container</code> 部分:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >env:
|
||
- name: DO_NOT_ENCRYPT
|
||
value: &#34;true&#34;
|
||
</code></pre>
|
||
<p>在下一节中,您将配置 TLS 发起以访问外部 Web 服务。</p>
|
||
<h2 id="Bookinfo-with-TLS-origination-to-a-google-books-web-service">具有 TLS 的 Bookinfo 起源于 Google Books 网络服务</h2>
|
||
<ol>
|
||
<li><p>部署 <em>details v2</em> 版本,将 HTTP 请求发送到 <a href="https://developers.google.com/books/docs/v1/getting_started">Google Books API</a>。
|
||
在 <a href="https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml"><code>bookinfo-details-v2.yaml</code></a> 中,
|
||
<code>DO_NOT_ENCRYPT</code> 变量设置为 true。</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-details-v2.yaml@
|
||
</code></pre></div></li>
|
||
<li><p>将指向 <em>details</em> 微服务的流量定向到 _details v2_。</p>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f @samples/bookinfo/networking/virtual-service-details-v2.yaml@
|
||
</code></pre></div></li>
|
||
<li><p>为 <code>www.google.apis</code> 创建网格外部 <code>ServiceEntry</code>,virtual service 将目标端口从 80 重写为 443,并执行 TLS 的 <code>destination rule</code>。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: ServiceEntry
|
||
metadata:
|
||
name: googleapis
|
||
spec:
|
||
hosts:
|
||
- www.googleapis.com
|
||
ports:
|
||
- number: 80
|
||
name: http
|
||
protocol: HTTP
|
||
- number: 443
|
||
name: https
|
||
protocol: HTTPS
|
||
resolution: DNS
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: rewrite-port-for-googleapis
|
||
spec:
|
||
hosts:
|
||
- www.googleapis.com
|
||
http:
|
||
- match:
|
||
- port: 80
|
||
route:
|
||
- destination:
|
||
host: www.googleapis.com
|
||
port:
|
||
number: 443
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: originate-tls-for-googleapis
|
||
spec:
|
||
host: www.googleapis.com
|
||
trafficPolicy:
|
||
loadBalancer:
|
||
simple: ROUND_ROBIN
|
||
portLevelSettings:
|
||
- port:
|
||
number: 443
|
||
tls:
|
||
mode: SIMPLE # 访问 edition.cnn.com 时启动 HTTPS
|
||
EOF
|
||
</code></pre></li>
|
||
<li><p>访问应用程序的网页,并验证显示的书籍详细信息没有错误。</p></li>
|
||
<li><p><a href="/v1.12/zh/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging">开启 Envoy 访问记录功能</a></p></li>
|
||
<li><p>检查 <em>details v2</em> 的 sidecar 代理的日志,并查看 HTTP 请求。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl logs $(kubectl get pods -l app=details -l version=v2 -o jsonpath=&#39;{.items[0].metadata.name}&#39;) istio-proxy | grep googleapis
|
||
[2018-08-09T11:32:58.171Z] &#34;GET /books/v1/volumes?q=isbn:0486424618 HTTP/1.1&#34; 200 - 0 1050 264 264 &#34;-&#34; &#34;Ruby&#34; &#34;b993bae7-4288-9241-81a5-4cde93b2e3a6&#34; &#34;www.googleapis.com:80&#34; &#34;172.217.20.74:80&#34;
|
||
EOF
|
||
</code></pre>
|
||
<p>请注意日志中的 URL 路径,可以监视路径并根据它来应用访问策略。要了解有关 HTTP 出口流量的监控和访问策略
|
||
的更多信息,请查看<a href="https://archive.istio.io/v0.8/blog/2018/egress-monitoring-access-control/#logging">归档博客之出口流量监控之日志</a>。</p></li>
|
||
</ol>
|
||
<h3 id="cleanup-of-TLS-origination-to-a-google-books-web-service">清除 TLS 原始数据到 Google Books 网络服务</h3>
|
||
<div><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo-details-v2.yaml'>Zip</a><a data-skipendnotes='true' style='display:none' href='https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/virtual-service-details-v2.yaml'>Zip</a><pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl delete serviceentry googleapis
|
||
$ kubectl delete virtualservice rewrite-port-for-googleapis
|
||
$ kubectl delete destinationrule originate-tls-for-googleapis
|
||
$ kubectl delete -f @samples/bookinfo/networking/virtual-service-details-v2.yaml@
|
||
$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo-details-v2.yaml@
|
||
</code></pre></div>
|
||
<h3 id="relation-to-Istio-mutual-TLS">Istio 双向 TLS 的关系</h3>
|
||
<p>请注意,在这种情况下,TLS 的源与 Istio 应用的<a href="/v1.12/zh/docs/concepts/security/#mutual-TLS-authentication">双向 TLS</a> 无关,
|
||
无论 Istio 双向 TLS 是否启用,外部服务的 TLS 源都将起作用 , 保证服务网<strong>内</strong>的服务到服务通信,
|
||
并为每个服务提供强大的身份认证, 在此博客文章中的 <strong>外部服务</strong>的情况下,我们有<strong>单向</strong> TLS,
|
||
这是用于保护 Web 浏览器和 Web 服务器之间通信的相同机制 , TLS 应用于与外部服务的通信,
|
||
以验证外部服务器的身份并加密流量。</p>
|
||
<h2 id="conclusion">结论</h2>
|
||
<p>在这篇博文中,我演示了 Istio 服务网格中的微服务如何通过 HTTPS 使用外部 Web 服务, 默认情况下,
|
||
Istio 会阻止集群外主机的所有流量, 要启用此类流量,请使用 mesh-external, 必须为服务网格创建 <code>ServiceEntry</code> ,
|
||
可以通过 HTTPS 访问外部站点,当微服务发出 HTTPS 请求时,流量是端到端加密的,但是 Istio 无法监视 HTTP 详细信息,
|
||
例如请求的 URL 路径。当微服务发出 HTTP 请求时,Istio 可以监视请求的 HTTP 详细信息并强制执行基于 HTTP 的访问策略。
|
||
但是,在这种情况下,微服务和 sidecar 代理之间的流量是未加密的。在具有非常严格的安全要求的组织中,
|
||
可以禁止未加密的部分流量。</p></description><pubDate>Wed, 31 Jan 2018 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2018/egress-https/</link><author>Vadim Eisenberg</author><guid isPermaLink="true">/v1.12/zh/blog/2018/egress-https/</guid><category>traffic-management</category><category>egress</category><category>https</category></item><item><title>Mixer 和 SPOF 神话</title><description>
|
||
<p><a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/">Mixer</a> 出现在请求路径上,很自然的会引发一个疑问:他对系统可用性和延迟会产生什么样的影响?第一次看到 Istio 架构图时,人们最常见的问题就是:&rdquo;这不就是一个单点失败的典型案例么?”</p>
|
||
<p>本文中我们会深入挖掘和阐述 Mixer 的设计原则,在这些设计原则的支持下 Mixer 能够令人惊奇的提高网格内的系统可用性,降低平均请求延时。</p>
|
||
<p>Istio 的 Mixer 对系统总体可用性和延迟有两个主要的好处:</p>
|
||
<ul>
|
||
<li><p><strong>提高 SLO</strong>:Mixer 把 Proxy 和服务从基础设施后端的故障中隔离出来,提供了高级、高效的网格可用性保障。作为一个整体来说,在同基础设施后端的交互中,有了 Mixer 的帮助,会有更低的故障率。</p></li>
|
||
<li><p><strong>降低延迟</strong>:通过对各个层次的分片缓存的积极使用和共享,Mixer 能够降低平均延迟。</p></li>
|
||
</ul>
|
||
<p>接下来会对上面的内容进行一下解释。</p>
|
||
<h2 id="how-we-got-here">Istio 是怎么来的</h2>
|
||
<p>Google 在多年中都在使用一个内部的 API 和服务管理系统,用于处理 Google 提供的众多 API。这一系统支持了最大的服务群(Google Maps、YouTube 以及 Gmail 等),承受上百万 QPS 峰值的冲击。这套系统运行的虽然很好,但是仍然无法跟上 Google 快速增长的脚步,很显然,要有新的架构来降低飞涨的运维成本。</p>
|
||
<p>2014 年,我们开始了一个草案,准备替换这一系统,进行更好的伸缩。这一决定最后证明是非常正确的,在 Google 进行整体部署之后,每月降低了上百万美元的运维成本。</p>
|
||
<p>过去,流量在进入具体的服务之前,首先会进入一个较重的代理,旧系统就是以这个代理为中心构建的。新的架构摒弃了共享代理的设计,用轻量高效的 Sidecar 代理取而代之,这一代理和服务实例并行,共享一个控制平面。</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:74.79295535770372%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2017/mixer-spof-myth/mixer-spof-myth-1.svg" title="Google 系统拓扑">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2017/mixer-spof-myth/mixer-spof-myth-1.svg" alt="Google 系统拓扑" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Google 的 API 和 服务管理系统</figcaption>
|
||
</figure>
|
||
<p>看起来很面熟吧?是的,跟 Istio 很像。Istio 就是作为这一分布式代理架构的继任者进行构思的。我们从内部系统中获取了核心的灵感,在同合作伙伴的协同工作中产生了很多概念,这些导致了 Istio 的诞生。</p>
|
||
<h2 id="architecture-recap">架构总结</h2>
|
||
<p>下图中,Mixer 在 Mesh 和基础设施之间:</p>
|
||
<figure style="width:75%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:65.89948886170049%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2017/mixer-spof-myth/mixer-spof-myth-2.svg" title="Istio 拓扑">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2017/mixer-spof-myth/mixer-spof-myth-2.svg" alt="Istio 拓扑" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio 拓扑</figcaption>
|
||
</figure>
|
||
<p>逻辑上,Envoy Sidecar 会在每次请求之前调用 Mixer,进行前置检查,每次请求之后又要进行指标报告。Sidecar 中包含本地缓存,一大部分的前置检查可以通过缓存来进行。另外,Sidecar 会把待发送的指标数据进行缓冲,这样可能在几千次请求之后才调用一次 Mixer。前置检查和请求处理是同步的,指标数据上送是使用 fire-and-forget 模式异步完成的。</p>
|
||
<p>抽象一点说,Mixer 提供:</p>
|
||
<ul>
|
||
<li><p><strong>后端抽象</strong>:Mixer 把 Istio 组件和网格中的服务从基础设施细节中隔离开来。</p></li>
|
||
<li><p><strong>中间人</strong>:Mixer 让运维人员能够对所有网格和基础设施后端之间的交互进行控制。</p></li>
|
||
</ul>
|
||
<p>除了这些纯功能方面,Mixer 还有一些其他特点,为系统提供更多益处。</p>
|
||
<h3 id="mixer-booster">Mixer:SLO 助推器</h3>
|
||
<p>有人说 Mixer 是一个 SPOF,会导致 Mesh 的崩溃,而我们认为 Mixer 增加了 Mesh 的可用性。这是如何做到的?下面是三个理由:</p>
|
||
<ul>
|
||
<li><p><strong>无状态</strong>:Mixer 没有状态,他不管理任何自己的持久存储。</p></li>
|
||
<li><p><strong>稳固</strong>:Mixer 是一个高可靠性的组件,设计要求所有 Mixer 实例都要有超过 99.999% 的可靠性。</p></li>
|
||
<li><p><strong>缓存和缓冲</strong>:Mixer 能够积累大量的短期状态数据。</p></li>
|
||
</ul>
|
||
<p>Sidecar 代理伴随每个服务实例而运行,必须节约使用内存,这样就限制了本地缓存和缓冲的数量。但是 Mixer 是独立运行的,能使用更大的缓存和缓冲。因此 Mixer 为 Sidecar 提供了高伸缩性高可用的二级缓存服务。</p>
|
||
<p>Mixer 的预期可用性明显高于多数后端(多数是 99.9%)。他的本地缓存和缓冲区能够在后端无法响应的时候继续运行,因此有助于对基础设施故障的屏蔽,降低影响。</p>
|
||
<h3 id="mixer-latency-slasher">Mixer:延迟削减器</h3>
|
||
<p>上面我们解释过,Istio Sidecar 具备有效的一级缓存,在为流量服务的时候多数时间都可以使用缓存来完成。Mixer 提供了更大的共享池作为二级缓存,这也帮助了 Mixer 降低平均请求的延迟。</p>
|
||
<p>不只是降低延迟,Mixer 还降低了 Mesh 到底层的请求数量,这样就能显著降低到基础设施后端的 QPS,如果你要付款给这些后端,那么这一优点就会节省更多成本。</p>
|
||
<h2 id="work-ahead">下一步</h2>
|
||
<p>我们还有机会对系统做出更多改进。</p>
|
||
<h3 id="configuration-canaries">以金丝雀部署的方式进行配置发布</h3>
|
||
<p>Mixer 具备高度的伸缩性,所以他通常不会故障。然而如果部署了错误的配置,还是会引发 Mixer 进程的崩溃。为了防止这种情况的出现,可以用金丝雀部署的方式来发布配置,首先为一小部分 Mixer 进行部署,然后扩大部署范围。</p>
|
||
<p>目前的 Mixer 并未具备这样的能力,我们期待这一功能成为 Istio 可靠性配置工作的一部分最终得以发布。</p>
|
||
<h3 id="cache-tuning">缓存调优</h3>
|
||
<p>我们的 Sidecar 和 Mixer 缓存还需要更好的调整,这部分的工作会着眼于资源消耗的降低和性能的提高。</p>
|
||
<h3 id="cache-sharing">缓存共享</h3>
|
||
<p>现在 Mixer 的实例之间是各自独立的。一个请求在被某个 Mixer 实例处理之后,并不会把过程中产生的缓存传递给其他 Mixer 实例。我们最终会试验使用 Memcached 或者 Redis 这样的分布式缓存,以期提供一个网格范围内的共享缓存,更好的降低对后端基础设施的调用频率。</p>
|
||
<h3 id="Sharding">分片</h3>
|
||
<p>在大规模的网格中,Mixer 的负载可能很重。我们可以使用大量的 Mixer 实例,每个实例都为各自承担的流量维护各自的缓存。我们希望引入智能分片能力,这样 Mixer 实例就能针对特定的数据流提供特定的服务,从而提高缓存命中率;换句话说,分片可以利用把相似的流量分配给同一个 Mixer 实例的方式来提高缓存效率,而不是把请求交给随机选择出来的 Mixer 实例进行处理。</p>
|
||
<h2 id="conclusion">结语</h2>
|
||
<p>Google 的实际经验展示了轻代理、大缓存控制平面结合的好处:提供更好的可用性和延迟。过去的经验帮助 Istio 构建了更精确更有效的缓存、预抓取以及缓冲策略等功能。我们还优化了通讯协议,用于降低缓存无法命中的时候,对性能产生的影响。</p>
|
||
<p>Mixer 还很年轻。在 Istio 0.3 中,Mixer 并没有性能方面的重要改进。这意味着如果一个请求没有被 Sidecar 缓存命中,Mixer 就会花费更多时间。未来的几个月中我们会做很多工作来优化同步的前置检查过程中的这种情况。</p>
|
||
<p>我们希望本文能够让读者能够意识到 Mixer 对 Istio 的益处。</p>
|
||
<p>如果有意见或者问题,无需犹豫,请前往 <a href="https://groups.google.com/forum/#!forum/istio-policies-and-telemetry">istio-policies-and-telemetry@</a>。</p></description><pubDate>Thu, 07 Dec 2017 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2017/mixer-spof-myth/</link><author>Martin Taillefer</author><guid isPermaLink="true">/v1.12/zh/blog/2017/mixer-spof-myth/</guid><category>adapters</category><category>mixer</category><category>policies</category><category>telemetry</category><category>availability</category><category>latency</category></item><item><title>Mixer 适配器模型</title><description>
|
||
<p>Istio 0.2 引入了一种新的 Mixer 适配器模型,这种模型使接入后端基础设施具有更多的灵活性 。本文将解释这种模型是如何工作的。</p>
|
||
<h2 id="why-adapters">为什么是适配器模型?</h2>
|
||
<p>后端基础设施提供了支持服务构建的功能。他们包括访问控制、遥测、配额控制、计费系统等等。传统服务会直接与这些后端系统集成,并与后端紧密耦合,并集成到其中的个性化语义和操作。</p>
|
||
<p>Mixer 服务作为 Istio 和一套开放式基础设施之间的抽象层。Istio 组件和运行在 Service Mesh 中的服务,通过 Mixer 就可以在不直接访问后端接口的情况下和这些后端进行交互。</p>
|
||
<p>除了作为应用层与基础设施隔离外,Mixer 提供了一种中介模型,这种模型允许注入和控制应用和后端的策略。操作人员可以控制哪些数据汇报给哪个后端,哪个后端提供授权等等。</p>
|
||
<p>考虑到每个基础服务都有不同的接口和操作模型,Mixer 需要用户通过代码来解决这些差异,我们可以称这些用户自己封装的代码为 <a href="https://github.com/istio/istio/wiki/Mixer-Compiled-In-Adapter-Dev-Guide"><em>适配器</em></a>。</p>
|
||
<p>适配器以 Go 包的形式直接链接到 Mixer 二进制中。如果默认的适配器不能满足特定的使用需求,自定义适配器也是很简单的。</p>
|
||
<h2 id="philosophy">设计哲学</h2>
|
||
<p>Mixer 本质上就是一个处理属性和路由的机器。代理将<a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#attributes">属性</a>作为预检和遥测报告的一部分发送出来,并且转换为一系列对适配器的调用。运维人员提供了用于描述如何将传入的属性映射为适配器的配置。</p>
|
||
<figure style="width:60%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:42.60859894197215%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/machine.svg" title="Attribute Machine">
|
||
<img class="element-to-stretch" src="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/machine.svg" alt="Attribute Machine" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Attribute Machine</figcaption>
|
||
</figure>
|
||
<p>配置是一个复杂的任务。有证据表明绝大多数服务中断是由配置错误造成的。为了帮助解决这一问题,Mixer 的配置模型通过做限制来避免错误。例如,在配置中使用强类型,以此来确保在上下文环境中使用了有意义的属性或者属性表达式。</p>
|
||
<h2 id="handlers-configuring-adapters">Handlers: 适配器的配置</h2>
|
||
<p>Mixer 使用的每个适配器都需要一些配置才能运行。一般来说,适配器需要一些信息。例如,到后端的 URL 、证书、缓存选项等等。每个适配器使用一个 <a href="https://developers.google.com/protocol-buffers/">protobuf</a> 消息来定义所需要的配置数据。</p>
|
||
<p>你可以通过创建 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#handlers"><em>handler</em></a> 为适配器提供配置。Handler 就是一套能让一个适配器就绪的完整配置。对同一个适配器可以有任意数量的 Handler,这样就可以在不同的场景下复用了。</p>
|
||
<h2 id="templates-adapter-input-schema">Templates: 适配输入结构</h2>
|
||
<p>通常对于进入到 Mesh 服务中的请求,Mixer 会发生两次调用,一次是预检,一次是遥测报告。每一次调用,Mixer 都会调用一个或更多的适配器。不同的适配器需要不同的数据作为输入来处理。例如,日志适配器需要日志输入,metric 适配器需要 metric 数据作为输入,认证的适配器需要证书等等。Mixer <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/templates/"><em>templates</em></a> 用来描述每次请求适配器消费的数据。</p>
|
||
<p>每个 Template 被指定为 <a href="https://developers.google.com/protocol-buffers/">protobuf</a> 消息。一个模板描述了一组数据,这些数据在运行时被传递给一个或多个适配器。一个适配器可以支持任意数量的模板,开发者还可以设计支持特定模板的是适配器。</p>
|
||
<p><a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/templates/metric/"><code>metric</code></a> 和 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/templates/logentry/"><code>logentry</code></a> 是两个最重要的模板,分别表示负载的单一指标,和到适当后端的单一日志条目。</p>
|
||
<h2 id="instances-attribute-mapping">Instances: 属性映射</h2>
|
||
<p>你可以通过创建 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#instances"><em>instances</em></a> 来决定哪些数据被传递给特定的适配器。Instances 决定了 Mixer 如何通过 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#attributes">attributes</a> 把来自代理的属性拆分为各种数据然后分发给不同的适配器。</p>
|
||
<p>创建实例通常需要使用 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/expression-language/">attribute expressions</a> 。这些表达式的功能是使用属性和常量来生成结果数据,用于给 instance 字段进行赋值。</p>
|
||
<p>在模板中定义的每个 instance 字段、每个属性、每个表达式都有一个 <a href="https://github.com/istio/api/blob/release-1.12/policy/v1beta1/value_type.proto">type</a>,只有兼容的数据类型才能进行赋值。例如不能把整型的表达式赋值给字符串类型。强类型设计的目的就是为了降低配置出错引发的风险。</p>
|
||
<h2 id="rules-delivering-data-to-adapters">Rules: 将数据交付给适配器</h2>
|
||
<p>最后一个问题就是告诉 Mixer 哪个 instance 在什么时候发送给哪个 handler。这个通过创建 <a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/#rules"><em>rules</em></a> 实现。每个规则都会指定一个特定的处理程序和要发送给该处理程序的示例。当 Mixer 处理一个调用时,它会调用指定的处理程序,并给他一组特定的处理实例。</p>
|
||
<p>Rule 中包含有匹配断言,这个断言是一个返回布尔值的属性表达式。只有属性表达式断言成功的 Rule 才会生效,否则这条规则就形同虚设,当然其中的 Handler 也不会被调用。</p>
|
||
<h2 id="future">未来的工作</h2>
|
||
<p>我们正在努力改进和提升适配器的使用及开发。例如,计划中包含很多新特性使用户更加方便地使用 Templates。另外,表达式语言也正在不断的发展和成熟。</p>
|
||
<p>长远来看,我们正在寻找不直接将适配器直接连接到 Mixer 二进制的方法。这将简化部署和开发使用。</p>
|
||
<h2 id="conclusion">结论</h2>
|
||
<p>新的 Mixer 适配器模型的设计是为了提供一个灵活的框架用来支持一个开放基础设施。</p>
|
||
<p>Handler 为各个适配器提供了配置数据,Template 用于在运行时确定不同的适配器所需的数据类型,Instance 让运维人员准备这些数据,Rule 将这些数据提交给一个或多个 Handler 进行处理。</p>
|
||
<p>更多信息可以关注<a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/mixer-overview/">这里</a>。更多关于 templates, handlers, 和 rules 的内容可以关注<a href="/v1.12/zh/docs/reference/config/policy-and-telemetry/">这里</a>。你也可以在<a href="https://github.com/istio/istio/tree/release-1.12/samples/bookinfo">这里</a>找到对应的示例。</p></description><pubDate>Fri, 03 Nov 2017 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2017/adapter-model/</link><author>Martin Taillefer</author><guid isPermaLink="true">/v1.12/zh/blog/2017/adapter-model/</guid><category>adapters</category><category>mixer</category><category>policies</category><category>telemetry</category></item><item><title>Istio 使用网络策略</title><description>
|
||
<p>使用网络策略去保护运行在 Kubernetes 上的应用程序现在是一种广泛接受的行业最佳实践。鉴于 Istio 也支持策略,我们希望花一些时间来解释 Istio 策略和 Kubernetes 网络策略的相互作用和互相支持提供应用程序的安全。</p>
|
||
<p>让我们从基础开始:为什么你想要同时使用 Istio 和 Kubernetes 网络策略?简短的回答是它们处理不同的事情。表格列出 Istio 和网络策略之间的主要区别(我们将描述“典型”实现,例如:Calico,但具体实现细节可能因不同的网络提供商而异):</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th></th>
|
||
<th>Istio 策略</th>
|
||
<th>网络策略</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>层级</strong></td>
|
||
<td>&ldquo;服务&rdquo; &mdash; L7</td>
|
||
<td>&ldquo;网络&rdquo; &mdash; L3-4</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>实现</strong></td>
|
||
<td>用户空间</td>
|
||
<td>内核</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>执行点</strong></td>
|
||
<td>Pod</td>
|
||
<td>节点</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="layer">层级</h2>
|
||
<p>从 OSI 模型的角度来看 7 层(应用程序),Istio 策略运行在网络应用程序的“服务”层。但事实上云原生应用程序模型是 7 层实际上至少包含两层:服务层和内容层。服务层通常是 HTTP ,它封装了实际的应用程序数据(内容层)。Istio 的 Envoy 代理运行的 HTTP 服务层。相比之下,网络策略在 OSI 模型中的第 3 层(网络)和第 4 层(传输)运行。</p>
|
||
<p>运行在服务层为 Envoy 代理提供了一组丰富的属性,以便基础协议进行策略决策,其中包括 HTTP/1.1 和 HTTP/2(gRPC 运行在 HTTP/2 上)。因此,您可以基于虚拟主机、URL 或其他 HTTP 头部应用策略。在未来,Istio 将支持广泛的 7 层协议、以及通用的 TCP 和 UDP 传输。</p>
|
||
<p>相比之下,Istio 策略运行在网络层具有通用的优势,因为所有网络应用程序都使用 IP。无论 7 层协议如何,您都可以在网络层应用策略:DNS 、SQL 数据库、实时流以及许多不使用 HTTP 的其他服务都可以得到保护。网络策略不仅限于经典防火墙的 IP 地址、协议和端口三元组,Istio 和网络策略都可以使用丰富的 Kubernetes 标签来描述 pod 端点。</p>
|
||
<h2 id="implementation">实现</h2>
|
||
<p>Istio 的代理基于 <a href="https://envoyproxy.github.io/envoy/"><code>Envoy</code></a>,它作为数据平面的用户空间守护进程实现的,使用标准套接字与网络层交互。这使它在处理方面具有很大的灵活性,并允许它在容器中分发(和升级!)。</p>
|
||
<p>网络策略数据平面通常在内核空间中实现(例如:使用 iptables 、eBPF 过滤器、或甚至自定义内核模块)。在内核空间使它们性能很好,但不像 Envoy 代理那样灵活。</p>
|
||
<h2 id="enforcement-point">执行点</h2>
|
||
<p>Envoy 代理的策略执行是在 pod 中,作为同一网络命名空间中的 sidecar 容器。这使得部署模型简单。某些容器赋予权限可以重新配置其 pod 中的网络(<code>CAP_NET_ADMIN</code>)。如果此类服务实例绕过代理受到损害或行为不当(如:在恶意租户中)。</p>
|
||
<p>虽然这不会让攻击者访问其他启用了 Istio 的 pod ,但通过配置,会打开几种攻击:</p>
|
||
<ul>
|
||
<li>攻击未受保护的 pods</li>
|
||
<li>尝试通过发送大量流量为受保护的 pods 造成访问拒绝</li>
|
||
<li>在 pod 中收集的漏出数据</li>
|
||
<li>攻击集群基础设施(服务器或 Kubernetes 服务)</li>
|
||
<li>攻击网格外的服务,如数据库,存储阵列或遗留系统。</li>
|
||
</ul>
|
||
<p>网络策略通常在客户机的网络命名空间之外的主机节点处执行。这意味着必须避免受损或行为不当的 pod 进入根命名空间的执行。通过在 Kubernetes 1.8 中添加 egress 策略,这是网络策略成为保护基础设施免受工作负载受损的关键部分。</p>
|
||
<h2 id="examples">举例</h2>
|
||
<p>让我们来看一些 Istio 应用程序使用 Kubernetes 网络策略的示例。下面我们以 Bookinfo 应用程序为例,介绍网络策略功能的用例:</p>
|
||
<ul>
|
||
<li>减少应用程序入口的攻击面</li>
|
||
<li>在应用程序中实现细粒度隔离</li>
|
||
</ul>
|
||
<h3 id="reduce-attack-surface-of-the-application-ingress">减少应用程序入口的攻击面</h3>
|
||
<p>应用程序的 ingress 控制器是外部世界进入我们应用程序的主要入口。快速查看 <code>istio.yaml</code> (用于安装 Istio )定义了 Istio-ingress,如下所示:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: istio-ingress
|
||
labels:
|
||
istio: ingress
|
||
spec:
|
||
type: LoadBalancer
|
||
ports:
|
||
- port: 80
|
||
name: http
|
||
- port: 443
|
||
name: https
|
||
selector:
|
||
istio: ingress
|
||
</code></pre>
|
||
<p><code>istio-ingress</code> 暴露端口 80 和 443 . 我们需要将流入流量限制在这两个端口上。Envoy 有 <a href="https://www.envoyproxy.io/docs/envoy/latest/operations/admin.html#operations-admin-interface"><code>内置管理接口</code></a>,我们不希望错误配置 <code>istio-ingress</code> 镜像而导致意外地将我们的管理接口暴露给外界。这里深度防御的示例:正确配置的镜像应该暴露接口,正确配置的网络策略将阻止任何人连接到它,要么失败,要么配置错误,受到保护。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.k8s.io/v1
|
||
kind: NetworkPolicy
|
||
metadata:
|
||
name: istio-ingress-lockdown
|
||
namespace: default
|
||
spec:
|
||
podSelector:
|
||
matchLabels:
|
||
istio: ingress
|
||
ingress:
|
||
- ports:
|
||
- protocol: TCP
|
||
port: 80
|
||
- protocol: TCP
|
||
port: 443
|
||
</code></pre>
|
||
<h3 id="enforce-fine-grained-isolation-within-the-application">在应用程序中实现细粒度隔离</h3>
|
||
<p>如下是 Bookinfo 应用程序的服务示意图:</p>
|
||
<figure style="width:80%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:59.086918235567985%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/docs/examples/bookinfo/withistio.svg" title="Bookinfo Service Graph">
|
||
<img class="element-to-stretch" src="/v1.12/zh/docs/examples/bookinfo/withistio.svg" alt="Bookinfo Service Graph" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Bookinfo Service Graph</figcaption>
|
||
</figure>
|
||
<p>此图显示了一个正确功能的应用程序应该允许的每个连接。所有其他连接,例如从 Istio Ingress 直接到 Rating 服务,不是应用程序的一部分。让我们排除那些无关的连接,它们不能被攻击者所用。例如:想象一下,Ingress pod 受到攻击者的攻击,允许攻击者运行任意代码。如果我们使用网络策略只允许连接到 <code>productpage</code>(<code>http://$GATEWAY_URL/productpage</code>)的 Pod ,则攻击者不再获得对我的应用程序后端的访问权限,尽管它们已经破坏了服务网格的成员。</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: networking.k8s.io/v1
|
||
kind: NetworkPolicy
|
||
metadata:
|
||
name: product-page-ingress
|
||
namespace: default
|
||
spec:
|
||
podSelector:
|
||
matchLabels:
|
||
app: productpage
|
||
ingress:
|
||
- ports:
|
||
- protocol: TCP
|
||
port: 9080
|
||
from:
|
||
- podSelector:
|
||
matchLabels:
|
||
istio: ingress
|
||
</code></pre>
|
||
<p>推荐你可以而且应该为每个服务编写类似的策略,允许其他 pod 访问执行。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>我们认为 Istio 和网络策略在应用策略方面有不同的优势。Istio 具有应用协议感知和高度灵活性,非常适合应用策略来支持运营目标,如:服务路由、重试、熔断等,以及在应用层开启的安全性,例如:令牌验证。网络策略是通用的、高效的、与 pod 隔离,使其成为应用策略以支持网络安全目标的理想选择。此外,拥有在网络堆栈的不同层运行的策略是一件非常好的事情,因为它为每个层提供特定的上下文而不会混合状态并允许责任分离。</p>
|
||
<p>这篇文章是基于 Spike Curtis 的三部分博客系列,他是 Tigera 的 Istio 团队成员之一。完整系列可以在这里找到:<a href="https://www.projectcalico.org/using-network-policy-in-concert-with-istio/">https://www.projectcalico.org/using-network-policy-in-concert-with-istio/</a></p></description><pubDate>Thu, 10 Aug 2017 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2017/0.1-using-network-policy/</link><author>Spike Curtis</author><guid isPermaLink="true">/v1.12/zh/blog/2017/0.1-using-network-policy/</guid></item><item><title>使用 Istio 进行金丝雀部署</title><description>
|
||
<div>
|
||
<aside class="callout tip">
|
||
<div class="type">
|
||
<svg class="large-icon"><use xlink:href="/v1.12/img/icons.svg#callout-tip"/></svg>
|
||
</div>
|
||
<div class="content">本篇博客最后更新时间 2018 年 5 月 16 号,采用了最新版本的流量管理模型。</div>
|
||
</aside>
|
||
</div>
|
||
<p>采用 <a href="/v1.12/zh/">Istio</a> 项目的一大好处就是为服务金丝雀方式部署提供了控制便利。金丝雀部署(或上线)背后的想法是通过让一小部分用户流量引入的新版本进行测试,如果一切顺利,则可以增加(可能逐渐增加)百分比,逐步替换旧版本。如在过程中出现任何问题,则可以中止并回滚到旧版本。最简单的方式,是随机选择百分比请求到金丝雀版本,但在更复杂的方案下,则可以基于请求的区域,用户或其他属性。</p>
|
||
<p>基于领域的专业水平,您可能想知道为什么需要 Istio 来支持金丝雀部署,因为像 Kubernetes 这样的平台已经提供了进行<a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment">版本上线</a>和<a href="https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments">金丝雀部署</a>的方法。问题解决了吗 ?不完全是。虽然以这种方式进行部署可以在简单的情况下工作,但功能非常有限,特别是在大规模自动缩放的云环境中大流量的情况下。</p>
|
||
<h2 id="canary-deployment-in-Kubernetes">Kubernetes 中的金丝雀部署</h2>
|
||
<p>假设我们有一个已部署的 <strong>helloworld</strong> 服务 <strong>v1</strong> 版本,我们想要测试(或简单上线)新版本 <strong>v2</strong>。使用 Kubernetes,您可以通过简单地更新服务的 <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/">Deployment</a> 中的镜像并自动进行部署来<a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment">上线</a>新版本的 <strong>helloworld</strong> 服务。如果我们特能够小心保证在启动并且在仅启动一个或两个 v2 副本<a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#pausing-and-resuming-a-deployment">暂停</a>上线时有足够的 <strong>v1</strong> 副本运行,则能够保持金丝雀发布对系统的影响非常小。后续我们可以观察效果,或在必要时进行<a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment">回滚</a>。最好,我们也能够对 Deployment 设置 <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#scaling-a-deployment">HPA</a>,在上线过程中减少或增加副本以处理流量负载时,也能够保持副本比例一致。</p>
|
||
<p>尽管这种机制能够很好工作,但这种方式只适用于部署的经过适当测试的版本,也就是说,更多的是蓝/绿发布,又称红/黑发布,而不是 “蜻蜓点水“ 式的金丝雀部署。实际上,对于后者(例如,并没有完全准备好或者无意对外暴露的版本),Kubernetes 中的金丝雀部署将使用具有<a href="https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively">公共 pod 标签</a>的两个 Deployment 来完成。在这种情况下,我们不能再使用自动缩放器,因为是有由两个独立的自动缩放器来进行控制,不同负载情况下,副本比例(百分比)可能与所需的比例不同。</p>
|
||
<p>无论我们使用一个或者两个部署,使用 Docker,Mesos/Marathon 或 Kubernetes 等容器编排平台进行的金丝雀发布管理都存在一个根本问题:使用实例扩容来管理流量;版本流量分发和副本部署在上述平台中并独立。所有 pod 副本,无论版本如何,在 <code>kube-proxy</code> 循环池中都被一视同仁地对待,因此管理特定版本接收的流量的唯一方法是控制副本比例。以小百分比维持金丝雀流量需要许多副本(例如,1% 将需要至少 100 个副本)。即使我们可以忽略这个问题,部署方式功能仍然非常有限,因为它只支持简单(随机百分比)金丝雀部署。如果我们想根据某些特定规则将请求路由到金丝雀版本上,我们仍然需要另一种解决方案。</p>
|
||
<h2 id="enter-Istio">使用 Istio</h2>
|
||
<p>使用 Istio,流量路由和副本部署是两个完全独立的功能。服务的 pod 数量可以根据流量负载灵活伸缩,与版本流量路由的控制完全正交。这在自动缩放的情况下能够更加简单地管理金丝雀版本。事实上,自动缩放管理器仍然独立运行,其在响应因流量路由导致的负载变化与其他原因导致负载变化的行为上没有区别。</p>
|
||
<p>Istio 的<a href="/v1.12/zh/docs/concepts/traffic-management/#routing-rules">路由规则</a>也带来了其他的便利;你可以轻松实现细粒度控制流量百分比(例如,路由 1% 的流量而不需要 100 个 pod),当然也可以使用其他规则来控制流量(例如,将特定用户的流量路由到金丝雀版本)。作为展示,让我们看一下采用这种方式部署 <strong>helloworld</strong> 服务的简单便捷。</p>
|
||
<p>首先我们定义 <strong>helloworld</strong> 服务,和普通 <strong>Kubernetes</strong> 服务一样,如下所示:</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: helloworld
|
||
labels:
|
||
app: helloworld
|
||
spec:
|
||
selector:
|
||
app: helloworld
|
||
...
|
||
</code></pre>
|
||
<p>然后我们添加 2 个 Deployment,分别为版本 <strong>v1</strong> 和 <strong>v2</strong>,这两个版本都包含服务选择标签 <code>app:helloworld</code> :</p>
|
||
<pre><code class='language-yaml' data-expandlinks='true' data-repo='istio' >kind: Deployment
|
||
metadata:
|
||
name: helloworld-v1
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: helloworld
|
||
version: v1
|
||
spec:
|
||
containers:
|
||
- image: helloworld-v1
|
||
...
|
||
---
|
||
apiVersion: extensions/v1beta1
|
||
kind: Deployment
|
||
metadata:
|
||
name: helloworld-v2
|
||
spec:
|
||
replicas: 1
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: helloworld
|
||
version: v2
|
||
spec:
|
||
containers:
|
||
- image: helloworld-v2
|
||
...
|
||
</code></pre>
|
||
<p>需要注意的是,这与使用普通 Kubernetes 进行<a href="https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments">金丝雀部署</a>的方式完全相同,但是在 Kubernetes 方式下控制流量分配需要调整每个 Deployment 的副本数目。例如,将 10% 的流量发送到金丝雀版本(v2),v1 和 v2 的副本可以分别设置为 9 和 1。</p>
|
||
<p>但是在<a href="/v1.12/zh/docs/setup/">启用 Istio</a> 的集群中,我们可以通过设置路由规则来控制流量分配。如将 10% 的流量发送到金丝雀版本本,我们可以使用 <code>kubectl</code> 来设置以下的路由规则:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: helloworld
|
||
spec:
|
||
hosts:
|
||
- helloworld
|
||
http:
|
||
- route:
|
||
- destination:
|
||
host: helloworld
|
||
subset: v1
|
||
weight: 90
|
||
- destination:
|
||
host: helloworld
|
||
subset: v2
|
||
weight: 10
|
||
---
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: DestinationRule
|
||
metadata:
|
||
name: helloworld
|
||
spec:
|
||
host: helloworld
|
||
subsets:
|
||
- name: v1
|
||
labels:
|
||
version: v1
|
||
- name: v2
|
||
labels:
|
||
version: v2
|
||
EOF
|
||
</code></pre>
|
||
<p>当规则设置生效后,Istio 将确保只有 10% 的请求发送到金丝雀版本,无论每个版本的运行副本数量是多少。</p>
|
||
<h2 id="autoscaling-the-deployments">部署中的自动缩放</h2>
|
||
<p>由于我们不再需要保持副本比例,所以我们可以安全地设置 Kubernetes <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">HPA</a> 来管理两个版本 Deployment 的副本:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl autoscale deployment helloworld-v1 --cpu-percent=50 --min=1 --max=10
|
||
deployment &#34;helloworld-v1&#34; autoscaled
|
||
</code></pre>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl autoscale deployment helloworld-v2 --cpu-percent=50 --min=1 --max=10
|
||
deployment &#34;helloworld-v2&#34; autoscaled
|
||
</code></pre>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get hpa
|
||
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
|
||
Helloworld-v1 Deployment/helloworld-v1 50% 47% 1 10 17s
|
||
Helloworld-v2 Deployment/helloworld-v2 50% 40% 1 10 15s
|
||
</code></pre>
|
||
<p>如果现在对 <strong>helloworld</strong> 服务上产生一些负载,我们会注意到,当扩容开始时,<strong>v1</strong> 扩容副本数目远高于 <strong>v2</strong> ,因为 <strong>v1</strong> pod 正在处理 90% 的负载。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods | grep helloworld
|
||
helloworld-v1-3523621687-3q5wh 0/2 Pending 0 15m
|
||
helloworld-v1-3523621687-73642 2/2 Running 0 11m
|
||
helloworld-v1-3523621687-7hs31 2/2 Running 0 19m
|
||
helloworld-v1-3523621687-dt7n7 2/2 Running 0 50m
|
||
helloworld-v1-3523621687-gdhq9 2/2 Running 0 11m
|
||
helloworld-v1-3523621687-jxs4t 0/2 Pending 0 15m
|
||
helloworld-v1-3523621687-l8rjn 2/2 Running 0 19m
|
||
helloworld-v1-3523621687-wwddw 2/2 Running 0 15m
|
||
helloworld-v1-3523621687-xlt26 0/2 Pending 0 19m
|
||
helloworld-v2-4095161145-963wt 2/2 Running 0 50m
|
||
</code></pre>
|
||
<p>如果更改路由规则将 50% 的流量发送到 <strong>v2</strong>,我们则可以在短暂的延迟后注意到 <strong>v1</strong> 副本数的减少,而 <strong>v2</strong> 副本数相应地增加。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods | grep helloworld
|
||
helloworld-v1-3523621687-73642 2/2 Running 0 35m
|
||
helloworld-v1-3523621687-7hs31 2/2 Running 0 43m
|
||
helloworld-v1-3523621687-dt7n7 2/2 Running 0 1h
|
||
helloworld-v1-3523621687-gdhq9 2/2 Running 0 35m
|
||
helloworld-v1-3523621687-l8rjn 2/2 Running 0 43m
|
||
helloworld-v2-4095161145-57537 0/2 Pending 0 21m
|
||
helloworld-v2-4095161145-9322m 2/2 Running 0 21m
|
||
helloworld-v2-4095161145-963wt 2/2 Running 0 1h
|
||
helloworld-v2-4095161145-c3dpj 0/2 Pending 0 21m
|
||
helloworld-v2-4095161145-t2ccm 0/2 Pending 0 17m
|
||
helloworld-v2-4095161145-v3v9n 0/2 Pending 0 13m
|
||
</code></pre>
|
||
<p>最终结果与 Kubernetes Deployment 上线非常相似,只是整个流程并不是集中地进行编排和管理。相反,我们看到几个组件独立完成工作,虽然它们有因果关系。</p>
|
||
<p>有一点不同的是,当我们停止负载时,无论设置路由规则如何,两个版本的副本数最终都会缩小到最小值(1)。</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl get pods | grep helloworld
|
||
helloworld-v1-3523621687-dt7n7 2/2 Running 0 1h
|
||
helloworld-v2-4095161145-963wt 2/2 Running 0 1h
|
||
</code></pre>
|
||
<h2 id="focused-canary-testing">聚焦金丝雀测试</h2>
|
||
<p>如上所述,Istio 路由规则可用于根据特定规则准进行流量路由,从而能够提供更复杂的金丝雀部署方案。例如,与简单通过将金丝雀版本暴露给任意百分比的用户方式不同,我们希望在内部用户上尝试,甚至可能只是内部用户的一部分。</p>
|
||
<p>以下命令可将特定网站上 50% 的用户流量路由到金丝雀版本,而其他用户则不受影响:</p>
|
||
<pre><code class='language-bash' data-expandlinks='true' data-repo='istio' >$ kubectl apply -f - &lt;&lt;EOF
|
||
apiVersion: networking.istio.io/v1alpha3
|
||
kind: VirtualService
|
||
metadata:
|
||
name: helloworld
|
||
spec:
|
||
hosts:
|
||
- helloworld
|
||
http:
|
||
- match:
|
||
- headers:
|
||
cookie:
|
||
regex: &#34;^(.*?;)?(email=[^;]*@some-company-name.com)(;.*)?$&#34;
|
||
route:
|
||
- destination:
|
||
host: helloworld
|
||
subset: v1
|
||
weight: 50
|
||
- destination:
|
||
host: helloworld
|
||
subset: v2
|
||
weight: 50
|
||
- route:
|
||
- destination:
|
||
host: helloworld
|
||
subset: v1
|
||
EOF
|
||
</code></pre>
|
||
<p>和以前一样,绑定到 2 个版本 Deployment 的自动缩放器会相应地自动管理副本,但这对流量分配没有影响。</p>
|
||
<h2 id="summary">总结</h2>
|
||
<p>本文中,我们看到了 Istio 如何支持通用可扩展的金丝雀部署,以及与 Kubernetes 部署的差异。Istio 服务网格提供了管理流量分配所需的基础控制,并完全独立于部署缩放。这允许简单而强大的方式来进行金丝雀测试和上线。</p>
|
||
<p>支持金丝雀部署的智能路由只是 Istio 的众多功能之一,它将使基于大型微服务的应用程序的生产部署变得更加简单。查看 <a href="/v1.12/zh/">istio.io</a> 了解更多信息。</p>
|
||
<p>可在<a href="https://github.com/istio/istio/tree/release-1.12/samples/helloworld">此处</a>查看示例代码。</p></description><pubDate>Wed, 14 Jun 2017 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2017/0.1-canary/</link><author>Frank Budinsky</author><guid isPermaLink="true">/v1.12/zh/blog/2017/0.1-canary/</guid><category>traffic-management</category><category>canary</category></item><item><title>使用 Istio 增强端到端安全</title><description>
|
||
<p>传统的网络安全方式无法解决部署在动态变化环境下分布式应用的安全威胁。这里,我们将描述 Istio Auth 如何帮助企业将其安全从边界保护转变为内部所有服务间通信保护。使用 Istio Auth 开发人员和运维人员可以在不改动程序代码的情况下,对于敏感数据进行保护,防止未经授权的内部人员访问。</p>
|
||
<p>Istio Auth 是更广泛的 <a href="/v1.12/zh">Istio 平台</a>的安全组件。它结合了 Google 生产环境中保护数百万微服务安全的经验。</p>
|
||
<h2 id="background">背景知识</h2>
|
||
<p>现代应用程序体系结构越来越多地基于共享服务,共享服务部署在云平台上,可被方便地进行动态部署和扩容。传统的网络边界安全性(例如防火墙)控制力度太粗,会导致部分非预期的客户端访问。使用盗取合法客户端的认证令牌进行重放攻击,就是一种常见的安全风险。对于持有敏感数据公司而言,内部威胁是一个需要关注的主要风险。其他网络安全方法(如 IP 白名单)通过静态方式定义,难以大规模管理,不适合动态变化的生产环境。</p>
|
||
<p>因此,安全管理员需要一种工具,其可以能够默认开启并且始终保护生产环境中服务间的所有通信。</p>
|
||
<h2 id="solution-strong-service-identity-and-authentication">解决方案:增强的服务身份和验证</h2>
|
||
<p>多年来,Google 通过研发架构和技术,帮助其生产环境中数百万个微服务抵御了外部攻击和内部威胁。关键安全原则包括信任端而不是网络,基于服务身份和级别授权的双向强身份验证。Istio Auth 基于相同的原则。</p>
|
||
<p>Istio Auth 服务 0.1 版本在 Kubernetes 上运行,并提供以下功能:</p>
|
||
<ul>
|
||
<li><p>服务间强身份认证</p></li>
|
||
<li><p>访问控制以限制可以访问服务(及其数据)的身份</p></li>
|
||
<li><p>传输中的数据自动加密</p></li>
|
||
<li><p>密钥和证书的大规模管理</p></li>
|
||
</ul>
|
||
<p>Istio Auth 基于双向 TLS 和 X.509 等行业标准。此外,Google 还积极参与一个开放的,社区驱动的 <a href="https://spiffe.io/">SPIFFE</a> 服务安全框架。随着 <a href="https://spiffe.io/">SPIFFE</a> 规范的成熟,我们打算让 Istio 安全验证参考并实现。</p>
|
||
<p>下图描述了 Kubernetes 上 Istio Auth 服务的体系结构。</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:56.25%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2017/0.1-auth/istio_auth_overview.svg" title="Istio Auth 概览">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2017/0.1-auth/istio_auth_overview.svg" alt="Istio Auth 概览" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio Auth 概览</figcaption>
|
||
</figure>
|
||
<p>上图说明了三个关键的安全功能:</p>
|
||
<h3 id="strong-identity">强身份认证</h3>
|
||
<p>Istio Auth 使用了 <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/">Kubernetes 服务帐户</a>来识别服务运行的身份。身份用于建立信任和定义服务级别访问策略。身份在服务部署时分配,并在 X.509 证书的 SAN(主题备用名称)字段中进行编码。使用服务帐户作为身份具有以下优点:</p>
|
||
<ul>
|
||
<li><p>管理员可以使用 Kubernetes 1.6 中引入的 <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/">RBAC</a> 功能配置谁有权访问服务帐户</p></li>
|
||
<li><p>灵活地识别人类用户,服务或一组服务</p></li>
|
||
<li><p>稳定地支持服务身份的动态配置和工作负载自动扩展</p></li>
|
||
</ul>
|
||
<h3 id="communication-security">通信安全</h3>
|
||
<p>服务间通信基于高性能客户端和服务器端 <a href="https://envoyproxy.github.io/envoy/">Envoy</a> 代理的传输隧道。代理之间的通信使用双向 TLS 来进行保护。使用双向 TLS 的好处是服务身份不会被替换为从源窃取或重放攻击的令牌。Istio Auth 还引入了安全命名的概念,以防止服务器欺骗攻击 - 客户端代理验证允许验证特定服务的授权的服务帐户。</p>
|
||
<h3 id="key-management-and-distribution">密钥管理和分配</h3>
|
||
<p>Istio Auth 为每个集群提供 CA(证书颁发机构),并可对密钥和证书自动管理。这种情况下,Istio Auth 具备以下功能 :</p>
|
||
<ul>
|
||
<li><p>为每个服务帐户生成密钥和证书对。</p></li>
|
||
<li><p>使用 <a href="https://kubernetes.io/docs/concepts/configuration/secret/">Kubernetes Secrets</a> 将密钥和证书分发到相应的 pod。</p></li>
|
||
<li><p>定期轮换密钥和证书。</p></li>
|
||
<li><p>必要时(未来)撤销特定密钥和证书对。</p></li>
|
||
</ul>
|
||
<p>下图说明了 Kubernetes 上的端到端 Istio Auth 工作流程:</p>
|
||
<figure style="width:100%">
|
||
<div class="wrapper-with-intrinsic-ratio" style="padding-bottom:56.25%">
|
||
<a data-skipendnotes="true" href="/v1.12/zh/blog/2017/0.1-auth/istio_auth_workflow.svg" title="Istio Auth 工作流程">
|
||
<img class="element-to-stretch" src="/v1.12/zh/blog/2017/0.1-auth/istio_auth_workflow.svg" alt="Istio Auth 工作流程" />
|
||
</a>
|
||
</div>
|
||
<figcaption>Istio Auth 工作流程</figcaption>
|
||
</figure>
|
||
<p>Istio Auth 是更广泛的容器安全中的一部分。Red Hat 是 Kubernetes 开发的合作伙伴,定义了 <a href="https://www.redhat.com/en/resources/container-security-openshift-cloud-devops-whitepaper">10 层</a>容器安全。Istio 和 Istio Auth 解决了其中两个层:”网络隔离” 和 “API 和服务端点管理”。随着集群联邦在 Kubernetes 和其他平台上的发展,我们的目的是让 Istio 对跨越多个联邦集群的服务间通信提供保护。</p>
|
||
<h2 id="benefits-of-Istio-authentication">Istio Auth 的优点</h2>
|
||
<p><strong>深度防御</strong>:当与 Kubernetes(或基础架构)网络策略结合使用时,用户可以获得更多的安全信心,因为他们知道 Pod 或服务间的通信在网络层和应用层上都得到保护。</p>
|
||
<p><strong>默认安全</strong>:当与 Istio 的代理和集中策略引擎一起使用时,可在极少或不更改应用的情况下部署并配置 Istio Auth 。因此,管理员和操作员可以确保默认开启服务通信保护,并且可以跨协议和运行时一致地实施这些策略。</p>
|
||
<p><strong>强大的服务认证</strong>:Istio Auth 使用双向 TLS 保护服务通信,以确保服务身份不会是其他来源窃取或重放攻击的令牌。这可确保只能从经过严格身份验证和授权的客户端才能够访问具有敏感数据的服务。</p>
|
||
<h2 id="join-us-in-this-journey">加入我们</h2>
|
||
<p>Istio Auth 是提供完整安全功能的第一步,安全功能可以用于抵御外部攻击和内部威胁,保护服务的敏感数据。虽然初始版本仅在 Kubernetes 上运行,但我们的目标是使其能够在不同的生产环境中保护服务通信。我们鼓励更多的社区<a href="https://github.com/istio/istio/tree/release-1.12/security">加入我们</a>,为不同的应用技术栈和运行平台上轻松地提供强大的服务安全保障。</p></description><pubDate>Thu, 25 May 2017 00:00:00 +0000</pubDate><link>/v1.12/zh/blog/2017/0.1-auth/</link><author>The Istio Team</author><guid isPermaLink="true">/v1.12/zh/blog/2017/0.1-auth/</guid></item></channel></rss> |