Merge branch 'master' into getting-started
This commit is contained in:
@@ -5,6 +5,9 @@ toc:
|
|||||||
- title: Kubectl Command Line
|
- title: Kubectl Command Line
|
||||||
section:
|
section:
|
||||||
- docs/concepts/tools/kubectl/object-management-overview.md
|
- 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
|
- title: Kubernetes Objects
|
||||||
section:
|
section:
|
||||||
- docs/concepts/abstractions/overview.md
|
- docs/concepts/abstractions/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 source of records except for what is live.
|
||||||
- Commands do not provide a template for creating new objects.
|
- 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
|
## Imperative object configuration
|
||||||
|
|
||||||
When using imperative object configuration, a user operates on object
|
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.
|
- 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.
|
- 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
|
## Declarative object configuration
|
||||||
|
|
||||||
When using declarative object configuration, a user operates on object
|
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.
|
- Declarative object configuration is harder to debug and understand results when they are unexpected.
|
||||||
- Partial updates using diffs create complex merge and patch operations.
|
- 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 %}
|
{% endcapture %}
|
||||||
|
|
||||||
{% capture whatsnext %}
|
{% 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/)
|
- [Kubectl Command Reference](/docs/user-guide/kubectl/v1.5/)
|
||||||
- [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/)
|
- [Kubernetes Object Schema Reference](/docs/resources-reference/v1.5/)
|
||||||
|
|
||||||
{% comment %}
|
{% 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 %}
|
{% endcomment %}
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
|
|||||||
@@ -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 <directory>/
|
||||||
|
```
|
||||||
|
|
||||||
|
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 <directory>/
|
||||||
|
```
|
||||||
|
|
||||||
|
**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 <filename>`
|
||||||
|
|
||||||
|
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 <filename>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Alternative: `kubectl apply -f <directory/> --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 <directory/> --prune -l <labels>
|
||||||
|
```
|
||||||
|
|
||||||
|
**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 <labels>` 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 <filename|url> -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 `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 `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.
|
||||||
|
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 `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.
|
||||||
|
- 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 <kind>/<name> -o yaml --export > <kind>_<name>.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 <kind>_<name>.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 <kind>_<name>.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 %}
|
||||||
@@ -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 <objecttype> [<subtype>] <instancename>`
|
||||||
|
|
||||||
|
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 <myservicename>
|
||||||
|
```
|
||||||
|
|
||||||
|
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` <field>: 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 <type>/<name>`
|
||||||
|
|
||||||
|
**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 <myservicename> -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 %}
|
||||||
@@ -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 <filename|url>`
|
||||||
|
|
||||||
|
## How to update objects
|
||||||
|
|
||||||
|
You can use `kubectl replace -f` to update a live object according to a
|
||||||
|
configuration file.
|
||||||
|
|
||||||
|
- `replace -f <filename|url>`
|
||||||
|
|
||||||
|
## How to delete objects
|
||||||
|
|
||||||
|
You can use `kubectl delete -f` to delete an object that is described in a
|
||||||
|
configuration file.
|
||||||
|
|
||||||
|
- `delete -f <filename|url>`
|
||||||
|
|
||||||
|
## 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 <filename|url> -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 <url> --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 <kind>/<name> -o yaml --export > <kind>_<name>.yaml
|
||||||
|
|
||||||
|
1. Manually remove the status field from the object configuration file.
|
||||||
|
|
||||||
|
1. For subsequent object management, use `replace` exclusively.
|
||||||
|
|
||||||
|
kubectl replace -f <kind>_<name>.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 %}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -33,7 +33,7 @@ cd kubernetes
|
|||||||
make release
|
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
|
### Download Kubernetes and automatically set up a default cluster
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user