Metacontroller Integration¶
Supported: from version v0.29.0
Alpha Feature
Metacontroller is an add-on for Kubernetes that makes it easy to write and deploy custom controllers.
For a more detailed explanation of how Metacontroller works and the many options of controllers it support please read the Upstream Documentation
Kubecfg
integrates with Metacontroller by exposing an httpd
endpoint that accept POSTs
from the metacontroller and respond with the expected JSON object.
By leveraging kubecfg
to produce the response you can use all the extra features provided on top of standard jsonnet.
Example usage¶
The following example will use code from metacontroller-example
Overview¶
kubecfg
supports exposing individual .jsonnet
files over https as hooks by rendering the TopLevelFunction
in those jsonnet files as expected by the metacontroller
the functionality is exposed by running kubecfg --alpha httpd <jsonnet files>
- each jsonnet file must expose a
TopLevelFunction
with arequest parameter
that will be called by kubecfg when the hook is called with aPOST
kubecfg --alpha httpd sync.jsonnet
- will expose on port:8080/sync
theTopLevelFunction
defined in thesync.jsonnet
kubecfg --alpha httpd sync-pods.jsonnet sync-services.jsonnet
- will expose multiple endpoints:8080/sync-pods
and:8080/sync-jsonnet
calling each individial TLF for each files
See sync.jsonnet in the metacontroller
example for a working example
Flow Diagram¶
sequenceDiagram
autonumber
kubectl->>apiserver: Post CR Instance
loop Validation
apiserver->>apiserver: Validate CR vs CRD
end
loop ETCd
apiserver->>apiserver: CR Persisted
end
metacontroller->>apiserver: Watch for instances of CRD
Note right of metacontroller: CompositeController defines hooks
metacontroller->>kubecfg-httpd: POST request to kubecfg-httpd
Note right of kubecfg-httpd: kubecfg render json response
kubecfg-httpd-->>metacontroller: response with manifests to create
metacontroller-->>apiserver: Manifests to Create
Create base cluster¶
Create a kind cluster using the provided Makefile
in the examples directory
➜ cd examples/metacontroller
➜ make kind
...
➜ kubectl rollout status --timeout 180s -n metacontroller statefulset/metacontroller
partitioned roll out complete: 1 new pods have been updated...
Kubecfg Controller¶
Create the example useless-controller
➜ make controller
➜ kubectl rollout status --timeout 180s -n metacontroller deployment/useless-controller
deployment "useless-controller" successfully rolled out
this Controller uses the CRD defined in v1/crdv1.yaml
( from api/types.go
) and the compositeController
defined in the manifests
directory
CompositeController
---
apiVersion: metacontroller.k8s.io/v1alpha1
kind: CompositeController
metadata:
name: useless-controller
spec:
generateSelector: true
parentResource:
apiVersion: example.com/v1
resource: uselesspods
revisionHistory:
fieldPaths:
- spec.name
childResources:
- apiVersion: apps/v1
resource: deployments
updateStrategy:
method: InPlace
hooks:
sync:
webhook:
url: http://useless-controller.metacontroller/sync
the compositeController defines how the metacontroller
will watch
for example.com/v1/uselesspods
resources and post the request, with the CR specs, to the kubecfg httpd
controller which will execute the sync.jsonnet
code
sync.jsonnet hook¶
the code of the hook can be examined in the examples directory sync.jsonnet
the hook must have a Top Level Function
which is executed on each POST
passing the request body
as json
local process = function(request) {
...
...
deployment:: { ... },
resyncAfterSeconds: 30.0,
status: {
observedGeneration: std.get(request.parent.metadata, 'generation', 0),
ready: if std.length(std.objectFields(request.children)) > 0 then 'true' else 'false',
},
children: [
$.deployment,
],
}
//Top Level Function
function(request)
local response = process(request);
std.trace('request: ' + std.manifestJsonEx(request, ' ') + '\n\nresponse: ' + std.manifestJsonEx(response, ' '), response)
every object returned in the children
key will be applied to Kubernetes by the metacontroller
Example¶
When an instance of the UselessPod
is created
- ApiServer will validate the
CR
against theCRD
definition - Persist the
CR
in etcd - Metacontroller watches the
UselessPods
CRs
- when an event on a watched CR is observed a
POST request
will be sent by themetacontroller
to theuseless-controller
with the CR as part of the request - the
useless-controller
will runkubecfg
on thesync.jsonnet
codeTop Level Function
using the request as parameter - the
response
to the metacontroller will include adeployment
in thechildren
field - the metacontroller will
apply
thechildren resources
( the deployment ) to the apiserver - kubernetes will create the generated deployment
➜ cat << EOF | kubectl apply -f -
apiVersion: "example.com/v1"
kind: UselessPod
metadata:
name: test1
namespace: default
spec:
name: instance1
EOF
uselesspod.example.com/test1 created
➜ kubectl rollout status -n default deployment/useless-instance1
deployment "useless-instance1" successfully rolled out
Cleanup¶
➜ make clean