深入分析kubelet(9)—— 根据resp注入pod信息

之前分析过kubelet与device plugin的交互,那么返回的resp kubelet是如何使用的呢?

猜想:
CRI在需要生成container运行参数的时候,调用某个方法,该方法会根据spec以及device plugin response返回opt,这样就实现了device plugin response注入到container。

kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1/api.pb.go

type ContainerAllocateResponse struct {
   // List of environment variable to be set in the container to access one of more devices.
   Envs map[string]string `protobuf:"bytes,1,rep,name=envs" json:"envs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
   // Mounts for the container.
   Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts" json:"mounts,omitempty"`
   // Devices for the container.
   Devices []*DeviceSpec `protobuf:"bytes,3,rep,name=devices" json:"devices,omitempty"`
   // Container annotations to pass to the container runtime
   Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}

kubernetes/pkg/kubelet/cm/devicemanager/pod_devices.go

// Returns combined container runtime settings to consume the container's allocated devices.
func (pdev podDevices) deviceRunContainerOptions(podUID, contName string) *DeviceRunContainerOptions {
   containers, exists := pdev[podUID]
   resources, exists := containers[contName]

   opts := &DeviceRunContainerOptions{}
   // Maps to detect duplicate settings.
   devsMap := make(map[string]string)
   mountsMap := make(map[string]string)
   envsMap := make(map[string]string)
   annotationsMap := make(map[string]string)
   // Loops through AllocationResponses of all cached device resources.
   for _, devices := range resources {
      resp := devices.allocResp
      // Each Allocate response has the following artifacts.
      // Environment variables
      // Mount points
      // Device files
      // Container annotations
      // These artifacts are per resource per container.
      // Updates RunContainerOptions.Envs.
      for k, v := range resp.Envs {
         envsMap[k] = v
         opts.Envs = append(opts.Envs, kubecontainer.EnvVar{Name: k, Value: v})
      }

      // Updates RunContainerOptions.Devices.
      for _, dev := range resp.Devices {
         devsMap[dev.ContainerPath] = dev.HostPath
         opts.Devices = append(opts.Devices, kubecontainer.DeviceInfo{
            PathOnHost:      dev.HostPath,
            PathInContainer: dev.ContainerPath,
            Permissions:     dev.Permissions,
         })
      }

      // Updates RunContainerOptions.Mounts.
      for _, mount := range resp.Mounts {
         mountsMap[mount.ContainerPath] = mount.HostPath
         opts.Mounts = append(opts.Mounts, kubecontainer.Mount{
            Name:          mount.ContainerPath,
            ContainerPath: mount.ContainerPath,
            HostPath:      mount.HostPath,
            ReadOnly:      mount.ReadOnly,
            // TODO: This may need to be part of Device plugin API.
            SELinuxRelabel: false,
         })
      }

      // Updates for Annotations
      for k, v := range resp.Annotations {
         annotationsMap[k] = v
         opts.Annotations = append(opts.Annotations, kubecontainer.Annotation{Name: k, Value: v})
      }
   }
   return opts
}

根据resp.Annotations反过来找到deviceRunContainerOptions方法,这里其实很明确了,会将resp所有的内容都返回给opt

kubernetes/pkg/kubelet/cm/devicemanager/manager.go

// GetDeviceRunContainerOptions checks whether we have cached containerDevices
// for the passed-in  and returns its DeviceRunContainerOptions
// for the found one. An empty struct is returned in case no cached state is found.
func (m *ManagerImpl) GetDeviceRunContainerOptions(pod *v1.Pod, container *v1.Container) (*DeviceRunContainerOptions, error) {

   return m.podDevices.deviceRunContainerOptions(string(pod.UID), container.Name), nil
}

kubernetes/pkg/kubelet/cm/container_manager_linux.go

// TODO: move the GetResources logic to PodContainerManager.
func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Container) (*kubecontainer.RunContainerOptions, error) {
   opts := &kubecontainer.RunContainerOptions{}
   // Allocate should already be called during predicateAdmitHandler.Admit(),
   // just try to fetch device runtime information from cached state here
   devOpts, err := cm.deviceManager.GetDeviceRunContainerOptions(pod, container)

   opts.Devices = append(opts.Devices, devOpts.Devices...)
   opts.Mounts = append(opts.Mounts, devOpts.Mounts...)
   opts.Envs = append(opts.Envs, devOpts.Envs...)
   opts.Annotations = append(opts.Annotations, devOpts.Annotations...)
   return opts, nil
}

kubernetes/pkg/kubelet/kubelet_pods.go

// GenerateRunContainerOptions generates the RunContainerOptions, which can be used by
// the container runtime to set parameters for launching a container.
func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Container, podIP string) (*kubecontainer.RunContainerOptions, func(), error) {
   opts, err := kl.containerManager.GetResources(pod, container)
   if err != nil {
      return nil, nil, err
   }

   return opts, cleanupAction, nil
}

这里就真相了,符合猜想,CRI根据resp生成的opt创建container

你可能感兴趣的:(深入分析kubelet(9)—— 根据resp注入pod信息)