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 object
  • kind: Object type
  • meta: Object information
    • name: 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, ie Deployment.
  • 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

Other materials

Previous Post Next Post

Kubernetes configuration files