Proyecto final#

Equipo ARFA-FGFG-ROFM#

  1. Arganis Ramírez Francisco - 108003620
  2. Flores García Fernando - 314107035
  3. Romo Olea Fhernanda - 314284286

Explicación de la creación de imágenes de contenedor con Docker#

Creación de la cuenta en Docker Hub#

Cada miembro del equipo creó una cuenta en Docker Hub. Tras ingresar los datos de la cuenta se recibió un link en un correo para la verificación de la cuenta.

Correo de verificación
Correo de confirmación

A continuación se muestran los usuarios de todos los miembros del equipo:

Nombre Usuario de Ducker Hub
Francisco franciscoalejandro1
Fernando Fernandondin
Fhernanda 08102001

Verificación de la instalación de Docker#

Para verificar que Docker se instaló correctamente, se ejecutó el contenedor hello-world

fernandondin@fernandondin:~$ docker run -it hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:80f31da1ac7b312ba29d65080fddf797dd76acfb870e677f390d5acba9741b17
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

El comando anterior baja la imagen del repositorio remoto y al inicializarla indica que la instalación fue completada de forma correcta.

Contenedor con un servidor web#

A continuación se descargó la imagen de contenedor nginx

franciscoalejandro@ideapad:~$ docker pull nginx:1.22-alpine
1.22-alpine: Pulling from library/nginx
2408cc74d12b: Pull complete
481c89e12e19: Pull complete
b6d5148443a7: Pull complete
829bc8d62f51: Pull complete
ace64a3c442d: Pull complete
5f1edd2b5d2c: Pull complete
Digest: sha256:f335d7436887b39393409261603fb248e0c385ec18997d866dd44f7e9b621096
Status: Downloaded newer image for nginx:1.22-alpine
docker.io/library/nginx:1.22-alpine
franciscoalejandro@ideapad:~$

y se ejecutó con el comando docker run, usando la opción -it para mostrar en pantalla la salida del proceso

franciscoalejandro@ideapad:~$ docker run -it -p 8080:80 docker.io/library/nginx:1.22-alpine
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/06/15 01:14:47 [notice] 1#1: using the "epoll" event method
2022/06/15 01:14:47 [notice] 1#1: nginx/1.22.0
2022/06/15 01:14:47 [notice] 1#1: built by gcc 11.2.1 20220219 (Alpine 11.2.1_git20220219)
2022/06/15 01:14:47 [notice] 1#1: OS: Linux 5.10.104-linuxkit
2022/06/15 01:14:47 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/06/15 01:14:47 [notice] 1#1: start worker processes
2022/06/15 01:14:47 [notice] 1#1: start worker process 31
2022/06/15 01:14:47 [notice] 1#1: start worker process 32
2022/06/15 01:14:47 [notice] 1#1: signal 28 (SIGWINCH) received
2022/06/15 01:14:47 [notice] 31#31: signal 28 (SIGWINCH) received
2022/06/15 01:14:47 [notice] 32#32: signal 28 (SIGWINCH) received
172.17.0.1 - - [15/Jun/2022:01:15:42 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0" "-"
2022/06/15 01:15:43 [error] 31#31: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
172.17.0.1 - - [15/Jun/2022:01:15:43 +0000] "GET /favicon.ico HTTP/1.1" 404 153 "http://localhost:8080/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0" "-"
172.17.0.1 - - [15/Jun/2022:01:15:57 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "-"

Mientras el contenedor se ejecutaba, en otra terminal se usó el comando docker ps para mostrar la lista de contenedores actuales

franciscoalejandro@ideapad:~$ docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                  NAMES
ac81aa71dc10   nginx:1.22-alpine   "/docker-entrypoint.…"   43 seconds ago   Up 40 seconds   0.0.0.0:8080->80/tcp   agitated_germain
franciscoalejandro@ideapad:~$

y verificar que respondiera el servicio en localhost:8080, tanto por terminal con el comando curl

franciscoalejandro@ideapad:~$ curl -fsSL http://localhost:8080/ | egrep '</?title>'
<title>Welcome to nginx!</title>
franciscoalejandro@ideapad:~$

como por un navegador, como se muestra en la siguiente imagen.

Página de nginx en localhost:8080

Creación de las imágenes con docker build#

Primero se documentaron los archivos Dockerfile, uno para la documentación de Linux y otro para el sitio de tareas, agregando comentarios que describen cada instrucción.

Para la imagen de la documentación de Linux, se estableció la variable de entorno TAG con el nombre del usuario de Docker Hub y el nombre de la imagen linux-doc y se ejecutó el comando docker build con la opción --progress plain para mostrar en pantalla cada paso del proceso y la opción -t "${TAG}" para especificar que se use la variable TAG como nombre de la nueva imagen.

franciscoalejandro@ideapad:~$ TAG=franciscoalejandro1/linux-doc
franciscoalejandro@ideapad:~$ docker build --progress plain -t "${TAG}" ./

La salida de completa de estos comandos para crear la imagen linux-doc se encuentra aquí.

Para la imagen del sitio de tareas, se estableció la variable de entorno TAG con el nombre del usuario de Docker Hub y el nombre de la imagen tarea-redes y se ejecutó el comando docker build con las mismas opciones.

franciscoalejandro@ideapad:~$ TAG=franciscoalejandro1/tareas-redes
franciscoalejandro@ideapad:~$ docker build --progress plain -t "${TAG}" ./

La salida de completa de estos comandos para crear la imagen tareas-redes se encuentra aquí.

Se verificó que ambas imágenes aparecen al usar docker images, comando que lista las imágenes disponibles

franciscoalejandro@ideapad:~$ docker images
REPOSITORY                         TAG           IMAGE ID       CREATED          SIZE
franciscoalejandro1/tareas-redes   latest        dd121b8e68b6   58 seconds ago   41MB
franciscoalejandro1/linux-doc      latest        10fa1df61e68   6 minutes ago    171MB
nginx                              1.22-alpine   4341472ddfe8   2 weeks ago      23.4MB
hello-world                        latest        feb5d9fea6a5   8 months ago     13.3kB
franciscoalejandro@ideapad:~$

y que al ejecutarlas en un contenedor con docker run -p 8080:80 franciscoalejandro1/linux-doc y docker run -p 8080:80 franciscoalejandro1/tareas-redes se tuviese respuesta en localhost:8080.

Docmuentación de Linux en localhost:8080 al ejecutar un contenedor de linux-doc
Sitio de tareas en localhost:8080 al ejecutar un contenedor de tareas-redes

Envío de las imágenes de contenedor a Docker Hub#

Se inció sesión con el comando docker login, con las credenciales de la cuenta creada anteriormente. Después se estableció la variable de entorno TAG al nombre de las imágenes de contenedor creadas y se usó el comando docker push con "${TAG}" para especificar el nombre de imagen a usar.

franciscoalejandro@ideapad:~$ TAG=franciscoalejandro1/linux-doc
franciscoalejandro@ideapad:~$ docker push "${TAG}"
Using default tag: latest
The push refers to repository [docker.io/franciscoalejandro1/linux-doc]
c3b9be855df0: Pushed
52f1ecfe1f3d: Mounted from library/nginx
9a67efa4e6c3: Mounted from library/nginx
9459445e6c18: Mounted from library/nginx
727fbf2dbefa: Mounted from library/nginx
a6a1040682a8: Mounted from library/nginx
24302eb7d908: Mounted from library/python
latest: digest: sha256:57b06e3431a41b76d4a72b9065f5b1ec21e2c8ada1d61696c8d8a5fcf539f4cd size: 1780
franciscoalejandro@ideapad:~$
franciscoalejandro@ideapad:~$ TAG=franciscoalejandro1/tareas-redes
franciscoalejandro@ideapad:~$ docker push "${TAG}"
Using default tag: latest
The push refers to repository [docker.io/franciscoalejandro1/tareas-redes]
3b54539e02ce: Pushed
52f1ecfe1f3d: Mounted from franciscoalejandro1/linux-doc
9a67efa4e6c3: Mounted from franciscoalejandro1/linux-doc
9459445e6c18: Mounted from franciscoalejandro1/linux-doc
727fbf2dbefa: Mounted from franciscoalejandro1/linux-doc
a6a1040682a8: Mounted from franciscoalejandro1/linux-doc
24302eb7d908: Mounted from franciscoalejandro1/linux-doc
latest: digest: sha256:9985938d4dbdd6b9de2dc7773d4a5b9e6a6f800b06c69ee132082b7c730752bd size: 1780
franciscoalejandro@ideapad:~$

Finalmente, se verificó que las imágenes aparecen en el registry de Docker Hub

Ambas imágenes en el registry de Docker Hub

Explicación del proceso de instalación de k3s en Debian 11 + krew#

Preparación de la máquina virtual para la instalación de k3s#

Ya que la máquina virtual de Azure que se tiene displonible es muy limitada en RAM, se redujo su uso de memoria como se describe en la bitácora preparacion-vm.txt.

Descarga del script de instalación de k3s#

Se escaneó la liga https://get.k3s.io/ del script de instalación de k3s en la página virustotal.com. El resultado del escaneo se muestra en la siguiente imagen

Captura del sitio virustotal.com al escanear la URL de descarga

Tras corroborar que el archivo en la liga no tiene contenido malicioso, se descargó el script de instalación y se le otorgó permiso de ejecución

redes@tacosdorados:~$ wget -c -nv -O ~/get-k3s-io.sh https://get.k3s.io/
2022-06-15 10:55:19 URL:https://get.k3s.io/ [27527/27527] -> "/home/redes/get-k3s-io.sh" [1]
redes@tacosdorados:~$ chmod -c +x ./get-k3s-io.sh
mode of './get-k3s-io.sh' changed from 0644 (rw-r--r--) to 0755 (rwxr-xr-x)

Ejecución del script de instalación de k3s#

Se utilizaron las variables de entorno INSTALL_K3S_SKIP_START y INSTALL_K3S_EXEC para personalizar la instalación de ks3. Establecer INSTALL_K3S_SKIP_START a true hace que no se inicie la ejecución de k3s inmediatamente después de terminar la instalación. INSTALL_K3S_EXEC se usa para indicar banderas con las que se va a ejecutar k3s:

  • --tls-san agrega un hostname o IP como alias al certificado TLS
  • --disable-cloud-controller deshabilita el administrator de controlador de la nube de k3s predeterminado
  • --disable se usa para que no despliegue el componente especificado

(el controlador de la nube, metric-server, servicelb y traefik no son indispensables y consumen memoria adicional)

redes@tacosdorados:~$ export INSTALL_K3S_SKIP_START="true"
redes@tacosdorados:~$ export INSTALL_K3S_EXEC="--tls-san='k3s.tacosdorados.cf' --tls-san='20.213.119.72' --disable-cloud-controller --disable=metrics-server --disable=servicelb --disable=traefik"

Con las variables de entorno anteriores, se ejecutó el script de instalación de ks3

redes@tacosdorados:~$ ~/get-k3s-io.sh

[INFO]  Finding release for channel stable
[INFO]  Using v1.23.6+k3s1 as release
[INFO]  Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.23.6+k3s1/sha256sum-amd64.txt
[INFO]  Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.23.6+k3s1/k3s
[INFO]  Verifying binary download
[INFO]  Installing k3s to /usr/local/bin/k3s
[INFO]  Skipping installation of SELinux RPM
[INFO]  Creating /usr/local/bin/kubectl symlink to k3s
[INFO]  Creating /usr/local/bin/crictl symlink to k3s
[INFO]  Creating /usr/local/bin/ctr symlink to k3s
[INFO]  Creating killall script /usr/local/bin/k3s-killall.sh
[INFO]  Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO]  env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s.service
[INFO]  systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.

Variables de entorno para ks3#

Se redujo aún más el consumo de RAM aumentando la frecuencia del recolector de basura, como se sugiere aquí

root@tacosdorados:~# cat /etc/systemd/system/k3s.service.env
# Aggressive garbage collector
GOGC=10

Se inició el servicio ks3 tras reiniciar la máquina y se verificó que se estuviera ejecutando con systemctl status

root@tacosdorados:~# PAGER=cat systemctl status --full k3s
● k3s.service - Lightweight Kubernetes
     Loaded: loaded (/etc/systemd/system/k3s.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-06-15 11:04:40 CDT; 41s ago
       Docs: https://k3s.io
   Main PID: 569 (k3s-server)
      Tasks: 66
     Memory: 623.4M
        CPU: 18.983s
     CGroup: /system.slice/k3s.service
             ├─ 569 /usr/local/bin/k3s server
             ├─ 640 containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd
             ├─1107 /var/lib/rancher/k3s/data/8c2b0191f6e36ec6f3cb68e2302fcc4be850c6db31ec5f8a74e4b3be403101d8/bin/containerd-shim-runc-v2 -namespace k8s.io -id c9004b4e1577cf8675c18e3a8cc2af4230535305caeaa862564e926b77a314ca -address /run/k3s/containerd/containerd.sock
             └─1120 /var/lib/rancher/k3s/data/8c2b0191f6e36ec6f3cb68e2302fcc4be850c6db31ec5f8a74e4b3be403101d8/bin/containerd-shim-runc-v2 -namespace k8s.io -id 2fad1a648f16fdefcb37a394dc03fac4816ddb28745201a5dda5d7df2e027a76 -address /run/k3s/containerd/containerd.sock

Nótese que en la línea 5, contando de arriba hacia abajo, se especifica que el estado del servicio ya se encuentra en activo.

Se verificó a continuación que servidor del API de Kubernetes esucha en el puerto 6443, con netstat. En la salida puede verse que efectivamente el puerto solicitado se encuentra abierto y a la escucha.

root@tacosdorados:~# netstat -ntulp | grep 6443
tcp6       0      0 :::6443                 :::*                    LISTEN      569/k3s server

Se agregó el usuario redes al grupo staff y se cambió el propietario a root y los permisos a solo lectura del archivo /etc/rancher/ks3/ks3.yaml

root@tacosdorados:~# adduser redes staff

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
    LANGUAGE = (unset),
    LC_ALL = (unset),
    LC_TERMINAL = "iTerm2",
    LC_CTYPE = "UTF-8",
    LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
Adding user `redes' to group `staff' ...
Adding user redes to group staff
Done.

root@tacosdorados:~# chown -c root:staff /etc/rancher/k3s/k3s.yaml

changed ownership of '/etc/rancher/k3s/k3s.yaml' from root:root to root:staff

root@tacosdorados:~# chmod -c 0440 /etc/rancher/k3s/k3s.yaml

mode of '/etc/rancher/k3s/k3s.yaml' changed from 0600 (rw-------) to 0440 (r--r-----)

Generamos una liga simbólica al archivo k3s.yaml.

root@tacosdorados:~# mkdir -vp ~/.kube
mkdir: created directory '/root/.kube'

root@tacosdorados:~# ln -vsf /etc/rancher/k3s/k3s.yaml ~/.kube/config

'/root/.kube/config' -> '/etc/rancher/k3s/k3s.yaml'

Acciones ejecutadas por el usuario redes, se copia el archivo anterior al directorio y ajustamos los permisos necesarios.

root@tacosdorados:~# su - redes
redes@tacosdorados:~$

redes@tacosdorados:~$ mkdir -vp ~/.kube
mkdir: created directory '/home/redes/.kube'

redes@tacosdorados:~$ sudo cp -v /etc/rancher/k3s/k3s.yaml ~/.kube/config
'/etc/rancher/k3s/k3s.yaml' -> '/home/redes/.kube/config'

redes@tacosdorados:~$ sudo chown -c redes:staff ~/.kube/config
changed ownership of '/home/redes/.kube/config' from root:root to redes:staff

Conexión al cluster desde la máquina virtual#

Se verificó que la herramiento de línea de comandos de Kubernetes, kubectl, se instaló correctamente en la máquina virtual.

Para esto, se confirmó que:

  • Se puede encontrar el binario de kubectl en el directorio /usr/local/bin/kubectl con which.
redes@tacosdorados:~$ which kubectl
/usr/local/bin/kubectl
  • La versión instalada de kubectl es la 1.23.6.
redes@tacosdorados:~$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6+k3s1", GitCommit:"418c3fa858b69b12b9cefbcff0526f666a6236b9", GitTreeState:"clean", BuildDate:"2022-04-28T22:16:18Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6+k3s1", GitCommit:"418c3fa858b69b12b9cefbcff0526f666a6236b9", GitTreeState:"clean", BuildDate:"2022-04-28T22:16:18Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
  • Se tiene conexión al cluster, para lo cual se usa el comando de kubectl para listar los nodos del cluster get nodes. La opción -o wide especifica que la salida muestre información adicional, incluyendo las direcciones IP, el sistema operativo y los datos del contenedor que se ejecuta.
redes@tacosdorados:~$ kubectl get nodes -o wide
NAME              STATUS   ROLES                  AGE     VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION          CONTAINER-RUNTIME
tacosdorados.cf   Ready    control-plane,master   8m25s   v1.23.6+k3s1   10.0.0.4      <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-15-cloud-amd64   containerd://1.5.11-k3s2

Se observa en la salida anterior que hay conexión pues se reporta un nodo en el cluster. Este nodo, en la máquina virtual, ejecuta el contenedor de k3s y funciona como el elemento de administración del cluster (se encargará de planificar y organizar los pods).

En el portal de Azure se abre el puerto 6443.

Vista de las reglas de seguridad desde el portal de Azure

Instalación de kubectl y krew#

Se instaló kubectl en el equipo local y krew tanto en el equipo local como en la máquina virtual, como se describe en la bitácora instalacion-kubectl-krew.txt.

Conexión al cluster desde el equipo local#

Se copió desde la máquina virtual el archivo ~/.kube/config (con la información para conectarse al servidor de Kubernetes) al equipo local como ~/Downloads/redes-kube-config.yaml. El archivo se editó reemplazando https://127.0.0.1:6443 por https://k3s.tacosdorados.cf:6443 (el nombre DNS de la máquina virtual) en este archivo, con el comando sed.

franciscoalejandro@ideapad:~$ sed -i'' -e 's/127.0.0.1/k3s.tacosdorados.cf/g' ~/Downloads/redes-kube-config.yaml

Se agregó la línea export KUBECONFIG=~/Downloads/redes-kube-config.yaml al archivo ~/.bashrc en el equipo local y se verificó que se puede encontrar la ruta al archivo de configuración de kubectl en el shell.

franciscoalejandro@ideapad:~$ echo $KUBECONFIG
/home/franciscoalejandro/Downloads/redes-kube-config.yaml
franciscoalejandro@ideapad:~$

A continuación se comprobó la conexión a k3s.tacosdorados.cf en el puerto 6443 usando netcat.

franciscoalejandro@ideapad:~$ nc -vz k3s.tacosdorados.cf 6443
Connection to k3s.tacosdorados.cf 6443 port [tcp/*] succeeded!
franciscoalejandro@ideapad:~$

Y que coinciden las versiones (1.23.6) del cliente y servidor con kubectl version. La opción --insecure-skip-tls-verify=false evita la omisión de verificación del certificado SSL del servidor API del cluster de Kubernetes.

franciscoalejandro@ideapad:~$ kubectl version --insecure-skip-tls-verify=false
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6", GitCommit:"ad3338546da947756e8a88aa6822e9c11e7eac22", GitTreeState:"clean", BuildDate:"2022-04-14T08:49:13Z", GoVersion:"go1.17.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6+k3s1", GitCommit:"418c3fa858b69b12b9cefbcff0526f666a6236b9", GitTreeState:"clean", BuildDate:"2022-04-28T22:16:18Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
franciscoalejandro@ideapad:~$

Por último, se listaron los nodos del cluster de Kubernetes con get nodes

franciscoalejandro@ideapad:~$ kubectl get nodes
NAME              STATUS   ROLES                  AGE     VERSION
tacosdorados.cf   Ready    control-plane,master   3h19m   v1.23.6+k3s1
franciscoalejandro@ideapad:~$

lo cual coincide con la lista que se muestra en la máquina virtual.

redes@tacosdorados:~$ kubectl get node
NAME              STATUS   ROLES                  AGE     VERSION
tacosdorados.cf   Ready    control-plane,master   3h21m   v1.23.6+k3s1
redes@tacosdorados:~$

Explicación del proceso de instalación del ingress controller en el cluster#

Instalación y configuración de ingress-nginx#

Primero se estableció la variable de entorno INGRESS_NGINX_VERSION para especificar la versión y se descargó el archivo YAML con la definición de los recursos de Kubernetes para el ingress controller

franciscoalejandro@ideapad:~$ INGRESS_NGINX_VERSION=v1.2.0
franciscoalejandro@ideapad:~$ wget -c -nv -o ingress-nginx-${INGRESS_NGINX_VERSION}.yaml  https://github.com/kubernetes/ingress-nginx/raw/controller-${INGRESS_NGINX_VERSION}/deploy/static/provider/cloud/deploy.yaml

Se instaló ingress-nginx con kubectl apply y el YAML que se descargó. El comando apply aplica una configuración a recursos según se especifica en el archivo o por la entrada estándar. Si no exísten previamente, crea los recursos especificados en el archivo de configuración.

franciscoalejandro@ideapad:~$ kubectl apply -f ingress-nginx-${INGRESS_NGINX_VERSION}.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
franciscoalejandro@ideapad:~$

Para abrir los puesrtos 80 (HTTP) y 443 (HTTPS), se aplicó un parche para actualizar los campos del recurso deployment/ingress-nginx-controller recien creado, estableciendo la opción hostNetwork a true.

franciscoalejandro@ideapad:~$ kubectl patch deployment/ingress-nginx-controller -n ingress-nginx --patch '{"spec":{"template":{"spec":{"hostNetwork":true}}}}'
deployment.apps/ingress-nginx-controller patched
franciscoalejandro@ideapad:~$

Se usó el comando wait para esperar (máximo 3 minutos con la opción --timeout=180s) a que el pod de ingress-nginx tuviera estado ready y pudiera recibir conexiones.

franciscoalejandro@ideapad:~$ kubectl wait --namespace ingress-nginx  --for=condition=ready pod  --selector=app.kubernetes.io/component=controller  --timeout=180s
pod/ingress-nginx-controller-7ff499d7dc-sq955 condition met
franciscoalejandro@ideapad:~$

Verificación de la instalación y configuración#

Se verificó lo siguiente:

  • Que en la máquina virtual, nginx escucha en los puertos 80 y 443, con netstat.
root@tacosdorados:~# netstat -ntulp | egrep -w '80|443'
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      7535/nginx: master
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      7535/nginx: master
tcp6       0      0 :::80                   :::*                    LISTEN      7535/nginx: master
tcp6       0      0 :::443                  :::*                    LISTEN      7535/nginx: master
root@tacosdorados:~#
  • El estado READY del deployment es 1/1, con get deployments
franciscoalejandro@ideapad:~$ kubectl get deployments -n ingress-nginx
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx-controller   1/1     1            1           49m
franciscoalejandro@ideapad:~$
  • El estado del pod de ingress-nginx es Running, con get pods
franciscoalejandro@ideapad:~$ kubectl get pods -n ingress-nginx --field-selector=status.phase==Running
NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-7ff499d7dc-sq955   1/1     Running   0          46m
franciscoalejandro@ideapad:~$
  • ingress-nginx-controller aparece en la lista de servicios activos, con get service
franciscoalejandro@ideapad:~$ kubectl get service ingress-nginx-controller -n ingress-nginx
NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.43.223.0   <pending>     80:31949/TCP,443:32641/TCP   66m
franciscoalejandro@ideapad:~$
  • Que hay conexión a tacosdorados.cf en los puertos 80 y 443, como se describe en la bitácora conexion-puertos.txt.

  • Que ingress-nginx responde a peticiones HTTP, con curl y un navegador

franciscoalejandro@ideapad:~$ curl -vk# 'http://tacosdorados.cf/'
* TCP_NODELAY set
* Connected to tacosdorados.cf (20.213.119.72) port 80 (#0)
> GET / HTTP/1.1
> Host: tacosdorados.cf
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Date: Wed, 15 Jun 2022 23:15:23 GMT
< Content-Type: text/html
< Content-Length: 146
< Connection: keep-alive
<
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host tacosdorados.cf left intact
franciscoalejandro@ideapad:~$
Respuesta HTTP 404 al acceder a http://tacosdorados.cf/

Se realizó también la prueba de acceso utilizando curl, al no haber aún configurado nada, es normal que obtengamos un código de error HTTP Not Found.

Explicación del proceso de despliegue de los sitios web en el cluster de Kubernetes#

Sitio web default#

Primero se creó el configmap index-equipo-arfa-fgfg-rofm usando el comando create configmap que asocia el valor del contenido del archivo index.html con su nombre como llave

franciscoalejandro@ideapad:~$ kubectl create configmap index-equipo-arfa-fgfg-rofm --from-file=index.html
configmap/index-equipo-arfa-fgfg-rofm created
franciscoalejandro@ideapad:~$

Se creó el nuevo deployment root-nginx usando el comando create deployment, especificando con --image que corre la imagen de contenedor nginx y con --port que escucha en el puerto 80

franciscoalejandro@ideapad:~$ kubectl create deployment root-nginx --image=nginx --port=80
deployment.apps/root-nginx created
franciscoalejandro@ideapad:~$

y se verificó que el pod de root-nginx creado en el paso anterior tuviera estado Running con get pods

franciscoalejandro@ideapad:~$ kubectl get pods -l app=root-nginx
NAME                          READY   STATUS    RESTARTS   AGE
root-nginx-68778df5d4-f2hf8   1/1     Running   0          3m52s
franciscoalejandro@ideapad:~$

Posteriormente se asignó el volúmen de la página de índice al deployment del servidor web, editando el deployment root-nginx con edit.

franciscoalejandro@ideapad:~$ kubectl edit deployment/root-nginx
deployment.apps/root-nginx edited
franciscoalejandro@ideapad:~$

En el archivo YAML de root-nginx se agregaron las líneas, se puso especial cuidado en identar correctamente.

      volumes:
      - name: index-equipo-arfa-fgfg-rofm
        configMap:
          name: index-equipo-arfa-fgfg-rofm

en spec:template:spec: y las líneas

        volumeMounts:
        - name: index-equipo-arfa-fgfg-rofm
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html

en spec:template:spec:containers:. Esto cambios montan el configmap index-equipo-arfa-fgfg-rofm que referencia a la página de índice.

Se verificó la creación de un nuevo pod para el deployment root-nginx con la nueva configuración. El pod antes de montar el configmap era root-nginx-68778df5d4-f2hf8 y después fue root-nginx-7df598fdcb-rqbqw

franciscoalejandro@ideapad:~$ kubectl get pods -l app=root-nginx
NAME                          READY   STATUS    RESTARTS   AGE
root-nginx-7df598fdcb-rqbqw   1/1     Running   0          8m28s
franciscoalejandro@ideapad:~$

Se usó el comando port-forward para que peticiones al puerto 8080 en el equipo local se redirijan al pod de root-nginx, que escucha en el puerto 80

franciscoalejandro@ideapad:~$ kubectl port-forward deployment/root-nginx 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080

Con la redirección activa se confirmó en un navegador que el pod responde las peticiones HTTP con la página index.html

Respuesta del pod de root-nginx en localhost:8080 con la página índice

Sitio de la página de documentación del kernel Linux#

Se creó el nuevo deployment linux-doc con create deployment. Se usó la imagen de contenedor franciscoalejandro1/linux-doc creada previamente y se indicó que escucha en el puerto 80

franciscoalejandro@ideapad:~$ CONTAINER_IMAGE="franciscoalejandro1/linux-doc"
franciscoalejandro@ideapad:~$ kubectl create deployment linux-doc --image="${CONTAINER_IMAGE}" --port=80
deployment.apps/linux-doc created
franciscoalejandro@ideapad:~$

Con get pods, se verificó que hay un pod ejecutándose (estado Running) en el deployment linux-doc. La opción app=linux-doc es un selector para que solo se muestren pods de linux-doc

franciscoalejandro@ideapad:~$ kubectl get pods -l app=linux-doc
NAME                        READY   STATUS    RESTARTS   AGE
linux-doc-98cd79bd6-6jqsl   1/1     Running   0          51s
franciscoalejandro@ideapad:~$

Y para comprobar que funciona correctamente se hizo un redireccionamiento de las peticiones al puerto 8081 hacia el puerto 80 del pod de linux-doc

franciscoalejandro@ideapad:~$ kubectl port-forward deployment/linux-doc 8081:80
Forwarding from 127.0.0.1:8081 -> 80
Forwarding from [::1]:8081 -> 80
Handling connection for 8081

después de lo cual se obtuvo respuesta HTTP en un navegador

Respuesta del pod de linux-doc en localhost:8081 con la documentación del kernel de Linux

Sitio de la página de tareas#

Repitiendo el procedimeinto anetrior, se creó el nuevo deployment tareas-redes con create deployment. Se usó la imagen de contenedor franciscoalejandro1/tareas-redes creada previamente y se indicó que escucha en el puerto 80.

franciscoalejandro@ideapad:~$ CONTAINER_IMAGE="franciscoalejandro1/tareas-redes"
franciscoalejandro@ideapad:~$ kubectl create deployment tareas-redes --image="${CONTAINER_IMAGE}" --port=80
deployment.apps/tareas-redes created
franciscoalejandro@ideapad:~$

Con get pods, se verificó que hay un pod ejecutándose (estado Running) en el deployment tareas-redes.

franciscoalejandro@ideapad:~$ kubectl get pods -l app=tareas-redes
NAME                            READY   STATUS    RESTARTS   AGE
tareas-redes-6746ddbbb7-6dsw5   1/1     Running   0          38s
franciscoalejandro@ideapad:~$

Para comprobar que funciona correctamente se hizo un redireccionamiento de las peticiones al puerto 8082 hacia el puerto 80 del pod de tareas-redes.

franciscoalejandro@ideapad:~$ kubectl port-forward deployment/tareas-redes 8082:80
Forwarding from 127.0.0.1:8082 -> 80
Forwarding from [::1]:8082 -> 80
Handling connection for 8082

y se obtuvo respuesta HTTP en un navegador

Respuesta del pod de tareas-redes en localhost:8082 con el sitio de tareas

Verificación de la configuración de los sitios#

Los comandos get deployments y get pods muestran que los 3 deployments tiene estado READY 1/1 y que los respectivos pods tiene estado Running.

franciscoalejandro@ideapad:~$ kubectl get deployments
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
root-nginx     1/1     1            1           92m
linux-doc      1/1     1            1           6m21s
tareas-redes   1/1     1            1           3m27s
franciscoalejandro@ideapad:~$ kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
root-nginx-7df598fdcb-rqbqw     1/1     Running   0          68m
linux-doc-98cd79bd6-6jqsl       1/1     Running   0          6m27s
tareas-redes-6746ddbbb7-6dsw5   1/1     Running   0          3m32s
franciscoalejandro@ideapad:~$

Creación de servicios para dirigir tráfico a los pods (ingress en Kubernetes)#

Con el comando get services se verificó que no hay servicios para los deployments

franciscoalejandro@ideapad:~$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   25h
franciscoalejandro@ideapad:~$

Se crearon los servicios con expose, comando que usa el selector del recurso (en este caso los deployments root-nginx, linux-doc y tareas-redes) como el selector de un nuevo servicio en el puerto especificado con --port

franciscoalejandro@ideapad:~$ kubectl expose deployment root-nginx --port=80
service/root-nginx exposed
franciscoalejandro@ideapad:~$ kubectl expose deployment linux-doc --port=80
service/linux-doc exposed
franciscoalejandro@ideapad:~$ kubectl expose deployment tareas-redes --port=80
service/tareas-redes exposed
franciscoalejandro@ideapad:~$

Se verificó que se crearon los servicios para los deployements y que apuntan al puerto 80 de HTTP con get services

franciscoalejandro@ideapad:~$ kubectl get services
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.43.0.1       <none>        443/TCP   25h
root-nginx     ClusterIP   10.43.113.114   <none>        80/TCP    95s
linux-doc      ClusterIP   10.43.118.48    <none>        80/TCP    92s
tareas-redes   ClusterIP   10.43.1.82      <none>        80/TCP    82s
franciscoalejandro@ideapad:~$

Creación de rutas para dirigir tráfico a los servicios#

Se editó el archivo YAML para la creación y configuración de un recurso ingress recurso-ingress.yaml, que utiliza rutas para exponer los servicios del cluster y recibir tráfico. Con las líneas en spec:rules:

  - host: kernel.tacosdorados.cf
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: linux-doc
            port:
              number: 80

se define una regla para el host kernel.tacosdorados.cf que redirige el tráfico a la raíz del sitio del servicio linux-doc en el puerto 80. Con las líneas en spec:rules:

  - host: tareas.tacosdorados.cf
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: tareas-redes
            port:
              number: 80

se define una regla para el host tareas.tacosdorados.cf que redirige el tráfico a la raíz del sitio del servicio tareas-redes en el puerto 80. Y con las líneas en spec:rules:

  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: root-nginx
            port:
              number: 80

se define una regla tipo catch-all que redirige todo lo que que no sea kernel.tacosdorados.cf ni tareas.tacosdorados.cf a la raíz del sitio del servicio root-nginx en el puerto 80. La anotación rewrite-target, usada en las siguientes líneas en metadata:annotations:, indica que el tráfico se redirecciona a la raíz del sitio web

    ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/rewrite-target: /

Con este archivo de configuración, se creó el servicio ingress con el comando apply

franciscoalejandro@ideapad:~$ kubectl apply -f recurso-ingress.yaml
ingress.networking.k8s.io/ingress-nginx created
franciscoalejandro@ideapad:~$

Verificación de la conectividad a los sitios web#

Se verificó que se puede alcanzar y obtener la respuesta HTTP esperada de los 3 servicios, tanto con un navegador como por terminal con curl, como se decribe en la bitácora conexion-sitios.txt.

  • Servicio root-nginx (host catch-all)
Página índice del sitio web default en http://tacosdorados.cf/
  • Servicio linux-doc (host kernel.tacosdorados.cf)
Documentación del kernel de Linux en http://kernel.tacosdorados.cf/
  • Servicio tareas-redes (host tareas.tacosdorados.cf)
Sitio de tareas en http://tareas.tacosdorados.cf/

Explicación de la configuración de SSL/TLS en el ingress controller#

Directorio de validación ACME en el host default#

En la máquina virtual, se creó un archivo index.html en /var/www/html/.well-known/acme-challenge/ con el contenido Move along.

Este directorio es utilizado para la validación que hace Let's Encrypt del certificado SSL utilizando el protocolo ACME.

root@tacosdorados:~# echo "Move along" > /var/www/html/.well-known/acme-challenge/index.html
root@tacosdorados:~#

Se verificó que el pod de root-nginx se estuviese ejecutando

franciscoalejandro@ideapad:~$ kubectl get pods -l app=root-nginx
NAME                          READY   STATUS    RESTARTS   AGE
root-nginx-7df598fdcb-rqbqw   1/1     Running   0          21h
franciscoalejandro@ideapad:~$

Se editó la configuración del deployment root-nginx para agregar el directorio de validación ACME

franciscoalejandro@ideapad:~$ kubectl edit deployment/root-nginx
deployment.apps/root-nginx edited
franciscoalejandro@ideapad:~$

Las líneas en spec:template:spec:volumes:

      - name: acme-challenge
        hostPath:
          path: /var/www/html/.well-known

agregan el punto de montaje "acme-challenge". Las líneas en spec:template:spec:containers:volumeMounts:

        - name: acme-challenge
          mountPath: /usr/share/nginx/html/.well-known

agregan el volumen hostPath "acme-challenge".

Después de la edición, se verificó que se haya lanzado otro pod. El pod de root-nginx antes de la edición era root-nginx-7df598fdcb-rqbqw y después root-nginx-7b49cb6746-2n8nz, es decir, cambió una vez realizada la edición.

franciscoalejandro@ideapad:~$ kubectl get pods -l app=root-nginx
NAME                          READY   STATUS    RESTARTS   AGE
root-nginx-7b49cb6746-2n8nz   1/1     Running   0          43s
franciscoalejandro@ideapad:~$

También se verificó el acceso en un navegador al directorio /.well-known/acme-challenge, con el contenido Move along en la página índice

Página índice en http://tareas.tacosdorados.cf/.well-known/acme-challenge

Validez del certficado SSL#

Se verificó la validez del certificado SSL como se describe en la bitácora validez-certificado.txt.

Configuración del certificado SSL y la llave privada en el cluster#

Se copíó el contenido del directorio /etc/letsencrypt/live/tacosdorados.cf en la máquina virtual a ~/Downloads/letsencrypt en el equipo local. El contenido se lista a continuación

franciscoalejandro@ideapad:~$ ls -la ~/Downloads/letsencrypt
total 48
drwxrwxr-x 2 franciscoalejandro franciscoalejandro  4096 jun 16 19:27 .
drwxr-xr-x 7 franciscoalejandro franciscoalejandro 12288 jun 16 19:29 ..
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro  1870 jun 16 19:29 cert.pem
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro  5272 jun 16 19:29 cert.txt
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro  3749 jun 16 19:29 chain.pem
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro  5619 jun 16 19:29 fullchain.pem
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro  1704 jun 16 19:29 privkey.pem
-rwxrwxr-x 1 franciscoalejandro franciscoalejandro   692 jun 16 19:29 README
franciscoalejandro@ideapad:~$

En seguida se creó un recurso secret TLS llamado nginx-ingress-tls con el comando create secret tls. La opción --cert especifica la ruta al certificado de la llave pública (en este caso el archivo fullchain.pem que contiene el certificado del servidor y los certificados de las CA intermedias) y la opción --key especifica la ruta a la llave privada asociada al certificado dado (en este caso el archivo privkey.pem)

franciscoalejandro@ideapad:~$ cd ~/Downloads/letsencrypt
franciscoalejandro@ideapad:~/Downloads/letsencrypt$ kubectl create secret tls nginx-ingress-tls --cert fullchain.pem --key privkey.pem
secret/nginx-ingress-tls created
franciscoalejandro@ideapad:~/Downloads/letsencrypt$

Con get secret se verificó que exíste el secret TLS nginx-ingress-tls y con nginx-ingress-tls que tiene los campos tls.crt y tls.key, correspondientes al certificado y la llave privada, respectivamente

franciscoalejandro@ideapad:~$ kubectl get secret nginx-ingress-tls
NAME                TYPE                DATA   AGE
nginx-ingress-tls   kubernetes.io/tls   2      9m8s
franciscoalejandro@ideapad:~$ kubectl nginx-ingress-tls nginx-ingress-tls
Name:         nginx-ingress-tls
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.key:  1704 bytes
tls.crt:  5619 bytes
franciscoalejandro@ideapad:~$

Soporte TLS en el recurso ingress#

Se editó el archivo recurso-ingress.yaml, agregando en spec: las líneas

  tls:
  - secretName: nginx-ingress-tls
    hosts:
    - '*.tacosdorados.cf'
    - kernel.tacosdorados.cf
    - tareas.tacosdorados.cf

Esta sección que hace referencia al secret le indica al ingress controller que asegure el canal del cliente al load balancer usando TLS. El campo secretName especifica el recurso secret que contiene el certificado y la llave privada. El campo host indica los nombres DNS de las rutas en las que se configura el soporte de TLS.

Para actualizar la configuración se utilizó apply

franciscoalejandro@ideapad:~$ kubectl apply -f recurso-ingress.yaml
ingress.networking.k8s.io/ingress-nginx configured
franciscoalejandro@ideapad:~$

Certificado SSL en el ingress controller#

Para usar el recurso secret que contiene el certificado y la llave privada, se editó el deployment ingress-nginx-controller en el namespace ingress-nginx, con edit

franciscoalejandro@ideapad:~$ kubectl edit deployment/ingress-nginx-controller -n ingress-nginx
deployment.apps/ingress-nginx-controller edited
franciscoalejandro@ideapad:~$

Se modificaron los argumentos con los que se lanza el proceso, agregando la línea

        - --default-ssl-certificate=default/nginx-ingress-tls

en spec:template:spec:containers:args: para asignar el valor default/nginx-ingress-tls (el secret creado anteriormente) al argumento --default-ssl-certificate. El argumento --default-ssl-certificate especifica el secret con el certificado que se usa para el servidor HTTPS por defecto (catch-all).

Reinicio del ingress controller en el cluster#

Para que se aplicaran los cambion, se prosiguió a reiniciar el pod principal del ingress controller, pues se modificaron los argumentos del proceso nginx-ingress-controller y los argumentos se toman al iniciar la ejecución.

Primero se listaron el deployment y pod con get deployments,pods del ingress controller instalado en el cluster, especificando el namespace ingress-nginx con la opción -n

franciscoalejandro@ideapad:~$ kubectl get deployments,pods -n ingress-nginx -l app.kubernetes.io/component=controller
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           27h

NAME                                            READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-7ff499d7dc-sq955   1/1     Running   0          27h
pod/ingress-nginx-controller-7f7dd56cc6-rsz8c   0/1     Pending   0          97s
franciscoalejandro@ideapad:~$

El pod antes de modificar los argumentos era pod/ingress-nginx-controller-7ff499d7dc-sq955 y sigue en ejecución. Al hacer los cambios a los argumentos del proceso nginx-ingress-controller se planificó un nuevo pod pero no inicia su ejecución de forma automática, por lo que es necesario el reinicio de forma manual.

Para detener el pod activo, se usó el comando scale deployment, que establece un nuevo tamaño (al valor de --replicas) de un deployment. Al cambiar el tamaño a 0 del deployment ingress-nginx-controller, se establece que no deben haber pods, por lo que se detene el proceso. Después, al cambiar el tamaño a 1, se establece que debe haber un pod y, al no haber ninguno, se inicia de nuevo la ejecución con un nuevo pod y tomando los argumentos modifcados

franciscoalejandro@ideapad:~$ kubectl scale deployment ingress-nginx-controller -n ingress-nginx --replicas 0
deployment.apps/ingress-nginx-controller scaled
franciscoalejandro@ideapad:~$ kubectl scale deployment ingress-nginx-controller -n ingress-nginx --replicas 1
deployment.apps/ingress-nginx-controller scaled
franciscoalejandro@ideapad:~$

Para confirmar que el proceso nginx-ingress-controller se reinició correctamente, se listaron el deployment y pod con get deployments,pods. El pod pod/ingress-nginx-controller-7f7dd56cc6-8jbfr en la salida del comando es diferente al que se tenía antes del escalamiento y también se observa que el tiempo de ejecución que tiene el nuevo pod es menor

franciscoalejandro@ideapad:~$ kubectl get deployments,pods -n ingress-nginx -l app.kubernetes.io/component=controller
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           27h

NAME                                            READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-7f7dd56cc6-8jbfr   1/1     Running   0          51s
franciscoalejandro@ideapad:~$

Verificación de la conectividad a los sitios web#

Se confirmó la conectividad a los puertos 80 y 443 del servidor, como se describe en la bitácora conexion-puertos.txt.

Se verificó la conexión con certificado SSL usando openssl s_client, como se describe en la bitácora openssl-s_client.txt.

Se verificó la conexión HTTPS de los 3 servicios, tanto por un navegador como por terminal con curl, como se describe en la bitácora conexion-sitios.txt.

  • Servicio root-nginx (host catch-all)
Página índice HTTPS del sitio web default en https://tacosdorados.cf/
  • Servicio linux-doc (host kernel.tacosdorados.cf)
Documentación del kernel de Linux HTTPS en https://kernel.tacosdorados.cf/
  • Servicio tareas-redes (host tareas.tacosdorados.cf)
Sitio de tareas HTTPS en https://tareas.tacosdorados.cf/

Por último, también se verificó la conexión al directorio de validación ACME (mostrando la página índice con Move along) en un navegador

Página índice HTTPS en https://tareas.tacosdorados.cf/.well-known/acme-challenge

Descripción de los archivos#

  • Archivos de configuración solicitados en la práctica
Nombre del archivo Descripción
letsencrypt.tar.gz Contenido del directorio /etc/letsencrypt de la máquina virtual
rancher.tar.gz Contenido del directorio /etc/rancher de la máquina virtual
  • Archivos de bitácora
Nombre del archivo Descripción
preparacion-vm.txt Preparación de la máqina virtual de Azure
instalacion-kubectl-krew.txt Instalación de kubectl y krew
conexion-puertos.txt Conexión a los puertos 80 y 443 del cluster de Kubernetes
openssl-s_client.txt Conexión al puerto 443 utilizando openssl s_client
validez-certificado.txt Comprobación de la validez del certificado SSL emitido por Let's Encrypt
conexion-sitios.txt Conexión a los sitios web hospedados utilizando HTTP y HTTPS
  • Archivos de datos
Nombre del archivo Descripción
linux-doc/Dockerfile Archivo Dockerfile usado para crear la imagen de contenedor franciscoalejandro1/linux-doc
tareas-redes/Dockerfile Archivo Dockerfile usado para crear la imagen de contenedor franciscoalejandro1/tareas-redes
html.tar.gz Contenido del directorio /var/www/html de la máquina virual
cert.txt Representación en texto del certificado SSL emitido por Let's Encrypt
  • Recursos de Kubernetes
Nombre del archivo Descripción
recursos-kubernetes.log Listado en texto de todos los recursos
recursos-kubernetes.yaml Archivo YAML con la configuración de todos los recursos
recursos-kubernetes.neat.yaml Archivo YAML sin campos innecesarios con la configuración de todos los recursos
nodes.yaml Archivo YAML con la configuración de los nodos
nodes.neat.yaml Archivo YAML sin campos innecesarios con la configuración de los nodos
configmap.yaml Archivo YAML con la configuración del configmap index-equipo-arfa-fgfg-rofm
configmap.neat.yaml Archivo YAML sin campos innecesarios con la configuración del configmap index-equipo-arfa-fgfg-rofm
root-nginx.yaml Archivo YAML con la configuración del deployment root-nginx
root-nginx.neat.yaml Archivo YAML sin campos innecesarios con la configuración del deployment root-nginx
linux-doc.yaml Archivo YAML con la configuración del deployment linux-doc
linux-doc.neat.yaml Archivo YAML sin campos innecesarios con la configuración del deployment linux-doc
tareas-redes.yaml Archivo YAML con la configuración del deployment tareas-redes
tareas-redes.neat.yaml Archivo YAML sin campos innecesarios con la configuración del deployment tareas-redes
nginx-ingress-tls.yaml Archivo YAML con la configuración del secret nginx-ingress-tls
nginx-ingress-tls.neat.yaml Archivo YAML sin campos innecesarios con la configuración del secret nginx-ingress-tls
ingress-nginx.yaml Archivo YAML con la configuración del ingress ingress-nginx
ingress-nginx.neat.yaml Archivo YAML sin campos innecesarios con la configuración del ingress ingress-nginx
ingress-nginx-controller.yaml Archivo YAML con la configuración del deployment ingress-nginx-controller
ingress-nginx-controller.neat.yaml Archivo YAML sin campos innecesarios con la configuración del deployment ingress-nginx-controller
  • Otros archivos
Nombre del archivo Descripción
campos-innecesarios.txt Explicación de los campos innecesarios que el plugin neat quita en los recursos de tipo deployment, configmap, secret e ingress
linux-doc/build-output.txt Salida del comando docker build al crear la imagen de contenedor franciscoalejandro1/linux-doc
tareas-redes/build-output.txt Salida del comando docker build al crear la imagen de contenedor franciscoalejandro1/tareas-redes
index.html Página índice del sitio default de tacosdorados.cf
recurso-ingress.yaml Archivo YAML usado para la configuración de ingress-nginx