出口网关
出口网关是一个专用代理,所有到外部服务的出站流量都必须经过它。 它为离开网格的流量提供了一个可验证的出口点,您可以在其中应用授权策略、启用可观测性并发起 TLS。
在 Sidecar 模式中,
为单个主机配置出口网关需要协调五个单独的对象:一个 ServiceEntry、
一个 Gateway、两个 HTTPRoute 资源(一个用于将网格流量引导到网关,一个用于将流量从网关转发到目的地)和一个
DestinationRule。每个新的外部主机都会重复大部分工作。
在 Ambient 模式中,
waypoint 代理自然充当出口网关。
ztunnel 在将流量转发到目的地之前自动将流量路由到服务的 waypoint。
如果您将 ServiceEntry
放置在注册使用 waypoint 的命名空间中,则到该外部主机的所有网格流量都会自动通过该
waypoint,无需额外的路由规则。
在开始之前
在启用 Ambient 模式的情况下安装 Istio。
部署工作负载以用作流量源。curl 示例运行良好:
$ kubectl apply -f @samples/curl/curl.yaml@将工作负载的命名空间标记为 Ambient 模式,以便 ztunnel 拦截其流量:
$ kubectl label namespace default istio.io/dataplane-mode=ambient
设置出口命名空间
为出口资源创建专用命名空间。将外部服务定义及其策略与应用程序命名空间隔离, 可以简化管理并减少错误配置的影响范围。
$ kubectl create namespace istio-egress
$ kubectl label namespace istio-egress istio.io/dataplane-mode=ambient部署出口 waypoint
在出口命名空间中部署 waypoint 代理并注册命名空间以使用它。
--enroll-namespace 标志将 istio.io/use-waypoint 标签添加到命名空间,
因此其中定义的每个服务,包括由 ServiceEntry 支持的服务,都将通过该路径点进行路由。
请注意,Kubernetes Gateway API CRD 不会默认安装在大多数 Kubernetes 集群上, 因此请确保在使用 Gateway API 之前已安装好这些 CRD:
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml$ istioctl waypoint apply --for service --enroll-namespace --namespace istio-egress
✅ waypoint istio-egress/waypoint applied
✅ namespace istio-egress labeled with "istio.io/use-waypoint: waypoint"确认 waypoint 已准备好:
$ istioctl waypoint list -n istio-egress
NAME REVISION TRAFFIC TYPE PROGRAMMED
waypoint default service True定义外部服务
在出口命名空间中创建一个 ServiceEntry 来表示外部主机。
由于命名空间已注册为使用 waypoint,因此 ztunnel 会自动通过 waypoint 将所有网格流量路由到该主机。
默认情况下,ServiceEntry 在集群范围内可见(exportTo: *),
因此每个节点上的 ztunnel 都会将 httpbin.org 解析为 istio-egress waypoint,无需任何其他配置。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: httpbin-org
namespace: istio-egress
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
EOF验证通过出口 waypoint 的流量路径
从 curl Pod 向外部主机发送请求并确认其到达目的地:
$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://httpbin.org/get
200要确认经过该 waypoint 的流量,请检查该 waypoint 的 Envoy 统计数据:
$ kubectl exec -n istio-egress deploy/waypoint -c istio-proxy -- pilot-agent request GET stats | grep upstream_rq_total非零的 upstream_rq_total 计数(waypoint 向上游转发的请求数)确认 waypoint 正在充当出口网关。
强制执行访问策略
由于流量会经过 waypoint,因此您可以将 L7 授权策略直接附加到 ServiceEntry。
以下策略允许任何源仅向 /get 发出 GET 请求:
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin-org
namespace: istio-egress
spec:
targetRefs:
- kind: ServiceEntry
group: networking.istio.io
name: httpbin-org
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
paths: ["/get"]
EOF应用策略后,验证允许的请求是否成功:
$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://httpbin.org/get
200确认不被允许的请求遭到拒绝:
$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" -X POST http://httpbin.org/post
403在出口网关发起 TLS 连接
应用程序 Pod 可以将明文 HTTP 发送到出口网关;网关在转发到外部主机之前升级到 HTTPS。 这将 TLS 凭证管理集中在网关处,并避免将证书分发到每个应用程序 Pod。
更新 ServiceEntry 以将明文端口映射到 TLS 端口,
并添加 DestinationRule 以发起 TLS 连接:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: httpbin-org
namespace: istio-egress
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
targetPort: 443
resolution: DNS
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: httpbin-org-tls
namespace: istio-egress
spec:
host: httpbin.org
trafficPolicy:
tls:
mode: SIMPLE
EOF验证应用程序是否仍然收到响应,现在由网关通过 HTTPS 发送:
$ kubectl exec deploy/curl -- curl -s http://httpbin.org/get | head -5添加不带 TLS 发起(TLS origination)的外部服务
要通过同一出口路径点公开其他外部主机,请在同一命名空间中创建另一个 ServiceEntry。
不需要额外的 waypoint 配置,因为命名空间已经注册:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: example-com
namespace: istio-egress
spec:
hosts:
- example.com
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
EOF验证到新主机的流量是否也通过该 waypoint 路由:
$ kubectl exec deploy/curl -- curl -s -o /dev/null -w "%{http_code}" http://example.com
200命名空间中的每个 ServiceEntry 都会自动通过 waypoint 进行路由,
并且可以携带自己的 AuthorizationPolicy。
清理
$ kubectl delete namespace istio-egress
$ kubectl delete -f @samples/curl/curl.yaml@
$ kubectl label namespace default istio.io/dataplane-mode-参见
- 配置 waypoint 代理:常规 waypoint 部署和注册
- 要求流量经过 waypoint:强制出口流量不能绕过 waypoint
- ServiceEntry 可见性:控制哪些命名空间可以发现每个
ServiceEntry - 使用 L7 功能:waypoint 可用的 L7 策略和路由的完整列表
- 出口网关(Sidecar 模式):用于比较的等效 Sidecar 模式配置