You will learn:
- create and publish the NGINX web server.
- use namespaces.
- create and modify Kubernetes
Service
andDeployment
objects using configuration files.
This is just an example. In a real deployment, you usually do not need to use your own Web server to publish the HTTP service, but rather use an Ingress object.
In the configuration file we define the desired state of the application (not the sequence of commands how to achieve it).
We can modify and reapply the configuration with a simple command. Kubernetes will make sure that the condition of the object is adjusted as needed. If the configuration has not changed, nothing will be done. Otherwise, only those changes that are necessary and possible will be made. If the configuration change cannot be made, e.g. due to dependencies on other objects, it is easy to delete the entire object and recreate it.
We can use configuration files to mark the desired state each object and save it to the GIT repository, for example. In the event of an accident or service intervention on the hardware, we can repeat the entire installation at another location as needed at another cloud service provider.
YAML markup language
We write configuration files in YAML format.
YAML is markup language for writing structured data It's easy to learn and concise (unlike XML). It resembles the notation JSON. Recognizes these data types: numbers, strings, lists, and associative fields.
The structure in YAML is characterized by indentation at the beginning, we don't have to use any parentheses or quotes.
Writing is easy:
attribute1: string
list:
- item 2
- item 2
number: 4
object:
parameter1: value 1
object_list:
- o1_parameter1: value2
o1_parameter2: value2
- o2_parameter1: value1
o2_parameter2: value2
See the configuration of the created object
Return to the deployment created last time. If it doesn't work, re-create it:
kubectl create deployment hello-kube --image=k8s.gcr.io/echoserver:1.10
You can also view the current object configuration in YAML format:
kubectl get deployment hello-kube -o yaml
See what the configuration of the object looks like.
Each Kubernetes object has the following attributes defined:
apiVersion
: API version used by the objectkind
: Object typemeta
: Object informationname
: Object name - what will be displayed inkubectl get
labels
: object label list - identity for other Kubernetes objects
spec
: object specification
In addition to these parameters, you will find many others there. You can see their meaning in the documentation for the [Deployment] object (https://kubernetes.io/docs/concepts/workloads/controllers/deployment/).
We will show you how to create a minimum configuration of an object of type Deployment
. The values of the other parameters are determined by the Kubernetes system.
Preparation
It is a good idea to have a separate folder for files created during the exercise:
cd zkt24
mkdir cv7
cd cv7
You can easily mark files on the GIT.
Namespace
It is possible that more than one application is running on one cluster at a time. The objects we have created so far have been placed in the default default
namespace. Over time, there may be too many objects in the default namespace. Unless otherwise stated, all kubectl
statements refer to the default namespace.
To make the administration and management of objects belonging to the application easier, we can organize objects into namespaces.
We can store all related objects in one namespace, e.g. belongs to one application. Namespaces allow you to manage one application without affecting another, unrelated application running on the same cluster.
See a list of all namespaces and the contents of the kube-system
namespace:
kubectl get namespaces
Select a specific namespace with the -n
switch:
kubetcl get all -n kube-system
The processes that belong to the cluster administration are located in the kube-system
namespace. The objects created so far are located in the default
namespace.
We create a namespace named cv7
with the command:
kubectl create namespace cv7
If we want to select the namespace we created, we use the -n
switch.
This is how we find out that the new namespace is still empty.
kubectl get all -n cv7
More about namespaces can be found in the official documentation.
You can use the kubectx and kubens tools to make it easier to switch between namespaces and between multiple clusters.
Configuration file for Kubernetes object
We can use a configuration file to describe an object much more accurately than with multiple command line arguments.
All required must go to the configuration file
items:
apiVersion
: TheapiVersion
item contains the used API version, which we read from the documentation.meta
: Enter the name of the object in themeta
attribute, mainly for our use.kind
: The item type goes tokind
, ieDeployment
.spec
: In the itemspec
we will enter a more detailed specification - the number of instances of pods to be created and the template according to which the pods will be created.
Let's write a simple object of type Deployment
. This is a similar process to writing the kubectl create
command,
but we can influence more parameters.
Create a text file nginx-deployment.yaml
and write in it:
# See the API version for documentation
apiVersion: apps/v1
# Object type
kind: Deployment
# About the object
metadata:
# Object name
name: nginxdep
# object specification
spec:
# The number of pods to create
replicas: 1
# The selector creates a Deployment and Pod link
# Selects those PODs that have the tag nginx
selector:
matchLabels:
app: nginx
# POD template
template:
metadata:
# POD label - to connect Deployment and Pod
labels:
app: nginx
spec:
# POD containers
containers:
# Only one nginx container
- name: nginx
# Image name and version
image: nginx:1.14.2
ports:
# POD has port 80 open
- containerPort: 80
# If necessary, we will list another one here
# container configuration, e.g. volume mapping
# or environment variables
You can create an object using the command:
kubectl apply -f nginx-deployment.yaml -n cv7
Verify the new cluster status using commands
get
,logs
and describe
:
kubectl get deployments/nginxdep -n cv7
kubectl describe deployments/nginxdep -n cv7
The survey shows that the Deployment
object also created theReplicaSet
object and it created an Pod
object.
Pod is created according to the template in the template
section and has an automatically generated name, derived from the deployment name.
For more information on how to create a Deployment
object, see the official documentation.
Creating a service within a cluster
For deployment, it is also necessary to create a service so that the container ports are accessible to other containers or to users.
The service is a symbolic name and port number under which functionality is available within or outside the cluster.
As with deployment, we need to specify which pods
will perform the service. We define the group of data related to the service using the selector
item in themeta
section.
Create the file nginx-service.yaml
and write in it:
# API version from documentation
apiVersion: v1
# Object type
kind: Service
# object information
metadata:
# Service name
name: nginxservice
# Service specification
spec:
# Which pods perform the service
selector:
app: nginx
# Service ports
ports:
- protocol: TCP
# Service port
port: 8800
# Port on Pod
targetPort: 80
This service will create a valid nginxservice
DNS name within the cluster. The service will connect all ports 80 on the slots labeled app: nxinx
with a DNS name ofnginxservice
and port 8800.
More about how DNS names are assigned can be found in the official documentation
The IP address with the service valid within the cluster can also be found using the environment variable in the container.
You can verify the functionality of the service by running the command line in a running container and testing the HTTP request.
Create a new container (the service is not accessible from the container that provides the service) and try the service from it
nginxservice
:
# Create a new container
kubectl create deployment inspector --image=k8s.gcr.io/echoserver:1.10 -n cv7
# Find the name of the pod
kubectl get pod
# Run the command line in the pod
kubectl exec -it <pod_name> bash
# Network tools installation
apt-get update
apt-get install curl iputils-ping
# You are checking if the name is available
ping nginxservice
# You are testing an HTTP GET request on port 80
curl nginxservice:8800
# See defined environment variables
env
If you receive an error message when connecting:
Unable to use a TTY - input is not a terminal or the right kind of file
add kubectl exec`` winpty kubectl exec
.
For more information on how to create a service configuration, see the official documentation.
Service Disclosure
The service defined in this way is only available within the cluster.
In order for it to be available from the external environment on the port of any node in the cluster, its type must be set to NodePort
.
Modify the service configuration file:
apiVersion: v1
kind: Service
metadata:
name: nginxservice
spec:
# Indication of which pods will be pa
rub service
selector:
# Selects pods that have the label app=nginx
app: nginx
# The service type changes from ClusterIP to NodePort
type: NodePort
ports:
- protocol: TCP
# Port services within Kubernetes
port: 8800
# Container port
targetPort: 80
# Public port on each node
nodePort: 30880
Port 30880 will be open on each cluster node (if firewall rules allow). According to the agreement, the ports opened by the Kubernetes system must be in the range of 30000-32767.
Enter the IP address of the minicube and the port number 30880. Professionals use:
curl <IP>:30880
You can find more about orientation in Kubernetes virtual networks in the tutorial at Digital Ocean.
Troubleshoot object creation issues
If something is not working as expected, it is needed first identify the problem.
First, check the status of the cluster to see if it has been created all objects.
kubectl get all
If the object is created but not correct, check its status:
kubectl describe object_type/object_name
The status of the object will be displayed.
In the statement, focus on the "Conditions" and "Events" sections.
There you will find the names of the created child objects, e.g. ReplicaSet
.
If it's not right, keep looking. The problem may be in the child object, e.g. Deployment
depends onReplicaSet
and it depends on Pod
. You can find a list of child objects from the kubectl describe
statement.
In some cases, it makes sense to verify the logs:
kubectl logs <object_type>/<object_name>
This may indicate that you have a typo in the configuration file or that the connection to the database has failed.
If you still can't identify the problem, connect to the running command:
kubectl exec -it <pod_name> - sh
and from the command line try to execute a command that does not work for you. If it has more than one container, we will specify the container to be connected using the -c <container_name>
switch.
To find a list of environment variables in a container, use:
kubectl exec <pod name> env
It is possible that basic diagnostic tools are not available in the container, such as ping
orcurl
.
In this case, it is necessary to install them using the tools of the operating system in the container, e.g.
apt-get update
apt-get install <package name with command>
Deleting a namespace
Namespaces allow us to easily "clean up" the created objects.
This will delete the entire cv7
namespace, including all the objects in it. Before that, it's good to see what we're deleting.
kubectl get all -n cv7
kubectl delete namespace cv7