433 lines
14 KiB
Markdown
433 lines
14 KiB
Markdown
---
|
|
title: Managing Resources
|
|
content_type: concept
|
|
reviewers:
|
|
- janetkuo
|
|
weight: 40
|
|
---
|
|
|
|
<!-- overview -->
|
|
|
|
You've deployed your application and exposed it via a service. Now what? Kubernetes provides a
|
|
number of tools to help you manage your application deployment, including scaling and updating.
|
|
|
|
<!-- body -->
|
|
|
|
## Organizing resource configurations
|
|
|
|
Many applications require multiple resources to be created, such as a Deployment and a Service.
|
|
Management of multiple resources can be simplified by grouping them together in the same file
|
|
(separated by `---` in YAML). For example:
|
|
|
|
{{% code_sample file="application/nginx-app.yaml" %}}
|
|
|
|
Multiple resources can be created the same way as a single resource:
|
|
|
|
```shell
|
|
kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
|
|
```
|
|
|
|
```none
|
|
service/my-nginx-svc created
|
|
deployment.apps/my-nginx created
|
|
```
|
|
|
|
The resources will be created in the order they appear in the file. Therefore, it's best to
|
|
specify the service first, since that will ensure the scheduler can spread the pods associated
|
|
with the service as they are created by the controller(s), such as Deployment.
|
|
|
|
`kubectl apply` also accepts multiple `-f` arguments:
|
|
|
|
```shell
|
|
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml \
|
|
-f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
|
|
```
|
|
|
|
|
|
It is a recommended practice to put resources related to the same microservice or application tier
|
|
into the same file, and to group all of the files associated with your application in the same
|
|
directory. If the tiers of your application bind to each other using DNS, you can deploy all of
|
|
the components of your stack together.
|
|
|
|
A URL can also be specified as a configuration source, which is handy for deploying directly from
|
|
configuration files checked into GitHub:
|
|
|
|
```shell
|
|
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx created
|
|
```
|
|
|
|
## Bulk operations in kubectl
|
|
|
|
Resource creation isn't the only operation that `kubectl` can perform in bulk. It can also extract
|
|
resource names from configuration files in order to perform other operations, in particular to
|
|
delete the same resources you created:
|
|
|
|
```shell
|
|
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
|
|
```
|
|
|
|
```none
|
|
deployment.apps "my-nginx" deleted
|
|
service "my-nginx-svc" deleted
|
|
```
|
|
|
|
In the case of two resources, you can specify both resources on the command line using the
|
|
resource/name syntax:
|
|
|
|
```shell
|
|
kubectl delete deployments/my-nginx services/my-nginx-svc
|
|
```
|
|
|
|
For larger numbers of resources, you'll find it easier to specify the selector (label query)
|
|
specified using `-l` or `--selector`, to filter resources by their labels:
|
|
|
|
```shell
|
|
kubectl delete deployment,services -l app=nginx
|
|
```
|
|
|
|
```none
|
|
deployment.apps "my-nginx" deleted
|
|
service "my-nginx-svc" deleted
|
|
```
|
|
|
|
Because `kubectl` outputs resource names in the same syntax it accepts, you can chain operations
|
|
using `$()` or `xargs`:
|
|
|
|
```shell
|
|
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
|
|
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
|
|
```
|
|
|
|
```none
|
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
|
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
|
|
```
|
|
|
|
With the above commands, we first create resources under `examples/application/nginx/` and print
|
|
the resources created with `-o name` output format (print each resource as resource/name).
|
|
Then we `grep` only the "service", and then print it with `kubectl get`.
|
|
|
|
If you happen to organize your resources across several subdirectories within a particular
|
|
directory, you can recursively perform the operations on the subdirectories also, by specifying
|
|
`--recursive` or `-R` alongside the `--filename,-f` flag.
|
|
|
|
For instance, assume there is a directory `project/k8s/development` that holds all of the
|
|
{{< glossary_tooltip text="manifests" term_id="manifest" >}} needed for the development environment,
|
|
organized by resource type:
|
|
|
|
```none
|
|
project/k8s/development
|
|
├── configmap
|
|
│ └── my-configmap.yaml
|
|
├── deployment
|
|
│ └── my-deployment.yaml
|
|
└── pvc
|
|
└── my-pvc.yaml
|
|
```
|
|
|
|
By default, performing a bulk operation on `project/k8s/development` will stop at the first level
|
|
of the directory, not processing any subdirectories. If we had tried to create the resources in
|
|
this directory using the following command, we would have encountered an error:
|
|
|
|
```shell
|
|
kubectl apply -f project/k8s/development
|
|
```
|
|
|
|
```none
|
|
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
|
|
```
|
|
|
|
Instead, specify the `--recursive` or `-R` flag with the `--filename,-f` flag as such:
|
|
|
|
```shell
|
|
kubectl apply -f project/k8s/development --recursive
|
|
```
|
|
|
|
```none
|
|
configmap/my-config created
|
|
deployment.apps/my-deployment created
|
|
persistentvolumeclaim/my-pvc created
|
|
```
|
|
|
|
The `--recursive` flag works with any operation that accepts the `--filename,-f` flag such as:
|
|
`kubectl {create,get,delete,describe,rollout}` etc.
|
|
|
|
The `--recursive` flag also works when multiple `-f` arguments are provided:
|
|
|
|
```shell
|
|
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
|
|
```
|
|
|
|
```none
|
|
namespace/development created
|
|
namespace/staging created
|
|
configmap/my-config created
|
|
deployment.apps/my-deployment created
|
|
persistentvolumeclaim/my-pvc created
|
|
```
|
|
|
|
If you're interested in learning more about `kubectl`, go ahead and read
|
|
[Command line tool (kubectl)](/docs/reference/kubectl/).
|
|
|
|
## Canary deployments
|
|
|
|
<!--TODO: make a task out of this for canary deployment, ref #42786-->
|
|
|
|
Another scenario where multiple labels are needed is to distinguish deployments of different
|
|
releases or configurations of the same component. It is common practice to deploy a *canary* of a
|
|
new application release (specified via image tag in the pod template) side by side with the
|
|
previous release so that the new release can receive live production traffic before fully rolling
|
|
it out.
|
|
|
|
For instance, you can use a `track` label to differentiate different releases.
|
|
|
|
The primary, stable release would have a `track` label with value as `stable`:
|
|
|
|
```none
|
|
name: frontend
|
|
replicas: 3
|
|
...
|
|
labels:
|
|
app: guestbook
|
|
tier: frontend
|
|
track: stable
|
|
...
|
|
image: gb-frontend:v3
|
|
```
|
|
|
|
and then you can create a new release of the guestbook frontend that carries the `track` label
|
|
with different value (i.e. `canary`), so that two sets of pods would not overlap:
|
|
|
|
```none
|
|
name: frontend-canary
|
|
replicas: 1
|
|
...
|
|
labels:
|
|
app: guestbook
|
|
tier: frontend
|
|
track: canary
|
|
...
|
|
image: gb-frontend:v4
|
|
```
|
|
|
|
The frontend service would span both sets of replicas by selecting the common subset of their
|
|
labels (i.e. omitting the `track` label), so that the traffic will be redirected to both
|
|
applications:
|
|
|
|
```yaml
|
|
selector:
|
|
app: guestbook
|
|
tier: frontend
|
|
```
|
|
|
|
You can tweak the number of replicas of the stable and canary releases to determine the ratio of
|
|
each release that will receive live production traffic (in this case, 3:1).
|
|
Once you're confident, you can update the stable track to the new application release and remove
|
|
the canary one.
|
|
|
|
For a more concrete example, check the
|
|
[tutorial of deploying Ghost](https://github.com/kelseyhightower/talks/tree/master/kubecon-eu-2016/demo#deploy-a-canary).
|
|
|
|
## Updating annotations
|
|
|
|
Sometimes you would want to attach annotations to resources. Annotations are arbitrary
|
|
non-identifying metadata for retrieval by API clients such as tools, libraries, etc.
|
|
This can be done with `kubectl annotate`. For example:
|
|
|
|
```shell
|
|
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
|
|
kubectl get pods my-nginx-v4-9gw19 -o yaml
|
|
```
|
|
|
|
```shell
|
|
apiVersion: v1
|
|
kind: pod
|
|
metadata:
|
|
annotations:
|
|
description: my frontend running nginx
|
|
...
|
|
```
|
|
|
|
For more information, see [annotations](/docs/concepts/overview/working-with-objects/annotations/)
|
|
and [kubectl annotate](/docs/reference/generated/kubectl/kubectl-commands/#annotate) document.
|
|
|
|
## Scaling your application
|
|
|
|
When load on your application grows or shrinks, use `kubectl` to scale your application.
|
|
For instance, to decrease the number of nginx replicas from 3 to 1, do:
|
|
|
|
```shell
|
|
kubectl scale deployment/my-nginx --replicas=1
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx scaled
|
|
```
|
|
|
|
Now you only have one pod managed by the deployment.
|
|
|
|
```shell
|
|
kubectl get pods -l app=nginx
|
|
```
|
|
|
|
```none
|
|
NAME READY STATUS RESTARTS AGE
|
|
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
|
|
```
|
|
|
|
To have the system automatically choose the number of nginx replicas as needed,
|
|
ranging from 1 to 3, do:
|
|
|
|
```shell
|
|
kubectl autoscale deployment/my-nginx --min=1 --max=3
|
|
```
|
|
|
|
```none
|
|
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
|
|
```
|
|
|
|
Now your nginx replicas will be scaled up and down as needed, automatically.
|
|
|
|
For more information, please see [kubectl scale](/docs/reference/generated/kubectl/kubectl-commands/#scale),
|
|
[kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands/#autoscale) and
|
|
[horizontal pod autoscaler](/docs/tasks/run-application/horizontal-pod-autoscale/) document.
|
|
|
|
## In-place updates of resources
|
|
|
|
Sometimes it's necessary to make narrow, non-disruptive updates to resources you've created.
|
|
|
|
### kubectl apply
|
|
|
|
It is suggested to maintain a set of configuration files in source control
|
|
(see [configuration as code](https://martinfowler.com/bliki/InfrastructureAsCode.html)),
|
|
so that they can be maintained and versioned along with the code for the resources they configure.
|
|
Then, you can use [`kubectl apply`](/docs/reference/generated/kubectl/kubectl-commands/#apply)
|
|
to push your configuration changes to the cluster.
|
|
|
|
This command will compare the version of the configuration that you're pushing with the previous
|
|
version and apply the changes you've made, without overwriting any automated changes to properties
|
|
you haven't specified.
|
|
|
|
```shell
|
|
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx configured
|
|
```
|
|
|
|
Note that `kubectl apply` attaches an annotation to the resource in order to determine the changes
|
|
to the configuration since the previous invocation. When it's invoked, `kubectl apply` does a
|
|
three-way diff between the previous configuration, the provided input and the current
|
|
configuration of the resource, in order to determine how to modify the resource.
|
|
|
|
Currently, resources are created without this annotation, so the first invocation of `kubectl
|
|
apply` will fall back to a two-way diff between the provided input and the current configuration
|
|
of the resource. During this first invocation, it cannot detect the deletion of properties set
|
|
when the resource was created. For this reason, it will not remove them.
|
|
|
|
All subsequent calls to `kubectl apply`, and other commands that modify the configuration, such as
|
|
`kubectl replace` and `kubectl edit`, will update the annotation, allowing subsequent calls to
|
|
`kubectl apply` to detect and perform deletions using a three-way diff.
|
|
|
|
### kubectl edit
|
|
|
|
Alternatively, you may also update resources with `kubectl edit`:
|
|
|
|
```shell
|
|
kubectl edit deployment/my-nginx
|
|
```
|
|
|
|
This is equivalent to first `get` the resource, edit it in text editor, and then `apply` the
|
|
resource with the updated version:
|
|
|
|
```shell
|
|
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
|
|
vi /tmp/nginx.yaml
|
|
# do some edit, and then save the file
|
|
|
|
kubectl apply -f /tmp/nginx.yaml
|
|
deployment.apps/my-nginx configured
|
|
|
|
rm /tmp/nginx.yaml
|
|
```
|
|
|
|
This allows you to do more significant changes more easily. Note that you can specify the editor
|
|
with your `EDITOR` or `KUBE_EDITOR` environment variables.
|
|
|
|
For more information, please see [kubectl edit](/docs/reference/generated/kubectl/kubectl-commands/#edit) document.
|
|
|
|
### kubectl patch
|
|
|
|
You can use `kubectl patch` to update API objects in place. This command supports JSON patch,
|
|
JSON merge patch, and strategic merge patch. See
|
|
[Update API Objects in Place Using kubectl patch](/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/)
|
|
and
|
|
[kubectl patch](/docs/reference/generated/kubectl/kubectl-commands/#patch).
|
|
|
|
## Disruptive updates
|
|
|
|
In some cases, you may need to update resource fields that cannot be updated once initialized, or
|
|
you may want to make a recursive change immediately, such as to fix broken pods created by a
|
|
Deployment. To change such fields, use `replace --force`, which deletes and re-creates the
|
|
resource. In this case, you can modify your original configuration file:
|
|
|
|
```shell
|
|
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx deleted
|
|
deployment.apps/my-nginx replaced
|
|
```
|
|
|
|
## Updating your application without a service outage
|
|
|
|
At some point, you'll eventually need to update your deployed application, typically by specifying
|
|
a new image or image tag, as in the canary deployment scenario above. `kubectl` supports several
|
|
update operations, each of which is applicable to different scenarios.
|
|
|
|
We'll guide you through how to create and update applications with Deployments.
|
|
|
|
Let's say you were running version 1.14.2 of nginx:
|
|
|
|
```shell
|
|
kubectl create deployment my-nginx --image=nginx:1.14.2
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx created
|
|
```
|
|
|
|
with 3 replicas (so the old and new revisions can coexist):
|
|
|
|
```shell
|
|
kubectl scale deployment my-nginx --current-replicas=1 --replicas=3
|
|
```
|
|
|
|
```none
|
|
deployment.apps/my-nginx scaled
|
|
```
|
|
|
|
To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2`
|
|
to `nginx:1.16.1` using the previous kubectl commands.
|
|
|
|
```shell
|
|
kubectl edit deployment/my-nginx
|
|
```
|
|
|
|
That's it! The Deployment will declaratively update the deployed nginx application progressively
|
|
behind the scene. It ensures that only a certain number of old replicas may be down while they are
|
|
being updated, and only a certain number of new replicas may be created above the desired number
|
|
of pods. To learn more details about it, visit [Deployment page](/docs/concepts/workloads/controllers/deployment/).
|
|
|
|
## {{% heading "whatsnext" %}}
|
|
|
|
- Learn about [how to use `kubectl` for application introspection and debugging](/docs/tasks/debug/debug-application/debug-running-pod/).
|
|
- See [Configuration Best Practices and Tips](/docs/concepts/configuration/overview/).
|
|
|