mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: add cleanup controller to helm chart (#5329)
* feat: add cleanup controller to helm chart Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * add webhook config Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * rbac Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fixes Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * secret Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * certs Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix labels Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * add server Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * rbac Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * handler Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix linter Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
511eb797e6
commit
86fc537ce0
15 changed files with 526 additions and 5 deletions
28
Makefile
28
Makefile
|
@ -236,6 +236,7 @@ ko-build-all: ko-build-kyvernopre ko-build-kyverno ko-build-cli ko-build-cleanup
|
||||||
REGISTRY_USERNAME ?= dummy
|
REGISTRY_USERNAME ?= dummy
|
||||||
KO_KYVERNOPRE_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/initcontainer
|
KO_KYVERNOPRE_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/initcontainer
|
||||||
KO_KYVERNO_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/kyverno
|
KO_KYVERNO_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/kyverno
|
||||||
|
KO_CLEANUP_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/cleanup-controller
|
||||||
|
|
||||||
.PHONY: ko-login
|
.PHONY: ko-login
|
||||||
ko-login: $(KO)
|
ko-login: $(KO)
|
||||||
|
@ -253,6 +254,10 @@ ko-publish-kyverno: ko-login ## Build and publish kyverno image (with ko)
|
||||||
ko-publish-cli: ko-login ## Build and publish cli image (with ko)
|
ko-publish-cli: ko-login ## Build and publish cli image (with ko)
|
||||||
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLI) $(KO) build $(CLI_DIR) --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS)
|
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLI) $(KO) build $(CLI_DIR) --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS)
|
||||||
|
|
||||||
|
.PHONY: ko-publish-cleanup-controller
|
||||||
|
ko-publish-cleanup-controller: ko-login ## Build and publish cleanup controller image (with ko)
|
||||||
|
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLEANUP) $(KO) build $(CLEANUP_DIR) --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS)
|
||||||
|
|
||||||
.PHONY: ko-publish-kyvernopre-dev
|
.PHONY: ko-publish-kyvernopre-dev
|
||||||
ko-publish-kyvernopre-dev: ko-login ## Build and publish kyvernopre dev image (with ko)
|
ko-publish-kyvernopre-dev: ko-login ## Build and publish kyvernopre dev image (with ko)
|
||||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_KYVERNOPRE) $(KO) build $(KYVERNOPRE_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_KYVERNOPRE) $(KO) build $(KYVERNOPRE_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||||
|
@ -265,11 +270,15 @@ ko-publish-kyverno-dev: ko-login ## Build and publish kyverno dev image (with ko
|
||||||
ko-publish-cli-dev: ko-login ## Build and publish cli dev image (with ko)
|
ko-publish-cli-dev: ko-login ## Build and publish cli dev image (with ko)
|
||||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLI) $(KO) build $(CLI_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLI) $(KO) build $(CLI_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||||
|
|
||||||
|
.PHONY: ko-publish-cleanup-controller-dev
|
||||||
|
ko-publish-cleanup-controller-dev: ko-login ## Build and publish cleanup controller dev image (with ko)
|
||||||
|
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLEANUP) $(KO) build $(CLEANUP_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||||
|
|
||||||
.PHONY: ko-publish-all
|
.PHONY: ko-publish-all
|
||||||
ko-publish-all: ko-publish-kyvernopre ko-publish-kyverno ko-publish-cli ## Build and publish all images (with ko)
|
ko-publish-all: ko-publish-kyvernopre ko-publish-kyverno ko-publish-cli ko-publish-cleanup-controller ## Build and publish all images (with ko)
|
||||||
|
|
||||||
.PHONY: ko-publish-all-dev
|
.PHONY: ko-publish-all-dev
|
||||||
ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-cli-dev ## Build and publish all dev images (with ko)
|
ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-cli-dev ko-publish-cleanup-controller-dev ## Build and publish all dev images (with ko)
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# BUILD (IMAGE) #
|
# BUILD (IMAGE) #
|
||||||
|
@ -277,6 +286,7 @@ ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-
|
||||||
|
|
||||||
LOCAL_KYVERNOPRE_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNOPRE_IMAGE)
|
LOCAL_KYVERNOPRE_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNOPRE_IMAGE)
|
||||||
LOCAL_KYVERNO_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNO_IMAGE)
|
LOCAL_KYVERNO_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNO_IMAGE)
|
||||||
|
LOCAL_CLEANUP_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_CLEANUP_IMAGE)
|
||||||
|
|
||||||
.PHONY: image-build-kyvernopre
|
.PHONY: image-build-kyvernopre
|
||||||
image-build-kyvernopre: $(BUILD_WITH)-build-kyvernopre
|
image-build-kyvernopre: $(BUILD_WITH)-build-kyvernopre
|
||||||
|
@ -287,6 +297,9 @@ image-build-kyverno: $(BUILD_WITH)-build-kyverno
|
||||||
.PHONY: image-build-cli
|
.PHONY: image-build-cli
|
||||||
image-build-cli: $(BUILD_WITH)-build-cli
|
image-build-cli: $(BUILD_WITH)-build-cli
|
||||||
|
|
||||||
|
.PHONY: image-build-cleanup-controller
|
||||||
|
image-build-cleanup-controller: $(BUILD_WITH)-build-cleanup-controller
|
||||||
|
|
||||||
.PHONY: image-build-all
|
.PHONY: image-build-all
|
||||||
image-build-all: $(BUILD_WITH)-build-all
|
image-build-all: $(BUILD_WITH)-build-all
|
||||||
|
|
||||||
|
@ -651,13 +664,20 @@ kind-load-kyverno: $(KIND) image-build-kyverno ## Build kyverno image and load i
|
||||||
@echo Load kyverno image... >&2
|
@echo Load kyverno image... >&2
|
||||||
@$(KIND) load docker-image --name $(KIND_NAME) $(LOCAL_KYVERNO_IMAGE):$(IMAGE_TAG_DEV)
|
@$(KIND) load docker-image --name $(KIND_NAME) $(LOCAL_KYVERNO_IMAGE):$(IMAGE_TAG_DEV)
|
||||||
|
|
||||||
|
.PHONY: kind-load-cleanup-controller
|
||||||
|
kind-load-cleanup-controller: $(KIND) image-build-cleanup-controller ## Build cleanup controller image and load it in kind cluster
|
||||||
|
@echo Load cleanup controller image... >&2
|
||||||
|
@$(KIND) load docker-image --name $(KIND_NAME) $(LOCAL_CLEANUP_IMAGE):$(IMAGE_TAG_DEV)
|
||||||
|
|
||||||
.PHONY: kind-load-all
|
.PHONY: kind-load-all
|
||||||
kind-load-all: kind-load-kyvernopre kind-load-kyverno ## Build images and load them in kind cluster
|
kind-load-all: kind-load-kyvernopre kind-load-kyverno kind-load-cleanup-controller ## Build images and load them in kind cluster
|
||||||
|
|
||||||
.PHONY: kind-deploy-kyverno
|
.PHONY: kind-deploy-kyverno
|
||||||
kind-deploy-kyverno: $(HELM) kind-load-all ## Build images, load them in kind cluster and deploy kyverno helm chart
|
kind-deploy-kyverno: $(HELM) kind-load-all ## Build images, load them in kind cluster and deploy kyverno helm chart
|
||||||
@echo Install kyverno chart... >&2
|
@echo Install kyverno chart... >&2
|
||||||
@$(HELM) upgrade --install kyverno --namespace kyverno --wait --create-namespace ./charts/kyverno \
|
@$(HELM) upgrade --install kyverno --namespace kyverno --wait --create-namespace ./charts/kyverno \
|
||||||
|
--set cleanupController.image.repository=$(LOCAL_CLEANUP_IMAGE) \
|
||||||
|
--set cleanupController.image.tag=$(IMAGE_TAG_DEV) \
|
||||||
--set image.repository=$(LOCAL_KYVERNO_IMAGE) \
|
--set image.repository=$(LOCAL_KYVERNO_IMAGE) \
|
||||||
--set image.tag=$(IMAGE_TAG_DEV) \
|
--set image.tag=$(IMAGE_TAG_DEV) \
|
||||||
--set initImage.repository=$(LOCAL_KYVERNOPRE_IMAGE) \
|
--set initImage.repository=$(LOCAL_KYVERNOPRE_IMAGE) \
|
||||||
|
@ -665,7 +685,7 @@ kind-deploy-kyverno: $(HELM) kind-load-all ## Build images, load them in kind cl
|
||||||
--set initContainer.extraArgs={--loggingFormat=text} \
|
--set initContainer.extraArgs={--loggingFormat=text} \
|
||||||
--set "extraArgs={--loggingFormat=text}"
|
--set "extraArgs={--loggingFormat=text}"
|
||||||
@echo Restart kyverno pods... >&2
|
@echo Restart kyverno pods... >&2
|
||||||
@kubectl rollout restart deployment -n kyverno kyverno
|
@kubectl rollout restart deployment -n kyverno
|
||||||
|
|
||||||
.PHONY: kind-deploy-kyverno-policies
|
.PHONY: kind-deploy-kyverno-policies
|
||||||
kind-deploy-kyverno-policies: $(HELM) ## Deploy kyverno-policies helm chart
|
kind-deploy-kyverno-policies: $(HELM) ## Deploy kyverno-policies helm chart
|
||||||
|
|
|
@ -214,6 +214,16 @@ The command removes all the Kubernetes components associated with the chart and
|
||||||
| grafana.enabled | bool | `false` | Enable grafana dashboard creation. |
|
| grafana.enabled | bool | `false` | Enable grafana dashboard creation. |
|
||||||
| grafana.namespace | string | `nil` | Namespace to create the grafana dashboard configmap. If not set, it will be created in the same namespace where the chart is deployed. |
|
| grafana.namespace | string | `nil` | Namespace to create the grafana dashboard configmap. If not set, it will be created in the same namespace where the chart is deployed. |
|
||||||
| grafana.annotations | object | `{}` | Grafana dashboard configmap annotations. |
|
| grafana.annotations | object | `{}` | Grafana dashboard configmap annotations. |
|
||||||
|
| cleanupController.enabled | bool | `false` | Enable cleanup controller. |
|
||||||
|
| cleanupController.image.registry | string | `nil` | Image registry |
|
||||||
|
| cleanupController.image.repository | string | `"ghcr.io/kyverno/cleanup-controller"` | Image repository |
|
||||||
|
| cleanupController.image.tag | string | `nil` | Image tag Defaults to appVersion in Chart.yaml if omitted |
|
||||||
|
| cleanupController.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
|
||||||
|
| cleanupController.image.pullSecrets | list | `[]` | Image pull secrets |
|
||||||
|
| cleanupController.service.port | int | `443` | Service port. |
|
||||||
|
| cleanupController.service.type | string | `"ClusterIP"` | Service type. |
|
||||||
|
| cleanupController.service.nodePort | string | `nil` | Service node port. Only used if `service.type` is `NodePort`. |
|
||||||
|
| cleanupController.service.annotations | object | `{}` | Service annotations. |
|
||||||
|
|
||||||
## TLS Configuration
|
## TLS Configuration
|
||||||
|
|
||||||
|
|
29
charts/kyverno/templates/cleanup-controller/_helpers.tpl
Normal file
29
charts/kyverno/templates/cleanup-controller/_helpers.tpl
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{{/* vim: set filetype=mustache: */}}
|
||||||
|
|
||||||
|
{{- define "kyverno.cleanup-controller.deploymentName" -}}
|
||||||
|
cleanup-controller
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
{{- define "kyverno.cleanup-controller.labels" -}}
|
||||||
|
app.kubernetes.io/component: cleanup-controller
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
app.kubernetes.io/name: {{ template "kyverno.name" . }}
|
||||||
|
app.kubernetes.io/part-of: {{ template "kyverno.name" . }}
|
||||||
|
app.kubernetes.io/version: "{{ .Chart.Version }}"
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "kyverno.cleanup-controller.matchLabels" -}}
|
||||||
|
app.kubernetes.io/component: cleanup-controller
|
||||||
|
app.kubernetes.io/name: {{ template "kyverno.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "kyverno.cleanup-controller.image" -}}
|
||||||
|
{{- if .image.registry -}}
|
||||||
|
{{ .image.registry }}/{{ required "An image repository is required" .image.repository }}:{{ default .defaultTag .image.tag }}
|
||||||
|
{{- else -}}
|
||||||
|
{{ required "An image repository is required" .image.repository }}:{{ default .defaultTag .image.tag }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end }}
|
25
charts/kyverno/templates/cleanup-controller/clusterrole.yaml
Normal file
25
charts/kyverno/templates/cleanup-controller/clusterrole.yaml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- kyverno.io
|
||||||
|
resources:
|
||||||
|
- clustercleanuppolicies
|
||||||
|
- cleanuppolicies
|
||||||
|
- clustercleanuppolicies/*
|
||||||
|
- cleanuppolicies/*
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- deletecollection
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
{{- end -}}
|
31
charts/kyverno/templates/cleanup-controller/deployment.yaml
Normal file
31
charts/kyverno/templates/cleanup-controller/deployment.yaml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "kyverno.cleanup-controller.matchLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
serviceAccountName: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
containers:
|
||||||
|
- name: controller
|
||||||
|
image: {{ include "kyverno.cleanup-controller.image" (dict "image" .Values.cleanupController.image "defaultTag" .Chart.AppVersion) | quote }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 9443
|
||||||
|
name: https
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 8000
|
||||||
|
name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
env: []
|
||||||
|
{{- end -}}
|
18
charts/kyverno/templates/cleanup-controller/role.yaml
Normal file
18
charts/kyverno/templates/cleanup-controller/role.yaml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
{{- end -}}
|
17
charts/kyverno/templates/cleanup-controller/rolebinding.yaml
Normal file
17
charts/kyverno/templates/cleanup-controller/rolebinding.yaml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
{{- end -}}
|
62
charts/kyverno/templates/cleanup-controller/secret.yaml
Normal file
62
charts/kyverno/templates/cleanup-controller/secret.yaml
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
{{- $ca := genCA (printf "*.%s.svc" (include "kyverno.namespace" .)) 1024 -}}
|
||||||
|
{{- $svcName := (printf "%s.%s.svc" (include "kyverno.cleanup-controller.deploymentName" .) (include "kyverno.namespace" .)) -}}
|
||||||
|
{{- $cert := genSignedCert $svcName nil (list $svcName) 1024 $ca -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}-ca
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
type: kubernetes.io/tls
|
||||||
|
data:
|
||||||
|
tls.key: {{ $ca.Key | b64enc }}
|
||||||
|
tls.crt: {{ $ca.Cert | b64enc }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}-tls
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
type: kubernetes.io/tls
|
||||||
|
data:
|
||||||
|
tls.key: {{ $cert.Key | b64enc }}
|
||||||
|
tls.crt: {{ $cert.Cert | b64enc }}
|
||||||
|
---
|
||||||
|
apiVersion: admissionregistration.k8s.io/v1
|
||||||
|
kind: ValidatingWebhookConfiguration
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
webhooks:
|
||||||
|
- admissionReviewVersions:
|
||||||
|
- v1beta1
|
||||||
|
clientConfig:
|
||||||
|
caBundle: {{ $ca.Cert | b64enc }}
|
||||||
|
service:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
path: /todo
|
||||||
|
port: 443
|
||||||
|
failurePolicy: Fail
|
||||||
|
matchPolicy: Equivalent
|
||||||
|
name: {{ printf "%s.%s.svc" (include "kyverno.cleanup-controller.deploymentName" .) (include "kyverno.namespace" .) }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- kyverno.io
|
||||||
|
apiVersions:
|
||||||
|
- v1alpha1
|
||||||
|
operations:
|
||||||
|
- CREATE
|
||||||
|
- UPDATE
|
||||||
|
resources:
|
||||||
|
- clustercleanuppolicies/*
|
||||||
|
- cleanuppolicies/*
|
||||||
|
scope: '*'
|
||||||
|
sideEffects: None
|
||||||
|
timeoutSeconds: 10
|
||||||
|
{{- end -}}
|
21
charts/kyverno/templates/cleanup-controller/service.yaml
Normal file
21
charts/kyverno/templates/cleanup-controller/service.yaml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.cleanupController.service.port }}
|
||||||
|
targetPort: https
|
||||||
|
protocol: TCP
|
||||||
|
name: https
|
||||||
|
{{- if and (eq .Values.cleanupController.service.type "NodePort") (not (empty .Values.cleanupController.service.nodePort)) }}
|
||||||
|
nodePort: {{ .Values.cleanupController.service.nodePort }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
{{- include "kyverno.cleanup-controller.matchLabels" . | nindent 4 }}
|
||||||
|
type: {{ .Values.cleanupController.service.type }}
|
||||||
|
{{- end -}}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{{- if .Values.cleanupController.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ template "kyverno.cleanup-controller.deploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "kyverno.cleanup-controller.labels" . | nindent 4 }}
|
||||||
|
namespace: {{ template "kyverno.namespace" . }}
|
||||||
|
{{- end -}}
|
|
@ -475,3 +475,35 @@ grafana:
|
||||||
namespace:
|
namespace:
|
||||||
# -- Grafana dashboard configmap annotations.
|
# -- Grafana dashboard configmap annotations.
|
||||||
annotations: {}
|
annotations: {}
|
||||||
|
|
||||||
|
cleanupController:
|
||||||
|
# -- Enable cleanup controller.
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
image:
|
||||||
|
# -- Image registry
|
||||||
|
registry:
|
||||||
|
# If you want to manage the registry you should remove it from the repository
|
||||||
|
# registry: ghcr.io
|
||||||
|
# repository: kyverno/kyverno
|
||||||
|
# -- Image repository
|
||||||
|
repository: ghcr.io/kyverno/cleanup-controller # kyverno: replaced in e2e tests
|
||||||
|
# -- Image tag
|
||||||
|
# Defaults to appVersion in Chart.yaml if omitted
|
||||||
|
tag: # replaced in e2e tests
|
||||||
|
# -- Image pull policy
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
# -- Image pull secrets
|
||||||
|
pullSecrets: []
|
||||||
|
# - secretName
|
||||||
|
|
||||||
|
service:
|
||||||
|
# -- Service port.
|
||||||
|
port: 443
|
||||||
|
# -- Service type.
|
||||||
|
type: ClusterIP
|
||||||
|
# -- Service node port.
|
||||||
|
# Only used if `service.type` is `NodePort`.
|
||||||
|
nodePort:
|
||||||
|
# -- Service annotations.
|
||||||
|
annotations: {}
|
||||||
|
|
37
cmd/cleanup-controller/informer.go
Normal file
37
cmd/cleanup-controller/informer.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: eventually move this in an util package
|
||||||
|
type startable interface {
|
||||||
|
Start(stopCh <-chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type informer interface {
|
||||||
|
startable
|
||||||
|
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func startInformers[T startable](ctx context.Context, informers ...T) {
|
||||||
|
for i := range informers {
|
||||||
|
informers[i].Start(ctx.Done())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForCacheSync(ctx context.Context, informers ...informer) bool {
|
||||||
|
ret := true
|
||||||
|
for i := range informers {
|
||||||
|
for _, result := range informers[i].WaitForCacheSync(ctx.Done()) {
|
||||||
|
ret = ret && result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func startInformersAndWaitForCacheSync(ctx context.Context, informers ...informer) bool {
|
||||||
|
startInformers(ctx, informers...)
|
||||||
|
return waitForCacheSync(ctx, informers...)
|
||||||
|
}
|
|
@ -1,4 +1,110 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
func main() {
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
kubeinformers "k8s.io/client-go/informers"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
kubeconfig string
|
||||||
|
clientRateLimitQPS float64
|
||||||
|
clientRateLimitBurst int
|
||||||
|
logFormat string
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
resyncPeriod = 15 * time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseFlags() error {
|
||||||
|
logging.Init(nil)
|
||||||
|
flag.StringVar(&logFormat, "loggingFormat", logging.TextFormat, "This determines the output format of the logger.")
|
||||||
|
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
|
||||||
|
flag.Float64Var(&clientRateLimitQPS, "clientRateLimitQPS", 20, "Configure the maximum QPS to the Kubernetes API server from Kyverno. Uses the client default if zero.")
|
||||||
|
flag.IntVar(&clientRateLimitBurst, "clientRateLimitBurst", 50, "Configure the maximum burst for throttle. Uses the client default if zero.")
|
||||||
|
if err := flag.Set("v", "2"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
flag.Parse()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createKubeClients(logger logr.Logger) (*rest.Config, *kubernetes.Clientset, error) {
|
||||||
|
logger = logger.WithName("kube-clients")
|
||||||
|
logger.Info("create kube clients...", "kubeconfig", kubeconfig, "qps", clientRateLimitQPS, "burst", clientRateLimitBurst)
|
||||||
|
clientConfig, err := config.CreateClientConfig(kubeconfig, clientRateLimitQPS, clientRateLimitBurst)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
kubeClient, err := kubernetes.NewForConfig(clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return clientConfig, kubeClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupSignals() (context.Context, context.CancelFunc) {
|
||||||
|
return signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// parse flags
|
||||||
|
if err := parseFlags(); err != nil {
|
||||||
|
fmt.Println("failed to parse flags", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
// setup logger
|
||||||
|
logLevel, err := strconv.Atoi(flag.Lookup("v").Value.String())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to setup logger", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := logging.Setup(logFormat, logLevel); err != nil {
|
||||||
|
fmt.Println("failed to setup logger", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
logger := logging.WithName("setup")
|
||||||
|
// create client config and kube clients
|
||||||
|
_, kubeClient, err := createKubeClients(logger)
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
kubeKyvernoInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod, kubeinformers.WithNamespace(config.KyvernoNamespace()))
|
||||||
|
|
||||||
|
// setup signals
|
||||||
|
signalCtx, signalCancel := setupSignals()
|
||||||
|
defer signalCancel()
|
||||||
|
secretLister := kubeKyvernoInformer.Core().V1().Secrets().Lister()
|
||||||
|
server := NewServer(
|
||||||
|
func() ([]byte, []byte, error) {
|
||||||
|
secret, err := secretLister.Secrets(config.KyvernoNamespace()).Get("cleanup-controller-tls")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return secret.Data[corev1.TLSCertKey], secret.Data[corev1.TLSPrivateKeyKey], nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// start informers and wait for cache sync
|
||||||
|
// we need to call start again because we potentially registered new informers
|
||||||
|
if !startInformersAndWaitForCacheSync(signalCtx, kubeKyvernoInformer) {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
// start webhooks server
|
||||||
|
server.Run(signalCtx.Done())
|
||||||
|
// wait for termination signal
|
||||||
|
<-signalCtx.Done()
|
||||||
}
|
}
|
||||||
|
|
88
cmd/cleanup-controller/server.go
Normal file
88
cmd/cleanup-controller/server.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||||
|
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
||||||
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server interface {
|
||||||
|
// Run TLS server in separate thread and returns control immediately
|
||||||
|
Run(<-chan struct{})
|
||||||
|
// Stop TLS server and returns control after the server is shut down
|
||||||
|
Stop(context.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
type server struct {
|
||||||
|
server *http.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
type TlsProvider func() ([]byte, []byte, error)
|
||||||
|
|
||||||
|
func TODO(logr.Logger, *admissionv1.AdmissionRequest, time.Time) *admissionv1.AdmissionResponse {
|
||||||
|
return admissionutils.ResponseSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates new instance of server accordingly to given configuration
|
||||||
|
func NewServer(
|
||||||
|
tlsProvider TlsProvider,
|
||||||
|
) Server {
|
||||||
|
mux := httprouter.New()
|
||||||
|
mux.HandlerFunc(
|
||||||
|
"POST",
|
||||||
|
"/todo",
|
||||||
|
handlers.AdmissionHandler(TODO).
|
||||||
|
WithAdmission(logging.WithName("todo")),
|
||||||
|
)
|
||||||
|
return &server{
|
||||||
|
server: &http.Server{
|
||||||
|
Addr: ":9443",
|
||||||
|
TLSConfig: &tls.Config{
|
||||||
|
GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
certPem, keyPem, err := tlsProvider()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pair, err := tls.X509KeyPair(certPem, keyPem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pair, nil
|
||||||
|
},
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
},
|
||||||
|
Handler: mux,
|
||||||
|
ReadTimeout: 30 * time.Second,
|
||||||
|
WriteTimeout: 30 * time.Second,
|
||||||
|
ReadHeaderTimeout: 30 * time.Second,
|
||||||
|
IdleTimeout: 5 * time.Minute,
|
||||||
|
// ErrorLog: logging.StdLogger(logger.WithName("server"), ""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) Run(stopCh <-chan struct{}) {
|
||||||
|
go func() {
|
||||||
|
if err := s.server.ListenAndServeTLS("", ""); err != nil {
|
||||||
|
logging.Error(err, "failed to start server")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) Stop(ctx context.Context) {
|
||||||
|
err := s.server.Shutdown(ctx)
|
||||||
|
if err != nil {
|
||||||
|
err = s.server.Close()
|
||||||
|
if err != nil {
|
||||||
|
logging.Error(err, "failed to start server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue