Skip to content

Commit f6ef4c4

Browse files
committed
Multi-tenancy proposal
This adds a proposal for how to implement the CAPI multi-tenancy contract for CAPM3. Signed-off-by: Lennart Jern <lennart.jern@est.tech>
1 parent 3dd7969 commit f6ef4c4

File tree

1 file changed

+275
-0
lines changed

1 file changed

+275
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<!--
2+
This work is licensed under a Creative Commons Attribution 3.0
3+
Unported License.
4+
5+
http://creativecommons.org/licenses/by/3.0/legalcode
6+
-->
7+
8+
# CAPM3 Multi-Tenancy Contract
9+
10+
## Status
11+
12+
implementable
13+
14+
## Summary
15+
16+
Implement the CAPI multi-tenancy contract for the Metal3 infrastructure provider
17+
by adding a new field to the Metal3Cluster resource. The new field will be a
18+
reference to a secret that contains the credentials for accessing the
19+
BareMetalHosts.
20+
21+
## Motivation
22+
23+
It is currently hard to use the Metal3 infrastructure provider in a multi-tenant
24+
environment. Some options are available (separate namespaces, separate
25+
CAPM3/BMO/Ironic instances), but they all come with drawbacks. Considering that
26+
there is a well defined CAPI contract for multi-tenancy, we should implement it.
27+
28+
### Goals
29+
30+
- Implement the CAPI multi-tenancy contract for the Metal3 infrastructure
31+
provider
32+
- Allow CAPM3 to work with BareMetalHosts in another cluster or namespace than
33+
where the Metal3Machine is.
34+
- To propagate back the relevant information to the Metal3Machine from the
35+
BareMetalHost.
36+
37+
### Non-Goals
38+
39+
- Removing or changing how CAPM3 is associating Metal3Machines with the
40+
BareMetalHosts.
41+
- Solving issues related to multiple CAPM3 instances working with the same
42+
BareMetalHosts. This should be handled separately, e.g. by introducing a
43+
[claim resource](https://github.com/metal3-io/metal3-docs/pull/408).
44+
- Limiting the scope of the credentials that CAPM3 needs to access the
45+
BareMetalHosts. This should be handled separately, e.g. by introducing a
46+
[claim resource](https://github.com/metal3-io/metal3-docs/pull/408).
47+
48+
## Proposal
49+
50+
Add a new field to the Metal3Cluster resource that will be a reference to a
51+
secret that contains the credentials for accessing the BareMetalHosts. CAPM3
52+
should use the credentials for associating Metal3Machines with the
53+
BareMetalHosts and for propagating back the relevant information to the
54+
Metal3Machine from the BareMetalHost.
55+
56+
### User Stories
57+
58+
#### Story 1
59+
60+
As an administrator of bare-metal resources, I want to be able to create
61+
separate pools of BareMetalHosts for different users so that they cannot
62+
interfere with each other.
63+
64+
#### Story 2
65+
66+
As an administrator of bare-metal resources, I want to be able to create common
67+
pools of BareMetalHosts that two or more users can collaborate on.
68+
69+
#### Story 3
70+
71+
As a user of CAPM3, I want to make use of the BareMetalHosts that another team
72+
has created and made available to me, without necessarily sharing the same
73+
cluster.
74+
75+
#### Story 4
76+
77+
As a one-man-show, I want to continue using the current single-tenant setup with
78+
in-cluster credentials for accessing the BareMetalHosts. This is especially
79+
important for bootstrapping a self-hosted management cluster.
80+
81+
### Implementation Details
82+
83+
The new Metal3Cluster field will be `.spec.identityRef` with sub-fields `name`
84+
and `context` (optional). The `name` should point to a secret in the same
85+
namespace as the Metal3Cluster, containing a kubeconfig file. The optional
86+
`context` should point to a context in the kubeconfig file. If the `context` is
87+
not specified, the current context will be used.
88+
89+
If the `identityRef` is not specified, CAPM3 should use in-cluster credentials
90+
for accessing the BareMetalHosts (current behavior).
91+
92+
CAPM3 should make use of the kubeconfig file to access the BareMetalHosts
93+
related to the Metal3Cluster. The kubeconfig file can point to a namespace in
94+
the same cluster or to a remote cluster. Secrets for metadata, networkdata and
95+
userdata must also be created next to the BareMetalHosts.
96+
97+
Example:
98+
99+
```yaml
100+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
101+
kind: Metal3Cluster
102+
metadata:
103+
name: cluster-1
104+
spec:
105+
identityRef:
106+
name: cluster-1-kubeconfig
107+
context: cluster-1-context
108+
```
109+
110+
The status of the Metal3Machine should be exteded with the information from the
111+
BareMetalHost. This is similar to how other providers work, as they propagate
112+
the relevant information from cloud resources back the the InfraMachine. For the
113+
Metal3Machine, we should add the following fields from the BareMetalHost:
114+
115+
- `.status.provisioning` on the BMH would become
116+
`.status.bareMetalHost.provisioning`
117+
- `.status.poweredOn` on the BMH would become `.status.bareMetalHost.poweredOn`
118+
- `.status.errorCount` on the BMH would become
119+
`.status.bareMetalHost.errorCount`
120+
- `.status.errorMessage` on the BMH would become
121+
`.status.bareMetalHost.errorMessage`
122+
- `.status.operationHistory` on the BMH would become
123+
`.status.bareMetalHost.operationHistory`
124+
- `.status.operationalStatus` on the BMH would become
125+
`.status.bareMetalHost.operationalStatus`
126+
127+
Fields related to the BMC credentials are not included, since they are only
128+
relevant for managing the BareMetalHost. Hardware details are also avoided since
129+
they are about to be removed from the BareMetalHost status now that we have a
130+
separate CRD (HardwareData) for them. We could think about propagating the
131+
information from the HardwareData or even copy the whole thing if deemed useful.
132+
133+
Note that the `.status.metaData` and `.status.userData` would be located in the
134+
same namespace and cluster as the BareMetalHost. The `.status.renderedData`
135+
on the other hand would be located in the same namespace as the Metal3Machine.
136+
137+
The status of the Metal3Cluster does not need to change. However, the Ready
138+
condition should be set only when CAPM3 has verified that the identityRef
139+
credentials are valid. Invalid credentials should result in an error on the
140+
Metal3Cluster.
141+
142+
Example Metal3Machine status:
143+
144+
```yaml
145+
status:
146+
# New fields
147+
bareMetalHost:
148+
provisioning:
149+
ID: f1e06671-6823-4676-9827-33efd7231c3f
150+
bootMode: legacy
151+
image:
152+
checksum: bed6ff0f7cde1edfd07e20aab324e406a9027b5cbf05c93fc10d7a7391ea0343
153+
checksumType: sha256
154+
format: raw
155+
url: http://192.168.222.1/ubuntu-2204-kube-v1.28.2.raw
156+
rootDeviceHints:
157+
deviceName: /dev/vda
158+
state: provisioned
159+
operationalStatus: OK
160+
errorCount: 0
161+
errorMessage: ""
162+
operationHistory:
163+
deprovision:
164+
end: null
165+
start: null
166+
inspect:
167+
end: "2024-05-17T10:58:28Z"
168+
start: "2024-05-17T10:55:47Z"
169+
provision:
170+
end: "2024-05-17T11:01:05Z"
171+
start: "2024-05-17T10:59:03Z"
172+
register:
173+
end: "2024-05-17T10:59:03Z"
174+
start: "2024-05-17T10:59:03Z"
175+
operationalStatus: OK
176+
# Existing fields
177+
addresses:
178+
- address: 192.168.222.100
179+
type: InternalIP
180+
- address: fe80::b331:705:526f:c2d8%enp1s0
181+
type: InternalIP
182+
- address: bmo-e2e-0
183+
type: Hostname
184+
- address: bmo-e2e-0
185+
type: InternalDNS
186+
conditions:
187+
- lastTransitionTime: "2024-05-17T11:01:35Z"
188+
status: "True"
189+
type: Ready
190+
- lastTransitionTime: "2024-05-17T10:59:02Z"
191+
status: "True"
192+
type: AssociateBMH
193+
- lastTransitionTime: "2024-05-17T11:01:35Z"
194+
status: "True"
195+
type: KubernetesNodeReady
196+
- lastTransitionTime: "2024-05-17T10:59:03Z"
197+
status: "True"
198+
type: Metal3DataReady
199+
lastUpdated: "2024-05-17T10:59:03Z"
200+
metaData:
201+
name: test-1-5jt87-metadata
202+
namespace: default
203+
ready: true
204+
renderedData:
205+
name: test-1-controlplane-template-0
206+
namespace: default
207+
userData:
208+
name: test-1-5jt87
209+
namespace: default
210+
```
211+
212+
### Risks & Mitigations
213+
214+
Considering that BareMetalHosts could be in a different cluster entirely, the
215+
move operation will be more complex. BareMetalHosts in external clusters should
216+
not be moved at all. BareMetalHosts in the same namespace and cluster should be
217+
handled as usual. An open question is how to handle BareMetalHosts in a
218+
different namespace.
219+
220+
In practice this is not really a Metal3 concern since it is a CAPI feature that
221+
we are using. CAPI will only move the CAPI/CAPM3 resources and other resources
222+
that are labeled to be moved. We will need to document it properly though so
223+
that users knows what to expect and in which cases the move operation will work.
224+
225+
### Work Items
226+
227+
- Add the new `identityRef` field to the Metal3Cluster resource and update CAPM3
228+
to make use of it.
229+
- Add E2E test (or modify existing test to use the new field).
230+
- Update documentation.
231+
232+
## Dependencies
233+
234+
None
235+
236+
## Test Plan
237+
238+
- Unit tests
239+
- At least one E2E test should use the new field and at least one E2E test
240+
should use in-cluster credentials.
241+
242+
## Upgrade / Downgrade Strategy
243+
244+
It will not be possible to downgrade to a version without support for the new
245+
field when making use of the new field.
246+
247+
## Drawbacks
248+
249+
None
250+
251+
## Alternatives
252+
253+
- Handle multi-tenancy through namespace isolation with a single cluster-wide
254+
CAPM3 instance. Users cannot share a BMH pool without working in the same
255+
namespace. The cluster-wide CAPM3 instance would have access to all the
256+
BareMetalHosts.
257+
- Handle multi-tenancy through namespace isolation with per namespace CAPM3
258+
instances. This is impractical since all CAPM3 instances would need to be of
259+
the same version (since CRDs are global). The same issue goes for per
260+
namespace BMO instances. Users cannot share a BMH pool without working in the
261+
same namespace.
262+
263+
None of these alternatives provide any way of separating the BareMetalHosts from
264+
the Metal3Machines.
265+
266+
- The `identityRef` field could allow referencing different kinds of credentials
267+
also. For example, a service account token. This may be simpler for users
268+
sharing a cluster, but it would not be possible to reference other clusters. A
269+
kubeconfig file covers all the use cases with a slight increase in complexity
270+
for same-cluster access and is therefore preferred.
271+
272+
## References
273+
274+
1. [CAPI multi-tenancy
275+
contract](https://cluster-api.sigs.k8s.io/developer/architecture/controllers/multi-tenancy#contract)

0 commit comments

Comments
 (0)