Refactor RBD volume

This commit is contained in:
Serguei Bezverkhi 2017-10-23 16:59:34 -04:00
parent 6f06408eea
commit 1411c2698e
13 changed files with 346 additions and 50 deletions

View File

@ -355,6 +355,20 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
r.Keyring = "/etc/ceph/keyring"
}
},
func(r *api.RBDPersistentVolumeSource, c fuzz.Continue) {
r.RBDPool = c.RandString()
if r.RBDPool == "" {
r.RBDPool = "rbd"
}
r.RadosUser = c.RandString()
if r.RadosUser == "" {
r.RadosUser = "admin"
}
r.Keyring = c.RandString()
if r.Keyring == "" {
r.Keyring = "/etc/ceph/keyring"
}
},
func(obj *api.HostPathVolumeSource, c fuzz.Continue) {
c.FuzzNoCustom(obj)
types := []api.HostPathType{api.HostPathUnset, api.HostPathDirectoryOrCreate, api.HostPathDirectory,

View File

@ -64,8 +64,16 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
return false
}
case source.RBD != nil:
if source.RBD.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.RBD.SecretRef.Name) {
return false
if source.RBD.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.RBD.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.RBD.SecretRef.Namespace
}
if !visitor(ns, source.RBD.SecretRef.Name) {
return false
}
}
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.ScaleIO.SecretRef.Name) {

View File

@ -65,9 +65,16 @@ func TestPVSecrets(t *testing.T) {
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
RBD: &api.RBDVolumeSource{
SecretRef: &api.LocalObjectReference{
RBD: &api.RBDPersistentVolumeSource{
SecretRef: &api.SecretReference{
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
RBD: &api.RBDPersistentVolumeSource{
SecretRef: &api.SecretReference{
Name: "Spec.PersistentVolumeSource.RBD.SecretRef",
Namespace: "rbdns"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
@ -141,6 +148,7 @@ func TestPVSecrets(t *testing.T) {
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
"rbdns/Spec.PersistentVolumeSource.RBD.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",

View File

@ -343,7 +343,7 @@ type PersistentVolumeSource struct {
NFS *NFSVolumeSource
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime
// +optional
RBD *RBDVolumeSource
RBD *RBDPersistentVolumeSource
// Quobyte represents a Quobyte mount on the host that shares a pod's lifetime
// +optional
Quobyte *QuobyteVolumeSource
@ -1006,6 +1006,37 @@ type RBDVolumeSource struct {
ReadOnly bool
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling.
type RBDPersistentVolumeSource struct {
// Required: CephMonitors is a collection of Ceph monitors
CephMonitors []string
// Required: RBDImage is the rados image name
RBDImage string
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// TODO: how do we prevent errors in the filesystem from compromising the machine
// +optional
FSType string
// Optional: RadosPool is the rados pool name,default is rbd
// +optional
RBDPool string
// Optional: RBDUser is the rados user name, default is admin
// +optional
RadosUser string
// Optional: Keyring is the path to key ring for RBDUser, default is /etc/ceph/keyring
// +optional
Keyring string
// Optional: SecretRef is reference to the authentication secret for User, default is empty.
// +optional
SecretRef *SecretReference
// Optional: Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
}
// Represents a cinder volume resource in Openstack. A Cinder volume
// must exist before mounting to a container. The volume must also be
// in the same region as the kubelet. Cinder volumes support ownership

View File

@ -368,6 +368,18 @@ func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
}
}
func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
if obj.RBDPool == "" {
obj.RBDPool = "rbd"
}
if obj.RadosUser == "" {
obj.RadosUser = "admin"
}
if obj.Keyring == "" {
obj.Keyring = "/etc/ceph/keyring"
}
}
func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
if obj.ProtectionDomain == "" {
obj.ProtectionDomain = "default"

View File

@ -1088,6 +1088,17 @@ func validateRBDVolumeSource(rbd *api.RBDVolumeSource, fldPath *field.Path) fiel
return allErrs
}
func validateRBDPersistentVolumeSource(rbd *api.RBDPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(rbd.CephMonitors) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("monitors"), ""))
}
if len(rbd.RBDImage) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("image"), ""))
}
return allErrs
}
func validateCinderVolumeSource(cd *api.CinderVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(cd.VolumeID) == 0 {
@ -1380,7 +1391,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(specPath.Child("rbd"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateRBDVolumeSource(pv.Spec.RBD, specPath.Child("rbd"))...)
allErrs = append(allErrs, validateRBDPersistentVolumeSource(pv.Spec.RBD, specPath.Child("rbd"))...)
}
}
if pv.Spec.Quobyte != nil {

View File

@ -898,6 +898,19 @@ func printRBDVolumeSource(rbd *api.RBDVolumeSource, w PrefixWriter) {
rbd.CephMonitors, rbd.RBDImage, rbd.FSType, rbd.RBDPool, rbd.RadosUser, rbd.Keyring, rbd.SecretRef, rbd.ReadOnly)
}
func printRBDPersistentVolumeSource(rbd *api.RBDPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tRBD (a Rados Block Device mount on the host that shares a pod's lifetime)\n"+
" CephMonitors:\t%v\n"+
" RBDImage:\t%v\n"+
" FSType:\t%v\n"+
" RBDPool:\t%v\n"+
" RadosUser:\t%v\n"+
" Keyring:\t%v\n"+
" SecretRef:\t%v\n"+
" ReadOnly:\t%v\n",
rbd.CephMonitors, rbd.RBDImage, rbd.FSType, rbd.RBDPool, rbd.RadosUser, rbd.Keyring, rbd.SecretRef, rbd.ReadOnly)
}
func printDownwardAPIVolumeSource(d *api.DownwardAPIVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tDownwardAPI (a volume populated by information about the pod)\n Items:\n")
for _, mapping := range d.Items {
@ -1108,7 +1121,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.Glusterfs != nil:
printGlusterfsVolumeSource(pv.Spec.Glusterfs, w)
case pv.Spec.RBD != nil:
printRBDVolumeSource(pv.Spec.RBD, w)
printRBDPersistentVolumeSource(pv.Spec.RBD, w)
case pv.Spec.Quobyte != nil:
printQuobyteVolumeSource(pv.Spec.Quobyte, w)
case pv.Spec.VsphereVolume != nil:

View File

@ -776,7 +776,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
RBD: &api.RBDVolumeSource{},
RBD: &api.RBDPersistentVolumeSource{},
},
},
},

View File

@ -39,7 +39,7 @@ type diskManager interface {
// Detaches the disk from the kubelet's host machine.
DetachDisk(disk rbdUnmounter, mntPath string) error
// Creates a rbd image
CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, volumeSizeGB int, err error)
CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error)
// Deletes a rbd image
DeleteImage(deleter *rbdVolumeDeleter) error
}

View File

@ -78,15 +78,19 @@ func (plugin *rbdPlugin) GetPluginName() string {
}
func (plugin *rbdPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
volumeSource, _, err := getVolumeSource(spec)
mon, err := getVolumeSourceMonitors(spec)
if err != nil {
return "", err
}
img, err := getVolumeSourceImage(spec)
if err != nil {
return "", err
}
return fmt.Sprintf(
"%v:%v",
volumeSource.CephMonitors,
volumeSource.RBDImage), nil
mon,
img), nil
}
func (plugin *rbdPlugin) CanSupport(spec *volume.Spec) bool {
@ -117,55 +121,79 @@ func (plugin *rbdPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
}
func (plugin *rbdPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
var secret string
var err error
source, _ := plugin.getRBDVolumeSource(spec)
if source.SecretRef != nil {
if secret, err = parsePodSecret(pod, source.SecretRef.Name, plugin.host.GetKubeClient()); err != nil {
glog.Errorf("Couldn't get secret from %v/%v", pod.Namespace, source.SecretRef)
secretName, secretNs, err := getSecretNameAndNamespace(spec, pod.Namespace)
if err != nil {
return nil, err
}
secret := ""
if len(secretName) > 0 && len(secretNs) > 0 {
// if secret is provideded, retrieve it
kubeClient := plugin.host.GetKubeClient()
if kubeClient == nil {
return nil, fmt.Errorf("Cannot get kube client")
}
secrets, err := kubeClient.Core().Secrets(secretNs).Get(secretName, metav1.GetOptions{})
if err != nil {
err = fmt.Errorf("Couldn't get secret %v/%v err: %v", secretNs, secretName, err)
return nil, err
}
for _, data := range secrets.Data {
secret = string(data)
}
}
// Inject real implementations here, test through the internal function.
return plugin.newMounterInternal(spec, pod.UID, &RBDUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
}
func (plugin *rbdPlugin) getRBDVolumeSource(spec *volume.Spec) (*v1.RBDVolumeSource, bool) {
// rbd volumes used directly in a pod have a ReadOnly flag set by the pod author.
// rbd volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD, spec.Volume.RBD.ReadOnly
} else {
return spec.PersistentVolume.Spec.RBD, spec.ReadOnly
}
}
func (plugin *rbdPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec, secret string) (volume.Mounter, error) {
source, readOnly := plugin.getRBDVolumeSource(spec)
pool := source.RBDPool
id := source.RadosUser
keyring := source.Keyring
mon, err := getVolumeSourceMonitors(spec)
if err != nil {
return nil, err
}
img, err := getVolumeSourceImage(spec)
if err != nil {
return nil, err
}
fstype, err := getVolumeSourceFSType(spec)
if err != nil {
return nil, err
}
pool, err := getVolumeSourcePool(spec)
if err != nil {
return nil, err
}
id, err := getVolumeSourceUser(spec)
if err != nil {
return nil, err
}
keyring, err := getVolumeSourceKeyRing(spec)
if err != nil {
return nil, err
}
ro, err := getVolumeSourceReadOnly(spec)
if err != nil {
return nil, err
}
return &rbdMounter{
rbd: &rbd{
podUID: podUID,
volName: spec.Name(),
Image: source.RBDImage,
Image: img,
Pool: pool,
ReadOnly: readOnly,
ReadOnly: ro,
manager: manager,
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
exec: exec,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
},
Mon: source.CephMonitors,
Mon: mon,
Id: id,
Keyring: keyring,
Secret: secret,
fsType: source.FSType,
fsType: fstype,
mountOptions: volume.MountOptionFromSpec(spec),
}, nil
}
@ -289,8 +317,9 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
var err error
adminSecretName := ""
adminSecretNamespace := rbdDefaultAdminSecretNamespace
secretName := ""
secret := ""
secretName := ""
secretNamespace := ""
imageFormat := rbdImageFormat2
fstype := ""
@ -313,6 +342,8 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
r.Pool = v
case "usersecretname":
secretName = v
case "usersecretnamespace":
secretNamespace = v
case "imageformat":
imageFormat = v
case "imagefeatures":
@ -370,8 +401,9 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
glog.Infof("successfully created rbd image %q", image)
pv := new(v1.PersistentVolume)
metav1.SetMetaDataAnnotation(&pv.ObjectMeta, volumehelper.VolumeDynamicallyCreatedByKey, "rbd-dynamic-provisioner")
rbd.SecretRef = new(v1.LocalObjectReference)
rbd.SecretRef = new(v1.SecretReference)
rbd.SecretRef.Name = secretName
rbd.SecretRef.Namespace = secretNamespace
rbd.RadosUser = r.Id
rbd.FSType = fstype
pv.Spec.PersistentVolumeSource.RBD = rbd
@ -486,16 +518,83 @@ func (c *rbdUnmounter) TearDownAt(dir string) error {
return diskTearDown(c.manager, *c, dir, c.mounter)
}
func getVolumeSource(
spec *volume.Spec) (*v1.RBDVolumeSource, bool, error) {
func getVolumeSourceMonitors(spec *volume.Spec) ([]string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD, spec.Volume.RBD.ReadOnly, nil
return spec.Volume.RBD.CephMonitors, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD, spec.ReadOnly, nil
return spec.PersistentVolume.Spec.RBD.CephMonitors, nil
}
return nil, false, fmt.Errorf("Spec does not reference a RBD volume type")
return nil, fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourceImage(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.RBDImage, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD.RBDImage, nil
}
return "", fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourceFSType(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.FSType, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD.FSType, nil
}
return "", fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourcePool(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.RBDPool, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD.RBDPool, nil
}
return "", fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourceUser(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.RadosUser, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD.RadosUser, nil
}
return "", fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourceKeyRing(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.Keyring, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
return spec.PersistentVolume.Spec.RBD.Keyring, nil
}
return "", fmt.Errorf("Spec does not reference a RBD volume type")
}
func getVolumeSourceReadOnly(spec *volume.Spec) (bool, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD.ReadOnly, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
// rbd volumes used as a PersistentVolume gets the ReadOnly flag indirectly through
// the persistent-claim volume used to mount the PV
return spec.ReadOnly, nil
}
return false, fmt.Errorf("Spec does not reference a RBD volume type")
}
func parsePodSecret(pod *v1.Pod, secretName string, kubeClient clientset.Interface) (string, error) {
@ -531,3 +630,26 @@ func parseSecretMap(secretMap map[string]string) (string, error) {
// If not found, the last secret in the map wins as done before
return secret, nil
}
func getSecretNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) {
if spec.Volume != nil && spec.Volume.RBD != nil {
localSecretRef := spec.Volume.RBD.SecretRef
if localSecretRef != nil {
return localSecretRef.Name, defaultNamespace, nil
}
return "", "", nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
secretRef := spec.PersistentVolume.Spec.RBD.SecretRef
secretNs := defaultNamespace
if secretRef != nil {
if len(secretRef.Namespace) != 0 {
secretNs = secretRef.Namespace
}
return secretRef.Name, secretNs, nil
}
return "", "", nil
}
return "", "", fmt.Errorf("Spec does not reference an RBD volume type")
}

View File

@ -22,6 +22,7 @@ import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@ -92,7 +93,7 @@ func (fake *fakeDiskManager) DetachDisk(c rbdUnmounter, mntPath string) error {
return nil
}
func (fake *fakeDiskManager) CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, volumeSizeGB int, err error) {
func (fake *fakeDiskManager) CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error) {
return nil, 0, fmt.Errorf("not implemented")
}
@ -180,7 +181,7 @@ func TestPluginPersistentVolume(t *testing.T) {
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
RBD: &v1.RBDVolumeSource{
RBD: &v1.RBDPersistentVolumeSource{
CephMonitors: []string{"a", "b"},
RBDImage: "bar",
FSType: "ext4",
@ -205,7 +206,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
RBD: &v1.RBDVolumeSource{
RBD: &v1.RBDPersistentVolumeSource{
CephMonitors: []string{"a", "b"},
RBDImage: "bar",
FSType: "ext4",
@ -329,3 +330,35 @@ func TestPersistAndLoadRBD(t *testing.T) {
}
}
}
func TestGetSecretNameAndNamespace(t *testing.T) {
secretName := "test-secret-name"
secretNamespace := "test-secret-namespace"
volSpec := &volume.Spec{
PersistentVolume: &v1.PersistentVolume{
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
RBD: &v1.RBDPersistentVolumeSource{
CephMonitors: []string{"a", "b"},
RBDImage: "bar",
FSType: "ext4",
},
},
},
},
}
secretRef := new(v1.SecretReference)
secretRef.Name = secretName
secretRef.Namespace = secretNamespace
volSpec.PersistentVolume.Spec.PersistentVolumeSource.RBD.SecretRef = secretRef
foundSecretName, foundSecretNamespace, err := getSecretNameAndNamespace(volSpec, "default")
if err != nil {
t.Errorf("getSecretNameAndNamespace failed to get Secret's name and namespace: %v", err)
}
if strings.Compare(secretName, foundSecretName) != 0 || strings.Compare(secretNamespace, foundSecretNamespace) != 0 {
t.Errorf("getSecretNameAndNamespace returned incorrect values, expected %s and %s but got %s and %s", secretName, secretNamespace, foundSecretName, foundSecretNamespace)
}
}

View File

@ -362,7 +362,7 @@ func (util *RBDUtil) DetachDisk(c rbdUnmounter, mntPath string) error {
return nil
}
func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, size int, err error) {
func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, size int, err error) {
var output []byte
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
volSizeBytes := capacity.Value()
@ -400,7 +400,7 @@ func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDVolumeSource
return nil, 0, fmt.Errorf("failed to create rbd image: %v, command output: %s", err, string(output))
}
return &v1.RBDVolumeSource{
return &v1.RBDPersistentVolumeSource{
CephMonitors: p.rbdMounter.Mon,
RBDImage: p.rbdMounter.Image,
RBDPool: p.rbdMounter.Pool,

View File

@ -398,7 +398,7 @@ type PersistentVolumeSource struct {
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md
// +optional
RBD *RBDVolumeSource `json:"rbd,omitempty" protobuf:"bytes,6,opt,name=rbd"`
RBD *RBDPersistentVolumeSource `json:"rbd,omitempty" protobuf:"bytes,6,opt,name=rbd"`
// ISCSI represents an ISCSI Disk resource that is attached to a
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
// +optional
@ -838,6 +838,50 @@ type RBDVolumeSource struct {
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,8,opt,name=readOnly"`
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling.
type RBDPersistentVolumeSource struct {
// A collection of Ceph monitors.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
CephMonitors []string `json:"monitors" protobuf:"bytes,1,rep,name=monitors"`
// The rados image name.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
RBDImage string `json:"image" protobuf:"bytes,2,opt,name=image"`
// Filesystem type of the volume that you want to mount.
// Tip: Ensure that the filesystem type is supported by the host operating system.
// Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd
// TODO: how do we prevent errors in the filesystem from compromising the machine
// +optional
FSType string `json:"fsType,omitempty" protobuf:"bytes,3,opt,name=fsType"`
// The rados pool name.
// Default is rbd.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
// +optional
RBDPool string `json:"pool,omitempty" protobuf:"bytes,4,opt,name=pool"`
// The rados user name.
// Default is admin.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
// +optional
RadosUser string `json:"user,omitempty" protobuf:"bytes,5,opt,name=user"`
// Keyring is the path to key ring for RBDUser.
// Default is /etc/ceph/keyring.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
// +optional
Keyring string `json:"keyring,omitempty" protobuf:"bytes,6,opt,name=keyring"`
// SecretRef is name of the authentication secret for RBDUser. If provided
// overrides keyring.
// Default is nil.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
// +optional
SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,7,opt,name=secretRef"`
// ReadOnly here will force the ReadOnly setting in VolumeMounts.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,8,opt,name=readOnly"`
}
// Represents a cinder volume resource in Openstack.
// A Cinder volume must exist before mounting to a container.
// The volume must also be in the same region as the kubelet.