资源类型
流量管理
网关
信息
Gateway(gw):用于管理服务网格的入站(ingress)和出站(egress)流量
。指定要进入或离开网格的流量。
$ kubectl -n test apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gateway
namespace: test
spec:
selector:
istio: ingressgateway # 与istio-system中ingressgateway的pod的label匹配
servers:
- port:
name: http
number: 80
protocol: HTTP
hosts:
- test/httpbin.example.com # 匹配指定namespace下的vs中的域名
- port:
name: https
number: 443
protocol: HTTPS
hosts:
- httpbin.example.com
tls:
mode: SIMPLE
credentialName: httpbin-secret # 默认在istio-system下查找
EOF
TLS类型
Name | Description |
---|---|
PASSTHROUGH | Istio 不干预 TLS 握手过程,客户端和服务直接进行加密通信。 |
SIMPLE | 启用TLS但不需要对客户端进行身份验证。服务之间的通信是加密的,但不要求客户端提供证书。 |
MUTUAL | 双向TLS模式。客户端和服务之间的通信是加密的,且双方都要验证对方的身份,即客户端和服务都要提供证书。 |
AUTO_PASSTHROUGH | 自动选择透传或简单模式。Istio将根据客户端请求是否提供证书来动态选择透传或简单模式。 |
ISTIO_MUTUAL | 由istio生成和管理证书,不需要手动配置,其他与MUTUAL 相同。 |
OPTIONAL_MUTUAL | 双向 TLS 模式,要求服务提供证书,但客户端可以选择是否提供证书。 |
虚拟服务
提示
VirtualService(vs):虚拟服务允许配置请求如何路由到特定的服务
,每个虚拟服务包含一组按顺序
评估的路由规则。与网关整合并配置流量规则能够控制出入流量。通过虚拟服务能处理特定ns下的所有服务,将单一虚拟服务映射到多个真实服务
。
$ kubectl -n test apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-virtual-service
spec:
hosts: # 与绑定gateway下的hosts匹配才会生效
- httpbin.example.com
gateways:
- nginx-gateway # 用来匹配绑定的网关
http:
- match:
- headers:
end-user:
exact: zhangsan # exact 精确匹配 请求头end-user=zhangsan才能匹配
route:
- destination:
host: nginx-svc # 必须是真实存在的svc
subset: v1 # 对应DestinationRule定义的subset
port:
number: 80
weight: 50 # 50%流量访问v1
- destination:
host: nginx-svc
subset: v2
port:
number: 80
weight: 50
headers:
request:
set:
custom-header: helloworld # 请求到达pod前添加自定义header
add:
hello: world # 添加到指定头中,多值用逗号分割
remove:
- end-user # 请求到达pod前移除header
response:
set:
end-user: helloworld # 设置响应头
add:
custom-header: custom-value # 添加到指定头中,多值用逗号分割
- match:
- uri:
exact: /hello # 匹配/hello
rewrite: # 重写uri /hello -> /
uri: /
route:
- destination:
host: nginx-svc
subset: v2
port:
number: 80
retries: # 重试三次,timeout 2s
attempts: 3
perTryTimeout: 2s
timeout: 10s # 10s超时
- match:
- uri:
exact: /
fault: # 故障注入,一百个访问中有一个访问会出现5s的延时
delay:
percentage:
value: 1 # 设置为100,就表示全部的请求都会5s延时
fixedDelay: 5s
route:
- destination:
host: nginx-svc
subset: v2
port:
number: 80
EOF
一个虚拟服务尽量只路由一个域名
,避免多个虚拟服务文件路由多个相同域名出现未知的情况。按照文件字母排序,前者会被后者覆盖。- 路由规则按照
从上到下
的顺序选择,第一条规则具有最高优先级,不满足则依次向后匹配。建议最后一个规则作为默认规则
,确保至少能匹配一条路由规则。- host属性如果使用短名称,默认会添加与vs相同的ns的域后缀,即
nginx-svc => nginx-svc.test.svc.cluster.local
- VirtualService支持对
header的增删改操作
、超时和重试
配置操作。- 故障注入是一种将
错误引入系统
以确保系统能够承受并从错误条件中恢复
的测试方法。一个路由中,故障注入和超时重试不能同时配置
。- 通过vs的weight能够很好的实现金丝雀部署(让
一小部分流量引入新版本
来进行测试,若顺利,则可以增加百分比
来逐步替换旧版本)。更多
目标规则
提示
DestinationRule(dr):虚拟服务侧重的是如何将流量路由给定目标地址,而目标规则可以通过调整负载均衡模型、TLS 安全模式或熔断器
设置来配置该目标的流量。
$ kubectl -n test apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-destination-rule
spec:
host: nginx-svc # 绑定真实的svc服务
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100 # 最多100个请求,超过熔断
http:
http1MaxPendingRequests: 100
http2MaxRequests: 100 # 最多100个请求,超过熔断,支持HTTP1.1&HTTP2
maxRequestsPerConnection: 1 # 每个连接到后端的最大请求数,默认为0表示不限制,设置为1表示禁用keepalive
loadBalancer:
simple: RANDOM # 如果subset不设置负载均衡策略,那么使用此处的随机策略
subsets:
- name: v1
labels:
version: v1 # 匹配label为version=v1的pod
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: LEAST_REQUEST # 请求负载最少的端点
EOF
- dr中的host是集群中
真实存在的svc
服务,dr中的subset通过name与vs中的subset绑定,用于匹配符合指定标签的pod
。- dr可以设置熔断策略,针对
一个服务中的单个host调用的限制
(并发连接数量限制,主机调用失败限制等),使用熔断后会快速失败。更多
负载均衡策略
Name | Description |
---|---|
UNSPECIFIED | 在不显式指定策略时,将使用默认的策略。 |
RANDOM | 随机选择一个健康实例,不配置健康检查的前提下,RANDOM > ROUND_ROBIN |
PASSTHROUGH | 把连接转发到调用者请求的原始IP地址,而不进行任何形式的负载平衡。此选项必须谨慎使用。 |
ROUND_ROBIN | 按照顺序将请求发送到每个可用的实例(更推荐LEAST_REQUEST) |
LEAST_REQUEST | 将新的请求发送到当前请求数最少的服务实例 LEAST_REQUEST > ROUND_ROBIN |
LEAST_CONN | 过期,使用LEAST_REQUEST代替 |
安全
istio安全功能提供了强大的身份、强大的策略、透明的 TLS 加密、 认证/授权/审计(AAA)工具
来保护您的服务和数据。
身份
istio使用经典的service identity
(服务身份)来确定一个请求源端的身份(人类用户,单个服务或一组服务)。istiod
基于证书的方式为每个服务都提供身份标识
,通过Envoy中的pilot-agent(istio-agent)
进程实现。
istio-agent
启动时创建私钥和CSR,将CSR和凭据发送到istiod
(基于grpc接收证书签名请求)进行签名。istiod
CA验证CSR中携带的凭据,成功验证后签署CSR以生成证书。- 服务启动后,Envoy 通过 Secret 发现服务(SDS)API向同容器内的
istio-agent
发送证书和密钥请求。istio-agent
将istiod
发来的证书和密钥发送给Envoy。istio-agent
监控工作负载证书的过期时间。上述过程会定期重复进行证书和密钥轮换。
认证
对等认证
提示
PeerAuthentication(pa):用于服务到服务的认证,以验证建立连接的客户端,istio默认提供了双向TLS(mTLS)
解决方案。
$ kubectl -n test apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: httpbin-peer-policy
spec:
selector:
matchLabels:
app: httpbin # 符合label app=httpbin 的服务互相通信都使用mTLS
mtls:
mode: STRICT
EOF
具有代理的服务间的所有流量即可启用双向TLS,无需做额外操作。启用mTLS后,会注入
X-Forwarded-Client-Cert
到后端的上游请求。
对等认证
通过selector去匹配服务,如果不指定,默认匹配命令空间下的所有服务。
相同范围
的多个策略和相同服务
上多个策略默认采用旧的
认证策略。
双向TLS(mTLS)通信流程
:
- istio将出站流量从客户端重新路由到客户端的本地Envoy。
- 客户端Envoy与服务器端Envoy开始双向TLS握手。在握手期间,客户端Envoy还做了
安全命名
检查,以验证服务器证书中显示的服务帐户是否被授权运行目标服务。- 客户端Envoy和服务器端Envoy建立了一个双向的TLS连接,istio将流量从客户端Envoy转发到服务器端Envoy。
- 服务器端Envoy
授权
请求。如果获得授权,它将流量转发到通过本地TCP连接的后端服务。安全命名:
将服务器身份映射到服务名称
。身份A
到服务名称B
的映射表示"授权A
运行服务B
。控制平面将映射关系分发到所有服务。服务器身份被编码在证书中,客户端调用服务端时,会从服务端证书中提取身份,并检查此身份是否被允许运行对应的服务
。
双向TLS策略
模式 | 含义 |
---|---|
PERMISSIVE | 工作负载接受双向 TLS 和纯文本流量。用来兼容没有sidecar的服务。 |
STRICT | 工作负载仅接收双向 TLS 流量。 |
DISABLE | 禁用双向 TLS。(不推荐) |
请求认证
提示
RequestAuthentication(ra):用于终端用户的认证(服务间也支持
),以验证附加到请求的凭证,默认支持JWT。也可以通过自定义实现的方式支持keycloak、OAuth 2
等符合openid connect
规范的协议。
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
name: "jwt-example"
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway #绑定istio的ingressgateway
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.20/security/tools/jwt/samples/jwks.json"
EOF
- 请求身份验证将在istio网关上启用
JWT校验
,issuer对应着jwt.claims[issuer]
的值,jwksUri对应着公钥的jwks地址。不携带令牌(禁止此类请求由授权控制)、携带正确令牌
的请求会被接收,携带错误令牌(issuer不匹配,令牌不合法等)
的请求不会被接收。更多
授权
提示
授权(AuthorizationPolicy)策略对服务器端Envoy代理的入站流量实施访问控制
。每个Envoy代理都运行一个授权引擎,该引擎在运行时授权请求。当请求到达代理
时,授权引擎根据当前授权策略评估请求上下文, 并返回授权结果ALLOW
或DENY
。
授权匹配流程图

注意
授权的匹配流程遵循CUSTOM -> DENY -> ALLOW
的顺序进行评估。
$ kubectl -n test apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin
namespace: test
spec:
selector:
matchLabels:
app: httpbin # 关联的服务很重要,关联谁,就是对谁控制
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/test/sa/sleep"] # 限制了必须是集群内的访问才可以,因为需要有sa账户
- to:
- operation:
paths: ["/headers"]
# notPaths: ["/headers"] # 访问除了headers外的
methods: ["GET"]
when:
- key: destination.port
values: ["80"]
EOF
- port == 80 && source.sa = sleep && to.paths == /headers && to.methods == "GET"? ALLOW : DENY
- from表示请求的来源,to表示请求的操作,when表示
授权规则应用所需要的条件
,when添加符合,规则会被应用,否则忽略。- 如果namespace设置的为
根目录空间(默认istio-system)
,那么策略会适用于所有的命令空间。- 授权策略中大部分字段都支持
值匹配模式
,即前缀匹配(*.aaa.com)、后缀匹配(abc.*)、存在匹配(["*"]即字段必须存在)
。- 授权策略支持
ALLOW
、DENY
、CUSTOM
操作,按照CUSTOM -> DNEY -> ALLOW
的顺序进行匹配。若不匹配最终会拒绝。- source字段下的
principals、notProncipals、namespaces、notNamespaces
要先开启mTLS
才能生效。
allow-nothing
$ kubectl -n test apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-nothing
spec:
action: ALLOW
EOF
该策略因为没有定义rules,所以从不匹配,最终都会拒绝。若有其他允许策略匹配,则允许访问,
建议默认添加
。
deny-all
$ kubectl -n test apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
spec:
action: DENY
# rules 字段有一个空白规则,策略将始终匹配。
rules:
- {}
EOF
该拒绝策略默认匹配所有规则,即使存在允许策略,因为DENY优先ALLOW,所以还是会被拒绝。
适合临时禁止所有访问
。
allow-all
$ kubectl -n test apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-all
spec:
action: ALLOW
# 这将匹配所有内容。
rules:
- {}
EOF
匹配所有策略,
允许所有服务的访问
(前提是不存在custom和deny策略)。