[单master节点k8s部署]27.Istio流量管理(三)
上面的内容先是部署了istio,后面又部署了bookinfo的微服务,现在来利用istio对bookinfo进行流量治理。
设置网关
进入/root/istio-1.10.1/samples/bookinfo/networking目录下,运行下面yaml文件,从而进行网关配置:
[root@master networking]# kubectl apply -f bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
确认网关是否创建完成:
[root@master networking]# kubectl get gateway
NAME AGE
bookinfo-gateway 66m
yaml文件中有一个gateway,一个virtualService。 Gateway 定义的是进出的端口、协议、主机名等网络层的配置。它不关心请求的具体路径或内容,而是为外部请求打开一个入口。而virtualService用来定义具体的路由规则。
下面的gateway配置中可以看到,hosts为任何主机名,入口为80端口,允许进入的是http请求。
而virtualService中定义了目标端口,为productpage的9080端口,对于进入gateway的http请求,只允许转发匹配到/productpage、/login等的。
[root@master networking]# cat bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
事实上,当我们查看istio的三个pod,可以发现有一个ingressgateway的pod
[root@master networking]# kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istio-egressgateway-798787bd74-kj7tr 1/1 Running 0 25h
istio-ingressgateway-5d6489bf96-ps5t5 1/1 Running 0 25h
istiod-7d58bfb8-xtfjd 1/1 Running 0 25h
而这个ingressgateway的pod,有以下标签,而我们写的gateway的selector就匹配了其中的标签。
Labels: app=istio-ingressgateway
chart=gateways
heritage=Tiller
install.operator.istio.io/owning-resource=unknown
istio=ingressgateway
istio.io/rev=default
operator.istio.io/component=IngressGateways
pod-template-hash=5d6489bf96
release=istio
service.istio.io/canonical-name=istio-ingressgateway
service.istio.io/canonical-revision=latest
sidecar.istio.io/inject=false
所以,我们写的gateway.yaml实际是指导istio的ingressgateway的pod来如何处理流量,实际当外部客户端发送请求(例如通过 HTTP 或 HTTPS),这些请求会首先到达 istio-ingressgateway Pod。Gateway 资源定义了这个 Pod 应该监听的端口(如 80 或 443),并且可以通过 VirtualService 进一步定义流量的路由规则。
蓝绿发布/金丝雀发布
上面的virtualservice里面有一个destination的字段,但是实际上为了实现蓝绿发布、金丝雀发布等更加高级的路由规则,可以另写一个destination的yaml文件。上面的virtualService定义的是针对所有host的,如果要针对不同的host,virtualservice需要定义不同的路由规则。假设有两个主机名:
myapp.example.com
testapp.example.com
其中针对myapp的主机名,进行了金丝雀发布,也就是只有10%的流量去v2版本,大部分都在v1版本处理。而对于testapp的主机名,进行蓝绿发布,也就是说v2是目前的版本,v1不再使用。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: multi-host-virtualservice
spec:
hosts:
- myapp.example.com
- testapp.example.com
http:
- match:
- headers:
host:
exact: myapp.example.com
route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: v2
subset: 10
- match:
- headers:
host:
exact: testapp.example.com
route:
- destination:
host: testapp
subset: v2
weight: 100
- destination:
host: testapp
subset: v1
weight: 0
这里还需要写service定义的destination文件,因为一个destination文件对应一个service,所以这里需要两个destination文件来描述myapp和testapp的配置。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp-destination
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: testapp-destination
spec:
host: test
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
流量镜像
流量镜像是一种测试策略,可以在不影响主流量的情况下,将请求副本发送到另一个服务,用于测试或监控。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp.example.com
http:
- route:
- destination:
host: myapp
subset: v1
- mirror:
host: myapp
subset: v2
mirrorPercentage:
value: 100.0
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
重试、超时和断路器
apiVersion: networking.iostio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp.example.com
http:
- route:
- destinatioon:
host: myapp
subset: v1
retries:
attempts: 3 #如果请求失败,最多试三次
perTryTimeout: 2s #每次请求的最大超时时间为2s
retryOn: gateway-error,connection-failure,refused-stream #重试的条件
timeout: 5s
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 100
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 5
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 50
确定ingress IP和端口
[root@master 34istio]# kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.105.230.164 <pending> 15021:32087/TCP,80:30636/TCP,443:32496/TCP,31400:32213/TCP,15443:30298/TCP 29h
可以看到,目前bookinfo无法从集群外部进行访问,针对这个问题,我们可以使用本地ip+暴露端口的方式来访问,已知productpage暴露的80端口映射到外面是30636端口,因此直接访问。根据上面的gateway规则,路径还需要加上productpage。
刷新页面,可以看到 book reviews部分的页面是会变化的,因为reviews有三个版本,且他们的selector都是一样的,所以在没有预设的情况下,istio会以轮询的方式给三个pod分发流量。
review流量转发规则
我们可以通过为review设置流量转发规则的方式来进行流量控制。已知review本身有一个服务svc,查看这个服务,可以看到selector是app:reviews
[root@master networking]# kubectl get svc reviews -o yaml
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"reviews","service":"reviews"},"name":"reviews","namespace":"default"},"spec":{"ports":[{"name":"http","port":9080}],"selector":{"app":"reviews"}}}
creationTimestamp: "2024-09-26T06:01:19Z"
labels:
app: reviews
service: reviews
name: reviews
namespace: default
resourceVersion: "8274224"
selfLink: /api/v1/namespaces/default/services/reviews
uid: fd3c4f5a-8081-41a9-8e39-1576d33ac078
spec:
clusterIP: 10.97.52.159
clusterIPs:
- 10.97.52.159
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: http
port: 9080
protocol: TCP
targetPort: 9080
selector:
app: reviews
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
我们写一个virtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
namespace: default
spec:
http:
- route:
- destination:
host: reviews
subset: v2
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
hosts:
- reviews
写一个destinationRule
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
namespace: default
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
就可以实现只展示v2和v3的reviews。