123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /*
- Copyright 2016 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package kuberuntime
- import (
- "fmt"
- "net"
- "net/url"
- "sort"
- "k8s.io/api/core/v1"
- kubetypes "k8s.io/apimachinery/pkg/types"
- utilfeature "k8s.io/apiserver/pkg/util/feature"
- runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
- "k8s.io/klog"
- "k8s.io/kubernetes/pkg/features"
- kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
- "k8s.io/kubernetes/pkg/kubelet/types"
- "k8s.io/kubernetes/pkg/kubelet/util/format"
- )
- // createPodSandbox creates a pod sandbox and returns (podSandBoxID, message, error).
- func (m *kubeGenericRuntimeManager) createPodSandbox(pod *v1.Pod, attempt uint32) (string, string, error) {
- podSandboxConfig, err := m.generatePodSandboxConfig(pod, attempt)
- if err != nil {
- message := fmt.Sprintf("GeneratePodSandboxConfig for pod %q failed: %v", format.Pod(pod), err)
- klog.Error(message)
- return "", message, err
- }
- // Create pod logs directory
- err = m.osInterface.MkdirAll(podSandboxConfig.LogDirectory, 0755)
- if err != nil {
- message := fmt.Sprintf("Create pod log directory for pod %q failed: %v", format.Pod(pod), err)
- klog.Errorf(message)
- return "", message, err
- }
- runtimeHandler := ""
- if utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && m.runtimeClassManager != nil {
- runtimeHandler, err = m.runtimeClassManager.LookupRuntimeHandler(pod.Spec.RuntimeClassName)
- if err != nil {
- message := fmt.Sprintf("CreatePodSandbox for pod %q failed: %v", format.Pod(pod), err)
- return "", message, err
- }
- if runtimeHandler != "" {
- klog.V(2).Infof("Running pod %s with RuntimeHandler %q", format.Pod(pod), runtimeHandler)
- }
- }
- podSandBoxID, err := m.runtimeService.RunPodSandbox(podSandboxConfig, runtimeHandler)
- if err != nil {
- message := fmt.Sprintf("CreatePodSandbox for pod %q failed: %v", format.Pod(pod), err)
- klog.Error(message)
- return "", message, err
- }
- return podSandBoxID, "", nil
- }
- // generatePodSandboxConfig generates pod sandbox config from v1.Pod.
- func (m *kubeGenericRuntimeManager) generatePodSandboxConfig(pod *v1.Pod, attempt uint32) (*runtimeapi.PodSandboxConfig, error) {
- // TODO: deprecating podsandbox resource requirements in favor of the pod level cgroup
- // Refer https://github.com/kubernetes/kubernetes/issues/29871
- podUID := string(pod.UID)
- podSandboxConfig := &runtimeapi.PodSandboxConfig{
- Metadata: &runtimeapi.PodSandboxMetadata{
- Name: pod.Name,
- Namespace: pod.Namespace,
- Uid: podUID,
- Attempt: attempt,
- },
- Labels: newPodLabels(pod),
- Annotations: newPodAnnotations(pod),
- }
- dnsConfig, err := m.runtimeHelper.GetPodDNS(pod)
- if err != nil {
- return nil, err
- }
- podSandboxConfig.DnsConfig = dnsConfig
- if !kubecontainer.IsHostNetworkPod(pod) {
- // TODO: Add domain support in new runtime interface
- hostname, _, err := m.runtimeHelper.GeneratePodHostNameAndDomain(pod)
- if err != nil {
- return nil, err
- }
- podSandboxConfig.Hostname = hostname
- }
- logDir := BuildPodLogsDirectory(pod.Namespace, pod.Name, pod.UID)
- podSandboxConfig.LogDirectory = logDir
- portMappings := []*runtimeapi.PortMapping{}
- for _, c := range pod.Spec.Containers {
- containerPortMappings := kubecontainer.MakePortMappings(&c)
- for idx := range containerPortMappings {
- port := containerPortMappings[idx]
- hostPort := int32(port.HostPort)
- containerPort := int32(port.ContainerPort)
- protocol := toRuntimeProtocol(port.Protocol)
- portMappings = append(portMappings, &runtimeapi.PortMapping{
- HostIp: port.HostIP,
- HostPort: hostPort,
- ContainerPort: containerPort,
- Protocol: protocol,
- })
- }
- }
- if len(portMappings) > 0 {
- podSandboxConfig.PortMappings = portMappings
- }
- lc, err := m.generatePodSandboxLinuxConfig(pod)
- if err != nil {
- return nil, err
- }
- podSandboxConfig.Linux = lc
- return podSandboxConfig, nil
- }
- // generatePodSandboxLinuxConfig generates LinuxPodSandboxConfig from v1.Pod.
- func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) (*runtimeapi.LinuxPodSandboxConfig, error) {
- cgroupParent := m.runtimeHelper.GetPodCgroupParent(pod)
- lc := &runtimeapi.LinuxPodSandboxConfig{
- CgroupParent: cgroupParent,
- SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{
- Privileged: kubecontainer.HasPrivilegedContainer(pod),
- SeccompProfilePath: m.getSeccompProfileFromAnnotations(pod.Annotations, ""),
- },
- }
- sysctls := make(map[string]string)
- if utilfeature.DefaultFeatureGate.Enabled(features.Sysctls) {
- if pod.Spec.SecurityContext != nil {
- for _, c := range pod.Spec.SecurityContext.Sysctls {
- sysctls[c.Name] = c.Value
- }
- }
- }
- lc.Sysctls = sysctls
- if pod.Spec.SecurityContext != nil {
- sc := pod.Spec.SecurityContext
- if sc.RunAsUser != nil {
- lc.SecurityContext.RunAsUser = &runtimeapi.Int64Value{Value: int64(*sc.RunAsUser)}
- }
- if sc.RunAsGroup != nil {
- lc.SecurityContext.RunAsGroup = &runtimeapi.Int64Value{Value: int64(*sc.RunAsGroup)}
- }
- lc.SecurityContext.NamespaceOptions = namespacesForPod(pod)
- if sc.FSGroup != nil {
- lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, int64(*sc.FSGroup))
- }
- if groups := m.runtimeHelper.GetExtraSupplementalGroupsForPod(pod); len(groups) > 0 {
- lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, groups...)
- }
- if sc.SupplementalGroups != nil {
- for _, sg := range sc.SupplementalGroups {
- lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, int64(sg))
- }
- }
- if sc.SELinuxOptions != nil {
- lc.SecurityContext.SelinuxOptions = &runtimeapi.SELinuxOption{
- User: sc.SELinuxOptions.User,
- Role: sc.SELinuxOptions.Role,
- Type: sc.SELinuxOptions.Type,
- Level: sc.SELinuxOptions.Level,
- }
- }
- }
- return lc, nil
- }
- // getKubeletSandboxes lists all (or just the running) sandboxes managed by kubelet.
- func (m *kubeGenericRuntimeManager) getKubeletSandboxes(all bool) ([]*runtimeapi.PodSandbox, error) {
- var filter *runtimeapi.PodSandboxFilter
- if !all {
- readyState := runtimeapi.PodSandboxState_SANDBOX_READY
- filter = &runtimeapi.PodSandboxFilter{
- State: &runtimeapi.PodSandboxStateValue{
- State: readyState,
- },
- }
- }
- resp, err := m.runtimeService.ListPodSandbox(filter)
- if err != nil {
- klog.Errorf("ListPodSandbox failed: %v", err)
- return nil, err
- }
- return resp, nil
- }
- // determinePodSandboxIP determines the IP address of the given pod sandbox.
- func (m *kubeGenericRuntimeManager) determinePodSandboxIP(podNamespace, podName string, podSandbox *runtimeapi.PodSandboxStatus) string {
- if podSandbox.Network == nil {
- klog.Warningf("Pod Sandbox status doesn't have network information, cannot report IP")
- return ""
- }
- ip := podSandbox.Network.Ip
- if len(ip) != 0 && net.ParseIP(ip) == nil {
- // ip could be an empty string if runtime is not responsible for the
- // IP (e.g., host networking).
- klog.Warningf("Pod Sandbox reported an unparseable IP %v", ip)
- return ""
- }
- return ip
- }
- // getPodSandboxID gets the sandbox id by podUID and returns ([]sandboxID, error).
- // Param state could be nil in order to get all sandboxes belonging to same pod.
- func (m *kubeGenericRuntimeManager) getSandboxIDByPodUID(podUID kubetypes.UID, state *runtimeapi.PodSandboxState) ([]string, error) {
- filter := &runtimeapi.PodSandboxFilter{
- LabelSelector: map[string]string{types.KubernetesPodUIDLabel: string(podUID)},
- }
- if state != nil {
- filter.State = &runtimeapi.PodSandboxStateValue{
- State: *state,
- }
- }
- sandboxes, err := m.runtimeService.ListPodSandbox(filter)
- if err != nil {
- klog.Errorf("ListPodSandbox with pod UID %q failed: %v", podUID, err)
- return nil, err
- }
- if len(sandboxes) == 0 {
- return nil, nil
- }
- // Sort with newest first.
- sandboxIDs := make([]string, len(sandboxes))
- sort.Sort(podSandboxByCreated(sandboxes))
- for i, s := range sandboxes {
- sandboxIDs[i] = s.Id
- }
- return sandboxIDs, nil
- }
- // GetPortForward gets the endpoint the runtime will serve the port-forward request from.
- func (m *kubeGenericRuntimeManager) GetPortForward(podName, podNamespace string, podUID kubetypes.UID, ports []int32) (*url.URL, error) {
- sandboxIDs, err := m.getSandboxIDByPodUID(podUID, nil)
- if err != nil {
- return nil, fmt.Errorf("failed to find sandboxID for pod %s: %v", format.PodDesc(podName, podNamespace, podUID), err)
- }
- if len(sandboxIDs) == 0 {
- return nil, fmt.Errorf("failed to find sandboxID for pod %s", format.PodDesc(podName, podNamespace, podUID))
- }
- req := &runtimeapi.PortForwardRequest{
- PodSandboxId: sandboxIDs[0],
- Port: ports,
- }
- resp, err := m.runtimeService.PortForward(req)
- if err != nil {
- return nil, err
- }
- return url.Parse(resp.Url)
- }
|