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
|
||||
|
||||
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
|
||||
|
||||
You can reach the maintainers of this project at:
|
||||
|
||||
- [Slack](https://kubernetes.slack.com/messages/sig-storage)
|
||||
- [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).
|
||||
# test
|
||||
- `kubectl create -f deploy/test-claim.yaml`
|
||||
- `kubectl create -f deploy/test-pod.yaml`
|
||||
- check the folder and file "SUCCESS" created
|
||||
- `kubectl delete -f deploy/test-pod.yaml`
|
||||
- `kubectl delete -f deploy/test-claim.yaml`
|
||||
- check the folder renamed
|
||||
|
|
|
|||
|
|
@ -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