From 31cbc8294370db0f9a5244c48fdc8a24a14b7d76 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 25 Mar 2021 17:33:01 -0700 Subject: [PATCH] This commit adds `--ca-secret-name` so users attempting to run bundles hosted by a registry using a custom CA can configure the registry Pod's `opm registry add` command with the root cert file. internal/olm/operator/registry: rename `--secret-name` to `--pull-secret-name` to disambiguate new flag docs/: consolidate private/custom CA registry configuration details into an olm-integration doc Signed-off-by: Eric Stroczynski --- .../fragments/ca-secret-name-run-bundle.yaml | 5 ++ .../fragments/run-bundle-with-secret.yaml | 2 +- .../operator/registry/index/registry_pod.go | 66 +++++++++++++------ .../registry/index/registry_pod_test.go | 36 ++++++---- internal/olm/operator/registry/index_image.go | 18 +++-- .../building-operators/ansible/migration.md | 6 +- .../building-operators/ansible/quickstart.md | 13 ++-- .../building-operators/ansible/tutorial.md | 13 ++-- .../building-operators/golang/migration.md | 5 +- .../building-operators/golang/quickstart.md | 13 ++-- .../building-operators/golang/tutorial.md | 13 ++-- .../docs/building-operators/helm/migration.md | 5 +- .../building-operators/helm/quickstart.md | 13 ++-- .../docs/building-operators/helm/tutorial.md | 12 ++-- .../cli/operator-sdk_run_bundle-upgrade.md | 13 ++-- .../en/docs/cli/operator-sdk_run_bundle.md | 3 +- .../en/docs/olm-integration/cli-overview.md | 58 ++++++++++++++-- .../docs/olm-integration/quickstart-bundle.md | 11 +--- .../olm-integration/testing-deployment.md | 9 +-- .../content/en/docs/overview/cheat-sheet.md | 2 +- 20 files changed, 183 insertions(+), 133 deletions(-) create mode 100644 changelog/fragments/ca-secret-name-run-bundle.yaml diff --git a/changelog/fragments/ca-secret-name-run-bundle.yaml b/changelog/fragments/ca-secret-name-run-bundle.yaml new file mode 100644 index 00000000000..222abf840a5 --- /dev/null +++ b/changelog/fragments/ca-secret-name-run-bundle.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure + the registry Pod with an in-cluster certificate Secret to use TLS with a private registry. + kind: addition diff --git a/changelog/fragments/run-bundle-with-secret.yaml b/changelog/fragments/run-bundle-with-secret.yaml index ffe121b2685..9ecb4f26197 100644 --- a/changelog/fragments/run-bundle-with-secret.yaml +++ b/changelog/fragments/run-bundle-with-secret.yaml @@ -4,7 +4,7 @@ entries: registry objects to a non-default service account. kind: addition - description: > - Added `--secret-name` to `run bundle` and `run bundle-upgrade` to configure + Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster docker config Secret to pull bundle images from private registries. kind: addition diff --git a/internal/olm/operator/registry/index/registry_pod.go b/internal/olm/operator/registry/index/registry_pod.go index af39e6f2e2f..5345aadcdf8 100644 --- a/internal/olm/operator/registry/index/registry_pod.go +++ b/internal/olm/operator/registry/index/registry_pod.go @@ -72,6 +72,11 @@ type RegistryPod struct { // can pull bundle images from a private registry. SecretName string + // SecretName holds the name of a secret for a CA cert file containing root certificates. + // This file is transiently added to the registry Pod's cert pool via `opm registry add --ca-file`. + // The secret's key for this file must be "cert.pem". + CASecretName string + // pod represents a kubernetes *corev1.pod that will be created on a cluster using an index image pod *corev1.Pod @@ -113,11 +118,11 @@ func (rp *RegistryPod) Create(ctx context.Context, cfg *operator.Configuration, // make catalog source the owner of registry pod object if err := controllerutil.SetOwnerReference(cs, rp.pod, rp.cfg.Scheme); err != nil { - return nil, fmt.Errorf("set registry pod owner reference: %v", err) + return nil, fmt.Errorf("error setting owner reference: %w", err) } if err := rp.cfg.Client.Create(ctx, rp.pod); err != nil { - return nil, fmt.Errorf("create registry pod: %v", err) + return nil, fmt.Errorf("error creating pod: %w", err) } // get registry pod key @@ -225,37 +230,58 @@ func (rp *RegistryPod) podForBundleRegistry() (*corev1.Pod, error) { } addImagePullSecret(rp.pod, rp.SecretName) + addCertSecret(rp.pod, rp.CASecretName) return rp.pod, nil } -// addImagePullSecret creates and mounts an image pull secret volume -// for a docker config secret "secretName" in each container in pod. +// addImagePullSecret creates a docker config volume for secretName +// and a volumeMount for that secret in each container in pod. func addImagePullSecret(pod *corev1.Pod, secretName string) { if secretName == "" { return } - pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{ + // Require a non-legacy docker config secret. + volume := makeSecretVolume(secretName, corev1.KeyToPath{Key: ".dockerconfigjson", Path: ".docker/config.json"}) + pod.Spec.Volumes = append(pod.Spec.Volumes, volume) + + addVolumeMountForSecret(pod, volume.Name, "/root") +} + +// addCertSecret creates and mounts a volume containing a CA root certificate +// to pass to `opm registry add`. +func addCertSecret(pod *corev1.Pod, secretName string) { + if secretName == "" { + return + } + + // Ensure the secret contains a key "cert.pem". + volume := makeSecretVolume(secretName, corev1.KeyToPath{Key: "cert.pem", Path: "cert.pem"}) + pod.Spec.Volumes = append(pod.Spec.Volumes, volume) + + addVolumeMountForSecret(pod, volume.Name, "/certs") +} + +func makeSecretVolume(secretName string, items ...corev1.KeyToPath) corev1.Volume { + return corev1.Volume{ Name: secretName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ SecretName: secretName, DefaultMode: newInt32(0400), Optional: newBool(false), - Items: []corev1.KeyToPath{ - // Require a non-legacy docker config secret. - {Key: ".dockerconfigjson", Path: ".docker/config.json"}, - }, + Items: items, }, }, - }) + } +} +func addVolumeMountForSecret(pod *corev1.Pod, secretName, mountPath string) { volumeMount := corev1.VolumeMount{ - Name: secretName, - ReadOnly: true, - // Mount in $HOME. - MountPath: "/root", + Name: secretName, + ReadOnly: true, + MountPath: mountPath, } for i := range pod.Spec.Containers { pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, volumeMount) @@ -274,9 +300,9 @@ func newBool(b bool) *bool { return bp } -const containerCommand = `/bin/mkdir -p {{ dirname .DBPath }} && \ +const cmdTemplate = `/bin/mkdir -p {{ dirname .DBPath }} && \ {{- range $i, $item := .BundleItems }} -/bin/opm registry add -d {{ $.DBPath }} -b {{ $item.ImageTag }} --mode={{ $item.AddMode }} && \ +/bin/opm registry add -d {{ $.DBPath }} -b {{ $item.ImageTag }} --mode={{ $item.AddMode }}{{ if $.CASecretName }} --ca-file=/certs/cert.pem{{ end }} && \ {{- end }} /bin/opm registry serve -d {{ .DBPath }} -p {{ .GRPCPort }} ` @@ -291,13 +317,13 @@ func (rp *RegistryPod) getContainerCmd() (string, error) { } // add the custom dirname template function to the - // template's FuncMap and parse the containerCommand - tmp := template.Must(template.New("cmd").Funcs(funcMap).Parse(containerCommand)) + // template's FuncMap and parse the cmdTemplate + t := template.Must(template.New("cmd").Funcs(funcMap).Parse(cmdTemplate)) - // execute the command by applying the parsed tmp to command + // execute the command by applying the parsed t to command // and write command output to out out := &bytes.Buffer{} - if err := tmp.Execute(out, rp); err != nil { + if err := t.Execute(out, rp); err != nil { return "", fmt.Errorf("parse container command: %w", err) } diff --git a/internal/olm/operator/registry/index/registry_pod_test.go b/internal/olm/operator/registry/index/registry_pod_test.go index 1c0a61d416a..836936a509e 100644 --- a/internal/olm/operator/registry/index/registry_pod_test.go +++ b/internal/olm/operator/registry/index/registry_pod_test.go @@ -45,10 +45,10 @@ func TestCreateRegistryPod(t *testing.T) { var _ = Describe("RegistryPod", func() { - var defaultBundleItem = BundleItem{ + var defaultBundleItems = []BundleItem{{ ImageTag: "quay.io/example/example-operator-bundle:0.2.0", AddMode: SemverBundleAddMode, - } + }} Describe("creating registry pod", func() { @@ -67,7 +67,7 @@ var _ = Describe("RegistryPod", func() { Namespace: "test-default", } rp = &RegistryPod{ - BundleItems: []BundleItem{defaultBundleItem}, + BundleItems: defaultBundleItems, IndexImage: testIndexImageTag, } By("initializing the RegistryPod") @@ -94,21 +94,27 @@ var _ = Describe("RegistryPod", func() { It("should return a valid container command for one image", func() { output, err := rp.getContainerCmd() Expect(err).To(BeNil()) - Expect(output).Should(Equal(containerCommandFor(defaultDBPath, []BundleItem{defaultBundleItem}))) + Expect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, false))) + }) + + It("should return a container command with --ca-file", func() { + rp.CASecretName = "foo-secret" + output, err := rp.getContainerCmd() + Expect(err).To(BeNil()) + Expect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, true))) }) It("should return a valid container command for three images", func() { - bundleItems := []BundleItem{ - defaultBundleItem, - { + bundleItems := append(defaultBundleItems, + BundleItem{ ImageTag: "quay.io/example/example-operator-bundle:0.3.0", AddMode: ReplacesBundleAddMode, }, - { + BundleItem{ ImageTag: "quay.io/example/example-operator-bundle:1.0.1", AddMode: SemverBundleAddMode, }, - } + ) rp2 := RegistryPod{ DBPath: defaultDBPath, GRPCPort: defaultGRPCPort, @@ -116,7 +122,7 @@ var _ = Describe("RegistryPod", func() { } output, err := rp2.getContainerCmd() Expect(err).To(BeNil()) - Expect(output).Should(Equal(containerCommandFor(defaultDBPath, bundleItems))) + Expect(output).Should(Equal(containerCommandFor(defaultDBPath, bundleItems, false))) }) It("check pod status should return successfully when pod check is true", func() { @@ -188,7 +194,7 @@ var _ = Describe("RegistryPod", func() { It("checkPodStatus should return error when pod check is false and context is done", func() { rp := &RegistryPod{ - BundleItems: []BundleItem{defaultBundleItem}, + BundleItems: defaultBundleItems, IndexImage: testIndexImageTag, } Expect(rp.init(cfg)).To(Succeed()) @@ -211,10 +217,14 @@ var _ = Describe("RegistryPod", func() { }) // containerCommandFor returns the expected container command for a db path and set of bundle items. -func containerCommandFor(dbPath string, items []BundleItem) string { +func containerCommandFor(dbPath string, items []BundleItem, hasCA bool) string { + var caFlag string + if hasCA { + caFlag = " --ca-file=/certs/cert.pem" + } additions := &strings.Builder{} for _, item := range items { - additions.WriteString(fmt.Sprintf("/bin/opm registry add -d %s -b %s --mode=%s && \\\n", dbPath, item.ImageTag, item.AddMode)) + additions.WriteString(fmt.Sprintf("/bin/opm registry add -d %s -b %s --mode=%s%s && \\\n", dbPath, item.ImageTag, item.AddMode, caFlag)) } return fmt.Sprintf("/bin/mkdir -p /database && \\\n%s/bin/opm registry serve -d /database/index.db -p 50051\n", additions.String()) } diff --git a/internal/olm/operator/registry/index_image.go b/internal/olm/operator/registry/index_image.go index 2d842b86657..a009c3babc7 100644 --- a/internal/olm/operator/registry/index_image.go +++ b/internal/olm/operator/registry/index_image.go @@ -64,6 +64,7 @@ type IndexImageCatalogCreator struct { BundleImage string BundleAddMode index.BundleAddMode SecretName string + CASecretName string cfg *operator.Configuration } @@ -78,10 +79,14 @@ func NewIndexImageCatalogCreator(cfg *operator.Configuration) *IndexImageCatalog } func (c *IndexImageCatalogCreator) BindFlags(fs *pflag.FlagSet) { - fs.StringVar(&c.SecretName, "secret-name", "", + fs.StringVar(&c.SecretName, "pull-secret-name", "", "Name of image pull secret (\"type: kubernetes.io/dockerconfigjson\") required "+ "to pull bundle images. This secret *must* be both in the namespace and an "+ "imagePullSecret of the service account that this command is configured to run in") + fs.StringVar(&c.CASecretName, "ca-secret-name", "", + "Name of a generic secret containing a PEM root certificate file required to pull bundle images. "+ + "This secret *must* be in the namespace that this command is configured to run in, "+ + "and the file *must* be encoded under the key \"cert.pem\"") } func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) { @@ -153,7 +158,7 @@ func (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha if prevRegistryPodName != "" { if err = c.deleteRegistryPod(ctx, prevRegistryPodName); err != nil { - return fmt.Errorf("error cleaning up previous registry pod: %v", err) + return fmt.Errorf("error cleaning up previous registry: %v", err) } } @@ -182,16 +187,17 @@ func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, c } // Initialize and create registry pod registryPod := index.RegistryPod{ - BundleItems: items, - IndexImage: c.IndexImage, - SecretName: c.SecretName, + BundleItems: items, + IndexImage: c.IndexImage, + SecretName: c.SecretName, + CASecretName: c.CASecretName, } if registryPod.DBPath, err = c.getDBPath(ctx); err != nil { return fmt.Errorf("get database path: %v", err) } pod, err := registryPod.Create(ctx, c.cfg, cs) if err != nil { - return fmt.Errorf("error creating registry pod: %v", err) + return err } // JSON marshal injected bundles diff --git a/website/content/en/docs/building-operators/ansible/migration.md b/website/content/en/docs/building-operators/ansible/migration.md index d0da2c3ab8e..cce3fe712e6 100644 --- a/website/content/en/docs/building-operators/ansible/migration.md +++ b/website/content/en/docs/building-operators/ansible/migration.md @@ -49,8 +49,7 @@ The easy migration path is to initialize a new project, re-recreate APIs, then c [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ### Creating a new project @@ -297,7 +296,7 @@ kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached- For further steps regarding the deployment of the operator, creation of custom resources, and cleaning up of resources, see the [tutorial][tutorial-deploy]. [install-guide]: /docs/building-operators/ansible/installation -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [kustomize]: https://github.com/kubernetes-sigs/kustomize [kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics @@ -306,4 +305,3 @@ For further steps regarding the deployment of the operator, creation of custom r [testing-guide]: /docs/building-operators/ansible/testing-guide [migration-doc]: /docs/upgrading-sdk-version/ [tutorial-deploy]: /docs/building-operators/ansible/tutorial/#run-the-operator - diff --git a/website/content/en/docs/building-operators/ansible/quickstart.md b/website/content/en/docs/building-operators/ansible/quickstart.md index 478d8cf8643..9d762a85fe2 100644 --- a/website/content/en/docs/building-operators/ansible/quickstart.md +++ b/website/content/en/docs/building-operators/ansible/quickstart.md @@ -15,8 +15,7 @@ This guide walks through an example of building a simple memcached-operator powe [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Steps @@ -56,14 +55,10 @@ This guide walks through an example of building a simple memcached-operator powe make bundle-build bundle-push ``` -1. Run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +1. Run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh - kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -110,6 +105,6 @@ Read the [full tutorial][tutorial] for an in-depth walkthough of building a Ansi [ansible-link]:https://www.ansible.com/ [install-guide]:/docs/building-operators/ansible/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm [tutorial]:/docs/building-operators/ansible/tutorial/ -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index e8dacffe6d5..a312398f80b 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -16,8 +16,7 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Overview @@ -209,14 +208,10 @@ in the `bundle` directory containing manifests and metadata defining your operat make bundle bundle-build bundle-push ``` -Finally, run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +Finally, run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh -kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -356,6 +351,7 @@ OLM will manage creation of most if not all resources required to run your opera [legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/ansible/quickstart/ [migration-guide]:/docs/building-operators/ansible/migration [install-guide]:/docs/building-operators/ansible/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [ansible-developer-tips]:/docs/building-operators/ansible/development-tips/ [ansible-watches]:/docs/building-operators/ansible/reference/watches [custom-resources]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ @@ -363,4 +359,3 @@ OLM will manage creation of most if not all resources required to run your opera [doc-bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#operator-bundle [quickstart-bundle]:/docs/olm-integration/quickstart-bundle [doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index ecedf558181..543cd7020b7 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -57,8 +57,7 @@ The easy migration path is to initialize a new project, re-recreate APIs, then c [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ### Create a new project @@ -417,7 +416,7 @@ For further steps regarding the deployment of the operator, creation of custom r [install-guide]: /docs/building-operators/ansible/installation -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics [memcached_controller]: https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v3/memcached-operator [rbac_markers]: https://book.kubebuilder.io/reference/markers/rbac.html diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index 130925ead7a..c38e143b96d 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -15,8 +15,7 @@ This guide walks through an example of building a simple memcached-operator usin [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Steps @@ -56,14 +55,10 @@ This guide walks through an example of building a simple memcached-operator usin make bundle-build bundle-push ``` -1. Run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +1. Run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh - kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -109,6 +104,6 @@ Read the [full tutorial][tutorial] for an in-depth walkthough of building a Go o [install-guide]:/docs/building-operators/golang/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm [tutorial]:/docs/building-operators/golang/tutorial/ -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 1b6aa6ae5c6..bd70fcc9c62 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -16,8 +16,7 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Overview @@ -339,14 +338,10 @@ in the `bundle` directory containing manifests and metadata defining your operat make bundle bundle-build bundle-push ``` -Finally, run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +Finally, run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh -kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -448,6 +443,7 @@ Next, check out the following: [legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ [migration-guide]:/docs/building-operators/golang/migration [install-guide]:/docs/building-operators/golang/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [enqueue_requests_from_map_func]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#EnqueueRequestsFromMapFunc [event_handler_godocs]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#hdr-EventHandlers [event_filtering]:/docs/building-operators/golang/references/event-filtering/ @@ -492,4 +488,3 @@ Next, check out the following: [openapi-validation]: /docs/building-operators/golang/references/openapi-validation [controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime [kb-doc-gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/website/content/en/docs/building-operators/helm/migration.md b/website/content/en/docs/building-operators/helm/migration.md index 127502271bd..53fc45cc525 100644 --- a/website/content/en/docs/building-operators/helm/migration.md +++ b/website/content/en/docs/building-operators/helm/migration.md @@ -48,8 +48,7 @@ The easy migration path is to initialize a new project, re-recreate APIs, then c [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ### Creating a new project @@ -183,7 +182,7 @@ kubectl logs deployment.apps/nginx-operator-controller-manager -n nginx-operator For further steps regarding the deployment of the operator, creation of custom resources, and cleaning up of resources, see the [tutorial][tutorial-deploy]. [install-guide]: /docs/building-operators/helm/installation -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [kustomize]: https://github.com/kubernetes-sigs/kustomize [kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics diff --git a/website/content/en/docs/building-operators/helm/quickstart.md b/website/content/en/docs/building-operators/helm/quickstart.md index 7b41d317a7e..06d578047ac 100644 --- a/website/content/en/docs/building-operators/helm/quickstart.md +++ b/website/content/en/docs/building-operators/helm/quickstart.md @@ -15,8 +15,7 @@ This guide walks through an example of building a simple nginx-operator powered [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Steps @@ -57,14 +56,10 @@ This guide walks through an example of building a simple nginx-operator powered make bundle-build bundle-push ``` -1. Run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +1. Run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh - kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -110,6 +105,6 @@ Read the [full tutorial][tutorial] for an in-depth walkthough of building a Helm [helm-official]:https://helm.sh/docs/ [install-guide]:/docs/building-operators/helm/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm [tutorial]:/docs/building-operators/helm/tutorial/ -[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 7842fce6b58..fe9e4d1b46d 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -16,8 +16,7 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar [quay.io](https://quay.io/)) and be logged in in your command line environment. - `example.com` is used as the registry Docker Hub namespace in these examples. Replace it with another value if using a different registry or namespace. - - The registry/namespace must be public, or the cluster must be provisioned with an - [image pull secret][k8s-image-pull-sec] if the image namespace is private. + - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA. ## Overview @@ -242,14 +241,10 @@ in the `bundle` directory containing manifests and metadata defining your operat make bundle bundle-build bundle-push ``` -Finally, run your bundle. If your bundle image is hosted in a private registry, -add the image pull secret for that registry host to the service account in use -and set `--secret-name` to the secret name: - +Finally, run your bundle. If your bundle image is hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ```sh -kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":""}]}' operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1 ``` @@ -366,6 +361,7 @@ Next, check out the following: [legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/helm/quickstart/ [migration-guide]:/docs/building-operators/helm/migration [install-guide]:/docs/building-operators/helm/installation +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [layout-doc]: /docs/overview/project-layout [helm-charts]:https://helm.sh/docs/topics/charts/ [helm-values]:https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing diff --git a/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md index 2aa458d21b1..461e0f2ab3b 100644 --- a/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md +++ b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md @@ -17,12 +17,13 @@ operator-sdk run bundle-upgrade [flags] ### Options ``` - -h, --help help for bundle-upgrade - --kubeconfig string Path to the kubeconfig file to use for CLI requests. - -n, --namespace string If present, namespace scope for this CLI request - --secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in - --service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account - --timeout duration Duration to wait for the command to complete before failing (default 2m0s) + --ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem" + -h, --help help for bundle-upgrade + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + -n, --namespace string If present, namespace scope for this CLI request + --pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in + --service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account + --timeout duration Duration to wait for the command to complete before failing (default 2m0s) ``` ### Options inherited from parent commands diff --git a/website/content/en/docs/cli/operator-sdk_run_bundle.md b/website/content/en/docs/cli/operator-sdk_run_bundle.md index 20603011d35..c80e1a350f4 100644 --- a/website/content/en/docs/cli/operator-sdk_run_bundle.md +++ b/website/content/en/docs/cli/operator-sdk_run_bundle.md @@ -17,12 +17,13 @@ operator-sdk run bundle [flags] ### Options ``` + --ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem" -h, --help help for bundle --index-image string index image in which to inject bundle (default "quay.io/operator-framework/upstream-opm-builder:latest") --install-mode InstallModeValue install mode --kubeconfig string Path to the kubeconfig file to use for CLI requests. -n, --namespace string If present, namespace scope for this CLI request - --secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in + --pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in --service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account --timeout duration Duration to wait for the command to complete before failing (default 2m0s) ``` diff --git a/website/content/en/docs/olm-integration/cli-overview.md b/website/content/en/docs/olm-integration/cli-overview.md index 032649c3901..e3f5caec469 100644 --- a/website/content/en/docs/olm-integration/cli-overview.md +++ b/website/content/en/docs/olm-integration/cli-overview.md @@ -8,9 +8,7 @@ This document gives an overview of using `operator-sdk` to work with Operator ma namely [bundles][bundle] and [package manifests][package-manifests]. See the [manifests generation][doc-olm-generate] doc for an in-depth discussion of these commands. -## Commands - -### OLM installation +## OLM installation The following `operator-sdk` subcommands manage an OLM installation: @@ -20,16 +18,16 @@ can infer the version of an error-free OLM installation. - [`olm uninstall`][cli-olm-uninstall]: uninstall a particular version of OLM running in a cluster. This command can infer the version of an error-free OLM installation. -### Manifests and metadata +## Manifests and metadata The following `make` recipes and `operator-sdk` subcommands create or interact with Operator package manifests and bundles: - [`generate kustomize manifests`][cli-gen-kustomize-manifests]: creates kustomize bases and a `kustomization.yaml` in `config/manifests`. -##### Bundles +### Bundles - `make bundle`: runs the following commands: - - `generate kustomize manifests`: see [above](#commands). + - `generate kustomize manifests`: see [above](#manifests-and-metadata). - [`generate bundle`][cli-gen-bundle]: creates a new or updates an existing bundle in the `/bundle` directory. This command generates both manifests and metadata. - [`bundle validate`][cli-bundle-validate]: validates an Operator bundle image or unpacked manifests and metadata. @@ -38,7 +36,53 @@ The following `make` recipes and `operator-sdk` subcommands create or interact w existing OLM installation. - [`run bundle-upgrade`][cli-run-bundle-upgrade]: upgrades the Operator bundle to a specified newer version. -##### Package Manifests +#### Private bundle and catalog image registries + +By default, projects are configured to push to and pull from a [docker.io] registry +with namespace being the value passed to `operator-sdk init --domain=`. +Modify this value to push/pull bundle and catalog images with a different registry host or namespace. + +All bundle and catalog image-related commands invoke [`opm`][opm] (except for bundle image builds, +for which `docker` is used directly). `opm` leverages the host's image build/pull tools indirectly +to perform various image tasks, so if your image registry is private or has a custom CA you +must ensure the in-use build tool is able to push to/pull from the registry: +- `docker`: [`config.json`][docker-pull-sec], [certificate configuration][docker-certs] +- `podman`: [`auth.json`][podman-pull-sec], [certificate configuration][podman-certs] +- `none` (containerd): uses docker's `config.json`, [certificate configuration][none-certs] + +The `run bundle` or `run bundle-upgrade` commands use the `none` image tool, described above, in-cluster. +These commands accept the names of secrets available in the deployment namesace that contain configuration file data. +Ideally a cluster admin will provision a namespace and service account for bundle testing, +such that they include and reference these secrets: +- Create an [image pull secret][k8s-image-pull-sec] for your `config.json` and [add it to your service account][k8s-pull-sec-sa]. + +- Create a [generic secret][k8s-gen-sec] with a `cert.pem` key containing root certificate(s) for your registry. + +Once the above secrets have been created, run the either command with `--pull-secret-name=` and `--ca-secret-name=`: + +```sh +operator-sdk run bundle private-custom-ca-reg.com/memcached-operator-bundle:v0.0.2 \ + --index-image private-custom-ca-reg.com/memcached-operator-catalog:v0.0.1 \ + --pull-secret-name foo-pull-sec \ + --ca-secret-name foo-cert-sec +``` + +You may have to set `--namespace=` if the namespace encoded in your kubeconfig's current context +was not provisioned with these secrets. + +[docker.io]:https://hub.docker.com/ +[opm]:https://github.com/operator-framework/operator-registry/blob/496ccce/docs/design/opm-tooling.md +[docker-pull-sec]:https://docs.docker.com/engine/reference/commandline/login/ +[docker-certs]:https://docs.docker.com/engine/security/certificates/ +[podman-pull-sec]:http://docs.podman.io/en/latest/markdown/podman-login.1.html#description +[podman-certs]:http://docs.podman.io/en/latest/markdown/podman-image-sign.1.html#cert-dir-path +[none-certs]:https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md#add +[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +[k8s-pull-sec-sa]:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-image-pull-secret-to-service-account +[k8s-gen-sec]:https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/#create-a-secret + +### Package Manifests - [`generate packagemanifests`][cli-gen-packagemanifests]: creates a new or updates an existing versioned directory as part of the package manifests in the `/packagemanifests` directory. diff --git a/website/content/en/docs/olm-integration/quickstart-bundle.md b/website/content/en/docs/olm-integration/quickstart-bundle.md index c0e114ba10e..4dcc61c7f84 100644 --- a/website/content/en/docs/olm-integration/quickstart-bundle.md +++ b/website/content/en/docs/olm-integration/quickstart-bundle.md @@ -110,14 +110,8 @@ to ensure the on-disk bundle representation is correct. At this point in development we've generated all files necessary to build the memcached-operator bundle. Now we're ready to test and deploy the Operator with OLM. -**Note:** if testing a bundle hosted in a private registry, add the image pull -secret for that registry host [to the service account][add-sa-secret] in use -and set `--secret-name` to the secret name. You may have to set `--namespace` -if the service account is in a different namespace than that configured in your kubeconfig. - - -[add-sa-secret]:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account +**Note:** If testing a bundle whose image will be hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ### Testing bundles @@ -287,6 +281,7 @@ In-depth discussions of OLM concepts mentioned here: [bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md [bundle-metadata]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-annotations [bundle-dockerfile]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-dockerfile +[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries [cli-olm]:/docs/cli/operator-sdk_olm [cli-run-bundle]:/docs/cli/operator-sdk_run_bundle [doc-cli-overview]:/docs/olm-integration/cli-overview diff --git a/website/content/en/docs/olm-integration/testing-deployment.md b/website/content/en/docs/olm-integration/testing-deployment.md index 5b058d1393f..8862c21a767 100644 --- a/website/content/en/docs/olm-integration/testing-deployment.md +++ b/website/content/en/docs/olm-integration/testing-deployment.md @@ -17,13 +17,8 @@ to inform OLM of that registry and which Operator versions it can deploy and whe - `run bundle` and `run packagemanifests` can only deploy one Operator and one version of that Operator at a time, and `run bundle-upgrade` can only upgrade one Operator and one version of that Operator at a time, hence their intended purpose being testing only. -- If testing a bundle hosted in a private registry, set the `--secret-name` flag to -the name of the appropriate in-cluster image pull secret, and add the same secret -[to a service account][add-sa-secret] and set `--service-account` to that service account's name; -you may have to set `--namespace` if the service account is in a different namespace -than that configured in your kubeconfig. - +- If testing a bundle or catalog whose image will be hosted in a registry that is private and/or +has a custom CA, these [configuration steps][image-reg-config] must be complete. ## `operator-sdk run bundle` command overview diff --git a/website/content/en/docs/overview/cheat-sheet.md b/website/content/en/docs/overview/cheat-sheet.md index bd244ef0cc0..409e0bfd0f0 100644 --- a/website/content/en/docs/overview/cheat-sheet.md +++ b/website/content/en/docs/overview/cheat-sheet.md @@ -38,7 +38,7 @@ For further information check [Operator SDK Integration with Operator Lifecycle | `make bundle-build BUNDLE_IMG=/:` | To build your bundle operator image. | | `make bundle-build bundle-push BUNDLE_IMG=/:` | To build and push your bundle operator image. | | `operator-sdk run bundle /:` | To deploy your bundle operator using OLM on your cluster for development purposes. | -| `operator-sdk run bundle --service-account sa-with-secret --secret-name registry-pull-secret private-registry.org/bundle:v1.2.3` | Configure `run bundle` (and `run bundle-upgrade`) to use an image pull secret and non-default service account configured with that secret | +| `operator-sdk run bundle private-registry.org/bundle:v1.2.3 --service-account sa-with-secret --pull-secret-name regcred --ca-secret-name cert-sec` | Configure `run bundle` (and `run bundle-upgrade`) to use an image pull secret, non-default service account configured with that secret, and custom CA certificate secret |