在Kubernetes中提供了Ingress用来接入集群外部的流量,将集群内部的Service暴露到集群外部。 而Istio提供了另一个配置模型Istio Gateway,使用Istio Gateway同样可以将服务暴露到服务器网格之外,它还允许我们将Istio的功能(诸如:监控和路由规则等)应用到进入集群的流量上。

确认Istio Ingress Gateway的入口IP和端口

使用defaultdemo profile部署的istio默认都安装了istio-ingressgateway组件:

 1kubectl get all -n istio-system -l app=istio-ingressgateway
 2NAME                                        READY   STATUS    RESTARTS   AGE
 3pod/istio-ingressgateway-5d57955454-fv5np   1/1     Running   0          3d1h
 4
 5NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                      AGE
 6service/istio-ingressgateway   LoadBalancer   10.106.130.216   <pending>     15021:31723/TCP,80:30709/TCP,443:31482/TCP,31400:32432/TCP,15443:31499/TCP   19d
 7
 8NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
 9deployment.apps/istio-ingressgateway   1/1     1            1           19d
10
11NAME                                              DESIRED   CURRENT   READY   AGE
12replicaset.apps/istio-ingressgateway-5d57955454   1         1         1       19d

上面istio-ingressgateway的Service的Type是LoadBalancer, 它的EXTERNAL-IP处于pending状态, 这是因为我们目前的环境并没有可用于Istio Ingress Gateway外部的负载均衡器,为了使得可以从外部访问, 通过修改istio-ingressgateway这个Service的externalIps,因为当前Kubernetes集群的kube-proxy启用了ipvs,所以这个指定一个VIP 192.168.96.50作为externalIp。

此时再次查看istio-ingressgateway这个Service,EXTERNAL-IP上已经变成我们设置的VIP了:

1kubectl get svc istio-ingressgateway -n istio-system
2NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                                                      
3istio-ingressgateway   LoadBalancer   10.106.130.216   192.168.96.50   15021:31723/TCP,80:30709/TCP,443:31482/TCP,31400:32432/TCP,15443:31499/TCP

在每个k8s node上kube-proxy会监听各个service的port:

1netstat -ntlp | grep 192.168.96.50
2tcp        0      0 192.168.96.50:15021     0.0.0.0:*               LISTEN      3055/kube-proxy
3tcp        0      0 192.168.96.50:80        0.0.0.0:*               LISTEN      3055/kube-proxy
4tcp        0      0 192.168.96.50:15443     0.0.0.0:*               LISTEN      3055/kube-proxy
5tcp        0      0 192.168.96.50:443       0.0.0.0:*               LISTEN      3055/kube-proxy
6tcp        0      0 192.168.96.50:31400     0.0.0.0:*               LISTEN      3055/kube-proxy

80和433将作为192.168.96.50这个VIP将集群外部流量接入的两个端口,分别对应http和https。

注意,这里使用k8s service的external ip则要求这个ip至少能够路由到集群中的一个或多个k8s节点,例如服务器是在openstack环境时,需要每个服务器的网络端口中配置添加一个可用地址对为external ip。

如果istio-ingressgateway这个Service的EXTERNAL-IP值已设置,istio-ingressgateway组件就可以为Ingress Gateway提供服务。 如果EXTERNAL-IP值为<none>或持续显示<pending>,则无法需要使用istio-ingressgateway这个Service的相关NodePort来访问Ingress Gateway提供服务,前面几节内容学习istio流量管理时就是使用NodePort来访问bookinfo应用。

使用Istio Gateway接入集群外部流量

前面我们可以从集群外部访问bookinfo应用,就是因为已经为bookinfo应用创建了Istio Gateway资源,对照k8s里的Ingress来理解的话:

  • Istio Gateway: 相当于k8s里的Ingress, 需要为某个服务创建以把服务暴露到集群外部
  • istio-ingressgateway组件相当于k8s里的ingress-controller

下面看一下前面部署bookinfo应用时创建的Gateway:

1kubectl get gateway bookinfo-gateway -o yaml
 1apiVersion: networking.istio.io/v1beta1
 2kind: Gateway
 3metadata:
 4  name: bookinfo-gateway
 5  namespace: default
 6spec:
 7  selector:
 8    istio: ingressgateway
 9  servers:
10  - hosts:
11    - '*'
12    port:
13      name: http
14      number: 80
15      protocol: HTTP

在k8s的Ingress资源配置中除了配置对外暴露的端口、协议、域名等信息外还会有一些流量路由的配置(如基于不同path的);而Istio Gateway资源中只定义对外暴露的端口、协议、域名,对于路由信息需要使用Istio的虚拟服务VirtualService的路由规则来配置。 上面的bookinfo-gateway配置了bookinfo应用以host为任意*, 80端口http协议暴露到集群外部,那么一定还有对应的虚拟服务配置路由信息:

1kubectl get virtualservice bookinfo -o yaml
 1apiVersion: networking.istio.io/v1beta1
 2kind: VirtualService
 3metadata:
 4  name: bookinfo
 5  namespace: default
 6spec:
 7  gateways:
 8  - bookinfo-gateway
 9  hosts:
10  - '*'
11  http:
12  - match:
13    - uri:
14        exact: /productpage
15    - uri:
16        prefix: /static
17    - uri:
18        exact: /login
19    - uri:
20        exact: /logout
21    - uri:
22        prefix: /api/v1/products
23    route:
24    - destination:
25        host: productpage
26        port:
27          number: 9080

gateways指定了此虚拟服务的路由规则是为哪些gateway的。

上面的配置使用http://192.168.96.50/productpage即可访问bookinfo应用。

实际中更多使用域名而非ip+path的形式来区分不同的应用,下面配置域名访问bookinfo应用,修改bookinfo的gateway如下:

 1apiVersion: networking.istio.io/v1alpha3
 2kind: Gateway
 3metadata:
 4  name: bookinfo-gateway
 5spec:
 6  selector:
 7    istio: ingressgateway # use istio default controller
 8  servers:
 9  - port:
10      number: 80
11      name: http
12      protocol: HTTP
13    hosts:
14    - "bookinfo.example.com"
15---
16apiVersion: networking.istio.io/v1alpha3
17kind: VirtualService
18metadata:
19  name: bookinfo
20spec:
21  hosts:
22  - "bookinfo.example.com"
23  gateways:
24  - bookinfo-gateway
25  http:
26  - match:
27    - uri:
28        exact: /productpage
29    - uri:
30        prefix: /static
31    - uri:
32        exact: /login
33    - uri:
34        exact: /logout
35    - uri:
36        prefix: /api/v1/products
37    route:
38    - destination:
39        host: productpage
40        port:
41          number: 9080

按上面的配置完成对bookinfo gateway和路由规则的修改后,可以直接以地址http://bookinfo.example.com/productpage访问bookinfo应用。

为Istio Gateway开启https

下面为bookinfo应用的istio gateway开启https。创建bookinfo应用的Ingress Gateway所需的https证书的secret,注意是在istio-system的namespace下创建:

1kubectl create -n istio-system secret tls bookinfo-credential --key=bookinfo.example.com.key --cert=bookinfo.example.com.crt

注意secret的名称不能是以istioprometheus开头,且不能包含token字段。

修改bookinfo应用的Gateway:

 1apiVersion: networking.istio.io/v1alpha3
 2kind: Gateway
 3metadata:
 4  name: bookinfo-gateway
 5spec:
 6  selector:
 7    istio: ingressgateway # use istio default controller
 8  servers:
 9  - port:
10      number: 80
11      name: http
12      protocol: HTTP
13    hosts:
14    - bookinfo.example.com
15    tls:
16      httpsRedirect: true
17  - port:
18      number: 443
19      name: https
20      protocol: HTTPS
21    tls:
22      mode: SIMPLE
23      credentialName: bookinfo-credential # must be the same as secret
24    hosts:
25    - bookinfo.example.com
26---
27apiVersion: networking.istio.io/v1alpha3
28kind: VirtualService
29metadata:
30  name: bookinfo
31spec:
32  hosts:
33  - bookinfo.example.com
34  gateways:
35  - bookinfo-gateway
36  http:
37  - match:
38    - uri:
39        exact: /productpage
40    - uri:
41        prefix: /static
42    - uri:
43        exact: /login
44    - uri:
45        exact: /logout
46    - uri:
47        prefix: /api/v1/products
48    route:
49    - destination:
50        host: productpage
51        port:
52          number: 9080

上面的bookinfo gateway配置了请求域名bookinfo.example.comhttp的80端口到https的443端口的自动重定向跳转,tls.mode=SIMPLE配置的是单向TLS,证书使用tls.credentialName指定前面创建在istio-system命名空间下的secret。 应用上面的配置后,使用https://bookinfo.example.com/productpage地址就可以打开bookinfo应用页面。

istio-gateway-tls-bookinfo.png

参考