nfs-client-provisioner initial code
(cherry picked from commit 5a51799e23)
This commit is contained in:
parent
d8553fbc86
commit
3376ae7e5f
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
nfs-client-provisioner
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
FROM alpine:3.5
|
||||||
|
RUN apk update --no-cache && apk add ca-certificates
|
||||||
|
COPY nfs-client-provisioner /nfs-client-provisioner
|
||||||
|
ENTRYPOINT ["/nfs-client-provisioner"]
|
||||||
27
README.md
27
README.md
|
|
@ -1,16 +1,15 @@
|
||||||
# nfs-subdir-external-provisioner
|
# kubernetes nfs-client-provisioner
|
||||||
|
- pv provisioned as ${namespace}-${pvcName}-${pvName}
|
||||||
|
- pv recycled as archieved-${namespace}-${pvcName}-${pvName}
|
||||||
|
|
||||||
Dynamic sub-dir volume provisioner on a remote NFS server.
|
# deploy
|
||||||
|
- modify and deploy `deploy/deployment.yaml`
|
||||||
|
- modify and deploy `deploy/class.yaml`
|
||||||
|
|
||||||
## Community, discussion, contribution, and support
|
# test
|
||||||
|
- `kubectl create -f deploy/test-claim.yaml`
|
||||||
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
|
- `kubectl create -f deploy/test-pod.yaml`
|
||||||
|
- check the folder and file "SUCCESS" created
|
||||||
You can reach the maintainers of this project at:
|
- `kubectl delete -f deploy/test-pod.yaml`
|
||||||
|
- `kubectl delete -f deploy/test-claim.yaml`
|
||||||
- [Slack](https://kubernetes.slack.com/messages/sig-storage)
|
- check the folder renamed
|
||||||
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-storage)
|
|
||||||
|
|
||||||
### Code of conduct
|
|
||||||
|
|
||||||
Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
CGO_ENABLED=0 go build ./cmd/nfs-client-provisioner #&& docker build -t quay.io/jackieli/nfs-client-provisioner .
|
||||||
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kubernetes-incubator/external-storage/lib/controller"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/pkg/api/v1"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
provisionerNameKey = "PROVISIONER_NAME"
|
||||||
|
)
|
||||||
|
|
||||||
|
type nfsProvisioner struct {
|
||||||
|
client kubernetes.Interface
|
||||||
|
server string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
mountPath = "/persistentvolumes"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ controller.Provisioner = &nfsProvisioner{}
|
||||||
|
|
||||||
|
func (p *nfsProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {
|
||||||
|
if options.PVC.Spec.Selector != nil {
|
||||||
|
return nil, fmt.Errorf("claim Selector is not supported")
|
||||||
|
}
|
||||||
|
glog.V(4).Infof("nfs provisioner: VolumeOptions %v", options)
|
||||||
|
|
||||||
|
pvcNamespace := options.PVC.Namespace
|
||||||
|
pvcName := options.PVC.Name
|
||||||
|
|
||||||
|
pvName := strings.Join([]string{pvcNamespace, pvcName, options.PVName}, "-")
|
||||||
|
|
||||||
|
fullPath := filepath.Join(mountPath, pvName)
|
||||||
|
glog.V(4).Infof("creating path %s", fullPath)
|
||||||
|
if err := os.MkdirAll(fullPath, 0777); err != nil {
|
||||||
|
return nil, errors.New("unable to create directory to provision new pv: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(p.path, pvName)
|
||||||
|
|
||||||
|
pv := &v1.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: pvName,
|
||||||
|
},
|
||||||
|
Spec: v1.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
|
||||||
|
AccessModes: options.PVC.Spec.AccessModes,
|
||||||
|
Capacity: v1.ResourceList{
|
||||||
|
v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
|
||||||
|
},
|
||||||
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
|
NFS: &v1.NFSVolumeSource{
|
||||||
|
Server: p.server,
|
||||||
|
Path: path,
|
||||||
|
ReadOnly: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return pv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *nfsProvisioner) Delete(volume *v1.PersistentVolume) error {
|
||||||
|
path := volume.Spec.PersistentVolumeSource.NFS.Path
|
||||||
|
pvName := filepath.Base(path)
|
||||||
|
oldPath := filepath.Join(mountPath, pvName)
|
||||||
|
archivePath := filepath.Join(mountPath, "archieved-"+pvName)
|
||||||
|
glog.V(4).Infof("archiving path %s to %s", oldPath, archivePath)
|
||||||
|
return os.Rename(oldPath, archivePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
flag.Set("logtostderr", "true")
|
||||||
|
|
||||||
|
server := os.Getenv("NFS_SERVER")
|
||||||
|
if server == "" {
|
||||||
|
glog.Fatal("NFS_SERVER not set")
|
||||||
|
}
|
||||||
|
path := os.Getenv("NFS_PATH")
|
||||||
|
if path == "" {
|
||||||
|
glog.Fatal("NFS_PATH not set")
|
||||||
|
}
|
||||||
|
provisionerName := os.Getenv(provisionerNameKey)
|
||||||
|
if provisionerName == "" {
|
||||||
|
glog.Fatalf("environment variable %s is not set! Please set it.", provisionerNameKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an InClusterConfig and use it to create a client for the controller
|
||||||
|
// to use to communicate with Kubernetes
|
||||||
|
config, err := rest.InClusterConfig()
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Failed to create config: %v", err)
|
||||||
|
}
|
||||||
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Failed to create client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The controller needs to know what the server version is because out-of-tree
|
||||||
|
// provisioners aren't officially supported until 1.5
|
||||||
|
serverVersion, err := clientset.Discovery().ServerVersion()
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Error getting server version: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientNFSProvisioner := &nfsProvisioner{
|
||||||
|
server: server,
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
// Start the provision controller which will dynamically provision efs NFS
|
||||||
|
// PVs
|
||||||
|
pc := controller.NewProvisionController(clientset, provisionerName, clientNFSProvisioner, serverVersion.GitVersion)
|
||||||
|
pc.Run(wait.NeverStop)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
apiVersion: storage.k8s.io/v1beta1
|
||||||
|
kind: StorageClass
|
||||||
|
metadata:
|
||||||
|
name: managed-nfs-storage
|
||||||
|
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
kind: Deployment
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: nfs-client-provisioner
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nfs-client-provisioner
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nfs-client-provisioner
|
||||||
|
image: quay.io/jackieli/nfs-client-provisioner:v1
|
||||||
|
volumeMounts:
|
||||||
|
- name: nfs-client-root
|
||||||
|
mountPath: /persistentvolumes
|
||||||
|
env:
|
||||||
|
- name: PROVISIONER_NAME
|
||||||
|
value: fuseim.pri/ifs
|
||||||
|
- name: NFS_SERVER
|
||||||
|
value: 10.10.10.60
|
||||||
|
- name: NFS_PATH
|
||||||
|
value: /ifs/kubernetes
|
||||||
|
volumes:
|
||||||
|
- name: nfs-client-root
|
||||||
|
nfs:
|
||||||
|
server: 10.10.10.60
|
||||||
|
path: /ifs/kubernetes
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: test-claim
|
||||||
|
annotations:
|
||||||
|
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Mi
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: test-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: test-pod
|
||||||
|
image: gcr.io/google_containers/busybox:1.24
|
||||||
|
command:
|
||||||
|
- "/bin/sh"
|
||||||
|
args:
|
||||||
|
- "-c"
|
||||||
|
- "touch /mnt/SUCCESS && exit 0 || exit 1"
|
||||||
|
volumeMounts:
|
||||||
|
- name: nfs-pvc
|
||||||
|
mountPath: "/mnt"
|
||||||
|
restartPolicy: "Never"
|
||||||
|
volumes:
|
||||||
|
- name: nfs-pvc
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: test-claim
|
||||||
Loading…
Reference in New Issue