"kubectl apply": A Deep Dive into Kubernetes Most Versatile Command
In the world of Kubernetes, one command that consistently stands out for its versatility and power is kubectl apply. This command is fundamental to the way we manage and interact with Kubernetes clusters. To truly appreciate its capabilities, it’s essential to understand how it operates under the hood.
Kubectl apply command is used for creating, updating or deleting an object in a declarative way.
- The “kubectl apply” command is intelligent to be able to create an object if it doesn’t already exist.
- It will look at the existing configuration and figure out what changes need to be made to the existing objects or applications.
When modifications are required in our application, such as updating the image version, we simply adjust the object configuration file and execute “kubectl apply -f object-definition.yaml”. In this instance, the apply command recognizes the existing object and updates it with the new changes.
So how does the kubectl apply command exactly works?
The kubectl apply takes the local configuration file, a live object definition on Kubernetes and the last applied configuration into consideration before making a decision on what changes are to be made.
nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type : front-end-service
spec:
containers:
- name: nginx-conatiner
image: nginx:1.18
So when you run the command
kubectl apply -f nginx.yamlif the object does not already exist, the object is created.
When the Object is created, a “live object configuration” similar to what we created locally is also created but with additional fields to store the status of the object.
live-nginx-configuration:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type : front-end-service
spec:
containers:
- name: nginx-conatiner
image: nginx:1.18
status:
conditions:
- lastProbeTime: null
status: "True"
type: InitializedThis is the method by which Kubernetes retains information about an object, regardless of the method employed (whether through “kubectl create” or “kubectl apply”) to generate the object.
However, when employing the “kubectl apply” command for object creation, it introduces an additional step. The YAML representation of the “local object configuration” file undergoes conversion to JSON format, subsequently serving as the “last applied configuration” for storage.
last applied configuration
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "myapp-pod",
"labels": {
"app": "myapp",
"type": "front-end-service"
}
},
"spec": {
"containers": [
{
"name": "nginx-conatiner",
"image": "nginx:1.18"
}
]
}
}Moving forward, any updates to the object involve a comparison among the three configurations: the local object configuration, the last applied configuration, and the live object configuration, in order to determine the necessary adjustments for the live object in the Kubernetes cluster.
For instance, suppose the Nginx image is upgraded to version 1.19 in our local file. Upon executing the “kubectl apply” command, this updated value is compared to the corresponding value in the live configuration. If disparities exist, the live configuration is modified to reflect the new value.
Subsequently, following any alteration, the last applied JSON format is consistently updated to ensure it remains current at all times.
So why do we really need the last applied configuration?
Let’s say a field was deleted, say for example, the type label was deleted, and now when we run the “kubectl apply” command, we see the last applied configuration had a label, but it’s not present in the local configuration.
This means that the field needs to be removed from the live configuration.
If a field is present in the live configuration but absent in both the local and last applied configurations, it remains unchanged.
However, if a field is missing in the local configuration but is present in the last applied configuration, it implies that this field existed in a previous configuration but has now been removed. In such cases, the last applied configuration serves as a valuable reference, helping identify the fields that have been removed from the local file. Consequently, the corresponding field is then removed from the live configuration to maintain consistency with the updated specifications.
As we seen have in above diagram, and we know that the local file is stored in our local system. The live object configuration is stored in the Kubernetes memory, but where is the JSON file that has the last applied configuration stored?
The JSON file containing the last applied configuration is stored within the live object configuration on the Kubernetes cluster itself. It is stored as an annotation with the specific name “last applied configuration.” This annotation serves as a reference point for tracking the most recent configuration applied to the object. By keeping this information within the live object configuration on the Kubernetes cluster, the system can efficiently compare and update configurations as needed, ensuring consistency and accuracy in managing object states.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
annotations:
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp-pod", "labels": {"app": "my-app","type": "front-end-service"}},"spec": {"containers": [{"name": "nginx-container","image": "nginx:1.18"
}]}}
labels:
app: myapp
type : front-end-service
spec:
containers:
- name: nginx-container
image: nginx:1.18
status:
conditions:
- lastProbeTime: null
status: "True"
type: InitializedThe mechanism of storing the last applied configuration as an annotation is specific to the kubectl apply command. When you use kubectl apply, it not only creates or updates the live object configuration but also stores a record of the last applied configuration as an annotation. This annotation aids in tracking changes and facilitating the comparison process for subsequent updates.
On the other hand, the kubectl create or kubectl replace commands do not incorporate this feature. They focus on creating or replacing the object directly without preserving the last applied configuration in the form of an annotation. Therefore, if you rely on kubectl apply for managing your objects, you benefit from the additional functionality of tracking and storing the last applied configuration for future reference.
As we’ve seen, kubectl apply is a command that embodies the essence of Kubernetes: simplicity, efficiency, and power. Whether you’re a novice or an expert, understanding this command is key to mastering Kubernetes.
Congratulations and thank you for following along. I hope you find this valuable in your journey. Let me know if you have any questions and I look forward to see you on my next project.