Q: How can I access the events which triggered the Reconciliation?
In the v1.* version events were exposed to Reconciler
(which was called ResourceController
then). This included events (Create, Update) of the custom resource, but also events produced by
Event Sources. After long discussions also with developers of golang version (controller-runtime),
we decided to remove access to these events. We already advocated to not use events in the
reconciliation logic, since events can be lost. Instead, reconcile all the resources on every
execution of reconciliation. On first this might sound a little opinionated, but there is a
sound agreement between the developers that this is the way to go.
Note that this is also consistent with Kubernetes level based reconciliation approach.
Q: Can I re-schedule a reconciliation, possibly with a specific delay?
Yes, this can be done
using UpdateControl
and DeleteControl
, see:
@Override
public UpdateControl<MyCustomResource> reconcile(
EventSourceTestCustomResource resource, Context context) {
...
return UpdateControl.patchStatus(resource).rescheduleAfter(10, TimeUnit.SECONDS);
}
without an update:
@Override
public UpdateControl<MyCustomResource> reconcile(
EventSourceTestCustomResource resource, Context context) {
...
return UpdateControl.<MyCustomResource>noUpdate().rescheduleAfter(10, TimeUnit.SECONDS);
}
Although you might consider using EventSources
, to handle reconciliation triggering in a smarter
way.
Q: How can I run an operator without cluster scope rights?
By default, JOSDK requires access to CRs at cluster scope. You may not be granted such rights and you will see some error at startup that looks like:
io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: GET at: https://kubernetes.local.svc/apis/mygroup/v1alpha1/mycr. Message: Forbidden! Configured service account doesn't have access. Service account may have been revoked. mycrs.mygroup is forbidden: User "system:serviceaccount:ns:sa" cannot list resource "mycrs" in API group "mygroup" at the cluster scope.
To restrict the operator to a set of namespaces, you may override which namespaces are watched by a reconciler at Reconciler-level configuration:
Operator operator;
Reconciler reconciler;
...
operator.register(reconciler, configOverrider ->
configOverrider.settingNamespace("mynamespace"));
Note that configuring the watched namespaces can also be done using the @ControllerConfiguration
annotation.
Furthermore, you may not be able to list CRDs at startup which is required when checkingCRDAndValidateLocalModel
is true
(false
by default). To disable, set it to false
at Operator-level configuration:
Operator operator = new Operator( override -> override.checkingCRDAndValidateLocalModel(false));
Q: I’m managing an external resource that has a generated ID, where should I store that?
It is common that a non-Kubernetes or external resource is managed from a controller. Those external resources might have a generated ID, so are not simply addressable based on the spec of a custom resources. Therefore, the generated ID needs to be stored somewhere in order to address the resource during the subsequent reconciliations.
Usually there are two options you can consider to store the ID:
- Create a separate resource (usually ConfigMap, Secret or dedicated CustomResource) where you store the ID.
- Store the ID in the status of the custom resource.
Note that both approaches are a bit tricky, since you have to guarantee the resources are cached for the next
reconciliation. For example if you patch the status at the end of the reconciliation (UpdateControl.patchStatus(...)
)
it is not guaranteed that during the next reconciliation you will see the fresh resource. Therefore, controllers
which do this, usually cache the updated status in memory to make sure it is present for next reconciliation.
Dependent Resources feature supports the first approach.
Q: How to fix sun.security.provider.certpath.SunCertPathBuilderException
on Rancher Desktop and k3d/k3s Kubernetes
It’s a common issue when using k3d and the fabric8 client tries to connect to the cluster an exception is thrown:
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:352)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:295)
The cause is that fabric8 kubernetes client does not handle elliptical curve encryption by default. To fix this, add the following dependency on the classpath:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>