...

Source file src/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_image.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  	"context"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    24  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    25  	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
    26  	"k8s.io/klog/v2"
    27  	credentialprovidersecrets "k8s.io/kubernetes/pkg/credentialprovider/secrets"
    28  	"k8s.io/kubernetes/pkg/features"
    29  	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
    30  	"k8s.io/kubernetes/pkg/util/parsers"
    31  )
    32  
    33  // PullImage pulls an image from the network to local storage using the supplied
    34  // secrets if necessary.
    35  func (m *kubeGenericRuntimeManager) PullImage(ctx context.Context, image kubecontainer.ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) {
    36  	img := image.Image
    37  	repoToPull, _, _, err := parsers.ParseImageName(img)
    38  	if err != nil {
    39  		return "", err
    40  	}
    41  
    42  	keyring, err := credentialprovidersecrets.MakeDockerKeyring(pullSecrets, m.keyring)
    43  	if err != nil {
    44  		return "", err
    45  	}
    46  
    47  	imgSpec := toRuntimeAPIImageSpec(image)
    48  
    49  	creds, withCredentials := keyring.Lookup(repoToPull)
    50  	if !withCredentials {
    51  		klog.V(3).InfoS("Pulling image without credentials", "image", img)
    52  
    53  		imageRef, err := m.imageService.PullImage(ctx, imgSpec, nil, podSandboxConfig)
    54  		if err != nil {
    55  			klog.ErrorS(err, "Failed to pull image", "image", img)
    56  			return "", err
    57  		}
    58  
    59  		return imageRef, nil
    60  	}
    61  
    62  	var pullErrs []error
    63  	for _, currentCreds := range creds {
    64  		auth := &runtimeapi.AuthConfig{
    65  			Username:      currentCreds.Username,
    66  			Password:      currentCreds.Password,
    67  			Auth:          currentCreds.Auth,
    68  			ServerAddress: currentCreds.ServerAddress,
    69  			IdentityToken: currentCreds.IdentityToken,
    70  			RegistryToken: currentCreds.RegistryToken,
    71  		}
    72  
    73  		imageRef, err := m.imageService.PullImage(ctx, imgSpec, auth, podSandboxConfig)
    74  		// If there was no error, return success
    75  		if err == nil {
    76  			return imageRef, nil
    77  		}
    78  
    79  		pullErrs = append(pullErrs, err)
    80  	}
    81  
    82  	return "", utilerrors.NewAggregate(pullErrs)
    83  }
    84  
    85  // GetImageRef gets the ID of the image which has already been in
    86  // the local storage. It returns ("", nil) if the image isn't in the local storage.
    87  func (m *kubeGenericRuntimeManager) GetImageRef(ctx context.Context, image kubecontainer.ImageSpec) (string, error) {
    88  	resp, err := m.imageService.ImageStatus(ctx, toRuntimeAPIImageSpec(image), false)
    89  	if err != nil {
    90  		klog.ErrorS(err, "Failed to get image status", "image", image.Image)
    91  		return "", err
    92  	}
    93  	if resp.Image == nil {
    94  		return "", nil
    95  	}
    96  	return resp.Image.Id, nil
    97  }
    98  
    99  func (m *kubeGenericRuntimeManager) GetImageSize(ctx context.Context, image kubecontainer.ImageSpec) (uint64, error) {
   100  	resp, err := m.imageService.ImageStatus(ctx, toRuntimeAPIImageSpec(image), false)
   101  	if err != nil {
   102  		klog.ErrorS(err, "Failed to get image status", "image", image.Image)
   103  		return 0, err
   104  	}
   105  	if resp.Image == nil {
   106  		return 0, nil
   107  	}
   108  	return resp.Image.Size_, nil
   109  }
   110  
   111  // ListImages gets all images currently on the machine.
   112  func (m *kubeGenericRuntimeManager) ListImages(ctx context.Context) ([]kubecontainer.Image, error) {
   113  	var images []kubecontainer.Image
   114  
   115  	allImages, err := m.imageService.ListImages(ctx, nil)
   116  	if err != nil {
   117  		klog.ErrorS(err, "Failed to list images")
   118  		return nil, err
   119  	}
   120  
   121  	for _, img := range allImages {
   122  		// Container runtimes may choose not to implement changes needed for KEP 4216. If
   123  		// the changes are not implemented by a container runtime, the exisiting behavior
   124  		// of not populating the runtimeHandler CRI field in ImageSpec struct is preserved.
   125  		// Therefore, when RuntimeClassInImageCriAPI feature gate is set, check to see if this
   126  		// field is empty and log a warning message.
   127  		if utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClassInImageCriAPI) {
   128  			if img.Spec == nil || (img.Spec != nil && img.Spec.RuntimeHandler == "") {
   129  				klog.V(2).InfoS("WARNING: RuntimeHandler is empty", "ImageID", img.Id)
   130  			}
   131  		}
   132  
   133  		images = append(images, kubecontainer.Image{
   134  			ID:          img.Id,
   135  			Size:        int64(img.Size_),
   136  			RepoTags:    img.RepoTags,
   137  			RepoDigests: img.RepoDigests,
   138  			Spec:        toKubeContainerImageSpec(img),
   139  			Pinned:      img.Pinned,
   140  		})
   141  	}
   142  
   143  	return images, nil
   144  }
   145  
   146  // RemoveImage removes the specified image.
   147  func (m *kubeGenericRuntimeManager) RemoveImage(ctx context.Context, image kubecontainer.ImageSpec) error {
   148  	err := m.imageService.RemoveImage(ctx, &runtimeapi.ImageSpec{Image: image.Image})
   149  	if err != nil {
   150  		klog.ErrorS(err, "Failed to remove image", "image", image.Image)
   151  		return err
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  // ImageStats returns the statistics of the image.
   158  // Notice that current logic doesn't really work for images which share layers (e.g. docker image),
   159  // this is a known issue, and we'll address this by getting imagefs stats directly from CRI.
   160  // TODO: Get imagefs stats directly from CRI.
   161  func (m *kubeGenericRuntimeManager) ImageStats(ctx context.Context) (*kubecontainer.ImageStats, error) {
   162  	allImages, err := m.imageService.ListImages(ctx, nil)
   163  	if err != nil {
   164  		klog.ErrorS(err, "Failed to list images")
   165  		return nil, err
   166  	}
   167  	stats := &kubecontainer.ImageStats{}
   168  	for _, img := range allImages {
   169  		stats.TotalStorageBytes += img.Size_
   170  	}
   171  	return stats, nil
   172  }
   173  
   174  func (m *kubeGenericRuntimeManager) ImageFsInfo(ctx context.Context) (*runtimeapi.ImageFsInfoResponse, error) {
   175  	allImages, err := m.imageService.ImageFsInfo(ctx)
   176  	if err != nil {
   177  		klog.ErrorS(err, "Failed to get image filesystem")
   178  		return nil, err
   179  	}
   180  	return allImages, nil
   181  }
   182  

View as plain text