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, 请执行:

      kubectl apply -f samples/httpbin/httpbin.yaml
    

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

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

配置ingress (HTTP)

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

     cat <<EOF | kubectl create -f -
     apiVersion: extensions/v1beta1
     kind: Ingress
     metadata:
       name: simple-ingress
       annotations:
         kubernetes.io/ingress.class: istio
     spec:
       rules:
       - http:
           paths:
           - path: /status/.*
             backend:
               serviceName: httpbin
               servicePort: 8000
           - path: /delay/.*
             backend:
               serviceName: httpbin
               servicePort: 8000
     EOF
    

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

验证 ingress

  1. 确定ingress URL:

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

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

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

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

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

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

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

配置安全ingress(HTTPS)

  1. 为ingress生成证书和密钥

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

    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。

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

3.为httpbin服务创建Ingress Resource

```bash
cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    kubernetes.io/ingress.class: istio
spec:
  tls:
    - secretName: istio-ingress-certs # currently ignored
  rules:
  - http:
      paths:
      - path: /status/.*
        backend:
          serviceName: httpbin
          servicePort: 8000
      - path: /delay/.*
        backend:
          serviceName: httpbin
          servicePort: 8000
EOF
```

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

再次验证ingress

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

  1. 确定ingress URL:

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

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

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

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

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

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

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

和ingress一起使用istio路由规则

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

cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: status-route
spec:
  destination:
    name: httpbin
  match:
    # Optionally limit this rule to istio ingress pods only
    source:
      name: istio-ingress
      labels:
        istio: ingress
    request:
      headers:
        uri:
          prefix: /delay/ #must match the path specified in ingress spec
              # if using prefix paths (/delay/.*), omit the .*.
              # if using exact match, use exact: /status
  route:
  - weight: 100
  httpReqTimeout:
    simpleTimeout:
      timeout: 4s
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定义

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

     kubectl delete -f samples/httpbin/httpbin.yaml
    

进阶阅读

results matching ""

    No results matching ""