Tasks·Traffic Management·Istio Ingress

这个课题描述如何配置才能让Istio服务网格集群中的服务暴露。在k8s环境中,Kubernetes Ingress Resource允许用户指定集群中暴露给外部的服务。它允许为每个虚拟主机和路径定义一个后端服务。
一旦Istio Ingress被指定,进入集群的流量将直接通过 istio-ingress 服务。因此,Isito的功能(如监控和路由规则)可应用于进入集群中的流量。

Istio Ingress的规则是基于标准的 Kubernetes Ingress Resource 规则,但有如下不同:
1. Istio Ingress规则包含 kubernetes.io/ingress.class: istio 注解。
2. 所有其他注解都被忽略。

下面是Istio Ingress的一些已知限制:
1. 路径中不支持正则表达式
2. 不支持Ingress的故障注入

Before you begin

  1. 先按照安装指导的描述安装Istio。
  2. 确保你的当前目录是istio
  3. 启动httpbin样例,该样本将用作要在外部公开的目标服务
    如果你安装了 Istio-Initializer,执行下述命令:
kubectl apply -f samples/httpbin/httpbin.yaml

否则执行:

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

Configuring ingress(HTTP)

  1. 为httpbin服务新建一个基础Ingress规则
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用来描述前缀匹配的一个特殊规则,一个特别的 rule match configuration 形式 (prefix: /)。

Verifying 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 controller pod的hostIP:
kubectl -n istio-system get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
169.47.243.100

以及istio-ingress服务的nodePort映射到80端口:

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,你将会看到HTTP 404状态码。

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

Configuring secure 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.创建密码
使用 kubectl 在命名空间 istio-system 创建密码 istio-ingress-certs 。Istio Ingress将会自动加载密码。
注意: 为了能被Istio Ingress安装,密码必须在命名空间 istio-system上且命名为 istio-ingress-certs

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

3.为httpbin服务创建Ingress规则

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

注意: 因为还不支持SNI,Envoy目前只允许ingress中只有一个TLS密码。这意味着在ingress资源中,secretName字段并没有被使用。

verifying 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 controller pod的hostIP:
kubectl -n istio-system get po -l istio=ingress -o jsonpath='{.items[0].status.hostIP}'
169.47.243.100

以及istio-ingress服务的nodePort映射到443端口:

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:32254

2.使用curl访问httpbin服务:

curl -I -k https://$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,你将会看到HTTP 404状态码。

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

4.为ingress密钥/证书配置RBAC
有服务账户即可访问此入口的密钥/证书,这有密钥/证书泄露的风险。我们可以通过设置RBAC进行保护。install/kubernetes/istio.yaml定义的ClusterRoles和ClusterRoleBindings 允许命名空间istio-system中的服务账户访问所有秘密资源。我们需要更新或替换这些RBAC来仅使istio-ingress-service-account访问ingress的密钥/证书。
我们可以使用kubectl列出我们需要保护的在命名空间 istio-system中的所有密码

kubectl get secrets -n istio-system

然后会有如下打印:

NAME                                        TYPE                                  DATA      AGE
istio-ingress-certs                         kubernetes.io/tls                     2         7d
istio.istio-ingress-service-account         istio.io/key-and-cert                 3         7d
......

5.为 istio-pilot-service-account 和 istio-mixer-istio-service-account 更新RBAC
记录ClusterRole istio-mixer-istio-system 和 istio-pilot-istio-system。 我们将在重新定义这些副本时参考这些副本,以免对其他资源的访问权限中断。

kubectl describe ClusterRole istio-mixer-istio-system
kubectl describe ClusterRole istio-pilot-istio-system

删除已经存在的ClusterRoleBindings 和 ClusterRole。

kubectl delete ClusterRoleBinding istio-pilot-admin-role-binding-istio-system
kubectl delete ClusterRoleBinding istio-mixer-admin-role-binding-istio-system
kubectl delete ClusterRole istio-mixer-istio-system

由于istio-pilot-istio-system 也绑定到 istio-ingress-service-account,我们下一步将会删除 istio-pilot-istio-system。
创建 istio-mixer-istio-system.yaml ,它允许 istio-mixer-service-account 读 istio.io/key-and-cert 以及 istio.io/ca-root 类型的密码实例。参阅 istio-mixer-istio-system 副本,并将访问权限添加到其他资源。

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: istio-mixer-istio-system
rules:  
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio.istio-ca-service-account"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio-ca-secret"]
  verbs: ["get", "list", "watch"]
......   
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: istio-mixer-admin-role-binding-istio-system
subjects:
- kind: ServiceAccount
  name: istio-mixer-service-account
  namespace: istio-system
roleRef:
  kind: ClusterRole
  name: istio-mixer-istio-system
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f istio-mixer-istio-system.yaml

6.更新istio-pilot-service-account 和 istio-ingress-service-account 的RBAC
删除已存的ClusterRoleBinding 和 ClusterRole

kubectl delete clusterrolebinding istio-ingress-admin-role-binding-istio-system
kubectl delete ClusterRole istio-pilot-istio-system

创建istio-pilot-istio-system.yaml,它允许 istio-pilot-service-account 读 istio.io/key-and-cert,及istio.io/ca-root 类型的密码实例。参照 istio-pilot-istio-system 副本,并将访问权限加入其他资源

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: istio-pilot-istio-system
rules:  
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio.istio-ca-service-account"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio-ca-secret"]
  verbs: ["get", "list", "watch"]
......   
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: istio-pilot-admin-role-binding-istio-system
subjects:
- kind: ServiceAccount
  name: istio-pilot-service-account
  namespace: istio-system
roleRef:
  kind: ClusterRole
  name: istio-pilot-istio-system
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f istio-pilot-istio-system.yaml

创建 istio-ingress-istio-system.yaml,允许istio-ingress-service-account读istio-ingress-certs以及其他密码实例。参照istio-pilot-istio-system的副本,并为其他资源添加访问权限。

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: istio-ingress-istio-system
rules: 
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio.istio-ca-service-account"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio-ca-secret"]
  verbs: ["get", "list", "watch"]
......
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  resourceNames: ["istio-ingress-certs"]
  verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: istio-ingress-admin-role-binding-istio-system
subjects:
- kind: ServiceAccount
  name: istio-ingress-service-account
  namespace: istio-system
roleRef:
  kind: ClusterRole
  name: istio-ingress-istio-system
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f istio-ingress-istio-system.yaml

7.为 istio-ca-service-account 更新RBAC
记录ClusterRole istio-ca-istio-system。

kubectl describe ClusterRole istio-ca-istio-system

创建istio-ca-istio-system.yaml,它更新已存ClusterRole istio-ca-istio-system,允许 istio-ca-service-account 读取,新建和修改所有 istio.io/key-and-cert及istio.io/ca-root类型的密码。

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: istio-ca-istio-system
rules:
- apiGroups: [""] # "" indicates the core API group
 resources: ["secrets"]
 resourceNames: ["istio.istio-ca-service-account"]
 verbs: ["get", "list", "watch", "create", "update"]
- apiGroups: [""] # "" indicates the core API group
 resources: ["secrets"]
 resourceNames: ["istio-ca-secret"]
 verbs: ["get", "list", "watch", "create", "update"]
......
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: istio-ca-role-binding-istio-system
subjects:
- kind: ServiceAccount
  name: istio-ca-service-account
  namespace: istio-system
roleRef:
  kind: ClusterRole
  name: istio-ca-istio-system
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f istio-ca-istio-system.yaml

8.确认新的ClusterRoles 如预期工作。

kubectl auth can-i get secret/istio-ingress-certs --as system:serviceaccount:istio-system:istio-ingress-service-account -n istio-system

输出应为

yes

这个命令中,我们用“list”或“watch”替换动词 “get” ,输出应该时 “yes”。现在让我们测试下其他服务账户。

kubectl auth can-i get secret/istio-ingress-certs --as system:serviceaccount:istio-system:istio-pilot-service-account -n istio-system

输出应为

no - Unknown user "system:serviceaccount:istio-system:istio-pilot-service-account"

这个命令中,我们可以用istio-mixer-service-account或istio-ca-service-account替换服务账户,我们可以用“list”或“watch”替换动词 “get” ,输出结果应该相同。
除了 istio-ingress-certs 可以获取密码资源, istio-ca-service-account, istio-ingress-service-account, istio-pilot-service-account and istio-mixer-service-account都可以。

kubectl auth can-i get secret/istio-ca-service-account-token-r14xm --as system:serviceaccount:istio-system:istio-ca-service-account -n istio-system

输出应为

yes

9.清理
我们删掉新定义的ClusterRoles 和ClusterRoleBindings,然后通过那些副本恢复初始的ClusterRoles 和ClusterRoleBindings 。

Using Istio Routing Rules with Ingress

Istio的路由规则在路由请求到后端服务时可以达到更好的控制程度。例如,下面路由规则为所有调用httpbin服务的/delay URL 设置了4s超时

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

如果你曾通过URL http://$INGRESS_HOST/delay/10 调用ingress,你会发现请求返回4s延迟,而不是预期的10s。
你可以使用路由规则的其他功能,如重定向,重写,路由多个版本,基于正则表达式的HTTP请求头匹配,websocker升级,超时,重试等。请参考 routing rules 查看更多细节。

注意1: Ingress不支持故障注入。
注意2: 当路由规则匹配请求时,使用与Ingress规范中使用的相同的确切路径或前缀。

Understanding ingresses

Ingresses为外部流量进入Istio服务网格提供网关,并且Istio可达的边缘服务提供路由管理和策略功能。
在Ingress规范中的servicePort字段可以采取端口号(整数)或名称。为了正确使用功能,端口名必须遵循Istio端口名规范 (e.g., grpc-*, http2-*, http-*, etc.)。使用的名称必须与后端服务声明中的端口名称匹配。

Cleanup

1.移除密码和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

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/80279523