有没有办法用 Kubernetes client-go 优雅地结束一个 pod?
Is there a way to gracefully end a pod with the Kubernetes client-go?
主要问题是是否有办法从 client-go sdk 完成 pod,我不是要删除 pod,我只是想完成它具有阶段状态:已完成。
在代码中,我正在尝试更新 pod 阶段,但它不起作用,它没有 return 错误或恐慌,但 pod 没有完成。
我的代码:
func main() {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
for {
pods, err := clientset.CoreV1().Pods("ns").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
for _, pod := range pods.Items {
podName:= pod.Name
if strings.Contains(strings.ToLower(podName), "single-condition") {
fmt.Println("get pods metadatada")
fmt.Println(pod.Name)
fmt.Printf("pod.Name %s \n", pod.Name)
fmt.Printf("Status.Phase %s \n", pod.Status.Phase)
fmt.Printf("PodIP %s \n", pod.Status.PodIP)
containers := pod.Status.ContainerStatuses
if len(containers) > 0 {
for _ ,c := range containers {
fmt.Printf("c.Name %s \n", c.Name)
fmt.Printf("c.State %s \n", c.State)
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
stateTerminated := c.State.Terminated
stateRunning := c.State.Running
if stateTerminated == nil && stateRunning != nil {
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
fmt.Printf("stateRunning Reason: %s\n", reflect.TypeOf(c.State.Running))
getPod, getErr := clientset.CoreV1().Pods("ns").Get(context.TODO(), "single-condition-pipeline-9rqrs-1224102659" , metav1.GetOptions{})
if getErr != nil {
fmt.Println("error1")
panic(fmt.Errorf("Failed to get: %v", getErr))
}
fmt.Println("update values")
fmt.Printf(" getPodName %d \n", getPod.Name)
getPod.Status.Phase = "Succeeded"
fmt.Println("updated status phase")
getContainers := getPod.Status.ContainerStatuses
fmt.Printf("len get container %d \n", len(getContainers))
_, updateErr := clientset.CoreV1().Pods("argo-workflows").Update(context.TODO(), getPod, metav1.UpdateOptions{})
fmt.Println("commit update")
if updateErr != nil {
fmt.Println("error updated")
panic(fmt.Errorf("Failed to update: %v", updateErr))
}
} else {
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated.Reason)
//fmt.Println("Not finished ready!!!")
//fmt.Printf("c.State.Running %s \n", c.State.Running)
//fmt.Printf("c.State.Waiting %s \n", c.State.Waiting)
}
}
}
}
}
time.Sleep(10 * time.Second)
}
}
和一些日志:
single-condition-pipeline-9rqrs-1224102659
pod.Name single-condition-pipeline-9rqrs-1224102659
Status.Phase Running
PodIP XXXXXXXXXXXX
c.Name main
---------------------------------------------------------------------------------------------
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
c.Name wait
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
---------------------------------------------------------------------------------------------
commit update
---------------------------------------------------------------------------------------------
get pods metadatada
single-condition-pipeline-9rqrs-1224102659
pod.Name single-condition-pipeline-9rqrs-1224102659
Status.Phase Running
PodIP XXXXXXXXXX
c.Name main
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
c.Name wait
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
所以在这里:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-status,它提到了一个补丁,但我不知道如何使用它,所以如果有人可以帮助我或者有其他方法可以完成它。
您不能在 Pod status
字段中设置 phase
或任何其他内容,这是 read only. According to the Pod Lifecycle 文档,您的 pod 在 [= 之后将具有 Succeeded
阶段28=]"Pod 中的所有容器都已成功终止,并且不会重新启动。" 因此只有当您可以使所有 Pod 的容器退出并显示状态码 0
时才会发生这种情况如果 pod restartPolicy
设置为 onFailure
或 Never
,如果它设置为 Always
(默认值),那么容器最终将重新启动并且您的 pod 最终将 return 到 Running
阶段。
总而言之,您无法直接通过 Kube API 执行您尝试执行的操作。你必须:
- 确保您的 pod 具有可以支持
Succeeded
阶段的 restartPolicy
。
- 导致您的应用程序终止,可能通过发送它
SIGINT
或 SIGTERM
,或者可能通过它自己的 API. 命令它
主要问题是是否有办法从 client-go sdk 完成 pod,我不是要删除 pod,我只是想完成它具有阶段状态:已完成。
在代码中,我正在尝试更新 pod 阶段,但它不起作用,它没有 return 错误或恐慌,但 pod 没有完成。 我的代码:
func main() {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
for {
pods, err := clientset.CoreV1().Pods("ns").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
for _, pod := range pods.Items {
podName:= pod.Name
if strings.Contains(strings.ToLower(podName), "single-condition") {
fmt.Println("get pods metadatada")
fmt.Println(pod.Name)
fmt.Printf("pod.Name %s \n", pod.Name)
fmt.Printf("Status.Phase %s \n", pod.Status.Phase)
fmt.Printf("PodIP %s \n", pod.Status.PodIP)
containers := pod.Status.ContainerStatuses
if len(containers) > 0 {
for _ ,c := range containers {
fmt.Printf("c.Name %s \n", c.Name)
fmt.Printf("c.State %s \n", c.State)
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
stateTerminated := c.State.Terminated
stateRunning := c.State.Running
if stateTerminated == nil && stateRunning != nil {
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
fmt.Printf("stateRunning Reason: %s\n", reflect.TypeOf(c.State.Running))
getPod, getErr := clientset.CoreV1().Pods("ns").Get(context.TODO(), "single-condition-pipeline-9rqrs-1224102659" , metav1.GetOptions{})
if getErr != nil {
fmt.Println("error1")
panic(fmt.Errorf("Failed to get: %v", getErr))
}
fmt.Println("update values")
fmt.Printf(" getPodName %d \n", getPod.Name)
getPod.Status.Phase = "Succeeded"
fmt.Println("updated status phase")
getContainers := getPod.Status.ContainerStatuses
fmt.Printf("len get container %d \n", len(getContainers))
_, updateErr := clientset.CoreV1().Pods("argo-workflows").Update(context.TODO(), getPod, metav1.UpdateOptions{})
fmt.Println("commit update")
if updateErr != nil {
fmt.Println("error updated")
panic(fmt.Errorf("Failed to update: %v", updateErr))
}
} else {
fmt.Printf("c.State.Terminated %s \n", c.State.Terminated.Reason)
//fmt.Println("Not finished ready!!!")
//fmt.Printf("c.State.Running %s \n", c.State.Running)
//fmt.Printf("c.State.Waiting %s \n", c.State.Waiting)
}
}
}
}
}
time.Sleep(10 * time.Second)
}
}
和一些日志:
single-condition-pipeline-9rqrs-1224102659
pod.Name single-condition-pipeline-9rqrs-1224102659
Status.Phase Running
PodIP XXXXXXXXXXXX
c.Name main
---------------------------------------------------------------------------------------------
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
c.Name wait
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
---------------------------------------------------------------------------------------------
commit update
---------------------------------------------------------------------------------------------
get pods metadatada
single-condition-pipeline-9rqrs-1224102659
pod.Name single-condition-pipeline-9rqrs-1224102659
Status.Phase Running
PodIP XXXXXXXXXX
c.Name main
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
c.Name wait
c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
c.State.Terminated nil
c.State.Terminated nil
stateRunning Reason: *v1.ContainerStateRunning
update values
getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
updated status phase
len get container 2
commit update
所以在这里:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-status,它提到了一个补丁,但我不知道如何使用它,所以如果有人可以帮助我或者有其他方法可以完成它。
您不能在 Pod status
字段中设置 phase
或任何其他内容,这是 read only. According to the Pod Lifecycle 文档,您的 pod 在 [= 之后将具有 Succeeded
阶段28=]"Pod 中的所有容器都已成功终止,并且不会重新启动。" 因此只有当您可以使所有 Pod 的容器退出并显示状态码 0
时才会发生这种情况如果 pod restartPolicy
设置为 onFailure
或 Never
,如果它设置为 Always
(默认值),那么容器最终将重新启动并且您的 pod 最终将 return 到 Running
阶段。
总而言之,您无法直接通过 Kube API 执行您尝试执行的操作。你必须:
- 确保您的 pod 具有可以支持
Succeeded
阶段的restartPolicy
。 - 导致您的应用程序终止,可能通过发送它
SIGINT
或SIGTERM
,或者可能通过它自己的 API. 命令它