Skip to content

Commit c0c4750

Browse files
committed
Conversion webhook
This patch implements a reversible conversion webhook from/to VolumeGroupSnapshots v1beta1 to/from VolumeGroupSnapshots v1beta2. The extra fields included in the new API are tracked in an annotation that is automatically set on v1beta1 objects.
1 parent c0e647a commit c0c4750

File tree

95 files changed

+38630
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+38630
-20
lines changed

.github/workflows/trivy.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
make
2424
docker build -t test/csi-snapshotter:latest -f ./cmd/csi-snapshotter/Dockerfile --output=type=docker --label revision=latest .
2525
docker build -t test/snapshot-controller:latest -f ./cmd/snapshot-controller/Dockerfile --output=type=docker --label revision=latest .
26+
docker build -t test/snapshot-webhook:latest -f ./cmd/snapshot-webhook/Dockerfile --output=type=docker --label revision=latest .
2627
2728
- name: Run Trivy vulnerability scanner on csi-snapshotter image
2829
uses: aquasecurity/trivy-action@master
@@ -47,3 +48,15 @@ jobs:
4748
ignore-unfixed: true
4849
vuln-type: 'os,library'
4950
severity: 'CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN'
51+
52+
- name: Run Trivy vulnerability scanner on snapshot-webhook image
53+
uses: aquasecurity/trivy-action@master
54+
env:
55+
TRIVY_DB_REPOSITORY: "public.ecr.aws/aquasecurity/trivy-db:2"
56+
with:
57+
image-ref: 'test/snapshot-webhook:latest'
58+
format: 'table'
59+
exit-code: '1'
60+
ignore-unfixed: true
61+
vuln-type: 'os,library'
62+
severity: 'CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN'

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
.PHONY: all snapshot-controller csi-snapshotter clean test
15+
.PHONY: all snapshot-controller csi-snapshotter snapshot-webhook clean test
1616

17-
CMDS=snapshot-controller csi-snapshotter
17+
CMDS=snapshot-controller csi-snapshotter snapshot-webhook
1818
all: build
1919
include release-tools/build.make
2020

README.md

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ The volume snapshot feature supports CSI v1.0 and higher. It was introduced as a
66

77
The volume group snapshot feature supports CSI v1.10.0 and higher, and have been introduced in [Kubernetes 1.27 as an alpha feature](https://kubernetes.io/blog/2023/05/08/kubernetes-1-27-volume-group-snapshot-alpha/).
88

9-
> :warning: **WARNING**: The validation webhook was deprecated in v8.0.0 and it is now removed. The validation webhook would prevent creating multiple default volume snapshot classes and multiple default volume group snapshot classes for the same CSI driver. With the removal of the validation webhook, an error will still be raised when dynamically provisioning a VolumeSnapshot or VolumeGroupSnapshot when multiple default volume snapshot classes or multiple default volume group snapshot classes for the same CSI driver exist.
10-
119
## Overview
1210

1311
With the promotion of Volume Snapshot to GA, the feature is enabled by default on standard Kubernetes deployments and cannot be turned off.
@@ -26,11 +24,11 @@ This information reflects the head of this branch.
2624
| ------------------------------------------------------------------------------------------ | ----------------------------| --------------- | --------------- | --------------- |
2725
| [CSI Spec v1.0.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) | [CSI Spec v1.5.0](https://github.com/container-storage-interface/spec/releases/tag/v1.5.0) | k8s.gcr.io/sig-storage/csi-snapshotter | 1.20 | 1.20 |
2826
| [CSI Spec v1.0.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) | [CSI Spec v1.5.0](https://github.com/container-storage-interface/spec/releases/tag/v1.5.0) | k8s.gcr.io/sig-storage/snapshot-controller | 1.20 | 1.20 |
29-
| [CSI Spec v1.0.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) | [CSI Spec v1.5.0](https://github.com/container-storage-interface/spec/releases/tag/v1.5.0) | k8s.gcr.io/sig-storage/snapshot-validation-webhook | 1.20 | 1.20 |
27+
| [CSI Spec v1.0.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) | [CSI Spec v1.5.0](https://github.com/container-storage-interface/spec/releases/tag/v1.5.0) | k8s.gcr.io/sig-storage/snapshot-webhook | 1.20 | 1.20 |
3028

31-
Note: snapshot-controller, csi-snapshotter v4.1 requires v1 snapshot CRDs to be installed, but it serves both v1 and v1beta1 snapshot objects. Storage version is changed from v1beta1 to v1 in 4.1.0 so v1beta1 is deprecated and will be removed in a future release.
29+
Note: snapshot-controller, snapshot-webhook, csi-snapshotter v4.1 requires v1 snapshot CRDs to be installed, but it serves both v1 and v1beta1 snapshot objects. Storage version is changed from v1beta1 to v1 in 4.1.0 so v1beta1 is deprecated and will be removed in a future release.
3230

33-
Note: when the volume group snapshot feature is enabled, snapshot-controller, csi-snapshotter require the v1alpha1 volumegroupsnapshot CRDs to be installed.
31+
Note: when the volume group snapshot feature is enabled, snapshot-controller, snapshot-webhook, csi-snapshotter require the v1alpha1 volumegroupsnapshot CRDs to be installed.
3432

3533
## Feature Status
3634

@@ -58,6 +56,7 @@ Volume Snapshot feature contains the following components:
5856

5957
* [Kubernetes Volume Snapshot and Volume Group Snapshot CRDs](https://github.com/kubernetes-csi/external-snapshotter/tree/master/client/config/crd)
6058
* [Volume snapshot and volume group snapshot controller](https://github.com/kubernetes-csi/external-snapshotter/tree/master/pkg/common-controller)
59+
* [Volume group snapshot conversion webhook](https://github.com/kubernetes-csi/external-snapshotter/tree/master/pkg/webhook)
6160
* CSI Driver along with [CSI Snapshotter sidecar](https://github.com/kubernetes-csi/external-snapshotter/tree/master/pkg/sidecar-controller)
6261

6362
The Volume Snapshot feature depends on a volume snapshot controller and the volume snapshot CRDs. Both the controller and the CRDs are independent of any CSI driver. The CSI Snapshotter sidecar must run once per CSI driver. The single snapshot controller deployment works for all CSI drivers in a cluster. With leader election configured, the CSI sidecars and snapshot controller elect one leader per deployment. If deployed with two or more pods and leader election is enabled, the non-leader containers will attempt to get the lease. If the leader container dies, a non-leader will take over.
@@ -66,6 +65,8 @@ Therefore, it is strongly recommended that Kubernetes distributors bundle and de
6665

6766
If your Kubernetes distribution does not bundle the snapshot controller, you may manually install these components by executing the following steps. Note that the snapshot controller YAML files in the git repository deploy into the default namespace for system testing purposes. For general use, update the snapshot controller YAMLs with an appropriate namespace prior to installing. For example, on a Vanilla Kubernetes cluster update the namespace from 'default' to 'kube-system' prior to issuing the kubectl create command.
6867

68+
There is a new validating webhook server which provides tightened validation on snapshot objects. The cluster admin or Kubernetes distribution admin should install the webhook alongside the snapshot controllers and CRDs. More details [below](#validating-webhook).
69+
6970
Install Snapshot and Volume Group Snapshot CRDs:
7071
* With the repo cloned locally: `kubectl kustomize client/config/crd | kubectl create -f -`
7172
* From the repo remotely: `kubectl kustomize https://github.com/kubernetes-csi/external-snapshotter/client/config/crd | kubectl create -f -`
@@ -82,6 +83,44 @@ Install CSI Driver:
8283
* With the repo cloned locally: `kubectl kustomize deploy/kubernetes/csi-snapshotter | kubectl create -f -`
8384
* From the repo remotely: `kubectl kustomize https://github.com/kubernetes-csi/external-snapshotter/deploy/kubernetes/csi-snapshotter | kubectl create -f -`
8485

86+
### Validating Webhook
87+
88+
The snapshot validating webhook is an HTTP callback which responds to [admission requests](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/). It is part of a larger [plan](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1900-volume-snapshot-validation-webhook) to tighten validation for volume snapshot objects. This webhook introduces the [ratcheting validation](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1900-volume-snapshot-validation-webhook#backwards-compatibility) mechanism targeting the tighter validation. The cluster admin or Kubernetes distribution admin should install the webhook alongside the snapshot controllers and CRDs.
89+
90+
Along with the validation webhook, the volume snapshot controller will start [labeling](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1900-volume-snapshot-validation-webhook#automatic-labelling-of-invalid-objects) invalid snapshot objects which already existed. This is to enable quick identification of invalid snapshot objects in the system by running:
91+
```
92+
kubectl get volumesnapshots --selector=snapshot.storage.kubernetes.io/invalid-snapshot-resource: ""
93+
kubectl get volumesnapshotcontents --selector=snapshot.storage.kubernetes.io/invalid-snapshot-content-resource: ""
94+
```
95+
96+
Users should run this to identify, remove any invalid objects, and correct their workflows before upgrading to v1. Once the API has been switched to the v1 type, those invalid objects will not be deletable from the system.
97+
98+
If there are no existing invalid v1beta1 objects, after upgrading to v1, the webhook and schema validation will prevent the user from creating new invalid v1 and v1beta1 objects.
99+
100+
If there are existing invalid v1beta1 objects, the user should make sure that the snapshot controller is upgraded to v3.0.0 or higher (v3.0.3 is the latest recommended v3.0.x release) and install the corresponding validation webhook before upgrading to v1 so that those invalid objects will be labeled and can be identified easily and removed before upgrading to v1.
101+
102+
If there are existing invalid v1beta1 objects, and the user didn't upgrade to the snapshot controller 3.0.0 or higher and install the corresponding validation webhook before upgrading to v1, those existing invalid v1beta1 objects will not be labeled by the snapshot controller.
103+
104+
So the recommendation is that before upgrading to v1 CRDs and upgrading snapshot controller and validation webhook to v4.0, the user should upgrade to the snapshot controller 3.0.0 and higher (v3.0.3 is the latest recommended version for 3.0.x) and install the corresponding validation webhook so that all existing invalid objects will be labeled and can be easily identified and deleted.
105+
106+
> :warning: **WARNING**: Cluster admins choosing not to install the webhook server and participate in the phased release process can cause future problems when upgrading from `v1beta1` to `v1` volumesnapshot API, if there are currently persisted objects which fail the new stricter validation. Potential impacts include being unable to delete invalid snapshot objects.
107+
108+
Read more about how to install the example webhook [here](deploy/kubernetes/webhook-example/README.md).
109+
110+
#### Validating Webhook Command Line Options
111+
112+
* `--tls-cert-file`: File containing the x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). Required.
113+
114+
* `--tls-private-key-file`: File containing the x509 private key matching --tls-cert-file. Required.
115+
116+
* `--port`: Secure port that the webhook listens on (default 443)
117+
118+
* `--kubeconfig <path>`: Path to Kubernetes client configuration that the webhook uses to connect to Kubernetes API server. When omitted, default token provided by Kubernetes will be used. This option is useful only when the snapshot controller does not run as a Kubernetes pod, e.g. for debugging.
119+
120+
* `--prevent-volume-mode-conversion`: Boolean that prevents an unauthorised user from modifying the volume mode when creating a PVC from an existing VolumeSnapshot. Was present as an alpha feature in `v6.0.0`; Having graduated to beta, defaults to true.
121+
122+
#### Validating Webhook Validations
123+
85124
##### Volume Snapshot
86125

87126
* Spec.VolumeSnapshotClassName must not be an empty string or nil on creation
@@ -242,6 +281,8 @@ If you have already deployed v1alpha1 snapshot APIs and external-snapshotter sid
242281

243282
### Upgrade from v1beta1 to v1
244283

284+
Validation webhook should be installed before upgrading to v1. Potential impacts of not installing the validation webhook before upgrading to v1 include being unable to delete invalid snapshot objects. See the section on Validation Webhook for details.
285+
245286
* When upgrading to 4.0, change from v1beta1 to v1 is backward compatible because both v1 and v1beta1 are served while the stored API version is still v1beta1. Future releases will switch the stored version to v1 and gradually remove v1beta1 support.
246287
* When upgrading from 3.x to 4.1, change from v1beta1 to v1 is no longer backward compatible because stored API version is changed to v1 although both v1 and v1beta1 are still served. v1beta1 is deprecated in 4.1.
247288
* v1beta1 support will be removed in a future release. It is recommended for users to switch to v1 as soon as possible. Any previously created invalid v1beta1 objects have to be deleted before upgrading to version 4.1.

cmd/snapshot-webhook/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM gcr.io/distroless/static:latest
2+
LABEL maintainers="Kubernetes Authors"
3+
LABEL description="Snapshot Webhook"
4+
ARG binary=./bin/snapshot-webhook
5+
6+
COPY ${binary} snapshot-webhook
7+
ENTRYPOINT ["/snapshot-webhook"]

cmd/snapshot-webhook/main.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"flag"
21+
22+
webhook "github.com/kubernetes-csi/external-snapshotter/v8/pkg/webhook"
23+
"k8s.io/klog/v2"
24+
)
25+
26+
func main() {
27+
rootCmd := webhook.CmdWebhook
28+
29+
loggingFlags := &flag.FlagSet{}
30+
klog.InitFlags(loggingFlags)
31+
rootCmd.PersistentFlags().AddGoFlagSet(loggingFlags)
32+
rootCmd.Execute()
33+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Validating Webhook
2+
3+
The snapshot validating webhook is an HTTP callback which responds to [admission requests](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/). It is part of a larger [plan](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1900-volume-snapshot-validation-webhook#proposal) to tighten validation for volume snapshot objects. This webhook introduces the [ratcheting validation](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1900-volume-snapshot-validation-webhook#backwards-compatibility) mechanism targeting the tighter validation. The cluster admin or Kubernetes distribution admin should install the webhook alongside the snapshot controllers and CRDs.
4+
5+
## How to build the webhook
6+
7+
Build the binary
8+
9+
```bash
10+
make
11+
```
12+
13+
Build the docker image
14+
15+
```bash
16+
docker build -t snapshot-webhook:latest -f ./cmd/snapshot-webhook/Dockerfile .
17+
```
18+
19+
## How to deploy the webhook
20+
21+
The webhook server is provided as an image which can be built from this repository. It can be deployed anywhere, as long as the api server is able to reach it over HTTPS. It is recommended to deploy the webhook server in the cluster as snapshotting is latency sensitive. A `ValidatingWebhookConfiguration` object is needed to configure the api server to contact the webhook server. Please see the [documentation](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) for more details. The webhook server code is adapted from the [webhook server](https://github.com/kubernetes/kubernetes/tree/v1.18.6/test/images/agnhost/webhook) used in the kubernetes/kubernetes end to end testing code.
22+
23+
### Example in-cluster deployment using Kubernetes Secrets
24+
25+
Please note this is not considered to be a production ready method to deploy the certificates and is only provided for demo purposes. This is only one of many ways to deploy the certificates, it is your responsibility to ensure the security of your cluster. TLS certificates and private keys should be handled with care and you may not want to keep them in plain Kubernetes secrets.
26+
27+
This method was heavily adapted from [banzai cloud](https://banzaicloud.com/blog/k8s-admission-webhooks/).
28+
29+
#### Method
30+
31+
These commands should be run from the top level directory.
32+
33+
1. Run the `create-cert.sh` script. Note using the default namespace will allow anyone with access to that namespace to read your secret. It is recommended to change the namespace in all the files and the commands given below.
34+
35+
36+
```bash
37+
# This script will create a TLS certificate signed by the [cluster](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/). It will place the public and private key into a secret on the cluster.
38+
./deploy/kubernetes/webhook-example/create-cert.sh --service snapshot-webhook-service --secret snapshot-webhook-secret --namespace default # Make sure to use a different namespace
39+
```
40+
41+
2. Patch the VolumeGroupSnapshot, VolumeGroupSnapshotContent and VolumeGroupSnapshotClass CRDs filling in the CA bundle field.
42+
43+
```bash
44+
./deploy/kubernetes/webhook-example/patch-ca-bundle.sh
45+
```
46+
47+
3. Change the namespace in the service and deployment in the `webhook.yaml` file.
48+
49+
4. Create the deployment, service, RBAC, and admission configuration objects on the cluster.
50+
51+
```bash
52+
kubectl apply -f ./deploy/kubernetes/webhook-example
53+
```
54+
55+
Once all the pods from the deployment are up and running, you should be ready to go.
56+
57+
#### Verify the webhook works
58+
59+
Try to query the API server for a VolumeGroupSnapshot object in the version `v1beta1`.
60+
61+
```bash
62+
kubectl get volumegroupsnapshotclass.v1beta1.groupsnapshot.storage.k8s.io
63+
64+
kubectl get volumegroupsnapshotcontent.v1beta1.groupsnapshot.storage.k8s.io
65+
66+
kubectl get volumegroupsnapshot.v1beta1.groupsnapshot.storage.k8s.io
67+
```
68+
69+
### Other methods to deploy the webhook server
70+
71+
Look into [cert-manager](https://cert-manager.io/) to handle the certificates, and this kube-builder [tutorial](https://book.kubebuilder.io/cronjob-tutorial/cert-manager.html) on how to deploy a webhook.
72+
73+
#### Important
74+
75+
Please see the deployment [yaml](./webhook.yaml) for the arguments expected by the webhook server. The snapshot validation webhook is served at the path `/volumesnapshot`.

0 commit comments

Comments
 (0)