出口网关

出口网关是一个专用代理,所有到外部服务的出站流量都必须经过它。 它为离开网格的流量提供了一个可验证的出口点,您可以在其中应用授权策略、启用可观测性并发起 TLS。

在 Sidecar 模式中, 为单个主机配置出口网关需要协调五个单独的对象:一个 ServiceEntry、 一个 Gateway、两个 HTTPRoute 资源(一个用于将网格流量引导到网关,一个用于将流量从网关转发到目的地)和一个 DestinationRule。每个新的外部主机都会重复大部分工作。

在 Ambient 模式中, waypoint 代理自然充当出口网关。 ztunnel 在将流量转发到目的地之前自动将流量路由到服务的 waypoint。 如果您将 ServiceEntry 放置在注册使用 waypoint 的命名空间中,则到该外部主机的所有网格流量都会自动通过该 waypoint,无需额外的路由规则。

在开始之前

  • 在启用 Ambient 模式的情况下安装 Istio。

  • 部署工作负载以用作流量源。curl 示例运行良好:

    Zip
    $ 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。

清理

Zip
$ kubectl delete namespace istio-egress
$ kubectl delete -f @samples/curl/curl.yaml@
$ kubectl label namespace default istio.io/dataplane-mode-

参见

这些信息有用吗?
您是否有更多建议和改进意见?

感谢您的反馈!