Core Concepts
kubectl
Basic commands
kubectl cluster-info
kubectl run nginx --image nginx
kubectl describe pod nginx
kubectl get pods
kubectl create -f pod-defination.yml
Nodes
Nodes is machines, it run containers. Get information about nodes, I have one node and it is master so it will show like that.
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master1 Ready control-plane 24h v1.28.4 10.10.10.51 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
master2 Ready control-plane 23h v1.28.4 10.10.10.52 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
master3 Ready control-plane 23h v1.28.4 10.10.10.53 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
node1 Ready <none> 23h v1.28.4 10.10.10.71 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
node2 Ready <none> 23h v1.28.4 10.10.10.72 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
node3 Ready <none> 23h v1.28.4 10.10.10.73 <none> Alpine Linux v3.19 6.6.4-1-virt containerd://1.7.10
The components on a node include the kubelet
, a container runtime
, and the kube-proxy
.
Pods
Smallest deployable units, group of one or more containers. Pod can contain init containers
that run during Pod startup, init containers run one by one until is completed pod container will run.
Example Pod configuration, named pod-nginx.yaml
but this just file name could be everything.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
apiVersion
is used for API location. If you are not sure apiVersion
, run below command.
$ kubectl explain pod
KIND: Pod
VERSION: v1
...
Explain command also usable for get information about data type.
$ kubectl explain pod --recursive
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.
FIELDS:
apiVersion <string>
kind <string>
metadata <ObjectMeta>
annotations <map[string]string>
...
There is another method to write yaml file easy. Impreatively declare pod with --dry-run=client
option with yaml output format. If you don't use --dry-run=client
option it run.
$ kubectl run nginx --dry-run=client --image=nginx --labels=env=test --image-pull-policy=IfNotPresent --overrides='{"spec":{"nodeSelector":{"disktype":"ssd"}}}' -o yaml > pod-nginx.yaml
When you check the file there are some additional fields but just ignore them.
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
env: test
name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
nodeSelector:
disktype: ssd
restartPolicy: Always
status: {}
After that run on file with create command. Create mean this is a new resource but if you edit in future give --save-config
option. Kubernetes protect you if you not save yaml file in cluster and making change after create, pod knowledge will destroy and cannot go back. But you can pass --force
option to edit it.
Just for inform you will understand in future.
$ kubectl create -f pod-nginx.yaml
# or use apply command, apply will understand this is new and run as 'create --save-config'
$ kubectl apply -f pod-nginx.yaml
If you want to check any events or get more information run describe
command. Use this command to detect errors.
$ kubectl describe pod nginx
Use get pods
to get list of pods
$ kubectl get pods
# or more detail
$ kubectl get pods -o wide
# or just one pod
$ kubectl get pods -o wide nginx
# or change name-space
$ kubectl get pods -n kube-system
# or get yaml file of running pod, you can edit and apply again to change
$ kubectl get pods nginx -o yaml > pod-nginx.yaml
# also you can pass `--no-headers`
# or you can filter by labels
$ kubectl get pods --selector=env=test
# or just use -l env=test
$ kubectl get pods -l env=test,foo=bar
$ kubectl get pods --show-labels
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 104s
READY mean is how many container is ready / how many containers is exist in pod.
Also you can edit running pod with edit option
$ kubectl edit pod nginx
If you want to edit in different text editor, set EDITOR
or KUBE_EDITOR
environment name. Default vi
in linux, notepad
in windows.
EDITOR="vim" kubectl edit pods nginx
WARNING
kubectl edit
will change your application and your yaml file remains old. Usually change yaml file and apply.
TIP
Annotations can usable to give additional information but this is not using for query. https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
kubectl expose pod redis --name redis-service --port 6379 --target-port 6379
kubectl run custom-nginx --image=nginx --port=8080
kubectl run httpd --image=httpd:alpine --port=80 --expose
ReplicationController
Scale Pods with wrap pad yaml file with this controller and it is guarantee the availability of a specified number of identical Pods. But new ways to use ReplicationSet
. Differences, Replicaset
support set-based label filter like in
, notin
, exists
selector.
Selector and template labels at least one is must be same.
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
if you want to write in command line use
$ cat <<EOF > nginx-replication.yaml
> apiVersion: v1
> ...
> EOF
You can use create
or apply
commands, if you are changing some fields use apply
.
$ kubectl create -f nginx-replicationController.yaml
# or
$ kubectl apply -f nginx-replicationController.yaml
Get information
$ kubectl get replicationcontrollers -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx 3 3 0 19m nginx nginx app=nginx
DESIRED
means wanted, CURRENT
is about active, READY
mean is working.
For delete write replication controller name, it will delete all pods. If you don't want to delete pods pass --cascade=false
option.
$ kubectl delete replicationcontrollers nginx
ReplicaSet
ReplicaSet as ReplicationController but selection is more useful and deployments use this. Usually you use deploymonts instead of replicaSet.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Diferences are kind, apiVersion and selector fields. In selector field also we can add matchExpression
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
Or write open style
matchExpressions:
- key: tier
operator: In
values:
- cache
- key: environment
operator: NotIn
values:
- dev
In, NotIn, Exists, DoesNotExist, Gt, Lt operators. If you use both everyone need to pass.
Use create
or apply
commands and check with get
.
$ kubectl get replicasets.apps
NAME DESIRED CURRENT READY AGE
nginx-replicaset 3 3 0 7s
Edit with edit
command or change file and use apply
command. Prefer edit yaml file.
$ kubectl edit replicasets.apps nginx-replicaset
# or change yaml file and run this command
$ kubectl replace -f nginx-replicaset.yaml
# or scale with given file
$ kubectl scale --replicas=6 -f nginx-replicaset.yaml
# or specifiy current name
$ kubectl scale --replicas=6 replicaset nginx-replicaset
If you want to check last applied.
kubectl apply view-last-applied -f nginx-replicaset.yaml -o yaml
# or look at the diff
kubectl diff -f nginx-replicaset.yaml
# or
cat nginx-replicaset.yaml | kubectl diff -f -
Also you can use set
or scale
commands to change some fields. https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#scale
Deployment
Deployment have useful stuff updating and rollback. Most of application use this. Yaml file is same with ReplicaSet
but kind is Deployment
. When you create deployment, you will see in replicaset fields also.
$ kubectl create deployment my-deployment --dry-run=client --image=nginx --replicas=3 -o yaml > nginx-deployment.yaml
$ cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: my-deployment
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-deployment
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: my-deployment
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
template field will be use when replicas is under 3 and this count looking to selector -> matchLabels field. So if you have app=my-deployment label pods deployment will use them also.
And run with apply
command. If you want to use create
you should add --save-config
option to change in future.
kubectl apply -f nginx-deployment.yaml
Get information of deployments and replicasets
$ kubectl get deployments,rs
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-deployment 0/3 3 0 74s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-deployment-57d86476b6 3 3 0 74s
replicaset.apps/nginx-replicaset 3 3 0 21m
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
Namespace
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
It is a virtual cluster.
Create namespace.
apiVersion: v1
kind: Namespace
metadata:
name: dev
$ kubectl create -f namespace-dev.yml
# or
$ kubectl create namespace dev
Get namespaces
kubectl get ns
List pods in namespaces
$ kubectl get pods --all-namespaces
# or
$ kubectl get pods --namespace=dev
# or
$ kubectl -n kube-system describe deployments nginx
We can add namespace when creating component
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
namespace: dev
labels:
app: myapp
type: front-end
spec:
containers:
- name: container
image: nginx
$ kubectl create -f pod-defination.yml
# or we can set when run command
$ kubectl create -f pod-defination.yml --namespace=dev
Resources
We can add resource to a namespace or pods with using namespaces. https://kubernetes.io/docs/concepts/policy/resource-quotas
Service
If we have more than one same pod, we can use service file to reach it.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: MyApp
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30008
NodePort is outside port. You can omit port field and targetPort show pod's port.
We declared NodePort to reach outside but in internal cluster we can use ClusterIP which is default. NodePort is not a load balancer, randomly choicing nodes. There are more type of service, check here https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
kubectl get services
Or you can use expose command to run service with specific component name like my-deployment. https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#expose
StatefulSet
ServiceName is same with headless service.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-statefulset
spec:
selector:
matchLabels:
app: my-statefulset
serviceName: my-statefulset-service
replicas: 3
template:
metadata:
labels:
app: my-statefulset
spec:
containers:
- name: my-statefulset
image: nginx
ports:
- containerPort: 80
podManagementPolicy: OrderedReady
volumeClaimTemplates:
- metadata:
name: my-statefulset-volume
spec:
accessModes:
- ReadWriteOnce
storageClassName: my-statefulset-storage
resources:
requests:
storage: 1Gi
Headless Service
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
selector:
app: my-headless-service
clusterIP: None
ports:
- port: 3306
Pod defined
apiVersion: v1
kind: Pod
metadata:
name: my-headless-service-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
subdomain: my-headless-service
hostname: mypod