Commit 63af7c22 authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #16069 from zmerlynn/nfs-1.1

Auto commit by PR queue bot
parents f13ed3ff b71bc4e4
...@@ -10,6 +10,7 @@ pkg-core: ...@@ -10,6 +10,7 @@ pkg-core:
- apt-transport-https - apt-transport-https
- python-apt - python-apt
- glusterfs-client - glusterfs-client
- nfs-common
- socat - socat
{% endif %} {% endif %}
# Ubuntu installs netcat-openbsd by default, but on GCE/Debian netcat-traditional is installed. # Ubuntu installs netcat-openbsd by default, but on GCE/Debian netcat-traditional is installed.
......
...@@ -291,15 +291,6 @@ before you can use it__ ...@@ -291,15 +291,6 @@ before you can use it__
See the [NFS example](../../examples/nfs/) for more details. See the [NFS example](../../examples/nfs/) for more details.
For example, [this file](../../examples/nfs/nfs-web-pod.yaml) demonstrates how to
specify the usage of an NFS volume within a pod.
In this example one can see that a `volumeMount` called `nfs` is being mounted
onto `/usr/share/nginx/html` in the container `web`. The volume "nfs" is defined as
type `nfs`, with the NFS server serving from `nfs-server.default.kube.local`
and exporting directory `/` as the share. The mount being created in this
example is writeable.
### iscsi ### iscsi
An `iscsi` volume allows an existing iSCSI (SCSI over IP) volume to be mounted An `iscsi` volume allows an existing iSCSI (SCSI over IP) volume to be mounted
......
...@@ -308,9 +308,13 @@ func TestExampleObjectSchemas(t *testing.T) { ...@@ -308,9 +308,13 @@ func TestExampleObjectSchemas(t *testing.T) {
"wordpress": &api.Pod{}, "wordpress": &api.Pod{},
}, },
"../examples/nfs": { "../examples/nfs": {
"nfs-server-pod": &api.Pod{}, "nfs-busybox-rc": &api.ReplicationController{},
"nfs-server-rc": &api.ReplicationController{},
"nfs-server-service": &api.Service{}, "nfs-server-service": &api.Service{},
"nfs-web-pod": &api.Pod{}, "nfs-pv": &api.PersistentVolume{},
"nfs-pvc": &api.PersistentVolumeClaim{},
"nfs-web-rc": &api.ReplicationController{},
"nfs-web-service": &api.Service{},
}, },
"../docs/user-guide/node-selection": { "../docs/user-guide/node-selection": {
"pod": &api.Pod{}, "pod": &api.Pod{},
......
...@@ -33,57 +33,115 @@ Documentation for other releases can be found at ...@@ -33,57 +33,115 @@ Documentation for other releases can be found at
# Example of NFS volume # Example of NFS volume
See [nfs-web-pod.yaml](nfs-web-pod.yaml) for a quick example, how to use NFS volume See [nfs-web-rc.yaml](nfs-web-rc.yaml) for a quick example of how to use an NFS
in a pod. volume claim in a replication controller. It relies on the
[NFS persistent volume](nfs-pv.yaml) and
[NFS persistent volume claim](nfs-pvc.yaml) in this example as well.
## Complete setup ## Complete setup
The example below shows how to export a NFS share from a pod and imports it The example below shows how to export a NFS share from a single pod replication
into another one. controller and import it into two replication controllers.
### Prerequisites ### NFS server part
Define [NFS server controller](nfs-server-rc.yaml) and
[NFS service](nfs-server-service.yaml):
```console
$ kubectl create -f examples/nfs/nfs-server-rc.yaml
$ kubectl create -f examples/nfs/nfs-server-service.yaml
```
The nfs server pod creates a privileged container, so if you are using a Salt based KUBERNETES_PROVIDER (**gce**, **vagrant**, **aws**), you have to enable the ability to create privileged containers by API. The server exports `/mnt/data` directory as `/` (fsid=0). The
directory contains dummy `index.html`. Wait until the pod is running
by checking `kubectl get pods -lrole=nfs-server`.
```sh ### Create the NFS claim
# At the root of Kubernetes source code
$ vi cluster/saltbase/pillar/privilege.sls
# If true, allow privileged containers to be created by API The [NFS busybox controller](nfs-busybox-rc.yaml) uses a simple script to
allow_privileged: true generate data written to the NFS server we just started. First, you'll need to
find the cluster IP of the server:
```console
$ kubectl describe services nfs-server
``` ```
For other non-salt based provider, you can set `--allow-privileged=true` for both api-server and kubelet, and then restart these components. Replace the invalid IP in the [nfs PV](nfs-pv.yaml). (In the future,
we'll be able to tie these together using the service names, but for
now, you have to hardcode the IP.)
Rebuild the Kubernetes and spin up a cluster using your preferred KUBERNETES_PROVIDER. Create the the [persistent volume](../../docs/user-guide/persistent-volumes.md)
and the persistent volume claim for your NFS server. The persistent volume and
claim gives us an indirection that allow multiple pods to refer to the NFS
server using a symbolic name rather than the hardcoded server address.
### NFS server part ```console
$ kubectl create -f examples/nfs/nfs-pv.yaml
$ kubectl create -f examples/nfs/nfs-pvc.yaml
```
Define [NFS server pod](nfs-server-pod.yaml) and ## Setup the fake backend
[NFS service](nfs-server-service.yaml):
$ kubectl create -f nfs-server-pod.yaml The [NFS busybox controller](nfs-busybox-rc.yaml) updates `index.html` on the
$ kubectl create -f nfs-server-service.yaml NFS server every 10 seconds. Let's start that now:
The server exports `/mnt/data` directory as `/` (fsid=0). The directory contains ```console
dummy `index.html`. Wait until the pod is running! $ kubectl create -f examples/nfs/nfs-busybox-rc.yaml
```
Conveniently, it's also a `busybox` pod, so we can get an early check
that our mounts are working now. Find a busybox pod and exec:
```console
$ kubectl get pod -lname=nfs-busybox
NAME READY STATUS RESTARTS AGE
nfs-busybox-jdhf3 1/1 Running 0 25m
nfs-busybox-w3s4t 1/1 Running 0 25m
$ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
Thu Oct 22 19:20:18 UTC 2015
nfs-busybox-w3s4t
```
You should see output similar to the above if everything is working well. If
it's not, make sure you changed the invalid IP in the [NFS PV](nfs-pv.yaml) file
and make sure the `describe services` command above had endpoints listed
(indicating the service was associated with a running pod).
### NFS client ### Setup the web server
[WEB server pod](nfs-web-pod.yaml) uses the NFS share exported above as a NFS The [web server controller](nfs-web-rc.yaml) is an another simple replication
volume and runs simple web server on it. The pod assumes your DNS is configured controller demonstrates reading from the NFS share exported above as a NFS
and the NFS service is reachable as `nfs-server.default.kube.local`. Edit the volume and runs a simple web server on it.
yaml file to supply another name or directly its IP address (use
`kubectl get services` to get it).
Define the pod: Define the pod:
$ kubectl create -f nfs-web-pod.yaml ```console
$ kubectl create -f examples/nfs/nfs-web-rc.yaml
```
This creates two pods, each of which serve the `index.html` from above. We can
then use a simple service to front it:
Now the pod serves `index.html` from the NFS server: ```console
kubectl create -f examples/nfs/nfs-web-service.yaml
```
$ curl http://<the container IP address>/ We can then use the busybox container we launched before to check that `nginx`
Hello World! is serving the data appropriately:
```console
$ kubectl get pod -lname=nfs-busybox
NAME READY STATUS RESTARTS AGE
nfs-busybox-jdhf3 1/1 Running 0 1h
nfs-busybox-w3s4t 1/1 Running 0 1h
$ kubectl get services nfs-web
NAME LABELS SELECTOR IP(S) PORT(S)
nfs-web <none> role=web-frontend 10.0.68.37 80/TCP
$ kubectl exec nfs-busybox-jdhf3 -- wget -qO- http://10.0.68.37
Thu Oct 22 19:28:55 UTC 2015
nfs-busybox-w3s4t
```
<!-- BEGIN MUNGE: GENERATED_ANALYTICS --> <!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
......
FROM fedora:21
MAINTAINER Jan Safranek <jsafrane@redhat.com>
EXPOSE 2049/tcp
RUN yum -y install nfs-utils && yum clean all
ADD run_nfs /usr/local/bin/
RUN chmod +x /usr/local/bin/run_nfs
ENTRYPOINT ["/usr/local/bin/run_nfs"]
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
The latest 1.0.x release of this document can be found
[here](http://releases.k8s.io/release-1.0/examples/nfs/exporter/README.md).
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
# NFS-exporter container
Inspired by https://github.com/cpuguy83/docker-nfs-server. Rewritten for
Fedora.
Serves NFS4 exports, defined on command line. At least one export must be defined!
Usage::
docker run -d --name nfs --privileged jsafrane/nfsexporter /path/to/share /path/to/share2 ...
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/nfs/exporter/README.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->
#!/bin/bash
# Copyright 2015 The Kubernetes Authors All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function start()
{
# prepare /etc/exports
seq=0
for i in "$@"; do
echo "$i *(rw,sync,no_root_squash,insecure,fsid=$seq)" >> /etc/exports
seq=$(($seq + 1))
echo "Serving $i"
done
# from /lib/systemd/system/proc-fs-nfsd.mount
mount -t nfsd nfds /proc/fs/nfsd
# from /lib/systemd/system/nfs-config.service
/usr/lib/systemd/scripts/nfs-utils_env.sh
# from /lib/systemd/system/nfs-mountd.service
. /run/sysconfig/nfs-utils
/usr/sbin/rpc.mountd $RPCMOUNTDARGS
# from /lib/systemd/system/nfs-server.service
. /run/sysconfig/nfs-utils
/usr/sbin/exportfs -r
/usr/sbin/rpc.nfsd -N 2 -N 3 -V 4 -V 4.1 $RPCNFSDARGS
echo "NFS started"
}
function stop()
{
echo "Stopping NFS"
# from /lib/systemd/system/nfs-server.service
/usr/sbin/rpc.nfsd 0
/usr/sbin/exportfs -au
/usr/sbin/exportfs -f
# from /lib/systemd/system/nfs-mountd.service
kill $( pidof rpc.mountd )
# from /lib/systemd/system/proc-fs-nfsd.mount
umount /proc/fs/nfsd
echo > /etc/exports
exit 0
}
trap stop TERM
start "$@"
# Ugly hack to do nothing and wait for SIGTERM
while true; do
read
done
# This mounts the nfs volume claim into /mnt and continuously
# overwrites /mnt/index.html with the time and hostname of the pod.
apiVersion: v1
kind: ReplicationController
metadata:
name: nfs-busybox
spec:
replicas: 2
selector:
name: nfs-busybox
template:
metadata:
labels:
name: nfs-busybox
spec:
containers:
- image: busybox
command:
- sh
- -c
- 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'
imagePullPolicy: IfNotPresent
name: busybox
volumeMounts:
# name must match the volume name below
- name: nfs
mountPath: "/mnt"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
capacity:
storage: 1Mi
accessModes:
- ReadWriteMany
nfs:
# FIXME: use the right IP
server: 10.999.999.999
path: "/"
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
apiVersion: v1 apiVersion: v1
kind: Pod kind: ReplicationController
metadata: metadata:
name: nfs-server name: nfs-server
labels:
role: nfs-server
spec: spec:
containers: replicas: 1
- name: nfs-server selector:
image: jsafrane/nfs-data role: nfs-server
ports: template:
- name: nfs metadata:
containerPort: 2049 labels:
securityContext: role: nfs-server
privileged: true spec:
containers:
- name: nfs-server
image: gcr.io/google_containers/volume-nfs
ports:
- name: nfs
containerPort: 2049
securityContext:
privileged: true
# # This pod mounts the nfs volume claim into /usr/share/nginx/html and
# This pod imports nfs-server.default.kube.local:/ into /usr/share/nginx/html # serves a simple web page.
#
apiVersion: v1 apiVersion: v1
kind: Pod kind: ReplicationController
metadata: metadata:
name: nfs-web name: nfs-web
spec: spec:
containers: replicas: 2
- name: web selector:
image: nginx role: web-frontend
ports: template:
- name: web metadata:
containerPort: 80 labels:
volumeMounts: role: web-frontend
# name must match the volume name below spec:
- name: nfs containers:
mountPath: "/usr/share/nginx/html" - name: web
volumes: image: nginx
- name: nfs ports:
nfs: - name: web
# FIXME: use the right hostname containerPort: 80
server: nfs-server.default.kube.local volumeMounts:
path: "/" # name must match the volume name below
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs
kind: Service
apiVersion: v1
metadata:
name: nfs-web
spec:
ports:
- port: 80
selector:
role: web-frontend
all: push all: push
TAG = 0.3 TAG = 0.4
container: container:
docker build -t gcr.io/google_containers/volume-nfs . # Build new image and automatically tag it as latest docker build -t gcr.io/google_containers/volume-nfs . # Build new image and automatically tag it as latest
......
...@@ -20,7 +20,7 @@ function start() ...@@ -20,7 +20,7 @@ function start()
# prepare /etc/exports # prepare /etc/exports
for i in "$@"; do for i in "$@"; do
# fsid=0: needed for NFSv4 # fsid=0: needed for NFSv4
echo "$i *(rw,fsid=0,no_root_squash)" >> /etc/exports echo "$i *(rw,fsid=0,insecure,no_root_squash)" >> /etc/exports
echo "Serving $i" echo "Serving $i"
done done
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment