概述
ServiceEntry 也是 Istio 中的一个重要的 API 资源对象。
它可以将外部的服务添加到网格的内部,从而可以实现管理集群内部服务调用外部服务的请求,达到扩展网格的目的。
示例图如下所示:
实战
场景描述
在本文中,我们会将 httpbin 注册为网格内的服务,并配置相关的流控策略。
通过本文的学习,我们相信你能够掌握:
- 学会通过 ServiceEntry 扩展网格。
- 掌握 ServiceEntry 的配置方法。
StepByStep
Step1:添加 sleep 服务作为客户端
kubectl apply -f samples/sleep/sleep.yaml -n istio-demo
# serviceaccount/sleep created
# service/sleep created
# deployment.apps/sleep created
Step2:试用外部服务 httpbin
为了模拟外部服务,我们使用了一个开放的 httpbin.org 网站。
它是一个简单的可以用于 HTTP 请求的测试的网站服务,可以使用浏览器打开。
它提供了很多常用的 api 可以用于测试 HTTP 请求。
例如:http://httpbin.org/headers
此时,我们可以用我们刚才创建的 sleep 容器作为客户端来测试一下调用 httpbin 服务的效果:
export POD_NAME=$(kubectl get pods -n istio-demo -l app=sleep -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -n istio-demo -c sleep curl http://httpbin.org/headers
Step3:关闭网格内服务直接访问外部权限
为了验证 ServiceEntry 的功能,下面,我们先来临时关闭网格内服务直接访问网格外部服务的权限,而仅允许访问注册了的网格外部服务。
配置方式如下:
kubectl edit cm istio -n istio-system
在 mesh 的配置中将 outboundTrafficPolicy 的 mode 修改为 REGISTRY_ONLY ,然后保存即可。
稍等片刻,再次重新访问一下 http://httpbin.org/headers 服务:
export POD_NAME=$(kubectl get pods -n istio-demo -l app=sleep -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -n istio-demo -c sleep curl http://httpbin.org/headers
你会发现此时已经看不到响应信息了,说明上述策略已经生效啦!
Step4:为外部服务(httpbin)配置ServiceEntry
下面我们来定义一个 ServiceEntry,配置文件为 serviceentry.yaml 。
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
我们让它生效一下:
kubectl apply -f ./samples/bookinfo/networking/serviceentry.yaml -n istio-demo
# serviceentry.networking.istio.io/httpbin-ext created
然后再次重新调用一下 httpbin.org 服务看看:
export POD_NAME=$(kubectl get pods -n istio-demo -l app=sleep -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -n istio-demo -c sleep curl http://httpbin.org/headers
又正常可以访问啦,说明我们的 ServiceEntry 已经正常生效啦!
原理说明
配置分析
下面,我们来了解一下刚才的配置文件表示的含义吧:
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
其中:
- hosts: 表示注册的服务名称;
- ports: 表示注册的端口;
- resolution: 表示解析注册服务名称的方式;
- location:表示注册服务真实的位置。
翻译一下就是:我们需要注册一个 http://httpbin.org:80 的服务,这个服务在 MESH 网格外部,访问该服务时,可以通过 DNS 的方式来解析真实的地址。
资源配置项
上述的配置是一个非常简单的配置方式,下面,我们来了解一下服务入口的完整的配置:
- hosts 表示定义的外部服务的名称。
- addresses 和 hosts 比较类似,可以认为是外部服务的 IP。
- ports 表示具体的外部服务的端口信息和协议。
- endpoints 可以用于定义具体的节点。
- resolution 表示服务发现的方式,支持 NONE,STATIC和DNS三种方式。
- location 表示该服务是在 MESH 内部还是外部。
思考与实战
配置一个 https 协议的服务入口
如果我们修改一下上述的 curl 命令,将 http 协议修改为 https 协议会发生什么呢?
kubectl exec -it $POD_NAME -n istio-demo -c sleep curl https://httpbin.org/headers
# curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to httpbin.org:443
# command terminated with exit code 35
你会看到请求失败了,但是 httpbin.org 网站本身其实是支持 https 协议的,失败的原因正是在于我们注册的 ServiceEntry 仅支持了 http 协议,没有支持 https 协议。
下面,我们修改一下 serviceentry.yaml 配置文件如下:
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: TLS
resolution: DNS
location: MESH_EXTERNAL
然后更新一下配置:
kubectl apply -f ./samples/bookinfo/networking/serviceentry.yaml -n istio-demo
再看访问看看:
kubectl exec -it $POD_NAME -n istio-demo -c sleep curl https://httpbin.org/headers
不错,又可以啦!