Regional PD documentation; edited validation for Volumes page (#8714)
This commit is contained in:
@@ -167,6 +167,7 @@ provisioner: kubernetes.io/gce-pd
|
|||||||
parameters:
|
parameters:
|
||||||
type: pd-standard
|
type: pd-standard
|
||||||
zones: us-central1-a, us-central1-b
|
zones: us-central1-a, us-central1-b
|
||||||
|
replication-type: none
|
||||||
```
|
```
|
||||||
|
|
||||||
* `type`: `pd-standard` or `pd-ssd`. Default: `pd-standard`
|
* `type`: `pd-standard` or `pd-ssd`. Default: `pd-standard`
|
||||||
@@ -177,6 +178,18 @@ parameters:
|
|||||||
is specified, volumes are generally round-robin-ed across all active zones
|
is specified, volumes are generally round-robin-ed across all active zones
|
||||||
where Kubernetes cluster has a node. `zone` and `zones` parameters must not
|
where Kubernetes cluster has a node. `zone` and `zones` parameters must not
|
||||||
be used at the same time.
|
be used at the same time.
|
||||||
|
* `replication-type`: `none` or `regional-pd`. Default: `none`.
|
||||||
|
|
||||||
|
If `replication-type` is set to `none`, a regular (zonal) PD will be provisioned.
|
||||||
|
|
||||||
|
If `replication-type` is set to `regional-pd`, a
|
||||||
|
[Regional Persistent Disk](https://cloud.google.com/compute/docs/disks/#repds)
|
||||||
|
will be provisioned. In this case, users must use `zones` instead of `zone` to
|
||||||
|
specify the desired replication zones. If exactly two zones are specified, the
|
||||||
|
Regional PD will be provisioned in those zones. If more than two zones are
|
||||||
|
specified, Kubernetes will arbitrarily choose among the specified zones. If the
|
||||||
|
`zones` parameter is omitted, Kubernetes will arbitrarily choose among zones
|
||||||
|
managed by the cluster.
|
||||||
|
|
||||||
### Glusterfs
|
### Glusterfs
|
||||||
|
|
||||||
|
|||||||
@@ -368,6 +368,38 @@ spec:
|
|||||||
fsType: ext4
|
fsType: ext4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Regional Persistent Disks
|
||||||
|
{{< feature-state for_k8s_version="v1.10" state="beta" >}}
|
||||||
|
|
||||||
|
The [Regional Persistent Disks](https://cloud.google.com/compute/docs/disks/#repds) feature allows the creation of Persistent Disks that are available in two zones within the same region. In order to use this feature, the volume must be provisioned as a PersistentVolume; referencing the volume directly from a pod is not supported.
|
||||||
|
|
||||||
|
#### Manually provisioning a Regional PD PersistentVolume
|
||||||
|
Dynamic provisioning is possible using a [StorageClass for GCE PD](/docs/concepts/storage/storage-classes/#gce).
|
||||||
|
Before creating a PersistentVolume, you must create the PD:
|
||||||
|
```shell
|
||||||
|
gcloud beta compute disks create --size=500GB my-data-disk
|
||||||
|
--region us-central1
|
||||||
|
--replica-zones us-central1-a,us-central1-b
|
||||||
|
```
|
||||||
|
Example PersistentVolume spec:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: test-volume
|
||||||
|
labels:
|
||||||
|
failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 400Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
gcePersistentDisk:
|
||||||
|
pdName: my-data-disk
|
||||||
|
fsType: ext4
|
||||||
|
```
|
||||||
|
|
||||||
### gitRepo
|
### gitRepo
|
||||||
|
|
||||||
A `gitRepo` volume is an example of what can be done as a volume plugin. It
|
A `gitRepo` volume is an example of what can be done as a volume plugin. It
|
||||||
@@ -527,7 +559,7 @@ durability characteristics of the underlying disk.
|
|||||||
The following is an example PersistentVolume spec using a `local` volume and
|
The following is an example PersistentVolume spec using a `local` volume and
|
||||||
`nodeAffinity`:
|
`nodeAffinity`:
|
||||||
|
|
||||||
``` yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
+30
-22
@@ -421,15 +421,15 @@ func TestExampleObjectSchemas(t *testing.T) {
|
|||||||
"tcp-liveness-readiness": {&api.Pod{}},
|
"tcp-liveness-readiness": {&api.Pod{}},
|
||||||
},
|
},
|
||||||
"docs/tasks/debug-application-cluster": {
|
"docs/tasks/debug-application-cluster": {
|
||||||
"counter-pod": {&api.Pod{}},
|
"counter-pod": {&api.Pod{}},
|
||||||
"event-exporter-deploy": {&api.ServiceAccount{}, &rbac.ClusterRoleBinding{}, &extensions.Deployment{}},
|
"event-exporter-deploy": {&api.ServiceAccount{}, &rbac.ClusterRoleBinding{}, &extensions.Deployment{}},
|
||||||
"fluentd-gcp-configmap": {&api.ConfigMap{}},
|
"fluentd-gcp-configmap": {&api.ConfigMap{}},
|
||||||
"fluentd-gcp-ds": {&extensions.DaemonSet{}},
|
"fluentd-gcp-ds": {&extensions.DaemonSet{}},
|
||||||
"nginx-dep": {&extensions.Deployment{}},
|
"nginx-dep": {&extensions.Deployment{}},
|
||||||
"node-problem-detector": {&extensions.DaemonSet{}},
|
"node-problem-detector": {&extensions.DaemonSet{}},
|
||||||
"node-problem-detector-configmap": {&extensions.DaemonSet{}},
|
"node-problem-detector-configmap": {&extensions.DaemonSet{}},
|
||||||
"shell-demo": {&api.Pod{}},
|
"shell-demo": {&api.Pod{}},
|
||||||
"termination": {&api.Pod{}},
|
"termination": {&api.Pod{}},
|
||||||
},
|
},
|
||||||
// TODO: decide whether federation examples should be added
|
// TODO: decide whether federation examples should be added
|
||||||
"docs/tasks/inject-data-application": {
|
"docs/tasks/inject-data-application": {
|
||||||
@@ -456,8 +456,8 @@ func TestExampleObjectSchemas(t *testing.T) {
|
|||||||
"secret-pod": {&api.Pod{}},
|
"secret-pod": {&api.Pod{}},
|
||||||
},
|
},
|
||||||
"docs/tasks/job": {
|
"docs/tasks/job": {
|
||||||
"cronjob": {&batch.CronJob{}},
|
"cronjob": {&batch.CronJob{}},
|
||||||
"job": {&batch.Job{}},
|
"job": {&batch.Job{}},
|
||||||
},
|
},
|
||||||
"docs/tasks/job/coarse-parallel-processing-work-queue": {
|
"docs/tasks/job/coarse-parallel-processing-work-queue": {
|
||||||
"job": {&batch.Job{}},
|
"job": {&batch.Job{}},
|
||||||
@@ -620,12 +620,19 @@ func TestExampleObjectSchemas(t *testing.T) {
|
|||||||
var sampleRegexp = regexp.MustCompile("(?ms)^```(?:(?P<type>yaml)\\w*\\n(?P<content>.+?)|\\w*\\n(?P<content>\\{.+?\\}))\\n^```")
|
var sampleRegexp = regexp.MustCompile("(?ms)^```(?:(?P<type>yaml)\\w*\\n(?P<content>.+?)|\\w*\\n(?P<content>\\{.+?\\}))\\n^```")
|
||||||
var subsetRegexp = regexp.MustCompile("(?ms)\\.{3}")
|
var subsetRegexp = regexp.MustCompile("(?ms)\\.{3}")
|
||||||
|
|
||||||
|
// Validates examples embedded in Markdown files.
|
||||||
func TestReadme(t *testing.T) {
|
func TestReadme(t *testing.T) {
|
||||||
|
// BlockVolume required for local volume example
|
||||||
|
utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
||||||
|
|
||||||
paths := []struct {
|
paths := []struct {
|
||||||
file string
|
file string
|
||||||
expectedType []runtime.Object
|
expectedType []runtime.Object // List of all valid types for the whole doc
|
||||||
}{
|
}{
|
||||||
{"../content/en/docs/concepts/storage/volumes.md", []runtime.Object{&api.Pod{}}},
|
{"../content/en/docs/concepts/storage/volumes.md", []runtime.Object{
|
||||||
|
&api.Pod{},
|
||||||
|
&api.PersistentVolume{},
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
@@ -639,7 +646,6 @@ func TestReadme(t *testing.T) {
|
|||||||
if matches == nil {
|
if matches == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ix := 0
|
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
var content, subtype string
|
var content, subtype string
|
||||||
for i, name := range sampleRegexp.SubexpNames() {
|
for i, name := range sampleRegexp.SubexpNames() {
|
||||||
@@ -655,21 +661,23 @@ func TestReadme(t *testing.T) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedType runtime.Object
|
|
||||||
if len(path.expectedType) == 1 {
|
|
||||||
expectedType = path.expectedType[0]
|
|
||||||
} else {
|
|
||||||
expectedType = path.expectedType[ix]
|
|
||||||
ix++
|
|
||||||
}
|
|
||||||
json, err := yaml.ToJSON([]byte(content))
|
json, err := yaml.ToJSON([]byte(content))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s could not be converted to JSON: %v\n%s", path, err, string(content))
|
t.Errorf("%s could not be converted to JSON: %v\n%s", path, err, string(content))
|
||||||
}
|
}
|
||||||
if err := runtime.DecodeInto(testapi.Default.Codec(), json, expectedType); err != nil {
|
|
||||||
|
var expectedType runtime.Object
|
||||||
|
for _, expectedType = range path.expectedType {
|
||||||
|
err = runtime.DecodeInto(testapi.Default.Codec(), json, expectedType)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(content))
|
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(content))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors := validateObject(expectedType); len(errors) > 0 {
|
if errors := validateObject(expectedType); len(errors) > 0 {
|
||||||
t.Errorf("%s did not validate correctly: %v", path, errors)
|
t.Errorf("%s did not validate correctly: %v", path, errors)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user