Skip to content

Commit 6ac7fcc

Browse files
authored
Merge pull request #17144 from rifelpet/warmpool-containerproxy
Normalize the hardcoded images used for warmpool pre-pulling
2 parents cd69582 + 9fe0a2e commit 6ac7fcc

File tree

25 files changed

+132
-173
lines changed

25 files changed

+132
-173
lines changed

pkg/assets/builder.go

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (a *AssetBuilder) RemapManifest(data []byte) ([]byte, error) {
144144
}
145145

146146
// RemapImage normalizes a containers location if a user sets the AssetsLocation ContainerRegistry location.
147-
func (a *AssetBuilder) RemapImage(image string) (string, error) {
147+
func (a *AssetBuilder) RemapImage(image string) string {
148148
asset := &ImageAsset{
149149
DownloadLocation: image,
150150
CanonicalLocation: image,
@@ -179,66 +179,27 @@ func (a *AssetBuilder) RemapImage(image string) (string, error) {
179179
}
180180
}
181181

182-
if a.AssetsLocation != nil && a.AssetsLocation.ContainerProxy != nil {
183-
containerProxy := strings.TrimSuffix(*a.AssetsLocation.ContainerProxy, "/")
184-
normalized := image
185-
186-
// If the image name contains only a single / we need to determine if the image is located on docker-hub or if it's using a convenient URL,
187-
// like registry.k8s.io/<image-name> or registry.k8s.io/<image-name>
188-
// In case of a hub image it should be sufficient to just prepend the proxy url, producing eg docker-proxy.example.com/weaveworks/weave-kube
189-
if strings.Count(normalized, "/") <= 1 && !strings.ContainsAny(strings.Split(normalized, "/")[0], ".:") {
190-
normalized = containerProxy + "/" + normalized
191-
} else {
192-
re := regexp.MustCompile(`^[^/]+`)
193-
normalized = re.ReplaceAllString(normalized, containerProxy)
194-
}
195-
196-
asset.DownloadLocation = normalized
197-
198-
// Run the new image
199-
image = asset.DownloadLocation
200-
}
201-
202-
if a.AssetsLocation != nil && a.AssetsLocation.ContainerRegistry != nil {
203-
registryMirror := *a.AssetsLocation.ContainerRegistry
204-
normalized := image
205-
206-
// Remove the 'standard' kubernetes image prefixes, just for sanity
207-
normalized = strings.TrimPrefix(normalized, "registry.k8s.io/")
208-
209-
// When assembling the cluster spec, kops may call the option more then once until the config converges
210-
// This means that this function may me called more than once on the same image
211-
// It this is pass is the second one, the image will already have been normalized with the containerRegistry settings
212-
// If this is the case, passing though the process again will re-prepend the container registry again
213-
// and again, causing the spec to never converge and the config build to fail.
214-
if !strings.HasPrefix(normalized, registryMirror+"/") {
215-
// We can't nest arbitrarily
216-
// Some risk of collisions, but also -- and __ in the names appear to be blocked by docker hub
217-
normalized = strings.Replace(normalized, "/", "-", -1)
218-
asset.DownloadLocation = registryMirror + "/" + normalized
219-
}
220-
221-
// Run the new image
222-
image = asset.DownloadLocation
223-
}
182+
normalized := NormalizeImage(a, image)
183+
image = normalized
184+
asset.DownloadLocation = normalized
224185

225186
a.ImageAssets = append(a.ImageAssets, asset)
226187

227188
if !featureflag.ImageDigest.Enabled() || os.Getenv("KOPS_BASE_URL") != "" {
228-
return image, nil
189+
return image
229190
}
230191

231192
if strings.Contains(image, "@") {
232-
return image, nil
193+
return image
233194
}
234195

235196
digest, err := crane.Digest(image, crane.WithAuthFromKeychain(authn.DefaultKeychain))
236197
if err != nil {
237198
klog.Warningf("failed to digest image %q: %s", image, err)
238-
return image, nil
199+
return image
239200
}
240201

241-
return image + "@" + digest, nil
202+
return image + "@" + digest
242203
}
243204

244205
// RemapFile returns a remapped URL for the file, if AssetsLocation is defined.
@@ -378,3 +339,46 @@ func (a *AssetBuilder) remapURL(canonicalURL *url.URL) (*url.URL, error) {
378339

379340
return fileRepo, nil
380341
}
342+
343+
func NormalizeImage(a *AssetBuilder, image string) string {
344+
if a.AssetsLocation != nil && a.AssetsLocation.ContainerProxy != nil {
345+
containerProxy := strings.TrimSuffix(*a.AssetsLocation.ContainerProxy, "/")
346+
normalized := image
347+
348+
// If the image name contains only a single / we need to determine if the image is located on docker-hub or if it's using a convenient URL,
349+
// like registry.k8s.io/<image-name> or registry.k8s.io/<image-name>
350+
// In case of a hub image it should be sufficient to just prepend the proxy url, producing eg docker-proxy.example.com/weaveworks/weave-kube
351+
if strings.Count(normalized, "/") <= 1 && !strings.ContainsAny(strings.Split(normalized, "/")[0], ".:") {
352+
normalized = containerProxy + "/" + normalized
353+
} else {
354+
re := regexp.MustCompile(`^[^/]+`)
355+
normalized = re.ReplaceAllString(normalized, containerProxy)
356+
}
357+
358+
// Run the new image
359+
image = normalized
360+
}
361+
362+
if a.AssetsLocation != nil && a.AssetsLocation.ContainerRegistry != nil {
363+
registryMirror := *a.AssetsLocation.ContainerRegistry
364+
normalized := image
365+
366+
// Remove the 'standard' kubernetes image prefixes, just for sanity
367+
normalized = strings.TrimPrefix(normalized, "registry.k8s.io/")
368+
369+
// When assembling the cluster spec, kops may call the option more then once until the config converges
370+
// This means that this function may me called more than once on the same image
371+
// It this is pass is the second one, the image will already have been normalized with the containerRegistry settings
372+
// If this is the case, passing though the process again will re-prepend the container registry again
373+
// and again, causing the spec to never converge and the config build to fail.
374+
if !strings.HasPrefix(normalized, registryMirror+"/") {
375+
// We can't nest arbitrarily
376+
// Some risk of collisions, but also -- and __ in the names appear to be blocked by docker hub
377+
normalized = strings.Replace(normalized, "/", "-", -1)
378+
normalized = registryMirror + "/" + normalized
379+
}
380+
image = normalized
381+
}
382+
// Run the new image
383+
return image
384+
}

pkg/assets/builder_test.go

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ func TestValidate_RemapImage_ContainerProxy_AppliesToDockerHub(t *testing.T) {
4242

4343
builder.AssetsLocation.ContainerProxy = &proxyURL
4444

45-
remapped, err := builder.RemapImage(image)
46-
if err != nil {
47-
t.Error("Error remapping image", err)
48-
}
49-
45+
remapped := builder.RemapImage(image)
5046
if remapped != expected {
5147
t.Errorf("Error remapping image (Expecting: %s, got %s)", expected, remapped)
5248
}
@@ -61,11 +57,7 @@ func TestValidate_RemapImage_ContainerProxy_AppliesToSimplifiedDockerHub(t *test
6157

6258
builder.AssetsLocation.ContainerProxy = &proxyURL
6359

64-
remapped, err := builder.RemapImage(image)
65-
if err != nil {
66-
t.Error("Error remapping image", err)
67-
}
68-
60+
remapped := builder.RemapImage(image)
6961
if remapped != expected {
7062
t.Errorf("Error remapping image (Expecting: %s, got %s)", expected, remapped)
7163
}
@@ -80,11 +72,7 @@ func TestValidate_RemapImage_ContainerProxy_AppliesToSimplifiedKubernetesURL(t *
8072

8173
builder.AssetsLocation.ContainerProxy = &proxyURL
8274

83-
remapped, err := builder.RemapImage(image)
84-
if err != nil {
85-
t.Error("Error remapping image", err)
86-
}
87-
75+
remapped := builder.RemapImage(image)
8876
if remapped != expected {
8977
t.Errorf("Error remapping image (Expecting: %s, got %s)", expected, remapped)
9078
}
@@ -99,11 +87,7 @@ func TestValidate_RemapImage_ContainerProxy_AppliesToLegacyKubernetesURL(t *test
9987

10088
builder.AssetsLocation.ContainerProxy = &proxyURL
10189

102-
remapped, err := builder.RemapImage(image)
103-
if err != nil {
104-
t.Error("Error remapping image", err)
105-
}
106-
90+
remapped := builder.RemapImage(image)
10791
if remapped != expected {
10892
t.Errorf("Error remapping image (Expecting: %s, got %s)", expected, remapped)
10993
}
@@ -118,11 +102,7 @@ func TestValidate_RemapImage_ContainerProxy_AppliesToImagesWithTags(t *testing.T
118102

119103
builder.AssetsLocation.ContainerProxy = &proxyURL
120104

121-
remapped, err := builder.RemapImage(image)
122-
if err != nil {
123-
t.Error("Error remapping image", err)
124-
}
125-
105+
remapped := builder.RemapImage(image)
126106
if remapped != expected {
127107
t.Errorf("Error remapping image (Expecting: %s, got %s)", expected, remapped)
128108
}
@@ -140,11 +120,7 @@ func TestValidate_RemapImage_ContainerRegistry_MappingMultipleTimesConverges(t *
140120
remapped := image
141121
iterations := make([]map[int]int, 2)
142122
for i := range iterations {
143-
remapped, err := builder.RemapImage(remapped)
144-
if err != nil {
145-
t.Errorf("Error remapping image (iteration %d): %s", i, err)
146-
}
147-
123+
remapped := builder.RemapImage(remapped)
148124
if remapped != expected {
149125
t.Errorf("Error remapping image (Expecting: %s, got %s, iteration: %d)", expected, remapped, i)
150126
}

pkg/kubemanifest/images.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ limitations under the License.
1717
package kubemanifest
1818

1919
import (
20-
"fmt"
2120
"strings"
2221

2322
"k8s.io/klog/v2"
2423
)
2524

26-
type ImageRemapFunction func(image string) (string, error)
25+
type ImageRemapFunction func(image string) string
2726

2827
func (m *Object) RemapImages(mapper ImageRemapFunction) error {
2928
visitor := &imageRemapVisitor{
@@ -57,10 +56,7 @@ func (m *imageRemapVisitor) VisitString(path []string, v string, mutator func(st
5756

5857
image := v
5958
klog.V(4).Infof("Consider image for re-mapping: %q", image)
60-
remapped, err := m.mapper(v)
61-
if err != nil {
62-
return fmt.Errorf("error remapping image %q: %v", image, err)
63-
}
59+
remapped := m.mapper(v)
6460
if remapped != image {
6561
mutator(remapped)
6662
}

pkg/model/components/context.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,7 @@ func Image(component string, clusterSpec *kops.ClusterSpec, assetsBuilder *asset
150150
if !kopsmodel.IsBaseURL(clusterSpec.KubernetesVersion) {
151151
image := "registry.k8s.io/" + imageName + ":" + "v" + kubernetesVersion.String()
152152

153-
image, err := assetsBuilder.RemapImage(image)
154-
if err != nil {
155-
return "", fmt.Errorf("unable to remap container %q: %v", image, err)
156-
}
157-
return image, nil
153+
return assetsBuilder.RemapImage(image), nil
158154
}
159155

160156
// The simple name is valid when pulling. But if we

pkg/model/components/etcdmanager/model.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,7 @@ func (b *EtcdManagerBuilder) buildPod(etcdCluster kops.EtcdClusterSpec, instance
314314
// Remap image via AssetBuilder
315315
for i := range pod.Spec.InitContainers {
316316
initContainer := &pod.Spec.InitContainers[i]
317-
remapped, err := b.AssetBuilder.RemapImage(initContainer.Image)
318-
if err != nil {
319-
return nil, fmt.Errorf("unable to remap init container image %q: %w", container.Image, err)
320-
}
321-
initContainer.Image = remapped
317+
initContainer.Image = b.AssetBuilder.RemapImage(initContainer.Image)
322318
}
323319
}
324320

@@ -334,11 +330,7 @@ func (b *EtcdManagerBuilder) buildPod(etcdCluster kops.EtcdClusterSpec, instance
334330
}
335331

336332
// Remap image via AssetBuilder
337-
remapped, err := b.AssetBuilder.RemapImage(container.Image)
338-
if err != nil {
339-
return nil, fmt.Errorf("unable to remap container image %q: %w", container.Image, err)
340-
}
341-
container.Image = remapped
333+
container.Image = b.AssetBuilder.RemapImage(container.Image)
342334
}
343335

344336
var clientHost string

pkg/model/components/kubeapiserver/model.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,7 @@ func (b *KubeApiserverBuilder) buildHealthcheckSidecar() (*corev1.Pod, error) {
138138
}
139139

140140
// Remap image via AssetBuilder
141-
{
142-
remapped, err := b.AssetBuilder.RemapImage(container.Image)
143-
if err != nil {
144-
return nil, fmt.Errorf("unable to remap container image %q: %v", container.Image, err)
145-
}
146-
container.Image = remapped
147-
}
141+
container.Image = b.AssetBuilder.RemapImage(container.Image)
148142

149143
return pod, nil
150144
}

pkg/model/components/kubelet.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,7 @@ func (b *KubeletOptionsBuilder) configureKubelet(cluster *kops.Cluster, kubelet
166166
// Prevent image GC from pruning the pause image
167167
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2040-kubelet-cri#pinned-images
168168
image := "registry.k8s.io/pause:3.9"
169-
var err error
170-
if image, err = b.AssetBuilder.RemapImage(image); err != nil {
171-
return err
172-
}
173-
kubelet.PodInfraContainerImage = image
169+
kubelet.PodInfraContainerImage = b.AssetBuilder.RemapImage(image)
174170

175171
if kubelet.FeatureGates == nil {
176172
kubelet.FeatureGates = make(map[string]string)

pkg/nodemodel/nodeupconfigbuilder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,8 @@ func (n *nodeUpConfigBuilder) buildWarmPoolImages(ig *kops.InstanceGroup) []stri
509509
if assetBuilder != nil {
510510
for _, image := range assetBuilder.ImageAssets {
511511
for _, prefix := range desiredImagePrefixes {
512-
if strings.HasPrefix(image.DownloadLocation, prefix) {
512+
remappedPrefix := assets.NormalizeImage(assetBuilder, prefix)
513+
if strings.HasPrefix(image.DownloadLocation, remappedPrefix) {
513514
images[image.DownloadLocation] = true
514515
}
515516
}

tests/integration/update_cluster/minimal-warmpool/data/aws_launch_template_master-us-test-1a.masters.minimal-warmpool.example.com_user_data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ ClusterName: minimal-warmpool.example.com
130130
ConfigBase: memfs://clusters.example.com/minimal-warmpool.example.com
131131
InstanceGroupName: master-us-test-1a
132132
InstanceGroupRole: ControlPlane
133-
NodeupConfigHash: BGYFM1S3GrCIH6JqycbfBr9wcltsONEgcz10QbL/9DE=
133+
NodeupConfigHash: MVBHdgdOuzS5NjzLCOVaRI+r8Yycu79zVfQIUF7qGc0=
134134
135135
__EOF_KUBE_ENV
136136

tests/integration/update_cluster/minimal-warmpool/data/aws_launch_template_nodes.minimal-warmpool.example.com_user_data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ ConfigServer:
153153
- https://kops-controller.internal.minimal-warmpool.example.com:3988/
154154
InstanceGroupName: nodes
155155
InstanceGroupRole: Node
156-
NodeupConfigHash: qx6ZYYfv4IWM31VjEaj+OnvW1dLilS7uvTY9PVeLP0c=
156+
NodeupConfigHash: LyRFWE+TmVjqI8Y5S+8LBIcnd15CBZ0EyvXGvEBRZcY=
157157
158158
__EOF_KUBE_ENV
159159

0 commit comments

Comments
 (0)