Skip to content

Commit 0ae0cd9

Browse files
authored
Adding documentation for multi-arch operators (#5178)
Signed-off-by: Frederic Giloux <[email protected]>
1 parent 8f4243f commit 0ae0cd9

File tree

6 files changed

+88
-9
lines changed

6 files changed

+88
-9
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: "Advanced Topics"
3+
linkTitle: "Advanced Topics"
4+
weight: 9
5+
date: 2021-10-05
6+
description: >
7+
Advanced Topics.
8+
---
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
title: Multiple Architectures
3+
linkTitle: Multiple Architectures
4+
weight: 80
5+
---
6+
7+
### Supporting Multiple Architectures
8+
9+
Authors may decide to distribute their bundles for various architectures: x86_64, aarch64, ppc64le, s390x, etc, to accomodate the diversity of Kubernetes clusters and reach a larger number of potential users. Each architecture requires however compatible binaries.
10+
11+
#### Manifest lists
12+
13+
The most straightforward way of building operators and operands supporting multiple architectures is to leverage manifest lists, specified by [Image Manifest V2, Schema 2][manifest_list] or [OCI Image Index][image_index]. A manifest list points to specific image manifests for one or more platforms.
14+
15+
For convenience tools like [buildah][buildah] allow to cross-build and manifest multi-arch containers on one host. For instance with buildah:
16+
17+
```shell
18+
for a in amd64 arm64 ppc64le s390x; do \
19+
buildah bud --manifest registry/username/repo:v1 --arch $a; \
20+
done
21+
```
22+
23+
This creates the manifest list, builds each image and adds them to the manifest list.
24+
25+
The result can then be pushed to the desired registry.
26+
27+
```shell
28+
buildah push registry/username/repo:v1
29+
```
30+
31+
Docker with [buildx][buildx] provides similar capabilities.
32+
33+
```shell
34+
docker buildx build --push --platform linux/amd64,linux/arm64,linux/ppc64le,linux/s390x --tag registry/username/repo:v1 .
35+
```
36+
37+
See [docker documentation][buildx_multiarch] for additional options.
38+
39+
**Caveats**: the Dockerfile generated by the SDK for the operator explicitely references GOARCH=amd64 for go build. This can be amended to GOARCH=$TARGETARCH. Docker will automatically set the environment variable to the value specified by --platform. With buildah --build-arg will need to be used for the purpose.
40+
41+
**Caveats**: When mirroring registries for disconnected installations (environments without internet connection) all the images referenced by a manifest list need to be copied, including images for architectures that may not be used in the environment.
42+
43+
#### Operator Lifecycle Manager
44+
45+
For operators distributed through the [Operator Lifecycle Manager (OLM)][olm]:
46+
47+
* [Bundle images][bundle] are not architecture-specific. They contain only plaintext kubernetes manifests and operator metadata.
48+
* All image references in the ClusterServiceVersion should be manifest lists containing the pointers to the image manifests for the supported architectures.
49+
* Labels for OS and architectures can be set in the CSV. Please refer to the [Operator Lifecycle Management Documentation][olm_multiarch] for details.
50+
51+
[manifest_list]: https://docs.docker.com/registry/spec/manifest-v2-2/#manifest-list
52+
[image_index]: https://github.com/opencontainers/image-spec/blob/main/image-index.md
53+
[buildah]: https://github.com/containers/buildah/blob/main/docs/buildah-bud.md#building-an-multi-architecture-image-using-a---manifest-option-requires-emulation-software
54+
[buildx]: https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images
55+
[buildx_multiarch]: https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images
56+
[olm]: https://olm.operatorframework.io/docs/
57+
[bundle]: https://olm.operatorframework.io/docs/glossary/#bundle
58+
[olm_multiarch]: https://olm.operatorframework.io/docs/advanced-tasks/ship-operator-supporting-multiarch/#multiple-architectures
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Best Practices"
33
linkTitle: "Best Practices"
4-
weight: 9
4+
weight: 10
55
description: >
66
Best practices, conventions and recommendations to work with SDK
77
---

website/content/en/docs/building-operators/golang/advanced-topics.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,17 @@ Operators may create objects as part of their operational duty. Object accumulat
124124
125125
#### Internal Resources
126126
127-
A typical example of correct resource cleanup is the [Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/job/) implementation. When a Job is created, one or multiple Pods are created as child resources. When a Job is deleted, the associated Pods are deleted as well. This is a very common pattern easily achieved by setting an owner reference from the parent (Job) to the child (Pod) object. Here is a code snippet for doing so, where "r" is the reconcilier and "ctrl" the controller-runtime library:
127+
A typical example of correct resource cleanup is the [Jobs][jobs] implementation. When a Job is created, one or multiple Pods are created as child resources. When a Job is deleted, the associated Pods are deleted as well. This is a very common pattern easily achieved by setting an owner reference from the parent (Job) to the child (Pod) object. Here is a code snippet for doing so, where "r" is the reconcilier and "ctrl" the controller-runtime library:
128128
129129
```go
130130
ctrl.SetControllerReference(job, pod, r.Scheme)
131131
```
132132
133-
Note that the default behavior for cascading deletion is background propagation, meaning deletion requests for child objects occur after the request to delete the parent object. [This Kubernetes doc](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/) provides alternative deletion types.
133+
Note that the default behavior for cascading deletion is background propagation, meaning deletion requests for child objects occur after the request to delete the parent object. [This Kubernetes doc][garbage_collection] provides alternative deletion types.
134134
135135
#### External Resources
136136
137-
Sometimes external resources or resources that are not owned by a custom resource, those across namespaces for example, need to be cleaned up when the parent resource is deleted. In that case [Finalizers](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) can be leveraged. A deletion request for an object with a finalizer becomes an update during which a deletion timestamp is set; the object is not deleted while the finalizer is present. The reconciliation loop of the custom resource's controller will then need to check whether a the deletion timestamp is set, perform the external cleanup operation(s), then remove the finalizer to allow garbage collection of the object. Multiple finalizers may be present on an object, each with a key that should indicate what external resources require deletion by the controller.
137+
Sometimes external resources or resources that are not owned by a custom resource, those across namespaces for example, need to be cleaned up when the parent resource is deleted. In that case [Finalizers][finalizers] can be leveraged. A deletion request for an object with a finalizer becomes an update during which a deletion timestamp is set; the object is not deleted while the finalizer is present. The reconciliation loop of the custom resource's controller will then need to check whether a the deletion timestamp is set, perform the external cleanup operation(s), then remove the finalizer to allow garbage collection of the object. Multiple finalizers may be present on an object, each with a key that should indicate what external resources require deletion by the controller.
138138
139139
The following is a snippet from a theoretical controller file `controllers/memcached_controller.go` that implements a finalizer handler:
140140
@@ -218,12 +218,12 @@ func (r *MemcachedReconciler) finalizeMemcached(reqLogger logr.Logger, m *cachev
218218
219219
#### Complex cleanup logic
220220
221-
Similar to the previous scenario, finalizers can be used for implementing complex cleanup logic. Take [CronJobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) as an example: the controller maintains limited-size lists of jobs that have been created by the CronJob controller to check for deletion. These list sizes are configured by the CronJob fields [`.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit`](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits), which specify how many completed and failed jobs should be kept. Check out the [Kubebuilder CronJob tutorial](https://book.kubebuilder.io/cronjob-tutorial/controller-implementation.html#3-clean-up-old-jobs-according-to-the-history-limit) for full implementation details.
221+
Similar to the previous scenario, finalizers can be used for implementing complex cleanup logic. Take [CronJobs][cronjobs] as an example: the controller maintains limited-size lists of jobs that have been created by the CronJob controller to check for deletion. These list sizes are configured by the CronJob fields [`.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit`][cronjob_fields], which specify how many completed and failed jobs should be kept. Check out the [Kubebuilder CronJob tutorial][cronjob_tutorial] for full implementation details.
222222
223223
#### Sensitive resources
224224
225-
Sensitive resources need to be protected against unintended deletion. An intuitive example of protecting resources is the [PersistentVolume (PV) / PersistentVolumeClaim (PVC)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) relationship. A PV is first created, after which users can request access to that PV's storage by creating a PVC, which gets bound to the PV. If a user tries to delete a PV currently bound by a PVC, the PV is not removed immediately. Instead, PV removal is postponed until the PV is not bound to any PVC. Finalizers again can be leveraged to achieve a similar behaviour for your own PV-like custom resources: by setting a finalizer on an object, your controller can make sure there are no remaining objects bound to it before removing the finalizer and deleting the object.
226-
Additionally, the user who created the PVC can specify what happens to the underlying storage allocated in a PV when the PVC is deleted through the [reclaim policy](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming). There are several options available, each of which defines a behavior that is achieved again through the use of finalizers. The key concept to take away is that your operator can give a user the power to decide how their resources are cleaned up via finalizers, which may be dangerous yet useful depending on your workloads.
225+
Sensitive resources need to be protected against unintended deletion. An intuitive example of protecting resources is the [PersistentVolume (PV) / PersistentVolumeClaim (PVC)][pv] relationship. A PV is first created, after which users can request access to that PV's storage by creating a PVC, which gets bound to the PV. If a user tries to delete a PV currently bound by a PVC, the PV is not removed immediately. Instead, PV removal is postponed until the PV is not bound to any PVC. Finalizers again can be leveraged to achieve a similar behaviour for your own PV-like custom resources: by setting a finalizer on an object, your controller can make sure there are no remaining objects bound to it before removing the finalizer and deleting the object.
226+
Additionally, the user who created the PVC can specify what happens to the underlying storage allocated in a PV when the PVC is deleted through the [reclaim policy][reclaiming]. There are several options available, each of which defines a behavior that is achieved again through the use of finalizers. The key concept to take away is that your operator can give a user the power to decide how their resources are cleaned up via finalizers, which may be dangerous yet useful depending on your workloads.
227227
228228
### Leader election
229229
@@ -285,16 +285,29 @@ func main() {
285285
286286
When the operator is not running in a cluster, the Manager will return an error on starting since it can't detect the operator's namespace in order to create the configmap for leader election. You can override this namespace by setting the Manager's `LeaderElectionNamespace` option.
287287
288+
### Multiple architectures
289+
290+
Authors may decide to distribute their bundles for various architectures: x86_64, aarch64, ppc64le, s390x, etc, to accomodate the diversity of Kubernetes clusters and reach a larger number of potential users. Each architecture requires however compatible binaries. Considerations on the topic are available in the [Multiple Architectures page][multi_arch].
291+
288292
[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
289293
[scheme_package]:https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go
290294
[deployments_register]: https://github.com/kubernetes/api/blob/master/apps/v1/register.go#L41
291295
[runtime_package]: https://pkg.go.dev/k8s.io/apimachinery/pkg/runtime
292296
[scheme_builder]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/scheme#Builder
293297
[metrics_doc]: https://book.kubebuilder.io/reference/metrics.html
298+
[jobs]: https://kubernetes.io/docs/concepts/workloads/controllers/job/
299+
[garbage_collection]: https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/
300+
[finalizers]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers
301+
[cronjobs]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
302+
[cronjobs_fields]: https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits
303+
[cronjob_tutorial]: https://book.kubebuilder.io/cronjob-tutorial/controller-implementation.html#3-clean-up-old-jobs-according-to-the-history-limit
304+
[pv]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/
305+
[reclaiming]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming
294306
[lease_split_brain]: https://github.com/kubernetes/client-go/blob/30b06a83d67458700a5378239df6b96948cb9160/tools/leaderelection/leaderelection.go#L21-L24
295307
[leader_for_life]: https://pkg.go.dev/github.com/operator-framework/operator-lib/leader
296308
[leader_with_lease]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/leaderelection
297309
[pod_eviction_timeout]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/#options
298310
[manager_options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options
299311
[apimachinery_condition]: https://github.com/kubernetes/apimachinery/blob/d4f471b82f0a17cda946aeba446770563f92114d/pkg/apis/meta/v1/types.go#L1368
300312
[helpers-conditions]: https://github.com/kubernetes/apimachinery/blob/master/pkg/api/meta/conditions.go
313+
[multi_arch]:/docs/advanced-topics/multi-arch
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: How to Contribute
33
linkTitle: Contribution Guide
4-
weight: 10
4+
weight: 11
55
description: Contribute to Operator SDK
66
---

website/content/en/docs/faqs/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Operator SDK FAQ
33
linkTitle: FAQ
4-
weight: 11
4+
weight: 12
55
---
66

77
## What are the the differences between Kubebuilder and Operator-SDK?

0 commit comments

Comments
 (0)