Ingress Gateway简介 传统上,Kubernetes使用Ingress
控制器来处理从外部进入集群的流量。使用Istio时,情况不再如此。 Istio已用新的Gateway
和VirtualServices
资源替换了熟悉的Ingress
资源。它们协同工作,将流量路由到网格中。在网格内部,不需要Gateway
,因为服务可以通过集群本地服务名称相互访问。
Istio流量分发控制 环境准备 主机名 IP 角色 k8s-master eth0:10.1.1.100、docker:172.17.100.0/24 K8S-master k8s-node1 eth0:10.1.1.120、docker:172.17.120.0/24 K8S-node k8s-node2 eth0:10.1.1.130、docker:172.17.130.0/24 K8S-node nginx-proxy eth0:10.1.1.11 代理节点
场景模型图 目前我们实现了后台服务层面,前端front调用后端service的流量策略,现在实现下客户访问前端的流量策略注入,区别是前端界面访问需要配置ingress域名。
准备资源配置清单 创建前端UI v2版本以及SVC
资源配置清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $ cat > front-tomcat-v2-dpl.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: labels: app: front-tomcat version: v2 name: front-tomcat-v2 spec: replicas: 1 selector: matchLabels: app: front-tomcat version: v2 template: metadata: labels: app: front-tomcat version: v2 spec: containers: - image: tomcat:9.0-jdk11 name: front-tomcat command: ["/bin/sh", "-c", "mkdir /usr/local/tomcat/webapps/ROOT;echo '这是tomcat-v2版本:<iframe name=\"footer\" marginwidth=0 marginheight=0 width=100% height=50 src=\"http://bill.istio.com/\" frameborder=0></iframe>'>/usr/local/tomcat/webapps/ROOT/index.html;/usr/local/tomcat/bin/catalina.sh run;"] EOF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ cat > front-tomcat-service.yaml <<EOF apiVersion: v1 kind: Service metadata: labels: app: front-tomcat name: front-tomcat spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: app: front-tomcat type: ClusterIP EOF
准备流量调度资源配置清单 将v1版本接入90%的流量,v2版本接入10%的流量
VirtualService DestinationRule 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ cat > front-tomcat-virtualservice.yaml <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: front-tomcat spec: hosts: - front-tomcat http: - name: front-tomcat-route route: - destination: host: front-tomcat subset: v1 weight: 90 - destination: host: front-tomcat subset: v2 weight: 10 EOF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ cat > front-tomcat-destinationrule.yaml <<EOF apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: front-tomcat spec: host: front-tomcat subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 EOF
应用资源配置清单 1 2 3 4 $ kubectl apply -f front-tomcat-service.yaml $ kubectl apply -f <(istioctl kube-inject -f front-tomcat-v2-dpl.yaml) $ kubectl apply -f front-tomcat-virtualservice.yaml $ kubectl apply -f front-tomcat-destinationrule.yaml
访问网格内服务 使用Ingress来访问网格服务] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cat > front-tomcat-ingress.yaml <<EOF apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: front-tomcat spec: rules: - host: tomcat.istio.com http: paths: - path: / pathType: Prefix backend: service: name: front-tomcat port: number: 8080 EOF
使用浏览器访问查看效果。
注意: 只有网格内部访问会遵从virtualservice
的规则,在宿主机中直接访问Service的ClusterIP还是按照默认的规则转发。此时还是各0.5权重,没有调度到istio。
Ingress: 对接ingress controller
,实现外部流量进入集群内部,只适用于 HTTP 流量,使用方式也很简单,只能对 service、port、HTTP 路径等有限字段匹配来路由流量,这导致它无法路由如 MySQL
、Redis
和各种私有 RPC 等 TCP 流量。要想直接路由南北向的流量,只能使用 Service 的 LoadBalancer
或 NodePort
,前者需要云厂商支持,后者需要进行额外的端口管理。有些 Ingress controller
支持暴露 TCP 和 UDP 服务,但是只能使用 Service 来暴露,Ingress 本身是不支持的,例如 nginx ingress controller,服务暴露的端口是通过创建 ConfigMap 的方式来配置的。
IngressGateway访问网格服务
对于入口流量管理,您可能会问: 为什么不直接使用 Kubernetes Ingress API ? 原因是 Ingress API 无法表达 Istio 的路由需求。 Ingress 试图在不同的 HTTP 代理之间取一个公共的交集,因此只能支持最基本的 HTTP 路由,最终导致需要将代理的其他高级功能放入到注解(annotation)中,而注解的方式在多个代理之间是不兼容的,无法移植。
Istio Gateway
通过将 L4-L6 配置与 L7 配置分离的方式克服了 Ingress
的这些缺点。 Gateway
只用于配置 L4-L6 功能(例如,对外公开的端口,TLS 配置),所有主流的L7代理均以统一的方式实现了这些功能。 然后,通过在 Gateway
上绑定 VirtualService
的方式,可以使用标准的 Istio 规则来控制进入 Gateway
的 HTTP 和 TCP 流量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cat > front-tomcat-gateway.yaml <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: front-tomcat-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - tomcat.istio.com EOF
效果是在Istio的ingress网关上加了一条规则,允许``tomcat.istio.com` 的外部http流量进入到网格中,但是只是接受访问和流量输入,当流量到达这个网关时,它还不知道发送到哪里去。
网关已准备好接收流量,我们必须告知它将收到的流量发往何处,这就用到了前面使用过的VirtualService
。
要为进入上面的 Gateway 的流量配置相应的路由,必须为同一个 host 定义一个 VirtualService
,并使用配置中的 gateways
字段绑定到前面定义的 Gateway
上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cat > front-tomcat-gateway-virtualservice.yaml <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: gateway-front-tomcat spec: gateways: - front-tomcat-gateway hosts: - tomcat.istio.com http: - name: front-tomcat-route route: - destination: host: front-tomcat subset: v1 weight: 90 - destination: host: front-tomcat subset: v2 weight: 10 EOF
该网关列表指定,只有通过我们指定的网关 front-tomcat-gateway
的流量是允许的。所有其他外部请求将被拒绝,并返回 404 响应。
请注意,在此配置中,来自网格内部的其他服务请求不受这些规则约束。
1 2 3 4 5 6 7 8 9 10 $ kubectl apply -f front-tomcat-gateway-virtualservice.yaml $ kubectl apply -f front-tomcat-gateway.yaml $ kubectl get vs gateway-front-tomcat NAME GATEWAYS HOSTS AGE gateway-front-tomcat ["front-tomcat-gateway" ] ["tomcat.istio.com" ] 1h $ kubectl get gw front-tomcat-gateway NAME AGE front-tomcat-gateway 1h
模拟访问:
此时我们已经走到ingressgateway上面了,所以要访问需要确认这里的svc是哪个映射端口,如下ingress映射80:80;ingressgateway映射80:32000,所以要访问域名:32000
1 2 3 4 5 6 7 8 9 10 $ kubectl get svc -n istio-system istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 192.168.231.83 <pending> 15021:30789/TCP,80:32000/TCP,443:31504/TCP,31400:30737/TCP,15443:32222/TCP 22h $ kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}' 32000 $ curl -HHost:tomcat.istio.com 10.1.1.100:32000/
访问流程图:
浏览器访问: http://tomcat.istio.com:30779/
配置Nginx转发域名请求 如何实现不加端口访问网格内服务?
在集群外Nginx配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ cat > /etc/nginx/conf.d/istio.com.conf <<EOF upstream default_backend_istio { server 10.1.1.120:32000 max_fails=3 fail_timeout=10s; server 10.1.1.100:32000 max_fails=3 fail_timeout=10s; server 10.1.1.130:32000 max_fails=3 fail_timeout=10s; } server { server_name *.istio.com; location / { proxy_pass http://default_backend_istio; proxy_http_version 1.1; # Istio 默认只支持 HTTP/1.1 以上协议版本,并不支持 HTTP/1.0 proxy_set_header Host $http_host; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; } } EOF
在集群内Nginx配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 在K8S集群中使用一台80端口未被占用的机器中,如ip为10.1.1.100 $ docker run -d --restart=always -p 80:80 --name istio-nginx nginx:alpine # 在容器的/etc/nginx/conf.d/目录中,新增配置文件 $ docker exec -it istio-nginx sh $ cat > /etc/nginx/conf.d/front-tomcat.conf <<EOF upstream front-tomcat { server 192.168.231.83:80; } server { listen 80; listen [::]:80; server_name tomcat.istio.com; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_pass http://front-tomcat; } } EOF $ nginx -s reload
绑定hosts win本地配置hosts,注意配置nginx部署的机器,而不是k8s集群ingress-nginx服务的机器
1 10.1.1.11 tomcat.istio.com
访问结果: