Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible

Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible

por Raúl Unzué

¿Por qué Kubernetes sobre Proxmox y con Ansible?

Si trabajas con virtualización y buscas orquestar contenedores sin complicarte demasiado la vida, Kubernetes es tu mejor amigo. Pero si además usas Proxmox como plataforma de virtualización y quieres automatizarlo todo sin hacer clics a lo loco… Ansible entra en juego como el tercer mosquetero.

En esta entrada vamos a montar un clúster Kubernetes sobre máquinas virtuales Ubuntu corriendo en Proxmox, todo orquestado y automatizado con Ansible. Nada de instalaciones manuales eternas. Vamos a dejarlo todo fino, bien montado, y replicable.

Requisitos de hardware y software

Antes de liarte con comandos, asegúrate de tener lo siguiente bien claro:

En tu host Proxmox:

  • Una instalación funcionando de Proxmox VE 7 o superior. El host Proxmox que usaremos será "nuc.negu.local"
  • Recurso NFS montado desde un NAS (Esto es totalmente opcional)
  • Usaremos una plantilla para desplegar, al menos 3 máquinas virtuales creadas con Ubuntu 22.04 LTS (1 master y 2 workers).
  • Las VMs deben tener acceso a la red LAN y entre ellas (idealmente en la misma VLAN).
  • Cada VM debe tener:
    • 2 CPUs mínimo
    • 2 GB de RAM (4 GB recomendados para el master)
    • 20 GB de disco mínimo
    • Una IP fija o reservada vía DHCP para cada máquina:
      • MASTER - 192.168.2.100
      • WORKER 1 - 192.168.2.101
      • WORKER 2 - 192.168.2.102

A nivel de software:

  • Ubuntu Server 22.04 (recomendado por compatibilidad con Kubernetes).
  • Acceso por SSH desde tu máquina de control (la que usará Ansible) al host Proxmox (con clave pública copiada o sshpass si no usas claves).
  • Ansible instalado en tu máquina local (o una máquina de administración). En el ejemplo, 2.17.11:
    apt update && apt install -y python3-pippip install proxmoxer requests
     # Verificacionpython3 -c "import proxmoxer; print('proxmoxer OK')"
  • Python 3 en las VMs (suele venir por defecto).

Paso a paso para montar Kubernetes con Ansible

  1. Lo primero que haremos es preparar el proyecto. Para ello generamos los ficheros y carpetas necesarios. Lo podéis hacer desde vuestra máquina Ansible con los siguientes comandos:
    mkdir k8s-proxmox-ansible && cd k8s-proxmox-ansible
     mkdir -p group_vars host_vars files venv roles/{proxmox_vm_create,k8s_master_setup,k8s_worker_setup}/{tasks,templates,handlers}
     touch ansible.cfg inventory.ini site.yml group_vars/all.yml roles/{proxmox_vm_create,k8s_master_setup,k8s_worker_setup}/{tasks,handlers}/main.yml

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 1

  2. Estructura del proyecto:

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 2

  3. Modificaciones el fichero "ansible.cfg" con el siguiente contenido:
    [defaults]host_key_checking = Falseinventory = inventory.ini
     # Forzar uso del python de tu venv
     interpreter_python = {{ playbook_dir }}/venv/bin/python3
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 3
  4. Editamos el fichero "inventory.ini" con "nano inventory.ini" y agregamos el siguiente texto, modificando la contraseña y las IPs/nombres de nuestros equipos:
    [proxmox]
     localhost ansible_connection=local ansible_python_interpreter=/root/k8s-proxmox-ansible/venv/bin/python3
     [k8s_master]
     k8s-master ansible_host=192.168.2.100 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
     [k8s_workers]
     k8s-worker1 ansible_host=192.168.2.101 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
     k8s-worker2 ansible_host=192.168.2.102 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
     [kubernetes:children]k8s_masterk8s_workers[k8s_workers:vars]
     ansible_python_interpreter=/usr/bin/python3
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 4
  5. Editamos el fichero "site.yml" y agregamos el siguiente contenido:
    - name: Crear VMs en Proxmox hosts: proxmox gather_facts: false roles:
     - proxmox_vm_create- name: Configurar Kubernetes Master hosts: master
     become: yes roles: - k8s_master_setup- name: Configurar Kubernetes Workers
     hosts: workers become: yes roles: - k8s_worker_setup
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 5

     

  6. Generamos el fichero "groups_vars/all.yml" con el siguiente contenido:
    ---proxmox_api_host: nuc.negu.localproxmox_api_user: root@pam
     proxmox_api_password: password-proxmoxproxmox_api_verify_ssl: False
     k8s_version: "1.27.0-00"pod_network_cidr: "192.168.0.0/16"
     service_cidr: "10.96.0.0/12"dns_domain: "cluster.local"
     ssh_public_key_path: "~/.ssh/id_rsa.pub"
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 6

     

  7. Ahora generaremos un Playbook para la creación de las máquinas virtuales.
  8.  - Definición de Playbook: Para los que sois nuevos, un Playbook, se utiliza comúnmente para referirse a los scripts o secuencias de tareas que automatizan procesos. 

    - La ruta del Playbook es "nano roles/proxmox_vm_create/tasks/main.yml" y colocaremos este contenido:

    ---- name: Leer clave SSH pública ansible.builtin.slurp:
     src: "{{ ssh_public_key_path }}" register: pubkey_raw- set_fact:
     pubkey: "{{ pubkey_raw.content | b64decode }}"
     - name: Crear contenedor LXC para cada nodo community.general.proxmox:
     api_user: "{{ proxmox_api_user }}"
     api_password: "{{ proxmox_api_password }}"
     api_host: "{{ proxmox_api_host }}"
     validate_certs: "{{ proxmox_api_verify_ssl }}" node: nuc
     vmid: "{{ item.vmid }}"
     ostemplate: "local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
     hostname: "{{ item.hostname }}" storage: local-lvm cores: 2
     memory: "{{ 4096 if item.hostname == 'k8s-master' else 2048 }}" netif:
     net0: "name=eth0,bridge=vmbr0,ip={{ item.ip_with_prefix }},gw=192.168.2.69"
     nameserver: "192.168.2.69" searchdomain: "negu.local" onboot: yes
     pubkey: "{{ pubkey }}" password: "kubernetes" state: present
     loop: "{{ lxc_nodes }}"- name: Arrancar todos los contenedores LXC
     community.general.proxmox: api_user: "{{ proxmox_api_user }}"
     api_password: "{{ proxmox_api_password }}"
     api_host: "{{ proxmox_api_host }}"
     validate_certs: "{{ proxmox_api_verify_ssl }}" node: nuc
     vmid: "{{ item.vmid }}" state: started
     loop: "{{ lxc_nodes }}"- name: Esperar a que SSH este listo en master
     wait_for: host: "{{ lxc_nodes[0].ip_with_prefix.split('/')[0] }}"
     port: 22 timeout: 300 state: started delegate_to: localhost
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 7

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 8

  9. Definimos el siguiente fichero "nano roles/k8s_master_setup/handlers/main.yml":
    ---- name: Restart SSH ansible.builtin.service: name: ssh
     state: restarted

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 9

  10. Una vez creadas las máquinas virtuales, necesitaremos configurar los roles dentro de ellas con otro Playbook, empezamos con el master, "nano roles/k8s_master_setup/tasks/main.yml":
    # roles/k8s_master_setup/tasks/main.yml---
     - name: Instalar dependencias en master ansible.builtin.apt: name:
     - apt-transport-https - ca-certificates - curl - gnupg
     - lsb-release state: latest update_cache: yes
     - name: Asegurar ruta por defecto en el master LXC ansible.builtin.shell: |
     ip route replace default via 192.168.2.69 args: executable: /bin/bash
     - name: Configurar DNS en el master LXC ansible.builtin.copy:
     dest: /etc/resolv.conf content: | nameserver 8.8.8.8
     nameserver 1.1.1.1 mode: '0644'
     - name: Instalar OpenSSH Server en master ansible.builtin.apt:
     name: openssh-server state: present update_cache: yes
     - name: Asegurar directorio .ssh para root ansible.builtin.file:
     path: /root/.ssh state: directory mode: '0700'
     - name: Instalar clave publica de root ansible.builtin.authorized_key:
     user: root state: present
     key: "{{ lookup('file', ssh_public_key_path) }}"
     - name: Permitir login root en SSH ansible.builtin.lineinfile:
     path: /etc/ssh/sshd_config regexp: '^PermitRootLogin'
     line: 'PermitRootLogin yes' notify: Restart SSH
     - name: Crear /etc/hosts con todos los nodos ansible.builtin.copy:
     dest: /etc/hosts content: | 127.0.0.1 localhost
     {% for host in groups['k8s_master'] %}
     {{ hostvars[host].ansible_host | default(hostvars[host].ansible_default_ipv4.address) }} {{ host }}
     {% endfor %} {% for host in groups['k8s_workers'] %}
     {{ hostvars[host].ansible_host | default(hostvars[host].ansible_default_ipv4.address) }} {{ host }}
     {% endfor %} mode: '0644'- name: Instalar K3s (canal estable)
     ansible.builtin.shell: |
     curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644 args:
     creates: /usr/local/bin/k3s executable: /bin/bash
     - name: Obtener token de nodo para K3s ansible.builtin.slurp:
     src: /var/lib/rancher/k3s/server/node-token register: k3s_token_raw
     - name: Definir fact con el token de K3s ansible.builtin.set_fact:
     k3s_node_token: "{{ k3s_token_raw.content | b64decode | trim }}"
     - name: Esperar a que K3s este listo en master ansible.builtin.wait_for:
     host: "{{ hostvars[inventory_hostname].ansible_host | default(ansible_default_ipv4.address) }}"
     port: 6443 timeout: 300 state: started delegate_to: localhost
     - name: Crear directorio .kube para root file: path: /root/.kube
     state: directory mode: '0700'- name: Copiar kubeconfig de K3s para root
     ansible.builtin.copy: remote_src: yes src: /etc/rancher/k3s/k3s.yaml
     dest: /root/.kube/config owner: root group: root mode: '0600'
    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 10

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 11Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 12

  11. Realizamos la misma operativa para los workers "nano roles/k8s_worker_setup/tasks/main.yml":
    # roles/k8s_worker_setup/tasks/main.yml---
     - name: Instalar dependencias en worker ansible.builtin.apt: name:
     - apt-transport-https - ca-certificates - curl - gnupg
     - lsb-release state: latest update_cache: yes
     - name: Asegurar que existe ruta por defecto en el contenedor
     ansible.builtin.shell: | ip route replace default via 192.168.2.69 args:
     executable: /bin/bash- name: Configurar DNS dentro del contenedor
     ansible.builtin.copy: dest: /etc/resolv.conf content: |
     nameserver 8.8.8.8 nameserver 1.1.1.1 mode: '0644'
     - name: Instalar OpenSSH Server en worker ansible.builtin.apt:
     name: openssh-server state: present update_cache: yes
     - name: Asegurar directorio .ssh para root ansible.builtin.file:
     path: /root/.ssh state: directory mode: '0700'
     - name: Instalar clave publica de root en worker
     ansible.builtin.authorized_key: user: root state: present
     key: "{{ lookup('file', ssh_public_key_path) }}"
     - name: Permitir login root en SSH ansible.builtin.lineinfile:
     path: /etc/ssh/sshd_config regexp: '^PermitRootLogin'
     line: 'PermitRootLogin yes'- name: Reiniciar SSHD en worker
     ansible.builtin.service: name: ssh state: restarted enabled: yes
     - name: Crear /etc/hosts con todos los nodos ansible.builtin.copy:
     dest: /etc/hosts content: | 127.0.0.1 localhost
     {% for host in groups['k8s_master'] %}
     {{ hostvars[host].ansible_host | default(hostvars[host].ansible_default_ipv4.address) }} {{ host }}
     {% endfor %} {% for host in groups['k8s_workers'] %}
     {{ hostvars[host].ansible_host | default(hostvars[host].ansible_default_ipv4.address) }} {{ host }}
     {% endfor %} mode: '0644'
     - name: Esperar a que SSH este listo en este worker ansible.builtin.wait_for:
     port: 22 state: started timeout: 120
     - name: Esperar a que master K3s este accesible (puerto 6443)
     ansible.builtin.wait_for:
     host: "{{ hostvars['k8s-master'].ansible_host | default(hostvars['k8s-master'].ansible_default_ipv4.address) }}"
     port: 6443 state: started timeout: 300 delegate_to: localhost
     - name: Mostrar token de K3s (debug) ansible.builtin.debug:
     msg: "Token master: {{ hostvars['k8s-master'].k3s_node_token }}"
     - name: Unir worker al cluster K3s (invocando directamente el binario)
     ansible.builtin.shell: | set -x sudo /usr/local/bin/k3s agent \
     --server https://{{ hostvars['k8s-master'].ansible_host }}:6443 \
     --token {{ hostvars['k8s-master'].k3s_node_token }} \
     --node-ip {{ ansible_default_ipv4.address }} args:
     executable: /bin/bash register: k3s_join failed_when: k3s_join.rc != 0
     - name: Mostrar resultado de la union ansible.builtin.debug: var: k3s_join
     - name: Listar nodos ya unidos ansible.builtin.shell: |
     sudo k3s kubectl get nodes register: k3s_nodes failed_when: false
     - name: Verificación final de nodos ansible.builtin.debug:
     var: k3s_nodes.stdout_lines
     - name: Esperar a que el agente K3s se registre (puerto 10250)
     ansible.builtin.wait_for: host: "{{ ansible_default_ipv4.address }}"
     port: 10250 state: started timeout: 300

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 13

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 14

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 15

  12. Con todo preparado lanzamos la ejecución:
    ansible-playbook -i inventory.ini site.yml

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 16

  13. Comienza el proceso, las máquinas serán generadas, arrancadas y tuneadas con las necesidades que hemos marcado:

    Geeknetic Cómo automatizar la creación de un clúster Kubernetes en VMs Ubuntu de Proxmox con Ansible 17

  14. En unos segundos veremos como el cluster de Kubernetes empieza a levantarse y configurarse por completo.

 

Kubernetes sobre Proxmox

Montar Kubernetes con Ansible sobre Proxmox es una forma muy limpia y flexible de tener control total de tu clúster. Si estás montando un laboratorio serio, o incluso algo de producción para pruebas internas, este combo te da potencia y automatización sin meterte en herramientas más pesadas como Rancher (aunque podrías agregarlo después).

Con Ansible como herramienta de automatización, te ahorras toneladas de clics y errores humanos. Con este setup puedes recrear entornos fácilmente, montar pruebas CI/CD o tener tu propio laboratorio de alto nivel. Y si dominas esto, dar el salto a producción solo es cuestión de escalar bien y meterle observabilidad.

Además, te ahorras depender de nubes públicas y tienes toda la infraestructura en casa. ¿Lo mejor? Puedes replicarlo una y otra vez.

 

Fin del Artículo. ¡Cuéntanos algo en los Comentarios!

Redactor del Artículo: Raúl Unzué

Raúl Unzué

Soy un apasionado de la virtualización con más de 20 años de experiencia, especializado en soluciones como VMware(premio vExpert y vExpert Pro desde 2013), Proxmox e Hyper-V. Durante mi carrera, he ayudado a empresas a optimizar sus infraestructuras TI mientras comparto mis conocimientos como redactor IT. Mi objetivo es traducir lo complejo en algo práctico y accesible, combinando teoría con experiencia real. Si te interesa la virtualización, las herramientas TI o simplemente aprender algo nuevo, espero ayudarte con mis artículos.