Istio 1.30.5 是一次以稳健性为核心的补丁发布。它没有引入醒目的新功能,而是集中解决 1.30.4 中可能导致流量重定向规则重复、JWKS 获取失败、工作负载元数据反复推送、Envoy 无法启动以及本地凭据插件被意外执行的问题。对正在运行 Ambient、多网络网关、外部认证或多集群环境的团队来说,这些修复值得尽快评估。
Ambient 与工作负载发现:减少重复规则和无效推送
Ambient 模式下,CNI 节点代理会自动判断节点使用的是 legacy iptables 还是 nft 后端。此前,这个自动检测结果可能在代理重启后发生变化,导致代理向已经纳管的 Pod 再次写入重定向规则。重复规则不一定立刻表现为故障,但会增加排障难度,也可能造成流量路径与预期不一致。
1.30.5 修复了后端选择在重启间发生翻转的问题。升级后,建议重点观察发生过 CNI 重启或节点维护的集群,而不是只验证新建 Pod。
这次发布还修复了几类工作负载发现问题:
- istiod 向 Envoy 推送工作负载元数据时,不再反复序列化同一个工作负载。
- 开启默认的
AMBIENT_SCOPED_ADDRESS_PUSHES时,仅地址发生变化的工作负载也能通过 MDS 获得增量更新。 - 一个网络配置多个网关时,网关选择不再因随机顺序而变化,避免每次重新计算都触发不必要的 WDS 推送,也避免工作负载的网关地址来回切换。
这些变化的直接价值不是“增加吞吐量”这么简单,而是减少无意义的控制面计算和配置分发,让代理最终看到的地址与网关选择更加稳定。
升级后可以这样检查 CNI 和控制面的基本状态。执行前请确保当前 kubectl 上下文指向目标集群,并使用 1.30.5 版本的 istioctl:
set -euo pipefail
export ISTIO_NAMESPACE=istio-system
kubectl config current-context
istioctl version
istioctl x precheck
istioctl analyze --all-namespaces
kubectl -n "$ISTIO_NAMESPACE" get pods -o wide
kubectl -n "$ISTIO_NAMESPACE" get daemonset -l k8s-app=istio-cni-node
kubectl -n "$ISTIO_NAMESPACE" rollout status deployment/istiod --timeout=5m
如果使用 Ambient 模式,还应在升级前后各做一次节点级验证:重启一个 CNI Pod,确认既有业务 Pod 的连接没有异常,同时观察 CNI 日志中是否出现重复写入或清理重定向规则的迹象。生产环境不要一次重启全部 CNI Pod。
JWKS 再次正确使用 HTTP/2
Istio 的 JWKS resolver 需要从身份提供方获取用于验证 JWT 的公钥。此前,为了实现 TLS 固定和 CIDR 阻断而设置的自定义 TLSClientConfig 与 DialContext,会让 Go 的 net/http 停止自动启用 HTTP/2。由于 ALPN 无法协商出 h2,所有公钥请求都被迫使用 HTTP/1.1。
多数服务器同时支持 HTTP/1.1,因此问题可能长期隐藏。但在某些 HTTP CONNECT 代理链路中,JWKS 请求通过 HTTP/1.1 会失败。1.30.5 重新启用了与 http.DefaultTransport 一致的 HTTP/2 行为,使这些环境能够正常协商 h2。
升级验证不应只看 istiod 是否 Ready。更有效的方式是发起一条真实的 JWT 认证请求,并同时检查控制面日志:
# 按实际环境修改命名空间、测试地址和令牌。
export ISTIO_NAMESPACE=istio-system
export APP_URL='https://app.example.com/protected'
export JWT_TOKEN='replace-with-a-valid-test-token'
curl --fail-with-body --verbose \
-H "Authorization: Bearer ${JWT_TOKEN}" \
"$APP_URL"
kubectl -n "$ISTIO_NAMESPACE" logs deployment/istiod \
--since=10m | grep -Ei 'jwks|openid|oauth|http2|error' || true
这个测试应从真实经过企业代理或出口代理的网络路径执行。直接从开发机访问身份提供方成功,并不能证明 istiod 所在网络中的 HTTP CONNECT 路径正常。
配置与状态修复:小字段也会阻断代理启动
1.30.5 修复了两个与 Sidecar 统计周期相关的问题:
sidecar.istio.io/statsFlushInterval使用一分钟及以上,或者使用亚秒值时,不再生成无效的 Envoy bootstrap。sidecar.istio.io/statsEvictionInterval不再静默截断亚秒精度。
在需要调整统计刷新和淘汰节奏时,可以这样实践。下面的 Deployment 仅用于演示注解位置;请替换镜像和业务端口后再应用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: stats-interval-demo
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: stats-interval-demo
template:
metadata:
labels:
app: stats-interval-demo
annotations:
sidecar.istio.io/statsFlushInterval: "1m"
sidecar.istio.io/statsEvictionInterval: "750ms"
spec:
containers:
- name: app
image: nginx:1.27-alpine
ports:
- containerPort: 80
应用并确认代理成功启动:
kubectl apply -f stats-interval-demo.yaml
kubectl rollout status deployment/stats-interval-demo --timeout=3m
kubectl get pod -l app=stats-interval-demo \
-o jsonpath='{range .items[*].status.containerStatuses[*]}{.name}{" ready="}{.ready}{" restarts="}{.restartCount}{"\n"}{end}'
istioctl proxy-status
此外,本次发布还修复了几项容易误导自动化系统的状态问题:
- 没有任何有效监听器的
ListenerSet,现在会将Accepted和Programmed设为False,原因是ListenersNotValid,而不是保留看似成功的状态。 - 当旧状态写入仍在队列中、资源又被修改时,
observedGeneration不再停留在过期值。 - 带有“存在但为空”的 workload selector 的
ServiceEntry,不再错误匹配命名空间中的全部工作负载。
最后一项尤其需要注意:不要依赖旧版本的错误行为。需要选择工作负载时,应使用明确标签,例如:
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: selected-database
namespace: default
spec:
hosts:
- database.internal.example
ports:
- number: 5432
name: tcp-postgres
protocol: TCP
resolution: STATIC
workloadSelector:
labels:
app: database
role: primary
升级前可以搜索现有的 ServiceEntry,人工检查是否存在空选择器以及是否有人依赖其错误的全匹配效果:
kubectl get serviceentry --all-namespaces -o yaml \
| grep -n -A4 -B2 'workloadSelector:' || true
多集群 secret:修补 istioctl analyze 的本地执行风险
本次发布中最值得安全团队关注的修复发生在 istioctl analyze。此前,该命令会直接根据 istio-system 中的多集群 secret 构建 Kubernetes 客户端,但没有先清理其中的 kubeconfig。
如果攻击者能够制作或修改这类 secret,就可能植入 exec 凭据插件,或者利用其他不安全的认证字段读取本地文件。当工程师在工作站或 CI Runner 上执行 istioctl analyze 时,这些内容可能在运行命令的机器上生效。
1.30.5 现在会像 istiod 一样清理这类 kubeconfig。即使完成升级,也仍应收紧 secret 的写权限,并审计多集群凭据的来源。下面的命令只列出元数据,不会解码或执行 secret 中的 kubeconfig:
kubectl -n istio-system get secrets \
-l istio/multiCluster=true \
-o custom-columns='NAME:.metadata.name,CREATED:.metadata.creationTimestamp,TYPE:.type'
kubectl auth can-i create secrets -n istio-system
kubectl auth can-i patch secrets -n istio-system
kubectl auth can-i update secrets -n istio-system
如果普通开发者或非预期的 CI ServiceAccount 能够修改 istio-system 中的 secret,应优先修正 RBAC,而不是把 1.30.5 当成唯一防线。升级前,也不要用旧版 istioctl analyze 检查来源不可信的多集群 secret。
升级建议:按故障面设计验证
使用原地升级的环境,可以在保留现有 profile 和 values 的前提下,先执行预检查,再通过团队既有的发布流程升级。下面是一组可改造的操作顺序:
set -euo pipefail
export ISTIO_NAMESPACE=istio-system
# 确认这里显示的客户端版本为 1.30.5。
istioctl version
# 升级前检查。
istioctl x precheck
istioctl analyze --all-namespaces
kubectl -n "$ISTIO_NAMESPACE" get pods
# 原地升级;运行前确认它会沿用团队要求的安装配置。
istioctl upgrade
# 控制面与配置收敛检查。
kubectl -n "$ISTIO_NAMESPACE" rollout status deployment/istiod --timeout=5m
istioctl proxy-status
istioctl analyze --all-namespaces
使用 revision/canary 模式的团队不应直接照搬原地升级命令,而应部署新的 1.30.5 revision,迁移测试命名空间,再逐步切换业务。
验收清单可以围绕本次实际修复展开:
- 重启单个 CNI 节点代理后,已纳管 Pod 没有出现重复重定向或连接异常。
- 真实代理链路上的 JWKS 获取和 JWT 验证成功。
- 使用分钟级和亚秒级统计注解的 Sidecar 能正常生成 bootstrap 并启动。
- 多网关网络中的工作负载地址保持稳定,WDS 推送没有无故持续抖动。
ListenerSet、observedGeneration与ServiceEntry的状态符合实际配置。- 执行多集群分析的工作站和 CI 已使用 1.30.5
istioctl,相关 secret 的写权限也经过审计。
这不是一次需要重新设计网格的升级,但它修复的恰好都是容易演变成间歇性故障或安全事故的边界问题。越依赖 Ambient、多网络、外部身份提供方和多集群分析,升级优先级就越高。