kubernetes - 使用 Kubernetes 服务的 Istio 导出

标签 kubernetes istio

(使用 Istio 0.5.1,kubectl 1.9.1/1.9.0 用于客户端/服务器,minikube 0.25.0)

我正在尝试让 Istio EgressRules 与 Kubernetes 服务一起使用,但遇到了一些麻烦。

我尝试通过 3 种方式设置 EgressRules:

  • 指向另一个域的 ExternalName 服务(例如
    www.google.com)
  • 没有选择器但有关联的服务
    端点对象(用于具有 IP 地址但没有 DNS 的服务
    姓名)
  • (用于比较)没有 Kubernetes 服务,只是一个 EgressRule

  • 我想我可以使用 kubernetes 服务的 FQDN 作为基于 HTTP 的 EgressRule 目标服务(如 ext-service.default.svc.cluster.local ),这就是我尝试的 ExternalName 服务以及没有选择器但关联的 Endpoints 对象的服务.

    对于前者,我创建了以下 yaml文件:
    kind: Service
    apiVersion: v1
    metadata:
      name: ext-service
    spec:
      type: ExternalName
      externalName: www.google.com
    ---
    apiVersion: config.istio.io/v1alpha2
    kind: EgressRule
    metadata:
      name: ext-egress-rule
    spec:
      destination:
        service: ext-service.default.svc.cluster.local
      ports:
        - port: 443
          protocol: https
    

    对于后者,我创建了 yaml文件(我只是 ping 了 google 并获取了 IP 地址):
    kind: Endpoints
    apiVersion: v1
    metadata:
      name: ext-service
    subsets:
      - addresses:
          - ip: 216.58.198.78
        ports:
          - port: 443
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: ext-service
    spec:
      ports:
      - protocol: TCP
        port: 443
        targetPort: 443
    ---
    apiVersion: config.istio.io/v1alpha2
    kind: EgressRule
    metadata:
      name: ext-service-egress-rule
    spec:
      destination:
        service: ext-service.default.svc.cluster.local
      ports:
        - port: 443
          protocol: https
    

    在这两种情况下,在应用程序代码中,我访问:
    http://ext-service.default.svc.cluster.local:443
    

    我的假设是流量会像这样流动:
    [[ app -> envoy proxy -> (tls origination) -> kubernetes service ]] -> external service
    

    在哪里 [[ ... ]]是服务网格的边界(也是 Kubernetes 集群)

    结果:
  • ExternalName服务几乎按预期工作,但它把我带到了谷歌的 404 页面(有时响应似乎是空的,不知道如何具体复制一个或另一个)
  • 带有 Endpoint 对象的服务不起作用,而是打印此消息(通过 Golang 发出请求时,但我认为这并不重要):

    Get http://ext-service.default.svc.cluster.local:443: EOF



    这有时也会给出空洞的回应。

  • 我想使用 Kubernetes 服务(即使它用于外部流量)有几个原因:
  • 您不能将 IP 地址用于 EgressRule 的目标服务。来自 Egress Rules configuration :“导出规则的目的地......可以是完全限定或通配符域名”。
  • 对于没有域名的外部服务(一些没有 DNS 名称的本地遗留/单体服务),我希望应用程序能够不通过 IP 地址而是通过 kube-dns 访问它们(或Istio 相关的类似)名称。
  • (与上一个相关)我喜欢 Kubernetes 服务提供的额外抽象层,因此我可以在不更改 EgressRule 的情况下更改底层目标(除非我弄错了,这不是构建它的正确方法)。 EgressRule 是否旨在完全替换 Kubernetes 服务以处理外部流量,而不创建额外的 Kubernetes 服务?

  • 使用 https://在应用程序代码中不是一个选项,因为这样请求将不得不禁用 TLS 验证,因为 kube-dns 名称与证书上的任何名称都不匹配。它也不会被观察到。

    如果我使用以下 EgressRule(没有任何 Kubernetes 服务),请通过 http://www.google.com:443 访问 Google工作正常,得到我期望的确切 html 表示:
    apiVersion: config.istio.io/v1alpha2
    kind: EgressRule
    metadata:
      name: google-egress-rule
    spec:
      destination:
        service: www.google.com
      ports:
        - port: 443
          protocol: https
    

    我看到有一个 TCP EgressRule,但我宁愿不必为每个 IP block 指定规则。来自 TCP Egress :“在 TCP 导出规则中,与基于 HTTP 的导出规则相反,目的地由 IP 或 CIDR 表示法中的 IP block 指定。”。

    此外,我仍然希望来自 L7 而不是 L4 的基于 HTTP 的可观察性,所以我更喜欢基于 HTTP 的导出。 (使用 TCP Egresses,“应用程序产生的 HTTPS 流量将被 Istio 视为不透明的 TCP”)。

    任何帮助将 Kubernetes 服务作为 EgressRule 的“目标服务”(或帮助理解为什么在这种情况下这不是必需的)都将受到赞赏。谢谢!

    最佳答案

    解决方案是:

  • 定义一个 Kubernetes ExternalName 服务指向 www.google.com
  • 不要定义任何 EgressRules
  • 创建一个 RouteRule 来设置 Host header 。

  • 在您的情况下,使用端口和协议(protocol)定义一个 ExternalName 服务:
    kind: Service
    apiVersion: v1
    metadata:
      name: ext-service
    spec:
      type: ExternalName
      externalName: www.google.com
       ports:
       - port: 80
       # important to set protocol name
       name: http
    ---
    

    定义一个 HTTP 重写路由规则来设置 Host 头:
    apiVersion: config.istio.io/v1alpha2
    kind: RouteRule
    metadata:
      name: externalgoogle-rewrite-rule
      #namespace: default
    spec:
      destination:
        name: ext-service
      rewrite:
        authority: www.google.com
    ---
    

    然后使用 curl 访问它,例如:curl ext-service
    如果没有路由规则,请求将到达 google.com,Host header 为 ext-service .由于 google.com 没有这样的虚拟主机,因此 Web 服务器不知道将此类请求转发到何处。这是你所经历的:

    it brought me to Google's 404 page

    关于kubernetes - 使用 Kubernetes 服务的 Istio 导出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49268369/

    相关文章:

    kubernetes - 将 K8s secret 的访问限制为特定服务帐户

    kubernetes - 为什么Nginx Ingress Minikube插件hostPort可以工作,而hostPort不能用于其他任何插件?

    kubernetes - 如何捕获每秒查询或微服务调用延迟? (没有 istio 或其他基于 envoy 的工具)

    docker - 自动将新的节点导出器添加到 prometheus.yml 的目标数组中

    docker - Kubernetes Redis rejson 持久化数据不保存

    kubernetes - 在 Mesos 或 Kubernetes 上支持公共(public)和私有(private)网络吗?

    kubernetes - 是否可以使用 Istio 搜索网格在 Kubernetes 中创建 Redis 集群?

    istio - knative的 "mesh"网关是什么

    kubernetes - istio可以调用lambda函数吗?

    kubernetes - 为什么 envoy sidecar 可以控制我的流量?