Kubernetes Pod

What is a Kubernetes Pod?

Pod is the most basic component to deploy and run an application, created and managed by kubernetes. Pods are used to group and run one or more containers together on the same worker node. Containers in a pod will share the same resources. Normally, you should only run a Pod with 1 container (I will explain when you should run a pod with one container and a pod with many containers in another article).

So why use Pod to run containers, why not run containers directly? Kubernetes Pod is like a container wrapper, providing us with more functions to manage and run a container, helping our containers run better than running containers directly, such as grouping container resources, checking container health and restart, make sure the application in the container is already running before sending requests to that container, provide a lifecycle number so we can add actions to the Pod when the Pod runs or shuts down, etc... And kubernetes will manage Manage Pods instead of managing containers directly

Run your first application using Pod

Now let's start practicing the first lesson. First, we create a folder and create an index.js file, copy the following code into it:

const http = require("http");

const server = http.createServer((req, res) => {
  res.end("Hello kube\n")
});

server.listen(3000, () => {
  console.log("Server listen on port 3000")
})

Create a Dockerfile file and copy the following code into it:

FROM node:12-alpine
WORKDIR /app
COPY index.js .
ENTRYPOINT [ "node", "index" ]

Run the build image command:

docker build . -t 080196/hello-kube

Test whether the container runs correctly or not, run the container with the command:

docker run -d --name hello-kube -p 3000:3000 080196/hello-kube

If we can print the word hello kube, our container is running. Delete the container

docker rm -f hello-kube

Now we will use Pod to run the container, you can use our image 080196/hello-kube or create your own image according to the instructions here

Create a file named hello-kube.yaml and copy the following config into it:

apiVersion: v1 # Descriptor conforms to version v1 of Kubernetes API
kind: Pod # Select Pod resource
metadata:
  name: hello-kube # The name of the pod
spec:
  containers:
    - image: 080196/hello-kube # Image to create the container
      name: hello-kube # The name of the container
      ports:
        - containerPort: 3000 # The port the app is listening on 
          protocol: TCP

Usually we will not run Pod directly like this, but will use other kube resources to run Pod, I will talk about it in the following articles.

Use kubectl CLI (if you have installed kubernetes locally, kubectl CLI will be available) to run the Pod's config file

kubectl apply -f hello-kube.yaml

Check if the pod is running or not

kubectl get pod

If the status column shows Running, your Pod has been successfully run, and ContainerCreating status means the Pod is being created. Next we will test the pod to see if it runs correctly or not. First of all, to test the Pod, we must expose the Pod's traffic so it can receive requests first, because currently our Pod is running in a local cluster and does not have an exposed port to the outside.There are 2 ways to expose the pod's port, using Service resource (I will talk about Service in the next article) or using kubectl port-forward. In this article we will use port-forward, run the following command to expose the pod's port

kubectl port-forward pod/hello-kube 3000:3000

Test sends request to pod

If we can print the word hello kube, our pod is running correctly. After running to clear the resource, we delete the pod with the command

kubectl delete pod hello-kube

Organize pods using labels

Using labels is a way for us to divide different pods depending on the project or environment. For example, our company has 3 environments: testing, staging, production. If we run pods without labels, it is difficult for us to know which pod belongs to which environment.

Labels is a key-value pair attribute that we assign to the resource in the metadata section. We can name the key and value with any name. For example:

apiVersion: v1
kind: Pod
metadata:
  name: hello-kube-testing
  labels:
    enviroment: testing # label with key is enviroment and value is testing
    project: kubernetes-series
spec:
  containers:
    - image: 080196/hello-kube
      name: hello-kube
      ports:
        - containerPort: 3000
          protocol: TCP

---
apiVersion: v1
kind: Pod
metadata:
  name: hello-kube-staging
  labels:
    enviroment: staging # label with key is enviroment and value is staging
    project: kubernetes-series
spec:
  containers:
    - image: 080196/hello-kube
      name: hello-kube
      ports:
        - containerPort: 3000
          protocol: TCP

---
apiVersion: v1
kind: Pod
metadata:
  name: hello-kube-production
  labels:
    enviroment: production # label with key is enviroment and value is production
    project: kubernetes-series
spec:
  containers:
    - image: 080196/hello-kube
      name: hello-kube
      ports:
        - containerPort: 3000
          protocol: TCP

kubectl apply -f hello-kube.yaml

We can list pods with labels as follows

kubectl get pod --show-labels

We can select the exact label column to display with -L options

kubectl get pod -L enviroment

And we can filter pods by label with -l options

kubectl get pod -l enviroment=production

Labels are a great way for us to organize pods the way we want and easily manage pods between different environments and projects. To clear the resource, let's delete the pod

kubectl delete -f hello-kube.yaml

Divide resources of kubernetes cluster using namespace

At this point, we know how to run pods and use labels to organize pods, but we haven't yet divided resources between different environments and projects. For example, in a project, we want production resources to be more than testing resources, so how do we do that? We will use namespace

Namespace is a way for us to divide the cluster's resources, and group all related resources together. You can understand namespace as a sub-cluster. First we list out all namespaces

kubectl get ns

We will see that there are several namespaces created by kube, including namespaces named default, kube-system. The default namespace is the namespace we are working with. When we use the kubectl get command to display resources, it will implicitly understand that we want to get the resource of the default namespace. We can specify the resource of the namespace we want by adding the --namespace option

kubectl get pod --namespace kube-system

Now we will try to create a namespace and create a pod in that namespace. A good way to organize namespaces is to create them according to <project_name>:<enviroment>. For example: mapp-testing, mapp-staging, mapp-production, kala-testing, kala-production. To do this quickly here, I will not set the namespace in the above way

kubectl create ns testing

Edit the hello-kube.yaml file

apiVersion: v1
kind: Pod
metadata:
  name: hello-kube-testing
  namespace: testing # namespace name
spec:
  containers:
    - image: 080196/hello-kube
      name: hello-kube
      ports:
        - containerPort: 3000
          protocol: TCP

Now if we list pods without specifying a testing namespace, we won't see any pods

To list pods, we must specify the namespace we want to get

kubectl get pod -n testing

So we have successfully created the pod in namespace testing. Let's delete the pod. When deleting, we also need to specify the namespace containing our resource.

kubectl delete pod hello-kube-testing -n testing

You can also delete a namespace by using the delete command. Note that when you delete a namespace, all resources in it will also be deleted.

kubectl delete ns testing

Using namespaces we can organize and manage the division of resources between different environments and projects more easily.

Last updated