1
16
17 package kuberuntime
18
19 import (
20 "encoding/json"
21 "strconv"
22
23 v1 "k8s.io/api/core/v1"
24 kubetypes "k8s.io/apimachinery/pkg/types"
25 utilfeature "k8s.io/apiserver/pkg/util/feature"
26 "k8s.io/klog/v2"
27 "k8s.io/kubelet/pkg/types"
28 "k8s.io/kubernetes/pkg/features"
29 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
30 )
31
32 const (
33
34 podDeletionGracePeriodLabel = "io.kubernetes.pod.deletionGracePeriod"
35 podTerminationGracePeriodLabel = "io.kubernetes.pod.terminationGracePeriod"
36
37 containerHashLabel = "io.kubernetes.container.hash"
38 containerHashWithoutResourcesLabel = "io.kubernetes.container.hashWithoutResources"
39 containerRestartCountLabel = "io.kubernetes.container.restartCount"
40 containerTerminationMessagePathLabel = "io.kubernetes.container.terminationMessagePath"
41 containerTerminationMessagePolicyLabel = "io.kubernetes.container.terminationMessagePolicy"
42 containerPreStopHandlerLabel = "io.kubernetes.container.preStopHandler"
43 containerPortsLabel = "io.kubernetes.container.ports"
44 )
45
46 type labeledPodSandboxInfo struct {
47
48 Labels map[string]string
49 PodName string
50 PodNamespace string
51 PodUID kubetypes.UID
52 }
53
54 type annotatedPodSandboxInfo struct {
55
56 Annotations map[string]string
57 }
58
59 type labeledContainerInfo struct {
60 ContainerName string
61 PodName string
62 PodNamespace string
63 PodUID kubetypes.UID
64 }
65
66 type annotatedContainerInfo struct {
67 Hash uint64
68 HashWithoutResources uint64
69 RestartCount int
70 PodDeletionGracePeriod *int64
71 PodTerminationGracePeriod *int64
72 TerminationMessagePath string
73 TerminationMessagePolicy v1.TerminationMessagePolicy
74 PreStopHandler *v1.LifecycleHandler
75 ContainerPorts []v1.ContainerPort
76 }
77
78
79 func newPodLabels(pod *v1.Pod) map[string]string {
80 labels := map[string]string{}
81
82
83 for k, v := range pod.Labels {
84 labels[k] = v
85 }
86
87 labels[types.KubernetesPodNameLabel] = pod.Name
88 labels[types.KubernetesPodNamespaceLabel] = pod.Namespace
89 labels[types.KubernetesPodUIDLabel] = string(pod.UID)
90
91 return labels
92 }
93
94
95 func newPodAnnotations(pod *v1.Pod) map[string]string {
96 return pod.Annotations
97 }
98
99
100 func newContainerLabels(container *v1.Container, pod *v1.Pod) map[string]string {
101 labels := map[string]string{}
102 labels[types.KubernetesPodNameLabel] = pod.Name
103 labels[types.KubernetesPodNamespaceLabel] = pod.Namespace
104 labels[types.KubernetesPodUIDLabel] = string(pod.UID)
105 labels[types.KubernetesContainerNameLabel] = container.Name
106
107 return labels
108 }
109
110
111 func newContainerAnnotations(container *v1.Container, pod *v1.Pod, restartCount int, opts *kubecontainer.RunContainerOptions) map[string]string {
112 annotations := map[string]string{}
113
114
115 for _, a := range opts.Annotations {
116 annotations[a.Name] = a.Value
117 }
118
119 annotations[containerHashLabel] = strconv.FormatUint(kubecontainer.HashContainer(container), 16)
120 if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) {
121 annotations[containerHashWithoutResourcesLabel] = strconv.FormatUint(kubecontainer.HashContainerWithoutResources(container), 16)
122 }
123 annotations[containerRestartCountLabel] = strconv.Itoa(restartCount)
124 annotations[containerTerminationMessagePathLabel] = container.TerminationMessagePath
125 annotations[containerTerminationMessagePolicyLabel] = string(container.TerminationMessagePolicy)
126
127 if pod.DeletionGracePeriodSeconds != nil {
128 annotations[podDeletionGracePeriodLabel] = strconv.FormatInt(*pod.DeletionGracePeriodSeconds, 10)
129 }
130 if pod.Spec.TerminationGracePeriodSeconds != nil {
131 annotations[podTerminationGracePeriodLabel] = strconv.FormatInt(*pod.Spec.TerminationGracePeriodSeconds, 10)
132 }
133
134 if container.Lifecycle != nil && container.Lifecycle.PreStop != nil {
135
136 rawPreStop, err := json.Marshal(container.Lifecycle.PreStop)
137 if err != nil {
138 klog.ErrorS(err, "Unable to marshal lifecycle PreStop handler for container", "containerName", container.Name, "pod", klog.KObj(pod))
139 } else {
140 annotations[containerPreStopHandlerLabel] = string(rawPreStop)
141 }
142 }
143
144 if len(container.Ports) > 0 {
145 rawContainerPorts, err := json.Marshal(container.Ports)
146 if err != nil {
147 klog.ErrorS(err, "Unable to marshal container ports for container", "containerName", container.Name, "pod", klog.KObj(pod))
148 } else {
149 annotations[containerPortsLabel] = string(rawContainerPorts)
150 }
151 }
152
153 return annotations
154 }
155
156
157 func getPodSandboxInfoFromLabels(labels map[string]string) *labeledPodSandboxInfo {
158 podSandboxInfo := &labeledPodSandboxInfo{
159 Labels: make(map[string]string),
160 PodName: getStringValueFromLabel(labels, types.KubernetesPodNameLabel),
161 PodNamespace: getStringValueFromLabel(labels, types.KubernetesPodNamespaceLabel),
162 PodUID: kubetypes.UID(getStringValueFromLabel(labels, types.KubernetesPodUIDLabel)),
163 }
164
165
166 for k, v := range labels {
167 if k != types.KubernetesPodNameLabel && k != types.KubernetesPodNamespaceLabel && k != types.KubernetesPodUIDLabel {
168 podSandboxInfo.Labels[k] = v
169 }
170 }
171
172 return podSandboxInfo
173 }
174
175
176 func getPodSandboxInfoFromAnnotations(annotations map[string]string) *annotatedPodSandboxInfo {
177 return &annotatedPodSandboxInfo{
178 Annotations: annotations,
179 }
180 }
181
182
183 func getContainerInfoFromLabels(labels map[string]string) *labeledContainerInfo {
184 return &labeledContainerInfo{
185 PodName: getStringValueFromLabel(labels, types.KubernetesPodNameLabel),
186 PodNamespace: getStringValueFromLabel(labels, types.KubernetesPodNamespaceLabel),
187 PodUID: kubetypes.UID(getStringValueFromLabel(labels, types.KubernetesPodUIDLabel)),
188 ContainerName: getStringValueFromLabel(labels, types.KubernetesContainerNameLabel),
189 }
190 }
191
192
193 func getContainerInfoFromAnnotations(annotations map[string]string) *annotatedContainerInfo {
194 var err error
195 containerInfo := &annotatedContainerInfo{
196 TerminationMessagePath: getStringValueFromLabel(annotations, containerTerminationMessagePathLabel),
197 TerminationMessagePolicy: v1.TerminationMessagePolicy(getStringValueFromLabel(annotations, containerTerminationMessagePolicyLabel)),
198 }
199
200 if containerInfo.Hash, err = getUint64ValueFromLabel(annotations, containerHashLabel); err != nil {
201 klog.ErrorS(err, "Unable to get label value from annotations", "label", containerHashLabel, "annotations", annotations)
202 }
203 if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) {
204 if containerInfo.HashWithoutResources, err = getUint64ValueFromLabel(annotations, containerHashWithoutResourcesLabel); err != nil {
205 klog.ErrorS(err, "Unable to get label value from annotations", "label", containerHashWithoutResourcesLabel, "annotations", annotations)
206 }
207 }
208 if containerInfo.RestartCount, err = getIntValueFromLabel(annotations, containerRestartCountLabel); err != nil {
209 klog.ErrorS(err, "Unable to get label value from annotations", "label", containerRestartCountLabel, "annotations", annotations)
210 }
211 if containerInfo.PodDeletionGracePeriod, err = getInt64PointerFromLabel(annotations, podDeletionGracePeriodLabel); err != nil {
212 klog.ErrorS(err, "Unable to get label value from annotations", "label", podDeletionGracePeriodLabel, "annotations", annotations)
213 }
214 if containerInfo.PodTerminationGracePeriod, err = getInt64PointerFromLabel(annotations, podTerminationGracePeriodLabel); err != nil {
215 klog.ErrorS(err, "Unable to get label value from annotations", "label", podTerminationGracePeriodLabel, "annotations", annotations)
216 }
217
218 preStopHandler := &v1.LifecycleHandler{}
219 if found, err := getJSONObjectFromLabel(annotations, containerPreStopHandlerLabel, preStopHandler); err != nil {
220 klog.ErrorS(err, "Unable to get label value from annotations", "label", containerPreStopHandlerLabel, "annotations", annotations)
221 } else if found {
222 containerInfo.PreStopHandler = preStopHandler
223 }
224
225 containerPorts := []v1.ContainerPort{}
226 if found, err := getJSONObjectFromLabel(annotations, containerPortsLabel, &containerPorts); err != nil {
227 klog.ErrorS(err, "Unable to get label value from annotations", "label", containerPortsLabel, "annotations", annotations)
228 } else if found {
229 containerInfo.ContainerPorts = containerPorts
230 }
231
232 return containerInfo
233 }
234
235 func getStringValueFromLabel(labels map[string]string, label string) string {
236 if value, found := labels[label]; found {
237 return value
238 }
239
240 klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
241
242 return ""
243 }
244
245 func getIntValueFromLabel(labels map[string]string, label string) (int, error) {
246 if strValue, found := labels[label]; found {
247 intValue, err := strconv.Atoi(strValue)
248 if err != nil {
249
250 return 0, err
251 }
252 return intValue, nil
253 }
254
255 klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
256
257 return 0, nil
258 }
259
260 func getUint64ValueFromLabel(labels map[string]string, label string) (uint64, error) {
261 if strValue, found := labels[label]; found {
262 intValue, err := strconv.ParseUint(strValue, 16, 64)
263 if err != nil {
264
265 return 0, err
266 }
267 return intValue, nil
268 }
269
270 klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
271
272 return 0, nil
273 }
274
275 func getInt64PointerFromLabel(labels map[string]string, label string) (*int64, error) {
276 if strValue, found := labels[label]; found {
277 int64Value, err := strconv.ParseInt(strValue, 10, 64)
278 if err != nil {
279 return nil, err
280 }
281 return &int64Value, nil
282 }
283
284 return nil, nil
285 }
286
287
288 func getJSONObjectFromLabel(labels map[string]string, label string, value interface{}) (bool, error) {
289 if strValue, found := labels[label]; found {
290 err := json.Unmarshal([]byte(strValue), value)
291 return found, err
292 }
293
294 return false, nil
295 }
296
View as plain text