云原生
Kubernetes基础
容器技术介绍
Docker快速入门
Containerd快速入门
K8S主要资源罗列
认识YAML
API资源对象
Kubernetes安全掌控
Kubernetes网络
Kubernetes高级调度
Kubernetes 存储
Kubernetes集群维护
Skywalking全链路监控
ConfigMap&Secret场景应用
Kubernetes基础概念及核心组件
水平自动扩容和缩容HPA
Jenkins
k8s中部署jenkins并利用master-slave模式实现CICD
Jenkins构建过程中常见问题排查与解决
Jenkins部署在k8s集群之外使用动态slave模式
Jenkins基于Helm的应用发布
Jenkins Pipeline语法
EFKStack
EFK日志平台部署管理
海量数据下的EFK架构优化升级
基于Loki的日志收集系统
Ingress
基于Kubernetes的Ingress-Nginx解决方案
Ingress-Nginx高级配置
使用 Ingress-Nginx 进行灰度(金丝雀)发布
Ingress-nginx优化配置
APM
Skywalking全链路监控
基于Helm部署Skywalking
应用接入Skywalking
服务网格
Istio
基于Istio的微服务可观察性
基于Istio的微服务Gateway实战
Kubernetes高可用集群部署
Kuberntes部署MetalLB负载均衡器
Ceph
使用cephadm部署ceph集群
使用Rook部署Ceph存储集群
openstack
glance上传镜像失败
mariadb运行不起来
创建域和项目错误_1
创建域和项目错误_2
安装计算节点
时钟源
网络创建失败
本文档使用 MrDoc 发布
-
+
首页
基于Istio的微服务Gateway实战
# 1、Gateway网关 Istio中的Gateway是一个用于将外部流量引入Istio服务网格的组件。它提供了**入出口流量管理**的功能,充当了服务网格中的边界和负载均衡器。Gateway可以让在服务网格外部的流量可以通过统一的入口接入到服务网格中的服务。 以下是一些与Istio Gateway相关的特性和概念: - 1. **边界流量**:Istio Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。这些外部流量可以是来自互联网的请求,也可以是来自其他网络环境的请求。Gateway允许你定义和配置多个虚拟主机(VirtualHosts),并将其映射到特定的服务。 2. **负载均衡**:Gateway支持对流量进行负载均衡,将请求分发到后端服务实例。咱们可以配置不同的负载均衡策略,如轮询、最小连接、最少请求数等。这样可以确保流量在后端服务之间均匀分布,增加系统的可伸缩性和可靠性。 3. **TLS 加密**:Istio Gateway支持通过TLS(Transport Layer Security)对外部流量进行加密,以确保数据的安全性和私密性。我们可以配置Gateway来使用自签名证书、公有证书或者通过集成第三方证书管理工具来管理证书。 4. **路由规则**:Gateway通过路由规则来定义如何将外部流量路由到后端服务。大家可以根据请求的目标主机名、路径、协议等条件来配置路由规则。这样可以根据不同的条件将流量导向到不同的服务版本或环境中。 5. **过滤器**:Gateway提供了强大的过滤器功能,可以对请求和响应进行改变、增加或删除。我们可以使用过滤器来实现各种功能,如认证、鉴权、请求转换、响应转换等。 ```bash #istio-ingressgateway-869d777659-hbmq9是入口网关 #istio-egressgateway-765d784c5-5q5ch是出口网关 $ kubectl get pod -n istio-system NAME READY STATUS RESTARTS AGE grafana-5f9b8c6c5d-8lwwb 1/1 Running 0 12m istio-egressgateway-765d784c5-5q5ch 1/1 Running 0 171m istio-ingressgateway-869d777659-hbmq9 1/1 Running 0 171m istiod-5c4f4498d-5bkpg 1/1 Running 0 171m kiali-cc67f8648-dw98r 1/1 Running 0 3m11s prometheus-5d5d6d6fc-cgzrm 2/2 Running 0 18m zipkin-7d7cd94c9b-6ssjg 1/1 Running 0 6m10s ``` **Istio网关服务**  **下面是一个网关资源的例子** ```yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: my-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - dev.example.com - test.kubernets.cn ``` **类似nginx 的监听配置** ```xml server { listen 80; server_name dev.example.com test.kubernets.cn; #... } ``` # 2、Virtualservice 虽然创建了 Istio Gateway,但是我们还不能直接通过网关访问到前面部署的微服务,我们还需要创建 Istio VirtualService 将 Istio Gateway 跟对应的 Kubernetes Service 绑定起来,然后流量才能正式流向 Pod。 Istio 中的 VirtualService 是一个用于定义流量路由规则和请求转发规则的重要组件。它可以根据请求的属性(如主机名、路径、头部信息等)将流量引导到特定的目标服务,从而实现灵活的流量管理和请求转发。 **VirtualService 功能**: - **请求路由**:将请求路由到特定的服务或版本,例如将请求分发到不同版本的服务,以实现灰度发布或金丝雀发布。 - **请求重试**:为失败的请求配置重试策略,以提高服务的可用性。 - **请求超时**:设置请求的超时时间,以便在特定时间内没有得到响应时中断请求。 - **请求镜像**:将请求的副本发送到另一个服务,用于测试新版本的服务,而不影响实际的生产流量。 - **流量分割**:将流量按照特定的比例分发到不同的服务或版本,以实现流量控制。 如下这张图形象的表达了流量从 Istio 的 ingressgateway 抓发到达最底层的应用pod。他们之间的关系就类似于Kubernetes中的 Ingress --> SVC --> EP --> Pod  **VirtualService 例子** ```yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: tomcat-virtualservice namespace: microservice spec: hosts: - "*" #把VirtualService绑定到ingressgateway80这个网关 gateways: - ingressgateway80 http: - route: #表示路由到tomcat这个service,microservice表示命名空间 - destination: host: tomcat.microservice.svc.cluster.local port: number: 80 ``` 这里类似 nginx 配置反向代理,配置监听之后,还需要指向将请求映射到哪个地址。 ```xml server { listen 80; server_name dev.example.com test.kubernets.cn; #... } location /tomcat/path/ { proxy_pass http://tomcat:9080; } ``` 为什么不直接将 Gateway 跟 Service 绑定,而是中间加个 VirtualService 呢?有句话叫做,计算机领域中的问题,都可以通过增加一个层来解决。 VirtualService 的主要目标是为服务提供稳定的入口地址,并通过配置一系列的路由规则来控制流量在网格内的行为。 就以最简单的路由区配来说,Kubernetes Service 是不支持路由规则的,而 Istio 可以通过指定路由后缀中; Service 不支持流量分析,负载均衡只有轮询。而 Istio 利用 Service 来发现 Pod,然后直接将流量转发到 Pod 中,可以实现各种功能。 # 3、DestinationRule 在本章中,算是提前预告 DestinationRule,下一章才会使用 DestinationRule,这里我们知道还有 DestinationRule 这个东西即可。 Istio VistualService 中可以限制外部能够访问的路由地址,而 DestinationRule 则可以配置访问的 Pod 策略。可以为 Istio VistualService 绑定一个 Istio DestinationRule,通过 DestinationRule 我们还可以定义版本子集等,通过更加丰富的策略转发流量。  # 4、Gateway|VirtualService|DestinationRule 关系 Gateway负责将外部流量引入服务网格,VirtualService定义了流量的路由和转发规则,而DestinationRule则配置了服务的属性和行为。它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。  # 5、实战(1):使用Gateway发布服务 **1、创建部署并使用网关暴露** 在这个实验中,我们将在集群中部署一个 tomcat 应用程序。然后我们将部署一个Gateway 资源和一个与 Gateway 绑定的 VirtualService,**以便在外部 IP 地址上公开该应用程序**。 ```bash #可以看到istio-ingressgateway的service类型为LoadBalancer,外部IP为10.0.10.0 $ kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana ClusterIP 10.15.91.110 <none> 3000/TCP 23m istio-egressgateway ClusterIP 10.15.58.173 <none> 80/TCP,443/TCP 27h istio-ingressgateway LoadBalancer 10.15.18.33 10.0.10.0 15021:30211/TCP,80:32225/TCP,443:30513/TCP,31400:32313/TCP,15443:30656/TCP 27h istiod ClusterIP 10.15.117.150 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 27h kiali ClusterIP 10.15.68.12 <none> 20001/TCP,9090/TCP 14m prometheus ClusterIP 10.15.61.43 <none> 9090/TCP 30m tracing ClusterIP 10.15.94.242 <none> 80/TCP 17m zipkin ClusterIP 10.15.198.147 <none> 9411/TCP 17m ``` 让我们先从部署 Gateway 资源开始。我们将**把`hosts`字段设置为`*`,所以我们可以直接从外部 IP 地址访问入口网关**。如果我们想通过域名访问入口网关,我们可以将`hosts`的值设置为域名(例如`example.com`),然后将外部 IP 地址添加到该域名的 A记录中。 按照如下方法创建网关: ```yaml $ vim ingressgateway80.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: ingressgateway80 namespace: microservice spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - '*' $ kubectl apply -f ingressgateway80.yaml gateway.networking.istio.io/ingressgateway80 created #网关创建完成,名字为ingressgateway80 $ kubectl get gw.networking.istio.io -o wide -nmicroservice NAME AGE ingressgateway80 75s ``` **如果我们试图访问入口网关的外部 IP 地址,我们将得到一个 HTTP 404,因为没有任何绑定到网关的 VirtualService。因为我们还没有定义任何路由,所以入口代理不知道要把流量路由到哪里。** 我们可以通过如下方式获得 Istio 网关的 LB 地址: ```bash $ kubectl get service -l istio=ingressgateway -n istio-system #访问入口网关的80端口,什么内容都没有 $ curl 10.0.10.0 -i HTTP/1.1 404 Not Found ``` **之后当我们谈到入口网关的外部 IP 时,我们将在例子和文本中使用`GATEWAY_URL`** 。 创建 Tomcat 部署和服务: ```bash #使用hub.c.163.com/library/tomcat:latest镜像创建deploy,生成deploy的yaml文件 $ kubectl create deploy tomcat --image=hub.c.163.com/library/tomcat:latest -n microservice --dryrun=client -o yaml > tomcatdeploy.yaml #yaml文件如下,标签设置为app: tomcat ,副本数为1 #- containerPort: 8080表示Tomcat镜像的端口为8080 $ cat tomcatdeploy.yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: tomcat name: tomcat namespace: microservice spec: replicas: 1 selector: matchLabels: app: tomcat strategy: {} template: metadata: creationTimestamp: null labels: app: tomcat spec: containers: - image: hub.c.163.com/library/tomcat:latest name: tomcat resources: {} status: {} #创建deploy $ kubectl apply -f tomcatdeploy.yaml deployment.apps/tomcat created #deploy创建成功 $ kubectl get deploy -n microservice NAME READY UP-TO-DATE AVAILABLE AGE tomcat 1/1 1 1 6s #pod创建成功,pod里有2个容器 #**如果我们看一下创建的 Pod,我们会发现有两个容器在运行。一个是 Envoy sidecar代理,第二个是应用程序**。 $ kubectl get pod -nmicroservice NAME READY STATUS RESTARTS AGE nginx-b64475554-c62n4 2/2 Running 0 32m tomcat-5b4b9896d4-4xkgb 2/2 Running 0 18s ``` 接着创建service ```bash #生成service的yaml文件 $ kubectl expose deployment tomcat --name=tomcat --port=80 --target-port=8080 -nmicroservice --dry-run=client -o yaml > tomcatsvc.yaml #- port: 80使service暴露的端口,targetPort: 8080 是tomcat容器的端口 $ cat tomcatsvc.yaml apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: tomcat name: tomcat namespace: microservice spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: tomcat status: loadBalancer: {} #创建service $ kubectl apply -f tomcatsvc.yaml service/tomcat created #svc的类型为ClusterIP,外界环境访问不了 $ kubectl get svc -o wide -nmicroservice NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginxsvc NodePort 10.15.215.87 <none> 80:32101/TCP 36m tomcat ClusterIP 10.15.171.152 <none> 80/TCP 17s ``` 下一步是为`tomcat`服务创建一个 VirtualService,并将其绑定到 Gateway 资源上: ```yaml $ vim tomcat-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: tomcat-virtualservice namespace: microservice spec: hosts: - "*" #把VirtualService绑定到ingressgateway80这个网关 gateways: - ingressgateway80 http: - route: #表示路由到tomcat这个service,microservice表示命名空间 - destination: host: tomcat.microservice.svc.cluster.local port: number: 80 #创建virtualservice $ kubectl apply -f tomcat-virtualservice.yaml virtualservice.networking.istio.io/tomcat-virtualservice created #virtualservices创建成功 $ kubectl get vs.networking.istio.io -o wide -nmicroservice NAME GATEWAYS HOSTS AGE tomcat-virtualservice ["ingressgateway80"] ["*"] 50s ``` 我们在`hosts`字段中使用`*`,就像我们在`Gateway`中做的那样。我们还将之前创建的Gateway 资源(`gateway`)添加到`gateways`数组中。 最后,我们指定了一个目的地为 Kubernetes 服务`tomcat.microservice.svc.cluster.local`的单一路由。 如果我们对`GATEWAY_URL`运行`cURL`或在浏览器中打开它,我们将得到`tomcat`的响应: ```bash #查看istio-ingressgateway的EXTERNAL-IP $ kubectl get svc -l istio=ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.15.18.33 10.0.10.0 15021:30211/TCP,80:32225/TCP,443:30513/TCP,31400:32313/TCP,15443:30656/TCP 27h #访问EXTERNAL-IP的80端口 #curl -v 参数表示显示一次 http 通信的整个过程,包括端口连接和 http request 头信息 $ curl -v 10.0.10.0:80 * Rebuilt URL to: 10.0.10.0:80/ * Uses proxy env variable NO_PROXY == '127.0.0.1,localhost,10.0.0.0/16,10.15.0.0/16,10.18.0.0/16,.local,local,*.zhoumx.cc,*.aliyuncs.com' * Trying 10.0.10.0... * TCP_NODELAY set * Connected to 10.0.10.0 (10.0.10.0) port 80 (#0) > GET / HTTP/1.1 > Host: 10.0.10.0 > User-Agent: curl/7.61.1 > Accept: */* > < HTTP/1.1 200 OK < content-type: text/html;charset=UTF-8 < date: Mon, 08 Jan 2024 12:40:20 GMT < x-envoy-upstream-service-time: 647 < server: istio-envoy < transfer-encoding: chunked < <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Apache Tomcat/8.5.20</title> <link href="favicon.ico" rel="icon" type="image/x-icon" /> <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> <link href="tomcat.css" rel="stylesheet" type="text/css" /> </head> ``` 另外,**注意到`server`头设置为`istio-envoy`,告诉我们该请求通过了 Envoy 代理**。 **2、清理(后续会有大量类似实验,按照章节保留好数据,方便后续恢复!)** 删除 Deployment、Service、VirtualService 和 Gateway: ```bash $ kubectl delete deployments tomcat -nmicroservice deployment.apps "tomcat" deleted $ kubectl delete service tomcat -nmicroservice service "tomcat" deleted $ kubectl delete virtualservices.networking.istio.io tomcat-virtualservice -nmicroservice virtualservice.networking.istio.io "tomcat-virtualservice" deleted $ kubectl delete gateways.networking.istio.io ingressgateway80 -nmicroservice gateway.networking.istio.io "ingressgateway80" deleted ``` # 6、实战(2):将Prometheus服务通过Istio的Ingress进行暴露 **1、Gateway** ```yaml #网关暴露80端口 $ cat prometheus-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - 'prometheus-istio.kubernets.cn' ``` **2、Virtualservices** ```yaml #vs绑定网关 $ cat prometheus-vs.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: prometheus-istio namespace: istio-system spec: hosts: - 'prometheus-istio.kubernets.cn' gateways: - gateway http: - route: - destination: host: prometheus.istio-system.svc.cluster.local port: number: 9090 ``` # 7、实战(3)、多个服务绑定一个网关 **需求**:将Grafana,Zipkin,Kiali绑定到一个虚拟网关 **1、Gateway** ```yaml #网关暴露80端口 $ cat allgateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: allgateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - '*' ``` **2、Virtualservices** Grafana: ```yaml #vs绑定网关 $ cat grafana-vs.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: grafana-istio namespace: istio-system spec: hosts: - 'grafana-istio.kubernets.cn' gateways: - allgateway http: - route: - destination: host: grafana.istio-system.svc.cluster.local port: number: 3000 ``` Kiali: ```yaml #vs绑定网关 $ cat kiali-vs.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: kiali-istio namespace: istio-system spec: hosts: - 'kiali-istio.kubernets.cn' gateways: - allgateway http: - route: - destination: host: kiali.istio-system.svc.cluster.local port: number: 20001 ``` Zipkin: ```yaml #vs绑定网关 $ cat zipkin-vs.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: zipkin-istio namespace: istio-system spec: hosts: - 'zipkin-istio.zhoumx.cc' gateways: - allgateway http: - route: - destination: host: zipkin.istio-system.svc.cluster.local port: number: 9411 ``` # 8、总结 Istio中的Gateway、VirtualService和DestinationRule是三个核心组件,它们共同构成了流量管理和服务配置的基础。 下面对它们进行简要总结: - Gateway(网关):作为服务网格的入口流量管理组件,Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。它充当了服务网格的边界和负载均衡器,支持入口流量的路由、负载均衡和TLS加密等功能。 - VirtualService(虚拟服务):VirtualService用于定义流量路由规则和请求转发规则。它根据请求的属性(如主机名、路径、头部信息等)将流量引导到特定的后端服务。VirtualService能够灵活地控制流量的路由、负载均衡、超时和重试、流量镜像等策略,实现高级的流量管理和控制。 - DestinationRule(目标规则):DestinationRule用于配置目标服务的规则和属性。它定义了服务的负载均衡策略、TLS设置、连接池大小、故障恢复等参数。DestinationRule允许对某个服务或服务的子集进行独立配置,以满足不同服务的需求。 综合来看,Gateway负责将外部流量引入服务网格,VirtualService定义了流量的路由和转发规则,而DestinationRule则配置了服务的属性和行为。它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。
阿星
2024年1月27日 20:08
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码