Skip to content

Add validating admission webhook to Helm chart#75

Merged
k8s-ci-robot merged 2 commits intokubernetes-sigs:mainfrom
nojnhuh:webhook
Mar 4, 2025
Merged

Add validating admission webhook to Helm chart#75
k8s-ci-robot merged 2 commits intokubernetes-sigs:mainfrom
nojnhuh:webhook

Conversation

@nojnhuh
Copy link
Contributor

@nojnhuh nojnhuh commented Jan 17, 2025

This change adds a validating admission webhook that validates the
driver-specific opaque parameters that can be specified in
ResourceClaims and ResourceClaimTemplates.

Fixes #49

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jan 17, 2025
@k8s-ci-robot k8s-ci-robot requested review from klueska and pohly January 17, 2025 20:21
@k8s-ci-robot k8s-ci-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Jan 17, 2025
Comment on lines +28 to +29
- name: Test
run: go test -v -race ./...
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also made this particular change in #70, but added that again here to run the new tests added by this PR in CI.

README.md Outdated
local-path-storage local-path-provisioner-7dbf974f64-9jmc7 1/1 Running 0 1m
```

When the validating admission webhook is enabled (as it is by default), cert-manager and its CRDs must be installed.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of taking on a cert-manager dependency, I experimented with Helm's builtin in genSignedCert and adjacent template functions. The main functional caveat with those is that every helm upgrade will generate a new cert, but if the Deployment doesn't change, then a new Pod will not be created to pick up to that new cert, leading to connection issues until a new Pod is created. That might be acceptable for what this example driver will be used for, but probably isn't a pattern we want to establish for "real" drivers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Webhook doesn't seem to be vital for a DRA driver to function. Why not keep the webhook disabled in values, and instruct to enable the webhook if needed, given that it has a dependency and that dependency is not part of the chart?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can do. Disabled it by default and reworded this to match.

limitations under the License.
*/

package main
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, this webhook implementation is largely based on the agnhost one.

Comment on lines +275 to +283
gpuConfig, ok := decodedConfig.(*configapi.GpuConfig)
if !ok {
errs = append(errs, fmt.Errorf("expected v1alpha1.GpuConfig at %s but got: %T", fieldPath, decodedConfig))
continue
}
err = gpuConfig.Validate()
if err != nil {
errs = append(errs, fmt.Errorf("object at %s is invalid: %w", fieldPath, err))
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is about the extent of the driver-specific logic, I wonder if we could eventually make most of this a library in https://github.com/kubernetes/dynamic-resource-allocation where driver authors would only have to provide this custom type, a validation function, and an invocation from a main package. Getting some mileage on this implementation though seems wise before making it too easy :)

LABEL description="See summary"

COPY --from=build /artifacts/dra-example-kubeletplugin /usr/bin/dra-example-kubeletplugin
COPY --from=build /artifacts/dra-example-webhook /usr/bin/dra-example-webhook
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it would be generally more desirable to have separate container images for the kubelet plugin and the webhook, but I wasn't 100% sure that's desired here based on the above make cmds invocation building all of the packages under ./cmd. It certainly does simplify some things in the Helm chart if there's only one image in play.

Comment on lines +102 to +109
{{- define "dra-example-driver.webhookServiceAccountName" -}}
{{- $name := printf "%s-webhook-service-account" (include "dra-example-driver.fullname" .) }}
{{- if .Values.webhook.serviceAccount.create }}
{{- default $name .Values.webhook.serviceAccount.name }}
{{- else }}
{{- default "default-webhook" .Values.webhook.serviceAccount.name }}
{{- end }}
{{- end }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted to create a separate ServiceAccount for the webhook since the webhook doesn't require any RBAC permissions. The Helm chart already seemed to be assuming that there will be only one ServiceAccount though, so the values structure is a little clunky where the kubelet plugin's ServiceAccount is rooted at serviceAccount where the webhook's is rooted at webhook.serviceAccount. Happy to make that more consistent how if that's desired.

namespace: {{ include "dra-example-driver.namespace" . }}
labels:
{{- include "dra-example-driver.labels" . | nindent 4 }}
app.kubernetes.io/component: kubeletplugin
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This label is used to distinguish the kubeletplugin from the webhook so selectors don't get confused.


const (
cdiVendor = "k8s." + DriverName
cdiVendor = "k8s." + consts.DriverName
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not generally a fan of consts packages but that seemed at least better than duplicating the variable. Open to suggestions for a better name or a place for this variable where it can be used by two different main packages. This change is in a separate commit from the rest of the webhook changes in case that makes this easier to review at all, but please let me know if I should squash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not, for what it's worth, I keep a version in a package, it can be overriden during build-time so we don't have to change the version manually - commit hash, for example, but the release version too.

@pohly
Copy link
Contributor

pohly commented Feb 19, 2025

/milestone v1.33

@byako: can you review this? Do we need to find someone else?

Copy link
Contributor

@byako byako left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, couple of NITs


const (
cdiVendor = "k8s." + DriverName
cdiVendor = "k8s." + consts.DriverName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not, for what it's worth, I keep a version in a package, it can be overriden during build-time so we don't have to change the version manually - commit hash, for example, but the release version too.

// verify the content type is accurate
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
msg := fmt.Sprintf("contentType=%s, expect application/json", contentType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
msg := fmt.Sprintf("contentType=%s, expect application/json", contentType)
msg := fmt.Sprintf("contentType=%s, expected application/json", contentType)

return
}

klog.V(2).Info(fmt.Sprintf("handling request: %s", body))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
klog.V(2).Info(fmt.Sprintf("handling request: %s", body))
klog.V(2).Infof("handling request: %s", body)

responseAdmissionReview.Response = admit(*requestedAdmissionReview)
responseAdmissionReview.Response.UID = requestedAdmissionReview.Request.UID

klog.V(2).Info(fmt.Sprintf("sending response: %v", responseAdmissionReview))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
klog.V(2).Info(fmt.Sprintf("sending response: %v", responseAdmissionReview))
klog.V(2).Infof("sending response: %v", responseAdmissionReview)

deviceConfigs = claimTemplate.Spec.Spec.Devices.Config
specPath = "spec.spec"
default:
msg := fmt.Sprintf("expect resource to be %s or %s, got %s", resourceClaimResource, resourceClaimTemplateResource, ar.Request.Resource)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
msg := fmt.Sprintf("expect resource to be %s or %s, got %s", resourceClaimResource, resourceClaimTemplateResource, ar.Request.Resource)
msg := fmt.Sprintf("expected resource to be %s or %s, got %s", resourceClaimResource, resourceClaimTemplateResource, ar.Request.Resource)

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: byako, nojnhuh

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 3, 2025
This change adds a validating admission webhook that validates the
driver-specific opaque parameters that can be specified in
ResourceClaims and ResourceClaimTemplates.
@nojnhuh
Copy link
Contributor Author

nojnhuh commented Mar 3, 2025

LGTM, couple of NITs

@byako I addressed those comments. Thanks!

@byako
Copy link
Contributor

byako commented Mar 4, 2025

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 4, 2025
@k8s-ci-robot k8s-ci-robot merged commit cfa165d into kubernetes-sigs:main Mar 4, 2025
6 checks passed
@johnbelamaric johnbelamaric moved this from 👀 In review to ✅ Done in Dynamic Resource Allocation Mar 4, 2025
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 12, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 12, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 12, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 19, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 19, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 20, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 20, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
klueska added a commit to klueska/k8s-dra-driver-gpu that referenced this pull request Aug 21, 2025
This is a straight copy of this PR
kubernetes-sigs/dra-example-driver#75, with
minimal changes to make it work in this repo.

Signed-off-by: Kevin Klues <kklues@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add example of validating admission webhook

4 participants