Istio 小入门 —— ServiceEntry 的对外通信

Posted 伪架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Istio 小入门 —— ServiceEntry 的对外通信相关的知识,希望对你有一定的参考价值。

上一篇讲了一些入口流量的事情,在实际项目运行中,还有另外一类边界流量,就是出口流量,也常被称为 egress 流量。这一篇结合一点实际需求,设计一些常用场景,讲讲服务网格中对外部服务的调用过程。

这里我们需要几个服务定义,首先是用于模拟客户端服务的工作负载,这里继续使用 dustise/sleep 镜像。外部我们使用两个网站作为我们的外部服务演示,分别代表 httphttps 两种:http://httpbin.orghttps://api.jd.com/

开始之前

根据安装文档的说明完成 Istio 的部署,这里建议使用 Helm 方式。

使用的 dustise/sleep 镜像生成两个负载,使用 version 标签将负载拆分为 v1v2 两个版本。源码见文末。

$ istioctl kube-inject -f sleep.dual.yaml | kubectl apply -f -
service/sleep created
deployment.extensions/sleep-v1 created
deployment.extensions/sleep-v2 created

然后使用环境变量保存新建 Pod 名称:

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})

创建 ServiceEntry

首先创建一个 ServiceEntry,指向 httpbin.org:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS

然后给 api.jd.com 创建一个 ServiceEntry:

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

发起外部访问

$ kubectl exec -it $SLEEP_V1 -c sleep sh
/ # curl http://httpbin.org/ip{  "origin": "168.63.251.242"}
/ # curl https://api.jd.com<html>
...
</html>
/ # curl -v http://api.jd.com...
< HTTP/1.1 404 Not Found
...
* Connection #0 to host api.jd.com left intact

可以看到,已经注册了的主机,可以通过对应的协议来进行访问了,但是如果协议不匹配,也会返回 404 代码。后面的内容,会选择几个常见场景进行演示。

服务质量监控

Istio 提供了很多的指标数据,对于外部服务来说,其服务端并不受控,但是还是可以从客户端获取一定的指标,来判断服务的状态。例如用下面的命令生成负载之后:

kubectl exec -it $SLEEP_V2 -c sleep -- wrk -d 10m http://httpbin.org/

可以在 Grafana 中看到如下的图形:

设置超时限制

外部应用的服务质量通常是不受调用方管理的,为了防止意外超时拖累整体应用,我们可以给外部服务设置一个超时限制,超过这一规则的调用直接中断。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin-service
spec:
  hosts:
  - httpbin.org
  http:
  - timeout: 3s
    route:
    - destination:
        host: httpbin.org

应用之后,再次进入 Pod 执行指令访问 http://httpbin.org

$ 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 >> /dev/nullreal    0m 2.51s
user    0m 0.00s
sys     0m 0.00s
/ # time curl -sSL http://httpbin.org/delay/5upstream request timeout
real    0m 3.01s
user    0m 0.00s
sys     0m 0.00s

上面的测试可以看出,第二次的延迟五秒调用已经返回了超时的结果,并且是在我们的三秒限制之内完成了调用。

使用 kubectl delete -f httpbin-timeout.yaml 删除这一定义,进行下一步。

仅允许指定源头访问

设想我们的网格中,仅有部分应用可以访问一些外部服务,这里我们借用 Istio 的故障注入功能,定义一个 abort 的注入,只允许 sleep:v2 访问 http://httpbin.org,其他服务的访问尝试会失败。

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

上面的定义中,我们首先让 sleep:v2 的筛选条件的请求,转发给 httpbin.org;而其余流量,则会被注入一个 403 错误。

我们分别从 sleep:v1sleep:v2 服务发起对 httpbin.org 的访问:

$ kubectl exec  $SLEEP_V2 -c sleep -- curl -s http://httpbin.org/ip
{  "origin": "168.63.251.242"}
$ kubectl exec  $SLEEP_V1 -c sleep -- curl -s -v http://httpbin.org/ip
*   Trying 52.72.80.190...
...
< HTTP/1.1 403 Forbidden
< content-length: 18< content-type: text/plain
< date: Wed, 22 Aug 2018 06:20:04 GMT
< server: envoy
<
{ [18 bytes data]
* Connection #0 to host httpbin.org left intactfault filter abort%

可以看到,结果和我们的预测是一致的。

To be continued

上面所述,只是针对 ServiceEntry 的一些粗浅应用,Istio 还提供了 Egress Gateway 这样的高级组件。可以提供更多管理能力,敬请期待。

相关链接

  1. 安装文档:https://istio.io/zh/docs/setup/kubernetes/

  2. RBAC:https://istio.io/zh/docs/tasks/security/role-based-access-control/

  3. 基于 Mixer Adaptor 的访问控制:https://istio.io/zh/docs/tasks/policy-enforcement/denial-and-list/

部分源码

sleep.yaml

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

以上是关于Istio 小入门 —— ServiceEntry 的对外通信的主要内容,如果未能解决你的问题,请参考以下文章

Istio ServiceEntry 引入外部服务

idou教你学Istio: 如何用Istio实现K8S Egress流量管理

idou教你学Istio10 : 如何用Istio实现K8S Egress流量管理

istio 0.8 TLS 简单测试

315 · Istio1.1 功能预告,真的假不了

Istio入门