Book Image

Kubernetes – An Enterprise Guide - Second Edition

By : Marc Boorshtein, Scott Surovich
Book Image

Kubernetes – An Enterprise Guide - Second Edition

By: Marc Boorshtein, Scott Surovich

Overview of this book

Kubernetes has taken the world by storm, becoming the standard infrastructure for DevOps teams to develop, test, and run applications. With significant updates in each chapter, this revised edition will help you acquire the knowledge and tools required to integrate Kubernetes clusters in an enterprise environment. The book introduces you to Docker and Kubernetes fundamentals, including a review of basic Kubernetes objects. You’ll get to grips with containerization and understand its core functionalities such as creating ephemeral multinode clusters using KinD. The book has replaced PodSecurityPolicies (PSP) with OPA/Gatekeeper for PSP-like enforcement. You’ll integrate your container into a cloud platform and tools including MetalLB, externalDNS, OpenID connect (OIDC), Open Policy Agent (OPA), Falco, and Velero. After learning to deploy your core cluster, you’ll learn how to deploy Istio and how to deploy both monolithic applications and microservices into your service mesh. Finally, you will discover how to deploy an entire GitOps platform to Kubernetes using continuous integration and continuous delivery (CI/CD).
Table of Contents (17 chapters)
15
Other Books You May Enjoy
16
Index

Using the Docker CLI

You used the Docker CLI when you ran the hello-world container to test your installation. The Docker command is what you will use to interact with the Docker daemon. Using this single executable, you can do the following, and more:

  • Start and stop containers
  • Pull and push images
  • Run a shell in an active container
  • Look at container logs
  • Create Docker volumes
  • Create Docker networks
  • Prune old images and volumes

This chapter is not meant to include an exhaustive explanation of every Docker command; instead, we will explain some of the common commands that you will need to use to interact with the Docker daemon and containers. Since we consider volumes and networking to be very important topics to understand for this book, we will go into additional details on those topics.

You can break down Docker commands into two categories: general Docker commands and Docker management commands. The standard Docker commands allow you to manage containers, while management commands allow you to manage Docker options such as managing volumes and networking.

docker help

It's common to forget an option or the syntax for a command, and Docker realizes this. Whenever you get stuck trying to remember a command, you can always use the docker help command to refresh your memory.

docker run

To run a container, use the docker run command with the provided image name. Before executing a docker run command, you should understand the options you can supply when starting a container.

In its simplest form, an example command you can use to run an NGINX web server would be docker run bitnami/nginx:latest. While this will start a container running NGINX, it will run in the foreground, showing logs of the application running in the container. Press Ctrl + C to stop running the container:

nginx 22:52:27.42
nginx 22:52:27.42 Welcome to the Bitnami nginx container
nginx 22:52:27.43 Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-nginx
nginx 22:52:27.43 Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-nginx/issues
nginx 22:52:27.44
nginx 22:52:27.44 INFO  ==> ** Starting NGINX setup **
nginx 22:52:27.49 INFO  ==> Validating settings in NGINX_* env vars
nginx 22:52:27.50 INFO  ==> Initializing NGINX
nginx 22:52:27.53 INFO  ==> ** NGINX setup finished! **
 
nginx 22:52:27.57 INFO  ==> ** Starting NGINX **

To run a container as a background process, you need to add the -d option to your Docker command, which will run your container in detached mode. Now, when you run a detached container, you will only see the container ID, instead of the interactive, or attached, screen:

Figure 1.5 – Docker run output

Figure 1.3: Container ID displayed

[root@localhost ~]# docker run -d bitnami/nginx:latest
13bdde13d0027e366a81d9a19a56c736c28feb6d8354b363ee738d2399023f80
[root@localhost ~]#

By default, containers will be given a random name once they are started. In our previous detached example, the container has been given the name silly_keldysh:

CONTAINER ID      IMAGE                      NAMES
13bdde13d002      bitnami/nginx:latest       silly_keldysh

If you do not assign a name to your container, it can quickly get confusing as you start to run multiple containers on a single host. To make management easier, you should always start your container with a name that will make it easier to manage. Docker provides another option with the run command: the --name option. Building on our previous example, we will name our container nginx-test. Our new docker run command will be as follows:

docker run --name nginx-test -d bitnami/nginx:latest

Just like running any detached image, this will return the container ID, but not the name you provided. In order to verify the container ran with the name nginx-test, we can list the containers using the docker ps command.

docker ps

Every day, you will need to retrieve a list of running containers or a list of containers that have been stopped. The Docker CLI has an option called ps that will list all running containers, or if you add an extra option to the ps command, all containers that are running and have been stopped. The output will list the containers, including their container ID, image tag, entry command, the creation date, status, ports, and the container name. The following is an example of containers that are currently running:

Figure 1.4: Currently running containers

CONTAINER ID   IMAGE                  COMMAND                 CREATED
13bdde13d002   bitnami/nginx:latest   "/opt/bitnami/script…"  Up 4 hours
3302f2728133   registry:2             "/entrypoint.sh /etc…"  Up 3 hours

This is helpful if the container you are looking for is currently running. What if the container was stopped, or even worse, what if you started the container and it failed to start and then stopped? You can view the status of all containers, including previously run containers, by adding the -a option to the docker ps command. When you execute docker ps -a, you will see the same output from a standard ps command, but you will notice that the list may include additional containers.

How can you tell what containers are running versus which ones have stopped? If you look at the STATUS field of the list, the running containers will show a running time; for example, Up xx hours, or Up xx days. However, if the container has been stopped for any reason, the status will show when it stopped; for example, Exited (0) 10 minutes ago.

IMAGE                  COMMAND                  CREATED         STATUS
bitnami/nginx:latest   "/opt/bitnami/script…"   10 minutes ago  Up 10 minutes
bitnami/nginx:latest   "/opt/bitnami/script…"   12 minutes ago  Exited (0) 10 minutes ago

A stopped container does not mean there was an issue running the image. There are containers that may execute a single task and, once completed, the container may stop gracefully. One way to determine whether an exit was graceful or whether it was due to a failed startup is to check the logs of the container.

docker start and stop

To stop a running container, use the docker stop option with the name of the container you want to stop. You may wish to stop a container due to the resources on the host since you may have limited resources and can only run a few containers simultaneously.

If you need to start that container at a future time for additional testing or development, execute docker start container name, which will start the container with all of the options that it was originally started with, including any networks or volumes that were assigned.

docker attach

You may need to access a container interactively to troubleshoot an issue or to look at a log file. One method to connect to a running container is to use the docker attach container name command. When you attach to a running container, you will connect to the running container's process, so if you attach to a container running a process, you are not likely to just see a command prompt of any kind. In fact, you may see nothing but a blank screen for some time until the container outputs some data to the screen.

You must be careful once you attach to the container – you may accidentally stop the running process and, in turn, stop the container. Let's use an example of attaching to a web server running NGINX. First, we need to verify that the container is running using docker ps:

CONTAINER ID   IMAGE                 COMMAND                   STATUS
4a77c14a236a   nginx                 "/docker-entrypoint.…"    Up 33 seconds
3302f2728133   registry:2            "/entrypoint.sh /etc…"    Up 8 minutes
13bdde13d002   bitnami/nginx:latest  "/opt/bitnami/script…"    Up 14 minutes

Using the attach command, we execute docker attach 4a77c14a236a.

Once you attach to the running container process, it may appear that nothing is happening. When you attach to a process, you will only be able to interact with the process, and the only output you will see is data being sent to standard output. In the case of the NGINX container, the attach command has attached to the NGINX process. To show this, we will leave the attachment and curl to the web server from another session. Once we curl to the container port, you will see logs outputted to the attached console:

[root@astra-master manifests]# docker attach 4a77c14a236a 
172.17.0.1 - - [15/Oct/2021:23:28:31 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
172.17.0.1 - - [15/Oct/2021:23:28:33 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
172.17.0.1 - - [15/Oct/2021:23:28:34 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
172.17.0.1 - - [15/Oct/2021:23:28:35 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
172.17.0.1 - - [15/Oct/2021:23:28:36 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"

Attaching to a running container has varying benefits, depending on what is running in the container.

We mentioned that you need to be careful once you attach to the container. Those who are new to Docker may attach to the NGINX image and assume that nothing is happening on the server or the attach failed. Since they think that there may be an issue, since it's just sitting there, they may decide to break out of the container using the standard Ctrl + C keyboard command. This will send them back to a bash prompt, where they may run docker ps to look at the running containers:

root@localhost:~# docker ps
CONTAINER ID      IMAGE  COMMAND    CREATED    STATUS
root@localhost:~#

Where is the NGINX container? We didn't execute a docker stop command, and the container was running until we attached to the container. Why did the container stop after the attachment?

When an attachment is made to a container, you are attached to the running process. All keyboard commands will act in the same way as if you were at a physical server that was running NGINX in an interactive shell. This means that when the user used Ctrl + C to return to a prompt, they stopped the running NGINX process.

If a container's running process stops, the container will also stop, and that's why the docker ps command does not show a running container.

Rather than use Ctrl + C to return to a prompt, the user should have used Ctrl + P, followed by Ctrl + Q.

There is an alternative to the attach command: the docker exec command. The exec command differs from an attach command since you supply the process to execute on the container.

docker exec

A better option when it comes to interacting with a running container is the exec command. Rather than attach to the container, you can use the docker exec command to execute a process in the container. You need to supply the container name and the process you want to execute in the image. Of course, the process must be included in the running image – if you do not have the bash executable in the image, you will receive an error when trying to execute bash in the container.

We will use an NGINX container as an example again. We will verify that NGINX is running using docker ps and then, using the container ID or the name, we execute into the container. The command syntax is docker exec <options> <container name> <command>:

root@localhost:~# docker exec -it nginx-test bash
I have no name!@a7c916e7411:/app$

The option we included is -it, which tells exec to run in an interactive TTY session. Here, the process we want to execute is bash. Notice how the name changed from the original user and hostname. The hostname is localhost, while the container name is @a7c916e7411. You may also have noticed that the current working directory changed from ~ to /app and that the prompt is not running as a root user, as shown by the $ prompt.

You can use this session the same way you would a standard SSH connection; you are running bash in the container.

Since we are not attached to the container, Ctrl + C will not stop any process from running. To exit an interactive session, you only need to type in exit, followed by Enter, which will exit the container. If you then run docker ps, you will notice that the container is still in a running state.

Next, let's see what we can learn about Docker log files.

docker logs

The docker logs command allows you to retrieve logs from a container using the container name or container ID that you retrieved using the docker ps command. You can view the logs from any container that was listed in your ps command; it doesn't matter if it's currently running or stopped.

Log files are often the only way to troubleshoot why a container may not be starting up, or why a container is in an exited state. For example, if you attempted to run an image and the image starts and suddenly stops, you may find the answer by looking at the logs for that container.

To look at the logs for a container, you can use the docker logs <container ID or name> command.

To view the logs for a container with a container ID of 7967c50b260f, you would use the following command:

docker logs 7967c50b260f

This will output the logs from the container to your screen, which may be very long and verbose. Since many logs may contain a lot of information, you can limit the output by supplying the logs command with additional options. The following table lists the options available for viewing logs:

Logs Options

Description

-f

Follow the log output (can also use --follow).

--tail xx

Show log output starting from the end of the file and retrieve xx lines.

--until xxx

Show log output before the xxx timestamp.

xxx can be a timestamp; for example, 2020-02-23T18:35:13.

xxx can be a relative time; for example, 60m.

--since xxx

Show log output after the xxx timestamp.

xxx can be a timestamp; for example, 2020-02-23T18:35:13.

xxx can be a relative time; for example, 60m.

Table 1.1: Logs options

Checking log files is a process you will find yourself doing often, and since they can be very lengthy, knowing options like tail, until, and since will help you to find the information in a log quicker.

docker rm

Once you name a container, the assigned name cannot be used to start a different container unless you remove it using the docker rm command. If you had a container running called nginx-test that was stopped and you attempted to start another container with the name nginx-test, the Docker daemon would return an error, stating that the name is in use:

Conflict.  The container name "/nginx-test" is already in use

This container is not running, but the daemon knows that the container name was used previously and that it's still in the list of previously run containers.

If you want to reuse the same name, you need to remove the container before starting another container with that name. This is a common scenario when you are testing container images. You may start a container only to discover an issue with the application or image. You stop the container, fix the image/application issue, and want to redeploy using the same name. Since the name was in use previously and is still part of the Docker history, you will need to remove the container before reusing the name.

To remove the nginx-test container, simply execute docker rm nginx-test:

root@localhost ~:# docker rm nginx-test
nginx-test
root@localhost ~:#

Assuming the container name is correct and it's not running, the only output you will see is the name of the image that you have removed.

We haven't discussed Docker volumes, but when removing a container that has a volume, or volumes, attached, it's a good practice to add the -v option to your remove command. Adding the -v option to the docker rm command will remove any volumes that were attached to the container.