Skip to content

Commit 6636b9d

Browse files
joelanfordclaude
andcommitted
feat: replace extractContent emptyDir+initContainers with image volumes
Use Kubernetes image volumes to eliminate disk I/O during catalog pod startup. The catalog image becomes the main container image (providing catalog data via its root filesystem), and the opm binary is provided by mounting the opmImage as an image volume. - Remove init containers and data-copying emptyDir volumes - Remove utilImage from registry reconciler (still used by bundle unpacker) - Simplify correctImages() and imageID() functions - Delete cmd/copy-content/ binary (no longer needed) - Update Dockerfile and .goreleaser.yml build targets Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 15860d3 commit 6636b9d

File tree

11 files changed

+121
-380
lines changed

11 files changed

+121
-380
lines changed

.goreleaser.yml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,23 +74,6 @@ builds:
7474
ldflags:
7575
- -X {{ .Env.PKG }}/pkg/version.GitCommit={{ .FullCommit }}
7676
- -X {{ .Env.PKG }}/pkg/version.OLMVersion={{ .Tag }}
77-
- id: copy-content
78-
main: ./cmd/copy-content
79-
binary: copy-content
80-
goos:
81-
- linux
82-
goarch:
83-
- amd64
84-
- arm64
85-
- ppc64le
86-
- s390x
87-
tags:
88-
- json1
89-
flags:
90-
- -mod=vendor
91-
ldflags:
92-
- -X {{ .Env.PKG }}/pkg/version.GitCommit={{ .FullCommit }}
93-
- -X {{ .Env.PKG }}/pkg/version.OLMVersion={{ .Tag }}
9477
dockers:
9578
- image_templates:
9679
- "{{ .Env.IMAGE_REPO }}:{{ .Tag }}-amd64"

AGENTS.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ operator-lifecycle-manager/
6767
├── cmd/ # Entry point binaries
6868
│ ├── catalog/ # Catalog Operator main
6969
│ ├── olm/ # OLM Operator main
70-
│ ├── package-server/ # Package API server
71-
│ └── copy-content/ # Content copy utility
70+
│ └── package-server/ # Package API server
7271
7372
├── pkg/ # Core implementation
7473
│ ├── api/ # API client and wrappers

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ RUN ["/busybox/ln", "-s", "/busybox/cp", "/bin/cp"]
77
COPY olm /bin/olm
88
COPY catalog /bin/catalog
99
COPY package-server /bin/package-server
10-
COPY copy-content /bin/copy-content
1110
COPY cpb /bin/cpb
1211
EXPOSE 8080
1312
EXPOSE 5443

cmd/copy-content/main.go

Lines changed: 0 additions & 55 deletions
This file was deleted.

pkg/controller/operators/catalog/operator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
221221
op.sources = grpc.NewSourceStore(logger, 10*time.Second, 10*time.Minute, op.syncSourceState)
222222
op.resolverSourceProvider = resolver.SourceProviderFromRegistryClientProvider(op.sources, lister.OperatorsV1alpha1().CatalogSourceLister(), logger)
223223
op.operatorCacheProvider = resolver.NewOperatorCacheProvider(lister, crClient, op.resolverSourceProvider, logger)
224-
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now, ssaClient, workloadUserID, opmImage, utilImage)
224+
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now, ssaClient, workloadUserID, opmImage)
225225
res := resolver.NewOperatorStepResolver(lister, crClient, operatorNamespace, op.operatorCacheProvider, logger)
226226
op.resolver = resolver.NewInstrumentedResolver(res, metrics.RegisterDependencyResolutionSuccess, metrics.RegisterDependencyResolutionFailure)
227227

pkg/controller/operators/catalog/operator_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string,
22792279
return nil, err
22802280
}
22812281
applier := controllerclient.NewFakeApplier(s, "testowner")
2282-
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now, applier, 1001, "", "")
2282+
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now, applier, 1001, "")
22832283
}
22842284

22852285
op.RunInformers(ctx)
@@ -2447,7 +2447,7 @@ func pod(t *testing.T, s v1alpha1.CatalogSource) *corev1.Pod {
24472447
Name: s.GetName(),
24482448
},
24492449
}
2450-
pod, err := reconciler.Pod(&s, "registry-server", "central-opm", "central-util", s.Spec.Image, serviceAccount, s.GetLabels(), s.GetAnnotations(), 5, 10, 1001, v1alpha1.Legacy)
2450+
pod, err := reconciler.Pod(&s, "registry-server", "central-opm", s.Spec.Image, serviceAccount, s.GetLabels(), s.GetAnnotations(), 5, 10, 1001, v1alpha1.Legacy)
24512451
if err != nil {
24522452
t.Fatal(err)
24532453
}

pkg/controller/registry/reconciler/configmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func (s *configMapCatalogSourceDecorator) Service() (*corev1.Service, error) {
113113
}
114114

115115
func (s *configMapCatalogSourceDecorator) Pod(image string, defaultPodSecurityConfig v1alpha1.SecurityConfig) (*corev1.Pod, error) {
116-
pod, err := Pod(s.CatalogSource, "configmap-registry-server", "", "", image, nil, s.Labels(), s.Annotations(), 5, 5, s.runAsUser, defaultPodSecurityConfig)
116+
pod, err := Pod(s.CatalogSource, "configmap-registry-server", "", image, nil, s.Labels(), s.Annotations(), 5, 5, s.runAsUser, defaultPodSecurityConfig)
117117
if err != nil {
118118
return nil, err
119119
}

pkg/controller/registry/reconciler/grpc.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
1414
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
15+
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/image"
1516
hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash"
1617
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
1718
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
@@ -39,7 +40,6 @@ type grpcCatalogSourceDecorator struct {
3940
*v1alpha1.CatalogSource
4041
createPodAsUser int64
4142
opmImage string
42-
utilImage string
4343
}
4444

4545
type UpdateNotReadyErr struct {
@@ -144,7 +144,7 @@ func (s *grpcCatalogSourceDecorator) ServiceAccount() *corev1.ServiceAccount {
144144
}
145145

146146
func (s *grpcCatalogSourceDecorator) Pod(serviceAccount *corev1.ServiceAccount, defaultPodSecurityConfig v1alpha1.SecurityConfig) (*corev1.Pod, error) {
147-
pod, err := Pod(s.CatalogSource, "registry-server", s.opmImage, s.utilImage, s.Spec.Image, serviceAccount, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser, defaultPodSecurityConfig)
147+
pod, err := Pod(s.CatalogSource, "registry-server", s.opmImage, s.Spec.Image, serviceAccount, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser, defaultPodSecurityConfig)
148148
if err != nil {
149149
return nil, err
150150
}
@@ -159,7 +159,6 @@ type GrpcRegistryReconciler struct {
159159
SSAClient *controllerclient.ServerSideApplier
160160
createPodAsUser int64
161161
opmImage string
162-
utilImage string
163162
}
164163

165164
var _ RegistryReconciler = &GrpcRegistryReconciler{}
@@ -262,23 +261,27 @@ func (c *GrpcRegistryReconciler) currentPodsWithCorrectImageAndSpec(logger *logr
262261
}
263262

264263
func correctImages(source grpcCatalogSourceDecorator, pod *corev1.Pod) bool {
264+
if len(pod.Spec.InitContainers) != 0 || len(pod.Spec.Containers) != 1 {
265+
return false
266+
}
267+
if pod.Spec.Containers[0].Image != source.CatalogSource.Spec.Image {
268+
return false
269+
}
265270
if source.CatalogSource.Spec.GrpcPodConfig != nil && source.CatalogSource.Spec.GrpcPodConfig.ExtractContent != nil {
266-
if len(pod.Spec.InitContainers) != 2 {
271+
if len(pod.Spec.Volumes) == 0 {
267272
return false
268273
}
269-
if len(pod.Spec.Containers) != 1 {
270-
return false
271-
}
272-
return pod.Spec.InitContainers[0].Image == source.utilImage &&
273-
pod.Spec.InitContainers[1].Image == source.CatalogSource.Spec.Image &&
274-
pod.Spec.Containers[0].Image == source.opmImage
274+
return pod.Spec.Volumes[0].Name == opmVolumeName &&
275+
pod.Spec.Volumes[0].VolumeSource.Image != nil &&
276+
pod.Spec.Volumes[0].VolumeSource.Image.Reference == source.opmImage &&
277+
pod.Spec.Volumes[0].VolumeSource.Image.PullPolicy == image.InferImagePullPolicy(source.opmImage)
275278
}
276-
return pod.Spec.Containers[0].Image == source.CatalogSource.Spec.Image
279+
return true
277280
}
278281

279282
// EnsureRegistryServer ensures that all components of registry server are up to date.
280283
func (c *GrpcRegistryReconciler) EnsureRegistryServer(logger *logrus.Entry, catalogSource *v1alpha1.CatalogSource) error {
281-
source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage, utilImage: c.utilImage}
284+
source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage}
282285

283286
// if service status is nil, we force create every object to ensure they're created the first time
284287
valid, err := isRegistryServiceStatusValid(&source)
@@ -618,21 +621,16 @@ func isPodDead(pod *corev1.Pod) bool {
618621
return false
619622
}
620623

621-
// imageID returns the ImageID of the primary catalog source container or an empty string if the image ID isn't available yet.
624+
// imageID returns the ImageID of the catalog source container or an empty string if the image ID isn't available yet.
622625
// Note: the pod must be running and the container in a ready status to return a valid ImageID.
623626
func imageID(pod *corev1.Pod) string {
624-
if len(pod.Status.InitContainerStatuses) == 2 && len(pod.Status.ContainerStatuses) == 1 {
625-
// spec.grpcPodConfig.extractContent mode was used for this pod
626-
return pod.Status.InitContainerStatuses[1].ImageID
627-
}
628-
if len(pod.Status.InitContainerStatuses) == 0 && len(pod.Status.ContainerStatuses) == 1 {
629-
// spec.grpcPodConfig.extractContent mode was NOT used for this pod (i.e. we're just running the catalog image directly)
627+
if len(pod.Status.ContainerStatuses) == 1 {
630628
return pod.Status.ContainerStatuses[0].ImageID
631629
}
632-
if len(pod.Status.InitContainerStatuses) == 0 && len(pod.Status.ContainerStatuses) == 0 {
633-
logrus.WithField("CatalogSource", pod.GetName()).Warn("pod status unknown; pod has not yet populated initContainer and container status")
630+
if len(pod.Status.ContainerStatuses) == 0 {
631+
logrus.WithField("CatalogSource", pod.GetName()).Warn("pod status unknown; pod has not yet populated container status")
634632
} else {
635-
logrus.WithField("CatalogSource", pod.GetName()).Warn("pod status unknown; pod contains unexpected initContainer and container configuration")
633+
logrus.WithField("CatalogSource", pod.GetName()).Warn("pod status unknown; pod contains unexpected container configuration")
636634
}
637635
return ""
638636
}
@@ -648,7 +646,7 @@ func (c *GrpcRegistryReconciler) removePods(pods []*corev1.Pod, namespace string
648646

649647
// CheckRegistryServer returns true if the given CatalogSource is considered healthy; false otherwise.
650648
func (c *GrpcRegistryReconciler) CheckRegistryServer(logger *logrus.Entry, catalogSource *v1alpha1.CatalogSource) (bool, error) {
651-
source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage, utilImage: c.utilImage}
649+
source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage}
652650

653651
// The CheckRegistryServer function is called by the CatalogSoruce controller before the registry resources are created,
654652
// returning a IsNotFound error will cause the controller to exit and never create the resources, so we should

pkg/controller/registry/reconciler/grpc_test.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -722,25 +722,12 @@ func TestGetPodImageID(t *testing.T) {
722722
result string
723723
}{
724724
{
725-
description: "default pod has status: return status",
725+
description: "pod has single container status: return imageID",
726726
pod: &corev1.Pod{Status: corev1.PodStatus{ContainerStatuses: []corev1.ContainerStatus{{ImageID: "xyz123"}}}},
727727
result: "xyz123",
728728
},
729729
{
730-
description: "extractConfig pod has status: return status",
731-
pod: &corev1.Pod{Status: corev1.PodStatus{
732-
InitContainerStatuses: []corev1.ContainerStatus{
733-
{ImageID: "xyz123"},
734-
{ImageID: "abc456"},
735-
},
736-
ContainerStatuses: []corev1.ContainerStatus{
737-
{ImageID: "xyz123"},
738-
},
739-
}},
740-
result: "abc456",
741-
},
742-
{
743-
description: "pod has unexpected container config",
730+
description: "pod has unexpected multiple container statuses",
744731
pod: &corev1.Pod{Status: corev1.PodStatus{ContainerStatuses: []corev1.ContainerStatus{
745732
{ImageID: "xyz123"},
746733
{ImageID: "abc456"},

0 commit comments

Comments
 (0)