ServiceEntry

ServiceEntry
ServiceEntry 允许向 Istio 的内部服务注册表中添加额外的条目,以便网格中的自动发现服务可以访问或路由到这些手动指定的服务。ServiceEntry 描述了服务的属性(DNS名称,VIP,端口,协议,endpoints)。这些服务可以是网格外部的(如 Web APIs),也可以是不属于平台服务注册表的网格内部服务(如 一组在 Kubernetes 中与服务通信的 VM)。

下面的示例中,声明了一些内部应用程序通过 HTTPS 访问的外部 API。sidecar 检查 ClientHello 消息中的 SNI 值,以路由到关联的的外部服务。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-https
spec:
  hosts:
  - api.dropboxapi.com
  - www.googleapis.com
  - api.facebook.com
  location: MESH_EXTERNAL
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: DNS
下面的示例中,将一组在非托管 VM 上运行的 MongoDB 实例添加到 Istio 的注册表中,这些服务就可以被视为网格中的任何其他服务。关联的 DestinationRule 用于初始化到数据库实例的 mTLS 连接。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-mongocluster
spec:
  hosts:
  - mymongodb.somedomain                # not used
  addresses:
  - 192.192.192.192/24              # VIPs
  ports:
  - number: 27018
    name: mongodb
    protocol: MONGO
  location: MESH_INTERNAL
  resolution: STATIC
  endpoints:
  - address: 2.2.2.2
  - address: 3.3.3.3
关联的 DestinationRule 如下:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: mtls-mongocluster
spec:
  host: mymongodb.somedomain
  trafficPolicy:
    tls:
      mode: MUTUAL
      clientCertificate: /etc/certs/myclientcert.pem
      privateKey: /etc/certs/client_private_key.pem
      caCertificates: /etc/certs/rootcacerts.pem
下面的示例中,在 VirtualService 中使用 ServiceEntry 和 TLS 路由的组合,根据 SNI 值将流量引导到内部 Egress 防火墙。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-redirect
spec:
  hosts:
  - wikipedia.org
  - "*.wikipedia.org"
  location: MESH_EXTERNAL
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: NONE
根据 SNI 值路由的关联 VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: tls-routing
spec:
  hosts:
  - wikipedia.org
  - "*.wikipedia.org"
  tls:
  - match:
    - sniHosts:
      - wikipedia.org
      - "*.wikipedia.org"
    route:
    - destination:
        host: internal-egress-firewall.ns1.svc.cluster.local
带有 TLS 匹配的 VirtualService 将覆盖默认的 SNI 匹配。在没有 VirtualService 的情况下,流量将被转发到 wikipedia.org。

下面的示例中,演示了出口网关的使用,通过 Gateway 可以转发所有外部服务的流量。exportTo 字段用于控制服务声明对网格中其他命名空间的可见性。默认情况下,服务会暴露到所有命名空间。. 表示将可见性限制为当前的命名空间,这样其他命名空间就无法使用它。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-httpbin
  namespace: egress
spec:
  hosts:
  - httpbin.com
  exportTo:
  - "."
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS

定义一个 Gateway 来处理所有出口流量:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: istio-egressgateway
 namespace: istio-system
spec:
 selector:
   istio: egressgateway
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   hosts:
   - "*"

下面是 关联的 VirtualService,从 Sidecar 到网关服务(istio-egressgateway.istio-system.svc.cluster.local)的路由,以及从网关到外部服务的路由。注意,VirtualService 已暴露到所有命名空间,从而使它们能够将流量通过网关路由到外部服务。强制流量通过这样的托管中间代理比较常见。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: gateway-routing
  namespace: egress
spec:
  hosts:
  - httpbin.com
  exportTo:
  - "*"
  gateways:
  - mesh
  - istio-egressgateway
  http:
  - match:
    - port: 80
      gateways:
      - mesh
    route:
    - destination:
        host: istio-egressgateway.istio-system.svc.cluster.local
  - match:
    - port: 80
      gateways:
      - istio-egressgateway
    route:
    - destination:
        host: httpbin.com

下面的示例中,演示了在外部服务的主机中使用通配符。如果必须将连接路由到应用程序请求的 IP 地址(即应用程序解析 DNS 并尝试连接到特定的 IP 地址),则发现模式必须设置为 NONE。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-wildcard-example
spec:
  hosts:
  - "*.bar.com"
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: NONE

下面的示例中,演示了通过客户端主机上的 Unix Domain Socket 可使用的服务。必须将 resolution 设置为 STATIC 才能使用 Unix 地址的 endpoints。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: unix-domain-socket-example
spec:
  hosts:
  - "example.unix.local"
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: STATIC
  endpoints:
  - address: unix:///var/run/example/socket

对于基于 HTTP 的服务,可以创建一个由多个 DNS 可寻址 endpoints 支持的 VirtualService。在这种情况下,应用程序可以使用 HTTP_PROXY 环境变量透明地将 VirtualService 的 API 调用重新路由到选定的后端。

下面的示例中,创建了一个不存在的外部服务,名为 foo.bar.com,该服务由三个域支持:us.foo.bar.com:8080, uk.foo.bar.com:9080, in.foo.bar.com:7080。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-dns
spec:
  hosts:
  - foo.bar.com
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  endpoints:
  - address: us.foo.bar.com
    ports:
      https: 8080
  - address: uk.foo.bar.com
    ports:
      https: 9080
  - address: in.foo.bar.com
    ports:
      https: 7080

使用 HTTP_PROXY=http://localhost/,应用程序对 http://foo.bar.com 的调用将在上面指定的三个域之间实现负载均衡。换句话说,对 http://foo.bar.com/baz 的调用将转换为 http://uk.foo.bar.com/baz。

下面的示例中,说明了 ServiceEntry 包含主题备用名称的用法,其格式符合 SPIFFE 标准:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin
  namespace : httpbin-ns
spec:
  hosts:
  - httpbin.com
  location: MESH_INTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: STATIC
  endpoints:
  - address: 2.2.2.2
  - address: 3.3.3.3
  subjectAltNames:
  - "spiffe://cluster.local/ns/httpbin-ns/sa/httpbin-service-account"