版本

istio: 1.2.5
K8S:v1.14.6
所用示例容器nginx

编写示例YAML

1、nginx service

vi nginx-service.yaml
---
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: nginx
    app: nginx
    istio: ingressgateway
  name: nginx
  namespace: default
  annotations:
    prometheus.io/port: "9913"
    prometheus.io/scrape: 'true'    
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  selector:
    k8s-app: nginx
    app: nginx
    istio: ingressgateway
  ports:
    - protocol: TCP
      port: 80
      name: web
    - protocol: TCP
      port: 8080
      name: vts
    - protocol: TCP
      port: 9913
      name: http-metrics
  type: ClusterIP

2、nginx Monitor

vi nginx-Monitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    k8s-app: nginx
  name: nginx
  namespace: default
spec:
  endpoints:
  - honorLabels: true
    interval: 15s
    port: http-metrics
  jobLabel: k8s-app
  selector:
    matchLabels:
      k8s-app: nginx

3、nginx ingress

# 说明: 由于前期已经部署好traefik 作为整个K8S 集群作为出口为了方便管理这里依然使用traefik 对外提供服务
vi nginx-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
  namespace: istio-system # istio-ingressgateway 部署命名空间
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.frontend.rule.type: PathPrefixStrip
spec:
  rules:
  - host: nginx.xxxx.com
    http:
      paths:
        - path: /
          backend:
            serviceName: istio-ingressgateway
            servicePort: 80

4、nginx ratings

vi nginx-ratings.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
   name: nginx-ratings
   namespace: default
spec:
   host: nginx
   trafficPolicy:   # 后端转发规则基于Cookie user 作为后端转发这样能保持session 
      loadBalancer:
       consistentHash:
         httpCookie:
           name: user
           ttl: 0s           
   subsets:  # 定义准发版本gateway 用到
   - name: v1
     labels:
       version: v1
   - name: v2
     labels:
       version: v2 

5、nginx gateway

# 说明: 添加流量入库百分比更新版本时更改此配置即可 下面是V2 版本百分之90流量 v1版本百分之10的流量 
vi nginx-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: nginx-web-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: web
      protocol: HTTP
    hosts:
    - "nginx.xxxx.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-web
  namespace: default
spec:
  hosts:
  - "nginx.xxxx.com"
  gateways:
  - nginx-web-gateway
  http:
  - match:
    - port: 80
    route:
    - destination:
        host: nginx
        port:
          number: 80
        subset: v2
      weight: 90
    - destination:
        host: nginx
        port:
          number: 80
        subset: v1
      weight: 10

6、nginx deployment v1

vi nginx-deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: nginx
      app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
        app: nginx # 必须有按照流量比例转发会用到
        istio: ingressgateway
        version: v1 # 必须有按照流量比例转发会用到
      annotations:
        sidecar.istio.io/inject: "true"
        #traffic.sidecar.istio.io/includeInboundPorts: "80,8080"     # 配置那些端口走proxy 默认是全局端口走proxy 如果配置这个端口kiali 状态监测会有报错提示
    spec:
      containers:
        - name: nginx
          image: docker.xxxx.com/library/nginx
          imagePullPolicy: IfNotPresent
          lifecycle:
            postStart:
              exec:
                command:  ["/bin/sh", "-c", "echo Hello v1 > /www/index.html"]
          ports:
            - containerPort: 80
              name: web
              protocol: TCP
            - containerPort: 8080
              name: vts
              protocol: TCP
          readinessProbe:
            failureThreshold: 10
            httpGet:
              path: /healthz
              port: vts
              scheme: HTTP
            initialDelaySeconds: 3
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 3
          resources:
            requests:
              cpu: 200m
              memory: 200Mi
        - name: nginx-vts-exporter
          image: docker.xxxx.com/library/nginx-vts-exporter
          imagePullPolicy: IfNotPresent
          args:
          - "-nginx.scrape_uri=http://localhost:8080/format/json"
          ports:
            - containerPort: 9913
              name: http-metrics
              protocol: TCP
          resources:
            requests:
              memory: 30Mi
              cpu: 102m
            limits:
              memory: 50Mi
              cpu: 250m

7、 nginx deployment v2

vi nginx-deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: nginx
      app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
        app: nginx
        istio: ingressgateway
        version: v2
      annotations:
        sidecar.istio.io/inject: "true"
        #traffic.sidecar.istio.io/includeInboundPorts: "80,8080"    
    spec:
      containers:
        - name: nginx
          image: docker.xxxx.com/library/nginx
          imagePullPolicy: IfNotPresent
          lifecycle:
            postStart:
              exec:
                command:  ["/bin/sh", "-c", "echo Hello v2 > /www/index.html"]
          ports:
            - containerPort: 80
              name: web
              protocol: TCP
            - containerPort: 8080
              name: vts
              protocol: TCP
          readinessProbe:
            failureThreshold: 10
            httpGet:
              path: /healthz
              port: vts
              scheme: HTTP
            initialDelaySeconds: 3
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 3
          resources:
            requests:
              cpu: 200m
              memory: 200Mi
        - name: nginx-vts-exporter
          image: docker.xxxx.com/library/nginx-vts-exporter
          imagePullPolicy: IfNotPresent
          args:
          - "-nginx.scrape_uri=http://localhost:8080/format/json"
          ports:
            - containerPort: 9913
              name: http-metrics
              protocol: TCP
          resources:
            requests:
              memory: 30Mi
              cpu: 102m
            limits:
              memory: 50Mi
              cpu: 250m

创建示例

kubectl apply -f .
# 查看示例是否完成启动
[root@]/mnt/e/work/k8s-nginx]#kubectl get all -n default | grep nginx
pod/nginx-v1-7f49cf7db7-bcp8k   3/3     Running   0          31m

pod/nginx-v1-7f49cf7db7-z4fwk   3/3     Running   0          31m

pod/nginx-v2-75d9ff9695-j4pf5   3/3     Running   0          33m
pod/nginx-v2-75d9ff9695-wmsht   3/3     Running   0          33m
service/nginx                      ClusterIP   10.64.72.76     <none>        80/TCP,8080/TCP,9913/TCP      47h

deployment.apps/nginx-v1   2/2     2            2           47h

deployment.apps/nginx-v2   2/2     2            2           47h

replicaset.apps/nginx-v1-56d79b9dc5   0         0         0       47h

replicaset.apps/nginx-v1-7698f86885   0         0         0       47h

replicaset.apps/nginx-v1-7f49cf7db7   2         2         2       31m
replicaset.apps/nginx-v1-7f9f9f466c   0         0         0       47h
replicaset.apps/nginx-v2-54bd7f7d78   0         0         0       47h
replicaset.apps/nginx-v2-598c855cdd   0         0         0       47h
replicaset.apps/nginx-v2-645c549b48   0         0         0       47h
replicaset.apps/nginx-v2-75d9ff9695   2         2         2       33m

http://10.64.72.76 看看能否访问
[root@]/mnt/e/work/k8s-nginx]#curl 10.64.72.76
Hello v1
[root@]/mnt/e/work/k8s-nginx]#kubectl get Ingress -n istio-system | grep nginx
nginx    nginx.xxxx.com              80, 443   7d20h
dns 解析到 Ingress 所在服务器然后访问
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v2

测试流量切换

所有流量走v1 版本
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-web
  namespace: default
spec:
  hosts:
  - "nginx.xxxx.com"
  gateways:
  - nginx-web-gateway
  http:
  - match:
    - port: 80
    route:
    - destination:
        host: nginx
        port:
          number: 80
        subset: v2
      weight: 0
    - destination:
        host: nginx
        port:
          number: 80
        subset: v1
      weight: 100
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
^[[AHello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
# 查看kiali

istio 示例

# v1 百分之90 v2 百分之10
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-web
  namespace: default
spec:
  hosts:
  - "nginx.xxxx.com"
  gateways:
  - nginx-web-gateway
  http:
  - match:
    - port: 80
    route:
    - destination:
        host: nginx
        port:
          number: 80
        subset: v2
      weight: 10
    - destination:
        host: nginx
        port:
          number: 80
        subset: v1
      weight: 90

[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v2
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v2
[root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v1
# 再次查看kiali

istio 示例

# 业务没问题把v1 配置0 v2 100 
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-web
  namespace: default
spec:
  hosts:
  - "nginx.xxxx.com"
  gateways:
  - nginx-web-gateway
  http:
  - match:
    - port: 80
    route:
    - destination:
        host: nginx
        port:
          number: 80
        subset: v2
      weight: 100
    - destination:
        host: nginx
        port:
          number: 80
        subset: v1
      weight: 0
    [root@]/mnt/e/work/k8s-nginx]#curl  nginx.xxxx.com
Hello v2
# 已经切换到v2 版本
# 再次查看 kiali

istio 示例
istio 示例
istio 示例

这只是一个简单的示例

istio 还可以根据用户进行更新或者Cookie 里面的数据进行灰度更新

istio 示例

红色就是一个项目的用户名称

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name:  nginx-web
spec:
  hosts:
  - "nginx.xxxx.com"
  http:
  - match:
    - headers:
        cookie:
          regex: "^(.*?;)?(za=demo)(;.*)?$"
    route:
    - destination:
        host: nginx
        subset: v2
  - route:
    - destination:
        host: nginx
        subset: v1

# 用户demo 登陆会走v2 版本