↓ Skip to main content
Kubernetes

PlayGround: K8S

·6 mins
Table of Contents

I have been working on Kubernetes cluster and will soon plan to give a Kubernetes Certified Developer exam. In my quest, I will just record some commands that I found helpful or useful in this blog. It may be multi-part, as I will keep adding on a daily basis the commands that I will be learning.

Labels
#

> k get nodes
NAME             STATUS                     ROLES    AGE    VERSION
docker-desktop   Ready,SchedulingDisabled   master   105d   v1.16.6-beta.0

Adding a label to the node

> k label node docker-desktop nodeName=docker-node
node/docker-desktop labeled
> k get nodes --show-labels
NAME             STATUS                     ROLES    AGE    VERSION          LABELS
docker-desktop   Ready,SchedulingDisabled   master   105d   v1.16.6-beta.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-desktop,kubernetes.io/os=linux,node-role.kubernetes.io/master=,nodeName=docker-node

Notice the new label at the end nodeName=docker-node. You can also validate the label has been applied by using the selector

>k get nodes -l nodeName=docker-node
NAME             STATUS                     ROLES    AGE    VERSION
docker-desktop   Ready,SchedulingDisabled   master   105d   v1.16.6-beta.0

I will create a nginx-pod on my local Docker CE/Kubernetes and validate the Scheduling.

nodeSelector objectNodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node’s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
    app: nginx-on-node
  name: nginx-node
spec:
  nodeSelector:
    nodeName: docker-node
  containers:
    - image: nginx
      name: nginx-container
      resources:
        limits:
          memory: 500Mi
          cpu: 500m
        requests:
          memory: 250Mi
          cpu: 500m
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

What I have used is a nodeSelector that uses the label define in the section above. As the only node on my local machine is the docker-desktop and it has a setting as SchedulingDisabled the container will forever be in the Pending state.

> k get nodes
NAME             STATUS                     ROLES    AGE    VERSION
docker-desktop   Ready,SchedulingDisabled   master   105d   v1.16.6-beta.0
> k get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/curl-69c656fd45-zwt8n   1/1     Running   0          7d
pod/nginx-node              0/1     Pending   0          15m

A quick describe on the pod

> k describe pod/nginx-node

Name:         nginx-node
Namespace:    default
Priority:     0
Node:         <none>
Labels:       app=nginx-on-node
              run=nginx
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"nginx-on-node","run":"nginx"},"name":"nginx-node","namespace...
Status:       Pending
IP:           
IPs:          <none>
Containers:
  nginx-container:
    Image:      nginx
    Port:       <none>
    Host Port:  <none>
    Limits:
      cpu:     500m
      memory:  500Mi
    Requests:
      cpu:        500m
      memory:     250Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ksbmz (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  default-token-ksbmz:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ksbmz
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  nodeName=docker-node
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age        From               Message
  ----     ------            ----       ----               -------
  Warning  FailedScheduling  <unknown>  default-scheduler  0/1 nodes are available: 1 node(s) were unschedulable.

It validates the un-scedulable node. To overcome this handicap, I will use the uncordon

k uncordon -h
Mark node as schedulable.

Examples:
  # Mark node "foo" as schedulable.
  $ kubectl uncordon foo

Options:
      --dry-run=false: If true, only print the object that would be sent, without sending it.
  -l, --selector='': Selector (label query) to filter on

Usage:
  kubectl uncordon NODE [options]
> k uncordon docker-desktop
node/docker-desktop uncordoned
> k get all
NAME                        READY   STATUS              RESTARTS   AGE
pod/curl-69c656fd45-zwt8n   1/1     Running             0          7d
pod/nginx-node              0/1     ContainerCreating   0          7m12s

The moment I mark it as schedulable the state changes and I can see the Container creating. A quick describe will show the events

 Type     Reason            Age        From                     Message
  ----     ------            ----       ----                     -------
  Warning  FailedScheduling  <unknown>  default-scheduler        0/1 nodes are available: 1 node(s) were unschedulable.
  Warning  FailedScheduling  <unknown>  default-scheduler        0/1 nodes are available: 1 node(s) were unschedulable.
  Warning  FailedScheduling  <unknown>  default-scheduler        0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
  Normal   Scheduled         <unknown>  default-scheduler        Successfully assigned default/nginx-node to docker-desktop
  Normal   Pulling           6m11s      kubelet, docker-desktop  Pulling image "nginx"
  Normal   Pulled            6m6s       kubelet, docker-desktop  Successfully pulled image "nginx"
  Normal   Created           6m6s       kubelet, docker-desktop  Created container nginx-container
  Normal   Started           6m6s       kubelet, docker-desktop  Started container nginx-container

Annotations
#

> k annotate pods nginx-node description='My nginx-node on a specific node'
pod/nginx-node annotated

A describe call for the pod nginx-node can reveal the annotation.

Annotations:  description: My nginx-node on a specific node

Create
#

k create -h

Available Commands:
  clusterrole         Create a ClusterRole.
  clusterrolebinding  Create a ClusterRoleBinding for a particular ClusterRole
  configmap           Create a configmap from a local file, directory or literal value
  cronjob             Create a cronjob with the specified name.
  deployment          Create a deployment with the specified name.
  job                 Create a job with the specified name.
  namespace           Create a namespace with the specified name
  poddisruptionbudget Create a pod disruption budget with the specified name.
  priorityclass       Create a priorityclass with the specified name.
  quota               Create a quota with the specified name.
  role                Create a role with single rule.
  rolebinding         Create a RoleBinding for a particular Role or ClusterRole
  secret              Create a secret using specified subcommand
  service             Create a service using specified subcommand.
  serviceaccount      Create a service account with the specified name

Lets create a deployment

k create deploy bbdeploy --image=busybox --dry-run=true -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: bbdeploy
  name: bbdeploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: bbdeploy
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: bbdeploy
    spec:
      containers:
      - image: busybox
        name: busybox
        resources: {}
status: {}

Lets change the replicas to 2 and create the deployment

k describe deploy
Name:                   bbdeploy
Namespace:              default
CreationTimestamp:      Mon, 31 Aug 2020 16:14:00 +0530
Labels:                 app=bbdeploy
Annotations:            deployment.kubernetes.io/revision: 1
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"bbdeploy"},"name":"bbdeploy","namespace":"defaul...
Selector:               app=bbdeploy
Replicas:               2 desired | 2 updated | 2 total | 0 available | 2 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=bbdeploy
  Containers:
   busybox:
    Image:      busybox
    Port:       <none>
    Host Port:  <none>
    Limits:
      cpu:     250m
      memory:  500Mi
    Requests:
      cpu:        250m
      memory:     500Mi
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      False   MinimumReplicasUnavailable
  Progressing    True    ReplicaSetUpdated
OldReplicaSets:  <none>
NewReplicaSet:   bbdeploy-5797fdc756 (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  7s    deployment-controller  Scaled up replica set bbdeploy-5797fdc756 to 2

Similar example for Nginx

--- # My deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-webserver
  name: deploy-nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-webserver-pod
  template:
    metadata:
      labels:
        app: nginx-webserver-pod
    spec:
      containers:
        - image: nginx
          name: nginx
          resources:
            requests:
              cpu: 250m
              memory: 500Mi
            limits:
              cpu: 250m
              memory: 500Mi
k get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE    LABELS
deploy-nginx-deploy-6d45895bf5-mv9wr   1/1     Running   0          21s    app=nginx-webserver-pod,pod-template-hash=6d45895bf5
deploy-nginx-deploy-6d45895bf5-vpt6p   1/1     Running   0          21s    app=nginx-webserver-pod,pod-template-hash=6d45895bf5
k get deploy --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
deploy-nginx-deploy   2/2     2            2           32s    app=nginx-webserver
Scaling to 3
> k scale --replicas=3 deploy/deploy-nginx-deploy
deployment.apps/deploy-nginx-deploy scaled
k get all
NAME                                       READY   STATUS              RESTARTS   AGE
pod/deploy-nginx-deploy-6d45895bf5-79kd7   0/1     ContainerCreating   0          4s
pod/deploy-nginx-deploy-6d45895bf5-mv9wr   1/1     Running             0          5m
pod/deploy-nginx-deploy-6d45895bf5-vpt6p   1/1     Running             0          5
Author
Samarthya
Engineer, learner, tinkerer. This is my trophy shelf of everyday work and leisure.

Related

Helpful links for K8S

·1 min
Always remember to refer the API and elements for the YAML structure API Overview — official K8S documentation The Kuberenetes documentation that has text descriptions and good explanatory examples.

Deployments: K8S

·1 min
A declarative way of maintaining the desired state. Continuing my example from the last blog --- # Pod deployment apiVersion: apps/v1 kind: Deployment metadata: name: go-server-deployment spec: replicas: 2 selector: matchLabels: app: my-go-server template: metadata: labels: app: my-go-server spec: containers: - name: go-server image: samarthya/epserver:2.0 resources: limits: memory: "256Mi" cpu: "1024m" env: - name: SERVERPORT value: "9090" ports: - containerPort: 9090 # Reference - https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ In my deployment, I have two replicas configured, which can be increased to three using the command like the one below.