有没有一种优雅地结束 Kubernetes client-go 中的 Pod 的方法?

huangapple go评论120阅读模式
英文:

Is there a way to gracefully end a pod with the Kubernetes client-go?

问题

主要问题是是否有一种方法可以使用client-go sdk完成一个Pod,我不是要删除一个Pod,我只是想将其状态设置为Completed

在代码中,我尝试更新Pod的状态,但它不起作用,它没有返回错误或崩溃,但Pod没有完成。
我的代码:

  1. func main() {
  2. // 创建集群内部配置
  3. config, err := rest.InClusterConfig()
  4. if err != nil {
  5. panic(err.Error())
  6. }
  7. // 创建客户端集
  8. clientset, err := kubernetes.NewForConfig(config)
  9. if err != nil {
  10. panic(err.Error())
  11. }
  12. for {
  13. pods, err := clientset.CoreV1().Pods("ns").List(context.TODO(), metav1.ListOptions{})
  14. if err != nil {
  15. panic(err.Error())
  16. }
  17. for _, pod := range pods.Items {
  18. podName := pod.Name
  19. if strings.Contains(strings.ToLower(podName), "single-condition") {
  20. fmt.Println("获取Pod元数据")
  21. fmt.Println(pod.Name)
  22. fmt.Printf("pod.Name %s \n", pod.Name)
  23. fmt.Printf("Status.Phase %s \n", pod.Status.Phase)
  24. fmt.Printf("PodIP %s \n", pod.Status.PodIP)
  25. containers := pod.Status.ContainerStatuses
  26. if len(containers) > 0 {
  27. for _, c := range containers {
  28. fmt.Printf("c.Name %s \n", c.Name)
  29. fmt.Printf("c.State %s \n", c.State)
  30. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
  31. stateTerminated := c.State.Terminated
  32. stateRunning := c.State.Running
  33. if stateTerminated == nil && stateRunning != nil {
  34. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
  35. fmt.Printf("stateRunning Reason: %s\n", reflect.TypeOf(c.State.Running))
  36. getPod, getErr := clientset.CoreV1().Pods("ns").Get(context.TODO(), "single-condition-pipeline-9rqrs-1224102659", metav1.GetOptions{})
  37. if getErr != nil {
  38. fmt.Println("错误1")
  39. panic(fmt.Errorf("获取失败:%v", getErr))
  40. }
  41. fmt.Println("更新值")
  42. fmt.Printf(" getPodName %d \n", getPod.Name)
  43. getPod.Status.Phase = "Succeeded"
  44. fmt.Println("更新状态阶段")
  45. getContainers := getPod.Status.ContainerStatuses
  46. fmt.Printf("len get container %d \n", len(getContainers))
  47. _, updateErr := clientset.CoreV1().Pods("argo-workflows").Update(context.TODO(), getPod, metav1.UpdateOptions{})
  48. fmt.Println("提交更新")
  49. if updateErr != nil {
  50. fmt.Println("更新错误")
  51. panic(fmt.Errorf("更新失败:%v", updateErr))
  52. }
  53. } else {
  54. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated.Reason)
  55. //fmt.Println("Not finished ready!!!")
  56. //fmt.Printf("c.State.Running %s \n", c.State.Running)
  57. //fmt.Printf("c.State.Waiting %s \n", c.State.Waiting)
  58. }
  59. }
  60. }
  61. }
  62. }
  63. time.Sleep(10 * time.Second)
  64. }
  65. }

一些日志:

  1. single-condition-pipeline-9rqrs-1224102659
  2. pod.Name single-condition-pipeline-9rqrs-1224102659
  3. Status.Phase Running
  4. PodIP XXXXXXXXXXXX
  5. c.Name main
  6. ---------------------------------------------------------------------------------------------
  7. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  8. c.State.Terminated nil
  9. c.State.Terminated nil
  10. stateRunning Reason: *v1.ContainerStateRunning
  11. update values
  12. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  13. updated status phase
  14. len get container 2
  15. commit update
  16. c.Name wait
  17. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  18. c.State.Terminated nil
  19. c.State.Terminated nil
  20. stateRunning Reason: *v1.ContainerStateRunning
  21. update values
  22. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  23. updated status phase
  24. len get container 2
  25. ---------------------------------------------------------------------------------------------
  26. commit update
  27. ---------------------------------------------------------------------------------------------
  28. 获取Pod元数据
  29. single-condition-pipeline-9rqrs-1224102659
  30. pod.Name single-condition-pipeline-9rqrs-1224102659
  31. Status.Phase Running
  32. PodIP XXXXXXXXXX
  33. c.Name main
  34. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  35. c.State.Terminated nil
  36. c.State.Terminated nil
  37. stateRunning Reason: *v1.ContainerStateRunning
  38. update values
  39. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  40. updated status phase
  41. len get container 2
  42. commit update
  43. c.Name wait
  44. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  45. c.State.Terminated nil
  46. c.State.Terminated nil
  47. stateRunning Reason: *v1.ContainerStateRunning
  48. update values
  49. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  50. updated status phase
  51. len get container 2
  52. commit update

所以在这里:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-status,它提到了一个Patch,但我不知道如何使用它,所以如果有人可以帮助我或者有其他方法来完成它。

英文:

The main question is if there is a way to finish a pod from the client-go sdk, I'm not trying to delete a pod, I just want to finish it with a Phase-Status: Completed.

In the code, I'm trying to update the pod phase but It doesn't work, It does not return an error or panic but The pod does not finish.
My code:

  1. func main() {
  2. // creates the in-cluster config
  3. config, err := rest.InClusterConfig()
  4. if err != nil {
  5. panic(err.Error())
  6. }
  7. // creates the clientset
  8. clientset, err := kubernetes.NewForConfig(config)
  9. if err != nil {
  10. panic(err.Error())
  11. }
  12. for {
  13. pods, err := clientset.CoreV1().Pods("ns").List(context.TODO(), metav1.ListOptions{})
  14. if err != nil {
  15. panic(err.Error())
  16. }
  17. for _, pod := range pods.Items {
  18. podName:= pod.Name
  19. if strings.Contains(strings.ToLower(podName), "single-condition") {
  20. fmt.Println("get pods metadatada")
  21. fmt.Println(pod.Name)
  22. fmt.Printf("pod.Name %s \n", pod.Name)
  23. fmt.Printf("Status.Phase %s \n", pod.Status.Phase)
  24. fmt.Printf("PodIP %s \n", pod.Status.PodIP)
  25. containers := pod.Status.ContainerStatuses
  26. if len(containers) > 0 {
  27. for _ ,c := range containers {
  28. fmt.Printf("c.Name %s \n", c.Name)
  29. fmt.Printf("c.State %s \n", c.State)
  30. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
  31. stateTerminated := c.State.Terminated
  32. stateRunning := c.State.Running
  33. if stateTerminated == nil && stateRunning != nil {
  34. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated)
  35. fmt.Printf("stateRunning Reason: %s\n", reflect.TypeOf(c.State.Running))
  36. getPod, getErr := clientset.CoreV1().Pods("ns").Get(context.TODO(), "single-condition-pipeline-9rqrs-1224102659" , metav1.GetOptions{})
  37. if getErr != nil {
  38. fmt.Println("error1")
  39. panic(fmt.Errorf("Failed to get: %v", getErr))
  40. }
  41. fmt.Println("update values")
  42. fmt.Printf(" getPodName %d \n", getPod.Name)
  43. getPod.Status.Phase = "Succeeded"
  44. fmt.Println("updated status phase")
  45. getContainers := getPod.Status.ContainerStatuses
  46. fmt.Printf("len get container %d \n", len(getContainers))
  47. _, updateErr := clientset.CoreV1().Pods("argo-workflows").Update(context.TODO(), getPod, metav1.UpdateOptions{})
  48. fmt.Println("commit update")
  49. if updateErr != nil {
  50. fmt.Println("error updated")
  51. panic(fmt.Errorf("Failed to update: %v", updateErr))
  52. }
  53. } else {
  54. fmt.Printf("c.State.Terminated %s \n", c.State.Terminated.Reason)
  55. //fmt.Println("Not finished ready!!!")
  56. //fmt.Printf("c.State.Running %s \n", c.State.Running)
  57. //fmt.Printf("c.State.Waiting %s \n", c.State.Waiting)
  58. }
  59. }
  60. }
  61. }
  62. }
  63. time.Sleep(10 * time.Second)
  64. }
  65. }

and some logs:

  1. single-condition-pipeline-9rqrs-1224102659
  2. pod.Name single-condition-pipeline-9rqrs-1224102659
  3. Status.Phase Running
  4. PodIP XXXXXXXXXXXX
  5. c.Name main
  6. ---------------------------------------------------------------------------------------------
  7. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  8. c.State.Terminated nil
  9. c.State.Terminated nil
  10. stateRunning Reason: *v1.ContainerStateRunning
  11. update values
  12. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  13. updated status phase
  14. len get container 2
  15. commit update
  16. c.Name wait
  17. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  18. c.State.Terminated nil
  19. c.State.Terminated nil
  20. stateRunning Reason: *v1.ContainerStateRunning
  21. update values
  22. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  23. updated status phase
  24. len get container 2
  25. ---------------------------------------------------------------------------------------------
  26. commit update
  27. ---------------------------------------------------------------------------------------------
  28. get pods metadatada
  29. single-condition-pipeline-9rqrs-1224102659
  30. pod.Name single-condition-pipeline-9rqrs-1224102659
  31. Status.Phase Running
  32. PodIP XXXXXXXXXX
  33. c.Name main
  34. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  35. c.State.Terminated nil
  36. c.State.Terminated nil
  37. stateRunning Reason: *v1.ContainerStateRunning
  38. update values
  39. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  40. updated status phase
  41. len get container 2
  42. commit update
  43. c.Name wait
  44. c.State {nil &ContainerStateRunning{StartedAt:2021-10-29 04:41:51 +0000 UTC,} nil}
  45. c.State.Terminated nil
  46. c.State.Terminated nil
  47. stateRunning Reason: *v1.ContainerStateRunning
  48. update values
  49. getPodName %!d(string=single-condition-pipeline-9rqrs-1224102659)
  50. updated status phase
  51. len get container 2
  52. commit update

so here: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-status, It mentions a Patch but I don't know how to use it, so if somebody could help me or if there is another way to finish it.

答案1

得分: 2

你不能在 Pod 的 status 字段中设置 phase 或其他任何内容,它是只读的。根据Pod 生命周期文档,在“所有 Pod 中的容器成功终止,并且不会重新启动”之后,你的 Pod 将处于 Succeeded 阶段。因此,只有当你能够使 Pod 中的所有容器以状态码 0 退出,并且 Pod 的 restartPolicy 设置为 onFailureNever 时,才会发生这种情况;如果设置为 Always(默认值),容器最终会重新启动,你的 Pod 最终会返回到 Running 阶段。

总之,你不能通过 Kube API 直接实现你所尝试的操作。你必须:

  1. 确保你的 Pod 具有支持 Succeeded 阶段的 restartPolicy
  2. 通过发送 SIGINTSIGTERM 终止你的应用程序,或通过其自身的 API 命令它。
英文:

You cannot set the phase or anything else in the Pod status field, it is read only. According to the Pod Lifecycle documentation your pod will have a phase of Succeeded after "All containers in the Pod have terminated in success, and will not be restarted." So this will only happen if you can cause all of your pod's containers to exit with status code 0 and if the pod restartPolicy is set to onFailure or Never, if it is set to Always (the default) then the containers will eventually restart and your pod will eventually return to the Running phase.

In summary, you cannot do what you are attempting to do via the Kube API directly. You must:

  1. Ensure your pod has a restartPolicy that can support the Succeeded phase.
  2. Cause your application to terminate, possibly by sending it SIGINT or SIGTERM, or possibly by commanding it via its own API.

huangapple
  • 本文由 发表于 2021年10月29日 15:34:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/69765180.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定