instruction: Explain Declarative Management of Kubernetes Objects Using Configuration Files
output: You are viewing documentation for Kubernetes version: v1.31
  Kubernetes v1.31 documentation is no longer actively maintained. The version you are currently viewing is a static snapshot. For up-to-date information, see the
  latest version.
  Declarative Management of Kubernetes Objects Using Configuration Files
  Kubernetes objects can be created, updated, and deleted by storing multiple
  object configuration files in a directory and using
  kubectl apply
  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.
  kubectl diff
  also gives you a
  preview of what changes
  apply
  will make.
  Before you begin
  Install
  kubectl
  You need to have a Kubernetes cluster, and the kubectl command-line tool must
  be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a
  cluster, you can create one by using
  minikube
  or you can use one of these Kubernetes playgrounds:
  Killercoda
  Play with Kubernetes
  To check the version, enter
  kubectl version
  Trade-offs
  kubectl
  tool supports three kinds of object management:
  Imperative commands
  Imperative object configuration
  Declarative object configuration
  Kubernetes Object Management
  for a discussion of the advantages and disadvantage of each kind of object management.
  Overview
  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
  Imperative Management of Kubernetes Objects Using Configuration Files
  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 referred to in this topic make changes
  to object configuration files and run
  kubectl apply
  to write the changes.
  How to create objects
  kubectl apply
  to create all objects, except those that already exist,
  defined by configuration files in a specified directory:
  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
  flag to recursively process directories.
  Here's an example of an object configuration file:
  application/simple_deployment.yaml
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  name
  nginx-deployment
  spec
  selector
  matchLabels
  nginx
  minReadySeconds
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  kubectl diff
  to print the object that will be created:
  kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml
  Note:
  diff
  uses
  server-side dry-run
  which needs to be enabled on
  kube-apiserver
  Since
  diff
  performs a server-side apply request in dry-run mode,
  it requires granting
  PATCH
  CREATE
  , and
  UPDATE
  permissions.
  Dry-Run Authorization
  for details.
  Create the object using
  kubectl apply
  kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
  Print the live configuration using
  kubectl get
  kubectl get -f https://k8s.io/examples/application/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:
  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":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  # ...
  minReadySeconds
  selector
  matchLabels
  # ...
  nginx
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.14.2
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  # ...
  # ...
  # ...
  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:
  Sets fields that appear in the configuration file in the live configuration.
  Clears fields removed from the configuration file in the live configuration.
  kubectl diff -f <directory>
  kubectl apply -f <directory>
  Note:
  Add the
  flag to recursively process directories.
  Here's an example configuration file:
  application/simple_deployment.yaml
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  name
  nginx-deployment
  spec
  selector
  matchLabels
  nginx
  minReadySeconds
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  Create the object using
  kubectl apply
  kubectl apply -f https://k8s.io/examples/application/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
  kubectl get -f https://k8s.io/examples/application/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:
  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":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  # ...
  minReadySeconds
  selector
  matchLabels
  # ...
  nginx
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.14.2
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  # ...
  # ...
  # ...
  Directly update the
  replicas
  field in the live configuration by using
  kubectl scale
  This does not use
  kubectl apply
  kubectl scale deployment/nginx-deployment --replicas
  Print the live configuration using
  kubectl get
  kubectl get deployment nginx-deployment -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
  apps/v1
  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":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  replicas
  # written by scale
  # ...
  minReadySeconds
  selector
  matchLabels
  # ...
  nginx
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.14.2
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  Update the
  simple_deployment.yaml
  configuration file to change the image from
  nginx:1.14.2
  nginx:1.16.1
  , and delete the
  minReadySeconds
  field:
  application/update_deployment.yaml
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  name
  nginx-deployment
  spec
  selector
  matchLabels
  nginx
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.16.1
  # update the image
  ports
  containerPort
  Apply the changes made to the configuration file:
  kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml
  kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml
  Print the live configuration using
  kubectl get
  kubectl get -f https://k8s.io/examples/application/update_deployment.yaml -o yaml
  The output shows the following changes to the live configuration:
  replicas
  field retains the value of 2 set by
  kubectl scale
  This is possible because it is omitted from the configuration file.
  image
  field has been updated to
  nginx:1.16.1
  from
  nginx:1.14.2
  last-applied-configuration
  annotation has been updated with the new image.
  minReadySeconds
  field has been cleared.
  last-applied-configuration
  annotation no longer contains the
  minReadySeconds
  field.
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  annotations
  # ...
  # The annotation contains the updated image to nginx 1.16.1,
  # but does not contain the updated replicas to 2
  kubectl.kubernetes.io/last-applied-configuration
  {"apiVersion":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  replicas
  # Set by `kubectl scale`. Ignored by `kubectl apply`.
  # minReadySeconds cleared by `kubectl apply`
  # ...
  selector
  matchLabels
  # ...
  nginx
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.16.1
  # Set by `kubectl apply`
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  # ...
  # ...
  # ...
  Warning:
  Mixing
  kubectl apply
  with the imperative object configuration commands
  create
  replace
  is not supported. This is because
  create
  replace
  do not retain the
  kubectl.kubernetes.io/last-applied-configuration
  that
  kubectl apply
  uses to compute updates.
  How to delete objects
  There are two approaches to delete objects managed by
  kubectl apply
  Recommended:
  kubectl 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:
  kubectl delete -f <filename>
  Alternative:
  kubectl apply -f <directory> --prune
  As an alternative to
  kubectl delete
  , you can use
  kubectl apply
  to identify objects to be deleted after
  their manifests have been removed from a directory in the local filesystem.
  In Kubernetes 1.31, there are two pruning modes available in kubectl apply:
  Allowlist-based pruning: This mode has existed since kubectl v1.5 but is still
  in alpha due to usability, correctness and performance issues with its design.
  The ApplySet-based mode is designed to replace it.
  ApplySet-based pruning: An
  apply set
  is a server-side object (by default, a Secret)
  that kubectl can use to accurately and efficiently track set membership across
  apply
  operations. This mode was introduced in alpha in kubectl v1.27 as a replacement for allowlist-based pruning.
  Allow list
  Apply set
  FEATURE STATE:
  Kubernetes v1.5 [alpha]
  Warning:
  Take care when using
  --prune
  with
  kubectl apply
  in allow list mode. Which
  objects are pruned depends on the values of the
  --prune-allowlist
  --selector
  --namespace
  flags, and relies on dynamic discovery of the objects in scope.
  Especially if flag values are changed between invocations, this can lead to objects
  being unexpectedly deleted or retained.
  To use allowlist-based pruning, add the following flags to your
  kubectl apply
  invocation:
  --prune
  : Delete previously applied objects that are not in the set passed to the current invocation.
  --prune-allowlist
  : A list of group-version-kinds (GVKs) to consider for pruning.
  This flag is optional but strongly encouraged, as its default value is a partial
  list of both namespaced and cluster-scoped types, which can lead to surprising results.
  --selector/-l
  : Use a label selector to constrain the set of objects selected
  for pruning. This flag is optional but strongly encouraged.
  --all
  : use instead of
  --selector/-l
  to explicitly select all previously
  applied objects of the allowlisted types.
  Allowlist-based pruning queries the API server for all objects of the allowlisted GVKs that match the given labels (if any), and attempts to match the returned live object configurations against the object
  manifest files. If an object matches the query, and it does not have a
  manifest in the directory, and it has a
  kubectl.kubernetes.io/last-applied-configuration
  annotation,
  it is deleted.
  kubectl apply -f <directory> --prune -l <labels> --prune-allowlist
  <gvk-list>
  Warning:
  Apply with prune should only be run against the root directory
  containing the object manifests. Running against sub-directories
  can cause objects to be unintentionally deleted if they were previously applied,
  have the labels given (if any), and do not appear in the subdirectory.
  FEATURE STATE:
  Kubernetes v1.27 [alpha]
  Caution:
  kubectl apply --prune --applyset
  is in alpha, and backwards incompatible
  changes might be introduced in subsequent releases.
  To use ApplySet-based pruning, set the
  KUBECTL_APPLYSET=true
  environment variable,
  and add the following flags to your
  kubectl apply
  invocation:
  --prune
  : Delete previously applied objects that are not in the set passed
  to the current invocation.
  --applyset
  : The name of an object that kubectl can use to accurately and
  efficiently track set membership across
  apply
  operations.
  KUBECTL_APPLYSET
  true
  kubectl apply -f <directory> --prune --applyset
  <name>
  By default, the type of the ApplySet parent object used is a Secret. However,
  ConfigMaps can also be used in the format:
  --applyset=configmaps/<name>
  When using a Secret or ConfigMap, kubectl will create the object if it does not already exist.
  It is also possible to use custom resources as ApplySet parent objects. To enable
  this, label the Custom Resource Definition (CRD) that defines the resource you want
  to use with the following:
  applyset.kubernetes.io/is-parent-type: true
  . Then, create
  the object you want to use as an ApplySet parent (kubectl does not do this automatically
  for custom resources). Finally, refer to that object in the applyset flag as follows:
  --applyset=<resource>.<group>/<name>
  (for example,
  widgets.custom.example.com/widget-name
  With ApplySet-based pruning, kubectl adds the
  applyset.kubernetes.io/part-of=<parentID>
  label to each object in the set before they are sent to the server. For performance reasons,
  it also collects the list of resource types and namespaces that the set contains and adds
  these in annotations on the live parent object. Finally, at the end of the apply operation,
  it queries the API server for objects of those types in those namespaces
  (or in the cluster scope, as applicable) that belong to the set, as defined by the
  applyset.kubernetes.io/part-of=<parentID>
  label.
  Caveats and restrictions:
  Each object may be a member of at most one set.
  --namespace
  flag is required when using any namespaced parent, including
  the default Secret. This means that ApplySets spanning multiple namespaces must
  use a cluster-scoped custom resource as the parent object.
  To safely use ApplySet-based pruning with multiple directories,
  use a unique ApplySet name for each.
  How to view an object
  You can use
  kubectl get
  with
  -o yaml
  to view the configuration of a live object:
  kubectl get -f <filename|url> -o yaml
  How apply calculates differences and merges changes
  Caution:
  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
  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 calculate which fields should be deleted or set:
  Calculate the fields to delete. These are the fields present in
  last-applied-configuration
  and missing from the configuration file.
  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:
  application/update_deployment.yaml
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  name
  nginx-deployment
  spec
  selector
  matchLabels
  nginx
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.16.1
  # update the image
  ports
  containerPort
  Also, suppose this is the live configuration for the same Deployment object:
  apiVersion
  apps/v1
  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":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  replicas
  # written by scale
  # ...
  minReadySeconds
  selector
  matchLabels
  # ...
  nginx
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.14.2
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  Here are the merge calculations that would be performed by
  kubectl apply
  Calculate the fields to delete by reading values from
  last-applied-configuration
  and comparing them to values in the
  configuration file.
  Clear fields explicitly set to  in the local object configuration file
  regardless of whether they appear in the
  last-applied-configuration
  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.
  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.
  Set the
  last-applied-configuration
  annotation to match the value
  of the configuration file.
  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:
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  annotations
  # ...
  # The annotation contains the updated image to nginx 1.16.1,
  # but does not contain the updated replicas to 2
  kubectl.kubernetes.io/last-applied-configuration
  {"apiVersion":"apps/v1","kind":"Deployment",
  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
  "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
  "spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
  "ports":[{"containerPort":80}]}]}}}}
  # ...
  spec
  selector
  matchLabels
  # ...
  nginx
  replicas
  # Set by `kubectl scale`. Ignored by `kubectl apply`.
  # minReadySeconds cleared by `kubectl apply`
  # ...
  template
  metadata
  # ...
  labels
  nginx
  spec
  containers
  image
  nginx:1.16.1
  # Set by `kubectl apply`
  # ...
  name
  nginx
  ports
  containerPort
  # ...
  # ...
  # ...
  # ...
  How different types of fields are merged
  How a particular field in a configuration file is merged 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
  replicas
  are primitive fields.
  Action:
  Replace.
  , also called
  object
  : A field of type map or a complex type that contains subfields. For example,
  labels
  annotations
  spec
  metadata
  are all maps.
  Action:
  Merge elements or subfields.
  list
  : A field containing a list of items that can be either primitive types or maps.
  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
  not replaced. Instead the subfields of
  spec
  , such as
  replicas
  , are compared
  and merged.
  Merging changes to primitive fields
  Primitive fields 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
  Set live to configuration file value.
  Set live to local configuration.
  Clear from live configuration.
  Do nothing. Keep live value.
  Merging changes to map fields
  Fields that represent maps are merged by comparing each of the subfields or elements of the map:
  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
  Compare sub fields values.
  Set live to local configuration.
  Delete from live configuration.
  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 if all its elements are primitives.
  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 if all its elements are primitives
  Treat the list the same as a primitive field. Replace or delete the
  entire list. This preserves ordering.
  Example:
  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.
  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.
  # last-applied-configuration value
  args
  # configuration file value
  args
  # live configuration
  args
  # result after merge
  args
  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
  When merging a list of maps, the field specified as the
  patchMergeKey
  for a given element
  is used like a map key for that element.
  Example:
  kubectl apply
  to update the
  containers
  field of a PodSpec.
  This merges the list as though it was a map where each element is keyed
  name
  # last-applied-configuration value
  containers
  name
  nginx
  image
  nginx:1.16
  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.16
  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.16
  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.16
  # 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
  patchStrategy
  tag in
  types.go
  If no
  patchStrategy
  is specified for a field of type list, then
  the list is replaced.
  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
  application/simple_deployment.yaml
  apiVersion
  apps/v1
  kind
  Deployment
  metadata
  name
  nginx-deployment
  spec
  selector
  matchLabels
  nginx
  minReadySeconds
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  Create the object using
  kubectl apply
  kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml
  Print the live configuration using
  kubectl get
  kubectl get -f https://k8s.io/examples/application/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.
  apiVersion
  apps/v1
  kind
  Deployment
  # ...
  spec
  selector
  matchLabels
  nginx
  minReadySeconds
  replicas
  # defaulted by apiserver
  strategy
  rollingUpdate
  # defaulted by apiserver - derived from strategy.type
  maxSurge
  maxUnavailable
  type
  RollingUpdate
  # defaulted by apiserver
  template
  metadata
  creationTimestamp
  
  labels
  nginx
  spec
  containers
  image
  nginx:1.14.2
  imagePullPolicy
  IfNotPresent
  # defaulted by apiserver
  name
  nginx
  ports
  containerPort
  protocol
  # 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
  # defaulted by apiserver
  # ...
  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:
  # last-applied-configuration
  spec
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  # configuration file
  spec
  strategy
  type
  Recreate
  # updated value
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  # live configuration
  spec
  strategy
  type
  RollingUpdate
  # defaulted value
  rollingUpdate
  # defaulted value derived from type
  maxSurge
  maxUnavailable
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  # result after merge - ERROR!
  spec
  strategy
  type: Recreate # updated value
  incompatible with rollingUpdate
  rollingUpdate: # defaulted value
  incompatible with "type: Recreate"
  maxSurge
  maxUnavailable
  template
  metadata
  labels
  nginx
  spec
  containers
  name
  nginx
  image
  nginx:1.14.2
  ports
  containerPort
  Explanation:
  The user creates a Deployment without defining
  strategy.type
  The server defaults
  strategy.type
  RollingUpdate
  and defaults the
  strategy.rollingUpdate
  values.
  The user changes
  strategy.type
  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.
  Apply fails because
  strategy.rollingUpdate
  is not cleared. The
  strategy.rollingupdate
  field cannot be defined with a
  strategy.type
  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
  Fields that do not appear in the configuration file can be cleared by
  setting their values to
  
  and then applying the configuration file.
  For fields defaulted by the server, this triggers re-defaulting
  the values.
  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:
  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.
  Note:
  It is OK to use imperative deletion with declarative management.
  Migrating from imperative command management to declarative object configuration
  Migrating from imperative command management to declarative object
  configuration involves several manual steps:
  Export the live object to a local configuration file:
  kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
  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.
  Set the
  kubectl.kubernetes.io/last-applied-configuration
  annotation on the object:
  kubectl replace --save-config -f <kind>_<name>.yaml
  Change processes to use
  kubectl apply
  for managing the object exclusively.
  Migrating from imperative object configuration to declarative object configuration
  Set the
  kubectl.kubernetes.io/last-applied-configuration
  annotation on the object:
  kubectl replace --save-config -f <kind>_<name>.yaml
  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:
  selector
  matchLabels
  controller-selector
  "apps/v1/deployment/nginx"
  template
  metadata
  labels
  controller-selector
  "apps/v1/deployment/nginx"
  What's next
  Managing Kubernetes Objects Using Imperative Commands
  Imperative Management of Kubernetes Objects Using Configuration Files
  Kubectl Command Reference
  Kubernetes API Reference
  Was this page helpful?
  Thanks for the feedback. If you have a specific, answerable question about how to use Kubernetes, ask it on
  Stack Overflow
  Open an issue in the
  GitHub Repository
  if you want to
  report a problem
  suggest an improvement
  Last modified August 24, 2023 at 6:38 PM PST:
  Use code_sample shortcode instead of code shortcode (e8b136c3b3)