Skip to content

Commit 14cdda5

Browse files
committed
Operator now generates validatingwebhookconfiguration for Helm deployment.
Signed-off-by: Aryan <[email protected]>
1 parent 54c8d6f commit 14cdda5

File tree

10 files changed

+342
-105
lines changed

10 files changed

+342
-105
lines changed

bundle/manifests/k8s-nim-operator.clusterserviceversion.yaml

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,18 @@ spec:
13451345
- watch
13461346
- create
13471347
- delete
1348+
- apiGroups:
1349+
- admissionregistration.k8s.io
1350+
resources:
1351+
- validatingwebhookconfigurations
1352+
verbs:
1353+
- get
1354+
- list
1355+
- watch
1356+
- create
1357+
- update
1358+
- patch
1359+
- delete
13481360
deployments:
13491361
- name: k8s-nim-operator
13501362
spec:
@@ -1401,6 +1413,8 @@ spec:
14011413
fieldPath: metadata.namespace
14021414
- name: ENABLE_WEBHOOKS
14031415
value: "true"
1416+
- name: OPERATOR_NAME_PREFIX
1417+
value: "k8s-nim-operator"
14041418
image: 'ghcr.io/nvidia/k8s-nim-operator:main'
14051419
imagePullPolicy: Always
14061420
livenessProbe:
@@ -1414,6 +1428,10 @@ spec:
14141428
successThreshold: 1
14151429
timeoutSeconds: 1
14161430
name: manager
1431+
volumeMounts:
1432+
- name: cert
1433+
mountPath: /tmp/k8s-webhook-server/serving-certs
1434+
readOnly: true
14171435
readinessProbe:
14181436
failureThreshold: 3
14191437
httpGet:
@@ -1435,6 +1453,11 @@ spec:
14351453
allowPrivilegeEscalation: false
14361454
terminationMessagePath: /dev/termination-log
14371455
terminationMessagePolicy: File
1456+
volumes:
1457+
- name: cert
1458+
secret:
1459+
secretName: k8s-nim-operator-webhook-server-cert
1460+
defaultMode: 420
14381461
dnsPolicy: ClusterFirst
14391462
imagePullSecrets: []
14401463
restartPolicy: Always
@@ -1458,45 +1481,3 @@ spec:
14581481
supported: false
14591482
- type: AllNamespaces
14601483
supported: true
1461-
webhookdefinitions:
1462-
- type: ValidatingAdmissionWebhook
1463-
admissionReviewVersions:
1464-
- v1
1465-
containerPort: 9443
1466-
targetPort: 9443
1467-
deploymentName: k8s-nim-operator
1468-
failurePolicy: Fail
1469-
generateName: vnimcache-v1alpha1.kb.io
1470-
rules:
1471-
- apiGroups:
1472-
- apps.nvidia.com
1473-
apiVersions:
1474-
- v1alpha1
1475-
operations:
1476-
- CREATE
1477-
- UPDATE
1478-
resources:
1479-
- nimcaches
1480-
sideEffects: None
1481-
webhookPath: /validate-apps-nvidia-com-v1alpha1-nimcache
1482-
- type: ValidatingAdmissionWebhook
1483-
admissionReviewVersions:
1484-
- v1
1485-
containerPort: 9443
1486-
targetPort: 9443
1487-
deploymentName: k8s-nim-operator
1488-
failurePolicy: Fail
1489-
generateName: vnimservice-v1alpha1.kb.io
1490-
rules:
1491-
- apiGroups:
1492-
- apps.nvidia.com
1493-
apiVersions:
1494-
- v1alpha1
1495-
operations:
1496-
- CREATE
1497-
- UPDATE
1498-
resources:
1499-
- nimservices
1500-
sideEffects: None
1501-
webhookPath: /validate-apps-nvidia-com-v1alpha1-nimservice
1502-
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: k8s-nim-operator-webhook-service
5+
labels:
6+
app.kubernetes.io/name: k8s-nim-operator
7+
app.kubernetes.io/instance: nim-operator
8+
control-plane: controller-manager
9+
annotations:
10+
service.beta.openshift.io/serving-cert-secret-name: k8s-nim-operator-webhook-server-cert
11+
spec:
12+
selector:
13+
app.kubernetes.io/name: k8s-nim-operator
14+
app.kubernetes.io/instance: nim-operator
15+
control-plane: controller-manager
16+
ports:
17+
- port: 443
18+
targetPort: 9443
19+
protocol: TCP

cmd/main.go

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"context"
2021
"crypto/tls"
2122
"flag"
2223
"os"
@@ -34,6 +35,7 @@ import (
3435
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3536
_ "k8s.io/client-go/plugin/pkg/client/auth"
3637
ctrl "sigs.k8s.io/controller-runtime"
38+
crclient "sigs.k8s.io/controller-runtime/pkg/client"
3739
"sigs.k8s.io/controller-runtime/pkg/healthz"
3840
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3941
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
@@ -43,7 +45,9 @@ import (
4345

4446
appsv1alpha1 "github.com/NVIDIA/k8s-nim-operator/api/apps/v1alpha1"
4547
"github.com/NVIDIA/k8s-nim-operator/internal/conditions"
48+
"github.com/NVIDIA/k8s-nim-operator/internal/config"
4649
"github.com/NVIDIA/k8s-nim-operator/internal/controller"
50+
"github.com/NVIDIA/k8s-nim-operator/internal/k8sutil"
4751
"github.com/NVIDIA/k8s-nim-operator/internal/render"
4852
webhookappsv1alpha1 "github.com/NVIDIA/k8s-nim-operator/internal/webhook/apps/v1alpha1"
4953
// +kubebuilder:scaffold:imports
@@ -256,27 +260,33 @@ func main() {
256260

257261
// nolint:goconst
258262
// Parse ENABLE_WEBHOOKS environment variable once as a boolean.
259-
var enableWebhooks bool
260263
if val, ok := os.LookupEnv("ENABLE_WEBHOOKS"); ok {
261264
var err error
262-
enableWebhooks, err = strconv.ParseBool(val)
265+
config.EnableWebhooks, err = strconv.ParseBool(val)
263266
if err != nil {
264267
setupLog.Error(err, "invalid value for ENABLE_WEBHOOKS, expected boolean")
265268
os.Exit(1)
266269
}
267270
}
268-
269-
if enableWebhooks {
270-
if err := webhookappsv1alpha1.SetupNIMCacheWebhookWithManager(mgr); err != nil {
271-
setupLog.Error(err, "unable to create webhook", "webhook", "NIMCache")
272-
os.Exit(1)
273-
}
274-
275-
if err := webhookappsv1alpha1.SetupNIMServiceWebhookWithManager(mgr); err != nil {
276-
setupLog.Error(err, "unable to create webhook", "webhook", "NIMService")
277-
os.Exit(1)
271+
if val, ok := os.LookupEnv("TLS_MODE"); ok {
272+
if val != "cert-manager" && val != "secret" {
273+
setupLog.Error(err, "invalid value for TLS_MODE, expected 'cert-manager' or 'secret")
278274
}
275+
config.TLSMode = val
279276
}
277+
if val, ok := os.LookupEnv("TLS_SECRET"); ok {
278+
config.TLSSecret = val
279+
}
280+
if val, ok := os.LookupEnv("TLS_CA"); ok {
281+
config.TLSCA = []byte(val)
282+
}
283+
if val, ok := os.LookupEnv("OPERATOR_NAME_PREFIX"); ok {
284+
config.OperatorNamePrefix = val
285+
}
286+
if val, ok := os.LookupEnv("OPERATOR_NAMESPACE"); ok {
287+
config.OperatorNamespace = val
288+
}
289+
280290
// +kubebuilder:scaffold:builder
281291

282292
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
@@ -288,6 +298,44 @@ func main() {
288298
os.Exit(1)
289299
}
290300

301+
cfg := ctrl.GetConfigOrDie()
302+
liveClient, err := crclient.New(cfg, crclient.Options{Scheme: scheme})
303+
if err != nil {
304+
setupLog.Error(err, "unable to construct live client")
305+
os.Exit(1)
306+
}
307+
ctx := context.Background()
308+
orch, err := k8sutil.GetOrchestratorType(ctx, liveClient) // uses direct REST calls
309+
if err != nil {
310+
setupLog.Error(err, "failed to detect orchestrator type")
311+
os.Exit(1)
312+
}
313+
config.OrchestratorType = orch
314+
setupLog.Info("detected orchestrator", "type", orch)
315+
316+
if config.EnableWebhooks {
317+
if err := webhookappsv1alpha1.SetupNIMCacheWebhookWithManager(mgr); err != nil {
318+
setupLog.Error(err, "unable to create webhook", "webhook", "NIMCache")
319+
os.Exit(1)
320+
}
321+
322+
if err := webhookappsv1alpha1.SetupNIMServiceWebhookWithManager(mgr); err != nil {
323+
setupLog.Error(err, "unable to create webhook", "webhook", "NIMService")
324+
os.Exit(1)
325+
}
326+
// Set up cluster-level ValidatingWebhookConfiguration.
327+
if err := webhookappsv1alpha1.EnsureValidatingWebhook(
328+
context.TODO(),
329+
mgr.GetAPIReader(), // uncached reads
330+
mgr.GetClient(), // writes go through the normal client
331+
config.OperatorNamespace,
332+
config.OperatorNamePrefix,
333+
); err != nil {
334+
setupLog.Error(err, "unable to ensure ValidatingWebhookConfiguration")
335+
os.Exit(1)
336+
}
337+
}
338+
291339
setupLog.Info("starting manager")
292340
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
293341
setupLog.Error(err, "problem running manager")

deployments/helm/k8s-nim-operator/templates/admission-controller.yaml

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ spec:
1919
app.kubernetes.io/instance: {{ .Release.Name }}
2020
{{- end }}
2121
---
22-
{{- if .Values.operator.admissionController.enabled }}
22+
{{ if and .Values.operator.admissionController.enabled (eq .Values.operator.admissionController.tls.mode "cert-manager") }}
23+
{{ $issuerType := default "selfsigned" .Values.operator.admissionController.tls.certManager.issuerType -}}
24+
{{ $issuerName := .Values.operator.admissionController.tls.certManager.issuerName -}}
2325
apiVersion: cert-manager.io/v1
2426
kind: Certificate
2527
metadata:
@@ -32,13 +34,16 @@ spec:
3234
dnsNames:
3335
- {{ include "k8s-nim-operator.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc
3436
- {{ include "k8s-nim-operator.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc.cluster.local
37+
{{- range .Values.operator.admissionController.tls.certManager.dnsNames }}
38+
- {{ . }}
39+
{{- end }}
3540
issuerRef:
36-
kind: Issuer
37-
name: {{ include "k8s-nim-operator.fullname" . }}-selfsigned-issuer
41+
kind: {{- if eq (lower $issuerType) "clusterissuer" }} ClusterIssuer {{- else }} Issuer {{- end }}
42+
name: {{- if eq (lower $issuerType) "selfsigned" }} {{ include "k8s-nim-operator.fullname" . }}-selfsigned-issuer {{- else }} {{ required "operator.admissionController.tls.certManager.issuerName is required when issuerType is 'issuer' or 'clusterissuer'" $issuerName }} {{- end }}
3843
secretName: {{ include "k8s-nim-operator.fullname" . }}-webhook-server-cert
3944
{{- end }}
4045
---
41-
{{- if .Values.operator.admissionController.enabled }}
46+
{{ if and .Values.operator.admissionController.enabled (eq .Values.operator.admissionController.tls.mode "cert-manager") (eq (lower (default "selfsigned" .Values.operator.admissionController.tls.certManager.issuerType)) "selfsigned") }}
4247
apiVersion: cert-manager.io/v1
4348
kind: Issuer
4449
metadata:
@@ -49,45 +54,4 @@ metadata:
4954
app.kubernetes.io/managed-by: helm
5055
spec:
5156
selfSigned: {}
52-
{{- end}}
53-
---
54-
{{- if .Values.operator.admissionController.enabled }}
55-
apiVersion: admissionregistration.k8s.io/v1
56-
kind: ValidatingWebhookConfiguration
57-
metadata:
58-
name: {{ include "k8s-nim-operator.fullname" . }}-validating-webhook-configuration
59-
annotations:
60-
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "k8s-nim-operator.fullname" . }}-serving-cert
61-
labels:
62-
app.kubernetes.io/name: k8s-nim-operator
63-
app.kubernetes.io/managed-by: helm
64-
webhooks:
65-
- name: vnimcache-v1alpha1.kb.io
66-
admissionReviewVersions: ["v1"]
67-
clientConfig:
68-
service:
69-
name: {{ include "k8s-nim-operator.fullname" . }}-webhook-service
70-
namespace: {{ .Release.Namespace }}
71-
path: /validate-apps-nvidia-com-v1alpha1-nimcache
72-
failurePolicy: Fail
73-
rules:
74-
- apiGroups: ["apps.nvidia.com"]
75-
apiVersions: ["v1alpha1"]
76-
operations: ["CREATE", "UPDATE"]
77-
resources: ["nimcaches"]
78-
sideEffects: None
79-
- name: vnimservice-v1alpha1.kb.io
80-
admissionReviewVersions: ["v1"]
81-
clientConfig:
82-
service:
83-
name: {{ include "k8s-nim-operator.fullname" . }}-webhook-service
84-
namespace: {{ .Release.Namespace }}
85-
path: /validate-apps-nvidia-com-v1alpha1-nimservice
86-
failurePolicy: Fail
87-
rules:
88-
- apiGroups: ["apps.nvidia.com"]
89-
apiVersions: ["v1alpha1"]
90-
operations: ["CREATE", "UPDATE"]
91-
resources: ["nimservices"]
92-
sideEffects: None
93-
{{- end }}
57+
{{- end}}

deployments/helm/k8s-nim-operator/templates/deployment.yaml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,21 @@ spec:
5151
valueFrom:
5252
fieldRef:
5353
fieldPath: metadata.namespace
54+
- name: OPERATOR_NAME_PREFIX
55+
value: {{ include "k8s-nim-operator.fullname" . }}
5456
- name: ENABLE_WEBHOOKS
5557
value: "{{ .Values.operator.admissionController.enabled }}"
58+
- name: TLS_MODE
59+
value: "{{ .Values.operator.admissionController.tls.mode }}"
60+
- name: TLS_SECRET
61+
value: "{{ .Values.operator.admissionController.tls.secret.name }}"
62+
- name: TLS_CA
63+
{{- if and (eq .Values.operator.admissionController.tls.mode "secret") (.Values.operator.admissionController.tls.secret.caBundle) }}
64+
value: |-
65+
{{ .Values.operator.admissionController.tls.secret.caBundle | nindent 14 }}
66+
{{- else }}
67+
value: ""
68+
{{- end }}
5669
livenessProbe:
5770
httpGet:
5871
path: /healthz
@@ -79,8 +92,12 @@ spec:
7992
volumes:
8093
- name: cert
8194
secret:
82-
secretName: {{ include "k8s-nim-operator.fullname" . }}-webhook-server-cert
83-
defaultMode: 420
95+
secretName: {{- if eq .Values.operator.admissionController.tls.mode "secret" }}
96+
{{ .Values.operator.admissionController.tls.secret.name }}
97+
{{- else }}
98+
{{ include "k8s-nim-operator.fullname" . }}-webhook-server-cert
99+
{{- end }}
100+
defaultMode: 420
84101
{{- end }}
85102
{{- with .Values.operator.nodeSelector }}
86103
nodeSelector:

deployments/helm/k8s-nim-operator/templates/manager-rbac.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,8 +582,10 @@ rules:
582582
- get
583583
- list
584584
- watch
585-
- patch
585+
- create
586586
- update
587+
- patch
588+
- delete
587589

588590
---
589591
apiVersion: rbac.authorization.k8s.io/v1

deployments/helm/k8s-nim-operator/values.yaml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,27 @@ operator:
5656
admissionController:
5757
# Enable the admission controller.
5858
# Note: cert-manager must be installed beforehand, as it is required to generate the TLS certificates.
59-
enabled: false
60-
59+
enabled: true
60+
# TLS certificate configuration
61+
tls:
62+
# Certificate management mode: "cert-manager" or "secret"
63+
# - "cert-manager": Use cert-manager to automatically generate and manage certificates
64+
# - "secret": Use a user-provided secret containing tls.crt and tls.key
65+
mode: "cert-manager"
66+
certManager:
67+
# Issuer type: "selfsigned", "clusterissuer", or "issuer"
68+
issuerType: "selfsigned"
69+
# Issuer name (required when issuerType is "clusterissuer" or "issuer")
70+
issuerName: ""
71+
# Additional DNS names for the certificate
72+
dnsNames: []
73+
secret:
74+
# Name of the secret containing tls.crt and tls.key
75+
name: ""
76+
# Base64-encoded CA certificate bundle for validating the webhook's TLS certificate (base64 encoded)
77+
# Required when using secret mode.
78+
# Note: Only include intermediate CA certificates, not root CA certificates
79+
caBundle:
6180
metricsService:
6281
ports:
6382
- name: metrics

0 commit comments

Comments
 (0)