You are viewing documentation for Kubernetes version: v1.30

Kubernetes v1.30 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.

Update API Objects in Place Using kubectl

Use kubectl to update Kubernetes API objects in place. Do a strategic merge or a JSON merge .

This task shows how to use kubectl to update an API object in place. The exercises in this task demonstrate a strategic merge and a JSON merge .

Before you begin

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:

To check the version, enter kubectl version.

Use a strategic merge to update a Deployment

Here's the configuration file for a Deployment that has two replicas. Each replica is a Pod that has one container:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: -demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: -demo-ctr
        image: nginx
      tolerations:
      - effect: NoSchedule
        key: dedicated
        value: test-team

Create the Deployment:

kubectl apply -f https://k8s.io/examples/application/deployment-.yaml

View the Pods associated with your Deployment:

kubectl get pods

The output shows that the Deployment has two Pods. The 1/1 indicates that each Pod has one container:

NAME                        READY     STATUS    RESTARTS   AGE
-demo-28633765-670qr   1/1       Running   0          23s
-demo-28633765-j5qs3   1/1       Running   0          23s

Make a note of the names of the running Pods. Later, you will see that these Pods get terminated and replaced by new ones.

At this point, each Pod has one Container that runs the nginx image. Now suppose you want each Pod to have two containers: one that runs nginx and one that runs redis.

Create a file named -file.yaml that has this content:

spec:
  template:
    spec:
      containers:
      - name: -demo-ctr-2
        image: redis

your Deployment:

kubectl  deployment -demo ---file -file.yaml

View the ed Deployment:

kubectl get deployment -demo --output yaml

The output shows that the PodSpec in the Deployment has two Containers:

containers:
- image: redis
  imagePullPolicy: Always
  name: -demo-ctr-2
  ...
- image: nginx
  imagePullPolicy: Always
  name: -demo-ctr
  ...

View the Pods associated with your ed Deployment:

kubectl get pods

The output shows that the running Pods have different names from the Pods that were running previously. The Deployment terminated the old Pods and created two new Pods that comply with the updated Deployment spec. The 2/2 indicates that each Pod has two Containers:

NAME                          READY     STATUS    RESTARTS   AGE
-demo-1081991389-2wrn5   2/2       Running   0          1m
-demo-1081991389-jmg7b   2/2       Running   0          1m

Take a closer look at one of the -demo Pods:

kubectl get pod <your-pod-name> --output yaml

The output shows that the Pod has two Containers: one running nginx and one running redis:

containers:
- image: redis
  ...
- image: nginx
  ...

Notes on the strategic merge

The you did in the preceding exercise is called a strategic merge . Notice that the did not replace the containers list. Instead it added a new Container to the list. In other words, the list in the was merged with the existing list. This is not always what happens when you use a strategic merge on a list. In some cases, the list is replaced, not merged.

With a strategic merge , a list is either replaced or merged depending on its strategy. The strategy is specified by the value of the Strategy key in a field tag in the Kubernetes source code. For example, the Containers field of PodSpec struct has a Strategy of merge:

type PodSpec struct {
  ...
  Containers []Container `json:"containers" Strategy:"merge" MergeKey:"name" ...`
  ...
}

You can also see the strategy in the OpenApi spec:

"io.k8s.api.core.v1.PodSpec": {
    ...,
    "containers": {
        "description": "List of containers belonging to the pod.  ...."
    },
    "x-kubernetes--merge-key": "name",
    "x-kubernetes--strategy": "merge"
}

And you can see the strategy in the Kubernetes API documentation.

Create a file named -file-tolerations.yaml that has this content:

spec:
  template:
    spec:
      tolerations:
      - effect: NoSchedule
        key: disktype
        value: ssd

your Deployment:

kubectl  deployment -demo ---file -file-tolerations.yaml

View the ed Deployment:

kubectl get deployment -demo --output yaml

The output shows that the PodSpec in the Deployment has only one Toleration:

tolerations:
- effect: NoSchedule
  key: disktype
  value: ssd

Notice that the tolerations list in the PodSpec was replaced, not merged. This is because the Tolerations field of PodSpec does not have a Strategy key in its field tag. So the strategic merge uses the default strategy, which is replace.

type PodSpec struct {
  ...
  Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
  ...
}

Use a JSON merge to update a Deployment

A strategic merge is different from a JSON merge . With a JSON merge , if you want to update a list, you have to specify the entire new list. And the new list completely replaces the existing list.

The kubectl command has a type parameter that you can set to one of these values:

Parameter valueMerge type
jsonJSON , RFC 6902
mergeJSON Merge , RFC 7386
strategicStrategic merge

For a comparison of JSON and JSON merge , see JSON and JSON Merge .

The default value for the type parameter is strategic. So in the preceding exercise, you did a strategic merge .

Next, do a JSON merge on your same Deployment. Create a file named -file-2.yaml that has this content:

spec:
  template:
    spec:
      containers:
      - name: -demo-ctr-3
        image: gcr.io/google-samples/hello-app:2.0

In your command, set type to merge:

kubectl  deployment -demo --type merge ---file -file-2.yaml

View the ed Deployment:

kubectl get deployment -demo --output yaml

The containers list that you specified in the has only one Container. The output shows that your list of one Container replaced the existing containers list.

spec:
  containers:
  - image: gcr.io/google-samples/hello-app:2.0
    ...
    name: -demo-ctr-3

List the running Pods:

kubectl get pods

In the output, you can see that the existing Pods were terminated, and new Pods were created. The 1/1 indicates that each new Pod is running only one Container.

NAME                          READY     STATUS    RESTARTS   AGE
-demo-1307768864-69308   1/1       Running   0          1m
-demo-1307768864-c86dc   1/1       Running   0          1m

Use strategic merge to update a Deployment using the retainKeys strategy

Here's the configuration file for a Deployment that uses the RollingUpdate strategy:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: retainkeys-demo
spec:
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 30%
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: retainkeys-demo-ctr
        image: nginx

Create the deployment:

kubectl apply -f https://k8s.io/examples/application/deployment-retainkeys.yaml

At this point, the deployment is created and is using the RollingUpdate strategy.

Create a file named -file-no-retainkeys.yaml that has this content:

spec:
  strategy:
    type: Recreate

your Deployment:

kubectl  deployment retainkeys-demo --type strategic ---file -file-no-retainkeys.yaml

In the output, you can see that it is not possible to set type as Recreate when a value is defined for spec.strategy.rollingUpdate:

The Deployment "retainkeys-demo" is invalid: spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate'

The way to remove the value for spec.strategy.rollingUpdate when updating the value for type is to use the retainKeys strategy for the strategic merge.

Create another file named -file-retainkeys.yaml that has this content:

spec:
  strategy:
    $retainKeys:
    - type
    type: Recreate

With this , we indicate that we want to retain only the type key of the strategy object. Thus, the rollingUpdate will be removed during the operation.

your Deployment again with this new :

kubectl  deployment retainkeys-demo --type strategic ---file -file-retainkeys.yaml

Examine the content of the Deployment:

kubectl get deployment retainkeys-demo --output yaml

The output shows that the strategy object in the Deployment does not contain the rollingUpdate key anymore:

spec:
  strategy:
    type: Recreate
  template:

Notes on the strategic merge using the retainKeys strategy

The you did in the preceding exercise is called a strategic merge with retainKeys strategy. This method introduces a new directive $retainKeys that has the following strategies:

  • It contains a list of strings.
  • All fields needing to be preserved must be present in the $retainKeys list.
  • The fields that are present will be merged with live object.
  • All of the missing fields will be cleared when ing.
  • All fields in the $retainKeys list must be a superset or the same as the fields present in the .

The retainKeys strategy does not work for all objects. It only works when the value of the Strategy key in a field tag in the Kubernetes source code contains retainKeys. For example, the Strategy field of the DeploymentSpec struct has a Strategy of retainKeys:

type DeploymentSpec struct {
  ...
  // +Strategy=retainKeys
  Strategy DeploymentStrategy `json:"strategy,omitempty" Strategy:"retainKeys" ...`
  ...
}

You can also see the retainKeys strategy in the OpenApi spec:

"io.k8s.api.apps.v1.DeploymentSpec": {
    ...,
    "strategy": {
        "$ref": "#/definitions/io.k8s.api.apps.v1.DeploymentStrategy",
        "description": "The deployment strategy to use to replace existing pods with new ones.",
        "x-kubernetes--strategy": "retainKeys"
    },
    ....
}

And you can see the retainKeys strategy in the Kubernetes API documentation.

Alternate forms of the kubectl command

The kubectl command takes YAML or JSON. It can take the as a file or directly on the command line.

Create a file named -file.json that has this content:

{
   "spec": {
      "template": {
         "spec": {
            "containers": [
               {
                  "name": "-demo-ctr-2",
                  "image": "redis"
               }
            ]
         }
      }
   }
}

The following commands are equivalent:

kubectl  deployment -demo ---file -file.yaml
kubectl  deployment -demo -- 'spec:\n template:\n  spec:\n   containers:\n   - name: -demo-ctr-2\n     image: redis'

kubectl  deployment -demo ---file -file.json
kubectl  deployment -demo -- '{"spec": {"template": {"spec": {"containers": [{"name": "-demo-ctr-2","image": "redis"}]}}}}'

Update an object's replica count using kubectl with --subresource

FEATURE STATE: Kubernetes v1.24 [alpha]

The flag --subresource=[subresource-name] is used with kubectl commands like get, , edit and replace to fetch and update status and scale subresources of the resources (applicable for kubectl version v1.24 or more). This flag is used with all the API resources (built-in and CRs) that have status or scale subresource. Deployment is one of the examples which supports these subresources.

Here's a manifest for a Deployment that has two replicas:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Create the Deployment:

kubectl apply -f https://k8s.io/examples/application/deployment.yaml

View the Pods associated with your Deployment:

kubectl get pods -l app=nginx

In the output, you can see that Deployment has two Pods. For example:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7fb96c846b-22567   1/1     Running   0          47s
nginx-deployment-7fb96c846b-mlgns   1/1     Running   0          47s

Now, that Deployment with --subresource=[subresource-name] flag:

kubectl  deployment nginx-deployment --subresource='scale' --type='merge' -p '{"spec":{"replicas":3}}'

The output is:

scale.autoscaling/nginx-deployment ed

View the Pods associated with your ed Deployment:

kubectl get pods -l app=nginx

In the output, you can see one new pod is created, so now you have 3 running pods.

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7fb96c846b-22567   1/1     Running   0          107s
nginx-deployment-7fb96c846b-lxfr2   1/1     Running   0          14s
nginx-deployment-7fb96c846b-mlgns   1/1     Running   0          107s

View the ed Deployment:

kubectl get deployment nginx-deployment -o yaml
...
spec:
  replicas: 3
  ...
status:
  ...
  availableReplicas: 3
  readyReplicas: 3
  replicas: 3

Summary

In this exercise, you used kubectl to change the live configuration of a Deployment object. You did not change the configuration file that you originally used to create the Deployment object. Other commands for updating API objects include kubectl annotate, kubectl edit, kubectl replace, kubectl scale, and kubectl apply.

What's next

Last modified June 02, 2024 at 2:43 AM PST: Modify the image node-hello to hello-app (#46582) (d5b194da5b)