...

Source file src/k8s.io/kubernetes/pkg/kubelet/kuberuntime/labels.go

Documentation: k8s.io/kubernetes/pkg/kubelet/kuberuntime

     1  /*
     2  Copyright 2016 The Kubernetes 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 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  	// TODO: change those label names to follow kubernetes's format
    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  	// Labels from v1.Pod
    48  	Labels       map[string]string
    49  	PodName      string
    50  	PodNamespace string
    51  	PodUID       kubetypes.UID
    52  }
    53  
    54  type annotatedPodSandboxInfo struct {
    55  	// Annotations from v1.Pod
    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  // newPodLabels creates pod labels from v1.Pod.
    79  func newPodLabels(pod *v1.Pod) map[string]string {
    80  	labels := map[string]string{}
    81  
    82  	// Get labels from v1.Pod
    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  // newPodAnnotations creates pod annotations from v1.Pod.
    95  func newPodAnnotations(pod *v1.Pod) map[string]string {
    96  	return pod.Annotations
    97  }
    98  
    99  // newContainerLabels creates container labels from v1.Container and v1.Pod.
   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  // newContainerAnnotations creates container annotations from v1.Container and v1.Pod.
   111  func newContainerAnnotations(container *v1.Container, pod *v1.Pod, restartCount int, opts *kubecontainer.RunContainerOptions) map[string]string {
   112  	annotations := map[string]string{}
   113  
   114  	// Kubelet always overrides device plugin annotations if they are conflicting
   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  		// Using json encoding so that the PreStop handler object is readable after writing as a label
   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  // getPodSandboxInfoFromLabels gets labeledPodSandboxInfo from labels.
   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  	// Remain only labels from v1.Pod
   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  // getPodSandboxInfoFromAnnotations gets annotatedPodSandboxInfo from annotations.
   176  func getPodSandboxInfoFromAnnotations(annotations map[string]string) *annotatedPodSandboxInfo {
   177  	return &annotatedPodSandboxInfo{
   178  		Annotations: annotations,
   179  	}
   180  }
   181  
   182  // getContainerInfoFromLabels gets labeledContainerInfo from labels.
   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  // getContainerInfoFromAnnotations gets annotatedContainerInfo from annotations.
   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  	// Do not report error, because there should be many old containers without label now.
   240  	klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
   241  	// Return empty string "" for these containers, the caller will get value by other ways.
   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  			// This really should not happen. Just set value to 0 to handle this abnormal case
   250  			return 0, err
   251  		}
   252  		return intValue, nil
   253  	}
   254  	// Do not report error, because there should be many old containers without label now.
   255  	klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
   256  	// Just set the value to 0
   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  			// This really should not happen. Just set value to 0 to handle this abnormal case
   265  			return 0, err
   266  		}
   267  		return intValue, nil
   268  	}
   269  	// Do not report error, because there should be many old containers without label now.
   270  	klog.V(3).InfoS("Container doesn't have requested label, it may be an old or invalid container", "label", label)
   271  	// Just set the value to 0
   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  	// If the label is not found, return pointer nil.
   284  	return nil, nil
   285  }
   286  
   287  // getJSONObjectFromLabel returns a bool value indicating whether an object is found.
   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  	// If the label is not found, return not found.
   294  	return false, nil
   295  }
   296  

View as plain text