Istio Ingress控制器

此任务将演示如何通过配置Istio将服务发布到service mesh集群外部。在Kubernetes环境中,Kubernetes Ingress Resources 允许用户指定某个服务是否要公开到集群外部。然而,Ingress Resource规范非常精简,只允许用户设置主机,路径,以及后端服务。下面是Istio ingress已知的局限:

  1. Istio支持不使用annotation的标准Kubernetes Ingress规范。不支持Ingress资源规范中的ingress.kubernetes.io annotation。kubernetes.io/ingress.class: istio之外的任何annotation将被忽略。
  2. 不支持路径中的正则表达式
  3. Ingress中不支持故障注入

前提条件

  • 参照文档安装指南中的步骤安装Istio。

  • 确保当前的目录是istio目录。

  • 启动 httpbin 示例, 我们会把这个服务作为目标服务发布到外部。

    如果你安装了Istio-Initializer, 请执行:

    1. kubectl apply -f samples/httpbin/httpbin.yaml

    如果没有Istio-Initializer, 请执行:

    1. kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)

配置ingress (HTTP)

  1. 为httpbin服务创建一个基本的Ingress Resource

    1. cat <<EOF | kubectl create -f -
    2. apiVersion: extensions/v1beta1
    3. kind: Ingress
    4. metadata:
    5. name: simple-ingress
    6. annotations:
    7. kubernetes.io/ingress.class: istio
    8. spec:
    9. rules:
    10. - http:
    11. paths:
    12. - path: /status/.*
    13. backend:
    14. serviceName: httpbin
    15. servicePort: 8000
    16. - path: /delay/.*
    17. backend:
    18. serviceName: httpbin
    19. servicePort: 8000
    20. EOF

    /.*是特殊的Istio表示方法,用于表示前缀匹配,特别是(prefix: /)形式的[规则匹配配置](前缀:/)。

验证 ingress

  1. 确定ingress URL:

    • 如果你的集群运行的环境支持外部的负载均衡器,请使用ingress的外部地址:

      1. kubectl get ingress simple-ingress -o wide
      1. NAME HOSTS ADDRESS PORTS AGE
      2. simple-ingress * 130.211.10.121 80 1d
      1. export INGRESS_HOST=130.211.10.121
    • 如果不支持负载均衡器,使用ingress控制器的pod的hostIP:

      1. kubectl get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
      1. 169.47.243.100

      同时也找到istio-ingress服务的80端口的nodePort映射端口:

      1. kubectl -n istio-system get svc istio-ingress
      1. NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      2. istio-ingress 10.10.10.155 <pending> 80:31486/TCP,443:32254/TCP 32m
      1. export INGRESS_HOST=169.47.243.100:31486
  2. 使用curl访问httpbin服务:

    1. curl -I http://$INGRESS_HOST/status/200
    1. HTTP/1.1 200 OK
    2. server: envoy
    3. date: Mon, 29 Jan 2018 04:45:49 GMT
    4. content-type: text/html; charset=utf-8
    5. access-control-allow-origin: *
    6. access-control-allow-credentials: true
    7. content-length: 0
    8. x-envoy-upstream-service-time: 48
  3. 如果访问其他的没有明确公开的URL,应该收到HTTP404错误

    1. curl -I http://$INGRESS_HOST/headers
    1. HTTP/1.1 404 Not Found
    2. date: Mon, 29 Jan 2018 04:45:49 GMT
    3. server: envoy
    4. content-length: 0

配置安全ingress(HTTPS)

  1. 为ingress生成证书和密钥

    使用OpenSSL创建测试私钥和证书

    1. openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt -subj "/CN=foo.bar.com"
  2. 创建secret

    使用kubectl在命名空间istio-system创建istio-ingress-certssecret。

    注意:secret在命名空间istio-system中必须被称为istio-ingress-certs,因为它要被加载到Isito Ingress。

    1. kubectl create -n istio-system secret tls istio-ingress-certs --key /tmp/tls.key --cert /tmp/tls.crt

3.为httpbin服务创建Ingress Resource

  1. ```bash
  2. cat <<EOF | kubectl create -f -
  3. apiVersion: extensions/v1beta1
  4. kind: Ingress
  5. metadata:
  6. name: secure-ingress
  7. annotations:
  8. kubernetes.io/ingress.class: istio
  9. spec:
  10. tls:
  11. - secretName: istio-ingress-certs # currently ignored
  12. rules:
  13. - http:
  14. paths:
  15. - path: /status/.*
  16. backend:
  17. serviceName: httpbin
  18. servicePort: 8000
  19. - path: /delay/.*
  20. backend:
  21. serviceName: httpbin
  22. servicePort: 8000
  23. EOF
  24. ```

注意: Envoy当前只允许一个TLS ingress密钥,因为SNI 尚未支持。也就是说看,ingress 中的 secretName 字段并没有被使用。

再次验证ingress

译者注:注意这里的命令和输出与前面的稍有不同。

  1. 确定ingress URL:

    • 如果你的集群运行的环境支持外部的负载均衡器,请使用ingress的外部地址:

      1. kubectl get ingress secure-ingress -o wide
      1. NAME HOSTS ADDRESS PORTS AGE
      2. secure-ingress * 130.211.10.121 80 1d
      1. export INGRESS_HOST=130.211.10.121
    • 如果不支持负载均衡器,使用ingress控制器的pod的hostIP:

      1. kubectl -n istio-system get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
      1. 169.47.243.100

      同时也找到istio-ingress服务的80端口的nodePort映射端口:

      1. kubectl -n istio-system get svc istio-ingress
      1. NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
      2. istio-ingress 10.10.10.155 <pending> 80:31486/TCP,443:32254/TCP 32m
      1. export INGRESS_HOST=169.47.243.100:31486
  2. 使用curl访问httpbin服务:

    1. curl -I http://$INGRESS_HOST/status/200
    1. HTTP/1.1 200 OK
    2. server: envoy
    3. date: Mon, 29 Jan 2018 04:45:49 GMT
    4. content-type: text/html; charset=utf-8
    5. access-control-allow-origin: *
    6. access-control-allow-credentials: true
    7. content-length: 0
    8. x-envoy-upstream-service-time: 96
  3. 如果访问其他的没有明确公开的URL,应该收到HTTP404错误

    1. curl -I http://$INGRESS_HOST/headers
    1. HTTP/1.1 404 Not Found
    2. date: Mon, 29 Jan 2018 04:45:49 GMT
    3. server: envoy
    4. content-length: 0

和ingress一起使用istio路由规则

Istio的路由规则可以在路由请求到后端服务时获取更大的控制度。例如,下列路由规则为到httpbin服务上的/delayURL的所有请求设置4秒的超时时间。

  1. cat <<EOF | istioctl create -f -
  2. apiVersion: config.istio.io/v1alpha2
  3. kind: RouteRule
  4. metadata:
  5. name: status-route
  6. spec:
  7. destination:
  8. name: httpbin
  9. match:
  10. # Optionally limit this rule to istio ingress pods only
  11. source:
  12. name: istio-ingress
  13. labels:
  14. istio: ingress
  15. request:
  16. headers:
  17. uri:
  18. prefix: /delay/ #must match the path specified in ingress spec
  19. # if using prefix paths (/delay/.*), omit the .*.
  20. # if using exact match, use exact: /status
  21. route:
  22. - weight: 100
  23. httpReqTimeout:
  24. simpleTimeout:
  25. timeout: 4s
  26. EOF

如果用URLhttp://$INGRESS_HOST/delay/10来发起对ingress的调用,会发现调用在4秒之后返回,而不是期待的10秒延迟。

可以使用路由规则的其他特性如重定向,重写,路由到多个版本,基于HTTP header的正则表达式匹配,websocket升级,超时,重试,等。更多详情请参考路由规则

注意1: 在Ingress中故障注入不可用
注意2: 当请求匹配路由规则时,使用完全相同的路径或者前缀,就像在Ingress规范中使用的那样。

理解Ingress

Ingress为外部流量提供网关来进入Istio服务网格,并使得Istio的流量管理和策略的特性对edge服务可用。

Ingress规范中的servicePort字段可以是一个端口数字(整型)或者一个名称。为了正确工作,端口名称必须遵循Istio端口命名约定(例如,grpc-*, http2-*, http-*, 等)。使用的名称必须匹配后端服务声明中的端口名称。

在前面的步骤中,我们在Isito服务网格中创建服务,并展示了如何暴露服务的HTTP和HTTPS终端到外部流量。也展示了如何使用Istio路由规则来控制ingress流量。

清理

  1. 删除secret和Ingress Resource定义

    1. kubectl delete ingress simple-ingress secure-ingress
    2. kubectl delete -n istio-system secret istio-ingress-certs
  2. 关闭httpbin服务

    1. kubectl delete -f samples/httpbin/httpbin.yaml

进阶阅读