本文记录istio搭建入口网关以及流量路由管控的场景。
本文创建一个sprinboot应用做为docker镜像用于后面的验证。该springboot应用只提供了一个接口,分两个版本。
v1 版本:
@RestController
@RequestMapping("/test")
public class TestEndpoint {
private RestTemplate restTemplate;
@GetMapping("/get")
public String get(@RequestParam("a") String a) {
return "V test get and the parameter a is : " + a;
}
}
latest 版本:
@RestController
@RequestMapping("/test")
public class TestEndpoint {
private RestTemplate restTemplate;
@GetMapping("/get")
public String get(@RequestParam("a") String a) {
return "latest test get and the parameter a is : " + a;
}
}
打包成镜像,具体方法参考:Java应用打包成Docker镜像
创建namespace
kubectl create ns istio-demos
添加istio-injection
kubectl label namespaces istio-demos istio-injection=enabled
查看标签是否添加成功
kubectl describe ns istio-demos

如果要删除标签的话,执行下面命令:
kubectl label namespaces istio-demos istio-injection-
创建service account
demo-sa.yaml内容如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: istio-demo
执行命令创建service account
kubectl apply -f demo-sa.yaml -n istio-demos
apiVersion: v1
kind: Service
metadata:
name: istio-springboot-demo-a
labels:
app: istio-springboot-demo-a
service: istio-springboot-demo-a
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: istio-springboot-demo-a
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-springboot-demo-a-v1
spec:
replicas: 1
selector:
matchLabels:
app: istio-springboot-demo-a
version: v1
template:
metadata:
labels:
app: istio-springboot-demo-a
version: v1
spec:
serviceAccountName: istio-demo
containers:
- image: demo-istio-springboot-demo-a:1.0-SNAPSHOT
imagePullPolicy: IfNotPresent
name: istio-springboot-demo-a
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-springboot-demo-a-latest
spec:
replicas: 1
selector:
matchLabels:
app: istio-springboot-demo-a
version: latest
template:
metadata:
labels:
app: istio-springboot-demo-a
version: latest
spec:
serviceAccountName: istio-demo
containers:
- image: demo-istio-springboot-demo-a:latest
imagePullPolicy: IfNotPresent
name: istio-springboot-demo-a
ports:
- containerPort: 8080
执行kubectl 命令创建service, Deployment
kubectl apply -f demo-a-vault.yaml -n istio-demos
创建Gateway和VirtualService
demo-a-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-springboot-demo-a-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-springboot-demo-a
spec:
hosts:
- "*"
gateways:
- istio-springboot-demo-a-gateway
http:
- route:
- destination:
host: istio-springboot-demo-a
port:
number: 8080
执行kubectl 命令:
kubectl apply -f demo-a-gateway.yaml -n istio-demos
查看标签为istio: ingressgateway 的service的EXTERNAL-IP
通过如下命令查看serivce信息:
kubectl get service -n istio-system
输出结果如下:
% kubectl get service -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 10.109.66.208 <none> 3000/TCP 5d8h
istio-egressgateway ClusterIP 10.106.23.204 <none> 80/TCP,443/TCP 5d9h
istio-ingressgateway LoadBalancer 10.104.206.232 localhost 15021:30447/TCP,80:32629/TCP,443:32284/TCP 5d9h
istiod ClusterIP 10.104.111.126 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 5d10h
jaeger-collector ClusterIP 10.97.49.134 <none> 14268/TCP,14250/TCP,9411/TCP 5d8h
kiali ClusterIP 10.105.33.122 <none> 20001/TCP,9090/TCP 5d9h
prometheus ClusterIP 10.96.74.154 <none> 9090/TCP 5d8h
tracing ClusterIP 10.98.198.75 <none> 80/TCP,16685/TCP 5d8h
zipkin ClusterIP 10.106.169.170 <none> 9411/TCP 5d8h
瞅着istio-ingressgateway最有可能,查看一下这个Service信息:
kubectl describe service istio-ingressgateway -n istio-systems
输出结果如下:

3.在/etc/hosts 中添加域名
Service istio-ingressgateway的EXTERNAL-IP是locahost, 可以在/etc/hosts中添加一个域名指向这个127.0.0.1,如下:

浏览器访问应用接口
通过域名访问: http://demoa.istiodemos.com/test/get?a=a35

此时会随机路由到v1版本和latest版本
要实现更精细的路由管理就需要添加DestinationRule,以及对VirtualService做些许调整。
先将之前实验使用到的Gateway和VirtualService删除:
kubectl delete -f demo-a-gateway.yaml -n istio-demos
现在调整路由规则:
querystring a 匹配上正则时,路由到v1版本,否则都路由到latest版本
v1版本的querystring a正则规则:av\d+$
demo-a-route-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-springboot-demo-a-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: istio-springboot-demo-a-dr
spec:
host: istio-springboot-demo-a
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: latest
labels:
version: latest
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-springboot-demo-a-vs
spec:
hosts:
- "*"
gateways:
- istio-springboot-demo-a-gateway
http:
- match:
- queryParams:
a:
# exact: ad
regex: av\d+$
route:
- destination:
host: istio-springboot-demo-a
subset: v1
- route:
- destination:
host: istio-springboot-demo-a
subset: latest
执行kubectl 命令:
kubectl apply -f demo-a-route-gateway.yaml -n istio-demos
实验:
1、http://demoa.istiodemos.com/test/get?a=av35 路由到v1版本

2、http://demoa.istiodemos.com/test/get?a=adfdsf 路由到latest版本
