Wednesday 1 May 2024

Managing Pods In A Minikube Cluster

These are custom notes that extend my notes from an Udemy course "Kubernetes for the Absolute Beginners - Hands-on". All course content rights belong to course creators. 

This is the second article in the series, the previous one being Introduction to Kubernetes | My Public Notepad.

Deploying/Creating a pod in the minikube cluster


A pod can be created with kubectrl in two ways, by providing the pod specification in the:
  1. command line arguments (kubectl run)
  2. YAML definition file (kubectl create)

To create a pod from the command line we can use the kubectl which is configured to work with the cluster.

Let's create a pod:

kubectl run nginx --image=nginx
pod/nginx created

The first nginx is the name of the pod and the second one is the name of the Docker image to be used.
While the pod name could be anything, the image name has to be the name of an image available at Docker Hub or any other container registry.

We can additionally specify a tag for the image name or a different address to an image hosted on another registry, if the image is hosted in a place that's other than Docker Hub.

To check the status (in general, to list all the pods currently present on the system):

kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          23m

READY column shows for each pod the number of containers in a ready state vs total number of containers.
RESTARTS columns shows if the container has restarted since it was created
AGE shows how long has the pod been running for.

kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          42m   10.244.0.6   minikube   <none>           <none>

-o wide option provides additional information such as the node where the pod is running and the internal IP address of the pod.  

Each port gets an internal IP of its own within the Kubernetes cluster.

We can get more information related to the pod by running:

kubectl describe pod nginx
Name:             nginx
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.59.100
Start Time:       Sun, 28 Apr 2024 22:13:21 +0100
Labels:           run=nginx
Annotations:      <none>
Status:           Running
IP:               10.244.0.6
IPs:
  IP:  10.244.0.6
Containers:
  nginx:
    Container ID:   docker://4a22ad38d0548f1a44f84b7258cbdd563f639d99d9658b7121b4eb5f084aa6a6
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:ed6d2c43c8fbcd3eaa44c9dab6d94cb346234476230dc1681227aa72d07181ee
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 28 Apr 2024 22:13:43 +0100
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-g7xlx (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-g7xlx:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  27m   default-scheduler  Successfully assigned default/nginx to minikube
  Normal  Pulling    27m   kubelet            Pulling image "nginx"
  Normal  Pulled     27m   kubelet            Successfully pulled image "nginx" in 20.386s (20.386s including waiting)
  Normal  Created    27m   kubelet            Created container nginx
  Normal  Started    27m   kubelet            Started container nginx

The output shows:
  • Pod name is nginx.
  • Labels that have been assigned to this pod. run label shows that this pod was created via run command.
  • The node that is that it is assigned to along with the IP address of the node. In this case, we just have a single node cluster set up using minikube and the node name is minikube and it is followed by the IP address of this worker node.
  • The IP address of the pod
  • Information related to the container which shows that there is a single container which uses the image nginx,  pulled from Docker Hub. If there were multiple containers, they would have been listed here.
  • Events section shows a list of events that occurred since the pod was created. We can see that it went through multiple stages before it started. We can see that the pod was assigned to the minikube node. If there were multiple nodes you would see which node the pod was assigned to. Then it entered the pulling phase where the nginx image was pulled down from Docker Hub successfully. Then the container called nginx was created and started.
As of version 1.18, kubectl run (without any arguments such as --generator) will create a pod instead of a deployment. To create a deployment using imperative command, use kubectl create:

kubectl create --help
Create a resource from a file or from stdin.

 JSON and YAML formats are accepted.

Examples:
  # Create a pod using the data in pod.json
  kubectl create -f ./pod.json
  
  # Create a pod based on the JSON passed into stdin
  cat pod.json | kubectl create -f -
  
  # Edit the data in registry.yaml in JSON then create the resource using the edited data
  kubectl create -f registry.yaml --edit -o json

Available Commands:
  clusterrole           Create a cluster role
  clusterrolebinding    Create a cluster role binding for a particular cluster role
  configmap             Create a config map from a local file, directory or literal value
  cronjob               Create a cron job with the specified name
  deployment            Create a deployment with the specified name
  ingress               Create an ingress 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 priority class with the specified name
  quota                 Create a quota with the specified name
  role                  Create a role with single rule
  rolebinding           Create a role binding for a particular role or cluster role
  secret                Create a secret using a specified subcommand
  service               Create a service using a specified subcommand
  serviceaccount        Create a service account with the specified name
  token                 Request a service account token

Options:
    --allow-missing-template-keys=true:
        If true, ignore any errors in templates when a field or map key is missing in the
        template. Only applies to golang and jsonpath output formats.

    --dry-run='none':
        Must be "none", "server", or "client". If client strategy, only print the object that
        would be sent, without sending it. If server strategy, submit server-side request without
        persisting the resource.

    --edit=false:
        Edit the API resource before creating

    --field-manager='kubectl-create':
        Name of the manager used to track field ownership.

    -f, --filename=[]:
        Filename, directory, or URL to files to use to create the resource

    -k, --kustomize='':
        Process the kustomization directory. This flag can't be used together with -f or -R.

    -o, --output='':
        Output format. One of: (json, yaml, name, go-template, go-template-file, template,
        templatefile, jsonpath, jsonpath-as-json, jsonpath-file).

    --raw='':
        Raw URI to POST to the server.  Uses the transport specified by the kubeconfig file.

    -R, --recursive=false:
        Process the directory used in -f, --filename recursively. Useful when you want to manage
        related manifests organized within the same directory.

    --save-config=false:
        If true, the configuration of current object will be saved in its annotation. Otherwise,
        the annotation will be unchanged. This flag is useful when you want to perform kubectl
        apply on this object in the future.

    -l, --selector='':
        Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l
        key1=value1,key2=value2). Matching objects must satisfy all of the specified label
        constraints.

    --show-managed-fields=false:
        If true, keep the managedFields when printing objects in JSON or YAML format.

    --template='':
        Template string or path to template file to use when -o=go-template, -o=go-template-file.
        The template format is golang templates
        [http://golang.org/pkg/text/template/#pkg-overview].

    --validate='strict':
        Must be one of: strict (or true), warn, ignore (or false).              "true" or "strict" will use a
        schema to validate the input and fail the request if invalid. It will perform server side
        validation if ServerSideFieldValidation is enabled on the api-server, but will fall back
        to less reliable client-side validation if not.                 "warn" will warn about unknown or
        duplicate fields without blocking the request if server-side field validation is enabled
        on the API server, and behave as "ignore" otherwise.            "false" or "ignore" will not
        perform any schema validation, silently dropping any unknown or duplicate fields.

    --windows-line-endings=false:
        Only relevant if --edit=true. Defaults to the line ending native to your platform.

Usage:
  kubectl create -f FILENAME [options]

Use "kubectl create <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).


Let's create a deployment resource:

kubectl create deployment nginx --image=nginx

Resources:


It is also possible to create a pod using a YAML definition file.

Quiz:
The smallest unit you can create in Kubernetes object model is:? Pod
A Pod can only have one container in it? False
What is the right approach to scale an application? Deploy additional pods.

Kubernetes uses YAML files as inputs for the creation of objects such as pods, replicas, deployment services, etc. All of these follow similar structure as Kubernetes definition file always contains 4 top level (root level) fields which are also required fields so we must have them in the configuration file:

pod-definition.yml:

apiVersion:
kind:
metadata:
spec:


apiVersion
  • string
  • Version of the Kubernetes API we're using to create the objects
  • Depending on what we are trying to create we must use the right API version. For now since we are working on the pod, we will set the API version as we want e.g. to v1
  • Few other possible values for this field are apps/v1-betaextensions/v1-beta
kind
  • string, case-sensitive!
  • Refers to the type of object we are trying to create which in this case happens to be a pod so we will set it as Pod
  • Some other possible values here could be ReplicaSetDeployment or Service 
metadata
  • dictionary
  • Data about the object (in our case a pod) like its namelabels etc. 
  • name is a string value so we can name our pod as myapp-pod
  • labels is a dictionary within the metadata dictionary and it can have any key value pairs as we wish. We can add a label named app with the value myapp. We could add other labels which will help us identify and/or group these objects at a later point in time. For example: there are hundreds of pods running a front end application and hundreds of pods running a backend application or a database. It will be difficult for us to group these parts once they are deployed. If we label them now as frontendbackend or database we will be able to filter the parts.
  • under metadata we can only specify name or labels or anything else that Kubernetes expects to be under metadata. We cannot add any other property as we wish under this. However, under labels we can have any kind of key or value pairs.
spec
  • specification section 
  • Depending on the object we are going to create, this is where we would provide additional information to Kubernetes pertaining to that object. This is going to be different for different objects so it's important to understand or refer to the documentation section to get the right format for each.
  • Since we are only creating a pod with a single container in it, spec is a dictionary.
  • So add a property under it called containers. Containers is a list or an array. The reason this property is a list is because the parts can have multiple containers within them.
  • In this case though we will only add a single item in the list since we plan to have only a single container in the part. That - right before the name indicates that this is the first item in the list the item in the list is a dictionary. So add a name and image property. The value for image is nginx, which is the name of the Docker image in the docker repository.

The complete pod-definition.yml file looks now like this:

apiVersion: v1
kind: Pod
metadata:
   name: myapp-pod
   labels:
      app: myapp
      type: frontend
spec:
   containers:
   - name: nginx-container
     image: nginx 


To make Kubernetes create the pod based on the YAML file, execute:

kubectl create -f pod-definition.yml


To see a list of pods available:

kubectl get pods 

In this case it's just one. 

To see detailed information about the pod.

kubectl describe pod myapp-pod

---

Another example:

pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
  - name: nginx
    # DockerHub image name
    image: nginx


To create this pod we can use either kubectl create or kubectl apply (kubernetes - kubectl apply vs kubectl create? - Stack Overflow):

$ kubectl apply -f minikube/pod.yaml
Warning: resource pods/nginx is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
pod/nginx configured


$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          24h


kubectl describe pod nginx
Name:             nginx
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.59.100
Start Time:       Sun, 28 Apr 2024 22:13:21 +0100
Labels:           app=nginx
                  run=nginx
                  tier=frontend
Annotations:      <none>
Status:           Running
IP:               10.244.0.6
IPs:
  IP:  10.244.0.6
Containers:
  nginx:
    Container ID:   docker://4a22ad38d0548f1a44f84b7258cbdd563f639d99d9658b7121b4eb5f084aa6a6
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:ed6d2c43c8fbcd3eaa44c9dab6d94cb346234476230dc1681227aa72d07181ee
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 28 Apr 2024 22:13:43 +0100
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-g7xlx (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-g7xlx:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>
---

If Docker image requires an environment variable to be set, we need to add a property env to container YAML object, making it a sibling of image and name

env is an array/list of objects which have two properties: name and valueName is the environment variable name and value is its value. 

Example: Postgres Docker image requires an environment variable to be set for password.  

pod_postgres.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: postgres
  labels:
    tier: db-tier
spec:
  containers:
  - name: postgres
    image: postgres
    env:
    - name: POSTGRES_PASSWORD
      value: mysecretpassword


---

To check how many pods are in currently present in the system:

$ kubectl get pods
No resources found in default namespace.


To check which image is container running in the pod based on:

$ kubectl describe pod newpods-prc2v | grep image
  Normal  Pulling    8m29s  kubelet            Pulling image "busybox"
  Normal  Pulled     8m29s  kubelet            Successfully pulled image "busybox" in 236ms (236ms including waiting)

To get the name of nodes on which the pod is running:

$ kubectl get pods -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
nginx           1/1     Running   0          10m   10.42.0.9    controlplane   <none>           <none>
newpods-prc2v   1/1     Running   0          10m   10.42.0.12   controlplane   <none>           <none>
newpods-cbqsb   1/1     Running   0          10m   10.42.0.11   controlplane   <none>           <none>
newpods-5cn9m   1/1     Running   0          10m   10.42.0.10   controlplane   <none>           <none>

To find out how many containers are running in the pod, which images are used in them, the state of the containers in the pod, the reason why some container in pod is in error (in events section): 

$ kubectl describe pod webapp
Name:             webapp
Namespace:        default
Priority:         0
Service Account:  default
Node:             controlplane/192.40.2.3
Start Time:       Tue, 30 Apr 2024 22:50:01 +0000
Labels:           <none>
Annotations:      <none>
Status:           Pending
IP:               10.42.0.13
IPs:
  IP:  10.42.0.13
Containers:
  nginx:
    Container ID:   containerd://c5f742b68a9a704c9f9e6069be04f073e6d784408efebb42725dc30ac6a41cad
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:ed6d2c43c8fbcd3eaa44c9dab6d94cb346234476230dc1681227aa72d07181ee
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Tue, 30 Apr 2024 22:50:03 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bfj5c (ro)
  agentx:
    Container ID:   
    Image:          agentx
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ImagePullBackOff
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bfj5c (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       False 
  ContainersReady             False 
  PodScheduled                True 
Volumes:
  kube-api-access-bfj5c:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  82s                default-scheduler  Successfully assigned default/webapp to controlplane
  Normal   Pulling    82s                kubelet            Pulling image "nginx"
  Normal   Pulled     81s                kubelet            Successfully pulled image "nginx" in 752ms (752ms including waiting)
  Normal   Created    81s                kubelet            Created container nginx
  Normal   Started    81s                kubelet            Started container nginx
  Normal   BackOff    15s (x4 over 80s)  kubelet            Back-off pulling image "agentx"
  Warning  Failed     15s (x4 over 80s)  kubelet            Error: ImagePullBackOff
  Normal   Pulling    1s (x4 over 81s)   kubelet            Pulling image "agentx"
  Warning  Failed     0s (x4 over 81s)   kubelet            Failed to pull image "agentx": failed to pull and unpack image "docker.io/library/agentx:latest": failed to resolve reference "docker.io/library/agentx:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
  Warning  Failed     0s (x4 over 81s)   kubelet            Error: ErrImagePull


Deleting the pod


To delete a pod:

kubectl delete --help
Delete resources by file names, stdin, resources and names, or by resources and label selector.

 JSON and YAML formats are accepted. Only one type of argument may be specified: file names,
resources and names, or resources and label selector.

 Some resources, such as pods, support graceful deletion. These resources define a default period
before they are forcibly terminated (the grace period) but you may override that value with the
--grace-period flag, or pass --now to set a grace-period of 1. Because these resources often
represent entities in the cluster, deletion may not be acknowledged immediately. If the node hosting
a pod is down or cannot reach the API server, termination may take significantly longer than the
grace period. To force delete a resource, you must specify the --force flag. Note: only a subset of
resources support graceful deletion. In absence of the support, the --grace-period flag is ignored.

 IMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been
terminated, which can leave those processes running until the node detects the deletion and
completes graceful deletion. If your processes use shared storage or talk to a remote API and depend
on the name of the pod to identify themselves, force deleting those pods may result in multiple
processes running on different machines using the same identification which may lead to data
corruption or inconsistency. Only force delete pods when you are sure the pod is terminated, or if
your application can tolerate multiple copies of the same pod running at once. Also, if you force
delete pods, the scheduler may place new pods on those nodes before the node has released those
resources and causing those pods to be evicted immediately.

 Note that the delete command does NOT do resource version checks, so if someone submits an update
to a resource right when you submit a delete, their update will be lost along with the rest of the
resource.

 After a CustomResourceDefinition is deleted, invalidation of discovery cache may take up to 6
hours. If you don't want to wait, you might want to run "kubectl api-resources" to refresh the
discovery cache.

Examples:
  # Delete a pod using the type and name specified in pod.json
  kubectl delete -f ./pod.json
  
  # Delete resources from a directory containing kustomization.yaml - e.g. dir/kustomization.yaml
  kubectl delete -k dir
  
  # Delete resources from all files that end with '.json'
  kubectl delete -f '*.json'
  
  # Delete a pod based on the type and name in the JSON passed into stdin
  cat pod.json | kubectl delete -f -
  
  # Delete pods and services with same names "baz" and "foo"
  kubectl delete pod,service baz foo
  
  # Delete pods and services with label name=myLabel
  kubectl delete pods,services -l name=myLabel
  
  # Delete a pod with minimal delay
  kubectl delete pod foo --now
  
  # Force delete a pod on a dead node
  kubectl delete pod foo --force
  
  # Delete all pods
  kubectl delete pods --all

Options:
    --all=false:
        Delete all resources, in the namespace of the specified resource types.

    -A, --all-namespaces=false:
        If present, list the requested object(s) across all namespaces. Namespace in current
        context is ignored even if specified with --namespace.

    --cascade='background':
        Must be "background", "orphan", or "foreground". Selects the deletion cascading strategy
        for the dependents (e.g. Pods created by a ReplicationController). Defaults to background.

    --dry-run='none':
        Must be "none", "server", or "client". If client strategy, only print the object that
        would be sent, without sending it. If server strategy, submit server-side request without
        persisting the resource.

    --field-selector='':
        Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector
        key1=value1,key2=value2). The server only supports a limited number of field queries per
        type.

    -f, --filename=[]:
        containing the resource to delete.

    --force=false:
        If true, immediately remove resources from API and bypass graceful deletion. Note that
        immediate deletion of some resources may result in inconsistency or data loss and requires
        confirmation.

    --grace-period=-1:
        Period of time in seconds given to the resource to terminate gracefully. Ignored if
        negative. Set to 1 for immediate shutdown. Can only be set to 0 when --force is true
        (force deletion).

    --ignore-not-found=false:
        Treat "resource not found" as a successful delete. Defaults to "true" when --all is
        specified.

    -i, --interactive=false:
        If true, delete resource only when user confirms. This flag is in Alpha.

    -k, --kustomize='':
        Process a kustomization directory. This flag can't be used together with -f or -R.

    --now=false:
        If true, resources are signaled for immediate shutdown (same as --grace-period=1).

    -o, --output='':
        Output mode. Use "-o name" for shorter output (resource/name).

    --raw='':
        Raw URI to DELETE to the server.  Uses the transport specified by the kubeconfig file.

    -R, --recursive=false:
        Process the directory used in -f, --filename recursively. Useful when you want to manage
        related manifests organized within the same directory.

    -l, --selector='':
        Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l
        key1=value1,key2=value2). Matching objects must satisfy all of the specified label
        constraints.

    --timeout=0s:
        The length of time to wait before giving up on a delete, zero means determine a timeout
        from the size of the object

    --wait=true:
        If true, wait for resources to be gone before returning. This waits for finalizers.

Usage:
  kubectl delete ([-f FILENAME] | [-k DIRECTORY] | TYPE [(NAME | -l label | --all)]) [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).


So let's delete pod:

kubectl delete pod webapp
pod "webapp" deleted


Changing the existing pod



If we create a pod based on definition file:

kubectl create -f pod-definition.yaml 
pod/redis created

... and then check pods and realize that our pod does not have containers in ready state (possibly for the error in the yaml file):

$ kubectl get pods
NAME            READY   STATUS             RESTARTS       AGE
nginx           1/1     Running            0              38m
newpods-prc2v   1/1     Running            2 (5m9s ago)   38m
newpods-cbqsb   1/1     Running            2 (5m9s ago)   38m
newpods-5cn9m   1/1     Running            2 (5m9s ago)   38m
redis           0/1     ImagePullBackOff   0              48s

...we can change YAML file after which we can apply changes with apply subcommand:


kubectl apply --help
Apply a configuration to a resource by file name or stdin. The resource name must be specified. This
resource will be created if it doesn't exist yet. To use 'apply', always create the resource
initially with either 'apply' or 'create --save-config'.

 JSON and YAML formats are accepted.

 Alpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of
what the current state is. See https://issues.k8s.io/34274.

Examples:
  # Apply the configuration in pod.json to a pod
  kubectl apply -f ./pod.json
  
  # Apply resources from a directory containing kustomization.yaml - e.g. dir/kustomization.yaml
  kubectl apply -k dir/
  
  # Apply the JSON passed into stdin to a pod
  cat pod.json | kubectl apply -f -
  
  # Apply the configuration from all files that end with '.json'
  kubectl apply -f '*.json'
  
  # Note: --prune is still in Alpha
  # Apply the configuration in manifest.yaml that matches label app=nginx and delete all other
resources that are not in the file and match label app=nginx
  kubectl apply --prune -f manifest.yaml -l app=nginx
  
  # Apply the configuration in manifest.yaml and delete all the other config maps that are not in
the file
  kubectl apply --prune -f manifest.yaml --all --prune-allowlist=core/v1/ConfigMap

Available Commands:
  edit-last-applied   Edit latest last-applied-configuration annotations of a resource/object
  set-last-applied    Set the last-applied-configuration annotation on a live object to match the
contents of a file
  view-last-applied   View the latest last-applied-configuration annotations of a resource/object

Options:
    --all=false:
        Select all resources in the namespace of the specified resource types.

    --allow-missing-template-keys=true:
        If true, ignore any errors in templates when a field or map key is missing in the
        template. Only applies to golang and jsonpath output formats.

    --cascade='background':
        Must be "background", "orphan", or "foreground". Selects the deletion cascading strategy
        for the dependents (e.g. Pods created by a ReplicationController). Defaults to background.

    --dry-run='none':
        Must be "none", "server", or "client". If client strategy, only print the object that
        would be sent, without sending it. If server strategy, submit server-side request without
        persisting the resource.

    --field-manager='kubectl-client-side-apply':
        Name of the manager used to track field ownership.

    -f, --filename=[]:
        The files that contain the configurations to apply.

    --force=false:
        If true, immediately remove resources from API and bypass graceful deletion. Note that
        immediate deletion of some resources may result in inconsistency or data loss and requires
        confirmation.

    --force-conflicts=false:
        If true, server-side apply will force the changes against conflicts.

    --grace-period=-1:
        Period of time in seconds given to the resource to terminate gracefully. Ignored if
        negative. Set to 1 for immediate shutdown. Can only be set to 0 when --force is true
        (force deletion).

    -k, --kustomize='':
        Process a kustomization directory. This flag can't be used together with -f or -R.

    --openapi-patch=true:
        If true, use openapi to calculate diff when the openapi presents and the resource can be
        found in the openapi spec. Otherwise, fall back to use baked-in types.

    -o, --output='':
        Output format. One of: (json, yaml, name, go-template, go-template-file, template,
        templatefile, jsonpath, jsonpath-as-json, jsonpath-file).

    --overwrite=true:
        Automatically resolve conflicts between the modified and live configuration by using
        values from the modified configuration

    --prune=false:
        Automatically delete resource objects, that do not appear in the configs and are created
        by either apply or create --save-config. Should be used with either -l or --all.

    --prune-allowlist=[]:
        Overwrite the default allowlist with <group/version/kind> for --prune

    -R, --recursive=false:
        Process the directory used in -f, --filename recursively. Useful when you want to manage
        related manifests organized within the same directory.

    -l, --selector='':
        Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l
        key1=value1,key2=value2). Matching objects must satisfy all of the specified label
        constraints.

    --server-side=false:
        If true, apply runs in the server instead of the client.

    --show-managed-fields=false:
        If true, keep the managedFields when printing objects in JSON or YAML format.

    --template='':
        Template string or path to template file to use when -o=go-template, -o=go-template-file.
        The template format is golang templates
        [http://golang.org/pkg/text/template/#pkg-overview].

    --timeout=0s:
        The length of time to wait before giving up on a delete, zero means determine a timeout
        from the size of the object

    --validate='strict':
        Must be one of: strict (or true), warn, ignore (or false).              "true" or "strict" will use a
        schema to validate the input and fail the request if invalid. It will perform server side
        validation if ServerSideFieldValidation is enabled on the api-server, but will fall back
        to less reliable client-side validation if not.                 "warn" will warn about unknown or
        duplicate fields without blocking the request if server-side field validation is enabled
        on the API server, and behave as "ignore" otherwise.            "false" or "ignore" will not
        perform any schema validation, silently dropping any unknown or duplicate fields.

    --wait=false:
        If true, wait for resources to be gone before returning. This waits for finalizers.

Usage:
  kubectl apply (-f FILENAME | -k DIRECTORY) [options]

Use "kubectl apply <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

So let's apply the changed resource configuration from a YAML file on the existing resource:

kubectl apply -f pod-definition.yaml 
Warning: resource pods/redis is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
pod/redis configured

kubectl get pods
NAME            READY   STATUS    RESTARTS      AGE
nginx           1/1     Running   0             44m
newpods-prc2v   1/1     Running   2 (11m ago)   44m
newpods-cbqsb   1/1     Running   2 (11m ago)   44m
newpods-5cn9m   1/1     Running   2 (11m ago)   44m
redis           1/1     Running   0             6m39s


Cool trick: Instead of manually creating a YAML file for specifying a pod with a single container based on some image we can do the following:

kubectl run redis --image=redis --dry-run=client -o yaml > pod-definition.yaml


No comments: