From 105bf6e1f2fb93ccf119f34b08c3122645e6a0fe Mon Sep 17 00:00:00 2001 From: Slava Semushin Date: Mon, 16 Jan 2017 17:55:46 +0100 Subject: [PATCH 01/17] docs/user-guide/secrets: fix invalid syntax of Pod.spec.containers.command. --- docs/user-guide/secrets/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/secrets/index.md b/docs/user-guide/secrets/index.md index 8388dac53f..9723e00aee 100644 --- a/docs/user-guide/secrets/index.md +++ b/docs/user-guide/secrets/index.md @@ -763,7 +763,7 @@ make that key begin with a dot. For example, when the following secret is mount { "name": "dotfile-test-container", "image": "gcr.io/google_containers/busybox", - "command": "ls -l /etc/secret-volume", + "command": [ "ls", "-l", "/etc/secret-volume" ], "volumeMounts": [ { "name": "secret-volume", From 10c6bc9e65ee371a23263b0433e9c39181075952 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 31 Jan 2017 17:45:03 +0000 Subject: [PATCH 02/17] Fix broken documentation link --- .../configure-pod-container/communicate-containers-same-pod.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/configure-pod-container/communicate-containers-same-pod.md b/docs/tasks/configure-pod-container/communicate-containers-same-pod.md index 815ee8dc19..853169a676 100644 --- a/docs/tasks/configure-pod-container/communicate-containers-same-pod.md +++ b/docs/tasks/configure-pod-container/communicate-containers-same-pod.md @@ -137,7 +137,7 @@ the shared Volume is lost. [composite containers for modular architecture](http://www.slideshare.net/Docker/slideshare-burns). * See -[Configuring a Pod to Use a Volume for Storage](http://localhost:4000/docs/tasks/configure-pod-container/configure-volume-storage/). +[Configuring a Pod to Use a Volume for Storage](/docs/tasks/configure-pod-container/configure-volume-storage/). * See [Volume](/docs/api-reference/v1/definitions/#_v1_volume). From c87772cd92e6e3be95ec7ac23f79fb45e20923ba Mon Sep 17 00:00:00 2001 From: Dave Sewell Date: Tue, 31 Jan 2017 10:43:02 -0500 Subject: [PATCH 03/17] Fix typo in xhyve --- docs/tutorials/stateless-application/hello-minikube.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/stateless-application/hello-minikube.md b/docs/tutorials/stateless-application/hello-minikube.md index a4d9af0e17..187e059b0a 100644 --- a/docs/tutorials/stateless-application/hello-minikube.md +++ b/docs/tutorials/stateless-application/hello-minikube.md @@ -88,7 +88,7 @@ If a proxy server is required, use the following method to start Minikube cluste minikube start --vm-driver=xhyve --docker-env HTTP_PROXY=http://your-http-proxy-host:your-http-proxy-port --docker-env HTTPS_PROXY=http(s)://your-https-proxy-host:your-https-proxy-port ``` -The `--vm-driver=xyhve` flag specifies that you are using Docker for Mac. The +The `--vm-driver=xhyve` flag specifies that you are using Docker for Mac. The default VM driver is VirtualBox. Now set the Minikube context. The context is what determines which cluster From 2dcac111291c03074975e430db62560d9aa5e0a3 Mon Sep 17 00:00:00 2001 From: Matt Singletary Date: Tue, 31 Jan 2017 10:32:31 -0500 Subject: [PATCH 04/17] typo fix --- docs/user-guide/persistent-volumes/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/persistent-volumes/index.md b/docs/user-guide/persistent-volumes/index.md index a1260ac22d..d6245e8198 100644 --- a/docs/user-guide/persistent-volumes/index.md +++ b/docs/user-guide/persistent-volumes/index.md @@ -543,7 +543,7 @@ and need persistent storage, we recommend that you use the following pattern: - Do include PersistentVolumeClaim objects in your bundle of config (alongside Deployments, ConfigMaps, etc). - Do not include PersistentVolume objects in the config, since the user instantiating the config may not have permission to create PersistentVolumes. -- Give the user the option of providing a storage class name when instantating the template. +- Give the user the option of providing a storage class name when instantiating the template. - If the user provides a storage class name, and the cluster is version 1.4 or newer, put that value into the `volume.beta.kubernetes.io/storage-class` annotation of the PVC. This will cause the PVC to match the right storage class if the cluster has StorageClasses enabled by the admin. - If the user does not provide a storage class name or the cluster is version 1.3, then instead put a `volume.alpha.kubernetes.io/storage-class: default` annotation on the PVC. From b3bfa8a906f0ab908b31ddbc445a0e16e9065ba4 Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Mon, 23 Jan 2017 17:13:13 +0100 Subject: [PATCH 05/17] adding fix for load balancer interference with helm --- .../ubuntu/troubleshooting.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/docs/getting-started-guides/ubuntu/troubleshooting.md b/docs/getting-started-guides/ubuntu/troubleshooting.md index e8c055b17a..44b3a34346 100644 --- a/docs/getting-started-guides/ubuntu/troubleshooting.md +++ b/docs/getting-started-guides/ubuntu/troubleshooting.md @@ -105,6 +105,102 @@ charm unit data, etc. Additional application-specific information may be included as well. ## Common Problems +### Load Balancer interfering with Helm + +This section assumes you have a working deployment of Kubernetes via Juju using a Load Balancer for the API, and that you are using Helm to deploy charts. + +To deploy Helm you will have run: + +``` +helm init +$HELM_HOME has been configured at /home/ubuntu/.helm +Tiller (the helm server side component) has been installed into your Kubernetes Cluster. +Happy Helming! +``` + +Then when using helm you may see one of the following errors: + +* Helm doesn't get the version from the Tiller server + +``` +helm version +Client: &version.Version{SemVer:"v2.1.3", GitCommit:"5cbc48fb305ca4bf68c26eb8d2a7eb363227e973", GitTreeState:"clean"} +Error: cannot connect to Tiller +``` + +* Helm cannot install your chart + +``` +helm install --debug +Error: forwarding ports: error upgrading connection: Upgrade request required +``` + +This is caused by the API load balancer not forwarding ports in the context of the helm client-server relationship. To deploy using helm, you will need to follow these steps: + +1. Expose the Kubernetes Master service + +``` +juju expose kubernetes-master +``` + +2. Identify the public IP address of one of your masters + +``` +juju status kubernetes-master +Model Controller Cloud/Region Version +production k8s-admin aws/us-east-1 2.0.0 + +App Version Status Scale Charm Store Rev OS Notes +flannel 0.6.1 active 1 flannel jujucharms 7 ubuntu +kubernetes-master 1.5.1 active 1 kubernetes-master jujucharms 10 ubuntu exposed + +Unit Workload Agent Machine Public address Ports Message +kubernetes-master/0* active idle 5 54.210.100.102 6443/tcp Kubernetes master running. + flannel/0 active idle 54.210.100.102 Flannel subnet 10.1.50.1/24 + +Machine State DNS Inst id Series AZ +5 started 54.210.100.102 i-002b7150639eb183b xenial us-east-1a + +Relation Provides Consumes Type +certificates easyrsa kubernetes-master regular +etcd etcd flannel regular +etcd etcd kubernetes-master regular +cni flannel kubernetes-master regular +loadbalancer kubeapi-load-balancer kubernetes-master regular +cni kubernetes-master flannel subordinate +cluster-dns kubernetes-master kubernetes-worker regular +cni kubernetes-worker flannel subordinate +``` + +In this context the public IP address is 54.210.100.102. + +If you want to access this data programmatically you can use the JSON output: + +``` +juju show-status kubernetes-master --format json | jq --raw-output '.applications."kubernetes-master".units | keys[]' +54.210.100.102 +``` + +3. Update the kubeconfig file + +Identify the kubeconfig file or section used for this cluster, and edit the server configuration. + +By default, it will look like ```https://54.213.123.123:443```. Replace it with the Kubernetes Master endpoint ```https://54.210.100.102:6443``` and save. + +Note that the default port used by CDK for the Kubernetes Master API is 6443 while the port exposed by the load balancer is 443. + +4. Start helming again! + +``` +helm install --debug +Created tunnel using local port: '36749' +SERVER: "localhost:36749" +CHART PATH: /home/ubuntu/.helm/ +NAME: +... +... + +``` ## etcd From 095b4bcf54e4c4408d61590b1b1f051130dfe797 Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Mon, 23 Jan 2017 17:56:00 +0100 Subject: [PATCH 06/17] adding operational hints for people running long lived clusters --- .../ubuntu/operations.md | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 docs/getting-started-guides/ubuntu/operations.md diff --git a/docs/getting-started-guides/ubuntu/operations.md b/docs/getting-started-guides/ubuntu/operations.md new file mode 100644 index 0000000000..53b848978d --- /dev/null +++ b/docs/getting-started-guides/ubuntu/operations.md @@ -0,0 +1,127 @@ +--- +title: Operations +--- + +{% capture overview %} +This page gives recommendations and hints for people managing long lived CDK clusters +{% endcapture %} +{% capture prerequisites %} +This page assumes you understand the basics of Juju and Kubernetes. +{% endcapture %} + +{% capture steps %} +## Managing Juju +### Sizing your controller node + +The Juju Controller: + +* requires about 2 to 2.5GB RAM to operate. +* uses a MongoDB database as a storage backend for the configuration and state of the cluster. This database can grow significantly, and can also be the biggest consumer of CPU cycles on the instance +* aggregates and stores the log data of all services and units. Therefore, significant storage is needed for long lived models. If your intention is to keep the cluster running, make sure to provision at least 64GB for the logs. + +To bootstrap a controller with constraints run the following command: + +``` +juju bootstrap --contraints "mem=8GB cpu-cores=4 root-disk=128G" +``` + +Juju will elect the cheapest instance type matching your constraints on your target cloud. You can also use the ```instance-type``` constraint in conjunction with ```root-disk``` for strict control. For more information about the constraints available, refer to the [official documentation](https://jujucharms.com/docs/stable/reference-constraints) + +### Connecting on the Controller Node + +By default, Juju will create a pair of SSH key that it will use to automate the connection to units. They are stored on the client node in ```~/.local/share/juju/ssh/``` + +After deployment, Juju Controller is a "silent unit" that acts as a proxy between the client and the deployed applications. Nevertheless it can be useful to SSH into it. To do so run the following command from your client node: + +``` +ssh -i ./.local/share/juju/ssh/juju_id_rsa ubuntu@ +``` + +where ```public-ip-of-juju-controller``` can be found in ```~/.local/share/juju/controllers.yaml``` in the ```api-endpoints``` section. + +### Restricting log verbosity + +Log verbosity in Juju is set at the model level. You can adjust it at any time: + +``` +juju add-model cdk-development --config logging-config='=DEBUG;unit=DEBUG' +``` + +and later + +``` +juju config-model cdk-production --config logging-config='=ERROR;unit=ERROR' +``` + +In addition, the jujud daemon is started in debug mode by default on all controllers. To remove that behavior edit ```/var/lib/juju/init/jujud-machine-0/exec-start.sh``` on the controller node and comment the ```--debug``` section. + +It will then look like: + +``` +#!/usr/bin/env bash + +# Set up logging. +touch '/var/log/juju/machine-0.log' +chown syslog:syslog '/var/log/juju/machine-0.log' +chmod 0600 '/var/log/juju/machine-0.log' +exec >> '/var/log/juju/machine-0.log' +exec 2>&1 + +# Run the script. +'/var/lib/juju/tools/machine-0/jujud' machine --data-dir '/var/lib/juju' --machine-id 0 # --debug +``` + +Then restart the service with: + +``` +sudo systemctl restart jujud-machine-0.service +``` + +See the [official documentation](https://jujucharms.com/docs/stable/models-config) for more information about logging and other model settings in Juju. + + +## Managing your Kubernetes cluster +### Running privileged containers + +By default CDK does not support running privileged containers. If you need them, you have to edit ```/etc/default/kube-apiserver``` on the master nodes, and ```/etc/default/kubelet``` on your worker nodes. + +On Kubernetes Core or on small deployment, run the following commands from the Juju client: + +#### Manually + +1. Update the Master + +``` +juju ssh kubernetes-master/0 "sudo sed -i 's/KUBE_API_ARGS=\"/KUBE_API_ARGS=\"--allow-privileged\ /' /etc/default/kube-apiserver && sudo systemctl restart kube-apiserver.service" +``` + +2. Update the Worker(s) + +``` +juju ssh kubernetes-worker/0 "sudo sed -i 's/KUBELET_ARGS=\"/KUBELET_ARGS=\"--allow-privileged\ /' /etc/default/kubelet && sudo systemctl restart kubelet.service" +``` + +#### Programmatically + +If the deployment is larger the following commands will run on all units successively: + +1. Update all Masters + +``` +juju show-status kubernetes-master --format json | \ + jq --raw-output '.applications."kubernetes-master".units | keys[]' | \ + xargs -I UNIT juju ssh UNIT "sudo sed -i 's/KUBE_API_ARGS=\"/KUBE_API_ARGS=\"--allow-privileged\ /' /etc/default/kube-apiserver && sudo systemctl restart kube-apiserver.service" +``` + +2. Update all workers + +``` +juju show-status kubernetes-worker --format json | \ + jq --raw-output '.applications."kubernetes-worker".units | keys[]' | \ + xargs -I UNIT juju ssh UNIT "sudo sed -i 's/KUBELET_ARGS=\"/KUBELET_ARGS=\"--allow-privileged\ /' /etc/default/kubelet && sudo systemctl restart kubelet.service" +``` + + +{% endcapture %} + +{% include templates/task.md %} \ No newline at end of file From e28cec48e900b96cc4dcee25176c9f23cbe9df7e Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Mon, 23 Jan 2017 18:10:09 +0100 Subject: [PATCH 07/17] dummy commit to register new email --- docs/getting-started-guides/ubuntu/operations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started-guides/ubuntu/operations.md b/docs/getting-started-guides/ubuntu/operations.md index 53b848978d..b2b3a5a688 100644 --- a/docs/getting-started-guides/ubuntu/operations.md +++ b/docs/getting-started-guides/ubuntu/operations.md @@ -120,7 +120,7 @@ juju show-status kubernetes-worker --format json | \ jq --raw-output '.applications."kubernetes-worker".units | keys[]' | \ xargs -I UNIT juju ssh UNIT "sudo sed -i 's/KUBELET_ARGS=\"/KUBELET_ARGS=\"--allow-privileged\ /' /etc/default/kubelet && sudo systemctl restart kubelet.service" ``` - + {% endcapture %} From 6f1c745bb6b828d628a4774ef53d9b40b2c149e1 Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Mon, 23 Jan 2017 18:12:53 +0100 Subject: [PATCH 08/17] dummy commit to register new email --- docs/getting-started-guides/ubuntu/operations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started-guides/ubuntu/operations.md b/docs/getting-started-guides/ubuntu/operations.md index b2b3a5a688..53b848978d 100644 --- a/docs/getting-started-guides/ubuntu/operations.md +++ b/docs/getting-started-guides/ubuntu/operations.md @@ -120,7 +120,7 @@ juju show-status kubernetes-worker --format json | \ jq --raw-output '.applications."kubernetes-worker".units | keys[]' | \ xargs -I UNIT juju ssh UNIT "sudo sed -i 's/KUBELET_ARGS=\"/KUBELET_ARGS=\"--allow-privileged\ /' /etc/default/kubelet && sudo systemctl restart kubelet.service" ``` - + {% endcapture %} From 147bb4cf0279e0c959fbc3570c202795b231adfc Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Tue, 24 Jan 2017 10:28:24 +0100 Subject: [PATCH 09/17] modified: docs/getting-started-guides/ubuntu/index.md * adding Operational Considerations section modified: docs/getting-started-guides/ubuntu/logging.md * Moving logging section from operational-considerations.md to logging.md renamed: docs/getting-started-guides/ubuntu/operations.md -> docs/getting-started-guides/ubuntu/operational-considerations.md * mapping to the proposed name * ditched CDK naming in favor of k8s or cluster * add whitelines for titles --- docs/getting-started-guides/ubuntu/index.md | 1 + docs/getting-started-guides/ubuntu/logging.md | 40 ++++++++++++++ ...tions.md => operational-considerations.md} | 52 +++---------------- 3 files changed, 49 insertions(+), 44 deletions(-) rename docs/getting-started-guides/ubuntu/{operations.md => operational-considerations.md} (70%) diff --git a/docs/getting-started-guides/ubuntu/index.md b/docs/getting-started-guides/ubuntu/index.md index 5e706f0add..d54b94a88c 100644 --- a/docs/getting-started-guides/ubuntu/index.md +++ b/docs/getting-started-guides/ubuntu/index.md @@ -43,6 +43,7 @@ These are more in-depth guides for users choosing to run Kubernetes in productio - [Storage](/docs/getting-started-guides/ubuntu/storage) - [Troubleshooting](/docs/getting-started-guides/ubuntu/troubleshooting) - [Decommissioning](/docs/getting-started-guides/ubuntu/decommissioning) + - [Operational Considerations](/docs/getting-started-guides/ubuntu/operational-considerations) - [Glossary](/docs/getting-started-guides/ubuntu/glossary) ## Developer Guides diff --git a/docs/getting-started-guides/ubuntu/logging.md b/docs/getting-started-guides/ubuntu/logging.md index b7ae3c9a10..ae7237a0a7 100644 --- a/docs/getting-started-guides/ubuntu/logging.md +++ b/docs/getting-started-guides/ubuntu/logging.md @@ -18,3 +18,43 @@ The `juju debug-log` will show all of the consolidated logs of all the Juju agen See the [Juju documentation](https://jujucharms.com/docs/stable/troubleshooting-logs) for more information. +## Managing log verbosity + +Log verbosity in Juju is set at the model level. You can adjust it at any time: + +``` +juju add-model k8s-development --config logging-config='=DEBUG;unit=DEBUG' +``` + +and later + +``` +juju config-model k8s-production --config logging-config='=ERROR;unit=ERROR' +``` + +In addition, the jujud daemon is started in debug mode by default on all controllers. To remove that behavior edit ```/var/lib/juju/init/jujud-machine-0/exec-start.sh``` on the controller node and comment the ```--debug``` section. + +It then contains: + +``` +#!/usr/bin/env bash + +# Set up logging. +touch '/var/log/juju/machine-0.log' +chown syslog:syslog '/var/log/juju/machine-0.log' +chmod 0600 '/var/log/juju/machine-0.log' +exec >> '/var/log/juju/machine-0.log' +exec 2>&1 + +# Run the script. +'/var/lib/juju/tools/machine-0/jujud' machine --data-dir '/var/lib/juju' --machine-id 0 # --debug +``` + +Then restart the service with: + +``` +sudo systemctl restart jujud-machine-0.service +``` + +See the [official documentation](https://jujucharms.com/docs/stable/models-config) for more information about logging and other model settings in Juju. + diff --git a/docs/getting-started-guides/ubuntu/operations.md b/docs/getting-started-guides/ubuntu/operational-considerations.md similarity index 70% rename from docs/getting-started-guides/ubuntu/operations.md rename to docs/getting-started-guides/ubuntu/operational-considerations.md index 53b848978d..25b910073c 100644 --- a/docs/getting-started-guides/ubuntu/operations.md +++ b/docs/getting-started-guides/ubuntu/operational-considerations.md @@ -1,16 +1,18 @@ --- -title: Operations +title: Operational Considerations --- {% capture overview %} -This page gives recommendations and hints for people managing long lived CDK clusters +This page gives recommendations and hints for people managing long lived clusters {% endcapture %} {% capture prerequisites %} This page assumes you understand the basics of Juju and Kubernetes. {% endcapture %} {% capture steps %} + ## Managing Juju + ### Sizing your controller node The Juju Controller: @@ -27,6 +29,8 @@ juju bootstrap --contraints "mem=8GB cpu-cores=4 root-disk=128G" Juju will elect the cheapest instance type matching your constraints on your target cloud. You can also use the ```instance-type``` constraint in conjunction with ```root-disk``` for strict control. For more information about the constraints available, refer to the [official documentation](https://jujucharms.com/docs/stable/reference-constraints) +Additional information about logging can be found in the [logging section](/docs/getting-started-guides/ubuntu/logging) + ### Connecting on the Controller Node By default, Juju will create a pair of SSH key that it will use to automate the connection to units. They are stored on the client node in ```~/.local/share/juju/ssh/``` @@ -39,51 +43,11 @@ ssh -i ./.local/share/juju/ssh/juju_id_rsa ubuntu@ where ```public-ip-of-juju-controller``` can be found in ```~/.local/share/juju/controllers.yaml``` in the ```api-endpoints``` section. -### Restricting log verbosity - -Log verbosity in Juju is set at the model level. You can adjust it at any time: - -``` -juju add-model cdk-development --config logging-config='=DEBUG;unit=DEBUG' -``` - -and later - -``` -juju config-model cdk-production --config logging-config='=ERROR;unit=ERROR' -``` - -In addition, the jujud daemon is started in debug mode by default on all controllers. To remove that behavior edit ```/var/lib/juju/init/jujud-machine-0/exec-start.sh``` on the controller node and comment the ```--debug``` section. - -It will then look like: - -``` -#!/usr/bin/env bash - -# Set up logging. -touch '/var/log/juju/machine-0.log' -chown syslog:syslog '/var/log/juju/machine-0.log' -chmod 0600 '/var/log/juju/machine-0.log' -exec >> '/var/log/juju/machine-0.log' -exec 2>&1 - -# Run the script. -'/var/lib/juju/tools/machine-0/jujud' machine --data-dir '/var/lib/juju' --machine-id 0 # --debug -``` - -Then restart the service with: - -``` -sudo systemctl restart jujud-machine-0.service -``` - -See the [official documentation](https://jujucharms.com/docs/stable/models-config) for more information about logging and other model settings in Juju. - - ## Managing your Kubernetes cluster + ### Running privileged containers -By default CDK does not support running privileged containers. If you need them, you have to edit ```/etc/default/kube-apiserver``` on the master nodes, and ```/etc/default/kubelet``` on your worker nodes. +By default juju-deployed clusters do not support running privileged containers. If you need them, you have to edit ```/etc/default/kube-apiserver``` on the master nodes, and ```/etc/default/kubelet``` on your worker nodes. On Kubernetes Core or on small deployment, run the following commands from the Juju client: From d6ee95c6a19d01211bf37431d535022ff0989baf Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Tue, 24 Jan 2017 16:48:56 +0100 Subject: [PATCH 10/17] adding link into _data/guides.yml --- _data/guides.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/_data/guides.yml b/_data/guides.yml index 38ee10b438..2d79fb00dd 100644 --- a/_data/guides.yml +++ b/_data/guides.yml @@ -164,6 +164,7 @@ toc: - docs/getting-started-guides/ubuntu/troubleshooting.md - docs/getting-started-guides/ubuntu/decommissioning.md - docs/getting-started-guides/ubuntu/calico.md + - docs/getting-started-guides/ubuntu/operational-considerations.md - docs/getting-started-guides/ubuntu/glossary.md - docs/getting-started-guides/ubuntu/local.md - docs/getting-started-guides/ubuntu/logging.md From c317ac00d8aad64dc877c2d64ea93d1e4b0f64f5 Mon Sep 17 00:00:00 2001 From: Samuel Cozannet Date: Tue, 24 Jan 2017 18:17:33 +0100 Subject: [PATCH 11/17] modified: docs/getting-started-guides/ubuntu/operational-considerations.md * Rewording the access section for the controller to make it more user friendly * fix typos --- .../ubuntu/operational-considerations.md | 81 +++++++++++++++++-- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/docs/getting-started-guides/ubuntu/operational-considerations.md b/docs/getting-started-guides/ubuntu/operational-considerations.md index 25b910073c..e6c6a02097 100644 --- a/docs/getting-started-guides/ubuntu/operational-considerations.md +++ b/docs/getting-started-guides/ubuntu/operational-considerations.md @@ -27,21 +27,90 @@ To bootstrap a controller with constraints run the following command: juju bootstrap --contraints "mem=8GB cpu-cores=4 root-disk=128G" ``` -Juju will elect the cheapest instance type matching your constraints on your target cloud. You can also use the ```instance-type``` constraint in conjunction with ```root-disk``` for strict control. For more information about the constraints available, refer to the [official documentation](https://jujucharms.com/docs/stable/reference-constraints) +Juju will select the cheapest instance type matching your constraints on your target cloud. You can also use the ```instance-type``` constraint in conjunction with ```root-disk``` for strict control. For more information about the constraints available, refer to the [official documentation](https://jujucharms.com/docs/stable/reference-constraints) Additional information about logging can be found in the [logging section](/docs/getting-started-guides/ubuntu/logging) -### Connecting on the Controller Node +### SSHing into the Controller Node -By default, Juju will create a pair of SSH key that it will use to automate the connection to units. They are stored on the client node in ```~/.local/share/juju/ssh/``` +By default, Juju will create a pair of SSH keys that it will use to automate the connection to units. They are stored on the client node in ```~/.local/share/juju/ssh/``` -After deployment, Juju Controller is a "silent unit" that acts as a proxy between the client and the deployed applications. Nevertheless it can be useful to SSH into it. To do so run the following command from your client node: +After deployment, Juju Controller is a "silent unit" that acts as a proxy between the client and the deployed applications. Nevertheless it can be useful to SSH into it. + +First you need to understand your environment, especially if you run several Juju models and controllers. Run ``` -ssh -i ./.local/share/juju/ssh/juju_id_rsa ubuntu@ +juju list-models --all +$ juju models --all +Controller: k8s + +Model Cloud/Region Status Machines Cores Access Last connection +admin/controller lxd/localhost available 1 - admin just now +admin/default lxd/localhost available 0 - admin 2017-01-23 +admin/whale* lxd/localhost available 6 - admin 3 minutes ago + ``` -where ```public-ip-of-juju-controller``` can be found in ```~/.local/share/juju/controllers.yaml``` in the ```api-endpoints``` section. +The first line ```Controller: k8s``` refers to how you bootstrapped. + +Then you will see 2, 3 or more models listed below. + +* admin/controller is the default model that hosts all controller units of juju +* admin/default is created by default as the primary model to host the user application, such as the Kubernetes cluster +* admin/whale is an additional model created if you use conjure-up as an overlay on top of Juju. + +Now to ssh into a controller node, you first ask Juju to switch context, then ssh as you would with a normal unit: + +``` +juju switch controller +``` + +At this stage, you can query the controller model as well: + +``` +juju status +Model Controller Cloud/Region Version +controller k8s lxd/localhost 2.0.2 + +App Version Status Scale Charm Store Rev OS Notes + +Unit Workload Agent Machine Public address Ports Message + +Machine State DNS Inst id Series AZ +0 started 10.191.22.15 juju-2a5ed8-0 xenial +``` + +Note that if you had bootstrapped in HA mode, you would see several machines listed. + +Now ssh-ing into the controller follows the same semantic as classic Juju commands: + +``` +$ juju ssh 0 +Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.8.0-34-generic x86_64) + + * Documentation: https://help.ubuntu.com + * Management: https://landscape.canonical.com + * Support: https://ubuntu.com/advantage + + Get cloud support with Ubuntu Advantage Cloud Guest: + http://www.ubuntu.com/business/services/cloud + +0 packages can be updated. +0 updates are security updates. + + +Last login: Tue Jan 24 16:38:13 2017 from 10.191.22.1 +ubuntu@juju-2a5ed8-0:~$ +``` + +When you are done and want to come back to your initial model, exit the controller and + + +Then if you need to switch back to your cluster and ssh into the units, run + +``` +juju switch default +``` ## Managing your Kubernetes cluster From a631ff3cc94fb3d9802f396485f8b9ef043dd31e Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Wed, 1 Feb 2017 12:14:21 +0100 Subject: [PATCH 12/17] Fixed link --- docs/api-reference/v1/definitions.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index e207f68c0a..fe869dc84f 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -4176,7 +4176,7 @@ The resulting set of endpoints can be viewed as:

nodeSelector

-

NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node’s labels for the pod to be scheduled on that node. More info: http://kubernetes.io/docs/user-guide/node-selection/README

+

NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node’s labels for the pod to be scheduled on that node. More info: http://kubernetes.io/docs/user-guide/node-selection

false

object

@@ -8267,4 +8267,4 @@ Last updated 2016-11-17 06:26:10 UTC - \ No newline at end of file + From 2027ed39bbb4318d650e015b3a1b245e71cd3637 Mon Sep 17 00:00:00 2001 From: Eugene Chow Date: Wed, 1 Feb 2017 16:12:52 +0800 Subject: [PATCH 13/17] Changed "haripin-veth" to "hairpin-veth" --- docs/user-guide/debugging-services.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/debugging-services.md b/docs/user-guide/debugging-services.md index a99c60e53a..de9cec5c3f 100644 --- a/docs/user-guide/debugging-services.md +++ b/docs/user-guide/debugging-services.md @@ -566,11 +566,11 @@ This mostly happens when `kube-proxy` is running in `iptables` mode and Pods are connected with bridge network. The `Kubelet` exposes a `hairpin-mode` [flag](http://kubernetes.io/docs/admin/kubelet/) that allows endpoints of a Service to loadbalance back to themselves if they try to access their own Service VIP. The `hairpin-mode` flag must either be -set to `haripin-veth` or `promiscuous-bridge`. +set to `hairpin-veth` or `promiscuous-bridge`. The common steps to trouble shoot this are as follows: -* Confirm `hairpin-mode` is set to `haripin-veth` or `promiscuous-bridge`. +* Confirm `hairpin-mode` is set to `hairpin-veth` or `promiscuous-bridge`. You should see something like the below. `hairpin-mode` is set to `promiscuous-bridge` in the following example. From a32a2a59c299a7efc769df3c28e01c57e7d42640 Mon Sep 17 00:00:00 2001 From: Jeff Mendoza Date: Wed, 21 Dec 2016 09:39:45 -0800 Subject: [PATCH 14/17] Getting started guides overhaul. --- _data/guides.yml | 16 +- _data/tutorials.yml | 4 +- docs/getting-started-guides/kubectl.md | 111 ----- docs/hellonode.md | 433 ------------------ .../stateless-application/hello-minikube.md | 3 + docs/user-guide/prereqs.md | 85 +++- 6 files changed, 95 insertions(+), 557 deletions(-) delete mode 100644 docs/getting-started-guides/kubectl.md delete mode 100755 docs/hellonode.md diff --git a/_data/guides.yml b/_data/guides.yml index 2d79fb00dd..3c7064014e 100644 --- a/_data/guides.yml +++ b/_data/guides.yml @@ -3,17 +3,7 @@ abstract: "How to get started, and accomplish tasks, using Kubernetes." toc: - docs/user-guide/index.md -- title: Getting Started - section: - - docs/whatisk8s.md - - docs/getting-started-guides/kubeadm.md - - docs/getting-started-guides/kops.md - - docs/getting-started-guides/kargo.md - - docs/hellonode.md - - docs/getting-started-guides/kubectl.md - - docs/getting-started-guides/binary_release.md - - title: Online Training Course - path: https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615 +- docs/whatisk8s.md - title: Accessing the Cluster section: @@ -119,11 +109,14 @@ toc: - title: Running Kubernetes on Custom Solutions section: - docs/getting-started-guides/scratch.md + - docs/getting-started-guides/kubeadm.md - title: Custom Cloud Solutions section: - docs/getting-started-guides/coreos/index.md - docs/getting-started-guides/ubuntu/index.md - docs/getting-started-guides/rackspace.md + - docs/getting-started-guides/kops.md + - docs/getting-started-guides/kargo.md - title: On-Premise VMs section: - docs/getting-started-guides/coreos/index.md @@ -175,6 +168,7 @@ toc: - docs/admin/cluster-large.md - docs/admin/multiple-zones.md - docs/admin/high-availability/index.md + - docs/getting-started-guides/binary_release.md - title: Administering Clusters section: diff --git a/_data/tutorials.yml b/_data/tutorials.yml index 395ff9d06d..695d2b8805 100644 --- a/_data/tutorials.yml +++ b/_data/tutorials.yml @@ -29,9 +29,11 @@ toc: section: - docs/tutorials/kubernetes-basics/update-intro.html - docs/tutorials/kubernetes-basics/update-interactive.html +- title: Online Training Course + path: https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615 +- docs/tutorials/stateless-application/hello-minikube.md - title: Stateless Applications section: - - docs/tutorials/stateless-application/hello-minikube.md - docs/tutorials/stateless-application/run-stateless-application-deployment.md - docs/tutorials/stateless-application/expose-external-ip-address-service.md - docs/tutorials/stateless-application/expose-external-ip-address.md diff --git a/docs/getting-started-guides/kubectl.md b/docs/getting-started-guides/kubectl.md deleted file mode 100644 index 508e1516da..0000000000 --- a/docs/getting-started-guides/kubectl.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: Installing kubectl ---- - - - -## Overview - -kubectl is the command line tool you use to interact with Kubernetes clusters. - -You should use a version of kubectl that is at least as new as your server. -`kubectl version` will print the server and client versions. Using the same version of kubectl -as your server naturally works; using a newer kubectl than your server also works; but if you use -an older kubectl with a newer server you may see odd validation errors . - -## Download a release - -Download kubectl from the [official Kubernetes releases](https://console.cloud.google.com/storage/browser/kubernetes-release/release/): - -On MacOS: - -```shell -wget https://storage.googleapis.com/kubernetes-release/release/v1.4.4/bin/darwin/amd64/kubectl -chmod +x kubectl -mv kubectl /usr/local/bin/kubectl -``` - -On Linux: - -```shell -wget https://storage.googleapis.com/kubernetes-release/release/v1.4.4/bin/linux/amd64/kubectl -chmod +x kubectl -mv kubectl /usr/local/bin/kubectl -``` - - -You may need to `sudo` the `mv`; you can put it anywhere in your `PATH` - some people prefer to install to `~/bin`. - - -## Alternatives - -### Download as part of the Google Cloud SDK - -kubectl can be installed as part of the Google Cloud SDK: - -First install the [Google Cloud SDK](https://cloud.google.com/sdk/). - -After Google Cloud SDK installs, run the following command to install `kubectl`: - -```shell -gcloud components install kubectl -``` - -Do check that the version is sufficiently up-to-date using `kubectl version`. - -### Install with brew - -If you are on MacOS and using brew, you can install with: - -```shell -brew install kubectl -``` - -The homebrew project is independent from Kubernetes, so do check that the version is -sufficiently up-to-date using `kubectl version`. - - -# Enabling shell autocompletion - -kubectl includes autocompletion support, which can save a lot of typing! - -The completion script itself is generated by kubectl, so you typically just need to invoke it from your profile. - -Common examples are provided here, but for more details please consult `kubectl completion -h` - -## On Linux, using bash - -To add it to your current shell: `source <(kubectl completion bash)` - -To add kubectl autocompletion to your profile (so it is automatically loaded in future shells): - -```shell -echo "source <(kubectl completion bash)" >> ~/.bashrc -``` - -## On MacOS, using bash - -On MacOS, you will need to install the bash-completion support first: - -```shell -brew install bash-completion -``` - -To add it to your current shell: - -```shell -source $(brew --prefix)/etc/bash_completion -source <(kubectl completion bash) -``` - -To add kubectl autocompletion to your profile (so it is automatically loaded in future shells): - -```shell -echo "source $(brew --prefix)/etc/bash_completion" >> ~/.bash_profile -echo "source <(kubectl completion bash)" >> ~/.bash_profile -``` - -Please note that this only appears to work currently if you install using `brew install kubectl`, -and not if you downloaded kubectl directly. \ No newline at end of file diff --git a/docs/hellonode.md b/docs/hellonode.md deleted file mode 100755 index fcb8eec480..0000000000 --- a/docs/hellonode.md +++ /dev/null @@ -1,433 +0,0 @@ ---- -assignees: -- dchen1107 -- pwittrock -title: Hello World on Google Container Engine ---- - -* TOC -{:toc} - -## Introduction - -The goal of this codelab is for you to turn a simple Hello World node.js app into a replicated application running on Kubernetes. We will show you how to take code that you have developed on your machine, turn it into a Docker container image, and then run that image on [Google Container Engine](https://cloud.google.com/container-engine/). - -Here's a diagram of the various parts in play in this codelab to help you understand how pieces fit with one another. Use this as a reference as we progress through the codelab; it should all make sense by the time we get to the end. - -![image](/images/hellonode/image_1.png) - -Kubernetes is an open source project which can run on many different environments, from laptops to high-availability multi-node clusters, from public clouds to on-premise deployments, from virtual machines to bare metal. Using a managed environment such as Google Container Engine (a Google-hosted version of Kubernetes) will allow you to focus more on experiencing Kubernetes rather than setting up the underlying infrastructure. - -## Setup and Requirements - -If you don't already have a Google Account (Gmail or Google Apps), you must [create one](https://accounts.google.com/SignUp). Then, sign-in to Google Cloud Platform console ([console.cloud.google.com](http://console.cloud.google.com)) and create a new project: - -![image](/images/hellonode/image_2.png) - -![image](/images/hellonode/image_3.png) - -Remember the project ID; it will be referred to later in this codelab as `$PROJECT_ID`. - -Make sure you have a Linux terminal available, you will use it to control your cluster via command line. You can use [Google Cloud Shell](https://console.cloud.google.com?cloudshell=true), it has the software this codelab uses pre-installed so that you can skip most of the environment configuration steps below. - -It may be helpful to store your project ID into a variable as many commands below use it: - -```shell -export PROJECT_ID="your-project-id" -``` - -Next, [enable billing](https://console.cloud.google.com/billing) in the Cloud Console in order to use Google Cloud resources and [enable the Container Engine API](https://console.cloud.google.com/project/_/kubernetes/list). - -New users of Google Cloud Platform receive a [$300 free trial](https://console.cloud.google.com/billing/freetrial?hl=en). Running through this codelab shouldn't cost you more than a few dollars of that trial. Google Container Engine pricing is documented [here](https://cloud.google.com/container-engine/pricing). - -Next, make sure you [download Node.js](https://nodejs.org/en/download/). You can skip this and the steps for installing Docker and Cloud SDK if you're using Cloud Shell. - -Then install [Docker](https://docs.docker.com/engine/installation/), and [Google Cloud SDK](https://cloud.google.com/sdk/). - -Finally, after Google Cloud SDK installs, run the following command to install [`kubectl`](http://kubernetes.io/docs/user-guide/kubectl-overview/): - -```shell -gcloud components install kubectl -``` - -You're all set up with an environment that can build container images, run Node apps, run Kubernetes clusters locally, and deploy Kubernetes clusters to Google Container Engine. Let's begin! - -## Create your Node.js application - -The first step is to write the application. Save this code in a folder called "`hellonode/`" with the filename `server.js`: - -#### server.js - -```javascript -const http = require('http'); -const handleRequest = (request, response) => { - console.log('Received request for URL: ' + request.url); - response.writeHead(200); - response.end('Hello World!'); -}; -const www = http.createServer(handleRequest); -www.listen(8080); -``` - -Now run this simple command: - -```shell -node server.js -``` - -You should be able to see your "Hello World!" message at http://localhost:8080/. If using Cloud Shell, use [Web Preview](https://cloud.google.com/shell/docs/using-web-preview) to view the URL. - -Stop the running node server by pressing Ctrl-C. - -Now let's package this application in a Docker container. - -## Create a Docker container image - -Next, create a file, also within `hellonode/` named `Dockerfile`. A Dockerfile describes the image that you want to build. Docker container images can extend from other existing images so for this image, we'll extend from an existing Node image. - -#### Dockerfile - -```conf -FROM node:4.5 -EXPOSE 8080 -COPY server.js . -CMD node server.js -``` - -This "recipe" for the Docker image will start from the official Node.js LTS image found on the Docker registry, expose port 8080, copy our `server.js` file to the image and start the Node server. - -Now build an image of your container by running `docker build`, tagging the image with the Google Container Registry repo for your `$PROJECT_ID`: - -```shell -docker build -t gcr.io/$PROJECT_ID/hello-node:v1 . -``` -Now there is a trusted source for getting an image of your containerized app. - -Let's try your image out with Docker: - -```shell -docker run -d -p 8080:8080 --name hello_tutorial gcr.io/$PROJECT_ID/hello-node:v1 -``` - -Visit your app in the browser, or use `curl` or `wget` if you'd like : - -```shell -curl http://localhost:8080 -``` - -You should see `Hello World!` - -**Note:** *If you receive a `Connection refused` message from Docker for Mac, ensure you are using the latest version of Docker (1.12 or later). Alternatively, if you are using Docker Toolbox on OSX, make sure you are using the VM's IP and not localhost:* - -```shell -curl "http://$(docker-machine ip YOUR-VM-MACHINE-NAME):8080" -``` - -Let's now stop the container. You can list the docker containers with: - -```shell -docker ps -``` - -You should see something like this: - -```shell -CONTAINER ID IMAGE COMMAND NAMES -c5b6d4b9f36d gcr.io/$PROJECT_ID/hello-node:v1 "/bin/sh -c 'node ser" hello_tutorial -``` - -Now stop the running container with - -``` -docker stop hello_tutorial -``` - -Now that the image works as intended and is all tagged with your `$PROJECT_ID`, we can push it to the [Google Container Registry](https://cloud.google.com/tools/container-registry/), a private repository for your Docker images accessible from every Google Cloud project (but also from outside Google Cloud Platform) : - -```shell -gcloud docker -- push gcr.io/$PROJECT_ID/hello-node:v1 -``` - -If all goes well, you should be able to see the container image listed in the console: *Compute > Container Engine > Container Registry*. We now have a project-wide Docker image available which Kubernetes can access and orchestrate. - -If you see an error message like the following: __denied: Unable to create the repository, please check that you have access to do so.__ ensure that you are pushing the image to Container Registry with the correct user credentials, use `gcloud auth list` and then `gcloud config set account example@gmail.com`. - -![image](/images/hellonode/image_10.png) - -**Note:** *Docker for Windows, Version 1.12 or 1.12.1, does not yet support this procedure. Instead, it replies with the message 'denied: Unable to access the repository; please check that you have permission to access it'. A bugfix is available at http://stackoverflow.com/questions/39277986/unable-to-push-to-google-container-registry-unable-to-access-the-repository?answertab=votes#tab-top.* - -## Create your Kubernetes Cluster - -A cluster consists of a Master API server and a set of worker VMs called Nodes. - -First, choose a [Google Cloud Project zone](https://cloud.google.com/compute/docs/regions-zones/regions-zones) to run -your service. For this tutorial, we will be using **us-central1-a**. This is -configured on the command line via: - -``` -gcloud config set compute/zone us-central1-a -``` - -Now, create a cluster via the `gcloud` command line tool: - -```shell -gcloud container clusters create hello-world -``` - -Alternatively, you can create a cluster via the [Google Cloud Console](https://console.cloud.google.com): *Compute > Container Engine > Container Clusters > New container cluster*. Set the name to **hello-world**, leaving all other options default. - -You should get a Kubernetes cluster with three nodes, ready to receive your container image! (this may take a couple of minutes) - -![image](/images/hellonode/image_11.png) - -It's now time to deploy your own containerized application to the Kubernetes cluster! - -```shell -gcloud container clusters get-credentials hello-world -``` - -**The rest of this document requires both the Kubernetes client and server version to be 1.3. Run `kubectl version` to see your current versions.** For 1.2 see [this document](https://github.com/kubernetes/kubernetes.github.io/blob/release-1.2/docs/hellonode.md). - -## Create your pod - -A Kubernetes **[pod](/docs/user-guide/pods/)** is a group of containers, tied together for the purposes of administration and networking. It can contain a single container or multiple. - -Create a Pod with the `kubectl run` command: - -```shell -kubectl run hello-node --image=gcr.io/$PROJECT_ID/hello-node:v1 --port=8080 -``` - -As shown in the output, the `kubectl run` created a **[Deployment](/docs/user-guide/deployments/)** object. Deployments are the recommended way for managing creation and scaling of pods. In this example, a new deployment manages a single pod replica running the *hello-node:v1* image. - -To view the Deployment we just created run: - -```shell -kubectl get deployments - -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -hello-node 1 1 1 1 3m -``` - -To view the Pod created by the deployment run: - -```shell -kubectl get pods - -NAME READY STATUS RESTARTS AGE -hello-node-714049816-ztzrb 1/1 Running 0 6m -``` - -To view the stdout / stderr from a Pod run (probably empty currently): - -```shell -kubectl logs -``` - -To view metadata about the cluster run: - -```shell -kubectl cluster-info -``` - -To view cluster events run: - -```shell -kubectl get events -``` - -To view the kubectl configuration run: - -```shell -kubectl config view -``` - -Full documentation for kubectl commands is available **[here](/docs/user-guide/kubectl-overview/)**: - -At this point you should have our container running under the control of Kubernetes but we still have to make it accessible to the outside world. - -## Allow external traffic - -By default, the pod is only accessible by its internal IP within the Kubernetes cluster. In order to make the `hello-node` container accessible from outside the Kubernetes virtual network, you have to expose the Pod as a Kubernetes **[Service](/docs/user-guide/services/)**. - -From our Development machine we can expose the pod to the public internet using the `kubectl expose` command combined with the `--type="LoadBalancer"` flag. The flag is needed for the creation of an externally accessible ip: - -```shell -kubectl expose deployment hello-node --type="LoadBalancer" -``` - -**If this fails, make sure your client and server are both version 1.3. See the [Create your cluster](#create-your-cluster) section for details.** - -The flag used in this command specifies that we'll be using the load-balancer provided by the underlying infrastructure (in this case the [Compute Engine load balancer](https://cloud.google.com/compute/docs/load-balancing/)). Note that we expose the deployment, and not the pod directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but we will add more replicas later). - -The Kubernetes master creates the load balancer and related Compute Engine forwarding rules, target pools, and firewall rules to make the service fully accessible from outside of Google Cloud Platform. - -To find the ip addresses associated with the service run: - -```shell -kubectl get services hello-node - -NAME CLUSTER_IP EXTERNAL_IP PORT(S) AGE -hello-node 10.3.246.12 8080/TCP 23s -``` - -The `EXTERNAL_IP` may take several minutes to become available and visible. If the `EXTERNAL_IP` is missing, wait a few minutes and try again. - -```shell -kubectl get services hello-node - -NAME CLUSTER_IP EXTERNAL_IP PORT(S) AGE -hello-node 10.3.246.12 23.251.159.72 8080/TCP 2m -``` - -Note there are 2 IP addresses listed, both serving port 8080. `CLUSTER_IP` is only visible inside your cloud virtual network. `EXTERNAL_IP` is externally accessible. In this example, the external IP address is 23.251.159.72. - -You should now be able to reach the service by pointing your browser to this address: http://EXTERNAL_IP**:8080** or running `curl http://EXTERNAL_IP:8080`. - -![image](/images/hellonode/image_12.png) - -Assuming you've sent requests to your new webservice via the browser or curl, -you should now be able to see some logs by running: - -```shell -kubectl logs -``` - -## Scale up your website - -One of the powerful features offered by Kubernetes is how easy it is to scale your application. Suppose you suddenly need more capacity for your application; you can simply tell the deployment to manage a new number of replicas for your pod: - -```shell -kubectl scale deployment hello-node --replicas=4 -``` - -You now have four replicas of your application, each running independently on the cluster with the load balancer you created earlier and serving traffic to all of them. - -```shell -kubectl get deployment - -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -hello-node 4 4 4 3 40m -``` - -```shell -kubectl get pods - -NAME READY STATUS RESTARTS AGE -hello-node-714049816-g4azy 1/1 Running 0 1m -hello-node-714049816-rk0u6 1/1 Running 0 1m -hello-node-714049816-sh812 1/1 Running 0 1m -hello-node-714049816-ztzrb 1/1 Running 0 41m -``` - -Note the **declarative approach** here - rather than starting or stopping new instances you declare how many instances you want to be running. Kubernetes reconciliation loops simply make sure the reality matches what you requested and take action if needed. - -Here's a diagram summarizing the state of our Kubernetes cluster: - -![image](/images/hellonode/image_13.png) - -## Roll out an upgrade to your website - -As always, the application you deployed to production requires bug fixes or additional features. Kubernetes is here to help you deploy a new version to production without impacting your users. - -First, let's modify the application. On the development machine, edit server.js and update the response message: - -```javascript - response.end('Hello Kubernetes World!'); -``` - -We can now build and publish a new container image to the registry with an incremented tag: - -```shell -docker build -t gcr.io/$PROJECT_ID/hello-node:v2 . -gcloud docker -- push gcr.io/$PROJECT_ID/hello-node:v2 -``` - -Building and pushing this updated image should be much quicker as we take full advantage of the Docker cache. - -We're now ready for Kubernetes to smoothly update our deployment to the new version of the application. In order to change -the image label for our running container, we will need to edit the existing *hello-node deployment* and change the image from -`gcr.io/$PROJECT_ID/hello-node:v1` to `gcr.io/$PROJECT_ID/hello-node:v2`. To do this, we will use the `kubectl set image` command. - -```shell -kubectl set image deployment/hello-node hello-node=gcr.io/$PROJECT_ID/hello-node:v2 -``` - -This updates the deployment with the new image, causing new pods to be created with the new image and old pods to be deleted. - -``` -kubectl get deployments - -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -hello-node 4 5 4 3 1h -``` - -While this is happening, the users of the services should not see any interruption. After a little while they will start accessing the new version of your application. You can find more details in the [deployment documentation](/docs/user-guide/deployments/). - -Hopefully with these deployment, scaling and update features you'll agree that once you've setup your environment (your GKE/Kubernetes cluster here), Kubernetes is here to help you focus on the application rather than the infrastructure. - -## Observe the Kubernetes Web UI (optional) - -Kubernetes comes with a graphical web user interface that is enabled by default with your clusters. - -This user interface allows you to get started quickly and enables some of the functionality found in the CLI as a more approachable and discoverable way of interacting with the system. - -Enjoy the Kubernetes graphical dashboard and use it for deploying containerized applications, as well as for monitoring and managing your clusters! - -![image](/images/docs/ui-dashboard-workloadview.png) - -Learn more about the web interface by taking the [Dashboard tour](/docs/user-guide/ui/). - -## Cleaning it Up - -That's it for the demo! So you don't leave this all running and incur charges, let's learn how to tear things down. - -Delete the Deployment (which also deletes the running pods) and Service (which also deletes your external load balancer): - -```shell -kubectl delete service,deployment hello-node -``` - -Delete your cluster: - -```shell -gcloud container clusters delete hello-world -``` - -You should see: - -``` -The following clusters will be deleted. - - [hello-world] in [us-central1-a] - -Do you want to continue (Y/n)? - -Deleting cluster hello-world...done. -Deleted [https://container.googleapis.com/v1/projects/<$PROJECT_ID>/zones/us-central1-a/clusters/hello-world]. -``` - -This deletes the Google Compute Engine instances that are running the cluster. - -Finally delete the Docker registry storage bucket hosting your image(s) by using -`gsutil`, which should have been installed during the gcloud installation -process. For more information on gsutil, see [the gsutil documentation](https://cloud.google.com/storage/docs/gsutil) - -To list the images we created earlier in the tutorial: - -```shell -gsutil ls -``` - -You should see: - -```shell -gs://artifacts.<$PROJECT_ID>.appspot.com/ -``` - -And then to remove the all the images under this path, run: - -```shell -gsutil rm -r gs://artifacts.$PROJECT_ID.appspot.com/ -``` - -You can also delete the entire Google Cloud project but note that you must first disable billing on the project. Additionally, deleting a project will only happen after the current billing cycle ends. diff --git a/docs/tutorials/stateless-application/hello-minikube.md b/docs/tutorials/stateless-application/hello-minikube.md index 187e059b0a..6f2a47b897 100644 --- a/docs/tutorials/stateless-application/hello-minikube.md +++ b/docs/tutorials/stateless-application/hello-minikube.md @@ -1,6 +1,9 @@ --- title: Hello Minikube +redirect_from: +- "/docs/hellonode/" +- "/docs/hellonode.html" --- {% capture overview %} diff --git a/docs/user-guide/prereqs.md b/docs/user-guide/prereqs.md index 6e630ec0ea..de3cd3264f 100644 --- a/docs/user-guide/prereqs.md +++ b/docs/user-guide/prereqs.md @@ -3,9 +3,24 @@ assignees: - bgrant0607 - mikedanese title: Installing and Setting up kubectl +redirect_from: +- "/docs/getting-started-guides/kubectl/" +- "/docs/getting-started-guides/kubectl.html" --- -To deploy and manage applications on Kubernetes, you'll use the Kubernetes command-line tool, [kubectl](/docs/user-guide/kubectl/). It lets you inspect your cluster resources, create, delete, and update components, and much more. You will use it to look at your new cluster and bring up example apps. +To deploy and manage applications on Kubernetes, you'll use the +Kubernetes command-line tool, [kubectl](/docs/user-guide/kubectl/). It +lets you inspect your cluster resources, create, delete, and update +components, and much more. You will use it to look at your new cluster +and bring up example apps. + +You should use a version of kubectl that is at least as new as your +server. `kubectl version` will print the server and client versions. +Using the same version of kubectl as your server naturally works; +using a newer kubectl than your server also works; but if you use an +older kubectl with a newer server you may see odd validation errors. + +Here are a few methods to install kubectl. ## Install kubectl Binary Via curl @@ -65,6 +80,31 @@ export PATH=/platforms/darwin/amd64:$PATH export PATH=/platforms/linux/amd64:$PATH ``` +## Download as part of the Google Cloud SDK + +kubectl can be installed as part of the Google Cloud SDK: + +First install the [Google Cloud SDK](https://cloud.google.com/sdk/). + +After Google Cloud SDK installs, run the following command to install `kubectl`: + +```shell +gcloud components install kubectl +``` + +Do check that the version is sufficiently up-to-date using `kubectl version`. + +## Install with brew + +If you are on MacOS and using brew, you can install with: + +```shell +brew install kubectl +``` + +The homebrew project is independent from kubernetes, so do check that the version is +sufficiently up-to-date using `kubectl version`. + ## Configuring kubectl In order for kubectl to find and access the Kubernetes cluster, it needs a [kubeconfig file](/docs/user-guide/kubeconfig-file), which is created automatically when creating a cluster using kube-up.sh (see the [getting started guides](/docs/getting-started-guides/) for more about creating clusters). If you need access to a cluster you didn't create, see the [Sharing Cluster Access document](/docs/user-guide/sharing-clusters). @@ -80,6 +120,49 @@ $ kubectl cluster-info If you see a url response, you are ready to go. +## Enabling shell autocompletion + +kubectl includes autocompletion support, which can save a lot of typing! + +The completion script itself is generated by kubectl, so you typically just need to invoke it from your profile. + +Common examples are provided here, but for more details please consult `kubectl completion -h` + +### On Linux, using bash + +To add it to your current shell: `source <(kubectl completion bash)` + +To add kubectl autocompletion to your profile (so it is automatically loaded in future shells): + +```shell +echo "source <(kubectl completion bash)" >> ~/.bashrc +``` + +### On MacOS, using bash + +On MacOS, you will need to install the bash-completion support first: + +```shell +brew install bash-completion +``` + +To add it to your current shell: + +```shell +source $(brew --prefix)/etc/bash_completion +source <(kubectl completion bash) +``` + +To add kubectl autocompletion to your profile (so it is automatically loaded in future shells): + +```shell +echo "source $(brew --prefix)/etc/bash_completion" >> ~/.bash_profile +echo "source <(kubectl completion bash)" >> ~/.bash_profile +``` + +Please note that this only appears to work currently if you install using `brew install kubectl`, +and not if you downloaded kubectl directly. + ## What's next? [Learn how to launch and expose your application.](/docs/user-guide/quick-start) From fa9cb16339273a7964869885140dea77d9a12871 Mon Sep 17 00:00:00 2001 From: Jared Date: Wed, 1 Feb 2017 11:11:48 -0800 Subject: [PATCH 15/17] Fixed broken link to build directory https://github.com/kubernetes/kubernetes.github.io/issues/2384 --- docs/getting-started-guides/binary_release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started-guides/binary_release.md b/docs/getting-started-guides/binary_release.md index 6b12c75e1d..aaf8d1eb6b 100644 --- a/docs/getting-started-guides/binary_release.md +++ b/docs/getting-started-guides/binary_release.md @@ -33,7 +33,7 @@ cd kubernetes make release ``` -For more details on the release process see the [`build-tools/`](http://releases.k8s.io/{{page.githubbranch}}/build-tools/) directory +For more details on the release process see the [`build`](http://releases.k8s.io/{{page.githubbranch}}/build/) directory ### Download Kubernetes and automatically set up a default cluster From bd9b561ad1cc416e2440921bde2e73817260c29c Mon Sep 17 00:00:00 2001 From: Phillip Wittrock Date: Sun, 22 Jan 2017 11:48:07 -0800 Subject: [PATCH 16/17] Concept docs for kubectl configuration management methods. --- _data/concepts.yml | 3 + .../kubectl/object-management-overview.md | 21 +- ...ect-management-using-declarative-config.md | 958 ++++++++++++++++++ ...ct-management-using-imperative-commands.md | 159 +++ ...ject-management-using-imperative-config.md | 129 +++ .../tools/kubectl/simple_deployment.yaml | 16 + .../tools/kubectl/update_deployment.yaml | 15 + 7 files changed, 1283 insertions(+), 18 deletions(-) create mode 100644 docs/concepts/tools/kubectl/object-management-using-declarative-config.md create mode 100644 docs/concepts/tools/kubectl/object-management-using-imperative-commands.md create mode 100644 docs/concepts/tools/kubectl/object-management-using-imperative-config.md create mode 100644 docs/concepts/tools/kubectl/simple_deployment.yaml create mode 100644 docs/concepts/tools/kubectl/update_deployment.yaml diff --git a/_data/concepts.yml b/_data/concepts.yml index 71c6512909..7c0d0082a7 100644 --- a/_data/concepts.yml +++ b/_data/concepts.yml @@ -5,6 +5,9 @@ toc: - title: Kubectl Command Line section: - docs/concepts/tools/kubectl/object-management-overview.md + - docs/concepts/tools/kubectl/object-management-using-imperative-commands.md + - docs/concepts/tools/kubectl/object-management-using-imperative-config.md + - docs/concepts/tools/kubectl/object-management-using-declarative-config.md - title: Kubernetes Objects section: - docs/concepts/abstractions/overview.md diff --git a/docs/concepts/tools/kubectl/object-management-overview.md b/docs/concepts/tools/kubectl/object-management-overview.md index 0969086ff9..2604a50468 100644 --- a/docs/concepts/tools/kubectl/object-management-overview.md +++ b/docs/concepts/tools/kubectl/object-management-overview.md @@ -59,12 +59,6 @@ Disadvantages compared to object configuration: - Commands do not provide a source of records except for what is live. - Commands do not provide a template for creating new objects. -{% comment %} -If we use Markdown comments instead of HTML comments, they won't appear in the built HTML files. -For a tutorial on how to use Imperative Commands for app management, see: -[App Management Using Comands](/docs/tutorials/kubectl/app-management-using-commands/) -{% endcomment %} - ## Imperative object configuration When using imperative object configuration, a user operates on object @@ -124,11 +118,6 @@ Disadvantages compared to declarative object configuration: - Imperative object configuration works best on files, not directories. - Updates to live objects must be reflected in configuration files, or they will be lost during the next replacement. -{% comment %} -For a tutorial on how to use Yaml Config for app management, see: -[App Management Yaml Config](/docs/tutorials/kubectl/app-management-using-yaml-config/) -{% endcomment %} - ## Declarative object configuration When using declarative object configuration, a user operates on object @@ -170,20 +159,16 @@ Disadvantages compared to imperative object configuration: - Declarative object configuration is harder to debug and understand results when they are unexpected. - Partial updates using diffs create complex merge and patch operations. -{% comment %} -For a tutorial on how to use Yaml Config with multiple writers, see: -[App Management Yaml Config](/docs/tutorials/kubectl/app-management-using-yaml-config-multiple-writers/) -{% endcomment %} - {% endcapture %} {% capture whatsnext %} +- [Managing Kubernetes Objects Using Imperative Commands](/docs/concepts/tools/kubectl/object-management-using-imperative-commands/) +- [Managing Kubernetes Objects Using Object Configuration (Imperative)](/docs/concepts/tools/kubectl/object-management-using-imperative-config/) +- [Managing Kubernetes Objects Using Object Configuration (Declarative)](/docs/concepts/tools/kubectl/object-management-using-declarative-config/) - [Kubectl Command Reference](/docs/user-guide/kubectl/v1.5/) - [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/) {% comment %} -- [App Management Using Yaml Config](/docs/tutorials/kubectl/declarative-app-management-using-yaml-config/) -- [App Management Using Yaml Config With Multiple Writers](/docs/tutorials/kubectl/declarative-app-management-using-yaml-config-multiple-writers/) {% endcomment %} {% endcapture %} diff --git a/docs/concepts/tools/kubectl/object-management-using-declarative-config.md b/docs/concepts/tools/kubectl/object-management-using-declarative-config.md new file mode 100644 index 0000000000..ce90126be8 --- /dev/null +++ b/docs/concepts/tools/kubectl/object-management-using-declarative-config.md @@ -0,0 +1,958 @@ +--- +title: Declarative Management of Kubernetes Objects Using Configuration Files +--- + +{% capture overview %} +Kubernetes objects can be created, updated, and deleted by storing multiple +object configuration files in a directory and using `kubectl apply` to +recursively create and update those objects as needed. This method +retains writes made to live objects without merging the changes +back into the object configuration files. +{% endcapture %} + +{% capture body %} + +## Trade-offs + +The `kubectl` tool supports three kinds of object management: + +* Imperative commands +* Imperative object configuration +* Declarative object configuration + +See [Kubernetes Object Management](/docs/concepts/tools/kubectl/object-management-overview/) +for a discussion of the advantages and disadvantage of each kind of object management. + +## Before you begin + +Declarative object configuration requires a firm understanding of +the Kubernetes object definitions and configuration. Read and complete +the following documents if you have not already: + +- [Managing Kubernetes Objects Using Imperative Commands](/docs/concepts/tools/kubectl/object-management-using-imperative-commands/) +- [Imperative Management of Kubernetes Objects Using Configuration Files](/docs/concepts/tools/kubectl/object-management-using-imperative-config/) + +Following are definitions for terms used in this document: + +- *object configuration file / configuration file*: A file that defines the + configuration for a Kubernetes object. This topic shows how to pass configuration + files to `kubectl apply`. Configuration files are typically stored in source control, such as Git. +- *live object configuration / live configuration*: The live configuration + values of an object, as observed by the Kubernetes cluster. These are kept in the Kubernetes + cluster storage, typically etcd. +- *declarative configuration writer / declarative writer*: A person or software component + that makes updates to a live object. The live writers refered to in this topic make changes + to object configuration files and run `kubectl apply` to write the changes. + +## How to create objects + +Use `kubectl apply` to create all objects, except those that already exist, +defined by configuration files in a specified directory: + +```shell +kubectl apply -f / +``` + +This sets the `kubectl.kubernetes.io/last-applied-configuration: '{...}'` +annotation on each object. The annotation contains the contents of the object +configuration file that was used to create the object. + +**Note**: Add the `-R` flag to recursively process directories. + +Here's an example of an object configuration file: + +{% include code.html language="yaml" file="simple_deployment.yaml" ghlink="/docs/concepts/tools/simple_deployment.yaml" %} + +Create the object using `kubectl apply`: + +```shell +kubectl apply -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml +``` + +Print the live configuration using `kubectl get`: + +```shell +kubectl get -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml -o yaml +``` + +The output shows that the `kubectl.kubernetes.io/last-applied-configuration` annotation +was written to the live configuration, and it matches the configuration file: + +```shell +kind: Deployment +metadata: + annotations: + # ... + # This is the json representation of simple_deployment.yaml + # It was written by kubectl apply when the object was created + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"minReadySeconds":5,"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + # ... + minReadySeconds: 5 + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.7.9 + # ... + name: nginx + ports: + - containerPort: 80 + # ... + # ... + # ... + # ... +``` + +## How to update objects + +You can also use `kubectl apply` to update all objects defined in a directory, even +if those objects already exist. This approach accomplishes the following: + +1. Sets fields that appear in the configuration file in the live configuration. +2. Clears fields removed from the configuration file in the live configuration. + +```shell +kubectl apply -f / +``` + +**Note**: Add the `-R` flag to recursively process directories. + +Here's an example configuration file: + +{% include code.html language="yaml" file="simple_deployment.yaml" ghlink="/docs/concepts/tools/simple_deployment.yaml" %} + +Create the object using `kubectl apply`: + +```shell +kubectl apply -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml +``` + +**Note:** For purposes of illustration, the preceding command refers to a single +configuration file instead of a directory. + +Print the live configuration using `kubectl get`: + +```shell +kubectl get -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml -o yaml +``` + +The output shows that the `kubectl.kubernetes.io/last-applied-configuration` annotation +was written to the live configuration, and it matches the configuration file: + +```shell +kind: Deployment +metadata: + annotations: + # ... + # This is the json representation of simple_deployment.yaml + # It was written by kubectl apply when the object was created + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"minReadySeconds":5,"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + # ... + minReadySeconds: 5 + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.7.9 + # ... + name: nginx + ports: + - containerPort: 80 + # ... + # ... + # ... + # ... +``` + +Directly update the `replicas` field in the live configuration by using `kubectl scale`. +This does not use `kubectl apply`: + +```shell +kubectl scale deployment/nginx-deployment --replicas 2 +``` + +Print the live configuration using `kubectl get`: + +```shell +kubectl get -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml -o yaml +``` + +The output shows that the `replicas` field has been set to 2, and the `last-applied-configuration` +annotation does not contain a `replicas` field: + +``` +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + annotations: + # ... + # note that the annotation does not contain replicas + # because it was not updated through apply + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"minReadySeconds":5,"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + replicas: 2 # written by scale + # ... + minReadySeconds: 5 + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.7.9 + # ... + name: nginx + ports: + - containerPort: 80 + # ... +``` + +Update the `simple_deployment.yaml` configuration file to change the image from +`nginx:1.7.9` to `nginx:1.11.9`, and delete the `minReadySeconds` field: + +{% include code.html language="yaml" file="update_deployment.yaml" ghlink="/docs/concepts/tools/update_deployment.yaml" %} + +Apply the changes made to the configuration file: + +```shell +kubectl apply -f http://k8s.io/docs/concepts/tools/kubectl/updated_deployment.yaml +``` + +Print the live configuration using `kubectl get`: + +``` +kubectl get -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml -o yaml +``` + +The output shows the following changes to the live configuration: + +- The `replicas` field retains the value of 2 set by `kubectl scale`. + This is possible because it is omitted from the configuration file. +- The `image` field has been updated to `nginx:1.11.9` from `nginx:1.7.9`. +- The `last-applied-configuration` annotation has been updated with the new image. +- The `minReadySeconds` field has been cleared. +- The `last-applied-configuration` annotation no longer contains the `minReadySeconds` field. + +```shell +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + annotations: + # ... + # The annotation contains the updated image to nginx 1.11.9, + # but does not contain the updated replicas to 2 + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + replicas: 2 # Set by `kubectl scale`. Ignored by `kubectl apply`. + # minReadySeconds cleared by `kubectl apply` + # ... + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.11.9 # Set by `kubectl apply` + # ... + name: nginx + ports: + - containerPort: 80 + # ... + # ... + # ... + # ... +``` + +**Warning**: Mixing `kubectl apply` with the imperative object configuration commands +`create` and `replace` is not supported. This is because `create` +and `replace` do not retain the `kubectl.kubernetes.io/last-applied-configuration` +that `kubectl apply` uses to compute updates. + +**Warning**: As of Kubernetes 1.5, the `kubectl edit` command is +incompatible with `kubectl apply`, and the two should not be +used together. + +## How to delete objects + +There are two approaches to delete objects managed by `kubectl apply`. + +### Recommended: `delete -f ` + +Manually deleting objects using the imperative command is the recommended +approach, as it is more explicit about what is being deleted, and less likely +to result in the user deleting something unintentionally: + +```shell +delete -f +``` + +### Alternative: `kubectl apply -f --prune -l your=label` + +Only use this if you know what you are doing. + +**Warning:** `kubectl apply --prune` is in alpha, and backwards incompatible +changes might be introduced in subsequent releases. + +**Warning**: You must be careful when using this command, so that you +do not delete objects unintentionally. + +As an alternative to `kubectl delete`, you can use `kubectl apply` to identify objects to be deleted after their +configuration files have been removed from the directory. Apply with `--prune` +queries the API server for all objects matching a set of labels, and attempts +to match the returned live object configurations against the object +configuration files. If an object matches the query, and it does not have a +configuration file in the directory, and it does not have a `last-applied-configuration` annotation, +it is deleted. + +{% comment %} +TODO(pwittrock): We need to change the behavior to prevent the user from running apply on subdirectories unintentionally. +{% endcomment %} + +```shell +kubectl apply -f --prune -l +``` + +**Important:** Apply with prune should only be run against the root directory +containing the object configuration files. Running against sub-directories +can cause objects to be unintentionally deleted if they are returned +by the label selector query specified with `-l ` and +do not appear in the subdirectory. + +## How to view an object + +You can use `kubectl get` with `-o yaml` to view the configuration of a live object: + +```shell +kubectl get -f -o yaml +``` + +## How apply calculates differences and merges changes + +**Definition:** A *patch* is an update operation that is scoped to specific +fields of an object instead of the entire object. +This enables updating only a specific set of fields on an object without +reading the object first. + +When `kubectl apply` updates the live configuration for an object, +it does so by sending a patch request to the API server. The +patch defines updates scoped to specific fields of the live object +configuration. The `kubectl apply` command calculates this patch request +using the configuration file, the live configuration, and the +`last-applied-configuration` annotation stored in the live configuration. + +### Merge patch calculation + +The `kubectl apply` command writes the contents of the configuration file to the +`kubectl.kubernetes.io/last-applied-configuration` annotation. This +is used to identify fields that have been removed from the configuration +file and need to be cleared from the live configuration. Here are the steps used +to caluculate which fields should be deleted or set: + +1. Calculate the fields to delete. Thes are the fields present in `last-applied-configuration` and missing from the configuration file. +2. Calculate the fields to add or set. These are the fields present in the configuration file whose values don't match the live configuration. + +Here's an example. Suppose this is the configuration file for a Deployment object: + +{% include code.html language="yaml" file="update_deployment.yaml" ghlink="/docs/concepts/tools/update_deployment.yaml" %} + +Also, suppose this is the live configuration for the same Deployment object: + +```shell +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + annotations: + # ... + # note that the annotation does not contain replicas + # because it was not updated through apply + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"minReadySeconds":5,"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + replicas: 2 # written by scale + # ... + minReadySeconds: 5 + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.7.9 + # ... + name: nginx + ports: + - containerPort: 80 + # ... +``` + +Here are the merge calculations that would be performed by `kubectl apply`: + +1. Calculate the fields to delete by reading values from + `last-applied-configuration` and comparing them to values in the + configuration file. In this example, `minReadySeconds` appears in the + `last-applied-configuration` annotation, but does not appear in the configuration file. + **Action:** Clear `minReadySeconds` from the live configuration. +2. Calculate the fields to set by reading values from the configuration + file and comparing them to values in the live configuration. In this example, + the value of `image` in the configuration file does not match + the value in the live configuration. **Action:** Set the value of `image` in the live configuration. +3. Set the `last-applied-configuration` annotation to match the value + of the configuration file. +4. Merge the results from 1, 2, 3 into a single patch request to the API server. + +Here is the live configuration that is the result of the merge: + +```shell +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + annotations: + # ... + # The annotation contains the updated image to nginx 1.11.9, + # but does not contain the updated replicas to 2 + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"extensions/v1beta1","kind":"Deployment", + "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"}, + "spec":{"template":{"metadata":{"labels":{"app":"nginx"}}, + "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx", + "ports":[{"containerPort":80}]}]}}}} + # ... +spec: + replicas: 2 # Set by `kubectl scale`. Ignored by `kubectl apply`. + # minReadySeconds cleared by `kubectl apply` + # ... + template: + metadata: + # ... + labels: + app: nginx + spec: + containers: + - image: nginx:1.11.9 # Set by `kubectl apply` + # ... + name: nginx + ports: + - containerPort: 80 + # ... + # ... + # ... + # ... +``` + +{% comment %} +TODO(1.6): For 1.6, add the following bullet point to 1. + +- clear fields explicitly set to null in the local object configuration file regardless of whether they appear in the last-applied-configuration +{% endcomment %} + +### How different types of fields are merged + +How a particular field in a configuration file is merged with +with the live configuration depends on the +type of the field. There are several types of fields: + +- *primitive*: A field of type string, integer, or boolean. + For example, `image` and `replicas` are primitive fields. **Action:** Replace. + +- *map*, also called *object*: A field of type map or a complex type that contains subfields. For example `labels` + and `annotations` are maps; `spec` and `metadata` are complex types. **Action:** Merge elements or subfields. + +- *list*: A field containing a list of items that can be either primitive types, maps, or complex types. + For example, `containers`, `ports`, and `args` are lists. **Action:** Varies. + +When `kubectl apply` updates a map or list field, it typically does +not replace the entire field, but instead updates the individual subelements. +For instance, when merging the `spec` on a Deployment, the entire `spec` is +not replaced. Instead the subfields of `spec`, such as `replicas`, are compared +and merged. + +### Merging changes to primitive fields + +Primative fieldss are replaced or cleared. + +**Note:** '-' is used for "not applicable" because the value is not used. + +| Field in object configuration file | Field in live object configuration | Field in last-applied-configuration | Action | +|-------------------------------------|------------------------------------|-------------------------------------|-------------------------------------------| +| Yes | Yes | - | Set live to configuration file value. | +| Yes | No | - | Set live to local configuration. | +| No | - | Yes | Clear from live configuration. | +| No | - | No | Do nothing. Keep live value. | + +### Merging changes to map or complex fields + +Fields that represent maps or complex-types are merged by comparing each of the sub fields or elements of of the map / complex-type: + +**Note:** '-' is used for "not applicable" because the value is not used. + +| Key in object configuration file | Key in live object configuration | Field in last-applied-configuration | Action | +|-------------------------------------|------------------------------------|-------------------------------------|----------------------------------| +| Yes | Yes | - | Compare sub fields values. | +| Yes | No | - | Set live to local configuration. | +| No | - | Yes | Delete from live configuration. | +| No | - | No | Do nothing. Keep live value. | + +### Merging changes for fields of type list + +Merging changes to a list uses one of three strategies: + +* Replace the list. +* Merge individual elements in a list of complex elements. +* Merge a list of primitive elements. + +The choice of strategy is made on a per-field basis. + +#### Replace the list + +Treat the list the same as a primitive field. Replace or delete the +entire list. This preserves ordering. + +**Example:** Use `kubectl apply` to update the `args` field of a Container in a Pod. This sets +the value of `args` in the live configuration to the value in the configuration file. +Any `args` elements that had previously been added to the live configuration are lost. +The order of the `args` elements defined in the configuration file is +retained in the live configuration. + +```yaml +# last-applied-configuration value + args: ["a, b"] + +# configuration file value + args: ["a", "c"] + +# live configuration + args: ["a", "b", "d"] + +# result after merge + args: ["a", "c"] +``` + +**Explanation:** The merge used the configuration file value as the new list value. + +#### Merge individual elements of a list of complex elements: + +Treat the list as a map, and treat a specific field of each element as a key. +Add, delete, or update individual elements. This does not preserve ordering. + +This merge strategy uses a special tag on each field called a `mergeKey`. The +`mergeKey` is defined for each field in the Kubernetes source code: +[types.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/api/v1/types.go#L2119) +When merging a list of complex elements, the field specified as the `mergeKey` for a given element +is used like a map key for that element. + +**Example:** Use `kubectl apply` to update the `containers` field of a PodSpec. +This merges the list as though `containers` was a map where each element is keyed +by `name`. + +```yaml +# last-applied-configuration value + containers: + - name: nginx + image: nginx:1.10 + - name: nginx-helper-a # key: nginx-helper-a; will be deleted in result + image: helper:1.3 + - name: nginx-helper-b # key: nginx-helper-b; will be retained + image: helper:1.3 + +# configuration file value + containers: + - name: nginx + image: nginx:1.11 + - name: nginx-helper-b + image: helper:1.3 + - name: nginx-helper-c # key: nginx-helper-c; will be added in result + image: helper:1.3 + +# live configuration + containers: + - name: nginx + image: nginx:1.10 + - name: nginx-helper-a + image: helper:1.3 + - name: nginx-helper-b + image: helper:1.3 + args: ["run"] # Field will be retained + - name: nginx-helper-d # key: nginx-helper-d; will be retained + image: helper:1.3 + +# result after merge + containers: + - name: nginx + image: nginx:1.10 + # Element nginx-helper-a was deleted + - name: nginx-helper-b + image: helper:1.3 + args: ["run"] # Field was retained + - name: nginx-helper-c # Element was added + image: helper:1.3 + - name: nginx-helper-d # Element was ignored + image: helper:1.3 +``` + +**Explanation:** + +- The container named "nginx-helper-a" was deleted because no container + named "nginx-helper-a" appeared in the configuration file. +- The container named "nginx-helper-b" retained the changes to `args` + in the live configuration. `kubectl apply` was able to identify + that "nginx-helper-b" in the live configuration was the same + "nginx-helper-b" as in the configuration file, even though their fields + had different values (no `args` in the configuration file). This is + because the `mergeKey` field value (name) was identical in both. +- The container named "nginx-helper-c" was added because no container + with that name appeared in the live configuration, but one with + that name appeared in the configuration file. +- The container named "nginx-helper-d" was retained because + no element with that name appeared in the last-applied-configuration. + +#### Merge a list of primitive elements + +As of Kubernetes 1.5, merging lists of primitive elements is not supported. + +**Note:** Which of the above strategies is chosen for a given field is controlled by +the `patchStrategy` tag in [types.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/api/v1/types.go#L2119) +If no `patchStrategy` is specified for a field of type list, then +the list is replaced. + +{% comment %} +TODO(pwittrock): Uncomment this for 1.6 + +- Treat the list as a set of primitives. Replace or delete individual + elements. Does not preserve ordering. Does not preserve duplicates. + +**Example:** Using apply to update the `finalizers` field of ObjectMeta +keeps elements added to the live configuration. Ordering of finalizers +is lost. +{% endcomment %} + +## Default field values + +The API server sets certain fields to default values in the live configuration if they are +not specified when the object is created. + +Here's a configuration file for a Deployment. The file does not specify `strategy` or `selector`: + +{% include code.html language="yaml" file="simple_deployment.yaml" ghlink="/docs/concepts/tools/simple_deployment.yaml" %} + +Create the object using `kubectl apply`: + +```shell +kubectl apply -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml +``` + +Print the live configuration using `kubectl get`: + +```shell +kubectl get -f http://k8s.io/docs/concepts/tools/kubectl/simple_deployment.yaml -o yaml +``` + +The output shows that the API server set several fields to default values in the live +configuration. These fields were not specified in the configuration file. + +```shell +apiVersion: extensions/v1beta1 +kind: Deployment +# ... +spec: + minReadySeconds: 5 + replicas: 1 # defaulted by apiserver + selector: + matchLabels: # defaulted by apiserver - derived from template.metadata.labels + app: nginx + strategy: + rollingUpdate: # defaulted by apiserver - derived from strategy.type + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate # defaulted apiserver + template: + metadata: + creationTimestamp: null + labels: + app: nginx + spec: + containers: + - image: nginx:1.7.9 + imagePullPolicy: IfNotPresent # defaulted by apiserver + name: nginx + ports: + - containerPort: 80 + protocol: TCP # defaulted by apiserver + resources: {} # defaulted by apiserver + terminationMessagePath: /dev/termination-log # defaulted by apiserver + dnsPolicy: ClusterFirst # defaulted by apiserver + restartPolicy: Always # defaulted by apiserver + securityContext: {} # defaulted by apiserver + terminationGracePeriodSeconds: 30 # defaulted by apiserver +# ... +``` + +**Note:** Some of the fields' default values have been derived from +the values of other fields that were specified in the configuration file, +such as the `selector` field. + +In a patch request, defaulted fields are not re-defaulted unless they are explicitly cleared +as part of a patch request. This can cause unexpected behavior for +fields that are defaulted based +on the values of other fields. When the other fields are later changed, +the values defaulted from them will not be updated unless they are +explicitly cleared. + +For this reason, it is recommended that certain fields defaulted +by the server are explicitly defined in the configuration file, even +if the desired values match the server defaults. This makes it +easier to recognize conflicting values that will not be re-defaulted +by the server. + +**Example:** + +```yaml +# last-applied-configuration +spec: + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 + +# configuration file +spec: + strategy: + type: Recreate # updated value + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 + +# live configuration +spec: + strategy: + type: RollingUpdate # defaulted value + rollingUpdate: # defaulted value derived from type + maxSurge : 1 + maxUnavailable: 1 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 + +# result after merge - ERROR! +spec: + strategy: + type: Recreate # updated value: incompatible with rollingUpdate + rollingUpdate: # defaulted value: incompatible with "type: Recreate" + maxSurge : 1 + maxUnavailable: 1 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 +``` + +**Explanation:** + +1. The user creates a Deployment without defining `strategy.type`. +2. The server defaults `strategy.type` to `RollingUpdate` and defaults the + `strategy.rollingUpdate` values. +3. The user changes `strategy.type` to `Recreate`. The `strategy.rollingUpdate` + values remain at their defaulted values, though the server expects them to be cleared. + If the `strategy.rollingUpdate` values had been defined initially in the configuration file, + it would have been more clear that they needed to be deleted. +4. Apply fails because `strategy.rollingUpdate` is not cleared. The `strategy.rollingupdate` + field cannot be defined with a `strategy.type` of `Recreate`. + +Recommendation: These fields should be explicitly defined in the object configuration file: + +- Selectors and PodTemplate labels on workloads, such as Deployment, StatefulSet, Job, DaemonSet, + ReplicaSet, and ReplicationController +- Deployment rollout strategy + +### How to clear server-defaulted fields or fields set by other writers + +As of Kubernetes 1.5, fields that do not appear in the configuration file cannot be +cleared by a merge operation. Here are some workarounds: + +Option 1: Remove the field by directly modifying the live object. + +**Note:** As of Kubernetes 1.5, `kubectl edit` does not work with `kubectl apply`. +Using these together will cause unexpected behavior. + +Option 2: Remove the field through the configuration file. + +1. Add the field to the configuration file to match the live object. +1. Apply the configuration file; this updates the annotation to include the field. +1. Delete the field from the configuration file. +1. Apply the configuration file; this deletes the field from the live object and annotation. + +{% comment %} +TODO(1.6): Update this with the following for 1.6 + +Fields that do not appear in the configuration file can be cleared by +setting their values to `null` and then applying the configuration file. +For fields defaulted by the server, this triggers re-defaulting +the values. +{% endcomment %} + +## How to change ownership of a field between the configuration file and direct imperative writers + +These are the only methods you should use to change an individual object field: + +- Use `kubectl apply`. +- Write directly to the live configuration without modifying the configuration file: +for example, use `kubectl scale`. + +### Changing the owner from a direct imperative writer to a configuration file + +Add the field to the configuration file. For the field, discontinue direct updates to +the live configuration that do not go through `kubectl apply`. + +### Changing the owner from a configuration file to a direct imperative writer + +As of Kubernetes 1.5, changing ownership of a field from a configuration file to +an imperative writer requires manual steps: + +- Remove the field from the configuration file. +- Remove the field from the `kubectl.kubernetes.io/last-applied-configuration` annotation on the live object. + +## Changing management methods + +Kubernetes objects should be managed using only one method at a time. +Switching from one method to another is possible, but is a manual process. + +**Exception:** It is OK to use imperative deletion with declarative management. + +{% comment %} +TODO(pwittrock): We need to make using imperative commands with +declarative object configuration work so that it doesn't write the +fields to the annotation, and instead. Then add this bullet point. + +- using imperative commands with declarative configuration to manage where each manages different fields. +{% endcomment %} + +### Migrating from imperative command management to declarative object configuration + +Migrating from imperative command management to declarative object +configuration involves several manual steps: + +1. Export the live object to a local configuration file: + + kubectl get / -o yaml --export > _.yaml + +1. Manually remove the `status` field from the configuration file. + + **Note:** This step is optional, as `kubectl apply` does not update the status field + even if it is present in the configuration file. + +1. Set the `kubectl.kubernetes.io/last-applied-configuration` annotation on the object: + + kubectl replace --save-config -f _.yaml + +1. Change processes to use `kubectl apply` for managing the object exclusively. + +{% comment %} +TODO(pwittrock): Why doesn't export remove the status field? Seems like it should. +{% endcomment %} + +### Migrating from imperative object configuration to declarative object configuration + +1. Set the `kubectl.kubernetes.io/last-applied-configuration` annotation on the object: + + kubectl replace --save-config -f _.yaml + +1. Change processes to use `kubectl apply` for managing the object exclusively. + +## Defining controller selectors and PodTemplate labels + +**Warning**: Updating selectors on controllers is strongly discouraged. + +The recommended approach is to define a single, immutable PodTemplate label +used only by the controller selector with no other semantic meaning. + +**Example:** + +```yaml +selector: + matchLabels: + controller-selector: "v1beta1/deployment/nginx" +template: + metadata: + labels: + controller-selector: "v1beta1/deployment/nginx" +``` + +## Support for ThirdPartyResources + +As of Kubernetes 1.5, ThirdPartyResources are not supported by `kubectl apply`. +The recommended approach for ThirdPartyResources is to use [imperative object configuration](/docs/concepts/tools/kubectl/object-management-using-imperative-config/). +{% endcapture %} + +{% capture whatsnext %} +- [Managing Kubernetes Objects Using Imperative Commands](/docs/concepts/tools/kubectl/object-management-using-imperative-commands/) +- [Imperative Management of Kubernetes Objects Using Configuration Files](/docs/concepts/tools/kubectl/object-management-using-imperative-config/) +- [Kubectl Command Reference](/docs/user-guide/kubectl/v1.5/) +- [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/) +{% endcapture %} + +{% include templates/concept.md %} diff --git a/docs/concepts/tools/kubectl/object-management-using-imperative-commands.md b/docs/concepts/tools/kubectl/object-management-using-imperative-commands.md new file mode 100644 index 0000000000..b49114f04a --- /dev/null +++ b/docs/concepts/tools/kubectl/object-management-using-imperative-commands.md @@ -0,0 +1,159 @@ +--- +title: Managing Kubernetes Objects Using Imperative Commands +--- + +{% capture overview %} +Kubernetes objects can quickly be created, updated, and deleted directly using +imperative commands built into the `kubectl` command-line tool. This document +explains how those commands are organized and how to use them to manage live objects. +{% endcapture %} + +{% capture body %} + +## Trade-offs + +The `kubectl` tool supports three kinds of object management: + +* Imperative commands +* Imperative object configuration +* Declarative object configuration + +See [Kubernetes Object Management](/docs/concepts/tools/kubectl/object-management-overview/) +for a discussion of the advantages and disadvantage of each kind of object management. + +## How to create objects + +The `kubectl` tool supports verb-driven commands for creating some of the most common +object types. The commands are named to be recognizable to users unfamiliar with +the Kubernetes object types. + +- `run`: Create a new Deployment object to run Containers in one or more Pods. +- `expose`: Create a new Service object to load balance traffic across Pods. +- `autoscale`: Create a new Autoscaler object to automatically horizontally scale a controller, such as a Deployment. + +The `kubectl` tool also supports creation commands driven by object type. +These commands support more object types and are more explicit about +their intent, but require users to know the type of objects they intend +to create. + +- `create [] ` + +Some objects types have subtypes that you can specify in the `create` command. +For example, the Service object has several subtypes including ClusterIP, +LoadBalancer, and NodePort. Here's an example that creates a Service with +subtype NodePort: + +```shell +kubectl create service nodeport +``` + +In the preceding example, the `create service nodeport` command is called +a subcommand of the `create service` command. + +You can use the `-h` flag to find the arguments and flags supported by +a subcommand: + +```shell +kubectl create service nodeport -h +``` + +## How to update objects + +The `kubectl` command supports verb-driven commands for some common update operations. +These commands are named to enable users unfamiliar with Kubernetes +objects to perform updates without knowing the specific fields +that must be set: + +- `scale`: Horizontally scale a controller to add or remove Pods by updating the replica count of the controller. +- `annotate`: Add or remove an annotation from an object. +- `label`: Add or remove a label from an object. + +The `kubectl` command also supports update commands driven by an aspect of the object. +Setting this aspect may set different fields for different object types: + +- `set` : Set an aspect of an object. + +**Note**: In Kubernetes version 1.5, not every verb-driven command has an +associated field-driven command. + +The `kubectl` tool supports these additional ways to update a live object directly, +however they require a better understanding of the Kubernetes object schema. + +- `edit`: Directly edit the raw configuration of a live object by opening its configuration in an editor. +- `patch`: Directly modify specific fields of a live object by using a patch string. +For more details on patch strings, see the patch section in +[API Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#patch-operations). + +## How to delete objects + +You can use the `delete` command to delete an object from a cluster: + +- `delete /` + +**Note**: You can use `kubectl delete` for both imperative commands and imperative object +configuration. The difference is in the arguments passed to the command. To use +`kubectl delete` as an imperative command, pass the object to be deleted as +an argument. Here's an example that passes a Deployment object named nginx: + +```shell +kubectl delete deployment/nginx +``` + +## How to view an object + +{% comment %} +TODO(pwittrock): Uncomment this when implemented. + +You can use `kubectl view` to print specific fields of an object. + +- `view`: Prints the value of a specific field of an object. + +{% endcomment %} + + + +There are several commands for printing information about an object: + +- `get`: Prints basic information about matching objects. Use `get -h` to see a list of options. +- `describe`: Prints aggregated detailed information about matching objects. +- `logs`: Prints the stdout and stderr for a container running in a Pod. + +## Using `set` commands to modify objects before creation + +There are some object fields that don't have a flag you can use +in a `create` command. In some of those cases, you can use a combination of +`set` and `create` to specify a value for the field before object +creation. This is done by piping the output of the `create` command to the +`set` command, and then back to the `create` command. Here's an example: + +```sh +kubectl create service clusterip -o yaml --dry-run | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f - +``` + +1. The `create service -o yaml --dry-run` command creates the configuration for the Service, but prints it to stdout as YAML instead of sending it to the Kubernetes API server. +1. The `set --local -f - -o yaml` command reads the configuration from stdin, and writes the updated configuration to stdout as YAML. +1. The `kubectl create -f -` command creates the object using the configuration provided via stdin. + +## Using `--edit` to modify objects before creation + +You can use `kubectl create --edit` to make arbitrary changes to an object +before it is created. Here's an example: + +```sh +kubectl create service clusterip my-svc -o yaml --dry-run > /tmp/srv.yaml +kubectl create --edit -f /tmp/srv.yaml +``` + +1. The `create service` command creates the configuration for the Service and saves it to `/tmp/srv.yaml`. +1. The `create --edit` command opens the configuration file for editing before it creates the object. + +{% endcapture %} + +{% capture whatsnext %} +- [Managing Kubernetes Objects Using Object Configuration (Imperative)](/docs/concepts/tools/kubectl/object-management-using-imperative-config/) +- [Managing Kubernetes Objects Using Object Configuration (Declarative)](/docs/concepts/tools/kubectl/object-management-using-declarative-config/) +- [Kubectl Command Reference](/docs/user-guide/kubectl/v1.5/) +- [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/) +{% endcapture %} + +{% include templates/concept.md %} diff --git a/docs/concepts/tools/kubectl/object-management-using-imperative-config.md b/docs/concepts/tools/kubectl/object-management-using-imperative-config.md new file mode 100644 index 0000000000..2ce6319749 --- /dev/null +++ b/docs/concepts/tools/kubectl/object-management-using-imperative-config.md @@ -0,0 +1,129 @@ +--- +title: Imperative Management of Kubernetes Objects Using Configuration Files +--- + +{% capture overview %} +Kubernetes objects can be created, updated, and deleted by using the `kubectl` +command-line tool along with an object configuration file written in YAML or JSON. +This document explains how to define and manage objects using configuration files. +{% endcapture %} + +{% capture body %} + +## Trade-offs + +The `kubectl` tool supports three kinds of object management: + +* Imperative commands +* Imperative object configuration +* Declarative object configuration + +See [Kubernetes Object Management](/docs/concepts/tools/kubectl/object-management-overview/) +for a discussion of the advantages and disadvantage of each kind of object management. + +## How to create objects + +You can use `kubectl create -f` to create an object from a configuration file. +Refer to the [kubernetes object schema reference](/docs/resources-reference/v1.5/) +for details. + +- `create -f ` + +## How to update objects + +You can use `kubectl replace -f` to update a live object according to a +configuration file. + +- `replace -f ` + +## How to delete objects + +You can use `kubectl delete -f` to delete an object that is described in a +configuration file. + +- `delete -f ` + +## How to view an object + +You can use `kubectl get -f` to view information about an object that is +described in a configuration file. + +- `get -f -o yaml` + +The `-o yaml` flag specifies that the full object configuration is printed. +Use `get -h` to see a list of options. + +## Limitations + +The `create`, `replace`, and `delete` commands work well when each object's +configuration is fully defined and recorded in its configuration +file. However when a live object is updated, and the updates are not merged +into its configuration file, the updates will be lost the next time a `replace` +is executed. This is can happen if a controller, such as +a HorizontalPodAutoscaler, makes updates directly to a live object. Here's +an example: + +1. You create an object from a configuration file. +1. Another source updates the object by changing some field. +1. You replace the object from the configuration file. Changes made by +the other source in step 2 are lost. + +If you need to support multiple writers to the same object, you can use +`kubectl apply` to manage the object. + +## Creating and editing an object from a URL without saving the configuration + +Suppose you have the URL of an object configuration file. You can use +`kubectl create --edit` to make changes to the configuration before the +object is created. This is particularly useful for tutorials and tasks +that point to a configuration file that could be modified by the reader. + +```sh +kubectl create -f --edit +``` + +## Migrating from imperative commands to imperative object configuration + +Migrating from imperative commands to imperative object configuration involves +several manual steps. + +1. Export the live object to a local object configuration file: + + kubectl get / -o yaml --export > _.yaml + +1. Manually remove the status field from the object configuration file. + +1. For subsequent object management, use `replace` exclusively. + + kubectl replace -f _.yaml + + +## Defining controller selectors and PodTemplate labels + +**Warning**: Updating selectors on controllers is strongly discouraged. + +The recommended approach is to define a single, immutable PodTemplate label +used only by the controller selector with no other semantic meaning. + +Example label: + +```yaml +selector: + matchLabels: + controller-selector: "v1beta1/deployment/nginx" +template: + metadata: + labels: + controller-selector: "v1beta1/deployment/nginx" +``` + +{% endcapture %} + +{% capture whatsnext %} +- [Managing Kubernetes Objects Using Imperative Commands](/docs/concepts/tools/kubectl/object-management-using-imperative-commands/) +- [Managing Kubernetes Objects Using Object Configuration (Declarative)](/docs/concepts/tools/kubectl/object-management-using-declarative-config/) +- [Kubectl Command Reference](/docs/user-guide/kubectl/v1.5/) +- [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/) +{% endcapture %} + +{% include templates/concept.md %} diff --git a/docs/concepts/tools/kubectl/simple_deployment.yaml b/docs/concepts/tools/kubectl/simple_deployment.yaml new file mode 100644 index 0000000000..0348883c24 --- /dev/null +++ b/docs/concepts/tools/kubectl/simple_deployment.yaml @@ -0,0 +1,16 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + minReadySeconds: 5 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 diff --git a/docs/concepts/tools/kubectl/update_deployment.yaml b/docs/concepts/tools/kubectl/update_deployment.yaml new file mode 100644 index 0000000000..d2c2d82010 --- /dev/null +++ b/docs/concepts/tools/kubectl/update_deployment.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.11.9 # update the image + ports: + - containerPort: 80 From db6506f640b8a0c68596fcacc0f7452b4db58b04 Mon Sep 17 00:00:00 2001 From: Phillip Wittrock Date: Wed, 1 Feb 2017 12:23:23 -0800 Subject: [PATCH 17/17] fix missnamed field in declarative docs --- .../kubectl/object-management-using-declarative-config.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/concepts/tools/kubectl/object-management-using-declarative-config.md b/docs/concepts/tools/kubectl/object-management-using-declarative-config.md index ce90126be8..593e6ffe58 100644 --- a/docs/concepts/tools/kubectl/object-management-using-declarative-config.md +++ b/docs/concepts/tools/kubectl/object-management-using-declarative-config.md @@ -574,10 +574,10 @@ retained in the live configuration. Treat the list as a map, and treat a specific field of each element as a key. Add, delete, or update individual elements. This does not preserve ordering. -This merge strategy uses a special tag on each field called a `mergeKey`. The -`mergeKey` is defined for each field in the Kubernetes source code: +This merge strategy uses a special tag on each field called a `patchMergeKey`. The +`patchMergeKey` is defined for each field in the Kubernetes source code: [types.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/api/v1/types.go#L2119) -When merging a list of complex elements, the field specified as the `mergeKey` for a given element +When merging a list of complex elements, the field specified as the `patchMergeKey` for a given element is used like a map key for that element. **Example:** Use `kubectl apply` to update the `containers` field of a PodSpec. @@ -638,7 +638,7 @@ by `name`. that "nginx-helper-b" in the live configuration was the same "nginx-helper-b" as in the configuration file, even though their fields had different values (no `args` in the configuration file). This is - because the `mergeKey` field value (name) was identical in both. + because the `patchMergeKey` field value (name) was identical in both. - The container named "nginx-helper-c" was added because no container with that name appeared in the live configuration, but one with that name appeared in the configuration file.