Instalación de Kubernetes (k8s) en Debian 12

kubernetes-k8s

¿Que es kubernetes (k8s)?

Kubernetes (k8s) o minikube es una herramienta que nos permite crear un cluster de kubernetes de un solo nodo en nuestra maquina local, esto nos permite crear y gestionar contenedores de forma local. Esta distribucion de kubernetes suele utilizarse para el aprendizaje y desarrollo de aplicaciones. No es recomendable utilizarlo en entornos de produccion.

Requisitos

  • Sistema Debian 12 actualizado.
  • Privilegios de root o sudo.
  • Acceso a internet.
  • Un hipervisor instalado (kvm, virtualbox, vmware, etc).

Instalacion

Para instalar kubernetes (k8s) en nuestra máquina local, debemos seguir los siguientes pasos:

-1 Descargamos la ultima version del binario de minikube con curl

usuario@minikube:~$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

Instalamos el binario de minikube en el directorio /usr/local/bin/minikube con el siguiente comando:

usuario@minikube:~$ sudo install minikube-linux-amd64 /usr/local/bin/minikube

Comprobamos que la instalacion se ha realizado correctamente:

usuario@minikube:~$ minikube version

minikube version: v1.31.2
commit: fd7ecd9c4599bef9f04c0986c4a0187f98a4396e

-2 Creacion del cluster de kubernetes (k8s)

En este post vamos a instalar minikube en el hipervisor kvm por lo que en el siguiente comando debemos especificar el driver que vamos a utilizar:

usuario@minikube:~$ minikube start --driver=kvm2

😄  minikube v1.31.2 en Debian 12.2
✨  Using the kvm2 driver based on user configuration
💾  Descargando el controlador docker-machine-driver-kvm2:
    > docker-machine-driver-kvm2-...:  65 B / 65 B [---------] 100.00% ? p/s 0s
    > docker-machine-driver-kvm2-...:  12.61 MiB / 12.61 MiB  100.00% 663.40 Mi
💿  Descargando la imagen de arranque de la VM
E1016 21:39:35.923611   17851 iso.go:90] Unable to download https://storage.googleapis.com/minikube-builds/iso/16971/minikube-v1.31.0-amd64.iso: getter: &{Ctx:context.Background Src:https://storage.googleapis.com/minikube-builds/iso/16971/minikube-v1.31.0-amd64.iso?checksum=file:https://storage.googleapis.com/minikube-builds/iso/16971/minikube-v1.31.0-amd64.iso.sha256 Dst:/home/retr0/.minikube/cache/iso/amd64/minikube-v1.31.0-amd64.iso.download Pwd: Mode:2 Umask:---------- Detectors:[0x3f9c8a8 0x3f9c8a8 0x3f9c8a8 0x3f9c8a8 0x3f9c8a8 0x3f9c8a8 0x3f9c8a8] Decompressors:map[bz2:0xc0004dc7d8 gz:0xc0004dc850 tar:0xc0004dc7e0 tar.bz2:0xc0004dc7f0 tar.gz:0xc0004dc800 tar.xz:0xc0004dc810 tar.zst:0xc0004dc820 tbz2:0xc0004dc7f0 tgz:0xc0004dc800 txz:0xc0004dc810 tzst:0xc0004dc820 xz:0xc0004dc858 zip:0xc0004dc860 zst:0xc0004dc870] Getters:map[file:0xc001193780 http:0xc00119be50 https:0xc00119bea0] Dir:false ProgressListener:0x3f579a0 Insecure:false DisableSymlinks:false Options:[0x12d0880]}: invalid checksum: Error downloading checksum file: bad response code: 404
💿  Descargando la imagen de arranque de la VM
    > minikube-v1.31.0-amd64.iso....:  65 B / 65 B [---------] 100.00% ? p/s 0s
    > minikube-v1.31.0-amd64.iso:  289.20 MiB / 289.20 MiB  100.00% 53.96 MiB p
👍  Starting control plane node minikube in cluster minikube
💾  Descargando Kubernetes v1.27.4 ...
    > preloaded-images-k8s-v18-v1...:  393.21 MiB / 393.21 MiB  100.00% 20.40 M
🔥  Creando kvm2 VM (CPUs=2, Memory=2200MB, Disk=20000MB) ...
🐳  Preparando Kubernetes v1.27.4 en Docker 24.0.4...
    ▪ Generando certificados y llaves
    ▪ Iniciando plano de control
    ▪ Configurando reglas RBAC...
🔗  Configurando CNI bridge CNI ...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🔎  Verifying Kubernetes components...
🌟  Complementos habilitados: default-storageclass, storage-provisioner
💡  kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Una vez finalizada la instalacion, podemos comprobar el estado del cluster con el siguiente comando:

usuario@minikube:~$ minikube status

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Ya hemos instalado minikube en nuestra maquina local y hemos creado un cluster de kubernetes (k8s), pero todavia necesitamos instalar la herramienta kubectl para poder gestionar el cluster.

-3 Instalacion de kubectl

Para instalar kubectl tenemos varias opciones, en este post vamos a instalarlo utilizando el fichero binario.

Opcion 1: Instalacion desde el repositorio oficial con apt

Para instalar kubectl desde el repositorio oficial, solo tenemos que ejecutar el siguiente comando:

root@minikube:~# apt install kubernetes-client -y
Opcion 2: Instalacion desde snap

Para instalar kubectl desde snap, solo tenemos que ejecutar el siguiente comando:

root@minikube:~# snap install kubectl --classic
Opcion 3: Instalacion desde el fichero binario

Este el metodo que vamos a utilizar en este post, para instalar kubectl. Para ello, debemos seguir los siguientes pasos:

Utilizamos curl para descargar el fichero binario de kubectl:

root@minikube:~# curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"

Instalamos el fichero binario de kubectl en el directorio /usr/local/bin/kubectl con el siguiente comando:

root@minikube:~# install kubectl /usr/local/bin/kubectl

Comprobamos que la instalacion se ha realizado correctamente:

usuario@minikube:~# kubectl version

Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.27.4

Si queremos autocompletar los comandos de kubectl, debemos ejecutar el siguiente comando:

usuario@minikube:~$ echo 'source <(kubectl completion bash)' >> ~/.bashrc

Podemos ver los nodos del cluster con el siguiente comando:

usuario@minikube:~$ kubectl get nodes

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   19h   v1.27.4

Despliegue de una aplicacion en kubernetes (k8s)

Para probar el funcionamiento de kubernetes (k8s), vamos a desplegar la aplicación nextcloud junto con una base de datos mariadb. Mi despliegue es el siguiente:

Tengo estos ficheros yaml:

mariadb-configmap1.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: db-datos
data:
  db_user: nextclouduser
  db_dbname: dbnextcloud

mariadb-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: pvc-mariadb
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

mariadb-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mariadb-deployment
  labels:
    app: nextcloud
    type: database
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextcloud
      type: database
  template:
    metadata:
      labels:
        app: nextcloud
        type: database
    spec:
      volumes:
        - name: vol-mariadb
          persistentVolumeClaim:
            claimName: pvc-mariadb
      containers:
        - name: contenedor-mariadb
          image: mariadb:10.5
          ports:
            - containerPort: 3306
              name: db-port
          volumeMounts:
            - mountPath: "/var/lib/mysql"
              name: vol-mariadb
          env:
            - name: MYSQL_USER
              valueFrom:
                configMapKeyRef:
                  name: db-datos
                  key: db_user
            - name: MYSQL_DATABASE
              valueFrom:
                configMapKeyRef:
                  name: db-datos
                  key: db_dbname
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-passwords
                  key: db_password
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-passwords
                  key: db_rootpassword

mariadb-srv.yaml

apiVersion: v1
kind: Service
metadata:
  name: nextcloud-service
  labels:
    app: nextcloud
    type: frontend
spec:
  selector:
    app: nextcloud
    type: frontend
  ports:
  - name: http-sv-port
    port: 80
    targetPort: http-port
  - name: https-sv-port
    port: 443
    targetPort: https-port
  type: NodePort

nextcloud-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: pvc-nextcloud
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

nextcloud-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextcloud-deployment
  labels:
    app: nextcloud
    type: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextcloud
      type: frontend
  template:
    metadata:
      labels:
        app: nextcloud
        type: frontend
    spec:
      volumes:
        - name: vol-nextcloud
          persistentVolumeClaim:
            claimName: pvc-nextcloud
      containers:
        - name: contenedor-nextcloud
          image: nextcloud
          ports:
            - containerPort: 80
              name: http-port
            - containerPort: 443
              name: https-port
          volumeMounts:
            - mountPath: "/var/www/html"
              name: vol-nextcloud
          env:
            - name: MYSQL_HOST
              value: mariadb-service
            - name: MYSQL_USER
              valueFrom:
                configMapKeyRef:
                  name: db-datos
                  key: db_user
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-passwords
                  key: db_password
            - name: MYSQL_DATABASE
              valueFrom:
                configMapKeyRef:
                  name: db-datos
                  key: db_dbname

nextcloud-srv.yaml

apiVersion: v1
kind: Service
metadata:
  name: nextcloud-service
  labels:
    app: nextcloud
    type: frontend
spec:
  selector:
    app: nextcloud
    type: frontend
  ports:
  - name: http-sv-port
    port: 80
    targetPort: http-port
  - name: https-sv-port
    port: 443
    targetPort: https-port
  type: NodePort

Para realizar el despliegue de la aplicacion, debemos seguir los siguientes pasos:

-1 Creamos el secret con las contraseñas de la base de datos

usuario@minikube:~$ kubectl create secret generic db-passwords --from-literal=db_password=nextcloudpass --from-literal=db_rootpassword=rootpass

-2 Desplegamos los ficheros yaml

Podemos desplegar los ficheros yaml de forma individual con el siguiente comando:

usuario@minikube:~$ kubectl apply -f mariadb-configmap1.yaml
usuario@minikube:~$ kubectl apply -f mariadb-pvc.yaml
usuario@minikube:~$ kubectl apply -f mariadb-deployment.yaml
usuario@minikube:~$ kubectl apply -f mariadb-srv.yaml
usuario@minikube:~$ kubectl apply -f nextcloud-pvc.yaml
usuario@minikube:~$ kubectl apply -f nextcloud-deployment.yaml
usuario@minikube:~$ kubectl apply -f nextcloud-srv.yaml

O podemos desplegar todos los ficheros yaml de una vez con el siguiente comando:

usuario@minikube:~$ kubectl apply -f .

-3 Comprobamos el estado de nuestro despliegue

usuario@minikube:~$ kubectl get pod,pv,service

NAME                                        READY   STATUS    RESTARTS   AGE
pod/mariadb-deployment-67cd7b78ff-6zsmd     1/1     Running   0          13s
pod/nextcloud-deployment-55df6885bc-sgcd8   1/1     Running   0          13s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
persistentvolume/pvc-cc357044-a9f4-455a-98d2-ba2c0df12904   4Gi        RWO            Delete           Bound    default/pvc-nextcloud   standard                13s
persistentvolume/pvc-f7a9d06c-ec6b-4f72-8c7b-0ac52b9cd038   4Gi        RWO            Delete           Bound    default/pvc-mariadb     standard                14s

NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/kubernetes          ClusterIP   10.96.0.1       <none>        443/TCP                      21h
service/mariadb-service     ClusterIP   10.103.79.139   <none>        3306/TCP                     14s
service/nextcloud-service   NodePort    10.99.90.40     <none>        80:32207/TCP,443:31495/TCP   13s

-4 Accedemos a la aplicacion

Para acceder a la aplicacion, tenemos que introducir en el navegador la ip de nuestro cluster y el puerto que nos indica el servicio nextcloud-service que en este caso es el 32207:

Como podemos ver en la siguiente imagen, la aplicacion nextcloud se ha desplegado correctamente y si nos fijamos no nos pide la información de la base de datos, ya que la hemos configurado en el fichero nextcloud-deployment.yaml:

nextcloud

Para eliminar el despliegue completo de la aplicación, podemos ejecutar el siguiente comando:

usuario@minikube:~$ kubectl delete -f .

y para eliminar el secret que hemos creado, utilizamos el siguiente comando:

usuario@minikube:~$ kubectl delete secret db-passwords

Con esto ya tendriamos en funcionamiento kubernetes (k8s) en nuestra maquina local y una aplicación desplegada en el cluster.