istio 灰度实验

istio 灰度实验

使用nginx模拟2个版本的后端服务,一个nginx做代理转发服务。

先结论:istio在匹配路由时使用服务hosts(services名)做匹配,如果hosts没匹配上路由规则不生效。

2个版本的nginx服务

启动后手工进入修改index.html 为 v1,v2。方便后期验证。

sh 复制代码
echo v1 > /usr/share/nginx/html/index.html 
echo v2 > /usr/share/nginx/html/index.html 
yaml 复制代码
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
  labels:
    app: nginx
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - image: nginx:1.17.8-alpine
        name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
  labels:
    app: nginx
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - image: nginx:1.17.8-alpine
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: nginx
  type: ClusterIP
代理转发服务
yaml 复制代码
---
apiVersion: v1
data:
  nginx.conf: |-
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    events {
      worker_connections  131072;
      multi_accept on;
    }
    
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      underscores_in_headers on;
      ignore_invalid_headers off;
    
      log_format  main  '$remote_addr - $remote_user [$time_local] "$host" "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';
    
      access_log  /var/log/nginx/access.log  main;
    
      server {
        listen   80;
        server_name _;
    
        # Add header
        # 这里重点,代理转发服务不能加上源hosts,否则转发会匹配不上istio路由规则。
        # proxy_set_header Host                     $http_host;
        proxy_set_header X-Real-IP                $remote_addr;
        proxy_set_header X-Forwarded-For          $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host         $http_host;
        proxy_set_header X-Forwarded-Port         $server_port;
        proxy_set_header X-Forwarded-Proto        $scheme;
        proxy_set_header X-Forwarded-Scheme       $scheme;
        proxy_set_header X-Scheme                 $scheme;
        proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
    
        # Route
        location ^~ / {
          proxy_pass    http://nginx:80;
        }
      }
    }
kind: ConfigMap
metadata:
  labels:
    app: nginx-route
  name: nginx-route
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-route
    service: nginx-route
  name: nginx-route
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-route
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-route
  name: nginx-route
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-route
  template:
    metadata:
      labels:
        app: nginx-route
    spec:
      containers:
      - image: nginx:1.22.1-alpine
        imagePullPolicy: IfNotPresent
        name: nginx-route
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        resources:
          limits:
            cpu: "2"
            memory: 1Gi
          requests:
            cpu: 20m
            memory: 256Mi
        volumeMounts:
        - mountPath: /etc/nginx/nginx.conf
          name: configs
          subPath: nginx.conf
      volumes:
      - configMap:
          name: nginx-route
        name: configs
配置istio gateway服务
yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: 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: nginx-route 
spec:
  hosts:
  - "*"
  gateways:
  - gateway
  http:
  - match:
    - uri:
        exact: /
    route:
    - destination:
        host: nginx-route
        port:
          number: 80
# 全部请求到nginx-route转发服务,再根据路由规则转发到不同的后端。
DestinationRule
yaml 复制代码
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: nginx
spec:
  host: nginx
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
查看服务状态
sh 复制代码
[root@test]# kubectl get pod,svc,configmap
NAME                               READY   STATUS    RESTARTS   AGE
pod/nginx-route-5458f4b5ff-jnsfm   2/2     Running   3          22h
pod/nginx-v1-7cdbb97474-nds9f      2/2     Running   2          23h
pod/nginx-v2-7f87f869c-gskqw       2/2     Running   2          23h

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP   23h
service/nginx         ClusterIP   10.110.225.75   <none>        80/TCP    23h
service/nginx-route   ClusterIP   10.103.42.115   <none>        80/TCP    22h

NAME                           DATA   AGE
configmap/istio-ca-root-cert   1      23h
configmap/nginx-route          1      22h

验证

配置好上面的服务使用crul请求istio-ingressgateway。

1、流量被随机分配到不同的服务。
sh 复制代码
[root@test]# IG=`kubectl get svc -A | grep ingressgateway | awk '{print $4}'`
[root@test]# for i in `seq 10`; do curl http://$IG;done
v1
v1
v1
v2
v1
v2
v2
v1
v2
v1
2、加上路由规则VirtualService

全部流量都访问v2服务

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx
spec:
  hosts:
    - nginx
  http:
  - route:
    - destination:
        host: nginx
        subset: v2

再请求全部流量都访问的v2

sh 复制代码
[root@test]# IG=`kubectl get svc -A | grep ingressgateway | awk '{print $4}'`
[root@test]# for i in `seq 10`; do curl http://$IG;done
v2
v2
v2
v2
v2
v2
v2
v2
v2
v2
3、修改nginx-route转发服务,带上源hosts后再请求。

configmap修改后须要重启代理服务生效。

sh 复制代码
      server {
        listen   80;
        server_name _;
    
        # Add header
        # 这里重点,代理转发服务不能加上源hosts,否则转发会匹配不上istio路由规则。
        proxy_set_header Host                     $http_host;
        proxy_set_header X-Real-IP                $remote_addr;
        proxy_set_header X-Forwarded-For          $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host         $http_host;
        proxy_set_header X-Forwarded-Port         $server_port;
        proxy_set_header X-Forwarded-Proto        $scheme;
        proxy_set_header X-Forwarded-Scheme       $scheme;
        proxy_set_header X-Scheme                 $scheme;
        proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
    
        # Route
        location ^~ / {
          proxy_pass    http://nginx:80;
        }

再请求发现又随机到不同的服务而不是按vs配置的只路由到v2服务。

sh 复制代码
[root@test]# IG=`kubectl get svc -A | grep ingressgateway | awk '{print $4}'`
[root@test]# for i in `seq 10`; do curl http://$IG;done
v1
v2
v1
v2
v1
v2
v1
v1
v1
v2
相关推荐
GreenMountainEcho6 小时前
Kubernetes 入门篇之 Node 安装与部署
云原生·容器·kubernetes
alden_ygq9 小时前
k8s statefulset pod重启顺序
云原生·容器·kubernetes
云上艺旅12 小时前
K8S学习之基础七十二:Ingress基于Https代理pod
学习·云原生·容器·https·kubernetes
liux352812 小时前
k8s之Ingress讲解
云原生·容器·kubernetes
阿里云云原生12 小时前
函数计算支持热门 MCP Server 一键部署
云原生
阿里云云原生13 小时前
AI 网关代理 LLMs 最佳实践
云原生
小刘爱喇石( ˝ᗢ̈˝ )16 小时前
玛卡巴卡的k8s知识点问答题(六)
云原生·容器·kubernetes
rider18916 小时前
【1】搭建k8s集群系列(二进制部署)之系统初始化
云原生·容器·kubernetes
阿里云云原生16 小时前
仅3步!即刻拥有 QwQ-32B,性能比肩全球最强开源模型
前端·云原生
小刘爱喇石( ˝ᗢ̈˝ )18 小时前
玛卡巴卡的k8s知识点问答题(七)
云原生·容器·kubernetes