<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>istio | 伪架构师</title>
    <link>/tags/istio/</link>
      <atom:link href="/tags/istio/index.xml" rel="self" type="application/rss+xml" />
    <description>istio</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Sat, 06 Aug 2022 21:53:29 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>istio</title>
      <link>/tags/istio/</link>
    </image>
    
    <item>
      <title>在 Istio 中合并监控指标</title>
      <link>/post/merge-metrics-in-istio/</link>
      <pubDate>Sat, 06 Aug 2022 21:53:29 +0800</pubDate>
      <guid>/post/merge-metrics-in-istio/</guid>
      <description>&lt;p&gt;前些天阅读 Istio 文档的时候发现个语焉不详的东西：&lt;a href=&#34;https://istio.io/latest/docs/ops/integrations/prometheus/#option-1-metrics-merging&#34; target=&#34;_blank&#34;&gt;Metrics Merging&lt;/a&gt;，原文如下：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This option is enabled by default but can be disabled by passing &amp;ndash;set meshConfig.enablePrometheusMerge=false during installation. When enabled, appropriate prometheus.io annotations will be added to all data plane pods to set up scraping. If these annotations already exist, they will be overwritten. With this option, the Envoy sidecar will merge Istio’s metrics with the application metrics. The merged metrics will be scraped from /stats/prometheus:15020.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;大致翻译一下：这是一个缺省开放的功能，可以在安装时用 &lt;code&gt;--set meshConfig.enablePrometheusMerge=false&lt;/code&gt; 参数停用这个功能。这个功能启用后，相对应的 &lt;code&gt;prometheus.io&lt;/code&gt; 注解就会被加入到所有数据面 Pod 上，以启用 Prometheus 的指标抓取能力。如果这些注解已经存在，那么就会被覆盖。有了这样的功能，Envoy Sidecar 就会把应用指标和 Istio 指标进行合并，Prometheus 可以从 &lt;code&gt;:15020/stats/prometheus&lt;/code&gt; 拉取合并后的指标。&lt;/p&gt;

&lt;p&gt;看完之后，一头雾水。翻翻代码看到另一番说辞：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;applyPrometheusMerge configures prometheus scraping annotations for the &amp;ldquo;metrics merge&amp;rdquo; feature. This moves the current prometheus.io annotations into an environment variable and replaces them pointing to the agent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这段代码实现了指标合并功能。它会把当前的 &lt;code&gt;prometheus.io&lt;/code&gt; 注解保存到环境变量之中，并且将原有注解替换为指向 Agent 的内容。&lt;/p&gt;

&lt;p&gt;再结合相关代码，大概可以推断其功能大致如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;网格化微服务在网格化之前使用 &lt;code&gt;prometheus.io&lt;/code&gt; 注解标注的抓取方法，会被保存到 Sidecar 的环境变量之中；&lt;/li&gt;
&lt;li&gt;合并指标功能，能够将被网格劫持的微服务输出的 Promethues 指标和 Sidecar 自身指标进行合并，输出到 &lt;code&gt;:15020/stats/prometheus&lt;/code&gt; 端点，供 Prometheus 拉取。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我们用 Python 的 &lt;a href=&#34;https://github.com/prometheus/client_python#custom-collectors&#34; target=&#34;_blank&#34;&gt;Prometheus Exporter SDK&lt;/a&gt; 中的测试代码做一个示例应用，并使用如下 Dockerfile 进行打包：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-dockerfile&#34;&gt;FROM python:3.9.13-slim-buster
RUN pip install prometheus-client &amp;amp;&amp;amp; mkdir app
COPY server.py /app/server.py
WORKDIR /app
EXPOSE 8000
CMD [ &amp;quot;python3&amp;quot;, &amp;quot;server.py&amp;quot; ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用 Docker 运行一下，可以看到他输出的简单指标：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ docker run -p 8000:8000 dustise/promclient:v0.1
Unable to find image &#39;dustise/promclient:v0.1&#39; locally
v0.1: Pulling from dustise/promclient
...
Status: Downloaded newer image for dustise/promclient:v0.1
$ curl http://127.0.0.1:8000
...
# HELP request_processing_seconds_created Time spent processing request
# TYPE request_processing_seconds_created gauge
request_processing_seconds_created 1.6597804647800276e+09
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会看到指标中是一些请求相关和 Python 特定的内容，这正像我们一个提供了监控指标的微服务，那么如何将这些“业务”指标和 Sidecar 合并输出呢？根据上文，需要加上 Prometheus 的注解，因此我们准备这样一个 YAML：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: apps/v1
kind: Deployment
...
  template:
    metadata:
...
      annotations:
        prometheus.io/path: /
        prometheus.io/port: 8000
        prometheus.io/scrape: true
    spec:
...
---
apiVersion: v1
kind: Service
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;注入 Sidecar 并提交到集群：&lt;code&gt;istioctl kube-inject -f promclient.yaml | kubectl apply -f  -&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;成功后，可以看看新 Pod 是不是发生了像文档所说的变化：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl describe po promclient-6c74596f4f-r5z29 | grep prometheus.io
              prometheus.io/path: /stats/prometheus
              prometheus.io/port: 15020
              prometheus.io/scrape: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看到我们原有的注解的确被替换为缺省内容，那原有内容是不是出现在环境变量之中？&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it [pod] -c istio-proxy -- env |  | grep ANNO
ISTIO_PROMETHEUS_ANNOTATIONS={&amp;quot;scrape&amp;quot;:&amp;quot;true&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/&amp;quot;,&amp;quot;port&amp;quot;:&amp;quot;8000&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;果然出现在这里了。那么指标是否完成合并了？采集一下 Pod 的 15020 端口：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ http 10.52.1.11:15020/stats/prometheus | grep python | more
# HELP python_gc_objects_collected_total Objects collected during gc
# TYPE python_gc_objects_collected_total counter
python_gc_objects_collected_total{generation=&amp;quot;0&amp;quot;} 101.0
python_gc_objects_collected_total{generation=&amp;quot;1&amp;quot;} 273.0
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，指标已经被合并到了 Sidecar 指标中之中。&lt;/p&gt;

&lt;p&gt;方法固然简单，还是存在一些不适用的场景，例如：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;用 mTLS 抓取指标&lt;/li&gt;
&lt;li&gt;应用指标和 Sidecar 指标重名&lt;/li&gt;
&lt;li&gt;Prometheus 未配置按照标准注解进行抓取&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;遇到上述问题，可能就需要关掉合并功能，采用自定义抓取的方式了。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istiod——回到单体的理由</title>
      <link>/post/istio-when-not-microservice/</link>
      <pubDate>Sat, 11 Jan 2020 20:59:19 +0800</pubDate>
      <guid>/post/istio-when-not-microservice/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://blog.christianposta.com/microservices/istio-as-an-example-of-when-not-to-do-microservices/&#34; target=&#34;_blank&#34;&gt;Istio as an Example of When Not to Do Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;http://twitter.com/christianposta&#34; target=&#34;_blank&#34;&gt;Christian Posta&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;近五年来，我尽心尽力帮助各种组织踏入云原生之路。要让团队变得现代化并增强基于软件的产品的交付能力，人、过程以及技术决策都很重要。当应用架构的上限已经成为应对变化和加速发展的瓶颈时，微服务方法可能是合适的，但这并不是唯一的方法。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;微服务并非应用架构的乌托邦。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;过去，我在这方面发表了一些看法，例如我认为很多团队无法将其落地，实现过程中的困难之处，还提出了一些长远来看会对这项工作有益处的技术。甚至还写了一本书来讲述这一主题。&lt;/p&gt;

&lt;p&gt;尽管很多组织已经踏上微服务之旅，&lt;a href=&#34;https://blog.christianposta.com/microservices/when-not-to-do-microservices/&#34; target=&#34;_blank&#34;&gt;远离微服务&lt;/a&gt;一文仍然可能是个好起点。&lt;/p&gt;

&lt;h2 id=&#34;如果你已经踏上了微服务旅程&#34;&gt;如果你已经踏上了微服务旅程&lt;/h2&gt;

&lt;p&gt;如果发现微服务不灵，就该正视现实。拨乱反正是做出成功产品的正确举措。&lt;/p&gt;

&lt;p&gt;尽管出发点是好的，但开始使用微服务之后，开倒车还是有可能的。如果之前的假设或周遭环境已经发生了变化，重回单体架构也是可以理解的。&lt;/p&gt;

&lt;p&gt;为微服务通信构建服务网格的 Istio 社区，控制平面的实现将&lt;a href=&#34;https://docs.google.com/document/d/1v8BxI07u-mby5f5rCruwF7odSXgb9G8-C9W5hQtSIAg/edit#&#34; target=&#34;_blank&#34;&gt;最终从微服务架构转向更为单体的方式&lt;/a&gt;。Google API 基础设施的首席工程师和架构师 &lt;a href=&#34;https://twitter.com/louiscryan?lang=en&#34; target=&#34;_blank&#34;&gt;Louis Ryan&lt;/a&gt;，在 2019 年 KubeConNA 上讲述了这一变化的动机，并在&lt;a href=&#34;https://docs.google.com/document/d/1v8BxI07u-mby5f5rCruwF7odSXgb9G8-C9W5hQtSIAg/edit#&#34; target=&#34;_blank&#34;&gt;设计文档&lt;/a&gt;中进行了阐述。从 Istio 1.5 开始（可能会在 2020 年 2 月中旬），我们可能就会看到 &lt;code&gt;istiod&lt;/code&gt; 了，这个组件把前作中多个组件集成为单一进程。&lt;/p&gt;

&lt;p&gt;Istio 用于解决因为微服务、云原生架构引入的复杂的应用网络问题，所以为什么 Istio 自身却反其道而行之？最直接答案是：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;事实证明，微服务的复杂性无法实现其预期的价值或目标。相反，它违背了这些目标。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;对于 Istio 项目来说，似乎单体方式能更好的为目标服务。&lt;/p&gt;

&lt;h2 id=&#34;微服务模式的-istio&#34;&gt;微服务模式的 Istio&lt;/h2&gt;

&lt;p&gt;Istio 是一个开源的服务网格产品，其实现和其它同类产品大同小异，由控制平面和数据平面组成。数据平面由反向代理服务器组成，这些反向代理和各个应用实例伴行，并替代应用行使通信职责。控制平面在请求路径之外，用于对数据平面的行为进行管控。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/istio-cp-jan2020.png&#34; alt=&#34;istio-overview&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Istio 的控制平面分为几个组成部分，其职责如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pilot&lt;/code&gt;：核心的数据平面配置（xDS）服务器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Galley&lt;/code&gt;：配置监听、验证和转发。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Injector&lt;/code&gt;：负责数据平面的注册和初始化。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Citadel&lt;/code&gt;：证书签发、Secret 生成、CA 集成等。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Telemetry&lt;/code&gt;：&lt;code&gt;Mixer&lt;/code&gt; 组件之一，负责聚合监控信息到多种后端。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Policy&lt;/code&gt;：&lt;code&gt;Mixer&lt;/code&gt; 组件之二，在请求路径之中负责实现策略支持。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;运维人员通过一组配置指令来借由这些部件为数据平面提供服务并对其进行控制。&lt;/p&gt;

&lt;h2 id=&#34;微服务的好处&#34;&gt;微服务的好处&lt;/h2&gt;

&lt;p&gt;微服务能够降低变更过程中因为耦合产生的冲突，因此能加快组织的调整速度。有了微服务架构的帮助，每个服务都能可以有自己的团队，独立进行运维，有各自的变更频率和生命周期。这使得开发和运维能够轻装上阵，不会因为变更过程中的锁定、同步、协作等问题拖慢部署和变更的进度。&lt;/p&gt;

&lt;p&gt;拆分成微服务的另一个原因就是它的用法和扩展方式。例如一个需要大量读写的服务，能从读写分离上受益，这是因为读取过程需要更多内存（缓存），而写入需要更多的存储或者网络资源。拆分之后就可以放心的给读取服务分配大量内存，而写入服务则可以运行在 SSD 或者 EBS/SAN 等设施加持的服务器上。&lt;/p&gt;

&lt;p&gt;拆分微服务的另外几个理由：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;安全考虑&lt;/li&gt;
&lt;li&gt;领域分隔&lt;/li&gt;
&lt;li&gt;针对不同语言的优化&lt;/li&gt;
&lt;li&gt;安全分级&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;微服务架构的复杂性是第一号问题。当单体应用拆分为一些互相通信的小玩意之后，架构的复杂性以及对应的基础设施的复杂性都显而易见地提高了。&lt;/p&gt;

&lt;p&gt;除非已经清楚的意识到，这是为了获得更多好处，而做出的一种必要的妥协；否则就应该对假设进行评估，并及时做出反应——这就是 Istio 现在的举措。&lt;/p&gt;

&lt;h2 id=&#34;回头草&#34;&gt;回头草&lt;/h2&gt;

&lt;p&gt;首先要清楚，你的服务是谁开发谁运维的。在 Istio 社区，项目里不同的&lt;a href=&#34;https://github.com/istio/community/blob/master/WORKING-GROUPS.md&#34; target=&#34;_blank&#34;&gt;工作组&lt;/a&gt;维持着不同的组件。另一方面，下载、安装和运维 Istio 的用户就不那么清楚了。目前看来，都是由单一的工作组（甚至一个人）在操作 Istio 的控制平面。某种程度上，一组微服务构建的 Istio 控制平面更适合被当做一个更大规模的 SaaS 看待，但是目前的情况看来并非如此。&lt;/p&gt;

&lt;p&gt;第二个需要注意的就是部署问题。这些微服务能独自部署么？Istio 的回答是：理论上可以，但实际上可能并非如此。当新版本 Istio 发布时，需要更新/部署所有控制平面的组件。&lt;/p&gt;

&lt;p&gt;最后一个问题：”Istio 的各个组件，有各自不同的安全考量和伸缩需求吗？“，答案也并不肯定。来自 &lt;code&gt;istiod&lt;/code&gt; 的一段陈述：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;目前看来，对于多数组件来说并非如此。然而——控制平面的成本由单一的功能（xDS）决定。相对而言，其它所有组件的消耗微不足道，因此分离并无必要。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;为了安全起见，所有的控制平面都处于相同的特权级别：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;当前的情况下，Mutating Webhook、Envoy Bootstrap 以及 Pilot，这几个组件的特权级别和 Citadel 基本持平，对它们的滥用所引发的损失几乎相同。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Istio 设计文档中的潜台词就是——“复杂性是万恶之源，或者换个说法：停止焦虑，爱上单体”。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istiod&lt;/code&gt; 是一个单体应用，它用较低的复杂性提供了和之前版本一致的功能。组成旧版控制平面的服务都还以子模块的方式存在于项目之中，但提供了更好的运维体验。操作者只需关注单一二进制文件的运行和升级了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/istiod.png&#34; alt=&#34;istiod&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Istio 一旦转向单体的控制平面，会大幅降低复杂性，从而：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;只需要对一个单独的服务进行部署和升级。&lt;/li&gt;
&lt;li&gt;因为无需关注编排服务自身的配置，因此配置复杂度也降低了。&lt;/li&gt;
&lt;li&gt;更容易除错。&lt;/li&gt;
&lt;li&gt;提高分发、共享和缓存的效率，降低开销。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;另外你可以看一下 &lt;a href=&#34;https://www.youtube.com/watch?v=QD115XiBXwY&#34; target=&#34;_blank&#34;&gt;Istiod 的 Demo 视频&lt;/a&gt;。这个视频基于一个早期版本，因此并不完善。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;很高兴看到 Istio 社区在持续提高其易用性和可运维性。转向单体应用的 Istio 带来了很多好处。这个过程会对你的项目产生什么启发么？如果有的话，你会采取什么措施么？&lt;/p&gt;

&lt;h2 id=&#34;相关链接&#34;&gt;相关链接&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Istio设计文档：&lt;code&gt;https://docs.google.com/document/d/1v8BxI07u-mby5f5rCruwF7odSXgb9G8-C9W5hQtSIAg/edit#&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Istiod 的 Demo 视频：&lt;code&gt;https://www.youtube.com/watch?v=QD115XiBXwY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;远离微服务：&lt;code&gt;https://blog.christianposta.com/microservices/when-not-to-do-microservices/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>istioctl 中的一些小工具</title>
      <link>/post/istioctl-tips/</link>
      <pubDate>Tue, 03 Dec 2019 19:38:20 +0800</pubDate>
      <guid>/post/istioctl-tips/</guid>
      <description>

&lt;h2 id=&#34;引子&#34;&gt;引子&lt;/h2&gt;

&lt;p&gt;许久不见，&lt;code&gt;istioctl&lt;/code&gt; 中加入了不少有趣的新命令。装备党自然是喜欢小工具了，选几个有趣的命令分享给大家。&lt;/p&gt;

&lt;h2 id=&#34;analyze&#34;&gt;Analyze&lt;/h2&gt;

&lt;p&gt;Istio 的配置是比较繁杂的，相信玩过的朋友都比较有体会，
&lt;a href=&#34;https://istio.io/docs/reference/commands/istioctl/#istioctl-experimental-analyze&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;istioctl x analyze&lt;/code&gt;&lt;/a&gt;，可以对 Istio 进行一些检查，&lt;/p&gt;

&lt;p&gt;目前该工具支持的检测范围包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IST0001：内部错误，基本上是属于实现部分的 Bug。&lt;/li&gt;
&lt;li&gt;IST0002：对象中存在过期特性。&lt;/li&gt;
&lt;li&gt;IST0101：应用对象不存在，例如有 VirtualService 无 Workload。&lt;/li&gt;
&lt;li&gt;IST0102：命名空间未开启自动注入。&lt;/li&gt;
&lt;li&gt;IST0103：有 Pod 没有注入 Istio Proxy。&lt;/li&gt;
&lt;li&gt;IST0104：网关端口没有工作负载。&lt;/li&gt;
&lt;li&gt;IST0105：Sidecar 版本和 Istio 版本不一致。&lt;/li&gt;
&lt;li&gt;IST0106：文件格式错误。&lt;/li&gt;
&lt;li&gt;IST0107：注解目标错误。&lt;/li&gt;
&lt;li&gt;IST0108：未知注解。&lt;/li&gt;
&lt;li&gt;IST0109：网关内 VirtualService 主机名冲突。&lt;/li&gt;
&lt;li&gt;IST0110：Sidecar 对象选择器重叠。&lt;/li&gt;
&lt;li&gt;IST0111：多于一个 Sidecar 对象没有负载选择器。&lt;/li&gt;
&lt;li&gt;IST0112：多端口服务的 VirtualService 缺乏选择。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ istioctl x analyze -k
Warn [IST0103] (Pod httpbin-7d9d5b55b9-jslpp.default) The pod is missing its Istio proxy. Run &#39;kubectl delete pod httpbin-
7d9d5b55b9-jslpp -n default&#39; to restart it
Error: Analyzer found issues.
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h2&gt;

&lt;p&gt;可能是向 Linkerd 致敬？&lt;/p&gt;

&lt;p&gt;打开 Istio 的各种仪表盘页面：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;controlz：打开指定控制平面组件的 &lt;code&gt;ctrlz&lt;/code&gt; 界面。&lt;/li&gt;
&lt;li&gt;envoy：打开特定 Pod 的 Envoy 仪表盘&lt;/li&gt;
&lt;li&gt;grafana：缺省 Grafana 页面&lt;/li&gt;
&lt;li&gt;jaeger、kiali、zipkin 和 Prometheus 页面&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;metrics&#34;&gt;Metrics&lt;/h2&gt;

&lt;p&gt;查看指定服务的性能指标：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;总体 RPS&lt;/li&gt;
&lt;li&gt;错误 RPS&lt;/li&gt;
&lt;li&gt;P50 延迟&lt;/li&gt;
&lt;li&gt;P90 延迟&lt;/li&gt;
&lt;li&gt;P99 延迟&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;manifest&#34;&gt;Manifest&lt;/h2&gt;

&lt;p&gt;用于生成或安装 Istio 清单，例如推荐的安装方式：&lt;code&gt;istioctl manifest apply --set profile=demo&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;profile&#34;&gt;Profile&lt;/h2&gt;

&lt;p&gt;几个内置的安装配置，用于 Manifest 命令的 &lt;code&gt;set profile&lt;/code&gt;，其中包含：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;minimal&lt;/li&gt;
&lt;li&gt;remote&lt;/li&gt;
&lt;li&gt;sds&lt;/li&gt;
&lt;li&gt;default&lt;/li&gt;
&lt;li&gt;demo&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;describe&#34;&gt;Describe&lt;/h2&gt;

&lt;p&gt;根据 Pod 和 Service，获取相关的配置内容，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ istioctl x describe service httpbin
Service: httpbin
   Port: http 8000/HTTP targets pod port 80
Pod is PERMISSIVE, client protocol unspecified
VirtualService: httpbin
   1 HTTP route(s)
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Envoy 和 Istio 的 6.18</title>
      <link>/post/envoy-and-istio-on-6-18/</link>
      <pubDate>Wed, 19 Jun 2019 18:24:32 +0800</pubDate>
      <guid>/post/envoy-and-istio-on-6-18/</guid>
      <description>

&lt;p&gt;地球对面的时间比我们这里晚一点，我们的 618 已经开始返场了，他们还在 618。&lt;/p&gt;

&lt;p&gt;服务网格方面，在这一天有了两个发布：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://eng.lyft.com/announcing-envoy-mobile-5c2067d9ade0&#34; target=&#34;_blank&#34;&gt;Envoy 发布了移动版&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/about/notes/1.2/&#34; target=&#34;_blank&#34;&gt;Istio 发布了 1.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;envoy-mobile&#34;&gt;Envoy Mobile&lt;/h2&gt;

&lt;p&gt;Envoy Mobile 是一个库，目的是可以直接将 Envoy 的功能封装到移动应用之中，&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;跨平台的底层网络支持：HTTP/2、QUIC、gRPC、推送、流、重试和超时策略等底层网络技术的实现以及跨平台都是需要付出大量努力来完成的事情，Evnoy Mobile 试图在客户端以一致的跨平台的方式提供这所有功能。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;xDS 支持：Envoy 的最深套路就是 xDS 了，Envoy 一旦潜入移动应用，就可以通过 xDS 的方式，在服务端对客户端的网络行为作出控制。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;API 的高级支持：用注解方式为 API 提供缓存、优先级等支持&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这个项目还非常早期，但是我觉得非常有意思，强悍的 Envoy 用这种方式为移动应用提供了一个可控的网络抽象的能力，目前已经提供了 Java、Swift、OC 等支持，这会不会成为一种新的边缘能力？&lt;/p&gt;

&lt;h2 id=&#34;istio-1-2&#34;&gt;Istio 1.2&lt;/h2&gt;

&lt;p&gt;补丁版本，没啥好说。&lt;/p&gt;

&lt;h2 id=&#34;参考链接&#34;&gt;参考链接&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;https://docs.google.com/document/d/1N0ZFJktK8m01uqqgfDRVB9mpC1iEn9dqkQaa_yMn_kE/edit#&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;https://istio.io/about/notes/1.2/&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;https://eng.lyft.com/announcing-envoy-mobile-5c2067d9ade0&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Istio：503、UC 和 TCP</title>
      <link>/post/istio-503-uc-debug/</link>
      <pubDate>Tue, 04 Jun 2019 16:53:52 +0800</pubDate>
      <guid>/post/istio-503-uc-debug/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://karlstoney.com/2019/05/31/istio-503s-ucs-and-tcp-fun-times/index.html&#34; target=&#34;_blank&#34;&gt;Istio: 503&amp;rsquo;s with UC&amp;rsquo;s and TCP Fun Times
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://karlstoney.com/&#34; target=&#34;_blank&#34;&gt;Karlstoney.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最近 AutoTrader 在调试一个有些复杂的问题，这一过程得到了 Istio 团队的很多帮助。这个问题现在已经基本得到了解决，这一过程中采取的一些措施可能对其他用户有所启发，因此有了本文。&lt;/p&gt;

&lt;h2 id=&#34;问题&#34;&gt;问题&lt;/h2&gt;

&lt;p&gt;我们注意到有些请求在第一次尝试的时候会失败，Istio 会自动进行重试，然后就成功了。在 Jaeger 中观察可以看到：第一个请求是 503 状态，&lt;code&gt;response_flags&lt;/code&gt; 为 &lt;code&gt;UC&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/Screenshot-2019-05-31-at-18.21.52.png&#34; alt=&#34;jaeger&#34; /&gt;&lt;/p&gt;

&lt;p&gt;如果你在关注或者正在使用 Istio，你可能会看到&lt;a href=&#34;https://github.com/istio/istio/issues/13848&#34; target=&#34;_blank&#34;&gt;很多千奇百怪的 503&lt;/a&gt;。目前 503 的主要问题就是，它太模糊了。&lt;/p&gt;

&lt;p&gt;看看这个简单的例子：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/simple-app.png&#34; alt=&#34;simple app&#34; /&gt;&lt;/p&gt;

&lt;p&gt;基本上，应用 2 的 Envoy 和应用通信过程中的任何问题都会被包裹成 503，发送回上游，然后上游就会进行重试。&lt;/p&gt;

&lt;p&gt;不管怎样，有了 Istio，重试并不是世界末日。Istio 检测到故障后进行重试，然后给上游返回了成功信息。然而值得注意的是，故障总会发生，我们应该面向故障进行应用的构建。我们的应用跨越多个 AZ，出现这种奇怪的问题，会有很多可能的错误源头。&lt;/p&gt;

&lt;p&gt;我们观察到，大概 0.012% 的请求发生了这种问题。我们的应用是一种微服务架构，这一种故障和 5 个应用相关，这样会看到 0.08% 的聚合请求失败率，（稳定的故障率）表明，这并非是偶然情况。&lt;/p&gt;

&lt;p&gt;当你开始考虑这一故障时，会注意到 Sidecar 模型增加了应用通信过程的复杂度，这就是网格的代价之一。&lt;/p&gt;

&lt;p&gt;回忆一下没有服务网格的世界，&lt;code&gt;consumer-gateway&lt;/code&gt; 管理一个通往 &lt;code&gt;sauron-seo-app&lt;/code&gt; 的连接池。然而有了服务网格，我们其实有了三个各行其是的连接池，各有各的配置：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/pools.png&#34; alt=&#34;pools&#34; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;consumer-gateway&lt;/code&gt; 到 &lt;code&gt;source-envoy&lt;/code&gt; ：Java 代码。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;source envoy&lt;/code&gt; 到 &lt;code&gt;destination envoy&lt;/code&gt;：&lt;a href=&#34;https://istio.io/docs/reference/config/networking/v1alpha3/destination-rule/#ConnectionPoolSettings&#34; target=&#34;_blank&#34;&gt;DestinationRule&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;destination envoy&lt;/code&gt; 到 &lt;code&gt;sauron-seo-app&lt;/code&gt;：在 Envoy 中进行配置，Istio 对其配置并无掌控。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这中间有很多出问题的机会，要查找根本原因，也有很大的排查范围。因此我们对真实场景中这一问题的应对方法进行回顾。&lt;/p&gt;

&lt;h2 id=&#34;指标&#34;&gt;指标&lt;/h2&gt;

&lt;h3 id=&#34;istio&#34;&gt;Istio&lt;/h3&gt;

&lt;p&gt;Istio 搜集了很多的指标，能帮我们凸显问题。Istio 提供的这种水平的可观测性很有趣，能能够凸显你之前发现的问题。这很直白，所以打开 Prometheus 并输入：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sort_desc(sum(changes(istio_requests_total{response_flags=&amp;quot;UC&amp;quot;, response_code=&amp;quot;503&amp;quot;, reporter=&amp;quot;destination&amp;quot;}[24h])) by (source_app, destination_app, reporter) &amp;gt;0)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这段指标的含义是：最近 24 小时内，状态为 503 并且被标记为 UC（上游连接问题），使用 &lt;code&gt;source_app&lt;/code&gt;、 &lt;code&gt;destination_app&lt;/code&gt; 以及 &lt;code&gt;reporter&lt;/code&gt; 进行汇总。&lt;/p&gt;

&lt;p&gt;注意：上图中，&lt;code&gt;reporter=source&lt;/code&gt; 就是来自于源 Envoy，而 &lt;code&gt;reporter=destination&lt;/code&gt; 就是目标 Envoy。&lt;/p&gt;

&lt;p&gt;所以看看我得出的结果，&lt;code&gt;{destination_app=&amp;quot;sauron-seo-app&amp;quot;,reporter=&amp;quot;destination&amp;quot;,source_app=&amp;quot;consumer-gateway&amp;quot;} 58&lt;/code&gt;，这代表过去 24 小时里，从 &lt;code&gt;consumer-gateway&lt;/code&gt; 到 &lt;code&gt;sauron-seo-app&lt;/code&gt; 的请求中有 58 个出了问题，得到了 &lt;code&gt;503UC&lt;/code&gt; 的结果，这一情况是由 &lt;code&gt;sauron-seo-app&lt;/code&gt; 的 Envoy 汇报而来。&lt;/p&gt;

&lt;p&gt;我们知道了，我们在目标一端发生了问题，这也跟前面的跟踪过程中得到的结论是一致的：源服务尝试了一个不同的目标并获得成功。我们来检查一下 Envoy 发生了什么事。&lt;/p&gt;

&lt;h3 id=&#34;envoy&#34;&gt;Envoy&lt;/h3&gt;

&lt;p&gt;我们要做的下一件事就是启用一些指标，帮助我们对 Envoy 进行排查。缺省情况下 &lt;code&gt;istio-proxy&lt;/code&gt; 只提供一些核心的 Envoy 指标。我们需要更多信息。在 &lt;code&gt;Deployment&lt;/code&gt; 里加入下列注解：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sidecar.istio.io/statsInclusionPrefixes: cluster.outbound,listener,cluster,cluster_manager,listener_manager,http_mixer_filter,tcp_mixer_filter,server,cluster.xds-grpc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：这个指标的数据量较大，缺省是关闭的。我只会在进行排错的时候才启用这些指标，并且在完成工作后就会关闭它们。&lt;/p&gt;

&lt;p&gt;完成这一操作后，就会看到一些&lt;a href=&#34;https://www.envoyproxy.io/docs/envoy/latest/configuration/cluster_manager/cluster_stats&#34; target=&#34;_blank&#34;&gt;新指标&lt;/a&gt;，例如 &lt;code&gt;envoy_cluster_upstream_cx_destroy_local_with_active_rq&lt;/code&gt; 和 &lt;code&gt;envoy_cluster_upstream_cx_destroy_remote_with_active_rq&lt;/code&gt;。这些指标来自 Envoy 的视角，因此它的本地和远程是这样的：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/localremote.png&#34; alt=&#34;local reote&#34; /&gt;&lt;/p&gt;

&lt;h4 id=&#34;envoy-cluster-upstream-cx-destroy-local-with-active-rq&#34;&gt;envoy_cluster_upstream_cx_destroy_local_with_active_rq&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;本地销毁的产生一个以上活动请求的链接数量。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;听起来很恐怖吧？没人希望活动请求被杀掉，我们的目标 Envoy 说，有大量的远程销毁，而我们的源 Envoy 有大量的本地销毁。&lt;/p&gt;

&lt;p&gt;这看起来云山雾罩，所以我觉得最简单的排查方法就是把他们列在一起。这样就会看到 &lt;code&gt;local&lt;/code&gt; 指标在源 Envoy 中出现，而目标 Envoy 中报告了 &lt;code&gt;remote&lt;/code&gt; 指标：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/Screenshot-2019-05-31-at-17.08.14.png&#34; alt=&#34;Grafana&#34; /&gt;&lt;/p&gt;

&lt;p&gt;上图说明 &lt;code&gt;sauron-seo-app&lt;/code&gt; 的 Envoy 和应用之间的连接关闭了。看起来是 &lt;code&gt;sauron-seo-app&lt;/code&gt; 关闭了（远程关闭）。然后 &lt;code&gt;consumer-gateway&lt;/code&gt; Envoy 也随即关闭了连接。这就能够解释 &lt;code&gt;consumer-gateway&lt;/code&gt; 在 HTTP 1.1 连接中（Envoy 之间的通信）收到的 &lt;code&gt;5xx&lt;/code&gt; 响应了。这个连接无法继续发送数据，除了关闭，别无他法（本地关闭）。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：这不是 http2.0 的情景，看起来 Istio 1.2 会有能力把 Envoy 之间的连接池切换为 http2.0。&lt;/p&gt;

&lt;p&gt;这样我们就决定，要进一步对 &lt;code&gt;sauron-seo-app&lt;/code&gt; 进行观察。&lt;/p&gt;

&lt;h2 id=&#34;istio-proxy-debug-日志&#34;&gt;istio-proxy debug 日志&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;istio-proxy&lt;/code&gt; 能够在运行时修改日志级别，对排除这类问题很有帮助。所以我们把这些日志设置为 &lt;code&gt;debug&lt;/code&gt; 级别：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kubectl exec -n sauron-seo-app sauron-seo-app-7667b9b7dc-jd3vg -c istio-proxy -- curl -XPOST -s -o /dev/null http://localhost:15000/logging?level=debug
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看看是否能有所斩获。&lt;/p&gt;

&lt;p&gt;修改日志级别后，可以用 &lt;code&gt;tail&lt;/code&gt; 来查看一下日志（可能有非常多的输出）。会看到 503 的相关内容：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[2019-05-30 08:24:09.206][34][debug][router] [external/envoy/source/common/router/router.cc:644] [C77][S184434754633764276] upstream reset: reset reason connection termination

[2019-05-30 08:24:09.206][34][debug][filter] [src/envoy/http/mixer/filter.cc:133] Called Mixer::Filter : encodeHeaders 2

[2019-05-30 08:24:09.206][34][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:1305] [C77][S184434754633764276] encoding headers via codec (end_stream=false):
 &#39;:status&#39;, &#39;503&#39;
 &#39;content-length&#39;, &#39;95&#39;
 &#39;content-type&#39;, &#39;text/plain&#39;
 &#39;date&#39;, &#39;Thu, 30 May 2019 08:24:08 GMT&#39;
 &#39;server&#39;, &#39;istio-envoy&#39;


[2019-05-30 08:24:09.208][34][debug][connection] [external/envoy/source/common/network/connection_impl.cc:502] [C77] remote close

[2019-05-30 08:24:09.208][34][debug][connection] [external/envoy/source/common/network/connection_impl.cc:183] [C77] closing socket: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里我们看到了 503 出现在连接 &lt;code&gt;[C77]&lt;/code&gt; 上。如果我们后退一下，会看到 &lt;code&gt;[C77]&lt;/code&gt; 连接上还有一段：&lt;code&gt;upstream reset: reset reason connection termination&lt;/code&gt;。 istio-proxy 告诉我们，上游复位了 77 号连接（这里的上游指的就是应用程序）。这进一步证实了，Envoy 认为 &lt;code&gt;sauron-seo-app&lt;/code&gt; 关闭了连接。&lt;/p&gt;

&lt;h2 id=&#34;抓包&#34;&gt;抓包&lt;/h2&gt;

&lt;p&gt;目前为止，我们用了很多的 Istio 和 Envoy 提供的功能，我们大概知道，很可能是目标应用断掉了连接。是时候开始抓包来进一步研究了。&lt;/p&gt;

&lt;p&gt;为了在 Kubernetes 上完成这个工作。我们使用了一个叫做 &lt;a href=&#34;https://github.com/eldadru/ksniff&#34; target=&#34;_blank&#34;&gt;ksniff&lt;/a&gt;，我得说，这个工具太棒了。因为我们运行的是非特权容器，因此无法在应用中进行 &lt;code&gt;tcpdump&lt;/code&gt;。ksniff 可以：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;检查你的目标应用运行在哪个节点上。&lt;/li&gt;
&lt;li&gt;部署一个和这个节点有亲和的 Pod，绑定到 Host network。&lt;/li&gt;
&lt;li&gt;从特权应用对流量进行 TCP Dump，并把流量发送回你笔记本上的 Wireshark。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TCP Dump 很吵，所以我们会做一下过滤：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;我们关注的是 TCP 连接相关的事件，所以只需要看 &lt;code&gt;SYN&lt;/code&gt;、&lt;code&gt;FIN&lt;/code&gt; 和 &lt;code&gt;RST&lt;/code&gt;。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;我们要观察的是本地 Envoy 和应用之间的流量，我们只想关注 &lt;code&gt;localhost&lt;/code&gt;，所以 &lt;code&gt;-i lo&lt;/code&gt; 就可以只查看 loopback 适配器了。&lt;/p&gt;

&lt;p&gt;kubectl sniff $pod -p -n $namespace -c istio-proxy -f &amp;lsquo;tcp[tcpflags] &amp;amp; (tcp-syn|tcp-fin|tcp-rst) != 0&amp;rsquo; -i lo&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我们很快就能看到 &lt;code&gt;RST&lt;/code&gt;，表明的确是我们的应用关闭了连接。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/thumbnail_image003.png&#34; alt=&#34;whireshark&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这就很清楚了，Envoy 应该能够处理上游的关闭连接。然而在极少数情况（0.003%）下，我们发现 Envoy 尝试向被应用关闭的连接中发送数据。Istio 团队还在尝试理解这种情况发生的原因（似乎是在服务端发送 &lt;code&gt;RST&lt;/code&gt; 和 Envoy 复用连接池中的连接的过程中发生的争用），并能够更好的处理这种场景（1.1.8 之后）。&lt;/p&gt;

&lt;p&gt;Istio 成员发现，在连接开始（&lt;code&gt;SYN&lt;/code&gt;）和复位（&lt;code&gt;RST&lt;/code&gt;）之间，总有五秒左右的间隔。&lt;/p&gt;

&lt;p&gt;我们的服务器是 nodejs，Google 搜索发现了 &lt;a href=&#34;https://nodejs.org/api/http.html#http_server_keepalivetimeout&#34; target=&#34;_blank&#34;&gt;Nodejs 文档&lt;/a&gt;中的一段内容：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;以毫秒为单位的超时时间，缺省值 5000（5秒）：服务器在处理完最后一个响应之后，等待新数据进入的时间，如果超过这一时间都未进行活动，就会销毁该 Socket。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;由上述文档看来，虽然 Envoy 为应用创建了连接池，但是应用会在发呆 5 秒钟之后销毁 Socket。这个超时太短了。&lt;/p&gt;

&lt;h2 id=&#34;tcp-socket-超时&#34;&gt;TCP Socket 超时&lt;/h2&gt;

&lt;p&gt;我们做了一番挖掘，我们发现不止在 Nodejs 中有这种情况，Python 应用、Java/Tomecat 都有这种问题。缺省设置如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nodejs：5 秒&lt;/li&gt;
&lt;li&gt;python：10 秒&lt;/li&gt;
&lt;li&gt;tomcat：20 秒&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以 Socket 超时越短，&lt;code&gt;RST&lt;/code&gt; 就会越多，也就会有越多的 503 问题。&lt;/p&gt;

&lt;p&gt;Istio 团队正在积极的寻求改进方法，我们发现可以简单的设置一个更高的 Socket 超时时间来解决这一问题。&lt;/p&gt;

&lt;h3 id=&#34;nodejs&#34;&gt;Nodejs&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const server = app.listen(port, &#39;0.0.0.0&#39;, () =&amp;gt; {
  logger.info(`App is now running on http://localhost:${port}`)
})
server.keepAliveTimeout = 1000 * (60 * 6) // 6 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;python&#34;&gt;Python&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;global_config = {
  &#39;server.socket_timeout&#39;: 6 * 60,
}
cherrypy.config.update(global_config)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;java-spring&#34;&gt;Java-Spring&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;server:
  connect-timeout: 360000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下图就是我们修复问题的结果：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/Screenshot-2019-05-31-at-16.36.43.png&#34; alt=&#34;result&#34; /&gt;&lt;/p&gt;

&lt;p&gt;我知道 Istio 团队正在努力改进这方面的 UX 问题，尽可能高效的处理这类场景，让 Istio 为更多用户提供开箱可用的高性能表现。所以我很相信他会越来越好。&lt;/p&gt;

&lt;p&gt;感谢 Chris McKean 和 Istio 社区的朋友们，他们在没有经历这种问题的情况下，依然提供了无私的帮助。希望这个排查过程能够对读者的工作有所助益。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 和 Linkerd 的性能测试分析</title>
      <link>/post/performance-benchmark-analysis-of-istio-and-linkerd/</link>
      <pubDate>Sun, 19 May 2019 13:29:38 +0800</pubDate>
      <guid>/post/performance-benchmark-analysis-of-istio-and-linkerd/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://kinvolk.io/blog/2019/05/performance-benchmark-analysis-of-istio-and-linkerd/&#34; target=&#34;_blank&#34;&gt;Performance Benchmark Analysis of Istio and Linkerd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/ThiloFM&#34; target=&#34;_blank&#34;&gt;Thilo Fromm&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;动机&#34;&gt;动机&lt;/h2&gt;

&lt;p&gt;过去几年里，服务网格在 Kubernetes 生态中迅速成长。Service Mesh 的&lt;strong&gt;价值&lt;/strong&gt;难以抗拒，然而对摩拳擦掌的用户来说，另一个基础问题就是：&lt;strong&gt;成本&lt;/strong&gt;怎样？&lt;/p&gt;

&lt;p&gt;成本有很多种，可不仅仅是学习新技术时的投入。在这一篇报告中，我们选择了一个易于量化的方面：在一定规模的服务中的资源消耗和性能影响。要进行这个测量，我们设计一系列测试场景，针对候选产品进行测试。我们的的候选包括 Istio（来自 Google 和 IBM 的 Istio 以及 Linkerd（CNCF 项目）。&lt;/p&gt;

&lt;p&gt;Buoyant 是 Linkerd 的首创者，他们和我们取得联系，目的是获得一个 Istio 和 Linkerd 的客观评判。这给我们一个深入服务网格技术的机会，欣然从命。&lt;/p&gt;

&lt;p&gt;Kinvolk 目前有客户正在尝试 Istio。我们的使命是在云原生世界中促进开源技术的发展，这也是我们呈现这一对比报告的根本原因。&lt;/p&gt;

&lt;p&gt;下面使用的测试方案也已经开放给开源社区，地址是 &lt;a href=&#34;https://github.com/kinvolk/service-mesh-benchmark。&#34; target=&#34;_blank&#34;&gt;https://github.com/kinvolk/service-mesh-benchmark。&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;目标&#34;&gt;目标&lt;/h2&gt;

&lt;p&gt;研究过程中我们有三个目标：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;提供一个可重现的测试框架，任何人都可以下载和使用。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;识别最能反应服务网格运行成本的场景和指标。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;根据业界在性能测试方面的最佳实践，例如控制编译来源，处理 Coordinated Omission（CO），来对流行服务网格进行评估。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;场景&#34;&gt;场景&lt;/h2&gt;

&lt;p&gt;我们的目标是在常规大负载集群的操作环境下，理解服务网格的性能表现。这意味着在产生压力的时候，集群应用还有能力在已定时间范围内给出响应。在系统受到压力的时候，用户访问该集群所服务的页面，还能够在一个可忍受的范围内提供服务。在真实世界中，延迟增大到一定程度之后，就会采取措施进行扩容了。&lt;/p&gt;

&lt;p&gt;在本文的测试中，测试负载（每秒 HTTP 请求）的水平是这样设置的——在给应用和服务网格施加压力的时候，运行其上的流量还在一个可控范围之内。&lt;/p&gt;

&lt;h2 id=&#34;指标&#34;&gt;指标&lt;/h2&gt;

&lt;h3 id=&#34;rps-用户体验和-co&#34;&gt;RPS、用户体验和 CO&lt;/h3&gt;

&lt;p&gt;测试中使用一个恒定的请求速率（RPS）发送 hTTP 请求，我们对响应延迟进行测量，来确定服务网格的总体性能。同样的 RPS 也会施加到一个无服务网格的集群上，以此结果来描述集群和应用的性能基线。&lt;/p&gt;

&lt;p&gt;我们的测试过程很注重 CO，在以 UX 为中心的视角下的一个重要因素。负载生成器只会在前一个请求完成之后才发起新请求，而不是为了满足 RPS 要求，不顾之前的请求直接按照时间点发起心情求。&lt;/p&gt;

&lt;p&gt;比如说如果我们要做一个 10 RPS 的延迟测试，我们每隔 100 毫秒就发出一个新请求，也就是一个 10 Hz 的速率。但是如果负载生成器在等待一个耗时超出 100 毫秒的请求的结束的话，那么这个 RPS 最多只能到 9。单一请求造成了高延迟，后续的请求也会受到拖累——处理的并不慢，只是开始得晚了。这种行为有两个缺点：第一个就是刚提到的，单一的高延迟请求造成后续请求的延迟；第二就是请求的发生过程被暂停，不符合 RPS 要求。在真实情况下，高延迟问题很可能因为用户蜂拥而至，产生大量积压。&lt;/p&gt;

&lt;p&gt;我们使用 &lt;a href=&#34;https://github.com/giltene/wrk2&#34; target=&#34;_blank&#34;&gt;wrk2&lt;/a&gt; 来生成负载并在客户端测量延迟。wrk2（Gil Tene）是流行的 http 压测工具 wrk（Will Glozer）的 Fork。wrk2 提供了 RPS 参数，可以用指定速率来生成负载，它通过在发起请求的时间点上测试延迟的方式来消除 CO 问题，还会尝试在请求迟发的情况下以双倍速率生成请求的方式来追赶进度。wrk2 还包含了 Gil Tene 的 HDR 直方图功能，提供了无损精确性的记录。越长的执行时间会有越高的精确度，这样后几个百分位的数据精度更高，也是我们更感兴趣的区域。&lt;/p&gt;

&lt;p&gt;为了完成这个测试，我们对 wrk2 的功能做了扩展，加入了多服务器地址和多 HTTP 资源路径的支持。我们不想将这个功能独立 Fork 出来，而是会和上游合作加入我们的&lt;a href=&#34;https://github.com/kinvolk/wrk2&#34; target=&#34;_blank&#34;&gt;变更&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&#34;性能&#34;&gt;性能&lt;/h3&gt;

&lt;p&gt;为了评估性能，我们可以研究一下延迟的分布（直方图），尤其是尾部的最后几个百分位的延迟。这反映了我们本次测试在 UE 上的焦点：一个典型的页面或者服务，需要不止一个请求来完成动作。如果一个请求延迟了，整个动作都会变慢。单一请求的 p99 在更复杂的操作中会有很大影响，例如浏览器访问一个页面，获取页面中的资源并进行顺序渲染——这就是我们看重 p99 的原因。&lt;/p&gt;

&lt;h3 id=&#34;资源消耗&#34;&gt;资源消耗&lt;/h3&gt;

&lt;p&gt;使用服务网格会让集群消耗更多资源，和业务逻辑发生争用。为了更好地理解这一效果，我们同时衡量了服务网格控制平面和应用 Sidecar 中的 CPU 和内存消耗。在测试期间，会用一个较高频率在容器级别收集 CPU 使用率和内存用量，每次运行中会选择组件的最大资源消耗，得出所有运行中的中位数并用于出具结果。&lt;/p&gt;

&lt;p&gt;我们注意到，内存消耗在测试结束时达到高峰。这个情况是合理的，根据上面的讨论，wrk2 用固定频率发起请求，当延迟超过一个阈值时，负载就会开始堆积，所以内存一旦分配就一直要到测试结束才会释放。CPU 使用率也会全程持续走高。&lt;/p&gt;

&lt;h2 id=&#34;测试环境&#34;&gt;测试环境&lt;/h2&gt;

&lt;h3 id=&#34;集群&#34;&gt;集群&lt;/h3&gt;

&lt;p&gt;我们使用了自动部署的测试集群，方便测试过程的启动和结束，也更加容易进行统计，生成可靠的数据。&lt;/p&gt;

&lt;p&gt;在这个服务网格性能测试过程中，我们使用了一个 5 节点的集群，每个节点使用 24核/48线程的 AMD EPYC CPU，主频为 2.4GHz，64G 内存。我们的工具可以使用可配置的节点数量，可以用不同的配置重新运行。&lt;/p&gt;

&lt;p&gt;负载的生成和延迟的测量都在集群内完成。为了消除噪音和 Ingress Gateway 的数据污染，我们把测试聚焦在应用之间的服务网格。负载生成器作为一个 Pod 部署在集群中，我们保留一个节点，用于负载生成和指标测量，在其它四个节点运行一定数量的应用实例。为了合理的统计分布，我们每次运行都会随机选择一个节点来运行负载生成器。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/clusterlayout.png&#34; alt=&#34;cluster layout&#34; /&gt;&lt;/p&gt;

&lt;p&gt;每次运行之前，会随机选择一个节点专门用于生成负载。其它节点运行应用负责承担负载。&lt;/p&gt;

&lt;p&gt;为了完成这次测试，我们选择 Packet 作为我们的 IaaS 供应商，工作节点我们选择了 c2.medium。Packet 提供了裸金属服务器，这样就让我们避免了虚拟化环境中常见的干扰问题。&lt;/p&gt;

&lt;h3 id=&#34;应用&#34;&gt;应用&lt;/h3&gt;

&lt;p&gt;根据前面的讨论，我们选择 wrk2 生成负载，并对这一工具进行了定制，可以同时访问多个 HTTP 端点。&lt;/p&gt;

&lt;p&gt;我们用来运行测试的目标应用是 Linkerd 的演示应用 &lt;code&gt;Emojivoto&lt;/code&gt;，这个应用自身跟 Linkerd/服务网格 的功能并无相关，Emojivoto 使用一个名为 &lt;code&gt;web-svc&lt;/code&gt;（&lt;code&gt;type: load-balancer&lt;/code&gt;）的 HTTP 微服务作为前端。&lt;code&gt;web-svc&lt;/code&gt; 使用 gRPC 和 &lt;code&gt;emoji-svc&lt;/code&gt;（提供表情符） 以及 &lt;code&gt;voting-svc&lt;/code&gt;（提供可控的投票）后端进行通信。这个应用简单清晰，包含了测试所需的云原生应用的所有要素，因此我们选择它作为测试应用。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/emojivoto.png&#34; alt=&#34;emojivoto&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Emojivoto 应用包含了三个微服务。&lt;/p&gt;

&lt;p&gt;然而只用一个应用进行服务网格测试，是很不现实的，真实世界中的服务网格，应该有复杂的多应用的部署。为了在保持简单的情况下更加仿真，我们用可部署的份数来部署 Emojivoto 应用，每个应用的名字中都加入序号。例如  &lt;code&gt;web-svc-1&lt;/code&gt;、&lt;code&gt;emoji-svc-1&lt;/code&gt;、&lt;code&gt;voting-svc-1&lt;/code&gt; 以及 &lt;code&gt;web-svc-2&lt;/code&gt;、&lt;code&gt;emoji-svc-2&lt;/code&gt;、&lt;code&gt;voting-svc-2&lt;/code&gt;。我们的负载均衡会将请求分发给所有这些 App，观察固定的 RPS。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/manyemojivotos.png&#34; alt=&#34;replica&#34; /&gt;&lt;/p&gt;

&lt;p&gt;循环利用 YAML，并在名字中加入序号，部署多套应用。&lt;/p&gt;

&lt;h3 id=&#34;运行测试和统计的稳健性&#34;&gt;运行测试和统计的稳健性&lt;/h3&gt;

&lt;p&gt;因为我们使用的是 Packet 提供的公共数据中心来运行我们的测试，所以也不能选择特定的服务器来进行部署。服务器的年龄和他的部件（内存、CPU 等），数据中心中的相对位置（同一个机架、房间、安全区），以及节点之间的物理连接，这些情况都会对测试的原始数据产生影响。其它服务器和我们的测试无关，但是在同一个数据中心内，共享同样的物理网络资源，也是可能对测试造成干扰的，最终会产生不可靠的测试数据。我们的每个数据点都有足够的统计分布样本，这样在进行对比的时候就能消除同一网络内外部因素造成的影响——例如 Istio 和 Linkerd 的延迟以及资源消耗方面的对比。我们还使用了不同数据中心的多个集群进行了测试，这也让我们对测试数据的可靠性信心大增。&lt;/p&gt;

&lt;p&gt;为了得到足够的统计分布，我们会每个测试都会运行两次，以得出平均值和标准差，我们在两个集群上同时独立部署，防止遭遇低档硬件或者故障网络，或有服务器被放置在数据中心的角落。&lt;/p&gt;

&lt;p&gt;典型的性能测试一般有几个步骤，这些步骤会在两个集群上同时运行，来消除上面提到的隐患。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;测试之前，重启所有工作节点。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;在两个集群的 &lt;code&gt;istio-stock&lt;/code&gt;、&lt;code&gt;istio-tuned&lt;/code&gt;、&lt;code&gt;linkerd&lt;/code&gt;、&lt;code&gt;bare&lt;/code&gt; 命名空间中，分别：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装服务网格（当然，不包含 &lt;code&gt;bare&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;部署 emojivoto 应用。&lt;/li&gt;
&lt;li&gt;部署负载生成器 Job。&lt;/li&gt;
&lt;li&gt;等 Job 结束，每 30 秒拉取一次资源消耗数据。&lt;/li&gt;
&lt;li&gt;拉取测试结果日志，其中包含了延迟指标。&lt;/li&gt;
&lt;li&gt;删除敷在生成 Job 以及 emojivoto。&lt;/li&gt;
&lt;li&gt;删除服务网格。&lt;/li&gt;
&lt;li&gt;回到第一步，测试下一个服务网格（顺序为：Linkerd-&amp;gt;Istio-&amp;gt;Bare）。&lt;/li&gt;
&lt;li&gt;在所有的 4 个测试结束之后，再运行第二次，以满足统计需要。&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;重现性&#34;&gt;重现性&lt;/h3&gt;

&lt;p&gt;w我们使用的是 Kinvolk 最近发布的 Kubernetes 发行版：Lokomotive。用于集群部署以及用于测试的代码都是开源的，保存在 Github 上。允许重新进行测试，也希望能够从其它用户那里得到改进。&lt;/p&gt;

&lt;h3 id=&#34;测试的运行和观测&#34;&gt;测试的运行和观测&lt;/h3&gt;

&lt;p&gt;我们在 &lt;code&gt;bare&lt;/code&gt;（无服务网格）、&lt;code&gt;istio-stock&lt;/code&gt;（无微调）、&lt;code&gt;istio-tuned&lt;/code&gt; 以及 &lt;code&gt;Linkerd&lt;/code&gt; 上，用 500 的 RPS 运行 30 分钟。在两个集群上各运行两次，每种数据就有了 4 个样本。测试集群分布在两个不同地理区域的不同的数据中心，一个是 Packet 的 Sunnyvale 数据中心，另一个是纽约的 Parsippany 数据中心。&lt;/p&gt;

&lt;h3 id=&#34;服务网格的版本&#34;&gt;服务网格的版本&lt;/h3&gt;

&lt;h4 id=&#34;istio-stock-和-tuned&#34;&gt;Istio：stock 和 tuned&lt;/h4&gt;

&lt;p&gt;我们用 &lt;a href=&#34;https://github.com/istio/istio/releases/tag/1.1.6&#34; target=&#34;_blank&#34;&gt;Istio 1.1.6&lt;/a&gt; 运行这一测试，&lt;code&gt;stock&lt;/code&gt; 运行的是根据&lt;a href=&#34;https://istio.io/docs/setup/kubernetes/install/kubernetes/&#34; target=&#34;_blank&#34;&gt;安装文档&lt;/a&gt;进行部署的版本，&lt;code&gt;tuned&lt;/code&gt; 版本则移除了内存限制，禁用了部分 Istio 组件，执行了不少推荐的微调。尤其是我们禁用了 Mixer、Policy、Tracing、Gateways 以及 Prometheus。&lt;/p&gt;

&lt;h4 id=&#34;linkerd&#34;&gt;Linkerd&lt;/h4&gt;

&lt;p&gt;我们使用的是 Linkerd 的 &lt;a href=&#34;https://github.com/linkerd/linkerd2/releases/tag/edge-19.5.2&#34; target=&#34;_blank&#34;&gt;Linkerd2-edge-19.5.2&lt;/a&gt;。我们使用的是 Linkerd 的&lt;a href=&#34;https://linkerd.io/2/getting-started/&#34; target=&#34;_blank&#34;&gt;标准配置&lt;/a&gt;，没有进行任何调整。&lt;/p&gt;

&lt;h3 id=&#34;测试服务网格的上限&#34;&gt;测试服务网格的上限&lt;/h3&gt;

&lt;p&gt;在使用稳定吞吐量开始长期运行之前，我们用一个较短的测试来确定服务网格吞吐量和延迟的范围。我们的目标是找到一个负载点，在这个点上，网格还能够用可接受的性能来处理流量。&lt;/p&gt;

&lt;p&gt;为了我们的测试，我们运行了 30 个 Emojivoto 应用，也就是 90 个微服务，平均下来每个节点有 7.5 个应用 22 个微服务。我们用多个 RPS 各运行 10 分钟，来确定前面所说的负载点。&lt;/p&gt;

&lt;h3 id=&#34;测试运行时间&#34;&gt;测试运行时间&lt;/h3&gt;

&lt;p&gt;我们最有兴趣的是尾部的百分位，因此测试的运行时间就很有影响了。越长的运行时间，在 99.9999 百分位和 100 百分位上的延迟就会越高。为了模拟用户涌入造成的高峰、以及新计算资源加入后的恢复，我们决定了 30 分钟的运行时间。注意，我们认为在多数环境里，尤其是自动伸缩的环境中，新资源的加入周期应该远低于 30 分钟；我们还认为，一个健壮的应用环境中，30 分钟足以应对扩容方面的意外。&lt;/p&gt;

&lt;h2 id=&#34;第一次测试-500-rps-30-分钟&#34;&gt;第一次测试：500 RPS，30 分钟&lt;/h2&gt;

&lt;p&gt;这次测试运行超过 30 分钟，500 RPS。&lt;/p&gt;

&lt;h3 id=&#34;延迟分布&#34;&gt;延迟分布&lt;/h3&gt;

&lt;p&gt;&lt;img src=&#34;images/500RPS-latency.png&#34; alt=&#34;500RPS-latency&#34; /&gt;&lt;/p&gt;

&lt;p&gt;我们在对数中观察到裸金属案例运行中，出现了很大的错误——可能是 Packet 的问题。这个情况在 99.9 和 99.999 上尤其明显，然而其他的数据点还是证明了整体趋势。我们看到 Linkerd 在这方面是胜出的，Istio 的缺省配置和微调配置相差不大，接下来看看资源消耗。&lt;/p&gt;

&lt;h3 id=&#34;内存和-cpu&#34;&gt;内存和 CPU&lt;/h3&gt;

&lt;p&gt;&lt;img src=&#34;images/500RPS-memory_usage.png&#34; alt=&#34;500RPS-memory_usage.png&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/500RPS-cpu_utilization.png&#34; alt=&#34;500RPS-cpu_utilization&#34; /&gt;&lt;/p&gt;

&lt;p&gt;我们在 4 个独立测试运行的过程中，测量了内存分配和 CPU 使用率，在这 4 个样本中，使用了中位数以及最高最低值。Linkerd 控制平面内存消耗的异常点是由 linkerd-prometheus 容器造成的，它消耗了 Linkerd 平面其他组件内存的两倍。&lt;/p&gt;

&lt;p&gt;而 Istio 中，我们看到了几次控制平面容器（Pilot 及其代理）消失的情况。我们不明白其中的原因，也没有深究，也没有把消失的容器计入结果。&lt;/p&gt;

&lt;h2 id=&#34;第二次测试-600-rps-30-分钟&#34;&gt;第二次测试：600 RPS，30 分钟&lt;/h2&gt;

&lt;p&gt;这次测试运行超过 30 分钟，600 RPS。&lt;/p&gt;

&lt;h3 id=&#34;延迟分布-1&#34;&gt;延迟分布&lt;/h3&gt;

&lt;p&gt;&lt;img src=&#34;images/600RPS-latency.png&#34; alt=&#34;600RPS-latency&#34; /&gt;&lt;/p&gt;

&lt;p&gt;我们再次观测到了裸金属测试中的抖动；然而其影响比 500 RPS 的时候更小。我们逼近了 Linkerd 的可接受响应时间的上限，在 100 百分位上的是 3 秒钟的延迟。&lt;/p&gt;

&lt;p&gt;Istio 轻松的把延迟时间推到了分钟级（别忘了 Y 轴是对数），我们还看到了大量的 Socket/HTTP 错误，占了大概 1%-5.2%，中位数在 3.6%。我们要指出，Istio 的 RPS 承受范围在 565 和 571 之间，中位数是 568。Istio 在本次测试中没能达到 600 RPS。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/600RPS-memory_usage.png&#34; alt=&#34;600RPS-memory_usage.png&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/600RPS-cpu_utilization.png&#34; alt=&#34;600RPS-cpu_utilization&#34; /&gt;&lt;/p&gt;

&lt;p&gt;上图的对比不太公平——我们看到的是 Linkerd 在 600 RPS 时候的表现，而 Istio 的是 570 RPS——但我们还是看得出，Istio 这里的资源需求。我们再次观察到 Istio 容器消失的情况，同样做了忽略处理。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;与裸金属相比，在常规条件下，Linkerd 和 Istio 的开销都算是可以接受的。当进入高负载状态时，相对于 Istio，Linkerd 能够提供更高的 RPS，并且使用更少的资源。&lt;/p&gt;

&lt;h2 id=&#34;下一步&#34;&gt;下一步&lt;/h2&gt;

&lt;p&gt;基于上面测试的观察，我们认为我们建立了一个良好的测试基础。未来的测试会进行更多的尝试，包括增强现有的测试，以及扩展测试场景。&lt;/p&gt;

&lt;p&gt;我们认为把负载生成器限制在一个 Pod 中是一个最大的限制。这限制了负载的生成能力。如果突破了这一限制，我们就有能力进行更多样的测试方法。然而在多个 Pod 中并列运行，又带来了结果合并的问题。&lt;/p&gt;

&lt;h2 id=&#34;后记&#34;&gt;后记&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;以下内容纯属个人胡言乱语&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;也不知道为啥，连续冒出几个性能测试来，与性能相比，更重要的是靠谱和有用好吗。Istio 还是 Linkerd，能长点心么。&lt;/p&gt;

&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://linkerd.io/2019/05/18/linkerd-benchmarks/&#34; target=&#34;_blank&#34;&gt;https://linkerd.io/2019/05/18/linkerd-benchmarks/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>关于 Anthos- Google 的混合多云平台</title>
      <link>/post/everything-u-want-to-now-about-anthos/</link>
      <pubDate>Tue, 16 Apr 2019 16:17:22 +0800</pubDate>
      <guid>/post/everything-u-want-to-now-about-anthos/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://www.forbes.com/sites/janakirammsv/2019/04/14/everything-you-want-to-know-about-anthos-googles-hybrid-and-multi-cloud-platform/amp/&#34; target=&#34;_blank&#34;&gt;Everything You Want To Know About Anthos - Google&amp;rsquo;s Hybrid And Multi-Cloud Platform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://www.forbes.com/sites/janakirammsv/&#34; target=&#34;_blank&#34;&gt;Janakiram MSV&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最近结束的 Cloud Next 会议上，Google 宣布企业级混合多云平台 &lt;a href=&#34;https://cloud.google.com/anthos/&#34; target=&#34;_blank&#34;&gt;Anthos&lt;/a&gt; 进入 GA 阶段。&lt;/p&gt;

&lt;p&gt;虽说会上有超过一百个发布，Anthos 依旧醒目。它标志着 Google 官方开始涉足企业数据中心。这是主流公有云厂商第一次以官方身份踏入多云平台的市场。&lt;/p&gt;

&lt;p&gt;从 Sundar Pichai 到 Thomas Kurian 再到 Urs Hölzle，Anthos 被描述为下一代技术。很明显，Google 的高层团队为该项目深感自豪。&lt;/p&gt;

&lt;p&gt;Anthos 和其它公有云服务不同。它不仅是一个产品，而是一个覆盖应用程序现代化、云迁移、混合云和多云管理等主题的家族品牌。&lt;/p&gt;

&lt;p&gt;虽然 Anthos 及其 GA 级别的成熟度被广泛报道，但是这一发布活动还是令人困惑的。文档非常稀少，相关服务并未完全集成到自助工作台之中。除了混合云的连接以及多云应用部署之外，Google 的这一新技术的更多细节并不为人所知。&lt;/p&gt;

&lt;h2 id=&#34;基础构成&#34;&gt;基础构成&lt;/h2&gt;

&lt;p&gt;Anthos 的核心是目前最流行的开源项目：Kubernetes。GKE 是 Google 云提供的容器即服务技术，Anthos正是构建于 GKE 的坚实基础之上。当然还有一些其它的重要技术为 Kubernetes 提供了必要的补充。&lt;/p&gt;

&lt;p&gt;镜头拉近，看看 Anthos 的核心组件：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;GKE：Anthos 的命令和控制核心。用户通过 GKE 的控制平面来对分散在 Google 云、私有数据中心一级其它云平台上的基础设施进行管理。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;GKE On-Prem：Google 推出了一个基于 Kubernetes 的和 GKE 一致的软件平台。用户能够在任何的兼容硬件上部署这一产品，而 Google 将会对其进行管理。从升级 Kubernetes 版本到应用最新补丁，Google 都视其为 GKE 的逻辑扩展。尤其需要注意的是 GKE On-Prem 运行在 VMWare vSphere 6.5 的虚拟化基础上，Hyper-V 和 KVM 等其它虚拟化技术的支持还在开发之中。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Istio：这一技术让跨平台的联邦网络管理成为可能。Anthos 需要为部署在不同数据中心、GCP 以及其它云上的多种应用程序的组件建立服务网格，Istio 自然是首选。它会和 VMWare NSX、Cisco ACI 以及 Google 自己的 Andromeda 等 SDN 进行无缝集成。已经在网络设施上（例如 F5） 进行投资的客户，可以将 Istio 和负载均衡及防火墙集成起来。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Velostrata：Google 在 2018 年收购了这一云迁移技术，来增强 Kubernetes 的竞争力。Velostrata 的主要功能——在 GCE 实例中复制物理机/虚拟机，并把现有虚拟机转换为 Kubernetes 应用（Pod）。这是业界首个物理机到 Kubernetes 的迁移工具，由 Google 提供。这一技术以 Anthos Migrate 的面目出现，目前是 Beta 阶段。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Anthos 配置管理：Kubernetes 是一个可扩展的策略驱动的平台。Anthos 的客户必须面对运行在不同环境中的多个 Kubernetes，因此 Google 尝试利用 Anthos 来简化配置管理工作。从发布工件、配置项目、网络策略、密文和密码等类型的配置，Anthos 配置管理都能够进行管理并将配置应用到一或多个集群之中。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Stackdriver：Stackdriver 为 Anthos 基础设施和应用提供了可观察性的支持。客户能够使用这一组件跟踪运行在 Anthos集群状态，以及部署在各个托管集群上的应用的健康情况。该组件负责集中地提供监控、日志、跟踪以及观察的支持。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;GCP Cloud Interconnect：在企业数据中心以及云基础设施之间的高速互联，是混合云平台的必要条件。Cloud Interconnect 能够在数据中心和云间交付高达 100Gbps 的高速网络。客户也可以使用 Equinix、NTT Communications、Softbanck 等电信厂商的网络将其数据中心延伸到 GCP。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;GCP Marketplace：Google 为能够在 Kubernetes 上运行的（来自 ISV 和开源的）软件列表。用户能够在 Anthos 中一键部署 Cassandra 数据库或者 GitLab 等软件。最终 Google 可能还会为内部 IT 提供一个私有的 Catalog 服务。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;应用程序-greenfield-vs-brownfield&#34;&gt;应用程序：Greenfield vs Brownfield&lt;/h2&gt;

&lt;p&gt;Anthos 的核心场景就是应用的现代化进程。Google 所展望的未来世界中，所有企业都运行在 Kubernetes 上。为了达成这一目标，Google 在 Velostrata 这样的技术上进行投资，从而完成从虚拟机到容器的就地升级。&lt;/p&gt;

&lt;p&gt;Google 为 VMware 的 vRealize 构建了一个插件，可以把现有虚拟机转换为 Kubernetes Pod。即使是 PostgreSQL 和 MySQL 这样的有状态应用，都能够转换为 StatefulSet 在 Kubernetes 中运行。&lt;/p&gt;

&lt;p&gt;在从自有虚拟机向云端虚拟机的迁移问题上，Google 表现得轻描淡写。但是 Velostrata 的原始服务都是基于 VM 的。客户的业务线应用程序，例如 SAP、Oracle Finacials 以及 Peoplesoft 都可以持续的运行在自家数据中心的虚拟机中，或者也可以选择迁移到 GCE 的虚拟机上。Anthos 在技术上提供虚拟机和 Kubernetes 容器化应用之间的互操作性。&lt;/p&gt;

&lt;p&gt;有了 Anthos，Google 想要拥有所有运行在 Kubernetes 之上现代微服务应用（Greenfield），同时也想将现有虚拟机（Brownfield）转换为容器。非 x86 架构中的存量应用会持续运行在物理或者虚拟机上。&lt;/p&gt;

&lt;h2 id=&#34;广泛的行业合作&#34;&gt;广泛的行业合作&lt;/h2&gt;

&lt;p&gt;因为缺乏与业内其它厂商的合作和伙伴关系，Google 经常受到批评。为了对抗微软和 Amazon，Google 准备和行业中的其它老牌企业进行合作。毫无疑问，这一举措会帮助 Google 在企业市场获得一席之地。&lt;/p&gt;

&lt;p&gt;为了让 Anthos 走向成功，Google 将不得不依靠现有的企业市场玩家进行推动。它要寻求的是和微软以及 Amazon 的合作伙伴，来一起推进混合云进程。&lt;/p&gt;

&lt;p&gt;Cisco 将 HyperFlex、ACI、SD-WAN 以及 Stealthwatch Cloud 扩展到 Anthos 之上，为其提供 SDN 能力。VMware 正在为 Pivotal Kubernetes Service（PKS）加入 Anthos 支持，另外还有 VeloCloud 提供的 SD-WAN 能力；它还将它的流行 SDN 方案 NSX 集成到了 Istio 之中。&lt;/p&gt;

&lt;p&gt;大量 ISV 正在启动对 Anthos 的支持。从 Citrix 到 NetApp 到 MongoDB，众多的平台供应商正在尝试将其软件集成到 Anthos 之中。&lt;/p&gt;

&lt;h2 id=&#34;google-的-kubernetes-攻势&#34;&gt;Google 的 Kubernetes 攻势&lt;/h2&gt;

&lt;p&gt;作为 Kubernetes 的创始人，毫无疑问的，Google 是很擅长管理容器的。在 Docker 开始展现出对开发者的吸引力之后，Google 意识到这是放养 Kubernetes 的绝佳机会。Google 也是业内第一个提供托管 Kubernetes 的公有云厂商。虽然有为数众多的竞争者，GKE 仍然是运行微服务的最佳平台。&lt;/p&gt;

&lt;p&gt;基于对 Kubernetes 的深入理解，以及在这方面的持续投入，Google 希望在容器和微服务的新世界之中占据主导地位。它希望企业能够跳出虚拟机，在 Kubernetes 上运行他们的现代应用。&lt;/p&gt;

&lt;p&gt;Anthos 是 Google 的重要一步。它正在冒险摆脱其对手用于吸引企业客户的混合云玩法。Anthos 对标的是微软的 Azure Stack 以及 AWS 提出的 VMware 结合 Outpost 的混合云方案。Google 和竞争对手的明显差别在于，它的方案根植于容器和 Kubernetes 技术。&lt;/p&gt;

&lt;p&gt;Google 希望利用在 Kubernetes 和云原生领域的领先地位。它迅速地围绕 Kubernetes 构建了企业战略。Google 意图通过 Anthos 成为容器生态系统中的 VMware。VMware 在企业中推动其 hypervisor 以及软件定义的基础设施的手段，正是现在 Google 的行为方式。&lt;/p&gt;

&lt;p&gt;但是微软同样在容器和 Kubernetes 方面下了重注。它通过将公有云中的旗舰级能力下放到私有云的方式，模糊了 Azure 和 Azure Stack 之间的界线。微软能够用 Azure Kubernetes 服务来复制 Anthos 的战术。Redmond 将如何使用 Azure Stack 玩转 Kubernetes，是个令人感兴趣的问题。&lt;/p&gt;

&lt;p&gt;如果一切如 Google 所愿，Anthos 最终会成为运行企业负载的首选平台。&lt;/p&gt;

&lt;h2 id=&#34;企业就绪&#34;&gt;企业就绪&lt;/h2&gt;

&lt;p&gt;让来自 Cisco 和 VMware 的高管和 Thomas Kurian 一起登台，这是来自 Google 的声明：已经为企业市场做好准备。这一表现当然会增强企业客户在 Anthos 和 GCP 上进行投入的信心。&lt;/p&gt;

&lt;p&gt;Kubernetes 被认为是一个高技术的、具有极客气息的平台，因此吸引了开发和运营人员。而有了 Anthos 的帮助，Google 将会改变客户对 Kubernetes 的刻板印象。它将 Kubernetes 变成一个可用的、可靠的企业级混合云平台。&lt;/p&gt;

&lt;p&gt;Thomas Kurian 掌舵之后，Google 开始关注企业市场。如果它能够用好合作伙伴关系，并持续和关键的行业参与者进行合作，Google 和 Anthos 将会给企业基础设施市场带来巨大冲击。&lt;/p&gt;

&lt;h2 id=&#34;云原生生态的巨大机会&#34;&gt;云原生生态的巨大机会&lt;/h2&gt;

&lt;p&gt;Anthos 提振了对云原生生态系统的信心。前面提到过，Google 希望成为 Kubernetes 世界中的 VMware。但是和 VMware 登上企业宝座的时候相比，世界已经不同了。&lt;/p&gt;

&lt;p&gt;最大的区别就是开源软件。Google 现在面临的环境中，软件已经不再是关键区别。&lt;/p&gt;

&lt;p&gt;为了 Anthos 的成功，Google 必须依赖社区和生态系统。为云原生环境提供利基产品的创业公司（例如 Tigera、Portworx、Robin、Confluent、Cloudbees）将会得到更好的机会，Anthos 的推出，会让其受益匪浅。&lt;/p&gt;

&lt;p&gt;从小型的本地供应商到埃森哲、高知特这样的全球 SI，供应商和集成商正在为 Anthos 做准备。Google 的混合云战略将转化为价值数百万没有的的服务机会。&lt;/p&gt;

&lt;p&gt;随着 Google 向企业宣传和销售 Kubernetes 的举措，创业公司将借势将其触角伸向企业。&lt;/p&gt;

&lt;p&gt;Google 在 Anthos 上的豪赌对行业大有裨益，开源社区和云原生生态系统将加速 Kubernetes 的采用过程。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 1.1 中的 Sidecar 资源</title>
      <link>/post/istio-sidecar-resource/</link>
      <pubDate>Wed, 10 Apr 2019 01:18:07 +0800</pubDate>
      <guid>/post/istio-sidecar-resource/</guid>
      <description>

&lt;p&gt;缺省情况下，Istio 在 Pod 创建之前将 &lt;code&gt;istio-init&lt;/code&gt; 和 &lt;code&gt;istio-proxy&lt;/code&gt; 注入到 Pod 之中，使用 &lt;code&gt;istio-init&lt;/code&gt; 对 iptables 进行初始化，将业务容器的流量拦截到 &lt;code&gt;istio-proxy&lt;/code&gt;，从而完成通信控制权的移交工作——应用容器的自发 Ingress 和 Egress 通信，都从 Envoy 中留过，Envoy 作为数据平面，需要接受来自控制面的 xDS 指令，据此作出通信决策。&lt;/p&gt;

&lt;p&gt;在 Istio 1.1 中引入了 Sidecar 资源对象，为这一拦截转发过程加入了一定的控制能力，可能给 Istio 的生产应用带来很好的效率提升。&lt;/p&gt;

&lt;h2 id=&#34;基本结构&#34;&gt;基本结构&lt;/h2&gt;

&lt;p&gt;Sidecar 资源的一级结构很简单，由三个成员构成：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;workloadSelector&lt;/code&gt;：标签选择器，用来对 Pod 进行选择。这一字段是可选字段，如果忽略这一字段，则会对命名空间内的所有 Pod 生效。需要注意的是，一个命名空间之内，只允许存在一个不设置此字段的 Sidecar 对象。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;ingress&lt;/code&gt;：一个数组，用于处理进入 Pod 的流量，如果省略这一字段，Istio 会根据业务应用的工作负载定义来设置监听过程。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;port&lt;/code&gt;：必要字段，监听的端口，如果使用 Unix domain socket，则设置为 0。

&lt;ul&gt;
&lt;li&gt;number&lt;/li&gt;
&lt;li&gt;protocal&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bind&lt;/code&gt;：监听器的绑定设置，可以是 &lt;code&gt;ip&lt;/code&gt;，也可以是 &lt;code&gt;unix:///path/to/uds&lt;/code&gt;，如果省略这一字段，Istio 会根据工作负载服务来自动填充。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;captureMode&lt;/code&gt;：如果 &lt;code&gt;bind&lt;/code&gt; 指定的是 IP 地址，这个字段可以指定是否拦截通信，如果绑定到 Unix domain socket，这一字段必须是 &lt;code&gt;DEFAULT&lt;/code&gt; 或者 &lt;code&gt;NONE&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaultEndpoint&lt;/code&gt;：必要字段，Envoy 接收进入 Pod 的流量之后的转发目标。目标可以是 &lt;code&gt;127.0.0.1:PORT&lt;/code&gt; 或者 &lt;code&gt;unix:///path/to/socket&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;egress&lt;/code&gt;：一个处理 Egress 流量的定义数组。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;port&lt;/code&gt;：监听器的端口，如果使用 Unix domain socket，则设为 0。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bind&lt;/code&gt;：绑定到地址或 socket。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;captureMode&lt;/code&gt;：同 &lt;code&gt;ingress&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hosts&lt;/code&gt;：必要字段，用 &lt;code&gt;命名空间/服务 FQDN&lt;/code&gt; 组合而成，可以是 VirtualService 或者 ServiceEntry 或者原始 Kubernetes 服务的名称，支持通配符。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;开始之前&#34;&gt;开始之前&lt;/h2&gt;

&lt;p&gt;安装 Kubernetes 集群和 Istio，这里采用 1.1.2 的 demo-auth 配置。创建新命名空间 &lt;code&gt;other&lt;/code&gt;，并打标签开启自动注入：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ helm template install/kubernetes/helm/istio-init \
    --name istio-init --namespace istio-system | kubectl apply -f -
...
$ helm template install/kubernetes/helm/istio \
    --name istio --namespace istio-system \
    --values install/kubernetes/helm/istio/values-istio-demo-auth.yaml | kubectl apply -f -
...
$ kubectl create ns other
namespace/other created

$ kubectl label namespaces other istio-injection=enabled --overwrite
namespace/other labeled

$ kubectl label namespaces default istio-injection=enabled --overwrite
namespace/default labeled
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;分别在 &lt;code&gt;default&lt;/code&gt; 和 &lt;code&gt;other&lt;/code&gt; 中启动 &lt;code&gt;flaskapp&lt;/code&gt; 和 &lt;code&gt;sleep&lt;/code&gt; 应用。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl apply -f sleep/sleep.yaml -n default
service/sleep created
deployment.extensions/sleep created
$ kubectl apply -f sleep/sleep.yaml -n other
service/sleep created
deployment.extensions/sleep created
$ kubectl apply -f httpbin/httpbin.yaml -n default
service/httpbin created
deployment.extensions/httpbin created
$ kubectl apply -f httpbin/httpbin.yaml -n other
service/httpbin created
deployment.extensions/httpbin created
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;检查一下调用关系：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -c sleep -it sleep-69bd44b5bb-vwpzf -- curl http://httpbin:8000/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;127.0.0.1&amp;quot;
}

$ kubectl exec -c sleep -it sleep-69bd44b5bb-vwpzf -- curl http://httpbin.other:8000/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;127.0.0.1&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;服务的可见性&#34;&gt;服务的可见性&lt;/h2&gt;

&lt;p&gt;缺省情况下，注入了 Istio 的工作负载会进行全网格的传播，假设 &lt;code&gt;default&lt;/code&gt; 和 &lt;code&gt;other&lt;/code&gt; 两个不相干的命名空间，&lt;code&gt;other&lt;/code&gt; 中有大量的服务，而 &lt;code&gt;default&lt;/code&gt; 中只有几个，因为路由传播的关系，&lt;code&gt;default&lt;/code&gt; 命名空间中的工作负载，其 Sidecar 也会带上 &lt;code&gt;other&lt;/code&gt; 命名空间中的路由信息。例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ istioctl proxy-config clusters sleep-69bd44b5bb-vwpzf | grep other
httpbin.other.svc.cluster.local 8000    -   outbound    &amp;amp;{EDS}
sleep.other.svc.cluster.local   80      -   outbound    &amp;amp;{EDS}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，在 &lt;code&gt;default&lt;/code&gt; 命名空间中的 Pod，保存了其它命名空间中的路由信息。这不管是对内存消耗还是路由控制来说，都会造成一定浪费，我们可以定义一个 Sidecar 资源，限制 sleep 服务只访问同一命名空间的其他服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: sleep
spec:
  workloadSelector:
    labels:
      app: sleep  
  egress:
  - hosts:
    - &amp;quot;default/*&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;提交到集群，看看效果：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl apply -f sleep-egress.yaml
sidecar.networking.istio.io/sleep created

$ istioctl proxy-config clusters sleep-69bd44b5bb-vwpzf | grep httpbin
httpbin.default.svc.cluster.local   8000    -   outbound    &amp;amp;{EDS}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，httpbin 的路由只剩下了本命名空间之内的服务。再次尝试访问：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -c sleep -it sleep-69bd44b5bb-vwpzf -- curl http://httpbin:8000/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;127.0.0.1&amp;quot;
}

$ kubectl exec -c sleep -it sleep-69bd44b5bb-vwpzf -- curl -v http://httpbin.other:8000/ip
*   Trying 10.245.156.252...
* TCP_NODELAY set
* Connected to httpbin.other (10.245.156.252) port 8000 (#0)
&amp;gt; GET /ip HTTP/1.1
&amp;gt; Host: httpbin.other:8000
&amp;gt; User-Agent: curl/7.61.1
&amp;gt; Accept: */*
&amp;gt;
&amp;lt; HTTP/1.1 404 Not Found
&amp;lt; date: Wed, 10 Apr 2019 04:50:15 GMT
&amp;lt; server: envoy
&amp;lt; content-length: 0
&amp;lt;
* Connection #0 to host httpbin.other left intact
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样一来，已经无法访问 &lt;code&gt;httpbin.other&lt;/code&gt; 的服务了，但是如果尝试从 &lt;code&gt;other&lt;/code&gt; 到 &lt;code&gt;default&lt;/code&gt; 访问的话，还是可以继续的。&lt;/p&gt;

&lt;h2 id=&#34;sidecar-的-ingress-和-egress&#34;&gt;Sidecar 的 Ingress 和 Egress&lt;/h2&gt;

&lt;p&gt;除了上面的小功能之外，Sidecar 的 &lt;code&gt;IstioEgressListener&lt;/code&gt; 和 &lt;code&gt;IstioIngressListener&lt;/code&gt; 都提供了很强大的功能，例如：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Envoy 可以为应用容器所监听的 Unix socket 提供反向代理服务。&lt;/li&gt;
&lt;li&gt;在没有 iptables 支持的情况下，可以使用 &lt;code&gt;bind&lt;/code&gt; 结合 &lt;code&gt;port&lt;/code&gt; 的方式，直接指定代理方案。&lt;/li&gt;
&lt;li&gt;可以在容器内部为 egress 服务提供基于 Unix socket 的反向代理。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;详情可以参考官方参考文档：&lt;a href=&#34;https://istio.io/docs/reference/config/networking/v1alpha3/sidecar/#IstioIngressListener&#34; target=&#34;_blank&#34;&gt;https://istio.io/docs/reference/config/networking/v1alpha3/sidecar/#IstioIngressListener&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;中文版：&lt;a href=&#34;https://skyao.io/learning-istio/crd/network/sidecar.html&#34; target=&#34;_blank&#34;&gt;https://skyao.io/learning-istio/crd/network/sidecar.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这些功能都非常有用，上面的文档中都提供了很好的应用场景，&lt;strong&gt;但是这些特性我只有可见性部分测试成功了(╬￣皿￣)=○&lt;/strong&gt;，目前正在讨说法，非常希望是我错了。。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 负载均衡的区域感知</title>
      <link>/post/locality-load-balancing/</link>
      <pubDate>Mon, 08 Apr 2019 13:45:32 +0800</pubDate>
      <guid>/post/locality-load-balancing/</guid>
      <description>

&lt;p&gt;Envoy/Istio 1.1 中有个有趣的新特性：负载均衡提供了&lt;a href=&#34;https://istio.io/help/ops/traffic-management/locality-load-balancing/&#34; target=&#34;_blank&#34;&gt;区域感知&lt;/a&gt;的能力。简单说来，就是在分区部署的较大规模的集群，或者公有云上，Istio 负载均衡可以根据节点的区域标签，对调用目标做出就近选择。在跨区部署的应用中，原始的 Kubernetes 负载均衡可能会把来自 A 区的请求发送给远在 B 区的服务，造成高成本的跨区调用。要缩减这种损耗，通常都需要实现更多的逻辑，Istio 的区域感知特性在某种程度上提供了一种解决办法。&lt;/p&gt;

&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;接下来首先做一些琐碎的安装工作，这里选择了常见的 GCP 作为测试环境，Istio 版本为 1.1.2。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;在 GCP 的 &lt;code&gt;us-central1&lt;/code&gt; 创建一个区域集群：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ gcloud beta container clusters create &amp;quot;standard-cluster-1&amp;quot; \
...
 --no-enable-basic-auth \
 --cluster-version &amp;quot;1.12.6-gke.10&amp;quot; \
 --machine-type &amp;quot;n1-standard-1&amp;quot; --image-type &amp;quot;COS&amp;quot; \
...
 --num-nodes &amp;quot;2&amp;quot; \
 --no-enable-cloud-logging --no-enable-cloud-monitoring \
...--no-enable-ip-alias \
 --addons HorizontalPodAutoscaling \
 --enable-autoupgrade --enable-autorepair
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;获取本地认证，为 &lt;code&gt;kubectl&lt;/code&gt; 生成 &lt;code&gt;context&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ gcloud beta container clusters get-credentials \
standard-cluster-1 --region us-central1 \
--project dustise-mesh-lab
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;查看节点标签，这里会看到不同的节点会使用&lt;a href=&#34;https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#failure-domain-beta-kubernetes-io-region&#34; target=&#34;_blank&#34;&gt;区域标签&lt;/a&gt;进行标识：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get nodes --show-labels

...
failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a
...
failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-c
...
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;为 Istio 准备 RBAC：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole=cluster-admin \
    --user=$(gcloud config get-value core/account)
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;初始化 Istio CRD：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl create namespace istio-system
$ helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | kubectl apply -f -

configmap/istio-crd-10 created
configmap/istio-crd-11 created
serviceaccount/istio-init-service-account created
clusterrole.rbac.authorization.k8s.io/istio-init-istio-system created
clusterrolebinding.rbac.authorization.k8s.io/istio-init-admin-role-binding-istio-system created
job.batch/istio-init-crd-10 created
job.batch/istio-init-crd-11 created
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/setup/kubernetes/install/helm/&#34; target=&#34;_blank&#34;&gt;安装 Isto&lt;/a&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ helm template install/kubernetes/helm/istio \
    --name istio --namespace istio-system \
    --values install/kubernetes/helm/istio/values-istio-demo-auth.yaml | kubectl apply -f -
......
handler.config.istio.io/kubernetesenv created
rule.config.istio.io/kubeattrgenrulerule created
rule.config.istio.io/tcpkubeattrgenrulerule created
kubernetes.config.istio.io/attributes created
destinationrule.networking.istio.io/istio-policy created
destinationrule.networking.istio.io/istio-telemetry created
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;标记 &lt;code&gt;default&lt;/code&gt; 命名空间，启动自动注入：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl label namespaces default istio-injection=enabled --overwrite
kubectl namespace/default labeled
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;部署应用&#34;&gt;部署应用&lt;/h2&gt;

&lt;p&gt;为了方便演示，我们给惯用的 flaskapp 和 sleep 加上 &lt;code&gt;NodeSelector&lt;/code&gt;，要求按照版本分布到不同区域的节点上，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;nodeSelector:
        failure-domain.beta.kubernetes.io/zone: us-central1-f
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;标签内容可以参照上文 &lt;code&gt;kubectl get nodes --show-labels&lt;/code&gt; 的显示结果。&lt;/p&gt;

&lt;p&gt;修改了部署清单之后，就可以部署了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl apply -f flaskapp/flaskapp.istio.yaml
service/flaskapp created
deployment.extensions/flaskapp-v1 created
deployment.extensions/flaskapp-v2 created
$ kubectl apply -f sleep/sleep.istio.yaml
service/sleep created
deployment.extensions/sleep-v1 created
deployment.extensions/sleep-v2 created
deployment.extensions/sleep-v3 created
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;稍候片刻，查看部署结果：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP          NODE                                                NOMINATED NODE
flaskapp-v1-b9644bd75-g82nj   2/2     Running   0          92m   10.40.4.9   gke-standard-cluster-1-default-pool-0570ecb1-lm7q   &amp;lt;none&amp;gt;
flaskapp-v2-77d648fbd-cvfql   2/2     Running   0          92m   10.40.3.5   gke-standard-cluster-1-default-pool-f2347d89-q79k   &amp;lt;none&amp;gt;
sleep-v1-84c85c8946-c7bvc     2/2     Running   0          91m   10.40.1.3   gke-standard-cluster-1-default-pool-0570ecb1-1qnq   &amp;lt;none&amp;gt;
sleep-v2-57cf55db78-vrvtc     2/2     Running   0          92m   10.40.3.7   gke-standard-cluster-1-default-pool-f2347d89-q79k   &amp;lt;none&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;和上文比较，可以看到，sleep 和 flaskapp 的 v1、v2 两个版本，分别运行在 &lt;code&gt;us-central1-a&lt;/code&gt; 和 &lt;code&gt;us-central1-f&lt;/code&gt; 中。&lt;/p&gt;

&lt;h2 id=&#34;验证路由的区域感知功能&#34;&gt;验证路由的区域感知功能&lt;/h2&gt;

&lt;p&gt;接下来分别从网格内部和 Ingress Gateway 来验证这一功能。&lt;/p&gt;

&lt;h3 id=&#34;服务网格内部请求&#34;&gt;服务网格内部请求&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -it -c sleep sleep-v1-84c85c8946-c7bvc bash
# for i in {1..10}; do http --body  http://flaskapp/env/version ; done
v1
v2
v2
v1
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，请求被随机分配到不同的版本，也就是说，此时的调用是无视分区的。接下来我们设置 Pilot 的环境变量，启用区域感知功能，过程很简单，给它的 Pod 加入环境变量 &lt;code&gt;PILOT_ENABLE_LOCALITY_LOAD_BALANCING&lt;/code&gt;，并任意赋值即可，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- name: PILOT_TRACE_SAMPLING
  value: &amp;quot;100&amp;quot;
...
- name: PILOT_ENABLE_LOCALITY_LOAD_BALANCING
  value: &amp;quot;1&amp;quot;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次进入 Pod 访问 flaskapp 服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -it -c sleep sleep-v1-84c85c8946-c7bvc bash
# for i in {1..10}; do http --body  http://flaskapp/env/version ; done
v1
v1
v1
...
# exit
$ kubectl exec -it -c sleep sleep-v2-57cf55db78-vrvtc bash
# for i in {1..10}; do http --body  http://flaskapp/env/version ; done
v2
v2
v2
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，果然按照我们预想的情况，不同区域的请求，会交由不同区域的服务来进行响应。如果此时删除同区的目标负载，会发现开始平均访问其它区的服务。&lt;/p&gt;

&lt;h3 id=&#34;ingress-网关&#34;&gt;Ingress 网关&lt;/h3&gt;

&lt;p&gt;Ingress 网关控制器在网格内同样也会分配到不同的节点上，因此也同样会受到区域的影响。例如我们为 flaskapp 创建一个 &lt;code&gt;VirtualService&lt;/code&gt; + &lt;code&gt;Gateway&lt;/code&gt; 的组合，引入外部流量：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: flaskapp-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - &amp;quot;flaskapp.example.com&amp;quot;
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - &amp;quot;flaskapp.example.com&amp;quot;
  gateways:
  - flaskapp-gateway
  http:
  - route:
    - destination:
        port:
          number: 80
        host: flaskapp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;提交后，可以在外使用 &lt;code&gt;curl --resolve&lt;/code&gt; 来验证：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=&#39;{.status.loadBalancer.ingress[0].ip}&#39;)
$ for i in {1..10}; do curl --resolve flaskapp.example.com:80:$INGRESS_HOST http://flaskapp.example.com/env/version ; done
v3v3v3v3v3v3v3v3v3v3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，对 Ingress Gateway 进入的流量，区域感知功能也是同样生效的。&lt;/p&gt;

&lt;h2 id=&#34;区域间分流&#34;&gt;区域间分流&lt;/h2&gt;

&lt;p&gt;如果只是简单的就近原则，虽然方便，但也难免有些枯燥，例如我的集群中的三个分区之间存在优先次序，或者强行指派一个区的请求需要由指定的其它分区的服务进行处理，又该怎样呢？&lt;/p&gt;

&lt;p&gt;istio-system 中有个叫做 istio 的 configmap，其中包含了 &lt;a href=&#34;https://istio.io/docs/reference/config/istio.mesh.v1alpha1/&#34; target=&#34;_blank&#34;&gt;Istio 的一些核心配置&lt;/a&gt;，里面的 &lt;a href=&#34;https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#LocalityLoadBalancerSetting&#34; target=&#34;_blank&#34;&gt;LocalityLoadBalancerSetting&lt;/a&gt;，包含了对区域感知负载均衡的一些行为配置。例如我们分配所有分区的流量，都分配到前面两个区域：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;    localityLbSetting:
      distribute:
      - from: us-central1/us-central1-a/*
        to:
          us-central1/us-central1-a/*: 90
          us-central1/us-central1-b/*: 10
      - from: us-central1/us-central1-b/*
        to:
          us-central1/us-central1-a/*: 90
          us-central1/us-central1-b/*: 10
      - from: us-central1/us-central1-f/*
        to:
          us-central1/us-central1-a/*: 90
          us-central1/us-central1-b/*: 10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;应用之后，重启 Galley、Pilot、Injector，并重新注入应用，再次在不同分区的 sleep 容器中进行测试。会发现其中的请求呈现了符合配置要求的分配，并且没有发送到 us-central1-b 区。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;事实上本次测试，并没有发现比率生效，仅达到有或无的区别。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;目前的分区域分流功能似乎还有些问题，但是不失为一个新的服务亲和思路。
分区是基于 Kubernetes Node 标签完成的，通过对标签的调整（例如机柜、楼层），能够比较方便的在&lt;strong&gt;无侵入&lt;/strong&gt;的情况下，实现就近调用，对服务的跨区 HA，有一定的辅助作用。&lt;/p&gt;

&lt;h2 id=&#34;参考链接&#34;&gt;参考链接&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Istio 负载均衡的区域感知：&lt;a href=&#34;https://istio.io/help/ops/traffic-management/locality-load-balancing/&#34; target=&#34;_blank&#34;&gt;https://istio.io/help/ops/traffic-management/locality-load-balancing/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;使用 Helm 安装 Istio：&lt;a href=&#34;https://istio.io/docs/setup/kubernetes/install/helm/&#34; target=&#34;_blank&#34;&gt;https://istio.io/docs/setup/kubernetes/install/helm/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubernetes 区域标签：&lt;a href=&#34;https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#failure-domain-beta-kubernetes-io-region&#34; target=&#34;_blank&#34;&gt;https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#failure-domain-beta-kubernetes-io-region&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Istio 1.1 中的限流问题</title>
      <link>/post/ratelimit-in-istio-1-1/</link>
      <pubDate>Sat, 23 Mar 2019 01:55:47 +0800</pubDate>
      <guid>/post/ratelimit-in-istio-1-1/</guid>
      <description>

&lt;p&gt;在 &lt;a href=&#34;https://blog.fleeto.us/post/servicemesh-and-chasm/&#34; target=&#34;_blank&#34;&gt;Istio 1.1 发布&lt;/a&gt;之后，对 &lt;a href=&#34;https://item.jd.com/12527008.html&#34; target=&#34;_blank&#34;&gt;《深入浅出 Istio》&lt;/a&gt;一书中的例子&lt;a href=&#34;https://blog.fleeto.us/post/istio-book-update-for-1-1/&#34; target=&#34;_blank&#34;&gt;进行了一遍快速的检查&lt;/a&gt;，发现限流功能已经无法使用了。&lt;/p&gt;

&lt;p&gt;在解决了 &lt;a href=&#34;https://blog.fleeto.us/post/handler-in-istio-1-1/&#34; target=&#34;_blank&#34;&gt;Prometheus 的 Handler 问题&lt;/a&gt;之后，开始查看限流的问题。&lt;/p&gt;

&lt;h2 id=&#34;mixer-日志控制的两个小技巧&#34;&gt;Mixer 日志控制的两个小技巧&lt;/h2&gt;

&lt;p&gt;Mixer 策略相关内容比较多，经常需要查看 Policy 和 Telemetry 的日志，然而这两种进程的缺省日志都是很多的，可以用一点小技巧来进行清理。&lt;/p&gt;

&lt;h3 id=&#34;godebug&#34;&gt;GODEBUG&lt;/h3&gt;

&lt;p&gt;首先，Mixer 的两个 Deployment 中都会带有 &lt;code&gt;GODEBUG&lt;/code&gt; 环境变量，用于开启调试信息，可以使用 &lt;code&gt;kubectl edit&lt;/code&gt; 命令删除环境变量。&lt;/p&gt;

&lt;h3 id=&#34;controlz&#34;&gt;ControlZ&lt;/h3&gt;

&lt;p&gt;Istio 组件都带有 ControlZ 接口，可以用于控制和查看核心组件的一些配置信息，其端口都开放在 9876，可以用端口转发的方式打开进行调整，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl port-forward -n istio-system \
&amp;gt; istio-telemetry-c545bb9bd-x7jpz 9876:9876
Forwarding from 127.0.0.1:9876 -&amp;gt; 9876
Forwarding from [::1]:9876 -&amp;gt; 9876
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后就可以用浏览器打开 &lt;code&gt;http://127.0.0.1:9876&lt;/code&gt; 进行调整了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/controlz.png&#34; alt=&#34;controlz&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;言归正传&#34;&gt;言归正传&lt;/h2&gt;

&lt;p&gt;应用书中的 YAML 代码的同时，可以打开 Mixer 的日志，会发现其中有几行错误：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;error  failed to evaluate expression for field &#39;Dimensions[destination]&#39;; unknown attribute destination.service
error  Instance not found: instance=&#39;dest-quota.quota&#39;
error  No valid instances found                                                error  No valid actions found in rule
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里发现了一个无法识别的属性：&lt;code&gt;destination.service&lt;/code&gt;。翻查文档发现，该属性在 &lt;a href=&#34;https://archive.istio.io/v1.0/docs/reference/config/policy-and-telemetry/attribute-vocabulary/#deprecated-attributes&#34; target=&#34;_blank&#34;&gt;Istio 1.0 的 Reference&lt;/a&gt; 中声明即将过期;在 1.1 中已经停用，因此将其改为 &lt;code&gt;destination.service.host&lt;/code&gt; 即可正常使用。更新代码已经上传到随书代码库的 &lt;a href=&#34;https://github.com/fleeto/istio-for-beginner/tree/1.1&#34; target=&#34;_blank&#34;&gt;1.1 分支&lt;/a&gt;中的第八章内容里。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 1.1 中的 Handler</title>
      <link>/post/handler-in-istio-1-1/</link>
      <pubDate>Fri, 22 Mar 2019 19:18:15 +0800</pubDate>
      <guid>/post/handler-in-istio-1-1/</guid>
      <description>&lt;p&gt;一直觉得 Mixer 的功能会比较不稳定，这次在&lt;a href=&#34;https://item.jd.com/12527008.html&#34; target=&#34;_blank&#34;&gt;《深入浅出 Istio》&lt;/a&gt;一书的的验证过程中发现，Prometheus 的部分无法工作了，因此今天排查一下，也因此有了些收获，这里做一个简单的记录。&lt;/p&gt;

&lt;p&gt;首先我发现，&lt;strong&gt;istio-system 中系统默认安装的 Prometheus 资源不见了&lt;/strong&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ kubectl get prometheus --all-namespaces
No resources found.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;但是好在相关的 Rule 还在，写法有了一些变化，例如 &lt;code&gt;istio-system&lt;/code&gt; 中的 &lt;code&gt;promtcp&lt;/code&gt; 的定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
...
  name: promtcp
  namespace: istio-system
spec:
  actions:
  - handler: prometheus
    instances:
    - tcpbytesent.metric
    - tcpbytereceived.metric
  match: context.protocol == &amp;quot;tcp&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;过去我们习惯的 Handler 填写一般会是 &lt;code&gt;handler.prometheus&lt;/code&gt;，也就是名为 handler 的 prometheus 资源。例如&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/metrics/collecting-metrics/#collecting-new-metrics&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;中的写法：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# Rule to send metric instances to a Prometheus handler
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
  name: doubleprom
  namespace: istio-system
spec:
  actions:
  - handler: doublehandler.prometheus
    instances:
    - doublerequestcount.metric
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;很明显的，1.1 的用法发生了变更，这个新用法中并没有提及对象名称，只知道名字是 &lt;code&gt;prometheus&lt;/code&gt;。在 Istio 1.1 的 Helm 源码中搜索一下 &lt;code&gt;name: prometheus&lt;/code&gt; 就会看到，在 &lt;code&gt;helm/istio/charts/mixer/templates/config.yaml&lt;/code&gt; 中定义了一个对象，一个 &lt;code&gt;handler&lt;/code&gt; 类型的对象：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: handler
metadata:
  name: prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样就可以查查他的定义了，运行 &lt;code&gt;kubectl get -n istio-system handler prometheus -o yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
...
  name: prometheus
  namespace: istio-system
...
spec:
  compiledAdapter: prometheus
  params:
    metrics:
    - instance_name: requestcount.metric.istio-system
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;是的，这个名为 &lt;code&gt;prometheus&lt;/code&gt; 的 &lt;code&gt;handler&lt;/code&gt; 对象和以前几乎一毛一样。现在有两种定义 Prometheus 的 Handler 了，对此&lt;a href=&#34;https://discuss.istio.io/t/promethues-or-handler/1547&#34; target=&#34;_blank&#34;&gt;开发给出的解释&lt;/a&gt;是，并非所有 Adapter 都会创建自己的 CRD，因此推荐共用的 Handler 类型来进行定义。&lt;/p&gt;

&lt;p&gt;在 &lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1/#Handler&#34; target=&#34;_blank&#34;&gt;Reference&lt;/a&gt; 中对这一对象做了个大概的讲解。需要注意其中的 &lt;code&gt;compiledAdapter: prometheus&lt;/code&gt;，用于指定 Adapter 类型。其中使用 &lt;code&gt;compiledAdapter&lt;/code&gt; 和 &lt;code&gt;adapter&lt;/code&gt; 两个字段分别用于描述进程内外的两种适配器类型。&lt;/p&gt;

&lt;p&gt;因此在 1.1 中，Handler 真正的成为了 Handler，下面给出一个简单的定义，来讲解一下自定义指标中，新 Handler 的定义方法，其中给指标定义名称为 &lt;code&gt;cxl_counter&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  labels:
    app: mixer
    chart: mixer
    heritage: Tiller
    release: istio
  name: prometheus
spec:
  compiledAdapter: prometheus
  params:
    metrics:
      - instance_name: cxl.metric.default
        kind: COUNTER
        label_names:
          - source_app
          - source_workload
          - source_workload_namespace
          - source_version
          - destination_app
          - destination_workload
          - destination_workload_namespace
          - destination_version
          - destination_service
          - destination_service_name
          - destination_service_namespace
          - reporter
          - response_code
        name: cxl_counter
    metricsExpirationPolicy:
      metricsExpiryDuration: 10m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;原有 Handler 的定义方式，同样的指标，定义为 &lt;code&gt;double_counter&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: prometheus
metadata:
  name: handler
spec:
  metrics:
    - instance_name: cxl.metric.default
      kind: COUNTER
      label_names:
        - source_app
        - source_workload
        - source_workload_namespace
        - source_version
        - destination_app
        - destination_workload
        - destination_workload_namespace
        - destination_version
        - destination_service
        - destination_service_name
        - destination_service_namespace
        - reporter
        - response_code
      name: double_counter
  metricsExpirationPolicy:
    metricsExpiryDuration: 10m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用一个 Rule，将同样的指标分别输出到两个 Handler 之中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: prom-http
spec:
  actions:
    - handler: prometheus
      instances:
        - cxl.metric
    - handler: handler.prometheus
      instances:
        - cxl.metric
  match: context.protocol == &amp;quot;http&amp;quot; || context.protocol == &amp;quot;grpc&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;而指标的定义不变：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: metric
metadata:
  name: cxl
spec:
  dimensions:
    destination_app: destination.labels[&amp;quot;app&amp;quot;] | &amp;quot;unknown&amp;quot;
    destination_service: destination.service.host | &amp;quot;unknown&amp;quot;
    destination_service_name: destination.service.name | &amp;quot;unknown&amp;quot;
    destination_service_namespace: destination.service.namespace | &amp;quot;unknown&amp;quot;
    destination_version: destination.labels[&amp;quot;version&amp;quot;] | &amp;quot;unknown&amp;quot;
    destination_workload: destination.workload.name | &amp;quot;unknown&amp;quot;
    destination_workload_namespace: destination.workload.namespace | &amp;quot;unknown&amp;quot;
    source_app: source.labels[&amp;quot;app&amp;quot;] | &amp;quot;unknown&amp;quot;
    source_version: source.labels[&amp;quot;version&amp;quot;] | &amp;quot;unknown&amp;quot;
    source_workload: source.workload.name | &amp;quot;unknown&amp;quot;
    source_workload_namespace: source.workload.namespace | &amp;quot;unknown&amp;quot;
    reporter:
      conditional((context.reporter.kind | &amp;quot;inbound&amp;quot;) == &amp;quot;outbound&amp;quot;, &amp;quot;source&amp;quot;,
      &amp;quot;destination&amp;quot;)
    response_code: response.code | 200
  monitored_resource_type: &#39;&amp;quot;UNSPECIFIED&amp;quot;&#39;
  value: &amp;quot;2&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;制造请求之后，会发现新旧 Handler 同时工作，并用各自的名字写入了指标。在 Prometheus 中即可查看。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这里真的要吐槽一句，Metric 定义中的所有 Label 需要照抄到 Handler 定义中，映射关系出错的时候，出的不是 Warning，而是 Panic。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;涉及到的代码已经更新到版本库的 &lt;a href=&#34;https://github.com/fleeto/istio-for-beginner/tree/1.1&#34; target=&#34;_blank&#34;&gt;1.1 分支&lt;/a&gt;的第八章内容里。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>《深入浅出 Istio》在 Istio 1.1 中的一些已知情况</title>
      <link>/post/istio-book-update-for-1-1/</link>
      <pubDate>Wed, 20 Mar 2019 23:51:05 +0800</pubDate>
      <guid>/post/istio-book-update-for-1-1/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://item.jd.com/12527008.html&#34; target=&#34;_blank&#34;&gt;《深入浅出 Istio》&lt;/a&gt;在编写之初，我大致估算了成书可能所需的工作量和完成时间，也预计了一下 Istio 1.1 可能的发布时间以及大略的变动范围，因此定下了入门书的调性。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://blog.fleeto.us/post/servicemesh-and-chasm/&#34; target=&#34;_blank&#34;&gt;Istio 1.1 推出&lt;/a&gt;后，就在第一时间进行了安装部署，对书中所涉代码进行了验证，一来是给读者一个交代，二来也是做个准备，根据 Istio 1.1 的变动，对本书进行更新。&lt;/p&gt;

&lt;p&gt;验证结果如下：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;章节&lt;/th&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7.8&lt;/td&gt;
&lt;td&gt;重试无法工作&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service/#HTTPRetry&#34; target=&#34;_blank&#34;&gt;HTTPRetry&lt;/a&gt; 结构发生变更。加入 &lt;code&gt;retryOn: 5xx&lt;/code&gt; 即可。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;7.11&lt;/td&gt;
&lt;td&gt;1.11 中的 Helm chart 结构已经改变，不再适用。&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;8.4、8.5&lt;/td&gt;
&lt;td&gt;限流不可用&lt;/td&gt;
&lt;td&gt;正在排查中&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;8.6&lt;/td&gt;
&lt;td&gt;Prometheus 监控指标定义失败&lt;/td&gt;
&lt;td&gt;1.1 中的指标定义发生部分变化&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;RBAC 等相关对象发生大量变更，部分对象失效&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;如上表所示，除 7.8 节的问题很明确之外，其它问题的解决过程也会尽快的逐步更新出来。&lt;/p&gt;

&lt;p&gt;随书代码已经新建 1.1 分支。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>鸿沟前的服务网格—Istio 1.1 新特性预览</title>
      <link>/post/servicemesh-and-chasm/</link>
      <pubDate>Wed, 13 Mar 2019 17:35:21 +0800</pubDate>
      <guid>/post/servicemesh-and-chasm/</guid>
      <description>

&lt;h2 id=&#34;引子&#34;&gt;引子&lt;/h2&gt;

&lt;p&gt;这几天拜读了灵雀云出品的一篇文章：&lt;a href=&#34;http://dockone.io/article/8666&#34; target=&#34;_blank&#34;&gt;《从“鸿沟理论”看云原生》&lt;/a&gt;，其中有两段关于 Istio 的陈述，我深感赞同：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在 Control Plane，Istio 是最具光环的明星级项目。它正在引领 Service Mesh 创造出一个全新的市场，不过从传播周期看现在还没有跨过技术鸿沟，处于 Early adopters 阶段。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;在开源领域，并不存在对Istio有实质性威胁的竞品。可能在经历了 Kubernetes 之后，以及 Istio 早期迅猛的发展和在社区中巨大的影响力之下，很少有开源项目愿意在 Control Plane 和 Istio 正面交锋。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;按照我对 Istio 的理解，正如该文所说，正处于鸿沟一侧，正是从早期采用者到早期大众之间关键阶段。然而这一系统的情况又比较特殊，Service Mesh 的饼，虽说是 Linkerd 画出来的，然而真正把饼变大的，正是 Istio。Istio 画了硕大无朋的饼之后，就步步泥潭，功能薄弱、进度拖沓，让包括我在内的众多用户大摇其头。然而，画饼的另一面，就是挖坑——Istio 放出的漫天卫星，极大的吊起了各种用户的胃口，可以说是用先声夺人的方式，强行提高了门槛，要想赶超 Istio，首先就要接班，完成 Istio 的各种承诺，才能满足用户心目中对 Service Mesh 的“基本”期待。&lt;/p&gt;

&lt;h2 id=&#34;istio-1-1&#34;&gt;Istio 1.1&lt;/h2&gt;

&lt;p&gt;Istio 自然还是在努力的完成满足早期用户要求的基础上，加强对早期大众的吸引。自 2018 年 7 月发布 1.0 之后，经过近 8 个月的漫长等待，千呼万唤的 1.1 又做出了什么样的变化，来帮助 Istio 来达成这样的目标呢？下面会介绍一些我所关注的 Istio 1.1 新特性。&lt;/p&gt;

&lt;h3 id=&#34;缺省关闭-mixer-策略检查&#34;&gt;缺省关闭 Mixer 策略检查&lt;/h3&gt;

&lt;p&gt;从 Istio 的早期版本开始，关于如何关闭 Mixer 策略检查的讨论就没有停止过，现在社区已经达成共识，绝大多数场景中，对性能的需求，其重要性是大于对预检功能的需求的，因此 1.1 版本中，缺省安装会关闭 Mixer 的这一功能。&lt;/p&gt;

&lt;h3 id=&#34;缺省开放-egress-通信&#34;&gt;缺省开放 Egress 通信&lt;/h3&gt;

&lt;p&gt;新增 &lt;code&gt;global.outboundTrafficPolicy.mode&lt;/code&gt; 参数，用于定制 Egress 通信的缺省行为，目前的缺省值为 &lt;code&gt;ALLOW_ANY&lt;/code&gt;，即允许全部 Egress 通信。&lt;/p&gt;

&lt;h3 id=&#34;新增-sidecar-资源&#34;&gt;新增 Sidecar 资源&lt;/h3&gt;

&lt;p&gt;目前版本中，Sidecar 会包含整个网格内的服务信息，在 1.1 中，新建了 Sidecar 资源，通过对这一 CRD 的配置，不但能够限制 Sidecar 的相关服务的数量，从而降低资源占用，提高传播效率；还能方便的对 Sidecar 的代理行为做出更多的精细控制——例如对 Ingress 场景中的被代理端点的配置能力。&lt;/p&gt;

&lt;h3 id=&#34;exportto&#34;&gt;ExportTo&lt;/h3&gt;

&lt;p&gt;多个路由管理对象加入了这一字段，用于指定该资源的生效范围。&lt;/p&gt;

&lt;h3 id=&#34;路由的区域感知能力&#34;&gt;路由的区域感知能力&lt;/h3&gt;

&lt;p&gt;新增了对 AZ/Region 等的区域感知能力，降低跨区请求造成的性能损耗。&lt;/p&gt;

&lt;h3 id=&#34;对-tcp-服务提供鉴权支持&#34;&gt;对 TCP 服务提供鉴权支持&lt;/h3&gt;

&lt;p&gt;在既有的 HTTP/gRPC 之外，又为 TCP 服务提供了 RBAC 功能。&lt;/p&gt;

&lt;h3 id=&#34;引入-sds-完成证书流程&#34;&gt;引入 SDS 完成证书流程&lt;/h3&gt;

&lt;p&gt;弃用原有的 Citadel-&amp;gt;Secret-&amp;gt;Sidecar 的证书流程，改用 Secret Discovery Service 完成。从而降低了安全风险，并且更新证书也无需重新启动了。&lt;/p&gt;

&lt;h2 id=&#34;硬广&#34;&gt;硬广&lt;/h2&gt;

&lt;p&gt;拙作《深入浅出 Istio》是基于 1.0.x 版本编写，目前已经将绝大多数 YAML 源码上传至 Github，目测绝大多数功能在 1.1 上是可用的；预备在 Istio 1.1 正式发布后，逐章进行校验。在征得出版方同意之后，会以补充文档的方式，在 Github 上，进行勘误以及增补，以保障本书相关内容的及时性。&lt;/p&gt;

&lt;h3 id=&#34;购买链接&#34;&gt;购买链接&lt;/h3&gt;

&lt;p&gt;&lt;img src=&#34;qr-book.png&#34; alt=&#34;jd&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;代码仓库链接&#34;&gt;代码仓库链接&lt;/h3&gt;

&lt;p&gt;&lt;img src=&#34;qr-repo.png&#34; alt=&#34;repo&#34; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>VirtualService 的校验脚本</title>
      <link>/post/virtualservice-validator/</link>
      <pubDate>Fri, 22 Feb 2019 20:59:42 +0800</pubDate>
      <guid>/post/virtualservice-validator/</guid>
      <description>&lt;p&gt;Istio 的流量控制功能中，&lt;code&gt;VirtualService&lt;/code&gt; 和 &lt;code&gt;DestinationRule&lt;/code&gt; 对象之间具有很强的关联性；另外这些规则需要用标签的形式落地到 Kubernetes 中的 &lt;code&gt;Service&lt;/code&gt; 和 &lt;code&gt;Pod&lt;/code&gt; 中，很多时候因为操作不慎导致的一点小错误，例如标签错误、缺少 &lt;code&gt;subset&lt;/code&gt; 定义、选择器冲突等，都会导致功能完全失效，因此就写了这个小脚本，从头到尾检查一遍相关配置。用法很简单：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;./virtual-service-scanner.py flaskapp-default-v2
Validating VirtualService: flaskapp-default-v2
Destinations referenced: {&#39;flaskapp.default.svc.cluster.local&#39;: [&#39;v2&#39;, &#39;v3&#39;]}
Fetching all destination rules in current namespace.
Validating subsets of host flaskapp.default.svc.cluster.local
Service label is: {&#39;app&#39;: &#39;flaskapp&#39;}
Subset label is: {&#39;version&#39;: &#39;v2&#39;}
Pod selector: app=flaskapp,version=v2
1 pods found
Traceback (most recent call last):
  File &amp;quot;./virtual-service-scanner.py&amp;quot;, line 148, in &amp;lt;module&amp;gt;
    main()
  File &amp;quot;./virtual-service-scanner.py&amp;quot;, line 88, in main
    verify_virtualservice(args.object_name, kubectl_command)
  File &amp;quot;./virtual-service-scanner.py&amp;quot;, line 117, in verify_virtualservice
    &amp;quot;Subset {} isn&#39;t defined.&amp;quot;.format(subset_name)
AssertionError: Subset v3 isn&#39;t defined.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;virtual-service-scanner.py [VirtualService]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会根据其中引用的 &lt;code&gt;host&lt;/code&gt;、&lt;code&gt;subset&lt;/code&gt; 对其依赖的 &lt;code&gt;DestinationRule&lt;/code&gt;、&lt;code&gt;Service&lt;/code&gt; 以及 &lt;code&gt;Pod&lt;/code&gt; 进行逐一检查，如果其中有环节无法通过，脚本会出错退出，例如上面的例子中，&lt;code&gt;VirtualService&lt;/code&gt; 引用了不存在的 &lt;code&gt;subset&lt;/code&gt;： &lt;code&gt;v3&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;项目地址：&lt;a href=&#34;https://github.com/fleeto/vs-scanner&#34; target=&#34;_blank&#34;&gt;Github&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Sidecar 注入：例外和除错</title>
      <link>/post/istio-sidecar-injection/</link>
      <pubDate>Tue, 18 Dec 2018 10:30:27 +0800</pubDate>
      <guid>/post/istio-sidecar-injection/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://bani.com.br/2018/09/istio-sidecar-injection-enabling-automatic-injection-adding-exceptions-and-debugging/&#34; target=&#34;_blank&#34;&gt;Istio sidecar injection: enabling automatic injection, adding exceptions and debugging&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/jwendell&#34; target=&#34;_blank&#34;&gt;Jonh Wendell&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes 环境下的 Istio 使用了 Sidecar 模型进行部署，把一个辅助容器（也就是 Sidecar）附加到业务 Pod 之中。这一过程让 Sidecar 容器和业务容器共享同样的网络栈，可以视为同一主机上的两个进程。这样一来，Istio 就能够接管业务应用的所有网络调用，就有了增强服务间通信能力的基础。&lt;/p&gt;

&lt;p&gt;这个 Sidecar 容器命名为 &lt;code&gt;istio-proxy&lt;/code&gt;，能够用手工或者自动方式进行注入。其实这个手工注入也不是 100% 徒手完成的。&lt;/p&gt;

&lt;h2 id=&#34;手工注入&#34;&gt;手工注入&lt;/h2&gt;

&lt;p&gt;Istio 的发行版本中会带有一个 &lt;code&gt;istioctl&lt;/code&gt; 工具。看名字就知道这工具很棒：）。它的一个能力就是把 &lt;code&gt;istio-proxy&lt;/code&gt; Sidecar 注入到业务容器之中。我们可以用一个简单的 &lt;code&gt;busybox&lt;/code&gt; Pod 来看看它的功能：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ cat busybox.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox-test
spec:
  containers:
  - name: busybox-container
    image: busybox
    command: [&#39;sh&#39;, &#39;-c&#39;, &#39;echo Hello Kubernetes! &amp;amp;&amp;amp; sleep infinity&#39;]

$ istioctl kube-inject -f busybox.yaml &amp;gt; busybox-injected.yaml
$ cat busybox-injected.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
  name: busybox-test
spec:
  containers:
  - command:
    - sh
    - -c
    - echo Hello Kubernetes! &amp;amp;&amp;amp; sleep infinity
    image: busybox
    name: busybox-container

  - image: docker.io/istio/proxyv2:1.0.2
    imagePullPolicy: IfNotPresent
    name: istio-proxy
    args:
      - proxy
      - sidecar
   ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上文可见，这个命令生成了一个 YAML 文件，和原始文件有点像，但是 Pod 中加入了一个 Sidecar（istio-proxy）。这的确不是纯手工吧——至少让我们少打了不少字。然后就可以使用 &lt;code&gt;kubectl apply&lt;/code&gt; 命令把这个修改后的文件提交给 Kubernetes 集群了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ kubectl apply -f busybox-injected.yaml
# 如果不想生成中间文件，可以直接用管道完成全部操作。
$ kubectl apply -f &amp;lt;(istioctl kube-inject -f busybox.yaml)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;随之而来的一个问题就是：这些数据是哪来的？它怎么知道 Sidecar 镜像是 &lt;code&gt;docker.io/istio/proxyv2:1.0.2&lt;/code&gt; 的？答案很简单：所有数据都来自于一个 ConfigMap，这个对象保存在 &lt;code&gt;istio-system&lt;/code&gt; 命名空间：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl -n istio-system describe configmap istio-sidecar-injector
Name:         istio-sidecar-injector
Namespace:    istio-system
 
Data
====
config:
----
policy: enabled
template: |-
  initContainers:
  - name: istio-init
    image: &amp;quot;docker.io/istio/proxy_init:1.0.2&amp;quot;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以对这个 ConfigMap 进行编辑，修改一些你需要的值，用来进行注入。不难发现，这主要是一个用于向 Pod 加入内容的模板。如果想要为 &lt;code&gt;istio-proxy&lt;/code&gt; 容器使用其它对象，只要修改这个字段的内容就可以了，或者还可以调整任何其它要注入的东西。这个 ConfigMap 是用来完成网格中所有 Pod 的注入工作的，所以要小心从事。&lt;/p&gt;

&lt;p&gt;因为 &lt;code&gt;istioctl&lt;/code&gt; 要根据 ConfigMap 来获知注入内容，也就是说执行 &lt;code&gt;istioctl&lt;/code&gt; 的用户必须能够访问到安装了 Istio 的 Kubernetes 集群的这一对象。如果因为某些原因无法访问到这一 ConfigMap，还可以在 &lt;code&gt;istioctl&lt;/code&gt; 中使用一个本地的配置文件。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# 首先使用有权限的用户运行这一命令
$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath=&#39;{.data.config}&#39; &amp;gt; inject-config.yaml
# 这个文件可以随时进行任意修改。
$ istioctl kube-inject --injectConfigFile inject-config.yaml ...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;自动注入&#34;&gt;自动注入&lt;/h2&gt;

&lt;p&gt;注入 &lt;code&gt;istio-proxy&lt;/code&gt; 还有另一个方式，就是要求 Istio 进行自动注入。为命名空间设置标签 istio-injection=enabled 就能满足这一需要了。如果命名空间加上了这个标签，所有其中的 Pod 都会被注入 &lt;code&gt;istio-proxy&lt;/code&gt; Sidecar，也就无需手工执行 &lt;code&gt;istioctl&lt;/code&gt; 处理 YAML 文件了。&lt;/p&gt;

&lt;p&gt;工作方式很简单：它使用了 Kubernetes 的 &lt;code&gt;MutatingWebhook&lt;/code&gt;，新 Pod 创建之前，这一功能会通知 Istio，让 Istio 有机会对新 Pod 进行就地修改，stio 会使用在 ConfigMap 中的模板把 &lt;code&gt;istio-proxy&lt;/code&gt; 注入到 Pod 中。&lt;/p&gt;

&lt;h2 id=&#34;看起来不错&#34;&gt;看起来不错？&lt;/h2&gt;

&lt;p&gt;自动注入过程有很大的弹性：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;istio-sidecar-injector&lt;/code&gt; ConfigMap 中有一个布尔值用来指定自动注入是否启用。&lt;/li&gt;
&lt;li&gt;只有使用标签进行标注的命名空间才会进行自动注入，也就是说用命名空间标签能够对自动注入进行控制。&lt;/li&gt;
&lt;li&gt;还可以使用 &lt;code&gt;kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector&lt;/code&gt; 命令，修改其中的 &lt;code&gt;namespaceSelector&lt;/code&gt; 字段来调整这个标签的用法，甚至移除这个限制（也就是为所有命名空间使用自动注入，慎用）。&lt;/li&gt;
&lt;li&gt;可以禁用特定 Pod 的自动注入。如果 Pod 包含注解 &lt;code&gt;sidecar.istio.io/inject: &amp;quot;false&amp;quot;&lt;/code&gt;，Istio 就不会为在这一 Pod 中注入 Sidecar。&lt;/li&gt;
&lt;li&gt;还有更保守的方式：只对选择的 Pod 进行注入——也就是白名单方式。设置策略为 false（&lt;code&gt;kubectl -n istio-system edit configmap istio-sidecar-injector&lt;/code&gt;），只对包含注解 &lt;code&gt;sidecar.istio.io/inject: &amp;quot;true&amp;quot;&lt;/code&gt; 进行注入。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;想要更大弹性&#34;&gt;想要更大弹性？&lt;/h2&gt;

&lt;p&gt;还有些上面提到的方法无法满足的弹性要求：&lt;/p&gt;

&lt;p&gt;如果不熟悉 Openshift 的用户，它有一个功能叫做 &lt;code&gt;source-to-image&lt;/code&gt;（代码到镜像，&lt;code&gt;s2i&lt;/code&gt;），这一功能会将代码构建为容器镜像。提供一个 git 仓库作为输入（支持多种语言），就会输出镜像并运行到 Openshift 集群上。&lt;/p&gt;

&lt;p&gt;这是一个神奇的功能。这里不会介绍很多细节，我只会告诉你本文中需要了解的事情：在这一过程中 Openshift 会创建一或更多个的用于进行构建的中间、辅助 Pod。构建过程结束之后，二进制工件被构建为容器镜像，而辅助 Pod 会被销毁。&lt;/p&gt;

&lt;p&gt;如果我们为指定命名空间启用了自动注入，并使用 Openshift 的 s2i 功能，会让这些辅助 Pod 也被注入 Sidecar，这些 Pod 是 Openshift 创建的，我们无法对其进行注解以阻止 Sidecar 的注入。辅助 Pod 无需进行注入，怎么办呢？&lt;/p&gt;

&lt;p&gt;一个可能的解决方法就是用上面提到的保守方案，只对特定 Pod 启用注入，但是就要对 Pod 进行特别的注解。还有别的方式。&lt;/p&gt;

&lt;h3 id=&#34;新方案&#34;&gt;新方案&lt;/h3&gt;

&lt;p&gt;1.1.0 中，Istio 自动注入可以根据标签进行例外设置：不管命名空间标签如何，策略如何设置，对符合标签选择器要求的 Pod 都不进行注入。可以在 &lt;code&gt;istio-sidecar-injector&lt;/code&gt; 中加入例外设置。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl -n istio-system describe configmap istio-sidecar-injector
apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-sidecar-injector
data:
  config: |-
    policy: enabled
    neverInjectSelector:
      - matchExpressions:
        - {key: openshift.io/build.name, operator: Exists}
      - matchExpressions:
        - {key: openshift.io/deployer-pod-for.name, operator: Exists}
    template: |-
      initContainers:
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到上面的 &lt;code&gt;neverInjectSelector&lt;/code&gt; 字段，它是一个 Kubernetes 标签选择器的数组。不同元素之间是“或”关系，第一次发现有符合条件的标签之后就会跳过其它判断。上面的语句意味着：包含 &lt;code&gt;openshift.io/build.name&lt;/code&gt; 或者 &lt;code&gt;openshift.io/deployer-pod-for.name&lt;/code&gt; 标签的 Pod，不管标签值如何，都不会进行注入。&lt;/p&gt;

&lt;p&gt;为了完整性起见，可以使用 &lt;code&gt;alwaysInjectSelector&lt;/code&gt; 字段，这个字段会无视全局策略，向符合条件的 Pod 进行注入。&lt;/p&gt;

&lt;p&gt;标签选择器方式产生了很大的弹性，能够处理更多的例外情况。阅读 &lt;a href=&#34;https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#resources-that-support-set-based-requirements&#34; target=&#34;_blank&#34;&gt;Kubernetes 文档&lt;/a&gt;可以了解更多这方面的内容。&lt;/p&gt;

&lt;p&gt;值得注意的是，Pod 注解还是有更高的优先级，如果 Pod 注解包含了 &lt;code&gt;sidecar.istio.io/inject: &amp;quot;true/false&amp;quot;&lt;/code&gt;，会被优先处理，所以自动注入的评估顺序是：&lt;/p&gt;

&lt;p&gt;Pod 注解 → NeverInjectSelector → AlwaysInjectSelector → 命名空间策略。&lt;/p&gt;

&lt;p&gt;注入选择器是新特性，这方面的文档还在更新，但是其它部分的文档和例子，都可以在&lt;a href=&#34;https://istio.io/docs/setup/kubernetes/sidecar-injection/&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;中查看。&lt;/p&gt;

&lt;h2 id=&#34;pod-为什么没注入&#34;&gt;Pod 为什么没注入？&lt;/h2&gt;

&lt;p&gt;这是个常见问题。按照前面的介绍（例如给命名空间打标签）进行操作，结果 Pod 还没有被注入。&lt;/p&gt;

&lt;p&gt;或者刚好相反，Pod 明明注解为 &lt;code&gt;sidecar.istio.io/inject: &amp;quot;false&lt;/code&gt;，还是被注入了，为什么？&lt;/p&gt;

&lt;p&gt;可以看看 &lt;code&gt;sidecar-injector&lt;/code&gt; Pod 的日志：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath=&#39;{.items[0].metadata.name}&#39;)
$ kubectl -n istio-system logs -f $pod
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后可以创建业务 Pod，看看日志输出的具体内容。要看到更详细的日志（经常会很有用），可以编辑 &lt;code&gt;sidecar-injector&lt;/code&gt; Deployment 对象，给它加上参数 &lt;code&gt;--log_output_level=default:debug&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl -n istio-system edit deployment istio-sidecar-injector
...
      containers:
      - args:
        - --caCertFile=/etc/istio/certs/root-cert.pem
        - --tlsCertFile=/etc/istio/certs/cert-chain.pem
        - --tlsKeyFile=/etc/istio/certs/key.pem
        - --injectConfig=/etc/istio/inject/config
        - --meshConfig=/etc/istio/config/mesh
        - --healthCheckInterval=2s
        - --healthCheckFile=/health
        - --log_output_level=default:debug
        image: docker.io/istio/sidecar_injector:1.0.2
        imagePullPolicy: IfNotPresent
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;编辑成功之后 Pod 会重启，完成之后就可以重新查看日志了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath=&#39;{.items[0].metadata.name}&#39;)
$ kubectl -n istio-system logs -f $pod
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;提示&#34;&gt;提示&lt;/h3&gt;

&lt;p&gt;如果在日志中还是找不到问题原因，就代表 &lt;code&gt;sidecar-injector&lt;/code&gt; Pod 没有收到 Pod 创建的通知，也就不会触发自动注入的操作。这可能是因为命名空间没有正确标签导致的，因此需要检查一下命名空间的标签以及 &lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; 中的配置。缺省情况下，命名空间应该设置 &lt;code&gt;istio-injection=enabled&lt;/code&gt; 标签。可以使用 &lt;code&gt;kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector&lt;/code&gt; 命令检查其中的 &lt;code&gt;namespaceSelector&lt;/code&gt; 字段内容。&lt;/p&gt;

&lt;p&gt;完成排查之后，可以再次编辑 &lt;code&gt;sidecar-injector&lt;/code&gt; Deployment 对象，清除新加入的参数。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>大闹 KubeCon：Istio 已成 Cloud Native 新宠？</title>
      <link>/post/has-istio-become-the-new-cn-darling/</link>
      <pubDate>Fri, 14 Dec 2018 17:44:01 +0800</pubDate>
      <guid>/post/has-istio-become-the-new-cn-darling/</guid>
      <description>&lt;p&gt;原文：&lt;a href=&#34;https://www.geekwire.com/2018/kubecon-week-istio-become-new-cloud-native-darling/&#34; target=&#34;_blank&#34;&gt;Crashing KubeCon: Has Istio become the new cloud-native darling?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/tomkrazit&#34; target=&#34;_blank&#34;&gt;Tom Krazit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这是非比寻常的一年。&lt;/p&gt;

&lt;p&gt;过去几年里，Kubernetes 已经成为云计算领域中最重要的开源项目，&lt;a href=&#34;https://events.linuxfoundation.org/events/kubecon-cloudnativecon-north-america-2018/&#34; target=&#34;_blank&#34;&gt;2018 年的北美 Kubecon&lt;/a&gt; 吸引了 8000 多人聚集在西雅图，比去年的&lt;a href=&#34;https://www.geekwire.com/2017/kubernetes-2018-going-gets-good-good-get-boring/&#34; target=&#34;_blank&#34;&gt;奥斯丁&lt;/a&gt;多出了一倍多。但是不少公司都推出了基于 Istio 的托管服务，容器编排项目在本次 &lt;a href=&#34;https://events.linuxfoundation.org/events/kubecon-cloudnativecon-north-america-2018/&#34; target=&#34;_blank&#34;&gt;KubeCon&lt;/a&gt; 上的热度大受影响。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://www.geekwire.com/2017/kubernetes-matures-cloud-native-movement-turns-attention-service-mesh/&#34; target=&#34;_blank&#34;&gt;随着 Kubernetes 的成熟，云原生的注意力开始转向了服务网格&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google 计划周二在 KubeCon 上宣布，服务网格技术的标志性产品——&lt;a href=&#34;https://istio.io/&#34; target=&#34;_blank&#34;&gt;Istio&lt;/a&gt;，现已在谷歌云上提供了测试版的托管服务，VMware 和 F5 也在本周介绍了各自的 Istio 托管服务，波特兰的 Twistlock 在周一宣布，该公司的旗舰产品已经提供了对 Istio 的支持。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.geekwire.com/2017/ibm-google-lyft-team-open-source-project-control-microservices/&#34; target=&#34;_blank&#34;&gt;Istio 是一个由 Google、IBM 和 Lyft 合作开发的开源项目&lt;/a&gt;，为开发&lt;a href=&#34;(https://www.geekwire.com/2018/google-doubles-service-mesh-hybrid-cloud-kicks-off-big-cloud-event/)&#34; target=&#34;_blank&#34;&gt;微服务应用&lt;/a&gt;的公司提供帮助，来应对微服务架构所引发的网络复杂性问题。它能够控制构成应用的服务之间的流量，还增强了微服务的安全性和可见性。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.geekwire.com/2017/seattles-pitchbook-making-multiyear-infrastructure-shift-microservices-speed-kills/&#34; target=&#34;_blank&#34;&gt;微服务让公司可以将服务拆分&lt;/a&gt;成为更小的更专门的代码，这些拆分出来的单元能够根据需求进行独立的调整和更新。过去的单体应用的代码是一个大的整体，这种架构对很多类型的应来说都是好的；但如果按照现代分布式应用的要求进行快速更新的话，这种应用就存在很大风险了。&lt;/p&gt;

&lt;p&gt;Jennifer Lin 是 Google 云的工程主管，她说“我们很多银行客户说，希望能够更快的开发移动版的银行应用，但也不想让安全和监控方面的功能滞后实现”。&lt;/p&gt;

&lt;p&gt;去年十一月的一个采访中，Google 的 &lt;a href=&#34;https://www.geekwire.com/2017/googles-urs-holzle-still-thinks-cloud-revenue-will-catch-ad-revenue-maybe-not-2020/&#34; target=&#34;_blank&#34;&gt;Urs Hölzle 说&lt;/a&gt;，Istio 可能会比 Kubernetes 本身更加重要。一个月后，奥斯丁的 KubeCon 2017 上就可以清晰的觉察到，在 Kubernetes 成为容器编排界的实施标准之后，&lt;a href=&#34;https://www.geekwire.com/2017/kubernetes-matures-cloud-native-movement-turns-attention-service-mesh/&#34; target=&#34;_blank&#34;&gt;服务网格正在成为下一个重要领域&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;Lin 说：“从我们的客户和合作伙伴获知，正在开发的应用，90% 都是以容器化微服务的方式实现的”。&lt;/p&gt;

&lt;p&gt;但是，尽管谷歌和 IBM 希望 Istio 能成为服务网格世界中的 Kubernetes，包括一些顶级公司在内的开发和运维人员都对 Istio 这种自上而下的方法提出了抱怨——又是一个事实标准。&lt;/p&gt;

&lt;p&gt;Istio 是一个控制平面，它建立在数据面的基础之上——正如 Kubernetes 是 Docker 容器的控制面一样。Istio 和 &lt;a href=&#34;https://www.envoyproxy.io/&#34; target=&#34;_blank&#34;&gt;Envoy&lt;/a&gt; 有着紧密的联系，这个来自 Lyft 的数据平面是一个 CNCF 成员项目，其中已经包含了一些用于管理服务网格的方法。&lt;/p&gt;

&lt;p&gt;去年，两个前 Twitter 工程师建立了 Buoyant，这个创业公司的 Linkerd 数据平面也是 CNCF 成员，还是 KubeCon 的赞助商。&lt;a href=&#34;https://techcrunch.com/2018/12/10/solo-io-raises-11m-to-help-enterprises-adopt-cloud-native-technologies/&#34; target=&#34;_blank&#34;&gt;Solo.io&lt;/a&gt;在本周破土而出，其 Gloo 产品获得了 Redpoint Ventures 和 True Ventures的 1100 万美元投资，该产品也是在 Envoy 的基础上运行的，用于协调微服务之间以及其它云原生工具之间的流量。&lt;/p&gt;

&lt;p&gt;HashiCorp 的 Consul 产品也刚刚获得了一亿美元的投入，用于推进服务网格方面的技术工作。AWS 这只巨兽，也在 re:Invent 2018 会议上&lt;a href=&#34;https://aws.amazon.com/blogs/compute/introducing-aws-app-mesh-service-mesh-for-microservices-on-aws/&#34; target=&#34;_blank&#34;&gt;发布了基于 Envoy 的服务网格产品&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;Istio 的优势是，它可以管理用户选择的任何数据平面用于完成微服务之间的连接，包括 Envoy、Linkerd 或者其它，对于使用 Kubernetes 进行容器管理的用户来说，Istio 是个非常友好的产品。然而在 KubeCon 的鸡尾酒会上给人一种感觉，多数企业计算客户仍然在追赶云计算时代，微服务还为时尚早。&lt;/p&gt;

&lt;p&gt;正如 &lt;a href=&#34;https://techcrunch.com/2015/07/21/as-kubernetes-hits-1-0-google-donates-technology-to-newly-formed-cloud-native-computing-foundation-with-ibm-intel-twitter-and-others/&#34; target=&#34;_blank&#34;&gt;2015 年的 Kubernetes&lt;/a&gt;，像 Google 这样的大型网络运营商在提供分布式微服务时所面临的问题，并不是随处可见的，因此 Istio 的优势可能还要几年才能得以显现。但是如果更多公司开支考虑&lt;a href=&#34;https://www.geekwire.com/2018/travel-giant-sabre-bets-big-multicloud-signing-new-deal-microsoft-azure-weeks-new-deal-amazon-web-services/&#34; target=&#34;_blank&#34;&gt;跨供应商的多云方案&lt;/a&gt;，Istio 可能因为在这一进程中起到重要作用而得以加速推广。&lt;/p&gt;

&lt;p&gt;另外一个 AWS 或者微软这样的主流云供应商，如果提供了托管 Istio 服务来和 Google 对抗，就意味着服务网格时代真的到来了。这两个公有云巨头在 2017 年刚刚开始提供托管的 Kubernetes 服务，代表着这一项目已经打败众多对手，并且成为这方面的实际标准。&lt;/p&gt;

&lt;p&gt;推广 Istio 是对公司推动的开源项目的市场能力的一个有趣测试，&lt;a href=&#34;https://www.geekwire.com/2018/open-source-companies-considering-closed-approach/&#34; target=&#34;_blank&#34;&gt;这一主题还会保持热度&lt;/a&gt;，如果可能的话，注册一个 IstioCon 商标吧。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - Pilot</title>
      <link>/post/istio-helm-deep-dive-pilot/</link>
      <pubDate>Sun, 02 Dec 2018 15:44:38 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-pilot/</guid>
      <description>

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;Pilot 也是 Istio 的核心组件，负责以下任务：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;监听注册中心，例如 Kubernetes 中的服务信息变化。&lt;/li&gt;
&lt;li&gt;监听 Istio 的路由相关 CRD 资源。&lt;/li&gt;
&lt;li&gt;两项内容结合，生成 Envoy 可以理解的配置信息发送给 Envoy。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;values-yaml-中的全局变量&#34;&gt;values.yaml 中的全局变量&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  enabled: true
  replicaCount: 1
  autoscaleMin: 1
  autoscaleMax: 5
  image: pilot
  sidecar: true
  traceSampling: 1.0
  # Resources for a small pilot install
  resources:
    requests:
      cpu: 500m
      memory: 2048Mi
  env:
    PILOT_PUSH_THROTTLE_COUNT: 100
    GODEBUG: gctrace=2
  cpu:
    targetAverageUtilization: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;image&lt;/code&gt; 字段使用的镜像名为 &lt;code&gt;pilot&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;老生常谈的 HPA 部分和其他组件区别不大，实例数量的上限为 5。&lt;/p&gt;

&lt;p&gt;值得注意的是 Pilot 的资源设置，缺省 CPU 500m，内存 2G，比其它组件来说是比较大的。这里还特意注明，这是针对小负载情况的。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sidecar&lt;/code&gt; 参数看来可以启用或者关闭 Pilot 组件的 Sidecar 注入。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;traceSampling&lt;/code&gt;、&lt;code&gt;PILOT_PUSH_THROTTLE_COUNT&lt;/code&gt; 和 &lt;code&gt;GODEBUG&lt;/code&gt;，目测都是性能向的参数。可以在后面的 Chart 中进行求证。&lt;/p&gt;

&lt;h2 id=&#34;rbac-相关&#34;&gt;RBAC 相关&lt;/h2&gt;

&lt;p&gt;授权部分，Pilot 的 ServiceAccount 为：&lt;code&gt;istio-pilot-service-account&lt;/code&gt;，从 &lt;code&gt;clusterrole.yaml&lt;/code&gt; 可以看到较多门类的权限：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;名称&lt;/th&gt;
&lt;th&gt;权限&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config.istio.io/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mixer 使用此配置对象将数据送入 Adapter。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rbac.istio.io/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只读&lt;/td&gt;
&lt;td&gt;RBAC 相关配置。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;networking.istio.io/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;流量控制相关配置。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;authentication.istio.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;认证策略相关配置。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apiextensions.k8s.io/customresourcedefinitions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kubernetes CRD。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;extensions/thirdpartyresources&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kubernetes TPR，1.8 以后已经弃用。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;extensions/thirdpartyresources.extensions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TPR 的扩展资源。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;extensions/ingresses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kubernetes Ingress 资源。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;configmaps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读写&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;endpoints&lt;/code&gt;, &lt;code&gt;pods&lt;/code&gt;, &lt;code&gt;services&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;namespaces&lt;/code&gt;, &lt;code&gt;nodes&lt;/code&gt;, &lt;code&gt;secrets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;gateway-yaml&#34;&gt;gateway.yaml&lt;/h2&gt;

&lt;p&gt;这个文件中包含了三个 Gateway 对象，用于&lt;a href=&#34;https://istio.io/zh/docs/setup/kubernetes/mesh-expansion/&#34; target=&#34;_blank&#34;&gt;网格扩展功能&lt;/a&gt;。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;istio-autogenerated-k8s-ingress&lt;/code&gt;：在 80 端口提供 http 边缘监听服务。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;meshexpansion-gateway&lt;/code&gt;：用于 MeshExpanshion，如果启用了 &lt;code&gt;global.meshExpansion&lt;/code&gt;，则创建 Gateway，在边缘提供 15011 的 Pilot 访问，以及 8060 的 citadel 组件访问。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;meshexpansion-ilb-gateway&lt;/code&gt;：如果启用了 &lt;code&gt;global.meshExpansionILB&lt;/code&gt;，则创建该对象，在内部网关中公开 Pilot 和 Citadel 的端口。&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;istio-autogenerated-k8s-ingress&lt;/code&gt; 对象其实是个 Bug，它使用了 &lt;code&gt;global.k8sIngressSelector&lt;/code&gt; 作为 Gateway 控制器，也就是说只有在 &lt;code&gt;global.ingress.enabled&lt;/code&gt; 为 True 的情况下才有可用的 Gateway 提供服务，这部分应该使用条件判断确定是否包含。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;meshexpansion-yaml&#34;&gt;meshexpansion.yaml&lt;/h2&gt;

&lt;p&gt;这个文件很明显也是用于网格扩展的。事实上这一文件和 &lt;code&gt;gateway.yaml&lt;/code&gt; 是一体的，今后可能会做合并。&lt;/p&gt;

&lt;p&gt;如果启用了 &lt;code&gt;global.meshExpansion&lt;/code&gt; 或者 &lt;code&gt;global.meshExpansionILB&lt;/code&gt;，会为 &lt;code&gt;gateway.yaml&lt;/code&gt; 中生成的 Gateway 创建 &lt;code&gt;VirtualService&lt;/code&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;meshexpansion-pilot&lt;/code&gt;：从边缘进入的 Pilot 请求，访问 &lt;code&gt;pilot.istio-system&lt;/code&gt; 主机时，如果端口为 15011，则指向 &lt;code&gt;istio-pilot.istio-system.svc.cluster.local&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ilb-meshexpansion-pilot&lt;/code&gt;：从内部网管进入的请求，访问主机为 &lt;code&gt;meshexpansionilb.istio-system&lt;/code&gt;，将 &lt;code&gt;15011&lt;/code&gt;、&lt;code&gt;15010&lt;/code&gt; 以及 &lt;code&gt;5353&lt;/code&gt; 端口分别转向到 &lt;code&gt;istio-pilot&lt;/code&gt; 明文端口、&lt;code&gt;istio-pilot&lt;/code&gt; mTLS 端口以及 DNS 服务的  53 端口。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;deployment-yaml&#34;&gt;deployment.yaml&lt;/h2&gt;

&lt;p&gt;主进程为 &lt;a href=&#34;https://istio.io/docs/reference/commands/pilot-discovery/&#34; target=&#34;_blank&#34;&gt;Pilot Discovery&lt;/a&gt;。注解部分要求不进行自动注入。&lt;/p&gt;

&lt;p&gt;除了 Chart 和 Release 之外，Pilot 的 Deployment 模板还引用了几个其它的全局变量。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;image&lt;/code&gt;：和其它核心组件类似，Pilot 中对 &lt;code&gt;image&lt;/code&gt; 的值如果包含了 &lt;code&gt;/&lt;/code&gt;，则会忽略 &lt;code&gt;hub&lt;/code&gt; 的内容，可以方便的替换为内网镜像。&lt;/li&gt;
&lt;li&gt;模板 &lt;code&gt;istio.configmap.checksum&lt;/code&gt;：来自 &lt;code&gt;templates/_helpers.tpl&lt;/code&gt;，Istio chart 中的 &lt;code&gt;/templates/configmap.yaml&lt;/code&gt; 文件的校验和。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.priorityClassName&lt;/code&gt;：&lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority&#34; target=&#34;_blank&#34;&gt;Pod 优先级&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.imagePullPolicy&lt;/code&gt;：镜像拉取策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.oneNamespace&lt;/code&gt;：如果启用了这一参数，则会在主进程参数中加入 &lt;code&gt;-a {{ .Release.Namespace }}&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sidecar&lt;/code&gt;：如果为 &lt;code&gt;True&lt;/code&gt;，会进行如下操作：

&lt;ul&gt;
&lt;li&gt;在 Pod 中注入 &lt;code&gt;istio-proxy&lt;/code&gt; 容器，这一容器会根据 &lt;code&gt;global.controlPlaneSecurityEnabled&lt;/code&gt; 设置，决定 &lt;code&gt;controlPlaneAuthPolicy&lt;/code&gt; 的值为 &lt;code&gt;MUTUAL_TLS&lt;/code&gt; 还是 &lt;code&gt;NONE&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;注入容器的资源设置来自于 &lt;code&gt;global.proxy.resources&lt;/code&gt; 或 &lt;code&gt;global.defaultResources&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sidecar&lt;/code&gt; 如果为 &lt;code&gt;False&lt;/code&gt;，会进行如下操作：

&lt;ul&gt;
&lt;li&gt;设置启动参数 &lt;code&gt;--secureGrpcAddr&lt;/code&gt; 为 &lt;code&gt;15011&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;开放容器端口 &lt;code&gt;15011&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;env&lt;/code&gt;：如果设置了 &lt;code&gt;key: value&lt;/code&gt; 类型的环境变量，此处会发送给 Pilot 进程。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;traceSampling&lt;/code&gt;：跟踪取样率，会被设置到 &lt;code&gt;PILOT_TRACE_SAMPLING&lt;/code&gt; 环境变量中。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nodeaffinity&lt;/code&gt; 模板：来自 &lt;code&gt;templates/_affinity.tpl&lt;/code&gt;，用于设置节点亲和性。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;service.yaml&lt;/h2&gt;

&lt;p&gt;这里并无特殊设置，开放如下几个端口：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;15010：gRPC 的 xDS 端口&lt;/li&gt;
&lt;li&gt;15011：mTLS 的 xDS 端口&lt;/li&gt;
&lt;li&gt;8080：传统 http 端口&lt;/li&gt;
&lt;li&gt;9093：监控端口&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;对 Pilot 的资源设置较大，同时 1.0.0 之后屡次出现 Pilot 内存消耗巨大的 Issue，其中的跟踪采样、GC 调试以及 Sidecar 注入方面应该都还有挖掘的潜力。但是很可惜 Pilot 的环境变量并无文档，须待日后进一步完善。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>云原生世界中的隐形人如何拥抱 Istio</title>
      <link>/post/invisible-men-in-the-world-of-cloudnative/</link>
      <pubDate>Wed, 21 Nov 2018 14:39:50 +0800</pubDate>
      <guid>/post/invisible-men-in-the-world-of-cloudnative/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;一直想给我所从事的企业服务行业写点啥，又千头万绪不知从何说起。此次 KubeCon 上海一行，眼见 CNCF 高起朱楼大宴宾客，深受触动。企业服务这个巨大的“角落”，似乎已被遗忘。本文尝试给云原生时代的同学们讲讲这个似乎有点蒙昧的角落。也希望能给奋斗在企业服务项目中的朋友们一点启发。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;谁是隐形人&#34;&gt;谁是隐形人&lt;/h2&gt;

&lt;p&gt;身为一个企业服务部门的 IT 工人，在为甲方殚精竭虑的同时，经常有一种跟世界脱节的感觉：流量经济持续不断的冲刷之下，微服务、云原生等新的架构和概念如火如荼；大咖说、InfoQ 等各色机构的活动也是越来越多；新技术产品和新技术偶像层出不穷。云原生时代以来，更大的困扰出现了：漫山遍野的“免费”、“开源”技术，似乎难于学习、无力推进、更不要说做出贡献了。&lt;/p&gt;

&lt;p&gt;各种困境各种难，让这一人群成为了一种隐身的状态：大会的讲台上下、热门的书籍和公众号、开源社区的贡献和参与统统都和他们毫无瓜葛，似乎只剩下了偶尔出现的产业新闻和咨询案例，才能提供一个“可能还在做技术”的证明。隐形人的一些生存特点：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;产品一般称为 “XXXX 管理系统”。&lt;/li&gt;
&lt;li&gt;在甲方自有数据中心或托管服务器上运行。&lt;/li&gt;
&lt;li&gt;硬件利用率不高，相对硬件规模来说，业务规模相当小。&lt;/li&gt;
&lt;li&gt;令出多头，一些工作内容可能需要多个公司/部门之间的配合。&lt;/li&gt;
&lt;li&gt;基础设施群之间，通常会采用传统的多分区、白名单系统来保证隔离。&lt;/li&gt;
&lt;li&gt;开发环境和生产环境之间经常会没有高速网络连接。&lt;/li&gt;
&lt;li&gt;上线活动需逐级审批、定时定点停服更新。&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在这种令人惶惑的情形之下，CNCF、微服务浪潮的出现更加剧了隐形人们的生存危机。尤其是台上大佬们大声疾呼——XX 产品那德行，不改还能用？这种时候，隐形人就更害怕了——我还没学会安装那！大佬们已经上手改了！还怎么活啊！&lt;/p&gt;

&lt;h2 id=&#34;几个问题&#34;&gt;几个问题&lt;/h2&gt;

&lt;h3 id=&#34;开源软件到底能不能用&#34;&gt;开源软件到底能不能用&lt;/h3&gt;

&lt;p&gt;首先要相信，世界上是很有些聪明人的。&lt;/p&gt;

&lt;p&gt;Apache 和 CNCF 都有严格的准入控制，对成熟度有明确的要求，同时热度够高的项目通常会吸引较多的高水平贡献者加入。高成熟度的系统。质量总体来说还是有一定保障的。&lt;/p&gt;

&lt;h3 id=&#34;大佬说不改就不能用是个什么情况&#34;&gt;大佬说不改就不能用是个什么情况&lt;/h3&gt;

&lt;p&gt;这通常是来自百度阿里京东蚂蚁等流量大厂的大佬们的呐喊，并不算是危言耸听。但是有个前提，就是国内几个巨头的流量和应用特点，都是属于极端情况。通常说来，并不会有哪个开源组织，有闲心又有能力，丧心病狂的做出能丢给几大厂一个直接可用适用的大系统。反过来说，经过大厂魔改的系统，很可能不再具备原有版本的普适性以及升级能力。作为透明人的 Istio 体验，应该遵循应用和 Istio 都无伤的做法。&lt;/p&gt;

&lt;h3 id=&#34;等前辈们踩过了坑我们再上会更稳妥&#34;&gt;等前辈们踩过了坑我们再上会更稳妥&lt;/h3&gt;

&lt;p&gt;这是个很不现实的想法，各家公司各个项目的情况千差万别，这些坑还是要自己踩的，多数情况下没人能够用微信帮你完成工作。&lt;/p&gt;

&lt;h3 id=&#34;生产应用-性能问题-解决了么&#34;&gt;生产应用/性能问题/..解决了么&lt;/h3&gt;

&lt;p&gt;其实这跟上一个问题是一体的，通常需要用户自行严格按照生产环境标准进行相应的测试。&lt;/p&gt;

&lt;p&gt;这里有一个前提，如果采用新的系统对现有系统的性能是有影响的，那么首先应该保证，技术团队有能力应对现有的业务负载，这样通过对新系统的学习，才能够有一个合适的技术基础。对一个服务进行容器化改造，不要希望它的容器化成功之后，立刻就出现十倍的性能提升。稳妥的方式是水平迁移稳定之后，才进一步的挖掘新技术的性能潜力。&lt;/p&gt;

&lt;h3 id=&#34;我们没有上-kubernetes&#34;&gt;我们没有上 Kubernetes&lt;/h3&gt;

&lt;p&gt;这一点上，我认为答案很简单，Istio 并不适合你。&lt;/p&gt;

&lt;h2 id=&#34;istio-的试点&#34;&gt;Istio 的试点&lt;/h2&gt;

&lt;p&gt;这两天学习了小剑同学在上海 ServiceMesh Meetup 上的演讲，在仰望蚁人们在面临棘手情况时展露出来的强大实力的同时，也有一些窃喜——在我们隐形人的隐形系统中，可没这么多麻烦。我们只求在原装系统的支持下，获得其有限的好处。&lt;/p&gt;

&lt;h3 id=&#34;为什么采用-istio&#34;&gt;为什么采用 Istio&lt;/h3&gt;

&lt;p&gt;首先要判断的是，这一系统对我们来说有什么好处，除了官方各种宣传之外，可能还会有一些边际效应，例如采用新系统带来的光环、声明式操作提高了对环境和配置的控制能力等。Istio 的官宣好处非常之多，然而按照开源系统通常的晚熟状况，我们可以仅挑选一些对我们促进最大的亮点来进行验证和测试，对于一些难于掌握的复杂特性或不稳定特性，可以徐徐图之——或者叫眼不见为净。&lt;/p&gt;

&lt;p&gt;而存量应用经常会比较落后于时代，经过各种补丁和重构，以及或真或假的微服务改造之后，往往会变成杂乱不堪的应用丛林；经过 Kubernetes 迁移之后，得益于 K8S 的支持，具备了容器调度、服务注册和发现、初步的配置管理等能力。&lt;/p&gt;

&lt;h4 id=&#34;服务监控和跟踪-高性价比-推荐&#34;&gt;服务监控和跟踪（高性价比，推荐）&lt;/h4&gt;

&lt;p&gt;现存应用的监控和跟踪通常都是比较欠缺的，Istio 能轻松的为应用注入这两种能力，熟悉 Istio 的用户可能会质疑，分布式跟踪还是要求对代码做出一定改动的，本着能不动就不动的原则，仅获取一对一调用的跟踪信息，也是一个巨大的进步。在这一功能的基础上形成的统一 Dashboard 对存量应用的增值会有非常大的帮助。&lt;/p&gt;

&lt;h4 id=&#34;流量控制-高性价比-推荐&#34;&gt;流量控制（高性价比，推荐）&lt;/h4&gt;

&lt;p&gt;这是 Istio 的核心功能，应该也是使用率最高的功能，这一功能有效的增强了基于 K8S 的应用支撑，对存量应用的通信控制大幅增强。并且在新应用的开发中，可以协助架构师将部分通信细节延后到部署和运维阶段来实现，也降低了新应用的开发难度。流量控制能力中的超时和重发等小功能，都能很好的提高存量应用的健壮性；而路由部分还为现有应用提供了金丝雀发布和蓝绿部署之类的新能力。&lt;/p&gt;

&lt;h4 id=&#34;边缘通信-刚需可用&#34;&gt;边缘通信（刚需可用）&lt;/h4&gt;

&lt;p&gt;这部分的功能通常会使用硬件负载均衡和其它相关的基础设施来实现，因此可以暂不考虑。&lt;/p&gt;

&lt;h4 id=&#34;mtls-和访问控制-刚需可用&#34;&gt;mTLS 和访问控制（刚需可用）&lt;/h4&gt;

&lt;p&gt;这部分功能在我们的情况中较少遇到，内网中的服务经常是无需访问控制和加密的，因此仅在存在刚需时候可以尝试使用。&lt;/p&gt;

&lt;h4 id=&#34;限流等其它-mixer-功能-慎用&#34;&gt;限流等其它 Mixer 功能（慎用）&lt;/h4&gt;

&lt;p&gt;Mixer 是 Istio 中比较遭人诟病的一个组件，强大但是难于驾驭，并且具体实现又依赖于各个 Adapter，因此这部分功能建议押后采纳。&lt;/p&gt;

&lt;h3 id=&#34;试点服务的选择&#34;&gt;试点服务的选择&lt;/h3&gt;

&lt;p&gt;Sidecar 注入导致的延迟是众所周知的，因此我们会选择调用链条较短、延迟不很敏感的应用来进行试点。&lt;/p&gt;

&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;

&lt;h3 id=&#34;环境准备&#34;&gt;环境准备&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;检查 Kubernetes 版本是否符合要求。&lt;/li&gt;
&lt;li&gt;检查试点应用的 Service 是否符合注入要求。&lt;/li&gt;
&lt;li&gt;为试点应用在负载均衡或其它类似基础设施上做好切换准备，防止故障无法恢复。&lt;/li&gt;
&lt;li&gt;获取 Istio 镜像文件并上传到私库。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;安装-istio&#34;&gt;安装 Istio&lt;/h3&gt;

&lt;p&gt;根据选择功能，对 Istio 的 &lt;code&gt;values.yaml&lt;/code&gt; 进行定制，因为是局部试点，不建议使用自动注入方式。另外原始设置中对资源的配置比较谨慎，这里建议适当放大。最后是对于镜像库等的地址进行设置。&lt;/p&gt;

&lt;p&gt;备份 &lt;code&gt;values.yaml&lt;/code&gt; 并部署 Istio，根据实际情况为 Dashboard 等管理功能设置 &lt;code&gt;Ingress&lt;/code&gt;/&lt;code&gt;NodePort&lt;/code&gt; 等开放方式。&lt;/p&gt;

&lt;h3 id=&#34;应用部署&#34;&gt;应用部署&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;加大试点应用的 Deployment 中的实例数量，降低 Istio 开销造成的损耗。&lt;/li&gt;
&lt;li&gt;为试点应用编写缺省路由和目标规则。和 Kubernetes 资源等同样纳入交付物的版本管理中。&lt;/li&gt;
&lt;li&gt;如果使用的是 CI/CD，建议在其中加入注入环节。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;部署完成之后，应该进行功能、压力、疲劳等一系列测试，来完成验证。&lt;/p&gt;

&lt;h3 id=&#34;应用上线&#34;&gt;应用上线&lt;/h3&gt;

&lt;p&gt;负载均衡进行切换，将 Istio 转入生产服务。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;以上步骤执行下来，最终我们用较小的代价，换来较大的系统改观，让传统应用像服务网格一样的运行了起来。另外在系统负载较低的情况下，Istio 的稳定性还是比较有保障的。最终，我们也保留了随时回滚的能力。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>在 Knative 中进行应用程序的构建和部署</title>
      <link>/post/building-and-deploying-applications-to-knative/</link>
      <pubDate>Tue, 13 Nov 2018 00:10:38 +0800</pubDate>
      <guid>/post/building-and-deploying-applications-to-knative/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://starkandwayne.com/blog/building-and-deploying-applications-to-knative/&#34; target=&#34;_blank&#34;&gt;Building and deploying applications to Knative&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/starkandwayne&#34; target=&#34;_blank&#34;&gt;Dr Nic Williams&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knative 有三个高级子系统：Serving 用来协调服务 Pod 的自动伸缩以及路由；Build 提供了将代码转换为镜像的工具链；Eventing 则会使用事件的发布订阅来触发松耦合服务。&lt;/p&gt;

&lt;p&gt;前一篇文章中我们将一个构件好的容器镜像发布到了 Knative Serving 中。&lt;/p&gt;

&lt;p&gt;本篇文章将使用 Knative Build 把我们的应用通过 Dockerfile 以及 Cloud Foundry buildpack 在发布过程中转化为容器镜像。我们还会尝试从本地文件系统以及远程 Git 仓库中进行部署的方式。&lt;/p&gt;

&lt;p&gt;前面的操作都很简单，看得出在 Kubernetes 环境中安装 Knative、运行现有容器镜像、使用 curl 与应用进行交互都不难。总结一下就是：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl install [--node-ports] [--exclude-monitoring]
knctl deploy --service &amp;lt;service-name&amp;gt; --image &amp;lt;image-name&amp;gt;
knctl curl --service &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;后面的两步 - 把镜像部署为 Kubernetes 并运行，为每个部署进行版本化处理，使用 HTTP 路由进行交互，都是 &lt;a href=&#34;https://github.com/knative/serving/blob/master/docs/spec/overview.md&#34; target=&#34;_blank&#34;&gt;Serving 子系统&lt;/a&gt;的功劳。&lt;/p&gt;

&lt;p&gt;Knative 还支持用于构建容器镜像的弹性子系统，构建生成的镜像将会以 Kubernetes Pod 的形式运行。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/knative/docs/tree/master/build&#34; target=&#34;_blank&#34;&gt;Knative Build&lt;/a&gt; 子系统非常有弹性。我们会探讨集中用例：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;上传一个本地目录，使用 Dockerfile 进行构建。&lt;/li&gt;
&lt;li&gt;上传一个本地目录，使用 Buildpack 进行构建。&lt;/li&gt;
&lt;li&gt;用上面两种方式来构建来自于远程 Git 仓库的代码。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;命名空间&#34;&gt;命名空间&lt;/h2&gt;

&lt;p&gt;前一篇文章中我们在每个 &lt;code&gt;knctl&lt;/code&gt; 命令中使用了 &lt;code&gt;--namespace helloworld&lt;/code&gt; 参数来显式的指定命名空间。对我来说这样显得更清晰。可能有别的用户希望设置一个缺省命名空间，从而能够缩短命令。&lt;/p&gt;

&lt;p&gt;可以给 &lt;code&gt;knctl&lt;/code&gt; 配置一个当前命名空间：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl create ns my-simple-app
export KNCTL_NAMESPACE=my-simple-app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;所有的 &lt;code&gt;knctl&lt;/code&gt; 命令都会使用这一命名空间。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ knctl service list
Services in namespace &#39;my-simple-app&#39;

Name  Domain  Annotations  Age

0 services
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以在 &lt;code&gt;kubectl&lt;/code&gt; 命令中复用 &lt;code&gt;$KNCTL_NAMESPACE&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get pods -n $KNCTL_NAMESPACE&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;上传一个带有-dockerfile-的本地目录&#34;&gt;上传一个带有 Dockerfile 的本地目录&lt;/h2&gt;

&lt;p&gt;在所有 Knative Build 的示例中，都会产生一个副产品——容器镜像。这些镜像必须放在什么地方，例如 &lt;a href=&#34;https://hub.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker Hub&lt;/a&gt;、&lt;a href=&#34;https://cloud.google.com/container-registry/&#34; target=&#34;_blank&#34;&gt;GCP 容器库&lt;/a&gt;、&lt;a href=&#34;https://azure.microsoft.com/en-au/services/container-registry/&#34; target=&#34;_blank&#34;&gt;Azure 容器库&lt;/a&gt;，或者借助 &lt;a href=&#34;https://goharbor.io/&#34; target=&#34;_blank&#34;&gt;Harbor&lt;/a&gt; 之类的软件自建的私库。&lt;/p&gt;

&lt;p&gt;我们需要在每个应用所在的 Kubernetes 命名空间中给 Knative 配置一个镜像库，然后 &lt;code&gt;knctl basic-auth-secret create&lt;/code&gt; 给 Knative 配置一个 Secret。&lt;/p&gt;

&lt;p&gt;以 Docker Hub 为例，使用 &lt;code&gt;--docker-hub&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --docker-hub -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;GCP 容器仓库可以使用 &lt;code&gt;--gcr&lt;/code&gt; 选项：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --gcr -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其它私库可以使用 &lt;code&gt;--type&lt;/code&gt; 和 &lt;code&gt;--url&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --type docker --url https://registry.domain.com/ -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一步把镜像库 Secret 映射到 &lt;a href=&#34;https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/&#34; target=&#34;_blank&#34;&gt;Kubernetes Service account&lt;/a&gt;，它会在 Knative Build 的 Pod 中提供上面的登录信息。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl service-account create --service-account build -s registry
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这个操作会体现在 Kubernetes 的 Service account 中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get serviceaccount -n $KNCTL_NAMESPACE
NAME      SECRETS   AGE
build     2         37s
default   1         3h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样我们就准备好使用 Knative Build 创建新容器镜像所需的认证凭据了。&lt;/p&gt;

&lt;p&gt;Clone 一个 Go 应用作为样例，并从它的本地目录推送到 Docker hub：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;git clone https://github.com/cppforlife/simple-app
cd simple-app

DOCKER_IMAGE=index.docker.io/&amp;lt;your hub.docker.com org or user&amp;gt;/knative-simple-app

knctl deploy \
    --service simple-app \
    --directory=$PWD \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from local directory using Dockerfile&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;容器的显式命名事实上只是从 Build 到 Serve 的工作过程中的一个中间步骤的副产品，但是必须提供。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 的输出大概是这样的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  simple-app

Waiting for new revision to be created...

Tagging new revision &#39;simple-app-00001&#39; as &#39;latest&#39;

Tagging new revision &#39;simple-app-00001&#39; as &#39;previous&#39;

[2018-10-15T13:18:31+10:00] Uploading source code...

[2018-10-15T13:19:59+10:00] Finished uploading source code...

Watching build logs...

build-step-build-and-push | INFO[0000] Downloading base image golang:1.10.1
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:20:01.547607       1 metadata.go:142] while reading &#39;google-dockercfg&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:20:01.550268       1 metadata.go:159] while reading &#39;google-dockercfg-url&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg-url
build-step-build-and-push | INFO[0001] Executing 0 build triggers
build-step-build-and-push | INFO[0001] Extracting layer 0
build-step-build-and-push | INFO[0003] Extracting layer 1
build-step-build-and-push | INFO[0004] Extracting layer 2
build-step-build-and-push | INFO[0004] Extracting layer 3
build-step-build-and-push | INFO[0007] Extracting layer 4
build-step-build-and-push | INFO[0010] Extracting layer 5
build-step-build-and-push | INFO[0015] Extracting layer 6
build-step-build-and-push | INFO[0015] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0027] WORKDIR /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] cmd: workdir
build-step-build-and-push | INFO[0027] Changed working directory to /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] Creating directory /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] COPY . .
build-step-build-and-push | INFO[0027] RUN CGO_ENABLED=0 GOOS=linux go build -v -o app
build-step-build-and-push | INFO[0027] cmd: /bin/sh
build-step-build-and-push | INFO[0027] args: [-c CGO_ENABLED=0 GOOS=linux go build -v -o app]
build-step-build-and-push | net
build-step-build-and-push | vendor/golang_org/x/net/lex/httplex
build-step-build-and-push | vendor/golang_org/x/net/proxy
build-step-build-and-push | net/textproto
build-step-build-and-push | crypto/x509
build-step-build-and-push | crypto/tls
build-step-build-and-push | net/http/httptrace
build-step-build-and-push | net/http
build-step-build-and-push | github.com/mchmarny/simple-app
build-step-build-and-push | INFO[0030] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0034] Storing source image from stage 0 at path /kaniko/stages/0
build-step-build-and-push | INFO[0038] trying to extract to /kaniko/0
build-step-build-and-push | INFO[0038] Extracting layer 0
build-step-build-and-push | INFO[0040] Extracting layer 1
build-step-build-and-push | INFO[0041] Extracting layer 2
build-step-build-and-push | INFO[0041] Extracting layer 3
build-step-build-and-push | INFO[0043] Extracting layer 4
build-step-build-and-push | INFO[0046] Extracting layer 5
build-step-build-and-push | INFO[0051] Extracting layer 6
build-step-build-and-push | INFO[0051] Extracting layer 7
build-step-build-and-push | INFO[0051] Deleting filesystem...
build-step-build-and-push | INFO[0053] No base image, nothing to extract
build-step-build-and-push | INFO[0053] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0062] COPY --from=0 /go/src/github.com/mchmarny/simple-app/app .
build-step-build-and-push | INFO[0063] Taking snapshot of files...
build-step-build-and-push | INFO[0063] EXPOSE 8080
build-step-build-and-push | INFO[0063] cmd: EXPOSE
build-step-build-and-push | INFO[0063] Adding exposed port: 8080/tcp
build-step-build-and-push | INFO[0063] ENTRYPOINT [&amp;quot;/app&amp;quot;]
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:21:04.751338       1 metadata.go:142] while reading &#39;google-dockercfg&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:21:04.753927       1 metadata.go:159] while reading &#39;google-dockercfg-url&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg-url
build-step-build-and-push | 2018/10/15 03:21:06 pushed blob sha256:72a682eea3309941d5e8e6f993a07ae4d33a413b8b7fa2762f8e969310b5996a
build-step-build-and-push | 2018/10/15 03:21:07 pushed blob sha256:9c24aa788ba416c5e1e631d8af3e3115519ad7ca0f659ac10f40682524c6d9cd
build-step-build-and-push | 2018/10/15 03:21:07 index.docker.io/drnic/knative-simple-app:latest: digest: sha256:b5823ead77d9544998b5bc844f049d1a7dfb0aefe7461b74b3e4f67fb5481fa1 size: 428
nop | Nothing to push

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;knative-build-的调试&#34;&gt;Knative Build 的调试&lt;/h2&gt;

&lt;p&gt;目前 &lt;code&gt;knctl deploy&lt;/code&gt; 没有显示任何来自 Knative Build 系统的内部错误或者警告。只需要看着 &lt;code&gt;Waiting for new revision to be created...&lt;/code&gt; 坐享其成就可以了。&lt;/p&gt;

&lt;p&gt;一个调试方法就是使用 &lt;a href=&#34;https://github.com/boz/kail&#34; target=&#34;_blank&#34;&gt;kail&lt;/a&gt; 工具处理来自 Knative Build 子系统的消息：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kail -n knative-build
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样就会看到大量的日志，可以再其中查找错误信息，例如 &lt;code&gt;&amp;quot;msg&amp;quot;:&amp;quot;Failed the resource specific validation{error 25 0 serviceaccounts \&amp;quot;build\&amp;quot; not found}&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;使用-buildpack-进行构建&#34;&gt;使用 Buildpack 进行构建&lt;/h2&gt;

&lt;p&gt;我本人很喜欢 Cloud Foundry 和 Heroku 的镜像构建方式，幸运的是，Knative Build 通过&lt;a href=&#34;https://github.com/knative/build-templates/tree/master/buildpack&#34; target=&#34;_blank&#34;&gt;自定义构建模板&lt;/a&gt;的方式提供了这种支持。&lt;/p&gt;

&lt;p&gt;首先用 &lt;code&gt;buildpack&lt;/code&gt; 这个名字在活动命名空间中注册一个&lt;a href=&#34;https://github.com/knative/build-templates/blob/master/buildpack/buildpack.yaml&#34; target=&#34;_blank&#34;&gt;构建模板&lt;/a&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl -n $KNCTL_NAMESPACE apply -f \
https://raw.githubusercontent.com/knative/build-templates/master/buildpack/buildpack.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;加入 &lt;code&gt;--template buildpack&lt;/code&gt; 就可以使用这一自定义模板了。构建模板所需的附加环境变量都可以用 &lt;code&gt;--template-env NAME=value&lt;/code&gt; 的方式进行植入。&lt;/p&gt;

&lt;p&gt;例如 Cloud Foundry Go Buildpack 需要 &lt;code&gt;$GOPACKNAME&lt;/code&gt;（&lt;a href=&#34;https://docs.cloudfoundry.org/buildpacks/go/index.html#pushing_Apps_with_native_Go_vendoring&#34; target=&#34;_blank&#34;&gt;参考文档&lt;/a&gt;）：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl deploy \
    --service simple-app \
    --directory=$PWD \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from local directory using Buildpack template&amp;quot; \
    --template buildpack \
    --template-env GOPACKAGENAME=main
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;输出内容和 Cloud Foundry buildpack 是一致的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  simple-app

Waiting for new revision (after revision &#39;simple-app-00001&#39;) to be created...

Tagging new revision &#39;simple-app-00002&#39; as &#39;latest&#39;

Tagging older revision &#39;simple-app-00001&#39; as &#39;previous&#39;

[2018-10-15T13:40:41+10:00] Uploading source code...

[2018-10-15T13:42:08+10:00] Finished uploading source code...

Watching build logs...

build-step-build | -----&amp;gt; Go Buildpack version 1.8.26
build-step-build | -----&amp;gt; Installing godep 80
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/godep/godep-v80-linux-x64-cflinuxfs2-06cdb761.tgz]
build-step-build | -----&amp;gt; Installing glide 0.13.1
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/glide/glide-v0.13.1-linux-x64-cflinuxfs2-aab48c6b.tgz]
build-step-build | -----&amp;gt; Installing dep 0.5.0
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/dep/dep-v0.5.0-linux-x64-cflinuxfs2-52c14116.tgz]
build-step-build | -----&amp;gt; Installing go 1.8.7
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/go/go1.8.7.linux-amd64-cflinuxfs2-fff10274.tar.gz]
build-step-build |        **WARNING** Installing package &#39;.&#39; (default)
build-step-build | -----&amp;gt; Running: go install -tags cloudfoundry -buildmode pie .
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:1124eb40dd68654b8ca8f5d9ec7e439988a4be752a58c8f4e06d60ab1589abdb
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:6be38da025345ffb57d1ddfcdc5a2bc052be5b9491825f648b49913d51e41acb
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:a5733e6358eec8957e81b1eb93d48ef94d649d65c69a6b1ac49f616a34a74ac1
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:21324a9f04e76c93078f3a782e3198d2dded46e4ec77958ddd64f701aecb69c0
build-step-export | 2018/10/15 03:47:59 pushed blob sha256:efa2d34b82bc07588a1a8fd4526322257408109547ee089a792b3f51c383f8e6
build-step-export | 2018/10/15 03:47:59 pushed blob sha256:d495696b33936c79216ec8178726b9fbe915fafbffdd0911a7fdabce4297d9a4
build-step-export | 2018/10/15 03:48:00 index.docker.io/drnic/knative-simple-app:latest: digest: sha256:e5ef1d4d255b4bcbb38d4b43bb6302423c33e6eeabd0e20d5fda4e5ce4c46668 size: 1082
nop | Nothing to push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在就能看到应用已经部署成功：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl -s simple-app
&amp;lt;h1&amp;gt;Built from local directory using Buildpack template&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;私有-git-secret&#34;&gt;私有 Git Secret&lt;/h2&gt;

&lt;p&gt;前面两节我们从本地上传了源码然后构建了 Docker 镜像（使用 Dockerfile 或 Cloud Foundry buildpack），最后运行应用。&lt;/p&gt;

&lt;p&gt;Knative 还能从 Git 仓库获取源码（正式的说法是，Knative Build 只支持从 Git 仓库获取源码，本地代码的支持是 &lt;code&gt;knctl&lt;/code&gt; 提供的）。&lt;/p&gt;

&lt;p&gt;让 Knative Build 获取 Git 仓库中的代码，需要用 &lt;code&gt;--git-url&lt;/code&gt; 和 &lt;code&gt;--git-revision&lt;/code&gt; 来取代 &lt;code&gt;--directory=$PWD&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果你的 Git 仓库是私有的，那就还需要在 Service account（在上面的例子中的 &lt;code&gt;build&lt;/code&gt;）里包含 Git ssh 凭据。&lt;code&gt;knctl ssh-auth-secret create&lt;/code&gt; 能够协助用户创建一个 kubernetes.io/ssh-auth secret。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl ssh-auth-secret create --secret git --github --private-key &amp;quot;$(cat ~/.ssh/id_rsa)&amp;quot;
Name  git
Type  kubernetes.io/ssh-auth

$ kubectl get secrets -n $KNCTL_NAMESPACE
NAME                  TYPE                                  DATA   AGE
...
git                   kubernetes.io/ssh-auth                1      5m
registry              kubernetes.io/basic-auth              2      3h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在需要把 &lt;code&gt;git&lt;/code&gt; secret 加入到我们的 &lt;code&gt;build&lt;/code&gt; Service account 之中了。&lt;/p&gt;

&lt;p&gt;在成文之时，&lt;code&gt;knctl&lt;/code&gt; 还没有提供 &lt;code&gt;knctl serviceaccounts update&lt;/code&gt; 这样的命令，所以需要删除重新创建：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl delete serviceaccounts -n $KNCTL_NAMESPACE build
knctl service-account create --service-account build -s registry -s git
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;从-git-部署&#34;&gt;从 Git 部署&lt;/h2&gt;

&lt;p&gt;用 &lt;code&gt;--git-url&lt;/code&gt; 和 &lt;code&gt;--git-revision&lt;/code&gt; 替代 &lt;code&gt;--directory&lt;/code&gt; 来进行 Git 部署：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl deploy \
    --service simple-app \
    --git-url git@github.com:cppforlife/simple-app.git \
    --git-revision master \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from Git repo using Buildpack template&amp;quot; \
    --template buildpack \
    --template-env GOPACKAGENAME=main
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 命令在 Knative 的基础上提供了创建新镜像的良好体验，可以从本地目录或者 Git 仓库开始，使用 Dockerfile 或 Cloud Foundry buildpack 进行构建，并支持不同的镜像仓库。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>在 Knative 上部署 12 要素应用程序</title>
      <link>/post/deploying-12-factor-apps-to-knative/</link>
      <pubDate>Mon, 12 Nov 2018 00:35:24 +0800</pubDate>
      <guid>/post/deploying-12-factor-apps-to-knative/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://starkandwayne.com/blog/introduction-to-knative/&#34; target=&#34;_blank&#34;&gt;Deploying 12 Factor Apps to Knative&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/starkandwayne&#34; target=&#34;_blank&#34;&gt;Dr Nic Williams&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;我尝试按照本文内容在 Azure 上使用 ACS-Engine 部署的 Kubernetes 上进行了测试，版本部分的案例得到了相反结果，不过还是按照原文发了出来，作为一个获取感性认识的入门还是不错的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google Next18 活动中，Google 宣称将会把 GKE 上的无服务器插件以 &lt;a href=&#34;https://github.com/knative/&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt; 的名称进行开源。当时它被描述为无服务器平台的构建块，由此推断，Knative 可能需要 Google、Pivotal 或者 RedHat 的协助才能使用。这可能是开源的古怪时机。从我最初的摸索来看，Knative 能工作；当我把 Heroku/Cloud Foundry buildpacks 加入进来之后，整个系统变得越来越像 Heroku/Cloud Foundry，相对于原始 Kubernetes，我更加了解和喜爱这一系统。&lt;/p&gt;

&lt;p&gt;本文中我们会将 Knative 安装到你自己的 Kubernetes 集群中（&lt;code&gt;knctl install&lt;/code&gt;），然后用 Knative 做些有趣的事情（&lt;code&gt;knctl deploy&lt;/code&gt;）。&lt;/p&gt;

&lt;p&gt;Knative 能够为在 Kubernetes 集群上运行无状态应用的运维人员带来很多惊喜。对我来说，最引人入胜的一点就是伸缩性：在高负载时候进行扩容，没人喜欢你的应用了，就会一直缩容到 0。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/cppforlife/knctl/releases&#34; target=&#34;_blank&#34;&gt;下载和安装&lt;/a&gt; Knative 客户端工具 &lt;code&gt;knctl&lt;/code&gt;，然后就可以在你的 Kubernetes 上部署 Knative，然后发布你的应用了。&lt;/p&gt;

&lt;p&gt;在 MacOS 中，可以利用我们的 Homebrew tap 进行安装：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install starkandwayne/kubernetes/knctl&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这里我假设你再使用 Minikube。在 Minikube 中，可以使用 Node Port 代替 Load balancer：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;minikube start --memory=8192 --cpus=3 \
  --kubernetes-version=v1.11.3 \
  --vm-driver=hyperkit \
  --bootstrapper=kubeadm

knctl install --node-ports --exclude-monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以参考 &lt;a href=&#34;https://github.com/knative/docs/tree/master/install&#34; target=&#34;_blank&#34;&gt;Knative 文档&lt;/a&gt;来获取在其它类型 Kubernetes 集群上进行部署的要点。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;knctl install&lt;/code&gt; 命令可能要花上几分钟，甚至是十分钟或者更多。这个过程中需要下载大概一打镜像。不管是互联网带宽还是镜像尺寸都可能有变化，所以坐下放松一会，或者出去走走也好。&lt;/p&gt;

&lt;p&gt;如果 &lt;code&gt;knctl install&lt;/code&gt; 失败了，可能是你的 Internet 比较慢，Docker 镜像在命令超时之前还没能完成下载。运行 &lt;code&gt;kubectl get pods --all-namespaces&lt;/code&gt; 直到所有 Pod 都在运行，然后再次运行 &lt;code&gt;knctl install&lt;/code&gt; 命令继续完成安装过程。&lt;/p&gt;

&lt;p&gt;现在你的 Kubernetes 就是无服务器架构了，不错吧。&lt;/p&gt;

&lt;p&gt;可以运行 &lt;code&gt;kubectl get pods --all-namespaces&lt;/code&gt; 看看原始的 Knative 的 Pod 们。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ kubectl get pods --all-namespaces
NAMESPACE         NAME                                        READY   STATUS      RESTARTS   AGE
istio-system      istio-citadel-7d8f9748c5-zgm9x              1/1     Running     0          21m
istio-system      istio-cleanup-secrets-j4pkx                 0/1     Completed   0          21m
istio-system      istio-egressgateway-676c8546c5-dnwsd        1/1     Running     0          21m
istio-system      istio-galley-5669f7c9b-g774b                1/1     Running     0          21m
istio-system      istio-ingressgateway-5475685bbb-q5f2x       1/1     Running     0          21m
istio-system      istio-pilot-5795d6d695-9klrz                2/2     Running     0          21m
istio-system      istio-policy-7f945bf487-2wh88               2/2     Running     0          21m
istio-system      istio-sidecar-injector-d96cd9459-7knkm      1/1     Running     0          21m
istio-system      istio-statsd-prom-bridge-549d687fd9-lcmb7   1/1     Running     0          21m
istio-system      istio-telemetry-6c587bdbc4-t4jql            2/2     Running     0          21m
istio-system      knative-ingressgateway-7f4477dd99-n9wz2     1/1     Running     0          4m
knative-build     build-controller-7dcc4b7544-rkgwb           1/1     Running     0          4m
knative-build     build-webhook-fb6484576-sr4fk               1/1     Running     0          4m
knative-serving   activator-77d46b585d-b6g8n                  2/2     Running     0          4m
knative-serving   controller-85768cfd45-t8ktc                 1/1     Running     0          4m
knative-serving   webhook-56dd548f8-hjw44                     1/1     Running     0          4m
...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;部署预构建的应用&#34;&gt;部署预构建的应用&lt;/h2&gt;

&lt;p&gt;接下来我们试试用一个现有的 Docker 镜像来作为自动伸缩的无状态应用运行到 Knative 上，在当前 Kubernetes 命令空间中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl create ns helloworld

knctl deploy \
      --namespace helloworld \
      --service hello \
      --image gcr.io/knative-samples/helloworld-go \
      --env TARGET=Rev1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;命令执行后会输出一些信息，表明 &lt;code&gt;hello&lt;/code&gt; 服务已经创建，它的第一个版本 &lt;code&gt;hello-00001&lt;/code&gt; 已经创建，并且被标记为 &lt;code&gt;latest&lt;/code&gt; 和 &lt;code&gt;previous&lt;/code&gt;（第一个版本）。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  hello

Waiting for new revision to be created...

Tagging new revision &#39;hello-00001&#39; as &#39;latest&#39;

Tagging new revision &#39;hello-00001&#39; as &#39;previous&#39;

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我们可以用一个 curl 请求，发送到 Knative 的路由层，来调用我们的 &lt;code&gt;hello&lt;/code&gt; 服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl --namespace helloworld --service hello
Running: curl &#39;-H&#39; &#39;Host: hello.helloworld.example.com&#39; &#39;http://192.168.64.8:32380&#39;

Hello World: Rev1!

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果没有马上显示 &lt;code&gt;Hello World: Rev1!&lt;/code&gt;，可能是因为你的系统还在下载应用镜像、可以稍后重试。&lt;/p&gt;

&lt;p&gt;我使用的是 Minikube 中的 NodePort Ingress，这意味着我不能设置漂亮的 DNS 路由。以后我会讨论一下公共负载均衡、DNS、Knative 路由以及 &lt;code&gt;https://github.com/cppforlife/kwt&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 之后，我们的 Kubernetes 用单 Pod 的形式运行这一服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          15s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Knative 中，服务的版本是一个重要特性。我们可以看到我们的唯一版本的服务正在处理 100% 的流量：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl revisions list --namespace helloworld --service hello
Revisions for service &#39;hello&#39;

Name         Tags      Allocated Traffic %  Serving State  Annotations  Age
hello-00001  latest    100%                 Active         -            3m
             previous

1 revisions
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一步我们使用 &lt;code&gt;knctl deploy&lt;/code&gt; 创建一个新的版本，然后把所有流量分配到新版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl deploy \
      --namespace helloworld \
      --service hello \
      --image gcr.io/knative-samples/helloworld-go \
      --env TARGET=Rev2

Name  hello

Waiting for new revision (after revision &#39;hello-00001&#39;) to be created...

Tagging new revision &#39;hello-00002&#39; as &#39;latest&#39;

Tagging older revision &#39;hello-00001&#39; as &#39;previous&#39;

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在请求被发送到了我们的新版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl revisions list --namespace helloworld --service hello
Revisions for service &#39;hello&#39;

Name         Tags      Allocated Traffic %  Serving State  Annotations  Age
hello-00002  latest    100%                 Active         -            1m
hello-00001  previous  0%                   Active         -            10m

$ knctl curl --namespace helloworld --service hello
Running: curl &#39;-H&#39; &#39;Host: hello.helloworld.example.com&#39; &#39;http://192.168.64.8:32380&#39;

Hello World: Rev2!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;部署第二个版本之后，起初两个版本的 Pod 都会持续运行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          1m
hello-00002-deployment-7874bf89b8-4b4k5   3/3     Running   0          29s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我们会看到 Knative 自动将没有路由指向的版本缩容到 0。&lt;/p&gt;

&lt;h2 id=&#34;路由&#34;&gt;路由&lt;/h2&gt;

&lt;p&gt;下图展示了路由到服务某版本的过程中所涉及到的 &lt;a href=&#34;https://github.com/knative/serving/blob/master/docs/spec/overview.md&#34; target=&#34;_blank&#34;&gt;Knative Serving&lt;/a&gt; 模块：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/object_model.png&#34; alt=&#34;Object Model&#34; /&gt;&lt;/p&gt;

&lt;p&gt;版本是代码、依赖和配置的的只读快照。没有被路由引用的版本会被放弃，其中的 Kubernetes 资源会被删除。&lt;/p&gt;

&lt;p&gt;我们可以看到当前的路由：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl routes list --namespace helloworld
Routes in namespace &#39;helloworld&#39;

Name   Traffic         All Traffic Assigned  Ready  Domain                        Age
hello  100% -&amp;gt; hello:  true                  true   hello.helloworld.example.com  2h
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;缩容至-0&#34;&gt;缩容至 0&lt;/h2&gt;

&lt;p&gt;如果离开五分钟再回来，你会发现 &lt;code&gt;hello-00002&lt;/code&gt; Pod 正在被终结或者已经不见了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS        RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running       0          6m
hello-00002-deployment-7874bf89b8-4b4k5   2/3     Terminating   0          5m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一次 &lt;code&gt;knctl curl&lt;/code&gt;，Knative 会动态的启动一个 Pod 来满足这一请求。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl --namespace helloworld --service hello
$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          8m
hello-00002-deployment-7874bf89b8-kfbm2   3/3     Running   0          10s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我还不太清楚为什么 &lt;code&gt;hello-00001-deployment-...&lt;/code&gt; Pod 没有被缩容和终结。&lt;/p&gt;

&lt;h2 id=&#34;未完待续&#34;&gt;未完待续&lt;/h2&gt;

&lt;p&gt;后续文章中将会尝试：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knative Build 组件：使用 &lt;code&gt;Dockerfile&lt;/code&gt; 或者 Cloud Foundry buildpack 自动从定制代码构建容器镜像（代码可以保存本地或者 Git 仓库之中）。&lt;/li&gt;
&lt;li&gt;为 Kubernetes 的负载均衡设置 DNS，从而为 Knative 路由和服务提供公共 URL。&lt;/li&gt;
&lt;li&gt;在不同版本之间进行流量分割（例如 10% 到最新版本，90% 到前一版本；然后将 100% 分配给新版本，老版本流量降低到 0%）。&lt;/li&gt;
&lt;li&gt;Knative Eventing：在应用中进行 &lt;a href=&#34;https://github.com/cloudevents/spec&#34; target=&#34;_blank&#34;&gt;CloudEvents&lt;/a&gt;的绑定和分发。让你的服务更加“无服务器”。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;社区&#34;&gt;社区&lt;/h2&gt;

&lt;p&gt;Knative 核心团队有自己的 &lt;a href=&#34;https://knative.slack.com/&#34; target=&#34;_blank&#34;&gt;Knative Slack&lt;/a&gt;，可以在 &lt;a href=&#34;https://slack.knative.dev&#34; target=&#34;_blank&#34;&gt;https://slack.knative.dev&lt;/a&gt; 申请加入。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://groups.google.com/forum/#!forum/knative-dev&#34; target=&#34;_blank&#34;&gt;knative-dev Group&lt;/a&gt; 中包含了总结和提议。&lt;/p&gt;

&lt;h2 id=&#34;鸣谢&#34;&gt;鸣谢&lt;/h2&gt;

&lt;p&gt;感谢 Google 的 &lt;a href=&#34;https://m.chmarny.com/&#34; target=&#34;_blank&#34;&gt;Mark Chmarny&lt;/a&gt;，在 2018 Spring One 上首先回应了我的问题。&lt;/p&gt;

&lt;p&gt;感谢 Pivotal 的 &lt;a href=&#34;https://github.com/cppforlife&#34; target=&#34;_blank&#34;&gt;Dmitriy Kalinin&lt;/a&gt; 花时间帮助我将 Knative 运行起来，并给我展示了他的 &lt;a href=&#34;https://github.com/cppforlife/knctl&#34; target=&#34;_blank&#34;&gt;knctl Knative CLI&lt;/a&gt;，以及 &lt;a href=&#34;https://github.com/cppforlife/kwt&#34; target=&#34;_blank&#34;&gt;kwt Kubernetes Workstation Tools&lt;/a&gt;。相对于 YAML + &lt;code&gt;kubectl&lt;/code&gt; 组合来说，一个好用的客户端工具更能够帮助 Knative 走向实用。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - Mixer</title>
      <link>/post/istio-helm-deep-dive-mixer/</link>
      <pubDate>Mon, 05 Nov 2018 16:37:23 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-mixer/</guid>
      <description>

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;Mixer 是 Istio 的核心组件之一，负责服务网格中的遥测和策略两部分重要功能，因此 Mixer 的部署也分成了 Policy 和 Telemetry 两部分。&lt;/p&gt;

&lt;h2 id=&#34;values-yaml-中的全局变量&#34;&gt;values.yaml 中的全局变量&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;mixer:
  enabled: true
  replicaCount: 1
  autoscaleMin: 1
  autoscaleMax: 5
  image: mixer

  istio-policy:
    autoscaleEnabled: true
    autoscaleMin: 1
    autoscaleMax: 5
    cpu:
      targetAverageUtilization: 80

  istio-telemetry:
    autoscaleEnabled: true
    autoscaleMin: 1
    autoscaleMax: 5
    cpu:
      targetAverageUtilization: 80

  prometheusStatsdExporter:
    hub: docker.io/prom
    tag: v0.6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里看到，和我们前面说到的功能分离相同，Policy 和 Telemetry 两个组件也是分别设置了各自的变量。根据前面几篇的经验看，&lt;code&gt;istio-policy&lt;/code&gt; 和 &lt;code&gt;istio-telemetry&lt;/code&gt; 两部分是用于控制两个部署的自动伸缩。而 &lt;code&gt;prometheusStatsdExporter&lt;/code&gt; 部分则是指定了一个镜像，用于提供 Prometheus 监控使用。而从 &lt;code&gt;enable&lt;/code&gt; 位置来看，两个组件是不推荐单独启用的，但是 HPA 是可以分别设置的。&lt;/p&gt;

&lt;h2 id=&#34;rbac-相关&#34;&gt;RBAC 相关&lt;/h2&gt;

&lt;p&gt;这里可以看到，Mixer 的两个组件使用的是同一个 &lt;code&gt;istio-mixer-service-account&lt;/code&gt;，根据对 &lt;code&gt;clusterole.yaml&lt;/code&gt; 的观察，可以看到如下权限：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组&lt;/th&gt;
&lt;th&gt;资源&lt;/th&gt;
&lt;th&gt;权限&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config.istio.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读写&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rbac.istio.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读写&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apiextensions.k8s.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;customresourcedefinitions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;configmaps&amp;quot;, &amp;quot;endpoints&amp;quot;, &amp;quot;pods&amp;quot;, &amp;quot;services&amp;quot;, &amp;quot;namespaces&amp;quot;, &amp;quot;secrets&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;extensions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replicasets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config.istio.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replicasets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;autoscale-yaml&#34;&gt;&lt;code&gt;autoscale.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这里用了一个循环：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;{{- range $key, $spec := .Values }}
{{- if or (eq $key &amp;quot;istio-policy&amp;quot;) (eq $key &amp;quot;istio-telemetry&amp;quot;) }}
{{- if and $spec.autoscaleEnabled $spec.autoscaleMin }}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;分别遍历全局变量中的 &lt;code&gt;mixer.istio-policy&lt;/code&gt; 和 &lt;code&gt;mixer.istio-telemetry&lt;/code&gt;，使用各自的 HPA 参数对伸缩过程进行配置。&lt;/p&gt;

&lt;p&gt;两个 HPA 对象的名字来自上面的循环：&lt;code&gt;istio-policy&lt;/code&gt; 和 &lt;code&gt;istio-telemetry&lt;/code&gt;。引用变量包括这两个分组中的所有变量。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这里不难发现 Mixer 中的根级变量 &lt;code&gt;autoscaleMin&lt;/code&gt;、&lt;code&gt;autoscaleMax&lt;/code&gt; 是无用的，该问题在新版本中已经修正。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;&lt;code&gt;service.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;和 HPA 的情况类似，这里用循环的方式生成了两个 Service，分别为 &lt;code&gt;istio-policy&lt;/code&gt; 和 &lt;code&gt;istio-telemetry&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;端口方面，两个服务都开放了 &lt;code&gt;grpc-mixer&lt;/code&gt;、&lt;code&gt;grcp-mixer-mtls&lt;/code&gt; 以及 &lt;code&gt;http-monitoring&lt;/code&gt; 三个端口：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grpc-mixer: 9091&lt;/code&gt;：用于 Mixer 的 gRPC API 端口。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grpc-mixer-mtls: 15004&lt;/code&gt;：启用 mtls 的时候使用的 API 端口。如果启用了 controlPlaneAuthPolicy，则使用该端口进行 Mixer API 通信。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http-monitoring&lt;/code&gt;：用于监测 Mixer 存活状态。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;另外如果是 &lt;code&gt;istio-telemetry&lt;/code&gt;，还多定义了一个端口 &lt;code&gt;prometheus&lt;/code&gt;，Prometheus 可以从这一端口获取遥测数据。&lt;/p&gt;

&lt;p&gt;此处仅引用了 &lt;code&gt;Chart&lt;/code&gt; 和 &lt;code&gt;Release&lt;/code&gt; 的全局变量。&lt;/p&gt;

&lt;h2 id=&#34;statsdtoprom-yaml&#34;&gt;&lt;code&gt;statsdtoprom.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这个组件用来把 Envoy 的 Statsd 指标转换为 Promtheus 指标。这里包含了 Service 和 Deployment 两部分。&lt;/p&gt;

&lt;h3 id=&#34;deployment&#34;&gt;Deployment&lt;/h3&gt;

&lt;p&gt;这里实际上是引用了 Prom 的一个 &lt;a href=&#34;https://github.com/prometheus/statsd_exporter&#34; target=&#34;_blank&#34;&gt;Exporter&lt;/a&gt;，除了引用了 &lt;code&gt;Chart&lt;/code&gt; 和 &lt;code&gt;Release&lt;/code&gt; 全局变量之外，还使用了如下几个变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheusStatsdExporter.hub&lt;/code&gt;：镜像仓库的地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheusStatsdExporter.tag&lt;/code&gt;：镜像版本。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.imagePullPolicy&lt;/code&gt;：镜像拉取策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheusStatsdExporter.resources&lt;/code&gt;：可以定义这一 Pod 的资源使用策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nodeSelector&lt;/code&gt;：可以根据资源情况，为该 Pod 进行节点选择，避免资源争用。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;除去上面的变量之外，还可以看到如下信息：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;该 Pod 不接受自动注入。&lt;/li&gt;
&lt;li&gt;开放了 TCP 端口 9102 以及 UDP 端口 9125。&lt;/li&gt;
&lt;li&gt;加载一个 ConfigMap：istio-statsd-prom-bridge，用于配置文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;上文提到的 Configmap 来自于模板文件 &lt;code&gt;configmap.yaml&lt;/code&gt;，这一文件没有提供任何额外配置。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;service&#34;&gt;Service&lt;/h3&gt;

&lt;p&gt;这里声明了 Exporter 的端口使用：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TCP 端口 9102 提供给 Prometheus 进行数据抓取。&lt;/li&gt;
&lt;li&gt;UDP 端口 9125，Envoy 会发送指标进入 Exporter。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;autoscale-yaml-1&#34;&gt;&lt;code&gt;autoscale.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这里使用 &lt;code&gt;values.yaml&lt;/code&gt; 中定义的内容，分别给 Telemetry 和 Policy 两个组件定义了各自的自动伸缩。&lt;/p&gt;

&lt;p&gt;缺省情况下，都是最少单副本，最多 5 副本，平均 CPU 用量 80%。&lt;/p&gt;

&lt;h2 id=&#34;deployment-yaml&#34;&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这个文件稍微有点古怪，首先分别定义了 &lt;code&gt;policy_container&lt;/code&gt; 和 &lt;code&gt;telemetry_container&lt;/code&gt; 两个模板，然后在文件尾部进行合并。&lt;/p&gt;

&lt;h3 id=&#34;policy-container&#34;&gt;policy_container&lt;/h3&gt;

&lt;p&gt;这个 Deployment 负责 Mixer 的策略实施功能，其主进程为 &lt;a href=&#34;https://istio.io/docs/reference/commands/mixs/&#34; target=&#34;_blank&#34;&gt;mixs&lt;/a&gt;，并且注入了 Sidecar。除了 Chart 和 Release 之外，引用全局变量包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;global.priorityClassName&lt;/code&gt;：&lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority&#34; target=&#34;_blank&#34;&gt;Pod 优先级&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.hub&lt;/code&gt;：镜像仓库。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.tag&lt;/code&gt;：镜像标签。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;image&lt;/code&gt;：镜像名称，如果名称中包含 &lt;code&gt;/&lt;/code&gt;，则忽略 &lt;code&gt;global.hub&lt;/code&gt; 和 &lt;code&gt;global.tag&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resource&lt;/code&gt; 和 &lt;code&gt;global.defaultResources&lt;/code&gt;：如果没有特别定义资源限制，则沿用 Chart 设计的缺省限制。&lt;strong&gt;需要注意的是，Policy 和 Telemetry 的两个组件，资源设置是共享的同一套值。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.controlPlaneSecurityEnabled&lt;/code&gt;：根据这个参数来设置 &lt;strong&gt;istio-proxy&lt;/strong&gt; 的 &lt;code&gt;--controlPlaneAuthPolicy&lt;/code&gt;，在 &lt;code&gt;MUTUAL_TLS&lt;/code&gt; 和 &lt;code&gt;NONE&lt;/code&gt; 之间选择。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.proxy.resources&lt;/code&gt; 和 &lt;code&gt;global.defaultResources&lt;/code&gt;：如果没有定义全局的 Proxy 资源限制，也会沿用缺省限制。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;mixs policy&lt;/code&gt; 进程使用了 &lt;code&gt;unix:///sock/mixer.socket&lt;/code&gt; 进行监听，这一点在 Envoy 配置中也有对应的处理。&lt;/p&gt;

&lt;h3 id=&#34;telemetry-container&#34;&gt;telemetry_container&lt;/h3&gt;

&lt;p&gt;该容器仅在命令行（&lt;code&gt;args&lt;/code&gt;）上和 &lt;code&gt;policy&lt;/code&gt; Pod 有差别，就无需介绍了。&lt;/p&gt;

&lt;h2 id=&#34;config-yaml&#34;&gt;&lt;code&gt;config.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这里包含了 Mixer 初始配置：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1/#AttributeManifest&#34; target=&#34;_blank&#34;&gt;attributemanifest&lt;/a&gt;：

&lt;ul&gt;
&lt;li&gt;istioproxy：定义了 Sidecar 中的属性清单。&lt;/li&gt;
&lt;li&gt;kubernetes：Kubernetes 相关的属性清单。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/stdio/&#34; target=&#34;_blank&#34;&gt;stdio&lt;/a&gt;：定义使用 JSON 格式进行输出的 stdio handler。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/templates/logentry/&#34; target=&#34;_blank&#34;&gt;logentry&lt;/a&gt;：定义了两个不同用途的日志模板实例，用不同属性组成不同内容，用于记录访问日志：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;accesslog&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcpaccesslog&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt; 对象用于定义遥测数据的结构清单：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requestcount&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requestduration&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requestsize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;responsesize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcpbytesent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcpbytereceived&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/prometheus/&#34; target=&#34;_blank&#34;&gt;prometheus&lt;/a&gt; Handler：把前面定义的 &lt;code&gt;metric&lt;/code&gt; 实例逐个映射为 Prometheus 的监控指标。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/kubernetesenv/&#34; target=&#34;_blank&#34;&gt;kubernetesenv&lt;/a&gt;：该 Handler 为 Mixer 提供 Kubernetes 集群的连接。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/templates/kubernetes/&#34; target=&#34;_blank&#34;&gt;kubernetes&lt;/a&gt;：用于生成 Kubernetes 相关的数据。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1/&#34; target=&#34;_blank&#34;&gt;rule&lt;/a&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;stdio&lt;/code&gt;：定义一条规则，将 &lt;code&gt;http&lt;/code&gt; 和 &lt;code&gt;grpc&lt;/code&gt; 协议的访问日志，用 &lt;code&gt;accesslog&lt;/code&gt; 的样式输出到 &lt;code&gt;stdio&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stdiotcp&lt;/code&gt;：定义一条规则，将 &lt;code&gt;http&lt;/code&gt; 和 &lt;code&gt;grpc&lt;/code&gt; 协议的访问日志，用 &lt;code&gt;tcpaccesslog&lt;/code&gt; 的样式输出到 &lt;code&gt;stdio&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;promhttp&lt;/code&gt;：将 &lt;code&gt;http&lt;/code&gt; 和 &lt;code&gt;grpc&lt;/code&gt; 协议产生的 &lt;code&gt;requestcount&lt;/code&gt;、&lt;code&gt;requestduration&lt;/code&gt;、&lt;code&gt;requestsize&lt;/code&gt; 以及 &lt;code&gt;responsesize&lt;/code&gt; 四种指标送入前面建立的 Prometheus handler。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;promtcp&lt;/code&gt;：将 &lt;code&gt;tcp&lt;/code&gt; 协议产生的 &lt;code&gt;tcpbytesent&lt;/code&gt; 和 &lt;code&gt;tcpbytereceived&lt;/code&gt; 指标送入前面建立的 Prometheus handler。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubeattrgenrulerule&lt;/code&gt;：将 &lt;code&gt;kubernetesenv&lt;/code&gt; 生成的数据交由 &lt;code&gt;kubernetes&lt;/code&gt; 属性模板处理。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcpkubeattrgenrulerule&lt;/code&gt;：将 &lt;code&gt;kubernetesenv&lt;/code&gt; 生成的 tcp 通信相关数据交由 &lt;code&gt;kubernetes&lt;/code&gt; 属性模板处理。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;目标规则：两条规则分别定义了到 policy 和 &lt;code&gt;telemetry&lt;/code&gt;控制器的连接池，如果启用了 &lt;code&gt;controlPlaneSecurityEnabled&lt;/code&gt;，则加入对 15004 端口的 tls 定义。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;在 Istio 中 Mixer 一直是一个备受争议的组件，一方面表达了 Istio 的远大设计目标，另一方面因为自身结构以及众多 Adapter 的缺陷，持续遭到用户诟病，因此也是目前为止部署体系变化最大的一块，相信后续版本中，Mixer 还会做出频繁的好的和坏的变更。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - Galley</title>
      <link>/post/istio-helm-deep-dive-galley/</link>
      <pubDate>Sat, 27 Oct 2018 15:50:59 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-galley/</guid>
      <description>

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/commands/galley/&#34; target=&#34;_blank&#34;&gt;Galley&lt;/a&gt; 是 Istio 的配置管理组件，根据&lt;a href=&#34;https://preliminary.istio.io/zh/docs/concepts/what-is-istio/#galley&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;的描述：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Galley 代表其他的 Istio 控制平面组件，用来验证用户编写的 Istio API 配置。随着时间的推移，Galley 将接管 Istio 获取配置、 处理和分配组件的顶级责任。它将负责将其他的 Istio 组件与从底层平台（例如 Kubernetes）获取用户配置的细节中隔离开来。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;values-yaml-中的相关变量&#34;&gt;values.yaml 中的相关变量&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;galley:
  enabled: true
  replicaCount: 1
  image: galley
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里看到，Galley 的相关变量只有启用、副本数量以及镜像三个。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enabled&lt;/code&gt;：负责在 &lt;code&gt;requirements.yaml&lt;/code&gt; 中标识是否启用 Galley 组件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;replicaCount&lt;/code&gt;：负责在 &lt;code&gt;deployment.yaml&lt;/code&gt; 中定义副本数量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;image&lt;/code&gt;：负责在 &lt;code&gt;deployment.yaml&lt;/code&gt; 中定义镜像。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;rbac-相关内容&#34;&gt;RBAC 相关内容&lt;/h2&gt;

&lt;p&gt;这里可以看到 Galley 使用 Service Account &lt;code&gt;istio-galley-service-account&lt;/code&gt; 的身份运行。全局变量中如果定义了 &lt;code&gt;imagePullSecrets&lt;/code&gt;，则会在 &lt;code&gt;serviceaccount.yaml&lt;/code&gt; 中进行引用。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clusterrole.yaml&lt;/code&gt; 模板中定义了 Galley 所需使用的系统资源：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;对 &lt;code&gt;admissionregistration.k8s.io&lt;/code&gt; 组中的 &lt;code&gt;validatingwebhookconfigurations&lt;/code&gt; 类型的完全控制。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config.istio.io&lt;/code&gt;： Mixer CRD 的所有资源的读取权限。&lt;/li&gt;
&lt;li&gt;对 &lt;code&gt;istio-galley&lt;/code&gt; Deployment 和 Endpoint 的读取权限。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;clusterrolebinding.yaml&lt;/code&gt; 将上面的两个对象连接起来完成授权。&lt;/p&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;service.yaml&lt;/h2&gt;

&lt;p&gt;这里看到为 Galley 开放了两个端口：443 是一个 https 端口，用来提供验证服务；而 9093 是一个用来进行 Galley 自身服务监控的 http 端口。&lt;/p&gt;

&lt;p&gt;该文件只引用了 &lt;code&gt;Release&lt;/code&gt; 内置变量。&lt;/p&gt;

&lt;h2 id=&#34;deployment-yaml&#34;&gt;deployment.yaml&lt;/h2&gt;

&lt;p&gt;这里以 &lt;a href=&#34;https://istio.io/docs/reference/commands/galley/&#34; target=&#34;_blank&#34;&gt;Galley&lt;/a&gt; 为主进程创建了一个 Deployment 对象。&lt;/p&gt;

&lt;p&gt;在 &lt;code&gt;annotation&lt;/code&gt; 一节中将 &lt;code&gt;sidecar.istio.io/inject&lt;/code&gt; 设置为 &lt;code&gt;false&lt;/code&gt; 来防止自动注入 Sidecar。&lt;/p&gt;

&lt;h3 id=&#34;全局变量&#34;&gt;全局变量&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Chart&lt;/li&gt;
&lt;li&gt;Release&lt;/li&gt;
&lt;li&gt;global.priorityClassName&lt;/li&gt;
&lt;li&gt;global.hub&lt;/li&gt;
&lt;li&gt;global.tag&lt;/li&gt;
&lt;li&gt;global.imagePullPolicy&lt;/li&gt;
&lt;li&gt;模板 nodeaffinity&lt;/li&gt;
&lt;li&gt;global.defaultResources&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;变量使用细节&#34;&gt;变量使用细节&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;部署在 Istio 所属命名空间中。&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中定义的模板给 App 标签赋值。&lt;/li&gt;
&lt;li&gt;使用 Chart 和 Release 变量生成 Deployment 标签。&lt;/li&gt;
&lt;li&gt;Chart 变量 &lt;code&gt;replicaCount&lt;/code&gt; 确定副本数量。&lt;/li&gt;
&lt;li&gt;如果定义了 &lt;code&gt;global.priorityClassName&lt;/code&gt;，则设置到 Pod 上，提高组件在集群内的优先级。&lt;/li&gt;
&lt;li&gt;使用 global.hub + image + global.tag 的方式设置镜像名称。&lt;/li&gt;
&lt;li&gt;如果 Chart 变量设置了 &lt;code&gt;resource&lt;/code&gt;，则使用独立的资源限制，否则使用缺省的 &lt;code&gt;global.defaultResources&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;使用缺省的节点亲和性定义。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;加载卷&#34;&gt;加载卷&lt;/h3&gt;

&lt;p&gt;加载了一个名为 &lt;code&gt;istio.istio-galley-service-account&lt;/code&gt; 的 Secret，注意这个资源的类型为 &lt;code&gt;istio.io/key-and-cert&lt;/code&gt;，说明是由 Citadel 生成的，其中包含了几个证书，供 &lt;code&gt;--caCertFile&lt;/code&gt;、&lt;code&gt;--tlsCertFile&lt;/code&gt; 和 &lt;code&gt;--tlsKeyFile&lt;/code&gt; 用来提供 https 服务。&lt;/p&gt;

&lt;p&gt;另外加载了一个 ConfigMap，其中的配置文件供 &lt;code&gt;--webhook-config-file&lt;/code&gt; 参数使用，作为 Webhook 的参数。这个 ConfigMap 是由模板 &lt;code&gt;configmap.yaml&lt;/code&gt; 和 &lt;code&gt;validatingwehookconfiguration.yaml.tpl&lt;/code&gt; 生成的，后面将会进行讲解。&lt;/p&gt;

&lt;h2 id=&#34;configmap-yaml-以及-validatingwehookconfiguration-yaml-tpl&#34;&gt;configmap.yaml 以及 validatingwehookconfiguration.yaml.tpl&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;configmap.yaml&lt;/code&gt; 模板中并没有实质内容，主要内容存在于 &lt;code&gt;validatingwehookconfiguration.yaml.tpl&lt;/code&gt; 之中。&lt;/p&gt;

&lt;p&gt;这个模板中定义了一个 &lt;a href=&#34;https://docs.okd.io/latest/rest_api/apis-admissionregistration.k8s.io/v1beta1.ValidatingWebhookConfiguration.html#object-schema&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;ValidatingWebhookConfiguration&lt;/code&gt;&lt;/a&gt; 类型的资源。这种资源用于在不改变资源的情况下，对其进行校验并发出接受或拒绝的决策。&lt;/p&gt;

&lt;h3 id=&#34;引用全局变量&#34;&gt;引用全局变量&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Chart&lt;/code&gt; 和 &lt;code&gt;Release&lt;/code&gt;：用于生成标签和命名空间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.configValidation&lt;/code&gt;：如果这一变量为 True，才会生成后续内容。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;webhook&#34;&gt;Webhook&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;webhooks&lt;/code&gt; 一节定义了两个元素，分别用于 Pilot 和 Mixer 的校验。以 Mixer 部分为例。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clientConfig&lt;/code&gt; 一节，定义了这个 Webhook 会调用的校验服务，标准情况下会使用 Istio 所在的命名空间的 &lt;code&gt;istio-galley&lt;/code&gt;，URL 相对路径为 &lt;code&gt;/admitmixer&lt;/code&gt;，其中的 &lt;code&gt;rules&lt;/code&gt; 内容，定义了针对 &lt;code&gt;config.istio.io/v1alpha2&lt;/code&gt; 的一系列对象的创建和更新操作进行校验，如果校验失败，则拒绝创建（&lt;code&gt;failurePolicy: Fail&lt;/code&gt;）。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;Galley 目前的文档非常少，主要在&lt;a href=&#34;https://istio.io/zh/docs/reference/commands/galley/&#34; target=&#34;_blank&#34;&gt;参考&lt;/a&gt;和&lt;a href=&#34;https://istio.io/zh/help/ops/setup/validation/&#34; target=&#34;_blank&#34;&gt;运维指南&lt;/a&gt;部分有一点介绍，但 Istio 的配置难度是很著名的，因此推测随着项目的推进和普及，Galley 会持续的增强，并提供更多这方面的文档。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - SidecarInjectorWebhook</title>
      <link>/post/istio-helm-deep-dive-injector-webhook/</link>
      <pubDate>Sun, 21 Oct 2018 19:56:03 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-injector-webhook/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;《Istio Helm Chart 详解》系列的第五篇，介绍 Chart SidecarInjectorWebhook，负责对工作负载进行自动注入。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;这个 Chart 负责 Istio Sidecar 的自动注入操作相关配置。&lt;/p&gt;

&lt;p&gt;关于自动注入操作的相关内容，可以参考&lt;a href=&#34;https://preliminary.istio.io/zh/docs/setup/kubernetes/sidecar-injection/&#34; target=&#34;_blank&#34;&gt;官方文档中的相应章节&lt;/a&gt;，简单说来自动注入的两个先决条件：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kubernetes 版本大于 1.9。&lt;/li&gt;
&lt;li&gt;启用了 &lt;code&gt;MutatingAdmissionWebhook&lt;/code&gt; 和 &lt;code&gt;ValidatingAdmissionWebhook&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;还有一点，在 Kubernetes 1.10 版本中的 AlwaysPullImage 会和自动注入功能冲突&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;代码中可以看到，这一 Chart 生成了自动注入所需的 Deployment、Service，运行依赖的 RBAC 资源，以及自定义资源。&lt;/p&gt;

&lt;p&gt;这个 Chart 会生成 &lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; 类型的自定义资源，根据对命名空间以及 Pod 注解的监控对新生成的 Pod 进行注入。可以通过对这一自定义资源的修改，结合 ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt; 的内容对注入行为进行控制，后面将会进行讲解。&lt;/p&gt;

&lt;h2 id=&#34;values-yaml-中的变量定义&#34;&gt;&lt;code&gt;values.yaml&lt;/code&gt; 中的变量定义&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;sidecarInjectorWebhook:
  enabled: true
  replicaCount: 1
  image: sidecar_injector
  enableNamespacesByDefault: false
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;chart-yaml-和-helpers-tpl&#34;&gt;Chart.yaml 和 _helpers.tpl&lt;/h2&gt;

&lt;p&gt;都是标准的 Helm Chart 文件，无需说明。&lt;/p&gt;

&lt;h2 id=&#34;rbac-相关内容&#34;&gt;RBAC 相关内容&lt;/h2&gt;

&lt;p&gt;类似其它 Chart，这里也使用 &lt;code&gt;serviceaccount.yaml&lt;/code&gt;、&lt;code&gt;clusterrolebinding.yaml&lt;/code&gt; 和 &lt;code&gt;clusterrole.yaml&lt;/code&gt; 三个文件来进行赋权操作。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;serviceaccount.yaml&lt;/code&gt; 中，引用变量除了 &lt;code&gt;Chart&lt;/code&gt; 和 &lt;code&gt;Release&lt;/code&gt; 两组保留变量之外，还引用到 &lt;code&gt;global.imagePullSecrets&lt;/code&gt;，用于 ServiceAccount 的镜像拉取授权。&lt;/p&gt;

&lt;p&gt;而 &lt;code&gt;clusterrole.yaml&lt;/code&gt; 文件中的 &lt;code&gt;rules&lt;/code&gt; 则表明，这个功能运行需要读取 ConfigMap，以及对前面提到的 &lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; 资源的读写。&lt;/p&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;service.yaml&lt;/h2&gt;

&lt;p&gt;这里创建了一个开放 443 端口的服务。&lt;/p&gt;

&lt;h2 id=&#34;depoyment-yaml&#34;&gt;depoyment.yaml&lt;/h2&gt;

&lt;p&gt;该文件所生成的 Deployment 是自动注入 Web hook 的主体。&lt;/p&gt;

&lt;p&gt;引用变量大致如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Release.Namespace&lt;/code&gt;：Istio 所在命名空间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;template &amp;quot;sidecar-injector.name&amp;quot; .&lt;/code&gt;：定义在 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中，命名规则基本等同于 Release。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Chart&lt;/code&gt; 以及 &lt;code&gt;Release&lt;/code&gt; 变量：Helm 内置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.tag&lt;/code&gt; 和 &lt;code&gt;global.hub&lt;/code&gt;：镜像的前后缀&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.priorityClassName&lt;/code&gt;：Kubernetes PriorityClass 定义。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.imagePullPolicy&lt;/code&gt;：镜像拉取策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;replicaCount&lt;/code&gt;：Deployment 的副本数量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;image&lt;/code&gt;：镜像名称，前后缀由全局变量控制，这里&lt;strong&gt;不可直接指定完整镜像地址&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resources&lt;/code&gt; 和 &lt;code&gt;global.defaultResources&lt;/code&gt;：优先使用 Chart 资源定义。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nodeaffinity&lt;/code&gt;：沿用全局节点亲和性定义。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这里会看到 Pod 模板中带有一个新的注解：&lt;code&gt;sidecar.istio.io/inject: &amp;quot;false&amp;quot;&lt;/code&gt;，该注解用于告知 Webhook，这个 Pod 无需进行注入，具体配置方式会在后面的 ConfigMap 部分解释。&lt;/p&gt;

&lt;p&gt;其中运行的主进程为 &lt;code&gt;sidecar-injector&lt;/code&gt;，官方有提供详细的&lt;a href=&#34;https://preliminary.istio.io/zh/docs/reference/commands/sidecar-injector/#sidecar-injector-probe&#34; target=&#34;_blank&#34;&gt;使用参考&lt;/a&gt;。对比一下会发现，除了显示的 &lt;code&gt;args&lt;/code&gt; 之外，这一命令有一个默认的 443 端口，和前面 Service 的定义一致。&lt;/p&gt;

&lt;p&gt;加载卷：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;istio&lt;/code&gt; ConfigMap：它的内容被加载到 &lt;code&gt;/etc/istio/config&lt;/code&gt;，作为 &lt;code&gt;sidecar-injector&lt;/code&gt; 的 &lt;code&gt;meshConfig&lt;/code&gt; 参数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;istio-sidecar-injector&lt;/code&gt; ConfigMap：被加载到路径 &lt;code&gt;/etc/istio/inject&lt;/code&gt;，它代表的注入配置，用作 &lt;code&gt;injectConfig&lt;/code&gt; 参数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;istio.istio-sidecar-injector-service-account&lt;/code&gt; Secret：来自于前面渲染的 ServiceAccount，会被加载到 &lt;code&gt;/etc/istio/certs&lt;/code&gt;，用作证书使用。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;mutatingwebhook-yaml&#34;&gt;mutatingwebhook.yaml&lt;/h2&gt;

&lt;p&gt;这一文件的渲染所生成的资源会对 MutatingWebhook 的执行产生一些影响。&lt;/p&gt;

&lt;p&gt;应用变量除了 Helm 的保留变量之外，使用了本地的 &lt;code&gt;enableNamespacesByDefault&lt;/code&gt;，来确定是否缺省为命名空间启用自动注入。如果启用了缺省注入，那么所有命名空间除非定义了 &lt;code&gt;istio-injection: disabled&lt;/code&gt; 的标签，否则都会进行注入；如果没有启用，则只有被标签 &lt;code&gt;istio-injection: enabled&lt;/code&gt; 的命名空间才会进行自动注入。&lt;/p&gt;

&lt;p&gt;渲染结果是一个 &lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; 类型的资源，该资源包含了一系列的 &lt;code&gt;webhook&lt;/code&gt; 元素，这里用一个 &lt;code&gt;sidecar-injector.istio.io&lt;/code&gt; webhook 定义了注入过程的触发时机为 Pod 的创建期间，命名空间则用了上面说到的表达式来进行选择。&lt;/p&gt;

&lt;p&gt;这一配置的具体格式可以参考 &lt;a href=&#34;https://docs.okd.io/latest/rest_api/apis-admissionregistration.k8s.io/v1beta1.MutatingWebhookConfiguration.html&#34; target=&#34;_blank&#34;&gt;OKD 官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&#34;sidecar-injector-configmap-yaml&#34;&gt;sidecar-injector-configmap.yaml&lt;/h2&gt;

&lt;p&gt;这个模板的内容，是 Istio Sidecar 自动注入过程中的主要配置。&lt;/p&gt;

&lt;p&gt;首先要查看 &lt;code&gt;global.omitSidecarInjectorConfigMap&lt;/code&gt; 变量，如果这一变量为 &lt;code&gt;true&lt;/code&gt;，则不会生成该配置。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;policy&lt;/code&gt; 字段来自 &lt;code&gt;global.proxy.autoInject&lt;/code&gt;：可选值包括 &lt;code&gt;enabled&lt;/code&gt; 和 &lt;code&gt;disabled&lt;/code&gt;，如果选择 &lt;code&gt;enabled&lt;/code&gt;，那么缺省情况下会进行注入，除非 Pod 中注解 &lt;code&gt;sidecar.istio.io/inject&lt;/code&gt; 为 &lt;code&gt;false&lt;/code&gt;；&lt;code&gt;disabled&lt;/code&gt; 则缺省不注入，除非注解 &lt;code&gt;sidecar.istio.io/inject&lt;/code&gt; 为 &lt;code&gt;true&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;template&lt;/code&gt; 部分对 &lt;code&gt;istio-init&lt;/code&gt;、&lt;code&gt;enable-core-dump&lt;/code&gt; 以及 &lt;code&gt;istio-proxy&lt;/code&gt; 三个待注入容器进行了渲染。&lt;/p&gt;

&lt;h3 id=&#34;istio-init&#34;&gt;&lt;code&gt;istio-init&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;这个镜像会完成 Istio 的流量劫持过程，其主体进程是一个&lt;a href=&#34;https://github.com/istio/istio/blob/master/tools/deb/istio-iptables.sh&#34; target=&#34;_blank&#34;&gt;用于操作 iptables 的 Shell 脚本&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;如果 &lt;code&gt;global.proxy_init.image&lt;/code&gt; 中包含了 &lt;code&gt;/&lt;/code&gt;，则直接使用该名称；否则使用 &lt;code&gt;global.hub&lt;/code&gt; 和 &lt;code&gt;global.tag&lt;/code&gt; 进行拼装。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ObjectMeta 和 Spec 都来自于 Pod。ProxyConfig 和 MeshConfig 来自 istio-system 命名空间中的 istio ConfigMap。模板可以使用这些数据，对将要注入的容器和卷进行定义。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;global.imagePullPolicy&lt;/code&gt; 则定义了镜像的拉取策略。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;global.proxy.privileged&lt;/code&gt; 定义了初始化容器的特权模式。&lt;/p&gt;

&lt;h3 id=&#34;enable-core-dump&#34;&gt;&lt;code&gt;enable-core-dump&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;如果 &lt;code&gt;global.proxy.enableCoreDump&lt;/code&gt; 设置为 &lt;code&gt;true&lt;/code&gt;，则会生成这一容器。&lt;/p&gt;

&lt;p&gt;容器名称固定为 &lt;code&gt;{{ .Values.global.hub }}/proxy_init:{{ .Values.global.tag }}&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&#34;istio-proxy&#34;&gt;&lt;code&gt;istio-proxy&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;这一容器的镜像可以在 Pod 注解 &lt;code&gt;sidecar.istio.io/proxyImage&lt;/code&gt; 中进行优先声明。如果没有该注解，则会使用 &lt;code&gt;{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;主进程为 &lt;code&gt;pilot-agent&lt;/code&gt;，官方提供了&lt;a href=&#34;https://istio.io/zh/docs/reference/commands/pilot-agent/&#34; target=&#34;_blank&#34;&gt;详细的命令文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;引用 Helm 变量包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;global.imagePullPolicy&lt;/code&gt;：镜像拉取策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.proxy.privileged&lt;/code&gt;：Sidecar 特权模式。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;global.envoyStatsd&lt;/code&gt;：监控指标上报相关配置。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;关于资源限制：&lt;/p&gt;

&lt;p&gt;可以在容器注解中加入 &lt;code&gt;sidecar.istio.io/proxyCPU&lt;/code&gt; 和 &lt;code&gt;sidecar.istio.io/proxyMemory&lt;/code&gt; 来设置 Sidecar 的 Request Resource，否则会使用 &lt;code&gt;proxy.resources&lt;/code&gt; 进行资源申请。&lt;/p&gt;

&lt;h2 id=&#34;小结&#34;&gt;小结&lt;/h2&gt;

&lt;p&gt;可以看到，Sidecar 的自动配置过程有很多相关内容，包括命名空间和 Pod 的注解、标签，以及 Helm 中跨越几段的配置数据；而具体的 Sidecar 工作内容，则基本上是由 &lt;code&gt;istio&lt;/code&gt; 这一 ConfigMap 决定的。这部分内容将会延续到 Pilot、Mixer 的相关内容之中。&lt;/p&gt;

&lt;h2 id=&#34;参考文档&#34;&gt;参考文档&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/zh/docs/setup/kubernetes/sidecar-injection/&#34; target=&#34;_blank&#34;&gt;Istio sidecar 的注入&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/zh/docs/reference/commands/pilot-agent/&#34; target=&#34;_blank&#34;&gt;pilot-agent reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/zh/help/ops/setup/injection/&#34; target=&#34;_blank&#34;&gt;Istio Webhook 运维指南&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/zh/help/faq/&#34; target=&#34;_blank&#34;&gt;Istio FAQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>在 Kubernetes 和 Istio 环境下进行蓝绿部署</title>
      <link>/post/tutorial-blue-green-deployments-with-kubernetes-and-istio/</link>
      <pubDate>Sat, 20 Oct 2018 00:46:47 +0800</pubDate>
      <guid>/post/tutorial-blue-green-deployments-with-kubernetes-and-istio/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://thenewstack.io/tutorial-blue-green-deployments-with-kubernetes-and-istio/&#34; target=&#34;_blank&#34;&gt;Tutorial: Blue/Green Deployments with Kubernetes and Istio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://thenewstack.io/author/janakiram/&#34; target=&#34;_blank&#34;&gt;Janakiram MSV&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作为一个服务网格系统，Istio 为服务间通信提供稳定性、透明性和安全性方面的保障。不论集群内外的服务，只要其访问目标是网格内的服务，就都会被 Istio 所拦截并进行处理。&lt;/p&gt;

&lt;p&gt;Istio 有很多功能，例如服务间通信的加密、自动的指标记录、访问控制策略、频率限制以及配额等，这里我们仅着眼于最常用的流量管理能力。&lt;/p&gt;

&lt;p&gt;Istio 让 DevOps 团队有能力为内部服务创建智能的路由规则。断路器、超时和重试之类的服务级属性非常容易配置，配置包含蓝绿部署及金丝雀发布的过程也很轻松。&lt;/p&gt;

&lt;p&gt;本文教程用于帮助读者理解配置 Kubernetes + Istio 环境下的蓝绿部署过程。无需很多知识背景，只要理解一些在 Kubernetes 中部署 Pod 和服务的基础概念就好。我们会在 Minikube 和 Istio 中完成示例。&lt;/p&gt;

&lt;p&gt;教程包含四个步骤：安装 Minikube、安装 Istio 并进行验证、安装一个应用的两个版本，最后配置服务的蓝绿部署。我们会使用两个简单的构建好了的镜像，分别作为蓝（v1）、绿（v2）两个版本。&lt;/p&gt;

&lt;h2 id=&#34;步骤-1-安装-minikube&#34;&gt;步骤 1：安装 Minikube&lt;/h2&gt;

&lt;p&gt;为了降低依赖，我们会使用 Minikube 作为测试平台。因为需要自定义配置，所以要删除已经存在的配置，并使用额外参数重新启动集群：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;minikube start --memory=8192 --cpus=4 --kubernetes-version=v1.10.0 \
--extra-config=controller-manager.cluster-signing-cert-file=&amp;quot;/var/lib/localkube/certs/ca.crt&amp;quot; \
--extra-config=controller-manager.cluster-signing-key-file=&amp;quot;/var/lib/localkube/certs/ca.key&amp;quot; \
--vm-driver=virtualbox
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;要在 Minikube 上运行 Istio，需要至少 8G 内存和 4 个 CPU 核心。等集群启动：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/b1cfb731-istio-0-1024x431.png&#34; alt=&#34;minikube startup&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;步骤-2-安装-istio&#34;&gt;步骤 2：安装 Istio&lt;/h2&gt;

&lt;p&gt;Kubernetes 集群成功启动之后，就可以安装 Istio 了。用下面的步骤完成：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -L https://git.io/getLatestIstio | sh -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在运行上述命令的目录中会发现一个 &lt;code&gt;istio-1.0.2&lt;/code&gt; 目录，可以把 &lt;code&gt;istio-1.0.2/bin&lt;/code&gt; 目录加入 &lt;code&gt;PATH&lt;/code&gt; 变量，方便后面的命令执行过程。&lt;/p&gt;

&lt;p&gt;由于我们在 Minikube 环境下运行的 Istio，所以我们要在下一步进行之前，要把 Ingress Gateway 服务从 &lt;code&gt;LoadBalancer&lt;/code&gt; 改为 &lt;code&gt;NodePort&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;打开文件 &lt;code&gt;istio-1.0.2/install/kubernetes/istio-demo.yaml&lt;/code&gt;，查找并替换：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/2a64731e-istio-1.png&#34; alt=&#34;Changing Service Type&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Istio 中包含了很多 CRD，可以帮用户来进行虚拟服务、规则、网关以及其他对象的管理。在部署服务网格之前首先要部署一下这些 CRD：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最后，在 Kubernetes 中安装 Istio：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl apply -f install/kubernetes/istio-demo.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的步骤会创建新的命名空间（&lt;code&gt;istio-system&lt;/code&gt;）：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/38e93379-istio-3.png&#34; alt=&#34;kubectl get ns&#34; /&gt;&lt;/p&gt;

&lt;p&gt;会看到这里还有很多服务：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/38e93379-istio-3-1024x524.png&#34; alt=&#34;kubectl get svc&#34; /&gt;&lt;/p&gt;

&lt;p&gt;稍候片刻，会看到很多 Pod：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/846a8174-istio-4-1024x498.png&#34; alt=&#34;kubectl get po&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Istio 如果成功部署，所有这些 Pod 只能是 &lt;code&gt;Running&lt;/code&gt; 或者 &lt;code&gt;Completed&lt;/code&gt; 状态。&lt;/p&gt;

&lt;p&gt;下一步就要准备用于蓝绿部署的应用了。&lt;/p&gt;

&lt;h2 id=&#34;步骤-3-安装同一应用的两个版本&#34;&gt;步骤 3：安装同一应用的两个版本&lt;/h2&gt;

&lt;p&gt;为了展示应用的不同版本，我构建了基于 Nginx 的简单镜像 - &lt;code&gt;janakiramm/myapp:v1&lt;/code&gt; 和 &lt;code&gt;janakiramm/myapp:v2&lt;/code&gt;。部署之后，会展示蓝色或者绿色的背景。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  type: ClusterIP
  ports:
  - port: 80
    name: http
  selector:
    app: myapp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: myapp
        version: v1
    spec:
      containers:
      - name: myapp
        image: janakiramm/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myapp-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: myapp
        version: v2
    spec:
      containers:
      - name: myapp
        image: janakiramm/myapp:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;也可以在 &lt;a href=&#34;https://gist.github.com/janakiramm/123dc67b78ef187a109e7f928d6a6878&#34; target=&#34;_blank&#34;&gt;Github&lt;/a&gt; 上看到这些代码。&lt;/p&gt;

&lt;p&gt;接着就要创建 YAML 文件来定义 v1 和 v2 服务了。注意 Pod 标签的差异代表了不同的版本 —— &lt;code&gt;app&lt;/code&gt; 保持一致，但 &lt;code&gt;version&lt;/code&gt; 是不同的。这样一来，Istio 就会认为这是同一应用的不同版本。&lt;/p&gt;

&lt;p&gt;而服务中的选择器定义只针对 &lt;code&gt;app&lt;/code&gt; 标签进行设置，也就是说不同版本的 Pod 都会参与这一服务。&lt;/p&gt;

&lt;p&gt;用 &lt;code&gt;kubectl&lt;/code&gt; 创建 &lt;code&gt;Service&lt;/code&gt; 和 &lt;code&gt;Deployment&lt;/code&gt;。注意这个简单的应用对 Istio 一无所知。Istio 和应用的唯一可见的连接就是标签：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl apply -f myapp.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/7ddbc930-istio-5.png&#34; alt=&#34;apply -f yaml&#34; /&gt;&lt;/p&gt;

&lt;p&gt;配置 Istio 路由之前，首先检查一下应用的版本。可以使用端口转发的方式来访问 Pod。&lt;/p&gt;

&lt;p&gt;要访问应用的 &lt;code&gt;v1&lt;/code&gt; 版本，可以运行下面的命令，然后访问 &lt;code&gt;localhost:8080&lt;/code&gt;，验证完成之后，按 &lt;code&gt;CTRL+C&lt;/code&gt; 结束端口映射命令。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl port-forward deployment/myapp-v1 8080:80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/b5088c7c-istio-6-300x183.png&#34; alt=&#34;app image blue&#34; /&gt;&lt;/p&gt;

&lt;p&gt;要访问应用的 &lt;code&gt;v2&lt;/code&gt; 版本，可以运行下面的命令，然后访问 &lt;code&gt;localhost:8081&lt;/code&gt;，验证完成之后，按 &lt;code&gt;CTRL+C&lt;/code&gt; 结束端口映射命令。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl port-forward deployment/myapp-v2 8081:80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/a187169b-istio-7-300x183.png&#34; alt=&#34;app image green&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;步骤-4-配置蓝绿部署&#34;&gt;步骤 4：配置蓝绿部署&lt;/h2&gt;

&lt;p&gt;我们的目标是在不停机的情况下，让流量选择性的进入某一版本。为了完成这一目的，就需要告知 Istio 根据权重进行路由。完成这一任务需要三个对象：&lt;/p&gt;

&lt;h3 id=&#34;gateway&#34;&gt;Gateway&lt;/h3&gt;

&lt;p&gt;Istio Gateway 描述了网格边缘的负载均衡组件，用于 HTTP/TCP 连接的接收和发出。定义中包含一组要开放的端口、使用的协议、负载均衡的 SNI 等。下面的定义中我们将 Gateway 指向 Istio 部署过程中建立的缺省的 Ingress Gategeway。&lt;/p&gt;

&lt;p&gt;用 Kubernetes 的方式创建 Gateway 对象：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: app-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - &amp;quot;*&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;目标规则&#34;&gt;目标规则&lt;/h3&gt;

&lt;p&gt;Istio &lt;code&gt;DestinationRule&lt;/code&gt; 定义了在一个服务成为路由目标之后的行为。注意一下这一规则中是如何通过标签来对 Kubernetes 的原生 Deployment 进行区分的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: myapp
spec:
  host: myapp
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;虚拟服务&#34;&gt;虚拟服务&lt;/h3&gt;

&lt;p&gt;虚拟服务中定义了一组流量路由规则，在其中的 &lt;code&gt;host&lt;/code&gt; 被访问时就会触发。每个路由规则中都定义了对某一协议进行匹配的标准。如果流量匹配这一标准，那么就发送给对应的区分了版本的目标服务。&lt;/p&gt;

&lt;p&gt;下面的定义中我们定义两个版本的服务权重都是 50，也就是说流量会在版本间进行平均分配：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - &amp;quot;*&amp;quot;
  gateways:
  - app-gateway
  http:
    - route:
      - destination:
          host: myapp
          subset: v1
        weight: 50
      - destination:
          host: myapp
          subset: v2
        weight: 50
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;所有这些都可以定义在同一个 YAML 文件中，然后用 &lt;code&gt;kubectl&lt;/code&gt; 提交给集群，同样可以在 &lt;a href=&#34;https://gist.github.com/janakiramm/35078d95730745caa62f81d917d6d553&#34; target=&#34;_blank&#34;&gt;Gtihub&lt;/a&gt; 中获取这一文件。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl apply -f app-gateway.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/b64331f6-istio-8-300x75.png&#34; alt=&#34;app gateway&#34; /&gt;&lt;/p&gt;

&lt;p&gt;接下来就可以尝试访问这一服务了。因为我们使用的是 NodePort 模式的服务，所以就需要首先判断一下 Ingress Gateway 所在的端口。&lt;/p&gt;

&lt;p&gt;运行下面的命令来访问 MiniKube 的 Ingress 端口。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ export INGRESS_HOST=$(minikube ip)

$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=&#39;{.spec.ports[?(@.name==&amp;quot;http2&amp;quot;)].nodePort}&#39;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;从浏览器访问这个 URL，会看到流量被均等的在蓝色和绿色版本之间进行分配。&lt;/p&gt;

&lt;p&gt;也可以在终端里面查看命令结果。运行下面的命令会看到 V1 和 V2 的响应：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;while : ;do export GREP_COLOR=&#39;1;33&#39;;curl -s  192.168.99.100:31380 \
 |  grep --color=always &amp;quot;V1&amp;quot; ; export GREP_COLOR=&#39;1;36&#39;;\
 curl -s  192.168.99.100:31380 \
 | grep --color=always &amp;quot;vNext&amp;quot; ; sleep 1; done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/840d897c-istio-9-1024x674.png&#34; alt=&#34;curl&#34; /&gt;&lt;/p&gt;

&lt;p&gt;上面的命令会循环运行，我们可以返回编辑 &lt;code&gt;gateway.yaml&lt;/code&gt;，修改其中的权重分配。把 V1 的权重设置为 0，V2 的权重设置为 100.&lt;/p&gt;

&lt;p&gt;把新的定义提交到 Istio。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ istioctl replace -f app-gateway.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;images/0b6f6f9e-istio-10-300x59.png&#34; alt=&#34;replace&#34; /&gt;&lt;/p&gt;

&lt;p&gt;更新权重之后，V2 的响应比例会提升到 100%。这一结果会体现在输出之中：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/82d4e75d-istio-11.png&#34; alt=&#34;v2-100%&#34; /&gt;&lt;/p&gt;

&lt;p&gt;可以继续对权重进行修改，查看路由的动态变化过程。&lt;/p&gt;

&lt;p&gt;流量管理只是 Istio 的一个功能，后续文章中尝试更多其他特性。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - Gateways</title>
      <link>/post/istio-helm-deep-dive-gateways/</link>
      <pubDate>Sun, 14 Oct 2018 00:06:31 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-gateways/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;这是《Istio Helm Chart 详解》系列的第四篇，对 Gateways Chart 进行一些介绍，并讲解一下使用 Helm 创建 Istio Gateway 的方法。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;前面提到过，Istio 的 Helm Chart，除去用于安装之外，还有部分对 Istio 部署进行调整的能力。Gateways 一节内容，就包含了定制 Istio Ingress/Egress Gateway 的能力。&lt;/p&gt;

&lt;p&gt;这个 Chart 的文件结构和其他组件类似，不同的在于内容，它通过对 &lt;code&gt;values.yaml&lt;/code&gt; 中定义的 Gateways 相关内容的循环遍历，生成不同的 Gateway 单元，下面将会进行讲解和试验。&lt;/p&gt;

&lt;h2 id=&#34;values-yaml-中的变量定义&#34;&gt;&lt;code&gt;values.yaml&lt;/code&gt; 中的变量定义&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;gateways:
  enabled: true

  istio-ingressgateway:
    enabled: true
    labels:
      app: istio-ingressgateway
      istio: ingressgateway
    replicaCount: 1
    autoscaleMin: 1
    autoscaleMax: 5
    resources: {}
      # limits:
      #  cpu: 100m
      #  memory: 128Mi
      #requests:
      #  cpu: 1800m
      #  memory: 256Mi
    cpu:
      targetAverageUtilization: 80
    loadBalancerIP: &amp;quot;&amp;quot;
    serviceAnnotations: {}
    type: LoadBalancer #change to NodePort, ClusterIP or LoadBalancer if need be

    ports:
      ## You can add custom gateway ports
    - port: 80
      targetPort: 80
      name: http2
      nodePort: 31380
    - port: 443
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其中包含了一个层次结构：Gateways 的下级除了用于 &lt;code&gt;requirements.yaml&lt;/code&gt; 使用的 &lt;code&gt;enabled&lt;/code&gt; 字段之外，还包含一个数组，数组的每个元素定义了一个网关。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;range $key, $spec := .Values&lt;/code&gt;：对 &lt;code&gt;gateways&lt;/code&gt; 一节的&lt;strong&gt;局部变量&lt;/strong&gt;进行遍历，第一层遍历的值用 &lt;code&gt;$key&lt;/code&gt; 和 &lt;code&gt;$spec&lt;/code&gt; 两个变量来表示键值对，根据每个键值对的定义，逐个创建资源，下面会提到的 &lt;code&gt;$spec&lt;/code&gt; 引用就是相当于每个网关控制器的定义变量，&lt;code&gt;$key&lt;/code&gt; 就是每个网关控制器的名称。&lt;/p&gt;

&lt;h2 id=&#34;chart-yaml&#34;&gt;Chart.yaml&lt;/h2&gt;

&lt;p&gt;元数据文件，无需赘述。&lt;/p&gt;

&lt;h2 id=&#34;autoscale-yaml&#34;&gt;autoscale.yaml&lt;/h2&gt;

&lt;p&gt;首先讲解一下头部的渲染条件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;{{- range $key, $spec := .Values }}
{{- if and (ne $key &amp;quot;global&amp;quot;) (ne $key &amp;quot;enabled&amp;quot;) }}
{{- if and $spec.enabled $spec.autoscaleMin }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
    name: {{ $key }}
    namespace: {{ $spec.namespace | default $.Release.Namespace }}
spec:
    maxReplicas: {{ $spec.autoscaleMax }}
    minReplicas: {{ $spec.autoscaleMin }}
    scaleTargetRef:
      apiVersion: apps/v1beta1
      kind: Deployment
      name: {{ $key }}
    metrics:
    - type: Resource
      resource:
        name: cpu
        targetAverageUtilization: {{ $spec.cpu.targetAverageUtilization }}
---
{{- end }}
{{- end }}
{{- end }}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;顾名思义，这个文件是用来创建 &lt;a href=&#34;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/&#34; target=&#34;_blank&#34;&gt;HPA&lt;/a&gt; 的，但是整个文件的外层由一个 &lt;a href=&#34;https://docs.helm.sh/chart_template_guide/#looping-with-the-range-action&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;range&lt;/code&gt;&lt;/a&gt; 语句所包围：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{{- if and (ne $key &amp;quot;global&amp;quot;) (ne $key &amp;quot;enabled&amp;quot;) }}&lt;/code&gt; 将会跳过 &lt;code&gt;global&lt;/code&gt; 和 &lt;code&gt;enabled&lt;/code&gt; 键。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{- if and $spec.enabled $spec.autoscaleMin }}&lt;/code&gt;：如果前面读到的 &lt;code&gt;$spec&lt;/code&gt; 变量中的 &lt;code&gt;enabled&lt;/code&gt; 和 &lt;code&gt;autoscaleMin&lt;/code&gt; 都是 &lt;code&gt;true&lt;/code&gt;，才会进行处理。这里条件跟其它几个文件不同：只有设置了 &lt;code&gt;autoscaleMin&lt;/code&gt; 的情况下才会渲染 HPA 对象。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;引用变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$key&lt;/code&gt;：也就是网关的名称，例如前面的 &lt;code&gt;istio-ingressgateway&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.namespace&lt;/code&gt;：可以为这一 Gateway 定义命名空间，如果没有定义，则沿用 Istio 的命名空间，也就是 &lt;code&gt;Release.Namespace&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.autoscaleMax&lt;/code&gt; 和 &lt;code&gt;$spec.autoscaleMin&lt;/code&gt;，Gateway 伸缩的上下限。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cpu.targetAverageUtilization&lt;/code&gt;：伸缩指标，目标平均 CPU 占用率。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;rbac-资源&#34;&gt;RBAC 资源&lt;/h2&gt;

&lt;p&gt;同样的，这里定义了每个网关所对应的 &lt;code&gt;ServiceAccount&lt;/code&gt;、&lt;code&gt;ClusterRole&lt;/code&gt; 以及 &lt;code&gt;ClusterRoleBinding&lt;/code&gt;，用于 RBAC。&lt;/p&gt;

&lt;p&gt;Gateway 角色需要对 &lt;code&gt;thirdpartyresources&lt;/code&gt;、&lt;code&gt;virtualservices&lt;/code&gt;、&lt;code&gt;destinationrules&lt;/code&gt; 以及 &lt;code&gt;gateways&lt;/code&gt; 几种资源进行读写。&lt;/p&gt;

&lt;p&gt;看 &lt;code&gt;meta.name&lt;/code&gt; 的定义可以看出，每个网关都会有自己的 RBAC 资源，命名规则为 &lt;code&gt;[网关名称]-[Istio 所在的命名空间]&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;另外 ServiceAccount 中引用了全局变量 &lt;code&gt;imagePullSecrets&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;deployment-yaml&#34;&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这个模板用于 &lt;code&gt;Deployment&lt;/code&gt; 的创建过程。这个部署运行的主要服务进程和 Ingress Chart 一样，是 &lt;a href=&#34;https://istio.io/docs/reference/commands/pilot-agent/&#34; target=&#34;_blank&#34;&gt;pilot-agent&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&#34;全局变量&#34;&gt;全局变量&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;priorityClassName&lt;/li&gt;
&lt;li&gt;hub&lt;/li&gt;
&lt;li&gt;tag&lt;/li&gt;
&lt;li&gt;istioNamespace&lt;/li&gt;
&lt;li&gt;proxy.envoyStatsd&lt;/li&gt;
&lt;li&gt;controlPlaneSecurityEnabled&lt;/li&gt;
&lt;li&gt;defaultResources&lt;/li&gt;
&lt;li&gt;nodeaffinity&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;变量使用细节&#34;&gt;变量使用细节&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$spec.labels&lt;/code&gt;：这里可以看出，我们可以使用在 &lt;code&gt;values.yaml&lt;/code&gt; 中定义标签 &lt;code&gt;labels&lt;/code&gt; 的方式，为新的 Deployment 指定标签。&lt;strong&gt;标签将同时出现在 Deployment 和下面的 Pod 中。&lt;/strong&gt;，从而定义 &lt;code&gt;Gateway&lt;/code&gt; 资源时，可以用标签来指定对应的控制器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.replicaCount&lt;/code&gt;：可以指定初始副本数量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.ports&lt;/code&gt;：在 &lt;code&gt;ports&lt;/code&gt; 中定义的各种端口，会在容器中进行发布。&lt;/li&gt;
&lt;li&gt;Gateway 名称在这里还作为 &lt;code&gt;--serviceCluster&lt;/code&gt; 的值，这一参数在 Sidecar 中一般取值为 &lt;code&gt;istio-proxy&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;如果定义了 &lt;code&gt;global.istioNamespace&lt;/code&gt;，会使用 &lt;code&gt;[服务名].[命名空间]&lt;/code&gt; 的方式定义 &lt;code&gt;zipkin&lt;/code&gt;、&lt;code&gt;istio-pilot&lt;/code&gt; 的服务地址。&lt;/li&gt;
&lt;li&gt;根据 &lt;code&gt;global.proxy.envoyStatsd&lt;/code&gt; 设置 &lt;code&gt;statsd&lt;/code&gt; 地址。&lt;/li&gt;
&lt;li&gt;如果 Gateway 定义中包含了资源限制的内容，则会在这里进行包含，否则只会使用缺省资源限制。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.additionalContainers&lt;/code&gt; 中还可以定义该 Pod 中额外的容器。&lt;/li&gt;
&lt;li&gt;如果有加载额外 tls secret 的需求，可以定义在 &lt;code&gt;$spec.secretVolume&lt;/code&gt; 中。&lt;/li&gt;
&lt;li&gt;如果有加载额外 Configmap 的需求，可以定义在 &lt;code&gt;$spec.configVolumes&lt;/code&gt; 中。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;service.yaml&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;和其他元素一样，Service 也是使用循环的方式逐个建立的。&lt;/li&gt;
&lt;li&gt;服务名称同样也是直接使用 &lt;code&gt;$key&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;端口、命名空间、标签和 Deployment 模板一致。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$spec.serviceAnnotations&lt;/code&gt; 用于生成服务注解。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;selector&lt;/code&gt; 的定义&lt;strong&gt;也和标签定义一致&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;如果定义了 &lt;code&gt;$spec.loadBalancerIP&lt;/code&gt;，这里会给服务的 &lt;code&gt;loadBalancerIP&lt;/code&gt; 赋值。&lt;/li&gt;
&lt;li&gt;如果定义了 &lt;code&gt;.type&lt;/code&gt;，则将服务类型进行修改。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;测试一下&#34;&gt;测试一下&lt;/h2&gt;

&lt;p&gt;在 &lt;code&gt;values.yaml&lt;/code&gt; 的 &lt;code&gt;gateways&lt;/code&gt; 一节加入这样一段：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  istio-myingress:
    enabled: true
    namespace: default
    labels:
      app: istio-ingressgateway
      istio: myingress
    replicaCount: 1
    autoscaleMax: 5
    resources: {}
    cpu:
      targetAverageUtilization: 80
    loadBalancerIP: &amp;quot;&amp;quot;
    serviceAnnotations: {}
    type: NodePort
    ports:
    - port: 80
      targetPort: 80
      name: http-myingress
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后用命令行生成对应的安装文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ helm template istio --name istio -f \
    values-new-gateway.yaml --namespace \
    istio-system &amp;gt; istio-myingress.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;生成的 yaml，用编辑器打开，使用正则表达式 &lt;code&gt;source:.*?gateways&lt;/code&gt; 进行搜索，会看到生成的内容符合之前的描述，在 &lt;code&gt;Default&lt;/code&gt; 命名空间中出现了新的 ServiceAccount、ClusterRole、ClusterRoleBinding 资源，因为删除了 &lt;code&gt;autoscaleMin&lt;/code&gt;，所以不会产生 HPA 对象，同时服务类型也改成了 NodePort。&lt;/p&gt;

&lt;p&gt;仔细看看会发现其中有一些问题：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pilot、Statsd 等依赖服务的地址还在本命名空间，没有引用 &lt;code&gt;istio-system&lt;/code&gt; 中的服务。&lt;/li&gt;
&lt;li&gt;ClusterRoleBinding 引用的 ServiceAccount 还是指向了 &lt;code&gt;istio-system&lt;/code&gt; 中的 ServiceAccount，但是很明显，这是不存在的。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这两点结合起来，足够给这个 Gateway 控制器判了死刑，是不可能正常工作的。如果用这一个文件安装 Istio，这个 Gateway 对应的 Pod 日志一定会出现错误。要修正错误，有三个方式：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;不再定义 &lt;code&gt;namespace&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;修正 Chart。&lt;/li&gt;
&lt;li&gt;修改渲染后的 YAML 文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以这里妥协一下，删掉 &lt;code&gt;namespace&lt;/code&gt; 一行，使用缺省设置，重新渲染安装。&lt;/p&gt;

&lt;p&gt;安装完成以后，按照&lt;a href=&#34;https://preliminary.istio.io/zh/docs/tasks/traffic-management/ingress/&#34; target=&#34;_blank&#34;&gt;控制 Ingress 流量&lt;/a&gt;一文的介绍，安装 &lt;code&gt;httpbin&lt;/code&gt; 服务，并为其设置 Gateway 和 VirtualService（注意替换其中的域名），其中的 Gateway Selector 使用我们新建的网关 &lt;code&gt;myingress&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: myingress
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - &amp;quot;httpbin.example.rocks&amp;quot;
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - &amp;quot;httpbin.example.rocks&amp;quot;
  gateways:
  - httpbin-gateway
  http:
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;创建这两个资源之后，使用 curl 访问 Ingress 服务，会看到正确的结果返回，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ curl httpbin.example.rocks/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;10.232.0.37&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;再来一次&#34;&gt;再来一次&lt;/h2&gt;

&lt;p&gt;前面的测试我们模拟了从头部署 Istio 的方式，如果是一个现存的 Istio 部署，又应该怎样新建网关？&lt;/p&gt;

&lt;p&gt;根据前面的分析，可以得出引用的所有全局变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;priorityClassName&lt;/li&gt;
&lt;li&gt;hub&lt;/li&gt;
&lt;li&gt;tag&lt;/li&gt;
&lt;li&gt;istioNamespace&lt;/li&gt;
&lt;li&gt;proxy&lt;/li&gt;
&lt;li&gt;controlPlaneSecurityEnabled&lt;/li&gt;
&lt;li&gt;defaultResources&lt;/li&gt;
&lt;li&gt;nodeaffinity&lt;/li&gt;
&lt;li&gt;imagePullSecrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果保证这些变量的完整性，并且和正在运行的 Istio 一致；同时关掉其它的不必要的组件渲染，应该就可以达到效果。这样写一个 &lt;code&gt;values.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;global:
  hub: docker.io/istio
  tag: 1.0.2
  proxy:
    envoyStatsd:
      enabled: true
      host: istio-statsd-prom-bridge
      port: 9125
  imagePullPolicy: IfNotPresent
  controlPlaneSecurityEnabled: false
  imagePullSecrets:
    # - private-registry-key
  defaultResources:
    requests:
      cpu: 10m
  priorityClassName: &amp;quot;&amp;quot;
sidecarInjectorWebhook:
  enabled: false
security:
  enabled: false
ingress:
  enabled: false
mixer:
  enabled: false
pilot:
  enabled: false
grafana:
  enabled: false
prometheus:
  enabled: false
servicegraph:
  enabled: false
tracing:
  enabled: false
galley:
  enabled: false
kiali:
  enabled: false
certmanager:
  enabled: false

gateways:
  enabled: true
  istio-ingressgateway:
    enabled: false
  istio-egressgateway:
    enabled: false    
  istio-newingress:
    enabled: true
    labels:
      app: istio-ingressgateway
      istio: newingress
    replicaCount: 1
    # autoscaleMin: 1
    autoscaleMax: 5
    resources: {}
    cpu:
      targetAverageUtilization: 80
    loadBalancerIP: &amp;quot;&amp;quot;
    serviceAnnotations: {}
    type: LoadBalancer
    ports:
    - port: 80
      targetPort: 80
      name: http-newingress
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;重新渲染并执行。&lt;/p&gt;

&lt;p&gt;修改 httpbin Gateway 定义，将 Selector 变更为 &lt;code&gt;istio: newingress&lt;/code&gt;，提交后使用 CURL 进行验证，会发现新的 Gateway 已经生效。&lt;/p&gt;

&lt;h2 id=&#34;小结&#34;&gt;小结&lt;/h2&gt;

&lt;p&gt;目前的 Gateway 管理还无法让人满意，多命名空间或者按需调度方面的功能还有很大缺憾；但是借用 Helm Chart 进行大块功能管理的方式还是一个有趣而且可能有效的尝试。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - Ingress</title>
      <link>/post/istio-helm-deep-dive-ingress/</link>
      <pubDate>Tue, 09 Oct 2018 14:25:42 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-ingress/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;这是《Istio Helm Chart 详解》系列的第三篇。开始逐个 Chart 进行阅读。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;全局变量之后，接下来就是 Ingress 一节了，这个 Chart 只是个兼容选项，为 Istio 提供了传统 Kubernetes Ingress 的功能。&lt;code&gt;ingress.enabled&lt;/code&gt; 变量用于在 &lt;code&gt;requirements.yaml&lt;/code&gt; 中控制该 Chart 是否启用。&lt;/p&gt;

&lt;h2 id=&#34;chart-yaml&#34;&gt;Chart.yaml&lt;/h2&gt;

&lt;p&gt;元数据文件，无需赘述。&lt;/p&gt;

&lt;h2 id=&#34;autoscale-yaml&#34;&gt;autoscale.yaml&lt;/h2&gt;

&lt;p&gt;该文件用于处理该模块的 &lt;a href=&#34;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/&#34; target=&#34;_blank&#34;&gt;HPA 对象&lt;/a&gt;。引用变量如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ingress.autoscaleMin&lt;/strong&gt;：水平伸缩的 Pod 数量下限，另外该变量被赋值的情况下才会渲染 HPA 对象。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ingress.autoscaleMax&lt;/strong&gt;：水平伸缩的 Pod 数量上限。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Release.Namespace&lt;/strong&gt;：HPA 对象所在的命名空间，使用 Istio 同一值。Release 是 Helm 的保留字，用于标识该 Release 所在的命名空间。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;代码中我们看到，&lt;code&gt;targetAverageUtilization&lt;/code&gt; 设置为固定值 &lt;code&gt;80&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;serviceaccount-yaml&#34;&gt;serviceaccount.yaml&lt;/h2&gt;

&lt;p&gt;这个模板用于为 Pod 生成 Service Account——&lt;code&gt;istio-ingress-service-account&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;其中引用变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;global.imagePullSecrets&lt;/strong&gt;：全局变量定义的数组，提供给 Service Account，在拉取镜像时使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chart&lt;/strong&gt; 和 &lt;strong&gt;Release&lt;/strong&gt; 都是 Helm 的内置对象。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;clusterrole-yaml-和-clusterrolebinding-yaml&#34;&gt;clusterrole.yaml 和 clusterrolebinding.yaml&lt;/h2&gt;

&lt;p&gt;Kubernetes &lt;a href=&#34;https://kubernetes.io/docs/reference/access-authn-authz/rbac/&#34; target=&#34;_blank&#34;&gt;RBAC&lt;/a&gt; 系统使用，这是一个集群范围内生效的 ClusterRole，声明了 Ingress 中需要的两组权限，并最终和 Service Account 进行绑定：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;对于 extensions.thirdpartyresources 和 extensions.ingresses 对象的读写权限。&lt;/li&gt;
&lt;li&gt;对 configmaps、pods、endpoints 和 services 对象的读取权限。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中引用变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;istio.name&lt;/strong&gt;：定义在 istio 的 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中，如果没有使用 &lt;code&gt;nameOverride&lt;/code&gt; 进行覆盖的话，会使用 Chart 名称。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chart&lt;/strong&gt; 和 &lt;strong&gt;Release&lt;/strong&gt; 都是 Helm 的内置对象。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;deployment-yaml&#34;&gt;deployment.yaml&lt;/h2&gt;

&lt;p&gt;这一模板用于生成 Deployment，主体部分和 Ingress Gateway 类似，使用的都是 &lt;code&gt;istio/proxyv2&lt;/code&gt; 镜像，&lt;a href=&#34;https://istio.io/docs/reference/commands/pilot-agent/#pilot-agent-proxy&#34; target=&#34;_blank&#34;&gt;参数稍有区别&lt;/a&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;istio-proxy&lt;/strong&gt;：&lt;code&gt;proxy sidecar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ingress&lt;/strong&gt;：&lt;code&gt;proxy ingress&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gateways&lt;/strong&gt;：&lt;code&gt;proxy router&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中引用变量：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;istio.name&lt;/strong&gt;：定义在 istio 的 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中，如果没有使用 &lt;code&gt;nameOverride&lt;/code&gt; 进行覆盖的话，会使用 Chart 名称。&lt;/li&gt;
&lt;li&gt;使用 Chart 和 Release 数据生成标签。这里可以看到，固定使用 &lt;code&gt;istio: ingress&lt;/code&gt; 提供给 Gateway  Selector 进行选择。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;global.hub&lt;/strong&gt; 和 &lt;strong&gt;global.tag&lt;/strong&gt;：生成镜像地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;replicaCount&lt;/strong&gt;：控制 Pod 数量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;global.imagePullPolicy&lt;/strong&gt;：拉取策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;global.priorityClassName&lt;/strong&gt;：&lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;PriorityClass&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;global.proxy.envoyStatsd.enabled&lt;/strong&gt;：如果启用，则加入 &lt;code&gt;--statsdUdpAddress&lt;/code&gt; 参数。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;global.controlPlaneSecurityEnabled&lt;/strong&gt;：根据这一设置确定 &lt;code&gt;controlPlaneAuthPolicy&lt;/code&gt; 设置：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# 如果启用
- --controlPlaneAuthPolicy
- MUTUAL_TLS
- --discoveryAddress
- istio-pilot:15005
# 如果没启用
- --controlPlaneAuthPolicy
- NONE
- --discoveryAddress
- istio-pilot:8080
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;resources&lt;/strong&gt; 和 &lt;strong&gt;globale.defaultResources&lt;/strong&gt;：优先使用 Chart 自身的资源定义，如果没有则使用缺省定义。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;nodeaffinity&lt;/strong&gt;：包含节点亲和性定义模板。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;另外这里还包含了对两个 secret 的可选加载：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;istio.istio-ingress-service-account&lt;/strong&gt;：用于 RBAC 的 Service Account 证书。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;istio-ingress-certs&lt;/strong&gt;：提供 https 服务时使用这一组证书。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;service-yaml&#34;&gt;service.yaml&lt;/h2&gt;

&lt;p&gt;这个模板用来为 Ingress 生成服务。&lt;/p&gt;

&lt;p&gt;引用变量包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;istio.name&lt;/strong&gt;：定义在 istio 的 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中，如果没有使用 &lt;code&gt;nameOverride&lt;/code&gt; 进行覆盖的话，会使用 Chart 名称。&lt;/li&gt;
&lt;li&gt;使用 Chart 和 Release 数据生成标签。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;service.loadBalancerIP&lt;/strong&gt;：如果指定了 IP，则使用指定 IP。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;service.type&lt;/strong&gt;：如果没有负载均衡支持，可以考虑采用 NodePort 方式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;service.annotations&lt;/strong&gt;：可以设置一系列的键值对，通过遍历的形式为 Service 对象生成注解。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;service.ports&lt;/strong&gt;：可以定义其它的非标准端口，以数组形式供 Helm 进行遍历，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- port: 80
name: http
nodePort: 32000
- port: 443
name: https
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;常用链接&#34;&gt;常用链接&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Helm 内置对象：&lt;a href=&#34;https://docs.helm.sh/chart_template_guide/#built-in-objects&#34; target=&#34;_blank&#34;&gt;https://docs.helm.sh/chart_template_guide/#built-in-objects&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - 全局变量</title>
      <link>/post/istio-helm-deep-dive-global-var/</link>
      <pubDate>Sun, 07 Oct 2018 10:40:16 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-global-var/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;这是《Istio Helm Chart 详解》系列的第二篇。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;我们在使用现有 Chart 的时候，通常都不会修改 Chart 的本体，仅通过对&lt;a href=&#34;https://docs.helm.sh/chart_template_guide/#variables&#34; target=&#34;_blank&#34;&gt;变量&lt;/a&gt;的控制来实现对部署过程的定制。Istio Helm Chart 提供了大量的变量来帮助用户进行定制。&lt;/p&gt;

&lt;p&gt;第一篇中我们提到过，Istio Chart 分为父子两层，因此变量也具有&lt;a href=&#34;https://docs.helm.sh/chart_template_guide/#subcharts-and-global-values&#34; target=&#34;_blank&#34;&gt;全局和本地&lt;/a&gt;两级，全局变量使用保留字 &lt;code&gt;global&lt;/code&gt; 来进行定义，子 Chart 可以通过 &lt;code&gt;.Values.global&lt;/code&gt; 的方式引用全局变量，而主 Chart 中也可以用 &lt;code&gt;chart.var&lt;/code&gt; 的方式为子 Chart 指定变量值，本篇会首先讲解一下 &lt;code&gt;values.yaml&lt;/code&gt; 中涉及到的全局变量，也就是 &lt;code&gt;global&lt;/code&gt; 一节；各个 Chart 涉及到的专属变量会留在各个 Chart 的章节中。&lt;/p&gt;

&lt;h2 id=&#34;hub-和-tag&#34;&gt;hub 和 tag&lt;/h2&gt;

&lt;p&gt;缺省值分别为 &lt;code&gt;docker.io/istio&lt;/code&gt; 和 &lt;code&gt;1.0.2&lt;/code&gt;。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这里看到版本的控制主要是在镜像层面的，Chart 自身的版本控制并不是很规矩，差评。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;多数情况下，这一配置代表所有镜像的地址，具体名称一般由 &lt;code&gt;{{ .Values.global.hub }}/[component]/:{{ .Values.global.tag }}&lt;/code&gt; 的形式拼接而成。proxy_init、Mixer、Grafana 和 Pilot 中，一旦其 &lt;code&gt;image&lt;/code&gt; 变量中包含了路径符 &lt;code&gt;/&lt;/code&gt;，则会弃用 &lt;code&gt;global.hub&lt;/code&gt;，直接采用 &lt;code&gt;image&lt;/code&gt; 的定义。&lt;/p&gt;

&lt;h3 id=&#34;影响范围&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/certmanager/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;certmanager&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-galley&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有 Gateway 的 Deployment&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/create-custom-resources-job.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-grafana-post-install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;grafana&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/kiali/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;kiali&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy&lt;/code&gt;/&lt;code&gt;istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;/&lt;code&gt;mixer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/statsdtoprom.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-statsd-prom-bridge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/cleanup-secrets.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-cleanup-secrets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/create-custom-resources-job.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-security-post-install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-citadel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/servicegraph/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;servicegraph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/tracing/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-tracing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;istio-init&lt;/code&gt;、&lt;code&gt;enable-core-dump&lt;/code&gt;、&lt;code&gt;istio-proxy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;k8singressselector&#34;&gt;k8sIngressSelector&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;ingress&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这一变量比较 Buggy。原则上讲，他仅在 &lt;code&gt;ingress.enabled&lt;/code&gt; 为 &lt;code&gt;true&lt;/code&gt; 的时候生效。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-1&#34;&gt;影响范围&lt;/h3&gt;

&lt;h4 id=&#34;charts-pilot-templates-gateway-yaml&#34;&gt;&lt;code&gt;charts/pilot/templates/gateway.yaml&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;这个文件中定义了一个 Gateway - &lt;code&gt;istio-autogenerated-k8s-ingress&lt;/code&gt;，其中的 &lt;code&gt;spec.selector&lt;/code&gt; 是这样设计的：&lt;code&gt;istio: {{ .Values.global.k8sIngressSelector }}&lt;/code&gt;，实际上该文件中并没有针对 &lt;code&gt;ingress.enabled&lt;/code&gt; 开关做出是否生成网关的判断，该网关一定会创建，但是只有在 &lt;code&gt;Ingress&lt;/code&gt; Chart 中才会创建符合该条件的 Deployment，因此在 &lt;code&gt;Ingress&lt;/code&gt; Chart 没有创建的情况下，该网关的 &lt;code&gt;Selector&lt;/code&gt; 就无法匹配成功，也就无法生效了。&lt;/p&gt;

&lt;h4 id=&#34;templates-configmap-yaml&#34;&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;这里会引用 &lt;code&gt;ingress.enabled&lt;/code&gt; 进行判断，如果判断成功，则在 &lt;code&gt;istio&lt;/code&gt; ConfigMap 对象中写入 &lt;code&gt;ingressService: istio-{{ .Values.global.k8sIngressSelector }}&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;k8singresshttps&#34;&gt;k8sIngressHttps&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-2&#34;&gt;影响范围&lt;/h3&gt;

&lt;h4 id=&#34;charts-pilot-templates-gateway-yaml-1&#34;&gt;&lt;code&gt;charts/pilot/templates/gateway.yaml&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;如果启用该字段，会给 Gateway 定义中加入 443 端口及其 TLS 配置。&lt;/p&gt;

&lt;p&gt;这段配置中对 &lt;code&gt;/etc/istio/ingress/certs/&lt;/code&gt; 下面的证书文件有依赖，因此需要启用这一选项，首先要启用 &lt;code&gt;ingress.enabled&lt;/code&gt;，从而能够成功创建 &lt;code&gt;ingress&lt;/code&gt; Chart 的 Deployment；另外还需要创建一个命名为 &lt;code&gt;ingress-certs&lt;/code&gt; 的 tls secret，给 &lt;code&gt;istio-ingress&lt;/code&gt; Deployment 进行加载。这些条件如果没有满足，LDS 会拒绝服务，从而无法提供 Ingress 功能。&lt;/p&gt;

&lt;h2 id=&#34;proxy-image&#34;&gt;proxy.image&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;proxyv2&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-3&#34;&gt;影响范围&lt;/h3&gt;

&lt;h4 id=&#34;istio-templates-sidecar-injector-configmap-yaml&#34;&gt;&lt;code&gt;istio/templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;其中的 ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt; 中的注入部分会使用该值作为 &lt;code&gt;istio-proxy&lt;/code&gt; 的镜像名。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;image: {{ &amp;quot;[[ if (isset .ObjectMeta.Annotations \&amp;quot;sidecar.istio.io/proxyImage\&amp;quot;) -]]&amp;quot; }}
{{ &amp;quot;\&amp;quot;[[ index .ObjectMeta.Annotations \&amp;quot;sidecar.istio.io/proxyImage\&amp;quot; ]]\&amp;quot;&amp;quot; }}
{{ &amp;quot;[[ else -]]&amp;quot; }}
{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}
{{ &amp;quot;[[ end -]]&amp;quot; }}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这段代码表明，首先会判断 Pod 的 &lt;code&gt;sidecar.istio.io/proxyImage&lt;/code&gt; 注解，如果注解不存在，才会使用这一变量，拼接方式为：&lt;code&gt;{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;proxy-resources&#34;&gt;proxy.resources&lt;/h2&gt;

&lt;p&gt;这里为 Sidecar 定义了资源分配的方案。根据官方的&lt;a href=&#34;https://preliminary.istio.io/zh/docs/concepts/performance-and-scalability/#scalability-and-sizing-guide&#34; target=&#34;_blank&#34;&gt;伸缩性和规模调整指南&lt;/a&gt;：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;开启访问日志（默认开启）时，为 Sidecar 每分配 1 个 vCPU 能够负担 1000 qps 的访问峰值，没有开启则 0.5 vCPU 即可负担同样峰值，节点上的 fluentd 由于需要捕获和上传日志，是主要的性能消耗者。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;影响范围-4&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy&lt;/code&gt;/&lt;code&gt;istio-telemetry&lt;/code&gt; Container：&lt;code&gt;istio-proxy&lt;/code&gt;/&lt;code&gt;mixer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;会注入到所有 Pod&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-concurrency&#34;&gt;proxy.concurrency&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;0&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;Proxy worker 线程数量，如果设置为 0，则根据 CPU 线程/核的数量进行分配。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-5&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;istio/templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-accesslogfile&#34;&gt;proxy.accessLogFile&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;/dev/stdout&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;Sidecar 的访问日志位置，如果设置为空字符串，则关闭访问日志功能。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-6&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-privileged&#34;&gt;proxy.privileged&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istio-init&lt;/code&gt;、&lt;code&gt;istio-proxy&lt;/code&gt; 的特权模式开关。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-7&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-enablecoredump&#34;&gt;proxy.enableCoreDump&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果打开，新注入的 Sidecar 会启动 CoreDump 功能，加入初始化容器 &lt;code&gt;enable-core-dump&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-8&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-includeipranges&#34;&gt;proxy.includeIPRanges&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;&amp;quot;*&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress.html#calling-external-services-directly&#34; target=&#34;_blank&#34;&gt;劫持白名单&lt;/a&gt;，仅劫持该 CIDR 范围内的 IP。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-9&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;修改 &lt;code&gt;istio-init&lt;/code&gt; 的 &lt;code&gt;-i&lt;/code&gt; 参数，等价的 Pod Annotation 为 &lt;code&gt;traffic.sidecar.istio.io/includeOutboundIPRanges&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;proxy-excludeipranges&#34;&gt;proxy.excludeIPRanges&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;CIDR 范围之外的所有 IP 都会被劫持。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-10&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;修改 &lt;code&gt;istio-init&lt;/code&gt; 的 &lt;code&gt;-x&lt;/code&gt; 参数，等价的 Pod Annotation 为 &lt;code&gt;traffic.sidecar.istio.io/excludeOutboundIPRanges&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;proxy-includeinboundports&#34;&gt;proxy.includeInboundPorts&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;&amp;quot;*&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;进入端口的劫持白名单，所有从范围内端口进入 Pod 的流量会被劫持。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-11&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;修改 &lt;a href=&#34;https://github.com/istio/istio/blob/master/tools/deb/istio-iptables.sh&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;istio-init&lt;/code&gt;&lt;/a&gt; 的 &lt;code&gt;-b&lt;/code&gt; 参数，等价的 Pod Annotation 为 &lt;code&gt;traffic.sidecar.istio.io/includeInboundPorts&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;proxy-excludeinboundports&#34;&gt;proxy.excludeInboundPorts&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;进入端口的劫持黑名单，所有从范围外端口进入 Pod 的流量会被劫持。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-12&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;修改 &lt;a href=&#34;https://github.com/istio/istio/blob/master/tools/deb/istio-iptables.sh&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;istio-init&lt;/code&gt;&lt;/a&gt; 的 &lt;code&gt;-d&lt;/code&gt; 参数，等价的 Pod Annotation 为 &lt;code&gt;traffic.sidecar.istio.io/excludeOutboundIPRanges&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;proxy-autoinject&#34;&gt;proxy.autoInject&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;enabled&lt;/code&gt;。用于指定 Sidecar 注入器的策略。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-13&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-envoystatsd&#34;&gt;proxy.envoyStatsd&lt;/h2&gt;

&lt;p&gt;缺省值为：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;enabled: true
host: istio-statsd-prom-bridge
port: 9125
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;设置 Envoy 的 statsd 目标，也就是 Envoy 的 &lt;code&gt;&amp;quot;--statsdUdpAddress&lt;/code&gt; 参数。某些情况下（例如没有安装 Mixer）可以关闭。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-14&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;istio-init&lt;/code&gt;、&lt;code&gt;enable-core-dump&lt;/code&gt;、&lt;code&gt;istio-proxy&lt;/code&gt; 三个容器的镜像&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;proxy-init-image&#34;&gt;proxy_init.image&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;proxy_init&lt;/code&gt;，指定初始化镜像。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;前面提到过，如果这里使用一个带有路径符号 &lt;code&gt;/&lt;/code&gt; 的镜像名称，会忽略前面的 &lt;code&gt;global.hub/tag&lt;/code&gt; 的设置。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;影响范围-15&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;imagepullpolicy&#34;&gt;imagePullPolicy&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;IfNotPresent&lt;/code&gt;。镜像的拉取策略。&lt;/p&gt;

&lt;h2 id=&#34;影响范围-16&#34;&gt;影响范围&lt;/h2&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/certmanager/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;certmanager&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-galley&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有 Gateway 的 Deployment&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;grafana&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy/istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;/&lt;code&gt;mixer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/statsdtoprom.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-statsd-prom-bridge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-citadel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/servicegraph/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;servicegraph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/tracing/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-tracing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/sidecar-injector-configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-init&lt;/code&gt;，&lt;code&gt;istio-proxy&lt;/code&gt;，&lt;code&gt;enable-core-dump&lt;/code&gt; 未受影响&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;controlplanesecurityenabled&#34;&gt;controlPlaneSecurityEnabled&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。控制面是否启用 mTLS。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-17&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制 Ingress 参数 &lt;code&gt;--controlPlaneAuthPolicy&lt;/code&gt; 的取值，&lt;code&gt;MUTUAL_TLS&lt;/code&gt; 或者 &lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/config.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DestinationRule: &lt;code&gt;istio-policy&lt;/code&gt; 和  DestinationRule: &lt;code&gt;istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;为端口 &lt;code&gt;15004&lt;/code&gt; 启用 &lt;code&gt;ISTIO_MUTUAL&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy&lt;/code&gt;/&lt;code&gt;istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制 Sidecar &lt;code&gt;istio-proxy&lt;/code&gt; 参数 &lt;code&gt;--controlPlaneAuthPolicy&lt;/code&gt; 的值，可选 &lt;code&gt;MUTUAL_TLS&lt;/code&gt; 或者 &lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制 Sidecar &lt;code&gt;istio-proxy&lt;/code&gt; 参数 &lt;code&gt;--controlPlaneAuthPolicy&lt;/code&gt; 的值，可选 &lt;code&gt;MUTUAL_TLS&lt;/code&gt; 或者 &lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制 Sidecar &lt;code&gt;istio-proxy&lt;/code&gt; 参数 &lt;code&gt;--controlPlaneAuthPolicy&lt;/code&gt; 的值，可选 &lt;code&gt;MUTUAL_TLS&lt;/code&gt; 或者 &lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;disablepolicychecks&#34;&gt;disablePolicyChecks&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;禁用 Mixer 策略检查。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-18&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;enabletracing&#34;&gt;enableTracing&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;true&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;设置请求跟踪。&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;影响范围-19&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap &lt;code&gt;istio&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;mtls-enabled&#34;&gt;mtls.enabled&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;false&lt;/code&gt;。服务间 mTLS 的缺省设置，可以使用目标规则或者服务注解进行覆盖。这一开关会控制生成一系列的 Job、ConfigMap 以及 Kubernetes RBAC 的相关内容，详情将会在 Security Chart 中讲解。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-20&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/configmap.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ConfigMap：&lt;code&gt;istio-security-custom-resources&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/create-custom-resources-job.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-security-post-install-account&lt;/code&gt; ClusterRole: &lt;code&gt;istio-security-post-install-istio-system&lt;/code&gt; ClusterRoleBinding: &lt;code&gt;istio-security-post-install-role-binding-istio-system&lt;/code&gt; Job：&lt;code&gt;istio-security-post-install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;这几个对象都需要启动这一开关才会创建&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;imagepullsecrets&#34;&gt;imagePullSecrets&lt;/h2&gt;

&lt;p&gt;缺省为空。&lt;/p&gt;

&lt;p&gt;用于为 ServiceAccount 分配镜像拉取过程所需的凭证。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-21&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/certmanager/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;certmanager&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-galley-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有 Gateways 自动生成的 ServiceAccount&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-ingress-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/kiali/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;kiali-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-mixer-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-pilot-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-citadel-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/serviceaccount.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServiceAccount: &lt;code&gt;istio-sidecar-injector-service-account&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;arch&#34;&gt;arch&lt;/h2&gt;

&lt;p&gt;缺省值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;amd64: 2
s390x: 2
ppc64le: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用于 Kubernetes 的节点亲和性调度过程。&lt;/p&gt;

&lt;p&gt;这里列出了几种支持的服务器架构，并给出了优先级。详情请参看本文系列第一篇。&lt;/p&gt;

&lt;h2 id=&#34;onenamespace&#34;&gt;oneNamespace&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果设置为 &lt;code&gt;true&lt;/code&gt;，会对控制面管理的应用命名空间进行限制。如果没有设置，则监控所有命名空间。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-22&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;设置 &lt;a href=&#34;https://istio.io/docs/reference/commands/pilot-discovery/#pilot-discovery-discovery&#34; target=&#34;_blank&#34;&gt;Pilot discovery 的 &lt;code&gt;-a&lt;/code&gt; 参数&lt;/a&gt;。这一参数取值为监控的命名空间名称，目前会选用 Istio 所在的命名空间。&lt;/p&gt;

&lt;h2 id=&#34;configvalidation&#34;&gt;configValidation&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;ture&lt;/code&gt;。用于配置是否开启服务端的配置验证。该选项开启之后，会生成一个 ValidatingWebhookConfiguration 对象，并被包含到 Galley 的配置之中，从而启用校验功能。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-23&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/validatingwehookconfiguration.yaml.tpl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ValidatingWebhookConfiguration: &lt;code&gt;istio-galley&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;meshexpansion&#34;&gt;meshExpansion&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。如果启用，Pilot 和 Citadel 会在 Ingress Gateway 上公开服务。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-24&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/gateway.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gateway：&lt;code&gt;meshexpansion-gateway&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;用于公开服务的 Gateway&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/meshexpansion.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VirtualService：&lt;code&gt;meshexpansion-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pilot 的 VirtualService&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/meshexpansion.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VirtualService：&lt;code&gt;meshexpansion-citadel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Citadel 的  的 VirtualService&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;meshexpansionilb&#34;&gt;meshExpansionILB&lt;/h2&gt;

&lt;p&gt;缺省值为 &lt;code&gt;false&lt;/code&gt;。Pilot 和 Citadel 的 mTLS 和明文端口会在内部网关进行公开。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-25&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/gateway.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gateway：&lt;code&gt;meshexpansion-ilb-gateway&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;用于公开服务的 Gateway&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/meshexpansion.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VirtualService：&lt;code&gt;ilb-meshexpansion-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pilot 的 VirtualService&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/meshexpansion.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VirtualService：&lt;code&gt;meshexpansion-ilb-citadel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Citadel 的  的 VirtualService&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;defaultresources&#34;&gt;defaultResources&lt;/h2&gt;

&lt;p&gt;缺省值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;requests:
  cpu: 10m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;为 Istio 组件提供一个最小的资源定义，以便 HPA 工作方便，每个组件可以定义自己的资源定义进行覆盖。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-26&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-galley&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有网关创建的 Deployment&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;grafana&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/kiali/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;kiali&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy&lt;/code&gt;/&lt;code&gt;istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;/&lt;code&gt;mixer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/statsdtoprom.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-statsd-prom-bridge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Container：&lt;code&gt;istio-proxy&lt;/code&gt;/&lt;code&gt;discovery&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-citadel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/servicegraph/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;servicegraph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deploymet: &lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/tracing/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-tracing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;hyperkube&#34;&gt;hyperkube&lt;/h2&gt;

&lt;p&gt;缺省值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;hub: quay.io/coreos
tag: v1.7.6_coreos.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用于创建 CRD 的容器镜像。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-27&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/create-custom-resources-job.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-grafana-post-install&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/cleanup-secrets.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-cleanup-secrets&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/create-custom-resources-job.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Job：&lt;code&gt;istio-security-post-install&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;priorityclassname&#34;&gt;priorityClassName&lt;/h2&gt;

&lt;p&gt;Kubernetes 1.11.0 以上有两个 &lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;PriorityClass&lt;/code&gt;&lt;/a&gt;，用这种方式创建 Istio 组件 Pod，可以防止因较低的优先级被杀掉。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-28&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/certmanager/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;certmanager&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-galley&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有网管创建的 Deployment&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;grafana&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/kiali/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;kiali&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy/istio-telemetry&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-citadel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/servicegraph/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;servicegraph&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/tracing/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-tracing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;crds&#34;&gt;crds&lt;/h2&gt;

&lt;p&gt;缺省值 &lt;code&gt;true&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果使用的是 Helm 2.10 以上的 &lt;code&gt;helm install&lt;/code&gt;，或者是 &lt;code&gt;helm template&lt;/code&gt; 方式的安装，应该设置为 &lt;code&gt;true&lt;/code&gt;；如果 Helm 版本小于 2.9，必须设置为 &lt;code&gt;false&lt;/code&gt;，并手工执行 &lt;code&gt;kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml&lt;/code&gt; 来首先创建 CRD。&lt;/p&gt;

&lt;h3 id=&#34;影响范围-29&#34;&gt;影响范围&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;templates/crds.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;随这一开关确定是否创建所有 CRD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;小结&#34;&gt;小结&lt;/h2&gt;

&lt;p&gt;本节中很多涉及到下层 Chart 的内容并未深入，会在子 Chart 的相关章节中尝试进一步说明。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio Helm Chart 详解 - 概述</title>
      <link>/post/istio-helm-deep-dive-overview/</link>
      <pubDate>Sat, 06 Oct 2018 12:55:00 +0800</pubDate>
      <guid>/post/istio-helm-deep-dive-overview/</guid>
      <description>

&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;

&lt;p&gt;Helm 是目前 Istio 官方推荐的安装方式，除去安装之外，还可以利用对输入值的一些调整，完成对 Istio 的部分配置工作。官方提供了 &lt;a href=&#34;https://preliminary.istio.io/zh/docs/setup/kubernetes/helm-install/&#34; target=&#34;_blank&#34;&gt;Istio 的 Helm 部署方式&lt;/a&gt;，侧重于快速启动，而这一组文章将会采用由上至下的顺序，基于 Istio 1.0.2 版本的 Helm Chart 做一系列的讲解。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Istio 的 Helm Chart 分为两个大分支：istio 和 istio-remote，后者为多集群部署方式，这里暂不涉及，后面的内容围绕 istio 展开。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;总体结构&#34;&gt;总体结构&lt;/h2&gt;

&lt;p&gt;Istio Chart 是一个总分结构，其分级结构和设计结构是一致的，这里做一个简单的说明。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/istio-overview.png&#34; alt=&#34;arch&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;chart-yaml&#34;&gt;Chart.yaml&lt;/h3&gt;

&lt;p&gt;Chart 的基础信息，这里看到 1.0.2 的 Release 中，&lt;code&gt;version&lt;/code&gt; 的值还是 1.0.1；要求的 Tiller 版本要大于等于 &lt;code&gt;2.7.2-0&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&#34;values-yaml&#34;&gt;values-*.yaml&lt;/h3&gt;

&lt;p&gt;这里提供了一组 values 文件，提供 Istio 在各种场景下的关键配置范本。对 Istio 的定制可以从 &lt;code&gt;values.yaml&lt;/code&gt; 的改写开始，完成后可以使用 &lt;code&gt;helm template&lt;/code&gt; 命令来生成最终的部署文件供 &lt;code&gt;kubectl&lt;/code&gt; 使用。&lt;code&gt;values.yaml&lt;/code&gt; 文件的一些细节可以参考&lt;a href=&#34;https://docs.helm.sh/chart_best_practices/values/&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;values-istio-auth-galley.yaml&lt;/strong&gt;：启用控制面 mTLS；缺省打开网格内的 mTLS；启用 Galley。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-auth-multicluster.yaml&lt;/strong&gt;：多集群配置；启用控制面 mTLS；缺省打开网格内的 mTLS；禁用自签署证书。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-auth.yaml&lt;/strong&gt;：启用控制面 mTLS；缺省打开网格内的 mTLS。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-demo-auth.yaml&lt;/strong&gt;：启用控制面 mTLS；缺省打开网格内的 mTLS；激活 Grafana、Jaeger、ServiceGraph 以及 Galley；允许自动注入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-demo.yaml&lt;/strong&gt;：激活 Grafana、Jaeger、ServiceGraph 以及 Galley；允许自动注入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-galley.yaml&lt;/strong&gt;：启用 Galley 和 Prometheus。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-gateways.yaml&lt;/strong&gt;：这是一个样例，可以用这种形式定义新的 Gateway。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-multicluster.yaml&lt;/strong&gt;：多集群配置，禁用自签发证书。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-one-namespace-auth.yaml&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio-one-namespace.yaml&lt;/strong&gt;：启用控制面 mTLS；缺省打开网格内的 mTLS；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values-istio.yaml&lt;/strong&gt;：oneNameSpace 设置为 True，让 Pilot 只监控单一的 Namespace，目前的情况是只监控 Istio 的部署命名空间。此处的 istiotesting 似乎是个 Issue。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;values.yaml&lt;/strong&gt;：罗列了（可能）所有变量，也是我们做定制的基础。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;requiremtens-yaml&#34;&gt;requiremtens.yaml&lt;/h3&gt;

&lt;p&gt;这个文件用于管理 Chart 的&lt;a href=&#34;https://docs.helm.sh/developing_charts/#chart-dependencies&#34; target=&#34;_blank&#34;&gt;依赖关系&lt;/a&gt;，Istio 的各个组件就是在这里定义的，并且可以通过变量进行控制。&lt;/p&gt;

&lt;h3 id=&#34;templates&#34;&gt;templates&lt;/h3&gt;

&lt;h4 id=&#34;affinity-tpl&#34;&gt;_affinity.tpl&lt;/h4&gt;

&lt;p&gt;该文件会生成一组&lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature&#34; target=&#34;_blank&#34;&gt;节点亲和/互斥&lt;/a&gt;元素，供各个组件在渲染 YAML 时候使用。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;nodeAffinityRequiredDuringScheduling&lt;/code&gt;：仅在本文件中使用。这里规定了对节点的要求，&lt;code&gt;values.yaml&lt;/code&gt; 中的 &lt;code&gt;global.arch&lt;/code&gt; 变量中列出了一系列的主机架构，只有出现在这一列表中，且对应值大于 &lt;code&gt;0&lt;/code&gt; 的节点，才会将 Pod 调度到该节点上。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;nodeAffinityPreferredDuringScheduling&lt;/code&gt;：仅在本文件中使用。这里规定了调度优先级，为各种架构的节点分配了权重。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;nodeaffinity&lt;/code&gt;：包含了上面谈到的两个模板，合成为一个节点亲和性的代码段，供外部文件使用，影响范围包括：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;文件名&lt;/th&gt;
&lt;th&gt;涉及对象&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/galley/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-galley&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/gateways/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;所有 gateways Chart 生成的 Deployment。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/grafana/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;grafana&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/ingress/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-ingress&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/mixer/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-policy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/pilot/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-pilot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/prometheus/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/security/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-citadel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/servicegraph/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;servicegraph&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/sidecarInjectorWebhook/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-sidecar-injector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charts/tracing/templates/deployment.yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment：&lt;code&gt;istio-tracing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;helpers-tpl&#34;&gt;_helpers.tpl&lt;/h4&gt;

&lt;p&gt;这个文件并不特别，创建了四个变量，供 Helm 使用。&lt;/p&gt;

&lt;h4 id=&#34;sidecar-injector-configmap-yaml&#34;&gt;sidecar-injector-configmap.yaml&lt;/h4&gt;

&lt;p&gt;这里定义了 ConfigMap 对象 &lt;code&gt;istio-sidecar-injector&lt;/code&gt;，为 &lt;code&gt;sidecarInjectorWebhook&lt;/code&gt; 提供配置支持，在全局变量 &lt;code&gt;omitSidecarInjectorConfigMap&lt;/code&gt; 为 &lt;code&gt;False&lt;/code&gt; 的时候进行渲染，这一参数会用在生成新的 Gateway 之类的调整功能上，防止创建多余的 ConfigMap。这里可以看到使用各种变量拼装而成的注入模板，用于为被注入 Pod 提供初始化和 Sidecar 容器的支持。其中涉及的变量会在后文中进行讲解。&lt;/p&gt;

&lt;h4 id=&#34;configmap-yaml&#34;&gt;configmap.yaml&lt;/h4&gt;

&lt;p&gt;这个文件定义了 ConfigMap 对象 &lt;code&gt;istio&lt;/code&gt;，该对象会随 Pilot 一同创建，也就是说它是 Pilot 的依赖项。其中所涉变量也同样会在其他文章中进行讲解。&lt;/p&gt;

&lt;h3 id=&#34;charts&#34;&gt;charts&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;certmanager&lt;/code&gt;：一个基于 &lt;a href=&#34;https://github.com/jetstack/cert-manager&#34; target=&#34;_blank&#34;&gt;Jetstack Cert-Manager 项目&lt;/a&gt;的 ACME 证书客户端，用于自动进行证书的申请、获取以及分发&lt;/li&gt;
&lt;li&gt;&lt;code&gt;galley&lt;/code&gt;：Istio 利用 &lt;a href=&#34;https://istio.io/zh/docs/reference/commands/galley/&#34; target=&#34;_blank&#34;&gt;Galley&lt;/a&gt; 进行配置管理工作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gateways&lt;/code&gt;：使用 Gateways 一节的配置，可以实现多个 Gateway Controller&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grafana&lt;/code&gt;：&lt;a href=&#34;https://grafana.com&#34; target=&#34;_blank&#34;&gt;图形化的 Istio Dashboard&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ingress&lt;/code&gt;：一个遗留设计，缺省关闭，v1alpha3 之后建议弃用。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kiali&lt;/code&gt;：带有分布式跟踪、配置校验等多项功能的 Dashboard。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mixer&lt;/code&gt;：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pilot&lt;/code&gt;：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus&lt;/code&gt;：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;security&lt;/code&gt;：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;servicegraph&lt;/code&gt;：&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sidecarInjectorWebhook&lt;/code&gt;：自动注入 Webhook 的相关配置&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tracing&lt;/code&gt;：&lt;a href=&#34;https://github.com/jaegertracing&#34; target=&#34;_blank&#34;&gt;Jaeger&lt;/a&gt; 的分布式跟踪相关配置。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;小结&#34;&gt;小结&lt;/h2&gt;

&lt;p&gt;本篇主要讲述的是整体结构以及顶层对象的一些内容。后面将会分几篇文章讲讲各种变量的应用以及各个 Chart 的配置。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 适配器模板列表</title>
      <link>/post/adapter-relations/</link>
      <pubDate>Sat, 08 Sep 2018 20:54:09 +0800</pubDate>
      <guid>/post/adapter-relations/</guid>
      <description>&lt;p&gt;Istio Mixer 是 Istio 和其他基础设施的沟通桥梁，其中的具体实现是通过适配器进行的，请求经过 Mixer 时候会使用模板进行处理，生成适配器所需的输入内容。根据 Istio 的对象参考，总结了一份适配器和模板的关系表，希望对 Mixer 用户能有所助益。&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;适配器&lt;/th&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;模板&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/apigee/&#34; target=&#34;_blank&#34;&gt;Apigee&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;apigee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/authorization/&#34; target=&#34;_blank&#34;&gt;authorization&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/analytics/&#34; target=&#34;_blank&#34;&gt;analytics&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://docs.apigee.com/api-platform/istio-adapter/concepts&#34; target=&#34;_blank&#34;&gt;APIGee&lt;/a&gt; 提供的用于认证、配额以及分析功能接口&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/circonus/&#34; target=&#34;_blank&#34;&gt;Circonus&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;circonus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;用于 &lt;a href=&#34;https://www.circonus.com/&#34; target=&#34;_blank&#34;&gt;Circonus&lt;/a&gt; 监控系统接入的适配器&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/cloudmonitor/&#34; target=&#34;_blank&#34;&gt;CloudMonitor&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cloudmonitor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://cloudmonitor.console.aliyun.com/&#34; target=&#34;_blank&#34;&gt;阿里云监控&lt;/a&gt;适配器&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/cloudwatch/&#34; target=&#34;_blank&#34;&gt;CloudWatch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cloudwatch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://aws.amazon.com/cloudwatch/&#34; target=&#34;_blank&#34;&gt;Amazon CloudWatch&lt;/a&gt; 监控适配器&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/datadog/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dogstatsd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;向 &lt;a href=&#34;https://www.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt; 代理发送监控指标的适配器&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/denier&#34; target=&#34;_blank&#34;&gt;Denier&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;denier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/checknothing/&#34; target=&#34;_blank&#34;&gt;checknothing&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/listentry/&#34; target=&#34;_blank&#34;&gt;listentry&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/quota/&#34; target=&#34;_blank&#34;&gt;quota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;用于在前置检查过程中返回一个指定的拒绝信息和错误码&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/fluentd/&#34; target=&#34;_blank&#34;&gt;Fluentd&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fluentd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/logentry/&#34; target=&#34;_blank&#34;&gt;logentry&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;向 Fluentd 发送日志&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/kubernetesenv/&#34; target=&#34;_blank&#34;&gt;Kubernetes Env&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kubernetesenv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/kubernetes/&#34; target=&#34;_blank&#34;&gt;kubernetesenv&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;从 Kubernetes 环境中取出信息生成 Istio 属性数据&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/list/&#34; target=&#34;_blank&#34;&gt;List&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/listentry/&#34; target=&#34;_blank&#34;&gt;listentry&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;可以用来进行简单的列表检查&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/memquota/&#34; target=&#34;_blank&#34;&gt;Memory quota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;memquota&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/quota/&#34; target=&#34;_blank&#34;&gt;quota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为 Istio 提供配额支持&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/opa/&#34; target=&#34;_blank&#34;&gt;OPA&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;opa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/authorization/&#34; target=&#34;_blank&#34;&gt;authorization&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;基于 &lt;a href=&#34;http://www.openpolicyagent.org/&#34; target=&#34;_blank&#34;&gt;Open Policy Agent&lt;/a&gt; 的访问控制支持&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/prometheus/&#34; target=&#34;_blank&#34;&gt;Prometheus&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;prometheus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;用于向 Prometheus 发送监控指标&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/rbac/&#34; target=&#34;_blank&#34;&gt;RBAC&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rbac&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/authorization/&#34; target=&#34;_blank&#34;&gt;authorization&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为网格中的服务提供基于角色的访问控制支持能力&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/redisquota/&#34; target=&#34;_blank&#34;&gt;Redis Quota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;redisquota&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/quota/&#34; target=&#34;_blank&#34;&gt;quota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为 Istio 提供配额支持，需要 Redis 服务进行分布处理&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/servicecontrol/&#34; target=&#34;_blank&#34;&gt;Service Control&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;servicecontrol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/servicecontrolreport/&#34; target=&#34;_blank&#34;&gt;servicecontroller&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/quota/&#34; target=&#34;_blank&#34;&gt;quota&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/apikey/&#34; target=&#34;_blank&#34;&gt;apikey&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;向 &lt;a href=&#34;https://cloud.google.com/service-control&#34; target=&#34;_blank&#34;&gt;Google Service Control&lt;/a&gt; 发送日志和指标&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/signalfx/&#34; target=&#34;_blank&#34;&gt;SignalFx&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;signalfx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/tracespan/&#34; target=&#34;_blank&#34;&gt;tracespan&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为 &lt;a href=&#34;https://signalfx.com/&#34; target=&#34;_blank&#34;&gt;SignalFX&lt;/a&gt; 提供指标和跟踪数据&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/solarwinds/&#34; target=&#34;_blank&#34;&gt;SolarWinds&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;solarwinds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/logentry/&#34; target=&#34;_blank&#34;&gt;logentry&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;分别向 &lt;a href=&#34;https://www.papertrailapp.com/&#34; target=&#34;_blank&#34;&gt;Papertrail&lt;/a&gt; 日志后端 and the &lt;a href=&#34;https://www.appoptics.com/&#34; target=&#34;_blank&#34;&gt;AppOptics&lt;/a&gt; 监控后端发送日志和指标数据&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/stackdriver/&#34; target=&#34;_blank&#34;&gt;Stackdriver&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stackdriver&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/logentry/&#34; target=&#34;_blank&#34;&gt;logentry&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/tracespan/&#34; target=&#34;_blank&#34;&gt;tracespan&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为 &lt;a href=&#34;https://cloud.google.com/stackdriver/&#34; target=&#34;_blank&#34;&gt;StackDriver&lt;/a&gt; 提供日志、指标和跟踪数据&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/statsd/&#34; target=&#34;_blank&#34;&gt;StatsD&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;statsd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;为 statsd 提供指标数据&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/adapters/stdio/&#34; target=&#34;_blank&#34;&gt;Stdio&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stdio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/metric/&#34; target=&#34;_blank&#34;&gt;metric&lt;/a&gt;，&lt;a href=&#34;https://preliminary.istio.io/docs/reference/config/policy-and-telemetry/templates/logentry/&#34; target=&#34;_blank&#34;&gt;logentry&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;在本机输出日志或指标数据&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
    </item>
    
    <item>
      <title>Istio 大入门——Egress Gateway</title>
      <link>/post/istio-egressgateway-dive/</link>
      <pubDate>Fri, 24 Aug 2018 11:46:24 +0800</pubDate>
      <guid>/post/istio-egressgateway-dive/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;Istio 还是早期版本的时候，我曾经有个蒙事的混蛋设想：在网格里面搭建一个反向代理，用于代理网格甚至是集群之外的存量应用，让这些改不得甚至动不得又正在赚钱的应用，以网格内成员的身份对网格中的微服务提供服务。后来知道了，Istio 的 Egress Gateway 实现了这一混蛋想法。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;原理&#34;&gt;原理&lt;/h2&gt;

&lt;p&gt;根据&lt;a href=&#34;https://istio.io/zh/docs/reference/config/istio.networking.v1alpha3/#gateway&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;的解释：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Gateway 描述了一个负载均衡器，用于承载网格边缘的进入和发出连接。这一规范中描述了一系列开放端口，以及这些端口所使用的协议、负载均衡的 SNI 配置等内容。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;之前的 &lt;a href=&#34;https://blog.fleeto.us/post/istio-egress-dive/&#34; target=&#34;_blank&#34;&gt;Service Entry&lt;/a&gt; 一文中讲到了 ServiceEntry 对象，让网格内部的应用在访问外部应用时，可以使用 &lt;code&gt;VirtualService&lt;/code&gt; 进行部分控制。但是如果我们进一步尝试策略的话，会发现常用的 Denier 等适配器都是无效的（这点并没有经过官方验证）。这里就需要使用刚才说的 Egress Gateway 了。&lt;/p&gt;

&lt;p&gt;根据&lt;a href=&#34;https://istio.io/zh/docs/tasks/traffic-management/egress-gateway/&#34; target=&#34;_blank&#34;&gt;官方示例&lt;/a&gt;介绍，这种方式的基本访问流程是：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;建立 Service Entry 对象，注册外部服务。&lt;/li&gt;
&lt;li&gt;建立 Egress Gateway 注册出口。&lt;/li&gt;
&lt;li&gt;创建 DestinationRule，定义一个到 &lt;code&gt;istio-egressgateway.istio-system.svc.cluster.local&lt;/code&gt; &lt;strong&gt;服务&lt;/strong&gt; 的目标规则。&lt;/li&gt;
&lt;li&gt;创建 VirtualService 对象，这一对象对主机名 &lt;code&gt;edition.cnn.com&lt;/code&gt; 生效：

&lt;ul&gt;
&lt;li&gt;如果流量发生在 &lt;code&gt;mesh&lt;/code&gt; gateway，则把请求转发给 &lt;code&gt;istio-egressgateway.istio-system&lt;/code&gt; 服务。&lt;/li&gt;
&lt;li&gt;如果流量发生在 &lt;code&gt;egress&lt;/code&gt; gateway，则把请求转发到外部。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;开始之前&#34;&gt;开始之前&lt;/h2&gt;

&lt;p&gt;跟前文一样，需要部署两个版本的 &lt;code&gt;sleep&lt;/code&gt; 服务。源码见后。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ istioctl kube-inject -f sleep-v1v2.yaml | kubectl apply -f -
service/sleep created
deployment.extensions/sleep-v1 created
deployment.extensions/sleep-v2 created
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来把两个版本的 Pod 分别保存到环境变量之中。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ export SLEEP_V1=$(kubectl get pod -l app=sleep,version=v1 -o jsonpath={.items..metadata.name})
$ export SLEEP_V2=$(kubectl get pod -l app=sleep,version=v2 -o jsonpath={.items..metadata.name})
$ env | grep SLEEP
SLEEP_V2=sleep-v2-69f4fc6c68-s9d96
SLEEP_V1=sleep-v1-d5b4f795f-fcrxs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再建立一个 ServiceEntry，完成准备工作。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
    - httpbin.org
  ports:
    - number: 80
      name: http
      protocol: HTTP
  resolution: DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;设立别名并确认可访问性：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ alias S1_HTTPBIN=&amp;quot;kubectl exec -it $SLEEP_V1 -c sleep -- curl http://httpbin.org/ip&amp;quot;
$ alias S2_HTTPBIN=&amp;quot;kubectl exec -it $SLEEP_V2 -c sleep -- curl http://httpbin.org/ip&amp;quot;
$ S1_HTTPBIN
{
  &amp;quot;origin&amp;quot;: &amp;quot;13.67.109.88&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;成功返回。&lt;/p&gt;

&lt;h2 id=&#34;创建-gateway-和-destinationrule&#34;&gt;创建 Gateway 和 DestinationRule&lt;/h2&gt;

&lt;h3 id=&#34;建立-gateway&#34;&gt;建立 Gateway&lt;/h3&gt;

&lt;p&gt;这里为域名 &amp;ldquo;httpbin.org&amp;rdquo; 创建一个网关，&lt;code&gt;selector&lt;/code&gt; 字段表明这里使用的是 Egress gateway。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: egressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - httpbin.org
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;为服务-istio-egressgateway-创建一个目标规则&#34;&gt;为服务 &lt;code&gt;istio-egressgateway&lt;/code&gt; 创建一个目标规则&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: dest-rule-httpbin
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
    - name: ext
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的 &lt;code&gt;host&lt;/code&gt; 字段使用了 &lt;code&gt;istio-egressgateway&lt;/code&gt; 的 FQDN，指向 &lt;code&gt;istio-system&lt;/code&gt; 命名空间。&lt;/p&gt;

&lt;h2 id=&#34;创建-virtualservice&#34;&gt;创建 VirtualService&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-httpbin
spec:
  hosts:
    - httpbin.org # 这一对象对域名 “httpbin.org” 生效。
  gateways: # 本对象所针对的 Gateway。
    - httpbin-gateway # 前面为 “httpbin.org” 注册的 Egress gateway。
    - mesh # 内置 Gateway，代表网格中的所有 Sidecar
  http:
    - match: # 这一条规则匹配的是 “mesh” Gateway 的流量
        - gateways:
            - mesh
          port: 80
      route: # 如果是 “mesh” gateway 的流量，则转发到 egress 网关服务。
        - destination:
            host: istio-egressgateway.istio-system.svc.cluster.local
            subset: ext
            port:
              number: 80
          weight: 100
    - match:
        - gateways: # 这一条规则匹配的是外发流量
            - httpbin-gateway
          port: 80
      route: # 通过 Service Entry 流向目标的外网流量
        - destination:
            host: httpbin.org
            port:
              number: 80
          weight: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这一对象创建之后，我们再次尝试访问 “&lt;a href=&#34;http://httpbin.org/ip”&#34; target=&#34;_blank&#34;&gt;http://httpbin.org/ip”&lt;/a&gt; ：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ S1_HTTPBIN
{
  &amp;quot;origin&amp;quot;: &amp;quot;10.240.0.41, 13.67.109.88&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到访问成功，并且返回地址中因为转发的原因，代入了 Pod IP。&lt;/p&gt;

&lt;p&gt;如果查看 Egress gateway controller 的日志，也会看到这一访问的踪迹：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubetail  egress -n istio-system
Will tail 1 logs...
istio-egressgateway-55449548bd-99mvl
[istio-egressgateway-55449548bd-99mvl] [2018-08-25T15:07:29.272Z] &amp;quot;GET /ip HTTP/2&amp;quot; 200 - 0 44 477 473 &amp;quot;10.240.0.41&amp;quot; &amp;quot;curl/7.35.0&amp;quot; &amp;quot;e9cc4d93-7617-9f97-b29e-3411c3b66543&amp;quot; &amp;quot;httpbin.org&amp;quot; &amp;quot;52.73.140.127:80&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;加入策略限制&#34;&gt;加入策略限制&lt;/h2&gt;

&lt;p&gt;经过上面一番折腾之后，应用对外部网站的请求就有了一段完全在网格内的部分，接下来就可尝试使用策略了。&lt;/p&gt;

&lt;h2 id=&#34;denier&#34;&gt;Denier&lt;/h2&gt;

&lt;p&gt;首先我们尝试编写一个 Denier 策略，只允许 “v2” 版本对 “httpbin.org” 的访问：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：跨命名空间的策略，必须在 “istio-system” 命名空间中创建。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;---
apiVersion: config.istio.io/v1alpha2
kind: denier
metadata:
  name: denysleepv1
  namespace: istio-system
spec:
  status:
    code: 7
    message: Not allowed
---
apiVersion: config.istio.io/v1alpha2
kind: checknothing
metadata:
  name: denysleepv1request
  namespace: istio-system
spec: null
---
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: deneysleepv1
  namespace: istio-system
spec:
  match: &amp;gt;-
    source.labels[&amp;quot;app&amp;quot;]==&amp;quot;sleep&amp;quot; &amp;amp;&amp;amp; source.labels[&amp;quot;version&amp;quot;]==&amp;quot;v1&amp;quot; &amp;amp;&amp;amp;
    request.host==&amp;quot;httpbin.org&amp;quot;
  actions:
    - handler: denysleepv1.denier
      instances:
        - denysleepv1request.checknothing
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;创建这一策略之后进行验证：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt; $ kubectl apply -f denier.yaml -n istio-system
denier.config.istio.io/denysleepv1 created
checknothing.config.istio.io/denysleepv1request created
rule.config.istio.io/deneysleepv1 created
$ S1_HTTPBIN
PERMISSION_DENIED:denysleepv1.denier.istio-system:Not allowed
$ S2_HTTPBIN
{
  &amp;quot;origin&amp;quot;: &amp;quot;10.240.0.21, 13.67.109.88&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;由上面的测试可以看到，策略应用之后。来自 “v1” 的请求被禁止。如果进一步测试还可以发现，“v1” 服务对其他的访问还是可以照常进行。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;补充：1.0.1 中，&lt;code&gt;ServiceEntry&lt;/code&gt; 应该在 &lt;code&gt;istio-system&lt;/code&gt; 中创建。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;频率限制&#34;&gt;频率限制&lt;/h2&gt;

&lt;p&gt;再次失败，等 Issue。&lt;/p&gt;

&lt;h2 id=&#34;源码&#34;&gt;源码&lt;/h2&gt;

&lt;h3 id=&#34;sleep-yaml&#34;&gt;sleep.yaml&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
spec:
  selector:
    app: sleep
  ports:
    - name: ssh
      port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
        version: v1
    spec:
      containers:
      - name: sleep
        image: dustise/sleep:latest
        imagePullPolicy: IfNotPresent
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
        version: v2
    spec:
      containers:
      - name: sleep
        image: dustise/sleep:latest
        imagePullPolicy: IfNotPresent
---
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Istio 小入门 —— ServiceEntry 的对外通信</title>
      <link>/post/istio-egress-dive/</link>
      <pubDate>Mon, 20 Aug 2018 19:44:05 +0800</pubDate>
      <guid>/post/istio-egress-dive/</guid>
      <description>

&lt;p&gt;上一篇讲了一些入口流量的事情，在实际项目运行中，还有另外一类边界流量，就是出口流量，也常被称为 egress 流量。这一篇结合一点实际需求，设计一些常用场景，讲讲服务网格中对外部服务的调用过程。&lt;/p&gt;

&lt;p&gt;这里我们需要几个服务定义，首先是用于模拟客户端服务的工作负载，这里继续使用 &lt;code&gt;dustise/sleep&lt;/code&gt; 镜像。外部我们使用两个网站作为我们的外部服务演示，分别代表 &lt;code&gt;http&lt;/code&gt; 和 &lt;code&gt;https&lt;/code&gt; 两种：&lt;code&gt;http://httpbin.org&lt;/code&gt; 和 &lt;code&gt;https://api.jd.com/&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;开始之前&#34;&gt;开始之前&lt;/h2&gt;

&lt;p&gt;根据&lt;a href=&#34;https://istio.io/zh/docs/setup/kubernetes/&#34; target=&#34;_blank&#34;&gt;安装文档&lt;/a&gt;的说明完成 Istio 的部署，这里建议使用 Helm 方式。&lt;/p&gt;

&lt;p&gt;使用的 &lt;code&gt;dustise/sleep&lt;/code&gt; 镜像生成两个负载，使用 &lt;code&gt;version&lt;/code&gt; 标签将负载拆分为 &lt;code&gt;v1&lt;/code&gt; 和 &lt;code&gt;v2&lt;/code&gt; 两个版本。源码见文末。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ istioctl kube-inject -f sleep.dual.yaml | kubectl apply -f -
service/sleep created
deployment.extensions/sleep-v1 created
deployment.extensions/sleep-v2 created
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后使用环境变量保存新建 Pod 名称：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export SLEEP_V1=$(kubectl get pod -l app=sleep,version=v1 -o jsonpath={.items..metadata.name})
export SLEEP_V2=$(kubectl get pod -l app=sleep,version=v2 -o jsonpath={.items..metadata.name})
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;创建-serviceentry&#34;&gt;创建 &lt;code&gt;ServiceEntry&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;首先创建一个 &lt;code&gt;ServiceEntry&lt;/code&gt;，指向 &lt;a href=&#34;http://httpbin.org&#34; target=&#34;_blank&#34;&gt;httpbin.org&lt;/a&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后给 &lt;a href=&#34;https://api.jd.com/&#34; target=&#34;_blank&#34;&gt;api.jd.com&lt;/a&gt; 创建一个 ServiceEntry：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: jd-api
spec:
  hosts:
  - api.jd.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;发起外部访问&#34;&gt;发起外部访问&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ kubectl exec -it $SLEEP_V1 -c sleep sh
/ # curl http://httpbin.org/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;168.63.251.242&amp;quot;
}
/ # curl https://api.jd.com
&amp;lt;html&amp;gt;
...
&amp;lt;/html&amp;gt;
/ # curl -v http://api.jd.com
...
&amp;lt; HTTP/1.1 404 Not Found
...
* Connection #0 to host api.jd.com left intact
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，已经注册了的主机，可以通过对应的协议来进行访问了，但是如果协议不匹配，也会返回 404 代码。后面的内容，会选择几个常见场景进行演示。&lt;/p&gt;

&lt;h2 id=&#34;服务质量监控&#34;&gt;服务质量监控&lt;/h2&gt;

&lt;p&gt;Istio 提供了很多的指标数据，对于外部服务来说，其服务端并不受控，但是还是可以从客户端获取一定的指标，来判断服务的状态。例如用下面的命令生成负载之后：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl exec -it $SLEEP_V2 -c sleep -- wrk -d 10m http://httpbin.org/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以在 Grafana 中看到如下的图形：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/httpbin.grafana.png&#34; alt=&#34;grafaba&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;设置超时限制&#34;&gt;设置超时限制&lt;/h2&gt;

&lt;p&gt;外部应用的服务质量通常是不受调用方管理的，为了防止意外超时拖累整体应用，我们可以给外部服务设置一个超时限制，超过这一规则的调用直接中断。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin-service
spec:
  hosts:
  - httpbin.org
  http:
  - timeout: 3s
    route:
    - destination:
        host: httpbin.org
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;应用之后，再次进入 Pod 执行指令访问 &lt;code&gt;http://httpbin.org&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ kubectl apply -f httpbin-timeout.yaml
virtualservice.networking.istio.io/httpbin-service created
$ kubectl exec -it $SLEEP_V1 -c sleep sh
/ # time curl -sSL http://httpbin.org/delay/2 &amp;gt;&amp;gt; /dev/null
real    0m 2.51s
user    0m 0.00s
sys     0m 0.00s
/ # time curl -sSL http://httpbin.org/delay/5
upstream request timeout
real    0m 3.01s
user    0m 0.00s
sys     0m 0.00s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的测试可以看出，第二次的延迟五秒调用已经返回了超时的结果，并且是在我们的三秒限制之内完成了调用。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;kubectl delete -f httpbin-timeout.yaml&lt;/code&gt; 删除这一定义，进行下一步。&lt;/p&gt;

&lt;h2 id=&#34;仅允许指定源头访问&#34;&gt;仅允许指定源头访问&lt;/h2&gt;

&lt;p&gt;设想我们的网格中，仅有部分应用可以访问一些外部服务，这里我们借用 Istio 的故障注入功能，定义一个 abort 的注入，只允许 &lt;code&gt;sleep:v2&lt;/code&gt; 访问 &lt;code&gt;http://httpbin.org&lt;/code&gt;，其他服务的访问尝试会失败。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin-service
spec:
  hosts:
  - httpbin.org
  http:
  - match:
    - sourceLabels:
        app: sleep
        version: v2
    route:
    - destination:
        host: httpbin.org
  - route:
    - destination:
        host: httpbin.org
    fault:
      abort:
        percent: 100
        httpStatus: 403
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的定义中，我们首先让 &lt;code&gt;sleep:v2&lt;/code&gt; 的筛选条件的请求，转发给 &lt;code&gt;httpbin.org&lt;/code&gt;；而其余流量，则会被注入一个 403 错误。&lt;/p&gt;

&lt;p&gt;我们分别从 &lt;code&gt;sleep:v1&lt;/code&gt; 和 &lt;code&gt;sleep:v2&lt;/code&gt; 服务发起对 &lt;code&gt;httpbin.org&lt;/code&gt; 的访问：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ kubectl exec  $SLEEP_V2 -c sleep -- curl -s http://httpbin.org/ip
{
  &amp;quot;origin&amp;quot;: &amp;quot;168.63.251.242&amp;quot;
}
$ kubectl exec  $SLEEP_V1 -c sleep -- curl -s -v http://httpbin.org/ip
*   Trying 52.72.80.190...
...
&amp;lt; HTTP/1.1 403 Forbidden
&amp;lt; content-length: 18
&amp;lt; content-type: text/plain
&amp;lt; date: Wed, 22 Aug 2018 06:20:04 GMT
&amp;lt; server: envoy
&amp;lt;
{ [18 bytes data]
* Connection #0 to host httpbin.org left intact
fault filter abort%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，结果和我们的预测是一致的。&lt;/p&gt;

&lt;h2 id=&#34;to-be-continued&#34;&gt;To be continued&lt;/h2&gt;

&lt;p&gt;上面所述，只是针对 &lt;code&gt;ServiceEntry&lt;/code&gt; 的一些粗浅应用，Istio 还提供了 Egress Gateway 这样的高级组件。可以提供更多管理能力，敬请期待。&lt;/p&gt;

&lt;h2 id=&#34;相关链接&#34;&gt;相关链接&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;安装文档&lt;/strong&gt;：&lt;code&gt;https://istio.io/zh/docs/setup/kubernetes/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RBAC&lt;/strong&gt;：&lt;code&gt;https://istio.io/zh/docs/tasks/security/role-based-access-control/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基于 Mixer Adaptor 的访问控制&lt;/strong&gt;：&lt;code&gt;https://istio.io/zh/docs/tasks/policy-enforcement/denial-and-list/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;部分源码&#34;&gt;部分源码&lt;/h2&gt;

&lt;h3 id=&#34;sleep-yaml&#34;&gt;sleep.yaml&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
spec:
  selector:
    app: sleep
  ports:
    - name: ssh
      port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
        version: v1
    spec:
      containers:
      - name: sleep
        image: dustise/sleep:v0.5
        imagePullPolicy: IfNotPresent
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
        version: v2
    spec:
      containers:
      - name: sleep
        image: dustise/sleep:v0.5
        imagePullPolicy: IfNotPresent
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>istio.networking.v1alpha3 文档 review 邀请</title>
      <link>/post/traffic-routing-review/</link>
      <pubDate>Thu, 16 Aug 2018 02:09:57 +0800</pubDate>
      <guid>/post/traffic-routing-review/</guid>
      <description>&lt;p&gt;继 &lt;a href=&#34;https://istio.io/zh/docs/reference/commands/istioctl/&#34; target=&#34;_blank&#34;&gt;istioctl 参考文档中文版&lt;/a&gt;之后，&lt;a href=&#34;https://github.com/istio/istio.github.io/pull/2256&#34; target=&#34;_blank&#34;&gt;Istio istio.networking.v1alpha3 中文版 PR&lt;/a&gt; 也已经创建。这篇文档的&lt;a href=&#34;https://istio.io/docs/reference/config/istio.networking.v1alpha3/&#34; target=&#34;_blank&#34;&gt;原文&lt;/a&gt;是经由源码注释生成的，受格式所限，行文较为杂乱和冗长，所以在翻译过程中也做了不少修改。&lt;/p&gt;

&lt;p&gt;参考文档，尤其是这一篇所涉及的内容可以说是 Istio 的核心功能，为提高准确程度，特地拖延到其他部分文档均已完成之后才陆续开始翻译。即便如此，受个人能力有限，入手之后，依旧是深感脑枯词穷，轻易不敢 Merge。&lt;/p&gt;

&lt;p&gt;因此这里邀请 Service Mesh 爱好者、Istio 社区关注者一同参与进来，参与方式：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;可以直接在 &lt;a href=&#34;https://github.com/istio/istio.github.io/pull/2256&#34; target=&#34;_blank&#34;&gt;PR&lt;/a&gt; 上提出修改意见（建议）。&lt;/li&gt;
&lt;li&gt;在 ServiceMesher 网站上的 Istio 官方文档翻译工作组浏览&lt;a href=&#34;https://github.com/servicemesher/istio-official-translation/issues/298&#34; target=&#34;_blank&#34;&gt;相关 Issue&lt;/a&gt; 并留下宝贵建议。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下面是几个相关链接：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/istio.networking.v1alpha3/&#34; target=&#34;_blank&#34;&gt;英文版原文&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://deploy-preview-2256--preliminary-istio.netlify.com/zh/docs/reference/config/istio.networking.v1alpha3/&#34; target=&#34;_blank&#34;&gt;中文版预览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/istio/istio.github.io/blob/fb97c078dd0300274a59dada80abbc2b0ad686ad/content_zh/docs/reference/config/istio.networking.v1alpha3/index.md&#34; target=&#34;_blank&#34;&gt;中文版代码&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Istio 1.0 的实战测试</title>
      <link>/post/battle-testing-istio-1.0/</link>
      <pubDate>Tue, 14 Aug 2018 11:42:06 +0800</pubDate>
      <guid>/post/battle-testing-istio-1.0/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://medium.com/vescloud/battle-testing-istio-1-0-a0248ce68403&#34; target=&#34;_blank&#34;&gt;Battle Testing Istio 1.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;原作者：&lt;a href=&#34;https://medium.com/@pupapaik&#34; target=&#34;_blank&#34;&gt;Jakub Pavlík&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最近 Istio 成功发布了 1.0，并宣称生产就绪。我们的 SRE 团队对 Istio 1.0 生产状态进行了全面分析，最后提出了我们的建议。&lt;/p&gt;

&lt;p&gt;本文结构：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;安装和环境。&lt;/li&gt;
&lt;li&gt;要点和建议。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;安装和环境&#34;&gt;安装和环境&lt;/h2&gt;

&lt;p&gt;Istio 构建在&lt;a href=&#34;https://medium.com/microservices-in-practice/microservices-layered-architecture-88a7fc38d3f1&#34; target=&#34;_blank&#34;&gt;微服务架构&lt;/a&gt;基础之上，其中的应用网络由多个服务构成：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sidecar&lt;/strong&gt;：接收来自 Pilot 的配置信息，以代理服务器的身份处理入站和出站流量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pilot&lt;/strong&gt;：管理代理服务器，并和 Kubernetes 进行交互。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mixer&lt;/strong&gt;：接收来自代理服务器的指标，实施访问控制、配额管理等功能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Citadel&lt;/strong&gt;：为服务和用户提供认证和鉴权、管理凭据和 RBAC。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&#34;images/istio-arch.png&#34; alt=&#34;Istio Architecture&#34; /&gt;&lt;/p&gt;

&lt;p&gt;更多细节可移步浏览&lt;a href=&#34;https://istio.io/docs/zh/concepts/what-is-istio/overview/#architecture&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;安装过程比较方便。支持不同的环境（例如 Docker），但是 Kubernetes 是最适合我们需要的。&lt;/p&gt;

&lt;p&gt;安装方法支持列表：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;预渲染的 YAML&lt;/strong&gt;：这种方式适合预制环境（演示、评估以及 PoC 等）；这是因为其中的参数调整非常困难。YAML 文件可以进行模板化处理，但是其中有超过 3700 行代码，需要较大投入才能完成定制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Helm&lt;/strong&gt;：这种方式是参数化的，比较适合真实世界中的部署活动。正式的环境部署应该需要这样的定制能力。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;本文只是一次评估，因此使用了第一种方式。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;用静态 YAML 部署的 Istio 1.0&lt;/strong&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;NAME                              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/grafana                    1         1         1            1           20h
deploy/istio-citadel              1         1         1            1           20h
deploy/istio-egressgateway        1         1         1            1           20h
deploy/istio-galley               1         1         1            1           20h
deploy/istio-ingressgateway       1         1         1            1           20h
deploy/istio-pilot                1         1         1            1           20h
deploy/istio-policy               1         1         1            1           20h
deploy/istio-sidecar-injector     1         1         1            1           20h
deploy/istio-statsd-prom-bridge   1         1         1            1           20h
deploy/istio-telemetry            1         1         1            1           20h
deploy/istio-tracing              1         1         1            1           20h
deploy/prometheus                 1         1         1            1           20h
deploy/servicegraph               1         1         1            1           20h


NAME                       REFERENCE                         TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
hpa/istio-egressgateway    Deployment/istio-egressgateway    &amp;lt;unknown&amp;gt; / 55%   1         5         1          20h
hpa/istio-ingressgateway   Deployment/istio-ingressgateway   &amp;lt;unknown&amp;gt; / 55%   1         5         1          20h

NAME                                DESIRED   SUCCESSFUL   AGE
jobs/istio-cleanup-secrets          1         1            20h
jobs/istio-grafana-post-install     1         1            20h
jobs/istio-mixer-post-install-1.0   1         1            20h

NAME                                           READY     STATUS    RESTARTS   AGE
po/grafana-67b5df5b97-d685n                    1/1       Running   0          20h
po/istio-citadel-65df4cf668-xspff              1/1       Running   0          20h
po/istio-egressgateway-6678667b46-pmfmx        1/1       Running   0          20h
po/istio-galley-7c64c8c948-8npwp               1/1       Running   27         20h
po/istio-ingressgateway-6dfd7fc84-w6snd        1/1       Running   0          3h
po/istio-pilot-6cc9f4f7c6-552h4                2/2       Running   0          20h
po/istio-policy-5476f99674-sqn7h               2/2       Running   0          20h
po/istio-sidecar-injector-5f47598cd7-8qlq6     1/1       Running   0          20h
po/istio-statsd-prom-bridge-5d44ddb7cf-lrc8t   1/1       Running   0          20h
po/istio-telemetry-654bfd8487-bmdwv            2/2       Running   0          20h
po/istio-tracing-5fbd79cc-pnq5n                1/1       Running   0          20h
po/prometheus-7b6f8b9996-t4t92                 1/1       Running   0          20h
po/servicegraph-7d7ccc9b7f-b86c4               1/1       Running   0          20h

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                                                                     AGE
svc/grafana                    ClusterIP      10.0.18.159    &amp;lt;none&amp;gt;          3000/TCP                                                                    20h
svc/istio-citadel              ClusterIP      10.0.228.1     &amp;lt;none&amp;gt;          8060/TCP,9093/TCP                                                           20h
svc/istio-egressgateway        ClusterIP      10.0.217.249   &amp;lt;none&amp;gt;          80/TCP,443/TCP                                                              20h
svc/istio-galley               ClusterIP      10.0.131.153   &amp;lt;none&amp;gt;          443/TCP,9093/TCP                                                            20h
svc/istio-ingressgateway       LoadBalancer   10.0.72.147    13.66.222.246   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30223/TCP,8060:31415/TCP   20h
svc/istio-pilot                ClusterIP      10.0.67.90     &amp;lt;none&amp;gt;          15010/TCP,15011/TCP,8080/TCP,9093/TCP                                       20h
svc/istio-policy               ClusterIP      10.0.135.115   &amp;lt;none&amp;gt;          9091/TCP,15004/TCP,9093/TCP                                                 20h
svc/istio-sidecar-injector     ClusterIP      10.0.158.161   &amp;lt;none&amp;gt;          443/TCP                                                                     20h
svc/istio-statsd-prom-bridge   ClusterIP      10.0.17.41     &amp;lt;none&amp;gt;          9102/TCP,9125/UDP                                                           20h
svc/istio-telemetry            ClusterIP      10.0.139.187   &amp;lt;none&amp;gt;          9091/TCP,15004/TCP,9093/TCP,42422/TCP                                       20h
svc/jaeger-agent               ClusterIP      None           &amp;lt;none&amp;gt;          5775/UDP,6831/UDP,6832/UDP                                                  20h
svc/jaeger-collector           ClusterIP      10.0.172.142   &amp;lt;none&amp;gt;          14267/TCP,14268/TCP                                                         20h
svc/jaeger-query               ClusterIP      10.0.51.47     &amp;lt;none&amp;gt;          16686/TCP                                                                   20h
svc/prometheus                 ClusterIP      10.0.156.162   &amp;lt;none&amp;gt;          9090/TCP                                                                    20h
svc/servicegraph               ClusterIP      10.0.163.81    &amp;lt;none&amp;gt;          8088/TCP                                                                    20h
svc/tracing                    ClusterIP      10.0.111.218   &amp;lt;none&amp;gt;          80/TCP                                                                      20h
svc/zipkin ClusterIP 10.0.89.198 &amp;lt;none&amp;gt; 9411/TCP 20h
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;要点和建议&#34;&gt;要点和建议&lt;/h2&gt;

&lt;h3 id=&#34;操作复杂度&#34;&gt;操作复杂度&lt;/h3&gt;

&lt;p&gt;Istio 的功能集随着每次发布逐步增长，运维需求也自然是水涨船高。要运维 Istio，不仅要有对 Istio 组件和配置的基本理解，还需要对 Kubernetes 有深入的认识。Istio 1.0 中包含了 51 个 CRD，比 0.8 版本又多出了 8 个。&lt;/p&gt;

&lt;p&gt;正如 &lt;a href=&#34;https://twitter.com/sebgoa&#34; target=&#34;_blank&#34;&gt;Sebastein Goasguen&lt;/a&gt; 在 &lt;a href=&#34;https://medium.com/vescloud/battle-testing-istio-1-0-a0248ce68403&#34; target=&#34;_blank&#34;&gt;Twitter&lt;/a&gt; 中说的：如果你觉得 Kubernetes 很难，来看看（理解和维护）Istio 和他的 43 个 API 对象吧。&lt;/p&gt;

&lt;p&gt;运维的复杂性，在未来可以用 Galley 对服务和客户端的配置管理来进行简化。Galley 是 1.0 中新引入的组件，在 Istio 中，承担配置的导入、处理和分发任务。这一组件的主要目标是应对现有的配置方面的挑战，例如检测、组件之间的复用、配置错误和验证等问题。这样就可以提供更好的运维体验，同时降低对 Istio 各组件深入理解的需求。Galley 负责把其它 Istio 组件和从底层平台获取用户配置的细节中隔离开来。它其中包含了 Kubernetes 的 CRD 监听器，用来收集配置；还有一个网格配置协议（Mesh Config Protocol-MCP）服务器用于配置分发；以及一个用于验证的 Webhook，使用 &lt;a href=&#34;https://github.com/istio/istio/tree/master/galley&#34; target=&#34;_blank&#34;&gt;Kubernetes API Server&lt;/a&gt; 对配置进行前置检查。&lt;/p&gt;

&lt;p&gt;Galley 在 Istio 1.0 中可以禁用，并且在 AWS EKS 中必须和 Sidecar 的自动注入一起禁用，这是因为 EKS 不支持启用准入控制器，例如这里要用到的修改和验证 Webhook。加入 &lt;a href=&#34;https://groups.google.com/forum/#!forum/istio-dev&#34; target=&#34;_blank&#34;&gt;Google Group&lt;/a&gt; 阅读 &lt;a href=&#34;https://docs.google.com/document/d/1477BlHU0leWA4IKFRwnbNl5MZngf5m2K-JsBIo6dxJE/edit#&#34; target=&#34;_blank&#34;&gt;Galley 概要设计文档&lt;/a&gt; 可以获得更多信息。&lt;/p&gt;

&lt;h3 id=&#34;管理-ingress-gateway&#34;&gt;管理 Ingress Gateway&lt;/h3&gt;

&lt;p&gt;在 &lt;a href=&#34;https://istio.io/docs/reference/config/istio.networking.v1alpha3/&#34; target=&#34;_blank&#34;&gt;v1alpha3&lt;/a&gt; 中， Istio Gateway 和 VirtualService 一起，替换了 Kubernetes 的原生 Ingress。相对于 Kubernetes 的原生 Ingress，这一组合提供了更多高级配置。然而这些资源只是定义，真正的流量管理是由 Ingress Gateway 完成的。&lt;/p&gt;

&lt;p&gt;Ingress Gateway 是一个 Istio proxy（Envoy），它会根据 Gateway 和 VirtualService 定义响应网格外发来的入站流量。缺省的安装只包含一个 &lt;code&gt;ingressgateway&lt;/code&gt; pod 并且只使用 LoadBalancer 服务申请了一个公共 IP。要注意下面的限制：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;多个服务无法同时监听同一个外部端口，例如网格外只能开放一个 3306 端口。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VirtualService&lt;/code&gt; 的路径不可重叠。如果有多个独立团队使用 Istio 的话可能会出现问题。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这两个限制都可以通过部署多个 &lt;code&gt;ingressgateway&lt;/code&gt; pod 来监听多个公共 IP 的方式来解决。遗憾的是，对多个 &lt;code&gt;ingressgateway&lt;/code&gt; 实例的管理不太简单，需要自行定义合适的选择器。&lt;/p&gt;

&lt;h3 id=&#34;配置验证和同步&#34;&gt;配置验证和同步&lt;/h3&gt;

&lt;p&gt;可以使用标准的 &lt;code&gt;kubectl&lt;/code&gt; 命令配置 Istio，也可以选择使用原生的 &lt;code&gt;istioctl&lt;/code&gt; 工具。两种方法会得到同样的结果——在 Kubernetes 中创建 CRD。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：只有 &lt;code&gt;istioctl&lt;/code&gt; 会在把定义文件发送给 Kubernetes API Server 之前对 CRD 进行验证。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kubernetes 中部署的 Istio Webhook 会进行第二次验证，但是他只会对配置的结构进行验证，功能验证目前还没有实现。因为只做语义验证不做功能验证，上面提到的路径叠加问题会很容易遇到。&lt;/p&gt;

&lt;p&gt;Istio 1.0 在 &lt;code&gt;istioctl&lt;/code&gt; 命令中加入很多状态和健康状态方面的改进。&lt;code&gt;istioctl proxy-status&lt;/code&gt; 命令会获取 Pilot 和 Envoy 之间最新发送和接收的 xDS 同步信息，并提供一个状态概览：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;istioctl proxy-status
PROXY                                                 CDS        LDS        EDS               RDS          PILOT                            VERSION
details-v1-7bcdcc4fd6-9p7sr.default                   SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
istio-egressgateway-6678667b46-pmfmx.istio-system     SYNCED     SYNCED     SYNCED (100%)     NOT SENT     istio-pilot-6cc9f4f7c6-552h4     1.0.0
istio-ingressgateway-6dfd7fc84-w6snd.istio-system     SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
kad-5f89bf94fc-b48z2.kad                              SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
productpage-v1-8584c875d8-9mlbr.default               SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
ratings-v1-54cf9dc8f8-hthzx.default                   SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
reviews-v1-59cbdd7959-2ng8m.default                   SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
reviews-v2-dccb4cfc9-rp6rx.default                    SYNCED     SYNCED     SYNCED (100%)     SYNCED       istio-pilot-6cc9f4f7c6-552h4     1.0.0
reviews-v3-5465dc97bc-k9rdb.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;statefulset-和-headless-服务的支持&#34;&gt;StatefulSet 和 Headless 服务的支持&lt;/h3&gt;

&lt;p&gt;Headless 服务是没有 IP 的，服务中的各个实例通常会用点对点的形式进行访问，因此在服务网格中，这种服务是个难于应对的问题。要给这种服务配置 mTLS 认证，流量的检测和处理都可能遇到问题。&lt;/p&gt;

&lt;p&gt;Kubernetes StatefulSet 经常和 Headless 服务一同使用。在服务实例之间进行通信时，我们也发现了问题。我们用 StatefulSet 运行 Cassandra 集群，第二个实例出现了如下问题：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;INFO  13:44:05 Handshaking version with cassandra-0.cassandra.sre.svc.cluster.local/10.244.4.33

INFO  13:44:05 Cannot handshake version with cassandra-0.cassandra.sre.svc.cluster.local/10.244.4.33
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;要解决这个问题，要把 Cassandra 移出网格，或者修改 mTLS 认证策略。这一问题在目前正在跟踪之中。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://github.com/istio/istio/issues/5005&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://github.com/istio/istio/pull/6885&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://github.com/istio/istio/issues/1277&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;pod-检测&#34;&gt;Pod 检测&lt;/h3&gt;

&lt;p&gt;Kubernetes 会进行 Pod 检测，查看 Pod 的存活和就绪状态。检测方法有多种实现方式，TCP 和 HTTP 是最常见的。当 Kubelet 能够通过 HTTP 请求或者 TCP 连接访问到 Pod，就会判定 Pod 检测成功。当服务间的 mTLS 启用时，Kubelet 却并非网格的一部分，因此就无法访问 Pod 了。&lt;/p&gt;

&lt;p&gt;要解决这一问题：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;推荐方案是为服务检测准备单独的端口，并在这一端口上禁用认证功能。&lt;/li&gt;
&lt;li&gt;禁止 Pod 检测也是一个可选方案。&lt;/li&gt;
&lt;li&gt;在 Pod 内部使用 exec 检测，代替 Kubelet 完成这一任务。然而我们不推荐这种方式，这种检测不够全面，可能会有隐藏问题存在，例如 CNI。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;多集群鸿沟&#34;&gt;多集群鸿沟&lt;/h3&gt;

&lt;p&gt;Istio 从 0.8 开始支持单控制平面下的多集群部署。&lt;a href=&#34;https://medium.com/ibm-cloud/multi-cluster-support-for-service-mesh-with-ibm-cloud-private-d7d791f9b778&#34; target=&#34;_blank&#34;&gt;博客&lt;/a&gt;中提供了 0.8 中运行多集群 Istio 的详细介绍。Google 还在上一次 KubeCon 上做了一次演示（&lt;a href=&#34;https://youtu.be/bLJL53UIcqI?t=14m9s&#34; target=&#34;_blank&#34;&gt;视频&lt;/a&gt;）。1.0 版本中加入了为数众多的安全和性能方面的改进，其中包括远程集群的 Sidecar 自动注入能力。这方面可以参考&lt;a href=&#34;https://docs.google.com/document/d/1cOxPnTpnVWKR0m7a6PYJ-0NSTZ-e2J1IULnfojz7OZ4/edit#&#34; target=&#34;_blank&#34;&gt;详细设计文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;不幸的是这一功能在我们的生产环境上也是有问题的，现列举如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;集群间的 Pod 网络需要打通——这超出了 Istio 的能力范围，应该由 VPN 来完成这一任务。目前有提案使用 &lt;a href=&#34;https://docs.google.com/document/d/1QLMeycCoj6fbBKoOLiaDCc09Fbi89s5VoBW-eAxKwVs/edit#heading=h.qex63c29z2to&#34; target=&#34;_blank&#34;&gt;Zero VPN&lt;/a&gt; 来解决这一问题。&lt;/li&gt;
&lt;li&gt;远端集群需要能够解析 Pilot、Policy、Telemetry 以及 StatsD 端点——目前远程集群会使用控制面集群的 Pod IP，而 Pod IP 是可能因为 Pod 重启或者 Node 崩溃而发生变化的，这就需要重新部署 Istio。目前已经有 &lt;a href=&#34;https://github.com/istio/istio/pull/6210&#34; target=&#34;_blank&#34;&gt;PR&lt;/a&gt; 在尝试解决这个问题：部署额外的 Istio Ingress Gateway 来负责对 Istio Pilot、Policy 以及 Telemetry 端点的访问。&lt;/li&gt;
&lt;li&gt;Istio 的配置和状态是保存在“主”集群上的，一旦主集群发生了故障，就会出现跨集群的瓶颈。&lt;/li&gt;
&lt;li&gt;Github 上还跟踪了其它 &lt;a href=&#34;https://github.com/istio/istio/issues/4822&#34; target=&#34;_blank&#34;&gt;Issue&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;Istio 是第一个&lt;a href=&#34;https://preliminary.istio.io/about/notes/1.0/&#34; target=&#34;_blank&#34;&gt;生产就绪的版本&lt;/a&gt;，多数核心组件都已稳定，我们对其稳定性基本满意，运维方面还存在一些问题，在生产环境中的应用很有挑战性。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;因为新的操作可能会对既有工作负载造成影响，动态环境中的运维活动颇具危险性。&lt;/li&gt;
&lt;li&gt;必须监控的一些内容：配置变更，Sidecar 日志，Mixer 中的 Kubernetes 适配器。&lt;/li&gt;
&lt;li&gt;部分 Kubernetes 特性并未完整集成，例如 Pod 检测、Headless 服务。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;迄今为止，Istio 获得了巨大成就。如果是对系统缺乏深入理解的用户，要在生产环境中操作 Kubernetes 还是有一定难度的。我们认为，Istio 1.0 的完成度是合乎要求的，目前的用户多数都要归为超级用户的类别。短期之内，需要托管的 Istio 产品来满足消费市场的需要。还需要持续关注性能、伸缩以及策略处理方面的进展。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 大入门 - Ingress</title>
      <link>/post/istio-ingress-dive/</link>
      <pubDate>Sat, 11 Aug 2018 14:44:26 +0800</pubDate>
      <guid>/post/istio-ingress-dive/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;本文涉及细节较多，需读者对 Docker、Kubernetes 以及 Istio 有一定了解和实践经验，否则可能难于操作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Istio 从 v1alpha3 开始，用 Ingress Gateway 组件替代了符合 Kubernetes 规范的 Ingress Controller，因此对入站流量具有了更大的控制能力，但是用法也有了较大不同。&lt;/p&gt;

&lt;p&gt;安装：在使用 Helm 进行 Istio 部署的时候，需要使用下面的设置来启用 Ingress Gateway：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;gateways:
  enabled: true
  istio-ingressgateway:
    enabled: true
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;基本概念&#34;&gt;基本概念&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;VirtualService&lt;/code&gt; 是流量控制的核心组件，起着承上（&lt;code&gt;Gateway&lt;/code&gt;）启下（&lt;code&gt;DestinationRule&lt;/code&gt;）的作用。这三种对象在本文中涉及的主要职责：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gateway&lt;/code&gt; 对象：

&lt;ul&gt;
&lt;li&gt;选择 Gateway Ingress Controller。&lt;/li&gt;
&lt;li&gt;设置端点开放方式：域名、端口、入站协议等。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DestinationRule&lt;/code&gt;：

&lt;ul&gt;
&lt;li&gt;定义负载均衡行为。&lt;/li&gt;
&lt;li&gt;定义服务版本子集。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VirtualService&lt;/code&gt;：

&lt;ul&gt;
&lt;li&gt;根据 Gateway 选择服务版本。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;根据 &lt;a href=&#34;https://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService&#34; target=&#34;_blank&#34;&gt;VirtualService 对象文档&lt;/a&gt;中的说明，&lt;code&gt;VirtaulService&lt;/code&gt; 对象中的 &lt;code&gt;gateways&lt;/code&gt; 字段的类型为 &lt;code&gt;string[]&lt;/code&gt;，包括一或多个字符串值。如果省略该字段内容，会隐式的赋值为 &lt;code&gt;[&amp;quot;mesh&amp;quot;]&lt;/code&gt;，&lt;code&gt;mesh&lt;/code&gt; 网关指代所有的网格内通信。如果要对外提供服务，就需要定义 &lt;code&gt;Gateway&lt;/code&gt; 对象，并在 &lt;code&gt;gateways&lt;/code&gt; 字段中进行赋值。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意，一旦在 &lt;code&gt;gateways&lt;/code&gt; 中填写了非缺省的对象名称，要继续对内部通信进行流量控制，必须显式的将内置的 &lt;code&gt;mesh&lt;/code&gt; 对象名称也加入到列表之中。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;

&lt;h3 id=&#34;环境准备&#34;&gt;环境准备&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;安装和部署 Kubernetes 以及 Istio，并启用 Ingress Gateway 支持。&lt;/li&gt;
&lt;li&gt;将备用的两个域名（假设为 &lt;code&gt;flask.example2.com&lt;/code&gt; 以及 &lt;code&gt;flask.example1.com&lt;/code&gt;）指向 &lt;code&gt;istio-ingressgateway&lt;/code&gt; 服务的外部 IP。&lt;/li&gt;
&lt;li&gt;为测试域名生成 HTTPS 证书。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;域名准备&#34;&gt;域名准备&lt;/h3&gt;

&lt;h3 id=&#34;工作负载&#34;&gt;工作负载&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;首先编写一个基于 Flask 的 Python 脚本，并打入镜像，脚本功能很简单，显示环境变量中的 &amp;ldquo;VERSION&amp;rdquo;。&lt;/li&gt;
&lt;li&gt;接下来编写 Dockerfile，安装 Python3、Flask，并进行构建和推送。&lt;/li&gt;
&lt;li&gt;编写 Kubernetes 工作负载文件，常见的 Deployment + Service 模式。&lt;/li&gt;
&lt;li&gt;在 Kubernetes 上运行工作负载。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上涉及代码可以在页面尾部获取。&lt;/p&gt;

&lt;h3 id=&#34;目标规则定义&#34;&gt;目标规则定义&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: flask
spec:
  host: flask
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里根据工作负载中的标签，将 &lt;code&gt;flask&lt;/code&gt; 服务拆分为 &lt;code&gt;v1&lt;/code&gt; 和 &lt;code&gt;v2&lt;/code&gt; 两个版本。&lt;/p&gt;

&lt;h2 id=&#34;在外网开放服务&#34;&gt;在外网开放服务&lt;/h2&gt;

&lt;p&gt;这里我们设计，将所有外网请求经过 &lt;code&gt;flask.example1.com&lt;/code&gt; 路由到 &lt;code&gt;v2&lt;/code&gt; 版本上。&lt;/p&gt;

&lt;p&gt;首先要编写一个 &lt;code&gt;Gateway&lt;/code&gt; 定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: flask-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - flask.example1.com
        - flask.example2.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里定义了一个 &lt;code&gt;Gateway&lt;/code&gt;，其中要求 80 端口响应两个域名的请求。接下来定义一个 &lt;code&gt;VirtualService&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
    name: flask
spec:
    hosts:
    - &amp;quot;flask.example1.com&amp;quot;
    gateways:
    - flask-gateway
    http:
    - route:
        - destination:
            host: flask
            subset: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后使用 curl 进行访问：&lt;code&gt;curl http://flask.example1.com&lt;/code&gt; 会发现返回了字符串 &amp;ldquo;v2&amp;rdquo;，证明我们的定义生效了，该域名指向了 &lt;code&gt;v2&lt;/code&gt; 服务。&lt;/p&gt;

&lt;p&gt;再用 curl 访问第二个域名 &lt;code&gt;curl http://flask.example2.com&lt;/code&gt;，会看到返回了 404，这是因为我们的 &lt;code&gt;Gateway&lt;/code&gt; 虽然接收了请求，但是并没有服务路由完成这一请求。那么可以再定义一个 &lt;code&gt;VirtualService&lt;/code&gt;，让 &lt;code&gt;flask.example2.com&lt;/code&gt; 域名指向 &lt;code&gt;v1&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
    name: flask1
spec:
    hosts:
    - &amp;quot;flask.example2.com&amp;quot;
    gateways:
    - flask-gateway
    http:
    - route:
        - destination:
            host: flask
            subset: v1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次使用 &lt;code&gt;curl http://flask.example2.com&lt;/code&gt;，访问，会看到返回结果变成了 &lt;code&gt;v1&lt;/code&gt;，证明我们的服务定义生效了。&lt;/p&gt;

&lt;h2 id=&#34;将一个域名服务升级为-tls&#34;&gt;将一个域名服务升级为 tls&lt;/h2&gt;

&lt;p&gt;随意修改一个需求，要求开放 &lt;code&gt;flask.example2.com&lt;/code&gt; 为 http，而 &lt;code&gt;flask.example1.com&lt;/code&gt; 升级为 https，既然涉及 https，就要用到证书，&lt;a href=&#34;https://istio.io/zh/docs/tasks/traffic-management/secure-ingress/&#34; target=&#34;_blank&#34;&gt;官方文档（中文版哦）&lt;/a&gt;陈述如下：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;具体说来就是使用 kubectl 命令在命名空间 istio-system 中创建一个 secret 对象，命名为 istio-ingressgateway-certs。Istio 网关会自动载入这个 secret。
这里的 secret 必须 在 istio-system 命名空间中，并且命名为 istio-ingressgateway-certs，否则就不会被正确载入，也就无法 Istio gateway 中使用了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;接着是使用命令为 &lt;code&gt;flask.example1.com&lt;/code&gt; 的证书创建 &lt;code&gt;Secret&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl create -n istio-system secret tls \
    istio-ingressgateway-certs \
    --key key.pem --cert cert.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最后修改我们的 &lt;code&gt;Gateway&lt;/code&gt; 定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: flask-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - flask.example2.com
    - port:
        number: 443
        name: https-rocks
        protocol: HTTPS
      tls:
        mode: SIMPLE
        serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
        privateKey: /etc/istio/ingressgateway-certs/tls.key
      hosts:
        - flask.example1.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后再次使用 curl 分别访问 &lt;code&gt;https://flask.example1.com/version&lt;/code&gt; 以及 &lt;code&gt;http://flask.example2.com/version&lt;/code&gt;，会发现返回了预期结果，而一旦错用 &lt;code&gt;http&lt;/code&gt; 和 &lt;code&gt;https&lt;/code&gt;，就会出现异常，这是因为我们的 &lt;code&gt;Gateway&lt;/code&gt; 限制了端口。&lt;/p&gt;

&lt;p&gt;这里如此操作的原因可以在他的部署中找到：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get deployment istio-ingressgateway \
    -o yaml -n istio-system
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;返回的 YAML 中会有这么一段&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;...
- mountPath: /etc/istio/ingressgateway-ca-certs
    name: ingressgateway-ca-certs
    readOnly: true
...
volumes:
- name: ingressgateway-certs
secret:
    defaultMode: 420
    optional: true
    secretName: istio-ingressgateway-certs
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上方代码可以看到，Ingress Gateway 中用可选方式加载了一个名称为 &lt;code&gt;istio-ingressgateway-certs&lt;/code&gt; 的 &lt;code&gt;Secret&lt;/code&gt;，并 Mount 到了 &lt;code&gt;/etc/istio/ingressgateway-ca-certs&lt;/code&gt; 目录之中，这就是上文中要求我们固定 Secret 名称和命名空间的原因。众所周知，&lt;code&gt;tls&lt;/code&gt; 类型的 &lt;code&gt;Secret&lt;/code&gt; 加载后会成为 &lt;code&gt;tls.key&lt;/code&gt; 和 &lt;code&gt;tls.crt&lt;/code&gt; 两个文件，因此在我们的 &lt;code&gt;Gateway&lt;/code&gt; 定义中就使用了 &lt;code&gt;/etc/istio/ingressgateway-certs/tls.crt&lt;/code&gt; 这样的文件名。&lt;/p&gt;

&lt;h2 id=&#34;所有域名都升级为-tls&#34;&gt;所有域名都升级为 tls&lt;/h2&gt;

&lt;p&gt;根据上一节的描写，不难发现按照官方文档，一个 &lt;code&gt;Gateway&lt;/code&gt; 是无法处理两个域名的 https 的：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;tls secret 只能包含一个证书对。&lt;/li&gt;
&lt;li&gt;泛域名证书可以完成这一任务，但因为 Envoy 的限制，这里无法同时使用两个泛域名。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;讨论到这里就很明显了，关键在于如何加载多个证书对，可以修改前面所说的加载指令为加载多个 &lt;code&gt;Secret&lt;/code&gt;，或者干脆换成 &lt;code&gt;Configmap&lt;/code&gt;，当然这样会引起服务中断，&lt;code&gt;Configmap&lt;/code&gt; 用于存放证书也略显粗糙——好在我们还可以换用 &lt;code&gt;Generic&lt;/code&gt; 类型的证书，这里我们可以删除原有 Secret 重新创建 ：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;kubectl delete secret istio-ingressgateway-certs \
    -n istio-system

kubectl create secret generic  \
    istio-ingressgateway-certs \
    -n istio-system \
    --from-file=rocks-crt.pem \
    --from-file=rocks-key.pem \
    --from-file=xyz-crt.pem \
    --from-file=xyz-key.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来改造我们的 &lt;code&gt;Gateway&lt;/code&gt; 定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: flask-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https-rocks
      protocol: HTTPS
    tls:
      mode: SIMPLE
      serverCertificate: /etc/istio/ingressgateway-certs/rocks-crt.pem
      privateKey: /etc/istio/ingressgateway-certs/rocks-key.pem
    hosts:
    - &amp;quot;flask.example1.com&amp;quot;
  - port:
      number: 443
      name: https-xyz
      protocol: HTTPS
    tls:
      mode: SIMPLE
      serverCertificate: /etc/istio/ingressgateway-certs/xyz-crt.pem
      privateKey: /etc/istio/ingressgateway-certs/xyz-key.pem
    hosts:
    - &amp;quot;flask.example2.com&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样一来，我们开放了两个 HTTPS 端口，各自使用不同的证书，分别都可以通过 &lt;code&gt;curl&lt;/code&gt; 命令获得正确结果了。&lt;/p&gt;

&lt;h2 id=&#34;补充&#34;&gt;补充&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tls.mode&lt;/code&gt; 实际还支持双向和透传两种方式，都可以在流量控制参考中找到相关内容。&lt;/p&gt;

&lt;h2 id=&#34;涉及链接&#34;&gt;涉及链接&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Istio 流量控制参考：&lt;code&gt;https://istio.io/docs/reference/config/istio.networking.v1alpha3/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用 HTTPS 加密 Gateway：&lt;code&gt;https://istio.io/zh/docs/tasks/traffic-management/secure-ingress/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;代码&#34;&gt;代码&lt;/h2&gt;

&lt;h3 id=&#34;python-脚本&#34;&gt;Python 脚本&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from flask import Flask
import os

app = Flask(__name__)

@app.route(&amp;quot;/&amp;quot;)
def hello_world():
    return &amp;quot;Hello, World!&amp;quot;

@app.route(&amp;quot;/version&amp;quot;)
def getversion():
    return os.getenv(&amp;quot;VERSION&amp;quot;)
if __name__ == &amp;quot;__main__&amp;quot;:
    app.run(host=&amp;quot;0.0.0.0&amp;quot;, port=80, debug=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;dockerfile&#34;&gt;Dockerfile&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-dockerfile&#34;&gt;FROM alpine
RUN  apk add --update --no-cache python3 &amp;amp;&amp;amp; \
  mkdir /web &amp;amp;&amp;amp; \
  pip3 install Flask
COPY server.py /web
CMD &amp;quot;/web/server.py&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;kubernetes-工作负载&#34;&gt;Kubernetes 工作负载&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: flask
  labels:
    app: flask
spec:
  ports:
    - name: http
      port: 80
  selector:
    app: flask
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flask-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flask
        version: v1
    spec:
      containers:
        - image: &#39;abc:25000/python-flask-server:v2&#39;
          imagePullPolicy: IfNotPresent
          name: flask
          env:
            - name: VERSION
              value: v1
          ports:
            - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flask-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flask
        version: v2
    spec:
      containers:
        - image: &#39;abc:25000/python-flask-server:v2&#39;
          imagePullPolicy: IfNotPresent
          name: flask
          env:
            - name: VERSION
              value: v2
          ports:
            - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Consul vs Istio</title>
      <link>/post/consul-vs-istio/</link>
      <pubDate>Wed, 11 Jul 2018 19:40:12 +0800</pubDate>
      <guid>/post/consul-vs-istio/</guid>
      <description>&lt;p&gt;原文：&lt;a href=&#34;https://www.consul.io/intro/vs/istio.html&#34; target=&#34;_blank&#34;&gt;Consul vs Istio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Istio 是一个开源平台，可以为微服务提供连接、管理和加密功能。&lt;/p&gt;

&lt;p&gt;要启用 Istio 的全部功能，必须部署多个服务。控制面包括了 Pilot、Mixer 以及 Citadel 这几个必要组件，数据面的 Envoy Sidecar 也是必不可少的。另外 Istio 需要第三方的服务发现支持，例如 Kubernetes、Consul、Eureka 或者其他别的什么。最后 Istio 需要一个外部系统用来进行存储，通常是 ETCD。换句话说，Istio 需要至少三个独立的服务，以及至少一个分布式系统才算完整。&lt;/p&gt;

&lt;p&gt;Istio 在七层提供了基于路径的路由、流量整形、负载均衡以及遥测功能。Istio 还基于服务认证功能提供了访问控制的支持，能使用七层和四层的属性对访问、路由进行控制。&lt;/p&gt;

&lt;p&gt;Consul 是一个单一的二进制文件，同时提供了服务器和客户端的能力，并自带全部的服务发现、配置、TLS、认证等功能。无需安装额外的系统即可使用，同时还为 Vault 之类的外部系统提供了可选支持，从而进行功能扩展。这一架构让 Consul 能够轻松的安装在任何平台上，也包括物理机。&lt;/p&gt;

&lt;p&gt;Consule 是一个基于 Agent 的模型，集群中的每个节点都需要运行一个 Consul 客户端。客户端软件管理一个本地缓存，缓存的数据来源于服务器。无需任何外部通信，所有的加密服务通信 API 都能在几毫秒的时间内进行响应。这样我们的连接过程发生在边缘，无需和中央服务器进行通信。Istio 将请求流入位于中央的 Mixer 服务，而数据的推送过程又必须由 Pilot 完成。这种机制极大的降低了 Istio 的稳定性，而 Consul 却能够在边缘高效的完成数据更新的分发以及其他工作。&lt;/p&gt;

&lt;p&gt;Consul 的数据面是可插接的。它包含了一个内置的代理服务器，这一服务牺牲了较多性能，换来易用性的提升。用户也可以使用 Envoy 这样的第三方代理。不同的任务会有各自合适的代理，Consul 就提供了这种能力，从而能够支持复杂多样的应用部署。&lt;/p&gt;

&lt;p&gt;除了第三方代理支持，应用可以直接和 Connect 协议进行集成。这样一来，引入 Connect 的开销就可以忽略不计了。任何其他的 Connect 支持的应用，不管使用代理或者 Connect 原生方式，都具备互联互通的能力。&lt;/p&gt;

&lt;p&gt;Consul 只在四层实现了认证和鉴权——TLS 连接是否能够建立。我们认为服务认证应该留在四层，七层要做的事情是路由、遥测等事情。我们鼓励用户借助我们的可插接数据面，为集群所需要的七层功能选择合适的代理服务器。Consul 会在未来加入更多七层特性。&lt;/p&gt;

&lt;p&gt;Consul 实现了自动的 TLS 认证管理，并且提供了完整的轮转支持。即使是一个大型的 Consul 集群中，也能够在无中断的情况下实现自动轮转。认证管理系统也是可插接的，目前通过代码集成在 Consul 中，很快我们会将其剥离成为外部插件。这就 Consul 就有了和任意 PKI 方案协同工作的能力。&lt;/p&gt;

&lt;p&gt;因为 Consul 的服务连接能力（”Connect“）是内置的，他也具备和 Consul 一样的稳定性。2014 年以来，Consule 就在大型企业的生产环境中工作，目前已经有单集群部署 50000 节点的规模。&lt;/p&gt;

&lt;p&gt;这一比较基于我们自己对 Istio 的有限认识，以及和 Istio 用户的交流。如果读者认为其中有不实之处，请点击 &lt;a href=&#34;https://github.com/hashicorp/consul/blob/master/website/source/intro/vs/istio.html.md&#34; target=&#34;_blank&#34;&gt;Edit this page&lt;/a&gt; 提交修改建议。我们会尽快对读者意见进行审核和更新，希望以此来保证本文的准确性。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>HTTP Egress 流量的监控和访问策略管理</title>
      <link>/post/egress-monitoring-access-control/</link>
      <pubDate>Sat, 23 Jun 2018 10:48:57 +0800</pubDate>
      <guid>/post/egress-monitoring-access-control/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://istio.io/blog/2018/egress-monitoring-access-control/&#34; target=&#34;_blank&#34;&gt;Monitoring and Access Policies for HTTP Egress Traffic&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：VADIM EISENBERG 和 RONEN SCHAFFER&lt;/p&gt;

&lt;p&gt;Istio 的主要功能就是在服务网格内部管理微服务之间的通信，除此之外，Istio 还能对 Ingress（从外部进入网格） 和 Egress（从网格发出到外部） 流量进行管理。不管是网格内部流量，还是 Ingress 或者 Egress 流量，Istio 都能够在其中进行访问策略的控制，并完成遥测数据的聚合工作。&lt;/p&gt;

&lt;p&gt;本文中我们会展示如何使用 Istio 在 HTTP Egress 流量中实施监控和访问策略控制。文中谈到的内容针对 &lt;a href=&#34;https://github.com/istio/istio/releases/tag/0.8.0&#34; target=&#34;_blank&#34;&gt;Istio 0.8.0&lt;/a&gt; 及以上是有效的。&lt;/p&gt;

&lt;h1 id=&#34;用例&#34;&gt;用例&lt;/h1&gt;

&lt;p&gt;假设一个组织正在运行的应用需要处理来自于 &lt;code&gt;cnn.com&lt;/code&gt; 的内容。这些应用已经被解构为部署在 Istio 服务网格中的微服务。这些应用要获取 &lt;code&gt;cnn.com&lt;/code&gt; 多个频道的内容：&lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt;、&lt;a href=&#34;https://edition.cnn.com/sport&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/sport&lt;/a&gt; 以及 &lt;a href=&#34;https://edition.cnn.com/health&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/health&lt;/a&gt;。目前已经&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-tls-origination/&#34; target=&#34;_blank&#34;&gt;配置 Istio 使其允许访问 &lt;code&gt;edition.cnn.com&lt;/code&gt;&lt;/a&gt;，一切运行良好。然而在某一天，他们决定限制政治方面的内容，技术上讲，就是要阻止对 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问，继续允许对 &lt;a href=&#34;https://edition.cnn.com/sport&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/sport&lt;/a&gt; 以及 &lt;a href=&#34;https://edition.cnn.com/health&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/health&lt;/a&gt; 的访问。对 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问需要在应用程序、命名空间以及用户的不同粒度上进行访问控制。&lt;/p&gt;

&lt;p&gt;要实现这个目标，运维人员需要监控对外部服务的访问，并分析 Istio 日志来确保对 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问都是经过授权的。另外他们还要配置 Istio，让 Istio 自动阻止对 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的（未授权）访问。&lt;/p&gt;

&lt;p&gt;该组织决定防止对新策略发生篡改，通过技术手段执行策略，防止恶意应用访问受限内容。&lt;/p&gt;

&lt;h2 id=&#34;相关任务&#34;&gt;相关任务&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress/&#34; target=&#34;_blank&#34;&gt;Egress 流量控制&lt;/a&gt;：网格内应用对（Kubernetes 集群）外部的 HTTP 和 HTTPS 服务的访问方式。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-tls-origination/&#34; target=&#34;_blank&#34;&gt;TLS 方式访问 Egress 流量&lt;/a&gt;：内部应用使用 HTTP 协议访问需要 HTTPS 的外部服务的能力。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/&#34; target=&#34;_blank&#34;&gt;配置 Egress Gateway&lt;/a&gt; ：如何配置 Istio 令其使用独立的 &lt;code&gt;egress gateway&lt;/code&gt; 网关服务来发送 Egress 流量。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/metrics-logs/&#34; target=&#34;_blank&#34;&gt;收集指标和日志&lt;/a&gt;：为网格中的服务配置指标和日志。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/using-istio-dashboard/&#34; target=&#34;_blank&#34;&gt;使用 Grafana 进行指标可视化&lt;/a&gt;：Istio Dashboard 在网格流量监控方面的作用。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/security/basic-access-control/&#34; target=&#34;_blank&#34;&gt;基础访问控制&lt;/a&gt;：网格内服务的访问控制问题。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istio.io/docs/tasks/security/secure-access-control/&#34; target=&#34;_blank&#34;&gt;安全访问控制&lt;/a&gt;：如何使用黑名单和白名单配置访问策略。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;和上面列出的任务不同，本文讲述的是 Istio 对 Egress 流量的监控和访问策略。&lt;/p&gt;

&lt;h2 id=&#34;开始之前&#34;&gt;开始之前&lt;/h2&gt;

&lt;p&gt;依照 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/#perform-tls-origination-with-the-egress-gateway&#34; target=&#34;_blank&#34;&gt;配置 Egress Gateway，使用 Egress Gateway 执行 TLS 访问&lt;/a&gt; 任务中的步骤，不要执行&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/#cleanup&#34; target=&#34;_blank&#34;&gt;清理&lt;/a&gt;操作。完成之后，就可在网格之内使用安装了 &lt;code&gt;curl&lt;/code&gt; 的容器来访问  &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 了。下面的内容中，我们假设名为 &lt;code&gt;SOURCE_POD&lt;/code&gt; 的环境变量中包含了 Pod 名称。&lt;/p&gt;

&lt;h2 id=&#34;配置监控和访问策略&#34;&gt;配置监控和访问策略&lt;/h2&gt;

&lt;p&gt;既然要用安全方式来完成任务，就需要通过 &lt;code&gt;egress gateway&lt;/code&gt; 来进行 egress 传输，这部分内容在 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/&#34; target=&#34;_blank&#34;&gt;配置 Egress Gateway&lt;/a&gt; 中有详细描述。这里所谓的安全方式指的是防止恶意应用绕过 Istio 监控和策略管理进行未经授权的访问。&lt;/p&gt;

&lt;p&gt;我们的场景中，该组织执行了上一节“开始之前”的步骤。这个步骤完成后，开放了对 &lt;code&gt;edition.cnn.com&lt;/code&gt; 的访问，并且配置了响应的 Egress Gateway。现在可以对 &lt;code&gt;edition.cnn.com&lt;/code&gt; 进行监控和策略进行配置了。&lt;/p&gt;

&lt;h3 id=&#34;日志&#34;&gt;日志&lt;/h3&gt;

&lt;p&gt;首先配置一下对 &lt;code&gt;*.cnn.com&lt;/code&gt; 的记录。创建一个 &lt;code&gt;logentry&lt;/code&gt; 和两个 &lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/stdio/&#34; target=&#34;_blank&#34;&gt;stdio&lt;/a&gt; 类型的 &lt;code&gt;handler&lt;/code&gt;，其中一个用 &lt;code&gt;error&lt;/code&gt; 级别的日志来记录受限的访问，另外一个用 &lt;code&gt;info&lt;/code&gt; 级别来记录所有到 &lt;code&gt;*.cnn.com&lt;/code&gt; 的访问。接下来创建 &lt;code&gt;rules&lt;/code&gt; 把 &lt;code&gt;logentry&lt;/code&gt; 定向到 &lt;code&gt;handler&lt;/code&gt; 上。对 &lt;code&gt;*.cnn.com/politics&lt;/code&gt; 的访问会被指派给受限访问的规则，剩余的访问则会被另一条规则接收。要理解 Istio 的 &lt;code&gt;logentries&lt;/code&gt;、&lt;code&gt;rules&lt;/code&gt; 以及 &lt;code&gt;handlers&lt;/code&gt;，可以阅读 &lt;a href=&#34;https://istio.io/blog/2017/adapter-model/&#34; target=&#34;_blank&#34;&gt;Istio Adaper Model&lt;/a&gt; 一文。下面的示意图中包含了刚才讲到的这些实体和依赖关系：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/egress-adapters-monitoring-policy.svg&#34; alt=&#34;用于监控 Egress 的 Instance、Rules 以及 Handlers&#34; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;创建 &lt;code&gt;logentries&lt;/code&gt;、&lt;code&gt;rules&lt;/code&gt; 以及 &lt;code&gt;handlers&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# egress 访问的日志条目
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: logentry
metadata:
name: egress-access
namespace: istio-system
spec:
severity: &#39;&amp;quot;info&amp;quot;&#39;
timestamp: request.time
variables:
destination: request.host | &amp;quot;unknown&amp;quot;
path: request.path | &amp;quot;unknown&amp;quot;
source: source.labels[&amp;quot;app&amp;quot;] | source.service | &amp;quot;unknown&amp;quot;
sourceNamespace: source.namespace | &amp;quot;unknown&amp;quot;
user: source.user | &amp;quot;unknown&amp;quot;
responseCode: response.code | 0
responseSize: response.size | 0
monitored_resource_type: &#39;&amp;quot;UNSPECIFIED&amp;quot;&#39;
---
# Handler for error egress access entries
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: stdio
metadata:
name: egress-error-logger
namespace: istio-system
spec:
severity_levels:
info: 2 # 输出级别为 error
outputAsJson: true
---
# 访问 *.cnn.com/politics 的规则
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
name: handle-politics
namespace: istio-system
spec:
match: request.host.endsWith(&amp;quot;cnn.com&amp;quot;) &amp;amp;&amp;amp; request.path.startsWith(&amp;quot;/politics&amp;quot;)
actions:
- handler: egress-error-logger.stdio
instances:
- egress-access.logentry
---
# Info 级别的 Egress 日志
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: stdio
metadata:
name: egress-access-logger
namespace: istio-system
spec:
severity_levels:
info: 0 # 输出为 Info 级别
outputAsJson: true
---
# 访问 *.cnn.com 的规则
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
name: handle-cnn-access
namespace: istio-system
spec:
match: request.host.endsWith(&amp;quot;.cnn.com&amp;quot;)
actions:
- handler: egress-access-logger.stdio
instances:
- egress-access.logentry
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;分别向 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt;、&lt;a href=&#34;https://edition.cnn.com/sport&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/sport&lt;/a&gt; 发送请求，所有请求都应该返回 &lt;code&gt;200 OK&lt;/code&gt;。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
200
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;查询 Mixer 的日志，查看日志中出现的请求信息：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath=&#39;{.items[0].metadata.name}&#39;) mixer | grep egress-access | grep cnn | tail -4
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;返回如下信息：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-18T13:22:58.317448Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:150448,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;error&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-18T13:22:58.317448Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:150448,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;error&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-18T13:22:58.317448Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:150448,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-18T13:22:59.354943Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/health&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:332218,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会看到关于三个请求的四条日志。三个 &lt;code&gt;info&lt;/code&gt; 级别的条目是关于 &lt;code&gt;edition.cnn.com&lt;/code&gt; 的，一条 &lt;code&gt;error&lt;/code&gt; 级别的条目就是关于 &lt;code&gt;edition.cnn.com/politics&lt;/code&gt; 的访问。服务网格的运维人员能看到所有的访问情况，并且也能通过对 &lt;code&gt;error&lt;/code&gt; 日志的搜索来查找受限访问。这是在禁止访问之前的第一个监控措施，把所有受限访问都作为错误记录下来，在某些情况下，这就足够安全了。&lt;/p&gt;

&lt;h3 id=&#34;利用路由进行访问控制&#34;&gt;利用路由进行访问控制&lt;/h3&gt;

&lt;p&gt;在启动对 &lt;code&gt;edition.cnn.com&lt;/code&gt; 的访问日志之后，自动启动了一个访问策略，只允许访问 &lt;code&gt;/health&lt;/code&gt; 和 &lt;code&gt;/sport&lt;/code&gt; URL。这样简单的策略控制可以用 Istio 路由来实现。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;重新定义 &lt;code&gt;edition.cnn.com&lt;/code&gt; 的 &lt;code&gt;VirtualService&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-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
    port:
      number: 443
  weight: 100
- match:
- gateways:
  - istio-egressgateway
  port: 443
  uri:
    regex: &amp;quot;^.health|^.sport&amp;quot;
route:
- destination:
    host: edition.cnn.com
    port:
      number: 443
  weight: 100
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注意这里加入了一个针对 &lt;code&gt;uri&lt;/code&gt; 的 &lt;code&gt;match&lt;/code&gt; 条件，会检查 URL 路径是不是 &lt;code&gt;/health&lt;/code&gt; 或者 &lt;code&gt;/sport&lt;/code&gt;。另外还要注意的是，这个条件是加入到 &lt;code&gt;VirtualService&lt;/code&gt; 的 &lt;code&gt;istio-egressgateway&lt;/code&gt; 部分，egress gateway 是一个需要注意安全的组件（参见 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/#additional-security-considerations&#34; target=&#34;_blank&#34;&gt;Egress Gateway 的安全考量&lt;/a&gt;），应该慎重对待其安全性，防止影响后续的策略实施过程。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;再次发送之前的三个 HTTP 请求：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
404
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;会看到 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 返回了 &lt;code&gt;404 Not Found&lt;/code&gt;，&lt;a href=&#34;https://edition.cnn.com/sport&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/sport&lt;/a&gt; 和 &lt;a href=&#34;https://edition.cnn.com/health&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/health&lt;/a&gt; 都返回了 200。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;VirtualService&lt;/code&gt; 的传播和生效可能需要几秒钟的等待。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;查询 Mixer 日志，看看刚才发生的请求在日志中的体现：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath=&#39;{.items[0].metadata.name}&#39;) mixer | grep egress-access | grep cnn | tail -4
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;得到结果如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T12:39:48.050666Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:404,&amp;quot;responseSize&amp;quot;:0,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;error&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T12:39:48.050666Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:404,&amp;quot;responseSize&amp;quot;:0,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T12:39:48.091268Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/health&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:334027,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T12:39:48.063812Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/sport&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:355267,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里还能看到 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问日志，只不过这次的 &lt;code&gt;responseCode&lt;/code&gt; 是 &lt;code&gt;404&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;使用 Istio 路由之后，我们成功的实现了初步的访问控制，但是如果是更复杂的需要，这种程度还是不够的。例如希望允许特定条件下对 &lt;a href=&#34;https://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问，这需要一些更复杂的策略，只判断 URL 是不够的。这就需要 &lt;a href=&#34;https://istio.io/blog/2017/adapter-model/&#34; target=&#34;_blank&#34;&gt;Istio Mixer Adapter&lt;/a&gt;，（例如&lt;a href=&#34;https://istio.io/docs/tasks/security/basic-access-control/#access-control-using-whitelists&#34; target=&#34;_blank&#34;&gt;白名单&lt;/a&gt;和&lt;a href=&#34;https://istio.io/docs/tasks/security/basic-access-control/#access-control-using-denials&#34; target=&#34;_blank&#34;&gt;黑名单&lt;/a&gt;）的协助，来协助控制对 URL 路径的允许和禁止行为。借 [Policy Rules] 的帮助，这样就可以使用 &lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/expression-language/&#34; target=&#34;_blank&#34;&gt;Istio expression language&lt;/a&gt; 来实现复杂条件的定义，完成包含逻辑控制在内的复杂限制了。这些规则可以在日志和策略检查之间进行复用。另外还可以使用 &lt;a href=&#34;https://istio.io/docs/concepts/security/rbac/&#34; target=&#34;_blank&#34;&gt;Istio RBAC&lt;/a&gt;进行更复杂的控制。&lt;/p&gt;

&lt;p&gt;还有一个额外的需要就是和远程访问策略系统进行集成。如果用例中设计的组织已经有使用一些 &lt;a href=&#34;https://en.wikipedia.org/wiki/Identity_management&#34; target=&#34;_blank&#34;&gt;认证和访问管理系统&lt;/a&gt;，可能会需要配置 Istio 从这些系统中获取访问策略方面的信息。可以通过实现 &lt;a href=&#34;https://istio.io/blog/2017/adapter-model/&#34; target=&#34;_blank&#34;&gt;Istio Mixer Adapter&lt;/a&gt; 的方式来进行集成。&lt;/p&gt;

&lt;p&gt;取消掉前面我们使用路由规则实现的访问控制，接下来使用 Mixer 策略来实现。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;用之前的 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/#perform-tls-origination-with-the-egress-gateway&#34; target=&#34;_blank&#34;&gt;Configure an Egress Gateway&lt;/a&gt; 中的版本替换 &lt;code&gt;edition.cnn.com&lt;/code&gt; 的 &lt;code&gt;VertualService&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-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
    port:
      number: 443
  weight: 100
- match:
- gateways:
  - istio-egressgateway
  port: 443
route:
- destination:
    host: edition.cnn.com
    port:
      number: 443
  weight: 100
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;再次发送之前的三个到 &lt;code&gt;cnn.com&lt;/code&gt; 的请求，这里会看到三个 200 的成功返回：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
200
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;VirtualService&lt;/code&gt; 的传播和生效可能需要几秒钟的等待。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;使用-mixer-策略进行访问控制&#34;&gt;使用 Mixer 策略进行访问控制&lt;/h3&gt;

&lt;p&gt;这一步中，我们使用 &lt;a href=&#34;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/list/&#34; target=&#34;_blank&#34;&gt;Listchecker adapter&lt;/a&gt;，这是白名单的一个变体。用一个静态 URL 列表定义一个 &lt;code&gt;listentry&lt;/code&gt;，然后在 &lt;code&gt;listchecker&lt;/code&gt; 中用 &lt;code&gt;overrides&lt;/code&gt; 字段进行检查。如果有外部的 &lt;a href=&#34;https://en.wikipedia.org/wiki/Identity_management&#34; target=&#34;_blank&#34;&gt;认证和访问管理系统&lt;/a&gt;，可以使用 &lt;code&gt;providerurl&lt;/code&gt; 字段取而代之。下面图示显示了更新之后的 对象关系。注意这里复用了同样的策略，&lt;code&gt;handle-cnn-access&lt;/code&gt; 对日志和访问策略同样生效。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/egress-adapters-monitoring-policy.svg&#34; alt=&#34;Egress 监控和访问策略使用的 Instance、Rule 和 Handler&#34; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;定义 &lt;code&gt;path-checker&lt;/code&gt; 以及 &lt;code&gt;request-path&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: listchecker
metadata:
name: path-checker
namespace: istio-system
spec:
overrides: [&amp;quot;/health&amp;quot;, &amp;quot;/sport&amp;quot;]  # 提供一个静态列表
blacklist: false
---
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: listentry
metadata:
name: request-path
namespace: istio-system
spec:
value: request.path
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;修改 &lt;code&gt;handle-cnn-access&lt;/code&gt; 规则，要求将 &lt;code&gt;request-path&lt;/code&gt; 发送给 &lt;code&gt;path-checker&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# 访问 cnn.com egress 的规则
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
name: handle-cnn-access
namespace: istio-system
spec:
match: request.host.endsWith(&amp;quot;.cnn.com&amp;quot;)
actions:
- handler: egress-access-logger.stdio
instances:
  - egress-access.logentry
- handler: path-checker.listchecker
instances:
  - request-path.listentry
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;再次执行 curl 指令，发现 &lt;a href=&#34;http://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 返回了 404：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
404
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;使用-mixer-策略进行访问控制-续&#34;&gt;使用 Mixer 策略进行访问控制（续）&lt;/h3&gt;

&lt;p&gt;在前面我们配置了日志和访问控制之后，新增一个需要就是允许在 &lt;code&gt;policics&lt;/code&gt; 命名空间内的应用能够访问 &lt;code&gt;cnn.com&lt;/code&gt; 的所有内容，并且不受监控。接下来我们在 Istio 中进行配置，完成这一要求。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;创建 &lt;code&gt;polictics&lt;/code&gt; 命名空间&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl create namespace politics
namespace &amp;quot;politics&amp;quot; created
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;在 &lt;code&gt;polictics&lt;/code&gt; 命名空间中启动 &lt;a href=&#34;https://github.com/istio/istio/tree/release-0.8/samples/sleep&#34; target=&#34;_blank&#34;&gt;sleep&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果使用了 &lt;a href=&#34;https://istio.io/docs/setup/kubernetes/sidecar-injection/#automatic-sidecar-injection&#34; target=&#34;_blank&#34;&gt;自动注入 Sidecar&lt;/a&gt;，执行：&lt;code&gt;$ kubectl apply -n politics -f samples/sleep/sleep.yaml&lt;/code&gt;，否则，就需要进行注入了：&lt;code&gt;kubectl apply -n politics -f &amp;lt;(istioctl kube-inject -f samples/sleep/sleep.yaml)&lt;/code&gt;。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;预备使用 &lt;code&gt;policics&lt;/code&gt; 命名空间中的 &lt;code&gt;sleep&lt;/code&gt; pod 来发送请求，这里定义一个环境变量来保存 Pod 名称。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;export SOURCE_POD_IN_POLITICS=$(kubectl get pod -n politics -l app=sleep -o jsonpath={.items..metadata.name})
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;这次从新的 Pod（&lt;code&gt;$SOURCE_POD_IN_POLITICS&lt;/code&gt;）中发送刚才的请求。因为我们还没有给新的命名空间中的应用设置例外，&lt;a href=&#34;http://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 还是返回了 404。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD_IN_POLITICS -n politics -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
404
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;查询 Mixer 日志，会看到来自 &lt;code&gt;politics&lt;/code&gt; 命名空间的访问记录：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath=&#39;{.items[0].metadata.name}&#39;) mixer | grep egress-access | grep cnn | tail -4
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;查询结果：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T17:37:14.639102Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:404,&amp;quot;responseSize&amp;quot;:76,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;politics&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;error&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T17:37:14.639102Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/politics&amp;quot;,&amp;quot;responseCode&amp;quot;:404,&amp;quot;responseSize&amp;quot;:76,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;politics&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T17:37:14.653225Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/sport&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:356349,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;politics&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
{&amp;quot;level&amp;quot;:&amp;quot;info&amp;quot;,&amp;quot;time&amp;quot;:&amp;quot;2018-06-19T17:37:14.767923Z&amp;quot;,&amp;quot;instance&amp;quot;:&amp;quot;egress-access.logentry.istio-system&amp;quot;,&amp;quot;destination&amp;quot;:&amp;quot;edition.cnn.com&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/health&amp;quot;,&amp;quot;responseCode&amp;quot;:200,&amp;quot;responseSize&amp;quot;:334027,&amp;quot;source&amp;quot;:&amp;quot;sleep&amp;quot;,&amp;quot;sourceNamespace&amp;quot;:&amp;quot;politics&amp;quot;,&amp;quot;user&amp;quot;:&amp;quot;unknown&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的输出中可以看到 &lt;code&gt;sourceNamespace&lt;/code&gt; 的值为 &lt;code&gt;politics&lt;/code&gt;。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;重新定义 &lt;code&gt;handle-cnn-access&lt;/code&gt; 以及 &lt;code&gt;handle-politics&lt;/code&gt; 策略，为新的命名空间定义例外的日志和访问策略。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
name: handle-politics
namespace: istio-system
spec:
match: request.host.endsWith(&amp;quot;cnn.com&amp;quot;) &amp;amp;&amp;amp; request.path.startsWith(&amp;quot;/politics&amp;quot;) &amp;amp;&amp;amp; source.namespace != &amp;quot;politics&amp;quot;
actions:
- handler: egress-error-logger.stdio
instances:
- egress-access.logentry
---
# 访问 egress cnn.com 的规则
apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
name: handle-cnn-access
namespace: istio-system
spec:
match: request.host.endsWith(&amp;quot;.cnn.com&amp;quot;) &amp;amp;&amp;amp; source.namespace != &amp;quot;politics&amp;quot;
actions:
- handler: egress-access-logger.stdio
instances:
  - egress-access.logentry
- handler: path-checker.listchecker
instances:
  - request-path.listentry
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;在 &lt;code&gt;$SOURCE_POD&lt;/code&gt; 中重复执行测试：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
404
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$SOURCE_POD&lt;/code&gt; 是在 &lt;code&gt;default&lt;/code&gt; 命名空间的，所以对 &lt;a href=&#34;http://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问会被拒绝。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在 &lt;code&gt;$SOURCE_POD_IN_POLITICS&lt;/code&gt; 中重复执行测试：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD_IN_POLITICS -n politics -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
200
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;现在所有访问都可以通过了。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;查看 Mixer 日志，会发现看不到 &lt;code&gt;sourceNamespace&lt;/code&gt; 为 &lt;code&gt;politics&lt;/code&gt; 的条目了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath=&#39;{.items[0].metadata.name}&#39;) mixer | grep egress-access | grep cnn
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h2&gt;

&lt;p&gt;让运维人员能够可视化的进行 egress 流量监控，也能增强安全性。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;浏览&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/using-istio-dashboard/#viewing-the-istio-dashboard&#34; target=&#34;_blank&#34;&gt;使用 Grafana 进行指标可视化&lt;/a&gt;任务，完成其中的步骤 1-3。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;从 &lt;code&gt;$SOURCE_POD&lt;/code&gt; 发送到 &lt;code&gt;cnn.com&lt;/code&gt; 的请求：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
404
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;因为 &lt;code&gt;$SOURCE_POD&lt;/code&gt; 是存在于 &lt;code&gt;default&lt;/code&gt; 命名空间中的，所以对 &lt;a href=&#34;http://edition.cnn.com/politics&#34; target=&#34;_blank&#34;&gt;edition.cnn.com/politics&lt;/a&gt; 的访问会被拒绝。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;从 &lt;code&gt;$SOURCE_POD_IN_POLITICS&lt;/code&gt; 发送到 &lt;code&gt;cnn.com&lt;/code&gt; 的请求：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl exec -it $SOURCE_POD_IN_POLITICS -n politics -c sleep -- bash -c &#39;curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/politics; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/sport; curl -sL -o /dev/null -w &amp;quot;%{http_code}\n&amp;quot; http://edition.cnn.com/health&#39;
200
200
200
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;滚动 Dashboard 到 HTTP 服务部分的 &lt;code&gt;istio-egressgateway.istio-system.svc.cluster.local&lt;/code&gt; 一节。会看到大致如下的显示：&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&#34;img/dashboard-egress-gateway.png&#34; alt=&#34;istio-gresssgateway dashboard&#34; /&gt;&lt;/p&gt;

&lt;p&gt;在左侧 &lt;code&gt;Requests by Source, Version and Response Code&lt;/code&gt; 中，会看到 default 命名空间中的 &lt;code&gt;unknown&lt;/code&gt; 版本的 sleep 应用收到的 404 返回码。运维人员可以据此发现试图访问受控目标的应用。还可以看到在 &lt;code&gt;polictics&lt;/code&gt; 命名空间中 &lt;code&gt;sleep&lt;/code&gt; 应用收到的 200 返回码，这样也就知道了对受控外部资源的有效访问情况。&lt;/p&gt;

&lt;h2 id=&#34;和-https-egress-控制的比较&#34;&gt;和 HTTPS egress 控制的比较&lt;/h2&gt;

&lt;p&gt;这个用例中，应用使用的是 HTTP 和 Istio Egress Gateway 结合提供 TLS 的。换个方式，应用可以自行发送 TLS 请求给 &lt;code&gt;edition.cnn.com&lt;/code&gt;，本节中我们会对两种方式的优劣进行一些比较。&lt;/p&gt;

&lt;p&gt;HTTP 方式中，请求在本地是明文传输，经由 Sidecar 转发给 Egress Gateway 的。如果 Istio 使用双向 TLS 部署，Sidecar 代理和 Egress Gateway 之间的通信就是加密的。Egress Gateway 解密信息，查看 URL 路径，HTTP 方法和 Header，上报监控数据、执行前置检查。如果请求没有被拒绝，Egress Gateway 就会为外部目标执行 TLS 封装，这样请求就会被再次加密，以密文形式发送给外部目标。下图演示了这种方式中的网络流向。图中 Gateway 方块中的 HTTP 标志，代表报文在 Gateway 解密之后变成明文的阶段。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/http-to-gateway.svg&#34; alt=&#34;HTTP egress traffic through an egress gateway&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这种方式的缺陷在于，请求在本机是明文传输的，可能会违反某些组织的安全需要。有些 SDK 的外部服务 URL 包含协议部分都是硬编码的，因此发送 HTTP 请求是不可能的。这种办法的好处是可以获取 HTTP 头、方法以及 URL 路径，并可以据此制定规则。&lt;/p&gt;

&lt;p&gt;在 HTTPS 形式下，从应用到外部目标的请求是端到端加密的。下图演示了这种方式的数据流。在 Gateway 中见到的报文，同样还是 HTTPS。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/https-to-gateway.svg&#34; alt=&#34;通过 Egress Gateway 的 HTTPS egress 流量&#34; /&gt;&lt;/p&gt;

&lt;p&gt;端到端的 HTTPS 可能是更好的一种加密方式。然而因为流量是加密通过 Istio 代理和 Egress Gateway 的，因此只能看到源和目的的 IP 以及 &lt;a href=&#34;https://en.wikipedia.org/wiki/Server_Name_Indication&#34; target=&#34;_blank&#34;&gt;SNI&lt;/a&gt;。在 Istio 开通双向 TLS 的情况下，&lt;a href=&#34;https://istio.io/docs/concepts/security/mutual-tls/#identity&#34; target=&#34;_blank&#34;&gt;源身份&lt;/a&gt;也是可知的。Gateway 无法获知 HTTP 头、方法以及 URL 路径，因此基于 HTTP 信息的策略就无法实现了。我们的用例中要求可以访问 &lt;code&gt;edition.cnn.com&lt;/code&gt;。如果 Istio 中启用了双向 TLS，组织可以设置部分应用允许访问 &lt;code&gt;edition.cnn.com&lt;/code&gt;。然而却无法允许或禁止访问特定的 URL。对 &lt;code&gt;/politics&lt;/code&gt; 的允许或者禁止，在这种上下文中都是无法实现的。&lt;/p&gt;

&lt;p&gt;我们认为，这样讲解之后，用户就可以对这两种方法进行优劣势的评估，进而做出合适的选择。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;本文中我们展示了 Istio 用 HTTP 访问 Egress 时的监控和策略。其中的监控过程，可以配置日志适配器结合 Istio Dashboard 来完成。而访问策略可以通过配置 &lt;code&gt;VirtualService&lt;/code&gt; 或者配置多种策略适配器来完成。我们演示了一个简单的策略，只允许某些 URL 的访问。我们另外还展示了稍微复杂一些的策略，通过放行指定命名空间中的指定应用，来做出例外。最后，我们比较了两种 HTTPS 过程的优劣，同时也就有不同的控制能力。&lt;/p&gt;

&lt;h2 id=&#34;清理&#34;&gt;清理&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;执行 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/&#34; target=&#34;_blank&#34;&gt;配置 Egress Gateway&lt;/a&gt; 任务中的 &lt;a href=&#34;https://istio.io/docs/tasks/traffic-management/egress-gateway/#cleanup&#34; target=&#34;_blank&#34;&gt;清理&lt;/a&gt;任务。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;删除日志和策略配置：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;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
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;删除 &lt;code&gt;politics&lt;/code&gt; 命名空间&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;执行&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/using-istio-dashboard/&#34; target=&#34;_blank&#34;&gt;使用 Grafana 进行指标可视化&lt;/a&gt;任务中的&lt;a href=&#34;https://istio.io/docs/tasks/telemetry/using-istio-dashboard/#cleanup&#34; target=&#34;_blank&#34;&gt;清理&lt;/a&gt;环节。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Istio 的软性多租户支持</title>
      <link>/post/soft-multitenancy/</link>
      <pubDate>Fri, 15 Jun 2018 15:20:36 +0800</pubDate>
      <guid>/post/soft-multitenancy/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://istio.io/blog/2018/soft-multitenancy/&#34; target=&#34;_blank&#34;&gt;Istio Soft Multi-tenancy Support&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://github.com/john-a-joyce&#34; target=&#34;_blank&#34;&gt;John Joyce&lt;/a&gt;, &lt;a href=&#34;https://github.com/rcurran1&#34; target=&#34;_blank&#34;&gt;Rich Curran&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;多租户是一个在各种环境和各种应用中都得到了广泛应用的概念，但是不同环境中，为每租户提供的具体实现和功能性都是有差异的。&lt;a href=&#34;https://github.com/kubernetes/community/blob/master/wg-multitenancy/README.md&#34; target=&#34;_blank&#34;&gt;Kubernetes 多租户工作组&lt;/a&gt;致力于在 Kubernetes 中定义多租户用例和功能。然而根据他们的工作进展来看，恶意容器和负载对于其他租户的 Pod 和内核资源的访问无法做到完全控制，因此只有“软性多租户”支持是可行的。&lt;/p&gt;

&lt;h2 id=&#34;软性多租户&#34;&gt;软性多租户&lt;/h2&gt;

&lt;p&gt;文中提到的“软性多租户”的定义指的是单一 Kubernetes 控制平面和多个 Istio 控制平面以及多个服务网格相结合；每个租户都有自己的一个控制平面和一个服务网格。集群管理员对所有 Istio 控制面都有控制和监控的能力，而租户管理员仅能得到指定 Istio 的控制权。使用 Kubernetes 的命名空间和 RBAC 来完成不同租户的隔离。&lt;/p&gt;

&lt;p&gt;这种模式的一个用例就是企业内部共享的基础设施中，虽然预计不会发生恶意行为，但租户之间的清晰隔离仍然是很有必要的。&lt;/p&gt;

&lt;p&gt;在文章最尾部会对 Istio 未来的多租户模型进行一些描述。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：这里仅就在有限多租户环境中部署 Istio 做一些概要描述。当官方多租户支持实现之后，会在&lt;a href=&#34;/docs/&#34;&gt;文档&lt;/a&gt;中具体呈现。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;部署&#34;&gt;部署&lt;/h2&gt;

&lt;h3 id=&#34;多个-istio-控制面&#34;&gt;多个 Istio 控制面&lt;/h3&gt;

&lt;p&gt;要部署多个 Istio 控制面，首先要在 Istio 清单文件中对所有的 &lt;code&gt;namespace&lt;/code&gt; 引用进行替换。以 &lt;code&gt;istio.yaml&lt;/code&gt; （v0.8 中应该是 &lt;code&gt;istio-demo.yaml&lt;/code&gt;） 为例：如果需要两个租户级的 Istio 控制面，那么第一个租户可以使用 &lt;code&gt;istio.yaml&lt;/code&gt; 中的缺省命名空间也就是 &lt;code&gt;istio-system&lt;/code&gt;；而第二个租户就要生成一个新的 Yaml 文件，并在其中使用不同的命名空间。例如使用下面的命令创建一个使用 &lt;code&gt;istio-system1&lt;/code&gt; 命名空间的 Yaml 文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;cat istio.yaml | sed s/istio-system/istio-system1/g &amp;gt; istio-system1.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Istio Yaml 文件包含了 Istio 控制面的部署细节，包含组成控制面的 Pod（Mixer、Pilot、Ingress 以及 CA）。部署这两个控制面 Yaml 文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;kubectl apply -f @install/kubernetes/istio.yaml@
kubectl apply -f @install/kubernetes/istio-system1.yaml@
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会在两个命名空间生成两个 Istio 控制面&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ 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
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果需要 Istio &lt;a href=&#34;/docs/setup/kubernetes/sidecar-injection/&#34;&gt;Sidecar 注入组件&lt;/a&gt;以及&lt;a href=&#34;/docs/tasks/telemetry/&#34;&gt;遥测组件&lt;/a&gt;，也需要根据租户的命名空间定义，修改所需的 Yaml 文件。&lt;/p&gt;

&lt;p&gt;需要由集群管理员、而不是租户自己的管理员来加载这两组 Yaml 文件。另外，要把租户管理员的操作权限限制在各自的命名空间内，还需要额外的 RBAC 配置。&lt;/p&gt;

&lt;h3 id=&#34;区分通用资源和命名空间资源&#34;&gt;区分通用资源和命名空间资源&lt;/h3&gt;

&lt;p&gt;Istio 仓库中的清单文件中会创建两种资源，一种是能够被所有 Istio 控制面访问的通用资源，另一种是每个控制平面一份的专属资源。上面所说的在 Yaml 文件中替换 &lt;code&gt;istio-system&lt;/code&gt; 命名空间的方法自然是很简单的，更好的一种方法就是把 Yaml 文件拆分为两块，一块是所有租户共享的通用部分；另一块就是租户自有的部分。根据 &lt;a href=&#34;https://kubernetes.io/docs/concepts/api-extension/custom-resources/#customresourcedefinitions&#34; target=&#34;_blank&#34;&gt;CRD 资源定义（Custom Resource Definitions）&lt;/a&gt;中的说法，角色和角色绑定资源需要从 Istio 文件中进行剥离。另外，清单文件中提供的角色和角色绑定的定义可能不适合多租户环境，还需要进一步的细化和定制。&lt;/p&gt;

&lt;h3 id=&#34;istio-控制面的-kubernetes-rbac-设置&#34;&gt;Istio 控制面的 Kubernetes RBAC 设置&lt;/h3&gt;

&lt;p&gt;租户管理员应该被限制在单独的 Istio 命名空间中，要完成这个限制，集群管理员需要创建一个清单，其中至少要包含一个 &lt;code&gt;Role&lt;/code&gt; 和 &lt;code&gt;RoleBinding&lt;/code&gt; 的定义，类似下面的文件所示。例子中定义了一个租户管理员，命名为 &lt;code&gt;sales-admin&lt;/code&gt;，他被限制在命名空间 &lt;code&gt;istio-system&lt;/code&gt; 之中。完整的清单中可能要在 &lt;code&gt;Role&lt;/code&gt; 中包含更多的 &lt;code&gt;apiGroups&lt;/code&gt; 条目，来定义租户管理员的资源访问能力。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: istio-system1
  name: ns-access-for-sales-admin-istio-system1
rules:
- apiGroups: [&amp;quot;&amp;quot;] # &amp;quot;&amp;quot; 代表核心 API 资源组
  resources: [&amp;quot;*&amp;quot;]
  verbs: [&amp;quot;*&amp;quot;]
---
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
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;关注特定命名空间进行服务发现&#34;&gt;关注特定命名空间进行服务发现&lt;/h3&gt;

&lt;p&gt;除了创建 RBAC 规则来限制租户管理员只能访问指定 Istio 控制平面之外，Istio 清单还需要为 Istio Pilot 指定一个用于应用程序的命名空间，以便生成 xDS 缓存。Pilot 组件提供了命令行参数 &lt;code&gt;--appNamespace, ns-1&lt;/code&gt; 可以完成这一任务。&lt;code&gt;ns-1&lt;/code&gt; 就是租户用来部署自己应用的命名空间。&lt;code&gt;istio-system1.yaml&lt;/code&gt; 中包含的相关代码大致如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: istio-pilot
  namespace: istio-system1
  annotations:
    sidecar.istio.io/inject: &amp;quot;false&amp;quot;
spec:
  replicas: 1
  template:
    metadata:
      labels:
        istio: pilot
    spec:
      serviceAccountName: istio-pilot-service-account
      containers:
      - name: discovery
        image: docker.io/&amp;lt;user ID&amp;gt;/pilot:&amp;lt;tag&amp;gt;
        imagePullPolicy: IfNotPresent
        args: [&amp;quot;discovery&amp;quot;, &amp;quot;-v&amp;quot;, &amp;quot;2&amp;quot;, &amp;quot;--admission-service&amp;quot;, &amp;quot;istio-pilot&amp;quot;, &amp;quot;--appNamespace&amp;quot;, &amp;quot;ns-1&amp;quot;]
        ports:
        - containerPort: 8080
        - containerPort: 443
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;在特定命名空间中部署租户应用&#34;&gt;在特定命名空间中部署租户应用&lt;/h3&gt;

&lt;p&gt;现在集群管理员已经给租户创建了命名空间（&lt;code&gt;istio-system1&lt;/code&gt;），并且对 Istio Pilot 的服务发现进行了配置，要求它关注应用的命名空间（&lt;code&gt;ns-1&lt;/code&gt;），创建应用的 Yaml 文件，将其部署到租户的专属命名空间中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Namespace
metadata:
  name: ns-1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后把每个资源的命名空间都指定到 &lt;code&gt;ns-1&lt;/code&gt;，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
  namespace: ns-1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;虽然没有展示出来，但是应用的命名空间也应该有 RBAC 设置，用来对特定资源进行访问控制。集群管理员和租户管理员都有权完成这种 RBAC 限制。&lt;/p&gt;

&lt;h3 id=&#34;在多租户环境中使用-istioctl&#34;&gt;在多租户环境中使用 &lt;code&gt;istioctl&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;定义&lt;a href=&#34;/docs/reference/config/istio.routing.v1alpha1/#RouteRule&#34;&gt;路由规则&lt;/a&gt;或者&lt;a href=&#34;/docs/reference/config/istio.routing.v1alpha1/#DestinationPolicy&#34;&gt;目标策略&lt;/a&gt;时，要确认 &lt;code&gt;istioctl&lt;/code&gt; 命令是针对专有的 Istio 控制面所在的命名空间运行的。另外规则自身的定义也要限制在租户的命名空间里，这样才能保证规则在租户自己的网格中生效。&lt;code&gt;-i&lt;/code&gt; 选项用来在 Istio 控制面所属的命名空间中创建（get 和 describe 也一样）规则。&lt;code&gt;-n&lt;/code&gt; 参数会限制规则的所在范围是租户的网格，取值就是租户应用所在的命名空间。如果 Yaml 文件中的资源已经指定了范围，&lt;code&gt;-n&lt;/code&gt; 参数会被跳过。&lt;/p&gt;

&lt;p&gt;例如下面的命令会创建到 &lt;code&gt;istio-system1&lt;/code&gt; 命名空间的路由规则：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;istioctl –i istio-system1 create -n ns-1 -f route_rule_v2.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用下面的命令可以查看：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ istioctl -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
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&#34;/blog/2018/soft-multitenancy/#multiple-istio-control-planes&#34;&gt;Multiple Istio control planes&lt;/a&gt; 中讲述了更多多租户环境下命名空间的相关问题。&lt;/p&gt;

&lt;h3 id=&#34;测试结果&#34;&gt;测试结果&lt;/h3&gt;

&lt;p&gt;根据前文的介绍，一个集群管理员能够创建一个受限于 RBAC 和命名空间的环境，租户管理员能在其中进行部署。&lt;/p&gt;

&lt;p&gt;完成部署后，租户管理员就可以访问指定的 Istio 控制平面的 Pod 了。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ 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
servicegraph-75ff8f7c95-wcjs7             1/1       Running   0          1d
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然而无法访问全部命名空间的 Pod：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl get pods --all-namespaces
Error from server (Forbidden): pods is forbidden: User &amp;quot;dev-admin&amp;quot; cannot list pods at the cluster scope
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;访问其他租户的命名空间也是不可以的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl get pods -n istio-system1
Error from server (Forbidden): pods is forbidden: User &amp;quot;dev-admin&amp;quot; cannot list pods in the namespace &amp;quot;istio-system1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;租户管理员能够在租户指定的应用命名空间中进行应用部署。例如可以修改一下 &lt;a href=&#34;/docs/guides/bookinfo/&#34;&gt;Bookinfo&lt;/a&gt; 的 Yaml 然后部署到租户的命名空间 &lt;code&gt;ns-0&lt;/code&gt; 中，然后租户管理员就可以在这一命名空间中列出 Pod 了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ 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
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;同样也是不能访问其他租户的应用程序命名空间：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-command&#34;&gt;$ kubectl get pods -n ns-1
Error from server (Forbidden): pods is forbidden: User &amp;quot;dev-admin&amp;quot; cannot list pods in the namespace &amp;quot;ns-1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果部署了&lt;a href=&#34;/docs/tasks/telemetry/&#34;&gt;遥测组件&lt;/a&gt;, 例如
&lt;a href=&#34;/docs/tasks/telemetry/querying-metrics/&#34;&gt;prometheus&lt;/a&gt;（限制在 Istio 的 &lt;code&gt;namespace&lt;/code&gt;），其中获得的统计结果展示的也只是租户应用命名空间的私有数据。&lt;/p&gt;

&lt;h2 id=&#34;结语&#34;&gt;结语&lt;/h2&gt;

&lt;p&gt;上面的一些尝试表明 Istio 有足够的能力和安全性，符合少量多租户的用例需求。另外也很明显的，Istio 和 Kubernetes &lt;strong&gt;无法&lt;/strong&gt; 提供足够的能力和安全性来满足其他的用例，尤其是在租户之间要求完全的安全性和隔离的要求的用例。如果容器技术例如 Kubernetes 能够提供更好的安全模型以及隔离能力，我们才能进一步的增强这方面的支持，Istio 的支持并不是很重要。&lt;/p&gt;

&lt;h2 id=&#34;问题&#34;&gt;问题&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;一个租户的 CA(Certificate Authority) 和 Mixer 的 Pod 中产生的 Log 包含了另一个租户的控制面的 &lt;code&gt;info&lt;/code&gt; 信息。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;其他多租户模型的挑战&#34;&gt;其他多租户模型的挑战&lt;/h2&gt;

&lt;p&gt;还有其他值得考虑的多租户部署模型：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;一个网格中运行多个应用程序，每个租户一个应用。集群管理员能控制和监控网格范围内的所有应用，租户管理员只能控制一个特定应用。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;单独的 Istio 控制平面控制多个网格，每个租户一个网格。集群管理员控制和监控整个 Istio 控制面以及所有网格，租户管理员只能控制特定的网格。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;一个云环境（集群控制），多个 Kubernetes 控制面（租户控制）&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这些选项，有的需要改写代码才能支持，有的无法满足用户要求。&lt;/p&gt;

&lt;p&gt;目前的 Istio 能力不适合第一种方案，这是因为其 RBAC 能力无法覆盖这种租户操作。另外在当前的网格模型中，Istio 的配置信息需要传递给 Envoy 代理服务器，多个租户在同一网格内共存的做法非常不安全。&lt;/p&gt;

&lt;p&gt;再看看第二个方式，目前的 Istio 假设每个 Istio 控制面对应一个网格。要支持这种模型需要大量改写。这种情况需要更好的对资源的范围限制进行调整，同时根据命名空间进行安全限制，此外还需要调整 Istio 的 RBAC 模型。这种模式未来可能会支持，但目前来说是不可能的。&lt;/p&gt;

&lt;p&gt;第三个方式对多数案例都是不合适的，毕竟多数集群管理员倾向于将同一个 Kubernetes 控制面作为 &lt;a href=&#34;https://en.wikipedia.org/wiki/Platform_as_a_service&#34; target=&#34;_blank&#34;&gt;PaaS&lt;/a&gt; 提供给他们的租户。&lt;/p&gt;

&lt;h2 id=&#34;未来&#34;&gt;未来&lt;/h2&gt;

&lt;p&gt;很明显，单一 Istio 控制面控制多个网格可能是下一个功能。还有可能就是在同一个网格中支持多个租户，并提供某种程度的隔离和安全保障。要完成这样的能力，就需要像 Kubernetes 中对命名空间的额操作那样，在一个单独的控制平面中进行分区，社区中发出了 &lt;a href=&#34;https://docs.google.com/document/d/14Hb07gSrfVt5KX9qNi7FzzGwB_6WBpAnDpPG6QEEd9Q&#34; target=&#34;_blank&#34;&gt;这篇文档&lt;/a&gt; 来定义其他的用例，以及要支持这些用例所需要的 Istio 功能。&lt;/p&gt;

&lt;h2 id=&#34;参考&#34;&gt;参考&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;视频：Kubernetes 多租户支持 &lt;a href=&#34;https://www.youtube.com/watch?v=ahwCkJGItkU&#34; target=&#34;_blank&#34;&gt;Multi-Tenancy Support &amp;amp; Security Modeling with RBAC and Namespaces&lt;/a&gt;, 以及&lt;a href=&#34;https://schd.ws/hosted_files/kccncna17/21/Multi-tenancy%20Support%20%26%20Security%20Modeling%20with%20RBAC%20and%20Namespaces.pdf&#34; target=&#34;_blank&#34;&gt;幻灯片&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Kubecon 讨论，关于对”协同软性多租户“的支持 &lt;a href=&#34;https://www.youtube.com/watch?v=YRR-kZub0cA&#34; target=&#34;_blank&#34;&gt;Building for Trust: How to Secure Your Kubernetes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Kubernetes &lt;a href=&#34;https://kubernetes.io/docs/admin/authorization/rbac/&#34; target=&#34;_blank&#34;&gt;RBAC 文档&lt;/a&gt; 以及 &lt;a href=&#34;https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/&#34; target=&#34;_blank&#34;&gt;命名空间文档&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Kubecon 幻灯片 &lt;a href=&#34;https://schd.ws/hosted_files/kccncna17/a9/kubecon-multitenancy.pdf&#34; target=&#34;_blank&#34;&gt;Multi-tenancy Deep Dive&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Google 文档 &lt;a href=&#34;https://docs.google.com/document/d/15w1_fesSUZHv-vwjiYa9vN_uyc--PySRoLKTuDhimjc/edit#heading=h.3dawx97e3hz6&#34; target=&#34;_blank&#34;&gt;Multi-tenancy models for Kubernetes&lt;/a&gt;. (需要授权)&lt;/li&gt;
&lt;li&gt;Cloud Foundry 提出的文档：&lt;a href=&#34;https://docs.google.com/document/d/14Hb07gSrfVt5KX9qNi7FzzGwB_6WBpAnDpPG6QEEd9Q&#34; target=&#34;_blank&#34;&gt;Multi-cloud and Multi-tenancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.google.com/document/d/12F183NIRAwj2hprx-a-51ByLeNqbJxK16X06vwH5OWE/edit#heading=h.x0f9qplja3q&#34; target=&#34;_blank&#34;&gt;Istio Auto Multi-Tenancy 101&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Istio 安全设置笔记</title>
      <link>/post/istio-security-notes/</link>
      <pubDate>Mon, 11 Jun 2018 00:05:25 +0800</pubDate>
      <guid>/post/istio-security-notes/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://istio.io/&#34; target=&#34;_blank&#34;&gt;Istio&lt;/a&gt; 为网格中的微服务提供了较为完善的安全加固功能，在不影响代码的前提下，可以从多个角度提供安全支撑，&lt;a href=&#34;https://istio.io/docs/tasks/security/&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;做了较为详细的介绍，但是也比较破碎，这里尝试做个简介兼索引，实现过程还是要根据官方文档进行。&lt;/p&gt;

&lt;p&gt;Istio 的安全功能主要分为三个部分的实现：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;双向 TLS 支持。&lt;/li&gt;
&lt;li&gt;基于黑白名单的访问控制。&lt;/li&gt;
&lt;li&gt;基于角色的访问控制。&lt;/li&gt;
&lt;li&gt;JWT 认证支持。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;首先回顾一下 Istio 网格中的服务通信过程：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;利用自动或者手工注入，把 Envoy Proxy 注入到每个服务 Pod 中，用 Sidecar 的方式运行。&lt;/li&gt;
&lt;li&gt;Pod 初始化过程里，使用 iptables 劫持所在 Pod 的&lt;strong&gt;出入&lt;/strong&gt;流量。&lt;/li&gt;
&lt;li&gt;服务间的通信，从原来的直接通信，转换为现在的 Envoy 之间通信，Envoy 在这里同时作为客户端和服务端负载均衡组件。&lt;/li&gt;
&lt;li&gt;Envoy 的工作过程中，可能会和 Mixer、Pilot 以及 Citadel 等组件发生互动。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;双向-tls-支持&#34;&gt;双向 TLS 支持&lt;/h2&gt;

&lt;p&gt;双向 TLS 支持主要针对的是通信方面，把明文传输的服务通信，通过转换为 Envoy 之间的加密通信。这一安全设置较为基础，可以在全局、Namespace 或者单个服务的范围内生效。&lt;/p&gt;

&lt;p&gt;这一功能主要通过两个 Istio CRD 对象来完成：&lt;/p&gt;

&lt;h3 id=&#34;policy&#34;&gt;Policy&lt;/h3&gt;

&lt;p&gt;例如 &lt;a href=&#34;https://istio.io/docs/tasks/security/authn-policy/&#34; target=&#34;_blank&#34;&gt;Basic Authentication Policy&lt;/a&gt; 中的一个样例，用于给单个服务设置 mtls：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;authentication.istio.io/v1alpha1&amp;quot;
kind: &amp;quot;Policy&amp;quot;
metadata:
  name: &amp;quot;example-2&amp;quot;
spec:
  targets:
  - name: httpbin
  peers:
  - mtls:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其中 &lt;code&gt;target&lt;/code&gt; 是可选项，如果去掉的话，作用域将扩展到整个 Namespace。&lt;/p&gt;

&lt;h3 id=&#34;destinationrule&#34;&gt;DestinationRule&lt;/h3&gt;

&lt;p&gt;同样的一个例子里面的目标规则如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;networking.istio.io/v1alpha3&amp;quot;
kind: &amp;quot;DestinationRule&amp;quot;
metadata:
  name: &amp;quot;example-2&amp;quot;
spec:
  host: httpbin.bar.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE
    portLevelSettings:
    - port:
        number: 1234
      tls:
        mode: ISTIO_MUTUAL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这个也很容易理解，这一规则用于指派对该地址的访问方式：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tls.mode = DISABLE&lt;/code&gt;，这个服务缺省是不开启 tls 支持的，如果取值 &lt;code&gt;ISTIO_MUTUAL&lt;/code&gt;，则代表这个地址（服务）的所有端口都开启 TLS。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;port...ISTIO_MUTUAL&lt;/code&gt;，只针对这一个端口启用 mTLS 支持。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;创建 Policy 之后，Citadel 会生成证书文件，并传递给 Envoy，我们可以在 Envoy 容器（kube-proxy）的 &lt;code&gt;/etc/certs/&lt;/code&gt; 目录中看到这几个 &lt;code&gt;*.pem&lt;/code&gt; 文件。如果使用 &lt;code&gt;openssl x509 -text -noout&lt;/code&gt; 查看 &lt;code&gt;cert-chain.pem&lt;/code&gt; 的证书内容，会看到 spiffe 编码的 ServiceAccount 内容来作为 SAN：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt; X509v3 Subject Alternative Name:
            URI:spiffe://cluster.local/ns/default/sa/default
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;规则生效之后，原有的服务间调用是没有差异的，但是如果在网格之外，就必须 https，结合上面谈到的证书来访问目标服务才能完成访问。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;另外这里也提供了&lt;a href=&#34;https://istio.io/docs/tasks/security/plugin-ca-cert/&#34; target=&#34;_blank&#34;&gt;外部 CA 的支持&lt;/a&gt;，可以使用已有的证书体系来替换网格内的自签发体系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;基于黑白名单的访问控制&#34;&gt;基于黑白名单的访问控制&lt;/h2&gt;

&lt;h3 id=&#34;黑名单&#34;&gt;黑名单&lt;/h3&gt;

&lt;p&gt;下面的例子来自&lt;a href=&#34;https://raw.githubusercontent.com/istio/istio/release-0.8/samples/bookinfo/kube/mixer-rule-deny-label.yaml&#34; target=&#34;_blank&#34;&gt;官方&lt;/a&gt;，禁止 Reviews 的 v3 版本访问 Ratings 服务。&lt;/p&gt;

&lt;p&gt;首先使用 &lt;code&gt;denier&lt;/code&gt; 适配器定义一个拒绝响应&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: denier
metadata:
  name: denyreviewsv3handler
spec:
  status:
    code: 7
    message: Not allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里不需要额外属性输入，因此采用了 &lt;code&gt;checknothing&lt;/code&gt; 模板：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: checknothing
metadata:
  name: denyreviewsv3request
spec:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最后使用 &lt;code&gt;rule&lt;/code&gt; 对象把这两者联系起来，并配合一个表达式来使之生效：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: rule
metadata:
  name: denyreviewsv3
spec:
  match: destination.labels[&amp;quot;app&amp;quot;] == &amp;quot;ratings&amp;quot; &amp;amp;&amp;amp; source.labels[&amp;quot;app&amp;quot;]==&amp;quot;reviews&amp;quot; &amp;amp;&amp;amp; source.labels[&amp;quot;version&amp;quot;] == &amp;quot;v3&amp;quot;
  actions:
  - handler: denyreviewsv3handler.denier
    instances: [ denyreviewsv3request.checknothing ]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;白名单&#34;&gt;白名单&lt;/h3&gt;

&lt;p&gt;官方案例设置了一个允许 &lt;code&gt;v2&lt;/code&gt; 和 &lt;code&gt;v3&lt;/code&gt; 版本访问 &lt;code&gt;ratings&lt;/code&gt; 服务的白名单。&lt;/p&gt;

&lt;p&gt;白名单适配器要使用的是 &lt;code&gt;listchecker&lt;/code&gt;，提供了一个允许访问的数组。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: listchecker
metadata:
  name: whitelist
spec:
  # providerUrl: 可以从外部 URL 获取列表内容
  overrides: [&amp;quot;v1&amp;quot;, &amp;quot;v2&amp;quot;]  # 静态列表
  blacklist: false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;需要使用一个模板将 Pod 标签转换为 &lt;code&gt;listchecker&lt;/code&gt; 的版本列表。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: listentry
metadata:
  name: appversion
spec:
  value: source.labels[&amp;quot;version&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;最后使用 Rule 进行连接：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: checkversion
spec:
  match: destination.labels[&amp;quot;app&amp;quot;] == &amp;quot;ratings&amp;quot;
  actions:
  - handler: whitelist.listchecker
    instances:
    - appversion.listentry
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：如果开启了 mTLS，可以使用 &lt;code&gt;source.user == &amp;quot;cluster.local/ns/default/sa/bookinfo-productpage&amp;quot;&lt;/code&gt; 的形式来匹配 ServiceAccount。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;rbac&#34;&gt;RBAC&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Helm 安装时，需要设置 &lt;code&gt;global.rbacEnabled: true&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;RBAC 提供较细粒度的访问控制。另外其中所使用的 &lt;code&gt;ServiceRole&lt;/code&gt; 和 &lt;code&gt;ServiceRoleBinding&lt;/code&gt; 也更直观、更加易于管理。&lt;/p&gt;

&lt;p&gt;例如来自&lt;a href=&#34;https://istio.io/docs/tasks/security/role-based-access-control/&#34; target=&#34;_blank&#34;&gt;官方 Task&lt;/a&gt; 的 &lt;code&gt;ServiceRole&lt;/code&gt; 定义，这个角色允许对指定服务进行只读访问：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: &amp;quot;config.istio.io/v1alpha2&amp;quot;
kind: ServiceRole
metadata:
  name: productpage-viewer
  namespace: default
spec:
  rules:
  - services: [&amp;quot;productpage.default.svc.cluster.local&amp;quot;]
    methods: [&amp;quot;GET&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果在 Namespace 级别进行设置，则可以这样：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;...
  rules:
  - services: [&amp;quot;*&amp;quot;]
    methods: [&amp;quot;GET&amp;quot;]
    constraints:
    - key: &amp;quot;app&amp;quot;
      values: [&amp;quot;productpage&amp;quot;]
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;和 Kubernetes 的 Rolebinding 类似，把用户和角色绑定起来，才能最后生效。&lt;/p&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  - user: alice@yahoo.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;或者&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  - properties:
      service: &amp;quot;reviews&amp;quot;
      namespace: &amp;quot;abc&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;subject&lt;/code&gt; 的内容，同样属于 Adapter 模型的实现范围，因此其可选项目仍然是由 Template 的输入产生的。具体样例可以参考 &lt;a href=&#34;https://github.com/istio/istio/blob/release-0.8/samples/bookinfo/kube/istio-rbac-enable.yaml&#34; target=&#34;_blank&#34;&gt;bookinfo 的 rbac 样板&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;jwt-认证&#34;&gt;JWT 认证&lt;/h2&gt;

&lt;p&gt;没有外部认证的需求，因此就先不理了 lol。&lt;/p&gt;

&lt;h2 id=&#34;参考链接&#34;&gt;参考链接：&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;安全任务：&lt;code&gt;https://istio.io/docs/tasks/security&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Istio RBAC 参考：&lt;code&gt;https://istio.io/docs/reference/config/istio.rbac.v1alpha1/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Istio Adapters 参考：&lt;code&gt;https://istio.io/docs/reference/config/policy-and-telemetry/adapters/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Bookinfo 示例：&lt;code&gt;https://github.com/istio/istio/blob/release-0.8/samples/bookinfo/kube/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>在 Istio 中使用 Opentracing Baggage 进行传播和路由</title>
      <link>/post/istio-routing-using-opentracing-baggage-distributed-context-propagation/</link>
      <pubDate>Fri, 08 Jun 2018 12:25:23 +0800</pubDate>
      <guid>/post/istio-routing-using-opentracing-baggage-distributed-context-propagation/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://medium.com/jaegertracing/istio-routing-using-opentracing-baggage-distributed-context-propagation-ed8d787a4bef&#34; target=&#34;_blank&#34;&gt;Istio Routing using OpenTracing Baggage/Distributed Context Propagation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://medium.com/@p.loffay?source=post_header_lockup&#34; target=&#34;_blank&#34;&gt;Pavol Loffay&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;现代服务网格架构提供了很多的新功能，基础设施相关的依赖部分被逐步从代码中移除，极大的降低了编码工作量。除此之外，这一架构的智能路由功能还把金丝雀发布以及类似功能大大的简化了。&lt;/p&gt;

&lt;p&gt;接下来的内容会探讨一下，Istio 路由规则是如何使用 Opentracing Baggage 的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/kiali-screen.jpg&#34; alt=&#34;kiali&#34; /&gt;&lt;/p&gt;

&lt;p&gt;想像一个场景，这个场景中我们需要通过 &lt;code&gt;User-Agent&lt;/code&gt; Header 来鉴别 Safari 用户，并把它们重定向到服务的一个特定版本去。这是一个典型的金丝雀场景：新版本发布时，首先开放给一部分用户。然而很明显只有第一个服务能够接收到 &lt;code&gt;User-Agent&lt;/code&gt; 头，如果路由规则中涉及到调用关系图中位置较低（靠后）的服务，就不得不把这个 Header 信息传播给所有途中经过的服务。这是一个分布式上下文传播的典型用例，很多跟踪系统都有这个功能。我们接下来会看看 &lt;a href=&#34;http://www.jaegertracing.io/&#34; target=&#34;_blank&#34;&gt;Jaeger&lt;/a&gt; 的 OpenTracing 实现。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item&#34; target=&#34;_blank&#34;&gt;Baggage 条目&lt;/a&gt;是字符串组成的键值对，和 &lt;code&gt;Span/SpanContext&lt;/code&gt; 互相关联，在一个 Trace 的范围内，会在所有的下游 Span 中进行传播。&lt;/p&gt;

&lt;p&gt;如果你的网格中使用的是 OpenTracing，那么就已经有这个功能了；如果不是，那就有点不幸了：需要通过其他的 &lt;a href=&#34;https://istio.io/docs/tasks/telemetry/distributed-tracing/#understanding-what-happened&#34; target=&#34;_blank&#34;&gt;跟踪 Header&lt;/a&gt; 来传递 &lt;code&gt;User-Agent&lt;/code&gt; 值了，这样就需要修途经的所有服务。&lt;/p&gt;

&lt;p&gt;Istio 缺省使用的 &lt;a href=&#34;https://github.com/openzipkin/b3-propagation&#34; target=&#34;_blank&#34;&gt;B3&lt;/a&gt; 传播是没有提供 Baggage 头的。但是可以用 &lt;a href=&#34;https://github.com/openzipkin/brave&#34; target=&#34;_blank&#34;&gt;Brave&lt;/a&gt;（Zipkin 的 Java 客户端）来配置 Baggage 支持。一般会使用 &lt;code&gt;baggage-key:value&lt;/code&gt; 的格式。Jaeger 实现了一个 B3 解码器，也用同样的格式来处理 Baggage。可以在&lt;a href=&#34;https://github.com/jaegertracing/jaeger/issues/755#issuecomment-393929718&#34; target=&#34;_blank&#34;&gt;这里&lt;/a&gt;查看 B3 Baggage 实现的进度。&lt;/p&gt;

&lt;h2 id=&#34;demo&#34;&gt;Demo&lt;/h2&gt;

&lt;p&gt;可以在当前的活动 Span 中这样设置 Baggage：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tracer.activeSpan().setBaggageItem(&amp;quot;user-agent&amp;quot;, userAgent);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这必须在第一个服务中完成。最后一个需要完成的任务就是定义一个识别 Baggage Header 的路由。下面的路由定义会查看请求是否包含了带有 &lt;code&gt;user-agent:Safari&lt;/code&gt; 条目的 Baggage，如果有，就进行转发：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: recommendation-safari
spec:
  destination:
    namespace: tutorial
    name: recommendation
  precedence: 2
  match:
    request:
      headers:
        baggage-user-agent:
          regex: &amp;quot;.*Safari.*&amp;quot;  
  route:
  - labels:
      version: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果是新版本的 Istio（0.8.0 以后）：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: recommendation-safari
spec:
  hosts:
  - recommendation
  http:
  - match:
    - headers:
        baggage-user-agent:
          regex: &amp;quot;.*Safari.*&amp;quot;
    route:
     - destination:
        host: recommendation
        subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: recommendation-destination
spec:
  host: recommendation
  subsets:
  - name: v2
    labels:
      version: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在所有的配置都已经完成，Safari 用户会被重定向到推荐的 v2 服务。&lt;/p&gt;

&lt;p&gt;下面的视频进行了使用 OpenTracing Baggage 进行路由的演示，参见 &lt;a href=&#34;https://github.com/redhat-developer-demos/istio-tutorial&#34; target=&#34;_blank&#34;&gt;Redhat 的 Istio Tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://youtu.be/sEbs3zkUnK8&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;images/yout.png&#34; alt=&#34;video&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;相关链接&#34;&gt;相关链接&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://opentracing.io/&#34; target=&#34;_blank&#34;&gt;OpenTracing&lt;/a&gt;：&lt;code&gt;http://opentracing.io/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item&#34; target=&#34;_blank&#34;&gt;OpenTracing baggage 规范&lt;/a&gt;：&lt;code&gt;https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jaegertracing/jaeger/issues/755#issuecomment-393929718&#34; target=&#34;_blank&#34;&gt;Jaeger 客户端的 B3 Baggage 支持&lt;/a&gt;：&lt;code&gt;https://github.com/jaegertracing/jaeger/issues/755#issuecomment-393929718&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/redhat-developer-demos/istio-tutorial&#34; target=&#34;_blank&#34;&gt;OpenShift 的 Istio 教程&lt;/a&gt;：&lt;code&gt;https://github.com/redhat-developer-demos/istio-tutorial&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kiali.org/&#34; target=&#34;_blank&#34;&gt;Kiali&lt;/a&gt;: &lt;code&gt;https://kiali.org/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Service Mesh 安全：用 Istio 应对攻击</title>
      <link>/post/service-mesh-security-addressing-attack-vectors-with-istio/</link>
      <pubDate>Thu, 07 Jun 2018 10:10:21 +0800</pubDate>
      <guid>/post/service-mesh-security-addressing-attack-vectors-with-istio/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://aspenmesh.io/2018/06/service-mesh-security-addressing-attack-vectors-with-istio/&#34; target=&#34;_blank&#34;&gt;Service Mesh Security: Addressing Attack Vectors with Istio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者： &lt;strong&gt;Zach Jory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;把单体应用拆分为微服务之后，会得到不少好处，例如稳定性的提高、持续运行时间的增长以及更好的故障隔离等。然而把大应用拆分为小服务的过程中，也会引入一个风险就是——可能的受攻击面积变大了。从前单体应用中通过函数调用完成的通信，现在都要通过网络完成。提高安全性从而避免这个问题带来的安全影响，是微服务之路上必须要着重考虑的问题。&lt;/p&gt;

&lt;p&gt;Aspen Mesh 的基础是一个开源软件：&lt;a href=&#34;https://istio.io/&#34; target=&#34;_blank&#34;&gt;Istio&lt;/a&gt;，他的关键能力之一就是为微服务提供安全性和策略控制方面的支持。Istio 为 Service Mesh 增加了很多安全特性，但是这并不是说微服务的安全工作就结束了。网络安全策略也是需要着重考虑的问题（推荐阅读：&lt;a href=&#34;https://medium.com/lightspeed-venture-partners/in-the-land-of-microservices-the-network-is-the-king-maker-37de7ec4119a&#34; target=&#34;_blank&#34;&gt;In the land of microservices, the network is the king(maker)&lt;/a&gt;），结合网络策略，可以检测和应对针对服务网格基础设施的攻击，从而解决各种安全威胁。&lt;/p&gt;

&lt;p&gt;后面的内容将会看看 Istio 所能够解决的问题，其中包含边缘通信的流量控制、网格内通信加密以及 7 层策略控制等。&lt;/p&gt;

&lt;h2 id=&#34;边缘通信安全&#34;&gt;边缘通信安全&lt;/h2&gt;

&lt;p&gt;针对不当进入网格的流量，Istio 加入了一个用来进行监控和防范的安全层。Istio 以 Ingress Controller 的形式和 Kubernetes 进行了集成，并完成了 Ingress 的负载均衡任务。用户可以用 Ingress Rule 的方式加入安全控制。可以通过监控来了解进入网格的流量，并通过路由规则来管理非法的边缘通信。&lt;/p&gt;

&lt;p&gt;要保证只有认证用户通过，Istio 的 RBAC（基于角色的访问控制）提供了有弹性的、可定制的访问控制，这种能力在网格内提供了 namespace、service 以及服务方法一级的控制能力。RBAC 引擎监控和跟进 RBAC 策略的变更，在运行时根据 RBAC 策略，根据请求的上下文对请求进行鉴权，最后返回鉴权结果。&lt;/p&gt;

&lt;h2 id=&#34;通信加密&#34;&gt;通信加密&lt;/h2&gt;

&lt;p&gt;边缘通信的安全是个好的开始，但是如果有恶意份子突破了边缘之后，Istio 还为服务之间的通信提供了双向 TLS 认证能力。网格能够对请求和响应进行自动的加密和解密，开发人员就无需在此投入精力了。这个功能还通过对连接的优先复用，减少了连接过程中的运算消耗。&lt;/p&gt;

&lt;p&gt;除了客户端和服务器之间的认证和鉴权能力之外，还让用户能够理解和管理服务间的通信和加密。Istio 把证书和密钥自动分发给服务，代理使用这些输入来给流量进行加密（提供双向 TLS），并周期性的进行证书轮转，从而降低证书暴露造成的威胁。可以利用 TLS 来确认 Istio 中的通信双方的服务实例都是合法的，从而防止中间人攻击。&lt;/p&gt;

&lt;p&gt;Istio 使用 Citadel 来进行密钥管理和认证控制，简化了 TLS 过程。他让用户能够保护流量，同时给每个服务提供基于身份的验证和授权功能。&lt;/p&gt;

&lt;h2 id=&#34;策略控制和执行&#34;&gt;策略控制和执行&lt;/h2&gt;

&lt;p&gt;Istio 给用户在应用级执行策略的能力。对于服务路由、重试、断路以及安全来说，在这一层进行控制是非常恰当的。Istio 为用户提供了黑白名单功能来来对服务进行准入的控制。&lt;/p&gt;

&lt;p&gt;Istio Mixer 可以把扩展集成进系统，用户用标准化的表达式语言来来声明网络以及服务行为方面的约束策略。这样做的好处是，可以用通用 API 在服务边缘来缓存策略的决策结果，如果下游的策略系统出现故障，网络还能保持运行。&lt;/p&gt;

&lt;p&gt;Istio 解决了一些微服务特定的关键问题。例如只允许被批准的服务间通信，加密通信防止通信过程中的入侵，执行应用范围内的策略等。当然还有很多其他方式可以实现这些能力，Mesh 的好处在于将这些能力融会贯通，让用户使用一致的稳定的方式来完成这些任务。&lt;/p&gt;

&lt;p&gt;Aspen Mesh 中正在做一些新的功能，在 Istio 中为用户提供更好的安全能力。近期我们会在博客上发点东西，所以请关注 &lt;a href=&#34;https://aspenmesh.io/blog/&#34; target=&#34;_blank&#34;&gt;Aspen Mesh 博客&lt;/a&gt;。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 0.8 的 Helm Chart 解析</title>
      <link>/post/istio-0.8.0-helm/</link>
      <pubDate>Mon, 04 Jun 2018 09:39:10 +0800</pubDate>
      <guid>/post/istio-0.8.0-helm/</guid>
      <description>

&lt;p&gt;儿童节期间，拖拉了一个多月的 Istio 0.8 正式发布了，这可能是 Istio 1.0 之前的最后一个 LTS 版本，意义重大。&lt;/p&gt;

&lt;p&gt;新版本中，原来的 Kubernetes 安装文件 &lt;code&gt;install/kubernetes/istio.yaml&lt;/code&gt;，变成了 &lt;code&gt;install/kubernetes/istio-demo.yaml&lt;/code&gt;，是的，你没看错，这个 LTS 的安装文件名字叫 demo。查看了一下文档，大概察觉到不靠谱的 Istio 发布组的意图了：这个项目的组件相对比较复杂，原有的一些选项是靠 ConfigMap 以及 istioctl 分别调整的，现在通过重新设计的 Helm Chart，安装选项用 values.yml 或者 helm 命令行的方式来进行集中管理了。下面就由看看 Istio 的 Helm Chart 的安装部署及其结构。&lt;/p&gt;

&lt;h2 id=&#34;使用-helm-安装-istio&#34;&gt;使用 Helm 安装 Istio&lt;/h2&gt;

&lt;p&gt;安装包内的 Helm 目录中包含了 Istio 的 Chart，官方提供了两种方法：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;用 Helm 生成 istio.yaml，然后自行安装。&lt;/li&gt;
&lt;li&gt;用 Tiller 直接安装。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;很明显，两种方法并没有什么本质区别。例如第一个命令：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;helm template install/kubernetes/helm/istio \
    --name istio --namespace  \
    istio-system &amp;gt; $HOME/istio.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里说的是使用 &lt;code&gt;install/kubernetes/helm/istio&lt;/code&gt; 目录中的 Chart 进行渲染，生成的内容保存到 &lt;code&gt;$HOME/istio.yaml&lt;/code&gt; 文件之中。而第二个命令&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;helm template install/kubernetes/helm/istio \
    --name istio --namespace istio-system \
    --set sidecarInjectorWebhook.enabled=false &amp;gt; $HOME/istio.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;只是设置了 Chart 中的一个变量 &lt;code&gt;sidecarInjectorWebhook.enabled&lt;/code&gt; 为 False。从而禁止自动注入属性生效。&lt;/p&gt;

&lt;p&gt;我们照猫画虎，看看命令二的结果提交到 Kubernetes 中会发生什么事情。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;helm template install/kubernetes/helm/istio --name istio \
--namespace istio-system --set sidecarInjectorWebhook.enabled=false &amp;gt; $HOME/istio.yaml

kubectl create namespace istio-system
kubectl create -f $HOME/istio.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;根据不同的网络情况，可能需要几分钟的等待，最后会看到这些 Pod 在运行：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;istio-citadel-ff5696f6f-h4rdz
istio-cleanup-old-ca-rp5p6
istio-egressgateway-58d98d898c-5jnpz
istio-ingress-6fb78f687f-wsl5q
istio-ingressgateway-6bc7c7c4bc-hhrh7
istio-mixer-post-install-d2kl5
istio-pilot-6c5c6b586c-dqv2w
istio-policy-5c7fbb4b9f-xmv6f
istio-statsd-prom-bridge-6dbb7dcc7f-27tx7
istio-telemetry-54b5bf4847-9gpr7
prometheus-586d95b8d9-gb846
&lt;/code&gt;&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;过去的 istio-ca 现已更名 istio-citadel。&lt;/li&gt;
&lt;li&gt;istio-cleanup-old-ca 是一个 job，用于清理过去的 Istio 遗留下来的 CA 部署（包括 sa、deploy 以及 svc 三个对象）。&lt;/li&gt;
&lt;li&gt;istio-mixer-post-install 同样也是一个 job，和上面的 Job 一样，简单的调用 kubectl 创建第三方资源，从而避免了之前的 CDR 需要重复创建的尴尬状况。&lt;/li&gt;
&lt;li&gt;egressgateway、ingress 以及 ingressgateway，可以看出边缘部分的变动很大，以后会另行发文。&lt;/li&gt;
&lt;li&gt;和从前不同，缺省已经打开了监控界面。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;helm-chart-的安装配置&#34;&gt;Helm Chart 的安装配置&lt;/h3&gt;

&lt;p&gt;下面的配置项目，都可以使用 helm 的 &lt;code&gt;--set key=value&lt;/code&gt; 来设置，可以重复使用，用来设置多个值。&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;选项&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;缺省值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;global.hub&lt;/td&gt;
&lt;td&gt;绝大部分镜像所在的镜像库地址&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker.io/istionightly&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.tag&lt;/td&gt;
&lt;td&gt;Istio 使用的绝大部分镜像的 Tag&lt;/td&gt;
&lt;td&gt;&lt;code&gt;circleci-nightly&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.proxy.image&lt;/td&gt;
&lt;td&gt;指定 Proxy 的镜像名称&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proxyv2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.imagePullPolicy&lt;/td&gt;
&lt;td&gt;镜像拉取策略&lt;/td&gt;
&lt;td&gt;&lt;code&gt;IfNotPresent&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.controlPlaneSecurityEnabled&lt;/td&gt;
&lt;td&gt;控制面是否启动 mTLS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.mtls.enabled&lt;/td&gt;
&lt;td&gt;服务间是否缺省启用 mTLS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.mtls.mtlsExcludedServices&lt;/td&gt;
&lt;td&gt;禁用 mTLS 的 FQDN 列表&lt;/td&gt;
&lt;td&gt;&lt;code&gt;- kubernetes.default.svc.cluster.local&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.rbacEnabled&lt;/td&gt;
&lt;td&gt;是否创建 RBAC 规则&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.refreshInterval&lt;/td&gt;
&lt;td&gt;Mesh 发现间隔&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10s&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.arch.amd64&lt;/td&gt;
&lt;td&gt;amd64 架构中的调度策略，0：never；1: least preferred；2：no preference；3：most preferred&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.arch.s390x&lt;/td&gt;
&lt;td&gt;amd64 架构中的调度策略，0：never；1: least preferred；2：no preference；3：most preferred&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;global.arch.ppc64le&lt;/td&gt;
&lt;td&gt;amd64 架构中的调度策略，0：never；1: least preferred；2：no preference；3：most preferred&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;galley.enabled&lt;/td&gt;
&lt;td&gt;是否安装 Galley 用于进行服务端的配置验证，需要 1.9 版本以上的 Kubernetes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;上面的内容来自&lt;a href=&#34;https://istio.io/docs/setup/kubernetes/helm-install/&#34; target=&#34;_blank&#34;&gt;官方文档&lt;/a&gt;，其实这是不符合实际情况的（Istio 用户的日常）。在 &lt;code&gt;install/kubernetes/helm/istio/values.yaml&lt;/code&gt; 中，包含这一发行版本中的所有的缺省值。可以直接修改或者新建 values.yaml，并在 helm 命令行使用 &lt;code&gt;-f my-values.yaml&lt;/code&gt; 参数来生成自行定制的 &lt;code&gt;istio.yaml&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;解读-istio-helm-chart-中的模块&#34;&gt;解读 Istio Helm Chart 中的模块&lt;/h2&gt;

&lt;p&gt;打开 Istio 的 Chart 之后，发现其中并没有任何组件的内容，只有两个 Configmap 对象的模板。其安装主体再次很非主流的通过依赖 Chart 的方式实现了完全的模块化。因此这个 Chart 的主体，实际上是 &lt;code&gt;requirements.yaml&lt;/code&gt;，打开这个文件，会看到规规矩矩的列出很多模块，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  - name: sidecarInjectorWebhook
    version: 0.8.0
    # repository: file://../sidecarInjectorWebhook
    condition: sidecarInjectorWebhook.enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这表明在 &lt;code&gt;sidecarInjectorWebhook&lt;/code&gt; 取值为 &lt;code&gt;enabled&lt;/code&gt; 的时候，就渲染这一模板。因此这里可以看做是模块的启用停用的控制点。这里列出的模块包括：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模块&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;egressgateway&lt;/td&gt;
&lt;td&gt;外发流量网关&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;galley&lt;/td&gt;
&lt;td&gt;在 K8S 服务端验证 Istio 的 CRD 资源的合法性&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;grafana&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;ingress&lt;/td&gt;
&lt;td&gt;Ingress Controller&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;ingressgateway&lt;/td&gt;
&lt;td&gt;Ingress Gateway&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;mixer&lt;/td&gt;
&lt;td&gt;Mixer&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;pilot&lt;/td&gt;
&lt;td&gt;Pilot&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;prometheus&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;security&lt;/td&gt;
&lt;td&gt;安全相关内容&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;servicegraph&lt;/td&gt;
&lt;td&gt;调用关系图&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;sidecarInjectorWebhook&lt;/td&gt;
&lt;td&gt;自动注入&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;tracing&lt;/td&gt;
&lt;td&gt;Zipkin Jeager 的跟踪服务&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;下面逐一做一下简要说明&lt;/p&gt;

&lt;h3 id=&#34;egressgateway&#34;&gt;egressgateway&lt;/h3&gt;

&lt;p&gt;外发通信的网关。&lt;/p&gt;

&lt;p&gt;他的设置保存在 &lt;code&gt;values.yaml&lt;/code&gt; 的 &lt;code&gt;egressgateway&lt;/code&gt; 一节中（都是保存在同名分支下，后面不再重复）。部署内容包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment 和 Service：一个 proxy。&lt;/li&gt;
&lt;li&gt;HPA&lt;/li&gt;
&lt;li&gt;RBAC 相关内容&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;可定制项目包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;服务端口和类型&lt;/li&gt;
&lt;li&gt;HPA 实例数量上下限&lt;/li&gt;
&lt;li&gt;资源限制&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;galley&#34;&gt;galley&lt;/h3&gt;

&lt;p&gt;之前的 istio 版本中，只能通过 istioctl 验证 Istio 相关 CRD 的有效性，这个模块提供一个在服务端验证 CRD 的方法，他的部署内容包含：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployement 和 Service。&lt;/li&gt;
&lt;li&gt;RBAC 相关&lt;/li&gt;
&lt;li&gt;用于 CRD 校验的 ValidatingWebhookConfiguration 对象。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;校验目标包含 Pilot（例如 destinationpolicies 和 routerules） 和 Mixer（例如 memquotas 和 prometheuses） 两类 CRD。&lt;/p&gt;

&lt;h3 id=&#34;grafana&#34;&gt;grafana&lt;/h3&gt;

&lt;p&gt;一个带有 Istio 定制 Dashboard 的 Grafana 封装。&lt;/p&gt;

&lt;p&gt;实际上将其镜像中的 Dashboard 复制出来就可以在其他 Grafana 实例上运行了。&lt;/p&gt;

&lt;p&gt;定制内容的 &lt;code&gt;grafana.ingress.*&lt;/code&gt; 中包含 Ingress 的配置，用于外网访问。&lt;/p&gt;

&lt;h3 id=&#34;ingress&#34;&gt;ingress&lt;/h3&gt;

&lt;p&gt;Istio 的 Ingress Controller&lt;/p&gt;

&lt;p&gt;具体部署内容和 egresscontroller 基本一致。&lt;/p&gt;

&lt;h3 id=&#34;ingressgateway&#34;&gt;ingressgateway&lt;/h3&gt;

&lt;p&gt;0.8.0 新增功能，为 Ingress 通信提供 Istio rules/destination 等特性。&lt;/p&gt;

&lt;p&gt;部署内容和 ingress 类似。&lt;/p&gt;

&lt;h3 id=&#34;mixer&#34;&gt;mixer&lt;/h3&gt;

&lt;p&gt;Mixer 负责的是遥测和前置检查，他的 Chart 相对比较复杂，部署内容包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;和前面的版本不同，Mixer 的部署分成了两个部分，分别是 Policy 和 Telemetry 两个 Deployment 对象。&lt;/li&gt;
&lt;li&gt;Service 也同样分成两个，其中 telemetry service 多了一个 prometheus 端口&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crds.yaml&lt;/code&gt; 中包含了 mixer 所支持的所有 crd 定义（例如 memquotas 和 prometheuses）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create-custom-resources-job.yaml&lt;/code&gt; 中包含了用于创建 crd 的 Job 对象。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;pilot&#34;&gt;pilot&lt;/h3&gt;

&lt;p&gt;Pilot 承上启下，负责服务发现和向 Proxy 下发配置。除了常规的 Deployment 和 Service 之外，还包含了 &lt;code&gt;crds.yaml&lt;/code&gt;，用于声明 CRD 资源类型（例如 destinationpolicies 和 routerules）。&lt;/p&gt;

&lt;h3 id=&#34;prometheus&#34;&gt;prometheus&lt;/h3&gt;

&lt;p&gt;这个组件跟前面的 Grafana 类似，也是一个预定义的镜像。这个模板中的 Configmap 就是 Prometheus 的抓取配置，可以直接用到其他的 Prometheus 实例之中。&lt;/p&gt;

&lt;h3 id=&#34;security&#34;&gt;security&lt;/h3&gt;

&lt;p&gt;旧版本中的 Istio-ca&lt;/p&gt;

&lt;p&gt;Security 部分的部署内容包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RBAC&lt;/li&gt;
&lt;li&gt;Job：使用 kubectl 清理旧版本 istio-ca 实例。&lt;/li&gt;
&lt;li&gt;Deployment，原 CA。&lt;/li&gt;
&lt;li&gt;Service：开放两个端口，分别服务于 http 和 gRPC。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;servicegraph&#34;&gt;servicegraph&lt;/h3&gt;

&lt;p&gt;Service Graph 支持，和 Grafana 基本一致。&lt;/p&gt;

&lt;h3 id=&#34;sidecarinjectorwebhook&#34;&gt;sidecarInjectorWebhook&lt;/h3&gt;

&lt;p&gt;这一部分的功能是自动为 K8S 对象注入 Envoy。主要包含：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment 和 Service&lt;/li&gt;
&lt;li&gt;RBAC 相关&lt;/li&gt;
&lt;li&gt;一个 &lt;code&gt;MutatingWebhookConfiguration&lt;/code&gt; 对象，会监听 Pod 的创建事件，用于自动注入。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;tracing&#34;&gt;tracing&lt;/h3&gt;

&lt;p&gt;Jeager 的跟踪支持，总体情况跟 Prometheus 和 Grafana 等监控组件类似，配置项和暴露服务方面稍有区别：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;配置中包含 Jaeger 的环境变量的控制。&lt;/li&gt;
&lt;li&gt;开启 jaeger 开关，会启用 Jaeger 的几个服务端口。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Istio 0.8：橘色警告</title>
      <link>/post/istio-0.8-code-orange/</link>
      <pubDate>Mon, 21 May 2018 18:11:04 +0800</pubDate>
      <guid>/post/istio-0.8-code-orange/</guid>
      <description>

&lt;p&gt;原文地址：&lt;a href=&#34;https://docs.google.com/document/d/1QQGR6ripB53Qv8v_fjfNd3R_5hOOEZRmTvVt0KqgBr4/edit#&#34; target=&#34;_blank&#34;&gt;Google Doc&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;

&lt;p&gt;2017 年 9 月发布 0.2 之后，我们再没有一个稳定的版本了。之前我们认为 0.7 可以作为 LTS 版本，然而他不够成熟，所以我们把希望放在了 0.8 的头上。我们过去计划在 4 月中旬发布 0.8 版本。然而直到今天（4 月 27 日），我们还是有很多的关键 BUG 需要解决，看起来这个月内是无法完成了。&lt;/p&gt;

&lt;p&gt;简单说，我们不仅无法发布 LTS 版本，甚至连月度版本都无法按时发布。因此，Istio 项目进入橘色状态（根据 &lt;a href=&#34;https://github.com/istio/istio/tree/master/release#code-orange&#34; target=&#34;_blank&#34;&gt;release process&lt;/a&gt; 定义）。&lt;/p&gt;

&lt;p&gt;根据上面的发布过程定义：Release 的稳定是 Istio 开发者的首要任务，&amp;hellip; 可以声明代码冻结，组织 SWAT 团队协助发布过程进入正轨。”。我们需要 TOC 的帮助来实现上述操作。&lt;/p&gt;

&lt;h2 id=&#34;问题&#34;&gt;问题&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;我们不知道我们的无知在哪里。最大最亟待解决的问题就是，我们要需要知道到底要解决什么问题。虽然经过多次沟通，构成发布障碍的 Issue 仍然没有被正确的识别和标记。这个问题在之前的 0.7 发布的时候已经发作过，现在影响到了 0.8。&lt;/li&gt;
&lt;li&gt;我们没有清楚的人员来定义发布障碍。因此就很难对现状进行评估，解决时间也就无从预测。我们需要给每个条目确定责任人。&lt;/li&gt;
&lt;li&gt;我们本来想 3 月份发布 LTS 版本，后来延迟到四月中旬，现在，我们计划是五月的某个时间。这成了一个移动目标，并且我们还是没有一个明确的评估。

&lt;ul&gt;
&lt;li&gt;多数团队都准备参加下周的 Kubecon，这很明显会影响生产力。&lt;/li&gt;
&lt;li&gt;目前为止，还有一些优秀劳动力投放在和发布障碍无关的工作上。&lt;/li&gt;
&lt;li&gt;计划了对 0.8 RC 的测试工作，但是我们还没有可用的 RC。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;发布分支访问量很低，有些很明显是 0.8 相关的内容，只被合并到了 Master 分支。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;计划&#34;&gt;计划&lt;/h2&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action Items&lt;/th&gt;
&lt;th&gt;Owner&lt;/th&gt;
&lt;th&gt;状态&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;联系所有工作组长，确认全部的 0.8 障碍被正确的识别、标记、跟踪和分配&lt;/td&gt;
&lt;td&gt;Andy 和各组长&lt;/td&gt;
&lt;td&gt;邮件已经发送&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;短期锁定 Master 分支，确认多数开发者都能正确的向 Release 分支合并，只有 TOC 成员批准才允许向 Master 进行合并&lt;/td&gt;
&lt;td&gt;Shriram&lt;/td&gt;
&lt;td&gt;Done&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;比对 0.8 和 Master，如果多数变更是针对 0.8 的，那么就撤回 1.0 的专属 PR，然后从 master rebase 或者 rebranch 0.8&lt;/td&gt;
&lt;td&gt;Sven、Andy 和 Costin&lt;/td&gt;
&lt;td&gt;Done: Rebase 所有发布分支。&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;所有障碍问题的责任人需要尽快解决手上的问题&lt;/td&gt;
&lt;td&gt;Issue owners&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;计划一个 30 分钟以内的日常站会，来跟踪障碍问题的进度，以此计划发布日期。 1. 从 4 月 30 日起，到 0.8.0 发布为止。 2. 所有未解决问题的责任人必须提供更新信息。如果任何 issue 有产生障碍的可能，Andy 和 Jasmine 有权增加开发者进行协助，以加快进度。所有其他工作的优先级都需要降低，直到橘色警告解除&lt;/td&gt;
&lt;td&gt;每周一三五 11 点的会议&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Istio oncall 监视发布分支的状态，并且修复和分析可能解决的任何问题，发布分支的问题是最高优先的问题，一旦发现发布障碍，必须加入 &lt;a href=&#34;https://docs.google.com/spreadsheets/d/1KquD8HJLlg-IwGYuF6O8AqJMpJPWLHjA-VEY24Eu8b8/edit#gid=0&#34; target=&#34;_blank&#34;&gt;0.8 障碍 Issue 列表&lt;/a&gt;。&lt;/td&gt;
&lt;td&gt;Oncall&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;一旦有 RC 可用（例如第一阶段的问题已解决之后发布的下一个 Build），应该尽快启动社区测试。一旦发现发布障碍，应该加入 &lt;a href=&#34;https://docs.google.com/spreadsheets/d/1KquD8HJLlg-IwGYuF6O8AqJMpJPWLHjA-VEY24Eu8b8/edit#gid=0&#34; target=&#34;_blank&#34;&gt;0.8 障碍 Issue 列表&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Jasmine&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;0.8 稳定之后，把所有 Commit 合并回 Master&lt;/td&gt;
&lt;td&gt;Andy&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;和所有开发者沟通这一计划&lt;/td&gt;
&lt;td&gt;Sven&lt;/td&gt;
&lt;td&gt;Done&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;0.8 发布之后，启动一个事后会，来改进未来的发布过程。&lt;/td&gt;
&lt;td&gt;Andy, Jasmine, TOC&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
    </item>
    
    <item>
      <title>Mixer 的 SPOF 迷思</title>
      <link>/post/spof-in-mixer/</link>
      <pubDate>Fri, 20 Apr 2018 20:11:36 +0800</pubDate>
      <guid>/post/spof-in-mixer/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://istio.io/blog/2017/mixer-spof-myth.html&#34; target=&#34;_blank&#34;&gt;Mixer and the SPOF Myth&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SPOF: Single Point of Failure
我理解 Istio 想要表达的的意思：
1. Mixer 很稳定
2. 你们说的延迟不是我说的延迟&lt;/p&gt;

&lt;p&gt;低延迟，高可用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作者：Martin Taillefer&lt;/p&gt;

&lt;p&gt;原文地址：&lt;a href=&#34;https://istio.io/blog/2017/mixer-spof-myth.html&#34; target=&#34;_blank&#34;&gt;https://istio.io/blog/2017/mixer-spof-myth.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mixer 出现在请求路径上，很自然的会引发一个疑问：他对系统可用性和延迟会产生什么样的影响？第一次看到 Istio 架构图时，人们最常见的问题就是：“这不就是一个单点失败的典型案例么？”&lt;/p&gt;

&lt;p&gt;本文中我们会深入挖掘和阐述 Mixer 的设计原则，在这些设计原则的支持下 Mixer 能够令人惊奇的提高 Mesh 内的系统可用性，降低平均请求延时。&lt;/p&gt;

&lt;p&gt;Istio 的 Mixer 对系统总体可用性和延迟有两个主要的好处：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;提高 SLO&lt;/strong&gt;：Mixer 把 Proxy 和服务从基础设施后端的故障中隔离出来，提供了高级、高效的 Mesh 可用性保障。Mesh 作为一个整体来说，在同基础设施后端的交互中，有了 Mixer 的帮助，会有更低的故障率。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;降低延迟&lt;/strong&gt;：通过对各个层次的分片缓存的积极使用和共享，Mixer 能够降低平均延迟。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接下来会对上面的内容进行一下解释。&lt;/p&gt;

&lt;h2 id=&#34;istio-是怎么来的&#34;&gt;Istio 是怎么来的&lt;/h2&gt;

&lt;p&gt;Google 在多年中都在使用一个内部的 API 和服务管理系统，用于处理 Google 提供的众多 API。这一系统支持了最大的服务群（Google Maps，YouTube 以及 Gmail 等），承受上百万 QPS 峰值的冲击。这套系统运行的虽然很好，但是仍然无法跟上 Google 快速增长的脚步，很显然，要有新的架构来降低飞涨的运维成本。&lt;/p&gt;

&lt;p&gt;2014 年，我们开始了一个草案，准备替换这一系统，进行更好的伸缩。这一决定最后证明是非常正确的，在 Google 进行整体部署之后，每月降低了上百万美元的运维成本。&lt;/p&gt;

&lt;p&gt;过去，流量在进入具体的服务之前，首先会进入一个较重的代理，旧系统就是以这个代理为中心构建的。新的架构摒弃了共享代理的设计，取而代之以轻量高效的 sidecar 代理，这一代理和服务实例并行，共享一个控制平面。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/mixer-spof-myth-1.svg&#34; alt=&#34;Google 的 API 和 服务管理系统
&#34; /&gt;&lt;/p&gt;

&lt;p&gt;看起来很面熟吧？是的，跟 Istio 很像。Istio 就是作为这一分布式代理架构的继任者进行构思的。我们从内部系统中获取了核心的灵感，在同合作伙伴的协同工作中产生了很多概念，这些导致了 Istio 的诞生。&lt;/p&gt;

&lt;h2 id=&#34;架构总结&#34;&gt;架构总结&lt;/h2&gt;

&lt;p&gt;下图中，Mixer 在 Mesh 和基础设施之间：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;img/mixer-spof-myth-2.svg&#34; alt=&#34;Istio 拓扑&#34; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;首层 sidercar 级别的缓存
第二层，共享缓存&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;逻辑上，Envoy sidecar 会在每次请求之前调用 Mixer，进行前置检查，每次请求之后又要进行指标报告。Sidecar 中包含本地缓存，一大部分的前置检查可以通过缓存来进行。另外，sidercar 会把待发送的指标数据进行缓冲，这样可能在几千次请求之后才调用一次 Mixer。前置检查和请求处理是同步的，指标数据上送是使用 fire-and-forget 模式异步完成的。&lt;/p&gt;

&lt;p&gt;抽象一点说，Mixer 提供：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;后端抽象&lt;/strong&gt;：Mixer 把 Istio 组件和 Mesh 中的服务从基础设施细节中隔离开来。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;中间人&lt;/strong&gt;：Mixer 让运维人员能够对所有 Mesh 和基础设施后端之间的交互进行控制。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;除了这些纯功能方面，Mixer 还有一些其他特点，为系统提供更多益处。&lt;/p&gt;

&lt;h3 id=&#34;mixer-slo-助推器&#34;&gt;Mixer：SLO 助推器&lt;/h3&gt;

&lt;p&gt;有人说 Mixer 是一个 SPOF，会导致 Mesh 的崩溃，而我们认为 Mixer 增加了 Mesh 的可用性。这是如何做到的？下面是三个理由：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;无状态&lt;/strong&gt;：Mixer 没有状态，他不管理任何自己的持久存储。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;稳固&lt;/strong&gt;：Mixer 是一个高可靠性的组件，设计要求所有 Mixer 实例都要有超过 99.999% 的可靠性。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;缓存和缓冲&lt;/strong&gt;：Mixer 能够积累大量的短期状态数据。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sidecar 代理伴随每个服务实例而运行，必须节约使用内存，这样就限制了本地缓存和缓冲的数量。但是 Mixer 是独立运行的，能使用更大的缓存和缓冲。因此 Mixer 为 Sidecar 提供了高伸缩性高可用的二级缓存服务。&lt;/p&gt;

&lt;p&gt;Mixer 的预期可用性明显高于多数后端（多数是 99.9%）。他的本地缓存和缓冲区能够在后端无法响应的时候继续运行，因此有助于对基础设施故障的屏蔽，降低影响。&lt;/p&gt;

&lt;h3 id=&#34;mixer-延迟削减者&#34;&gt;Mixer：延迟削减者&lt;/h3&gt;

&lt;p&gt;上面我们解释过，Istio sidecar 具备有效的一级缓存，在为流量服务的时候多数时间都可以使用缓存来完成。Mixer 提供了更大的共享池作为二级缓存，这也帮助了 Mixer 降低平均请求的延迟。&lt;/p&gt;

&lt;p&gt;不只是降低延迟，Mixer 还降低了 Mesh 到底层的请求数量，这样就能显著降低到基础设施后端的 QPS，如果你要付款给这些后端，那么这一优点就会节省更多成本。&lt;/p&gt;

&lt;h2 id=&#34;下一步&#34;&gt;下一步&lt;/h2&gt;

&lt;p&gt;我们还有机会对系统做出更多改进。&lt;/p&gt;

&lt;h3 id=&#34;以金丝雀部署的方式进行配置发布&#34;&gt;以金丝雀部署的方式进行配置发布&lt;/h3&gt;

&lt;p&gt;Mixer 具备高度的伸缩性，所以他通常不会故障。然而如果部署了错误的配置，还是会引发 Mixer 进程的崩溃。为了防止这种情况的出现，可以用金丝雀部署的方式来发布配置，首先为一小部分 Mixer 进行部署，然后扩大部署范围。&lt;/p&gt;

&lt;p&gt;目前的 Mixer 并未具备这样的能力，我们期待这一功能成为 Istio 可靠性配置工作的一部分最终得以发布。&lt;/p&gt;

&lt;h3 id=&#34;缓存调节&#34;&gt;缓存调节&lt;/h3&gt;

&lt;p&gt;我们的 Sidecar 和 Mixer 缓存还需要更好的调整，这部分的工作会着眼于资源消耗的降低和性能的提高。&lt;/p&gt;

&lt;h3 id=&#34;缓存共享&#34;&gt;缓存共享&lt;/h3&gt;

&lt;p&gt;现在 Mixer 的实例之间是各自独立的。一个请求在被某个 Mixer 实例处理之后，并不会把过程中产生的缓存传递给其他 Mixer 实例。我们最终会试验使用 Memcached 或者 Redis 这样的分布式缓存，以期提供一个 Mesh 范围内的共享缓存，更好的降低对后端基础设施的调用频率。&lt;/p&gt;

&lt;h3 id=&#34;分片&#34;&gt;分片&lt;/h3&gt;

&lt;p&gt;在大规模的 Mesh 中，Mixer 的负载可能很重。我们可以使用大量的 Mixer 实例，每个实例都为各自承担的流量维护各自的缓存。我们希望引入智能分片能力，这样 Mixer 实例就能针对特定的数据流提供特定的服务，从而提高缓存命中率；换句话说，分片可以利用把相似的流量分配给同一个 Mixer 实例的方式来提高缓存效率，而不是把请求交给随机选择出来的 Mixer 实例进行处理。&lt;/p&gt;

&lt;h2 id=&#34;结语&#34;&gt;结语&lt;/h2&gt;

&lt;p&gt;Google 的实际经验展示了轻代理、大缓存控制平面结合的好处：提供更好的可用性和延迟。过去的经验帮助 Istio 构建了更精确更有效的缓存、预抓取以及缓冲策略等功能。我们还优化了通讯协议，用于降低缓存无法命中的时候，对形同产生的影响。&lt;/p&gt;

&lt;p&gt;Mixer 还很年轻。在 Istio 0.3 中，Mixer 并没有性能方面的重要改进。这意味着如果一个请求没有被 Sidecar 缓存命中，Mixer 就会花费更多时间。未来的几个月中我们会做很多工作来优化同步的前置检查过程中的这种情况。&lt;/p&gt;

&lt;p&gt;我们希望本文能够让读者能够意识到 Mixer 对 Istio 的益处。&lt;/p&gt;

&lt;p&gt;可以在论坛发表意见或问题：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://groups.google.com/forum/#!forum/istio-integrations&lt;/code&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 限流的正确姿势</title>
      <link>/post/istio-rate-limit-upgraded/</link>
      <pubDate>Wed, 18 Apr 2018 05:47:27 +0800</pubDate>
      <guid>/post/istio-rate-limit-upgraded/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;这一部分的官方文档很落后，这一例子主要内容来自于我们团队，在各位大师的工作基础上，结合 Mixer 的一些相关内容，参考Bookinfo 中附带的新版本源代码，拼凑而成。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Istio 的限流功能和路由不同，关系到 Istio 的 &lt;a href=&#34;http://blog.fleeto.us/translation/mixer-adapter-model&#34; target=&#34;_blank&#34;&gt;Mixer 适配器模型&lt;/a&gt;，因此这里从这一模型的角度来进行限流方面的测试。&lt;/p&gt;

&lt;h2 id=&#34;handler&#34;&gt;Handler&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Mixer 使用的每个适配器都需要一些配置来进行操作。一般来说适配器需要一些内容，例如后端的 URL、认证信息、缓存选项等等。每个适配器使用一个 protobuf 消息来定义所需的配置数据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这里使用的是 memquota Handler，memquota 是绑定在 Mixer 进程上的，没有持久化，无 HA 能力，因此并不适合生产使用；建议今后改用 redisquota（目前暂不可用）。&lt;/p&gt;

&lt;p&gt;这个 Handler 顾名思义，是用来解决配额管理问题的。可以定义一组 memquota，设置缺省的配额以及相关的模板等。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: memquota
metadata:
  name: memquota-handler
spec:
  quotas:
    - name: tmpl-quota.quota.istio-workload # 引用模板名称 格式：[quota 模板].quota.[namespace]
      maxAmount: 5000 # 缺省限制
      validDuration: 10s # 计时窗口
      overrides: # 根据条件进行重载
      - dimensions:
          destination: php-server
          source: sleep
        maxAmount: 5
        validDuration: 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;模板&#34;&gt;模板&lt;/h2&gt;

&lt;p&gt;前面的 memquota 中，有一个条目引用了一个模板。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;一个请求到达 Mesh 中的服务时，一般会发生两次对 Mixer 的调用，一次是前置检查，一次是遥测报告。每一次这种调用，Mixer 都需要调用一个或更多的适配器。不同的适配器需要不同的数据块作为输入来进行处理。例如日志适配器需要日志输入，指标适配器需要指标输入，认证适配器需要凭据输入。适配器在请求时消费的数据就是由 Mixer 的 Template 来描述的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: quota
metadata:
  name: tmpl-quota
spec:
  dimensions:
    source: source.labels[&amp;quot;app&amp;quot;] | source.service | &amp;quot;unknown&amp;quot;
    sourceVersion: source.labels[&amp;quot;version&amp;quot;] | &amp;quot;unknown&amp;quot;
    destination: destination.labels[&amp;quot;app&amp;quot;] | destination.service | &amp;quot;unknown&amp;quot;
    destinationVersion: destination.labels[&amp;quot;version&amp;quot;] | &amp;quot;unknown&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这一模板中，定义了 memquota 适配器所需要的 Dimension 数据。&lt;/p&gt;

&lt;h2 id=&#34;规则&#34;&gt;规则&lt;/h2&gt;

&lt;p&gt;Rule 对象的任务相对比较简单：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;他负责告诉 Mixer，哪个 Instance 应该在什么时候发送给哪个 Handler。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: rule-quota
spec:
  actions:
  - handler: memquota-handler.memquota # 引用适配器名称，这里需要加上适配器类型
    instances:
    - tmpl-quota.quota # 引用 Quota 模板
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;quotaspec&#34;&gt;QuotaSpec&lt;/h2&gt;

&lt;p&gt;这个对象用于对额度消费过程的行为进行定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: QuotaSpec
metadata:
  name: spec-request-count
spec:
  rules:
  - quotas:
    - charge: 5 # 每请求的消耗资源数量/倍数
      quota: &amp;quot;tmpl-quota&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;quotaspecbinding&#34;&gt;QuotaSpecBinding&lt;/h2&gt;

&lt;p&gt;有了配额消费规格的定义之后，我们还需要把它绑定到具体的服务上去，这样才凑齐了最后一环。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: QuotaSpecBinding
metadata:
  name: request-count
spec:
  quotaSpecs:
  - name: spec-request-count # quotaspec 名称
    namespace: istio-workload # 必须
  services:
  - name: php-server
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;具体测试过程非常简单，分别启动一个名为 &lt;code&gt;php-server&lt;/code&gt; 的服务，以及一个包含有 curl 等能够发起 http 访问的客户端服务，都使用 istio 进行注入之后，就可以进入控制台客户端 Pod，发起请求。例如：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;for i in $(seq 6); do curl -s http://php-server/version.php ; done&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会出现 &lt;code&gt;RESOURCE_EXHAUSTED:Quota is exhausted&lt;/code&gt; 的信息，通过调整 &lt;code&gt;QuotaSpec&lt;/code&gt; 中 &lt;code&gt;charge&lt;/code&gt; 的值，会很容易的看到额度消费的效率产生的变化。&lt;/p&gt;

&lt;h2 id=&#34;参考阅读&#34;&gt;参考阅读&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Mixer 适配器模型：&lt;a href=&#34;http://blog.fleeto.us/translation/mixer-adapter-model&#34; target=&#34;_blank&#34;&gt;http://blog.fleeto.us/translation/mixer-adapter-model&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>摸索：Istio 路由规则 Alpha v3</title>
      <link>/post/istio-route-alpha1v3/</link>
      <pubDate>Mon, 16 Apr 2018 11:48:10 +0800</pubDate>
      <guid>/post/istio-route-alpha1v3/</guid>
      <description>

&lt;p&gt;Istio 近期的版本中出现了一个新的 API 组：&lt;code&gt;networking.istio.io/v1alpha3&lt;/code&gt;，应该会替代现有的&lt;code&gt;config.istio.io/v1alpha2&lt;/code&gt; API。新的 API 不管是结构上还是功能上、以及命名上，都有很大差异。这里使用一些简单例子，体验一下 Alpha 3 带来的变化。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：正常情况下 istioctl 和 kubectl 都可以用来操作这些对象，但是 kubectl 缺乏验证功能，因此调试阶段使用 istioctl 会更方便一些。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;路由分配&#34;&gt;路由分配&lt;/h2&gt;

&lt;p&gt;过去的路由分配比较简单，使用标签即可。新的版本中，提出了 &lt;a href=&#34;https://istio.io/docs/reference/config/istio.networking.v1alpha3.html#VirtualService&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;VirtualService&lt;/code&gt;&lt;/a&gt; 的概念。VirtualService 由一组路由规则构成，用于对服务实体（原文为 Host，个人认为在 K8S 中对应为 Pod）进行寻址。一旦有流量符合其中规则的选择条件，就会发送流量给对应的服务（或者服务的一个版本/子集）。&lt;/p&gt;

&lt;p&gt;流量的特征除了请求数据之外，还包括流量的来源，这样就能根据一些上下文来进行灵活的定义了。&lt;/p&gt;

&lt;p&gt;这里我们定义来自 sleep 对 php-server 的请求，都转向 v1：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;
apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

  name: sleep-server-route

spec:

  hosts:

  - &amp;quot;php-server&amp;quot;

  http:

  - match:

    - sourceLabels:

        app: sleep

    route:

    - destination:

        name: php-server

        subset: v3

  - route:

    - destination:

        name: php-server

        subset: v2

&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;这里的匹配策略是具有从上到下的优先级的，也就是说，最下一条就是缺省路由。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;可以看到，&lt;code&gt;match&lt;/code&gt;中不再包含 &lt;code&gt;source&lt;/code&gt;，这里使用标签来过滤。写完应用之后，我们在 Sleep Pod 中使用 curl 发起请求，会发现并没有生效。这是因为，&lt;strong&gt;在 v3 中，目标规则不再是小透明了。&lt;/strong&gt;，路由定义必须以目标策略为基础。&lt;/p&gt;

&lt;p&gt;因此这里需要定义一个 &lt;code&gt;DestinationRule&lt;/code&gt; 对象，来满足上面的目标需求：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;
apiVersion: networking.istio.io/v1alpha3

kind: DestinationRule

metadata:

  name: phpserver

spec:

  name: php-server

  subsets:

  - name: v1

    labels:

      version: v1

  - name: v2

    labels:

      version: v2

  - name: v3

    labels:

      version: v3

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的文件，创建了名为 &lt;code&gt;phpserver&lt;/code&gt; 的目标规则，并在下级使用标签创建了三个子集。再次测试，会发现按照我们的要求执行了。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：VirtualService 中引用的 Destination.name 似乎对应的是目标规则中的 spec.name，而不是 metadata.name。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;断路器&#34;&gt;断路器&lt;/h2&gt;

&lt;p&gt;这部分的 API 变化较大。可以在上面的 DestinationRule 中加入熔断策略：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;
  - name: v2

    labels:

      version: v2

  trafficPolicy:

    connectionPool:

      http:

        http1MaxPendingRequests: 1

        maxRequestsPerConnection: 1

      tcp:

        maxConnections: 100

    outlierDetection:

      http:

        baseEjectionTime: 180.000s

        consecutiveErrors: 1

        interval: 1.000s

        maxEjectionPercent: 100

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来就可以使用 Fortio 或其他工具来测试熔断效果了，具体操作可以参考官方文档的&lt;a href=&#34;https://istio.io/docs/tasks/traffic-management-v1alpha3/circuit-breaking.html&#34; target=&#34;_blank&#34;&gt;断路器一节&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;新版本 API 加入了相当多的非 K8S 特性，另外突出了 Gateway，VirtualService 等主要对象，使得各个定义的条理性大为增强。但是目前这一组 API 仍然是 Alpha 阶段，因此还是存在相当大的变数的，但是个人推测的是，新 API 会得到更大的支持力度，因此可靠性应该更强。总之 Alpha 有风险，使用需谨慎。&lt;/p&gt;

&lt;h2 id=&#34;参考链接&#34;&gt;参考链接&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;VirtualService&lt;/code&gt;: &lt;code&gt;https://istio.io/docs/reference/config/istio.networking.v1alpha3.html#VirtualService&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;断路器&lt;/code&gt;：&lt;code&gt;https://istio.io/docs/tasks/traffic-management-v1alpha3/circuit-breaking.html&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>istio 0.5.0 新特性：流量镜像</title>
      <link>/post/istio-shadow-traffic/</link>
      <pubDate>Tue, 13 Feb 2018 07:52:05 +0800</pubDate>
      <guid>/post/istio-shadow-traffic/</guid>
      <description>

&lt;p&gt;在类似 Dark launch 的测试、发布过程中，流量复制是个非常有用的功能，istio 0.5.0 的更新，带来了一个新的路由相关特性：流量镜像。&lt;/p&gt;

&lt;p&gt;这一场景中，我们会将正常的流量进行复制，将复制出来的流量分发给待上线的应用(V2)，使用实际流量对新版本应用进行测试；而现有客户端则仅会感知到单一版本(V1)的存在。&lt;/p&gt;

&lt;p&gt;下面做个小实验来进行验证。&lt;/p&gt;

&lt;h2 id=&#34;条件&#34;&gt;条件&lt;/h2&gt;

&lt;p&gt;基于 Kubernetes 运行的 Istio 0.5.0 版本部署。&lt;/p&gt;

&lt;h2 id=&#34;部署&#34;&gt;部署&lt;/h2&gt;

&lt;p&gt;源码见后。&lt;/p&gt;

&lt;p&gt;用&lt;code&gt;nginx:stabel-alpine&lt;/code&gt;镜像，生成&lt;code&gt;v1&lt;/code&gt;和&lt;code&gt;v2&lt;/code&gt;两个版本的 Deployment，以及一个&lt;code&gt;target&lt;/code&gt;服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;istioctl kube-inject -f v1.deploy.yaml| kubectl apply -f -
istioctl kube-inject -f v2.deploy.yaml| kubectl apply -f -
kubectl apply -f service.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用&lt;code&gt;dustise/sleep&lt;/code&gt;镜像作为客户端服务，来制造请求访问目标服务。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;istioctl kube-inject -f sleep.yaml | kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用&lt;code&gt;kubectl get po&lt;/code&gt;验证 Pod 生成情况，就绪之后开始进行验证。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;NAME                         READY     STATUS    RESTARTS   AGE
sleep-6f569f4c9-hs6wx        2/2       Running   0          10m
target-v1-7f78d974c-mfhzz    2/2       Running   0          1h
target-v2-5886cd585d-tr22d   2/2       Running   0          1h
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;验证&#34;&gt;验证&lt;/h2&gt;

&lt;h3 id=&#34;初始化&#34;&gt;初始化&lt;/h3&gt;

&lt;p&gt;首先我们生成一个缺省路由，将全部流量引入 v1：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: rule-all-http
spec:
  destination:
    name: target
  precedence: 1
  route:
  - labels:
      app: target
      version: v1
    weight: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用&lt;code&gt;kubectl apply -f rules.yaml&lt;/code&gt;应用这一规则。&lt;/p&gt;

&lt;p&gt;接下来监控 nginx 的访问日志：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kubectl logs -f [v1-pod] -c nginx
kubectl logs -f [v2-pod] -c nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;或者可以使用 &lt;code&gt;kubetail&lt;/code&gt; 工具：&lt;code&gt;kubetail target -c nginx&lt;/code&gt;，对部署内容的日志进行监控。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;kubectl exec -it [sleep-pod] -c sleep bash&lt;/code&gt; 进入客户端服务 Pod，执行&lt;code&gt;curl http://target&lt;/code&gt;，会看到在 &lt;code&gt;v1&lt;/code&gt; Pod 中出现了访问迹象：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:30 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;-&amp;quot;
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:31 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;-&amp;quot;
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:32 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;-&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;开始镜像&#34;&gt;开始镜像&lt;/h3&gt;

&lt;p&gt;修改路由规则：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: rule-all-http
spec:
  destination:
    name: target
  precedence: 1
  route:
  - labels:
      app: target
      version: v1
    weight: 100
  - labels:
      app: target
      version: v2
    weight: 0
  mirror:
    name: target
    labels:
      app: target
      version: v2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;这里为 &lt;code&gt;v2&lt;/code&gt; 建立了一个权重为 &lt;code&gt;0&lt;/code&gt; 的路由项，这是一个硬性规定，启用 &lt;code&gt;mirror&lt;/code&gt; 的路由必须要在上面的 &lt;code&gt;route&lt;/code&gt; 中具备一致的入口，以此通知 Envoy 进行相应的数据面操作。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;kubectl apply -f rules.yaml&lt;/code&gt; 来更新路由规则。&lt;/p&gt;

&lt;p&gt;再次在客户端 Pod 中访问 &lt;code&gt;target&lt;/code&gt; 服务，会发现两个版本的 Pod 中都出现了访问日志，并且数量上是一一对应的：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[target-v2-5886cd585d-tr22d] 127.0.0.1 - - [12/Feb/2018:15:20:16 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;10.240
.0.29&amp;quot;
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:20:16 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;-&amp;quot;
[target-v2-5886cd585d-tr22d] 127.0.0.1 - - [12/Feb/2018:15:20:17 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;10.240
.0.29&amp;quot;
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:20:17 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 612 &amp;quot;-&amp;quot; &amp;quot;curl/7.38.0&amp;quot; &amp;quot;-&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;从语法来看，仅支持一个复制&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;源码&#34;&gt;源码&lt;/h2&gt;

&lt;h3 id=&#34;v1-deploy-yaml&#34;&gt;v1.deploy.yaml&lt;/h3&gt;

&lt;p&gt;将 &lt;code&gt;v1&lt;/code&gt; 替换成 &lt;code&gt;v2&lt;/code&gt; 生成另外一个部署。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: target-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: target
        version: v1
    spec:
      containers:
      - image: nginx:stable-alpine
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;sleep-yaml&#34;&gt;sleep.yaml&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: target
  labels:
    app: target
spec:
  ports:
  - name: http
    port: 80
  selector:
    app: target
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;sleep-yaml-1&#34;&gt;sleep.yaml&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
    version: v1
spec:
  selector:
    app: sleep
    version: v1
  ports:
    - name: ssh
      port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
        version: v1
    spec:
      containers:
      - name: sleep
        image: dustise/sleep
        imagePullPolicy: IfNotPresent
---
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>ChatBot：在 Slack 中使用监控和告警</title>
      <link>/post/errbot-on-slack/</link>
      <pubDate>Wed, 07 Feb 2018 05:30:24 +0800</pubDate>
      <guid>/post/errbot-on-slack/</guid>
      <description>

&lt;p&gt;前面文章中我们使用 Errbot 通过 Kubernetes API 在 Slack 中进行 Kubernetes 查询。这种方式很局限。毕竟拉更多组件下水，写更多代码才是大势所趋 LOL。本文以 Istio 中的响应时间监控为例，看看 Errbot 和 Prometheus 的互动。&lt;/p&gt;

&lt;h2 id=&#34;前提&#34;&gt;前提&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Istio&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;公网部署&lt;/li&gt;
&lt;li&gt;接入 Slack 的 Errbot&lt;/li&gt;
&lt;li&gt;Errbot 开放 3141 端口，能够被 Alertmanager 使用。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注意：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;这里只是介绍一下这种思路，例子要求比较高，源文件也不会很完整。要投入实际使用，需要更多配合。&lt;/li&gt;
&lt;li&gt;选择 Istio 做监控目标，只是因为目前环境方便，并无特殊含义。&lt;/li&gt;
&lt;li&gt;Errbot 的 Slack 接入在之前的文章有一些介绍可以参考。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;在-bot-中获取监控指标&#34;&gt;在 Bot 中获取监控指标&lt;/h2&gt;

&lt;p&gt;Prometheus 提供了很方便的 &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/api/&#34; target=&#34;_blank&#34;&gt;HTTP API（注 1）&lt;/a&gt;，简单的使用 HTTP 客户端即可获取。下面的表达式用于从 Istio 中获取响应时间的 p99 指标：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    histogram_quantile(0.99,
    sum(irate(istio_request_duration_bucket[1m]))
    by (source_service, source_version,
    destination_service, destination_version, le))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里为行文方便，直接硬编码，实际上可以通过查询模板、Bot 参数等方式，获得更灵活的查询。或者更加简单粗暴的，在聊天室向 Bot 提供查询公式直接查询。&lt;/p&gt;

&lt;p&gt;下面的代码，会将 Prometheus 中的指标，在 Slack 中以卡片的方式输出到指定聊天室中。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;指定一个 &lt;code&gt;query&lt;/code&gt; 参数，取值为刚才提到的 Prometheus 查询语句，&lt;code&gt;{&amp;quot;query&amp;quot;: prom}&lt;/code&gt;的形式进行 URL Encode。&lt;/li&gt;
&lt;li&gt;API 指令发出后，Prometheus 会响应一段 JSON 报文，报文的&lt;code&gt;result&lt;/code&gt;字段包含一个列表，包含了各个服务的各个版本之间的通信响应时间。&lt;/li&gt;
&lt;li&gt;这里使用 Errbot 的 &lt;a href=&#34;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.send_card&#34; target=&#34;_blank&#34;&gt;send_card（注 2）&lt;/a&gt;功能，通过 Field 方式逐个输出服务记录。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;room = self.build_identifier(&amp;quot;#bot&amp;quot;)&lt;/code&gt;，使用 &lt;a href=&#34;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.build_identifier&#34; target=&#34;_blank&#34;&gt;self.build_identifier（注 3）&lt;/a&gt;设置发送目标。&lt;/li&gt;
&lt;li&gt;代码放入 Errbot 插件之后，私聊窗口输入&lt;code&gt;!restart&lt;/code&gt;，重启。会看到 Errbot 发出重启信息之后断线。&lt;/li&gt;
&lt;li&gt;等 Errbot 再次在线，在聊天室输入指令&lt;code&gt;!service quality&lt;/code&gt;，会看到类似如下的信息回应：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&#34;images/errbot-prom1.png&#34; alt=&#34;metrics&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;使用-bot-接收-prometheus-告警&#34;&gt;使用 Bot 接收 Prometheus 告警&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;实际上 Prometheus 的 Alert Manager 提供了到 Slack 的集成，这里纯属演示，绕了个远。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;配置-bot&#34;&gt;配置 Bot&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;在聊天室私信中发布命令 &lt;code&gt;!plugin config Webserver {&#39;HOST&#39;: &#39;0.0.0.0&#39;,&#39;PORT&#39;: 3141}&lt;/code&gt;，要求 Errbot 开放端口启动 Webhook 服务。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;同样的使用私信发送命令 &lt;code&gt;!status&lt;/code&gt;，查询插件运行状态，可以看到 &lt;code&gt;Webserver&lt;/code&gt; 已经启动。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/bot-status.png&#34; alt=&#34;Bot Status&#34; /&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;为 Bot 插件加入 Webhook 代码，并重新启动 Bot，这里定义了路径&lt;code&gt;alertmanager&lt;/code&gt;用于接受告警，同样使用卡片方式，发送告警信息到&lt;code&gt;bot&lt;/code&gt;频道，在卡片中显示告警的相关服务及其版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def alertmanager(self, data):
  &amp;quot;&amp;quot;&amp;quot;Webhook for alerts from Prometheus&amp;quot;&amp;quot;&amp;quot;
  target = self.build_identifier(&amp;quot;#bot&amp;quot;)
  self.send(target, &amp;quot;Alert!!&amp;quot;)
  for alert in data[&#39;alerts&#39;]:
      self.send_card(
          to=target,
          summary=&#39;[{}] {}&#39;.format(
              data[&#39;status&#39;].upper(),
              data[&#39;commonLabels&#39;][&#39;alertname&#39;]
          ),
          title=&amp;quot;Prometheus Alert&amp;quot;,
          fields=[(&#39;From&#39;, alert[&#39;annotations&#39;][&#39;from&#39;]),
                  (&#39;To&#39;, alert[&#39;annotations&#39;][&#39;to&#39;])],
          body=alert[&#39;annotations&#39;][&#39;summary&#39;]
      )
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;prometheus-配置&#34;&gt;Prometheus 配置&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;配置 Prometheus 告警规则：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;使用前面提到的同一个公式&lt;/li&gt;
&lt;li&gt;使用注解来传递应用标签&lt;/li&gt;

&lt;li&gt;&lt;p&gt;这里我们配置大于 3 秒钟的耗时发生告警&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;groups:
- name: fake
rules:
- alert: rules-alert
expr: |
    histogram_quantile(0.99,
    sum(irate(istio_request_duration_bucket[1m]))
    by (source_service, source_version,
    destination_service, destination_version, le)) &amp;gt; 3
for: 1m
labels:
    alertname: &amp;quot;request-duration-3&amp;quot;
annotations:
    summary: &amp;quot;Request duration gt 3&amp;quot;
    from: &amp;quot;{{ $labels.source_service }}:{{ $labels.source_version }}&amp;quot;
    to: &amp;quot;{{ $labels.destination_service }}:{{ $labels.destination_version }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;配置和重启 Alert Manager，定义使用 Web hook 通知 errbot 发送告警到 Slack：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;route:
    receiver: &#39;webhook&#39;
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
    group_by: [&#39;from&#39;, &#39;to&#39;]
    routes:

receivers:
- name: &#39;webhook&#39;
    webhook_configs:
    - url: &amp;quot;http://errbot.default:3141/alertmanager&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Prometheus 连接到 AlertManager 上，用于发送告警，修改后重启 Prometheus：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;alerting:
alertmanagers:
- scheme: http
  static_configs:
  - targets:
    - &amp;quot;alertmanager:9093&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;运行&#34;&gt;运行&lt;/h2&gt;

&lt;p&gt;在负载上调用耗时操作，例如持续访问&lt;code&gt;httpbin&lt;/code&gt;的&lt;code&gt;/delay/5&lt;/code&gt;指令，满足标准后，可以看到，告警的传递线路：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/prom-alert.png&#34; alt=&#34;prom alert&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/alert-alert.png&#34; alt=&#34;alert alert&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/slack-alert-card.png&#34; alt=&#34;slack alert&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;注&#34;&gt;注&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;https://prometheus.io/docs/prometheus/latest/querying/api/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.send_card&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.build_identifier&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;附录&#34;&gt;附录&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;查询&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;@botcmd
def service_quality(self, message, args):
url = &amp;quot;http://prometheus-server.kube-system/api/v1/query?&amp;quot;
prom = &amp;quot;&amp;quot;&amp;quot;
histogram_quantile(0.99,
sum(irate(istio_request_duration_bucket[1m]))
by (source_service, source_version,
destination_service, destination_version, le))
&amp;quot;&amp;quot;&amp;quot;
query = {&amp;quot;query&amp;quot;: prom}
query = urlencode(query)
f = urllib.request.urlopen(url + query)
resp = f.read()
record_list = json.loads(resp)
room = self.build_identifier(&amp;quot;#bot&amp;quot;)
field_list = []
for record in record_list[&amp;quot;data&amp;quot;][&amp;quot;result&amp;quot;]:
    metric = record[&amp;quot;metric&amp;quot;]
    value = record[&amp;quot;value&amp;quot;]
    domain = &amp;quot;.svc.cluster.local&amp;quot;
    field = (&amp;quot;From {}:{} to {}:{}&amp;quot;.format(
        metric[&amp;quot;source_service&amp;quot;].replace(domain, &amp;quot;&amp;quot;),
        metric[&amp;quot;source_version&amp;quot;],
        metric[&amp;quot;destination_service&amp;quot;].replace(domain, &amp;quot;&amp;quot;),
        metric[&amp;quot;destination_version&amp;quot;],
    ), value[-1])
    field_list.append(field)
self.send_card(to=room, body=prom,
               title=&amp;quot;Query Statement&amp;quot;, summary=&amp;quot;From prometheus&amp;quot;,
               color=&amp;quot;green&amp;quot;, fields=field_list)
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>在 Azure 上运行 Istio 的注意事项</title>
      <link>/post/istion-on-azure-k8s/</link>
      <pubDate>Fri, 02 Feb 2018 23:04:20 +0800</pubDate>
      <guid>/post/istion-on-azure-k8s/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;ACS Engine: v0.12.4&lt;/li&gt;
&lt;li&gt;Istio: v0.5.0&lt;/li&gt;
&lt;li&gt;Kubernetes: v1.8.7&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在 Istio 注入之后，生成的 Init 容器中会有 RunAs 的 SecurityContext，而 ACS Engine 的缺省 admission 包含了&lt;code&gt;SecurityContextDeny&lt;/code&gt;，会拒绝这一选项，造成 Istio Workload 无法运行，&lt;/p&gt;

&lt;p&gt;解决方法很简单，只要在定义文件中修改 api server 配置：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;&amp;quot;properties&amp;quot;: {
  &amp;quot;orchestratorProfile&amp;quot;: {
    &amp;quot;kubernetesConfig&amp;quot;: {
        &amp;quot;apiServerConfig&amp;quot;: {
            &amp;quot;--request-timeout&amp;quot;: &amp;quot;30s&amp;quot;,
            &amp;quot;--admission-control&amp;quot;: &amp;quot;NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,DenyEscalatingExec,AlwaysPullImages&amp;quot;
        }

&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Istio 尾行记</title>
      <link>/post/istio-tracker/</link>
      <pubDate>Sat, 30 Dec 2017 17:19:47 +0800</pubDate>
      <guid>/post/istio-tracker/</guid>
      <description>

&lt;p&gt;Istio 一直没有什么像样的更新，Conduit 也迟迟不出来怼，眼看 2017 就要过去，安装试用也不新鲜了，补一篇 Istio 的笔记，算做个收尾了。&lt;/p&gt;

&lt;p&gt;Istio 最大的亮点之一，就是使用 Pilot 将集群控制语言翻译成为 Envoy 配置，利用 Sidecar 的方式对服务通信进行控制，下面就是对这一过程的跟踪尝试。&lt;/p&gt;

&lt;h2 id=&#34;kubectl-apply-f-install-kubernetes-istio-yaml&#34;&gt;&lt;code&gt;kubectl apply -f install/kubernetes/istio.yaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cat istio.yaml| grep ^kind&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;会看到，这里生成了相当多的内容，除去 Deployment、Service 和 ConfigMap 老几样之外，还有当前集群必须的 RBAC 几要素：Service Account、ClusterRole 以及 ClusterRoleBinding。然后就是 Kubernetes 世界里强力扩展的标志：各种 CRD(CustomResourceDefinition) 了。&lt;/p&gt;

&lt;h2 id=&#34;kubectl-apply-f-install-kubernetes-addons&#34;&gt;&lt;code&gt;kubectl apply -f install/kubernetes/addons/&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这里会生成一系列的监控用具，包括了 Prometheus、Grafana、ZipKin 以及 ServiceGraph，原则上这些并非必须组件。不过为了监控方便，一般还是会加上。&lt;/p&gt;

&lt;p&gt;另外这里的 Prometheus 以及 Grafana 的监控、仪表盘配置都可以保存下来，方便同现有设施进行融合。&lt;/p&gt;

&lt;h2 id=&#34;istioctl-kube-inject-f&#34;&gt;&lt;code&gt;istioctl kube-inject -f ...&lt;/code&gt;&lt;/h2&gt;

&lt;h3 id=&#34;运行这个命令之前-务必注意几个对-workload-的要求&#34;&gt;运行这个命令之前，务必注意几个对 Workload 的要求：&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;目前，Pod 对应单一服务的情况才能得到支持。&lt;/li&gt;
&lt;li&gt;服务端口必须命名，[协议]-[后缀] 的方式，后缀部分可以忽略，写一部分可以使用 http, http2, grpc, mongo 以及 redis。如果不进行合理的命名，又没有显示声明这一端口是 UDP 端口，那么就会被当做普通 TCP 端口处理。&lt;/li&gt;
&lt;li&gt;Deployment 需要有 App 标签，注意看示例应用的标签方法。&lt;/li&gt;
&lt;li&gt;目前的缺省安装不支持 &lt;code&gt;cluster.local&lt;/code&gt; 之外的 Kubernetes 域名。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在安装好 Istio 之后，一般会使用这一命令对服务进行注入（同样也有自动注入的能力），使之称为被 istio 加持的 Service Mesh 成员服务。注入之后的 YAML 会变得比较丰腴：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;一组注解&lt;/li&gt;
&lt;li&gt;两个 Init&lt;/li&gt;
&lt;li&gt;一个同 Pod 容器&lt;/li&gt;
&lt;li&gt;两个卷&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面分别讲解一下多出来的这些部分：&lt;/p&gt;

&lt;h3 id=&#34;annotation&#34;&gt;Annotation&lt;/h3&gt;

&lt;p&gt;为 Deployment 和 Pod 加入了同样的注解：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sidecar.istio.io/status: injected-version...&lt;/code&gt;，目前理解是，标注了这一部署和 Pod 是否已经被注入，被什么版本注入。&lt;/p&gt;

&lt;h3 id=&#34;init-1&#34;&gt;Init 1&lt;/h3&gt;

&lt;p&gt;使用 Alpine 镜像，设置内核 Dump 模板，以及 ulimit。&lt;/p&gt;

&lt;h3 id=&#34;init-2&#34;&gt;Init 2&lt;/h3&gt;

&lt;p&gt;使用 &lt;code&gt;docker.io/istio/proxy_init:0.4.0&lt;/code&gt; 进行初始化，参数为 &lt;code&gt;-p 15001 -u 1337&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&#34;sidecar&#34;&gt;Sidecar&lt;/h3&gt;

&lt;p&gt;镜像为： &lt;code&gt;docker.io/istio/proxy_debug:0.4.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;其中定义了大量的服务关系，包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Istio Pilot&lt;/li&gt;
&lt;li&gt;Zipkin&lt;/li&gt;
&lt;li&gt;Mixer&lt;/li&gt;
&lt;li&gt;管理端口&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;卷&#34;&gt;卷&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;内存卷用于存储配置；&lt;/li&gt;
&lt;li&gt;Secret 卷用于后面的 TLS。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;运行&#34;&gt;运行&lt;/h2&gt;

&lt;p&gt;利用 &lt;code&gt;kubectlapply -f&lt;/code&gt;，将注入后的 yaml 文件运行起来，接下来就可以使用各个 Pod 来查看刚才注入的内容的行迹了。&lt;/p&gt;

&lt;p&gt;列出 Pod：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NAME                          READY     STATUS    RESTARTS   AGE
httpbin-7965799df7-ll75q      2/2       Running   0          53m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;通过前面的 yaml 定义，我们知道这个 Pod 的两个容器分别是 &lt;code&gt;httpbin&lt;/code&gt; 和 &lt;code&gt;istio-proxy&lt;/code&gt;，Istio 强调的是 Sidecar 模式的无侵入管理，因此我们可以认为 &lt;code&gt;httpbin&lt;/code&gt; 是没有变化的，Service Mesh 的 Sidecar 功能会体现在 &lt;code&gt;istio-proxy&lt;/code&gt; 这一容器中。&lt;/p&gt;

&lt;h3 id=&#34;初始化&#34;&gt;初始化&lt;/h3&gt;

&lt;p&gt;上一节中提到了，使用 &lt;code&gt;proxy_init&lt;/code&gt; 进行的初始化（Alpine 部分修改内核参数，就不用多说了），我们可以进入源码，查查他的初始化做了什么。&lt;/p&gt;

&lt;p&gt;Dockerfile 中我们看到，这一容器的入口命令为 &lt;code&gt;istio-start.sh&lt;/code&gt;，找出这个文件，会看到其中使用这两个参数对 iptables 的 nat 部分做了配置，另外还可以看到，其中加入了 iptables 命令，这里我们可以进行验证：&lt;code&gt;kubectl exec httpbin-7965799df7-ll75q -c istio-proxy  sudo iptables-save&lt;/code&gt;，输出内容可以这样解读：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;跳过和 Proxy 进程用户一致的用户进程的流量处理；&lt;/li&gt;
&lt;li&gt;跳过 Loopback 流量处理；&lt;/li&gt;
&lt;li&gt;所有流量转发到 15001 端口。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;和脚本初始化内容一致。&lt;/p&gt;

&lt;h3 id=&#34;istio-proxy&#34;&gt;istio-proxy&lt;/h3&gt;

&lt;p&gt;启动之后，我们可以使用 &lt;code&gt;kubectl exec -it [httpbin] -c istio-proxy sh&lt;/code&gt; 进入 Proxy 容器，执行命令 &lt;code&gt;ps -ef&lt;/code&gt;，会发现有两个正在运行的进程：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/usr/local/bin/pilot-agent&lt;/li&gt;
&lt;li&gt;/usr/local/bin/envoy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;并且 Envoy 的父进程就是这个 pilot-agent。其运行参数和我们前面注入到 YAML 中的参数一致。&lt;/p&gt;

&lt;p&gt;另外还可以查看 &lt;code&gt;/etc/istio/proxy/&lt;/code&gt; 下面的配置文件，可以看出：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Envoy 通过 pilot-agent 传递的参数运行&lt;/li&gt;
&lt;li&gt;服务发现是通过 Pilot 完成的&lt;/li&gt;
&lt;li&gt;Envoy 开放了 15000 端口进行管理&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;验证路由规则&#34;&gt;验证路由规则&lt;/h2&gt;

&lt;p&gt;执行 &lt;code&gt;kubectl exec [Pod] -c istio-proxy curl localhost:15000/routes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;可以看到 httpbin 的路由如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;quot;version_info&amp;quot;: &amp;quot;hash_35afd004f717e588&amp;quot;,
    &amp;quot;route_config_name&amp;quot;: &amp;quot;8000&amp;quot;,
    &amp;quot;cluster_name&amp;quot;: &amp;quot;rds&amp;quot;,
    &amp;quot;route_table_dump&amp;quot;: {&amp;quot;name&amp;quot;:&amp;quot;8000&amp;quot;,&amp;quot;virtual_hosts&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;httpbin.default.svc.cluster.local|http&amp;quot;,&amp;quot;domains&amp;quot;:[&amp;quot;httpbi
n:8000&amp;quot;,&amp;quot;httpbin&amp;quot;,&amp;quot;httpbin.default:8000&amp;quot;,&amp;quot;httpbin.default&amp;quot;,&amp;quot;httpbin.default.svc:8000&amp;quot;,&amp;quot;httpbin.default.svc&amp;quot;,&amp;quot;httpbin.defaul
t.svc.cluster:8000&amp;quot;,&amp;quot;httpbin.default.svc.cluster&amp;quot;,&amp;quot;httpbin.default.svc.cluster.local:8000&amp;quot;,&amp;quot;httpbin.default.svc.cluster.loc
al&amp;quot;,&amp;quot;10.0.34.255:8000&amp;quot;,&amp;quot;10.0.34.255&amp;quot;],&amp;quot;routes&amp;quot;:[{&amp;quot;match&amp;quot;:{&amp;quot;prefix&amp;quot;:&amp;quot;/&amp;quot;},&amp;quot;route&amp;quot;:{&amp;quot;cluster&amp;quot;:&amp;quot;out.httpbin.default.svc.cluster
.local|http&amp;quot;,&amp;quot;timeout&amp;quot;:&amp;quot;0s&amp;quot;},&amp;quot;decorator&amp;quot;:{&amp;quot;operation&amp;quot;:&amp;quot;default-route&amp;quot;}}]}]}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;新建缺省路由：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: rule-all-http
spec:
  destination:
    name: httpbin
  precedence: 1
  route:
  - labels:
      app: httpbin
    weight: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次查询路由，可以看到其中发生了变化：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;quot;version_info&amp;quot;: &amp;quot;hash_146c02ed176ff12b&amp;quot;,
    &amp;quot;route_config_name&amp;quot;: &amp;quot;8000&amp;quot;,
    &amp;quot;cluster_name&amp;quot;: &amp;quot;rds&amp;quot;,
    &amp;quot;route_table_dump&amp;quot;: {&amp;quot;name&amp;quot;:&amp;quot;8000&amp;quot;,&amp;quot;virtual_hosts&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;httpbin.default.svc.cluster.local|http&amp;quot;,&amp;quot;domains&amp;quot;:[&amp;quot;httpbi
n:8000&amp;quot;,&amp;quot;httpbin&amp;quot;,&amp;quot;httpbin.default:8000&amp;quot;,&amp;quot;httpbin.default&amp;quot;,&amp;quot;httpbin.default.svc:8000&amp;quot;,&amp;quot;httpbin.default.svc&amp;quot;,&amp;quot;httpbin.defaul
t.svc.cluster:8000&amp;quot;,&amp;quot;httpbin.default.svc.cluster&amp;quot;,&amp;quot;httpbin.default.svc.cluster.local:8000&amp;quot;,&amp;quot;httpbin.default.svc.cluster.loc
al&amp;quot;,&amp;quot;10.0.34.255:8000&amp;quot;,&amp;quot;10.0.34.255&amp;quot;],&amp;quot;routes&amp;quot;:[{&amp;quot;match&amp;quot;:{&amp;quot;prefix&amp;quot;:&amp;quot;/&amp;quot;},&amp;quot;route&amp;quot;:{&amp;quot;cluster&amp;quot;:&amp;quot;out.httpbin.default.svc.cluster
.local|http|app=httpbin&amp;quot;,&amp;quot;timeout&amp;quot;:&amp;quot;0s&amp;quot;},&amp;quot;decorator&amp;quot;:{&amp;quot;operation&amp;quot;:&amp;quot;rule-all-http&amp;quot;}}]}]}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;cluster&#34;&gt;cluster&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;kubectl exec [pod] -c istio-proxy curl localhost:15000/routes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;可以看到所有对应的服务信息，以及可能存在的断路器信息。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>试译：Mixer 的适配器模型</title>
      <link>/post/mixer-modal-of-istio/</link>
      <pubDate>Fri, 10 Nov 2017 09:53:02 +0800</pubDate>
      <guid>/post/mixer-modal-of-istio/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://istio.io/blog/2017/adapter-model.html&#34; target=&#34;_blank&#34;&gt;Mixer Adapter Model&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mixer 插件架构概述&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Istio 0.2 引入了新的 Mixer 适配器模型，从而具有了更大的灵活性去接入各种基础设施后端。本文尝试讲述这一模型及其工作机制。&lt;/p&gt;

&lt;h2 id=&#34;为什么是适配器模型&#34;&gt;为什么是适配器模型？&lt;/h2&gt;

&lt;p&gt;各种基础设施都提供了用于支持服务构建的功能，例如访问控制、遥测、配额、计费等等。传统服务会直接和这些后端系统打交道，和后端紧密耦合，并集成其中的个性化语义以及用法。&lt;/p&gt;

&lt;p&gt;Mixer 服务构成了基础设施和 Istio 之间的抽象层。Istio 组件和运行于 Service Mesh 中的服务，借助 Mixer 的能力就能在不直接访问后端接口的情况下和这些后端进行交互。&lt;/p&gt;

&lt;p&gt;Mixer 除了作为应用和基础设施之间的隔离层之外，操作者还可以借助 Mixer 的中介模型，注入或者操作应用和后端之间的策略，例如哪些数据需要报告给哪些后端、哪些后端提供认证等。&lt;/p&gt;

&lt;p&gt;每种后端都有各自不同的接口和操作方式，因此 Mixer 需要有代码来支持这种差异，我们称这些内容为&lt;a href=&#34;https://github.com/istio/istio/wiki/Mixer-Adapter-Dev-Guide&#34; target=&#34;_blank&#34;&gt;适配器&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;适配器是 Go 包的形式存在的，直接链接到 Mixer 二进制中。如果缺省适配器无法满足特定的用例，创建自己的适配器也是比较简单的。&lt;/p&gt;

&lt;h2 id=&#34;哲学&#34;&gt;哲学&lt;/h2&gt;

&lt;p&gt;本质上 Mixer 这个模块就是用来处理属性和路由的。代理把&lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/attributes.html&#34; target=&#34;_blank&#34;&gt;属性&lt;/a&gt;作为前置检查和遥测报告的一部分发送出来，转换为对适配器的一系列调用。运维人员提供了用于描述如何将属性转换为适配器指令的配置。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://istio.io/docs/concepts/policy-and-control/img/mixer-config/machine.svg&#34; alt=&#34;Attribute Machine&#34; /&gt;&lt;/p&gt;

&lt;p&gt;配置是一个复杂的任务。有证据表明，绝大多数的服务中断都来自于配置错误。为了解决这一问题，Mixer 加入了很多限制来避免错误。例如在配置中使用强类型，以此保障在任何上下文中都只能使用有意义的属性或表达式。&lt;/p&gt;

&lt;h2 id=&#34;handler-适配器的配置&#34;&gt;Handler：适配器的配置&lt;/h2&gt;

&lt;p&gt;Mixer 使用的每个适配器都需要一些配置来进行操作。一般来说适配器需要一些数据进项实例化，例如后端的 URL、认证信息、缓存选项等等。每个适配器使用一个 &lt;a href=&#34;https://developers.google.com/protocol-buffers/&#34; target=&#34;_blank&#34;&gt;protobuf&lt;/a&gt; 消息来定义所需的配置数据。&lt;/p&gt;

&lt;p&gt;可以通过创建 &lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/mixer-config.html#handlers&#34; target=&#34;_blank&#34;&gt;Handler&lt;/a&gt; 的方式来为适配器提供配置。Handler 就是一套能让一个适配器就绪的完整配置。对同一个适配器可以有任意数量的 Handler，这样就可以在不同场景下复用了。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;例如：memquota 适配器，可以配置多个不同的 Handler，用于进行不同的限制。
或者同类服务的不同服务端点的实例&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;template-模板-适配器的输入结构-schema&#34;&gt;Template（模板？）：适配器的输入结构（Schema）&lt;/h2&gt;

&lt;p&gt;一个请求到达 Mesh 中的服务时，一般会发生两次对 Mixer 的调用，一次是前置检查，一次是遥测报告。每一次这种调用，Mixer 都需要调用一个或更多的适配器。不同的适配器需要不同的数据块作为输入来进行处理。例如日志适配器需要日志输入，指标适配器需要指标输入，认证适配器需要凭据输入。适配器在请求时消费的数据就是由 Mixer 的 &lt;a href=&#34;https://istio.io/docs/reference/config/mixer/template/&#34; target=&#34;_blank&#34;&gt;Template&lt;/a&gt; 来描述的。&lt;/p&gt;

&lt;p&gt;每个 Template 对应一个 protobuf 消息。在运行时一个 Templates 描述了一系列的发送给一或多个适配器的数据。适配器和 Template 是多对多的关系，其对应关系由开发者决定。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/reference/config/mixer/template/metric.html&#34; target=&#34;_blank&#34;&gt;Metric（指标）&lt;/a&gt;和&lt;a href=&#34;https://istio.io/docs/reference/config/mixer/template/logentry.html&#34; target=&#34;_blank&#34;&gt;Logentry（日志条目）&lt;/a&gt;是最重要的两个 Template，分别用于描述工作负载的一个指标和一条日志。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Template 定义同样来自于 Adapter&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;instances-实例-属性映射&#34;&gt;Instances(实例？) ：属性映射&lt;/h2&gt;

&lt;p&gt;创建 &lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/mixer-config.html#instances&#34; target=&#34;_blank&#34;&gt;Instance&lt;/a&gt; 用于决定把什么数据发送给特定的适配器。Instance 决定了 Mixer 如何把来自代理的属性拆分为各种数据然后分发给不同的适配器。&lt;/p&gt;

&lt;p&gt;一般来说需要使用 &lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/mixer-config.html#attribute-expressions&#34; target=&#34;_blank&#34;&gt;Attribute Expression&lt;/a&gt; 来创建 Instance。属性表达式的功能是使用属性和常量来生成可以给 Instance 字段赋值的结果。&lt;/p&gt;

&lt;p&gt;每个 Instance 字段都有类型，类型的定义来自于 Template，每个&lt;a href=&#34;https://github.com/istio/api/blob/master/mixer/v1/config/descriptor/value_type.proto&#34; target=&#34;_blank&#34;&gt;属性也有类型&lt;/a&gt;，然后每个属性表达式还是有类型。只有类型一致的情况才可以进行赋值。例如不能把整数型的表达式赋值给字符串字段。强类型设计的目的就是降低配置出错引发的风险。&lt;/p&gt;

&lt;h2 id=&#34;rules-规则-把数据分发给适配器&#34;&gt;Rules（规则）：把数据分发给适配器&lt;/h2&gt;

&lt;p&gt;拼图的最后一块就是 &lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/mixer-config.html#rules&#34; target=&#34;_blank&#34;&gt;Rules&lt;/a&gt;，他负责告诉 Mixer，哪个 Instance 应该在什么时候发送给哪个 Handler。每个 Rule 包含了一系列的 Instance，以及将要发送这些 Instance 的目标 Handler。Mixer 被触发以后，就会调用指定的 Handler，令其处理指定的 Instance。&lt;/p&gt;

&lt;p&gt;Rules 包含有匹配断言，这一断言是一个返回布尔值的属性表达式。只有断言成功的属性表达式才会触发 Handler。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;符合条件的 Instance 被发给 Handler&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;未来&#34;&gt;未来&lt;/h2&gt;

&lt;p&gt;我们一直在尝试提高适配器的使用和开发的端到端体验。例如计划中包含很多特性来帮助用户更方便的创建 Tempalte。另外表达式语言也在不断地发展和成熟。&lt;/p&gt;

&lt;p&gt;长期来看，我们在评估如何让适配器不再直接连入 Mixer 的方式，这样会更加方便的进行开发和使用。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;新的 Mixer 适配器模型，设计目的是提供一个有弹性的框架，以此支持开放的基础设施后端。&lt;/p&gt;

&lt;p&gt;Handler 为适配器提供了配置，Template 在运行时能够决定不同的适配器需要的数据种类，数据经由 Instance，被 Rules 发送给一个或多个 Handler。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://istio.io/docs/concepts/policy-and-control/&#34; target=&#34;_blank&#34;&gt;策略和控制&lt;/a&gt;中介绍了更多的 Mixer 架构的内容，&lt;a href=&#34;https://istio.io/docs/reference/config/mixer/&#34; target=&#34;_blank&#34;&gt;Mixer 参考&lt;/a&gt;包含更多的 Template、Handler 以及 Rules 的内容。&lt;a href=&#34;https://github.com/istio/istio/tree/master/samples/bookinfo/kube&#34; target=&#34;_blank&#34;&gt;Bookinfo 示例中&lt;/a&gt;提供了对应的示例文件。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 的频率限制</title>
      <link>/post/rate-limit-with-istio/</link>
      <pubDate>Fri, 10 Nov 2017 08:24:46 +0800</pubDate>
      <guid>/post/rate-limit-with-istio/</guid>
      <description>

&lt;p&gt;本来这个应该是作为第三天“零散功能点”介绍的，结果目标规则部分遇到一个 bug 一直没得到修正，就拖
着了——然后后来发现自己这个想法挺无知的——零散的功能点非常多，非常大，而且文档非常弱，很难搞，只好
逐个介绍了。&lt;/p&gt;

&lt;h2 id=&#34;简介&#34;&gt;简介&lt;/h2&gt;

&lt;p&gt;调用频率限制这个功能其实也是比较常见的东西了。这里就不多做介绍了。下面简单粗暴的介绍一下测试要完
成的目标。&lt;/p&gt;

&lt;p&gt;测试中我们将使用两个服务，服务叫 workload，客户端叫 sleep，workload 服务正常返回群众喜闻乐见
的 “Hello World”，而 sleep 仅用来做 Shell 方便测试。&lt;/p&gt;

&lt;p&gt;测试过程将为 workload 建立规则：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;对于任意访问，十秒钟之内仅能访问两次；&lt;/li&gt;
&lt;li&gt;对于来自 sleep 的访问，十秒钟之内仅能访问一次&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;下面所有内容都在 default 命名空间进行&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;建立测试环境&#34;&gt;建立测试环境&lt;/h2&gt;

&lt;p&gt;编辑 workload.yaml 以及 sleep.yaml 之后，
我们使用如下命令运行(这两部分源码，只有些乌七八糟的标签和命名有点问题，其他很普通。
见最后页)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;istioctl kube-inject -f workload.yaml | kubectl apply -f -
istioctl kube-inject -f sleep.yaml | kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;kubectl get pods&lt;/code&gt; 确定 Pod 成功启动，也可以使用 curl 测试 NodePort，会得到 40x 的错误
页面。&lt;/p&gt;

&lt;h3 id=&#34;建立规则&#34;&gt;建立规则&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;quota.yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这部分内容规则来自：&lt;code&gt;https://istio.io/docs/reference/config/mixer/template/quota.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这个对象用于设置检测服务来源、目标的标准维度，下面我们设置的是利用服务名称来检测。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这部分可能存在 bug，官方介绍的 source 定义是 &lt;code&gt;source.labels[&amp;quot;app&amp;quot;] | source.service | &amp;quot;unknown&amp;quot;&lt;/code&gt;
我的理解是说首先获取服务 Pod 的 app 标签内容，如果没有，再获取服务名称。但是后面我们会看到，
删除&lt;code&gt;source.labels[&amp;quot;app&amp;quot;]&lt;/code&gt;的定义之后，最终生效的依旧是 app 标签，这也是为什么给 workload 加上这么多奇怪标签的原因。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: quota
metadata:
  name: requestcount
spec:
  dimensions:
    source: source.service | &amp;quot;unknown&amp;quot;
    sourceVersion: source.labels[&amp;quot;version&amp;quot;] | &amp;quot;unknown&amp;quot;
    destination:  destination.service | &amp;quot;unknown&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;handler.yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这一对象的定义来自：&lt;code&gt;https://istio.io/docs/reference/config/mixer/adapters/memquota.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;下面的代码对应我们之前的目的，任意访问都是每 10 秒钟两次，而特定源和目标的访问则是每 10 秒钟一
次。&lt;/p&gt;

&lt;p&gt;其中 quotas 部分，name 字段的来源是上面的 quota.yaml&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这个不知道是不是 bug，必须写上半个 fqdn。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dimentions 字段则需要使用 quota.yaml 定义的维度。这里的维度可以比 quota.yaml 中定义的
维度宽松（也就是少，例如定义三个，只使用其中的两个），可以理解，这也符合匹配的规则。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: memquota
metadata:
  name: handler
spec:
  quotas:
  - name: requestcount.quota.default
    maxAmount: 2
    validDuration: 10s
    overrides:
    - dimensions:
        destination: workload-pod.default.svc.cluster.local
        source: sleep.default.svc.cluster.local
      maxAmount: 1
      validDuration: 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;rule.yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这部分的定义参考：&lt;code&gt;https://istio.io/docs/reference/config/mixer/policy-and-telemetry-rules.html#istio.mixer.v1.config.Rule&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这个对象的作用就是，对于符合筛选条件的服务调用，使用对应的 handler 进行处理。&lt;/p&gt;

&lt;p&gt;这里的 handler 和 requestcount 两个字段的内容，也需要是&lt;code&gt;实例名称.对象类型&lt;/code&gt;的方式。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: quota
spec:
  actions:
  - handler: handler.memquota
    instances:
    - requestcount.quota
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;测试运行&#34;&gt;测试运行&lt;/h2&gt;

&lt;h3 id=&#34;集群外&#34;&gt;集群外&lt;/h3&gt;

&lt;p&gt;使用 curl 重复访问 NodePort 三次，会发现第三次出现：&lt;code&gt;RESOURCE_EXHAUSTED:Quota is exhausted for: RequestCount#&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这说明我们设置的通用规则生效了。&lt;/p&gt;

&lt;h3 id=&#34;集群内&#34;&gt;集群内&lt;/h3&gt;

&lt;p&gt;在 sleep pod 中同样执行 curl 三次，发现第二次就开始出现超限说明。&lt;/p&gt;

&lt;p&gt;上面两种情况，在超过时间窗口限制之后，都会自动恢复。&lt;/p&gt;

&lt;h2 id=&#34;幕后&#34;&gt;幕后&lt;/h2&gt;

&lt;p&gt;定义 quota 对象，在系统中会展现为一系列的计数器，计数器的维度就是quota 中的维度的笛卡尔积。如果在 validDuration 的时间窗口过期之前调用次数超过了 maxAmount 规定，Mixer 就会返回 RESOURCE_EXHAUSTED 给 Envoy，Envoy 则会反馈 429 代码给调用方。&lt;/p&gt;

&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;

&lt;p&gt;文档不完善的开源系统。。坑真大啊！&lt;/p&gt;

&lt;h2 id=&#34;源码&#34;&gt;源码&lt;/h2&gt;

&lt;h3 id=&#34;workload-的-deployment-和-service&#34;&gt;Workload 的 Deployment 和 Service：&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: workload-app
    version: http200
  name: workload-200
spec:
  replicas: 1
  selector:
    matchLabels:
      app: workload-pod
      version: http200
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: workload-pod
        version: http200
    spec:
      containers:
      - image: php:7.0-apache
        imagePullPolicy: IfNotPresent
        name: http200
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: workload-service
    version: http200
  name: workload-200
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30200
  selector:
    app: workload-pod
    version: http200
  sessionAffinity: None
  type: NodePort
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;sleep-的定义&#34;&gt;Sleep 的定义&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: sleep
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
    spec:
      containers:
      - name: sleep
        image: tutum/curl
        command: [&amp;quot;/bin/sleep&amp;quot;,&amp;quot;infinity&amp;quot;]
        imagePullPolicy: IfNotPresent
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>非缺省域名下 Istio 的使用</title>
      <link>/post/istio-with-non-standard-domain-name/</link>
      <pubDate>Sun, 22 Oct 2017 05:08:21 +0800</pubDate>
      <guid>/post/istio-with-non-standard-domain-name/</guid>
      <description>

&lt;p&gt;Kubernetes 缺省的域名为 &lt;code&gt;cluster.local&lt;/code&gt;，好死不死的，istio 的缺省安装也沿用了这一设定，
并且文档中并没有明确指出这一假设。Istio 中使用了大量的 FQDN 进行服务的甄别，域名不一致这样
的问题可以说是后患无穷。经过 101 号 issue 的讨论，得知 proxy 和 pilot 组件提供了域名的设置功能，大致用法如下：&lt;/p&gt;

&lt;h2 id=&#34;pilot&#34;&gt;Pilot&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kubectl edit deploy istio-pilot -n istio-system&lt;/code&gt; 或者编辑官方的 &lt;code&gt;istio.yaml&lt;/code&gt;，查找
&lt;code&gt;docker.io/istio/pilot:0.2.9&lt;/code&gt; 的容器，并在 args 一节中加入如下的两行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- --domain
- cloud.ctrm
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;proxy&#34;&gt;Proxy&lt;/h2&gt;

&lt;p&gt;这部分略讨厌，因为每个业务 Pod 中都会有 SideCar 加载，因此只能逐个修改，方法同样有两个，
一个是使用 &lt;code&gt;kubectl edit deploy [workload-deployment]&lt;/code&gt; 的方式，另外一个就是，保存
&lt;code&gt;istioctl kube-inject -f [workload.yaml]&lt;/code&gt; 输出的文本。同样在
&lt;code&gt;docker.io/istio/proxy_debug:0.2.9&lt;/code&gt; 所在容器的 args 一节中加入下面的参数：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- --domain
- cloud.ctrm
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这些 Deployment 修改之后，会进行更新，接下来 Pilot 和 Mixer 就能正确的识别和处理集群中的服务了。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio 0.2 发布：增强的 Service Mesh 以及多环境支持</title>
      <link>/post/istio-0.2-ann/</link>
      <pubDate>Wed, 11 Oct 2017 11:22:19 +0800</pubDate>
      <guid>/post/istio-0.2-ann/</guid>
      <description>

&lt;p&gt;在 2017 年 5 月 24 日，我们启动了 Istio —— 一个为微服务提供连接、监控和安全支持的平台。互联
网对我们投入了巨大的关注，开发、运维和合作伙伴的社区日益壮大，这一切让我们诚惶诚恐。0.1 版本
展示了 Kubernetes 环境下 Istio 的所有概念。&lt;/p&gt;

&lt;p&gt;今天我们高兴的宣布 0.2 版，这一版本在稳定和性能方面有了增强，在 Kubernetes 中提供了全集群范围内
的部署和 Sidecar 的自动注入功能，为 TCP 提供了策略和认证支持，Service Mesh 的扩展能力进一步
覆盖到了虚拟机上。另外，Istio 现在可以在 Kubernetes 之外的环境运行，例如 Consul/Nomad 或者
Eureka。除了核心功能之外，Istio 还为第三方公司和个人提供了扩展开发的能力。&lt;/p&gt;

&lt;h2 id=&#34;0-2-版本亮点&#34;&gt;0.2 版本亮点&lt;/h2&gt;

&lt;h3 id=&#34;提高可用性&#34;&gt;提高可用性&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;多命名空间支持：响应 0.1 版本的用户呼声，Istio 可以在集群范围内的多个命名空间内运行。&lt;/li&gt;
&lt;li&gt;TCP 服务的策略和安全支持：除了 HTTP 服务之外，我们为 TCP 服务加入了双向 TLS 认证以及策略支持。这使得我们所提供的观测、策略以及安全能力能够覆盖到更多 Kubernetes 应用之中。&lt;/li&gt;
&lt;li&gt;Sidecar 的自动注入：在 Kubernetes 1.7 加入了 Alpha 版本的 initializer 特性之后，可以利用这一能力将 Envoy sidecar 自动注入到应用之中了。这样就可以像没有 istio 之前一样，直接使用 kubectl 进行应用部署。&lt;/li&gt;
&lt;li&gt;使用自定义 CA 认证：让用户能够为 Istio CA 提供自己的 Key 并存储。签署的密钥和证书会加快CA 的重启。&lt;/li&gt;
&lt;li&gt;增强的路由和指标：支持 WebSocket、MongoDB 以及 Redis 协议。可以把断路器这样的能力应用到第三方服务中去。另外除去 Mixer 的指标之外，上百个来自于 Envoy 的关于所有接收、外发以及Service Mesh 内部的流量指标都可以使用 Prometheus 获取了。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;跨环境支持&#34;&gt;跨环境支持&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Mesh 扩展：Istio 的 Mesh 现在可以跨出 Kubernetes 为外部服务提供自动双向 TLS 认证、流量管理、监控以及策略的支持了。&lt;/li&gt;
&lt;li&gt;脱离 Kubernetes 运行：我们知道很多用户在使用其他的服务注册和编排方案，例如 Consul/Nomad 以及 Eureka。Istio Pilot 现在可以在 Kubernetes 之外，依赖上述系统独立运行了，并同时对运行于虚拟机和容器中的 Envoy 进行管理。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;加入-istio-共塑未来&#34;&gt;加入 Istio，共塑未来&lt;/h2&gt;

&lt;p&gt;我们还有很长的路要走，Roadmap 中包含了众多尚待实现的强大功能。我们希望下个版本能够继续增强可靠性、稳定性和对第三方的集成能力，以及多集群的支持。&lt;/p&gt;

&lt;p&gt;最简单的加入方法就是在众多的&lt;a href=&#34;https://github.com/istio/istio/blob/master/GROUPS.md&#34; target=&#34;_blank&#34;&gt;工作组&lt;/a&gt;中选择一个符合兴趣的加入进去。这些工作组会经常展开对范围内的 Issue 的讨论，并协助完善该领域的Roadmap。如果有对 Istio 社区的建议，可以加入每周的&lt;a href=&#34;https://docs.google.com/document/d/14ZCWMfEV9MPDYrjhKYMErVXHTZrSwJNMm1ztKo8efPw/&#34; target=&#34;_blank&#34;&gt;社区会议&lt;/a&gt;。另外还可以加入&lt;a href=&#34;https://github.com/istio/istio/blob/master/GROUPS.md#master-working-group-list&#34; target=&#34;_blank&#34;&gt;邮件列表&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;我们要感谢我们的强大社区，为 Istio 做出了测试、Bug 报告、代码以及成员沟通和无数的讨论等等各方面的贡献。这些贡献让项目在 Github 赢得了 3000 星的评价，以及几百个活跃成员。&lt;/p&gt;

&lt;p&gt;谢谢大家。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>istio 的自动注入</title>
      <link>/post/auto-injection-istio/</link>
      <pubDate>Fri, 29 Sep 2017 19:04:22 +0800</pubDate>
      <guid>/post/auto-injection-istio/</guid>
      <description>

&lt;p&gt;从小白角度上来讲，istio 的吸引力不在于那些花里胡哨或者说精彩纷呈的功能，而是&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;第一：背景深厚&lt;/li&gt;
&lt;li&gt;第二：可以流水线操作的一键注入功能&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;而目前的 0.2 预发布版又提供了自动注入功能，进一步提高了易用性。&lt;/p&gt;

&lt;h2 id=&#34;开始之前&#34;&gt;开始之前&lt;/h2&gt;

&lt;p&gt;istio 的 0.2.4 版本。&lt;/p&gt;

&lt;p&gt;根据官方文档，自动注入功能需要 Kubernetes 1.7.4 以上，并且需要启用两个 Alpha 功能，可以把
如下参数加入 kube-apiserver 的启动文件之中：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;--runtime-config=admissionregistration.k8s.io/v1alpha1=true
--runtime-config=batch/v2alpha1=true
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;开启自动注入功能&#34;&gt;开启自动注入功能&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;kubectl apply -f install/kubernetes/istio-initializer.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;等待运行结果。注意其中的镜像地址可以按需求进行编辑。&lt;/p&gt;

&lt;h2 id=&#34;测试自动注入&#34;&gt;测试自动注入&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;默认的规则中，这一功能对 kube-system kube-public 和 istio-system
这三个命名空间是无效的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在 Default 命名空间中，运行这样两个应用：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: service-one
  labels:
    app: service-one
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: http
  selector:
    app: service-one
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: service-one
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: service-one
    spec:
      containers:
      - name: app
        image: gcr.io/google_containers/echoserver:1.4
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: service-two
  labels:
    app: service-two
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: http-status
  selector:
    app: service-two
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: service-two
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: service-two
    spec:
      containers:
      - name: app
        image: gcr.io/google_containers/echoserver:1.4
        ports:
        - containerPort: 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;运行成功之后，我们可以看看自动注入对这两个 Deployment 做了什么：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kubectl get deploy service-one -o yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会看到返回内容中多了些东西：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;
...

annotations:
  sidecar.istio.io/status: injected-version-0.2.4

...

image: docker.io/istio/proxy:0.2.4
  imagePullPolicy: IfNotPresent

...

initContainers:
 - args:
   - -p
   - &amp;quot;15001&amp;quot;
   - -u
   - &amp;quot;1337&amp;quot;
   image: docker.io/istio/proxy_init:0.2.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;很明显的动了手脚，接下来获取一下 Pod 信息：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# kubectl get po | grep service
service-one-2087957768-fpqqd   2/2       Running           0          1h
service-two-875897890-tmfng    2/2       Running           0          1h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;测试 Pod 的功能：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kubectl exec -it service-one-2087957768-fpqqd -c app -- curl service-two:80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会看到从 Service one 的 pod 中使用 curl 访问 service-two 的服务，会被注入一些内容，
证明这一功能正常生效：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;...

HEADERS RECEIVED:
accept=*/*
content-length=0
host=service-two
user-agent=curl/7.47.0
x-b3-sampled=1
x-b3-spanid=0000c703da4c3c5d
x-b3-traceid=0000c703da4c3c5d
x-envoy-expected-rq-timeout-ms=15000
x-forwarded-proto=http
x-ot-span-context=0000c703da4c3c5d;0000c703da4c3c5d;0000000000000000
x-request-id=207c124e-36ee-973e-bcc0-84dc70b8c71f

...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;幕后&#34;&gt;幕后&lt;/h2&gt;

&lt;p&gt;istio 会根据存储于&lt;code&gt;istio-inject&lt;/code&gt; config-map 中的策略，对集群中的新的工作负载进行监控，
如果有了符合条件的对象生成，就会利用 PATCH 方法对对象进行更新，注入所需内容。&lt;/p&gt;

&lt;p&gt;缺省策略如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-inject
  namespace: istio-system
data:
  config: |-
    policy: &amp;quot;enabled&amp;quot;
    namespaces: [&amp;quot;&amp;quot;] # 除了几个特定名称之外的所有命名空间
    initializerName: &amp;quot;sidecar.initializer.istio.io&amp;quot;
    params: # 自定义 sidecar 执行参数
      initImage: docker.io/istio/proxy_init:0.2.4
      proxyImage: docker.io/istio/proxy:0.2.4
      verbosity: 2
      version: 0.2.4
      meshConfigMapName: istio
      imagePullPolicy: IfNotPresent
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;policy&#34;&gt;Policy&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;off&lt;/strong&gt;：关闭注入&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;disabled&lt;/strong&gt;：禁用注入，但是可以设置&lt;code&gt;sidecar.istio.io/inject&lt;/code&gt;标签为&lt;code&gt;true&lt;/code&gt;，来强制开启。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;enabled&lt;/strong&gt;：启用注入，可以设置&lt;code&gt;sidecar.istio.io/inject&lt;/code&gt;标签为&lt;code&gt;false&lt;/code&gt;来关闭这一功能。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>istio 三日谈之二 路由规则</title>
      <link>/post/istio-route-rules/</link>
      <pubDate>Fri, 28 Jul 2017 17:35:28 +0800</pubDate>
      <guid>/post/istio-route-rules/</guid>
      <description>

&lt;p&gt;路由控制是 istio 的最常用功能了，经过前面的准备，我们已经基本可以进行这些内容的尝试了。&lt;/p&gt;

&lt;p&gt;注意下面的路由规则都忽略了对来源的过滤，会显得比较呆板或者说没用，但是在加入过滤条件之后，就完全不可同日而语了。具体的过滤规则的写法可以参考官方文档或者 istio 中的 bookinfo 实例。&lt;/p&gt;

&lt;h2 id=&#34;创建-frontend-v2&#34;&gt;创建 frontend-v2&lt;/h2&gt;

&lt;p&gt;为了展示路由分配的能力，我们首先创建一个名为&lt;code&gt;frontend-v2&lt;/code&gt;的&lt;code&gt;Deployment&lt;/code&gt;，这个&lt;code&gt;deploy&lt;/code&gt;跟之前的 v1 共享同一个 PVC，也就是共享同一套页面。利用环境变量来控制输出。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: frontend-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: frontend
        version: &amp;quot;2&amp;quot;
    spec:
      containers:
      - name: php
        image: 10.211.55.86:5000/php:7.1.7-apache
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: wwwroot
          mountPath: /var/www/html
        env:
        - name: &amp;quot;SERVICE_VERSION&amp;quot;
          value: &amp;quot;2&amp;quot;
      volumes:
      - name: wwwroot
        persistentVolumeClaim:
          claimName: frontend-v1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;同前面的 v1 一样，这个&lt;code&gt;Deployment&lt;/code&gt;也需要使用&lt;code&gt;istioctl kube-inject&lt;/code&gt;进行注入，最后使用&lt;code&gt;kubectl apply -f&lt;/code&gt; 运行。&lt;/p&gt;

&lt;h2 id=&#34;流量分配&#34;&gt;流量分配&lt;/h2&gt;

&lt;h3 id=&#34;首先创建如下路由规则&#34;&gt;首先创建如下路由规则&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;default.yaml&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: frontend-default
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 1
  route:
  - tags:
      version: &amp;quot;2&amp;quot;
    weight: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;destination：必须是服务的 fqdn&lt;/li&gt;
&lt;li&gt;precedence：整数，优先级，越大越先&lt;/li&gt;
&lt;li&gt;route：数组

&lt;ul&gt;
&lt;li&gt;tag：&lt;strong&gt;Pod&lt;/strong&gt; 的标签选择器。&lt;/li&gt;
&lt;li&gt;weigh: 整数，权重，分配到当前路由的比率。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;创建之后，使用&lt;code&gt;istioctl create -f default.yaml&lt;/code&gt;，创建这一规则。接下来我们使用&lt;code&gt;kubectl exec -it&lt;/code&gt;进入 tool pod 进行测试：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ curl svc-frontend/index.php

-----------------------------
From: frontend-797054967-r12m5
Version: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;返回内容表明这一服务调用的是最初的 v1 版本的 frontend。&lt;/p&gt;

&lt;p&gt;接下来修改 default.yaml 的&lt;code&gt;version &amp;quot;1&amp;quot;&lt;/code&gt;为&lt;code&gt;version &amp;quot;2&amp;quot;&lt;/code&gt;，然后用&lt;code&gt;istioctl replace -f default.yaml&lt;/code&gt;更新路由规则。再次验证：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ curl svc-frontend/index.php

-----------------------------
From: frontend-v2-90739004-xpmrn
Version: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里可以看到，这一响应来自于 v2 版本的 Pod，并且返回的版本号也是 2。&lt;/p&gt;

&lt;p&gt;然后我们再次修改路由规则，测试一下路由分配：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: frontend-default
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 1
  route:
  - tags:
      version: &amp;quot;2&amp;quot;
    weight: 10
  - tags:
      version: &amp;quot;1&amp;quot;
    weight: 90
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;根据上面的路由规则，对  svc-frontend 这一服务的访问，应该有 10% 流量分给版本 2，其余的 90% 分配给了版本 1。我们在 tool pod 中使用如下脚本测试这一分配：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
for i in {1..100}
do
  curl -s svc-frontend/index.php | grep Version
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;执行效果：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$  ./curl.batch.sh  | grep 2 | wc -l
10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，完全符合之前我们的路由设置。&lt;/p&gt;

&lt;h2 id=&#34;超时策略&#34;&gt;超时策略&lt;/h2&gt;

&lt;p&gt;为了保障服务质量，我们有时会要求对某些服务的返回时间进行限制&lt;/p&gt;

&lt;p&gt;前面提到，我们生成了一个&lt;code&gt;delay.php&lt;/code&gt;，用于进行延时测试，文件内容如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
header(&amp;quot;Content-type: text/plain&amp;quot;);
sleep(4);
echo &amp;quot;\n-----------------------------\n&amp;quot;;
echo &amp;quot;\nFrom: &amp;quot;.gethostname().&amp;quot;\n&amp;quot;;
echo &amp;quot;Version: &amp;quot;.$_ENV[&#39;SERVICE_VERSION&#39;].&amp;quot;\n&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;正常执行&lt;code&gt;time curl -s svc-frontend/delay.php&lt;/code&gt;，会返回如下结果：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-----------------------------
From: frontend-797054967-r12m5
Version: 1

real    0m4.025s
user    0m0.005s
sys     0m0.004s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我们在这里加入一个策略，两秒超时：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: front-timeout
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 9
  route:
  - tags:
      version: &amp;quot;1&amp;quot;
  httpReqTimeout:
    simpleTimeout:
      timeout: 2s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次测试，则会返回超时的结果：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;upstream request timeout
real    0m2.015s
user    0m0.006s
sys     0m0.003s
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;重试策略&#34;&gt;重试策略&lt;/h2&gt;

&lt;p&gt;在服务超时的时候，我们可能会希望请求自动重试。&lt;/p&gt;

&lt;p&gt;这一测试要求保留前面的超时策略，以便形成失败结果：&lt;/p&gt;

&lt;p&gt;策略文件如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: front-timeout
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 9
  route:
  - tags:
      version: &amp;quot;1&amp;quot;
  httpReqRetries:
    simpleRetry:
      attempts: 3
      perTryTimeout: 2s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里表示每次尝试的超时时间是两秒，重试三次。使用 curl 测试：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ time curl -s svc-frontend/delay.php
upstream request timeout
real    0m8.136s
user    0m0.005s
sys     0m0.006s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;时间为 8 秒，相当于四次超时的时间。&lt;/p&gt;

&lt;h2 id=&#34;rewrite&#34;&gt;Rewrite&lt;/h2&gt;

&lt;p&gt;和反向代理的情况类似，有时我们需要对进入服务的 URL 进行重写，下面的路由策略会将 &lt;code&gt;/front&lt;/code&gt; 替换为 &lt;code&gt;/&lt;/code&gt; 进行访问：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: front-timeout
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 9
  match:
    httpHeaders:
      uri:
        prefix: &amp;quot;/front/&amp;quot;
  rewrite:
    uri: &amp;quot;/&amp;quot;
  route:
  - tags:
      version: &amp;quot;1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;注意这里对&lt;code&gt;uri&lt;/code&gt;的操作，是使用 rewrite 中的 uri 替换 match 中的 uri，二者的对应关系是强制的。&lt;/p&gt;

&lt;p&gt;在 tool 里面进行测试访问：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ curl http://svc-frontend/front/index.php
-----------------------------

From: frontend-797054967-r12m5
Version: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;故障注入&#34;&gt;故障注入&lt;/h2&gt;

&lt;p&gt;微服务测试过程中，能够自动生成一些错误，无疑是个很有帮助的事情。目前 istio 支持两种故障的模拟：时延和中断&lt;/p&gt;

&lt;h2 id=&#34;时延&#34;&gt;时延&lt;/h2&gt;

&lt;p&gt;下面的规则会为每个对该服务的请求都生成 7 秒的时延：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: fdelay
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 9
  route:
  - tags:
      version: &amp;quot;1&amp;quot;
  httpFault:
    delay:
      percent: 100
      fixedDelay: 7s
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;percent: 产生时延的比例&lt;/li&gt;
&lt;li&gt;fixedDelay: 时间&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用 curl 验证，可以看到的确多出了 7 秒的处理时间。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ time curl -s http://svc-frontend/index.php
-----------------------------

From: frontend-797054967-r12m5
Version: 1

real    0m7.028s
user    0m0.007s
sys     0m0.003s
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;中断&#34;&gt;中断&lt;/h2&gt;

&lt;p&gt;这一功能可以模拟服务中断的情景，下面的 yaml 定义了该服务 100% 会返回 403 错误。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;type: route-rule
name: fdelay
spec:
  destination: svc-frontend.default.svc.cluster.local
  precedence: 9
  route:
  - tags:
      version: &amp;quot;1&amp;quot;
  httpFault:
    abort:
      percent: 100
      httpStatus: 403
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;curl 的验证结果如下：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$  curl -v svc-frontend/error.php
* Connected to svc-frontend (10.100.186.68) port 80 (#0)
&amp;gt; GET /error.php HTTP/1.1
&amp;gt; User-Agent: curl/7.38.0
&amp;gt; Host: svc-frontend
&amp;gt; Accept: */*
&amp;gt;
&amp;lt; HTTP/1.1 403 Forbidden
&amp;lt; date: Fri, 28 Jul 2017 01:27:52 GMT
* Server envoy is not blacklisted
&amp;lt; server: envoy
&amp;lt; content-length: 0
&amp;lt;
* Connection #0 to host svc-frontend left intact
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>istio 三日谈之一，环境准备</title>
      <link>/post/istio-env-prepare/</link>
      <pubDate>Fri, 28 Jul 2017 07:00:12 +0800</pubDate>
      <guid>/post/istio-env-prepare/</guid>
      <description>

&lt;p&gt;笔者尝试在一个准生产环境下，利用 istio 来对运行在 Kubernetes 上的微服务进行管理。&lt;/p&gt;

&lt;p&gt;这一篇是第一篇，将一些主要的坑和环境准备工作。&lt;/p&gt;

&lt;p&gt;内容较多，因此无法写成手把手教程，希望读者有一定 Kubernetes 的操作基础。&lt;/p&gt;

&lt;h2 id=&#34;准备镜像&#34;&gt;准备镜像&lt;/h2&gt;

&lt;p&gt;初始运行需要的镜像包括以下几个：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;istio/mixer:0.1.6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pilot:0.1.6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;proxy_debug:0.1.6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;istio-ca:0.1.6&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;首先要解决的自然还是镜像的存放问题，官方在源码中提供了很方便的工具，用来根据模板生成在 Kubernetes 中运行 istio 的 YAML 文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./updateVersion.sh \
	-p 10.211.55.86:5000/istio,0.1.6 \
	-c 10.211.55.86:5000/istio,0.1.6 \
	-x 10.211.55.86:5000/istio,0.1.6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这一脚本在源码的 install 目录下。&lt;/p&gt;

&lt;h2 id=&#34;kubernetes-环境&#34;&gt;Kubernetes 环境&lt;/h2&gt;

&lt;p&gt;这里我们使用的集群大概情况是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.7.1 版本的 Kubernetes&lt;/li&gt;
&lt;li&gt;开启了 RBAC&lt;/li&gt;
&lt;li&gt;预备使用的命名空间为：default&lt;/li&gt;
&lt;li&gt;PVC 自动供给&lt;/li&gt;
&lt;li&gt;无互联网连接&lt;/li&gt;
&lt;li&gt;具有自己的私库&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;启动-istio&#34;&gt;启动 istio&lt;/h2&gt;

&lt;h3 id=&#34;rbac-相关&#34;&gt;RBAC 相关&lt;/h3&gt;

&lt;p&gt;首先，install 目录中提供的 rbac 文件授权范围不足，所以需要手工编辑&lt;code&gt;istio-rbac-beta.yaml&lt;/code&gt;，把其中的几个 RoleBinding，改为 ClusterRoleBinding。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kubectl create \
	-f istio-rbac-beta.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;另外缺省的 ClusterRole 中缺乏对 Namespace 的权限，新版本已经修正，目前版本仍需添加：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: istio-pilot
rules:
- apiGroups: [&amp;quot;istio.io&amp;quot;]
  resources: [&amp;quot;istioconfigs&amp;quot;, &amp;quot;istioconfigs.istio.io&amp;quot;]
  verbs: [&amp;quot;*&amp;quot;]
- apiGroups: [&amp;quot;extensions&amp;quot;]
  resources: [&amp;quot;thirdpartyresources&amp;quot;, &amp;quot;thirdpartyresources.extensions&amp;quot;, &amp;quot;ingresses&amp;quot;, &amp;quot;ingresses/status&amp;quot;]
  verbs: [&amp;quot;*&amp;quot;]
- apiGroups: [&amp;quot;&amp;quot;]
  resources: [&amp;quot;configmaps&amp;quot;, &amp;quot;endpoints&amp;quot;, &amp;quot;pods&amp;quot;, &amp;quot;services&amp;quot;]
  verbs: [&amp;quot;*&amp;quot;]
- apiGroups: [&amp;quot;&amp;quot;]
  resources: [&amp;quot;namespaces&amp;quot;, &amp;quot;nodes&amp;quot;, &amp;quot;secrets&amp;quot;]
  verbs: [&amp;quot;get&amp;quot;, &amp;quot;list&amp;quot;, &amp;quot;watch&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;启动-istio-组件&#34;&gt;启动 istio 组件&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;kubectl create \
	-f istio.yaml \
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;创建-pvc&#34;&gt;创建 PVC&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: frontend-v1
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;准备工作负载&#34;&gt;准备工作负载&lt;/h2&gt;

&lt;p&gt;这里我们使用官方的 PHP + Apache 镜像作为工作负载来进行下面的测试，例如我们准备好的 YAML 如下：&lt;/p&gt;

&lt;p&gt;Deployment：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: frontend
  labels:
    name: frontend
    version: &amp;quot;1&amp;quot;
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: frontend
        version: &amp;quot;1&amp;quot;
    spec:
      containers:
      - name: php
        image: 10.211.55.86:5000/php:7.1.7-apache
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: wwwroot
          mountPath: /var/www/html
        env:
        - name: &amp;quot;SERVICE_VERSION&amp;quot;
          value: &amp;quot;1&amp;quot;      
     	volumes:
      - name: wwwroot
        persistentVolumeClaim:
          claimName: frontend-v1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;服务定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Service
apiVersion: v1
metadata:
  name: svc-frontend
  labels:
    name: frontend
    version: &amp;quot;1&amp;quot;
spec:
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 32010  
  selector:
    name: frontend

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在 Web 目录中我们随便做了个&lt;code&gt;index.php&lt;/code&gt;，用来展示当前所在 Pod 和环境变量中的服务版本号，备用。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tips：一般这类测试，我都懒得重新做一个 Docker 镜像，一般是另外用一个 Pod 挂载同一个 PVC，直接编辑页面文件，或者使用&lt;code&gt;kubectl cp&lt;/code&gt;命令进行拷贝。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;index-php&#34;&gt;index.php&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
header(&amp;quot;Content-type: text/plain&amp;quot;);
echo &amp;quot;From: &amp;quot;.gethostname().&amp;quot;\n&amp;quot;;
echo &amp;quot;Version: &amp;quot;.$_ENV[&#39;SERVICE_VERSION&#39;].&amp;quot;\n&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;delay-php&#34;&gt;delay.php&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;
&amp;lt;?php
header(&amp;quot;Content-type: text/plain&amp;quot;);
sleep(4);
echo &amp;quot;\n-----------------------------\n&amp;quot;;
echo &amp;quot;\nFrom: &amp;quot;.gethostname().&amp;quot;\n&amp;quot;;
echo &amp;quot;Version: &amp;quot;.$_ENV[&#39;SERVICE_VERSION&#39;].&amp;quot;\n&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;运行成功后，访问该服务的 nodePort，会看到相应的输出内容。&lt;/p&gt;

&lt;h2 id=&#34;istio-的注入&#34;&gt;istio 的注入&lt;/h2&gt;

&lt;p&gt;首先用&lt;code&gt;kubectl delete -f&lt;/code&gt;删除上文的服务和 Deployment。&lt;/p&gt;

&lt;p&gt;上面为了测试方便，给 Service 使用了 NodePort 类型，这里我们去掉这一服务的 NodePort，用 ClusterIP 的形式运行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    name: frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来进行注入操作&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;istioctl kube-inject -f frontend-v1.yaml &amp;gt; frontend-v1-istio.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;观察注入操作会发现，其中多了一个 Sidecar Container（下面的 Image 节内容已经被我修改为本地私库）：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    image: 10.211.55.86:5000/istio/proxy_debug:0.1.6
    imagePullPolicy: Always
    name: proxy
    resources: {}
    securityContext:
      runAsUser: 1337
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;另外还在&lt;code&gt;pod.beta.kubernetes.io/init-containers&lt;/code&gt;注解中进行了初始化：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;[{
  &amp;quot;args&amp;quot;: [&amp;quot;-p&amp;quot;, &amp;quot;15001&amp;quot;, &amp;quot;-u&amp;quot;, &amp;quot;1337&amp;quot;],
  &amp;quot;image&amp;quot;: &amp;quot;10.211.55.86:5000/istio/init:0.1&amp;quot;,
  &amp;quot;imagePullPolicy&amp;quot;: &amp;quot;Always&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;init&amp;quot;,
  &amp;quot;securityContext&amp;quot;: {
    &amp;quot;capabilities&amp;quot;: {
      &amp;quot;add&amp;quot;: [&amp;quot;NET_ADMIN&amp;quot;]
    }
  }
}, {
  &amp;quot;args&amp;quot;: [&amp;quot;-c&amp;quot;, &amp;quot;sysctl -w kernel.core_pattern=/tmp/core.%e.%p.%t &amp;amp;&amp;amp; ulimit -c unlimited&amp;quot;],
  &amp;quot;command&amp;quot;: [&amp;quot;/bin/sh&amp;quot;],
  &amp;quot;image&amp;quot;: &amp;quot;10.211.55.86:5000/alpine&amp;quot;,
  &amp;quot;imagePullPolicy&amp;quot;: &amp;quot;Always&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;enable-core-dump&amp;quot;,
  &amp;quot;securityContext&amp;quot;: {
    &amp;quot;privileged&amp;quot;: true
  }
}]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到上面一共涉及三个镜像：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;docker.io/istio/proxy_debug:0.1&lt;/li&gt;
&lt;li&gt;docker.io/istio/init:0.1&lt;/li&gt;
&lt;li&gt;alpine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;经过一番折腾：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;原有 YAML&lt;/li&gt;
&lt;li&gt;注入，生成新的 YAML&lt;/li&gt;
&lt;li&gt;替换新 YAML 中的镜像地址&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;就把原有的容器应用封装成新的 istio 支持的微服务了。&lt;/p&gt;

&lt;h2 id=&#34;准备测试素材&#34;&gt;准备测试素材&lt;/h2&gt;

&lt;p&gt;另外我们需要准备一个工具服务，用于在 shell 中进行测试：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: tool
  labels:
    name: tool
    version: &amp;quot;1&amp;quot;
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: tool
        version: &amp;quot;1&amp;quot;
    spec:
      containers:
      - name: tool
        image: 10.211.55.86:5000/php:7.1.7-apache
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: wwwroot
          mountPath: /var/www/html
      volumes:
      - name: wwwroot
        persistentVolumeClaim:
          claimName: frontend-v1
---
kind: Service
apiVersion: v1
metadata:
  name: tool
  labels:
    name: tool
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    name: tool
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;同样的，这里也需要执行&lt;code&gt;istioctl kube-inject&lt;/code&gt;进行注入，运行之后，就得到一个运行于集群内部的 Linux Shell，&lt;strong&gt;istio 中的路由策略经常是客户端和服务器协同完成的，因此上客户和服务器的 Deployment 都需要进行注入操作&lt;/strong&gt;。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Istio，Kubernetes 的微服务支持</title>
      <link>/post/istio-for-kubernetes-microservice/</link>
      <pubDate>Sun, 16 Jul 2017 17:17:08 +0800</pubDate>
      <guid>/post/istio-for-kubernetes-microservice/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;参考资料：
&lt;a href=&#34;https://developer.ibm.com/dwblog/2017/istio/&#34; target=&#34;_blank&#34;&gt;https://developer.ibm.com/dwblog/2017/istio/&lt;/a&gt;
&lt;a href=&#34;http://blog.kubernetes.io/2017/05/managing-microservices-with-istio-service-mesh.html&#34; target=&#34;_blank&#34;&gt;http://blog.kubernetes.io/2017/05/managing-microservices-with-istio-service-mesh.html&lt;/a&gt;
&lt;a href=&#34;https://istio.io/docs/&#34; target=&#34;_blank&#34;&gt;https://istio.io/docs/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;简介&#34;&gt;简介&lt;/h2&gt;

&lt;p&gt;Istio 是一个由 IBM、Google 以及 Lyft 联合推出的开源软件，以无痛方式为运行在 Kubernetes 上的微服务提供流量管理，访问策略管理以及监控等功能。这一软件目前仅在 Kubernetes 上运行，今后可能会扩展到其他平台。本文会结合官方例子，完成安装和基础的监控内容。&lt;/p&gt;

&lt;h2 id=&#34;架构和组件&#34;&gt;架构和组件&lt;/h2&gt;

&lt;p&gt;总体架构如图所示。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://istio.io/docs/concepts/what-is-istio/img/architecture/arch.svg&#34; alt=&#34;arch&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;envoy&#34;&gt;Envoy&lt;/h3&gt;

&lt;p&gt;一个 C++ 编写的高性能代理服务器，这里做了扩展，在 Istio 中会以 Sidecar 方式跟应用运行在同一 Pod 内，一方面可以接收并执行关于规则、流量拆分等方面的指令，另一方面能够产生各种指标用于监控和跟踪。&lt;/p&gt;

&lt;h3 id=&#34;mixer&#34;&gt;Mixer&lt;/h3&gt;

&lt;p&gt;Mixer 组件，主要进行访问控制以及策略控制，同时也负责从 Envoy 中获取各项指标。&lt;/p&gt;

&lt;h3 id=&#34;pilot&#34;&gt;Pilot&lt;/h3&gt;

&lt;p&gt;Pilot 是用户和 Isito 之间的桥梁，负责接收各种配置，并发送给各个组件。&lt;/p&gt;

&lt;h3 id=&#34;istio-auth&#34;&gt;Istio auth&lt;/h3&gt;

&lt;p&gt;内置认证和凭证管理，利用 TLS 提供服务之间、用户和服务之间的认证。
可以用来将没有加密支持的服务升级为加密版本，并且在网络策略之外，提供服务级别的策略控制，今后还会增加更多的鉴权和审计方面的能力。&lt;/p&gt;

&lt;h3 id=&#34;功能-特性&#34;&gt;功能 &amp;amp; 特性&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;无需对现有服务进行变更&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;支持 http 1.1/2、gRPC 以及 TCP 流量的负载均衡和故障转移&lt;/li&gt;
&lt;li&gt;可替换的组件&lt;/li&gt;
&lt;li&gt;流量监控&lt;/li&gt;
&lt;li&gt;可提供身份认证功能&lt;/li&gt;
&lt;li&gt;可定制的路由规则&lt;/li&gt;
&lt;li&gt;错误处理，例如超时、重试、访问量控制、健康检查和熔断器等。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;

&lt;h3 id=&#34;先决条件&#34;&gt;先决条件&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;互联网连接&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;准备工作&#34;&gt;准备工作&lt;/h3&gt;

&lt;p&gt;首先去&lt;code&gt;https://github.com/istio/istio/releases&lt;/code&gt;下载最新版本（目前为 0.1.6），解压并设置 istioctl 命令的执行路径 。下面命令中描述的相对目录就是基于此目录&lt;/p&gt;

&lt;p&gt;执行命令&lt;code&gt;kubectl api-versions | grep rbac&lt;/code&gt;查看当前集群的 RBAC 设置：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;如果返回内容为空则无需理会。&lt;/li&gt;
&lt;li&gt;如果返回内容中包含&lt;code&gt;beta&lt;/code&gt;，则需要运行&lt;code&gt;kubectl apply -f install/kubernetes/istio-rbac-beta.yaml
&lt;/code&gt;来进行授权&lt;/li&gt;
&lt;li&gt;如果返回内容中只有&lt;code&gt;alpha&lt;/code&gt; ，就要&lt;code&gt;kubectl apply -f install/kubernetes/istio-rbac-beta.yaml
&lt;/code&gt;创建相应的角色和绑定了。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;运行&#34;&gt;运行&lt;/h3&gt;

&lt;p&gt;最后，运行&lt;code&gt;kubectl create -f install/kubernetes/istio.yaml&lt;/code&gt;创建一系列的 Deployment 以及 Services。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注1： 其实上面的内容照做并不一定能成功，反正我的 1.6.6 上面是没能成功，Pilot Pod 中的 API Server 容器会出错，错误信息大概是“system:serviceaccount:default:istio-pilot-service-account&amp;rdquo; cannot get thirdpartyresources.extensions at the cluster scope.”，也就证明了 beta.yaml 中的 RBAC 设置是不够的，这里我把几个 RoleBinding 都改成为 ClusterRoleBinding，运行就成功了。&lt;/p&gt;

&lt;p&gt;注2：istio.yaml 中的 Ingress 服务是 Loadbalancer 类型的，如果测试集群不具备这样的条件，还请自行修改成其他合适内容。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;至此，基础的 istio 组件就已经运行完毕了。&lt;/p&gt;

&lt;h2 id=&#34;运行应用&#34;&gt;运行应用&lt;/h2&gt;

&lt;p&gt;安装包内包含了一个叫 bookinfo 的小应用，由 Product（入口页）、Detail 和 Review 三部分组成，具体应用 YAML 在安装目录的&lt;code&gt;samples/apps/bookinfo/bookinfo-v1.yaml&lt;/code&gt;文件中。打开文件我们会发现这是个很简单的小应用，无非是几个 Deployment 和 Service 的组合。&lt;/p&gt;

&lt;p&gt;该应用的微服务相互关系大致如下图所示，这个例子很好的展示了 istio 的一大特性——不拘泥于某种语言。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;/sites/default/files/get_image/c26c9a2771b4008770270ba15c6a0f8f.png&#34; alt=&#34;v1&#34; /&gt;&lt;/p&gt;

&lt;p&gt;istio 提供了一个工具叫 istioctl，这个工具的功能之一，就是把普通的应用 YAML 注入为 istio 支持的应用模式，例如：&lt;code&gt;istioctl kube-inject -f bookinfo-v1.yaml &amp;gt; bookinfo-istio-v1.yaml&lt;/code&gt;，比较新旧两个文件不难发现，这一工具为每个 Pod 新增了一个名为 proxy 的容器，以此接管流量，给监控和管理打下基础。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;/sites/default/files/get_image/42138edb04f53163c7a97702cfc66698.png&#34; alt=&#34;v1+istio&#34; /&gt;&lt;/p&gt;

&lt;p&gt;接下来我们运行这一应用：
- &lt;code&gt;kubectl create -f bookinfo-istio-v1.yaml&lt;/code&gt;：运行注入后的 应用
- &lt;code&gt;kubectl create -f bookinfo-ingress.yaml&lt;/code&gt;：创建 Ingress 资源&lt;/p&gt;

&lt;h2 id=&#34;监控&#34;&gt;监控&lt;/h2&gt;

&lt;p&gt;istio 内置了对 ServiceGraph、Prometheus 以及 Zipkin 的支持，简单的运行一下&lt;code&gt;kubectl create -f install/kubernetes/addons&lt;/code&gt;，就会启用这几个服务。注意这几个服务使用的也都是 Loadbalancer 模式，读者应根据集群情况自行修改。&lt;/p&gt;

&lt;p&gt;各个服务启动之后，可以使用负载工具例如 wrk 对 Productpage 页面进行一段时间的访问，来模拟工作情况。&lt;/p&gt;

&lt;h2 id=&#34;grafana&#34;&gt;Grafana&lt;/h2&gt;

&lt;p&gt;Grafana 启动后，我们可以使用服务暴露的地址进行访问，在其中可以看到如下图所示的 Dashboard，展示了我们应用中的几个服务的各种监控数据。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;/sites/default/files/get_image/16a47d78ee8e4046f8e8a90f5ded543f.png&#34; alt=&#34;grafana&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;service-graph&#34;&gt;Service Graph&lt;/h2&gt;

&lt;p&gt;这一个服务提供了两个入口，一个是 &lt;code&gt;/dotvz&lt;/code&gt;，以图形的方式供服务关系展示，而&lt;code&gt;/graph&lt;/code&gt;则提供了 JSON 格式的文档供结构化使用。例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;quot;nodes&amp;quot;: {
        &amp;quot;details&amp;quot;: {},
        &amp;quot;productpage&amp;quot;: {},
        &amp;quot;reviews&amp;quot;: {},
        &amp;quot;unknown&amp;quot;: {}
    },
    &amp;quot;edges&amp;quot;: [
        {
            &amp;quot;source&amp;quot;: &amp;quot;productpage&amp;quot;,
            &amp;quot;target&amp;quot;: &amp;quot;reviews&amp;quot;,
            &amp;quot;labels&amp;quot;: {
                &amp;quot;qps&amp;quot;: &amp;quot;0.030416&amp;quot;,
                &amp;quot;version&amp;quot;: &amp;quot;v1&amp;quot;
            }
        },
        {
            &amp;quot;source&amp;quot;: &amp;quot;unknown&amp;quot;,
            &amp;quot;target&amp;quot;: &amp;quot;productpage&amp;quot;,
            &amp;quot;labels&amp;quot;: {
                &amp;quot;qps&amp;quot;: &amp;quot;0.030416&amp;quot;,
                &amp;quot;version&amp;quot;: &amp;quot;v1&amp;quot;
            }
        },
        {
            &amp;quot;source&amp;quot;: &amp;quot;productpage&amp;quot;,
            &amp;quot;target&amp;quot;: &amp;quot;details&amp;quot;,
            &amp;quot;labels&amp;quot;: {
                &amp;quot;qps&amp;quot;: &amp;quot;0.030416&amp;quot;,
                &amp;quot;version&amp;quot;: &amp;quot;v1&amp;quot;
            }
        }
    ]
}	
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;zipkin&#34;&gt;Zipkin&lt;/h2&gt;

&lt;p&gt;Istio 提供了开箱即用的 Zipkin 跟踪支持，打开页面之后，我们会看到 Zipkin 的查找页面，并无特殊内容，就不展开细谈了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;/sites/default/files/get_image/89331f5f59d1ba743b2d839763198946.png&#34; alt=&#34;zipkin&#34; /&gt;&lt;/p&gt;

&lt;p&gt;文中介绍内容只是很粗浅的入门操作，后续会进一步跟进、挖掘和学习这一系统的其他强大功能。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
