In the last part we created a few pods using the run
command and by accident created some other things also, deployment, replicaset.
Pods, deployments, replicasets are all kubernetes (k8s) resources. The idea here is they are available for you to use. Many resources, such as pods and replicasets are available to you out-of-the-box. Later in this course we play with creating our own Custom Resources.
All resources are configurable and you specify the configuration with a Resource Definition. Lets see a definition for a Pod
apiVersion: "v1"
kind: Pod
metadata:
name: ubuntu-pod
labels:
app: ubuntu-pod
version: v1
role: backend
spec:
containers:
- name: ubuntu-container
image: ubuntu
command: ["/bin/bash"]
args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"Hi\"; sleep 5; done" ]
The structure here will mostly be the same. The above is a yaml file so spaces matter, if you don’t like adhering to spaces (and love ‘ ” ‘, ‘{}’s and ‘,’s) you can specify the same as json (yuck!).
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "ubuntu-pod",
"labels": {
"app": "ubuntu-pod",
"version": "v1",
"role": "backend"
}
},
"spec": {
"containers": [{
"name": "ubuntu-container",
"image": "ubuntu",
"command": ["/bin/bash"],
"args": ["-c", "while [ \"a\" = \"a\" ]; do echo \"Hi\"; sleep 5; done" ]
}]
}
}
apiVersion: This is the api version you want to avail of. Different api versions give you different resources that you can create. v1 is the base version, most of the standard resources such as pods, deployments, services are in the v1 api. To find out which api version the resource is in, a google of
“kubernetes <type of resource>”
should get you the needed information. I tend to rely on kubernetes.io for this kind of information.
kind: is the type of resource you want to create. In this case Pod. Please note that kind is case-sensitive.
metadata: This, as the name suggests is about the resource instance you are creating. name is mandatory, labels are optional and both key and value are defined by you.
spec: This is the actual configuration for the resource. This changes depending on the resource you are creating. In this example we specify the array of containers and the container specifications.
Creating resources
In the case of run
, you can actually specify many of these on the command line. For example in the last post we specified the image on the command line. For a list of all options, just do
kubectl run --help
This is not recommended though! The best practice is to write the definition in a file and apply or create it.
kubectl apply -f resource.json
kubectl create -f resource.json
kubectl apply -f resource.yaml
kubectl create -f resource.yaml
Difference between apply and create
create: Create this resource. If it exists throw an error. It doesn’t care about a change in config. It only looks for the name.
apply: update the resource with this definition. If it doesn’t exist create it.
Lets change the definition of the pod slightly. Changing ‘Hi’ to ‘Bye’ on the last line.
apiVersion: "v1"
kind: Pod
metadata:
name: ubuntu-pod
labels:
app: ubuntu-pod
version: v1
role: backend
spec:
containers:
- name: ubuntu-container
image: ubuntu
command: ["/bin/bash"]
args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"Bye\"; sleep 5; done" ]
I already have ubuntu-pod running. Now lets try to create it.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
ubuntu-pod 1/1 Running 0 23m
$ kubectl create -f ubuntuPod.yml
Error from server (AlreadyExists): error when creating "ubuntuPod.yml": pods "ubuntu-pod" already exists
As expected it failed as the resource already exists.
Now lets try to apply it
$ kubectl apply -f ubuntuPod.yml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
The Pod "ubuntu-pod" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
One warning, one error here!. Lets tackle the warning
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
The reason this warning exists is because if you try to edit a pod created in some other way, the resource that created the pod in the first place may change it back or end up in a wierd state. Remember, resources need not be directly created by you, resources can create more resources. You might also have the wrong config completely!
Now the error
The Pod "ubuntu-pod" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
This error tells us that you can only change certain fields in the specification. Lets reedit to change only the image. Lets use a better OS, move ubuntu to more hardened and secure centos.
apiVersion: "v1"
kind: Pod
metadata:
name: ubuntu-pod
labels:
app: ubuntu-pod
version: v1
role: backend
spec:
containers:
- name: ubuntu-container
image: centos
command: ["/bin/bash"]
args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"Hi\"; sleep 5; done" ]
Now the excerpt of the output of kubectl get pod/ubuntu-pod -oyaml
after apply.
spec:
containers:
- args:
- -c
- while [ "a" = "a" ]; do echo "Hi"; sleep 5; done
command:
- /bin/bash
image: centos
Now lets check the Uptime of the pod with kubectl get pod/ubuntu-pod
$ kubectl get pod/ubuntu-pod
NAME READY STATUS RESTARTS AGE
ubuntu-pod 1/1 Running 0 48m
Wow! it says no restarts and age 48m. We changed the operating system for gods sake!!!!! This doesn’t make sense! But after a while…
$ kubectl get pod/ubuntu-pod
NAME READY STATUS RESTARTS AGE
ubuntu-pod 1/1 Running 1 56m
As usual patience is virtue. This is better, so now we had 1 Restart but the pod has been up for 56 minutes (this is the time since first creation). This definitely makes more sense.
Learnings
kubectl commands may take time to execute.
If it doesn’t make sense, then either your mental model is wrong or your observation. Patience pays.
Learning is the process of firming up your mental model so that it reflects reality.
differences between create and apply.
Conclusion
In this post we learnt to define and create resources. We didn’t talk much about resource behaviour. Resources have a behaviour as well as being things. These behaviours could be interaction with other resources or things that resource does on its own. For example, a pod runs the containers it holds. What happens if a container inside it crashes ? Does the pod restart ? or is that container only restarted ?