Getting Started with Kubernetes
Kubernetes is an open source container orchestration engine that automates how container applications are deployed, scaled, and managed. Since it was first released 7 years ago, it has made great strides in a short period. It has previously had to compete with and outperform container orchestration engines such as Cloud Foundry Diego, CoreOS's Fleet, Docker Swarm, Kontena, HashiCorp's Nomad, Apache Mesos, Rancher's Cattle, Amazon ECS, and more. Kubernetes is now operating in an entirely different landscape. This indicates that developers only need to master one container orchestration engine so that they can be employed for 90% of container-related jobs.
The Kubernetes container orchestration framework is a ready-for-production open source platform built on Google's 15+ years of experience running production workloads, as well as community-contributed best-of-breed principles and concepts. Kubernetes divides an application's containers into logical units for easier administration and discovery. Containers (cgroups) have been around since early 2007 when they were first included in the mainline Linux kernel. A container's small size and portability allows it to host an exponentially higher number of containers than VMs, lowering infrastructure costs and allowing more programs to be deployed faster. However, until Docker (2013) came along, it didn't generate significant interest due to usability concerns.
Docker is different from standard virtualization; it is based on operating-system-level virtualization. Containers, unlike hypervisor virtualization, which uses an intermediation layer (hypervisor) to run virtual machines on physical hardware, run in user space on top of the kernel of an operating system. As a result, they're incredibly light and fast. This can be seen in the following diagram:

Figure 1.1 – Virtual machines versus containers
The Kubernetes container orchestration framework automates much of the operational effort that's necessary to run containerized workloads and services. This covers provisioning, deployment, scaling (up and down), networking, load balancing, and other tasks that software teams must perform to manage a container's life cycle. Some of the key benefits that Kubernetes brings to developers are as follows:
- Declarative Application Topology: This describes how each service should be implemented, as well as their reliance on other services and resource requirements. Because we have all of this data in an executable format, we can test the application's deployment parts early on in development and treat it like programmable application infrastructure:

Figure 1.2 – Declarative application topology
- Declarative Service Deployments: The update and rollback process for a set of containers is encapsulated, making it a repetitive and automated procedure.
- Dynamically Placed Applications: This allows applications to be deployed in a predictable sequence on the cluster, based on application requirements, resources available, and governing policies.
- Flexible scheduler: There is a lot of flexibility in terms of defining conditions for assigning pods to a specific or a set of worker nodes that meet those conditions.
- Application Resilience: Containers and management platforms help applications be more robust in a variety of ways, as follows:
- Resource consumption policies such as CPU and memory quotas
- Handling the failures using a circuit breaker, timeout, retry, and so on
- Failover and service discovery
- Autoscaling and self-healing
- Self-Service Environments: These allow teams and individuals to create secluded environments for CI/CD, experimentation, and testing purposes from the cluster in real time.
- Service Discovery, Load Balancing, and Circuit Breaker: Without the use of application agents, services can discover and consume other services. There's more to this than what is listed here.
In this chapter, we're going to cover the following main topics:
- The evolution of containers
- Kubernetes overview – understanding Kubernetes components
- Understanding pods
- Understanding deployments
- Understanding StatefulSets and DaemonSets
- Understanding lobs and CronJobs
- Understanding services
The evolution of containers
Container technology is a means of packaging an application so that it may run with separated dependencies, and its compartmentalization of a computer system has radically transformed software development today. In this section, we'll look at some of the key aspects, including where this technology originated and the background behind the container technology:

Figure 1.3 – A brief history of container technology
Early containers (chroot systems with Unix version 7), developed in the 1970s, offered an isolated environment in which services and applications could operate without interfering with other processes, thereby creating a sandbox for testing programs, services, and other processes. The original concept was to separate the workload of the container from that of production systems, allowing developers to test their apps and procedures on production hardware without disrupting other services. Containers have improved their abilities to isolate users, data, networking, and more throughout time.
With the release of Free BSD Jails in the 2000s, container technology finally gained traction. "Jails" are computer partitions that can have several jails/partitions on the same system. This jail architecture was developed in 2001 with Linux VServer, which included resource partitioning and was later linked to the Linux kernel with OpenVZ in 2005. Jails were merged with boundary separation to become Solaris Containers in 2004.
Container technology advanced substantially after the introduction of control groups in 2006. Control groups, or cgroups, were created to track and isolate resource utilization, such as CPU and memory. They were quickly adopted and improved upon in Linux Containers (LXC) in 2008, which was the most full and stable version of any container technology at the time since it functioned without changes having to be made to the Linux kernel. Many new technologies have sprung up because of LXC's reliability and stability, the first of which was Warden in 2011 and, more importantly, Docker in 2013.
Containers have gained a lot of usage since 2013 due to a slew of Linux distributions releasing new deployment and management tools. Containers running on Linux systems have been transformed into virtualization solutions at the operating system level, aiming to provide several isolated Linux environments on a single Linux host. Linux containers don't need their own guest operating systems; instead, they share the kernel of the host operating system. Containers spin up significantly faster than virtual machines since they don't require a specialized operating system.
Containers can employ Linux kernel technologies such as namespaces, Apparmor, SELinux profiles, chroot, and cgroups to create an isolated operational environment, while Linux security modules offer an extra degree of protection, ensuring that containers can't access the host machine or kernel. Containerization in terms of Linux provided even more versatility by allowing containers to run various Linux distributions from their host operating system if both were running on the same CPU architecture.
Linux containers provided us with a way to build container images based on a variety of Linux distributions, as well as an API for managing the containers' lifespan. Linux distributions also included client tools for dealing with the API, as well as snapshot features and support for moving container instances from one container host to another.
However, while containers running on a Linux platform broadened their applicability, they still faced several fundamental hurdles, including unified management, real portability, compatibility, and scaling control.
The emergence of Apache Mesos, Google Borg, and Facebook Tupperware, all of which provided varying degrees of container orchestration and cluster management capabilities, marked a significant advancement in the use of containers on Linux platforms. These platforms allowed hundreds of containers to be created instantly, and also provided support for automated failover and other mission-critical features that are required for container management at scale. However, it wasn't until Docker, a variation of containers, that the container revolution began in earnest.
Because of Docker's popularity, several management platforms have emerged, including Marathon, Kubernetes, Docker Swarm, and, more broadly, the DC/OS environment that Mesosphere built on top of Mesos to manage not only containers but also a wide range of legacy applications and data services written in, for example, Java. Even though each platform has its unique approach to orchestration and administration, they all share one goal: to make containers more mainstream in the workplace.
The momentum of container technology accelerated in 2017 with the launch of Kubernetes, a highly effective container orchestration solution. Kubernetes became the industry norm after being adopted by CNCF and receiving backing from Docker. Thus, using a combination of Kubernetes and other container tools became the industry standard.
With the release of cgroups v2 (Linux version 4.5), several new features have been added, including rootless containers, enhanced management, and, most crucially, the simplicity of cgroup controllers.
Container usage has exploded in the last few years (https://juju.is/cloud-native-kubernetes-usage-report-2021) in both emerging "cloud-native" apps and situations where IT organizations wish to "containerize" an existing legacy program to make it easier to lift and shift onto the cloud. Containers have now become the de facto standard for application delivery as acceptance of cloud-native development approaches matures.
We'll dive more into Kubernetes components in the next section.
Kubernetes overview – understanding Kubernetes components
In this section, we'll go through the various components of the Kubernetes system, as well as their abstractions.
The following diagram depicts the various components that are required for a fully functional Kubernetes cluster:

Figure 1.4 – A Kubernetes system and its abstractions
Let's describe the components of a Kubernetes cluster:
- Nodes, which are worker machines that run containerized work units, make up a Kubernetes cluster. Every cluster has at least one worker node.
- There is an API layer (Kubernetes API) that can communicate with Kubernetes clusters, which may be accessed via a command-line interface called kubectl.
There are two types of resources in a Kubernetes cluster (as shown in the preceding diagram):
- The control plane, which controls and manages the cluster
- The nodes, which are the workers' nodes that run applications
All the operations in your cluster are coordinated by the control plane, including application scheduling, maintaining the intended state of applications, scaling applications, and deploying new updates.
A cluster's nodes might be virtual machines (VMs) or physical computers that serve as worker machines. A kubelet is a node-managing agent that connects to each node's Kubernetes control plane. Container management tools, such as Docker, should be present on the node as well.
The control plane executes a command to start the application containers whenever an application needs to be started on Kubernetes. Containers are scheduled to run on the cluster's nodes by the control plane.
The nodes connect to the control plane using the Kubernetes API that the control plane provides. The Kubernetes API allows end users to interface directly with the cluster. The master components offer the cluster's control plane capabilities.
API Server, Controller-Manager, and Scheduler are the three processes that make up the Kubernetes control plane. The Kubernetes API is exposed through the API Server. It is the Kubernetes control plane's frontend. Controller-Manager is in charge of the cluster's controllers, which are responsible for handling everyday activities. The Scheduler keeps an eye out for new pods that don't have a node assigned to them and assigns them one. Each worker node in the cluster is responsible for the following processes:
- Kubelet: This handles all the communication with the Kubernetes MasterControl plane.
- kube-proxy: This handles all the networking proxy services on each node.
- The container runtime, such as Docker.
Control plane components are in charge of making global cluster decisions (such as application scheduling), as well as monitoring and responding to cluster events. For clusters, there is a web-based Kubernetes dashboard. This allows users to administer and debug cluster-based applications, as well as the cluster itself. Kubernetes clusters may run on a wide range of platforms, including your laptop, cloud-hosted virtual machines, and bare-metal servers.
MicroK8s is a simplistic streamlined Kubernetes implementation that builds a Kubernetes cluster on your local workstation and deploys all the Kubernetes services on a tiny cluster that only includes one node. It can be used to experiment with your local Kubernetes setup. MicroK8s is compatible with Linux, macOS X, Raspberry Pi, and Windows and can be used to experiment with local Kubernetes setups or for edge production use cases. Start, stop, status, and delete are all basic bootstrapping procedures that are provided by the MicroK8s CLI for working with your cluster. We'll learn how to install MicroK8s, check the status of the installation, monitor and control the Kubernetes cluster, and deploy sample applications and add-ons in the next chapter.
Other objects that indicate the state of the system exist in addition to the components listed in Figure 1.3. The following are some of the most fundamental Kubernetes objects:
- Pods
- Deployments
- StatefulSets and DaemonSets
- Jobs and CronJobs
- Services
In the Kubernetes system, Kubernetes objects are persistent entities. These entities are used by Kubernetes to represent the state of your cluster. It will operate indefinitely to verify that the object exists once it has been created. You're simply telling the Kubernetes framework how your cluster's workloads should look by building an object; this is your cluster's ideal state. You must use the Kubernetes API to interact with Kubernetes objects, whether you want to create, update, or delete them. The CLI handles all Kubernetes API queries when you use the kubectl
command-line interface, for example. You can also directly access the Kubernetes API in your apps by using any of the client libraries. The following diagram illustrates the various Kubernetes objects:

Figure 1.5 – Overview of Kubernetes objects
Kubernetes provides the preceding set of objects (such as pods, services, and controllers) to satisfy our application's requirements and drive its architecture. The guiding design principles and design patterns we employ to build any new services are determined by these new primitives and platform abilities. A deployment object, for example, is a Kubernetes object that can represent an application running on your cluster. When you build the deployment, you can indicate that three replicas of the application should be running in the deployment specification. The Kubernetes system parses the deployment specification and deploys three instances of your desired application, altering its status as needed. If any of those instances fails for whatever reason, the Kubernetes framework responds to the discrepancy between the specification and the status by correcting it – in this case, by establishing a new instance.
Understanding how Kubernetes works is essential, but understanding how to communicate with Kubernetes is just as important. We'll go over some of the ways to interact with a Kubernetes cluster in the next section.
Interacting with a Kubernetes cluster
In this section, we'll look at different ways to interface with a Kubernetes cluster.
Kubernetes Dashboard is a user interface that can be accessed via the web. It can be used to deploy containerized applications to a Kubernetes cluster, troubleshoot them, and control the cluster's resources. This dashboard can be used for a variety of purposes, including the following:
- All the nodes and persistent storage volumes are listed in the Admin overview, along with aggregated metrics for each node.
- The Workloads view displays a list of all running applications by namespace, as well as current pod memory utilization and the number of pods in a deployment that are currently ready.
- The Discover view displays a list of services that have been made public and have enabled cluster discovery.
- You can drill down through logs from containers that belong to a single pod using the Logs view.
- For each clustered application and all the Kubernetes resources running in the cluster, the Storage view identifies any persistent volume claims:

Figure 1.6 – Kubernetes Dashboard
- With the help of the Kubernetes command-line tool,
kubectl
, you can perform commands against Kubernetes clusters.kubectl
is a command-line tool for deploying applications, inspecting and managing cluster resources, and viewing logs.kubectl
can be installed on a variety of Linux, macOS, and Windows platforms.
The basic syntax for kubectl
looks as follows:
kubectl [command] [type] [name] [flags]
Let's look at command
, type
, name
, and flags
in more detail:
command
: This defines the action you wanted to obtain on one or more resources, such ascreate
,get
,delete
, anddescribe
.type
: This defines the types of your resources, such as pods and jobs.name
: This defines the name of the resource. Names are case-sensitive. If the name is omitted, details for all the resources are displayed; for example,kubectl get pods
.flags
: This defines optional flags.
We'll take a closer look at each of these Kubernetes objects in the upcoming sections.
Understanding pods
Pods are the minimal deployable computing units that can be built and managed in Kubernetes. They are made up of one or more containers that share storage and network resources, as well as running instructions. Pods have the following components:
- An exclusive IP address that enables them to converse with one another
- Persistent storage volumes based on the application's needs
- Configuration information that determines how a container should run
The following diagram shows the various components of a pod:

Figure 1.7 – The components of a pod
Workload resources known as controllers create pods and oversee the rollout, replication, and health of pods in the cluster.
The most common types of controllers are as follows:
- Jobs for batch-type jobs that are short-lived and will run a task to completion
- Deployments for applications that are stateless and persistent, such as web servers
- StatefulSets for applications that are both stateful and persistent, such as databases
These controllers build pods using configuration information from a pod template, and they guarantee that the operating pods meet the deployment specification provided in the pod template by creating replicas in the number of instances specified in the deployment.
As we mentioned previously, the Kubectl command-line interface includes various commands that allow users to build pods, deploy them, check on the status of operating pods, and delete pods that are no longer needed.
The following are the most commonly used kubectl
commands concerning pods:
- The
create
command creates the pod:kubectl create -f FILENAME.
For example, the kubectl create -f ./mypod.yaml
command will create a new pod from the mypod
YAML file.
- The
get pod
/pods
command will display information about one or more resources. Information can be filtered using the respective label selectors:kubectl get pod pod1
- The
delete
command deletes the pod:kubectl delete -f FILENAME.
For example, the kubectl delete -f ./mypod.yaml
command will delete the mypod
pod from the cluster.
With that, we've learned that a pod is the smallest unit of a Kubernetes application and is made up of one or more Linux containers. In the next section, we will look at deployments.
Understanding deployments
Deployment allows you to make declarative changes to pods and ReplicaSets. You can provide a desired state for the deployment, and the deployment controller will incrementally change the actual state to the desired state.
Deployments can be used to create new ReplicaSets or to replace existing deployments with new deployments. When a new version is ready to go live in production, the deployment can easily handle the upgrade with no downtime by using predefined rules. The following diagram shows an example of a deployment:

Figure 1.8 – A deployment
The following is an example of a deployment. It creates a ReplicaSet to bring up three nginx
pods:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-sample-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1:21 ports: - containerPort: 80
In the preceding example, the following occurred:
- A deployment called
nginx-sample-deployment
is created, as indicated by themetadata.name
field. - The image for this deployment is set by the
Spec.containers.image
field (nginx:latest
). - The deployment creates three replicated pods, as indicated by the
replicas
field.
The most commonly used kubectl
commands concerning deployment are as follows:
- The
apply
command creates the pod:kubectl apply -f FILENAME.
For example, the kubectl apply -f ./nginx-deployment.yaml
command will create a new deployment from the nginx-deployment.yaml
YAML file.
- The
get deployments
command checks the status of the deployment:kubectl get deployments
This will produce the following output:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-sample-deployment 3/3 0 0 1s
The following fields are displayed:
NAME
indicates the names of the deployments in the namespace.READY
shows how many replicas of the application are available.UP-TO-DATE
shows the number of replicas that have been updated to achieve the desired state.AVAILABLE
shows the number of available replicas.
AGE
indicates the length of time the application has been running.- The
describe deployments
command indicates the details of the deployment:kubectl describe deployments
- The
delete
command removes the deployment that was made by theapply
command:kubectl delete -f FILENAME.
With that, we have learned that deployments are used to define the life cycle of an application, including which container images to use, how many pods you should have, and how they should be updated. In the next section, we will look at StatefulSets and DaemonSets.
Understanding StatefulSets and DaemonSets
In this section, we'll go over two distinct approaches to deploying our application on Kubernetes: using StatefulSets and DaemonSets.
StatefulSets
The StatefulSet API object is used to handle stateful applications. A StatefulSet, like a deployment, handles pods that have the same container specification. A StatefulSet, unlike a deployment, continues using a persistent identity for each of its pods. These pods are generated for identical specifications, but they can't be exchanged: each has a unique identity that it keeps throughout any rescheduling.
The following example demonstrates the components of a StatefulSet:
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx serviceName: "nginx" replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 name: web volumeMounts: - name: www_volume mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www_volume spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "my-storage-class" resources: requests: storage: 10Gi
In the preceding example, we have the following:
nginx
is the headless service that is used to control the network domain.web
is the StatefulSet that has a specification that indicates that three replicas from thenginx
container will be launched in unique pods.volumeClaimTemplates
will use PersistentVolumes provisioned by a PersistentVolume provisioner to offer stable storage.
Now, let's move on to DaemonSets.
DaemonSets
A DaemonSet guarantees that all (or some) nodes have a copy of a pod running. As nodes are added to the cluster, pods are added to them. As nodes are removed from the cluster, garbage is collected in pods. When you delete a DaemonSet, the pods it produced are also deleted.
The following are some example use cases regarding DaemonSets:
- Run a daemon for cluster storage on each node, such as
glusterd
andceph
. - Run a daemon for logs to be collected on each node, such as
Fluentd
orFluentBit
andlogstash
. - Run a daemon for monitoring on every node, such as Prometheus Node Exporter,
collectd
, or Datadog agent.
The following code shows a DaemonSet that's running the fluent-bit
Docker image:
apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: kube-system labels: k8s-app: fluent-bit spec: selector: matchLabels: name: fluent-bit template: metadata: labels: name: fluent-bit spec: tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule containers: - name: fluent-bit image: fluent/fluent-bit:latest resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi
In the preceding example, the fluent-bit
DaemonSet has a specification that tells fluent-bit
to run on all the containers.
The most commonly used kubectl
commands concerning DaemonSets are as follows:
- The
create
orapply
command creates the DaemonSet:kubectl apply -f FILENAME.
For example, the kubectl apply -f ./daemonset-deployment.yaml
command will create a new DaemonSet from the daemonset-deployment.yaml
YAML file.
- The
get daemonset
command is used to monitor the status of the DaemonSet:kubectl get daemonset
This will produce the following output:
NAME READY UP-TO-DATE AVAILABLE AGE daemonset-deployment 3/3 0 0 1s
The following fields are displayed:
NAME
indicates the names of the DaemonSets in the namespace.READY
shows how many replicas of the application are available.UP-TO-DATE
shows the number of replicas that have been updated to achieve the desired state.AVAILABLE
shows how many replicas of the application are available.
AGE
indicates the length of time the application has been running.- The
describe daemonset
command indicates the details of the DaemonSets:kubectl describe daemonset
- The
delete
command removes the deployment that was made by theapply
command:kubectl delete <<daemonset>>
With that, we've learned that a DaemonSet ensures that all or a set of nodes run a copy of a pod, while a StatefulSet is used to manage stateful applications. In the next section, we will look at jobs and CronJobs.
Understanding jobs and CronJobs
In this section, we will learn how to use Kubernetes jobs to build temporary pods that do certain tasks. CronJobs are similar to jobs, but they run tasks according to a set schedule.
Jobs
A job launches one or more pods and continues to try executing them until a specific number of them succeed. The job keeps track of how many pods have been completed successfully. The task (that is, the job) is completed when a certain number of successful completions is met.
When you delete a job, it also deletes all the pods it created. Suspending a job causes all the current pods to be deleted until the job is resumed. The following code shows a job config that runs every minute and prints example Job Pod is Running
as its output:
apiVersion: batch/v1 kind: Job metadata: name: example-job spec: template: spec: containers: - name: example-job image: busybox command: ['echo', 'echo example Job Pod is Running'] restartPolicy: OnFailure backoffLimit: 4
The most commonly used kubectl
commands concerning jobs are as follows:
- The
create
orapply
command creates the pod:kubectl apply -f FILENAME.
For example, the kubectl apply -f ./jobs-deployment.yaml
command will create new jobs from the jobs-deployment.yaml
YAML file.
- The
describe jobs
command indicates the details of the jobs:kubectl describe jobs <<job name>>
CronJob
A CronJob is a job that is created regularly. It is equivalent to a single line in a crontab (cron table) file. It executes a job that is written in Cron format regularly.
CronJobs are used to automate common processes such as backups and report generation. You can decide when the work should begin within that period by setting each of those jobs to repeat indefinitely (for example, once a day, week, or month).
The following is an example of a CronJob that prints the example-cronjob Pod is Running
output every minute:
apiVersion: batch/v1 kind: CronJob metadata: name: example-cronjob spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: example-cronjob image: busybox imagePullPolicy: IfNotPresent command: - /bin/sh - -c - date; echo example-cronjob Pod is Running ; sleep 5 restartPolicy: OnFailure
Here, schedule: /1 *
indicates that the crontab syntax is used in Linux systems.
Jobs and CronJobs are critical components of Kubernetes, particularly for performing batch processes and other critical ad hoc tasks. We'll examine service abstraction in the next section.
Understanding services
In Kubernetes, a service is an abstraction that defines a logical set of pods, as well as a policy for accessing them. An example service definition is shown in the following code block, which includes a collection of pods that each listen on TCP port 9876
with the app=exampleApp
label:
apiVersion: v1 kind: Service metadata: name: example-service spec: selector: app: exampleApp ports: - protocol: TCP port: 80 targetPort: 9876
In the preceding example, a new Service
object named example-service
was created that routes TCP port 9876
to any pod with the app=exampleApp
label. This service is given an IP address by Kubernetes, which is utilized by the service proxies. A Kubernetes service, in simple terms, connects a group of pods to an abstracted service name and IP address. Discovery and routing between pods are provided by services. Services, for example, connect an application's frontend to its backend, which are both deployed in different cluster deployments. Labels and selectors are used by services to match pods with other applications.
The core attributes of a Kubernetes service are as follows:
- A label selector that locates pods
- The cluster IP address and the assigned port number
- Port definitions
- (Optional) Mapping for incoming ports to a targetPort
Kubernetes will automatically assign a cluster IP address, which will be used to route traffic by service proxies. The selector's controller will check for pods that match the defined label. Some applications will require multiple ports to be exposed via the service. Kubernetes facilitates this by using multi-port services, where a user can define multiple ports in a single service object.
In the following example, we have exposed ports 80
and 443
to target ports 8080
and 8090
to route HTTP and HTTPS traffic to any underlying pods using the app=webserver-nginx-multiport-example
selector:
apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: webserver-nginx-multiport-example ports: - name: http protocol: TCP port: 80 targetPort: 8080 - name: https protocol: TCP port: 443 targetPort: 8090
A service can also be defined without the use of a selector; however, you must explicitly connect the service (IP address, port, and so on) using an endpoints
object. This is because, unlike with a selector, Kubernetes does not know which pods the service should be connected to, so endpoint
objects are not built automatically.
Some use cases for services without selectors are as follows:
- Connecting to another service in a different namespace or cluster
- Communicating with external services, data migration, testing services, deployments, and so on
Let's create a deployment with three replicas of an Apache web server:
apiVersion: apps/v1 kind: Deployment metadata: name: apache-deployment labels: app: webserver spec: replicas: 3 selector: matchLabels: app: webserver template: metadata: labels: app: webserver spec: containers: - name: apache image: httpd:latest ports: - containerPort: 80
Create the deployment using the following command:
kubectl apply -f apache-deployment.yaml
The following are the most common types of services:
- ClusterIP: This is the default type and exposes the service via the cluster's internal IP address. These services are only accessible within the cluster. So, users need to implement port forwarding or a proxy to expose a ClusterIP to a wider ingress of traffic.
- NodePort: A static port on each node's IP is used to expose a service. To route traffic to the NordPort service, a ClusterIP service is automatically created. Requesting
NodeIP:NodePort>
from the outside allows users to communicate with the service. - LoadBalancer: This is the preferred solution for exposing the cluster to the wider internet. The LoadBalancer type of service will create a load balancer (the load balancer's type depends on the cloud provider) and expose the service externally. It will also automatically create ClusterIP and NodePort services and route traffic accordingly.
- ExternalName: Maps a service to a predefined
externalName ex.sampleapp.test.com
field by returning a value for theCNAME
record.
Summary
To conclude, Kubernetes is a container orchestration system that maintains a highly available cluster of machines that work together as a single entity. In this chapter, we discovered that Kubernetes supports several abstractions that allow containerized applications to be deployed to a cluster without being bound to specific machines. We also learned that pods represent a set of operating containers on your cluster. A deployment is an excellent fit for managing a stateless application workload on your cluster. StatefulSets can be used to run one or more connected pods to manage stateful applications, while DaemonSets specify pods and provide node-specific functionality. Finally, jobs and CronJobs handle batch processing and other key ad hoc tasks. In a nutshell, Kubernetes is a container orchestration system that is portable, extensible, and self-healing.
In the next chapter, we'll look at the lightweight Kubernetes engine known as MicroK8s, which can run on the edge, IoT, and appliances. MicroK8s is also ideal for offline prototyping, testing, and development.