Skip to content

Commit 0b62a3e

Browse files
authored
Merge pull request #2906 from camilamacedo86/test
✨ add options and guidance to provide solutions for other platforms and within multiple architecture support
2 parents ccd6554 + efdb1ce commit 0b62a3e

File tree

66 files changed

+1123
-15
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1123
-15
lines changed

docs/book/src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
- [controller-gen CLI](./reference/controller-gen.md)
9393
- [completion](./reference/completion.md)
9494
- [Artifacts](./reference/artifacts.md)
95-
95+
- [Platform Support](platform.md)
9696
- [Configuring EnvTest](./reference/envtest.md)
9797

9898
- [Metrics](./reference/metrics.md)
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# Platforms Supported
2+
3+
Kubebuilder produces solutions that by default can work on multiple platforms or specific ones, depending on how you
4+
build and configure your workloads. This guide aims to help you properly configure your projects according to your needs.
5+
6+
## Overview
7+
8+
To provide support on specific or multiple platforms, you must ensure that all images used in workloads are built to
9+
support the desired platforms. Note that may not be the same as the platform where you develop your solutions
10+
and use KubeBuilder, but instead the platform(s) where your solution should run and be distributed.
11+
It is recommended to build solutions that work on multiple platforms so that your project works
12+
on any Kubernetes cluster regardless of the underlying operating system and architecture.
13+
14+
## How to define which platforms are supported
15+
16+
The following covers what you need to do to provide the support for one or more platforms or architectures.
17+
18+
### 1) Build workload images to provide the support for other platform(s)
19+
20+
The images used in workloads such as in your Pods/Deployments will need to provide the support for this other platform.
21+
You can inspect the images using a ManifestList of supported platforms using the command
22+
[docker manifest inspect <image>][docker-manifest], i.e.:
23+
24+
```shell
25+
$ docker manifest inspect myresgystry/example/myimage:v0.0.1
26+
{
27+
"schemaVersion": 2,
28+
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
29+
"manifests": [
30+
{
31+
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
32+
"size": 739,
33+
"digest": "sha256:a274a1a2af811a1daf3fd6b48ff3d08feb757c2c3f3e98c59c7f85e550a99a32",
34+
"platform": {
35+
"architecture": "arm64",
36+
"os": "linux"
37+
}
38+
},
39+
{
40+
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
41+
"size": 739,
42+
"digest": "sha256:d801c41875f12ffd8211fffef2b3a3d1a301d99f149488d31f245676fa8bc5d9",
43+
"platform": {
44+
"architecture": "amd64",
45+
"os": "linux"
46+
}
47+
},
48+
{
49+
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
50+
"size": 739,
51+
"digest": "sha256:f4423c8667edb5372fb0eafb6ec599bae8212e75b87f67da3286f0291b4c8732",
52+
"platform": {
53+
"architecture": "s390x",
54+
"os": "linux"
55+
}
56+
},
57+
{
58+
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
59+
"size": 739,
60+
"digest": "sha256:621288f6573c012d7cf6642f6d9ab20dbaa35de3be6ac2c7a718257ec3aff333",
61+
"platform": {
62+
"architecture": "ppc64le",
63+
"os": "linux"
64+
}
65+
},
66+
]
67+
}
68+
```
69+
70+
### 2) (Recommended as a Best Practice) Ensure that node affinity expressions are set to match the supported platforms
71+
72+
Kubernetes provides a mechanism called [nodeAffinity][node-affinity] which can be used to limit the possible node
73+
targets where a pod can be scheduled. This is especially important to ensure correct scheduling behavior in clusters
74+
with nodes that span across multiple platforms (i.e. heterogeneous clusters).
75+
76+
**Kubernetes manifest example**
77+
78+
```yaml
79+
affinity:
80+
nodeAffinity:
81+
requiredDuringSchedulingIgnoredDuringExecution:
82+
nodeSelectorTerms:
83+
- matchExpressions:
84+
- key: kubernetes.io/arch
85+
operator: In
86+
values:
87+
- amd64
88+
- arm64
89+
- ppc64le
90+
- s390x
91+
- key: kubernetes.io/os
92+
operator: In
93+
values:
94+
- linux
95+
```
96+
97+
**Golang Example**
98+
99+
```go
100+
Template: corev1.PodTemplateSpec{
101+
...
102+
Spec: corev1.PodSpec{
103+
Affinity: &corev1.Affinity{
104+
NodeAffinity: &corev1.NodeAffinity{
105+
RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
106+
NodeSelectorTerms: []corev1.NodeSelectorTerm{
107+
{
108+
MatchExpressions: []corev1.NodeSelectorRequirement{
109+
{
110+
Key: "kubernetes.io/arch",
111+
Operator: "In",
112+
Values: []string{"amd64"},
113+
},
114+
{
115+
Key: "kubernetes.io/os",
116+
Operator: "In",
117+
Values: []string{"linux"},
118+
},
119+
},
120+
},
121+
},
122+
},
123+
},
124+
},
125+
SecurityContext: &corev1.PodSecurityContext{
126+
...
127+
},
128+
Containers: []corev1.Container{{
129+
...
130+
}},
131+
},
132+
```
133+
134+
<aside class="note">
135+
<h1> Example(s) </h1>
136+
137+
You can look for some code examples by checking the code which is generated via the Deploy
138+
Image plugin. ([More info](../plugins/deploy-image-plugin-v1-alpha.md))
139+
140+
</aside>
141+
142+
## Producing projects that support multiple platforms
143+
144+
You can use [`docker buildx`][buildx] to cross-compile via emulation ([QEMU](https://www.qemu.org/)) to build the manager image.
145+
See that projects scaffold with the latest versions of Kubebuilder have the Makefile target `docker-buildx`.
146+
147+
**Example of Usage**
148+
149+
```shell
150+
$ make docker-buildx IMG=myregistry/myoperator:v0.0.1
151+
```
152+
153+
Note that you need to ensure that all images and workloads required and used by your project will provide the same
154+
support as recommended above, and that you properly configure the [nodeAffinity][node-affinity] for all your workloads.
155+
Therefore, ensure that you uncomment the following code in the `config/manager/manager.yaml` file
156+
157+
```yaml
158+
# TODO(user): Uncomment the following code to configure the nodeAffinity expression
159+
# according to the platforms which are supported by your solution.
160+
# It is considered best practice to support multiple architectures. You can
161+
# build your manager image using the makefile target docker-buildx.
162+
# affinity:
163+
# nodeAffinity:
164+
# requiredDuringSchedulingIgnoredDuringExecution:
165+
# nodeSelectorTerms:
166+
# - matchExpressions:
167+
# - key: kubernetes.io/arch
168+
# operator: In
169+
# values:
170+
# - amd64
171+
# - arm64
172+
# - ppc64le
173+
# - s390x
174+
# - key: kubernetes.io/os
175+
# operator: In
176+
# values:
177+
# - linux
178+
```
179+
180+
<aside class="note">
181+
<h1>Building images for releases</h1>
182+
183+
184+
You will probably want to automate the releases of your projects to ensure that the images are always built for the
185+
same platforms. Note that Goreleaser also supports [docker buildx][buildx]. See its [documentation][goreleaser-buildx] for more detail.
186+
187+
Also, you may want to configure GitHub Actions, Prow jobs, or any other solution that you use to build images to
188+
provide multi-platform support. Note that you can also use other options like `docker manifest create` to customize
189+
your solutions to achieve the same goals with other tools.
190+
191+
By using Docker and the target provided by default you should NOT change the Dockerfile to use
192+
any specific GOOS and GOARCH to build the manager binary. However, if you are looking for to
193+
customize the default scaffold and create your own implementations you might want to give
194+
a look in the Golang [doc](https://go.dev/doc/install/source#environment) to knows
195+
its available options.
196+
197+
</aside>
198+
199+
## Which (workload) images are created by default?
200+
201+
Projects created with the Kubebuilder CLI have two workloads which are:
202+
203+
### Manager
204+
205+
The container to run the manager implementation is configured in the `config/manager/manager.yaml` file.
206+
This image is built with the Dockerfile file scaffolded by default and contains the binary of the project \
207+
which will be built via the command `go build -a -o manager main.go`.
208+
209+
Note that when you run `make docker-build` OR `make docker-build IMG=myregistry/myprojectname:<tag>`
210+
an image will be built from the client host (local environment) and produce an image for
211+
the client os/arch, which is commonly linux/amd64 or linux/arm64.
212+
213+
<aside class="note">
214+
<h1>Mac Os</h1>
215+
216+
If you are running from an Mac Os environment then, Docker also will consider it as linux/$arch. Be aware that
217+
when, for example, is running Kind on a Mac OS operational system the nodes will
218+
end up labeled with ` kubernetes.io/os=linux`
219+
220+
</aside>
221+
222+
### Kube RBAC Proxy
223+
224+
A workload will be created to run the image [gcr.io/kubebuilder/kube-rbac-proxy:<tag>][proxy-images] which is
225+
configured in the `config/default/manager_auth_proxy_patch.yaml` manifest. It is a side-car proxy whose purpose
226+
is to protect the manager from malicious attacks. You can learn more about its motivations by looking at
227+
the README of this project [github.com/brancz/kube-rbac-proxy][https://github.com/brancz/kube-rbac-proxy].
228+
229+
Kubebuilder has been building this image with support for multiple architectures by default.( Check it [here][proxy-images] ).
230+
If you need to address any edge case scenario where you want to produce a project that
231+
only provides support for a specific architecture platform, you can customize your
232+
configuration manifests to use the specific architecture types built for this image.
233+
234+
[node-affinity]: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
235+
[docker-manifest]: https://docs.docker.com/engine/reference/commandline/manifest/
236+
[proxy-images]: https://console.cloud.google.com/gcr/images/kubebuilder/GLOBAL/kube-rbac-proxy
237+
[buildx]: https://docs.docker.com/build/buildx/
238+
[goreleaser-buildx]: https://goreleaser.com/customization/docker/#use-a-specific-builder-with-docker-buildx

docs/book/src/reference/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
- [controller-gen CLI](controller-gen.md)
3131
- [completion](completion.md)
3232
- [Artifacts](artifacts.md)
33+
- [Platform Support](platform.md)
3334
- [Writing controller tests](writing-tests.md)
3435
- [Metrics](metrics.md)
3536

pkg/plugins/common/kustomize/v1/scaffolds/internal/templates/config/kdefault/manager_auth_proxy_patch.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ metadata:
5353
spec:
5454
template:
5555
spec:
56+
affinity:
57+
nodeAffinity:
58+
requiredDuringSchedulingIgnoredDuringExecution:
59+
nodeSelectorTerms:
60+
- matchExpressions:
61+
- key: kubernetes.io/arch
62+
operator: In
63+
values:
64+
- amd64
65+
- arm64
66+
- ppc64le
67+
- s390x
68+
- key: kubernetes.io/os
69+
operator: In
70+
values:
71+
- linux
5672
containers:
5773
- name: kube-rbac-proxy
5874
securityContext:

pkg/plugins/common/kustomize/v1/scaffolds/internal/templates/config/manager/config.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@ spec:
8383
labels:
8484
control-plane: controller-manager
8585
spec:
86+
# TODO(user): Uncomment the following code to configure the nodeAffinity expression
87+
# according to the platforms which are supported by your solution.
88+
# It is considered best practice to support multiple architectures. You can
89+
# build your manager image using the makefile target docker-buildx.
90+
# affinity:
91+
# nodeAffinity:
92+
# requiredDuringSchedulingIgnoredDuringExecution:
93+
# nodeSelectorTerms:
94+
# - matchExpressions:
95+
# - key: kubernetes.io/arch
96+
# operator: In
97+
# values:
98+
# - amd64
99+
# - arm64
100+
# - ppc64le
101+
# - s390x
102+
# - key: kubernetes.io/os
103+
# operator: In
104+
# values:
105+
# - linux
86106
securityContext:
87107
runAsNonRoot: true
88108
# TODO(user): For common cases that do not require escalating privileges

pkg/plugins/common/kustomize/v2-alpha/scaffolds/internal/templates/config/kdefault/manager_auth_proxy_patch.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ metadata:
5353
spec:
5454
template:
5555
spec:
56+
affinity:
57+
nodeAffinity:
58+
requiredDuringSchedulingIgnoredDuringExecution:
59+
nodeSelectorTerms:
60+
- matchExpressions:
61+
- key: kubernetes.io/arch
62+
operator: In
63+
values:
64+
- amd64
65+
- arm64
66+
- ppc64le
67+
- s390x
68+
- key: kubernetes.io/os
69+
operator: In
70+
values:
71+
- linux
5672
containers:
5773
- name: kube-rbac-proxy
5874
securityContext:

pkg/plugins/common/kustomize/v2-alpha/scaffolds/internal/templates/config/manager/config.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@ spec:
8383
labels:
8484
control-plane: controller-manager
8585
spec:
86+
# TODO(user): Uncomment the following code to configure the nodeAffinity expression
87+
# according to the platforms which are supported by your solution.
88+
# It is considered best practice to support multiple architectures. You can
89+
# build your manager image using the makefile target docker-buildx.
90+
# affinity:
91+
# nodeAffinity:
92+
# requiredDuringSchedulingIgnoredDuringExecution:
93+
# nodeSelectorTerms:
94+
# - matchExpressions:
95+
# - key: kubernetes.io/arch
96+
# operator: In
97+
# values:
98+
# - amd64
99+
# - arm64
100+
# - ppc64le
101+
# - s390x
102+
# - key: kubernetes.io/os
103+
# operator: In
104+
# values:
105+
# - linux
86106
securityContext:
87107
runAsNonRoot: true
88108
# TODO(user): For common cases that do not require escalating privileges

pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/internal/templates/controllers/controller.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,34 @@ func (r *{{ .Resource.Kind }}Reconciler) deploymentFor{{ .Resource.Kind }}(
378378
Labels: ls,
379379
},
380380
Spec: corev1.PodSpec{
381+
// TODO(user): Uncomment the following code to configure the nodeAffinity expression
382+
// according to the platforms which are supported by your solution. It is considered
383+
// best practice to support multiple architectures. build your manager image using the
384+
// makefile target docker-buildx. Also, you can use docker manifest inspect <image>
385+
// to check what are the platforms supported.
386+
// More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
387+
//Affinity: &corev1.Affinity{
388+
// NodeAffinity: &corev1.NodeAffinity{
389+
// RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
390+
// NodeSelectorTerms: []corev1.NodeSelectorTerm{
391+
// {
392+
// MatchExpressions: []corev1.NodeSelectorRequirement{
393+
// {
394+
// Key: "kubernetes.io/arch",
395+
// Operator: "In",
396+
// Values: []string{"amd64", "arm64", "ppc64le", "s390x"},
397+
// },
398+
// {
399+
// Key: "kubernetes.io/os",
400+
// Operator: "In",
401+
// Values: []string{"linux"},
402+
// },
403+
// },
404+
// },
405+
// },
406+
// },
407+
// },
408+
//},
381409
SecurityContext: &corev1.PodSecurityContext{
382410
RunAsNonRoot: &[]bool{true}[0],
383411
// IMPORTANT: seccomProfile was introduced with Kubernetes 1.19

0 commit comments

Comments
 (0)