You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently controllers that use `controller-runtime` need to configure the `ctrl.Manager` by using flags or hard coding values into the initialization methods. Core Kubernetes has started to move away from using flags as a mechanism for configuring components and standardized along the pattern of [`ComponentConfig` or Versioned Component Configuration Files](https://docs.google.com/document/d/1FdaEJUEh091qf5B98HM6_8MS764iXrxxigNIdwHYW9c/edit). This proposal is to bring `ComponentConfig` patterns into `controller-runtime` to allow controller authors to make `go` types backed by apimachinery to unmarshal and configure the `ctrl.Manager` reducing the flags and allowing code based tools to easily configure controllers instead of requiring them to mutate CLI args.
34
+
Currently controllers that use `controller-runtime` need to configure the `ctrl.Manager` by using flags or hardcoding values into the initialization methods. Core Kubernetes has started to move away from using flags as a mechanism for configuring components and standardized along the pattern of [`ComponentConfig` or Versioned Component Configuration Files](https://docs.google.com/document/d/1FdaEJUEh091qf5B98HM6_8MS764iXrxxigNIdwHYW9c/edit). This proposal is to bring `ComponentConfig` patterns into `controller-runtime` to allow controller authors to make `go` types backed by `apimachinery` to unmarshal and configure the `ctrl.Manager` reducing the flags and allowing code based tools to easily configure controllers instead of requiring them to mutate CLI args.
32
35
33
36
34
37
## Motivation
35
38
36
39
This change is important because:
37
40
- it will help make it easier for controllers to be configured by other machine processes
38
-
- it will reduce the upfront flags required to start a controller
41
+
- it will reduce the required flags required to start a controller
39
42
- allow for more configuration types which flags don't natively support
40
43
- allow using and upgrading older configurations avoiding breaking changes in flags
41
44
42
45
### Links to Open Issues
43
46
44
-
-[Provide a ComponentConfig to tweak the Manager](https://github.com/kubernetes-sigs/controller-runtime/issues/518)
45
-
-[Reduce command line flag boilerplate](https://github.com/kubernetes-sigs/controller-runtime/issues/207)
46
-
-[Implement ComponentConfig by default & stop using (most) flags](https://github.com/kubernetes-sigs/kubebuilder/issues/722)
47
+
-[#518Provide a ComponentConfig to tweak the Manager](https://github.com/kubernetes-sigs/controller-runtime/issues/518)
48
+
-[#207Reduce command line flag boilerplate](https://github.com/kubernetes-sigs/controller-runtime/issues/207)
49
+
-[#722Implement ComponentConfig by default & stop using (most) flags](https://github.com/kubernetes-sigs/kubebuilder/issues/722)
47
50
48
51
### Goals
49
52
50
53
- Provide an interface for pulling configuration data out of exposed `ComponentConfig` types (see below for implementation)
51
54
- Provide a new `ctrl.NewFromComponentConfig()` function for initializing a manager
55
+
- Provide a `DefaultControllerConfig` to make the switch easier
52
56
53
57
### Non-Goals/Future Work
54
58
55
59
-`kubebuilder` implementation and design in another PR
56
60
- Changing the default `controller-runtime` implementation
57
61
- Dynamically reloading ComponentConfig object
62
+
- Providing `flags` interface and overrides
58
63
59
64
## Proposal
60
65
@@ -90,18 +95,22 @@ type ManagerConfiguration interface {
To enable `controller-runtime` to have a default `ComponentConfig` struct which can be used instead of requiring each controller or extension to build it's own `ComponentConfig` type, we can create a `DefaultControllerConfiguration` type which can exist in `pkg/api/v1alpha1/types.go`. This will allow the controller authors to use this before needing to implement their own type with additional configs.
This would allow a controller author to use this struct with any config that supports the json/yaml structure. For example a controller author could define their `Kind` as `FoobarControllerConfiguration` and have it defined as the following.
170
+
171
+
```yaml
172
+
# config.yaml
173
+
apiVersion: somedomain.io/v1alpha1
174
+
kind: FoobarControllerConfiguration
175
+
spec:
176
+
port: 9443
177
+
metricsBindAddress: ":8080"
178
+
leaderElection:
179
+
leaderElect: false
180
+
```
181
+
182
+
Given the following config and `DefaultControllerConfiguration` we'd be able to initialize the controller using the following.
The above example uses `configname` which is the name of the file to load the configuration from and uses `scheme` to get the specific serializer, eg `serializer.NewCodecFactory(scheme)`. This will allow the configuration to be unmarshalled into the `runtime.Object` type and passed into the
193
+
`ctrl.NewManagerFromComponentConfig()`as a `ManagerConfiguration` interface.
194
+
195
+
##### Caveats
196
+
197
+
> ⚠️ Using `DecodeComponentConfigFileInto` does not support the overrides for flags, this is something that is left up to the controller author since they could be using many different flagging interfaces. eg [`flag`](https://golang.org/pkg/flag/), [`pflag`](https://godoc.org/github.com/spf13/pflag), [`flagnum`](https://godoc.org/github.com/luci/luci-go/common/flag/flagenum) and `controller-runtime` should be agnostic to the CLI implementation.
198
+
199
+
#### Kubebuilder Scaffolding Example
200
+
114
201
Within a separate design (link once created) this will require controller authors to generate a type that implements the `ManagerConfiguration` interface. The following is a sample of what this looks like:
@@ -194,29 +272,29 @@ func (in *ControllerNameConfiguration) GetCertDir() string {}
194
272
195
273
Besides the implementation of the `ComponentConfig` The controller author as it stands would also need to implement the unmarshalling of the `ConfigMap` into the `ComponentConfig`, for this `controller-runtime` could expose helper methods to load a file from disk, unmarshal to the struct and pass the pointer into the `NewFromComponentConfig()` to return the `ctrl.Manager`
196
274
197
-
###User Stories
275
+
## User Stories
198
276
199
-
####Controller Author with `controller-runtime`
277
+
### Controller Author with `controller-runtime`
200
278
201
279
- Implement `ComponentConfig` type
202
280
- Implement `ManagerConfiguration` interface for `ComponentConfig` object
203
281
- Set up `ConfigMap` unmarshalling into `ComponentConfig` type
204
282
- Initialize `ctrl.Manager` with `NewFromComponentConfig`
205
283
- Build custom controller as usual
206
284
207
-
####Controller Author with `kubebuilder` (tbd proposal for `kubebuilder`)
285
+
### Controller Author with `kubebuilder` (tbd proposal for `kubebuilder`)
208
286
209
287
- Initialize `kubebuilder` project using `--component-config-name=XYZConfiguration`
210
288
- Build custom controller as usual
211
289
212
-
####Controller User without modifications to config
290
+
### Controller User without modifications to config
213
291
214
292
_Provided that the controller provides manifests_
215
293
216
294
- Apply the controller to the cluster
217
295
- Deploy custom resources
218
296
219
-
####Controller User with modifications to config
297
+
### Controller User with modifications to config
220
298
221
299
-_Following from previous example without changes_
222
300
- Create a new `ConfigMap` for changes
@@ -225,19 +303,19 @@ _Provided that the controller provides manifests_
225
303
- Deploy custom resources
226
304
227
305
228
-
###Risks and Mitigations
306
+
## Risks and Mitigations
229
307
230
308
- Given that this isn't changing the core Manager initialization for `controller-runtime` it's fairly low risk
231
-
- If the underlaying `ctrl.Options{}`
232
309
233
310
## Alternatives
234
311
235
-
*`NewFromComponentConfig()` could load the object from disk and hydrate the `ComponentConfig` type
312
+
*`NewFromComponentConfig()` could load the object from disk based on the file name and hydrate the `ComponentConfig` type.
236
313
237
314
## Implementation History
238
315
239
316
-[x] 02/19/2020: Proposed idea in an issue or [community meeting]
240
317
-[x] 02/24/2020: Proposal submitted to `controller-runtime`
318
+
-[x] 03/02/2020: Updated with default `DefaultControllerConfiguration`
0 commit comments