mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
Added more to README, tweaked pod, added service, fixed validation
This commit is contained in:
parent
b634f17ca7
commit
2cf4e6564b
@ -3,15 +3,19 @@
|
|||||||
The purpose of this guide is to help you become familiar with Kubernetes Persistent Volumes. By the end of the guide, we'll have
|
The purpose of this guide is to help you become familiar with Kubernetes Persistent Volumes. By the end of the guide, we'll have
|
||||||
nginx serving content from your persistent volume.
|
nginx serving content from your persistent volume.
|
||||||
|
|
||||||
This guide assumes knowledge of Kubernetes fundamentals and that a user has a cluster up and running.
|
This guide assumes knowledge of Kubernetes fundamentals and that you have a cluster up and running.
|
||||||
|
|
||||||
## Provisioning
|
## Provisioning
|
||||||
|
|
||||||
A PersistentVolume in Kubernetes represents a real piece of underlying storage capacity in the infrastructure. Cluster administrators
|
A PersistentVolume in Kubernetes represents a real piece of underlying storage capacity in the infrastructure. Cluster administrators
|
||||||
must first create storage (create their GCE disks, export their NFS shares, etc.) in order for Kubernetes to mount it.
|
must first create storage (create their GCE disks, export their NFS shares, etc.) in order for Kubernetes to mount it.
|
||||||
|
|
||||||
PVs are intended for "network volumes" like GCE Persistent Disks, NFS shares, and AWS ElasticBlockStore volumes. `HostPath` was included
|
PVs are intended for "network volumes" like GCE Persistent Disks, NFS shares, and AWS ElasticBlockStore volumes. ```HostPath``` was included
|
||||||
for ease of development and testing. You'll create a local `HostPath` for this example.
|
for ease of development and testing. You'll create a local ```HostPath``` for this example.
|
||||||
|
|
||||||
|
> IMPORTANT! For ```HostPath``` to work, you will need to run a single node cluster. Kubernetes does not
|
||||||
|
support local storage on the host at this time. There is no guarantee your pod ends up on the correct node where the ```HostPath``` resides.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -28,17 +32,17 @@ PVs are created by posting them to the API server.
|
|||||||
cluster/kubectl.sh create -f examples/persistent-volumes/volumes/local-01.yaml
|
cluster/kubectl.sh create -f examples/persistent-volumes/volumes/local-01.yaml
|
||||||
cluster/kubectl.sh get pv
|
cluster/kubectl.sh get pv
|
||||||
|
|
||||||
NAME LABELS CAPACITY ACCESSMODES STATUS CLAIM
|
NAME LABELS CAPACITY ACCESSMODES STATUS CLAIM
|
||||||
pv0001 map[] 10737418240 RWO Available
|
pv0001 map[] 10737418240 RWO Available
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Requesting storage
|
## Requesting storage
|
||||||
|
|
||||||
Users of Kubernetes request persistent storage for their pods. They don't know how the underlying cluster is provisioned.
|
Users of Kubernetes request persistent storage for their pods. They don't know how the underlying cluster is provisioned.
|
||||||
They just know they can rely on their claim to storage and they can manage its lifecycle independently from the many pods that may use it.
|
They just know they can rely on their claim to storage and can manage its lifecycle independently from the many pods that may use it.
|
||||||
|
|
||||||
You must be in a namespace to create claims.
|
Claims must be created in the same namespace as the pods that use them.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -60,7 +64,7 @@ myclaim-1 map[] Bound f5c3a89a-e50a-11e4-972f-80e6500a981e
|
|||||||
|
|
||||||
cluster/kubectl.sh get pv
|
cluster/kubectl.sh get pv
|
||||||
|
|
||||||
NAME LABELS CAPACITY ACCESSMODES STATUS CLAIM
|
NAME LABELS CAPACITY ACCESSMODES STATUS CLAIM
|
||||||
pv0001 map[] 10737418240 RWO Bound myclaim-1 / 6bef4c40-e50b-11e4-972f-80e6500a981e
|
pv0001 map[] 10737418240 RWO Bound myclaim-1 / 6bef4c40-e50b-11e4-972f-80e6500a981e
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -70,7 +74,8 @@ pv0001 map[] 10737418240 RWO
|
|||||||
Claims are used as volumes in pods. Kubernetes uses the claim to look up its bound PV. The PV is then exposed to the pod.
|
Claims are used as volumes in pods. Kubernetes uses the claim to look up its bound PV. The PV is then exposed to the pod.
|
||||||
|
|
||||||
```
|
```
|
||||||
k create -f examples/persistent-volumes/simpletest/pod.yaml
|
|
||||||
|
cluster/kubectl.sh create -f examples/persistent-volumes/simpletest/pod.yaml
|
||||||
|
|
||||||
cluster/kubectl.sh get pods
|
cluster/kubectl.sh get pods
|
||||||
|
|
||||||
@ -78,14 +83,30 @@ POD IP CONTAINER(S) IMAGE(S) HOST LABELS
|
|||||||
mypod 172.17.0.2 myfrontend nginx 127.0.0.1/127.0.0.1 <none> Running 12 minutes
|
mypod 172.17.0.2 myfrontend nginx 127.0.0.1/127.0.0.1 <none> Running 12 minutes
|
||||||
|
|
||||||
|
|
||||||
k create -f examples/persistent-volumes/simpletest/service.json
|
cluster/kubectl.sh create -f examples/persistent-volumes/simpletest/service.json
|
||||||
cluster/kubectl.sh get services
|
cluster/kubectl.sh get services
|
||||||
Running: cluster/../cluster/gce/../../cluster/../_output/local/bin/darwin/amd64/kubectl --v=5 get services
|
|
||||||
NAME LABELS SELECTOR IP PORT(S)
|
NAME LABELS SELECTOR IP PORT(S)
|
||||||
kubernetes component=apiserver,provider=kubernetes <none> 10.0.0.2 443/TCP
|
frontendservice <none> name=frontendhttp 10.0.0.241 3000/TCP
|
||||||
kubernetes-ro component=apiserver,provider=kubernetes <none> 10.0.0.1 80/TCP
|
kubernetes component=apiserver,provider=kubernetes <none> 10.0.0.2 443/TCP
|
||||||
|
kubernetes-ro component=apiserver,provider=kubernetes <none> 10.0.0.1 80/TCP
|
||||||
|
|
||||||
|
|
||||||
curl 10.0.0.168:3000
|
|
||||||
I love Kubernetes storage!
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
You should be able to query your service endpoint and see what content nginx is serving. A "forbidden" error might mean you
|
||||||
|
need to disable SELinux (setenforce 0).
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
curl 10.0.0.241:3000
|
||||||
|
I love Kubernetes storage!
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Hopefully this simple guide is enough to get you started with PersistentVolumes. If you have any questions, join
|
||||||
|
```#google-containers``` on IRC and ask!
|
||||||
|
|
||||||
|
Enjoy!
|
||||||
|
@ -2,17 +2,19 @@ kind: Pod
|
|||||||
apiVersion: v1beta3
|
apiVersion: v1beta3
|
||||||
metadata:
|
metadata:
|
||||||
name: mypod
|
name: mypod
|
||||||
|
labels:
|
||||||
|
name: frontendhttp
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: nginx
|
- name: myfrontend
|
||||||
name: myfrontend
|
image: dockerfile/nginx
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: "http-server"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: "/var/www/html"
|
- mountPath: "/var/www/html"
|
||||||
name: mypd
|
name: mypd
|
||||||
volumes:
|
volumes:
|
||||||
- name: mypd
|
- name: mypd
|
||||||
source:
|
persistentVolumeClaim:
|
||||||
persistentVolumeClaim:
|
claimName: myclaim-1
|
||||||
accessMode: ReadWriteOnce
|
|
||||||
claimRef:
|
|
||||||
name: myclaim-1
|
|
9
examples/persistent-volumes/simpletest/service.json
Normal file
9
examples/persistent-volumes/simpletest/service.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"apiVersion": "v1beta1",
|
||||||
|
"kind": "Service",
|
||||||
|
"id": "frontendservice",
|
||||||
|
"port": 3000,
|
||||||
|
"containerPort": "http-server",
|
||||||
|
"selector": { "name": "frontendhttp" },
|
||||||
|
"createExternalLoadBalancer": false
|
||||||
|
}
|
@ -319,6 +319,11 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
|
|||||||
numVolumes++
|
numVolumes++
|
||||||
allErrs = append(allErrs, validateGlusterfs(source.Glusterfs).Prefix("glusterfs")...)
|
allErrs = append(allErrs, validateGlusterfs(source.Glusterfs).Prefix("glusterfs")...)
|
||||||
}
|
}
|
||||||
|
if source.PersistentVolumeClaimVolumeSource != nil {
|
||||||
|
numVolumes++
|
||||||
|
allErrs = append(allErrs, validatePersistentClaimVolumeSource(source.PersistentVolumeClaimVolumeSource).Prefix("glusterfs")...)
|
||||||
|
}
|
||||||
|
|
||||||
if numVolumes != 1 {
|
if numVolumes != 1 {
|
||||||
allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required"))
|
allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required"))
|
||||||
}
|
}
|
||||||
@ -394,6 +399,14 @@ func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) errs.Valid
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validatePersistentClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeSource) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
if claim.ClaimName == "" {
|
||||||
|
allErrs = append(allErrs, errs.NewFieldRequired("claimName"))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
func validateNFS(nfs *api.NFSVolumeSource) errs.ValidationErrorList {
|
func validateNFS(nfs *api.NFSVolumeSource) errs.ValidationErrorList {
|
||||||
allErrs := errs.ValidationErrorList{}
|
allErrs := errs.ValidationErrorList{}
|
||||||
if nfs.Server == "" {
|
if nfs.Server == "" {
|
||||||
|
@ -18,6 +18,7 @@ package volumeclaimbinder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
@ -30,7 +31,6 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PersistentVolumeClaimBinder is a controller that synchronizes PersistentVolumeClaims.
|
// PersistentVolumeClaimBinder is a controller that synchronizes PersistentVolumeClaims.
|
||||||
@ -94,7 +94,6 @@ func NewPersistentVolumeClaimBinder(kubeClient client.Interface, syncPeriod time
|
|||||||
syncClaim(volumeIndex, binderClient, claim)
|
syncClaim(volumeIndex, binderClient, claim)
|
||||||
},
|
},
|
||||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||||
// oldClaim := newObj.(*api.PersistentVolumeClaim)
|
|
||||||
newClaim := newObj.(*api.PersistentVolumeClaim)
|
newClaim := newObj.(*api.PersistentVolumeClaim)
|
||||||
if newClaim.Status.VolumeRef == nil {
|
if newClaim.Status.VolumeRef == nil {
|
||||||
syncClaim(volumeIndex, binderClient, newClaim)
|
syncClaim(volumeIndex, binderClient, newClaim)
|
||||||
|
@ -17,10 +17,10 @@ limitations under the License.
|
|||||||
package volumeclaimbinder
|
package volumeclaimbinder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||||
|
@ -17,9 +17,10 @@ limitations under the License.
|
|||||||
package volumeclaimbinder
|
package volumeclaimbinder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMatchVolume(t *testing.T) {
|
func TestMatchVolume(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user