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
相关推荐
lagrahhn28 分钟前
无服务器计算简单介绍
云原生·云计算·无服务器
张3231 小时前
ConfigMap
云原生·kubernetes
东北甜妹2 小时前
Docker 命令
云原生·eureka
倔强的胖蚂蚁3 小时前
Ollama 大模型参数调整
运维·人工智能·云原生
努力搬砖的咸鱼18 小时前
Label 与 Selector:Kubernetes 资源选择的核心机制
微服务·云原生·容器·架构·kubernetes
立莹Sir1 天前
SaaS多租户资源隔离的云原生解决方案:在不单独部署的情况下实现租户级资源保障
云原生
人道领域1 天前
GPT-5架构泄露?Kubernetes 1.31发布与Rust重构浪潮下的云原生之变
gpt·云原生·架构
刘~浪地球1 天前
云原生与容器--Service Mesh (Istio) 入门实战
云原生·istio·service_mesh
倔强的胖蚂蚁1 天前
Gemma4 优势与 Ollama 更新
运维·云原生
立莹Sir1 天前
【架构图解+实战配置】SaaS多租户资源隔离的云原生完整方案
云原生·架构