...

Source file src/k8s.io/kubernetes/pkg/kubelet/config/common.go

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

     1  /*
     2  Copyright 2014 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 config
    18  
    19  import (
    20  	"crypto/md5"
    21  	"encoding/hex"
    22  	"errors"
    23  	"fmt"
    24  	"strings"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/apimachinery/pkg/types"
    30  	utilyaml "k8s.io/apimachinery/pkg/util/yaml"
    31  	api "k8s.io/kubernetes/pkg/apis/core"
    32  	"k8s.io/kubernetes/pkg/apis/core/helper"
    33  
    34  	// TODO: remove this import if
    35  	// api.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() is changed
    36  	// to "v1"?
    37  	"k8s.io/kubernetes/pkg/api/legacyscheme"
    38  	// Ensure that core apis are installed
    39  	_ "k8s.io/kubernetes/pkg/apis/core/install"
    40  	k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
    41  	"k8s.io/kubernetes/pkg/apis/core/validation"
    42  	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
    43  	"k8s.io/kubernetes/pkg/util/hash"
    44  
    45  	"k8s.io/klog/v2"
    46  )
    47  
    48  const (
    49  	maxConfigLength = 10 * 1 << 20 // 10MB
    50  )
    51  
    52  // Generate a pod name that is unique among nodes by appending the nodeName.
    53  func generatePodName(name string, nodeName types.NodeName) string {
    54  	return fmt.Sprintf("%s-%s", name, strings.ToLower(string(nodeName)))
    55  }
    56  
    57  func applyDefaults(pod *api.Pod, source string, isFile bool, nodeName types.NodeName) error {
    58  	if len(pod.UID) == 0 {
    59  		hasher := md5.New()
    60  		hash.DeepHashObject(hasher, pod)
    61  		// DeepHashObject resets the hash, so we should write the pod source
    62  		// information AFTER it.
    63  		if isFile {
    64  			fmt.Fprintf(hasher, "host:%s", nodeName)
    65  			fmt.Fprintf(hasher, "file:%s", source)
    66  		} else {
    67  			fmt.Fprintf(hasher, "url:%s", source)
    68  		}
    69  		pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:]))
    70  		klog.V(5).InfoS("Generated UID", "pod", klog.KObj(pod), "podUID", pod.UID, "source", source)
    71  	}
    72  
    73  	pod.Name = generatePodName(pod.Name, nodeName)
    74  	klog.V(5).InfoS("Generated pod name", "pod", klog.KObj(pod), "podUID", pod.UID, "source", source)
    75  
    76  	if pod.Namespace == "" {
    77  		pod.Namespace = metav1.NamespaceDefault
    78  	}
    79  	klog.V(5).InfoS("Set namespace for pod", "pod", klog.KObj(pod), "source", source)
    80  
    81  	// Set the Host field to indicate this pod is scheduled on the current node.
    82  	pod.Spec.NodeName = string(nodeName)
    83  
    84  	if pod.Annotations == nil {
    85  		pod.Annotations = make(map[string]string)
    86  	}
    87  	// The generated UID is the hash of the file.
    88  	pod.Annotations[kubetypes.ConfigHashAnnotationKey] = string(pod.UID)
    89  
    90  	if isFile {
    91  		// Applying the default Taint tolerations to static pods,
    92  		// so they are not evicted when there are node problems.
    93  		helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{
    94  			Operator: "Exists",
    95  			Effect:   api.TaintEffectNoExecute,
    96  		})
    97  	}
    98  
    99  	// Set the default status to pending.
   100  	pod.Status.Phase = api.PodPending
   101  	return nil
   102  }
   103  
   104  type defaultFunc func(pod *api.Pod) error
   105  
   106  // A static pod tried to use a ClusterTrustBundle projected volume source.
   107  var ErrStaticPodTriedToUseClusterTrustBundle = errors.New("static pods may not use ClusterTrustBundle projected volume sources")
   108  
   109  // tryDecodeSinglePod takes data and tries to extract valid Pod config information from it.
   110  func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod *v1.Pod, err error) {
   111  	// JSON is valid YAML, so this should work for everything.
   112  	json, err := utilyaml.ToJSON(data)
   113  	if err != nil {
   114  		return false, nil, err
   115  	}
   116  	obj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), json)
   117  	if err != nil {
   118  		return false, pod, err
   119  	}
   120  
   121  	newPod, ok := obj.(*api.Pod)
   122  	// Check whether the object could be converted to single pod.
   123  	if !ok {
   124  		return false, pod, fmt.Errorf("invalid pod: %#v", obj)
   125  	}
   126  
   127  	if newPod.Name == "" {
   128  		return true, pod, fmt.Errorf("invalid pod: name is needed for the pod")
   129  	}
   130  
   131  	// Apply default values and validate the pod.
   132  	if err = defaultFn(newPod); err != nil {
   133  		return true, pod, err
   134  	}
   135  	if errs := validation.ValidatePodCreate(newPod, validation.PodValidationOptions{}); len(errs) > 0 {
   136  		return true, pod, fmt.Errorf("invalid pod: %v", errs)
   137  	}
   138  	v1Pod := &v1.Pod{}
   139  	if err := k8s_api_v1.Convert_core_Pod_To_v1_Pod(newPod, v1Pod, nil); err != nil {
   140  		klog.ErrorS(err, "Pod failed to convert to v1", "pod", klog.KObj(newPod))
   141  		return true, nil, err
   142  	}
   143  
   144  	for _, v := range v1Pod.Spec.Volumes {
   145  		if v.Projected == nil {
   146  			continue
   147  		}
   148  
   149  		for _, s := range v.Projected.Sources {
   150  			if s.ClusterTrustBundle != nil {
   151  				return true, nil, ErrStaticPodTriedToUseClusterTrustBundle
   152  			}
   153  		}
   154  	}
   155  
   156  	return true, v1Pod, nil
   157  }
   158  
   159  func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods v1.PodList, err error) {
   160  	obj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data)
   161  	if err != nil {
   162  		return false, pods, err
   163  	}
   164  
   165  	newPods, ok := obj.(*api.PodList)
   166  	// Check whether the object could be converted to list of pods.
   167  	if !ok {
   168  		err = fmt.Errorf("invalid pods list: %#v", obj)
   169  		return false, pods, err
   170  	}
   171  
   172  	// Apply default values and validate pods.
   173  	for i := range newPods.Items {
   174  		newPod := &newPods.Items[i]
   175  		if newPod.Name == "" {
   176  			return true, pods, fmt.Errorf("invalid pod: name is needed for the pod")
   177  		}
   178  		if err = defaultFn(newPod); err != nil {
   179  			return true, pods, err
   180  		}
   181  		if errs := validation.ValidatePodCreate(newPod, validation.PodValidationOptions{}); len(errs) > 0 {
   182  			err = fmt.Errorf("invalid pod: %v", errs)
   183  			return true, pods, err
   184  		}
   185  	}
   186  	v1Pods := &v1.PodList{}
   187  	if err := k8s_api_v1.Convert_core_PodList_To_v1_PodList(newPods, v1Pods, nil); err != nil {
   188  		return true, pods, err
   189  	}
   190  	return true, *v1Pods, err
   191  }
   192  

View as plain text