Code Monkey home page Code Monkey logo

using-kubectl-generate-yaml-manifests's Introduction

Using kubectl to Generate YAML Manifests

Tom Dean - 5/16/2023

Introduction

I'm currently studying to take the CKAD and CKA exams, and there remain a few key areas where I need to build my Kubernetes muscles. Coming from a Linux background (of many years), the cluster building and troubleshooting doesn't faze me. Creating declarative manifests, well, that's a different story.

Using the kubectl command imperatively to create Kubernetes manifests for declarative deployment, an important skill for both exams, lands at the top of that list. On the CKAD and CKA exams, every second counts, and this skill facilitates the rapid and consistent generation of YAML manifests that can quickly be edited and deployed to Kubernetes.

What makes this skill so important?

  • Fast: Seconds count. Less reliant on finding an example in the docs, then copying it.
  • Accurate: No typos. No formatting errors. Manifest works the first time.
  • Easy: Let kubectl do the heavy lifting.

Adrien Trouillaud wrote an excellent Medium article, Imperative vs. Declarative โ€” a Kubernetes Tutorial, which I discovered while researching this topic. Adrien's article, a comprehensive tutorial on how to leverage the imperative approach to creating objects in Kubernetes, clarified the topic for me. The article dates back to early 2019, so some of the syntax has changed, but the concepts in the article still ring true. I learned even more by digging into the commands and updating the syntax, where needed. I would highly recommend giving it a read.

In this tutorial, you're not only going to learn about the kubectl command, you're going to get hands-on with using the kubectl command imperatively to create some common objects, as well as some declarative YAML manifests. You will also practice some common kubectl commands used to manage and deploy these manifests.

Let's dig in!

References

Medium: Imperative vs. Declarative โ€” a Kubernetes Tutorial

Kubernetes: Command line tool (kubectl)

Kubernetes: kubectl Cheat Sheet

Kubernetes: Install Tools

GitHub: cka-d-cluster-builder-lab

GitHub: Deploying a Kubernetes In Docker (KIND) Cluster Using Podman on Ubuntu Linux

Kubernetes: Managing Kubernetes Objects Using Imperative Commands

Kubernetes: Service

Kubernetes: Use a Service to Access an Application in a Cluster

Kubernetes: ReplicaSet

Kubernetes: Deployments

Kubernetes: Logging Architecture

Prerequisites

Kubernetes: Install Tools

GitHub: cka-d-cluster-builder-lab

GitHub: Deploying a Kubernetes In Docker (KIND) Cluster Using Podman on Ubuntu Linux

The examples in this guide come from an Ubuntu Linux 22.04 operating system environment with a two-node Kubernetes 1.26.1 cluster configured with kubeadm, using the cka-d-cluster-builder-lab automation.

You're going to need a Kubernetes environment to perform the steps in this tutorial. If you have access to one already, you can use it. If not, you'll need to create one. I've provided some resources in the links in this section.

The first link, from the Kubernetes documentation, contains resources detailing several options for cluster installation.

I've also provided links to two of my GitHub repositories with tutorials, one for creating a kubeadm cluster using Terraform and KVM (GitHub: cka-d-cluster-builder-lab) and a second for creating a Kubernetes In Docker, or KIND, cluster (GitHub: Deploying a Kubernetes In Docker (KIND) Cluster Using Podman on Ubuntu Linux). Either of these will work for this tutorial.

When you have your cluster, check it out. Start with the high-level cluster information.

High-level information:

kubectl cluster-info

Sample Output:

$ kubectl cluster-info

Kubernetes control plane is running at https://10.0.1.132:6443
CoreDNS is running at https://10.0.1.132:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

You can use the kubectl get command to take a look at objects in your cluster. Take a look at your Kubernetes nodes.

List of nodes, with detail:

kubectl get nodes -o wide

Sample Output:

$ kubectl get nodes -o wide

NAME               STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
control-plane-01   Ready    control-plane   6d22h   v1.26.1   10.0.1.132    <none>        Ubuntu 22.04.2 LTS   5.15.0-69-generic   containerd://1.6.20
worker-node-01     Ready    <none>          6d22h   v1.26.1   10.0.1.204    <none>        Ubuntu 22.04.2 LTS   5.15.0-69-generic   containerd://1.6.20

The Kubernetes cluster in the previous example consists of two nodes, one Control Plane node and one Worker node.

Take a look at all the objects on your cluster.

List all objects, in all namespaces:

kubectl get all -A

Sample Output:

$ kubectl get all -A

NAMESPACE     NAME                                           READY   STATUS    RESTARTS   AGE
kube-system   pod/calico-kube-controllers-57b57c56f-4hvfl    1/1     Running   0          6d22h
kube-system   pod/calico-node-s28hb                          1/1     Running   0          6d22h
kube-system   pod/calico-node-tqb6g                          1/1     Running   0          6d22h
kube-system   pod/coredns-787d4945fb-cg5wh                   1/1     Running   0          6d22h
kube-system   pod/coredns-787d4945fb-xdbll                   1/1     Running   0          6d22h
kube-system   pod/etcd-control-plane-01                      1/1     Running   0          6d22h
kube-system   pod/kube-apiserver-control-plane-01            1/1     Running   0          6d22h
kube-system   pod/kube-controller-manager-control-plane-01   1/1     Running   0          6d22h
kube-system   pod/kube-proxy-blgcf                           1/1     Running   0          6d22h
kube-system   pod/kube-proxy-t9wb4                           1/1     Running   0          6d22h
kube-system   pod/kube-scheduler-control-plane-01            1/1     Running   0          6d22h

NAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  6d22h
kube-system   service/kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   6d22h

NAMESPACE     NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   daemonset.apps/calico-node   2         2         2       2            2           kubernetes.io/os=linux   6d22h
kube-system   daemonset.apps/kube-proxy    2         2         2       2            2           kubernetes.io/os=linux   6d22h

NAMESPACE     NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/calico-kube-controllers   1/1     1            1           6d22h
kube-system   deployment.apps/coredns                   2/2     2            2           6d22h

NAMESPACE     NAME                                                DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/calico-kube-controllers-57b57c56f   1         1         1       6d22h
kube-system   replicaset.apps/coredns-787d4945fb                  2         2         2       6d22h

The previous example represents the resources on a basic Kubernetes cluster.

List all namespaces:

kubectl get ns

Sample Output:

$ kubectl get ns
NAME              STATUS   AGE
default           Active   6d22h
kube-node-lease   Active   6d22h
kube-public       Active   6d22h
kube-system       Active   6d22h

This cluster has four namespaces.

With a working cluster at your disposal, you're ready to proceed.

Exploring the kubectl Command

Kubernetes: Command line tool (kubectl)

Kubernetes: kubectl Cheat Sheet

The kubectl command, the primary tool you're going to use to interact with your Kubernetes cluster, both in this tutorial and the CKA/CKAD exams, provides a user-friendly, or user-friendlier, method of interacting with the Kubernetes API.

Help in kubectl

Let's take a look at the kubectl command, starting at the top.

Top-level help:

kubectl --help

Sample Output:

$ kubectl --help

kubectl controls the Kubernetes cluster manager.

 Find more information at: https://kubernetes.io/docs/reference/kubectl/

Basic Commands (Beginner):
  create          Create a resource from a file or from stdin
  expose          Take a replication controller, service, deployment or pod and expose it as a new Kubernetes service
  run             Run a particular image on the cluster
  set             Set specific features on objects

Basic Commands (Intermediate):
  explain         Get documentation for a resource
  get             Display one or many resources
  edit            Edit a resource on the server
  delete          Delete resources by file names, stdin, resources and names, or by resources and label selector

Deploy Commands:
  rollout         Manage the rollout of a resource
  scale           Set a new size for a deployment, replica set, or replication controller
  autoscale       Auto-scale a deployment, replica set, stateful set, or replication controller

Cluster Management Commands:
  certificate     Modify certificate resources.
  cluster-info    Display cluster information
  top             Display resource (CPU/memory) usage
  cordon          Mark node as unschedulable
  uncordon        Mark node as schedulable
  drain           Drain node in preparation for maintenance
  taint           Update the taints on one or more nodes

Troubleshooting and Debugging Commands:
  describe        Show details of a specific resource or group of resources
  logs            Print the logs for a container in a pod
  attach          Attach to a running container
  exec            Execute a command in a container
  port-forward    Forward one or more local ports to a pod
  proxy           Run a proxy to the Kubernetes API server
  cp              Copy files and directories to and from containers
  auth            Inspect authorization
  debug           Create debugging sessions for troubleshooting workloads and nodes
  events          List events

Advanced Commands:
  diff            Diff the live version against a would-be applied version
  apply           Apply a configuration to a resource by file name or stdin
  patch           Update fields of a resource
  replace         Replace a resource by file name or stdin
  wait            Experimental: Wait for a specific condition on one or many resources
  kustomize       Build a kustomization target from a directory or URL.

Settings Commands:
  label           Update the labels on a resource
  annotate        Update the annotations on a resource
  completion      Output shell completion code for the specified shell (bash, zsh, fish, or powershell)

Other Commands:
  alpha           Commands for features in alpha
  api-resources   Print the supported API resources on the server
  api-versions    Print the supported API versions on the server, in the form of "group/version"
  config          Modify kubeconfig files
  plugin          Provides utilities for interacting with plugins
  version         Print the client and server version information

Usage:
  kubectl [flags] [options]

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

The kubectl --help command provides you with a great high-level view of all the commands available to kubectl. You can dig down further by adding the command, such as kubectl run --help.

Drilling down, into the kubectl run command:

kubectl run --help

Sample Output:

$ kubectl run --help

Create and run a particular image in a pod.

Examples:
  # Start a nginx pod
  kubectl run nginx --image=nginx

  # Start a hazelcast pod and let the container expose port 5701
  kubectl run hazelcast --image=hazelcast/hazelcast --port=5701

  # Start a hazelcast pod and set environment variables "DNS_DOMAIN=cluster" and "POD_NAMESPACE=default" in the
container
  kubectl run hazelcast --image=hazelcast/hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default"

  # Start a hazelcast pod and set labels "app=hazelcast" and "env=prod" in the container
  kubectl run hazelcast --image=hazelcast/hazelcast --labels="app=hazelcast,env=prod"

  # Dry run; print the corresponding API objects without creating them
  kubectl run nginx --image=nginx --dry-run=client

  # Start a nginx pod, but overload the spec with a partial set of values parsed from JSON
  kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'

  # Start a busybox pod and keep it in the foreground, don't restart it if it exits
  kubectl run -i -t busybox --image=busybox --restart=Never

  # Start the nginx pod using the default command, but use custom arguments (arg1 .. argN) for that command
  kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN>

  # Start the nginx pod using a different command and custom arguments
  kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>

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.

    --annotations=[]:
	Annotations to apply to the pod.

    --attach=false:
	If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called.
	Default false, unless '-i/--stdin' is set, in which case the default is true. With '--restart=Never' the exit
	code of the container process is returned.

    --command=false:
	If true and extra arguments are present, use them as the 'command' field in the container, rather than the
	'args' field which is the default.

    --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.

    --env=[]:
	Environment variables to set in the container.

    --expose=false:
	If true, create a ClusterIP service associated with the pod.  Requires `--port`.

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

    --image='':
	The image for the container to run.

    --image-pull-policy='':
	The image pull policy for the container.  If left empty, this value will not be specified by the client and
	defaulted by the server.

    -l, --labels='':
	Comma separated labels to apply to the pod. Will override previous values.

    --leave-stdin-open=false:
	If the pod is started in interactive mode or with stdin, leave stdin open after the first attach completes. By
	default, stdin will be closed after the first attach completes.

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

    --override-type='merge':
	The method used to override the generated object: json, merge, or strategic.

    --overrides='':
	An inline JSON override for the generated object. If this is non-empty, it is used to override the generated
	object. Requires that the object supply a valid apiVersion field.

    --pod-running-timeout=1m0s:
	The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one pod is running

    --port='':
	The port that this container exposes.

    --privileged=false:
	If true, run the container in privileged mode.

    -q, --quiet=false:
	If true, suppress prompt messages.

    --restart='Always':
	The restart policy for this Pod.  Legal values [Always, OnFailure, Never].

    --rm=false:
	If true, delete the pod after it exits.  Only valid when attaching to the container, e.g. with '--attach' or
	with '-i/--stdin'.

    --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.

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

    -i, --stdin=false:
	Keep stdin open on the container in the pod, even if nothing is attached.

    --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].

    -t, --tty=false:
	Allocate a TTY for the container in the pod.

Usage:
  kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=server|client] [--overrides=inline-json]
[--command] -- [COMMAND] [args...] [options]

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

This view gives you a high-level explanation of the kubectl run command, including usage examples and the syntax and switches.

Go ahead, play around, get familiar with the help functionality in the kubectl command. It's the fastest documentation for kubectl, both when taking the exams and for day-to-day use.

Kubernetes API Resources

Kubernetes API resources, another part of the kubectl command you should understand, can be viewed using the kubectl api-resources command.

Listing all available API resources:

kubectl api-resources

Sample Output:

$ kubectl api-resources

NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
bindings                                       v1                                     true         Binding
componentstatuses                 cs           v1                                     false        ComponentStatus
configmaps                        cm           v1                                     true         ConfigMap
endpoints                         ep           v1                                     true         Endpoints
events                            ev           v1                                     true         Event
limitranges                       limits       v1                                     true         LimitRange
namespaces                        ns           v1                                     false        Namespace
nodes                             no           v1                                     false        Node
persistentvolumeclaims            pvc          v1                                     true         PersistentVolumeClaim
persistentvolumes                 pv           v1                                     false        PersistentVolume
pods                              po           v1                                     true         Pod
podtemplates                                   v1                                     true         PodTemplate
replicationcontrollers            rc           v1                                     true         ReplicationController
resourcequotas                    quota        v1                                     true         ResourceQuota
secrets                                        v1                                     true         Secret
serviceaccounts                   sa           v1                                     true         ServiceAccount
services                          svc          v1                                     true         Service
mutatingwebhookconfigurations                  admissionregistration.k8s.io/v1        false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io/v1        false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io/v1                false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io/v1              false        APIService
controllerrevisions                            apps/v1                                true         ControllerRevision
daemonsets                        ds           apps/v1                                true         DaemonSet
deployments                       deploy       apps/v1                                true         Deployment
replicasets                       rs           apps/v1                                true         ReplicaSet
statefulsets                      sts          apps/v1                                true         StatefulSet
tokenreviews                                   authentication.k8s.io/v1               false        TokenReview
localsubjectaccessreviews                      authorization.k8s.io/v1                true         LocalSubjectAccessReview
selfsubjectaccessreviews                       authorization.k8s.io/v1                false        SelfSubjectAccessReview
selfsubjectrulesreviews                        authorization.k8s.io/v1                false        SelfSubjectRulesReview
subjectaccessreviews                           authorization.k8s.io/v1                false        SubjectAccessReview
horizontalpodautoscalers          hpa          autoscaling/v2                         true         HorizontalPodAutoscaler
cronjobs                          cj           batch/v1                               true         CronJob
jobs                                           batch/v1                               true         Job
certificatesigningrequests        csr          certificates.k8s.io/v1                 false        CertificateSigningRequest
leases                                         coordination.k8s.io/v1                 true         Lease
bgpconfigurations                              crd.projectcalico.org/v1               false        BGPConfiguration
bgppeers                                       crd.projectcalico.org/v1               false        BGPPeer
blockaffinities                                crd.projectcalico.org/v1               false        BlockAffinity
caliconodestatuses                             crd.projectcalico.org/v1               false        CalicoNodeStatus
clusterinformations                            crd.projectcalico.org/v1               false        ClusterInformation
felixconfigurations                            crd.projectcalico.org/v1               false        FelixConfiguration
globalnetworkpolicies                          crd.projectcalico.org/v1               false        GlobalNetworkPolicy
globalnetworksets                              crd.projectcalico.org/v1               false        GlobalNetworkSet
hostendpoints                                  crd.projectcalico.org/v1               false        HostEndpoint
ipamblocks                                     crd.projectcalico.org/v1               false        IPAMBlock
ipamconfigs                                    crd.projectcalico.org/v1               false        IPAMConfig
ipamhandles                                    crd.projectcalico.org/v1               false        IPAMHandle
ippools                                        crd.projectcalico.org/v1               false        IPPool
ipreservations                                 crd.projectcalico.org/v1               false        IPReservation
kubecontrollersconfigurations                  crd.projectcalico.org/v1               false        KubeControllersConfiguration
networkpolicies                                crd.projectcalico.org/v1               true         NetworkPolicy
networksets                                    crd.projectcalico.org/v1               true         NetworkSet
endpointslices                                 discovery.k8s.io/v1                    true         EndpointSlice
events                            ev           events.k8s.io/v1                       true         Event
flowschemas                                    flowcontrol.apiserver.k8s.io/v1beta3   false        FlowSchema
prioritylevelconfigurations                    flowcontrol.apiserver.k8s.io/v1beta3   false        PriorityLevelConfiguration
ingressclasses                                 networking.k8s.io/v1                   false        IngressClass
ingresses                         ing          networking.k8s.io/v1                   true         Ingress
networkpolicies                   netpol       networking.k8s.io/v1                   true         NetworkPolicy
runtimeclasses                                 node.k8s.io/v1                         false        RuntimeClass
poddisruptionbudgets              pdb          policy/v1                              true         PodDisruptionBudget
clusterrolebindings                            rbac.authorization.k8s.io/v1           false        ClusterRoleBinding
clusterroles                                   rbac.authorization.k8s.io/v1           false        ClusterRole
rolebindings                                   rbac.authorization.k8s.io/v1           true         RoleBinding
roles                                          rbac.authorization.k8s.io/v1           true         Role
priorityclasses                   pc           scheduling.k8s.io/v1                   false        PriorityClass
csidrivers                                     storage.k8s.io/v1                      false        CSIDriver
csinodes                                       storage.k8s.io/v1                      false        CSINode
csistoragecapacities                           storage.k8s.io/v1                      true         CSIStorageCapacity
storageclasses                    sc           storage.k8s.io/v1                      false        StorageClass
volumeattachments                              storage.k8s.io/v1                      false        VolumeAttachment

Note that many API resource types have shortnames that you can use to speed up typing commands.

You can dig deeper into these API resources using the kubectl explain command, which serves as a great reference when creating manifests.

More information about deployments API resource, via the kubectl explain command:

kubectl explain deploy

Sample Output:

$ kubectl explain deploy

KIND:     Deployment
VERSION:  apps/v1

DESCRIPTION:
     Deployment enables declarative updates for Pods and ReplicaSets.

FIELDS:
   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec	<Object>
     Specification of the desired behavior of the Deployment.

   status	<Object>
     Most recently observed status of the Deployment.

Use kubectl get deploy to list all deployments:

kubectl get deploy

Sample Output:

$ kubectl get deploy

No resources found in default namespace.

You're not seeing any deployments because, without providing a namespace, you're only looking at the default namespace.

List all deployments in all namespaces:

kubectl get deploy -A

Sample Output:

$ kubectl get deploy -A

NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   calico-kube-controllers   1/1     1            1           6d23h
kube-system   coredns                   2/2     2            2           6d23h

You can see that the previous example shows two deployments in the the kube-system namespace.

Sometimes you want to see more than one API resource. You can do that, by separating the resources with commas, as shown in the following example.

List all deployments, replicasets and pods, in all namespaces:

kubectl get deploy,rs,pod -A

Sample Output:

$ kubectl get deploy,rs,pod -A

NAMESPACE     NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/calico-kube-controllers   1/1     1            1           6d23h
kube-system   deployment.apps/coredns                   2/2     2            2           6d23h

NAMESPACE     NAME                                                DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/calico-kube-controllers-57b57c56f   1         1         1       6d23h
kube-system   replicaset.apps/coredns-787d4945fb                  2         2         2       6d23h

NAMESPACE     NAME                                           READY   STATUS    RESTARTS   AGE
kube-system   pod/calico-kube-controllers-57b57c56f-4hvfl    1/1     Running   0          6d23h
kube-system   pod/calico-node-s28hb                          1/1     Running   0          6d23h
kube-system   pod/calico-node-tqb6g                          1/1     Running   0          6d23h
kube-system   pod/coredns-787d4945fb-cg5wh                   1/1     Running   0          6d23h
kube-system   pod/coredns-787d4945fb-xdbll                   1/1     Running   0          6d23h
kube-system   pod/etcd-control-plane-01                      1/1     Running   0          6d23h
kube-system   pod/kube-apiserver-control-plane-01            1/1     Running   0          6d23h
kube-system   pod/kube-controller-manager-control-plane-01   1/1     Running   0          6d23h
kube-system   pod/kube-proxy-blgcf                           1/1     Running   0          6d23h
kube-system   pod/kube-proxy-t9wb4                           1/1     Running   0          6d23h
kube-system   pod/kube-scheduler-control-plane-01            1/1     Running   0          6d23h

The previous example shows how you can neatly check on multiple API resource types in a single command.

Take some time, explore the kubectl command, the built-in help documentation, API resources and how to use the kubectl explain command as a resource.

AGAIN:

Adrien Trouillaud wrote an excellent Medium article, Imperative vs. Declarative โ€” a Kubernetes Tutorial which I discovered while researching this topic. Adrien's article, a comprehensive tutorial on how to leverage the imperative approach to creating objects in Kubernetes, clarified the topic for me. The article dates back to early 2019, so some of the syntax has changed, but the concepts in the article still ring true. I learned even more by digging into the commands and updating the syntax, where needed. I would highly recommend giving it a read.

Now that you've warmed up with some kubectl exercises, it's time to put kubectl to use.

Creating a Pod Imperatively Using the kubectl run Command

Kubernetes: Managing Kubernetes Objects Using Imperative Commands

Quite often, you just want to create a straightforward Kubernetes object, like a Pod, without having to write a manifest and feed it to Kubernetes. You can, using the kubectl command imperatively.

Say you've been presented with the following request:

"Create a single pod, named nginx-pod, using the image nginx:latest, in the imperative namespace, with port 80 exposed."

Create the nginx-pod imperatively:

kubectl run nginx-pod --image nginx:latest --namespace imperative --port=80

You will get the message Error from server (NotFound): namespaces "imperative" not found. You need to create the imperative namespace. This can also be done imperatively using kubectl create.

Create the imperative namespace imperatively:

kubectl create namespace imperative

You should see namespace/imperative created.

Try creating your Pod again. Create the nginx-pod imperatively:

kubectl run nginx-pod --image nginx:latest --namespace imperative --port=80

You should get pod/nginx-pod created.

Checking your work:

kubectl get pod --namespace imperative -o wide

Sample Output:

$ kubectl get pod --namespace imperative -o wide

NAME        READY   STATUS    RESTARTS   AGE   IP                NODE             NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          10s   192.168.126.201   worker-node-01   <none>           <none>

You can dig deeper and get more information on the Pod using the kubectl describe command.

More information on our pod:

kubectl describe pod nginx-pod --namespace imperative

Sample Output:

$ kubectl describe pod nginx-pod --namespace imperative

Name:             nginx-pod
Namespace:        imperative
Priority:         0
Service Account:  default
Node:             worker-node-01/10.0.1.204
Start Time:       Thu, 27 Apr 2023 18:49:16 +0000
Labels:           run=nginx-pod
Annotations:      cni.projectcalico.org/containerID: 69fa1b2e11018aa307d1ee64fd99c3ba6c1d91f0f74ffa0a40eb93c0560ae041
                  cni.projectcalico.org/podIP: 192.168.126.201/32
                  cni.projectcalico.org/podIPs: 192.168.126.201/32
Status:           Running
IP:               192.168.126.201
IPs:
  IP:  192.168.126.201
Containers:
  nginx-pod:
    Container ID:   containerd://e66a03ed5344e3c6927369774a35df446ee93c937ee038453afd5e297e79c5d7
    Image:          nginx:latest
    Image ID:       docker.io/library/nginx@sha256:63b44e8ddb83d5dd8020327c1f40436e37a6fffd3ef2498a6204df23be6e7e94
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 27 Apr 2023 18:49:18 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vbfgp (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-vbfgp:
    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  51s   default-scheduler  Successfully assigned imperative/nginx-pod to worker-node-01
  Normal  Pulling    50s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     50s   kubelet            Successfully pulled image "nginx:latest" in 399.613484ms (399.621888ms including waiting)
  Normal  Created    50s   kubelet            Created container nginx-pod
  Normal  Started    49s   kubelet            Started container nginx-pod

Using kubectl describe provides you with a thorough description of the Pod.

Kubernetes reports a good status for our nginx-pod Pod. Let's look at it from another angle. Use the curl command to test the NGINX server in your Pod.

Test using curl, replace with your Pod's IP address:

curl http://<POD_IP>

Sample Output:

$ curl http://192.168.126.201

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

The NGINX web server in our nginx-pod Pod responds with the default web page. Everything appears to be working as expected.

What if you want to use kubectl imperatively, but want to generate a declarative manifest and not immediately create the objects in Kubernetes?

Let's take a look at how you can use the kubectl command imperatively to create manifests!

Generating a Namespace Manifest Using the kubectl create namespace Command

You created your imperative Namespace to hold the objects you want to create imperatively, using kubectl. Now, you're going to start creating objects declarively, and you're going to put those into the declarative Namespace.

Creating a Namespace provides a great example of how you can leverage the imperative to create the declarative. You can use the imperative command kubectl create namespace declarative with the --dry-run=client and --output=yaml swiches, and redirect the output into a file.

Create the declarative Namespace:

kubectl create namespace declarative --dry-run=client --output=yaml > declarative-ns.yaml

Checking your work:

cat declarative-ns.yaml

Sample Output:

$ cat declarative-ns.yaml

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: declarative
spec: {}
status: {}

You will get a file named declarative-ns.yaml with the manifest for the declarative Namespace.

Now, let's use the declarative-ns.yaml manifest to create our Namespace:

kubectl create -f declarative-ns.yaml

Sample Output:

$ kubectl create -f declarative-ns.yaml

namespace/declarative created

Checking your work:

kubectl get ns

Sample Output:

$ kubectl get ns

NAME              STATUS   AGE
declarative       Active   23s
default           Active   7d3h
imperative        Active   5m7s
kube-node-lease   Active   7d3h
kube-public       Active   7d3h
kube-system       Active   7d3h

You've created the declarative Namespace, declaratively!

Let's try it with a Pod.

Generating a Pod Manifest Using the kubectl run Command

Kubernetes: Managing Kubernetes Objects Using Imperative Commands

Say you've been presented with the following request:

"Create a manifest for a single Pod, named nginx-pod, using the image nginx:latest, in the declarative namespace, with port 80 exposed."

You can use the imperative command kubectl run nginx-pod with the --dry-run=client and --output=yaml swiches, and redirect the output into a file, like you did when you created the declarative Namespace.

Create the nginx-pod.yaml manifest file:

kubectl run nginx-pod --image nginx:latest --namespace declarative --port=80 --dry-run=client --output=yaml > nginx-pod.yaml

Checking your work:

cat nginx-pod.yaml

Sample Output:

$ cat nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx-pod
  name: nginx-pod
  namespace: declarative
spec:
  containers:
  - image: nginx:latest
    name: nginx-pod
    ports:
    - containerPort: 80
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

You have a Pod manifest!

Create the Pod, using the manifest:

kubectl create -f nginx-pod.yaml

You should get pod/nginx-pod created.

Checking your work:

kubectl get pod --namespace declarative -o wide

Sample Output:

$ kubectl get pod --namespace declarative -o wide

NAME        READY   STATUS    RESTARTS   AGE   IP                NODE             NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          13s   192.168.126.202   worker-node-01   <none>           <none>

Kubernetes reports the status of our nginx-pod pod as Running. Let's look at it from another angle. Use the curl command to test the NGINX server in your pod.

Test using curl, replace with your pod's IP address:

curl http://<POD_IP>

Sample Output:

$ curl http://192.168.126.202

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

The NGINX web server in our nginx-pod Pod responds with the default web page. Everything appears to be working as expected.

You created a Pod manifest, quickly and easily, using the kubectl command! Let's build on this and try a Deployment.

Creating Deployment Manifests Using the kubectl create deploy Command

Kubernetes: Deployments

Kubernetes: ReplicaSet

A more typical way to manage Pods uses ReplicaSets, managed by Deployments. This approach gives you more control over scaling, upgrades and more. As the complexity and number of objects increases, manifests get larger. Using the imperative to declarative approach to create manifests becomes very attractive here.

To create a Deployment imperatively, use the kubectl create deploy command:

kubectl create deploy --help

Sample Output:

$ kubectl create deploy --help

Create a deployment with the specified name.

Aliases:
deployment, deploy

Examples:
  # Create a deployment named my-dep that runs the busybox image
  kubectl create deployment my-dep --image=busybox

  # Create a deployment with a command
  kubectl create deployment my-dep --image=busybox -- date

  # Create a deployment named my-dep that runs the nginx image with 3 replicas
  kubectl create deployment my-dep --image=nginx --replicas=3

  # Create a deployment named my-dep that runs the busybox image and expose port
5701
  kubectl create deployment my-dep --image=busybox --port=5701

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.

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

    --image=[]:
	Image names to run.

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

    --port=-1:
	The port that this container exposes.

    -r, --replicas=1:
	Number of replicas to create. Default is 1.

    --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.

    --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.

Usage:
  kubectl create deployment NAME --image=image -- [COMMAND] [args...] [options]

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

Say you've been presented with the following request, for a new Namespace:

Create a YAML manifest for a Namespace, named my-nginx-namespace in a file named my-nginx-namespace.yaml.

Create the my-nginx-deployment namespace manifest:

kubectl create namespace my-nginx-namespace --dry-run=client --output=yaml > my-nginx-namespace.yaml

Checking your work:

cat my-nginx-namespace.yaml

Sample Output:

$ cat my-nginx-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: my-nginx-namespace
spec: {}
status: {}

You now have a manifest for the my-nginx-namespace Namespace. You're going to hold on to this for a minute.

Say you've also been presented with the following request, for a new Deployment:

Create a YAML manifest for a Deployment, named my-nginx-deployment, using the nginx-latest container image, in the my-nginx-namespace namespace, with 3 replicas, exposing port 80, in a file named my-nginx-deployment.yaml.

Create the my-nginx-deployment Deployment manifest:

kubectl create deployment my-nginx-deployment --image=nginx:latest --namespace my-nginx-namespace --replicas=3 --port=80 --dry-run=client --output=yaml > my-nginx-deployment.yaml

Checking your work:

cat my-nginx-deployment.yaml

Sample Output:

$ cat my-nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: my-nginx-deployment
  name: my-nginx-deployment
  namespace: my-nginx-namespace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx-deployment
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: my-nginx-deployment
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
        resources: {}
status: {}

You now have a manifest for the my-nginx-deployment Deployment. You can now deploy your Namespace and Deployment manifests to Kubernetes.

Deploy the Namespace, then the Deployment manifest:

kubectl create -f my-nginx-namespace.yaml ; kubectl create -f my-nginx-deployment.yaml

Sample Output:

$ kubectl create -f my-nginx-namespace.yaml ; kubectl create -f my-nginx-deployment.yaml

namespace/my-nginx-namespace created
deployment.apps/my-nginx-deployment created

Checking your work:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          55s
pod/my-nginx-deployment-9cbcd46b4-7nmn8   1/1     Running   0          55s
pod/my-nginx-deployment-9cbcd46b4-xt89j   1/1     Running   0          55s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   3/3     3            3           55s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   3         3         3       55s

You can see that you have a total of three Pods (replica 3), managed by a Replica set, managed by a Deployment. Everything lives in the my-nginx-namespace Namespace. Check the labels on your Pods.

Show Pod labels for all Pods in the my-nginx-namespace Namespace:

kubectl get pods -o wide -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get pods -o wide -n my-nginx-namespace --show-labels
NAME                                  READY   STATUS    RESTARTS   AGE   IP                NODE               NOMINATED NODE   READINESS GATES   LABELS
my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          20h   192.168.173.196   control-plane-01   <none>           <none>            app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-7nmn8   1/1     Running   0          20h   192.168.126.204   worker-node-01     <none>           <none>            app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-xt89j   1/1     Running   0          20h   192.168.126.203   worker-node-01     <none>           <none>            app=my-nginx-deployment,pod-template-hash=9cbcd46b4

You can see that all the Pods have the app=my-nginx-deployment label applied, by the Deployment.

Test using curl, replace with any of your three pods; IP addresses:

curl http://<POD_IP>

Sample Output:

$ curl http://192.168.126.203

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Repeat as desired, with the other IP addresses.

The NGINX web servers in our my-nginx-deployment Pods respond with the default web page. Everything appears to be working as expected with our my-nginx-deployment deployment.

Wouldn't it be nice if you didn't have to access the NGINX server pods by a bunch of individual IP addresses? You can, adding a Service to direct traffic to your Pods!

Let's see how you can create a manifest for a Service, imperatively!

Creating a Service Manifest Using the kubectl Command

Kubernetes: Service

Kubernetes: Use a Service to Access an Application in a Cluster

Kubernetes: Managing Kubernetes Objects Using Imperative Commands

In order to simplify access to the Pods in our my-nginx-deployment Deployment, we're going to create a Service:

Create a YAML manifest for a Service, named my-nginx-service, of type clusterip, in the my-nginx-namespace namespace, exposed on port 8888, in a file named my-nginx-service.yaml. Use the app=my-nginx-deployment label as a Selector for your Service.

This request has two parts:

  • Create the Service manifest (kubectl create service clusterip)
  • Add a Selector to the Service manifest (kubectl set selector)

The Pods have been labeled with the app=my-nginx-deployment label, so you can use that as a Selector for your Service.

Before you get started, take an inventory of the Services on your cluster.

List all Services:

kubectl get service -A

Sample Output:

$ kubectl get service -A

NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  7d4h
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   7d4h

Let's take a look at those commands.

The kubectl create service Command

You can use the kubectl create service command to create a Service manifest.

Take a look at the help information for the kubectl create service command:

kubectl create service --help

Sample Output:

$ kubectl create service --help

Create a service using a specified subcommand.

Aliases:
service, svc

Available Commands:
  clusterip      Create a ClusterIP service
  externalname   Create an ExternalName service
  loadbalancer   Create a LoadBalancer service
  nodeport       Create a NodePort service

Usage:
  kubectl create service [flags] [options]

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

You'll have to specify a Service type of:

  • ClusterIP
  • ExternalName
  • LoadBalancer
  • NodePort

We're going to create a ClusterIP Service. Let's take a closer look at the kubectl create service clusterip command.

Help information on the kubectl create service clusterip command:

kubectl create service clusterip --help

Sample Output:

$ kubectl create service clusterip --help

Create a ClusterIP service with the specified name.

Examples:
  # Create a new ClusterIP service named my-cs
  kubectl create service clusterip my-cs --tcp=5678:8080

  # Create a new ClusterIP service named my-cs (in headless mode)
  kubectl create service clusterip my-cs --clusterip="None"

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.

    --clusterip='':
	Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).

    --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-create':
	Name of the manager used to track field ownership.

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

    --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.

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

    --tcp=[]:
	Port pairs can be specified as '<port>:<targetPort>'.

    --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.

Usage:
  kubectl create service clusterip NAME [--tcp=<port>:<targetPort>] [--dry-run=server|client|none] [options]

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

The kubectl set selector Command

We're going to use the app=my-nginx-deployment label as a Selector to tell the Service which Pods to send the traffic to.

Help information on the kubectl set selector command:

kubectl set selector --help

Sample Output:

$ kubectl set selector --help

Set the selector on a resource. Note that the new selector will overwrite the old selector if the resource had one prior to the invocation of 'set selector'.

 A selector must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters. If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. Note: currently selectors can only be set on Service objects.

Examples:
  # Set the labels and selector before creating a deployment/service pair
  kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run=client | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f -
  kubectl create deployment my-dep -o yaml --dry-run=client | kubectl label --local -f - environment=qa -o yaml | kubectl create -f -

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.

    --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-set':
	Name of the manager used to track field ownership.

    -f, --filename=[]:
	identifying the resource.

    --local=false:
	If true, annotation will NOT contact api-server but run locally.

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

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

    --resource-version='':
	If non-empty, the selectors update will only succeed if this is the current resource-version for the object.
	Only valid when specifying a single resource.

    --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].

Usage:
  kubectl set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version] [options]

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

So, how do we put these two commands together?

Creating a Service Manifest Using the kubectl create service and kubectl set selector Commands

In order to simplify access to the Pods in our my-nginx-deployment Deployment, we're going to create a Service:

Create a YAML manifest for a Service, named my-nginx-service, of type clusterip, in the my-nginx-namespace namespace, exposed on port 8888, in a file named my-nginx-service.yaml. Use the app=my-nginx-deployment label as a Selector for your Service.

This request has two parts:

  • Create the Service manifest
  • Add a Selector to the Service manifest

You can do this by using an imperative kubectl create service clusterip command to create the Service, then pipe the output of that command (the YAML Service manifest) into the kubectl set selector command to add the app=my-nginx-deployment selector to the manifest, then redirect that output to a file named my-nginx-service.yaml.

The Pods have been labeled with the app=my-nginx-deployment label, so you can use that as a Selector for your Service.

Let's give it a try!

Create the Service manifest and add the Selector:

kubectl create service clusterip my-nginx-service --tcp=8888:80 --namespace my-nginx-namespace --dry-run=client --output=yaml | kubectl set selector --local -f - 'app=my-nginx-deployment' --output=yaml > my-nginx-service.yaml

Checking your work:

cat my-nginx-service.yaml

Sample Output:

$ cat my-nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: my-nginx-service
  name: my-nginx-service
  namespace: my-nginx-namespace
spec:
  ports:
  - name: 8888-80
    port: 8888
    protocol: TCP
    targetPort: 80
  selector:
    app: my-nginx-deployment
  type: ClusterIP
status:
  loadBalancer: {}

So, in one command, we created the Service manifest (kubectl create service clusterip my-nginx-service --tcp=8888:80 --namespace my-nginx-namespace --dry-run=client --output=yaml), added the Selector (kubectl set selector --local -f - 'app=my-nginx-deployment' --output=yaml), as shown below, and wrote this manifest to a file (my-nginx-service.yaml).

Selector:

  selector:
    app: my-nginx-deployment

Now that you have a Service manifest, you're ready to create your Service.

Create the my-nginx-service Service from the manifest file:

kubectl create -f my-nginx-service.yaml

Sample Output:

$ kubectl create -f my-nginx-service.yaml

service/my-nginx-service created

Checking your work:

kubectl get service -A

Sample Output:

$ kubectl get service -A
NAMESPACE            NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default              kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP                  8d
kube-system          kube-dns           ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   8d
my-nginx-namespace   my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP                 6s

You can see the my-nginx-service Service, it's IP address and that it's available on port 8888. Let's take a look at everything in the my-nginx-namespace Namespace.

List all objects in the my-nginx-namespace Namespace:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          20h
pod/my-nginx-deployment-9cbcd46b4-7nmn8   1/1     Running   0          20h
pod/my-nginx-deployment-9cbcd46b4-xt89j   1/1     Running   0          20h

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   3m35s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   3/3     3            3           20h

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   3         3         3       20h

You can see the my-nginx-service Service alongside the Deployment, ReplicaSet and the three Pods. Let's see if the Service works.

Test using curl, via the Service IP address and port:

curl http://<SVC_IP>:<SVC_PORT>

Sample Output:

$ curl http://10.111.212.138:8888

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

It works! Now you can access the NGINX web servers in your Pods via a single IP address and port.

Scaling a Deployment/ReplicaSet Using the kubectl scale Command

Kubernetes: ReplicaSet

Kubernetes: Deployments

Managing Pods via ReplicaSets and Deployments enables scaling up and down with ease. Let's take a look at how it works!

Say you get the following request:

Scale the my-nginx-deployment from 3 Pod replicas to 10 replicas.

Let's confirm the current state of the ReplicaSet for your Deployment.

List ReplicaSets in the my-nginx-namespace Namespace:

kubectl get rs -n my-nginx-namespace

Sample Output:

$ kubectl get rs -n my-nginx-namespace

NAME                            DESIRED   CURRENT   READY   AGE
my-nginx-deployment-9cbcd46b4   3         3         3       21h

Show more detail on the ReplicaSet:

kubectl describe rs <YOUR_REPLICA_SET> -n my-nginx-namespace

Sample Output:

$ kubectl describe rs my-nginx-deployment-9cbcd46b4 -n my-nginx-namespace

Name:           my-nginx-deployment-9cbcd46b4
Namespace:      my-nginx-namespace
Selector:       app=my-nginx-deployment,pod-template-hash=9cbcd46b4
Labels:         app=my-nginx-deployment
                pod-template-hash=9cbcd46b4
Annotations:    deployment.kubernetes.io/desired-replicas: 3
                deployment.kubernetes.io/max-replicas: 4
                deployment.kubernetes.io/revision: 1
Controlled By:  Deployment/my-nginx-deployment
Replicas:       3 current / 3 desired
Pods Status:    3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=my-nginx-deployment
           pod-template-hash=9cbcd46b4
  Containers:
   nginx:
    Image:        nginx:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:           <none>

By using kubectl describe, you get a summary of all the ReplicaSet's important information. Let's take a look at the my-nginx-namespace Namespace.

Show all the objects in the my-nginx-namespace Namespace:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          21h
pod/my-nginx-deployment-9cbcd46b4-7nmn8   1/1     Running   0          21h
pod/my-nginx-deployment-9cbcd46b4-xt89j   1/1     Running   0          21h

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   22m

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   3/3     3            3           21h

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   3         3         3       21h

There are currently three replicas of our Deployment's Pods. What if we wanted to change that? We can adjust the number of Pod replicas using the kubectl scale command.

Retrieve information on the kubectl scale command:

kubectl scale --help

Sample Output:

$ kubectl scale --help

Set a new size for a deployment, replica set, replication controller, or stateful set.

 Scale also allows users to specify one or more preconditions for the scale action.

 If --current-replicas or --resource-version is specified, it is validated before the scale is attempted, and it is
guaranteed that the precondition holds true when the scale is sent to the server.

Examples:
  # Scale a replica set named 'foo' to 3
  kubectl scale --replicas=3 rs/foo

  # Scale a resource identified by type and name specified in "foo.yaml" to 3
  kubectl scale --replicas=3 -f foo.yaml

  # If the deployment named mysql's current size is 2, scale mysql to 3
  kubectl scale --current-replicas=2 --replicas=3 deployment/mysql

  # Scale multiple replication controllers
  kubectl scale --replicas=5 rc/foo rc/bar rc/baz

  # Scale stateful set named 'web' to 3
  kubectl scale --replicas=3 statefulset/web

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.

    --current-replicas=-1:
	Precondition for current size. Requires that the current size of the resource match this value in order to
	scale. -1 (default) for no condition.

    --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.

    -f, --filename=[]:
	Filename, directory, or URL to files identifying the resource to set a new size

    -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).

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

    --replicas=0:
	The new desired number of replicas. Required.

    --resource-version='':
	Precondition for resource version. Requires that the current resource version match this value in order to
	scale.

    -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].

    --timeout=0s:
	The length of time to wait before giving up on a scale operation, zero means don't wait. Any other values
	should contain a corresponding time unit (e.g. 1s, 2m, 3h).

Usage:
  kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
[options]

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

Let's see what happens when we scale our ReplicaSet to ten replicas, imperatively.

Scale ReplicaSet to ten replicas:

kubectl scale --replicas=10 rs <YOUR_REPLICA_SET>

Sample Output:

$ kubectl get rs -n my-nginx-namespace
NAME                            DESIRED   CURRENT   READY   AGE
my-nginx-deployment-9cbcd46b4   3         3         3       21h

Why isn't the ReplicaSet scaling? Because the Deployment manages the ReplicaSet. We need to scale the Deployment, not the ReplicaSet. Once we issue the command to scale, the Deployment overrides our request, keeping the replica count at three. Let's try scaling the Deployment, imperatively.

Scale Deployment to ten replicas:

kubectl scale --replicas=10 deployment my-nginx-deployment -n my-nginx-namespace

Sample Output:

$ kubectl scale --replicas=10 deployment my-nginx-deployment -n my-nginx-namespace

deployment.apps/my-nginx-deployment scaled

Now that we've scaled our Deployment, let's take a look at the my-nginx-namespace Namespace again.

Show all the objects in the my-nginx-namespace Namespace:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          21h
pod/my-nginx-deployment-9cbcd46b4-4hwxb   1/1     Running   0          5m22s
pod/my-nginx-deployment-9cbcd46b4-7fdwm   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-8hczb   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-dv572   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-lgvk7   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-v9d9w   1/1     Running   0          29s
pod/my-nginx-deployment-9cbcd46b4-xt89j   1/1     Running   0          21h

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   36m

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   10/10   10           10          21h

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      21h

Congratulations! You've scaled your Deployment to ten replicas, imperatively. This works just fine, but what happens if you come back and re-apply your Deployment manifest?

Re-apply Depolyment manifest:

kubectl apply -f my-nginx.deployment.yaml

Sample Output:

$ kubectl apply -f my-nginx-deployment.yaml

deployment.apps/my-nginx-deployment configured

Now that you've re-applied your Deployment manifest, take a look at the my-nginx-namespace Namespace.

Show all the objects in the my-nginx-namespace Namespace:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS        RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running       0          21h
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running       0          117s
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running       0          117s

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   38m

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   3/3     3            3           21h

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   3         3         3       21h

You're back to three Pod replicas, as you would expect. Checking the Deployment manifest confirms this.

Check the number of replicas in the Deployment manifest:

grep -i replica my-nginx-deployment.yaml

Sample Output:

$ grep -i replica my-nginx-deployment.yaml

  replicas: 3

Let's change the number of replicas in the Deployment manifest, using the sed command. We'll replace the string replicas: 3 with the string replicas: 10. You could also use your favorite editor to make the edit in your manifest.

Change the replicas string with sed:

sed -i 's/replicas\:\ 3/replicas\:\ 10/g' my-nginx-deployment.yaml

Checking your work:

grep -i replica my-nginx-deployment.yaml

Sample Output:

$ grep -i replica my-nginx-deployment.yaml

  replicas: 10

Now that you've changed the number of replicas in your manifest, apply your changes.

Apply the mainfest changes:

kubectl apply -f my-nginx-deployment.yaml

Sample Output:

$ kubectl apply -f my-nginx-deployment.yaml

deployment.apps/my-nginx-deployment configured

Checking your work:

kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl get all -n my-nginx-namespace

NAME                                      READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          21h
pod/my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          8m8s
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          8m8s
pod/my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          23s
pod/my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          23s

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   44m

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx-deployment   10/10   10           10          21h

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      21h

You can see the Deployment has been scaled to ten replicas. Let's verify the functionality of our Service using curl.

Checking the my-nginx-service, using curl:

curl http://<SVC_IP>:<SVC_PORT>

Sample Output:

$ curl http://10.111.212.138:8888

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Everything's working!

Scaling our deployment, both imperatively and declaratively makes managing our Deployment fast and easy!

Adding Labels to Kubernetes Objects Using the kubectl label Command

Kubernetes: Labels and Selectors

Labels and Selectors play an important role in Kubernetes, so be sure to read the Labels and Selectors documentation and know the things of value contained within.

Let's take a look at some of the ways we can work with Labels. You should be able to identify the labels applied to an object. A good example of this can be demonstrated by examining the labels on out Pods.

Show labels on pods in the my-nginx-namespace namespace:

kubectl get pods -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get pods -n my-nginx-namespace --show-labels
NAME                                  READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          22h   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          89m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          89m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          81m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

You can use the kubectl label command to manipulate labels on Kubernetes resources.

Show help information for kubectl label:

kubectl label --help

Sample Output:

$ kubectl label --help

Update the labels on a resource.

  *  A label key and value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and
underscores, up to 63 characters each.
  *  Optionally, the key can begin with a DNS subdomain prefix and a single '/', like example.com/my-app.
  *  If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will
result in an error.
  *  If --resource-version is specified, then updates will use this resource version, otherwise the existing
resource-version will be used.

Examples:
  # Update pod 'foo' with the label 'unhealthy' and the value 'true'
  kubectl label pods foo unhealthy=true

  # Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value
  kubectl label --overwrite pods foo status=unhealthy

  # Update all pods in the namespace
  kubectl label pods --all status=unhealthy

  # Update a pod identified by the type and name in "pod.json"
  kubectl label -f pod.json status=unhealthy

  # Update pod 'foo' only if the resource is unchanged from version 1
  kubectl label pods foo status=unhealthy --resource-version=1

  # Update pod 'foo' by removing a label named 'bar' if it exists
  # Does not require the --overwrite flag
  kubectl label pods foo bar-

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

    -A, --all-namespaces=false:
	If true, check the specified action in all namespaces.

    --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.

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

    --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=[]:
	Filename, directory, or URL to files identifying the resource to update the labels

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

    --list=false:
	If true, display the labels for a given resource.

    --local=false:
	If true, label will NOT contact api-server but run locally.

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

    --overwrite=false:
	If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.

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

    --resource-version='':
	If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only
	valid when specifying a single resource.

    -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].

Usage:
  kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]
[options]

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

So, if you wanted to add a label of type=webserver to all the Pods in the my-nginx-namespace Namespace, you would use the following example.

Label Pods:

kubectl label pods --all type=webserver -n my-nginx-namespace

Sample Output:

$ kubectl label pods --all type=webserver -n my-nginx-namespace

pod/my-nginx-deployment-9cbcd46b4-42n2q labeled
pod/my-nginx-deployment-9cbcd46b4-6hlwl labeled
pod/my-nginx-deployment-9cbcd46b4-7t2fr labeled
pod/my-nginx-deployment-9cbcd46b4-bls2n labeled
pod/my-nginx-deployment-9cbcd46b4-f4lkn labeled
pod/my-nginx-deployment-9cbcd46b4-mxxbl labeled
pod/my-nginx-deployment-9cbcd46b4-nq7xw labeled
pod/my-nginx-deployment-9cbcd46b4-smcv6 labeled
pod/my-nginx-deployment-9cbcd46b4-sz27h labeled
pod/my-nginx-deployment-9cbcd46b4-v8bp5 labeled

Checking your work:

kubectl get pods -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get pods -n my-nginx-namespace --show-labels

NAME                                  READY   STATUS    RESTARTS   AGE    LABELS
my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          106m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          106m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          98m    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver

You can see the Pods now have an additional label of type=webserver. It's relatively straightforward to add labels, but how do you remove a label? You use the same command, but specify the label, without the value, with a - appended, like the following example.

Remove the type=webserver labels:

kubectl label pods --all type- -n my-nginx-namespace

Sample Output:

$ kubectl label pods --all type- -n my-nginx-namespace

pod/my-nginx-deployment-9cbcd46b4-42n2q unlabeled
pod/my-nginx-deployment-9cbcd46b4-6hlwl unlabeled
pod/my-nginx-deployment-9cbcd46b4-7t2fr unlabeled
pod/my-nginx-deployment-9cbcd46b4-bls2n unlabeled
pod/my-nginx-deployment-9cbcd46b4-f4lkn unlabeled
pod/my-nginx-deployment-9cbcd46b4-mxxbl unlabeled
pod/my-nginx-deployment-9cbcd46b4-nq7xw unlabeled
pod/my-nginx-deployment-9cbcd46b4-smcv6 unlabeled
pod/my-nginx-deployment-9cbcd46b4-sz27h unlabeled
pod/my-nginx-deployment-9cbcd46b4-v8bp5 unlabeled

Checking your work:

kubectl get pods -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get pods -n my-nginx-namespace --show-labels

NAME                                  READY   STATUS    RESTARTS   AGE    LABELS
my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          102m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

You can see the type=webserver labels have been removed from the Pods. How do you examine the labels on other resources? Let's take a look!

Show the labels on all the objects in the my-nginx-namespace Namespace:

kubectl get all -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get all -n my-nginx-namespace --show-labels

NAME                                      READY   STATUS    RESTARTS   AGE    LABELS
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          113m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          113m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          105m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE    LABELS
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   149m   app=my-nginx-service

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/my-nginx-deployment   10/10   10           10          23h   app=my-nginx-deployment

NAME                                            DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      23h   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

Everything has the app=my-nginx-deployment label, except for the Service, which has the app=my-nginx-service label.

You can apply labels to other resources, like Deployments. Let's try it with your Deployment.

Label deployment:

kubectl label deploy my-nginx-deployment type=webserver -n my-nginx-namespace

Sample Output:

$ kubectl label deploy my-nginx-deployment type=webserver -n my-nginx-namespace

deployment.apps/my-nginx-deployment labeled

Checking your work:

kubectl get all -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get all -n my-nginx-namespace --show-labels

NAME                                      READY   STATUS    RESTARTS   AGE    LABELS
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          115m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          115m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          107m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE    LABELS
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   151m   app=my-nginx-service

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/my-nginx-deployment   10/10   10           10          23h   app=my-nginx-deployment,type=webserver

NAME                                            DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      23h   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

You can see the type=webserver label has been applied to the Deployment. Let's add the label to the rest of the items in the Namespace.

Label Pods and ReplicaSets in my-nginx-namespace:

kubectl label pods,rs --all type=webserver -n my-nginx-namespace

Sample Output:

$ kubectl label pods,rs --all type=webserver -n my-nginx-namespace

pod/my-nginx-deployment-9cbcd46b4-42n2q labeled
pod/my-nginx-deployment-9cbcd46b4-6hlwl labeled
pod/my-nginx-deployment-9cbcd46b4-7t2fr labeled
pod/my-nginx-deployment-9cbcd46b4-bls2n labeled
pod/my-nginx-deployment-9cbcd46b4-f4lkn labeled
pod/my-nginx-deployment-9cbcd46b4-mxxbl labeled
pod/my-nginx-deployment-9cbcd46b4-nq7xw labeled
pod/my-nginx-deployment-9cbcd46b4-smcv6 labeled
pod/my-nginx-deployment-9cbcd46b4-sz27h labeled
pod/my-nginx-deployment-9cbcd46b4-v8bp5 labeled
replicaset.apps/my-nginx-deployment-9cbcd46b4 labeled

Checking your work:

kubectl get all -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get all -n my-nginx-namespace --show-labels
NAME                                      READY   STATUS    RESTARTS   AGE    LABELS
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          117m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          117m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver
pod/my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          110m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE    LABELS
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   154m   app=my-nginx-service

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/my-nginx-deployment   10/10   10           10          23h   app=my-nginx-deployment,type=webserver

NAME                                            DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      23h   app=my-nginx-deployment,pod-template-hash=9cbcd46b4,type=webserver

Everything in the my-nginx-namespace Namespace now has the type=webserver label. How can you remove the label? Just like before, specify the label name without the value, with a - following the label.

Remove the label from all Pods, ReplicaSets and Deployments in my-nginx-namespace:

kubectl label pods,rs,deploy --all type- -n my-nginx-namespace

Sample Output:

$ kubectl label pods,rs,deploy --all type- -n my-nginx-namespace

pod/my-nginx-deployment-9cbcd46b4-42n2q unlabeled
pod/my-nginx-deployment-9cbcd46b4-6hlwl unlabeled
pod/my-nginx-deployment-9cbcd46b4-7t2fr unlabeled
pod/my-nginx-deployment-9cbcd46b4-bls2n unlabeled
pod/my-nginx-deployment-9cbcd46b4-f4lkn unlabeled
pod/my-nginx-deployment-9cbcd46b4-mxxbl unlabeled
pod/my-nginx-deployment-9cbcd46b4-nq7xw unlabeled
pod/my-nginx-deployment-9cbcd46b4-smcv6 unlabeled
pod/my-nginx-deployment-9cbcd46b4-sz27h unlabeled
pod/my-nginx-deployment-9cbcd46b4-v8bp5 unlabeled
replicaset.apps/my-nginx-deployment-9cbcd46b4 unlabeled
deployment.apps/my-nginx-deployment unlabeled

Checking your work:

kubectl get all -n my-nginx-namespace --show-labels

Sample Output:

$ kubectl get all -n my-nginx-namespace --show-labels

NAME                                      READY   STATUS    RESTARTS   AGE    LABELS
pod/my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          23h    app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          120m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          120m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4
pod/my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          112m   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE    LABELS
service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP   156m   app=my-nginx-service

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/my-nginx-deployment   10/10   10           10          23h   app=my-nginx-deployment

NAME                                            DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/my-nginx-deployment-9cbcd46b4   10        10        10      23h   app=my-nginx-deployment,pod-template-hash=9cbcd46b4

The type=webserver label has been removed from everything in the my-nginx-namespace Namespace.

You can apply labels to non-namespaced resources, like nodes. Let's take a look at the labels on your nodes.

Show labels on nodes:

kubectl get nodes --show-labels

Sample Output:

$ kubectl get nodes --show-labels

NAME               STATUS   ROLES           AGE   VERSION   LABELS
control-plane-01   Ready    control-plane   8d    v1.26.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=control-plane-01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
worker-node-01     Ready    <none>          8d    v1.26.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker-node-01,kubernetes.io/os=linux

You can see some standard labels Kubernetes has applied to our nodes. If you want to add labels to the nodes, it's just like adding labels to other resources.

Again, labels and Selectors play an important role in Kubernetes, so be sure to read the Labels and Selectors documentation and know the things of value contained within.

Checking Logs Using kubectl logs

Kubernetes: Logging Architecture

Help information for kubectl logs:

kubectl logs --help

Sample Output:

$ kubectl logs --help

Print the logs for a container in a pod or specified resource. If the pod has only one container, the container name is
optional.

Examples:
  # Return snapshot logs from pod nginx with only one container
  kubectl logs nginx

  # Return snapshot logs from pod nginx with multi containers
  kubectl logs nginx --all-containers=true

  # Return snapshot logs from all containers in pods defined by label app=nginx
  kubectl logs -l app=nginx --all-containers=true

  # Return snapshot of previous terminated ruby container logs from pod web-1
  kubectl logs -p -c ruby web-1

  # Begin streaming the logs of the ruby container in pod web-1
  kubectl logs -f -c ruby web-1

  # Begin streaming the logs from all containers in pods defined by label app=nginx
  kubectl logs -f -l app=nginx --all-containers=true

  # Display only the most recent 20 lines of output in pod nginx
  kubectl logs --tail=20 nginx

  # Show all logs from pod nginx written in the last hour
  kubectl logs --since=1h nginx

  # Show logs from a kubelet with an expired serving certificate
  kubectl logs --insecure-skip-tls-verify-backend nginx

  # Return snapshot logs from first container of a job named hello
  kubectl logs job/hello

  # Return snapshot logs from container nginx-1 of a deployment named nginx
  kubectl logs deployment/nginx -c nginx-1

Options:
    --all-containers=false:
	Get all containers' logs in the pod(s).

    -c, --container='':
	Print the logs of this container

    -f, --follow=false:
	Specify if the logs should be streamed.

    --ignore-errors=false:
	If watching / following pod logs, allow for any errors that occur to be non-fatal

    --insecure-skip-tls-verify-backend=false:
	Skip verifying the identity of the kubelet that logs are requested from.  In theory, an attacker could provide
	invalid log content back. You might want to use this if your kubelet serving certificates have expired.

    --limit-bytes=0:
	Maximum bytes of logs to return. Defaults to no limit.

    --max-log-requests=5:
	Specify maximum number of concurrent logs to follow when using by a selector. Defaults to 5.

    --pod-running-timeout=20s:
	The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one pod is running

    --prefix=false:
	Prefix each log line with the log source (pod name and container name)

    -p, --previous=false:
	If true, print the logs for the previous instance of the container in a pod if it exists.

    -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.

    --since=0s:
	Only return logs newer than a relative duration like 5s, 2m, or 3h. Defaults to all logs. Only one of
	since-time / since may be used.

    --since-time='':
	Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be
	used.

    --tail=-1:
	Lines of recent log file to display. Defaults to -1 with no selector, showing all log lines otherwise 10, if a
	selector is provided.

    --timestamps=false:
	Include timestamps on each line in the log output

Usage:
  kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]

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

List Pods in my-nginx-namespace:

kubectl get pods -n my-nginx-namespace

Sample Output:

$ kubectl get pods -n my-nginx-namespace
NAME                                  READY   STATUS    RESTARTS   AGE
my-nginx-deployment-9cbcd46b4-42n2q   1/1     Running   0          24h
my-nginx-deployment-9cbcd46b4-6hlwl   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-7t2fr   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-bls2n   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-f4lkn   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-mxxbl   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-nq7xw   1/1     Running   0          164m
my-nginx-deployment-9cbcd46b4-smcv6   1/1     Running   0          164m
my-nginx-deployment-9cbcd46b4-sz27h   1/1     Running   0          156m
my-nginx-deployment-9cbcd46b4-v8bp5   1/1     Running   0          156m

Checking Pod logs for the my-nginx-deployment-9cbcd46b4-42n2q Pod:

kubectl logs my-nginx-deployment-9cbcd46b4-42n2q -n my-nginx-namespace

Sample Output:

$ kubectl logs my-nginx-deployment-9cbcd46b4-42n2q -n my-nginx-namespace

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/04/27 19:19:20 [notice] 1#1: using the "epoll" event method
2023/04/27 19:19:20 [notice] 1#1: nginx/1.23.4
2023/04/27 19:19:20 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2023/04/27 19:19:20 [notice] 1#1: OS: Linux 5.15.0-69-generic
2023/04/27 19:19:20 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/04/27 19:19:20 [notice] 1#1: start worker processes
2023/04/27 19:19:20 [notice] 1#1: start worker process 29
2023/04/27 19:19:20 [notice] 1#1: start worker process 30
10.0.1.132 - - [27/Apr/2023:19:25:37 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
10.0.1.132 - - [28/Apr/2023:16:01:12 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
kubectl logs -f -l app=my-nginx-deployment --all-containers=true -n my-nginx-namespace --max-log-requests 10

Transition

Exporting Running Kubernetes Objects to a Manifest Using the kubectl get Command

kubectl get deploy my-nginx-deployment -n my-nginx-namespace -o yaml

Sample Output:

$ kubectl get deploy my-nginx-deployment -n my-nginx-namespace -o yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"creationTimestamp":null,"labels":{"app":"my-nginx-deployment"},"name":"my-nginx-deployment","namespace":"my-nginx-namespace"},"spec":{"replicas":10,"selector":{"matchLabels":{"app":"my-nginx-deployment"}},"strategy":{},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"my-nginx-deployment"}},"spec":{"containers":[{"image":"nginx:latest","name":"nginx","ports":[{"containerPort":80}],"resources":{}}]}}},"status":{}}
  creationTimestamp: "2023-04-27T19:19:11Z"
  generation: 6
  labels:
    app: my-nginx-deployment
  name: my-nginx-deployment
  namespace: my-nginx-namespace
  resourceVersion: "979655"
  uid: 26df08d5-4b69-41a5-acc8-d444fc4239bd
spec:
  progressDeadlineSeconds: 600
  replicas: 10
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: my-nginx-deployment
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: my-nginx-deployment
    spec:
      containers:
      - image: nginx:latest
        imagePullPolicy: Always
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 10
  conditions:
  - lastTransitionTime: "2023-04-27T19:19:11Z"
    lastUpdateTime: "2023-04-27T19:19:20Z"
    message: ReplicaSet "my-nginx-deployment-9cbcd46b4" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  - lastTransitionTime: "2023-04-28T16:44:39Z"
    lastUpdateTime: "2023-04-28T16:44:39Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 6
  readyReplicas: 10
  replicas: 10
  updatedReplicas: 10
cat my-nginx-deployment.yaml

Sample Output:

$ cat my-nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: my-nginx-deployment
  name: my-nginx-deployment
  namespace: my-nginx-namespace
spec:
  replicas: 10
  selector:
    matchLabels:
      app: my-nginx-deployment
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: my-nginx-deployment
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
        resources: {}
status: {}
kubectl 

Sample Output:

kubectl 

Sample Output:

kubectl 

Sample Output:

Transition

Deleting Kubernetes Objects Using kubectl delete

kubectl get all -A

Sample Output:

$ kubectl get all -A
NAMESPACE            NAME                                           READY   STATUS    RESTARTS   AGE
declarative          pod/nginx-pod                                  1/1     Running   0          26h
imperative           pod/nginx-pod                                  1/1     Running   0          35s
kube-system          pod/calico-kube-controllers-57b57c56f-4hvfl    1/1     Running   0          8d
kube-system          pod/calico-node-s28hb                          1/1     Running   0          8d
kube-system          pod/calico-node-tqb6g                          1/1     Running   0          8d
kube-system          pod/coredns-787d4945fb-cg5wh                   1/1     Running   0          8d
kube-system          pod/coredns-787d4945fb-xdbll                   1/1     Running   0          8d
kube-system          pod/etcd-control-plane-01                      1/1     Running   0          8d
kube-system          pod/kube-apiserver-control-plane-01            1/1     Running   0          8d
kube-system          pod/kube-controller-manager-control-plane-01   1/1     Running   0          8d
kube-system          pod/kube-proxy-blgcf                           1/1     Running   0          8d
kube-system          pod/kube-proxy-t9wb4                           1/1     Running   0          8d
kube-system          pod/kube-scheduler-control-plane-01            1/1     Running   0          8d
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-42n2q        1/1     Running   0          26h
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-6hlwl        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-7t2fr        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-bls2n        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-f4lkn        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-mxxbl        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-nq7xw        1/1     Running   0          4h58m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-smcv6        1/1     Running   0          4h58m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-sz27h        1/1     Running   0          4h50m
my-nginx-namespace   pod/my-nginx-deployment-9cbcd46b4-v8bp5        1/1     Running   0          4h50m

NAMESPACE            NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default              service/kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP                  8d
kube-system          service/kube-dns           ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   8d
my-nginx-namespace   service/my-nginx-service   ClusterIP   10.111.212.138   <none>        8888/TCP                 5h34m

NAMESPACE     NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   daemonset.apps/calico-node   2         2         2       2            2           kubernetes.io/os=linux   8d
kube-system   daemonset.apps/kube-proxy    2         2         2       2            2           kubernetes.io/os=linux   8d

NAMESPACE            NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system          deployment.apps/calico-kube-controllers   1/1     1            1           8d
kube-system          deployment.apps/coredns                   2/2     2            2           8d
my-nginx-namespace   deployment.apps/my-nginx-deployment       10/10   10           10          26h

NAMESPACE            NAME                                                DESIRED   CURRENT   READY   AGE
kube-system          replicaset.apps/calico-kube-controllers-57b57c56f   1         1         1       8d
kube-system          replicaset.apps/coredns-787d4945fb                  2         2         2       8d
my-nginx-namespace   replicaset.apps/my-nginx-deployment-9cbcd46b4       10        10        10      26h
kubectl delete pod/nginx-pod -n imperative

Sample Output:

$ kubectl delete pod/nginx-pod -n imperative

pod "nginx-pod" deleted
kubectl delete ns/imperative

Sample Output:

$ kubectl delete ns/imperative

namespace "imperative" deleted
kubectl get all -n imperative

Sample Output:

$ kubectl get all -n imperative

No resources found in imperative namespace.
kubectl delete pod/nginx-pod -n declarative ; kubectl delete ns/declarative

Sample Output:

$ kubectl delete pod/nginx-pod -n declarative ; kubectl delete ns/declarative

pod "nginx-pod" deleted
namespace "declarative" deleted
kubectl delete -f my-nginx-service.yaml
kubectl delete -f my-nginx-deployment.yaml
kubectl delete -f my-nginx-namespace.yaml
kubectl get all -n my-nginx-namespace

Sample Output:

$ kubectl delete -f my-nginx-service.yaml

service "my-nginx-service" deleted

$ kubectl delete -f my-nginx-deployment.yaml

deployment.apps "my-nginx-deployment" deleted

$ kubectl delete -f my-nginx-namespace.yaml

namespace "my-nginx-namespace" deleted

$ kubectl get all -n my-nginx-namespace

No resources found in my-nginx-namespace namespace.
kubectl get all -A

Sample Output:

$ kubectl get all -A

NAMESPACE     NAME                                           READY   STATUS    RESTARTS   AGE
kube-system   pod/calico-kube-controllers-57b57c56f-4hvfl    1/1     Running   0          8d
kube-system   pod/calico-node-s28hb                          1/1     Running   0          8d
kube-system   pod/calico-node-tqb6g                          1/1     Running   0          8d
kube-system   pod/coredns-787d4945fb-cg5wh                   1/1     Running   0          8d
kube-system   pod/coredns-787d4945fb-xdbll                   1/1     Running   0          8d
kube-system   pod/etcd-control-plane-01                      1/1     Running   0          8d
kube-system   pod/kube-apiserver-control-plane-01            1/1     Running   0          8d
kube-system   pod/kube-controller-manager-control-plane-01   1/1     Running   0          8d
kube-system   pod/kube-proxy-blgcf                           1/1     Running   0          8d
kube-system   pod/kube-proxy-t9wb4                           1/1     Running   0          8d
kube-system   pod/kube-scheduler-control-plane-01            1/1     Running   0          8d

NAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  8d
kube-system   service/kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   8d

NAMESPACE     NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   daemonset.apps/calico-node   2         2         2       2            2           kubernetes.io/os=linux   8d
kube-system   daemonset.apps/kube-proxy    2         2         2       2            2           kubernetes.io/os=linux   8d

NAMESPACE     NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/calico-kube-controllers   1/1     1            1           8d
kube-system   deployment.apps/coredns                   2/2     2            2           8d

NAMESPACE     NAME                                                DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/calico-kube-controllers-57b57c56f   1         1         1       8d
kube-system   replicaset.apps/coredns-787d4945fb                  2         2         2       8d

Everything you created has been cleaned up. Good job!

Practice Exercises

Use the following practice exercises to test the skills you learned in this tutorial.

Try and solve the exercises on your own before checking the solutions. If a required resource or object does not exist, create it.

Exercise 1

Create a single Pod, imperatively, named apache-pod, using the image httpd:latest, in the apache-imperative namespace, with port 80 exposed. Confirm that your Pod is in the Running state. Confirm you can reach the Apache web server using curl.

Exercise 1: Solution

Exercise 2

Create a YAML manifest in a file named declarative-apache-pod.yaml, for a single Pod, imperatively, named apache-pod, using the image httpd:latest, in the apache-declarative namespace, with port 80 exposed. Review this manifest, deploy it, and confirm all the objects have been created. Confirm your Pod is in the Running state. Confirm you can reach the Apache web server using curl.

Exercise 2: Solution

Exercise 3

Create a YAML manifest for a Namespace, named my-nginx-namespace in a file named my-nginx-namespace.yaml. Review this manifest, deploy it, and confirm all the objects have been created.

Exercise 3: Solution

Exercise 4

Create a YAML manifest for a Deployment, named my-nginx-deployment, using the nginx-latest container image, in the my-nginx-namespace namespace, with 5 replicas, exposing port 80, in a file named my-nginx-deployment.yaml. Review this manifest, deploy it, and confirm all the objects have been created.

Exercise 4: Solution

Exercise 5

Create a YAML manifest for a Service, named my-nginx-service, of type clusterip, in the my-nginx-namespace namespace, exposed on port 8888, in a file named my-nginx-service.yaml. Use the app=my-nginx-deployment label as a Selector for your Service.

Exercise 5: Solution

Exercise 6

Scale the my-nginx-deployment, declaratively, from 3 Pod replicas to 10 replicas.

Exercise 6: Solution

Exercise 7

Create a manifest for a Pod named nginx-pod, using image nginx:latest, in the nginx-test namespace, with labels nginx=test and test=nginx, in a file named test-nginx-pod.yaml. Review this manifest, deploy it, and confirm all the objects have been properly created with the correct labels applied.

Exercise 7: Solution

Exercise 8

Create a manifest, in a file named top-secret.yaml for a Secret named top-secret with key1=ultra and key2=secret.

Exercise 8: Solution

Exercise 9

Create a Namespace manifest for the apache-imperative Namespace and a Pod manifest for the apache-pod Pod, using the existing objects. Verify your work.

Exercise 9: Solution

Exercise 10

Clean up everything you created. Verify your work.

Exercise 10: Solution

Transition

Summary

Enjoy!

Tom Dean

using-kubectl-generate-yaml-manifests's People

Watchers

Tom Dean avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.