Istio 的镜像仓库迁移方案发生了重要变化:原计划作为长期统一入口的 registry.istio.io/release 将与 gcr.io/istio-release 一样,在 2026 年末停止服务。Istio 镜像仍会发布到 docker.io/istio,项目也计划增加更多镜像站点。对集群管理员来说,真正要做的不是记住又一个仓库地址,而是尽快找出旧引用、修改安装配置,并为镜像拉取增加一层可控的缓存。
为什么统一代理方案无法继续
registry.istio.io/release 原本被设计成一个由 Cloudflare Worker 提供的 OCI 代理入口。其价值很直接:Istio 项目可以在后端切换实际托管平台,而用户的镜像地址保持不变。
问题出在流量模型上。代理会把大量用户请求集中到少数出口 IP。项目计划在 2027 年使用免费容器托管平台控制基础设施成本,但集中出口容易触发这些平台的限流策略。经过与托管平台沟通后,Istio 决定放弃这一代理入口。
时间线可以概括为:
registry.istio.io/release将维持到 2026 年末。gcr.io/istio-release仍按原计划在 2026 年末退役。docker.io/istio将继续发布 Istio 镜像。- Istio 计划在未来发布到更多镜像站点,但不应把尚未公布的镜像当作当前迁移依赖。
这不是需要立即停机处理的事故,但也不适合等到截止日期前再集中修改。镜像地址经常散落在 Helm values、IstioOperator、GitOps 仓库、准入策略和离线安装清单中,清理周期通常比预期更长。
哪些集群会受影响
默认情况下,Istio 1.30 安装使用 registry.istio.io/release;其他 Istio 版本默认使用 docker.io/istio。不过,默认值不能代替实际检查:升级遗留配置、私有模板或手工部署的工作负载都可能继续引用旧仓库。
下面的命令同时检查普通容器和初始化容器,并覆盖两个计划退役的地址。运行前需要安装 kubectl 和 jq,并确保当前 kubeconfig 对目标集群具有读取 Pod 的权限:
kubectl get pods --all-namespaces -o json | jq -r '
.items[]
| .metadata.namespace as $ns
| .metadata.name as $pod
| ((.spec.initContainers // []) + (.spec.containers // []))[]
| select(
.image | startswith("registry.istio.io/release/") or
startswith("gcr.io/istio-release/")
)
| [$ns, $pod, .name, .image] | @tsv
'
没有输出表示当前正在运行的 Pod 未引用这两个前缀,但这还不等于配置已经清理干净。Pod 只是运行结果,下一次部署仍可能由旧模板重新生成旧地址。继续检查常见工作负载和本地配置仓库:
kubectl get deploy,daemonset,statefulset,job,cronjob -A -o yaml \
| grep -nE 'registry\.istio\.io/release|gcr\.io/istio-release' || true
rg -n 'registry\.istio\.io/release|gcr\.io/istio-release' \
./clusters ./charts ./manifests
请按实际仓库结构修改 rg 后面的目录。若环境中没有 rg,可以改用 grep -RInE。
使用 istioctl 修改镜像来源
通过 istioctl 管理 Istio 时,可以在 IstioOperator 中显式设置 hub。下面是一份可直接改造的最小配置;部署前应把 profile 和其他字段调整为现有环境的值:
# istiooperator.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: default
hub: docker.io/istio
应用配置:
istioctl install -f istiooperator.yaml
如果只需在现有安装命令中覆盖仓库,也可以这样执行:
istioctl install --set hub=docker.io/istio
不要仅修改命令行而遗漏声明式配置。对于 GitOps 环境,应把 hub 写回受版本控制的源文件,否则后续同步可能恢复旧地址。
安装完成后,可以检查 Istio 命名空间中的实际镜像:
kubectl get pods -n istio-system \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]} {.image}{"\n"}{end}{end}'
使用 Helm 完成迁移
Helm 安装可能分别管理 base、控制面和网关 chart。根据现有 values 的结构,更新顶层 hub、global.hub,或者两者都设置:
# values-registry.yaml
hub: docker.io/istio
global:
hub: docker.io/istio
然后对实际 release 执行升级。下面假设控制面 release 名为 istiod,命名空间为 istio-system;运行前请替换成集群中的真实名称,并保留原有 values 文件:
helm list -A
helm upgrade istiod istio/istiod \
--namespace istio-system \
--reuse-values \
-f values-registry.yaml \
--wait
如果 base 和 ingress gateway 是独立 release,也要检查并升级它们。可以先渲染清单,避免在集群中才发现旧引用:
helm template istiod istio/istiod \
--namespace istio-system \
-f values-registry.yaml \
| grep -E 'image:|registry\.istio\.io|gcr\.io/istio-release'
这里的示例假设已经配置 Istio Helm 仓库,并且 chart 版本与当前升级流程一致。生产环境不要因为修改镜像仓库而顺便跨版本升级;把两个变更拆开,更容易验证和回滚。
为什么更推荐拉取缓存
直接改成 docker.io/istio 可以消除退役地址,但仍会让节点直接依赖公共仓库的可用性、限流和网络路径。Istio 给出的更稳妥方向是配置 pull-through cache,也就是让集群从内部仓库拉取镜像,由内部仓库按需向上游获取并缓存内容。
可以这样实践:假设企业已经配置了一个代理 docker.io 的缓存项目,并通过 registry.example.com/dockerhub 暴露,那么安装配置可改为:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: default
hub: registry.example.com/dockerhub/istio
registry.example.com/dockerhub 只是示例,必须替换成实际缓存服务生成的路径。上线前需要验证完整镜像名称能否解析,例如:
docker pull registry.example.com/dockerhub/istio/pilot:1.30.0
请把版本替换为正在部署的 Istio 版本。缓存服务还需要处理上游凭据、容量回收、高可用、TLS 证书和节点访问权限;否则只是把公共仓库故障变成了内部单点故障。
迁移时应守住的边界
建议在 2026 年末之前完成以下工作:
- 盘点所有集群中的
registry.istio.io/release和gcr.io/istio-release引用。 - 同时搜索运行中 Pod、控制器模板、Helm values、
IstioOperator和 GitOps 仓库。 - 将来源改为
docker.io/istio,或经过验证的内部 pull-through cache。 - 固定并核对现有 Istio 版本,避免把仓库迁移与版本升级混成一次变更。
- 在预生产环境验证拉取、滚动更新、节点扩容和故障恢复。
- 迁移后重新运行扫描命令,并监控
ImagePullBackOff、ErrImagePull和仓库限流事件。
两个旧入口在 2026 年末前仍会继续提供镜像,这段缓冲期应当用于逐批迁移和验证,而不是作为继续写入旧地址的理由。对多集群平台而言,内部拉取缓存加上配置仓库中的统一镜像策略,通常比再次依赖某个永久公共入口更可靠。