1. Introduction
The ConfigSeeder® Admission Controller is a Mutating Kubernetes Admission Controller that can automatically inject one of the ConfigSeeder Connectors in a kubernetes object at creation time.
Manually configuring these connectors can be laborious and in some cases nearly impossible (for example if you use Helm Charts that are provided by a 3rd party).
The ConfigSeeder Admission Controller simplifies injecting connectors. This documentation describes:
-
How to set up the ConfigSeeder Admission Controller
-
How to let the ConfigSeeder Admission Controller inject Connectors in various Kubernetes objects
Be aware that the ConfigSeeder® Admission Controller is currently in the status of a technical preview and should not be used in production. |
1.1. Supported Kubernetes objects
The ConfigSeeder® Admission Controller can inject the connectors in different Kubernetes objects:
-
CronJob (Creation of the CronJob, Job, or Pod)
-
Deployment (Creation of the Deployment or Pod)
-
Job (Creation of the Job or Pod)
-
Pod (Creation of the Pod, regardless of the owner ressource)
-
StatefulSet (Creation of the StatefulSet or Pod)
1.2. Preconditions
The following preconditions must be met so that the admission controller can be used:
-
Basic ConfigSeeder® installation must be up and running (ConfigSeeder Management)
-
The ConfigSeeder extension Kubernetes Connector must be licensed
-
Permission to deploy a mutating webhook configuration (See setting up the Mutation Webhook Configuration)
2. Admission Controller Configuration
2.1. Configuration of the injected connectors
2.1.1. Concept
2.1.2. Global / Admission Controller wide options
The ConfigSeeder Admission Controller can be configured by the following options:
All keys are prefixed with |
Key | Mandatory | Value |
---|---|---|
|
yes |
Read timeout for accessing ConfigSeeder, used by the injected containers. Defaults to |
|
yes |
Connection timeout for accessing ConfigSeeder, used by the injected containers.. Defaults to |
|
yes |
URL of the ConfigSeeder, used by the injected containers. |
|
no |
Key of the ConfigSeeder tenant to access, used by the injected containers. Defaults to `default'. |
|
yes |
Image of the Kubernetes Connector that should be injected into the pods. |
|
yes |
Image of the OS Connector that should be injected into the pods. |
|
no |
Name of the logfile, the controller should write, used by the injected containers.
Only relevant if togeter with log target Defaults to |
|
no |
Flag to define if the log output should be formatted as Defaults to |
|
no |
Log Level used by the controller, used by the injected containers. Defaults to |
|
no |
Log Level used by the controller, used by the injected containers.
Defaults to |
2.1.3. Options configurable per pod/deployment
2.1.3.1. Labels
Key | Mandatory | Value |
---|---|---|
|
yes |
Read timeout for accessing ConfigSeeder, used by the injected containers. |
2.1.3.2. Annotations
All keys are prefixed with |
Key | Mandatory | Connector | Value |
---|---|---|---|
|
no |
All |
Name of the Secret holding the API Key required for accessing ConfigSeeder. Defaults to
|
|
no |
All |
Name of the ConfigMap holding the certificates for verifying the TLS connection to ConfigSeeder. Only required if
No default, if the annotation is not present, no additional certificates will be injected |
|
no |
All |
Name of the ConfigMap holding the configuration for the injected connector. No default. As an alternative, the configuration group(s), environment and other configuration can be provided with dedicated annotations. |
|
no |
All |
Key(s) of the configuration group that should be read by the injected connector. This annotations should only be used if no |
|
no |
All |
Key of the environment that should be read by the injected connector. This annotations should only be used if no |
|
no |
All |
Log level that should be used by the injected connector. This annotations should only be used if no |
|
no |
Kubernetes |
Name of the configmap in which the state of the kubernetes connector will be stored. Defaults to |
|
no |
Kubernetes |
Namespace which the ConfigMap holding the state of the kubernetes connector will be stored. Defaults to the current namespace |
|
no |
OS |
Location, where the OS Connector should inject data to. A volume of type emptydir is created together with volumeMounts to the specified location for all containers listed in the pod. Defaults to |
3. Installation
3.1. Overview
The installation of the ConfigSeeder® Admission Controller consists of two parts:
-
Deploy the Admission Controller
-
Setup the Mutating Webhook Configuration (tell Kubernetes to use the Admission Controller)
3.2. Deploy the ConfigSeeder® Admission Controller
The easiest way to deploy the Admission Controller is to use the provided Helm Charts:
-
Get the Helm Charts from https://configseeder.com/download/
-
Provide a
admission-controller-values.yaml
with the following content:(Only required if the defaults should be overwritten)
admissionController: configseeder: url: "https://configseeder-management.cs-demo-management-h2.svc:8443" tenantKey: "default" # images and it's subproperties define which image & version of the connectors should be injected images: kubernetesConnector: "configseeder/kubernetes-connector/kubernetes-connector:1.3.4-alpine" osConnector: "configseeder/os-connector/linux-connector:1.1.4-alpine"
-
Create a rsa key and server certificate for the admission controller
-
Add the following SAN:
-
admission-controller.configseeder-admission-controller.svc.cluster.local
-
admission-controller.configseeder-admission-controller.svc
-
-
Store the key and certificate in a Secret of type TLS and name
tls-secret
in the namespaceconfigseeder-admission-controller
kubectl -n configseeder-admission-controller create secret tls tls-secret --cert="admission-controller-crt.pem" --key="admission-controller-key.pem" --dry-run=client -o yaml | kubectl -n configseeder-admission-controller apply -f -
-
-
Install the Chart using the following command:
helm -n "configseeder-admission-controller" upgrade -i "admission-controller" "configseeder-admission-controller-version.tar.gz" --values-admission-controller.yaml
3.3. Setting up the Mutation Webhook Configuration
The following snippet shows the mutating webhook configuration for the ConfigSeeder® Admission Controller:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: configseeder-admission-controller
webhooks:
- name: "admission-controller.configseeder.com"
objectSelector:
matchExpressions:
- key: admissioncontroller.configseeder.com/injectConnector
operator: In
values: [ "kubernetes-connector", "os-connector" ]
rules:
- apiGroups: [ "apps" ]
apiVersions: [ "v1" ]
operations: [ "CREATE" ]
resources: [ "deployments", "statefulsets" ]
scope: Namespaced
- apiGroups: [ "batch" ]
apiVersions: [ "v1", "v1beta1" ]
operations: [ "CREATE" ]
resources: [ "cronjobs", "jobs" ]
scope: Namespaced
- apiGroups: [ "" ]
apiVersions: [ "v1" ]
operations: [ "CREATE" ]
resources: [ "pods" ]
scope: "Namespaced"
clientConfig:
caBundle: REPLACE_WITH_BASE64_ENCODED_CERTIFICATE
service:
namespace: configseeder-admission-controller
name: admission-controller
path: /mutate
admissionReviewVersions: [ "v1", "v1beta1" ]
sideEffects: None
timeoutSeconds: 1
Setup Instructions:
-
Get the certificate used to sign the admission controller certificate
-
Encode the certificate using base64 (cat rootca.crt | base64 -w0)
-
Replace
REPLACE_WITH_BASE64_ENCODED_CERTIFICATE
with the encoded certificate -
Deploy the mutating webhook configuration (
kubectl apply -f configseeder-admission-controller.yaml
)
4. Examples for injecting the connectors
4.1. Generic examples
4.1.1. Preconditions
In the examples below, the following assumptions apply:
-
The Connectors will
-
be configured by the ConfigMap
connector
-
use the certificates stored in the ConfigMap
connector-certificates
for verifying the TLS connection to the ConfigSeeder -
use the api key stored in the ConfigMap
connector-apikey
to access ConfigSeeder
-
-
A connector of type
os-connector
(linux connector) will be injected (it works the same for the kubernetes connector)
4.1.2. Inject when creating a Pod
The Admission Controller can inject a connector whenever a new pod is created (and regardless of the owner of the pod).
The following example shows how to configure a pod so that a linux connector is injected as init-container:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
The Admission Controller will be activated because of the label admissioncontroller.configseeder.com/injectConnector
and inject the os-connector
.
The resulting pod will look something like this:
apiVersion: v1
kind: Pod
metadata:
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
...
name: my-pod
...
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
volumeMounts:
- mountPath: /data
name: injected-config
readOnly: true
...
initContainers:
- env:
- name: CONNECTOR_CONFIGSEEDER_APIKEY
valueFrom:
secretKeyRef:
key: apiKey
name: connector-apikey-test
optional: false
- name: CONNECTOR_FILEPROPERTIES_PATHPREFIX
value: /data
- name: CONNECTOR_CONFIGSEEDER_SERVERURL
value: https://configseeder-management.cs-demo-management-h2.svc:8443
- name: CONNECTOR_CONFIGSEEDER_TENANTKEY
value: default
- name: CONNECTOR_CONFIGSEEDER_CONNECTIONTIMEOUT
value: "10000"
- name: CONNECTOR_CONFIGSEEDER_READTIMEOUT
value: "10000"
- name: CONNECTOR_CONFIGSEEDER_CERTIFICATEFILENAME
value: /certificates.pem
envFrom:
- configMapRef:
name: connector-test
optional: false
image: registry.gitlab.com/configseeder/os-connector/linux-connector:staging-alpine
imagePullPolicy: Always
name: os-connector
resources:
limits:
cpu: 500m
memory: 100Mi
requests:
cpu: 50m
memory: 10Mi
volumeMounts:
- mountPath: /data
name: injected-config
- mountPath: /certificates.pem
name: connector-certificate-volume
readOnly: true
subPath: certificates.pem
...
volumes:
- configMap:
defaultMode: 420
name: connector-certificates-test
optional: false
name: connector-certificate-volume
- emptyDir: {}
name: injected-config
...
4.1.3. Injecting connectors to Deployments, Jobs, and StatefulSets
The Admission Controller can inject a connector whenever a new Deployment, Job or StatefulSet is created or whenever a pod is created because of one of the mentioned kubernetes objects.
4.1.3.1. Inject connectors at kubernetes object creation time
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
app.kubernetes.io/name: my-deployment
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: my-deployment
template:
metadata:
labels:
app.kubernetes.io/name: my-deployment
spec:
restartPolicy: Always
containers:
- name: alpine
image: alpine
imagePullPolicy: Always
command: ["/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
4.1.3.2. Inject connectors at Pod creation time
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
labels:
app.kubernetes.io/name: my-deployment
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: my-deployment
template:
metadata:
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
spec:
restartPolicy: Always
containers:
- name: alpine
image: alpine
imagePullPolicy: Always
command: ["/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
4.1.4. Inject when creating a CronJob
The Admission Controller can inject a connector whenever a new CronJob is created or whenever a pod is created because of the CronJob.
4.1.4.1. Inject connectors at CronJob creation time
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: my-cronjob
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels:
# without this label, the `admissioncontroller.configseeder.com/injectConnector` label is set. Kubernetes bug?
just: a-label
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 604800
template:
metadata:
spec:
# Don't restart if an error occures
restartPolicy: Never
containers:
- name: alpine
image: alpine
imagePullPolicy: Always
4.1.4.2. Inject connectors at Pod creation time
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: my-cronjob
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels:
# without this label, the `admissioncontroller.configseeder.com/injectConnector` label is set. Kubernetes bug?
just: a-label
spec:
metadata:
annotations:
admissioncontroller.configseeder.com/injectApiKeySecret: connector-apikey
admissioncontroller.configseeder.com/injectConfigMap: connector
admissioncontroller.configseeder.com/injectConfigMapCertificates: connector-certificates
admissioncontroller.configseeder.com/injectPathPrefix: /data
labels:
admissioncontroller.configseeder.com/injectConnector: os-connector
backoffLimit: 0
ttlSecondsAfterFinished: 604800
template:
metadata:
spec:
# Don't restart if an error occures
restartPolicy: Never
containers:
- name: alpine
image: alpine
imagePullPolicy: Always
4.2. Real world examples
4.2.1. Inject configuration data in an existing application
4.2.1.1. Situation
-
Configuration Data should be provided to an application
-
The application is installed via a Helm Chart
-
The Helm Chart shouldn’t be modified or can’t be modified
-
There is a ConfigSeeder® Setup with ConfigSeeder Management and the Admission Controller up and running
4.2.1.2. Solution
Depending on the exact requirements (and how the Helm Chart of the application is built), there are different solutions:
-
Provide Configuration Files via OS Connector by setting the Admission Controller label and annotations to the Chart
-
Provide ConfigMaps & Secrets via Kubernetes Connector running as a Helm pre-* Hook Job
Solution | Description |
---|---|
1 |
Provide Configuration Files via OS Connector by setting the Admission Controller label and annotations to the Chart Preconditions:
Solution description:
The custom labels and annotations will look something like this:
|
2 |
Provide ConfigMaps & Secrets via Kubernetes Connector running as a Helm pre-* Hook Job Preconditions:
Solution description:
The Job could look like this:
The custom labels and annotations will look something like this:
|