创建sleep客户端

apiVersion: v1
kind: ServiceAccount
metadata:
name: sleep
---
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
spec:
ports:
- port: 80
name: http
selector:
app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
serviceAccountName: sleep
containers:
- name: sleep
image: pstauffer/curl
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
command:
- "/bin/sleep"
- "3650d"

创建ServiceEntry

创建一个ServiceEntry,允许流量直接访问外部服务

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS

我们通过在sleep客户端发送请求验证下ServiceEntry是否正确应用

kubectl exec -it sleep-f67b89b64-t42hv -- sh
curl -sL -o /dev/null -D - http://edition.cnn.com/politics

我们可以看下访问egress pod的日志,发现是没有这个访问日志的输出的

kubectl log -f istio-egressgateway-7c9f7d5bd6-hcf2x -n istio-system

配置egress Gateway和destination rule

我们为edition.cnn.com端口80创建一个egress gateway ,并且为egress gateway指向一个destination rule

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- edition.cnn.com
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn

配置VirtualService

将流量从sidercar引导到egress gateway,在从egress gateway引导到外部

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- 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: cnn
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 80
weight: 100

测试

通过sleep客户端访问 http://edition.cnn.com/politics

kubectl exec -it sleep-f67b89b64-t42hv -- sh
curl -sL -o /dev/null -D - http://edition.cnn.com/politics

可以看到egress pod的日志中有访问输出

kubectl log -f istio-egressgateway-7c9f7d5bd6-hcf2x -n istio-system

会有人疑问,我直接通过ServiceEntry也可以直接访问外部服务,为什么还要如此麻烦将出站流量都经过egress gateway呢?其实,我个人觉得有以下原因:第一,并不是所有节点都可以访问外网的,如果pod所在的节点无法访问外网,直接通过ServerEntry是无法访问外网的,那么egress gateway可以统一管理出站流量,所有出站流量都经由egress gateway发送;第二,通过egress gateway管理出站流量,可以配置一些网络策略,例如Kubernetes网络策略可以禁止所有不是从 egress gateway 发起的出站流量。