Skip to content

Commit

Permalink
Make CephFS plugin stateless reusing RADOS based journal scheme
Browse files Browse the repository at this point in the history
This is a part of the stateless set of commits for CephCSI.

This commit removes the dependency on config maps to store cephFS provisioned
volumes, and instead relies on RADOS based objects and keys, and required
CSI VolumeID encoding to detect the provisioned volumes.

Changes:
- Provide backward compatibility to provisioned volumes by older plugin versions (1.0.0 or older)
- Remove Create/Delete support for statically provisioned volumes (fixes ceph#382)
- Added namespace support to RADOS OMaps and used the same to store RADOS CSI objects and keys in the CephFS metadata pool
- Added support to mention fsname for CephFS provisioning (fixes ceph#359)
- Changed field name in CSI Identifier to 'location', to denote a pool or fscid
- Updated mounter cache to use new scheme
- Required Helm manifests are updated
- Required documentation and other manifests are updated
- Made driver option 'metadatastorage' as optional, as fresh installs do not need to specify the same

Testing done:
- Create/Mount/Delete PVC
- Create/Delete 5 PVCs
- Mount version 1.0.0 PVC
- Delete version 1.0.0 PV
- Mount Statically defined PV/PVC/Pod
- Mount Statically defined version 1.0.0 PV/PVC/Pod
- Delete Statically defined version 1.0.0 PV/PVC/Pod
- Node restart when mounted to test mountcache
- Use InstanceID other than 'default'
- RBD basic round of tests, as namespace is added to OMaps
- csitest against ceph-fs plugin
  - NOTE: CephFS plugin still does not detect and address already created
  volumes but of a different size
- Test not providing any value to the metadata storage parameter

Signed-off-by: ShyamsundarR <srangana@redhat.com>
  • Loading branch information
ShyamsundarR committed May 28, 2019
1 parent 82e12c9 commit 47b1156
Show file tree
Hide file tree
Showing 35 changed files with 945 additions and 248 deletions.
18 changes: 11 additions & 7 deletions cmd/cephcsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ var (
endpoint = flag.String("endpoint", "unix://tmp/csi.sock", "CSI endpoint")
driverName = flag.String("drivername", "", "name of the driver")
nodeID = flag.String("nodeid", "", "node id")
instanceID = flag.String("instanceid", "", "Unique ID distinguishing this instance of Ceph CSI among other"+
" instances, when sharing Ceph clusters across CSI instances for provisioning")

// rbd related flags
containerized = flag.Bool("containerized", true, "whether run as containerized")
instanceID = flag.String("instanceid", "", "Unique ID distinguishing this instance of Ceph CSI among other"+
" instances, when sharing Ceph clusters across CSI instances for provisioning")

// cephfs related flags
volumeMounter = flag.String("volumemounter", "", "default volume mounter (possible options are 'kernel', 'fuse')")
Expand Down Expand Up @@ -93,6 +93,8 @@ func getDriverName() string {
}

func main() {
var cp util.CachePersister

driverType := getType()
if len(driverType) == 0 {
klog.Fatalln("driver type not specified")
Expand All @@ -112,13 +114,15 @@ func main() {

case cephfsType:
cephfs.PluginFolder = cephfs.PluginFolder + dname
cp, err := util.CreatePersistanceStorage(
cephfs.PluginFolder, *metadataStorage, dname)
if err != nil {
os.Exit(1)
if *metadataStorage != "" {
cp, err = util.CreatePersistanceStorage(
cephfs.PluginFolder, *metadataStorage, dname)
if err != nil {
os.Exit(1)
}
}
driver := cephfs.NewDriver()
driver.Run(dname, *nodeID, *endpoint, *volumeMounter, *mountCacheDir, cp)
driver.Run(dname, *nodeID, *endpoint, *volumeMounter, *mountCacheDir, *instanceID, cp)

default:
klog.Fatalln("invalid volume type", vtype) // calls exit
Expand Down
14 changes: 14 additions & 0 deletions deploy/cephfs/helm/templates/csiplugin-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.configMapName | quote }}
labels:
app: {{ include "ceph-csi-cephfs.name" . }}
chart: {{ include "ceph-csi-cephfs.chart" . }}
component: {{ .Values.provisioner.name }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
data:
config.json: |-
[]
11 changes: 8 additions & 3 deletions deploy/cephfs/helm/templates/nodeplugin-daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
spec:
serviceAccountName: {{ include "ceph-csi-cephfs.serviceAccountName.nodeplugin" . }}
hostNetwork: true
hostPID: true
hostPID: true
# to use e.g. Rook orchestrated cluster, and mons' FQDN is
# resolved through k8s service, set dns policy to cluster first
dnsPolicy: ClusterFirstWithHostNet
Expand Down Expand Up @@ -97,12 +97,14 @@ spec:
- mountPath: /dev
name: host-dev
- mountPath: /rootfs
name: host-rootfs
name: host-rootfs
- mountPath: /sys
name: host-sys
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- name: ceph-csi-config
mountPath: /etc/ceph-csi-config/
resources:
{{ toYaml .Values.nodeplugin.plugin.resources | indent 12 }}
volumes:
Expand All @@ -129,13 +131,16 @@ spec:
path: /dev
- name: host-rootfs
hostPath:
path: /
path: /
- name: host-sys
hostPath:
path: /sys
- name: lib-modules
hostPath:
path: /lib/modules
- name: ceph-csi-config
configMap:
name: {{ .Values.configMapName | quote }}
{{- if .Values.nodeplugin.affinity -}}
affinity:
{{ toYaml .Values.nodeplugin.affinity . | indent 8 }}
Expand Down
5 changes: 5 additions & 0 deletions deploy/cephfs/helm/templates/provisioner-statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ spec:
mountPath: {{ .Values.socketDir }}
- name: host-rootfs
mountPath: "/rootfs"
- name: ceph-csi-config
mountPath: /etc/ceph-csi-config/
resources:
{{ toYaml .Values.nodeplugin.plugin.resources | indent 12 }}
volumes:
Expand All @@ -94,6 +96,9 @@ spec:
- name: host-rootfs
hostPath:
path: /
- name: ceph-csi-config
configMap:
name: {{ .Values.configMapName | quote }}
{{- if .Values.provisioner.affinity -}}
affinity:
{{ toYaml .Values.provisioner.affinity . | indent 8 }}
Expand Down
1 change: 1 addition & 0 deletions deploy/cephfs/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ socketFile: csi.sock
registrationDir: /var/lib/kubelet/plugins_registry
volumeDevicesDir: /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices
driverName: cephfs.csi.ceph.com
configMapName: ceph-csi-config
attacher:
name: attacher
enabled: true
Expand Down
5 changes: 5 additions & 0 deletions deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ spec:
readOnly: true
- name: host-dev
mountPath: /dev
- name: ceph-csi-config
mountPath: /etc/ceph-csi-config/
volumes:
- name: socket-dir
hostPath:
Expand All @@ -99,3 +101,6 @@ spec:
- name: host-dev
hostPath:
path: /dev
- name: ceph-csi-config
configMap:
name: ceph-csi-config
5 changes: 5 additions & 0 deletions deploy/cephfs/kubernetes/csi-cephfsplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ spec:
readOnly: true
- name: host-dev
mountPath: /dev
- name: ceph-csi-config
mountPath: /etc/ceph-csi-config/
volumes:
- name: mount-cache-dir
emptyDir: {}
Expand Down Expand Up @@ -114,3 +116,6 @@ spec:
- name: host-dev
hostPath:
path: /dev
- name: ceph-csi-config
configMap:
name: ceph-csi-config
8 changes: 8 additions & 0 deletions deploy/cephfs/kubernetes/csi-config-map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[]
metadata:
name: ceph-csi-config
44 changes: 27 additions & 17 deletions docs/deploy-cephfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ make image-cephfsplugin
Option | Default value | Description
--------------------|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`--endpoint` | `unix://tmp/csi.sock` | CSI endpoint, must be a UNIX socket
`--drivername` | `cephfs.csi.ceph.com` | name of the driver (Kubernetes: `provisioner` field in StorageClass must correspond to this value)
`--drivername` | `cephfs.csi.ceph.com` | name of the driver (Kubernetes: `provisioner` field in StorageClass must correspond to this value)
`--nodeid` | _empty_ | This node's ID
`--volumemounter` | _empty_ | default volume mounter. Available options are `kernel` and `fuse`. This is the mount method used if volume parameters don't specify otherwise. If left unspecified, the driver will first probe for `ceph-fuse` in system's path and will choose Ceph kernel client if probing failed.
`--metadatastorage` | _empty_ | Whether metadata should be kept on node as file or in a k8s configmap (`node` or `k8s_configmap`)
`--mountcachedir` | _empty_ | volume mount cache info save dir. If left unspecified, the dirver will not record mount info, or it will save mount info and when driver restart it will remount volume it cached.
`--mountcachedir` | _empty_ | volume mount cache info save dir. If left unspecified, the dirver will not record mount info, or it will save mount info and when driver restart it will remount volume it cached.
`--instanceid` | "default" | Unique ID distinguishing this instance of Ceph CSI among other instances, when sharing Ceph clusters across CSI instances for provisioning
`--metadatastorage` | _empty_ | Points to where older (1.0.0 or older plugin versions) metadata about provisioned volumes are kept, as file or in as k8s configmap (`node` or `k8s_configmap` respectively)

**Available environmental variables:**

Expand All @@ -50,22 +51,28 @@ is used to define in which namespace you want the configmaps to be stored

Parameter | Required | Description
----------------------------------------------------------------------------------------------------|--------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`monitors` | yes | Comma separated list of Ceph monitors (e.g. `192.168.100.1:6789,192.168.100.2:6789,192.168.100.3:6789`)
`monValueFromSecret` | one of `monitors` and `monValueFromSecret` must be set | a string pointing the key in the credential secret, whose value is the mon. This is used for the case when the monitors' IP or hostnames are changed, the secret can be updated to pick up the new monitors. If both `monitors` and `monValueFromSecret` are set and the monitors set in the secret exists, `monValueFromSecret` takes precedence.
`clusterID` | yes | String representing a Ceph cluster, must be unique across all Ceph clusters in use for provisioning, cannot be greater than 36 bytes in length, and should remain immutable for the lifetime of the Ceph cluster in use
`fsName` | yes | CephFS filesystem name into which the volume shall be created
`mounter` | no | Mount method to be used for this volume. Available options are `kernel` for Ceph kernel client and `fuse` for Ceph FUSE driver. Defaults to "default mounter", see command line arguments.
`provisionVolume` | yes | Mode of operation. BOOL value. If `true`, a new CephFS volume will be provisioned. If `false`, an existing volume will be used.
`pool` | for `provisionVolume=true` | Ceph pool into which the volume shall be created
`rootPath` | for `provisionVolume=false` | Root path of an existing CephFS volume
`csi.storage.k8s.io/provisioner-secret-name`, `csi.storage.k8s.io/node-stage-secret-name` | for Kubernetes | name of the Kubernetes Secret object containing Ceph client credentials. Both parameters should have the same value
`csi.storage.k8s.io/provisioner-secret-namespace`, `csi.storage.k8s.io/node-stage-secret-namespace` | for Kubernetes | namespaces of the above Secret objects
`pool` | yes | Ceph pool into which the volume shall be created
`csi.storage.k8s.io/provisioner-secret-name`, `csi.storage.k8s.io/node-stage-secret-name` | for Kubernetes | Name of the Kubernetes Secret object containing Ceph client credentials. Both parameters should have the same value
`csi.storage.k8s.io/provisioner-secret-namespace`, `csi.storage.k8s.io/node-stage-secret-namespace` | for Kubernetes | Namespaces of the above Secret objects

**Required secrets for `provisionVolume=true`:**
**NOTE:** An accompanying CSI configuration file, needs to be provided to the
running pods. Refer to [Creating CSI configuration](../examples/README.md#creating-csi-configuration)
for more information.

**NOTE:** A suggested way to populate and retain uniqueness of the clusterID is
to use the output of `ceph fsid` of the Ceph cluster to be used for
provisioning.

**Required secrets for provisioning:**
Admin credentials are required for provisioning new volumes

* `adminID`: ID of an admin client
* `adminKey`: key of the admin client

**Required secrets for `provisionVolume=false`:**
**Required secrets for statically provisioned volumes:**
User credentials with access to an existing volume

* `userID`: ID of a user client
Expand Down Expand Up @@ -132,11 +139,14 @@ service/csi-cephfsplugin-provisioner ClusterIP 10.101.78.75 <none>
...
```

You can try deploying a demo pod from `examples/cephfs` to test the deployment further.
Once the CSI plugin configuration is updated with details from a Ceph cluster of
choice, you can try deploying a demo pod from examples/cephfs using the
instructions [provided](../examples/README.md#deploying-the-storage-class) to
test the deployment further.

### Notes on volume deletion

Volumes that were provisioned dynamically (i.e. `provisionVolume=true`) are
allowed to be deleted by the driver as well, if the user chooses to do
so.Otherwise, the driver is forbidden to delete such volumes - attempting to
delete them is a no-op.
Dynamically povisioned volumes are deleted by the driver, when requested to
do so. Statically provisioned volumes, from plugin versions less than or
equal to 1.0.0, are a no-op when a delete operation is performed against the
same, and are expected to be deleted on the Ceph cluster by the user.
5 changes: 2 additions & 3 deletions docs/deploy-rbd.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ Parameter | Required | Description
`mounter`| no | if set to `rbd-nbd`, use `rbd-nbd` on nodes that have `rbd-nbd` and `nbd` kernel modules to map rbd images

**NOTE:** An accompanying CSI configuration file, needs to be provided to the
running pods. Refer to [Creating CSI configuration for RBD based
provisioning](../examples/README.md#creating-csi-configuration-for-rbd-based-provisioning)
running pods. Refer to [Creating CSI configuration](../examples/README.md#creating-csi-configuration)
for more information.

**NOTE:** A suggested way to populate and retain uniquness of the clusterID is
**NOTE:** A suggested way to populate and retain uniqueness of the clusterID is
to use the output of `ceph fsid` of the Ceph cluster to be used for
provisioning.

Expand Down
13 changes: 5 additions & 8 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ By default, they look for the YAML manifests in
`../../deploy/{rbd,cephfs}/kubernetes`.
You can override this path by running `$ ./plugin-deploy.sh /path/to/my/manifests`.

## Creating CSI configuration for RBD based provisioning
## Creating CSI configuration

**NOTE:** This section is not required for cephfs based provisioning, and SHOULD
be skipped.

For RBD based provisioning, the CSI plugin requires configuration information
regarding the Ceph cluster(s), that would host the RBD based block devices. This
The CSI plugin requires configuration information regarding the Ceph cluster(s),
that would host the dynamically or statically provisioned volumes. This
is provided by adding a per-cluster identifier (referred to as clusterID), and
the required monitor details for the same, as in the provided [sample config
map](./rbd/csi-config-map-sample.yaml).
Expand All @@ -31,12 +28,12 @@ Gather the following information from the Ceph cluster(s) of choice,
* Alternatively, choose a `<cluster-id>` value that is distinct per Ceph
cluster in use by this kubernetes cluster

Update the [sample config map](./rbd/csi-config-map-sample.yaml) with values
Update the [sample config map](./csi-config-map-sample.yaml) with values
from a Ceph cluster and replace `<cluster-id>` with the chosen clusterID, to
create the manifest for the config map which can be updated in the cluster
using the following command,

* `kubectl replace -f rbd/csi-config-map-sample.yaml`
* `kubectl replace -f ./csi-config-map-sample.yaml`

Storage class and snapshot class, using `<cluster-id>` as the value for the
option `clusterID`, can now be created on the cluster.
Expand Down
2 changes: 1 addition & 1 deletion examples/cephfs/plugin-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fi

cd "$deployment_base" || exit 1

objects=(csi-provisioner-rbac csi-nodeplugin-rbac csi-cephfsplugin-provisioner csi-cephfsplugin)
objects=(csi-provisioner-rbac csi-nodeplugin-rbac csi-config-map csi-cephfsplugin-provisioner csi-cephfsplugin)

for obj in "${objects[@]}"; do
kubectl create -f "./$obj.yaml"
Expand Down
2 changes: 1 addition & 1 deletion examples/cephfs/plugin-teardown.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fi

cd "$deployment_base" || exit 1

objects=(csi-cephfsplugin-provisioner csi-cephfsplugin csi-provisioner-rbac csi-nodeplugin-rbac)
objects=(csi-cephfsplugin-provisioner csi-cephfsplugin csi-config-map csi-provisioner-rbac csi-nodeplugin-rbac)

for obj in "${objects[@]}"; do
kubectl delete -f "./$obj.yaml"
Expand Down
4 changes: 2 additions & 2 deletions examples/cephfs/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ metadata:
name: csi-cephfs-secret
namespace: default
data:
# Required if provisionVolume is set to false
# Required for statically provisioned volumes
userID: BASE64-ENCODED-VALUE
userKey: BASE64-ENCODED-VALUE

# Required if provisionVolume is set to true
# Required for dynamically provisioned volumes
adminID: BASE64-ENCODED-VALUE
adminKey: BASE64-ENCODED-VALUE
26 changes: 10 additions & 16 deletions examples/cephfs/storageclass.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,21 @@ metadata:
name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
# Comma separated list of Ceph monitors
# if using FQDN, make sure csi plugin's dns policy is appropriate.
monitors: mon1:port,mon2:port,...
# String representing a Ceph cluster to provision storage from.
# Should be unique across all Ceph clusters in use for provisioning,
# cannot be greater than 36 bytes in length, and should remain immutable for
# the lifetime of the StorageClass in use.
# Ensure to create an entry in the config map named ceph-csi-config, based on
# csi-config-map-sample.yaml, to accompany the string chosen to
# represent the Ceph cluster in clusterID below
clusterID: <cluster-id>

# For provisionVolume: "true":
# A new volume will be created along with a new Ceph user.
# Requires admin credentials (adminID, adminKey).
# For provisionVolume: "false":
# It is assumed the volume already exists and the user is expected
# to provide path to that volume (rootPath) and user credentials
# (userID, userKey).
provisionVolume: "true"
# CephFS filesystem name into which the volume shall be created
fsName: myfs

# Ceph pool into which the volume shall be created
# Required for provisionVolume: "true"
pool: cephfs_data

# Root path of an existing CephFS volume
# Required for provisionVolume: "false"
# rootPath: /absolute/path

# The secrets have to contain user and/or Ceph admin credentials.
csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/rbd/plugin-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fi

cd "$deployment_base" || exit 1

objects=(csi-provisioner-rbac csi-nodeplugin-rbac csi-rbdplugin-provisioner csi-rbdplugin)
objects=(csi-provisioner-rbac csi-nodeplugin-rbac csi-config-map csi-rbdplugin-provisioner csi-rbdplugin)

for obj in "${objects[@]}"; do
kubectl create -f "./$obj.yaml"
Expand Down
2 changes: 1 addition & 1 deletion examples/rbd/plugin-teardown.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fi

cd "$deployment_base" || exit 1

objects=(csi-rbdplugin-provisioner csi-rbdplugin csi-provisioner-rbac csi-nodeplugin-rbac)
objects=(csi-rbdplugin-provisioner csi-rbdplugin csi-config-map csi-provisioner-rbac csi-nodeplugin-rbac)

for obj in "${objects[@]}"; do
kubectl delete -f "./$obj.yaml"
Expand Down
Loading

0 comments on commit 47b1156

Please sign in to comment.