From 1d3b7c42289f6b0af041c69a037fe45bf2affc18 Mon Sep 17 00:00:00 2001 From: Krishna m-Kumar Date: Wed, 6 Sep 2017 07:27:36 +0530 Subject: [PATCH 01/58] updated Readme with several links missing 5 missing links updated Added Review Issues Tab and Link from the same folder's file. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 264822b1df..280a4ceb40 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,12 @@ You can click the **Fork** button in the upper-right area of the screen to creat For more information about contributing to the Kubernetes documentation, see: * [Contributing to the Kubernetes Documentation](http://kubernetes.io/editdocs/) -* [Creating a Documentation Pull Request](http://kubernetes.io/docs/contribute/create-pull-request/) -* [Writing a New Topic](http://kubernetes.io/docs/contribute/write-new-topic/) -* [Staging Your Documentation Changes](http://kubernetes.io/docs/contribute/stage-documentation-changes/) -* [Using Page Templates](http://kubernetes.io/docs/contribute/page-templates/) -* [Documentation Style Guide](http://kubernetes.io/docs/contribute/style-guide/) +* [Creating a Documentation Pull Request](http://kubernetes.io/docs/home/contribute/create-pull-request/) +* [Writing a New Topic](http://kubernetes.io/docs/home/contribute/write-new-topic/) +* [Review Issues](http://kubernetes.io/docs/home/contribute/review-issues/) +* [Staging Your Documentation Changes](http://kubernetes.io/docs/home/contribute/stage-documentation-changes/) +* [Using Page Templates](http://kubernetes.io/docs/home/contribute/page-templates/) +* [Documentation Style Guide](http://kubernetes.io/docs/home/contribute/style-guide/) ## Thank you! From 11161b63515dc20f310044f347e171684f9ce56e Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 7 Sep 2017 17:09:24 -0700 Subject: [PATCH 02/58] Edits deployment.md - Fixes an inaccuracy: `template: metadata: labels:` labels the Pod template rather than the containers - Elaborates some more on the explanation of the manifest --- docs/concepts/workloads/controllers/deployment.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/concepts/workloads/controllers/deployment.md b/docs/concepts/workloads/controllers/deployment.md index 0312a6390f..70dfe589fe 100644 --- a/docs/concepts/workloads/controllers/deployment.md +++ b/docs/concepts/workloads/controllers/deployment.md @@ -41,15 +41,18 @@ The following is an example of a Deployment. It creates a ReplicaSet to bring up In this example: -* A Deployment named `nginx` is created. -* The `nginx` Deployment creates three replicated Pods. -* The Pods are created from the `template` field. +* A Deployment named `nginx` is created, indicated by the `metadata: name` field. +* The Deployment creates three replicated Pods, indicated by the `replicas` field. +* The Pod template's specification, or `template: spec` field, indicates that + the Pods run one container, `nginx`, which runs the `nginx` + [Docker Hub](https://hub.docker.com/) image at version 1.7.9. +* The Deployment opens port 80 for use by the Pods. The `template` field contains the following instructions: -* Create one container in each Pod. -* Label the container `app: nginx`. -* Run the [Docker Hub](https://hub.docker.com) image `nginx` at version `1.7.9`. +* The Pod template is labelled `app: nginx` +* Create one container and name it `nginx`. +* Run the `nginx` image at version `1.7.9`. * Open port `80` so that the container can send and accept traffic. To create this Deployment, run the following command: From 15b57839b89304e1958e17abf89d6ece6c69dbc6 Mon Sep 17 00:00:00 2001 From: Andrew Bonventre Date: Thu, 7 Sep 2017 21:40:35 -0400 Subject: [PATCH 03/58] Fix typo (TEMPALTE -> TEMPLATE) (#5337) --- docs/concepts/workloads/controllers/deployment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/workloads/controllers/deployment.md b/docs/concepts/workloads/controllers/deployment.md index 0312a6390f..80bf2ef873 100644 --- a/docs/concepts/workloads/controllers/deployment.md +++ b/docs/concepts/workloads/controllers/deployment.md @@ -112,7 +112,7 @@ NAME DESIRED CURRENT READY AGE nginx-deployment-2035384211 3 3 3 18s ``` -Notice that the name of the ReplicaSet is always formatted as `[DEPLOYMENT-NAME]-[POD-TEMPALTE-HASH-VALUE]`. The hash value is automatically generated when the Deployemnt is created. +Notice that the name of the ReplicaSet is always formatted as `[DEPLOYMENT-NAME]-[POD-TEMPLATE-HASH-VALUE]`. The hash value is automatically generated when the Deployemnt is created. To see the labels automatically generated for each pod, run `kubectl get pods --show-labels`. The following output is returned: From 02155b7b964932e082dce26291b6815001ca4157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20L=C3=B3pez=20Galeiras?= Date: Fri, 8 Sep 2017 13:14:21 +0200 Subject: [PATCH 04/58] Add quotes to JSONPATH bash variable The command was failing with error: error parsing jsonpath {range, unclosed action We need to quote `$JSONPATH` so the full contents of the variable are passed to `-o jsonpath=`. Fixes #4258 --- docs/user-guide/kubectl-cheatsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/kubectl-cheatsheet.md b/docs/user-guide/kubectl-cheatsheet.md index ddba577c75..db16eed44b 100644 --- a/docs/user-guide/kubectl-cheatsheet.md +++ b/docs/user-guide/kubectl-cheatsheet.md @@ -128,7 +128,7 @@ $ echo $(kubectl get pods --selector=$sel --output=jsonpath={.items..metadata.na # Check which nodes are ready $ JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}' \ - && kubectl get nodes -o jsonpath=$JSONPATH | grep "Ready=True" + && kubectl get nodes -o jsonpath="$JSONPATH" | grep "Ready=True" # List all Secrets currently in use by a pod $ kubectl get pods -o json | jq '.items[].spec.containers[].env[]?.valueFrom.secretKeyRef.name' | grep -v null | sort | uniq From 0347e50b82b0628b100fd5ce90a4a08fbe8eb29d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Fri, 8 Sep 2017 07:32:40 -0700 Subject: [PATCH 05/58] Update deployment.md --- docs/concepts/workloads/controllers/deployment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/workloads/controllers/deployment.md b/docs/concepts/workloads/controllers/deployment.md index 70dfe589fe..3b011d9585 100644 --- a/docs/concepts/workloads/controllers/deployment.md +++ b/docs/concepts/workloads/controllers/deployment.md @@ -50,7 +50,7 @@ In this example: The `template` field contains the following instructions: -* The Pod template is labelled `app: nginx` +* The Pods are labeled `app: nginx` * Create one container and name it `nginx`. * Run the `nginx` image at version `1.7.9`. * Open port `80` so that the container can send and accept traffic. From 93133cca2f6c34bb91304e234af113fea53d0f32 Mon Sep 17 00:00:00 2001 From: jianglingxia Date: Sat, 9 Sep 2017 00:04:16 +0800 Subject: [PATCH 06/58] duplicate not (#5347) --- docs/tasks/run-application/scale-stateful-set.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/run-application/scale-stateful-set.md b/docs/tasks/run-application/scale-stateful-set.md index ca73a3997e..0ee87d9b20 100644 --- a/docs/tasks/run-application/scale-stateful-set.md +++ b/docs/tasks/run-application/scale-stateful-set.md @@ -70,7 +70,7 @@ kubectl patch statefulsets -p '{"spec":{"replicas": Date: Sat, 9 Sep 2017 00:09:48 +0800 Subject: [PATCH 07/58] Update kube-proxy.md (#5344) there lost a blank character. --- docs/admin/kube-proxy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/kube-proxy.md b/docs/admin/kube-proxy.md index 167b9f3d6c..6e6551af65 100644 --- a/docs/admin/kube-proxy.md +++ b/docs/admin/kube-proxy.md @@ -11,7 +11,7 @@ notitle: true The Kubernetes network proxy runs on each node. This reflects services as defined in the Kubernetes API on each node and can do simple -TCP,UDP stream forwarding or round robin TCP,UDP forwarding across a set of backends. +TCP, UDP stream forwarding or round robin TCP, UDP forwarding across a set of backends. Service cluster IPs and ports are currently found through Docker-links-compatible environment variables specifying ports opened by the service proxy. There is an optional addon that provides cluster DNS for these cluster IPs. The user must create a service From 108a4051fe66415d28ea8153f515457c3b87395b Mon Sep 17 00:00:00 2001 From: Ahmet Kizilay Date: Fri, 8 Sep 2017 12:10:24 -0400 Subject: [PATCH 08/58] updated kops download link to latest version (#5345) * 1.6.1 -> 1.7.0 --- docs/getting-started-guides/kops.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started-guides/kops.md b/docs/getting-started-guides/kops.md index a8720aa46e..e4a030584e 100644 --- a/docs/getting-started-guides/kops.md +++ b/docs/getting-started-guides/kops.md @@ -34,7 +34,7 @@ Download kops from the [releases page](https://github.com/kubernetes/kops/releas On MacOS: ``` -wget https://github.com/kubernetes/kops/releases/download/1.6.1/kops-darwin-amd64 +wget https://github.com/kubernetes/kops/releases/download/1.7.0/kops-darwin-amd64 chmod +x kops-darwin-amd64 mv kops-darwin-amd64 /usr/local/bin/kops # you can also install using Homebrew @@ -44,7 +44,7 @@ brew update && brew install kops On Linux: ``` -wget https://github.com/kubernetes/kops/releases/download/1.6.1/kops-linux-amd64 +wget https://github.com/kubernetes/kops/releases/download/1.7.0/kops-linux-amd64 chmod +x kops-linux-amd64 mv kops-linux-amd64 /usr/local/bin/kops ``` From c3209bb6803229e295801946c94d5c56dd03867e Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Fri, 8 Sep 2017 17:25:33 +0800 Subject: [PATCH 09/58] fix the command output fix the command output --- docs/tasks/administer-cluster/static-pod.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/administer-cluster/static-pod.md b/docs/tasks/administer-cluster/static-pod.md index 1c21a6f178..f2f439470a 100644 --- a/docs/tasks/administer-cluster/static-pod.md +++ b/docs/tasks/administer-cluster/static-pod.md @@ -92,7 +92,7 @@ Notice we cannot delete the pod with the API server (e.g. via [`kubectl`](/docs/ ```shell [joe@my-master ~] $ kubectl delete pod static-web-my-node1 -pods/static-web-my-node1 +pod "static-web-my-node1" deleted [joe@my-master ~] $ kubectl get pods NAME READY STATUS RESTARTS AGE static-web-my-node1 1/1 Running 0 12s From e0cb103488e1cc3c097e731c5c3c36c9abd1073c Mon Sep 17 00:00:00 2001 From: John Belamaric Date: Fri, 8 Sep 2017 16:17:08 -0400 Subject: [PATCH 10/58] Add coredns to add-on list (#5358) * Add CoreDNS addon * Update text --- docs/concepts/cluster-administration/addons.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/concepts/cluster-administration/addons.md b/docs/concepts/cluster-administration/addons.md index 53b94997dc..eb62a0795e 100644 --- a/docs/concepts/cluster-administration/addons.md +++ b/docs/concepts/cluster-administration/addons.md @@ -21,6 +21,10 @@ Add-ons in each section are sorted alphabetically - the ordering does not imply * [Weave Net](https://www.weave.works/docs/net/latest/kube-addon/) provides networking and network policy, will carry on working on both sides of a network partition, and does not require an external database. * [CNI-Genie](https://github.com/Huawei-PaaS/CNI-Genie) enables Kubernetes to seamlessly connect to a choice of CNI plugins, such as Flannel, Calico, Canal, Romana, or Weave. +## Service Discovery + +* [CoreDNS](https://coredns.io) is a flexible, extensible DNS server which can be [installed](https://github.com/coredns/deployment/tree/master/kubernetes) as the in-cluster DNS for pods. + ## Visualization & Control * [Dashboard](https://github.com/kubernetes/dashboard#kubernetes-dashboard) is a dashboard web interface for Kubernetes. From ef24a54abd0ed3b4ef3b9795af3923579c12c157 Mon Sep 17 00:00:00 2001 From: Cliff Burdick <30670611+cliffburdick@users.noreply.github.com> Date: Fri, 8 Sep 2017 17:37:19 -0700 Subject: [PATCH 11/58] Update downward-api-volume-expose-pod-information.md (#5309) Keeping the capitalization uniform. --- .../downward-api-volume-expose-pod-information.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information.md b/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information.md index 9caad6cdff..e6962e2389 100644 --- a/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information.md +++ b/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information.md @@ -188,15 +188,15 @@ You can use similar commands to view the `cpu_request`, `mem_limit` and The following information is available to Containers through environment variables and DownwardAPIVolumeFiles: -* The node’s name -* The node's IP +* The Node’s name +* The Node's IP * The Pod’s name * The Pod’s namespace * The Pod’s IP address * The Pod’s service account name * The Pod’s UID * A Container’s CPU limit -* A container’s CPU request +* A Container’s CPU request * A Container’s memory limit * A Container’s memory request From 9981d7e6c9ee25370986d74371e8e552c4784833 Mon Sep 17 00:00:00 2001 From: Kyle Bai Date: Sat, 9 Sep 2017 08:44:41 +0800 Subject: [PATCH 12/58] Remove unknown flag for apiserver (#5312) --- docs/getting-started-guides/scratch.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/getting-started-guides/scratch.md b/docs/getting-started-guides/scratch.md index de475a07bb..eebdebb78b 100644 --- a/docs/getting-started-guides/scratch.md +++ b/docs/getting-started-guides/scratch.md @@ -68,20 +68,20 @@ another pod using the IP of the second pod. This connectivity can be accomplished in two ways: - **Using an overlay network** - - An overlay network obscures the underlying network architecture from the + - An overlay network obscures the underlying network architecture from the pod network through traffic encapsulation (e.g. vxlan). - Encapsulation reduces performance, though exactly how much depends on your solution. - **Without an overlay network** - Configure the underlying network fabric (switches, routers, etc.) to be aware of pod IP addresses. - - This does not require the encapsulation provided by an overlay, and so can achieve + - This does not require the encapsulation provided by an overlay, and so can achieve better performance. -Which method you choose depends on your environment and requirements. There are various ways -to implement one of the above options: +Which method you choose depends on your environment and requirements. There are various ways +to implement one of the above options: - **Use a network plugin which is called by Kubernetes** - Kubernetes supports the [CNI](https://github.com/containernetworking/cni) network plugin interface. - - There are a number of solutions which provide plugins for Kubernetes (listed alphabetically): + - There are a number of solutions which provide plugins for Kubernetes (listed alphabetically): - [Calico](http://docs.projectcalico.org/) - [Flannel](https://github.com/coreos/flannel) - [Open vSwitch (OVS)](http://openvswitch.org/) @@ -628,7 +628,6 @@ Here are some apiserver flags you may need to set: - `--cloud-provider=` see [cloud providers](#cloud-providers) - `--cloud-config=` see [cloud providers](#cloud-providers) - `--address=${MASTER_IP}` *or* `--bind-address=127.0.0.1` and `--address=127.0.0.1` if you want to run a proxy on the master node. -- `--cluster-name=$CLUSTER_NAME` - `--service-cluster-ip-range=$SERVICE_CLUSTER_IP_RANGE` - `--etcd-servers=http://127.0.0.1:4001` - `--tls-cert-file=/srv/kubernetes/server.cert` @@ -792,7 +791,6 @@ Template for controller manager pod: Flags to consider using with controller manager: - - `--cluster-name=$CLUSTER_NAME` - `--cluster-cidr=`, the CIDR range for pods in cluster. - `--allocate-node-cidrs=`, if you are using `--cloud-provider=`, allocate and set the CIDRs for pods on the cloud provider. - `--cloud-provider=` and `--cloud-config` as described in apiserver section. From bc0eae1b341a04a5945868f48fc18d1185c44029 Mon Sep 17 00:00:00 2001 From: Evgeny Shmarnev Date: Sat, 9 Sep 2017 02:45:40 +0200 Subject: [PATCH 13/58] Update persistent-volumes.md (#5314) Add necessary line breaks so vSphere yaml examples will be shown correctly. --- docs/concepts/storage/persistent-volumes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/concepts/storage/persistent-volumes.md b/docs/concepts/storage/persistent-volumes.md index f20004aff7..ef67f78e8b 100644 --- a/docs/concepts/storage/persistent-volumes.md +++ b/docs/concepts/storage/persistent-volumes.md @@ -574,6 +574,7 @@ parameters: #### vSphere 1. Create a persistent volume with a user specified disk format. + ```yaml kind: StorageClass apiVersion: storage.k8s.io/v1 @@ -587,6 +588,7 @@ parameters: - `diskformat`: `thin`, `zeroedthick` and `eagerzeroedthick`. Default: `"thin"`. 2. Create a persistent volume with a disk format on a user specified datastore. + ```yaml kind: StorageClass apiVersion: storage.k8s.io/v1beta1 @@ -602,6 +604,7 @@ parameters: - `datastore`: The user can also specify the datastore in the Storageclass. The volume will be created on the datastore specified in the storage class which in this case is `VSANDatastore`. This field is optional. If not specified as in previous YAML description, the volume will be created on the datastore specified in the vsphere config file used to initialize the vSphere Cloud Provider. 3. Create a persistent volume with user specified VSAN storage capabilities. + ```yaml kind: StorageClass apiVersion: storage.k8s.io/v1beta1 From 728598298f4e7f3d728fa3bfda1f4eca5e77f72f Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Sat, 9 Sep 2017 08:46:32 +0800 Subject: [PATCH 14/58] fix the command output (#5315) fix the command output --- .../run-single-instance-stateful-application.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/tasks/run-application/run-single-instance-stateful-application.md b/docs/tasks/run-application/run-single-instance-stateful-application.md index ca0bb66775..6a1c305fa9 100644 --- a/docs/tasks/run-application/run-single-instance-stateful-application.md +++ b/docs/tasks/run-application/run-single-instance-stateful-application.md @@ -140,6 +140,8 @@ for a secure solution. Name: mysql-pv Labels: + Annotations: pv.kubernetes.io/bound-by-controller=yes + StorageClass: Status: Bound Claim: default/mysql-pv-claim Reclaim Policy: Retain @@ -152,7 +154,7 @@ for a secure solution. FSType: ext4 Partition: 0 ReadOnly: false - No events. + Events: 1. Inspect the PersistentVolumeClaim: @@ -160,12 +162,15 @@ for a secure solution. Name: mysql-pv-claim Namespace: default + StorageClass: Status: Bound Volume: mysql-pv Labels: + Annotations: pv.kubernetes.io/bind-completed=yes + pv.kubernetes.io/bound-by-controller=yes Capacity: 20Gi Access Modes: RWO - No events. + Events: ## Accessing the MySQL instance From 162e042d427ef4ee96f6d6fec11714a2c7333f0f Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Sat, 9 Sep 2017 08:47:46 +0800 Subject: [PATCH 15/58] fix the command output (#5316) fix the command output --- .../index.md | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/docs/tasks/job/coarse-parallel-processing-work-queue/index.md b/docs/tasks/job/coarse-parallel-processing-work-queue/index.md index 6ffd1fe1ae..e40bb2d238 100644 --- a/docs/tasks/job/coarse-parallel-processing-work-queue/index.md +++ b/docs/tasks/job/coarse-parallel-processing-work-queue/index.md @@ -225,24 +225,37 @@ Now wait a bit, then check on the job. $ kubectl describe jobs/job-wq-1 Name: job-wq-1 Namespace: default -Image(s): gcr.io/causal-jigsaw-637/job-wq-1 -Selector: app in (job-wq-1) +Selector: controller-uid=41d75705-92df-11e7-b85e-fa163ee3c11f +Labels: controller-uid=41d75705-92df-11e7-b85e-fa163ee3c11f + job-name=job-wq-1 +Annotations: Parallelism: 2 Completions: 8 -Labels: app=job-wq-1 +Start Time: Wed, 06 Sep 2017 16:42:02 +0800 Pods Statuses: 0 Running / 8 Succeeded / 0 Failed -No volumes. +Pod Template: + Labels: controller-uid=41d75705-92df-11e7-b85e-fa163ee3c11f + job-name=job-wq-1 + Containers: + c: + Image: gcr.io/causal-jigsaw-637/job-wq-1 + Port: + Environment: + BROKER_URL: amqp://guest:guest@rabbitmq-service:5672 + QUEUE: job1 + Mounts: + Volumes: Events: - FirstSeen LastSeen Count From SubobjectPath Reason Message - ───────── ──────── ───── ──── ───────────── ────── ─────── - 27s 27s 1 {job } SuccessfulCreate Created pod: job-wq-1-hcobb - 27s 27s 1 {job } SuccessfulCreate Created pod: job-wq-1-weytj - 27s 27s 1 {job } SuccessfulCreate Created pod: job-wq-1-qaam5 - 27s 27s 1 {job } SuccessfulCreate Created pod: job-wq-1-b67sr - 26s 26s 1 {job } SuccessfulCreate Created pod: job-wq-1-xe5hj - 15s 15s 1 {job } SuccessfulCreate Created pod: job-wq-1-w2zqe - 14s 14s 1 {job } SuccessfulCreate Created pod: job-wq-1-d6ppa - 14s 14s 1 {job } SuccessfulCreate Created pod: job-wq-1-p17e0 + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + ───────── ──────── ───── ──── ───────────── ────── ────── ─────── + 27s 27s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-hcobb + 27s 27s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-weytj + 27s 27s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-qaam5 + 27s 27s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-b67sr + 26s 26s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-xe5hj + 15s 15s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-w2zqe + 14s 14s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-d6ppa + 14s 14s 1 {job } Normal SuccessfulCreate Created pod: job-wq-1-p17e0 ``` All our pods succeeded. Yay. From 7a7718378a6db53be389b857f311cfd35f12dd92 Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Sat, 9 Sep 2017 08:48:15 +0800 Subject: [PATCH 16/58] fix the command output (#5317) fix the command output --- .../index.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/tasks/job/fine-parallel-processing-work-queue/index.md b/docs/tasks/job/fine-parallel-processing-work-queue/index.md index 887f5e6dd2..9d19895039 100644 --- a/docs/tasks/job/fine-parallel-processing-work-queue/index.md +++ b/docs/tasks/job/fine-parallel-processing-work-queue/index.md @@ -178,14 +178,24 @@ Now wait a bit, then check on the job. $ kubectl describe jobs/job-wq-2 Name: job-wq-2 Namespace: default -Image(s): gcr.io/exampleproject/job-wq-2 -Selector: app in (job-wq-2) +Selector: controller-uid=b1c7e4e3-92e1-11e7-b85e-fa163ee3c11f +Labels: controller-uid=b1c7e4e3-92e1-11e7-b85e-fa163ee3c11f + job-name=job-wq-2 +Annotations: Parallelism: 2 -Completions: Unset +Completions: Start Time: Mon, 11 Jan 2016 17:07:59 -0800 -Labels: app=job-wq-2 Pods Statuses: 1 Running / 0 Succeeded / 0 Failed -No volumes. +Pod Template: + Labels: controller-uid=b1c7e4e3-92e1-11e7-b85e-fa163ee3c11f + job-name=job-wq-2 + Containers: + c: + Image: gcr.io/exampleproject/job-wq-2 + Port: + Environment: + Mounts: + Volumes: Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- From f179452a9a12f15e0e28a1bf7529e5ce84b87aaf Mon Sep 17 00:00:00 2001 From: Stewart-YU Date: Sat, 9 Sep 2017 08:49:56 +0800 Subject: [PATCH 17/58] Update create-cluster-kubeadm.md (#5318) Fix leading spaces in commands. --- docs/setup/independent/create-cluster-kubeadm.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/setup/independent/create-cluster-kubeadm.md b/docs/setup/independent/create-cluster-kubeadm.md index 9ca5dd13a0..65a05b634d 100644 --- a/docs/setup/independent/create-cluster-kubeadm.md +++ b/docs/setup/independent/create-cluster-kubeadm.md @@ -468,9 +468,9 @@ control of your Kubernetes cluster. ## Feedback * kubeadm support Slack Channel: - [#kubeadm](https://kubernetes.slack.com/messages/kubeadm/) + [kubeadm](https://kubernetes.slack.com/messages/kubeadm/) * General SIG Cluster Lifecycle Development Slack Channel: - [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) + [sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) * Mailing List: [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) * [GitHub Issues in the kubeadm @@ -561,10 +561,10 @@ Verify that the `$HOME/.kube/config` file contains a valid certificate, and rege Another workaround is to overwrite the default `kubeconfig` for the "admin" user: ``` - mv $HOME/.kube $HOME/.kube.bak - mkdir -p $HOME/.kube - sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config - sudo chown $(id -u):$(id -g) $HOME/.kube/config +mv $HOME/.kube $HOME/.kube.bak +mkdir -p $HOME/.kube +sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` 1. If you are using CentOS and encounter difficulty while setting up the master node, From 1e4399ee8908140496b22fd04f983d05f3cc4c20 Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Sat, 9 Sep 2017 03:50:44 +0300 Subject: [PATCH 18/58] Mailing list moved to kubernetes-users group (#5320) --- docs/tasks/debug-application-cluster/debug-service.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/debug-application-cluster/debug-service.md b/docs/tasks/debug-application-cluster/debug-service.md index 6ca474efc9..b2ee1307d3 100644 --- a/docs/tasks/debug-application-cluster/debug-service.md +++ b/docs/tasks/debug-application-cluster/debug-service.md @@ -627,7 +627,7 @@ us know, so we can help investigate! Contact us on [Slack](/docs/troubleshooting/#slack) or -[email](https://groups.google.com/forum/#!forum/google-containers) or +[email](https://groups.google.com/forum/#!forum/kubernetes-users) or [GitHub](https://github.com/kubernetes/kubernetes). ## More information From 6a4fde54b21098670339b7e9937dbb1571883d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Fri, 8 Sep 2017 20:51:21 -0400 Subject: [PATCH 19/58] Update link in AWS documentation (#5325) --- docs/concepts/cluster-administration/cloud-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/cluster-administration/cloud-providers.md b/docs/concepts/cluster-administration/cloud-providers.md index e0b60896dd..4c0034efb9 100644 --- a/docs/concepts/cluster-administration/cloud-providers.md +++ b/docs/concepts/cluster-administration/cloud-providers.md @@ -44,7 +44,7 @@ Different settings can be applied to a load balancer service in AWS using _annot * `service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix`: Used to specify access log s3 bucket prefix. * `service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags`: Used on the service to specify a comma-separated list of key-value pairs which will be recorded as additional tags in the ELB. For example: `"Key1=Val1,Key2=Val2,KeyNoVal1=,KeyNoVal2"`. * `service.beta.kubernetes.io/aws-load-balancer-backend-protocol`: Used on the service to specify the protocol spoken by the backend (pod) behind a listener. If `http` (default) or `https`, an HTTPS listener that terminates the connection and parses headers is created. If set to `ssl` or `tcp`, a "raw" SSL listener is used. If set to `http` and `aws-load-balancer-ssl-cert` is not used then a HTTP listener is used. -* `service.beta.kubernetes.io/aws-load-balancer-ssl-cert`: Used on the service to request a secure listener. Value is a valid certificate ARN. For more, see http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-listener-config.html CertARN is an IAM or CM certificate ARN, e.g. `arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012`. +* `service.beta.kubernetes.io/aws-load-balancer-ssl-cert`: Used on the service to request a secure listener. Value is a valid certificate ARN. For more, see [ELB Listener Config](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-listener-config.html) CertARN is an IAM or CM certificate ARN, e.g. `arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012`. * `service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled`: Used on the service to enable or disable connection draining. * `service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout`: Used on the service to specify a connection draining timeout. * `service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout`: Used on the service to specify the idle connection timeout. From de452f864ed7d541004f5e1b598b6685471b5f93 Mon Sep 17 00:00:00 2001 From: Joel Roggeman Date: Fri, 8 Sep 2017 20:43:23 -0700 Subject: [PATCH 20/58] Fix MD formatting issue in docs (#5326) --- docs/getting-started-guides/windows/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/getting-started-guides/windows/index.md b/docs/getting-started-guides/windows/index.md index ad5c1b9329..96e3c49216 100644 --- a/docs/getting-started-guides/windows/index.md +++ b/docs/getting-started-guides/windows/index.md @@ -32,7 +32,8 @@ The following diagram illustrates the Windows Server networking setup for Kubern ![Windows Setup](windows-setup.png) ## Setting up Windows Server Containers on Kubernetes -To run Windows Server Containers on Kubernetes, you'll need to set up both your host machines and the Kubernetes node components for Windows and setup Routes for Pod communication on different nodes +To run Windows Server Containers on Kubernetes, you'll need to set up both your host machines and the Kubernetes node components for Windows and setup Routes for Pod communication on different nodes. + ### Host Setup **Windows Host Setup** From 8c37e43a183837015edce11b20716c50ccd26016 Mon Sep 17 00:00:00 2001 From: Weihua Meng Date: Fri, 8 Sep 2017 23:05:36 -0500 Subject: [PATCH 21/58] Update opaque-integer-resource.md (#5331) remove irrelevant words --- docs/tasks/configure-pod-container/opaque-integer-resource.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/configure-pod-container/opaque-integer-resource.md b/docs/tasks/configure-pod-container/opaque-integer-resource.md index fff8f55703..fafe753792 100644 --- a/docs/tasks/configure-pod-container/opaque-integer-resource.md +++ b/docs/tasks/configure-pod-container/opaque-integer-resource.md @@ -53,7 +53,7 @@ Describe the Pod: kubectl describe pod oir-demo ``` -The output shows the memory, CPU, and dongle requests: +The output shows dongle requests: ```yaml Requests: From d19e83c3c1ad1a073191a6a145c445f7151dd9e7 Mon Sep 17 00:00:00 2001 From: XsWack Date: Sat, 9 Sep 2017 12:08:09 +0800 Subject: [PATCH 22/58] add Node Condition Type (#5334) add Node Condition Type --- docs/concepts/architecture/nodes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/concepts/architecture/nodes.md b/docs/concepts/architecture/nodes.md index 1d361db045..43c5d722c0 100644 --- a/docs/concepts/architecture/nodes.md +++ b/docs/concepts/architecture/nodes.md @@ -51,6 +51,7 @@ The `conditions` field describes the status of all `Running` nodes. | `Ready` | `True` if the node is healthy and ready to accept pods, `False` if the node is not healthy and is not accepting pods, and `Unknown` if the node controller has not heard from the node in the last 40 seconds | | `MemoryPressure` | `True` if pressure exists on the node memory -- that is, if the node memory is low; otherwise `False` | | `DiskPressure` | `True` if pressure exists on the disk size -- that is, if the disk capacity is low; otherwise `False` | +| `NetworkUnavailable` | `True` if the network for the node is not correctly configured, otherwise `False` | The node condition is represented as a JSON object. For example, the following response describes a healthy node. From 511402d8e2d5bbf6feeff2d35fe5dd4e4c1691ed Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Sat, 9 Sep 2017 12:15:45 +0800 Subject: [PATCH 23/58] fix the command output (#5350) fix the command output --- .../debug-application-introspection.md | 69 ++++++++++++------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/docs/tasks/debug-application-cluster/debug-application-introspection.md b/docs/tasks/debug-application-cluster/debug-application-introspection.md index ac936adf74..55c4c24c7f 100644 --- a/docs/tasks/debug-application-cluster/debug-application-introspection.md +++ b/docs/tasks/debug-application-cluster/debug-application-introspection.md @@ -280,34 +280,55 @@ kubernetes-node-unaj Ready 1h v1.6.0+fff5156 $ kubectl describe node kubernetes-node-861h Name: kubernetes-node-861h -Labels: kubernetes.io/hostname=kubernetes-node-861h -CreationTimestamp: Fri, 10 Jul 2015 14:32:29 -0700 +Role +Labels: beta.kubernetes.io/arch=amd64 + beta.kubernetes.io/os=linux + kubernetes.io/hostname=kubernetes-node-861h +Annotations: node.alpha.kubernetes.io/ttl=0 + volumes.kubernetes.io/controller-managed-attach-detach=true +Taints: +CreationTimestamp: Mon, 04 Sep 2017 17:13:23 +0800 +Phase: Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message - Ready Unknown Fri, 10 Jul 2015 14:34:32 -0700 Fri, 10 Jul 2015 14:35:15 -0700 Kubelet stopped posting node status. + ---- ------ ----------------- ------------------ ------ ------- + OutOfDisk Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. + MemoryPressure Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. + DiskPressure Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. + Ready Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. Addresses: 10.240.115.55,104.197.0.26 Capacity: - cpu: 1 - memory: 3800808Ki - pods: 100 -Version: - Kernel Version: 3.16.0-0.bpo.4-amd64 - OS Image: Debian GNU/Linux 7 (wheezy) - Container Runtime Version: docker://Unknown - Kubelet Version: v0.21.1-185-gffc5a86098dc01 - Kube-Proxy Version: v0.21.1-185-gffc5a86098dc01 -PodCIDR: 10.244.0.0/24 -ExternalID: 15233045891481496305 -Pods: (0 in total) - Namespace Name -Events: - FirstSeen LastSeen Count From SubobjectPath Reason Message - Fri, 10 Jul 2015 14:32:28 -0700 Fri, 10 Jul 2015 14:32:28 -0700 1 {kubelet kubernetes-node-861h} NodeNotReady Node kubernetes-node-861h status is now: NodeNotReady - Fri, 10 Jul 2015 14:32:30 -0700 Fri, 10 Jul 2015 14:32:30 -0700 1 {kubelet kubernetes-node-861h} NodeNotReady Node kubernetes-node-861h status is now: NodeNotReady - Fri, 10 Jul 2015 14:33:00 -0700 Fri, 10 Jul 2015 14:33:00 -0700 1 {kubelet kubernetes-node-861h} starting Starting kubelet. - Fri, 10 Jul 2015 14:33:02 -0700 Fri, 10 Jul 2015 14:33:02 -0700 1 {kubelet kubernetes-node-861h} NodeReady Node kubernetes-node-861h status is now: NodeReady - Fri, 10 Jul 2015 14:35:15 -0700 Fri, 10 Jul 2015 14:35:15 -0700 1 {controllermanager } NodeNotReady Node kubernetes-node-861h status is now: NodeNotReady - + cpu: 2 + hugePages: 0 + memory: 4046788Ki + pods: 110 +Allocatable: + cpu: 1500m + hugePages: 0 + memory: 1479263Ki + pods: 110 +System Info: + Machine ID: 8e025a21a4254e11b028584d9d8b12c4 + System UUID: 349075D1-D169-4F25-9F2A-E886850C47E3 + Boot ID: 5cd18b37-c5bd-4658-94e0-e436d3f110e0 + Kernel Version: 4.4.0-31-generic + OS Image: Debian GNU/Linux 8 (jessie) + Operating System: linux + Architecture: amd64 + Container Runtime Version: docker://1.12.5 + Kubelet Version: v1.6.9+a3d1dfa6f4335 + Kube-Proxy Version: v1.6.9+a3d1dfa6f4335 +ExternalID: 15233045891481496305 +Non-terminated Pods: (9 in total) + Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits + --------- ---- ------------ ---------- --------------- ------------- +...... +Allocated resources: + (Total limits may be over 100 percent, i.e., overcommitted.) + CPU Requests CPU Limits Memory Requests Memory Limits + ------------ ---------- --------------- ------------- + 900m (60%) 2200m (146%) 1009286400 (66%) 5681286400 (375%) +Events: $ kubectl get node kubernetes-node-861h -o yaml apiVersion: v1 From c4fde406f0f90e00485ba1a401469db15f9da62d Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Fri, 8 Sep 2017 21:20:29 -0700 Subject: [PATCH 24/58] fixing broken note annotation, and cleaning blank line endings (#5360) * fixing broken note annotation, and cleaning blank line endings * fixing caution annotation typo --- docs/getting-started-guides/kubespray.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/getting-started-guides/kubespray.md b/docs/getting-started-guides/kubespray.md index eee97f6a2a..9ceb1b5af9 100644 --- a/docs/getting-started-guides/kubespray.md +++ b/docs/getting-started-guides/kubespray.md @@ -21,15 +21,15 @@ To choose a tool which best fits your use case, read [this comparison](https://g Provision servers with the following requirements: -* `Ansible v2.3` (or newer) -* `Jinja 2.9` (or newer) +* `Ansible v2.3` (or newer) +* `Jinja 2.9` (or newer) * `python-netaddr` installed on the machine that running Ansible commands * Target servers must have access to the Internet in order to pull docker images * Target servers are configured to allow IPv4 forwarding * Target servers have SSH connectivity ( tcp/22 ) directly to your nodes or through a bastion host/ssh jump box * Target servers have a privileged user * Your SSH key must be copied to all the servers that are part of your inventory -* Firewall rules configured properly to allow Ansible and Kubernetes components to communicate +* Firewall rules configured properly to allow Ansible and Kubernetes components to communicate * If using a cloud provider, you must have the appropriate credentials available and exported as environment variables Kubespray provides the following utilities to help provision your environment: @@ -44,7 +44,7 @@ Kubespray provides the following utilities to help provision your environment: ### (2/5) Compose an inventory file -After you provision your servers, create an [inventory file for Ansible](http://docs.ansible.com/ansible/intro_inventory.html). You can do this manually or via a dynamic inventory script. For more information, see "[Building your own inventory](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#building-your-own-inventory)". +After you provision your servers, create an [inventory file for Ansible](http://docs.ansible.com/ansible/intro_inventory.html). You can do this manually or via a dynamic inventory script. For more information, see "[Building your own inventory](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#building-your-own-inventory)". ### (3/5) Plan your cluster deployment @@ -65,10 +65,10 @@ Kubespray customizations can be made to a [variable file](http://docs.ansible.co Next, deploy your cluster with one of two methods: * [ansible-playbook](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#starting-custom-deployment). -* [kubespray-cli tool](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md) +* [kubespray-cli tool](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md) **Note:** kubespray-cli is no longer actively maintained. -{. :note} +{: .note} Both methods run the default [cluster definition file](https://github.com/kubernetes-incubator/kubespray/blob/master/cluster.yml). @@ -84,11 +84,11 @@ Kubespray provides additional playbooks to manage your cluster: _scale_ and _upg ### Scale your cluster -You can scale your cluster by running the scale playbook. For more information, see "[Adding nodes](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#Adding-nodes)". +You can scale your cluster by running the scale playbook. For more information, see "[Adding nodes](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#Adding-nodes)". ### Upgrade your cluster -You can upgrade your cluster by running the upgrade-cluster playbook. For more information, see "[Upgrades](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/upgrades.md)". +You can upgrade your cluster by running the upgrade-cluster playbook. For more information, see "[Upgrades](https://github.com/kubernetes-incubator/kubespray/blob/master/docs/upgrades.md)". ## What's next @@ -99,7 +99,7 @@ Check out planned work on Kubespray's [roadmap](https://github.com/kubernetes-in You can reset your nodes and wipe out all components installed with Kubespray via the [reset playbook](https://github.com/kubernetes-incubator/kubespray/blob/master/reset.yml). **Caution:** When running the reset playbook, be sure not to accidentally target your production cluster! -{. :caution} +{: .caution} ## Feedback From 16e44fcc9a9746613b0c1c6f61ff824f8774cde6 Mon Sep 17 00:00:00 2001 From: Errien Date: Sat, 9 Sep 2017 07:14:12 +0200 Subject: [PATCH 25/58] Update configure-pod-configmap.md (#4017) Setting correct key for LOG_LEVEL env value From 38d3414a794cd27171d750dbef6a0247cb40257a Mon Sep 17 00:00:00 2001 From: Malepati Bala Siva Sai Akhil Date: Sat, 9 Sep 2017 11:22:39 +0530 Subject: [PATCH 26/58] Fixed Broken Link (#4798) Fixed Broken Link in Case Study of Box Signed-off-by: Malepati Bala Siva Sai Akhil --- case-studies/box.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/case-studies/box.html b/case-studies/box.html index 468a7b2e4a..6b816631bf 100644 --- a/case-studies/box.html +++ b/case-studies/box.html @@ -55,7 +55,7 @@ css: /css/style_box.css A platform that allows its more than 50 million users (including governments and big businesses like General Electric) to manage and share content in the cloud, Box was originally a PHP monolith of millions of lines of code built exclusively with bare metal inside of its own data centers. It had already begun to slowly chip away at the monolith, decomposing it into microservices. And "as we’ve been expanding into regions around the globe, and as the public cloud wars have been heating up, we’ve been focusing a lot more on figuring out how we run our workload across many different environments and many different cloud infrastructure providers," says Box Cofounder and Services Architect Sam Ghods. "It’s been a huge challenge thus far because of all these different providers, especially bare metal, have very different interfaces and ways in which you work with them."

Box’s cloud native journey accelerated that June, when Ghods attended DockerCon. The company had come to the realization that it could no longer run its applications only off bare metal, and was researching containerizing with Docker, virtualizing with OpenStack, and supporting public cloud.

At that conference, Google announced the release of its Kubernetes container management system, and Ghods was won over. "We looked at a lot of different options, but Kubernetes really stood out, especially because of the incredibly strong team of Borg veterans and the vision of having a completely infrastructure-agnostic way of being able to run cloud software," he says, referencing Google’s internal container orchestrator Borg. "The fact that on day one it was designed to run on bare metal just as well as Google Cloud meant that we could actually migrate to it inside of our data centers, and then use those same tools and concepts to run across public cloud providers as well."

- Another plus: Ghods liked that Kubernetes has a universal set of API objects like pod, service, replica set and deployment object, which created a consistent surface to build tooling against. "Even PaaS layers like OpenShift or Deis that build on top of Kubernetes still treat those objects as first-class principles," he says. "We were excited about having these abstractions shared across the entire ecosystem, which would result in a lot more momentum than we saw in other potential solutions."

+ Another plus: Ghods liked that Kubernetes has a universal set of API objects like pod, service, replica set and deployment object, which created a consistent surface to build tooling against. "Even PaaS layers like OpenShift or Deis that build on top of Kubernetes still treat those objects as first-class principles," he says. "We were excited about having these abstractions shared across the entire ecosystem, which would result in a lot more momentum than we saw in other potential solutions."

Box deployed Kubernetes in a cluster in a production data center just six months later. Kubernetes was then still pre-beta, on version 0.11. They started small: The very first thing Ghods’s team ran on Kubernetes was a Box API checker that confirms Box is up. "That was just to write and deploy some software to get the whole pipeline functioning," he says. Next came some daemons that process jobs, which was "nice and safe because if they experienced any interruptions, we wouldn’t fail synchronous incoming requests from customers." From d58b78d05898bd94a6278eb9f4ca2f438f65d71f Mon Sep 17 00:00:00 2001 From: Weihua Meng Date: Sat, 9 Sep 2017 11:18:05 -0500 Subject: [PATCH 27/58] Update opaque-integer-resource-node.md (#5330) typo correction --- docs/tasks/administer-cluster/opaque-integer-resource-node.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tasks/administer-cluster/opaque-integer-resource-node.md b/docs/tasks/administer-cluster/opaque-integer-resource-node.md index 71925c1642..026488ebe2 100644 --- a/docs/tasks/administer-cluster/opaque-integer-resource-node.md +++ b/docs/tasks/administer-cluster/opaque-integer-resource-node.md @@ -134,7 +134,7 @@ opaque-int-resource-special-storage. ```yaml Capacity: ... - pod.alpha.kubernetes.io/opaque-int-special-storage: 8 + pod.alpha.kubernetes.io/opaque-int-resource-special-storage: 8 ``` If you want to allow arbitrary requests for special storage, you @@ -144,7 +144,7 @@ could advertise special storage in chunks of size 1 byte. In that case, you woul ```yaml Capacity: ... - pod.alpha.kubernetes.io/opaque-int-special-storage: 8Gi + pod.alpha.kubernetes.io/opaque-int-resource-special-storage: 8Gi ``` Then a Container could request any number of bytes of special storage, up to 800Gi. From 7eb3fa9f2eb04c12d5396d9419697d76bee1839e Mon Sep 17 00:00:00 2001 From: Steve Perry Date: Sat, 9 Sep 2017 09:22:48 -0700 Subject: [PATCH 28/58] Update opaque-integer-resource-node.md --- docs/tasks/administer-cluster/opaque-integer-resource-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/administer-cluster/opaque-integer-resource-node.md b/docs/tasks/administer-cluster/opaque-integer-resource-node.md index 026488ebe2..cae82948be 100644 --- a/docs/tasks/administer-cluster/opaque-integer-resource-node.md +++ b/docs/tasks/administer-cluster/opaque-integer-resource-node.md @@ -144,7 +144,7 @@ could advertise special storage in chunks of size 1 byte. In that case, you woul ```yaml Capacity: ... - pod.alpha.kubernetes.io/opaque-int-resource-special-storage: 8Gi + pod.alpha.kubernetes.io/opaque-int-resource-special-storage: 800Gi ``` Then a Container could request any number of bytes of special storage, up to 800Gi. From fdbe5086a0fe268de6c3fe50638c0a194d3bfbe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=93=E9=9B=B7=E4=B8=8D=E6=80=95?= Date: Sun, 10 Sep 2017 00:45:38 +0800 Subject: [PATCH 29/58] cn-translation-from-2017-08-14-to-2017-09-03 (#5364) --- .../architecture/master-node-communication.md | 71 +++ cn/docs/concepts/architecture/nodes.md | 234 ++++++++++ .../concepts/cluster-administration/addons.md | 45 ++ .../cluster-administration-overview.md | 86 ++++ .../access-cluster-services.md | 110 +++++ .../apply-resource-quota-limit.md | 411 ++++++++++++++++++ .../change-default-storage-class.md | 94 ++++ .../change-pv-reclaim-policy.md | 80 ++++ .../administer-cluster/cluster-management.md | 227 ++++++++++ 9 files changed, 1358 insertions(+) create mode 100644 cn/docs/concepts/architecture/master-node-communication.md create mode 100644 cn/docs/concepts/architecture/nodes.md create mode 100644 cn/docs/concepts/cluster-administration/addons.md create mode 100644 cn/docs/concepts/cluster-administration/cluster-administration-overview.md create mode 100644 cn/docs/tasks/administer-cluster/access-cluster-services.md create mode 100644 cn/docs/tasks/administer-cluster/apply-resource-quota-limit.md create mode 100644 cn/docs/tasks/administer-cluster/change-default-storage-class.md create mode 100644 cn/docs/tasks/administer-cluster/change-pv-reclaim-policy.md create mode 100644 cn/docs/tasks/administer-cluster/cluster-management.md diff --git a/cn/docs/concepts/architecture/master-node-communication.md b/cn/docs/concepts/architecture/master-node-communication.md new file mode 100644 index 0000000000..e090ed3197 --- /dev/null +++ b/cn/docs/concepts/architecture/master-node-communication.md @@ -0,0 +1,71 @@ +--- +approvers: +- dchen1107 +- roberthbailey +- liggitt + +title: Master 节点通信 +--- + +* TOC +{:toc} + + +## 概览 + + +本文对 Master 节点(确切说是 apiserver)和 Kubernetes 集群之间的通信路径进行了分类。目的是为了让用户能够自定义他们的安装,对网络配置进行加固,使得集群能够在不可信的网络上(或者在一个云服务商完全公共的 IP 上)运行。 + + +## Cluster -> Master + + +所有从集群到 master 的通信路径都终止于 apiserver(其它 master 组件没有被设计为可暴露远程服务)。在一个典型的部署中,apiserver 被配置为在一个安全的 HTTPS 端口(443)上监听远程连接并启用一种或多种形式的客户端[身份认证](/docs/admin/authentication/)机制。一种或多种客户端[身份认证](/docs/admin/authentication/)机制应该被启用,特别是在允许使用 [匿名请求](/docs/admin/authentication/#anonymous-requests) 或 [service account tokens](/docs/admin/authentication/#service-account-tokens) 的时候。 + + +应该使用集群的公共根证书开通节点,如此它们就能够基于有效的客户端凭据安全的连接 apiserver。例如:在一个默认的 GCE 部署中,客户端凭据以客户端证书的形式提供给 kubelet。请查看 [kubelet TLS bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) 获取如何自动提供 kubelet 客户端证书。 + + +想要连接到 apiserver 的 Pods 可以使用一个 service account 安全的进行连接。这种情况下,当 Pods 被实例化时 Kubernetes 将自动的把公共根证书和一个有效的不记名令牌注入到 pod 里。`kubernetes` service (所有 namespaces 中)都配置了一个虚拟 IP 地址,用于转发(通过 kube-proxy)请求到 apiserver 的 HTTPS endpoint。 + + +Master 组件通过非安全(没有加密或认证)端口和集群的 apiserver 通信。这个端口通常只在 master 节点的 localhost 接口暴露,这样,所有在相同机器上运行的 master 组件就能和集群的 apiserver 通信。一段时间以后,master 组件将变为使用带身份认证和权限验证的安全端口(查看[#13598](https://github.com/kubernetes/kubernetes/issues/13598))。 + + +这样的结果使得从集群(在节点上运行的 nodes 和 pods)到 master 的缺省连接操作模式默认被保护,能够在不可信或公网中运行。 + + +## Master -> Cluster + + +从 master(apiserver)到集群有两种主要的通信路径。第一种是从 apiserver 到集群中每个节点上运行的 kubelet 进程。第二种是从 apiserver 通过它的代理功能到任何 node、pod 或者 service。 + + +### apiserver -> kubelet + + +从 apiserver 到 kubelet 的连接用于获取 pods 日志、连接(通过 kubectl)运行中的 pods,以及使用 kubele 的端口转发功能。这些连接终止于 kubelet 的 HTTPS endpoint。 + + +默认的,apiserver 不会验证 kubelet 的服务证书,这会导致连接遭到中间人攻击,因而在不可信或公共网络上是不安全的。 + + +为了对这个连接进行认证,请使用 `--kubelet-certificate-authority` 标记给 apiserver 提供一个根证书捆绑,用于 kubelet 的服务证书。 + + +如果这样不可能,又要求避免在不可信的或公共的网络上进行连接,请在 apiserver 和 kubelet 之间使用 [SSH 隧道](/docs/concepts/architecture/master-node-communication/#ssh-tunnels)。 + + +最后,应该启用[Kubelet 用户认证和/或权限认证](/docs/admin/kubelet-authentication-authorization/)来保护 kubelet API。 + + +### apiserver -> nodes, pods, and services + + +从 apiserver 到 node、pod或者service 的连接默认为纯 HTTP 方式,因此既没有认证,也没有加密。他们能够通过给API URL 中的 node、pod 或 service 名称添加前缀 `https:` 来运行在安全的 HTTPS 连接上。但他们即不会认证 HTTPS endpoint 提供的证书,也不会提供客户端证书。这样虽然连接是加密的,但它不会提供任何完整性保证。这些连接**目前还不能安全的**在不可信的或公共的网络上运行。 + + +### SSH 隧道 + + +[Google Container Engine](https://cloud.google.com/container-engine/docs/) 使用 SSH 隧道保护 Master -> Cluster 通信路径。在这种配置下,apiserver 发起一个到集群中每个节点的 SSH 隧道(连接到在 22 端口监听的 ssh 服务)并通过这个隧道传输所有到 kubelet、node、pod 或者 service 的流量。这个隧道保证流量不会在集群运行的私有 GCE 网络之外暴露。 diff --git a/cn/docs/concepts/architecture/nodes.md b/cn/docs/concepts/architecture/nodes.md new file mode 100644 index 0000000000..1e611c896a --- /dev/null +++ b/cn/docs/concepts/architecture/nodes.md @@ -0,0 +1,234 @@ +--- +assignees: +- caesarxuchao +- dchen1107 + +title: Nodes +redirect_from: +- "/docs/admin/node/" +- "/docs/admin/node.html" +- "/docs/concepts/nodes/node/" +- "/docs/concepts/nodes/node.html" +--- + +* TOC +{:toc} + + +## Node 是什么? + + +`Node` 是 Kubernetes 的工作节点,以前叫做 `minion`。取决于你的集群,Node 可以是一个虚拟机或者物理机器。每个 node 都有用于运行 [pods](/docs/user-guide/pods) 的必要服务,并由 master 组件管理。Node 上的服务包括 Docker、kubelet 和 kube-proxy。请查阅架构设计文档中 [The Kubernetes Node](https://git.k8s.io/community/contributors/design-proposals/architecture.md#the-kubernetes-node) 一节获取更多细节。 + + +## Node 状态 + + + 一个 node 的状态包含以下信息: + +* [地址](#地址) +* ~~[阶段](#阶段)~~ **已废弃** +* [条件](#条件) +* [容量](#容量) +* [信息](#信息) + + +下面对每个章节进行详细描述。 + + +### 地址 + + +这些字段组合的用法取决于你的云服务商或者裸金属配置。 + +* HostName:HostName 和 node 内核报告的相同。可以通过 kubelet 的 `--hostname-override` 参数覆盖。 +* ExternalIP:通常是可以外部路由的 node IP 地址(从集群外可访问)。 +* InternalIP:通常是仅可在集群内部路由的 node IP 地址。 + + +### 阶段 + + +一废弃:node 阶段已经不再使用。 + + +### 条件 + + +`conditions` 字段描述了所有 `Running` nodes 的状态。 + + +| Node 条件 | 描述 | +| ---------------- | ---------------------------------------- | +| `OutOfDisk` | `True` 表示 node 的空闲空间不足以用于添加新 pods, 否则为 `False` | +| `Ready` | `True` 表示 node 是健康的并已经准备好接受 pods;`False` 表示 node 不健康而且不能接受 pods;`Unknown` 表示 node 控制器在最近 40 秒内没有收到 node 的消息 | +| `MemoryPressure` | `True` 表示 node 不存在内存压力 -- 即 node 内存用量低, 否则为 `False` | +| `DiskPressure` | `True` 表示 node 不存在磁盘压力 -- 即磁盘用量低, 否则为 `False` | + + +Node 条件使用一个 JSON 对象表示。例如,下面的响应描述了一个健康的 node。 + +```json +"conditions": [ + { + "kind": "Ready", + "status": "True" + } +] +``` + + +如果 Ready 条件处于状态 "Unknown" 或者 "False" 的时间超过了 `pod-eviction-timeout`(一个传递给 [kube-controller-manager](/docs/admin/kube-controller-manager/) 的参数),node 上的所有 Pods 都会被 Node 控制器计划删除。默认的删除超时时长为**5分钟**。某些情况下,当 node 不可访问时,apiserver 不能和其上的 kubelet 通信。删除 pods 的决定不能传达给 kubelet,直到它重新建立和 apiserver 的连接为止。与此同时,被计划删除的 pods 可能会继续在分区 node 上运行。 + + +在 1.5 版本之前的 Kubernetes 里,node 控制器会将不能访问的 pods 从 apiserver 中[强制删除](/docs/concepts/workloads/pods/pod/#force-deletion-of-pods)。但在 1.5 或更高的版本里,在node 控制器确认这些 pods 已经在集群里停运行前不会强制删除它们。你可以看到这些处于 "Terminating" 或者 "Unknown" 状态的 pods 可能在无法访问的 node 上运行。为了防止 kubernetes 不能从底层基础设施中推断出一个 node 是否已经永久的离开了集群,集群管理员可能需要手动删除这个 node 对象。从 Kubernetes 删除 node 对象将导致 apiserver 删除 node 上所有运行的 Pod 对象并释放它们的名字。 + + +### 容量 + + +描述 node 上的可用资源:CPU、内存和可以调度到 node 上的 pods 的最大数量。 + + +### 信息 + + +关于 node 的通用信息,例如内核版本、Kubernetes 版本(kubelet 和 kube-proxy 版本)、Docker 版本 (如果使用了)和 OS 名。这些信息由 Kubelet 从 node 搜集而来。 + + +## 管理 + + +与 [pods](/docs/user-guide/pods) 和 [services](/docs/user-guide/services) 不同,node 并不是在 Kubernetes 内部创建的:它是被外部的云服务商创建,例如 Google Compute Engine 或者你的集群中的物理或者虚拟机。这意味着当 Kubernetes 创建一个 node 时,它其实仅仅创建了一个对象来代表这个 node。创建以后,Kubernetes 将检查这个 node 是否可用。例如,如果你尝试使用如下内容创建一个 node: + +```json +{ + "kind": "Node", + "apiVersion": "v1", + "metadata": { + "name": "10.240.79.157", + "labels": { + "name": "my-first-k8s-node" + } + } +} +``` + + +Kubernetes 会在内部创一个 node 对象(象征 node),并基于 `metadata.name` 字段(我们假设 `metadata.name` 能够被解析)通过健康检查来验证 node。如果 node 可用,意即所有必要服务都已运行,它就符合了运行一个 pod 的条件;否则它将被所有的集群动作忽略指导变为可用。请注意,Kubernetes 将保存不可用 node 的对象,除非它被客户端显式的删除。Kubernetes 将持续检查 node 是否变的可用。 + + +当前,有3个组件同 Kubernetes node 接口交互:node 控制器、kubelet 和 kubectl。 + + +### Node 控制器 + + +Node 控制器是一个 Kubernetes master 组件,管理 nodes 的方方面面。 + + +Node 控制器在 node 的生命周期中扮演了多个角色。第一个是当 node 注册时为它分配一个 CIDR block(如果打开了 CIDR 分配)。 + + +第二个是使用云服务商提供了可用节点列表保持 node 控制器内部的 nodes 列表更新。如果在云环境下运行,任何时候当一个 node 不健康时 node 控制器将询问云服务 node 的虚拟机是否可用。如果不可用,node 控制器会将这个 node 从它的 nodes 列表删除。 + + +第三个是监控 nodes 的健康情况。Node 控制器负责在 node 不能访问时(也即是 node 控制器因为某些原因没有收到心跳,例如 node 宕机)将它的 NodeStatus 的 NodeReady 状态更新为 ConditionUnknown。后续如果 node 持续不可访问,Node 控制器将删除 node 上的所有 pods(使用优雅终止)。(默认情况下 40s 开始报告 ConditionUnknown,在那之后 5m 开始删除 pods。)Node 控制器每隔 `--node-monitor-period` 秒检查每个 node 的状态。 + + +在 Kubernetes 1.4 中我们更新了 node 控制器逻辑以更好的处理大批量 nodes 访问 master 出问题的情况(例如 master 的网络出了问题)。从 1.4 开始,node 控制器在决定删除 pod 之前会检查集群中所有 nodes 的状态。 + + +大部分情况下, node 控制器把删除频率限制在每秒 `--node-eviction-rate` 个(默认为 0.1)。这表示它在 10 秒钟内不会从超过一个 node 上删除 pods。 + + +当一个 availability zone 中的 node 变为不健康时,它的删除行为将发生改变。Node 控制器会同时检查 zone 中不健康(NodeReady 状态为 ConditionUnknown 或 ConditionFalse)的 nodes 的百分比。如果不健康 nodes 的部分超过 `--unhealthy-zone-threshold` (默认为 0.55),删除速率将会减小:如果集群较小(意即小于等于 `--large-cluster-size-threshold` 个 nodes - 默认为50),删除将会停止,否则删除速率将降为每秒 `--secondary-node-eviction-rate` 个(默认为 0.01)。在单个 availability zone 实施这些策略的原因是当一个 availability zone 可能从 master 分区时其它的仍然保持连接。如果你的集群没有跨越云服务商的多个 availability zones,那就只有一个 availability zone(整个集群)。 + + +在多个 availability zones 分布你的 nodes 的一个关键原因是当整个 zone 故障时,工作负载可以转移到健康的 zones。因此,如果一个 zone 中的所有 nodes 都不健康时,node 控制器会以正常的速率 `--node-eviction-rate` 删除。在所有的 zones 都不健康(也即集群中没有健康 node)的极端情况下,node 控制器将假设 master 的连接出了某些问题,它将停止所有删除动作直到一些连接恢复。 + + +从 Kubernetes 1.6 开始,NodeController 还负责删除运行在拥有 `NoExecute` taints 的 nodes 上的 pods,如果这些 pods 没有 tolerate 这些 taints。此外,作为一个默认禁用的 alpha 特性,NodeController 还负责根据 node 故障(例如 node 不可访问或没有 ready)添加 taints。请查看 [这个文档](/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature)了解关于 `NoExecute` taints 和这个 alpha 特性。 + + +### Nodes 自注册 + + +当 kubelet 标志 `--register-node` 为 true (默认)时,它会尝试向 API 服务注册自己。这是首选模式,被绝大多数发行版选用。 + + + 对于自注册模式,kubelet 使用下列参数启动: + + - `--api-servers` - apiservers 地址。 + - `--kubeconfig` - 用于向 apiserver 验证自己的凭据路径。 + - `--cloud-provider` - 如何从云服务商读取关于自己的元数据。 + - `--register-node` - 自动向 API 服务注册。 + - `--register-with-taints` - 使用 taints 列表(逗号分隔的 `=:`)注册 node。当 `register-node` 为 false 时无效。 + - `--node-ip` - node IP 地址。 + - `--node-labels` - 向集群注册时给 node 添加的 labels。 + - `--node-status-update-frequency` - 指定 kubelet 向 master 发送状态的频率。 + + +目前,任何 kubelet 都被授权可以创建/修改任意 node 资源,但通常只对自己的进行创建/修改。(未来我们计划只允许一个 kubelet 修改它自己 node 的资源。) + + +#### 手动 Node 管理 + + +集群管理员可以创建及修改 node 对象。 + + +如果管理员希望手动创建 node 对象,请设置 kubelet 标记 `--register-node=false`。 + + +管理员可以修改 node 资源(忽略 `--register-node` 设置)。修改包括在 node 上设置 labels及标记它为不可调度。 + + +Nodes 上的 labels 可以和 pods 的 node selectors 一起使用来控制调度,例如限制一个 pod 只能在一个符合要求的 nodes 子集上运行。 + + +标记一个 node 为不可调度的将防止新建 pods 调度到那个 node 之上,但不会影响任何已经在它之上的 pods。这是重启 node 等操作之前的一个有用的准备步骤。例如,标记一个 node 为不可调度的,执行以下命令: + +```shell +kubectl cordon $NODENAME +``` + + +请注意,被 daemonSet 控制器创建的 pods 将忽略 Kubernetes 调度器,且不会遵照 node 上不可调度的属性。这个假设基于守护程序属于节点机器,即使在准备重启而隔离应用的时候。 + + +### Node 容量 + + +Node 的容量(cpu 数量和内存容量)是 node 对象的一部分。通常情况下,在创建 node 对象时,它们会注册自己并报告自己的容量。如果你正在执行[手动 node 管理](#manual-node-administration),那么你需要在添加 node 时手动设置 node 容量。 + + +Kubernetes 调度器保证一个 node 上有足够的资源供其上的所有 pods 使用。它会检查 node 上所有容器要求的总和不会超过 node 的容量。这包括所有 kubelet 启动的容器,但不包含 Docker 启动的容器和不在容器中的进程。 + + +如果希望显式的为非 pod 进程预留资源,你可以创建一个占位 pod。使用如下模板: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: resource-reserver +spec: + containers: + - name: sleep-forever + image: gcr.io/google_containers/pause:0.8.0 + resources: + requests: + cpu: 100m + memory: 100Mi +``` + + +设置 `cpu` 和 `memory` 值为你希望预留的资源量。将文件放在清单文件夹中(kubelet 的 `--config=DIR` 标志)。当你希望预留资源时,在每个 kubelet 上都这样执行。 + + +## API 对象 + + +Node 是 Kubernetes REST API 的顶级资源。更多关于 API 对象的细节可以在这里找到: [Node API +object](/docs/api-reference/{{page.version}}/#node-v1-core).`` diff --git a/cn/docs/concepts/cluster-administration/addons.md b/cn/docs/concepts/cluster-administration/addons.md new file mode 100644 index 0000000000..1ddac950f1 --- /dev/null +++ b/cn/docs/concepts/cluster-administration/addons.md @@ -0,0 +1,45 @@ +--- + +title: 安装扩展(Addons) +--- + + +## 概览 + + +Add-ons 扩展了 Kubernetes 的功能。 + + +本文列举了一些可用的 add-ons 以及到它们各自安装说明的链接。 + + +每个 add-ons 按字母顺序排序 - 顺序不代表任何优先地位。 + + +## 网络和网络策略 + + +* [Calico](http://docs.projectcalico.org/latest/getting-started/kubernetes/installation/hosted/) 是一个安全的 L3 网络和网络策略提供者。 +* [Canal](https://github.com/tigera/canal/tree/master/k8s-install) 结合 Flannel 和 Calico, 提供网络和网络策略。 +* [Cilium](https://github.com/cilium/cilium) 是一个 L3 网络和网络策略插件, 能够透明的实施 HTTP/API/L7 策略。 同时支持路由(routing)和叠加/封装( overlay/encapsulation)模式。 +* [Contiv](http://contiv.github.io) 为多种用例提供可配置网络(使用 BGP 的原生 L3,使用 vxlan 的 overlay,经典 L2 和 Cisco-SDN/ACI)和丰富的策略框架。Contiv 项目完全[开源](http://github.com/contiv)。[安装工具](http://github.com/contiv/install)同时提供基于和不基于 kubeadm 的安装选项。 +* [Flannel](https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml) 是一个可以用于 Kubernetes 的 overlay 网络提供者。 +* [Romana](http://romana.io) 是一个 pod 网络的层 3 解决方案,并且支持 [NetworkPolicy API](/docs/concepts/services-networking/network-policies/)。Kubeadm add-on 安装细节可以在[这里](https://github.com/romana/romana/tree/master/containerize)找到。 +* [Weave Net](https://www.weave.works/docs/net/latest/kube-addon/) 提供了在网络分组两端参与工作的网络和网络策略,并且不需要额外的数据库。 +* [CNI-Genie](https://github.com/Huawei-PaaS/CNI-Genie) 使 Kubernetes 无缝连接到一种 CNI 插件,例如:Flannel、Calico、Canal、Romana 或者 Weave。 + + +## 可视化管理 + + +* [Dashboard](https://github.com/kubernetes/dashboard#kubernetes-dashboard) 是一个 Kubernetes 的 web 控制台界面。 +* [Weave Scope](https://www.weave.works/documentation/scope-latest-installing/#k8s) 是一个图形化工具,用于查看你的 containers、 pods、services等。 请和一个 [Weave Cloud account](https://cloud.weave.works/) 一起使用,或者自己运行 UI。 + + +## 遗留 Add-ons + + +还有一些其它 add-ons 归档在已废弃的 [cluster/addons](https://git.k8s.io/kubernetes/cluster/addons) 路径中。 + + +维护完善的 add-ons 应该被链接到这里。欢迎提出 PRs! diff --git a/cn/docs/concepts/cluster-administration/cluster-administration-overview.md b/cn/docs/concepts/cluster-administration/cluster-administration-overview.md new file mode 100644 index 0000000000..9f6fbf0f9e --- /dev/null +++ b/cn/docs/concepts/cluster-administration/cluster-administration-overview.md @@ -0,0 +1,86 @@ +--- +approvers: +- davidopp +- lavalamp + +title: 集群管理概述 +--- + +{% capture overview %} + +集群管理概述面向任何创建和管理 Kubernetes 集群的读者人群。我们假设你对 [用户指南](/docs/user-guide/)中的概念有一些熟悉。 +{% endcapture %} + +{% capture body %} + +## 规划集群 + + +查阅 [选择正确解决方案](/docs/setup/pick-right-solution/) 中的指导,获取如何规划、建立以及配置 Kubernetes 集群的示例。本文所列的文章称为*发行版*。 + + +在选择一个指南前,有一些因素需要考虑: + + - 你是打算在你的电脑上尝试 Kubernetes,还是要构建一个高可用的多节点集群?请选择最适合你需求的发行版。 + - **如果你正在设计一个高可用集群**,请了解[在多个 zones 中配置集群](/docs/admin/multi-cluster)。 + - 你的集群是在**本地**还是**云(IaaS)**上?Kubernetes 不能直接支持混合集群。作为代替,你可以建立多个集群。 + - **如果你在本地配置 Kubernetes**,需要考虑哪种[网络模型](/docs/admin/networking)最适合。一种自定义网络的选项是 [*OpenVSwitch GRE/VxLAN 网络*](/docs/admin/ovs-networking/),它使用 OpenVSwitch 在跨 Kubernetes 节点的 pods 之间建立起网络。 + - 你的 Kubernetes 在 **裸金属硬件** 还是 **虚拟机(VMs)**上运行? + - 你**只想运行一个集群**,还是打算**活动开发 Kubernetes 项目代码**?如果是后者,请选择一个活动开发的发行版。某些发行版只提供二进制发布版,但提供更多的选择。 + - 让你自己熟悉运行一个集群所需的[组件](/docs/admin/cluster-components) 。 + + +请注意:不是所有的发行版都被积极维护着。请选择测试过最近版本的 Kubernetes 的发行版。 + + +如果你正在使用和 Salt 有关的指南,请查阅 [使用 Salt 配置 Kubernetes](/docs/admin/salt)。 + + +## 管理集群 + + +[管理集群](/docs/concepts/cluster-administration/cluster-management/)叙述了和集群生命周期相关的几个主题:创建一个新集群、升级集群的 master 和 worker 节点、执行节点维护(例如内核升级)以及升级活动集群的 Kubernetes API 版本。 + + +## 保护集群 + + +* [Kubernetes 容器环境](/docs/concepts/containers/container-environment-variables/) 描述了 Kubernetes 节点上由 Kubelet 管理的容器的环境。 + + +* [控制到 Kubernetes API 的访问](/docs/admin/accessing-the-api) 描述了如何为用户和 service accounts 建立权限许可. + + +* [用户认证](/docs/admin/authentication) 阐述了 Kubernetes 中的认证功能,包括许多认证选项。 + + +* [授权](/docs/admin/authorization)从认证中分离出来,用于控制如何处理 HTTP 请求。 + + +* [使用 Admission Controllers](/docs/admin/admission-controllers) 阐述了在认证和授权之后拦截到 Kubernetes API 服务的请求的插件。 + + +* [在 Kubernetes Cluster 中使用 Sysctls](/docs/concepts/cluster-administration/sysctl-cluster/) 描述了管理员如何使用 `sysctl` 命令行工具来设置内核参数。 + + +* [审计](/docs/tasks/debug-application-cluster/audit/) 描述了如何与 Kubernetes 的审计日志交互。 + + +### 保护 kubelet + + * [Master 节点通信](/docs/concepts/cluster-administration/master-node-communication/) + * [TLS 引导](/docs/admin/kubelet-tls-bootstrapping/) + * [Kubelet 认证/授权](/docs/admin/kubelet-authentication-authorization/) + + +## 可选集群服务 + + +* [DNS 与 SkyDNS 集成](/docs/concepts/services-networking/dns-pod-service/)描述了如何将一个 DNS 名解析到一个Kubernetes service。 + + +* [记录和监控集群活动](/docs/concepts/cluster-administration/logging/) 阐述了Kubernetes 的日志如何工作以及怎样实现。 + +{% endcapture %} + +{% include templates/concept.md %} diff --git a/cn/docs/tasks/administer-cluster/access-cluster-services.md b/cn/docs/tasks/administer-cluster/access-cluster-services.md new file mode 100644 index 0000000000..00e06266ab --- /dev/null +++ b/cn/docs/tasks/administer-cluster/access-cluster-services.md @@ -0,0 +1,110 @@ +--- + +title: 访问集群上运行的服务 +redirect_from: +- "/docs/user-guide/accessing-the-cluster/" +- "/docs/user-guide/accessing-the-cluster.html" +--- + +{% capture overview %} + +本文展示了如何连接 Kubernetes 集群上运行的服务。 +{% endcapture %} + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} +{% endcapture %} + +{% capture steps %} + +## 访问集群上运行的服务 + + +在 Kubernetes 里, [nodes](/docs/admin/node)、[pods](/docs/user-guide/pods) 和 [services](/docs/user-guide/services) 都有它们自己的 IP。许多情况下,集群上的 node IP、pod IP 和某些 service IP 路由不可达,所以不能从一个集群之外的节点访问它们,例如从你自己的台式机。 + + +### 连接方式 + + +你有多种从集群外连接 nodes、pods 和 services 的选项: + + + - 通过公共 IP 访问 services。 + - 使用具有 `NodePort` 或 `LoadBalancer` 类型的 service,可以从外部访问它们。请查阅 [services](/docs/user-guide/services) 和 [kubectl expose](/docs/user-guide/kubectl/v1.6/#expose) 文档。 + - 取决于你的集群环境,你可以仅把 service 暴露在你的企业网络环境中,也可以将其暴露在因特网上。需要考虑暴露的 service 是否安全,它是否有自己的用户认证? + - 将 pods 放置于 services 背后。如果要访问一个副本集合中特定的 pod,例如用于调试目的时,请给 pod 指定一个独特的标签并创建一个新 service 选择这个标签。 + - 大部分情况下,都不需要应用开发者通过节点 IP 直接访问 nodes。 + - 通过 Proxy Verb 访问 services、nodes 或者 pods。 + - 在访问 Apiserver 远程服务之前是否经过认证和授权?如果你的服务暴露到因特网中不够安全,或者需要获取 node IP 之上的端口,又或者处于调试目的时,请使用这个特性。 + - Proxies 可能给某些应用带来麻烦。 + - 仅适用于 HTTP/HTTPS。 + - 在[这里](#manually-constructing-apiserver-proxy-urls)描述 + - 从集群中的 node 或者 pod 访问。 + - 运行一个 pod,然后使用 [kubectl exec](/docs/user-guide/kubectl/v1.6/#exec) 连接到它的一个shell。从那个 shell 连接其他的 nodes、pods 和 services。 + - 某些集群可能允许你 ssh 到集群中的节点。你可能可以从那儿访问集群服务。这是一个非标准的方式,可能在一些集群上能工作,但在另一些上却不能。浏览器和其他工具可能安装或可能不会安装。集群 DNS 可能不会正常工作。 + + +### 发现内置服务 + + +典型情况下,kube-system 会启动集群中的几个服务。使用 `kubectl cluster-info` 命令获取它们的列表: + +```shell +$ kubectl cluster-info + + Kubernetes master is running at https://104.197.5.247 + elasticsearch-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy + kibana-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kibana-logging/proxy + kube-dns is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kube-dns/proxy + grafana is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy + heapster is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy +``` + +这显示了用于访问每个服务的 proxy-verb URL。例如,这个集群启用了(使用 Elasticsearch)集群层面的日志,如果提供合适的凭据可以通过 `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/` 访问,或通过一个 kubectl 代理地址访问,如:`http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/`。(请查看 [上文](#accessing-the-cluster-api) 关于如何传递凭据或者使用 kubectl 代理的说明。) + + +#### 手动构建 apiserver 代理 URLs + + +如同上面所提到的,你可以使用 `kubectl cluster-info` 命令取得 service 的代理 URL。为了创建包含 service endpoints、suffixes 和 parameters 的代理 URLs,你可以简单的在 service 的代理 URL中 添加: +`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`service_name[:port_name]`*`/proxy` + + +如果还没有为你的端口指定名称,你可以不用在 URL 中指定 *port_name*。 + + +##### 示例 + + + * 你可以通过 `http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy` 访问 Elasticsearch service endpoint `_search?q=user:kimchy`。 + * 你可以通过 `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true` 访问 Elasticsearch 集群健康信息 endpoint `_cluster/health?pretty=true`。 + +```json + { + "cluster_name" : "kubernetes_logging", + "status" : "yellow", + "timed_out" : false, + "number_of_nodes" : 1, + "number_of_data_nodes" : 1, + "active_primary_shards" : 5, + "active_shards" : 5, + "relocating_shards" : 0, + "initializing_shards" : 0, + "unassigned_shards" : 5 + } +``` + + +#### 通过 web 浏览器访问集群中运行的服务 + + +你或许能够将 apiserver 代理的 url 放入浏览器的地址栏,然而: + + + - Web 服务器不总是能够传递令牌,所以你可能需要使用基本(密码)认证。 Apiserver 可以配置为接受基本认证,但你的集群可能并没有这样配置。 + - 某些 web 应用可能不能工作,特别是那些使用客户端侧 javascript 的应用,它们构造 url 的方式可能不能理解代理路径前缀。 + +{% endcapture %} + +{% include templates/task.md %} diff --git a/cn/docs/tasks/administer-cluster/apply-resource-quota-limit.md b/cn/docs/tasks/administer-cluster/apply-resource-quota-limit.md new file mode 100644 index 0000000000..5ffd280425 --- /dev/null +++ b/cn/docs/tasks/administer-cluster/apply-resource-quota-limit.md @@ -0,0 +1,411 @@ +--- +assignees: +- derekwaynecarr +- janetkuo + +title: 应用资源配额和限额 +redirect_from: +- "/docs/admin/resourcequota/walkthrough/" +- "/docs/admin/resourcequota/walkthrough.html" +- "/docs/tasks/configure-pod-container/apply-resource-quota-limit/" +- "/docs/tasks/configure-pod-container/apply-resource-quota-limit.html" +--- + +{% capture overview %} + + +本示例展示了在一个 namespace 中控制资源用量的典型设置。 + + +本文展示了以下资源的使用: [Namespace](/docs/admin/namespaces), [ResourceQuota](/docs/concepts/policy/resource-quotas/) 和 [LimitRange](/docs/tasks/configure-pod-container/limit-range/)。 + +{% endcapture %} + +{% capture prerequisites %} + +* {% include task-tutorial-prereqs.md %} + +{% endcapture %} + +{% capture steps %} + +## 场景 + + +集群管理员正在操作一个代表用户群体的集群,他希望控制一个特定 namespace 中可以被使用的资源总量,以达到促进对集群的公平共享及控制成本的目的。 + + +集群管理员有以下目标: + + +* 限制运行中 pods 使用的计算资源数量 +* 限制 persistent volume claims 数量以控制对存储的访问 +* 限制 load balancers 数量以控制成本 +* 防止使用 node ports 以保留稀缺资源 +* 提供默认计算资源请求以实现更好的调度决策 + + +## 创建 namespace + + +本示例将在一个自定义的 namespace 中运行,以展示相关概念。 + + +让我们创建一个叫做 quota-example 的新 namespace: + +```shell +$ kubectl create namespace quota-example +namespace "quota-example" created +$ kubectl get namespaces +NAME STATUS AGE +default Active 2m +kube-system Active 2m +quota-example Active 39s +``` + + +## 应用 object-count 配额到 namespace + + +集群管理员想要控制下列资源: + +* persistent volume claims +* load balancers +* node ports + + +我们来创建一个简单的配额,用于控制这个 namespace 中那些资源类型的对象数量。 + +```shell +$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-object-counts.yaml --namespace=quota-example +resourcequota "object-counts" created +``` + + +配额系统将察觉到有一个配额被创建,并且会计算 namespace 中的资源消耗量作为响应。这应该会很快发生。 + + +让我们显示一下配额来观察这个 namespace 中当前被消耗的资源: + +```shell +$ kubectl describe quota object-counts --namespace=quota-example +Name: object-counts +Namespace: quota-example +Resource Used Hard +-------- ---- ---- +persistentvolumeclaims 0 2 +services.loadbalancers 0 2 +services.nodeports 0 0 +``` + + +配额系统现在将阻止用户创建比各个资源指定数量更多的资源。 + + + +## 应用计算资源配额到 namespace + + +为了限制这个 namespace 可以被使用的计算资源数量,让我们创建一个跟踪计算资源的配额。 + +```shell +$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-compute-resources.yaml --namespace=quota-example +resourcequota "compute-resources" created +``` + + +让我们显示一下配额来观察这个 namespace 中当前被消耗的资源: + +```shell +$ kubectl describe quota compute-resources --namespace=quota-example +Name: compute-resources +Namespace: quota-example +Resource Used Hard +-------- ---- ---- +limits.cpu 0 2 +limits.memory 0 2Gi +pods 0 4 +requests.cpu 0 1 +requests.memory 0 1Gi +``` + + +配额系统现在会防止 namespace 拥有超过 4 个没有终止的 pods。此外它还将强制 pod 中的每个容器配置一个 `request` 并为 `cpu` 和 `memory` 定义 `limit`。 + + +## 应用默认资源请求和限制 + + +Pod 的作者很少为它们的 pods 指定资源请求和限制。 + + +既然我们对项目应用了配额,我们来看一下当终端用户通过创建一个没有 cpu 和 内存限制的 pod 时会发生什么。这通过在 pod 里创建一个 nginx 容器实现。 + + +作为演示,让我们来创建一个运行 nginx 的 deployment: + +```shell +$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example +deployment "nginx" created +``` + + +现在我们来看一下创建的 pods。 + +```shell +$ kubectl get pods --namespace=quota-example +``` + + +发生了什么?我一个 pods 都没有!让我们 describe 这个 deployment 来看看发生了什么。 + +```shell +$ kubectl describe deployment nginx --namespace=quota-example +Name: nginx +Namespace: quota-example +CreationTimestamp: Mon, 06 Jun 2016 16:11:37 -0400 +Labels: run=nginx +Selector: run=nginx +Replicas: 0 updated | 1 total | 0 available | 1 unavailable +StrategyType: RollingUpdate +MinReadySeconds: 0 +RollingUpdateStrategy: 1 max unavailable, 1 max surge +OldReplicaSets: +NewReplicaSet: nginx-3137573019 (0/1 replicas created) +... +``` + + +Deployment 创建了一个对应的 replica set 并尝试按照大小来创建一个 pod。 + + +让我们看看 replica set 的更多细节。 + +```shell +$ kubectl describe rs nginx-3137573019 --namespace=quota-example +Name: nginx-3137573019 +Namespace: quota-example +Image(s): nginx +Selector: pod-template-hash=3137573019,run=nginx +Labels: pod-template-hash=3137573019 + run=nginx +Replicas: 0 current / 1 desired +Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed +No volumes. +Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 4m 7s 11 {replicaset-controller } Warning FailedCreate Error creating: pods "nginx-3137573019-" is forbidden: Failed quota: compute-resources: must specify limits.cpu,limits.memory,requests.cpu,requests.memory +``` + + +Kubernetes API server 拒绝了 replica set 创建一个 pod 的请求,因为我们的 pods 没有为 `cpu` 和 `memory` 指定 `requests` 或 `limits`。 + + +因此,我们来为 pod 指定它可以使用的 `cpu` 和 `memory` 默认数量。 + +```shell +$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-limits.yaml --namespace=quota-example +limitrange "limits" created +$ kubectl describe limits limits --namespace=quota-example +Name: limits +Namespace: quota-example +Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio +---- -------- --- --- --------------- ------------- ----------------------- +Container memory - - 256Mi 512Mi - +Container cpu - - 100m 200m - +``` + + +如果 Kubernetes API server 发现一个 namespace 中有一个创建 pod 的请求,并且 pod 中的容器没有设置任何计算资源请求时,作为准入控制的一部分,一个默认的 request 和 limit 将会被应用。 + + +在本例中,创建的每个 pod 都将拥有如下的计算资源限制: + +```shell +$ kubectl run nginx \ + --image=nginx \ + --replicas=1 \ + --requests=cpu=100m,memory=256Mi \ + --limits=cpu=200m,memory=512Mi \ + --namespace=quota-example +``` + + +由于已经为我们的 namespace 申请了默认的计算资源,我们的 replica set 应该能够创建它的 pods 了。 + +```shell +$ kubectl get pods --namespace=quota-example +NAME READY STATUS RESTARTS AGE +nginx-3137573019-fvrig 1/1 Running 0 6m +``` + + +而且如果打印出我们在这个 namespace 中的配额使用情况: + +```shell +$ kubectl describe quota --namespace=quota-example +Name: compute-resources +Namespace: quota-example +Resource Used Hard +-------- ---- ---- +limits.cpu 200m 2 +limits.memory 512Mi 2Gi +pods 1 4 +requests.cpu 100m 1 +requests.memory 256Mi 1Gi + + +Name: object-counts +Namespace: quota-example +Resource Used Hard +-------- ---- ---- +persistentvolumeclaims 0 2 +services.loadbalancers 0 2 +services.nodeports 0 0 +``` + + +就像你看到的,创建的 pod 消耗了明确的计算资源量,并且正被 Kubernetes 正确的追踪着。 + + +## 高级配额 scopes + + +让我们想象一下如果你不希望为你的 namespace 指定默认计算资源使用量。 + + +作为替换,你希望用户在它们的 namespace 中运行指定数量的 `BestEffort` pods,以从宽松的计算资源中获得好处。然后要求用户为需要更高质量服务的 pods 配置一个显式的资源请求。 + + +让我们新建一个拥有两个配额的 namespace 来演示这种行为: + +```shell +$ kubectl create namespace quota-scopes +namespace "quota-scopes" created +$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-best-effort.yaml --namespace=quota-scopes +resourcequota "best-effort" created +$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-not-best-effort.yaml --namespace=quota-scopes +resourcequota "not-best-effort" created +$ kubectl describe quota --namespace=quota-scopes +Name: best-effort +Namespace: quota-scopes +Scopes: BestEffort + * Matches all pods that have best effort quality of service. +Resource Used Hard +-------- ---- ---- +pods 0 10 + + +Name: not-best-effort +Namespace: quota-scopes +Scopes: NotBestEffort + * Matches all pods that do not have best effort quality of service. +Resource Used Hard +-------- ---- ---- +limits.cpu 0 2 +limits.memory 0 2Gi +pods 0 4 +requests.cpu 0 1 +requests.memory 0 1Gi +``` + + +在这种场景下,一个没有配置计算资源请求的 pod 将会被 `best-effort` 配额跟踪。 + + +而配置了计算资源请求的则会被 `not-best-effort` 配额追踪。 + + +让我们创建两个 deployments 作为演示: + +```shell +$ kubectl run best-effort-nginx --image=nginx --replicas=8 --namespace=quota-scopes +deployment "best-effort-nginx" created +$ kubectl run not-best-effort-nginx \ + --image=nginx \ + --replicas=2 \ + --requests=cpu=100m,memory=256Mi \ + --limits=cpu=200m,memory=512Mi \ + --namespace=quota-scopes +deployment "not-best-effort-nginx" created +``` + + +虽然没有指定默认的 limits,`best-effort-nginx` deployment 还是会创建 8 个 pods。这是由于它被 `best-effort` 配额追踪,而 `not-best-effort` 配额将忽略它。`not-best-effort` 配额将追踪 `not-best-effort-nginx` deployment,因为它创建的 pods 具有 `Burstable` 服务质量。 + + +让我们列出 namespace 中的 pods: + +```shell +$ kubectl get pods --namespace=quota-scopes +NAME READY STATUS RESTARTS AGE +best-effort-nginx-3488455095-2qb41 1/1 Running 0 51s +best-effort-nginx-3488455095-3go7n 1/1 Running 0 51s +best-effort-nginx-3488455095-9o2xg 1/1 Running 0 51s +best-effort-nginx-3488455095-eyg40 1/1 Running 0 51s +best-effort-nginx-3488455095-gcs3v 1/1 Running 0 51s +best-effort-nginx-3488455095-rq8p1 1/1 Running 0 51s +best-effort-nginx-3488455095-udhhd 1/1 Running 0 51s +best-effort-nginx-3488455095-zmk12 1/1 Running 0 51s +not-best-effort-nginx-2204666826-7sl61 1/1 Running 0 23s +not-best-effort-nginx-2204666826-ke746 1/1 Running 0 23s +``` + + +如你看到的,所有 10 个 pods 都已经被准许创建。 + + +让我们 describe 这个 namespace 当前的配额使用情况: + +```shell +$ kubectl describe quota --namespace=quota-scopes +Name: best-effort +Namespace: quota-scopes +Scopes: BestEffort + * Matches all pods that have best effort quality of service. +Resource Used Hard +-------- ---- ---- +pods 8 10 + + +Name: not-best-effort +Namespace: quota-scopes +Scopes: NotBestEffort + * Matches all pods that do not have best effort quality of service. +Resource Used Hard +-------- ---- ---- +limits.cpu 400m 2 +limits.memory 1Gi 2Gi +pods 2 4 +requests.cpu 200m 1 +requests.memory 512Mi 1Gi +``` + + +如你看到的,`best-effort` 配额追踪了我们在 `best-effort-nginx` deployment 中创建的 8 个 pods 的资源用量,而 `not-best-effort` 配额追踪了我们在 `not-best-effort-nginx` deployment 中创的两个 pods 的用量。 + + +Scopes 提供了一种来对任何配额文档追踪的资源集合进行细分的机制,给操作人员部署和追踪资源消耗带来更大的灵活性。 + + +除 `BestEffort` 和 `NotBestEffort` scopes 之外,还有用于限制长时间运行和有时限 pods 的scopes。`Terminating` scope 将匹配任何 `spec.activeDeadlineSeconds` 不为 `nil` 的 pod。`NotTerminating` scope 将匹配任何 `spec.activeDeadlineSeconds` 为 `nil` 的 pod。这些 scopes 允许你基于 pods 在你集群中 node 上的预期持久程度来为它们指定配额。 + +{% endcapture %} + +{% capture discussion %} + +## 总结 + + +消耗节点 cpu 和 memory 资源的动作受到 namespace 配额定义的硬性配额限制的管制。 + + +任意消耗那些资源的动作能够被调整,或者获得一个 namespace 级别的默认值以符合你最终的目标。 + + +可以基于服务质量或者在你集群中节点上的预期持久程度来分配配额。 + +{% endcapture %} + +{% include templates/task.md %} diff --git a/cn/docs/tasks/administer-cluster/change-default-storage-class.md b/cn/docs/tasks/administer-cluster/change-default-storage-class.md new file mode 100644 index 0000000000..b1ba51a064 --- /dev/null +++ b/cn/docs/tasks/administer-cluster/change-default-storage-class.md @@ -0,0 +1,94 @@ +--- + +title: 改变默认 StorageClass +--- + +{% capture overview %} + +本文展示了如何改变默认的 Storage Class,它用于为没有特殊需求的 PersistentVolumeClaims 配置 volumes。 + +{% endcapture %} + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + +{% capture steps %} + + +## 为什么要改变默认 storage class? + + +取决于安装模式,您的 Kubernetes 集群可能和一个被标记为默认的已有 StorageClass 一起部署。这个默认的 StorageClass 以后将被用于动态的为没有特定 storage class 需求的 PersistentVolumeClaims 配置存储。更多细节请查看 [PersistentVolumeClaim 文档](/docs/user-guide/persistent-volumes/#class-1)。 + + +预先安装的默认 StorageClass 可能不能很好的适应您期望的工作负载;例如,它配置的存储可能太过昂贵。如果是这样的话,您可以改变默认 StorageClass,或者完全禁用它以防止动态配置存储。 + + +简单的删除默认 StorageClass 可能行不通,因为它可能会被您集群中的扩展管理器自动重建。请查阅您的安装文档中关于扩展管理器的细节,以及如何禁用单个扩展。 + + +## 改变默认 StorageClass + + +1. 列出您集群中的 StorageClasses: + + kubectl get storageclass + + + 输出类似这样: + + NAME TYPE + standard (default) kubernetes.io/gce-pd + gold kubernetes.io/gce-pd + + + 默认 StorageClass 以 `(default)` 标记。 + + +2. 标记默认 StorageClass 非默认: + + + 默认 StorageClass 的注解 `storageclass.kubernetes.io/is-default-class` 设置为 `true`。注解的其它任意值或者缺省值将被解释为 `false`。 + + + 要标记一个 StorageClass 为非默认的,您需要改变它的值为 `false`: + + kubectl patch storageclass -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' + + + 这里的 `` 是您选择的 StorageClass 的名字。 + + +3. 标记一个 StorageClass 为默认的: + + + 和前面的步骤类似,您需要添加/设置注解 `storageclass.kubernetes.io/is-default-class=true`。 + + kubectl patch storageclass -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' + + + 请注意,最多只能有一个 StorageClass 能够被标记为默认。如果它们中有两个或多个被标记为默认,Kubernetes 将忽略这个注解,也就是它将表现为没有默认 StorageClass。 + + +4. 验证您选用的 StorageClass 为默认的: + + kubectl get storageclass + + + 输出类似这样: + + NAME TYPE + standard kubernetes.io/gce-pd + gold (default) kubernetes.io/gce-pd + +{% endcapture %} + +{% capture whatsnext %} + +* 了解更多关于 [StorageClasses](/docs/concepts/storage/persistent-volumes/)。 + {% endcapture %} + +{% include templates/task.md %} diff --git a/cn/docs/tasks/administer-cluster/change-pv-reclaim-policy.md b/cn/docs/tasks/administer-cluster/change-pv-reclaim-policy.md new file mode 100644 index 0000000000..14844d903e --- /dev/null +++ b/cn/docs/tasks/administer-cluster/change-pv-reclaim-policy.md @@ -0,0 +1,80 @@ +--- +title: 更改 PersistentVolume 的回收策略 +--- + + +{% capture overview %} + +本文展示了如何更改 Kubernetes PersistentVolume 的回收策略。 +{% endcapture %} + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + +{% capture steps %} + + +## 为什么要更改 PersistentVolume 的回收策略 + + +`PersistentVolumes` 可以有多种回收策略,包括 "Retain"、"Recycle" 和 "Delete"。对于动态配置的 `PersistentVolumes` 来说,默认回收策略为 "Delete"。这表示当用户删除对应的 `PeristentVolumeClaim` 时,动态配置的 volume 将被自动删除。如果 volume 包含重要数据时,这种自动行为可能是不合适的。那种情况下,更适合使用 "Retain" 策略。使用 "Retain" 时,如果用户删除 `PersistentVolumeClaim`,对应的 `PersistentVolume` 不会被删除。相反,它将变为 `Released` 状态,表示所有的数据可以被手动恢复。 + + +## 更改 PersistentVolume 的回收策略 + + +1. 列出你集群中的 PersistentVolumes + + kubectl get pv + + 输出类似于这样: + + NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE + pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim1 10s + pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim2 6s + pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim3 3s + + + 这个列表同样包含了绑定到每个 volume 的 claims 名称,以便更容易的识别动态配置的 volumes。 + + +2. 选择你的 PersistentVolumes 中的一个并更改它的回收策略: + + kubectl patch pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' + + 这里的 `` 是你选择的 PersistentVolume 的名字。 + +3. 验证你选择的 PersistentVolume 拥有正确的策略: + + kubectl get pv + + 输出类似于这样: + + NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE + pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim1 40s + pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim2 36s + pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Retain Bound default/claim3 33s + + + 在前面的输出中,你可以看到绑定到 claim `default/claim3` 的 volume 拥有的回收策略为 `Retain`。当用户删除 claim `default/claim3` 时,它不会被自动删除。 + +{% endcapture %} + +{% capture whatsnext %} + +* 了解更多关于 [PersistentVolumes](/docs/concepts/storage/persistent-volumes/)的信息。 +* 了解更多关于 [PersistentVolumeClaims](/docs/user-guide/persistent-volumes/#persistentvolumeclaims) 的信息。 + + +### 参考 + +* [PersistentVolume](/docs/api-reference/{{page.version}}/#persistentvolume-v1-core) +* [PersistentVolumeClaim](/docs/api-reference/{{page.version}}/#persistentvolumeclaim-v1-core) + +* 查阅 [PersistentVolumeSpec](/docs/api-reference/{{page.version}}/#persistentvolumeclaim-v1-core) 的 `persistentVolumeReclaimPolicy` 字段。 +{% endcapture %} + +{% include templates/task.md %} diff --git a/cn/docs/tasks/administer-cluster/cluster-management.md b/cn/docs/tasks/administer-cluster/cluster-management.md new file mode 100644 index 0000000000..f492a2314d --- /dev/null +++ b/cn/docs/tasks/administer-cluster/cluster-management.md @@ -0,0 +1,227 @@ +--- +approvers: +- lavalamp +- thockin +title: 集群管理 +--- + + +* TOC +{:toc} + + +本文描述了和集群生命周期相关的几个主题:创建新集群、更新集群的 master 和 worker 节点、执行节点维护(例如升级内核)以及升级运行中集群的 Kubernetes API 版本。 + + +## 创建和配置集群 + + +要在一组机器上安装 Kubernetes, 请根据您的环境,查阅现有的 [入门指南](/docs/getting-started-guides/) + + +## 升级集群 + + +集群升级当前是配套提供的,某些发布版本在升级时可能需要特殊处理。推荐管理员在升级他们的集群前,同时查阅 [发行说明](https://git.k8s.io/kubernetes/CHANGELOG.md) 和版本具体升级说明。 + + +* [升级到 1.6](/docs/admin/upgrade-1-6) + + +### 升级 Google Compute Engine 集群 + + +Google Compute Engine Open Source (GCE-OSS) 通过删除和重建 master 来支持 master 升级。通过维持相同的 Persistent Disk (PD) 以保证在升级过程中保留数据。 + + +GCE 的 Node 升级采用 [管理实例组](https://cloud.google.com/compute/docs/instance-groups/),每个节点将被顺序的删除,然后使用新软件重建。任何运行在那个节点上的 Pod 需要用 Replication Controller 控制,或者在扩容之后手动重建。 + + +开源 Google Compute Engine (GCE) 集群上的升级过程由 `cluster/gce/upgrade.sh` 脚本控制。 + + +运行 `cluster/gce/upgrade.sh -h` 获取使用说明。 + + +例如,只将 master 升级到一个指定的版本 (v1.0.2): + +```shell +cluster/gce/upgrade.sh -M v1.0.2 +``` + + +或者,将整个集群升级到最新的稳定版本: + +```shell +cluster/gce/upgrade.sh release/stable +``` + + +### 升级 Google Container Engine (GKE) 集群 + + +Google Container Engine 自动升级 master 组件(例如 `kube-apiserver`、`kube-scheduler`)至最新版本。它还负责 master 运行的操作系统和其它组件。 + + +节点升级过程由用户初始化,[GKE 文档](https://cloud.google.com/container-engine/docs/clusters/upgrade) 里有相关描述。 + + +### 在其他平台上升级集群 + + +不同的供应商和工具管理升级的过程各不相同。建议您查阅它们有关升级的主要文档。 + +* [kops](https://github.com/kubernetes/kops) +* [kubespray](https://github.com/kubernetes-incubator/kubespray) +* [CoreOS Tectonic](https://coreos.com/tectonic/docs/latest/admin/upgrade.html) +* ... + + +## 调整集群大小 + + +如果集群资源短缺,您可以轻松的添加更多的机器,如果集群正运行在[节点自注册模式](/docs/admin/node/#self-registration-of-nodes)下的话。如果正在使用的是 GCE 或者 GKE,这将通过调整管理节点的实例组的大小完成。在 [Google Cloud Console page](https://console.developers.google.com) 的 `Compute > Compute Engine > Instance groups > your group > Edit group` 下修改实例数量或使用 gcloud CLI 都可以完成这个任务。 + +```shell +gcloud compute instance-groups managed resize kubernetes-minion-group --size 42 --zone $ZONE +``` + + +实例组将负责在新机器上放置恰当的镜像并启动它们。Kubelet 将向 API server 注册它的节点以使其可以用于调度。如果您对 instance group 进行缩容,系统将会随机选取节点来终止。 + + +在其他环境上,您可能需要手动配置机器并告诉 Kubelet API server 在哪台机器上运行。 + + +### 集群自动伸缩 + + +如果正在使用 GCE 或者 GKE,您可以配置您的集群,使其能够基于 pod 需求自动重新调整大小。 + + +如 [Compute Resource](/docs/concepts/configuration/manage-compute-resources-container/) 所述,用户可以控制预留多少 CPU 和内存来分配给 pod。这个信息被 Kubernetes scheduler 用来寻找一个运行 pod 的地方。如果没有一个节点有足够的空闲容量(或者不能满足其他 pod 的需求),这个 pod 就需要等待某些 pod 结束,或者一个新的节点被添加。 + + +集群 autoscaler 查找不能被调度的 pod 并检查添加一个新节点(和集群中其它节点类似的)是否有帮助。如果是的话,它将调整集群的大小以容纳等待调度的 pod。 + + +如果发现在一段延时时间内(默认10分钟,将来有可能改变)某些节点不再需要,集群 autoscaler 也会缩小集群。 + + +集群 autoscaler 在每一个实例组(GCE)或节点池(GKE)上配置。 + + +如果您使用 GCE,那么您可以在使用 kube-up.sh 脚本创建集群的时候启用它。要想配置集群 autoscaler,您需要设置三个环境变量: + + +* `KUBE_ENABLE_CLUSTER_AUTOSCALER` - 如果设置为 true 将启用集群 autoscaler。 +* `KUBE_AUTOSCALER_MIN_NODES` - 集群的最小节点数量。 +* `KUBE_AUTOSCALER_MAX_NODES` - 集群的最大节点数量。 + + +示例: + +```shell +KUBE_ENABLE_CLUSTER_AUTOSCALER=true KUBE_AUTOSCALER_MIN_NODES=3 KUBE_AUTOSCALER_MAX_NODES=10 NUM_NODES=5 ./cluster/kube-up.sh +``` + + +在 GKE 上,您可以在创建、更新集群或创建一个特别的节点池(您希望自动伸缩的)时,通过给对应的 `gcloud` 命令传递 `--enable-autoscaling` `--min-nodes` 和 `--max-nodes` 来配置集群 autoscaler。 + + +示例: + +```shell +gcloud container clusters create mytestcluster --zone=us-central1-b --enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5 +``` + +```shell +gcloud container clusters update mytestcluster --enable-autoscaling --min-nodes=1 --max-nodes=15 +``` + + +**集群 autoscaler 期望节点未被手动修改过(例如通过 kubectl 添加标签),因为那些属性可能不能被传递到相同节点组中的新节点上。** + + +## 维护节点 + + +如果需要重启节点(例如内核升级、libc 升级、硬件维修等),且停机时间很短时,当 Kubelet 重启后,它将尝试重启调度到节点上的 pod。如果重启花费较长时间(默认时间为 5 分钟,由 controller-manager 的 `--pod-eviction-timeout` 控制),节点控制器将会结束绑定到这个不可用节点上的 pod。如果存在对应的 replica set(或者 replication controller)时,则将在另一个节点上启动 pod 的新副本。所以,如果所有的 pod 都是复制而来,那么在不是所有节点都同时停机的前提下,升级可以在不需要特殊调整情况下完成。 + + +如果您希望更多的控制升级过程,可以使用下面的工作流程: + + +使用 `kubectl drain` 优雅的结束节点上的所有 pod 并同时标记节点为不可调度: + +```shell +kubectl drain $NODENAME +``` + + +在您正试图使节点离线时,这将阻止新的 pod 落到它们上面。 + + +对于有 replica set 的 pod 来说,它们将会被新的 pod 替换并且将被调度到一个新的节点。此外,如果 pod 是一个 service 的一部分,则客户端将被自动重定向到新的 pod。 + + +对于没有 replica set 的 pod,您需要手动启动 pod 的新副本,并且如果它不是 service 的一部分,您需要手动将客户端重定向到这个 pod。 + + +在节点上执行维护工作。 + + +重新使节点可调度: + +```shell +kubectl uncordon $NODENAME +``` + + +如果删除了节点的虚拟机实例并重新创建,那么一个新的可调度节点资源将被自动创建(只在您使用支持节点发现的云服务提供商时;当前只有 Google Compute Engine,不包括在 Google Compute Engine 上使用 kube-register 的 CoreOS)。相关详细信息,请查阅 [节点](/docs/admin/node)。 + + +## 高级主题 + + +### 升级到不同的 API 版本 + + +当新的 API 版本发布时,您可能需要升级集群支持新的 API 版本(例如当 'v2' 发布时从 'v1' 切换到 'v2')。 + + +这不是一个经常性的事件,但需要谨慎的处理。这里有一系列升级到新 API 版本的步骤。 + + 1. 开启新 API 版本。 + 2. 升级集群存储来使用新版本。 + 3. 升级所有配置文件。识别使用旧 API 版本 endpoint 的用户。 + 4. 运行 `cluster/update-storage-objects.sh` 升级存储中的现有对象为新版本。 + 5. 关闭旧 API 版本。 + + +### 打开或关闭集群的 API 版本 + + +可以在启动 API server 时传递 `--runtime-config=api/` 标志来打开或关闭特定的 API 版本。例如:要关闭 v1 API,请传递 `--runtime-config=api/v1=false`。运行时配置还支持两个特殊键值:api/all 和 api/legacy,分别控制全部和遗留 API。例如要关闭除 v1 外全部 API 版本,请传递 `--runtime-config=api/all=false,api/v1=true`。对于这些标志来说,_legacy_ API 指那些被显式废弃的 API(例如 `v1beta3`)。 + + +### 切换集群存储的 API 版本 + + +存储于磁盘中,用于在集群内部代表 Kubernetes 活跃资源的对象使用特定的 API 版本书写。当支撑的 API 改变时,这些对象可能需要使用更新的 API 重写。重写失败将最终导致资源不再能够被 Kubernetes API server 解析或使用。 + + +`kube-apiserver` 二进制文件的 `KUBE_API_VERSIONS` 环境变量控制了集群支持的 API 版本。列表中的第一个版本被用作集群的存储版本。因此,要设置特定的版本为存储版本,请将其放在 `KUBE_API_VERSIONS` 参数值版本列表的最前面。您需要重启 `kube-apiserver` 二进制以使这个变量的改动生效。 + + +### 切换配置文件为新 API 版本 + + +可以使用 `kubectl convert` 命令对不同 API 版本的配置文件进行转换。 + +```shell +kubectl convert -f pod.yaml --output-version v1 +``` + + +更多选项请参考 [kubectl convert](/docs/user-guide/kubectl/v1.6/#convert) 命令用法。 From eac3d83e94643d317cbcb631954fb1244b49fb3b Mon Sep 17 00:00:00 2001 From: Jesse Kinkead Date: Sat, 9 Sep 2017 09:48:50 -0700 Subject: [PATCH 30/58] Complete documentation of SSL-on-AWS. (#5357) The SSL-on-AWS documentation was missing a critical annotation, without which SSL termination doesn't work (all ports are configured to use SSL). This also fixes the indentation of the existing YAML. --- docs/concepts/services-networking/service.md | 54 ++++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/docs/concepts/services-networking/service.md b/docs/concepts/services-networking/service.md index c566b42047..1d348bd60c 100644 --- a/docs/concepts/services-networking/service.md +++ b/docs/concepts/services-networking/service.md @@ -479,25 +479,25 @@ metadata: {% include tabs.md %} #### SSL support on AWS -For partial SSL support on clusters running on AWS, starting with 1.3 two +For partial SSL support on clusters running on AWS, starting with 1.3 three annotations can be added to a `LoadBalancer` service: ``` - metadata: - name: my-service - annotations: - service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 +metadata: + name: my-service + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 ``` -The first specifies which certificate to use. It can be either a +The first specifies the ARN of the certificate to use. It can be either a certificate from a third party issuer that was uploaded to IAM or one created within AWS Certificate Manager. ```yaml - metadata: - name: my-service - annotations: - service.beta.kubernetes.io/aws-load-balancer-backend-protocol: (https|http|ssl|tcp) +metadata: + name: my-service + annotations: + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: (https|http|ssl|tcp) ``` The second annotation specifies which protocol a pod speaks. For HTTPS and @@ -512,6 +512,40 @@ ELB at the other end of its connection) when forwarding requests. TCP and SSL will select layer 4 proxying: the ELB will forward traffic without modifying the headers. +```yaml +metadata: + name: my-service + annotations: + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: (comma-separated-port-names) +``` + +The third annotation indicates which port(s) should accept SSL traffic on the ELB. If a certificate is set on the +Service, the default is to configure all ports on the ELB to use SSL. This is not typically desired for HTTP servers. + +A complete HTTP Service supporting SSL might look like: + +```yaml +kind: Service +apiVersion: v1 +metadata: + name: my-service + annotations: + service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http + service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 + service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https" +spec: + type: LoadBalancer + ports: + - port: 80 + name: http + targetPort: 8080 + - port: 443 + name: https + targetPort: 8080 + selector: + app: MyApp +``` + ### External IPs If there are external IPs that route to one or more cluster nodes, Kubernetes services can be exposed on those From 7f83f2be59ec78280d962eb4881ee2d63f89506d Mon Sep 17 00:00:00 2001 From: Tony-CCIE <1278146756@qq.com> Date: Sun, 10 Sep 2017 00:50:45 +0800 Subject: [PATCH 31/58] k8smeetup-admin-ovs-networking-pr-2017-07-15 (#5356) * admin-ovs-networking-pr-2017-07-15 * Update ovs-networking.md --- cn/docs/admin/ovs-networking.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 cn/docs/admin/ovs-networking.md diff --git a/cn/docs/admin/ovs-networking.md b/cn/docs/admin/ovs-networking.md new file mode 100644 index 0000000000..7153f2a7b1 --- /dev/null +++ b/cn/docs/admin/ovs-networking.md @@ -0,0 +1,22 @@ +--- +assignees: +- thockin +title: Kubernetes OpenVSwitch GRE/VxLAN 网络 +--- + +本文档介绍了如何使用OpenVSwitch,在跨nodes的pods之间设置网络。 +隧道类型可以是GRE或者是VxLAN。如需在网络内执行大规模隔离时,最好使用VxLAN。 + +![OVS Networking](/images/docs/ovs-networking.png) + +Kubernetes中Vagrant的设置如下: + +docker网桥被brctl生成的Linux网桥(kbr0)所代替,kbr0是具有256个地址空间的子网。总的来说,node会得到10.244.x.0/24的子网,docker上配置使用的网桥会代替默认docker0的网桥。 + +另外,OVS网桥创建(obr0),并将其作为端口添加到kbr0的网桥中。所有OVS网桥通过GRE隧道连接所有的nodes。因此,每个node都有一个到其他nodes的出站GRE隧道。这个隧道没有必要是一个完整的网状物,但是越像网状结构越好。在网桥上开启STP(生成树)模式以防止环路的发生。 + +路由规则允许任何10.244.0.0/16通过与隧道相连的OVS网桥到达目标。 + + + + From 4a55e281661a29c2bb37401141c47b349587087d Mon Sep 17 00:00:00 2001 From: Sylvain WITMEYER Date: Sat, 9 Sep 2017 22:41:45 -0400 Subject: [PATCH 32/58] Label can't have whitespaces (#4086) My nvidia GPU name was "GeForce GTX 1070" which isn't a correct label "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character" --- docs/tasks/manage-gpus/scheduling-gpus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/manage-gpus/scheduling-gpus.md b/docs/tasks/manage-gpus/scheduling-gpus.md index 8981bc5a31..fa701e4cfa 100644 --- a/docs/tasks/manage-gpus/scheduling-gpus.md +++ b/docs/tasks/manage-gpus/scheduling-gpus.md @@ -60,7 +60,7 @@ Following is an illustration of this workflow: As part of your Node bootstrapping, identify the GPU hardware type on your nodes and expose it as a node label. ```shell -NVIDIA_GPU_NAME=$(nvidia-smi --query-gpu=gpu_name --format=csv,noheader --id=0) +NVIDIA_GPU_NAME=$(nvidia-smi --query-gpu=gpu_name --format=csv,noheader --id=0 | sed -e 's/ /-/g') source /etc/default/kubelet KUBELET_OPTS="$KUBELET_OPTS --node-labels='alpha.kubernetes.io/nvidia-gpu-name=$NVIDIA_GPU_NAME'" echo "KUBELET_OPTS=$KUBELET_OPTS" > /etc/default/kubelet From 3e49e008ccec4c0ae144b9ae456e7edba4ad0d0c Mon Sep 17 00:00:00 2001 From: Stewart-YU Date: Sun, 10 Sep 2017 18:07:38 +0800 Subject: [PATCH 33/58] Update bare_metal_offline.md Fix format. --- .../coreos/bare_metal_offline.md | 186 ++++++++---------- 1 file changed, 83 insertions(+), 103 deletions(-) diff --git a/docs/getting-started-guides/coreos/bare_metal_offline.md b/docs/getting-started-guides/coreos/bare_metal_offline.md index a471d2db8d..0dec61168f 100644 --- a/docs/getting-started-guides/coreos/bare_metal_offline.md +++ b/docs/getting-started-guides/coreos/bare_metal_offline.md @@ -42,154 +42,134 @@ To setup CentOS PXELINUX environment there is a complete [guide here](http://doc 1. Install packages needed on CentOS -```shell -sudo yum install tftp-server dhcp syslinux -``` + sudo yum install tftp-server dhcp syslinux 2. `vi /etc/xinetd.d/tftp` to enable tftp service and change disable to 'no' -```conf -disable = no -``` + go get github.com/vmware/photon-controller-cli/photon 3. Copy over the syslinux images we will need. -```shell -su - -mkdir -p /tftpboot -cd /tftpboot -cp /usr/share/syslinux/pxelinux.0 /tftpboot -cp /usr/share/syslinux/menu.c32 /tftpboot -cp /usr/share/syslinux/memdisk /tftpboot -cp /usr/share/syslinux/mboot.c32 /tftpboot -cp /usr/share/syslinux/chain.c32 /tftpboot + su - + mkdir -p /tftpboot + cd /tftpboot + cp /usr/share/syslinux/pxelinux.0 /tftpboot + cp /usr/share/syslinux/menu.c32 /tftpboot + cp /usr/share/syslinux/memdisk /tftpboot + cp /usr/share/syslinux/mboot.c32 /tftpboot + cp /usr/share/syslinux/chain.c32 /tftpboot -/sbin/service dhcpd start -/sbin/service xinetd start -/sbin/chkconfig tftp on -``` + /sbin/service dhcpd start + /sbin/service xinetd start + /sbin/chkconfig tftp on 4. Setup default boot menu -```shell -mkdir /tftpboot/pxelinux.cfg -touch /tftpboot/pxelinux.cfg/default -``` + mkdir /tftpboot/pxelinux.cfg + touch /tftpboot/pxelinux.cfg/default 5. Edit the menu `vi /tftpboot/pxelinux.cfg/default` -```conf -default menu.c32 -prompt 0 -timeout 15 -ONTIMEOUT local -display boot.msg + default menu.c32 + prompt 0 + timeout 15 + ONTIMEOUT local + display boot.msg -MENU TITLE Main Menu + MENU TITLE Main Menu -LABEL local - MENU LABEL Boot local hard drive - LOCALBOOT 0 -``` + LABEL local + MENU LABEL Boot local hard drive + LOCALBOOT 0 Now you should have a working PXELINUX setup to image CoreOS nodes. You can verify the services by using VirtualBox locally or with bare metal servers. ## Adding CoreOS to PXE This section describes how to setup the CoreOS images to live alongside a pre-existing PXELINUX environment. - 1. Find or create the TFTP root directory that everything will be based on. - * For this document we will assume `/tftpboot/` is our root directory. -2. Once we know and have our tftp root directory we will create a new directory structure for our CoreOS images. + - For this document we will assume `/tftpboot/` is our root directory. +2. Once we know and have our tftp root directory we will create a new directory structure for our CoreOS images. 3. Download the CoreOS PXE files provided by the CoreOS team. -```shell -MY_TFTPROOT_DIR=/tftpboot -mkdir -p $MY_TFTPROOT_DIR/images/coreos/ -cd $MY_TFTPROOT_DIR/images/coreos/ -wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz -wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz.sig -wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz -wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz.sig -gpg --verify coreos_production_pxe.vmlinuz.sig -gpg --verify coreos_production_pxe_image.cpio.gz.sig -``` + MY_TFTPROOT_DIR=/tftpboot + mkdir -p $MY_TFTPROOT_DIR/images/coreos/ + cd $MY_TFTPROOT_DIR/images/coreos/ + wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz + wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz.sig + wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz + wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz.sig + gpg --verify coreos_production_pxe.vmlinuz.sig + gpg --verify coreos_production_pxe_image.cpio.gz.sig 4. Edit the menu `vi /tftpboot/pxelinux.cfg/default` again -```conf -default menu.c32 -prompt 0 -timeout 300 -ONTIMEOUT local -display boot.msg + default menu.c32 + prompt 0 + timeout 300 + ONTIMEOUT local + display boot.msg -MENU TITLE Main Menu + MENU TITLE Main Menu -LABEL local - MENU LABEL Boot local hard drive - LOCALBOOT 0 + LABEL local + MENU LABEL Boot local hard drive + LOCALBOOT 0 -MENU BEGIN CoreOS Menu + MENU BEGIN CoreOS Menu - LABEL coreos-master - MENU LABEL CoreOS Master - KERNEL images/coreos/coreos_production_pxe.vmlinuz - APPEND initrd=images/coreos/coreos_production_pxe_image.cpio.gz cloud-config-url=http:///pxe-cloud-config-single-master.yml + LABEL coreos-master + MENU LABEL CoreOS Master + KERNEL images/coreos/coreos_production_pxe.vmlinuz + APPEND initrd=images/coreos/coreos_production_pxe_image.cpio.gz cloud-config-url=http:///pxe-cloud-config-single-master.yml - LABEL coreos-slave - MENU LABEL CoreOS Slave - KERNEL images/coreos/coreos_production_pxe.vmlinuz - APPEND initrd=images/coreos/coreos_production_pxe_image.cpio.gz cloud-config-url=http:///pxe-cloud-config-slave.yml -MENU END -``` + LABEL coreos-slave + MENU LABEL CoreOS Slave + KERNEL images/coreos/coreos_production_pxe.vmlinuz + APPEND initrd=images/coreos/coreos_production_pxe_image.cpio.gz cloud-config-url=http:///pxe-cloud-config-slave.yml + MENU END This configuration file will now boot from local drive but have the option to PXE image CoreOS. ## DHCP configuration This section covers configuring the DHCP server to hand out our new images. In this case we are assuming that there are other servers that will boot alongside other images. - 1. Add the `filename` to the _host_ or _subnet_ sections. -```conf -filename "/tftpboot/pxelinux.0"; -``` + filename "/tftpboot/pxelinux.0"; 2. At this point we want to make pxelinux configuration files that will be the templates for the different CoreOS deployments. -```conf -subnet 10.20.30.0 netmask 255.255.255.0 { - next-server 10.20.30.242; - option broadcast-address 10.20.30.255; - filename ""; + subnet 10.20.30.0 netmask 255.255.255.0 { + next-server 10.20.30.242; + option broadcast-address 10.20.30.255; + filename ""; - ... - # http://www.syslinux.org/wiki/index.php/PXELINUX - host core_os_master { - hardware ethernet d0:00:67:13:0d:00; - option routers 10.20.30.1; - fixed-address 10.20.30.40; - option domain-name-servers 10.20.30.242; - filename "/pxelinux.0"; + ... + # http://www.syslinux.org/wiki/index.php/PXELINUX + host core_os_master { + hardware ethernet d0:00:67:13:0d:00; + option routers 10.20.30.1; + fixed-address 10.20.30.40; + option domain-name-servers 10.20.30.242; + filename "/pxelinux.0"; + } + host core_os_slave { + hardware ethernet d0:00:67:13:0d:01; + option routers 10.20.30.1; + fixed-address 10.20.30.41; + option domain-name-servers 10.20.30.242; + filename "/pxelinux.0"; + } + host core_os_slave2 { + hardware ethernet d0:00:67:13:0d:02; + option routers 10.20.30.1; + fixed-address 10.20.30.42; + option domain-name-servers 10.20.30.242; + filename "/pxelinux.0"; + } + ... } - host core_os_slave { - hardware ethernet d0:00:67:13:0d:01; - option routers 10.20.30.1; - fixed-address 10.20.30.41; - option domain-name-servers 10.20.30.242; - filename "/pxelinux.0"; - } - host core_os_slave2 { - hardware ethernet d0:00:67:13:0d:02; - option routers 10.20.30.1; - fixed-address 10.20.30.42; - option domain-name-servers 10.20.30.242; - filename "/pxelinux.0"; - } - ... -} -``` We will be specifying the node configuration later in the guide. From e96a9f992cbe0beedc518cbc1a03d4150beaddf1 Mon Sep 17 00:00:00 2001 From: Abdullah Al Maruf - Tuhin Date: Mon, 11 Sep 2017 03:38:49 +0600 Subject: [PATCH 34/58] Fix Typos --- docs/admin/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/authentication.md b/docs/admin/authentication.md index 4a2fb19195..b0f4467527 100644 --- a/docs/admin/authentication.md +++ b/docs/admin/authentication.md @@ -549,7 +549,7 @@ checked. Keystone authentication is enabled by passing the `--experimental-keystone-url=` option to the API server during startup. The plugin is implemented in `plugin/pkg/auth/authenticator/password/keystone/keystone.go` and currently uses -basic auth to verify used by username and password. +basic auth to verify user by username and password. If you have configured self-signed certificates for the Keystone server, you may need to set the `--experimental-keystone-ca-file=SOMEFILE` option when From 94d9e2759717bd2073e6cea0b19aa9acd761bfb5 Mon Sep 17 00:00:00 2001 From: Stewart-YU Date: Mon, 11 Sep 2017 07:59:24 +0800 Subject: [PATCH 35/58] Update bare_metal_offline.md Fix copy error. --- docs/getting-started-guides/coreos/bare_metal_offline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started-guides/coreos/bare_metal_offline.md b/docs/getting-started-guides/coreos/bare_metal_offline.md index 0dec61168f..c7684f73b2 100644 --- a/docs/getting-started-guides/coreos/bare_metal_offline.md +++ b/docs/getting-started-guides/coreos/bare_metal_offline.md @@ -46,7 +46,7 @@ To setup CentOS PXELINUX environment there is a complete [guide here](http://doc 2. `vi /etc/xinetd.d/tftp` to enable tftp service and change disable to 'no' - go get github.com/vmware/photon-controller-cli/photon + -disable = no 3. Copy over the syslinux images we will need. From f9f9d60c84289127b6b15fafed8d32e21301f996 Mon Sep 17 00:00:00 2001 From: jianglingxia Date: Fri, 8 Sep 2017 14:19:14 +0800 Subject: [PATCH 36/58] run-application-scale-stateful-set-2017-09-08 --- .../run-application/scale-stateful-set.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 cn/docs/tasks/run-application/scale-stateful-set.md diff --git a/cn/docs/tasks/run-application/scale-stateful-set.md b/cn/docs/tasks/run-application/scale-stateful-set.md new file mode 100644 index 0000000000..94c750b25c --- /dev/null +++ b/cn/docs/tasks/run-application/scale-stateful-set.md @@ -0,0 +1,88 @@ +--- +approvers: +- bprashanth +- enisoc +- erictune +- foxish +- janetkuo +- kow3ns +- smarterclayton +title: 伸缩StatefulSet +--- + +{% capture overview %} +本文介绍如何伸缩StatefulSet. +{% endcapture %} + +{% capture prerequisites %} + +* StatefulSets仅适用于Kubernetes1.5版本或高于1.5. +* **不是所有stateful applications都适合伸缩.** 在伸缩前您必须了解您的StatefulSets应用. 如果您不确定, 请记住伸缩该StatefulSets也许不安全. +* 仅当您确定该stateful应用的集群是完全健康才可执行伸缩操作. + +{% endcapture %} + +{% capture steps %} + +## 使用 `kubectl` 伸缩StatefulSets + +伸缩前确保 `kubectl` 已升级至Kubernetes1.5版本或高于1.5. 如果不确定, 执行 `kubectl version` 命令并检查使用的 `Client Version`. + +### `kubectl 伸缩` + +首先, 找到您想要伸缩的StatefulSet. 记住, 您需先清楚是否能伸缩该应用. + +```shell +kubectl get statefulsets +``` + +改变StatefulSet副本数量: + +```shell +kubectl scale statefulsets --replicas= +``` + +### 可使用其他命令: `kubectl apply` / `kubectl edit` / `kubectl patch` + +另外, 您可以 [in-place updates](/docs/concepts/cluster-administration/manage-deployment/#in-place-updates-of-resources) StatefulSets. + +如果您的StatefulSet开始由 `kubectl apply` 或 `kubectl create --save-config`创建, +更新StatefulSet manifests中的 `.spec.replicas`, 然后执行命令 `kubectl apply`: + +```shell +kubectl apply -f +``` + +除此之外, 可以通过命令 `kubectl edit`编辑该字段: + +```shell +kubectl edit statefulsets +``` + +或使用 `kubectl patch`: + +```shell +kubectl patch statefulsets -p '{"spec":{"replicas":}}' +``` + +## 排查故障 + +### 缩容工作不正常 + +当stateful管理下的任何一个Pod不健康时您不能缩容该StatefulSet. 仅当stateful下的所有Pods都处于运行和ready状态后才可缩容. + +当一个StatefulSet的size > 1, 如果有一个不健康的Pod, 没有办法让Kubernetes知道是否是由于永久性故障还是瞬态(升级/维护/节点重启)导致. 如果该Pod不健康是由于永久性 +故障导致, 则在不纠正该故障的情况下进行缩容可能会导致一种状态, 即StatefulSet下的Pod数量低于应正常运行的副本数. 这也许会导致StatefulSet变成不可用. + +如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在这些情况下,最好是在应用级别进行伸缩操作, 并且只有在您确保stateful应用的集群是完全健康时才执行伸缩. + + +{% endcapture %} + +{% capture whatsnext %} + +了解更多 [deleting a StatefulSet](/docs/tasks/manage-stateful-set/deleting-a-statefulset/). + +{% endcapture %} + +{% include templates/task.md %} From f482482d72d390903bf0d89199989a87b9ae25a8 Mon Sep 17 00:00:00 2001 From: jianglingxia Date: Mon, 11 Sep 2017 09:56:49 +0800 Subject: [PATCH 37/58] run-application-scale-stateful-set-pr-2017-09-11 --- .../run-application/scale-stateful-set.md | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cn/docs/tasks/run-application/scale-stateful-set.md b/cn/docs/tasks/run-application/scale-stateful-set.md index 94c750b25c..508b484bef 100644 --- a/cn/docs/tasks/run-application/scale-stateful-set.md +++ b/cn/docs/tasks/run-application/scale-stateful-set.md @@ -7,18 +7,18 @@ approvers: - janetkuo - kow3ns - smarterclayton -title: 伸缩StatefulSet +title: 弹缩StatefulSet --- {% capture overview %} -本文介绍如何伸缩StatefulSet. +本文介绍如何弹缩StatefulSet. {% endcapture %} {% capture prerequisites %} -* StatefulSets仅适用于Kubernetes1.5版本或高于1.5. -* **不是所有stateful applications都适合伸缩.** 在伸缩前您必须了解您的StatefulSets应用. 如果您不确定, 请记住伸缩该StatefulSets也许不安全. -* 仅当您确定该stateful应用的集群是完全健康才可执行伸缩操作. +* StatefulSets仅适用于Kubernetes1.5及以上版本. +* **不是所有Stateful应用都适合弹缩.** 在弹缩前您的应用前. 您必须充分了解您的应用, 不适当的弹缩StatefulSet或许会造成应用自身功能的不稳定. +* 仅当您确定该Stateful应用的集群是完全健康才可执行弹缩操作. {% endcapture %} @@ -26,11 +26,11 @@ title: 伸缩StatefulSet ## 使用 `kubectl` 伸缩StatefulSets -伸缩前确保 `kubectl` 已升级至Kubernetes1.5版本或高于1.5. 如果不确定, 执行 `kubectl version` 命令并检查使用的 `Client Version`. +弹缩请确认 `kubectl` 已经升级到Kubernetes1.5及以上版本. 如果不确定, 执行 `kubectl version` 命令并检查使用的 `Client Version`. -### `kubectl 伸缩` +### `kubectl 弹缩` -首先, 找到您想要伸缩的StatefulSet. 记住, 您需先清楚是否能伸缩该应用. +首先, 找到您想要弹缩的StatefulSet. 记住, 您需先清楚是否能弹缩该应用. ```shell kubectl get statefulsets @@ -53,7 +53,7 @@ kubectl scale statefulsets --replicas= kubectl apply -f ``` -除此之外, 可以通过命令 `kubectl edit`编辑该字段: +除此之外, 可以通过命令 `kubectl edit` 编辑该字段: ```shell kubectl edit statefulsets @@ -69,12 +69,13 @@ kubectl patch statefulsets -p '{"spec":{"replicas": 1, 如果有一个不健康的Pod, 没有办法让Kubernetes知道是否是由于永久性故障还是瞬态(升级/维护/节点重启)导致. 如果该Pod不健康是由于永久性 -故障导致, 则在不纠正该故障的情况下进行缩容可能会导致一种状态, 即StatefulSet下的Pod数量低于应正常运行的副本数. 这也许会导致StatefulSet变成不可用. +当一个StatefulSet的size > 1, 如果有一个Pod不健康, 没有办法让Kubernetes知道是否是由于永久性故障还是瞬态(升级/维护/节点重启)导致. 如果该Pod不健康是由于永久性 +故障导致, 则在不纠正该故障的情况下进行缩容可能会导致一种状态, 即StatefulSet下的Pod数量低于应正常运行的副本数. 这也许会导致StatefulSet不可用. -如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在这些情况下,最好是在应用级别进行伸缩操作, 并且只有在您确保stateful应用的集群是完全健康时才执行伸缩. +如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在 +这些情况下,最好是在应用级别进行弹缩操作, 并且只有在您确保Stateful应用的集群是完全健康时才执行弹缩. {% endcapture %} From c9e835c66e9c62e1fa3f6adce1ce3cdbd27b7e38 Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Mon, 11 Sep 2017 10:33:56 +0800 Subject: [PATCH 38/58] fix typo fix typo --- docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md b/docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md index 23049680ee..a78cc683b5 100644 --- a/docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md +++ b/docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md @@ -42,7 +42,7 @@ You need to have a Kubernetes cluster running version 1.6.x. 2. Restart kubelet. - sudo systemctl restart kubelet + systemctl restart kubelet 3. Delete the `kube-proxy` DaemonSet. @@ -88,7 +88,7 @@ You need to have a Kubernetes cluster running version 1.6.x. 2. Restart kubelet. - sudo systemctl restart kubelet + systemctl restart kubelet {% endcapture %} From 4165c64a8e7dc35063f6dce7031a0a69024e097d Mon Sep 17 00:00:00 2001 From: jianglingxia Date: Mon, 11 Sep 2017 13:44:08 +0800 Subject: [PATCH 39/58] run-application-scale-stateful-set-pr-2017-09-11-13 --- cn/docs/tasks/run-application/scale-stateful-set.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cn/docs/tasks/run-application/scale-stateful-set.md b/cn/docs/tasks/run-application/scale-stateful-set.md index 508b484bef..9262faae2e 100644 --- a/cn/docs/tasks/run-application/scale-stateful-set.md +++ b/cn/docs/tasks/run-application/scale-stateful-set.md @@ -24,7 +24,7 @@ title: 弹缩StatefulSet {% capture steps %} -## 使用 `kubectl` 伸缩StatefulSets +## 使用 `kubectl` 弹缩StatefulSets 弹缩请确认 `kubectl` 已经升级到Kubernetes1.5及以上版本. 如果不确定, 执行 `kubectl version` 命令并检查使用的 `Client Version`. @@ -46,8 +46,7 @@ kubectl scale statefulsets --replicas= 另外, 您可以 [in-place updates](/docs/concepts/cluster-administration/manage-deployment/#in-place-updates-of-resources) StatefulSets. -如果您的StatefulSet开始由 `kubectl apply` 或 `kubectl create --save-config`创建, -更新StatefulSet manifests中的 `.spec.replicas`, 然后执行命令 `kubectl apply`: +如果您的StatefulSet开始由 `kubectl apply` 或 `kubectl create --save-config` 创建,更新StatefulSet manifests中的 `.spec.replicas`, 然后执行命令 `kubectl apply`: ```shell kubectl apply -f @@ -74,7 +73,8 @@ kubectl patch statefulsets -p '{"spec":{"replicas": 1, 如果有一个Pod不健康, 没有办法让Kubernetes知道是否是由于永久性故障还是瞬态(升级/维护/节点重启)导致. 如果该Pod不健康是由于永久性 故障导致, 则在不纠正该故障的情况下进行缩容可能会导致一种状态, 即StatefulSet下的Pod数量低于应正常运行的副本数. 这也许会导致StatefulSet不可用. -如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在 +如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对 +StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在 这些情况下,最好是在应用级别进行弹缩操作, 并且只有在您确保Stateful应用的集群是完全健康时才执行弹缩. From 010449ee60fb2424ae4852b3af1ad4adc01d3ce1 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Mon, 11 Sep 2017 17:54:35 +0200 Subject: [PATCH 40/58] Fix configmaps resource name in rbac.md (#5389) The resource is 'configmaps', not 'configmap'. --- docs/admin/authorization/rbac.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/authorization/rbac.md b/docs/admin/authorization/rbac.md index 5e7ce7de5d..5eae556f61 100644 --- a/docs/admin/authorization/rbac.md +++ b/docs/admin/authorization/rbac.md @@ -181,7 +181,7 @@ metadata: name: configmap-updater rules: - apiGroups: [""] - resources: ["configmap"] + resources: ["configmaps"] resourceNames: ["my-configmap"] verbs: ["update", "get"] ``` From be8ea1e37cbf658c1240c68da45e14da1a8e6fb2 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 11 Sep 2017 23:58:47 +0800 Subject: [PATCH 41/58] Elaborate the scheme field in httpGet (#5386) --- .../configure-liveness-readiness-probes.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/tasks/configure-pod-container/configure-liveness-readiness-probes.md b/docs/tasks/configure-pod-container/configure-liveness-readiness-probes.md index a842c449cd..9ae8da1f1e 100644 --- a/docs/tasks/configure-pod-container/configure-liveness-readiness-probes.md +++ b/docs/tasks/configure-pod-container/configure-liveness-readiness-probes.md @@ -268,7 +268,7 @@ have additional fields that can be set on `httpGet`: * `host`: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. -* `scheme`: Scheme to use for connecting to the host. Defaults to HTTP. +* `scheme`: Scheme to use for connecting to the host (HTTP or HTTPS). Defaults to HTTP. * `path`: Path to access on the HTTP server. * `httpHeaders`: Custom headers to set in the request. HTTP allows repeated headers. * `port`: Name or number of the port to access on the container. Number must be @@ -276,12 +276,13 @@ in the range 1 to 65535. For an HTTP probe, the kubelet sends an HTTP request to the specified path and port to perform the check. The kubelet sends the probe to the container’s IP address, -unless the address is overridden by the optional `host` field in `httpGet`. -In most scenarios, you do not want to set the `host` field. Here's one scenario -where you would set it. Suppose the Container listens on 127.0.0.1 and the Pod's -`hostNetwork` field is true. Then `host`, under `httpGet`, should be set to 127.0.0.1. -If your pod relies on virtual hosts, which is probably the more common case, -you should not use `host`, but rather set the `Host` header in `httpHeaders`. +unless the address is overridden by the optional `host` field in `httpGet`. If +`scheme` field is set to `HTTPS`, the kubelet sends an HTTPS request skipping the +certificate verification. In most scenarios, you do not want to set the `host` field. +Here's one scenario where you would set it. Suppose the Container listens on 127.0.0.1 +and the Pod's `hostNetwork` field is true. Then `host`, under `httpGet`, should be set +to 127.0.0.1. If your pod relies on virtual hosts, which is probably the more common +case, you should not use `host`, but rather set the `Host` header in `httpHeaders`. {% endcapture %} From 51104cb1fc0605d1800a79303a16ddb0b04f0f90 Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Tue, 12 Sep 2017 00:00:38 +0800 Subject: [PATCH 42/58] fix the command output (#5380) fix the command output --- docs/tasks/administer-cluster/namespaces.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/tasks/administer-cluster/namespaces.md b/docs/tasks/administer-cluster/namespaces.md index eee6e75e46..c59da6b890 100644 --- a/docs/tasks/administer-cluster/namespaces.md +++ b/docs/tasks/administer-cluster/namespaces.md @@ -42,9 +42,10 @@ Or you can get detailed information with: ```shell $ kubectl describe namespaces -Name: default -Labels: -Status: Active +Name: default +Labels: +Annotations: +Status: Active No resource quota. From a9208e8a5de8cbdc6050347d6048df226c4ecede Mon Sep 17 00:00:00 2001 From: Kaitlyn Barnard Date: Mon, 11 Sep 2017 19:01:43 +0200 Subject: [PATCH 43/58] Updates to partner page design to add KCSPs (#5336) * Updates to partner page design to add KCSPs * Update index.html * Update partner-style.css * Update partner-script.js * Add files via upload * Update partner-script.js * Add files via upload * Update partner-script.js --- _includes/partner-script.js | 150 ++++++++++++++-------- _includes/partner-style.css | 72 ++++++++++- images/square-logos/accenture.png | Bin 0 -> 13997 bytes images/square-logos/applatix.png | Bin 0 -> 12404 bytes images/square-logos/biarca.png | Bin 0 -> 9809 bytes images/square-logos/bitnami.png | Bin 12870 -> 11503 bytes images/square-logos/boozallenhamilton.png | Bin 0 -> 6717 bytes images/square-logos/claranet.png | Bin 0 -> 10283 bytes images/square-logos/cloudkite.png | Bin 0 -> 9582 bytes images/square-logos/cloudops.png | Bin 0 -> 12656 bytes images/square-logos/contino.png | Bin 0 -> 5877 bytes images/square-logos/ghostcloud.png | Bin 0 -> 9854 bytes images/square-logos/heptio.png | Bin 0 -> 7554 bytes partners/index.html | 19 ++- 14 files changed, 181 insertions(+), 60 deletions(-) create mode 100644 images/square-logos/accenture.png create mode 100644 images/square-logos/applatix.png create mode 100644 images/square-logos/biarca.png create mode 100644 images/square-logos/boozallenhamilton.png create mode 100644 images/square-logos/claranet.png create mode 100644 images/square-logos/cloudkite.png create mode 100644 images/square-logos/cloudops.png create mode 100644 images/square-logos/contino.png create mode 100644 images/square-logos/ghostcloud.png create mode 100644 images/square-logos/heptio.png diff --git a/_includes/partner-script.js b/_includes/partner-script.js index cb991e19d1..c77537e522 100644 --- a/_includes/partner-script.js +++ b/_includes/partner-script.js @@ -1,21 +1,14 @@ ;(function () { var partners = [ { - type: 0, + type: 2, name: 'CoreOS', logo: 'core_os', link: 'https://tectonic.com/', blurb: 'Tectonic is the enterprise-ready Kubernetes product, by CoreOS. It adds key features to allow you to manage, update, and control clusters in production.' }, { - type: 0, - name: 'Deis', - logo: 'deis', - link: 'https://deis.com', - blurb: 'Deis the creators of Helm, Workflow, and Steward, helps developers and operators build, deploy, manage and scale their applications on top of Kubernetes.' - }, - { - type: 0, + type: 2, name: 'StackPointCloud', logo: 'stackpoint', link: 'https://stackpoint.io', @@ -49,13 +42,6 @@ link: 'https://www.cockroachlabs.com/blog/running-cockroachdb-on-kubernetes/', blurb: 'CockroachDB is a distributed SQL database whose built-in replication and survivability model pair with Kubernetes to truly make data easy.' }, - { - type: 0, - name: 'Skippbox', - logo: 'skippbox', - link: 'http://www.skippbox.com/tag/products/', - blurb: 'Creator of Cabin the first mobile application for Kubernetes, and kompose. Skippbox’s solutions distill all the power of k8s in simple easy to use interfaces.' - }, { type: 0, name: 'Weave Works', @@ -134,7 +120,7 @@ blurb: 'Deep, automated security for your containers running on Kubernetes.' }, { - type: 0, + type: 2, name: 'Canonical', logo: 'canonical', link: 'https://jujucharms.com/canonical-kubernetes/', @@ -183,14 +169,14 @@ blurb: 'Aporeto makes cloud-native applications secure by default without impacting developer velocity and works at any scale, on any cloud.' }, { - type: 0, + type: 2, name: 'Giant Swarm', logo: 'giant_swarm', link: 'https://giantswarm.io', blurb: 'Giant Swarm provides fully-managed Kubernetes Clusters in your location of choice, so you can focus on your product.' }, { - type: 0, + type: 2, name: 'Mirantis', logo: 'mirantis', link: 'https://content.mirantis.com/Containerizing-OpenStack-on-Kubernetes-Video-Landing-Page.html', @@ -218,42 +204,28 @@ blurb: 'ReactiveOps has written automation on best practices for infrastructure as code on GCP & AWS using Kubernetes, helping you build and maintain a world-class infrastructure at a fraction of the price of an internal hire.' }, { - type: 1, + type: 2, name: 'Livewyer', logo: 'livewyer', link: 'https://livewyer.io/services/kubernetes-experts/', blurb: 'Kubernetes experts that on-board applications and empower IT teams to get the most out of containerised technology.' }, { - type: 1, - name: 'Deis', - logo: 'deis', - link: 'https://deis.com/services/', - blurb: 'Deis provides professional services and 24x7 operational support for any Kubernetes cluster managed by our global cluster operations team.' - }, - { - type: 1, - name: 'StackPointCloud', - logo: 'stackpoint', - link: 'https://stackpoint.io', - blurb: 'StackPointCloud offers a wide range of support plans for managed Kubernetes clusters built through its universal control plane for Kubernetes Anywhere.' - }, - { - type: 1, + type: 2, name: 'Samsung SDS', logo: 'samsung_sds', link: 'http://www.samsungsdsa.com/cloud-infrastructure_kubernetes', blurb: 'Samsung SDS’s Cloud Native Computing Team offers expert consulting across the range of technical aspects involved in building services targeted at a Kubernetes cluster.' }, { - type: 1, + type: 2, name: 'Container Solutions', logo: 'container_solutions', link: 'http://container-solutions.com/resources/kubernetes/', blurb: 'Container Solutions is a premium software consultancy that focuses on programmable infrastructure, offering our expertise in software development, strategy and operations to help you innovate at speed and scale.' }, { - type: 1, + type: 2, name: 'Jetstack', logo: 'jetstack', link: 'https://www.jetstack.io/', @@ -288,7 +260,7 @@ blurb: 'Spotinst uses a prediction algorithm in the Amazon EC2 Spot allowing k8s clusters to increase performance and lower the infrastructure costs' }, { - type: 1, + type: 2, name: 'inwinSTACK', logo: 'inwinstack', link: 'http://www.inwinstack.com/index.php/en/solutions-en/', @@ -330,7 +302,7 @@ blurb: 'NATS is a simple, secure, and scalable cloud native messaging system.' }, { - type: 1, + type: 2, name: 'RX-M', logo: 'rxm', link: 'http://rx-m.com/training/kubernetes-training/', @@ -372,7 +344,7 @@ blurb: 'Full stack monitoring of containers and microservices orchestrated by Kubernetes. Powered by anomaly detection to find problems faster.' }, { - type: 0, + type: 2, name: 'Supergiant.io', logo: 'supergiant', link: 'https://supergiant.io/blog/supergiant-packing-algorithm-unique-save-money', @@ -418,7 +390,7 @@ name: 'Cobe', logo: 'cobe', link: 'https://cobe.io/product-page/', - blurb: 'Manage Kubernetes clusters with a live, searchable model that captures all relationships and performance data in full visualised context.' + blurb: 'Manage Kubernetes clusters with a live, searchable model that captures all relationships and performance data in full visualised context.' }, { type: 0, @@ -463,7 +435,7 @@ blurb: 'Strong DevOps and Cloud talent working with couple clients on kubernetes and helm implementations. ' }, { - type: 0, + type: 2, name: 'Bitnami', logo: 'bitnami', link: 'http://bitnami.com/kubernetes', @@ -491,7 +463,7 @@ blurb: 'Opcito is a software consultancy that uses Kubernetes to help organisations build, architect & deploy highly scalable applications.' }, { - type: 0, + type: 2, name: 'Huawei Technologies Co., Ltd.', logo: 'huawei', link: 'http://developer.huawei.com/ict/en/site-paas', @@ -533,14 +505,7 @@ blurb: 'Fluentd Enterprise brings smart, secure logging to Kubernetes, and brings integrations with backends such as Splunk, Kafka, or AWS S3.' }, { - type: 0, - name: 'IBM', - logo: 'IBM', - link: 'https://www.ibm.com/cloud-computing/bluemix/containers', - blurb: 'IBM Container Service is a managed k8s environment with built-in cluster security and isolation while leveraging services including Watson, IoT, Weather, etc.' - }, - { - type: 1, + type: 2, name: 'IBM', logo: 'IBM', link: 'https://www.ibm.com/cloud-computing/bluemix/containers', @@ -566,9 +531,80 @@ logo: 'endocode', link: 'https://endocode.com/kubernetes/', blurb: 'Endocode practices and teaches the open source way. Kernel to cluster - Dev to Ops. We offer Kubernetes trainings, services and support.' - } + }, + { + type: 2, + name: 'Accenture', + logo: 'accenture', + link: 'https://www.accenture.com/us-en/service-application-containers', + blurb: 'Architecture, implementation and operation of world-class Kubernetes solutions for cloud-native clients.' + }, + { + type: 1, + name: 'Biarca', + logo: 'biarca', + link: 'http://biarca.io/', + blurb: 'Biarca is a cloud services provider and key focus areas Key areas of focus for Biarca include Cloud Adoption Services, Infrastructure Services, DevOps Services and Application Services. Biarca leverages Kubernetes to deliver containerized solutions.' + }, + { + type: 2, + name: 'Claranet', + logo: 'claranet', + link: 'http://www.claranet.co.uk/hosting/google-cloud-platform-consulting-managed-services', + blurb: 'Claranet helps people migrate to the cloud and take full advantage of the new world it offers. We consult, design, build and proactively manage the right infrastructure and automation tooling for clients to achieve this.' + }, + { + type: 1, + name: 'CloudKite', + logo: 'cloudkite', + link: 'https://cloudkite.io/', + blurb: 'CloudKite.io helps companies build and maintain highly automated, resilient, and impressively performing software on Kubernetes.' + }, + { + type: 1, + name: 'CloudOps', + logo: 'CloudOps', + link: 'https://www.cloudops.com/services/docker-and-kubernetes-workshops/', + blurb: 'CloudOps gets you hands-on with the K8s ecosystem via workshop/lab. Get prod ready K8s in cloud(s) of your choice with our managed services.' + }, + { + type: 2, + name: 'Ghostcloud', + logo: 'ghostcloud', + link: 'https://www.ghostcloud.cn/ecos-kubernetes', + blurb: 'EcOS is an enterprise-grade PaaS / CaaS based on Docker and Kubernetes, which makes it easier to configure, deploy and manage containerized applications.' + }, + { + type: 2, + name: 'Contino', + logo: 'contino', + link: 'https://www.contino.io/', + blurb: 'We help enterprise organizations adopt DevOps, containers and cloud computing. Contino is a global consultancy that enables regulated organizations to accelerate innovation through the adoption of modern approaches to software delivery.' + }, + { + type: 2, + name: 'Heptio', + logo: 'heptio', + link: 'http://heptio.com', + blurb: 'Heptio helps businesses of all sizes get closer to the vibrant Kubernetes community.' + }, + { + type: 2, + name: 'Booz Allen Hamilton', + logo: 'boozallenhamilton', + link: 'https://www.boozallen.com/', + blurb: 'Booz Allen partners with public and private sector clients to solve their most difficult challenges through a combination of consulting, analytics, mission operations, technology, systems delivery, cybersecurity, engineering, and innovation expertise.' + }, + { + type: 0, + name: 'Applatix', + logo: 'applatix', + link: 'https://applatix.com/applatix-product/', + blurb: 'Applatix helps build and run containerized apps on public cloud using Docker and Kubernetes.' + } ] + var kcspContainer = document.getElementById('kcspContainer') var isvContainer = document.getElementById('isvContainer') var servContainer = document.getElementById('servContainer') @@ -601,7 +637,15 @@ box.appendChild(img) box.appendChild(div) - var container = obj.type ? servContainer : isvContainer + var container; + if (obj.type === 0) { + container = isvContainer; + } else if (obj.type === 1) { + container = servContainer; + } else if (obj.type === 2) { + container = kcspContainer; + } + container.appendChild(box) }) })(); diff --git a/_includes/partner-style.css b/_includes/partner-style.css index a8cc125992..191d6b340b 100644 --- a/_includes/partner-style.css +++ b/_includes/partner-style.css @@ -1,5 +1,65 @@ +/* SECTIONS */ +.section { + clear: both; + padding: 0px; + margin-bottom: 2em; +} + +/* COLUMN SETUP */ +.col { + display: block; + float:left; + margin: 1% 0 1% 1.6%; + background-color: #f9f9f9; +} +.col:first-child { margin-left: 0; } + + +/* GROUPING */ +.group:before, +.group:after { + content:""; + display:table; +} +.group:after { + clear:both; +} +.group { + zoom:1; /* For IE 6/7 */ +} + +/* GRID OF THREE */ +.span_3_of_3 { + width: 32.2%; + background-color: #f9f9f9; + padding: 20px; +} +.span_2_of_3 { + width: 32.2%; + background-color: #f9f9f9; + padding: 20px; +} +.span_1_of_3 { + width: 32.2%; + background-color: #f9f9f9; + padding: 20px; +} + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .col { margin: 1% 0 1% 0%;} + .span_3_of_3, .span_2_of_3, .span_1_of_3 { width: 100%; } +} + +.button{ + max-width: 100%; + line-height: 14px; + padding: 15px; + } + h5 { - font-size: 18px; + font-size: 16px; line-height: 1.5em; margin-bottom: 2em; } @@ -9,7 +69,7 @@ h5 { background-color: #f9f9f9; } -#isvContainer, #servContainer { +#kcspContainer, #isvContainer, #servContainer { position: relative; width: 100%; display: flex; @@ -21,6 +81,10 @@ h5 { margin-bottom: 80px; } +#kcspContainer { + margin-bottom: 80px; +} + .partner-box { position: relative; width: 47%; @@ -58,7 +122,7 @@ h5 { } @media screen and (max-width: 568px) { - #isvContainer, #servContainer { + #kcspContainer, #isvContainer, #servContainer { justify-content: center; } @@ -76,7 +140,7 @@ h5 { } @media screen and (max-width: 568px) { - #isvContainer, #servContainer { + #kcspContainer, #isvContainer, #servContainer { justify-content: center; } diff --git a/images/square-logos/accenture.png b/images/square-logos/accenture.png new file mode 100644 index 0000000000000000000000000000000000000000..473e6afd7ec1b1f580e8f846e3924cc8de35971a GIT binary patch literal 13997 zcmd6ObyQr>66WAea19dN-CcvbyL)gOoZt?@9fAgz;0_@;3_%0Io!}N6_U7&Tz1=-$ z-~PRvGu)Xz)pEP5tH1iHI$Bj(1`U}A83Y2M$;nEo1J6?6la2@v{O|oPy97K4J*0I# zG@PwHyv^LKK;o9p=2ql#j%GGi>Q-i!KCYuyLLd+fot>txhpv*MfQ7Roi`icp7OmX%c{saiIy-;( zXBJg$ojsi0ZJk}nB_;pP8ZSAWl9`2_)89h+f7Mb_5|DFp_b_v^u#%G!rU2Suv9q%j z;Cj!_Eycwv#U~*l#m+9x%O}ky!7s_qCc()sE%}~{>z}$(&K91IR!$!O)V2Iyb*2An z-MJ{HOUT9*|V4C~+J{oj`R zpCUkq{(k+B@&Z5pqyAP-fX=%C%AK=X-v$D463a=6Yl4@L^AIvMzqhn>`a!e7j3udw ziG>s*%Hv35$R&RlQ>7Y#!i9+rwJ^5+u3wwSdl4+H^EzCYc&VUI8yP zok>qszp=2%@^2AbDfNFVqGQ(kD`X8zPvj}J{o$3Ex1a$DX;=lX+m(>4R^v^K< zH>p?C81z?iO3H8dN4Jl8y$|AQ-9<%3%Iz!!r~<54?YEIKo^|aI@j!ByG48$YdqoIW z!J+ZhhcoUyPWPIZ-%D!_o_S#8AY(q!Jnfzvn7Af#LfU*+B9S+ue4Nqsk8s4hjz=51py>@|jK6F1P}?ITps_s_vO) z+75}Xvf4!r6Rf)?2z-VazP{F!3WbUbk+J^h4@C$N^g14ST=ib(cAWe2gErX1$Jh6v zH<47>_b}<5dxyEDWgahgMpN*xu~W)!9TsbAe)a~v z;*X~>-i~*89=$(V?QHc~tTl?A$mV7ws*gZ_%eOJSeD|$81g^C7>OE*OBRBVLJoQA) zEi|o|(tbcb5;l#8{Y=TIM=&2FJNreyR+Y9Eses1;T&LFw^7F+oSw_ci$q5mqge`PB`kmtMz@A9u5@RI6*eQds&_Hdd~xc z(`=cNObkA2zHCI`KsV10^z`d`>tm=*G1qG?@1V8%FT85w?v5*{)3%{R z(HHRK-eivRh89^89%3SMJPNCN$;hey{Uym2G>@Pdk&c779lb^p-I89blTp_F)xOE= zenF6Nr~Q0oM=Tz5#|pMLe76|Rrv}z)ow~IrpsgS!_+ClVc~5?*oqNNy#=<9rj*Dv9 z@i@z6@oLLSI21e~UeDii@G^;{lNQzaOvPJ@DV`R%w>*x^9(b;M)%wl$%(c1=Tklnv z4k1XQuT*UMsxL}cNlTb`Gq>|PCTZ}QH?XpkN<>w3V!w$%ZGiq-n{a>l=`w|@W7yDP z+8+`*&`02AlBGYAOBW3okjSmAEq}{}(ZO&TaE?yO{zL8{O}pc-7Lz8sS!??=1}$w< zTwZXQV{Ykty;)h;lF`bq+13q(O|BMY=~q7+EP90f{_KeO-?@aW=~Qak8AYO#&~V$& z*?Qey?(*WW7=n8dJ_LG;@Dy2bokR}Dzg}C(qKx$t<{H<7@~4$}S4(c?fN6Uzl1riC zJX)xE3>Ab+{f#E->1S_m-vOn2SJJ81b*Ey8(8?&VZzfHfE5oX?8L->^Iv9=ZDwFVb zG@Mv;V?q95^>HvPhLr~IS8MR zvNx}v)|Z&rPh!Q9 z5#U8Y237Ow4Jmxbhv}mG=uL5=i2T{~XGwWLEmRCWen^XC-pD|w{*rqI%(kTH^L0u=%cVJ#xiNS%{3pFe z87u<&+syaxvzMD47IzqH+a&Vb;CZnM=N2xuhheCY`dzn&cC*% z)utSckb~;xwDU~aZlPKaSuPAVhh7D1>mv+8i0IRKXhF|TX)ilqXUCdte-y<5Hm$V9 zZk7gjJk7A(&1#flgJEJ+d|HI4Hu3wU{00N-6+V+L+ucU!8*6gj*MV@9=kt_0%hBY9 zy6!*v*SzcgDH6YEZ3PMS1a7~OFj-)%xvzt_<12h4pfWl6x*{Q|HU$CNDaS8fC(ES^ zU(_fi3-5nd)fMee(;&chgZu!fQwz2^fclE6+B zQY#dL8qPMWD5h1)#;N+L6@&QtaVVa+9N3a{lq&f`gq${0*Fkrikv{V`4Hm*6dH_=o~hVvvi7On^fyIzyOxcD1KTbN5J#<3WwF$ap%MDs=RI{v!%vYKs8VU z9uCW0n*nK26zL5%DyeQvgQ7w zhoINzTZ}G~m13F19KtVnz0ZFP;4;cRQa_M|yhQH@$orxAO!Wghapjx}g`~tJeDiTV z=DA6TZlehHvEKgKC(x|VpRvHZux^(@yPBYC5S~9k&~UR1w1yoIhdL=8CTyUKA}Qj14&{O&d>8y{_BE&ZGT zX9;n27Qd))P>X_V#?Cjt?Hl@?GzYkILurhCz>;`Qm}@r-ecI+uO8NEl;n0b51rV(ZVzFNOIU1Mg4wOz+-7?Yoip zf0q}F33*%lQQMMMCiNU2tL?#kZ-U?I!=%Ry{Z0NR8DdgfR)?)cBavhk$8;1IwtH4& zp_-k4zSG)vM1cf|9lBYJKA!6RrI}G@rh|v@0vC6#S%CHO0CKHN+x!m}1jR-%`~CL) ze8!NRf}?JkE}vg&#K!sgK6_dFx2LN)2EnO~h^hd@Jnw!y?dH9o(GSNVPojSvt+cm#4k_0V-4IzR1n-%lL~rI%3k#AqAbc<;SB)>euG zb6i6bDe3Oxb9kN6+boDNQ_I`W1_uZI-w2)eNMIU93R3-p1pVT2NPQNyy}k+0|SjS9>`5U2J`Cm2)xFa9!^S2*+7D z$}UyN&>lp)bzbYbU-h`F-&1$RR13p)HgzTb5-jfcg;|&w<*5ob6dr%6&D8=9R9!-^ zwf=3kxUJ{A?mFQZsf!F@lSX7iz_0TXim0}>wrx-#jbn`z{T1dLW5(}Xi>7Fm{^$J& zD)Rso%E`wyF1277!SvGWj=^L0h4pdN!3qiQ&4ijb^BfPpAgaFc95EwqRN8Mp+PLRS zuLz?bW7Cq%FmxN`8G1)Tsxp1*`u)tw4LtUB)vheqCgu?5r7LJvaqTP`1tz~_WRxiS z-I!4dWdP*N$D9&C8SwnQW&AlSvu+C?PliLY@BP%RdKA$`(71w%E% zMU83I89z(%UZE2)E_QmKxq>#JzkfpHB=Y8hz~wYV9S%yVfUQ9FSL<%$%qCzTXo8Bi z<(7y1!M;}W?=g)L&Xh3CC@w7?zvm9~nGIS}hbGfcf3==xFK#5)riCNVoLhVFB6xI)=_6pMuh9tDHgL~=a#-8d=r=z^T|}|F%?SiO z{yCA6_ZqVQeHMjD=?i0CE~R43WS|i3Glh`3XRjPGRD@Gt1|_qh{Yv%q3X}7GWVvO< zLpoTrGm2!?c@i|_b;`{NnT?Kwte-p4;(u|f_1 zlx7(F{xB@Bz+0|-gA(h3Chn%9r_QNW1d;6%@%vp-Zp=1{G4ShWz1cUYt~xYR7H+sk z)B~kKi8}L73w;XBCPB~59fB@U7w=cPa6ssmN&dRxGDrtk@9v1=IOc|9_A|ai&#?!0 zpw|)V&T=VTg;7Tm^=Xe50X?MJTrcug2X+~ z=W3aD(MisN!~Fo{Mnfow$f$AH%;QVB@?@U{z3XGD$fVg*Yx3clWO`&>+g1#0*JPeC zqk@0W<~oLa>idC%V3hH*&Xbm3@EqyQ=e6^SMch_nsS6`dlwG5r-&(C(s+nNNLEylL zT&W?T8Cfy^D(#vWTDGZh5DZ&Jh?o-I?rnBpz!y)0gZBgp99b12BPIq+-J1jk2@(UG~G{^wzSJ2L;sEBj6xhZD3dOx==@@ACXg|XBMowD zhxWiqho?h0py^$pbZg%AaFx$+QIF_JKY}Xb@bm`dBY4-q7D<86)?nUC(9RFw6_G%u zH|$Z;jD>a#&NVlNFwyM4^?+h19^b8Z&&F2hin zMadq#!M>~8^>pTAr3*1{j6t;*uiGFTqy*T3XRQX76T4+vMAd+7+GD_zAm|>jX>THf z$JZsLj^c*Ka@M^X3hqUH8fw2P4s55|DhHbvVh!218<$`#lSS^Lu+ky6kGV}KidMu| z^Q5$s?(E3N_Ys+?FSiNpKfbLV3>(l{b8DQz<+<6rhSPZ#UOVpw4lMpeZ=d)V04%E~ zX;FVm;g=N$_xbkJHKTaPQ4co(hRv>}s4@e=2PsZHH*!%my-;%@)&;wsB@y$e$+*+Y zk-EKQB5VUK(+J}sO0WsHsZda7uWQFGx;3|wz`N`Vo)#}Nj9mJ*Z+vRW}dN1oRdiTu|fAEo%eUznGnf7had6v->f_$ zj&=hRKS1o4P8IX*?r4z=W?LM8SuVoBuV%6pO2bt9env!cL+W;$;kg|D&PX$yvTyiy z9UyR!+A6ede(8DVa|nbuj3BDiTjm*J+<)UT9M?XiAx8CPH%_uIRJ6-@ty8=5Gs@Is zNf{R!mq0EjS1-+qZ1GpwssKkQj^UF^e+Yft7MQhL7C-!di=;cEV^> z^543Z6Tj_)p(5)VAINv%oJfM=y_gvU_@aPVEtW6x9J2|hi@|gvI8}5Gr+}YA%j3M} z-#U=uE)1cq`iOcfmesz@v~p_)5+r`1xF}3QS}H)?Pdj%A1VGI&yYYQ@b2^8rJUO)j zca<)2YrX_x)9i@?oq=isiD1iD+P&xnbGr9amF=GEfgnh?cGCJi7x*jgnXw*z5ySUpLi^MO!X*q0Mp+De)c6GQK|oEnI0UQ?Y(j zlSkEIN^WsXE-w2BEAa_S?IU<7j!>kA6e$xq;5q;d<(ghd6;XXG+#A8?LVK|*D^O0L zEEmG*T%OrSd`8euPt*PS^2nXhdJVu@_V2jLxJc3ONj{6SBNs+%Nh6uc(i-%>WxOXK zY{SC*_#V4S+`Jp28nLR|UNh(x9zTyuC;E8&^}S`wwru|OhxQZ?W>1J%ATh7V!9oWDA;Oh~(OX$&AaER%_z(X|+jj53a>Z6q68A`<}Y>n_!dev;Mc#0=`L$S`2OL zfboSA0H-#IY7w$~yd%`YP6^JOl1ItrvfI+|8f*Rvb$tqekgu6`C>vUY02J+=$`gD8 zU$38i)o(kYBKqth8r-eP5bxmS8#Kwi$kcY)ag^LJByRX^QRvp5o%Mywipy!Gtp@;$ z`AV0`BVYY3w?*LVUw{MGcQiXo3;xt70&b1I2NA6-k%;>@oYeyS2EY(k2$~N@d08$O z@Y+s`X^4x|WS<*JE|WrIVE+NoIkHJZ81=T#&|~%`pN`InoW4YU+u~V#j#|mnxeLtY z{oYCI`oeV<7k_*`4X$xQ&Q3qbaw?bqgfJr-TtOMk*KE=os0NJvS^>m))*dp`7iz<} zvK$tv_xbtAx)dF*C%K`U4FAOhT&k&*_0Ayv8?NQ?YqQlj-lRquV^O8*=KPRhNtyz@CA3XkOVXdiS(~=3 zoLLj4VWF!DP8icCi?9V4#``|NA1ud)@k*xVc4ZO<%GqRSf`^;!0{D(Fmm5aN$&&MFo=0 zBvPG>7rB|!a4rUi+Lp6JJ3RrMw5ZA#4)jSKt<)eM;|2%7*c?ze;} zlqqJ-EDT2OL(4n&qrcO-q)ZgLti0e+CnpTfFbTZ>fk5W((p5R8>clK0gsLr)&FgHe zl`8N>(&UpXsF;gL@6_9dv9S(oK*3^y=*HlB1{2NJh1YsHyo7ETy}jk;p2prF_-5$}Fu@lT0-4c+&~i`mqiY1Kda zDdqbn8Vm1hm2!AYFyL{x2U4kNrABlBG(??WgnmLW*H~)L_U2%hlx0_Fn28fB8Flgg zQ;eBb(x#C$*R%R&sNomA-<%4zREe$O_(Dnk@q@_2oo?R9KF$F6dh@+AhOleA)k)1` zIT#8ipL@Fre6jU=aP_Fm5xF4dbM&hE99h87tK7)F>Q9dCg^6@RrJ#n!I_Sa`C#ZUP z45hsju!i2c(`rXN_X!bc7_P+U&}9b26=#Is_qUizbt1}5bBO#~a(;m{wts#9`=_?PSc_+B5d6QR6P1z<)M z51?=eU1k2rnly>P7a~xw6Nuk%H|q2vse4?V7eXim z@t}u~?<@D)aVs88{}8wcW!n)MveZd0p9?S6&j1dkhWiBkYt9|CrODMAk-h+ntl>^u z-=wdQ{y&PgIY2R9;&$ zcxIzrd&T*V;tx+eW>v>k;3`&>G;>Ku6N+px+GfHR|Wo{732QjxF>g*lbGpGd& zmS%4ku*=imC3xRyNGG9&*Y-~z&pwBtvC`ACb7-1$aVI(bh{XEE=Mw^utE}2&l=0Cq z`~|+MgToIF`V=!eE1vOP(gy^J@Lr{oYBe1uW4Z&2bZniRno7bL+Xv z*;S;IA{7S7fR0MO57}2KSbs~ifzjz}u527+kD%4+J8%#F`lh~?+Upk;N{L9DKdkU$ z1;7r}H@sNS%WKnLXJiTTdslLUYne?gsR?6c#C(4;k+yY7KQ|xoNH(%6=Njm10X!}c zRg)aZ8^)2VOCltMK|QEXFRLcvx3TUxb?HfECNP&U@jNiO$YSXeSzc zJB=)jiE+kn?i;pzbdzhJZF$>cMp6!|1~-Mbf6!$u)#KT@30Ccjc_&Vf!r%_z4r#Pu zx^4(Pdoi_^uN<@^$$ZB2<(2WlTg{%n9*E>EKTDeLSXMj56178RwE)cz*p6V2c5Z7PUSY= zGzMedLdYK>rs^xdS~x4}pc0b;;Ds3(jB&z*kjfxmiIO+RD8?*=B~O2AzAp(yHDrrm zG*`YKclrQhY_Un0;=Vq40A=$YZ{4c-EAt`hY!Jl+MLuuv&~C? zSQS~8Mkzc*?yg9qQ{wy2cVUS?RXY#*j7>}hTmbWvc9^93C-Z)=<@DW^epK$kO3;OxaXrC*c-^Z9-kPRGkL!La349VrN5GY5r@>25J z5Ss00_ur#}=j!8$5 ztFDbH)RN708_#2Rn&whWmH6?A93QL&jr?70(fjUg+c;@!|AJ`mv15;p^A~Ggk&m)? zgSoKQq_);qtBvdhf!2~)US1^}99r>~)<359A-0*4h1zw-B-xxc34ykp!;S@sp}!$> z19>$$+%mNGZ@CaY1gGb@oa5OLdcX~Z9|cIr6%pdL?W_HzV6ZRLtNJT=ya zhASs0zgo%EK1+mqGJHxTSG2kMan}3#qOY#5E-Ip5v&-Ka$4mfK_z}^7Kv`Ls9Wl_G zWA)hC%X%oDkwgB=sE2VV5tnU!r&Kf+gUxakXWPm>`&oBSJ%YfA75f(&L2jET*n!6* zhHH8aJ|{nMl?9^nKa?qtFCFhB6w9z#0cR3#xM~S7gmo3|>vHUjwd;H! ze0MC(J*LE{JvTMW9T5cmBlt?;(5XqrKunQ9UeA?e%lvkg0MMDD~+X|^MX zom6pWMz12~_;DfT^SKGX_d~r;mUpW($`h6a>`eC|1!OC2uEp+H1i>11h9I;z1Ld3< zWj4Qm?g6NKVK2J`2tHkz4aCFH)6)ln$CJ4GD#M6)ovNWN%k$j@HTnsW_nVPqP0V`F zu3!nf<~J)k4d&7(Yp7X)(@qC_InE0v<)PPP7m(NKwkA zhyB97*Rn8d^d40DHk%lc6WbjysB!4FW92Y#(_OKyIh-IpRFVg!Gz!!a(o7~{z*)(O zdS^bpbNgdQ81&6KeGB9O73|u;Fo5Yn0;~Q|)4KL>z7@;*690$`eNYnqKsSC31mwBl1HFk?3uJ=E&wK!wo=v%BOvuA?K-)?|2L`VYwSK(|?7@N>+@bK9`K(ACc{B<$LCAb38|`*Kq!CuG4H^L9(03}yvJSC5g&BAIQj-aI$hsOge4>)qDob&DD5Mz+-}V znR42j+grGjoTL-O6WT>gmN+@NzTPgMtG!vvc+V}QZMP=C&8Q?d2`@!u^O7dmmj{?J zqv{RXWsvfTPTpn~j5Iz2qPbcRd_2*Z_Hs;L z6gVuk)rTRy-UPCQDxsoiG4~)KHeB-V=s&4FHwy->oTl+*%6Sin5_j6t&;X>{lhlof z0g{(~hLcxeKQ;{(DZyki;KvSx9PV$(7n-rw0q!-wgc2-jI1>KpY#=$wS%{bujEBH` z8)hP1tc_+hV#Mog9b+FWF8P$c#~Q<4IT$F@F*8DKtU#u~?RegYqP$j*!x<}>!n*J7 z%b*Fp^W+yGQX8a5>Ja5tSJ{VD$ z>?4uqYmL0ImbjKH#azCN_=lS#ga$spLlYgQ1?}az3NN*x=23M9pWh$Q-brAbf3fOdLAlaP9~xg6K{n9XSE=S z&Ik>Z2wEUp_dDyZ1=YI)DM{(3Uw&5`wqM#mT*DX_Bpwf7iFtm9Q}s~zFdV&3t@NYMg_)}%+-jxdV>yD1Am-D=G|LID^QW`)`Gf+%Nh`*WPh(mxIxGr z@Nj*K2u70#sPwx%{dPDFo99@pWE|YW7;`ST@CBsppZOcP0h<0nnY%!@kp22I>40Ob z7WgZm;VJE{*T6Z#2e;v=*^Ue8hTXjcl0X+^63adA=p+`TLq7 zRM%p&&TP;h4eAGE z(4EBY_T;Fx^Yj@w<}!c)>%b%3gO8{=WVPLW-;AMS8o~fGqXSShwZw|-QehvKSylFi zN|iq$Kd+$oJp=URcM^eb2nsK(J1>lz6Qo0?u#MS5K;Tsq_cNV4LevF8jsy%ms;pG| zEmYgy(<`@eC873(E^v0XnjQ{AJ;AlDYz~B1PHvu<5JX`Ph6^ma@*&^SlQV^*lJ&Xu z4%%Q}xGiEYeR(*d(ZhXP059(tBzEU8U2s~@3@5ddtHwx_VA#(A}?Ik<*19*d-!s_V2*If08&8J5iVuN5OaBr2XEnc(~` z#M^zVx2(gDOdDBtaRzd65+r?p(k&UO)!K8FkF|0tE3BB%&6;Yhs>jR`vuD;H;_RRs zg%nNPU?#@swhV=q$lP{E`~|ukxwyZa1{TE~ixKv1ISzI|7lNh3>{K#-X;LS4*33J{ ze87AuwcJ@gNP|Me!f?@RebDU>%pRLBIT5%+bm2pI=d-AF5Hr5;6Bn0(aJ@4B+N5~((mJT^DQE-_EA0Ygx2fM397eRQ2;{ioj z8luglBSJ*qCpNxYY2MWbP<|Rwko7_8MT&Id1h2Il0Alo1B71&Rzjy;vdF5KP+K+ZX z#}9vOxlr06Cgv8Vj9W_C-QL1AKp#zg6f3PCv!tW6P1LuD#@K~&l)Lhmkpb!Z%zIM= z53HrZ+R>!nL0bg^sW>m7STD@6xyb!N%;6TADLeE`k-o{Jre)|#sMPv{Iui}tYvzKx z^l-C27FE;QQ7fei*+;@V(3tASvu#A?bawKKL2xsilvVn&<&bAPZpcA3b>74{IUXsW z%Lawj0F@F9Arr~`3Z}z_fDq0+9%Aqs7Mx<=SS^&$Ef(}mU%-C@nYY=ANZ!;Vpe(S!HJuvc6hI5CP!Qi$=!kB=g+>9Tg z4kn@-5N!L2W4K3Z-YkvyEZi-E=$HfwN@Y(ofBvwB$kX9~H%t0tN27&2y*~ z(&zRFQR33DKFbn&#ua+;UcRDlwfOxQh?Mmxqx&^%z5?kU*OXJ{;EJ>%{n6cahq^V# z4LtzlOV@NvW9z=)qR!yul@`Nbf@Tv}f@7Lz{RbTRet#fm;(h74Ywn#xl&R zHzA9tsH5-iMyBV`-Coh0UBmux1!TN8J{N8@8ql49j~fP6pnC)$=D+?${Jo54p9joH zkgF8)!(3|<2s31)TwB}&MA^;>7A_2MD8k#Wu=}2Jj0H>%niq|U#e&c|tk*vwbRo!6 zKR)?uGyFQi$QGS>m!aS2-U=EyIlQg|f5n$HFl8HzmWNW(g!> zBDp0t>Yn1^T97;>D~VBag93J*H!dQ;lv@0fGzK< zKZORKwX>d{))r3yqwt8Tz4zXZo$21KDfHkc@dn!Q z=a{nOl@P7oa=^ohMyGdC(TjES)+6fAyR1Un)9GHZiwHhixN&Ek8cWh+R+}JrI;tMf zU?>TAeTI?W#Qxc_)>L)O`^99?C6-9>>&N=y2j!N1C*o-kKO^<^?oQ>XiQgJ@%tceI zrq<0n-gb6}<h!jf&UCAo zdRaPi1Z3cs&#tYLyJcWDrw#3kEaEUBtg!R7`|bwr^X|)8wUZ10w?7;kdnaxGxry=5 lwTu4`Z+}=m1VN*M-Zv22h-)uW{JlUXC#@`1D`6V)KLFwj3nl;n literal 0 HcmV?d00001 diff --git a/images/square-logos/applatix.png b/images/square-logos/applatix.png new file mode 100644 index 0000000000000000000000000000000000000000..15a30708cad437672ff9c56bc7c65c6573d17697 GIT binary patch literal 12404 zcmaKT19WA}x^8TC*s*PA#kOtRwmVkGwmKc#w%xHhSur|x^0Lo8``r8Pc>Ap})~Y$b z@#Cwie~dY+>RXYD@)C$}IB*~!Ac#_uqRO9b$>%o}2I}*-XGn7Ov-#>Ors=BUVD9Q+ zBDrK;(wDJKgsaj;`B`pbsF)6VhJ8w7+` zz|+yl#Kz2($k@!n%ASwpvZIHD$jX$DM1x(9NzPHk%+gBI+u2OTTVB<~+s1_3lth4^ zh}RSF8NklW)riQ`&eq-q;K@hwuegBE>%U+|5~6>ZxZ3cM{1+)rIYlB72WK-Pb_Nc5 z6J}N}B2I1wW_E5a7B)H}7A9s6Mka1XW;S{zW&jg6fQgyt-yf3CY|f_U0A*3}f9LwV z<0G+jb#(+VGJ1G;FnF*sI5=A{GIMitGcvI-vary9TF|?A*}EEf(%ZX`{vAQo%*Djn z%F)%z!Jg=^h(^W^ZmxVJpG^O&3wDnG32X22?_v5JFh)-!M@D7_roX!Mx1pTe|KHTk z?myNpuF7Wr&G-Kq*hSUL(Tq{q%*DaY+2nKL%t`-B

aQHZyW{a8`A2u>E@!6)hcH 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%0AxxyZkQC^Ys;#jsp0o3Kc7HD`aE`( zHm(^sZ)-H#-B^xdO=9q;X>w@(F$OGA|M4sqs%0<)s^$w^YZ~Kd(YP7CbdN{=b~oxC(ok2czVH*Mbl9;a$X07s$HUm)e8(HfXg#VBQCe;bKk<--AU=7 z!6CQ3*ZV6L)?x4z!6?C}zNI-0c@!1M*|<1h)|N3-Ny`}gxw0^1vn(KC1b>A#wT45g zGb{rRi8gmT8)SI>IeBX z@`b_uwoYSIkv5xz=mhd zKi}kK91{6USqnGcAS<-|58RSzX~$k*|ezcES=!%qe_v* zEGTh#EW0>Q^D{O$RikdhlNm5e$eFQDdqInA=0z5EL@{5amOttqAY4Q$v6OO4tVkAB zA{lIFt{Skr#$g8O+z9}Tn`z63AERo}87Wu3wun4!RFv18&lh)3=I5=jZWl>qLVT+z zx6O*^mr)>lw{LSN^*-=(FkY$7`1r`Sd`aE}y&}iO)yD*sz48Yp<-dExL}v@cHT;mF-offE+k$q=@X4x0 zNk+*R`?~;rHI_mudyx(f(~+pBId0$zs8{YZtv&QYHG=u`DP8W*AB$x@ z(p(ovn<1j2raH!FZD?6Z1)AwI#|lba`X?3k6nPj1N4W#K*3`Lc@(;Rge))QMIpsPu ze=tRQ(+Sv~fpB)|5;5OPC-tAYw!P>wIFMAWOUW`JZPgm@p5kInzlD%ZXxRQKvXh!q zVlr=VF@41l+qsCE_&7>N`IiXyAGEapLxlUc;`ZNK+P`$U{|owGD&K#W*Z#8>_-`8j tLmvD$^lvTj-#PymGk(1%1yCrEWy*G%2n6N7{!;)VB_=OgEo>P4e*hlDfO`M{ literal 0 HcmV?d00001 diff --git a/images/square-logos/biarca.png b/images/square-logos/biarca.png new file mode 100644 index 0000000000000000000000000000000000000000..d99a06d245aa95a8ce9e6457624a8f98f81d83b7 GIT binary patch literal 9809 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

7?4pM&*S9NGgj5rb=MWsaV&;aQ&kmjQ-%$1 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 ZB4iLQS|O>H_xp#AhKi1I5!5#LzW{QjaXbJ3 literal 0 HcmV?d00001 diff --git a/images/square-logos/claranet.png b/images/square-logos/claranet.png new file mode 100644 index 0000000000000000000000000000000000000000..63e208eb5b3f60dd450082964902ce4e0ec5575a GIT binary patch literal 10283 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 PzkpJZQI)O&m<0YGAHDm% literal 0 HcmV?d00001 diff --git a/images/square-logos/cloudops.png b/images/square-logos/cloudops.png new file mode 100644 index 0000000000000000000000000000000000000000..731a0c11af16353c954b67ac320c165b06048178 GIT binary patch literal 12656 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 F{{R7}DZu~$ literal 0 HcmV?d00001 diff --git a/images/square-logos/contino.png b/images/square-logos/contino.png new file mode 100644 index 0000000000000000000000000000000000000000..f2d42c95b069adbf80a3d22c52a25905387cd476 GIT binary patch literal 5877 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 g+wc=!PK`RFtlvVSu4ixs&y(3+#E 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 JTOw`f|34_?GpYap literal 0 HcmV?d00001 diff --git a/partners/index.html b/partners/index.html index c4b58d73da..f19649cf77 100644 --- a/partners/index.html +++ b/partners/index.html @@ -13,10 +13,23 @@ cid: partners

-
We are working with a broad group of partners who contribute to the Kubernetes core codebase, making it stronger and richer. These partners create a vibrant Kubernetes ecosystem supporting a spectrum of complementing platforms, from open source solutions to market-leading technologies. Partners can get their services and offerings added to this page by completing and submitting the partner request form.
-

Technology Partners

+
Kubernetes works with partners to create a strong, vibrant codebase that supports a spectrum of complementary platforms.
+
+
Kubernetes Certified Service Providers
Vetted service providers with deep experience helping enterprises successfully adopt Kubernetes.

+
Technology Partners
Integrations and plugins that add features to Kubernetes applications.


+
Service Providers
Consulting or management services to help companies implement Kubernetes in commercial applications.

+
+

Kubernetes Certified Service Providers (KCSP)

+

The KCSP program is a vetted tier of service providers who have deep experience helping enterprises successfully adopt Kubernetes. KCSP partners offer Kubernetes support, consulting, professional services and training for organizations embarking on their Kubernetes journey.

+

Interested in becoming a KCSP? Learn more.

+
+

Technology Partners

+

Technology partners offer integrations and plugins that add features to Kubernetes applications.

+

Interested in becoming a Technology Partner? Please fill out this form.

-

Services Partners

+

Services Partners

+

Service Providers offer consulting or management services to help companies implement and use Kubernetes in commercial applications.

+

Interested in becoming a Service Provider? Please fill out this form

From 87bf3696ca75fc314e779fa1334bb28ebe27ade4 Mon Sep 17 00:00:00 2001 From: Stewart-YU Date: Sun, 10 Sep 2017 18:13:03 +0800 Subject: [PATCH 44/58] Update photon-controller.md Fix leading spaces in commands. --- docs/getting-started-guides/photon-controller.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started-guides/photon-controller.md b/docs/getting-started-guides/photon-controller.md index 45e4251565..ecdaf13f82 100644 --- a/docs/getting-started-guides/photon-controller.md +++ b/docs/getting-started-guides/photon-controller.md @@ -22,13 +22,13 @@ setup: the actual creation of the cluster can be done by anyone.) needs to be installed on the machine on which you'll be running kube-up. If you have go installed, this can be easily installed with: - go get github.com/vmware/photon-controller-cli/photon + go get github.com/vmware/photon-controller-cli/photon 3. `mkisofs` needs to be installed. The installation process creates a CD-ROM ISO image to bootstrap the VMs with cloud-init. If you are on a Mac, you can install this with [brew](http://brew.sh/): - brew install cdrtools + brew install cdrtools 4. Several common tools need to be installed: `ssh`, `scp`, `openssl` From 9a472c4fbba416a4d19e5628181610ae69d344d8 Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Mon, 11 Sep 2017 14:44:06 +0800 Subject: [PATCH 45/58] fix typo fix typo --- .../configure-multiple-schedulers.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/tasks/administer-cluster/configure-multiple-schedulers.md b/docs/tasks/administer-cluster/configure-multiple-schedulers.md index 00c1f1c597..157fa4b7e7 100644 --- a/docs/tasks/administer-cluster/configure-multiple-schedulers.md +++ b/docs/tasks/administer-cluster/configure-multiple-schedulers.md @@ -138,9 +138,9 @@ scheduler in that pod spec. Let's look at three examples. Save this file as `pod1.yaml` and submit it to the Kubernetes cluster. - ```shell - kubectl create -f pod1.yaml - ``` +```shell +kubectl create -f pod1.yaml +``` - Pod spec with `default-scheduler` @@ -151,9 +151,9 @@ scheduler in that pod spec. Let's look at three examples. Save this file as `pod2.yaml` and submit it to the Kubernetes cluster. - ```shell - kubectl create -f pod2.yaml - ``` +```shell +kubectl create -f pod2.yaml +``` - Pod spec with `my-scheduler` From 496b1758c7961df419fa4a769c436a917018c06b Mon Sep 17 00:00:00 2001 From: Stewart-YU Date: Sun, 10 Sep 2017 19:12:18 +0800 Subject: [PATCH 46/58] Update libvirt-coreos.md Add som urls. --- docs/getting-started-guides/libvirt-coreos.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started-guides/libvirt-coreos.md b/docs/getting-started-guides/libvirt-coreos.md index 7bcb341e73..4c067f8d65 100644 --- a/docs/getting-started-guides/libvirt-coreos.md +++ b/docs/getting-started-guides/libvirt-coreos.md @@ -59,7 +59,7 @@ You can test it with the following command: virsh -c qemu:///system pool-list ``` -If you have access error messages, please read https://libvirt.org/acl.html and https://libvirt.org/aclpolkit.html . +If you have access error messages, please read [https://libvirt.org/acl.html](https://libvirt.org/acl.html) and [https://libvirt.org/aclpolkit.html](https://libvirt.org/aclpolkit.html). In short, if your libvirt has been compiled with Polkit support (ex: Arch, Fedora 21), you can create `/etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules` as follows to grant full access to libvirt to `$USER` @@ -125,7 +125,7 @@ There is both an automated way and a manual, customizable way of setting up libv #### Automated setup -There is an automated setup script on https://get.k8s.io that will download the tarball for Kubernetes and spawn a Kubernetes cluster on a local CoreOS instances that the script creates. To run this script, use wget or curl with the KUBERNETES_PROVIDER environment variable set to libvirt-coreos: +There is an automated setup script on [https://get.k8s.io]( https://get.k8s.io ) that will download the tarball for Kubernetes and spawn a Kubernetes cluster on a local CoreOS instances that the script creates. To run this script, use wget or curl with the KUBERNETES_PROVIDER environment variable set to libvirt-coreos: ```shell export KUBERNETES_PROVIDER=libvirt-coreos; wget -q -O - https://get.k8s.io | bash From ac3c40c91d54afb19d3224f927dfebf5ddedb4ee Mon Sep 17 00:00:00 2001 From: chenhuan12 Date: Tue, 12 Sep 2017 11:07:16 +0800 Subject: [PATCH 47/58] fix the command output fix the command output --- .../stateless-application/expose-external-ip-address.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/stateless-application/expose-external-ip-address.md b/docs/tutorials/stateless-application/expose-external-ip-address.md index 39b7bfaa0c..6d4b0a39bc 100644 --- a/docs/tutorials/stateless-application/expose-external-ip-address.md +++ b/docs/tutorials/stateless-application/expose-external-ip-address.md @@ -85,6 +85,7 @@ external IP address. Name: my-service Namespace: default Labels: run=load-balancer-example + Annotations: Selector: run=load-balancer-example Type: LoadBalancer IP: 10.3.245.137 @@ -93,7 +94,7 @@ external IP address. NodePort: 32377/TCP Endpoints: 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2 more... Session Affinity: None - Events: + Events: Make a note of the external IP address exposed by your service. In this example, the external IP address is 104.198.205.71. Also note From 6dabd96cd67b211b359facae0422d976122ead79 Mon Sep 17 00:00:00 2001 From: jianglingxia Date: Tue, 12 Sep 2017 16:21:46 +0800 Subject: [PATCH 48/58] fix typo of configure-volume-storage --- docs/tasks/configure-pod-container/configure-volume-storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/configure-pod-container/configure-volume-storage.md b/docs/tasks/configure-pod-container/configure-volume-storage.md index d2f945097b..56b839619e 100644 --- a/docs/tasks/configure-pod-container/configure-volume-storage.md +++ b/docs/tasks/configure-pod-container/configure-volume-storage.md @@ -40,7 +40,7 @@ restarts. Here is the configuration file for the Pod: 1. Verify that the Pod's Container is running, and then watch for changes to the Pod: - kubectl get --watch pod redis + kubectl get pod redis --watch The output looks like this: From 48714d5c9d5fe9c20c75fb5af526f0b4fda3e919 Mon Sep 17 00:00:00 2001 From: kairen Date: Mon, 11 Sep 2017 01:21:20 +0800 Subject: [PATCH 49/58] Remove manual deploy on Ubuntu --- _data/setup.yml | 1 - docs/getting-started-guides/ubuntu/manual.md | 308 ------------------- docs/setup/pick-right-solution.md | 1 - 3 files changed, 310 deletions(-) delete mode 100644 docs/getting-started-guides/ubuntu/manual.md diff --git a/_data/setup.yml b/_data/setup.yml index 576fe257c0..86d591f46d 100644 --- a/_data/setup.yml +++ b/_data/setup.yml @@ -94,7 +94,6 @@ toc: - docs/getting-started-guides/ubuntu/glossary.md - docs/getting-started-guides/ubuntu/local.md - docs/getting-started-guides/ubuntu/logging.md - - docs/getting-started-guides/ubuntu/manual.md - docs/getting-started-guides/windows/index.md diff --git a/docs/getting-started-guides/ubuntu/manual.md b/docs/getting-started-guides/ubuntu/manual.md deleted file mode 100644 index 7957e10bef..0000000000 --- a/docs/getting-started-guides/ubuntu/manual.md +++ /dev/null @@ -1,308 +0,0 @@ ---- -approvers: -- thockin -title: Manually Deploying Kubernetes on Ubuntu Nodes ---- - -{% capture overview %} -This document describes how to deploy Kubernetes on ubuntu nodes, 1 master and 3 nodes involved -in the given examples. You can scale to **any number of nodes** by changing some settings with ease. -The original idea was heavily inspired by @jainvipin 's ubuntu single node -work, which has been merge into this document. -{% endcapture %} - -The scripting referenced here can be used to deploy Kubernetes with -networking based either on Flannel or on a CNI plugin that you supply. -This document is focused on the Flannel case. See -`kubernetes/cluster/ubuntu/config-default.sh` for remarks on how to -use a CNI plugin instead. - -[Cloud team from Zhejiang University](https://github.com/ZJU-SEL) will maintain this work. - -{% capture prerequisites %} -## Prerequisites - -1. The nodes have installed docker version 1.2+ and bridge-utils to manipulate linux bridge. -2. All machines can communicate with each other. Master node needs to be connected to the -Internet to download the necessary files, while worker nodes do not. -3. These guide is tested OK on Ubuntu 14.04 LTS 64bit server, but it can not work with -Ubuntu 15 which uses systemd instead of upstart. -4. Dependencies of this guide: etcd-2.2.1, flannel-0.5.5, k8s-1.2.0, may work with higher versions. -5. All the remote servers can be ssh logged in without a password by using key authentication. -6. The remote user on all machines is using /bin/bash as its login shell, and has sudo access. -{% endcapture %} - -{% capture steps %} -## Starting a Cluster - -### Set up working directory - -Clone the Kubernetes github repo locally - -```shell -$ git clone --depth 1 https://github.com/kubernetes/kubernetes.git -``` - -#### Configure and start the Kubernetes cluster - -The startup process will first download all the required binaries automatically. -By default etcd version is 2.2.1, flannel version is 0.5.5 and k8s version is 1.2.0. -You can customize your etcd version, flannel version, k8s version by changing corresponding variables -`ETCD_VERSION` , `FLANNEL_VERSION` and `KUBE_VERSION` like following. - -```shell -$ export KUBE_VERSION=1.2.0 -$ export FLANNEL_VERSION=0.5.0 -$ export ETCD_VERSION=2.2.0 -``` - -**Note** - -For users who want to bring up a cluster with k8s version v1.1.1, `controller manager` may fail to start -due to [a known issue](https://github.com/kubernetes/kubernetes/issues/17109). You could raise it -up manually by using following command on the remote master server. Note that -you should do this only after `api-server` is up. Moreover, this issue is fixed in v1.1.2 and later. - -```shell -$ sudo service kube-controller-manager start -``` - -Note that we use flannel here to set up overlay network, yet it's optional. Actually you can build up k8s -cluster natively, or use flannel, Open vSwitch or any other SDN tool you like. - -An example cluster is listed below: - -```shell -| IP Address | Role | -|-------------|----------| -|10.10.103.223| node | -|10.10.103.162| node | -|10.10.103.250| both master and node| -``` - -First configure the cluster information in cluster/ubuntu/config-default.sh, following is a simple sample. - -```shell -export nodes="vcap@10.10.103.250 vcap@10.10.103.162 vcap@10.10.103.223" - -export roles="ai i i" - -export NUM_NODES=${NUM_NODES:-3} - -export SERVICE_CLUSTER_IP_RANGE=192.168.3.0/24 - -export FLANNEL_NET=172.16.0.0/16 -``` - -The first variable `nodes` defines all your cluster nodes, master node comes first and -separated with blank space like ` ` - -Then the `roles` variable defines the roles of above machine in the same order, "ai" stands for machine -acts as both master and node, "a" stands for master, "i" stands for node. - -The `NUM_NODES` variable defines the total number of nodes. - -The `SERVICE_CLUSTER_IP_RANGE` variable defines the Kubernetes service IP range. Please make sure -that you do have a valid private ip range defined here, because some IaaS provider may reserve private ips. -You can use below three private network range according to rfc1918. Besides you'd better not choose the one -that conflicts with your own private network range. - -```shell -10.0.0.0 - 10.255.255.255 (10/8 prefix) - -172.16.0.0 - 172.31.255.255 (172.16/12 prefix) - -192.168.0.0 - 192.168.255.255 (192.168/16 prefix) -``` - -The `FLANNEL_NET` variable defines the IP range used for flannel overlay network, -should not conflict with above `SERVICE_CLUSTER_IP_RANGE`. -You can optionally provide additional Flannel network configuration -through `FLANNEL_BACKEND` and `FLANNEL_OTHER_NET_CONFIG`, as explained in `cluster/ubuntu/config-default.sh`. - -The default setting for `ADMISSION_CONTROL` is right for the latest -release of Kubernetes, but if you choose an earlier release then you -might want a different setting. See -[the admission control doc](/docs/admin/admission-controllers/#is-there-a-recommended-set-of-plug-ins-to-use) -for the recommended settings for various releases. - -**Note:** When deploying, master needs to be connected to the Internet to download the necessary files. -If your machines are located in a private network that need proxy setting to connect the Internet, -you can set the config `PROXY_SETTING` in cluster/ubuntu/config-default.sh such as: - - PROXY_SETTING="http_proxy=http://server:port https_proxy=https://server:port" - -After all the above variables being set correctly, we can use following command in `cluster/` directory to -bring up the whole cluster. - -```shell -$ KUBERNETES_PROVIDER=ubuntu ./kube-up.sh -``` - -The scripts automatically copy binaries and config files to all the machines via `scp` and start Kubernetes -service on them. The only thing you need to do is to type the sudo password when promoted. - -```shell -Deploying node on machine 10.10.103.223 -... -[sudo] password to start node: -``` - -If everything works correctly, you will see the following message from console indicating the k8s cluster is up. - -```shell -Cluster validation succeeded -``` - -### Test it out - -You can use `kubectl` command to check if the newly created cluster is working correctly. -The `kubectl` binary is under the `cluster/ubuntu/binaries` directory. -You can make it available via PATH, then you can use the below command smoothly. - -For example, use `$ kubectl get nodes` to see if all of your nodes are ready. - -```shell -$ kubectl get nodes -NAME STATUS AGE VERSION -10.10.103.162 Ready 3d v1.6.0+fff5156 -10.10.103.223 Ready 3d v1.6.0+fff5156 -10.10.103.250 Ready 3d v1.6.0+fff5156 -``` - -Also you can run Kubernetes [guest-example](https://github.com/kubernetes/examples/tree/{{page.githubbranch}}/guestbook/) to build a redis backend cluster. - - -### Deploy addons - -Assuming you have a starting cluster now, this section will tell you how to deploy addons like DNS -and UI onto the existing cluster. - -The configuration of DNS is configured in cluster/ubuntu/config-default.sh. - -```shell -ENABLE_CLUSTER_DNS="${KUBE_ENABLE_CLUSTER_DNS:-true}" - -DNS_SERVER_IP="192.168.3.10" - -DNS_DOMAIN="cluster.local" - -DNS_REPLICAS=1 -``` - -The `DNS_SERVER_IP` is defining the ip of dns server which must be in the `SERVICE_CLUSTER_IP_RANGE`. -The `DNS_REPLICAS` describes how many dns pod running in the cluster. - -By default, we also take care of kube-ui addon. - -```shell -ENABLE_CLUSTER_UI="${KUBE_ENABLE_CLUSTER_UI:-true}" -``` - -After all the above variables have been set, just type the following command. - -```shell -$ cd cluster/ubuntu -$ KUBERNETES_PROVIDER=ubuntu ./deployAddons.sh -``` - -After some time, you can use `$ kubectl get pods --namespace=kube-system` to see the DNS and UI pods are running in the cluster. - -### On going - -We are working on these features which we'd like to let everybody know: - -1. Run Kubernetes binaries in Docker using [kube-in-docker](https://github.com/ZJU-SEL/kube-in-docker/tree/baremetal-kube), -to eliminate OS-distro differences. -2. Tearing Down scripts: clear and re-create the whole stack by one click. - -### Troubleshooting - -Generally, what this approach does is quite simple: - -1. Download and copy binaries and configuration files to proper directories on every node. -2. Configure `etcd` for master node using IPs based on input from user. -3. Create and start flannel network for worker nodes. - -So if you encounter a problem, check etcd configuration of master node first. - -1. Check `/var/log/upstart/etcd.log` for suspicious etcd log -2. You may find following commands useful, the former one to bring down the cluster, while the latter one could start it again. - -```shell -$ KUBERNETES_PROVIDER=ubuntu ./kube-down.sh -$ KUBERNETES_PROVIDER=ubuntu ./kube-up.sh -``` - -3. You can also customize your own settings in `/etc/default/{component_name}` and restart it via -`$ sudo service {component_name} restart`. - - -## Upgrading a Cluster - -If you already have a Kubernetes cluster, and want to upgrade to a new version, -you can use following command in `cluster/` directory to update the whole cluster -or a specified node to a new version. - -```shell -$ KUBERNETES_PROVIDER=ubuntu ./kube-push.sh [-m|-n ] -``` - -It can be done for all components (by default), master(`-m`) or specified node(`-n`). -Upgrading a single node is currently experimental. -If the version is not specified, the script will try to use local binaries. You should ensure all -the binaries are well prepared in the expected directory path cluster/ubuntu/binaries. - -```shell -$ tree cluster/ubuntu/binaries -binaries/ -├── kubectl -├── master -│   ├── etcd -│   ├── etcdctl -│   ├── flanneld -│   ├── kube-apiserver -│   ├── kube-controller-manager -│   └── kube-scheduler -└── minion - ├── flanneld - ├── kubelet - └── kube-proxy -``` - -You can use following command to get a help. - -```shell -$ KUBERNETES_PROVIDER=ubuntu ./kube-push.sh -h -``` - -Here are some examples: - -* upgrade master to version 1.0.5: `$ KUBERNETES_PROVIDER=ubuntu ./kube-push.sh -m 1.0.5` -* upgrade node `vcap@10.10.103.223` to version 1.0.5 : `$ KUBERNETES_PROVIDER=ubuntu ./kube-push.sh -n 10.10.103.223 1.0.5` -* upgrade master and all nodes to version 1.0.5: `$ KUBERNETES_PROVIDER=ubuntu ./kube-push.sh 1.0.5` - -The script will not delete any resources of your cluster, it just replaces the binaries. - -### Test it out - -You can use the `kubectl` command to check if the newly upgraded Kubernetes cluster is working correctly. - -To make sure the version of the upgraded cluster is what you expect, you will find these commands helpful. - -* upgrade all components or master: `$ kubectl version`. Check the *Server Version*. -* upgrade node `vcap@10.10.102.223`: `$ ssh -t vcap@10.10.102.223 'cd /opt/bin && sudo ./kubelet --version'`* -{% endcapture %} - - -## Support Level - - -IaaS Provider | Config. Mgmt | OS | Networking | Docs | Conforms | Support Level --------------------- | ------------ | ------ | ---------- | --------------------------------------------- | ---------| ---------------------------- -Bare-metal | custom | Ubuntu | flannel | [docs](/docs/getting-started-guides/ubuntu) | | Community ([@resouer](https://github.com/resouer), [@WIZARD-CXY](https://github.com/WIZARD-CXY)) - - -For support level information on all solutions, see the [Table of solutions](/docs/getting-started-guides/#table-of-solutions) chart. - -{% include templates/task.md %} diff --git a/docs/setup/pick-right-solution.md b/docs/setup/pick-right-solution.md index 2b05534ff4..5c65f1a38c 100644 --- a/docs/setup/pick-right-solution.md +++ b/docs/setup/pick-right-solution.md @@ -120,7 +120,6 @@ These solutions are combinations of cloud providers and operating systems not co * [Fedora (Multi Node)](/docs/getting-started-guides/fedora/flannel_multi_node_cluster) * [CentOS](/docs/getting-started-guides/centos/centos_manual_config) * [Kubernetes on Ubuntu](/docs/getting-started-guides/ubuntu/) -* [Manually Deploying Kubernetes on Ubuntu Nodes](/docs/getting-started-guides/ubuntu/manual) * [CoreOS on AWS or GCE](/docs/getting-started-guides/coreos) ## Integrations From 97f089ed881ffd60423cd271eb0b78252be3094d Mon Sep 17 00:00:00 2001 From: Kyle Bai Date: Wed, 13 Sep 2017 03:21:34 +0800 Subject: [PATCH 50/58] Unified use of YAML for Secret example (#5418) * Unified use of YAML for Secret example * Fix dotfiles in secret volume yaml --- docs/concepts/configuration/secret.md | 482 ++++++++++---------------- 1 file changed, 187 insertions(+), 295 deletions(-) diff --git a/docs/concepts/configuration/secret.md b/docs/concepts/configuration/secret.md index 23a1dc1401..102eee8648 100644 --- a/docs/concepts/configuration/secret.md +++ b/docs/concepts/configuration/secret.md @@ -182,32 +182,23 @@ To consume a Secret in a volume in a Pod: This is an example of a pod that mounts a secret in a volume: -```json -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "mypod", - "namespace": "myns" - }, - "spec": { - "containers": [{ - "name": "mypod", - "image": "redis", - "volumeMounts": [{ - "name": "foo", - "mountPath": "/etc/foo", - "readOnly": true - }] - }], - "volumes": [{ - "name": "foo", - "secret": { - "secretName": "mysecret" - } - }] - } -} +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret ``` Each secret you want to use needs to be referred to in `spec.volumes`. @@ -222,36 +213,26 @@ You can package many files into one secret, or use many secrets, whichever is co We can also control the paths within the volume where Secret keys are projected. You can use `spec.volumes[].secret.items` field to change target path of each key: -```json -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "mypod", - "namespace": "myns" - }, - "spec": { - "containers": [{ - "name": "mypod", - "image": "redis", - "volumeMounts": [{ - "name": "foo", - "mountPath": "/etc/foo", - "readOnly": true - }] - }], - "volumes": [{ - "name": "foo", - "secret": { - "secretName": "mysecret", - "items": [{ - "key": "username", - "path": "my-group/my-username" - }] - } - }] - } -} +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + items: + - key: username + path: my-group/my-username ``` What will happen: @@ -271,32 +252,23 @@ mode for the whole secret volume and override per key if needed. For example, you can specify a default mode like this: -```json -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "mypod", - "namespace": "myns" - }, - "spec": { - "containers": [{ - "name": "mypod", - "image": "redis", - "volumeMounts": [{ - "name": "foo", - "mountPath": "/etc/foo" - }] - }], - "volumes": [{ - "name": "foo", - "secret": { - "secretName": "mysecret", - "defaultMode": 256 - } - }] - } -} +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + defaultMode: 256 ``` Then, the secret will be mounted on `/etc/foo` and all the files created by the @@ -309,36 +281,26 @@ notation to specify permissions in a more natural way. You can also use mapping, as in the previous example, and specify different permission for different files like this: -```json -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "mypod", - "namespace": "myns" - }, - "spec": { - "containers": [{ - "name": "mypod", - "image": "redis", - "volumeMounts": [{ - "name": "foo", - "mountPath": "/etc/foo" - }] - }], - "volumes": [{ - "name": "foo", - "secret": { - "secretName": "mysecret", - "items": [{ - "key": "username", - "path": "my-group/my-username", - "mode": 511 - }] - } - }] - } -} +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + items: + - key: username + path: my-group/my-username + mode: 511 ``` In this case, the file resulting in `/etc/foo/my-group/my-username` will have @@ -393,19 +355,19 @@ metadata: name: secret-env-pod spec: containers: - - name: mycontainer - image: redis - env: - - name: SECRET_USERNAME - valueFrom: - secretKeyRef: - name: mysecret - key: username - - name: SECRET_PASSWORD - valueFrom: - secretKeyRef: - name: mysecret - key: password + - name: mycontainer + image: redis + env: + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + - name: SECRET_PASSWORD + valueFrom: + secretKeyRef: + name: mysecret + key: password restartPolicy: Never ``` @@ -515,40 +477,25 @@ $ kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/ Now we can create a pod which references the secret with the ssh key and consumes it in a volume: -```json -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "secret-test-pod", - "labels": { - "name": "secret-test" - } - }, - "spec": { - "volumes": [ - { - "name": "secret-volume", - "secret": { - "secretName": "ssh-key-secret" - } - } - ], - "containers": [ - { - "name": "ssh-test-container", - "image": "mySshImage", - "volumeMounts": [ - { - "name": "secret-volume", - "readOnly": true, - "mountPath": "/etc/secret-volume" - } - ] - } - ] - } -} +```yaml +kind: Pod +apiVersion: v1 +metadata: + name: secret-test-pod + labels: + name: secret-test +spec: + volumes: + - name: secret-volume + secret: + secretName: ssh-key-secret + containers: + - name: ssh-test-container + image: mySshImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` When the container's command runs, the pieces of the key will be available in: @@ -577,78 +524,46 @@ secret "test-db-secret" created Now make the pods: -```json -{ - "apiVersion": "v1", - "kind": "List", - "items": - [{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "prod-db-client-pod", - "labels": { - "name": "prod-db-client" - } - }, - "spec": { - "volumes": [ - { - "name": "secret-volume", - "secret": { - "secretName": "prod-db-secret" - } - } - ], - "containers": [ - { - "name": "db-client-container", - "image": "myClientImage", - "volumeMounts": [ - { - "name": "secret-volume", - "readOnly": true, - "mountPath": "/etc/secret-volume" - } - ] - } - ] - } - }, - { - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "test-db-client-pod", - "labels": { - "name": "test-db-client" - } - }, - "spec": { - "volumes": [ - { - "name": "secret-volume", - "secret": { - "secretName": "test-db-secret" - } - } - ], - "containers": [ - { - "name": "db-client-container", - "image": "myClientImage", - "volumeMounts": [ - { - "name": "secret-volume", - "readOnly": true, - "mountPath": "/etc/secret-volume" - } - ] - } - ] - } - }] -} +```yaml +apiVersion: v1 +kind: List +items: +- kind: Pod + apiVersion: v1 + metadata: + name: prod-db-client-pod + labels: + name: prod-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: prod-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +- kind: Pod + apiVersion: v1 + metadata: + name: test-db-client-pod + labels: + name: test-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: test-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` Both containers will have the following files present on their filesystems with the values for each container's environment: @@ -665,26 +580,18 @@ You could further simplify the base pod specification by using two Service Accou one called, say, `prod-user` with the `prod-db-secret`, and one called, say, `test-user` with the `test-db-secret`. Then, the pod spec can be shortened to, for example: -```json -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "prod-db-client-pod", - "labels": { - "name": "prod-db-client" - } - }, - "spec": { - "serviceAccount": "prod-db-client", - "containers": [ - { - "name": "db-client-container", - "image": "myClientImage" - } - ] - } -} +```yaml +kind: Pod +apiVersion: v1 +metadata: + name: prod-db-client-pod + labels: + name: prod-db-client +spec: + serviceAccount: prod-db-client + containers: + - name: db-client-container + image: myClientImage ``` ### Use-case: Dotfiles in secret volume @@ -692,49 +599,34 @@ one called, say, `prod-user` with the `prod-db-secret`, and one called, say, In order to make piece of data 'hidden' (i.e., in a file whose name begins with a dot character), simply make that key begin with a dot. For example, when the following secret is mounted into a volume: -```json -{ - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": "dotfile-secret" - }, - "data": { - ".secret-file": "dmFsdWUtMg0KDQo=" - } -} - -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "secret-dotfiles-pod" - }, - "spec": { - "volumes": [ - { - "name": "secret-volume", - "secret": { - "secretName": "dotfile-secret" - } - } - ], - "containers": [ - { - "name": "dotfile-test-container", - "image": "gcr.io/google_containers/busybox", - "command": [ "ls", "-l", "/etc/secret-volume" ], - "volumeMounts": [ - { - "name": "secret-volume", - "readOnly": true, - "mountPath": "/etc/secret-volume" - } - ] - } - ] - } -} +```yaml +kind: Secret +apiVersion: v1 +metadata: + name: dotfile-secret +data: + .secret-file: dmFsdWUtMg0KDQo= +--- +kind: Pod +apiVersion: v1 +metadata: + name: secret-dotfiles-pod +spec: + volumes: + - name: secret-volume + secret: + secretName: dotfile-secret + containers: + - name: dotfile-test-container + image: gcr.io/google_containers/busybox + command: + - ls + - "-l" + - "/etc/secret-volume" + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` @@ -798,7 +690,7 @@ reference a secret then `watch` the resource, re-requesting the secret when the reference changes. Additionally, a ["bulk watch" API]( https://github.com/kubernetes/community/blob/master/contributors/design-proposals/bulk_watch.md) to let clients `watch` individual resources has also been proposed, and will likely -be available in future releases of Kubernetes. +be available in future releases of Kubernetes. ## Security Properties From 9e198467064133e8c291a97bb0178f67cce89349 Mon Sep 17 00:00:00 2001 From: kairen Date: Wed, 13 Sep 2017 20:41:01 +0800 Subject: [PATCH 51/58] Fix typo and examples --- docs/concepts/storage/persistent-volumes.md | 72 +++++++++++---------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/docs/concepts/storage/persistent-volumes.md b/docs/concepts/storage/persistent-volumes.md index ef67f78e8b..c708ef0181 100644 --- a/docs/concepts/storage/persistent-volumes.md +++ b/docs/concepts/storage/persistent-volumes.md @@ -86,7 +86,7 @@ However, an administrator can configure a custom recycler pod template using the apiVersion: v1 kind: Pod metadata: - name: pv-recycler- + name: pv-recycler namespace: default spec: restartPolicy: Never @@ -128,7 +128,7 @@ For volume plugins that support the Delete reclaim policy, deletion removes both * Glusterfs * VsphereVolume * Quobyte Volumes -* HostPath (single node testing only -- local storage is not supported in any way and WILL NOT WORK in a multi-node cluster) +* HostPath (Single node testing only -- local storage is not supported in any way and WILL NOT WORK in a multi-node cluster) * VMware Photon * Portworx Volumes * ScaleIO Volumes @@ -139,20 +139,20 @@ For volume plugins that support the Delete reclaim policy, deletion removes both Each PV contains a spec and status, which is the specification and status of the volume. ```yaml - apiVersion: v1 - kind: PersistentVolume - metadata: - name: pv0003 - spec: - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - persistentVolumeReclaimPolicy: Recycle - storageClassName: slow - nfs: - path: /tmp - server: 172.17.0.2 +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0003 +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Recycle + storageClassName: slow + nfs: + path: /tmp + server: 172.17.0.2 ``` ### Capacity @@ -220,7 +220,7 @@ it will become fully deprecated in a future Kubernetes release. Current reclaim policies are: * Retain -- manual reclamation -* Recycle -- basic scrub ("rm -rf /thevolume/*") +* Recycle -- basic scrub (`rm -rf /thevolume/*`) * Delete -- associated storage asset such as AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder volume is deleted Currently, only NFS and HostPath support recycling. AWS EBS, GCE PD, Azure Disk, and Cinder volumes support deletion. @@ -591,7 +591,7 @@ parameters: ```yaml kind: StorageClass -apiVersion: storage.k8s.io/v1beta1 +apiVersion: storage.k8s.io/v1 metadata: name: fast provisioner: kubernetes.io/vsphere-volume @@ -607,7 +607,7 @@ parameters: ```yaml kind: StorageClass -apiVersion: storage.k8s.io/v1beta1 +apiVersion: storage.k8s.io/v1 metadata: name: vsan-policy-fast provisioner: kubernetes.io/vsphere-volume @@ -639,22 +639,22 @@ You can see [vSphere example](https://github.com/kubernetes/examples/tree/master #### Ceph RBD ```yaml - apiVersion: storage.k8s.io/v1 - kind: StorageClass - metadata: - name: fast - provisioner: kubernetes.io/rbd - parameters: - monitors: 10.16.153.105:6789 - adminId: kube - adminSecretName: ceph-secret - adminSecretNamespace: kube-system - pool: kube - userId: kube - userSecretName: ceph-secret-user - fsType: ext4 - imageFormat: "2" - imageFeatures: "layering" +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: fast +provisioner: kubernetes.io/rbd +parameters: + monitors: 10.16.153.105:6789 + adminId: kube + adminSecretName: ceph-secret + adminSecretNamespace: kube-system + pool: kube + userId: kube + userSecretName: ceph-secret-user + fsType: ext4 + imageFormat: "2" + imageFeatures: "layering" ``` * `monitors`: Ceph monitors, comma delimited. This parameter is required. @@ -785,6 +785,7 @@ parameters: * `ephemeral`: specifies whether the volume should be cleaned-up after unmount or should be persistent. `emptyDir` use case can set this value to true and `persistent volumes` use case such as for databases like Cassandra should set to false, [true/false] (default `false`). A string is expected here i.e. `"true"` and not `true`. #### ScaleIO + ```yaml kind: StorageClass apiVersion: storage.k8s.io/v1 @@ -821,6 +822,7 @@ $> kubectl create secret generic sio-secret --type="kubernetes.io/scaleio" --fro ``` #### StorageOS + ```yaml kind: StorageClass apiVersion: storage.k8s.io/v1 From d13227afa4a6f0fce9ad97a6ce877edd27c7e4b3 Mon Sep 17 00:00:00 2001 From: Samuel Giles Date: Wed, 13 Sep 2017 15:33:58 +0100 Subject: [PATCH 52/58] Typo in environment variable `KUBECONGIG` -> `KUBECONFIG` --- .../configuration/organize-cluster-access-kubeconfig.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/configuration/organize-cluster-access-kubeconfig.md b/docs/concepts/configuration/organize-cluster-access-kubeconfig.md index 3fd78f0ac4..78a63da117 100644 --- a/docs/concepts/configuration/organize-cluster-access-kubeconfig.md +++ b/docs/concepts/configuration/organize-cluster-access-kubeconfig.md @@ -50,7 +50,7 @@ credentials of the user listed in the current context. ## The KUBECONFIG environment variable -The `KUBECONGIG` environment variable holds a list of kubeconfig files. +The `KUBECONFIG` environment variable holds a list of kubeconfig files. For Linux and Mac, the list is colon-delimited. For Windows, the list is semicolon-delimited. The `KUBECONFIG` environment variable is not required. If the `KUBECONFIG` environment variable doesn't exist, From 34d2a2e7f25d8075a86fab21a03f606b73d92ab2 Mon Sep 17 00:00:00 2001 From: Weibin Lin Date: Thu, 14 Sep 2017 06:40:32 +0800 Subject: [PATCH 53/58] fix typos in /admin/authorization/rbac.md (#5427) --- docs/admin/authorization/rbac.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/admin/authorization/rbac.md b/docs/admin/authorization/rbac.md index 5eae556f61..23d36f7185 100644 --- a/docs/admin/authorization/rbac.md +++ b/docs/admin/authorization/rbac.md @@ -102,7 +102,7 @@ This allows administrators to define a set of common roles for the entire cluste then reuse them within multiple namespaces. For instance, even though the following `RoleBinding` refers to a `ClusterRole`, -"dave" (the subject) will only be able read secrets in the "development" +"dave" (the subject) will only be able to read secrets in the "development" namespace (the namespace of the `RoleBinding`). ```yaml @@ -258,7 +258,7 @@ A `RoleBinding` or `ClusterRoleBinding` binds a role to *subjects*. Subjects can be groups, users or service accounts. Users are represented by strings. These can be plain usernames, like -"alice", email-style names, like "bob@example.com", or numeric ids +"alice", email-style names, like "bob@example.com", or numeric IDs represented as a string. It is up to the Kubernetes admin to configure the [authentication modules](/docs/admin/authentication/) to produce usernames in the desired format. The RBAC authorization system does From bfecfa7f9c109924fca5dba8eaccf25ac15bd56e Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Wed, 13 Sep 2017 19:31:14 -0700 Subject: [PATCH 54/58] Link to persistent volume tutorial from concept doc (#5447) Signed-off-by: Ahmet Alp Balkan --- docs/concepts/storage/volumes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/concepts/storage/volumes.md b/docs/concepts/storage/volumes.md index d58e2717b8..8a4ae45fd8 100644 --- a/docs/concepts/storage/volumes.md +++ b/docs/concepts/storage/volumes.md @@ -849,4 +849,8 @@ several media types. {% endcapture %} +{% capture whatsnext %} +* Follow an example of [deploying WordPress and MySQL with Persistent Volumes](/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/). +{% endcapture %} + {% include templates/concept.md %} From db3f59bea592b93413ef8fb37446bfe63e7aab68 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Wed, 13 Sep 2017 19:37:35 -0700 Subject: [PATCH 55/58] Link cassandra statefulset tutorial from the guide (#5446) Signed-off-by: Ahmet Alp Balkan --- docs/concepts/workloads/controllers/statefulset.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/concepts/workloads/controllers/statefulset.md b/docs/concepts/workloads/controllers/statefulset.md index 52168247c7..e06551d6d4 100644 --- a/docs/concepts/workloads/controllers/statefulset.md +++ b/docs/concepts/workloads/controllers/statefulset.md @@ -226,6 +226,7 @@ update, roll out a canary, or perform a phased roll out. {% capture whatsnext %} * Follow an example of [deploying a stateful application](/docs/tutorials/stateful-application/basic-stateful-set). +* Follow an example of [deploying Cassandra with Stateful Sets](/docs/tutorials/stateful-application/cassandra/). {% endcapture %} {% include templates/concept.md %} From ccb82b10f2fd03761c89514a07085a43bb38de9f Mon Sep 17 00:00:00 2001 From: Kyle Bai Date: Thu, 14 Sep 2017 10:39:01 +0800 Subject: [PATCH 56/58] Fix init containers code block (#5428) --- docs/concepts/workloads/pods/init-containers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/concepts/workloads/pods/init-containers.md b/docs/concepts/workloads/pods/init-containers.md index 73cb6b5b40..e902b296c6 100644 --- a/docs/concepts/workloads/pods/init-containers.md +++ b/docs/concepts/workloads/pods/init-containers.md @@ -150,7 +150,7 @@ spec: Yaml file below outlines the `mydb` and `myservice` services: -``` +```yaml kind: Service apiVersion: v1 metadata: @@ -174,7 +174,7 @@ spec: This Pod can be started and debugged with the following commands: -``` +```shell $ kubectl create -f myapp.yaml pod "myapp-pod" created $ kubectl get -f myapp.yaml @@ -220,7 +220,7 @@ $ kubectl logs myapp-pod -c init-mydb # Inspect the second init container Once we start the `mydb` and `myservice` services, we can see the Init Containers complete and the `myapp-pod` is created: -``` +```shell $ kubectl create -f services.yaml service "myservice" created service "mydb" created From c912140727d48f814f6247c7a443c696b29cd30f Mon Sep 17 00:00:00 2001 From: Jun Xiang Tee Date: Wed, 13 Sep 2017 19:43:00 -0700 Subject: [PATCH 57/58] update wordpress and mysql PV doc to use apps/v1beta2 APIs (#5424) --- .../mysql-wordpress-persistent-volume/mysql-deployment.yaml | 6 +++++- .../wordpress-deployment.yaml | 6 +++++- .../mysql-wordpress-persistent-volume.md | 2 +- .../mysql-wordpress-persistent-volume/mysql-deployment.yaml | 6 +++++- .../wordpress-deployment.yaml | 6 +++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml b/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml index 2253600de6..ce3eb1bf74 100644 --- a/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml +++ b/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml @@ -25,13 +25,17 @@ spec: requests: storage: 20Gi --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1beta2 kind: Deployment metadata: name: wordpress-mysql labels: app: wordpress spec: + selector: + matchLabels: + app: wordpress + tier: mysql strategy: type: Recreate template: diff --git a/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml b/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml index e15edc5998..c354cdef88 100644 --- a/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml +++ b/cn/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml @@ -25,13 +25,17 @@ spec: requests: storage: 20Gi --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1beta2 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: + selector: + matchLabels: + app: wordpress + tier: frontend strategy: type: Recreate template: diff --git a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume.md b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume.md index 217c0c9bfd..afce6bd65d 100644 --- a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume.md +++ b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume.md @@ -151,7 +151,7 @@ The following manifest describes a single-instance WordPress Deployment and Serv You should see the WordPress set up page similar to the following screenshot. - ![wordpress-init](https://github.com/kubernetes/examples/blob/master/mysql-wordpress-pd/WordPress.png) + ![wordpress-init](https://raw.githubusercontent.com/kubernetes/examples/master/mysql-wordpress-pd/WordPress.png) **Warning:** Do not leave your WordPress installation on this page. If another user finds it, they can set up a website on your instance and use it to serve malicious content.

Either install WordPress by creating a username and password or delete your instance. {: .warning} diff --git a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml index 2253600de6..ce3eb1bf74 100644 --- a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml +++ b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/mysql-deployment.yaml @@ -25,13 +25,17 @@ spec: requests: storage: 20Gi --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1beta2 kind: Deployment metadata: name: wordpress-mysql labels: app: wordpress spec: + selector: + matchLabels: + app: wordpress + tier: mysql strategy: type: Recreate template: diff --git a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml index e15edc5998..c354cdef88 100644 --- a/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml +++ b/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/wordpress-deployment.yaml @@ -25,13 +25,17 @@ spec: requests: storage: 20Gi --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1beta2 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: + selector: + matchLabels: + app: wordpress + tier: frontend strategy: type: Recreate template: From d428cf6581c3ceaa991c9dffa88d1b888481cd0e Mon Sep 17 00:00:00 2001 From: emanic Date: Wed, 13 Sep 2017 19:46:14 -0700 Subject: [PATCH 58/58] Adds link to Calico install instructions (#5423) --- docs/tasks/administer-cluster/calico-network-policy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/administer-cluster/calico-network-policy.md b/docs/tasks/administer-cluster/calico-network-policy.md index 8409bc5576..4543aa7069 100644 --- a/docs/tasks/administer-cluster/calico-network-policy.md +++ b/docs/tasks/administer-cluster/calico-network-policy.md @@ -9,7 +9,7 @@ This page shows how to use Calico for NetworkPolicy. {% endcapture %} {% capture prerequisites %} -* Install Calico for Kubernetes. +* [Install Calico for Kubernetes](https://docs.projectcalico.org/latest/getting-started/kubernetes/installation/). {% endcapture %} {% capture steps %}