From 5fcba270f6f88fc1ddb9e14f15b7f352b40fe142 Mon Sep 17 00:00:00 2001 From: xing-yang Date: Sun, 1 Jul 2018 10:27:52 -0700 Subject: [PATCH 1/8] Add Design Spec for CSI Snapshot This PR proposes to add snapshot support for CSI Volume Drivers and provide a way to restore volumes from snapshots. --- .../design-proposals/storage/csi-snapshot.md | 373 ++++++++++++++++++ .../storage/csi-snapshot_diagram.png | Bin 0 -> 78838 bytes 2 files changed, 373 insertions(+) create mode 100644 contributors/design-proposals/storage/csi-snapshot.md create mode 100644 contributors/design-proposals/storage/csi-snapshot_diagram.png diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md new file mode 100644 index 00000000000..8c096067ae0 --- /dev/null +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -0,0 +1,373 @@ +Kubernetes CSI Snapshot Proposal +================================ + +**Authors:** [Jing Xu](https://github.com/jingxu97), [Xing Yang](https://github.com/xing-yang), [Tomas Smetana](https://github.com/tsmetana), [Huamin Chen ](https://github.com/rootfs) + +## Background + +Many storage systems (GCE PD, Amazon EBS, etc.) provide the ability to create "snapshots" of persistent volumes to protect against data loss. Snapshots can be used in place of a traditional backup system to back up and restore primary and critical data. Snapshots allow for quick data backup (for example, it takes a fraction of a second to create a GCE PD snapshot) and offer fast recovery time objectives (RTOs) and recovery point objectives (RPOs). Snapshots can also be used for data replication, distribution and migration. + +As the initial effort to support snapshot in Kubernetes, volume snapshotting has been released as a prototype in Kubernetes 1.8. An external controller and provisioner (i.e. two separate binaries) have been added in the [external storage repo](https://github.com/kubernetes-incubator/external-storage/tree/master/snapshot). The prototype currently supports GCE PD, AWS EBS, OpenStack Cinder, GlusterFS, and Kubernetes hostPath volumes. Volume snapshots APIs are using [CRD](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/). + +To continue that effort, this design is proposed to add the snapshot support for CSI Volume Drivers. Because the overal trend in Kubernetes is to keep the core APIs as small as possible and use CRD for everything else, this proposal adds CRD definitions to represent snapshots, and an external snapshot controller to handle volume snapshotting. Out-of-tree external provisioner can be upgraded to support creating volume from snapshot. In this design, only CSI volume drivers will be supported. The CSI snapshot spec is proposed [here](https://github.com/container-storage-interface/spec/pull/224). + + +## Objectives + +For the first version of snapshotting support in Kubernetes, only on-demand snapshots for CSI Volume Drivers will be supported. + + +### Goals + +* Goal 1: Expose standardized snapshotting operations to create, list, and delete snapshots in Kubernetes REST API. +Currently the APIs will be implemented with CRD (CustomResourceDefinitions). + +* Goal 2: Implement CSI volume snapshot support. +An external snapshot controller will be deployed with other external components (e.g., external-attacher, external-provisioner) for each CSI Volume Driver. + +* Goal 3: Provide a convenient way of creating new and restoring existing volumes from snapshots. + + +### Non-Goals + +The following are non-goals for the current phase, but will be considered at a later phase. + +* Goal 4: Offer application-consistent snapshots by providing pre/post snapshot hooks to freeze/unfreeze applications and/or unmount/mount file system. + +* Goal 5: Provide higher-level management, such as backing up and restoring a pod and statefulSet, and creating a consistent group of snapshots. + + +## Design Details + +In this proposal, volume snapshots are considered as another type of storage resources managed by Kubernetes. Therefore the snapshot API and controller follow the design pattern of existing volume management. There are three APIs, VolumeSnapshot and VolumeSnapshotContent, and VolumeSnapshotClass which are similar to the structure of PersistentVolumeClaim and PersistentVolume, and storageClass. The external snapshot controller functions similar to the in-tree PV controller. With the snapshots APIs, we also propose to add a new data source struct in PersistentVolumeClaim (PVC) API in order to support restore snapshots to volumes. The following section explains in more details about the APIs and the controller design. + + +### Snapshot API Design + +The API design of VolumeSnapshot and VolumeSnapshotContent is modeled after PersistentVolumeClaim and PersistentVolume. In the first version, the VolumeSnapshot lifecycle is completely independent of its volumes source (PVC). When PVC/PV is deleted, the corresponding VolumeSnapshot and VolumeSnapshotContents objects will continue to exist. However, for some volume plugins, snapshots have a dependency on their volumes. In a future version, we plan to have a complete lifecycle management which can better handler the relationship between snapshots and their volumes. (e.g., a finalizer to prevent deleting volumes while there are snapshots depending on them). + +#### The `VolumeSnapshot` Object + +```GO + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshot is a user's request for taking a snapshot. Upon successful creation of the actual +// snapshot by the volume provider it is bound to the corresponding VolumeSnapshotContent. +// Only the VolumeSnapshot object is accessible to the user in the namespace. +type VolumeSnapshot struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec defines the desired characteristics of a snapshot requested by a user. + Spec VolumeSnapshotSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` + + // Status represents the latest observed state of the snapshot + // +optional + Status VolumeSnapshotStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotList is a list of VolumeSnapshot objects +type VolumeSnapshotList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of VolumeSnapshots + Items []VolumeSnapshot `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// VolumeSnapshotSpec describes the common attributes of a volume snapshot +type VolumeSnapshotSpec struct { + // Source has the information about where the snapshot is created from. + // In Alpha version, only PersistentVolumeClaim is supported as the source. + // If not specified, user can create VolumeSnapshotContent and bind it with VolumeSnapshot manually. + // +optional + Source *TypedLocalObjectReference `json:"source" protobuf:"bytes,1,opt,name=source"` + + // SnapshotContentName binds the VolumeSnapshot object with the VolumeSnapshotContent + // +optional + SnapshotContentName string `json:"snapshotContentName" protobuf:"bytes,2,opt,name=snapshotContentName"` + + // Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will + // be used if it is available. + // +optional + VolumeSnapshotClassName string `json:"snapshotClassName" protobuf:"bytes,3,opt,name=snapshotClassName"` +} + +// VolumeSnapshotStatus is the status of the VolumeSnapshot +type VolumeSnapshotStatus struct { + // CreationTime is the time the snapshot was successfully created. If it is set, + // it means the snapshot was created; Otherwise the snapshot was not created. + // +optional + CreationTime *metav1.Time `json:"createdAt" protobuf:"bytes,1,opt,name=createdAt"` + + // Ready is set to true only if the snapshot is ready to use (e.g., finish uploading if + // there is an uploading phase) and also VolumeSnapshot and its VolumeSnapshotContent + // bind correctly with each other. If any of the above condition is not true, Ready is + // set to false + // +optional + Ready bool `json:"ready" protobuf:"varint,2,opt,name=ready"` + + // The last error encountered during create snapshot operation, if any. + // This field must only be set by the entity completing the create snapshot + // operation, i.e. the external-snapshotter. + // +optional + Error *storage.VolumeError +} + +``` + +Note that if an error occurs before the snapshot is cut, `Error` will be set and none of `CreatedAt`/`AvailableAt` will be set. If an error occurs after the snapshot is cut but before it is available, `Error` will be set and `CreatedAt` should still be set, but `AvailableAt` will not be set. If an error occurs after the snapshot is available, `Error` will be set and `CreatedAt` should still be set, but `AvailableAt` will no longer be set. + +#### The `VolumeSnapshotContent` Object + +```GO + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotContent represents the actual snapshot object +type VolumeSnapshotContent struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec defines a specification of a volume snapshot + Spec VolumeSnapshotContentSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotContentList is a list of VolumeSnapshotContent objects +type VolumeSnapshotContentList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of VolumeSnapshotContents + Items []VolumeSnapshotContent `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// VolumeSnapshotContentSpec is the spec of the volume snapshot content +type VolumeSnapshotContentSpec struct { + // Source represents the location and type of the volume snapshot + VolumeSnapshotSource `json:",inline" protobuf:"bytes,1,opt,name=volumeSnapshotSource"` + + // VolumeSnapshotRef is part of bi-directional binding between VolumeSnapshot + // and VolumeSnapshotContent. It becomes non-nil when bound. + // +optional + VolumeSnapshotRef *core_v1.ObjectReference `json:"volumeSnapshotRef" protobuf:"bytes,2,opt,name=volumeSnapshotRef"` + + // PersistentVolumeRef represents the PersistentVolume that the snapshot has been + // taken from. It becomes non-nil when VolumeSnapshot and VolumeSnapshotContent are bound. + // +optional + PersistentVolumeRef *core_v1.ObjectReference `json:"persistentVolumeRef" protobuf:"bytes,3,opt,name=persistentVolumeRef"` +} + +// VolumeSnapshotSource represents the actual location and type of the snapshot. Only one of its members may be specified. +type VolumeSnapshotSource struct { + // CSI (Container Storage Interface) represents storage that handled by an external CSI Volume Driver (Alpha feature). + // +optional + CSI *CSIVolumeSnapshotSource `json:"csiVolumeSnapshotSource,omitempty"` +} + +// Represents the source from CSI volume snapshot +type CSIVolumeSnapshotSource struct { + // Driver is the name of the driver to use for this snapshot. + // Required. + Driver string `json:"driver"` + + // SnapshotHandle is the unique snapshot id returned by the CSI volume + // plugin’s CreateSnapshot to refer to the snapshot on all subsequent calls. + // Required. + SnapshotHandle string `json:"snapshotHandle"` + + // Timestamp when the point-in-time snapshot is taken on the storage + // system. This timestamp will be generated by the CSI volume driver after + // the snapshot is cut. The format of this field should be a Unix nanoseconds + // time encoded as an int64. On Unix, the command `date +%s%N` returns + // the current time in nanoseconds since 1970-01-01 00:00:00 UTC. + // This field is REQUIRED. + CreatedAt int64 `json:"createdAt,omitempty" protobuf:"varint,3,opt,name=createdAt"` +} + +``` + +#### The `VolumeSnapshotClass` Object + +A new VolumeSnapshotClass API object will be added instead of resuing the existing StorageClass, in order to avoid mixing parameters between snapshots and volumes. Each CSI Volume Driver can have its own default VolumeSnapshotClass. If VolumeSnapshotClass is not provided, a default will be used. It allows to add new parameters for snapshots. + +``` + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotClass describes the parameters used by storage system when +// provisioning VolumeSnapshots from PVCs. +// The name of a VolumeSnapshotClass object is significant, and is how users can request a particular class. +type VolumeSnapshotClass struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Snapshotter is the driver expected to handle this VolumeSnapshotClass. + Snapshotter string `json:"snapshotter" protobuf:"bytes,2,opt,name=snapshotter"` + + // Parameters holds parameters for the snapshotter. + // These values are opaque to the system and are passed directly + // to the snapshotter. + // +optional + Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"` +} + + +``` +### Volume API Changes + +With Snapshot API available, users could provision volumes from snapshot and data will be prepopulated to the volumes. Also considering clone and other possible storage operations, there could be many different types of sources used for populating the data to the volumes. In this proposal, we add a general "DataSource" which could be used to represent different types of data sources. + +#### The `DataSource` Object in PVC + +Add a new `DataSource` field into both PVC and PV to represent the source of the data which is prepopulated to the provisioned volume. If an external-provisioner does not understand the new `DataSource` field and does not pre-populate the new volume, PV/PVC controller should be able to detect that (e.g. PVC has `DataSource` but PV does not) and fail the operation. Please see more details in [here](https://github.com/kubernetes/community/pull/2495) + +Possible `DataSource` types may include the following: + + * VolumeSnapshot: restore snapshot to a new volume + * PersistentVolumeClaim: clone volume which is represented by PVC + +``` + +type PersistentVolumeClaimSpec struct { + // If specified when creating, volume will be prepopulated with data from the DataSource. + // +optional + DataSource *TypedLocalObjectReference `json:"dataSource" protobuf:"bytes,2,opt,name=dataSource"` +} + +type PersistentVolumeSpec struct { + // If specified, volume will be prepopulated with data from the DataSource. + // +optional + DataSource *ypedLocalObjectReference `json:"dataSource" protobuf:"bytes,2,opt,name=dataSource"` +} + +``` + +Add a TypedLocalObjectReference in core API. + +``` + +// TypedLocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. +type TypedLocalObjectReference struct { + // Name of the object reference. + Name string + // Kind indicates the type of the object reference. + Kind string +} + +``` + +In the first version, only VolumeSnapshot is the supported `Type` for data source object reference. Other types will be added in a future version. If unsupported `Type` is used, the PV Controller SHALL fail the operation. + + +### Snapshot Controller Design +As the figure below shows, the CSI snapshot controller architecture consists of an external snapshotter which talks to out-of-tree CSI Volume Driver over socket (/run/csi/socket by default, configurable by -csi-address). External snapshotter is part of Kubernetes implementation of [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec). It is an external controller that monitors `VolumeSnapshot` and `VolumeSnapshotContent` objects and creates/deletes snapshot. +![CSI Snapshot Diagram](csi-snapshot_diagram.png?raw=true "CSI Snapshot Diagram") + +* External snapshotter uses ControllerGetCapabilities to find out if CSI driver supports CREATE_DELETE_SNAPSHOT calls. It degrades to trivial mode if not. + +* External snapshotter is responsible for creating/deleting snapshots and binding snapshot and SnapshotContent objects. It follows [controller](https://github.com/kubernetes/community/blob/master/contributors/devel/controllers.md) pattern and uses informers to watch for `VolumeSnapshot` and `VolumeSnapshotContent` create/update/delete events. It filters out `VolumeSnapshot` instances with `Snapshotter==` and processes these events in workqueues with exponential backoff. + +* For dynamically created snapshot, it should have a VolumeSnapshotClass associated with it. User can explicitly specify a VolumeSnapshotClass in the VolumeSnapshot API object. If user does not specify a VolumeSnapshotClass, a default VolumeSnapshotClass created by the admin will be used. This is similar to how a default StorageClass created by the admin will be used for the provisioning of a PersistentVolumeClaim. + +* For statically binding snapshot, user/admin must specify bi-pointers correctly for both VolumeSnapshot and VolumeSnapshotContent, so that the controller knows how to bind them. Otherwise, if VolumeSnapshot points to a non-exist VolumeSnapshotContent, or VolumeSnapshotContent does not point back to the VolumeSnapshot, the Error status will be set for VolumeSnapshot + +* External snapshotter is running in the sidecar along with external-attacher and external-provisioner for each CSI Volume Driver. + +* In current design, when the storage system fails to create snapshot, retry will not be performed in the controller. This is because users may not want to retry when taking consistent snapshots or scheduled snapshots when the timing of the snapshot creation is important. In a future version, a maxRetries flag or retry termination timestamp will be added to allow users to control whether retries are needed. + + +#### Changes in CSI External Provisioner + +`DataSource` is available in both `StorageClass` and `PersistentVolumeClaim` to represent the source of the data which is prepopulated to the provisioned volume. If `DataSource` is added to both during volume provisioning, `DataSource` in `PersistentVolumeClaim` will override `DataSource` in `StorageClass`. + +The operation of the provisioning of a volume from a snapshot data source will be handled by the out-of-tree CSI External Provisioner. The in-tree PV Controller will handle the binding of the PV and PVC once they are ready. + + +#### CSI Volume Driver Snapshot Support + +The out-of-tree CSI Volume Driver creates a snapshot on the backend storage system or cloud provider, and calls CreateSnapshot through CSI ControllerServer and returns CreateSnapshotResponse. The out-of-tree CSI Volume Driver needs to implement the following functions: + +* CreateSnapshot, DeleteSnapshot, and create volume from snapshot if it supports CREATE_DELETE_SNAPSHOT. +* ListSnapshots if it supports LIST_SNAPSHOTS. + +ListSnapshots can be an expensive operation because it will try to list all snapshots on the storage system. For a storage system that takes nightly periodic snapshots, the total number of snapshots on the system can be huge. Kubernetes should try to avoid this call if possible. Instead, calling ListSnapshots with a specific snapshot_id as filtering to query the status of the snapshot will be more desirable and efficient. + +CreateSnapshot is a synchronous function and it must be blocking until the snapshot is cut. For cloud providers that support the uploading of a snapshot as part of the creating snapshot operation, CreateSnapshot function must also be blocking until the snapshot is cut and after that it shall return an operation pending gRPC error code until the uploading process is complete. + +Refer to [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec) for detailed instructions on how CSI Volume Driver shall implement snapshot functions. + + +## Transition to the New Snapshot Support + +### Existing Implementation in External Storage Repo + +For the snapshot implementation in [external storage repo](https://github.com/kubernetes-incubator/external-storage/tree/master/snapshot), an external snapshot controller and an external provisioner need to be deployed. + +* The old implementation does not support CSI volume drivers. +* VolumeSnapshotClass concept does not exist in the old design. +* To restore a volume from the snapshot, however, user needs to create a new StorageClass that is different from the original one for the PVC. + +Here is an example yaml file to create a snapshot in the old design: + +```GO + +apiVersion: volumesnapshot.external-storage.k8s.io/v1 +kind: VolumeSnapshot +metadata: + name: hostpath-test-snapshot +spec: + persistentVolumeClaimName: pvc-test-hostpath + +``` + +### New Snapshot Design for CSI + +For the new snapshot model, a sidecar "Kubernetes to CSI" proxy container called "external-snapshotter" needs to be deployed in addition to the sidecar container for the external provisioner. This deployment model is shown in the CSI Snapshot Diagram in the CSI External Snapshot Controller section. + +* The new design supports CSI volume drivers. +* To create a snapshot for CSI, a VolumeSnapshotClass can be created and specified in the spec of VolumeSnapshot. +* To restore a volume from the snapshot, user could use the same StorageClass that is used for the original PVC. + +Here is an example to create a VolumeSnapshotClass and to create a snapshot in the new design: + +```GO + +apiVersion: snapshot.storage.k8s.io/v1alpha1 +kind: VolumeSnapshotClass +metadata: + name: csi-hostpath-snapclass +snapshotter: csi-hostpath +--- +apiVersion:snapshot.storage.k8s.io/v1alpha1 +kind: VolumeSnapshot +metadata: + name: snapshot-demo +spec: + snapshotClassName: csi-hostpath-snapclass + source: + name: hpvc + kind: PersistentVolumeClaim + +``` diff --git a/contributors/design-proposals/storage/csi-snapshot_diagram.png b/contributors/design-proposals/storage/csi-snapshot_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e040126e15f8c2d66fd10f14881751f217b7c58b GIT binary patch literal 78838 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 z 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%0A{Ugvm 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 E4HvIdA^-pY literal 0 HcmV?d00001 From 6268b50498ea1c716e512e2d011f437ffa12dfe3 Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Tue, 14 Aug 2018 14:12:02 -0700 Subject: [PATCH 2/8] Update csi-snapshot.md --- .../design-proposals/storage/csi-snapshot.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index 8c096067ae0..03bed8b0101 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -106,14 +106,18 @@ type VolumeSnapshotStatus struct { // CreationTime is the time the snapshot was successfully created. If it is set, // it means the snapshot was created; Otherwise the snapshot was not created. // +optional - CreationTime *metav1.Time `json:"createdAt" protobuf:"bytes,1,opt,name=createdAt"` + CreationTime *metav1.Time `json:"creationTime" protobuf:"bytes,1,opt,name=creationTime"` + // The size of the snapshot. When restoring volume from the snapshot, the volume size + // should be equal or larger than its snapshot size. + Size *resource.Quantity `json:"size" protobuf:"bytes,2,opt,name=size"` + // Ready is set to true only if the snapshot is ready to use (e.g., finish uploading if // there is an uploading phase) and also VolumeSnapshot and its VolumeSnapshotContent // bind correctly with each other. If any of the above condition is not true, Ready is // set to false // +optional - Ready bool `json:"ready" protobuf:"varint,2,opt,name=ready"` + Ready bool `json:"ready" protobuf:"varint,3,opt,name=ready"` // The last error encountered during create snapshot operation, if any. // This field must only be set by the entity completing the create snapshot @@ -197,8 +201,11 @@ type CSIVolumeSnapshotSource struct { // the snapshot is cut. The format of this field should be a Unix nanoseconds // time encoded as an int64. On Unix, the command `date +%s%N` returns // the current time in nanoseconds since 1970-01-01 00:00:00 UTC. - // This field is REQUIRED. - CreatedAt int64 `json:"createdAt,omitempty" protobuf:"varint,3,opt,name=createdAt"` + CreationTime *int64 `json:"creationTime,omitempty" protobuf:"varint,3,opt,name=creationTime"` + + // The size of the snapshot. When restoring volume from the snapshot, the volume size + // should be equal or larger than its snapshot size. + Size *resource.Quantity `json:"size" protobuf:"bytes,2,opt,name=size"` } ``` From 766ec7022f3ba2c2d98f470190c4161ba3b93f8e Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Mon, 20 Aug 2018 16:22:25 -0700 Subject: [PATCH 3/8] Update csi-snapshot.md --- .../design-proposals/storage/csi-snapshot.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index 03bed8b0101..b0d460362f0 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -108,9 +108,11 @@ type VolumeSnapshotStatus struct { // +optional CreationTime *metav1.Time `json:"creationTime" protobuf:"bytes,1,opt,name=creationTime"` - // The size of the snapshot. When restoring volume from the snapshot, the volume size - // should be equal or larger than its snapshot size. - Size *resource.Quantity `json:"size" protobuf:"bytes,2,opt,name=size"` + // When restoring volume from the snapshot, the volume size should be equal or + // larger than the Restoresize if it is specified. If RestoreSize is set to nil, it means + // that the storage plugin does not have this information avaialble. + // +optional + RestoreSize *resource.Quantity `json:"restoreSize" protobuf:"bytes,2,opt,name=restoreSize"` // Ready is set to true only if the snapshot is ready to use (e.g., finish uploading if // there is an uploading phase) and also VolumeSnapshot and its VolumeSnapshotContent @@ -203,9 +205,11 @@ type CSIVolumeSnapshotSource struct { // the current time in nanoseconds since 1970-01-01 00:00:00 UTC. CreationTime *int64 `json:"creationTime,omitempty" protobuf:"varint,3,opt,name=creationTime"` - // The size of the snapshot. When restoring volume from the snapshot, the volume size - // should be equal or larger than its snapshot size. - Size *resource.Quantity `json:"size" protobuf:"bytes,2,opt,name=size"` + // When restoring volume from the snapshot, the volume size should be equal or + // larger than the Restoresize if it is specified. If RestoreSize is set to nil, it means + // that the storage plugin does not have this information avaialble. + // +optional + RestoreSize *resource.Quantity `json:"restoreSize" protobuf:"bytes,2,opt,name=restoreSize"` } ``` From 4b0fb4cbd07266de5baa896c8233f102aa14691f Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Wed, 22 Aug 2018 18:11:10 -0700 Subject: [PATCH 4/8] Fixed some typos. --- contributors/design-proposals/storage/csi-snapshot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index b0d460362f0..d69d7506612 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -110,7 +110,7 @@ type VolumeSnapshotStatus struct { // When restoring volume from the snapshot, the volume size should be equal or // larger than the Restoresize if it is specified. If RestoreSize is set to nil, it means - // that the storage plugin does not have this information avaialble. + // that the storage plugin does not have this information available. // +optional RestoreSize *resource.Quantity `json:"restoreSize" protobuf:"bytes,2,opt,name=restoreSize"` @@ -207,7 +207,7 @@ type CSIVolumeSnapshotSource struct { // When restoring volume from the snapshot, the volume size should be equal or // larger than the Restoresize if it is specified. If RestoreSize is set to nil, it means - // that the storage plugin does not have this information avaialble. + // that the storage plugin does not have this information available. // +optional RestoreSize *resource.Quantity `json:"restoreSize" protobuf:"bytes,2,opt,name=restoreSize"` } From 127a5b7526bfb58e97c33e0f9c65432f00786397 Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Thu, 23 Aug 2018 12:02:48 -0700 Subject: [PATCH 5/8] Update csi-snapshot.md change VolumeSnapshotClassName as pointer --- contributors/design-proposals/storage/csi-snapshot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index d69d7506612..4c7ac60e241 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -98,7 +98,7 @@ type VolumeSnapshotSpec struct { // Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will // be used if it is available. // +optional - VolumeSnapshotClassName string `json:"snapshotClassName" protobuf:"bytes,3,opt,name=snapshotClassName"` + VolumeSnapshotClassName *string `json:"snapshotClassName" protobuf:"bytes,3,opt,name=snapshotClassName"` } // VolumeSnapshotStatus is the status of the VolumeSnapshot From 7eb005ce301b93a4babcd8120413a3d580b49517 Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Thu, 23 Aug 2018 12:16:10 -0700 Subject: [PATCH 6/8] Update csi-snapshot.md --- contributors/design-proposals/storage/csi-snapshot.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index 4c7ac60e241..c882aa50046 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -178,6 +178,10 @@ type VolumeSnapshotContentSpec struct { // taken from. It becomes non-nil when VolumeSnapshot and VolumeSnapshotContent are bound. // +optional PersistentVolumeRef *core_v1.ObjectReference `json:"persistentVolumeRef" protobuf:"bytes,3,opt,name=persistentVolumeRef"` + // Name of the VolumeSnapshotClass used by the VolumeSnapshotContent. If not specified, a default snapshot class will + // be used if it is available. + // +optional + VolumeSnapshotClassName *string `json:"snapshotClassName" protobuf:"bytes,4,opt,name=snapshotClassName"` } // VolumeSnapshotSource represents the actual location and type of the snapshot. Only one of its members may be specified. From 71b354dfbe48da8c6a1fc3fa1f421416d79ce031 Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Fri, 24 Aug 2018 11:30:01 -0700 Subject: [PATCH 7/8] Update csi-snapshot.md --- .../design-proposals/storage/csi-snapshot.md | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index c882aa50046..1863827db29 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -9,7 +9,7 @@ Many storage systems (GCE PD, Amazon EBS, etc.) provide the ability to create "s As the initial effort to support snapshot in Kubernetes, volume snapshotting has been released as a prototype in Kubernetes 1.8. An external controller and provisioner (i.e. two separate binaries) have been added in the [external storage repo](https://github.com/kubernetes-incubator/external-storage/tree/master/snapshot). The prototype currently supports GCE PD, AWS EBS, OpenStack Cinder, GlusterFS, and Kubernetes hostPath volumes. Volume snapshots APIs are using [CRD](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/). -To continue that effort, this design is proposed to add the snapshot support for CSI Volume Drivers. Because the overal trend in Kubernetes is to keep the core APIs as small as possible and use CRD for everything else, this proposal adds CRD definitions to represent snapshots, and an external snapshot controller to handle volume snapshotting. Out-of-tree external provisioner can be upgraded to support creating volume from snapshot. In this design, only CSI volume drivers will be supported. The CSI snapshot spec is proposed [here](https://github.com/container-storage-interface/spec/pull/224). +To continue that effort, this design is proposed to add the snapshot support for CSI Volume Drivers. Because the overall trend in Kubernetes is to keep the core APIs as small as possible and use CRD for everything else, this proposal adds CRD definitions to represent snapshots, and an external snapshot controller to handle volume snapshotting. Out-of-tree external provisioner can be upgraded to support creating volume from snapshot. In this design, only CSI volume drivers will be supported. The CSI snapshot spec is proposed [here](https://github.com/container-storage-interface/spec/pull/224). ## Objectives @@ -44,7 +44,7 @@ In this proposal, volume snapshots are considered as another type of storage res ### Snapshot API Design -The API design of VolumeSnapshot and VolumeSnapshotContent is modeled after PersistentVolumeClaim and PersistentVolume. In the first version, the VolumeSnapshot lifecycle is completely independent of its volumes source (PVC). When PVC/PV is deleted, the corresponding VolumeSnapshot and VolumeSnapshotContents objects will continue to exist. However, for some volume plugins, snapshots have a dependency on their volumes. In a future version, we plan to have a complete lifecycle management which can better handler the relationship between snapshots and their volumes. (e.g., a finalizer to prevent deleting volumes while there are snapshots depending on them). +The API design of VolumeSnapshot and VolumeSnapshotContent is modeled after PersistentVolumeClaim and PersistentVolume. In the first version, the VolumeSnapshot lifecycle is completely independent of its volumes source (PVC). When PVC/PV is deleted, the corresponding VolumeSnapshot and VolumeSnapshotContents objects will continue to exist. However, for some volume plugins, snapshots have a dependency on their volumes. In a future version, we plan to have a complete lifecycle management which can better handle the relationship between snapshots and their volumes. (e.g., a finalizer to prevent deleting volumes while there are snapshots depending on them). #### The `VolumeSnapshot` Object @@ -220,7 +220,7 @@ type CSIVolumeSnapshotSource struct { #### The `VolumeSnapshotClass` Object -A new VolumeSnapshotClass API object will be added instead of resuing the existing StorageClass, in order to avoid mixing parameters between snapshots and volumes. Each CSI Volume Driver can have its own default VolumeSnapshotClass. If VolumeSnapshotClass is not provided, a default will be used. It allows to add new parameters for snapshots. +A new VolumeSnapshotClass API object will be added instead of reusing the existing StorageClass, in order to avoid mixing parameters between snapshots and volumes. Each CSI Volume Driver can have its own default VolumeSnapshotClass. If VolumeSnapshotClass is not provided, a default will be used. It allows to add new parameters for snapshots. ``` @@ -252,11 +252,11 @@ type VolumeSnapshotClass struct { ``` ### Volume API Changes -With Snapshot API available, users could provision volumes from snapshot and data will be prepopulated to the volumes. Also considering clone and other possible storage operations, there could be many different types of sources used for populating the data to the volumes. In this proposal, we add a general "DataSource" which could be used to represent different types of data sources. +With Snapshot API available, users could provision volumes from snapshot and data will be pre-populated to the volumes. Also considering clone and other possible storage operations, there could be many different types of sources used for populating the data to the volumes. In this proposal, we add a general "DataSource" which could be used to represent different types of data sources. #### The `DataSource` Object in PVC -Add a new `DataSource` field into both PVC and PV to represent the source of the data which is prepopulated to the provisioned volume. If an external-provisioner does not understand the new `DataSource` field and does not pre-populate the new volume, PV/PVC controller should be able to detect that (e.g. PVC has `DataSource` but PV does not) and fail the operation. Please see more details in [here](https://github.com/kubernetes/community/pull/2495) +Add a new `DataSource` field into both PVC to represent the source of the data which is populated to the provisioned volume. External-provisioner will check `DataSource` field and try to provision volume from the sources. In the first version, only VolumeSnapshot is the supported `Type` for data source object reference. Other types will be added in a future version. If unsupported `Type` is used, the PV Controller SHALL fail the operation. Please see more details in [here](https://github.com/kubernetes/community/pull/2495) Possible `DataSource` types may include the following: @@ -264,19 +264,12 @@ Possible `DataSource` types may include the following: * PersistentVolumeClaim: clone volume which is represented by PVC ``` - type PersistentVolumeClaimSpec struct { // If specified when creating, volume will be prepopulated with data from the DataSource. // +optional DataSource *TypedLocalObjectReference `json:"dataSource" protobuf:"bytes,2,opt,name=dataSource"` } -type PersistentVolumeSpec struct { - // If specified, volume will be prepopulated with data from the DataSource. - // +optional - DataSource *ypedLocalObjectReference `json:"dataSource" protobuf:"bytes,2,opt,name=dataSource"` -} - ``` Add a TypedLocalObjectReference in core API. @@ -293,7 +286,7 @@ type TypedLocalObjectReference struct { ``` -In the first version, only VolumeSnapshot is the supported `Type` for data source object reference. Other types will be added in a future version. If unsupported `Type` is used, the PV Controller SHALL fail the operation. + ### Snapshot Controller Design @@ -329,7 +322,7 @@ The out-of-tree CSI Volume Driver creates a snapshot on the backend storage syst ListSnapshots can be an expensive operation because it will try to list all snapshots on the storage system. For a storage system that takes nightly periodic snapshots, the total number of snapshots on the system can be huge. Kubernetes should try to avoid this call if possible. Instead, calling ListSnapshots with a specific snapshot_id as filtering to query the status of the snapshot will be more desirable and efficient. -CreateSnapshot is a synchronous function and it must be blocking until the snapshot is cut. For cloud providers that support the uploading of a snapshot as part of the creating snapshot operation, CreateSnapshot function must also be blocking until the snapshot is cut and after that it shall return an operation pending gRPC error code until the uploading process is complete. +CreateSnapshot is a synchronous function and it must be blocking until the snapshot is cut. For cloud providers that support the uploading of a snapshot as part of creating snapshot operation, CreateSnapshot function must also be blocking until the snapshot is cut and after that it shall return an operation pending gRPC error code until the uploading process is complete. Refer to [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec) for detailed instructions on how CSI Volume Driver shall implement snapshot functions. @@ -363,7 +356,7 @@ For the new snapshot model, a sidecar "Kubernetes to CSI" proxy container called * The new design supports CSI volume drivers. * To create a snapshot for CSI, a VolumeSnapshotClass can be created and specified in the spec of VolumeSnapshot. -* To restore a volume from the snapshot, user could use the same StorageClass that is used for the original PVC. +* To restore a volume from the snapshot, users could use the same StorageClass that is used for the original PVC. Here is an example to create a VolumeSnapshotClass and to create a snapshot in the new design: From 772498694fba68a37f450ed9c0f21e4aedd0e5bf Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Fri, 24 Aug 2018 11:44:22 -0700 Subject: [PATCH 8/8] Update csi-snapshot.md --- contributors/design-proposals/storage/csi-snapshot.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/contributors/design-proposals/storage/csi-snapshot.md b/contributors/design-proposals/storage/csi-snapshot.md index 1863827db29..beb46d58a2f 100644 --- a/contributors/design-proposals/storage/csi-snapshot.md +++ b/contributors/design-proposals/storage/csi-snapshot.md @@ -256,7 +256,7 @@ With Snapshot API available, users could provision volumes from snapshot and dat #### The `DataSource` Object in PVC -Add a new `DataSource` field into both PVC to represent the source of the data which is populated to the provisioned volume. External-provisioner will check `DataSource` field and try to provision volume from the sources. In the first version, only VolumeSnapshot is the supported `Type` for data source object reference. Other types will be added in a future version. If unsupported `Type` is used, the PV Controller SHALL fail the operation. Please see more details in [here](https://github.com/kubernetes/community/pull/2495) +Add a new `DataSource` field into PVC to represent the source of the data which is populated to the provisioned volume. External-provisioner will check `DataSource` field and try to provision volume from the sources. In the first version, only VolumeSnapshot is the supported `Type` for data source object reference. Other types will be added in a future version. If unsupported `Type` is used, the PV Controller SHALL fail the operation. Please see more details in [here](https://github.com/kubernetes/community/pull/2495) Possible `DataSource` types may include the following: @@ -286,9 +286,6 @@ type TypedLocalObjectReference struct { ``` - - - ### Snapshot Controller Design As the figure below shows, the CSI snapshot controller architecture consists of an external snapshotter which talks to out-of-tree CSI Volume Driver over socket (/run/csi/socket by default, configurable by -csi-address). External snapshotter is part of Kubernetes implementation of [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec). It is an external controller that monitors `VolumeSnapshot` and `VolumeSnapshotContent` objects and creates/deletes snapshot. ![CSI Snapshot Diagram](csi-snapshot_diagram.png?raw=true "CSI Snapshot Diagram") @@ -308,9 +305,7 @@ As the figure below shows, the CSI snapshot controller architecture consists of #### Changes in CSI External Provisioner -`DataSource` is available in both `StorageClass` and `PersistentVolumeClaim` to represent the source of the data which is prepopulated to the provisioned volume. If `DataSource` is added to both during volume provisioning, `DataSource` in `PersistentVolumeClaim` will override `DataSource` in `StorageClass`. - -The operation of the provisioning of a volume from a snapshot data source will be handled by the out-of-tree CSI External Provisioner. The in-tree PV Controller will handle the binding of the PV and PVC once they are ready. +`DataSource` is available in `PersistentVolumeClaim` to represent the source of the data which is prepopulated to the provisioned volume. The operation of the provisioning of a volume from a snapshot data source will be handled by the out-of-tree CSI External Provisioner. The in-tree PV Controller will handle the binding of the PV and PVC once they are ready. #### CSI Volume Driver Snapshot Support