linux12企业实战 -- 09VirtualService(虚拟服务)

Posted FikL-09-19

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux12企业实战 -- 09VirtualService(虚拟服务)相关的知识,希望对你有一定的参考价值。

一、VirtualService(虚拟服务)

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

二、VirtualService和k8s service的区别

如果没有 Istio virtual service,仅仅使用 k8s service 的话,那么只能实现最基本的流量负载均衡转发,但是就不能实现类似按百分比来分配流量等更加复杂、丰富、细粒度的流量控制了。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  hosts:
    - "svc.test.com"
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local   # 代理的SVC

三、exportTo 生效命名空间

1、当前名称空间有效

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  exportTo:
    - "."
  hosts:
    - "svc.test.com"
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local   # 代理的SVC

2、所有名称空间有效

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  exportTo:
    - "*"
  hosts:
    - "svc.test.com"
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local   # 代理的SVC

3、VirtualService + Gateway

Gateway 名称列表,Sidecar 会据此使用路由。VirtualService 对象可以用于网格中的 Sidecar,也可以用于一个或多个 Gateway。这里公开的选择条件可以在协议相关的路由过滤条件中进行覆盖。保留字 mesh 用来指代网格中的所有 Sidecar。当这一字段被省略时,就会使用缺省值(mesh),也就是针对网格中的所有 Sidecar 生效。如果提供了 gateways 字段,这一规则就只会应用到声明的 Gateway 之中。要让规则同时对 Gateway 和网格内服务生效,需要显式的将 mesh 加入 gateways 列表。
1、单个gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: web-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: httpd
        protocol: HTTP
      hosts:
        - "svc.test.com"
    - port:
        number: 80
        name: nginx
        protocol: HTTP
      hosts:
        - "svc.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  hosts:
    - "svc.test.com"
  gateways:
    - web-gateway
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local
            port:
              number: 80
2、 测试结果
/ # while true; do wget -q -O- http://svc.test.com:32623 ;sleep 1; done
<html><body><h1>It works!</h1></body></html>
<h1>Welcome to nginx!</h1>
<h1>Welcome to nginx!</h1>
<html><body><h1>It works!</h1></body></html>
3、多个Gateway
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: web-gateway-nginx
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: nginx
        protocol: HTTP
      hosts:
        - "svc.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: web-gateway-httpd
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: httpd
        protocol: HTTP
      hosts:
        - "svc.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  hosts:
    - "svc.test.com"
  gateways:
    - web-gateway-nginx
    - web-gateway-httpd
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local
            port:
              number: 80
4、 测试结果
/ # while true; do wget -q -O- http://svc.test.com:32623 ;sleep 1; done
<html><body><h1>It works!</h1></body></html>
<html><body><h1>It works!</h1></body></html>
<html><body><h1>It works!</h1></body></html>
<h1>Welcome to nginx!</h1>
<html><body><h1>It works!</h1></body></html>
<h1>Welcome to nginx!</h1>
<html><body><h1>It works!</h1></body></html>

4、不同命名空间下的Gateway

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: web-gateway-httpd
  namespace: test
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: httpd
        protocol: HTTP
      hosts:
        - "svc.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-namespace
spec:
  hosts:
    - "svc.test.com"
  gateways:
    - test/web-gateway-httpd
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: httpd-web-svc.test.svc.cluster.local
            port:
              number: 80
5、省略gateways跨域
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx-web
  labels:
    app: nginx
    deploy: nginx
    server: web
spec:
  selector:
    matchLabels:
      app: nginx
      deploy: nginx
      server: web
  template:
    metadata:
      labels:
        app: nginx
        deploy: nginx
        server: web
    spec:
      containers:
        - name: nginx
          image: alvinos/nginx:v1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-web-svc
  labels:
    app: nginx-web-svc
    deploy: nginx-web-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      name: nginx
      protocol: TCP
  selector:
    server: web
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: web-gateway-nginx
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: nginx
        protocol: HTTP
      hosts:
        - "svc.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: allow
spec:
  hosts:
    - "svc.test.com"
  gateways:
    - default/web-gateway-nginx
  http:
    - corsPolicy:
        allowCredentials: true   # 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。
        allowOrigins: # 响应头指定了该响应的资源是否被允许与给定的origin共享。
          - exact: "http://svc.test.com:32623" # 完全匹配
      match:
        - uri:
            prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local
            port:
              number: 80

6、allowOrigins prefix(前缀匹配)

  http:
    - corsPolicy:
        allowCredentials: true   # 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。
        allowOrigins: # 响应头指定了该响应的资源是否被允许与给定的origin共享。
          - prefix: "http://svc.test.com" 

8、allowOrigins regex(正则匹配)

  http:
    - corsPolicy:
        allowCredentials: true   # 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。
        allowOrigins: # 响应头指定了该响应的资源是否被允许与给定的origin共享。
          - regex: ".*"

9、设置exposeHeaders

 http:
    - corsPolicy:
        allowCredentials: true
        allowOrigins:
          - prefix: "http://localhost" 
        exposeHeaders:  # 响应头指定了该响应首部添加响应header头
          - test
          - test2

10、设置allowHeaders

    allowHeaders:
      - X-Custom-Header
      - content-type

11、设置allowMethods

 allowMethods:
          - GET
          - DELETE 

12、长短fqdn

# 在default名称空间创建vs
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-fqdn
spec:
  hosts:
    - "nginx.default.svc.cluster.local"   # 长fqdn
    - "nginx" # 短fqdn
  http:
    - match:
        - uri:
          prefix: /
      route:
        - destination:
            host: nginx-web-svc.default.svc.cluster.local
            port:
              number: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
    - port: 80
      name: http
  selector:
    app: nginx

四、基于TLS的HTTPS请求

一个有序列表,对应的是透传 TLS 和 HTTPS 流量。路由过程通常利用 ClientHello 消息中的 SNI 来完成。TLS 路由通常应用在 https-、tls- 前缀的平台服务端口,或者经 Gateway 透传的 HTTPS、TLS 协议端口,以及使用 HTTPS 或者 TLS 协议的 ServiceEntry 端口上。注意:没有关联 VirtualService 的 https- 或者 tls- 端口流量会被视为透传 TCP 流量。

1、创建证书

# 因为是测试环境,我在这里手动签发证书,如果是生产环境最好在云服务商哪里购买证书
[root@kubernetes-master-01 cert]# openssl genrsa -out tls.key 2048
[root@kubernetes-master-01 cert]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=ShangHai/L=ShangHai/O=Ingress/CN=svc.test.com

2、创建secret

[root@kubernetes-master-01 cert]# kubectl -n default create secret tls nginx-tls --cert=tls.crt --key=tls.key
secret/nginx-tls created
[root@kubernetes-master-01 cert]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
nginx-tls             kubernetes.io/tls                     2      19s

3、创建Nginx配置文件

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tls
  labels:
    app: tls
data:
  nginx.conf: |
    worker_processes auto;
    error_log /var/log/nginx/error.log;
    pid /run/nginx.pid;
    events 
        worker_connections 1024;
    
    http 
         log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';
         access_log  /var/log/nginx/access.log  main;
         include             /etc/nginx/mime.types;
         default_type        application/octet-stream;
         server 
             listen 443 ssl;
             ssl_certificate /etc/nginx-server-certs/tls.crt;
             ssl_certificate_key /etc/nginx-server-certs/tls.key;
             server_name  _;
             location / 
                root         /usr/share/nginx/html;
                index index.html;
             
         
    

4、创建Deployment资源

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: tls
spec:
  selector:
    matchLabels:
      app: tls
  template:
    metadata:
      labels:
        app: tls
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: nginx 
          volumeMounts:
            - mountPath: /etc/nginx/nginx.conf
              name: nginxconfig
              readOnly: true
              subPath: nginx.conf
            - mountPath: /etc/nginx-server-certs
              name: nginx-tls
              readOnly: true
      volumes:
        - name: nginxconfig
          configMap:
            name: tls
            items:
              - key: nginx.conf
                path: nginx.conf
        - name: nginx-tls
          secret:
            secretName: nginx-tls
---
kind: Service
apiVersion: v1
metadata:
  name: tls
  labels:
    app: tls
spec:
  ports:
    - port: 443
      targetPort: 443
      name: tls
  selector:
    app: tls

5、创建Gateway资源

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: tls
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: tls
        protocol: HTTPS
      hosts:
        - "svc.test.com"
      tls:
        mode: PASSTHROUGH

6、创建VirtualService资源

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx
spec:
  hosts:
    - tls.test.com
  gateways:
    - tls
  tls:
    - match:
        - port: 443
          sniHosts:
            - tls.test.com
      route:
        - destination:
            host: tls.default.svc.cluster.local
            port:
              number: 443

五、 基于TCP的各种服务

一个针对透传 TCP 流量的有序路由列表。TCP 路由对所有 HTTP 和 TLS 之外的端口生效。进入流量会使用匹配到的第一条规则。

1、创建基础服务

---
apiVersion: v1
kind: Service
metadata:
  name: tcp-echo
  labels:
    app: tcp-echo
    service: tcp-echo
spec:
  ports:
    - name: tcp
      port: 3306
  selector:
    app: tcp-echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tcp-echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tcp-echo
      version: v1
  template:
    metadata:
      labels:
        app: tcp-echo
        version: v1
    spec:
      containers:
        - name: tcp-echo
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          ports:
            - containerPort: 3306

2、创建网关服务

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: tcp-echo-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 31400
        name: tcp
        protocol: TCP
      hosts:
        - "mysql.test.com"

3、创建VirtualService资源

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: tcp-echo
spec:
  hosts:
    - "mysql.test.com"
  gateways:
    - tcp-echo-gateway
  tcp:
    - match:
        - port: 31400
      route:
        - destination:
            host: tcp-echo
            port:
              number: 3306

4、部署结果

以上是关于linux12企业实战 -- 09VirtualService(虚拟服务)的主要内容,如果未能解决你的问题,请参考以下文章

linux12企业实战 -- 13多主机磁盘挂载

linux12企业实战 -- 17queue messages

linux12企业实战 -- 11服务条目

linux12企业实战 -- 12ubuntu部署K8s集群

linux12企业实战 -- 49优化

linux12企业实战 -- 47飞书告警