Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cephfs CSI plugin #30

Merged
merged 47 commits into from
Apr 20, 2018
Merged

cephfs CSI plugin #30

merged 47 commits into from
Apr 20, 2018

Conversation

gman0
Copy link
Contributor

@gman0 gman0 commented Mar 5, 2018

This is a Work-In-Progress draft of cephfs CSI plugin. Internally, it uses ceph-fuse for mounting and setfattr for setting quotas on volume.
I've tested it with CSI 0.1.0 (since the version of Kubernetes installed on my system only supports 0.1.0 - no problem to bump the version later) and while it does work, at least for now the cephfsplugin container expects to have a hostPath volume with populated /etc/ceph containing the config and the keyring - though ceph-fuse should be easy enough to modify so that the credentials can be passed through command-line arguments.
Also, the merge for Kubernete's KeyMutex.TryLockKey is still not done, so this code contains the same bug as in #29 (see pkg/cephfs/util.go tryLock)

I'm guessing the whole codebase could do some refactoring as cephfsplugin and rbdplugin both share some parts of the code.

Please review / post feedback.

Makefile Outdated
docker build -t $(CEPHFS_IMAGE_NAME):$(CEPHFS_IMAGE_VERSION) deploy/cephfs/docker

push-container: rbdplugin-container
docker push $(RBD_IMAGE_NAME):$(RBD_IMAGE_VERSION)
Copy link
Member

Choose a reason for hiding this comment

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

add a cephfs container push here and i'll test it

verbs: ["get", "list", "update"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
Copy link
Member

Choose a reason for hiding this comment

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

why do we need secret?

Copy link
Contributor

Choose a reason for hiding this comment

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

Getting secret only requires for a provisioner

resources: ["namespaces"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["persistentvolumes"]
Copy link
Member

Choose a reason for hiding this comment

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

ditto

- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
Copy link
Member

Choose a reason for hiding this comment

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

ditto

resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
Copy link
Member

Choose a reason for hiding this comment

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

same

path: /var/lib/kubelet/plugins/cephfsplugin
type: DirectoryOrCreate
- name: host-dev
hostPath:
Copy link
Member

Choose a reason for hiding this comment

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

why need /dev? (for fuse?)

- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
Copy link
Member

Choose a reason for hiding this comment

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

you need secret (eventually)

name: cephfs-pvc
spec:
accessModes:
- ReadWriteOnce
Copy link
Member

Choose a reason for hiding this comment

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

ReadWriteMany

})

fs.driver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{
csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
Copy link
Member

Choose a reason for hiding this comment

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

multi node writer

}

fs.driver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
Copy link
Member

Choose a reason for hiding this comment

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

you don't need controller publish/unpublish for ceph fs

return cs.Driver.ValidateControllerServiceRequest(v, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME)
}

func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
Copy link
Member

Choose a reason for hiding this comment

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

this needs rework, see cephfs provisioner code here https://github.com/kubernetes-incubator/external-storage/tree/master/ceph/cephfs

return nil
}

func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
Copy link
Member

Choose a reason for hiding this comment

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

node pubish volume call should expect ceph mon and secret to run ceph-fuse mount.

gman0 added 5 commits March 7, 2018 14:19
…access to fs

Uses a slightly modified version of https://github.com/kubernetes-incubator/external-storage/blob/master/ceph/cephfs/cephfs_provisioner/cephfs_provisioner.py
This should be rewritten properly in Go, but for it works for now - for demonstration purposes

TODO:
* readOnly is not taken into account
* controllerServer.DeleteVolume does nothing
@@ -4,5 +4,9 @@ metadata:
name: cephfs
provisioner: cephfsplugin
parameters:
provisionRoot: /cephfs
reclaimPolicy: Delete
adminID: admin
Copy link
Contributor

Choose a reason for hiding this comment

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

With CSI Spec 0.2.0 you do not have to keep ceph username/key in StorageClass. Please refer to updated CSI RBD driver StorageClass and also controller.go to see how to use credentails which are passed now inside of RPC call.

@gman0
Copy link
Contributor Author

gman0 commented Mar 16, 2018

Hey, I'm having some trouble testing the driver - could you please share some info on how you do the testing yourself, so we can have a common test environment? To speed things up a little
So far I've been using minikube 0.25.0 and ceph-container, but lately there have been some breaking changes
I've applied your patch kubernetes-retired/drivers@e18c7cf manually but I'm still left with this output:

  Type     Reason                 Age               From               Message
  ----     ------                 ----              ----               -------
  Normal   Scheduled              28s               default-scheduler  Successfully assigned web-server to minikube
  Normal   SuccessfulMountVolume  27s               kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-xbfjj"
  Warning  FailedMount            7s (x5 over 19s)  kubelet, minikube  MountVolume.SetUp failed for volume "kubernetes-dynamic-pv-0dcde436283d11e8" : rpc error: code = Unimplemented desc = unknown service csi.Identity

since minikube's kubelet probably hasn't moved to csi.v0.* yet.

(oops sorry about the close&reopening, misclicked)

@gman0 gman0 closed this Mar 16, 2018
@gman0 gman0 reopened this Mar 16, 2018
@sbezverk
Copy link
Contributor

@gman0 For testing I am using my local single node k8s cluster and another single node ceph cluster. Both runs as VM on bare metal linux box.
If you want I can share my deployment yaml file, I use all in one POD, basically all 4 components provisioner/attacher/registrar/rbdplugin runs in the same pod.

@gman0
Copy link
Contributor Author

gman0 commented Mar 16, 2018

Sure, that would be cool, thanks a lot!

@rootfs
Copy link
Member

rootfs commented Mar 16, 2018

@gman0 there is some discussion to update minikube here

@gman0
Copy link
Contributor Author

gman0 commented Mar 19, 2018

Ok so I set up a VM with Kubernetes 1.10.0-beta.4 (since k8s 1.9.* doesn't support csi.v0.*, only csi.* - at least from looking at the code), and I'm running kube-apiserver with flag --runtime-config=storage.k8s.io/v1beta1 (instead of v1alpha1, as it's mentioned in the docs) otherwise it wouldn't start, not sure why.

Now, when I deploy the driver and create the PersistentVolumeClaim, it seems to work:

$ kubectl describe pvc csi-cephfs-pvc
Name:          csi-cephfs-pvc
Namespace:     default
StorageClass:  csi-cephfs
Status:        Bound
Volume:        kubernetes-dynamic-pv-d80d09d62b5911e8
Labels:        <none>
Annotations:   control-plane.alpha.kubernetes.io/leader={"holderIdentity":"d77a6894-2b59-11e8-b802-0a580af40029","leaseDurationSeconds":15,"acquireTime":"2018-03-19T09:42:30Z","renewTime":"2018-03-19T09:42:32Z","lea...
               pv.kubernetes.io/bind-completed=yes
               pv.kubernetes.io/bound-by-controller=yes
               volume.beta.kubernetes.io/storage-provisioner=csi-cephfsplugin
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5Gi
Access Modes:  RWX
Events:
  Type    Reason                 Age                From                                                                     Message
  ----    ------                 ----               ----                                                                     -------
  Normal  ExternalProvisioning   24m (x2 over 24m)  persistentvolume-controller                                              waiting for a volume to be created, either by external provisioner "csi-cephfsplugin" or manually created by system administrator
  Normal  Provisioning           24m                csi-cephfsplugin csi-provisioner-0 d77a6894-2b59-11e8-b802-0a580af40029  External provisioner is provisioning volume for claim "default/csi-cephfs-pvc"
  Normal  ProvisioningSucceeded  24m                csi-cephfsplugin csi-provisioner-0 d77a6894-2b59-11e8-b802-0a580af40029  Successfully provisioned volume kubernetes-dynamic-pv-d80d09d62b5911e8

$ kubectl describe pv kubernetes-dynamic-pv-d80d09d62b5911e8
Name:            kubernetes-dynamic-pv-d80d09d62b5911e8
Labels:          <none>
Annotations:     pv.kubernetes.io/provisioned-by=csi-cephfsplugin
StorageClass:    csi-cephfs
Status:          Bound
Claim:           default/csi-cephfs-pvc
Reclaim Policy:  Delete
Access Modes:    RWX
Capacity:        5Gi
Message:         
Source:
    Type:    CSI (a Container Storage Interface (CSI) volume source)
    Driver:      ReadOnly:  %v

    VolumeHandle:                                                                    csi-cephfsplugin
%!(EXTRA string=csi-cephfs-d8354a58-2b59-11e8-8a48-5254007d7491, bool=false)Events:  <none>

Only when I create a testing pod that is supposed to mount this volume, this happens:

$ kubectl describe po/web-server
...
Events:
  Type     Reason                  Age                From                     Message
  ----     ------                  ----               ----                     -------
  Warning  FailedScheduling        32s (x4 over 36s)  default-scheduler        pod has unbound PersistentVolumeClaims
  Normal   Scheduled               28s                default-scheduler        Successfully assigned web-server to kube.vlocal
  Normal   SuccessfulMountVolume   27s                kubelet, kube.vlocal     MountVolume.SetUp succeeded for volume "default-token-z7hr4"
  Normal   SuccessfulAttachVolume  12s                attachdetach-controller  AttachVolume.Attach succeeded for volume "kubernetes-dynamic-pv-d80d09d62b5911e8"
  Warning  FailedMount             4s (x5 over 12s)   kubelet, kube.vlocal     MountVolume.WaitForAttach failed for volume "kubernetes-dynamic-pv-d80d09d62b5911e8" : watch error:unknown (get volumeattachments.storage.k8s.io) for volume csi-cephfs-d8354a58-2b59-11e8-8a48-5254007d7491

Could you please describe your testing environment in more detail? And how you managed to run the RBD driver, because I'm running out of ideas on how do I get this one going.

@sbezverk
Copy link
Contributor

@gman0 Here is my deployment yaml.
https://gist.github.com/sbezverk/8343f6f1578ab45b0cd712104bf3b808
If you see PV gets created it means the controller part is done, after that kubelet will call csi plugin and csi plugin will call your driver's node call NodePublishVolume. I would suggest to focus in that area.

@@ -56,7 +56,7 @@ func (ids *DefaultIdentityServer) GetPluginCapabilities(ctx context.Context, req
{
Type: &csi.PluginCapability_Service_{
Service: &csi.PluginCapability_Service{
Type: csi.PluginCapability_Service_UNKNOWN,
Copy link
Member

Choose a reason for hiding this comment

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

you shouldn't change vendor code directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, I'll revert that

provisioner: csi-cephfsplugin
parameters:
# The driver can use either ceph-fuse (fuse) or ceph kernel client (kernel)
mounter: fuse
Copy link
Member

Choose a reason for hiding this comment

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

put the storage class on par with existing cephfs storage class, don't set mounter here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if not here, what would be the correct place to store such configuration?

Copy link
Member

Choose a reason for hiding this comment

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

probe cephfs-fuse first, if not exit, fall back to kernel cephfs

see kubernetes/kubernetes#55866

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But it can be assumed that both fuse and kernel client should be present anyway, since that's what the cephfsplugin Docker image contains, no? And one of our use-cases would be to override the defaults and use the kernel client instead, for performance reasons.

Copy link
Member

Choose a reason for hiding this comment

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

the probe idea tries one at a time till mounted. In this case, you can either make mounter order hard coded or based on a cli option. You can first try cephfs-fuse, if works then done, if not, try kernel cephfs.

Choose a reason for hiding this comment

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

It's fine to have a probe if not given, but we would like our users to be able to choose between using ceph-fuse or the kernel client explicitly. The best i think is to let them pass it (optionally) in the storage class.

rootPath: /
user: admin

csiProvisionerSecretName: csi-cephfs-secret
Copy link
Member

Choose a reason for hiding this comment

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

use the secret to create cephfs volumes

@gman0
Copy link
Contributor Author

gman0 commented Apr 13, 2018

  1. The default volume mounter is now determined by probing for ceph-fuse: if this succeeds - ceph-fuse it is, otherwise ceph kernel client is used. This probing heuristic can be overriden by a command line argument --volumemounter that accepts either fuse or kernel options. The mounter parameter in StorageClass is now optional and has the highest priority when choosing a mounter.
  2. New bool property provisionVolume in StorageClass: if set to true, a new volume is provisioned along with a dedicated user which is then used to mount this volume - requires admin access. Otherwise it expects an existing volume - rootPath as well as user credentials are required.
  3. Implemented DeleteVolume

@gman0
Copy link
Contributor Author

gman0 commented Apr 16, 2018

@rootfs @sbezverk could you please review? This PR is getting quite big, it would be cool to have it merged.

@rochaporto
Copy link

This looks ok now.

Can we get it merged and try to iterate with smaller PRs after? It got massive and seems kind of stuck.

@sbezverk
Copy link
Contributor

@rochaporto @gman0 Please address CI discovered failures and we will merge it.

@sbezverk sbezverk merged commit 2da9522 into ceph:master Apr 20, 2018
@gman0
Copy link
Contributor Author

gman0 commented Apr 20, 2018

Thanks a lot!

wilmardo pushed a commit to wilmardo/ceph-csi that referenced this pull request Jul 29, 2019
nixpanic pushed a commit to nixpanic/ceph-csi that referenced this pull request Mar 22, 2021
ocs: add initial ocs/README.md
Rakshith-R referenced this pull request in Rakshith-R/ceph-csi Sep 8, 2021
…-to-release-4.9

[release-4.9] syncing devel branch to get latest  updates
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants