最近半年一直在用Istio做服务网格的落地,从最开始的调研到后来的生产环境部署,踩了不少坑,也积累了一些配置经验。

Istio作为目前最主流的Service Mesh实现,功能很强大,但是配置也比较复杂,很多人刚接触的时候会觉得无从下手。今天这篇文章就来详细讲解Istio的实战配置,从基础到高级,一步步带你掌握Istio的核心配置。

内容包括流量管理、安全策略、可观测性、故障注入、流量镜像等核心功能的配置方法,以及一些生产环境的最佳实践和踩坑经验。希望能给正在学习或者使用Istio的朋友一些参考。

一、先说说Istio是什么

在讲配置之前,先简单说说Istio是什么,以及它的核心架构。

Istio是一个开源的服务网格(Service Mesh)框架,由Google、IBM、Lyft等公司联合开发。它的核心思想是把服务间的通信、安全、监控等功能从业务代码中抽离出来,放到一个独立的基础设施层来处理,这样业务代码就不需要关心这些非业务功能了,只需要关注业务逻辑本身。

Istio的架构分为数据平面和控制平面两部分。

数据平面由一系列的Sidecar代理组成,每个服务实例旁边都会部署一个Envoy代理作为Sidecar,所有的入站和出站流量都会经过这个Sidecar代理。Sidecar代理负责处理服务间的通信、负载均衡、熔断、限流、安全认证、监控数据采集等功能。

控制平面负责管理和配置数据平面的Sidecar代理。Istio 1.5版本之前控制平面由Pilot、Mixer、Citadel、Galley等多个组件组成,1.5版本之后合并成了一个单一的istiod组件,简化了部署和运维。

Istio的核心功能包括:

  • 流量管理:动态路由、负载均衡、熔断、限流、重试、超时、故障注入、流量镜像等
  • 安全:服务间的TLS加密、身份认证、授权策略等
  • 可观测性:分布式追踪、指标采集、访问日志等

了解了架构之后,我们来看具体的配置。

二、基础配置:部署Istio和注入Sidecar

首先是基础配置,包括部署Istio和给服务注入Sidecar。

部署Istio最简单的方式是用istioctl命令行工具。先下载对应版本的istioctl,然后执行安装命令:

istioctl manifest apply --set profile=default

profile是安装配置的预设,常用的有default、demo、minimal等。default是默认配置,适合生产环境;demo是演示配置,开启了所有功能,适合学习和测试;minimal是最小配置,只安装核心组件。

安装完成之后,可以用下面的命令查看Istio的组件是否正常运行:

kubectl get pods -n istio-system

接下来是给服务注入Sidecar。Istio支持两种注入方式:手动注入和自动注入。

手动注入是用istioctl命令给已经部署的服务注入Sidecar:

istioctl kube-inject -f deployment.yaml | kubectl apply -f -

自动注入更方便,只需要给命名空间打上标签,这个命名空间下新创建的Pod就会自动注入Sidecar:

kubectl label namespace default istio-injection=enabled

打上标签之后,新创建的Pod会自动注入Sidecar,已经存在的Pod需要重启才会注入。

注入完成之后,可以用下面的命令查看Pod是否有Sidecar容器:

kubectl get pods

正常情况下,每个Pod应该有两个容器,一个是业务容器,一个是istio-proxy容器。

三、流量管理:VirtualService和DestinationRule

流量管理是Istio最核心也是最常用的功能,主要通过VirtualService和DestinationRule两个资源来配置。

VirtualService用来定义流量的路由规则,比如根据请求的路径、域名、Header等把流量路由到不同的服务或者不同的版本。

DestinationRule用来定义目标服务的配置,比如负载均衡策略、连接池配置、熔断配置、版本定义等。

先看一个简单的VirtualService例子,把流量按比例分配到两个版本:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-service
spec:
  hosts:
  - my-service
  http:
  - route:
    - destination:
        host: my-service
        subset: v1
      weight: 80
    - destination:
        host: my-service
        subset: v2
      weight: 20

这个配置把80%的流量路由到v1版本,20%的流量路由到v2版本。这里的subset需要在DestinationRule中定义。

对应的DestinationRule配置:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-service
spec:
  host: my-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 100
        maxRequestsPerConnection: 10
    outlierDetection:
      consecutiveErrors: 5
      interval: 30s
      baseEjectionTime: 30s

这个配置定义了两个subset,分别对应version标签为v1和v2的Pod。同时配置了负载均衡策略为随机,连接池大小,以及异常检测(熔断)配置。

异常检测的意思是,如果某个实例连续5次请求失败,就把它从负载均衡池中剔除30秒,30秒之后再尝试恢复。这样可以避免故障实例影响整体服务的可用性。

VirtualService还支持更复杂的路由规则,比如根据Header路由:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-service
spec:
  hosts:
  - my-service
  http:
  - match:
    - headers:
        user-agent:
          regex: ".*Chrome.*"
    route:
    - destination:
        host: my-service
        subset: v2
  - route:
    - destination:
        host: my-service
        subset: v1

这个配置把使用Chrome浏览器的请求路由到v2版本,其他请求路由到v1版本。这种方式常用于灰度发布或者A/B测试。

还可以根据请求路径路由:

http:
- match:
  - uri:
      prefix: /api/v1
  route:
  - destination:
      host: service-v1
- match:
  - uri:
      prefix: /api/v2
  route:
  - destination:
      host: service-v2

VirtualService还支持超时、重试等配置:

http:
- route:
  - destination:
      host: my-service
  timeout: 5s
  retries:
    attempts: 3
    perTryTimeout: 2s

这个配置设置了请求超时时间为5秒,失败后最多重试3次,每次重试的超时时间为2秒。

四、高级流量管理:故障注入和流量镜像

除了基础的路由功能,Istio还支持一些高级的流量管理功能,比如故障注入和流量镜像。

故障注入是指在系统中主动注入一些故障,比如延迟、错误等,用来测试系统的容错能力和弹性。这在微服务架构中非常重要,因为服务之间的依赖关系很复杂,需要确保某个服务出现故障的时候不会导致整个系统崩溃。

Istio支持两种故障注入:延迟注入和错误注入。

延迟注入的配置:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-service
spec:
  hosts:
  - my-service
  http:
  - fault:
      delay:
        percentage:
          value: 10
        fixedDelay: 3s
    route:
    - destination:
        host: my-service

这个配置给10%的请求注入3秒的延迟,用来测试系统在高延迟情况下的表现。

错误注入的配置:

http:
- fault:
    abort:
      percentage:
        value: 5
      httpStatus: 500
  route:
  - destination:
      host: my-service

这个配置给5%的请求返回500错误,用来测试系统在服务出错情况下的容错能力。

故障注入是混沌工程的重要手段,通过主动注入故障来发现系统的薄弱环节,提高系统的可靠性。

流量镜像是指把生产环境的流量复制一份发送到另一个服务,而不影响原来的服务。这样可以在不影响生产环境的情况下测试新版本的服务,或者进行数据分析、监控等。

流量镜像的配置:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-service
spec:
  hosts:
  - my-service
  http:
  - route:
    - destination:
        host: my-service
        subset: v1
      weight: 100
    mirror:
      host: my-service
      subset: v2
    mirrorPercentage:
      value: 100

这个配置把所有发送到v1版本的流量镜像一份发送到v2版本。镜像的流量是"即发即忘"的,v2版本的响应会被忽略,不会影响原来的请求。

流量镜像非常适合用来做新版本的验证,在不影响生产环境的情况下,把生产流量复制到新版本,观察新版本的表现,确认没问题之后再切流量。

五、安全配置:认证和授权

Istio的安全功能也是非常强大的,主要包括身份认证、TLS加密和授权策略。

Istio默认支持服务间的mTLS(双向TLS)加密,也就是说服务之间的通信会自动加密,而且服务之间会互相验证身份。这样即使网络被监听,攻击者也无法窃取或者篡改服务间的通信内容。

开启mTLS的配置很简单,只需要创建一个PeerAuthentication资源:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT

这个配置在整个网格范围内开启严格的mTLS模式,所有服务之间的通信都必须使用mTLS加密。

mode有三个选项:

  • STRICT:严格模式,必须使用mTLS
  • PERMISSIVE:宽容模式,既接受mTLS也接受明文流量,适合迁移过程中使用
  • DISABLE:关闭mTLS

除了mTLS,Istio还支持请求级别的认证和授权。

请求认证(RequestAuthentication)用来验证请求的身份,通常是验证JWT token:

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: my-jwt-auth
spec:
  selector:
    matchLabels:
      app: my-service
  jwtRules:
  - issuer: "https://auth.example.com"
    jwksUri: "https://auth.example.com/.well-known/jwks.json"

这个配置给带有app: my-service标签的服务启用JWT认证,验证来自指定issuer的JWT token。

授权策略(AuthorizationPolicy)用来控制谁可以访问服务:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: my-service-authz
spec:
  selector:
    matchLabels:
      app: my-service
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/other-service"]
    to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/*"]

这个配置只允许other-service服务访问my-service的/api/*路径,而且只允许GET和POST方法。

授权策略支持非常灵活的规则配置,可以根据来源服务、请求方法、请求路径、请求Header、JWT claims等进行授权控制。

六、可观测性:追踪、指标和日志

Istio的可观测性功能也很完善,支持分布式追踪、指标采集和访问日志。

分布式追踪方面,Istio默认集成了Jaeger、Zipkin等追踪系统。因为所有的流量都经过Sidecar代理,所以Istio可以自动采集服务间的调用链数据,不需要修改业务代码。

只需要在安装Istio的时候开启追踪功能,然后配置采样率:

apiVersion: networking.istio.io/v1alpha3
kind: MeshConfig
metadata:
  name: istio
  namespace: istio-system
spec:
  enableTracing: true
  defaultConfig:
    tracing:
      sampling: 10

这个配置开启了分布式追踪,采样率为10%,也就是10%的请求会被追踪。

需要注意的是,虽然Istio可以自动采集追踪数据,但是业务服务需要把请求中的追踪Header(比如x-request-id、x-b3-traceid等)传递下去,这样才能把同一个请求的多个服务调用关联起来。

指标采集方面,Istio默认会采集很多服务间通信的指标,比如请求量、延迟、错误率等,并且集成了Prometheus和Grafana。可以通过Grafana仪表盘直观地查看服务的性能指标。

访问日志方面,Istio的Sidecar代理会记录所有经过的请求的访问日志,包括请求时间、来源、目标、方法、路径、状态码、延迟等信息。可以通过配置来控制访问日志的格式和输出位置。

这些可观测性功能对于微服务架构的运维非常重要,能够帮助我们快速定位问题、分析性能瓶颈、了解系统的运行状态。

七、生产环境最佳实践和踩坑经验

最后分享一些生产环境的最佳实践和踩坑经验。

第一,渐进式开启mTLS。不要一开始就开启STRICT模式,建议先用PERMISSIVE模式运行一段时间,确保所有服务都已经注入Sidecar并且支持mTLS,然后再切换到STRICT模式。不然可能会导致有些服务无法通信。

第二,合理配置资源。Istio的Sidecar代理会占用一定的CPU和内存资源,生产环境要根据服务的流量情况合理配置Sidecar的资源请求和限制。一般来说,每个Sidecar至少要请求0.1核和128MB内存,流量大的服务需要更多。

第三,控制Sidecar的配置大小。如果服务网格很大,服务很多,Sidecar需要同步的配置就会很多,会导致Sidecar占用内存过大,而且配置同步慢。可以通过Sidecar资源来限制每个Sidecar需要同步的配置范围,只同步相关命名空间的配置:

apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: default
  namespace: default
spec:
  egress:
  - hosts:
    - "default/*"
    - "istio-system/*"

这个配置限制default命名空间的Sidecar只同步default和istio-system命名空间的配置。

第四,注意版本兼容性。Istio的版本更新比较快,不同版本之间的API可能会有变化,升级的时候要注意兼容性。建议在测试环境充分测试之后再升级生产环境,而且不要跨太多版本升级。

第五,做好监控和告警。要监控Istio控制平面和数据平面的运行状态,比如istiod的健康状态、Sidecar的配置同步状态、代理的资源使用情况等。发现异常要及时告警和处理。

第六,灰度发布Istio本身。升级Istio版本的时候,建议用灰度的方式,先升级一部分Sidecar,观察没问题之后再全部升级,避免一次性升级导致全量故障。

踩过的坑:

  • 最开始开启STRICT模式的时候,有几个服务没有注入Sidecar,导致这些服务无法和其他服务通信,排查了很久才发现。所以一定要先确认所有服务都注入了Sidecar再开启STRICT模式。
  • Sidecar的资源限制设置得太小,导致流量大的时候Sidecar被OOM杀掉,服务不可用。后来把资源限制调大就好了。
  • 服务网格太大的时候,Sidecar同步配置很慢,新创建的服务要等很久才能正常通信。后来用Sidecar资源限制了配置范围就解决了。
  • 故障注入配置忘记删除,导致线上服务一直有错误,排查了很久才发现是故障注入的问题。所以故障注入用完之后一定要记得删除。

八、写在最后

Istio是一个非常强大的服务网格框架,功能很完善,但是学习曲线也比较陡,配置比较复杂。不过只要掌握了核心的配置方法,理解了它的工作原理,用起来还是很方便的。

这篇文章介绍了Istio的核心配置,包括基础部署、流量管理、安全配置、可观测性等,还有一些生产环境的最佳实践和踩坑经验。希望能给正在学习或者使用Istio的朋友一些参考。

当然Istio的功能远不止这些,还有很多高级功能和细节,需要在实际使用中慢慢学习和体会。建议大家多动手实践,搭一个测试环境多试试,这样才能真正掌握。

服务网格是云原生领域的一个重要方向,Istio作为目前最主流的实现,值得每一个做微服务和云原生的开发者学习和掌握。希望这篇文章能帮到大家,也欢迎大家在评论区交流讨论自己使用Istio的经验和问题。