<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>egress | 伪架构师</title>
    <link>/tags/egress/</link>
      <atom:link href="/tags/egress/index.xml" rel="self" type="application/rss+xml" />
    <description>egress</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Fri, 24 Aug 2018 11:46:24 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>egress</title>
      <link>/tags/egress/</link>
    </image>
    
    <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>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>
    
  </channel>
</rss>
