[Cloud Native | Learn istio from scratch] Five, istio grayscale release and core resources

insert image description here

Follow the previous chapter to deploy bookinfo

1.进入 istio 安装目录。 

2.istio 默认自动注入 sidecar,需要为 default 命名空间打上标签 istio-injection=enabled,然后 default 也会自动注入了
[root@k8smaster istio-1.10.1]# kubectl label namespace default istio-injection=enabled 
namespace/default labeled

3.使用 kubectl 部署应用 
[root@k8smaster istio-1.10.1]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)可以去自己查看一下这个yaml写的啥。 

4.确认所有的服务和 Pod 都已经正确的定义和启动: 
[root@k8smaster istio-1.10.1]# kubectl get services
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.97.7.165     <none>        9080/TCP   2m22s
productpage   ClusterIP   10.105.145.13   <none>        9080/TCP   2m22s
ratings       ClusterIP   10.105.6.245    <none>        9080/TCP   2m22s
reviews       ClusterIP   10.106.50.234   <none>        9080/TCP   2m22s

[root@k8smaster istio-1.10.1]# kubectl get pods 
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-65bbfd4f58-7w985       2/2     Running   0          2m45s
productpage-v1-6b746f74dc-hxn89   2/2     Running   0          2m44s
ratings-v1-b45758b-kz668          2/2     Running   0          2m45s
reviews-v1-74894b48c8-g8nv8       2/2     Running   0          2m44s
reviews-v2-f649764d-2lc54         2/2     Running   0          2m45s
reviews-v3-6c675c6774-smbvr       2/2     Running   0          2m45s
 
5.确认 Bookinfo 应用是否正在运行,在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings: 
[root@k8smaster istio-1.10.1]# kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>" 
#显示下面这个就是没问题
<title>Simple Bookstore App</title>

6.确定 Ingress 的 IP 和端口 
现在 Bookinfo 服务已经启动并运行,你需要使应用程序可以从 Kubernetes 集群外部访问,例如从浏览器访问,那可以用 Istio Gateway 来实现这个目标。 
1)为应用程序定义 gateway 网关: 
[root@k8smaster istio-1.10.1]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml 
#这个yaml里的控制器是ingressgateway,对应了istio-system下的ingresspod,hosts:*是所有主机,下一个定义的是虚拟服务。
[root@k8smaster istio-1.10.1]# kubectl describe pods istio-ingressgateway-569f64cdf8-kc8cj -n istio-system
#也可以查看它的详细信息,里面有个标签istio=ingressgateway,网管会找到这个pod去进行操作。
[root@k8smaster istio-1.10.1]# kubectl api-versions | grep istio
install.istio.io/v1alpha1
networking.istio.io/v1alpha3
networking.istio.io/v1beta1
security.istio.io/v1beta1
telemetry.istio.io/v1alpha1
#查看istio的apiversion

2)确认网关创建完成: 
[root@k8smaster istio-1.10.1]# kubectl get gateway 
NAME               AGE
bookinfo-gateway   19s
[root@k8smaster istio-1.10.1]# kubectl get virtualservice
NAME       GATEWAYS               HOSTS   AGE
bookinfo   ["bookinfo-gateway"]   ["*"]   19m

3)确定 ingress ip 和端口 
执行如下指令,明确自身 Kubernetes 集群环境支持外部负载均衡: 
[root@k8smaster istio-1.10.1]# kubectl get svc istio-ingressgateway -n istio-system
如果 EXTERNAL-IP 值已设置,说明环境正在使用外部负载均衡,可以用其为 ingress gateway 提供服务。如果 EXTERNAL-IP 值为<none>(或持续显示<pending>),说明环境没有提供外部负载均衡,无法使用 ingress gateway。无法使用域名访问,但是可以用ip和端口,在这种情况下,使用服务的 NodePort 访问网关。 
 
若自身环境未使用外部负载均衡器,需要通过 node port 访问。可以通过以下命令获取 Istio Gateway 的地址: 
 
[root@k8smaster istio-1.10.1]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') 
#定义一个变量 指定名称空间,获取到ingress映射到物理机的端口,端口协议是httpd2,赋值给这个变量。
[root@k8smaster istio-1.10.1]# echo $INGRESS_PORT
31411

[root@k8smaster istio-1.10.1]# export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') 
[root@k8smaster istio-1.10.1]# echo $SECURE_INGRESS_PORT
31608
 
4)设置 GATEWAY_URL 
[root@k8smaster istio-1.10.1]# INGRESS_HOST=192.168.11.129
[root@k8smaster istio-1.10.1]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT 
#把host和port的值赋给网关url
[root@k8smaster istio-1.10.1]# echo $GATEWAY_URL
192.168.11.129:31411
 
确认可以从集群外部访问应用,可以用 curl 命令来确认是否能够从集群外部访问 Bookinfo 应用程序: 
[root@k8smaster istio-1.10.1]# curl -s http://${GATEWAY_URL}/productpage | grep -o "<title>.*</title>" 
<title>Simple Bookstore App</title>

还可以用浏览器打开网址 192.168.11.129:31411/productpage 来浏览应用的 Web 页面。如果刷新几次应用的页面,就会看到 productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者没有显示)。 

通过 istio 的 ingressgateway 访问可以在官网学习: 
https://istio.io/docs/examples/bookinfo/#determine-the-ingress-ip-and-port 
 
扩展:添加外部 IP-extertal-IP 
[root@xianchaomaster1 ~]# kubectl edit svc istio-ingressgateway -n istio-system
在clusterIPs:下添加
externalIPs:
  - 192.168.11.129
在 windows 机器上的 C:\Windows\System32\drivers\etc\hosts 里面最后一行加上如下域名解析: 
192.168.11.129 productpage.xianchao.cn 
在浏览器访问 http://productpage.paopao.cn/productpage 就可以看到网站了!在自己电脑做了ip和域名,访问域名(默认的80,因为没制定)然后会访问到根据网关设置的80映射的端口31411,这个更符合七层代理。

卸载 bookinfo 服务 
可以使用下面的命令来完成应用的删除和清理了: 
1.删除路由规则,并销毁应用的 Pod 
sh samples/bookinfo/platform/kube/cleanup.sh 
2.确认应用已经关停 
kubectl get virtualservices #-- there should be no virtual services 
kubectl get destinationrules #-- there should be no destination rules 
kubectl get gateway #-- there should be no gateway 
kubectl get pods #-- the Bookinfo pods should be deleted 

VirtualService中文名称虚拟服务,是istio中一个重要的资源,它定义了一系列针对指定服务的流量路由规则。每个路由规则都针对特定协议的匹配规则。如果流量符合这些特征,就会根据规则发送到服务注册表中的目标服务(或者目标服务的子集或版本)。

Grayscale release through Istio

What is Grayscale Publishing?

Grayscale release is also called canary release, which refers to the gradual replacement of old and new versions by controlling the proportion of traffic.

For example, there are two versions of service A, version1 and version2. The current two versions are deployed at the same time, but the proportion of version1 is 90%, and the proportion of version2 is 10%. It depends on the operation effect. If the effect is good, gradually adjust the traffic ratio to 80-20, 70-30 · ····10~90, 0, 100, the final version1 is offline.

Features of Grayscale Release:

1) The new boss coexists
2) The proportion can be dynamically adjusted in real time according to the feedback
3) Theoretically, there is no complete downtime of the service.
4) Suitable for smooth upgrade and dynamic update of services.

Use istio for grayscale publishing

[root@k8snode1 ~]# docker load -i canary-v2.tar.gz 
[root@k8snode1 ~]# docker load -i canary-v1.tar.gz 
[root@k8smaster ~]# mkdir istio-canary
[root@k8smaster ~]# cd istio-canary/
[root@k8smaster istio-canary]# vim deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv1
  labels:
    app: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v1
      apply: canary
  template:
    metadata:
      labels:
        app: v1
        apply: canary
    spec:
      containers:
      - name: nginx
        image: xianchao/canary:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv2
  labels:
    app: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v2
      apply: canary
  template:
    metadata:
      labels:
        app: v2
        apply: canary
    spec:
      containers:
      - name: nginx
        image: xianchao/canary:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
[root@k8smaster istio-canary]# kubectl apply -f deployment.yaml
[root@k8smaster istio-canary]# kubectl get deployment
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
appv1            1/1     1            1           2m4s
appv2            1/1     1            1           2m4s

创建 service
[root@k8smaster istio-canary]# vim service.yaml
apiVersion: v1
kind: Service 
metadata: 
  name: canary 
  labels: 
    apply: canary
spec: 
  selector:
    apply: canary
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
[root@k8smaster istio-canary]# kubectl apply -f service.yaml 
[root@k8smaster istio-canary]# kubectl get svc
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
canary        ClusterIP   10.104.100.198   <none>        80/TCP     16s

创建 gateway 
[root@k8smaster istio-canary]# vim gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway 
metadata: 
  name: canary-gateway
spec: 
  selector:
    istio: ingressgateway
  servers:
  - port: 
      number: 80
      name: http
      protocol: HTTP 
    hosts:
    - "*"
[root@k8smaster istio-canary]# kubectl apply -f gateway.yaml
[root@k8smaster istio-canary]# kubectl get gateway
NAME               AGE
canary-gateway     15s

创建 virtualservice(虚拟服务)
[root@k8smaster istio-canary]# vim virtual.yaml 
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1		#v1的全局量域名权重90
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2		#v2的全局量域名权重10
      weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule						#目标规则
metadata:
  name: canary			
spec:
  host: canary.default.svc.cluster.local	#全局量域名
  subsets:
  - name: v1
    labels:
      app: v1
  - name: v2
    labels:
      app: v2
[root@k8smaster istio-canary]# kubectl apply -f virtual.yaml
[root@k8smaster istio-canary]# kubectl get virtualservice
NAME       GATEWAYS               HOSTS   AGE
canary     ["canary-gateway"]     ["*"]   2m22s
[root@k8smaster istio-canary]# kubectl get DestinationRule
NAME     HOST                               AGE
canary   canary.default.svc.cluster.local   2m54s
[root@k8smaster istio-canary]# vim /etc/hosts
192.168.11.129 productpage.paopao.cn
#添加一个域名解析,下面验证的时候域名也可以

验证金丝雀发布效果: 
[root@k8smaster istio-canary]# for i in `seq 1 100`; do curl productpage.paopao.cn;done > 1.txt
或者
[root@k8smaster istio-canary]# for i in `seq 1 100`; do curl 192.168.40.180:30871;done > 1.txt #请求100次
打开 1.txt 可以看到结果有 90 次出现 v1,10 次出现 canary-v2,符合我们预先设计的流量走向。 

Interpretation of istio core resources

Gateway

In a Kubernetes environment, the Ingress controller (layer seven proxy) is used to manage traffic entering the cluster. In the Istio service grid, the Istio Ingress Gateway assumes the corresponding role, and it uses the new configuration model (Gateway and VirtualServices) to complete the function of traffic management. Make a general description through the figure below.
insert image description here
1. The user sends a request to a certain port

2. The load balancer listens to the port and forwards the request to a node in the cluster. The Istio Ingress Gateway Service will listen for requests from cluster node ports

3. The Istio Ingress Gateway Service hands the request to the Istio Ingress Gateway Pod for processing. The IngressGateway Pod handles requests through Gateway and VirtualService configuration rules. Among them, Gateway is used to configure ports, protocols and certificates; VirtualService is used to configure some routing information (find the service App Service corresponding to the request)

4. Istio Ingress Gateway Pod forwards the request to App Service

5. The final request will be handed over to the App Deployment associated with the App Service for processing

[root@k8smaster istio-canary]# cat gateway.yaml 
apiVersion: networking.istio.io/v1beta1 
kind: Gateway 
metadata: 
  name: canary-gateway 
spec: 
  selector: 
    istio: ingressgateway 
  servers: 
  - port: 
      number: 80 
      name: http 
      protocol: HTTP 
    hosts: 
    - "*" 

A gateway is a load balancer running at the edge of the mesh to receive incoming or outgoing HTTP/TCP connections. The main job is to accept external requests and forward them to internal services. Ingress traffic at the edge of the grid will enter the cluster through the corresponding Istio IngressGateway Controller.
In the above yaml, we configured an ingress gateway listening on port 80, which will import http traffic on port 80 to the corresponding Virtual Service in the cluster.
Note: hosts:

  • "*"
    * represents a wildcard, which can be accessed through any domain name

VirtualService

VirtualService is a core configuration of Istio traffic governance, arguably the most important and complex in Istio traffic governance. VirtualService formally represents a virtual service that forwards all traffic that meets the conditions to the corresponding service backend. This service backend can be a service or a subset of services defined in DestinationRule.

[root@k8smaster istio-canary]# cat virtual.yaml 
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: v1
  - name: v2
    labels:
      app: v2

This virtual service will receive all http traffic from port 80 in the previous gateway.

VirtualService is mainly composed of the following parts
1. hosts: virtual host name, if in Kubernetes cluster, this host name can be service service name.
The hosts field lists the virtual hosts for the virtual service. It is one or more addresses used by the client to send a request to the service, access the virtual service through the address provided in this field, and then access the backend service. When used inside the cluster (in the grid), it usually has the same name as the Service of kubernetes; when it needs to be accessed outside the cluster (outside the grid), this field is the address requested by the gateway, which is the same as the hosts field of the gateway.
hosts:

  • The hostname for the reviews
    virtual service can be an IP address, a DNS name, or a short name (such as the Kubernetes service short name) that resolves to a Fully Qualified Domain Name (FQDN) implicitly or explicitly, depending on the istio dependencies platform. A set of routing rules can be created for all matching services using a prefix wildcard ("*"). The hosts of the virtual service are not necessarily part of the Istio service registry, they are just virtual destinations that allow the user to model traffic for virtual hosts that the mesh cannot route to.

When the hosts short domain name of the virtual service is resolved to a complete domain name, the completed namespace is the namespace where the VirtualService is located, not the namespace where the Service is located. The hosts in the above example will be resolved as: reviews.default.svc.cluster.local. When writing, it is best to use the global domain name
hosts:

  • "*"
    * means a wildcard, any domain name is fine, for example, configure the hosts file
    192.168.11.129 k8smaster hello.com.cn
    in the virtual machine, so that you can access the internal services of istio through the domain name hello.com.cn in the virtual machine

Extension: virtualservice configuration routing
rules The functions of routing rules are: traffic that meets the http.match condition is routed to http.route.destination, and redirection (HTTPRedirect), rewriting (HTTPRewrite), retry (HTTPRetry), and fault injection are performed (HTTPFaultInjection), cross-site (CorsPolicy) strategy, etc. HTTPRoute can not only do route matching, but also do some write operations to modify the request itself.
as follows:

apiVersion: networking.istio.io/v1alpha3 
kind: VirtualService 
metadata: 
 name: reviews 
spec: 
 hosts: 
 - reviews 
 http: 
 - match: 
 - headers: 
 end-user: 
 exact: jason 
 route: 
 - destination: 
 host: reviews 
 subset: v2 
 - route: 
 - destination: 
 host: reviews 
 subset: v3 
在 http 字段包含了虚拟服务的路由规则,用来描述匹配条件和路由行为,它们把 HTTP/1.1、HTTP2 和 gRPC 等流量发送到 hosts 字段指定的目标。示例中的第一个路由规则有一个条件,以 match 字段开始。此路由接收来自 ”jason“ 用户的所有请求,把请求发送到 destination 指定的 v2 子集。 
 
路由规则优先级 
在上面例子中,不满足第一个路由规则的流量均流向一个默认的目标,该目标在第二条规则中指定。因此,第二条规则没有 match 条件,直接将流量导向 v3 子集。多路由规则详细配置可参考: https://istio.io/latest/zh/docs/reference/config/networking/virtualservice/#HTTPMatchRequest 

apiVersion: networking.istio.io/v1alpha3 
kind: VirtualService 
metadata: 
 name: bookinfo 
spec: 
 hosts: 
 - bookinfo.com 
 http: 
 - match: 
 - uri: 
 	prefix: /reviews 
 route: 
 - destination: 
 	host: reviews 
 - match: 
 - uri: 
	 prefix: /ratings 
 route: 
 - destination: 
	 host: ratings 
 
路由规则是将特定流量子集路由到指定目标地址的工具。可以在流量端口,header字段,URI等内容上设置匹配条件。例如上面这个虚拟服务让用户发送请求到两个独立的服务ratings和reviews,相当于访问http://bookinfo.com/ratings和http://bookinfo.com/reviews,虚拟服务规则根据请求的 URI 把请求路由到特定的目标地址。 

2、Gateway:流量来源网关。 

3、路由
路由的 destination 字段指定了匹配条件的流量的实际地址。与 virtual service 的主机不同,该 host 必须是存在于 istio 的服务注册表(如 kubernetes services,consul services 等)中的真实目的地或由 ServiceEntries 声明的 hosts,否则 Envoy 不知道应该将流量发送到哪里。它可以是一个带代理的网格服务或使用 service entry 添加的非网格服务。在 kubernetes 作为平台的情况下,host 表示名为 kubernetes 的 service 名称: 
- destination: 
host: canary.default.svc.cluster.local 
subset: v1 
weight: 90	#权重,多少流量到这

DestinationRule

Destination rules are an important part of istio's traffic routing capabilities. A virtual service can be seen as how to distribute traffic to a specific destination, and then call the destination rule to configure the traffic distributed to the destination. The destination rule works after the routing rules of the virtual service (that is, it works after the math->route-destination of the virtual service, and it works only if the rule does not match, and the traffic has been distributed to the real service at this time) applied to the real destination. You can use the destination rule to specify named service subsets, such as grouping service instances according to versions, and then distribute control traffic to different service instances through the service subsets in the routing rules of the virtual service.

apiVersion: networking.istio.io/v1beta1 
kind: DestinationRule 
metadata: 
 name: canary 
spec: 
 host: canary.default.svc.cluster.local 
 subsets: 
 - name: v1 
 labels: 
 app: v1 
 - name: v2 
 labels: 
 app: v2 
在虚拟服务中使用 Hosts 配置默认绑定的路由地址,用 http.route 字段,设置 http 进入的路由地址,可以看到,上面导入到了目标规则为 v1 和 v2 的子集。 
 
v1 子集对应的是具有如下标签的 pod: 
selector: 
matchLabels: 
app: v1 
 
流量控制流程: 
Gateway->VirtaulService->TCP/HTTP Router->DestinationWeight->Subset:Port

write at the end

It is not easy to create, if you think the content is helpful to you, please support me by giving me three consecutive attentions! If there is an error, please point it out in the comment area, and I will change it in time!

The series currently being updated: learn istio from scratch

Thank you for watching, the article is mixed with personal understanding, if there is any mistake, please contact me to point out~

Guess you like

Origin blog.csdn.net/qq_45400861/article/details/127573831