diff --git a/Makefile b/Makefile index 6778e36f..7314287e 100644 --- a/Makefile +++ b/Makefile @@ -407,4 +407,4 @@ check-release: echo "You must specify a VERSION for release" ; exit 1 ; \ fi -prep-release: check-release generate manifests api-docs kvdictl-docs \ No newline at end of file +prep-release: check-release generate manifests api-docs kvdictl-docs bundle \ No newline at end of file diff --git a/README.md b/README.md index a6103785..ac71f172 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ _Except as I've continued to work on this, I've noticed this is really just a fr --- -**ATTENTION:** The `helm` chart repository has been relocated (since the repo has been relocated). To update your repository you can do the following: +**ATTENTION:** The `helm` chart repository has been moved to a [separate repo](https://github.com/kvdi/helm-charts) to tidy things up here more. To update your repository you can do the following: ```sh -helm repo remove tinyzimmer -helm repo add kvdi https://kvdi.github.io/kvdi/deploy/charts +helm repo remove kvdi +helm repo add kvdi https://kvdi.github.io/helm-charts/charts helm repo update helm install kvdi kvdi/kvdi # yes, that's a lot of kvdi @@ -67,6 +67,7 @@ I wrote up a [`CONTRIBUTING`](CONTRIBUTING.md) doc just outlining some of the st - "App Profiles" - I have a POC implementation on `main` but it is still pretty buggy - DOSBox/Game profiles could be cool...same as "App Profiles" + - ARM64 support. Should be easy, but the build files will need some shuffling. - UI could use a serious makeover from someone who actually knows what they are doing ## Requirements @@ -103,7 +104,7 @@ For more complete installation instructions see the `helm` chart docs [here](dep The [API Reference](doc/appv1.md) can also be used for details on `kVDI` app-level configurations. ```bash -helm repo add kvdi https://kvdi.github.io/kvdi/deploy/charts # Add the kvdi repo +helm repo add kvdi https://kvdi.github.io/helm-charts/charts # Add the kvdi charts repo helm repo update # Sync your repositories # Install kVDI @@ -126,7 +127,7 @@ You can then create a [VDICluster](doc/appv1.md#VDIClusterSpec) object manually To install the manifest: ```bash -export KVDI_VERSION=v0.3.1 +export KVDI_VERSION=v0.3.6 kubectl apply -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/deploy/bundle.yaml --validate=false ``` @@ -141,7 +142,7 @@ They can be found in the [config](config/) directory in this repository. Most of the time you can just run a regular helm upgrade to update your deployment manifests to the latest images. ```bash -helm upgrade kvdi kvdi/kvdi --version v0.3.2 +helm upgrade kvdi kvdi/kvdi --version v0.3.6 ``` However, sometimes there may be changes to the CRDs, though I will always do my best to make sure they are backwards compatible. @@ -151,20 +152,20 @@ You can get around this by applying the CRDs for the version you are upgrading t For example: ```bash -export KVDI_VERSION=v0.3.2 +export KVDI_VERSION=v0.3.6 kubectl apply \ - -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/deploy/charts/kvdi/crds/app.kvdi.io_vdiclusters.yaml \ - -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/deploy/charts/kvdi/crds/desktops.kvdi.io_sessions.yaml \ - -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/deploy/charts/kvdi/crds/desktops.kvdi.io_templates.yaml \ - -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/deploy/charts/kvdi/crds/rbac.kvdi.io_vdiroles.yaml + -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/config/crd/bases/app.kvdi.io_vdiclusters.yaml \ + -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/config/crd/bases/desktops.kvdi.io_sessions.yaml \ + -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/config/crd/bases/crds/desktops.kvdi.io_templates.yaml \ + -f https://raw.githubusercontent.com/kvdi/kvdi/${KVDI_VERSION}/config/crd/bases/crds/rbac.kvdi.io_vdiroles.yaml ``` When there is a change to one or more CRDs, it will be mentioned in the notes for that release. ## Building and Running Locally -The `Makefiles` contain helpers for testing the full solution locally using `kind`. Run `make help` to see all the available options. +The `Makefile` contains helpers for testing the full solution locally using `k3d`. Run `make help` to see all the available options. _If you choose to pull the images from the registry instead of building and loading first - you probably want to set `VERSION=latest` (or a previous version) in your environment also. The `Makefile` is usually pointed at the next version to be released and published images may not exist yet_. diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index adbd5d75..afdcf2b4 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -160,7 +160,7 @@ spec: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' + description: 'Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: Source for the environment variable's value. Cannot be used if value is not empty. @@ -768,7 +768,23 @@ spec: type: string type: array dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source.' + description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Alpha) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. @@ -1775,7 +1791,23 @@ spec: type: string type: array dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source.' + description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Alpha) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. @@ -1812,6 +1844,9 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + retainPVCs: + description: RetainPVCs tells the desktop controller to leave PVCs in-tact after they are allocated for a user. The default behavior is to free the volume from the PVC after each desktop session so it can be used across other namespaces. Note that if you set this value to `true` users will only be able to launch sessions in a single namespace (unless the PVC is manually removed). + type: boolean selector: description: A label query over volumes to consider for binding. properties: @@ -2120,7 +2155,7 @@ spec: description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' + description: 'Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' type: string valueFrom: description: Source for the environment variable's value. Cannot be used if value is not empty. @@ -2728,7 +2763,23 @@ spec: type: string type: array dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source.' + description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Alpha) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. @@ -3735,7 +3786,23 @@ spec: type: string type: array dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source.' + description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Alpha) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. @@ -3772,6 +3839,9 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + retainPVCs: + description: RetainPVCs tells the desktop controller to leave PVCs in-tact after they are allocated for a user. The default behavior is to free the volume from the PVC after each desktop session so it can be used across other namespaces. Note that if you set this value to `true` users will only be able to launch sessions in a single namespace (unless the PVC is manually removed). + type: boolean selector: description: A label query over volumes to consider for binding. properties: @@ -4242,7 +4312,7 @@ spec: - --leader-elect command: - /manager - image: ghcr.io/kvdi/manager:v0.3.5 + image: ghcr.io/kvdi/manager:v0.3.6 livenessProbe: httpGet: path: /healthz diff --git a/doc/appv1.md b/doc/appv1.md index 42836038..5e6db849 100644 --- a/doc/appv1.md +++ b/doc/appv1.md @@ -20,6 +20,7 @@ Types - [ServiceMonitorConfig](#ServiceMonitorConfig) - [TLSConfig](#TLSConfig) - [UserdataSelector](#UserdataSelector) +- [UserdataSpec](#UserdataSpec) - [VDICluster](#VDICluster) - [VDIClusterSpec](#VDIClusterSpec) - [VaultConfig](#VaultConfig) @@ -501,6 +502,32 @@ yourself. +### UserdataSpec + +(*Appears on:* [VDIClusterSpec](#VDIClusterSpec)) + +UserdataSpec is an inline of the corev1 PersistentVolumeClaimSpec. It +contains additional fields for controlling how kvdi works with volumes. + +
Field | +Description | +
---|---|
PersistentVolumeClaimSpec Kubernetes core/v1.PersistentVolumeClaimSpec |
+(Members of |
+
retainPVCs bool |
+RetainPVCs tells the desktop controller to leave PVCs in-tact after they are allocated for a user. The default behavior is to free the volume from the PVC after each desktop session so it can be used across other namespaces. Note that if you set this value to |
+
Pull secrets to use when pulling container images
userdataSpec
Kubernetes core/v1.PersistentVolumeClaimSpecuserdataSpec
UserdataSpecThe configuration for user $HOME volumes to be managed by kVDI.
NOTE: Even though the controller will try to force the reclaim policy on created volumes to Retain
, you may want to set it explicitly on your storage-class controller as an extra safeguard.
Pull secrets to use when pulling container images
userdataSpec
Kubernetes core/v1.PersistentVolumeClaimSpecuserdataSpec
UserdataSpecThe configuration for user $HOME volumes to be managed by kVDI.
NOTE: Even though the controller will try to force the reclaim policy on created volumes to Retain
, you may want to set it explicitly on your storage-class controller as an extra safeguard.