You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

k8s.go 6.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package cloud
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/aliyun/alibaba-cloud-sdk-go/services/eci"
  6. "github.com/go-resty/resty/v2"
  7. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/participant/cloud"
  8. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/service/collector"
  9. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
  10. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
  11. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils/restyclient"
  12. v1 "k8s.io/api/core/v1"
  13. v2 "k8s.io/apimachinery/pkg/apis/meta/v1"
  14. "k8s.io/apimachinery/pkg/util/json"
  15. )
  16. // 定义枚举类型
  17. type ParticipantCloud struct {
  18. participantId int64
  19. platform string
  20. host string
  21. userName string
  22. accessToken string
  23. *restyclient.RestyClient
  24. }
  25. func NewCloud(host string, id int64, platform string) *ParticipantCloud {
  26. return &ParticipantCloud{
  27. host: host,
  28. participantId: id,
  29. platform: platform,
  30. RestyClient: restyclient.InitClient(host, ""),
  31. }
  32. }
  33. func (c *ParticipantCloud) GetContainer(ctx context.Context, name string, queryParam string, clusterId string) (collector.Task, error) {
  34. resp := collector.Task{}
  35. reqUrl := c.host + cloud.GetContainer
  36. containerResp := &collector.ContainerDetailResp{}
  37. httpClient := resty.New().R()
  38. _, err := httpClient.SetHeaders(
  39. map[string]string{
  40. "Content-Type": "application/json",
  41. "traceId": result.TraceIDFromContext(ctx),
  42. }).
  43. SetQueryParams(map[string]string{
  44. "pfId": clusterId,
  45. }).SetBody(cloud.GetParam{Name: name}).
  46. SetResult(&containerResp).
  47. Post(reqUrl)
  48. if err != nil {
  49. return resp, err
  50. }
  51. fmt.Println("containerResp:", containerResp.Data)
  52. if queryParam != "" && queryParam != "null" {
  53. resp = getEciStatusEnum(containerResp)
  54. } else {
  55. resp = getK8sStatusEnum(containerResp)
  56. }
  57. return resp, nil
  58. }
  59. func getK8sStatusEnum(containerDetail *collector.ContainerDetailResp) collector.Task {
  60. var resp collector.Task
  61. var pod v1.Pod
  62. bytes, err := json.Marshal(containerDetail.Data)
  63. if err != nil {
  64. return resp
  65. }
  66. json.Unmarshal(bytes, &pod)
  67. // 优先判断Pod的删除状态(是否正在删除)
  68. if !pod.DeletionTimestamp.IsZero() {
  69. // 已标记删除但未完全删除 → WaitDelete;已删除(若能查询到则表示未完全删除)
  70. resp.Status = constants.WaitDelete
  71. }
  72. // 根据Pod的Phase(宏观状态)判断
  73. switch pod.Status.Phase {
  74. case v1.PodRunning:
  75. // 运行中:检查是否有容器在重启(可能处于WaitRestart)
  76. for _, cs := range pod.Status.ContainerStatuses {
  77. if cs.RestartCount > 0 && cs.State.Running == nil {
  78. // 有重启记录且当前运行中 → 刚重启完,对应WaitRestart
  79. resp.Status = constants.WaitRestart
  80. }
  81. }
  82. resp.Status = constants.Running
  83. case v1.PodPending:
  84. // Pending状态:检查容器是否在等待启动
  85. for _, cs := range pod.Status.ContainerStatuses {
  86. if cs.State.Waiting != nil {
  87. switch cs.State.Waiting.Reason {
  88. case "ContainerCreating", "PodInitializing":
  89. resp.Status = constants.WaitStart // 等待启动
  90. case "Paused":
  91. resp.Status = constants.WaitPause // 等待暂停(罕见,通常对应Pause状态)
  92. default:
  93. resp.Status = constants.Waiting // 其他等待状态
  94. }
  95. }
  96. }
  97. resp.Status = constants.Pending
  98. case v1.PodSucceeded:
  99. // 所有容器成功终止
  100. resp.Status = constants.Succeeded
  101. case v1.PodFailed:
  102. // 至少一个容器失败终止
  103. resp.Status = constants.Failed
  104. case v1.PodUnknown:
  105. // 未知状态 → 暂归为Waiting
  106. resp.Status = constants.Waiting
  107. }
  108. // 检查容器状态(补充Phase未覆盖的情况)
  109. for _, cs := range pod.Status.ContainerStatuses {
  110. switch {
  111. case cs.State.Terminated != nil:
  112. if cs.State.Terminated.Reason == "Completed" {
  113. resp.Status = constants.Completed // 容器正常完成
  114. }
  115. if cs.State.Terminated.Reason == "Error" {
  116. resp.Status = constants.Failed // 错误终止
  117. }
  118. if cs.State.Terminated.Reason == "Cancelled" {
  119. resp.Status = constants.Cancelled // 被取消
  120. }
  121. case cs.State.Waiting != nil && cs.State.Waiting.Reason == "Paused":
  122. resp.Status = constants.WaitPause // 容器被暂停
  123. }
  124. }
  125. // 提取 StartTime(Pod 启动时间)
  126. startTime := pod.Status.StartTime
  127. if startTime == nil {
  128. fmt.Println("Pod 尚未启动,无 startTime")
  129. } else {
  130. resp.Start = startTime.Time.Format("2006-01-02 15:04:05")
  131. }
  132. // 提取 EndTime(容器终止时间,仅当 Pod 已结束时存在)
  133. // 遍历所有容器状态,查找已终止的容器
  134. var endTime *v2.Time
  135. for _, containerStatus := range pod.Status.ContainerStatuses {
  136. if containerStatus.State.Terminated != nil {
  137. endTime = &containerStatus.State.Terminated.FinishedAt
  138. break // 取第一个终止的容器时间(若有多个容器,可根据需求调整)
  139. }
  140. }
  141. if endTime == nil {
  142. fmt.Println("Pod 尚未终止,无 endTime(可能仍在运行中)")
  143. } else {
  144. resp.End = endTime.Time.Format("2006-01-02 15:04:05")
  145. }
  146. return resp
  147. }
  148. func getEciStatusEnum(containerDetail *collector.ContainerDetailResp) collector.Task {
  149. var resp collector.Task
  150. var eciResp eci.DescribeContainerGroupsResponse
  151. bytes, err := json.Marshal(containerDetail.Data)
  152. if err != nil {
  153. return resp
  154. }
  155. json.Unmarshal(bytes, &eciResp)
  156. if len(eciResp.ContainerGroups) == 0 {
  157. return resp
  158. }
  159. switch eciResp.ContainerGroups[0].Status {
  160. case "Pending":
  161. resp.Status = constants.Pending
  162. case "Creating":
  163. resp.Status = constants.WaitStart
  164. case "Running":
  165. resp.Status = constants.Running
  166. case "Stopping":
  167. resp.Status = constants.Stopped
  168. case "Stopped":
  169. resp.Status = constants.Stopped
  170. case "Failed":
  171. resp.Status = constants.Failed
  172. case "Deleting":
  173. resp.Status = constants.Deleted
  174. case "Succeeded":
  175. resp.Status = constants.Succeeded
  176. case "Unknown":
  177. resp.Status = constants.Failed
  178. }
  179. resp.Start = eciResp.ContainerGroups[0].CreationTime
  180. resp.End = eciResp.ContainerGroups[0].SucceededTime
  181. return resp
  182. }

PCM is positioned as Software stack over Cloud, aiming to build the standards and ecology of heterogeneous cloud collaboration for JCC in a non intrusive and autonomous peer-to-peer manner.