github.com/kubewharf/katalyst-core@v0.5.3/pkg/metaserver/agent/pod/runtime.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pod 18 19 import ( 20 "fmt" 21 "time" 22 23 kubetypes "k8s.io/apimachinery/pkg/types" 24 cri "k8s.io/cri-api/pkg/apis" 25 runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" 26 "k8s.io/klog/v2" 27 "k8s.io/kubernetes/pkg/kubelet/cri/remote" 28 "k8s.io/kubernetes/pkg/kubelet/types" 29 30 "github.com/kubewharf/katalyst-core/pkg/config/agent/global" 31 "github.com/kubewharf/katalyst-core/pkg/util/general" 32 ) 33 34 // RuntimePod is a group of containers. 35 type RuntimePod struct { 36 // The UID of the pod, which can be used to retrieve a particular pod 37 // from the pod list returned by GetPods(). 38 UID kubetypes.UID 39 // The name and namespace of the pod, which is readable by human. 40 Name string 41 Namespace string 42 // List of containers that belongs to this pod. It may contain only 43 // running containers, or mixed with dead ones (when GetPods(true)). 44 Containers []*runtimeapi.Container 45 // List of sandboxes associated with this pod. This is only populated 46 // by kuberuntime. 47 Sandboxes []*runtimeapi.PodSandbox 48 } 49 50 type labeledContainerInfo struct { 51 ContainerName string 52 PodName string 53 PodNamespace string 54 runtimeName string 55 PodUID kubetypes.UID 56 } 57 58 type RuntimePodFetcher interface { 59 GetPods(all bool) ([]*RuntimePod, error) 60 } 61 62 type runtimePodFetcherImpl struct { 63 runtimeService cri.RuntimeService 64 } 65 66 func NewRuntimePodFetcher(baseConf *global.BaseConfiguration) (RuntimePodFetcher, error) { 67 runtimeService, err := remote.NewRemoteRuntimeService(baseConf.RuntimeEndpoint, 2*time.Minute) 68 if err != nil { 69 return nil, fmt.Errorf("create remote runtime service failed %s", err) 70 } 71 72 return &runtimePodFetcherImpl{runtimeService: runtimeService}, nil 73 } 74 75 // GetPods returns a list of containers grouped by pods. The boolean parameter 76 // specifies whether the runtime returns all containers including those already 77 // exited and dead containers (used for garbage collection). 78 func (r *runtimePodFetcherImpl) GetPods(all bool) ([]*RuntimePod, error) { 79 pods := make(map[kubetypes.UID]*RuntimePod) 80 sandboxes, err := r.getKubeletSandboxes(all) 81 if err != nil { 82 return nil, err 83 } 84 for i := range sandboxes { 85 s := sandboxes[i] 86 if s.Metadata == nil { 87 klog.V(4).InfoS("Sandbox does not have metadata", "sandbox", s) 88 continue 89 } 90 podUID := kubetypes.UID(s.Metadata.Uid) 91 if _, ok := pods[podUID]; !ok { 92 pods[podUID] = &RuntimePod{ 93 UID: podUID, 94 Name: s.Metadata.Name, 95 Namespace: s.Metadata.Namespace, 96 } 97 } 98 p := pods[podUID] 99 p.Sandboxes = append(p.Sandboxes, s) 100 } 101 102 containers, err := r.getKubeletContainers(all) 103 if err != nil { 104 return nil, err 105 } 106 for i := range containers { 107 c := containers[i] 108 if c.Metadata == nil { 109 klog.V(4).InfoS("Container does not have metadata", "container", c) 110 continue 111 } 112 113 labelledInfo := getContainerInfoFromLabels(c.Labels) 114 pod, found := pods[labelledInfo.PodUID] 115 if !found { 116 pod = &RuntimePod{ 117 UID: labelledInfo.PodUID, 118 Name: labelledInfo.PodName, 119 Namespace: labelledInfo.PodNamespace, 120 } 121 pods[labelledInfo.PodUID] = pod 122 } 123 pod.Containers = append(pod.Containers, c) 124 } 125 126 // Convert map to list. 127 var result []*RuntimePod 128 for _, pod := range pods { 129 result = append(result, pod) 130 } 131 132 return result, nil 133 } 134 135 // getKubeletSandboxes lists all (or just the running) sandboxes managed by kubelet. 136 func (r *runtimePodFetcherImpl) getKubeletSandboxes(all bool) ([]*runtimeapi.PodSandbox, error) { 137 var filter *runtimeapi.PodSandboxFilter 138 if !all { 139 readyState := runtimeapi.PodSandboxState_SANDBOX_READY 140 filter = &runtimeapi.PodSandboxFilter{ 141 State: &runtimeapi.PodSandboxStateValue{ 142 State: readyState, 143 }, 144 } 145 } 146 147 resp, err := r.runtimeService.ListPodSandbox(filter) 148 if err != nil { 149 klog.ErrorS(err, "Failed to list pod sandboxes") 150 return nil, err 151 } 152 153 return resp, nil 154 } 155 156 // getKubeletContainers lists containers managed by kubelet. 157 // The boolean parameter specifies whether returns all containers including 158 // those already exited and dead containers (used for garbage collection). 159 func (r *runtimePodFetcherImpl) getKubeletContainers(allContainers bool) ([]*runtimeapi.Container, error) { 160 filter := &runtimeapi.ContainerFilter{} 161 if !allContainers { 162 filter.State = &runtimeapi.ContainerStateValue{ 163 State: runtimeapi.ContainerState_CONTAINER_RUNNING, 164 } 165 } 166 167 containers, err := r.runtimeService.ListContainers(filter) 168 if err != nil { 169 klog.ErrorS(err, "ListContainers failed") 170 return nil, err 171 } 172 173 return containers, nil 174 } 175 176 // getContainerInfoFromLabels gets labeledContainerInfo from labels. 177 func getContainerInfoFromLabels(labels map[string]string) *labeledContainerInfo { 178 return &labeledContainerInfo{ 179 PodName: general.GetStringValueFromMap(labels, types.KubernetesPodNameLabel), 180 PodNamespace: general.GetStringValueFromMap(labels, types.KubernetesPodNamespaceLabel), 181 PodUID: kubetypes.UID(general.GetStringValueFromMap(labels, types.KubernetesPodUIDLabel)), 182 ContainerName: general.GetStringValueFromMap(labels, types.KubernetesContainerNameLabel), 183 } 184 }