k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/kubelet/kuberuntime/kuberuntime_image.go (about) 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 }