调用k8s api接口实现服务镜像的更新与回滚

最近接到一个需求,自动更新替换k8s集群中某些服务的镜像,并支持回滚到原先版本。

我首先想到的是使用 kubectl命令,通过编写一个shell脚本,并传送到k8s集群某个管理节点,执行类似下面这种命令:

arduino 复制代码
kubectl set image deployment/<deployment-name> <container-name>=<new-image>

其中,是服务的Deployment名称,是服务容器的名称,是新的镜像名称。

例如,如果服务的Deployment名称为my-service,容器名称为my-container,新的镜像名称为my-registry/my-image:latest,则命令如下:

kubectl set image deployment/my-service my-container=my-registry/my-image:latest

但是后续了解到在部署该k8s集群时,不会预装 kubectl 命令,所以上述方法有局限性,需要客户先手动安装 kubectl 命令。

后来选择调用 k8s 的api接口进行实现镜像版本替换。

bash 复制代码
/apis/apps/v1/namespaces/{namespace}/deployments/{name}

相关接口的解释在k8s官网中有解释,但是感觉过于简单,具体的调用方法实现还是借助的chatgpt

官网文档地址: kubernetes.io/docs/refere...

示例代码如下:

python 复制代码
import requests
​
def update_service_image(deployment_name, container_name, new_image):
    api_server = "<api-server>"
    token = "<your-token>"
    namespace = "<namespace>"
    
    # 构建API URL
    url = f"{api_server}/apis/apps/v1/namespaces/{namespace}/deployments/{deployment_name}"
    
    # 构建请求头,包括认证信息
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/strategic-merge-patch+json"
    }
    
    # 构建要更新的镜像的部分
    patch = {
        "spec": {
            "template": {
                "spec": {
                    "containers": [
                        {
                            "name": container_name,
                            "image": new_image
                        }
                    ]
                }
            }
        }
    }
    
    # 发送 PATCH 请求
    response = requests.patch(url, headers=headers, json=patch, verify=False)
    
    if response.status_code == 200:
        print("Service image updated successfully")
    else:
        print("Failed to update service image. Status code:", response.status_code)
​
# 使用示例
update_service_image("my-deployment", "my-container", "new-image:latest")

但是该api接口返回200只会保证修改deployement相关配置成功,并不意味着后续的滚动升级也会成功。

常见的一个错误场景就是替换成一个不存在的镜像版本,调用该接口时也会成功,返回200。

但是在后续的滚动升级时,新的pod会出现异常,提示镜像不存在,更新失败。

所以我们要调用 GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}/status接口来获取deployment相关状态来判断是否更新成功。

有一个情况注意下,调用完更新接口后立即调用该查询接口时会返回旧版本状态,不包含新版本的状态,建议先停顿一会再调用该接口。

如何根据上述接口返回的参数进行判断是否成功呢?

上述接口返回信息里有这几个信息:

json 复制代码
 "status": { "observedGeneration": 3, "replicas": 3, "readyReplicas": 3, "availableReplicas": 3}

参考kubernets源码中的方法判断:

位置:pkg/controller/deployment/util/deployment_util.go:708

代码:

ini 复制代码
func DeploymentComplete(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool {
  return newStatus.UpdatedReplicas == *(deployment.Spec.Replicas) &&
    newStatus.Replicas == *(deployment.Spec.Replicas) &&
    newStatus.AvailableReplicas == *(deployment.Spec.Replicas) &&
    newStatus.ObservedGeneration >= deployment.Generation
}

如何进行回滚呢?

在kunernetes官网中并没有搜到相关api介绍,咨询chatgpt给出的方法如下,但是没有生效,没有找到失效的原因:

python 复制代码
import requests
import json
​
def rollback_deployment(deployment_name, namespace):
    # 构建API请求的URL
    url = f"https://your-kubernetes-api-url/apis/apps/v1/namespaces/{namespace}/deployments/{deployment_name}"
​
    # 获取Deployment的当前修订版本
    current_revision = get_current_revision(deployment_name, namespace)
​
    # 构建回滚请求的Body
    body = {
        "kind": "Deployment",
        "apiVersion": "apps/v1",
        "metadata": {
            "name": deployment_name,
            "annotations": {
                "deployment.kubernetes.io/revision": str(current_revision)  # 回滚到当前修订版本
            }
        }
    }
​
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_API_TOKEN"  # 替换为你的API Token
    }
​
    # 发送回滚请求
    response = requests.patch(url, headers=headers, data=json.dumps(body), verify=False)
​
    if response.status_code == 200:
        print("Deployment回滚成功!")
    else:
        print(f"Deployment回滚失败:{response.text}")
​
def get_current_revision(deployment_name, namespace):
    # 构建API请求的URL
    url = f"https://your-kubernetes-api-url/apis/apps/v1/namespaces/{namespace}/deployments/{deployment_name}"
​
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_API_TOKEN"  # 替换为你的API Token
    }
​
    # 发送请求获取Deployment的���细信息
    response = requests.get(url, headers=headers, verify=False)
​
    if response.status_code == 200:
        deployment_info = json.loads(response.text)
        current_revision = deployment_info["metadata"]["annotations"]["deployment.kubernetes.io/revision"]
        return current_revision
    else:
        print(f"获取Deployment信息失败:{response.text}")
        return None
​
# 使用示例
rollback_deployment("my-deployment", "my-namespace")

后面最终实行的方法是在更新前先保留一份deployment配置备份,然后在回滚时直接替换成这个配置即可。

但是直接替换会提示错误,需要删除之前配置metadata.creationTimestampmetadata.generationmetadata.resourceVersion等信息。

相关推荐
运维全栈笔记21 小时前
K8S部署Redis高可用全攻略:1主2从3哨兵架构实战
redis·docker·云原生·容器·架构·kubernetes·bootstrap
尘世壹俗人21 小时前
使用K8s部署模型
kubernetes
AI木马人1 天前
9.人工智能实战:GPU 服务如何上 Kubernetes?从单机部署到 K8s + NVIDIA Device Plugin + HPA 的生产级改造
人工智能·容器·kubernetes
码点滴1 天前
告别显存焦虑:PagedAttention 如何将大模型吞吐量提升 4 倍?
人工智能·架构·kubernetes·大模型·pagedattention
键盘鼓手苏苏1 天前
Kubernetes 容器安全最佳实践
云原生·kubernetes·k8
键盘鼓手苏苏1 天前
Kubernetes 安全最佳实践
云原生·kubernetes·k8
木雷坞2 天前
K8s GPU 推理服务 ImagePullBackOff 排查与预热
云原生·容器·kubernetes·gpu算力
吴爃2 天前
Spring Boot 项目在 K8S 中的打包、部署与运维发布实践
运维·spring boot·kubernetes
The Straggling Crow2 天前
Monitoring 2026-04-30
kubernetes
AOwhisky2 天前
Kubernetes调度与服务暴露:从“定时任务”到“服务发现”的完全指南
linux·运维·云原生·容器·kubernetes·服务发现