如何在Kubernetes中通过单个Deployment实现双版本金丝雀部署?
首先直接给结论:单个Deployment无法长期稳定地同时运行v1和v2各3个Pod,这和Deployment的设计初衷有关,下面详细解释并给出可行方案。
为什么你的两个Deployment只运行了最新版本?
你创建的两个Deployment的metadata.name都是process,而Kubernetes要求同一命名空间下的资源名称必须唯一。当你创建第二个Deployment时,它会覆盖第一个Deployment的配置——K8s会认为你是在更新已有的process Deployment,因此会逐步将第一个Deployment对应的ReplicaSet(管理v1 Pod)的副本数缩为0,只保留第二个Deployment对应的ReplicaSet(管理v2 Pod)的3个Pod,这就是为什么你只看到了最新版本的Pod。
能不能用单个Deployment实现同时运行v1和v2各3个Pod?
答案是不能长期稳定实现。Deployment的核心逻辑是通过ReplicaSet管理同一版本的Pod,它的滚动更新机制是逐步替换旧版本Pod为新版本,最终只会保留一个活跃的ReplicaSet(除非你通过revisionHistoryLimit保留旧ReplicaSet,但旧ReplicaSet的副本数会被缩为0)。
如果你想临时实现“v1和v2各3个Pod”的状态(比如做金丝雀验证),可以通过以下步骤操作,但这只是临时状态,无法长期维持:
- 先创建初始的v1 Deployment,设置
replicas: 6 - 更新Deployment的镜像为v2,同时配置滚动更新参数:
spec: strategy: rollingUpdate: maxSurge: 3 # 最多新增3个Pod maxUnavailable: 0 # 不允许旧版本Pod被删除 - 当K8s启动3个v2 Pod后,立即暂停滚动更新:
kubectl rollout pause deployment process
此时你会看到v1和v2各3个Pod,但这个状态是临时的——如果你恢复滚动更新(kubectl rollout resume deployment process),K8s会继续将剩余的v1 Pod替换为v2 Pod,最终全部变为v2。
推荐的金丝雀部署方案(长期稳定运行两个版本)
如果你需要长期同时运行v1和v2的Pod,建议使用两个独立的Deployment,具体步骤如下:
1. 修改两个Deployment的名称
将两个Deployment的metadata.name改为不同的名称,比如process-v1和process-v2,各自保持replicas: 3:
deployment-process-v1.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: process-v1 labels: app: process version: v1 spec: replicas: 3 selector: matchLabels: app: process version: v1 template: metadata: labels: app: process version: v1 spec: containers: - name: pull image: parma/k8s-php:red ports: - containerPort: 80
deployment-process-v2.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: process-v2 labels: app: process version: v2 spec: replicas: 3 selector: matchLabels: app: process version: v2 template: metadata: labels: app: process version: v2 spec: containers: - name: pull image: parma/k8s-php:green ports: - containerPort: 80
2. 创建Service统一入口
创建一个Service,通过app: process标签匹配两个版本的Pod:
apiVersion: v1 kind: Service metadata: name: process-service spec: selector: app: process ports: - protocol: TCP port: 80 targetPort: 80
3. 实现流量分流(金丝雀核心)
如果需要将部分流量导向v2,其余导向v1,可以通过以下方式:
- Ingress流量拆分:比如使用NGINX Ingress配置权重,将指定比例的流量导向v2,剩余导向v1
- Service Mesh:使用Istio、Linkerd等工具,更精细地控制流量比例、灰度发布策略
这种方案的优势是两个Deployment完全独立,各自管理自己的ReplicaSet和Pod,你可以随时调整每个版本的副本数、更新版本,而不会互相影响,是生产环境中金丝雀部署的常用方式。
内容的提问来源于stack exchange,提问作者Paramanand Dhuri

