k8s进阶:Istio概述

ServiceMesh

服务网格
概念,不是产品,针对微服务,解决网络层面的问题

实现

  • Linkerd:
    • 1.x基于节点(物理机,虚拟机)
    • 2.x基于kubernetes
  • Istio
    • google+IBM+Lyft发起的开源项目
    • 多平台支持
  • 相同点
    • 都基于sidecar
      • 每个服务都会被分配到一个单独的代理
      • 代理负责服务间通讯与转发,将请求的数据路由到目标服务的代理
      • 该代理再将请求转发到其管理的微服务
    • 都分为数据层和控制层

Istio

架构

高纬架构: data plane + control plane

核心组件: (Envoy proxy) + (Envoy + Istiod)

数据层: 一系列的代理,以sidecar方式运行,负责所有的网络通讯以及策略

  • proxy: Envoy Istio的具体工作基本都由其完成.内置很多功能:
    • 动态服务发现
    • 负载均衡
    • TLS终端
    • HTTP/2与gRPC代理
    • 熔断器
    • 健康检查
    • 基于百分比流量分割的分阶段发布
    • 故障注入
    • 丰富的指标

控制层: Istiod,提供服务发现,配置和证书管理

  • Pilot: 好比是envoy的直接领导或者上司,指导envoy工作,为其提供信息.客户端为Pilot配置,Pilot将其转成envoy可以读取的格式.
  • Galley: 控制层的配置管理中心
  • Citadel: 安全相关,可以将http服务无感知升级成https;服务授权;RBAC访问控制;访问授权等等

解决的问题

部署

istioctl

照着官方文档(比如v1.13.4)做就行了,有几个注意点:

  • helm安装部署从v1.11就开始废弃了,推荐使用istioctl安装部署

  • istio的版本对k8s的版本有对应要求,先查清楚是否支持

  • 基本上部署就是下载release包,解压,进到里面执行istioctl命令

  • 部署的版本受两个因素影响

    • 环境变量: ISTIO_VERSION

    • istioctl的版本=istio的版本,这是最高优先级

  • 部署示例应用的时候,可以把istio-ingressgateway svc的type从默认的LoadBalance改成NodePort,这样就可以直接访问示例应用,或者按官方文档的做法获取LoadBanlance监听的NodePort和NodeIP去访问也行.

  • 同样,部署dashboard kiali时候,svc默认是clusterIP,端口只监听localhost,改成NodePort就能在集群外访问,其实包括prometheus/grafana等addon都可以这么搞(测试环境),或者搞了ingress暴露出来?U can try.

  • 列出profiles,istio支持多种不同的profile,不同profile包含不同的组件,demo包含所有组件,适合用来测试,default适合用于生产环境

    1
    istioctl profile list
  • 预检查

    1
    istioctl x precheck

GetMesh

istio是最受欢迎和发展迅速的开源项目之一,这意味着它的发布和变更有时候会十分激进.GetMesh工具可以帮助我们管理不同版本istio,类似anaconda管理不同版本的python.

它可以通过针对不同的kubernetes分发版测试所有的istio版本以确保功能的完整性,另外GetMesh的istio版本再安全补丁和其他错误更新方面得到积极的支持.

对于一些安全性要求更高的客户,GetMesh提供两种istio发行版来解决合规性问题:

  • tetrate发行版,跟踪上有istio并可能应用额外的补丁

  • tetratefips发行版,符合FIPS标准的terate发行版

tetrate应该是istio的一个发行版,没有仔细研究.官网

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#下载getmesh
$ curl -sL https://istio.tetratelabs.io/getmesh/install.sh | bash
#验证
$ getmesh version

#使用getmesh安装istio
#getmesh通过kubernetes配置文件与活跃的kubernetes集群通信
#通过以下命令安装demo配置文件的istio
#该命令还会检查集群,以确保它准备好安装istio
getmesh istioctl install istio --set profile=demo

#config-validate验证配置
#可以验证有没有当前namespace有没有写enable注入sidecar
getmesh config-validate
#也可以验证资源的yaml文件
getmesh config-validate my-resources.yml


#管理多个istio
#显示当前集群上的istio版本
getmesh show
#显示所有可信的istio版本
getmesh list
#获取一个特定的版本,并设置为活跃
getmesh fetch --version 1.9.0 --flavor teratefips --flavor-version 1
#查看当前istioctl版本
getmesh istioctl version
#切换istioctl版本
getmesh switch --version 1.9.5 --flavor tetrate --flavor-version 0

istioctl + operator

这方式基于1.10.3,tetrate教程,估计其他版本也差不多.

初始化operator

1
2
3
#创建istio-operator命名空间,并部署CRD,operator deployment和operator工作所需的其他资源
istioctl operator init
#默认会自动创建istio-system命名空间

指定profile

要安装istio,我们需要创建istioOperator资源,并指定我们要使用的配置文件:

1
2
3
4
5
6
7
8
# profile-demo.yml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: demo-istio-install
spec:
profile: demo #指定使用demo配置文件
1
2
3
4
5
6
7
8
9
kubectl apply -f profile-demo.yml
# 当operator检测到istioOperator资源的创建,它将会安装istio,大概需要5分钟左右
# 查看istio-system中的pod状态以检查istio的安装状态
kubectl get pods -n istio-system
#以下输出表示安装完成
NAME READY STATUS RESTARTS AGE
istio-egressgateway-7bfdcc9d86-5kz2h 1/1 Running 0 3m20s
istio-ingressgateway-565bffd4d-v5t48 1/1 Running 0 3m21s
istiod-cc7f656cd-rhjm4 1/1 Running 0 3m47s

启用sidecar注入

往任意一个namespace中添加istio-injection=enable标签,就能在该命名空间上启用sidecar注入,这个namespace中每个一pod都被isitio自动注入envoy proxy sidecar.默认下default已被注入.

也可以使用istioctl kube-inject -h命令

部署一个deploy测试一下,可以看到里面的直接就有了两个容器,里面会跑一个名为istio-init的init pod和一个名为istio-proxy的sidecar

1
2
3
$ kubectl create deploy my-nginx --image=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-6b74b79f57-mbkr8 2/2 Running 0 2m15s

概念

istio本身会在内部维护一个服务发现表,里面记录所有基于平台的服务注册信息,例如k8s的services或consul services.也支持手动添加服务入口(ServiceEntry)来添加一个入口到istio内部维护的服务注册中心.

虚拟服务(virtual service)和目标规则(destination rule)

基于istio与平台(k8s)提供的基本连通性(CNI)和服务发现能力(service),让你配置如何将服务网格内将请求路由到服务,.每个虚拟服务包含一组路由规则,istio按顺序评估他们,将每个给定的请求匹配到虚拟服务指定的实际目标地址

下面是istio的virtual service + destination rule 示例:

默认情况下路由所有http流量到打了”version:v1”reviews pod

另外匹配/wpcatalog和/consumercatalog两个uri,重写为/newcatalog并路由到打了”version:v2”reviews pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
namespace: prod
spec:
hosts:
- reviews.prod.svc.cluster.local
http: # 匹配uri: /wpcatelog 和 /consumercatalog
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite: # 将上面两个uri重写为/newcatalog
uri: "/newcatalog"
route:
- destination: # 路由到标签为"version:v2"的review pod
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route" # 默认下路由所有http流量到标签为"version: v1"的reviews服务的pod
route: # 没有match条件,为默认规则
- destination:
host: reviews.prod.svc.cluster.local
subset: v1

virtual service

可以看到,virtual service本质上就是一个istio开发的CRD资源.

有点类似ingress,与service绑定,可以指定uri转发规则.

但是与ingress不一样的在于,它还可以根据subset和destination rule转发到指定版本的后端,以及配置一些istio更高级的功能.

  • hosts:

    • 列举虚拟服务的主机,即用户指定的目标或路由规则设定的目标.可以是IP,DNS,或者依赖于平台的短名称,官方建议在kuberbnetes中最好使用FQDN.

    • 也可以使用通配符”*”前缀

    • 不必是istio服务注册表中的实际内容,可以是虚拟的目标地址,帮助你”虚空建模”

  • http: 包含虚拟服务的路由规则,用来描述匹配条件和路由行为,把http/1.1,http2和gRPC流量发送到hosts指定的目标

    • match: 匹配条件,举个例子:

      1
      2
      3
      4
      - match: #此路由匹配headers中含有end-user=json的流量
      - headers:
      end-user:
      exact: jason
    • .rule.destination: 指定实际的目标地址,于hosts不同,这里指定定的host必须真实存在于istio服务注册表中.可以是一个由代理的服务网格,或是一个通过服务入口添加进来的非网格服务,比如kubernetes的SVC.

      • 路由优先级:

        • 默认从上到下

        • 官方建议配置一个”无条件”或基于权重的规则作为最后一条规则,此规则也将成为默认规则

destination rule

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews.prod.svc.cluster.local #通过指定同一个svc绑定virtual service和destination rule
subsets:
- name: v1
labels:
version: v1 # 必须显示声明使用使用哪个label给subset指定
- name: v2
labels:
version: v2 # 每个版本的label都要声明才能被virtual service使用

虚拟服务定义如何将流量路由给指定目标地址,目标规则配置该目标的流量.

也可以指定命名的服务子集(subsets),例如按版本给实例分组,然后在虚拟服务中使用match控制到不同实例的流量

还可以定制envoy流量策略,比如LB模型,TLS安全模式或熔断器等.

网关

由两部份组成:

  1. 网关代理,也叫gateway controller

    • 比如istio-ingressgateway和istio-egressgateway

实际上是运行在网格边界的独立的Envoy代理,可以配置4-6层的LB属性(如端口,TLS设置等),也可以替代7层(应用层)的流量路由功能(ingress-controller).

绑定一个virtual service到网关,就可以像管理其他数据层面的流量一样去管理网关流量.

一般而言,主要用入口网关来管理进入的流量,当然出口网关也同样支持配置.通过”入门”文档部署的istio,会自动部署好两个预配置好的网关代理(istio-ingressgateway和istio-egressgateway),本质上是svc+pod(Envoy).

  • 网关配置:

这个例子指定让https流量从ext-host.example.com通过443端口流入网格,但没有指定任何路由规则.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ext-host-gwy
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- ext-host.example.com
tls:
mode: SIMPLE
serverCertificate: /tmp/tls.crt
privateKey: /tmp/tls.key

要指定路由规则,必须要在virtual service上绑定网关

1
2
3
4
5
6
7
8
9
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- ext-host.example.com
gateways:
- ext-host-gwy

更多

istio的流量配置还支持更多高级功能,例如根据header转发,字符串匹配,重试,百分比转发等

官方示例

实验架构

TBD

流量管理

应用部署

bookinfo.yaml

可以看到,和一般的deployment并没有太大区别,但要注意看deployment和pod都定义了label: version=v1/v2/v3,这个在后面配置中有用.

网关配置

bookinfo-gateway.yaml

根据入门教程在部署istio的时候,部署了一些预先配置好的网关(istio-ingressgateway和istio-egressgateway),默认使用ClusterIP类型的SVC.为了方便,把istio-ingressgateway的SVC类型改成了NodePort.

与 Kubernetes Ingress API 这种控制进入系统流量的其他机制不同,Istio 网关让您充分利用流量路由的强大能力和灵活性。您可以这么做的原因是 Istio 的网关资源可以配置 4-6 层的负载均衡属性,如对外暴露的端口、TLS 设置等。也可以把应用层流量路由(L7)到相同的 API 资源.如果您绑定了一个常规的 Istio 虚拟服务到网关。这让您可以像管理网格中其他数据平面的流量一样去管理网关流量。

里面定义了一个网关和一个virtual service,配置了uri和网关关联.

此时通过http://:/productpage访问,多次刷新,发现版本会不停变动(review显示的星星).

那是因为还没有定义具体的review的virtual service,默认会轮询.review由三个版本在跑,所以不停刷新就看到不停变动.

virtual service

virtual-service-all-v1.yaml

这里面定义的virtual service: productpage其实和上面的bookinfo重复了,可以去掉的.

在bookinfo中加上subset: v1就可以指定版本

destination rule

destination-rule-all.yaml

验证

使用以下命令查看virtual service和destination rule:

1
2
kubectl get virtualservices -o yaml
kubectl get destinationrules -o yaml

通过浏览器访问http://:/productpage,多次刷新,发现版本已经固定,那是因为virtual-service-all-v1.yaml已经指定了使用的review版本,流量只会去到version: v1的pod.

把review的virtual service改一下,改成subnets: v2就能使用v2版本.实际上不同的版本一直在跑,只是流量的路由被istio控制.


k8s进阶:Istio概述
http://example.com/2023/03/21/k8s-istio/
作者
Peter Pan
发布于
2023年3月21日
许可协议