最近公司产品在适配 openshift 平台,想要弃用掉外部 nginx 的代理,决定使用 redhat 认证过的 serviceMesh 来做代理,也就是将k8s集群外部的流量引入集群内。

istio 的 ServiceEntry CRD有这个能力,原理与 svc 和 endpoint 是一样的,将外部流量作为 endpoint 引入 ServiceEntry 中,并赋予自定义域名,就像集群内部的 [svc_name].[namespace].svc.cluster.local 一样。

ServiceEntry

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: xxx
  namespace: yyy
spec:
  hosts:
  - test.feiyiblog.com    # 这里改为自定义域名
  addresses:
  - "10.10.26.110/32"     # 代表所处网段,这里也可以写10.10.26.0/24
  ports:
  - number: 5670          # 外部服务的访问端口
    name: http            # 如果是https就改为https
    protocol: HTTP        # 如果是HTTPS就改为HTTPS
  location: MESH_EXTERNAL # 表示这个域名是从外部引入的
  exportTo:               # 文件中配置的hosts的生效命名空间
  - "*"
  resolution: STATIC      # 域名解析后的upstream
  endpoints:
  - address: 10.10.26.110  # 实际外部服务的 IP,支持负载均衡

将上述内容更改为自己所需后,在集群内创建,ServiceEntry 的特点是,创建后,只能是网格内的 pod 才能通过域名访问。

因为我也接触 istio 不多,这里的网格内指的是,创建 pod 时启动了 istio 的 sidecar,sidecar 代理 Envoy 代理,可以将流量拦截在 sidecar 中,再通过 istio 内部处理流量后转发,而外部流量引入网格的功能仅仅是众多功能中的冰山一角。

网格内验证

命名空间需要支持注入 sidecar

oc label ns [namespace] istio-injection=enabled --overwrite

创建一个支持 curl 的 pod 来验证:注意要添加 sidecar.istio.io/inject: 'true' 的 label 才会被注入 sidecar

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-curl
  namespace: yyy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-curl
  template:
    metadata:
      labels:
        app: test-curl
        sidecar.istio.io/inject: 'true'
    spec:
      containers:
      - name: curl
        image: dockerproxy.net/curlimages/curl
        command: [ "sleep", "infinity" ]

进入 pod 验证

kubectl exec -it -n [namespace] test-curl-xxxxx-yyyy -- curl http://test.feiyiblog.com:5670

返回正常则识别没问题

Gateway

创建 ServiceEntry 仅仅是集群内部访问,集群外的环境是无法访问的,我的需求是要替代 nginx 代理

Istio 的 GatewayVirtualService 具有暴露服务到外部的功能

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: test-gateway
  namespace: yyy
spec:
  selector:
    istio: ingressgateway  # 用来匹配ingressgateway
  servers:
  - hosts:
    - 'test.feiyiblog.com' # 外部访问要使用的域名
    port:
      number: 80      # 这里使用了ingressgateway的80端口
      protocol: HTTP
      name: http1

VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: external-dbgpt
  namespace: yyy
spec:
  gateways:
  - yyy/test-gateway   # 对应gateway的namespace/name,同命名空间可省略namespace
  hosts:
  - "*"
  http:
  - route:
    - destination:
        host: test.feiyiblog.com   # 对应ServiceEntry中的hosts域名
        port:
          number: 5670

集群外部访问:http://test.feiyiblog.com

集群内部访问:http://test.feiyiblog.com:5670

拓展

我这里还有一个服务默认访问 / 会返回404,通过 VirtualService 来做路径重定向,服务本身要访问到 /anything/ 会自动跳转到 /angything/#/home,所以我这只重定向到 /qanything/

  http:
  - match:
    - uri:
        exact: /
    redirect:
      uri: /qanything/  # 当访问 / 时重定向到 /qanything/
  - route:
    - destination:
        host: qanything.feiyiblog.com
        port:
          number: 8777

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0