Skip to content

Commit

Permalink
NFSMount storage plugin for kubelet.
Browse files Browse the repository at this point in the history
* If you want to test this out when an actual NFS export a good place
 to start is by running the NFS server in a container:

docker run -d --name nfs --privileged cpuguy83/nfs-server /tmp

More detail can be found here:
https://github.com/cpuguy83/docker-nfs-server
  • Loading branch information
calfonso committed Mar 19, 2015
1 parent d845d49 commit 1a45e37
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cmd/kubelet/app/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/gce_pd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/git_repo"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/host_path"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/nfs"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/secret"
)

Expand All @@ -41,6 +42,7 @@ func ProbeVolumePlugins() []volume.Plugin {
allPlugins = append(allPlugins, git_repo.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, host_path.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, secret.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, nfs.ProbeVolumePlugins()...)

return allPlugins
}
21 changes: 21 additions & 0 deletions examples/nfs/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: v1beta1
desiredState:
manifest:
containers:
- name: testpd
image: dockerfile/nginx
volumeMounts:
# name must match the volume name below
- name: nfs
mountPath: "/var/www/html/mount-test"
id: nfspd
version: v1beta1
volumes:
- name: nfs
source:
nfs:
server: "172.17.0.2"
path: "/tmp"
readOnly: false
id: nfspd
kind: Pod
9 changes: 9 additions & 0 deletions examples/storage/persistentvolume-nfs-example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
id: pv0003
kind: PersistentVolume
apiVersion: v1beta1
spec:
source:
nfsMount:
server: "172.17.0.2"
path: "/tmp"
readOnly: false
2 changes: 1 addition & 1 deletion pkg/api/testing/fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
func(vs *api.VolumeSource, c fuzz.Continue) {
// Exactly one of the fields should be set.
//FIXME: the fuzz can still end up nil. What if fuzz allowed me to say that?
fuzzOneOf(c, &vs.HostPath, &vs.EmptyDir, &vs.GCEPersistentDisk, &vs.GitRepo, &vs.Secret)
fuzzOneOf(c, &vs.HostPath, &vs.EmptyDir, &vs.GCEPersistentDisk, &vs.GitRepo, &vs.Secret, &vs.NFS)
},
func(d *api.DNSPolicy, c fuzz.Continue) {
policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault}
Expand Down
15 changes: 15 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ type VolumeSource struct {
GitRepo *GitRepoVolumeSource `json:"gitRepo"`
// Secret represents a secret that should populate this volume.
Secret *SecretVolumeSource `json:"secret"`
// NFS represents an NFS mount on the host that shares a pod's lifetime
NFS *NFSVolumeSource `json:"nfs"`
}

// HostPathVolumeSource represents a host directory mapped into a pod.
Expand Down Expand Up @@ -256,6 +258,19 @@ type SecretVolumeSource struct {
Target ObjectReference `json:"target"`
}

// NFSVolumeSource represents an NFS Mount that lasts the lifetime of a pod
type NFSVolumeSource struct {
// Server is the hostname or IP address of the NFS server
Server string `json:"server"`

// Path is the exported NFS share
Path string `json:"path"`

// Optional: Defaults to false (read/write). ReadOnly here will force
// the NFS export to be mounted with read-only permissions
ReadOnly bool `json:"readOnly,omitempty"`
}

// ContainerPort represents a network port in a single container
type ContainerPort struct {
// Optional: If specified, this must be a DNS_LABEL. Each named port
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,9 @@ func init() {
if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil {
return err
}
if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil {
return err
}
return nil
},
func(in *VolumeSource, out *newer.VolumeSource, s conversion.Scope) error {
Expand All @@ -1072,6 +1075,9 @@ func init() {
if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil {
return err
}
if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil {
return err
}
return nil
},

Expand Down
15 changes: 15 additions & 0 deletions pkg/api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ type VolumeSource struct {
GitRepo *GitRepoVolumeSource `json:"gitRepo" description:"git repository at a particular revision"`
// Secret represents a secret to populate the volume with
Secret *SecretVolumeSource `json:"secret" description:"secret to populate volume with"`
// NFS represents an NFS mount on the host that shares a pod's lifetime
NFS *NFSVolumeSource `json:"nfs" description:"NFS volume that will be mounted in the host machine "`
}

// HostPathVolumeSource represents bare host directory volume.
Expand Down Expand Up @@ -1154,6 +1156,19 @@ type ResourceQuotaList struct {
Items []ResourceQuota `json:"items" description:"items is a list of ResourceQuota objects"`
}

// NFSVolumeSource represents an NFS Mount that lasts the lifetime of a pod
type NFSVolumeSource struct {
// Server is the hostname or IP address of the NFS server
Server string `json:"server" description:"the hostname or IP address of the NFS server"`

// Path is the exported NFS share
Path string `json:"path" description:"the path that is exported by the NFS server"`

// Optional: Defaults to false (read/write). ReadOnly here will force
// the NFS export to be mounted as read-only permissions
ReadOnly bool `json:"readOnly,omitempty" description:"forces the NFS export to be mounted with read-only permissions"`
}

// Secret holds secret data of a certain type. The total bytes of the values in
// the Data field must be less than MaxSecretSize bytes.
type Secret struct {
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/v1beta2/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,9 @@ func init() {
if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil {
return err
}
if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil {
return err
}
return nil
},
func(in *VolumeSource, out *newer.VolumeSource, s conversion.Scope) error {
Expand All @@ -1000,6 +1003,9 @@ func init() {
if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil {
return err
}
if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil {
return err
}
return nil
},

Expand Down
15 changes: 15 additions & 0 deletions pkg/api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type VolumeSource struct {
GitRepo *GitRepoVolumeSource `json:"gitRepo" description:"git repository at a particular revision"`
// Secret is a secret to populate the volume with
Secret *SecretVolumeSource `json:"secret" description:"secret to populate volume"`
// NFS represents an NFS mount on the host that shares a pod's lifetime
NFS *NFSVolumeSource `json:"nfs" description:"NFS volume that will be mounted in the host machine"`
}

// HostPathVolumeSource represents bare host directory volume.
Expand Down Expand Up @@ -1215,6 +1217,19 @@ type ResourceQuotaList struct {
Items []ResourceQuota `json:"items" description:"items is a list of ResourceQuota objects"`
}

// NFSVolumeSource represents an NFS mount that lasts the lifetime of a pod
type NFSVolumeSource struct {
// Server is the hostname or IP address of the NFS server
Server string `json:"server" description:"the hostname or IP address of the NFS server"`

// Path is the exported NFS share
Path string `json:"path" description:"the path that is exported by the NFS server"`

// Optional: Defaults to false (read/write). ReadOnly here will force
// the NFS export to be mounted with read-only permissions
ReadOnly bool `json:"readOnly,omitempty" description:"forces the NFS export to be mounted with read-only permissions"`
}

// Secret holds secret data of a certain type. The total bytes of the values in
// the Data field must be less than MaxSecretSize bytes.
//
Expand Down
15 changes: 15 additions & 0 deletions pkg/api/v1beta3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ type VolumeSource struct {
GitRepo *GitRepoVolumeSource `json:"gitRepo" description:"git repository at a particular revision"`
// Secret represents a secret that should populate this volume.
Secret *SecretVolumeSource `json:"secret" description:"secret to populate volume"`
// NFS represents an NFS mount on the host that shares a pod's lifetime
NFS *NFSVolumeSource `json:"nfs" description:"NFS volume that will be mounted in the host machine"`
}

// HostPathVolumeSource represents bare host directory volume.
Expand Down Expand Up @@ -266,6 +268,19 @@ type SecretVolumeSource struct {
Target ObjectReference `json:"target" description:"target is a reference to a secret"`
}

// NFSVolumeSource represents an NFS mount that lasts the lifetime of a pod
type NFSVolumeSource struct {
// Server is the hostname or IP address of the NFS server
Server string `json:"server" description:"the hostname or IP address of the NFS server"`

// Path is the exported NFS share
Path string `json:"path" description:"the path that is exported by the NFS server"`

// Optional: Defaults to false (read/write). ReadOnly here will force
// the NFS export to be mounted with read-only permissions
ReadOnly bool `json:"readOnly,omitempty" description:"forces the NFS export to be mounted with read-only permissions"`
}

// ContainerPort represents a network port in a single container.
type ContainerPort struct {
// Optional: If specified, this must be a DNS_LABEL. Each named port
Expand Down
19 changes: 19 additions & 0 deletions pkg/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package validation

import (
"fmt"
"path"
"strings"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
Expand Down Expand Up @@ -290,6 +291,10 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
numVolumes++
allErrs = append(allErrs, validateSecretVolumeSource(source.Secret).Prefix("secret")...)
}
if source.NFS != nil {
numVolumes++
allErrs = append(allErrs, validateNFS(source.NFS).Prefix("nfs")...)
}
if numVolumes != 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required"))
}
Expand Down Expand Up @@ -340,6 +345,20 @@ func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) errs.Valid
return allErrs
}

func validateNFS(nfs *api.NFSVolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{}
if nfs.Server == "" {
allErrs = append(allErrs, errs.NewFieldRequired("server"))
}
if nfs.Path == "" {
allErrs = append(allErrs, errs.NewFieldRequired("path"))
}
if !path.IsAbs(nfs.Path) {
allErrs = append(allErrs, errs.NewFieldInvalid("path", nfs.Path, "must be an absolute path"))
}
return allErrs
}

var supportedPortProtocols = util.NewStringSet(string(api.ProtocolTCP), string(api.ProtocolUDP))

func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
Expand Down
Loading

0 comments on commit 1a45e37

Please sign in to comment.