diff --git a/ansible/.gitignore b/ansible/.gitignore deleted file mode 100644 index 0f18981..0000000 --- a/ansible/.gitignore +++ /dev/null @@ -1 +0,0 @@ -secrets/ \ No newline at end of file diff --git a/ansible/README.md b/ansible/README.md deleted file mode 100644 index 52c1297..0000000 --- a/ansible/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# Ansible Playbook for Proxmox VM Management - -This Ansible playbook automates the creation, deletion, and configuration of -virtual machines (VMs) on a Proxmox server. - -## Prerequisites - -- Ansible installed on the local machine -- Ansible community.general.proxmox_kvm module -- Access to a Proxmox server with API access enabled -- Python `proxmoxer` library installed (`pip install proxmoxer`) - -## Setup - -1. Clone this repository: - ```sh - git clone https://github.com/TheTaqiTahmid/proxmox_ansible_automation - ``` - -2. Update the `inventory` file with your Proxmox server details: - ```yaml - all: - hosts: - proxmox: - ansible_host: your_proxmox_ip - ansible_user: your_proxmox_user - ansible_password: your_proxmox_password - ``` - In the current example implementation in `inventories/hosts.yaml`, there are - multiple groups depending on the types of hosts. - -3. Add group-related variables to the group file under the `group_vars` directory - and individual host-related variables to the files under the `host_vars` - directory. Ansible will automatically pick up these variables. - -4. Add the following secrets to the ansible-vault: - - proxmox_api_token_id - - proxmox_api_token - - ansible_proxmox_user - - ansible_vm_user - - proxmox_user - - ansible_ssh_private_key_file - - ciuser - - cipassword - - One can create the secret file using the following command: - ```sh - ansible-vault create secrets/vault.yml - ``` - - To encrypt and decrypt the file, use the following commands: - ```sh - ansible-vault encrypt secrets/vault.yml - ansible-vault decrypt secrets/vault.yml - ``` - The password for vault file can be stored in a file or can be provided during - the encryption/decryption process. The password file location can be specified - in the `ansible.cfg` file. - -## Playbooks - -### Create VM - -To create the VMs, run the following command: -```sh -ansible-playbook playbooks/create-vms.yaml -``` -The playbook can be run against specific Proxmox instance using: -```sh -ansible-playbook playbooks/create-vms.yaml --limit proxmox1 -``` - -### Delete VM - -To delete existing VMs, run the following command: -```sh -ansible-playbook playbooks/destroy-vms.yaml -``` - -Similarly the destory playbook can be run against specific Proxmox instance using: -```sh -ansible-playbook playbooks/destroy-vms.yaml --limit proxmox1 -``` - -### Configure VM - -To configure an existing VM, run the following command: -```sh -ansible-playbook playbooks/configure-vms.yaml -``` - -The configuration can be limited to individual VMs using limits: -```sh -ansible-playbook playbooks/configure-vms.yaml --limit vm6 -``` - -## Variables - -The playbooks use the following variables, which can be customized in the -`group_vars/proxmox.yml` file: - -- `vm_id`: The ID of the VM -- `vm_name`: The name of the VM -- `vm_memory`: The amount of memory for the VM -- `vm_cores`: The number of CPU cores for the VM -- `vm_disk_size`: The size of the VM disk - -## Author - -- Taqi Tahmid (mdtaqitahmid@gmail.com) diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg deleted file mode 100644 index 5a0d385..0000000 --- a/ansible/ansible.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[defaults] -inventory = ./inventory/hosts.yaml -roles_path = ./roles -host_key_checking = False -vault_password_file = ~/.ansible_vault_pass \ No newline at end of file diff --git a/ansible/inventory/group_vars/all.yaml b/ansible/inventory/group_vars/all.yaml deleted file mode 100644 index 347565c..0000000 --- a/ansible/inventory/group_vars/all.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Proxmox access related variables -proxmox_api_url: "192.168.1.121" - -# Cloud-init image related variables -image_url: "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img" -image_dest: "/tmp/cloud-image.img" -image_format: "qcow2" -storage_name: "local" - -# ansible venv -ansible_venv: "/home/taqi/.venv/ansible/bin/python" \ No newline at end of file diff --git a/ansible/inventory/group_vars/vms.yaml b/ansible/inventory/group_vars/vms.yaml deleted file mode 100644 index 0305a57..0000000 --- a/ansible/inventory/group_vars/vms.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apt_packages: - - curl - - vim - - htop - -# Kubernetes k0sctl configuration vars -master1_ip: "192.168.1.151" -master1_hostname: "vm6" -master2_ip: "192.168.1.161" -master2_hostname: "vm8" -worker1_ip: "192.168.1.152" -worker1_hostname: "vm7" -worker2_ip: "192.168.1.162" -worker2_hostname: "vm9" - -pod_CIDR: "10.244.0.0/16" -service_CIDR: "10.96.0.0/12" -metallb_ip_range: "192.168.1.201-192.168.1.220" - -k0s_version: "v1.33.2+k0s.0" -metallb_version: "0.15.2" -traefik_version: "36.2.0" \ No newline at end of file diff --git a/ansible/inventory/host_vars/proxmox1.yaml b/ansible/inventory/host_vars/proxmox1.yaml deleted file mode 100644 index b65a766..0000000 --- a/ansible/inventory/host_vars/proxmox1.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# VM related variables -vm_list: - - id: 106 - name: "vm6" - memory: 4096 - cores: 2 - disk_size: 30G - ip: "192.168.1.151/24" - gateway: "192.168.1.1" - nameserver1: "192.168.1.145" - nameserver2: "1.1.1.1" - - id: 107 - name: "vm7" - memory: 4096 - cores: 2 - disk_size: 30G - ip: "192.168.1.152/24" - gateway: "192.168.1.1" - nameserver1: "192.168.1.145" - nameserver2: "1.1.1.1" - -# cloud-init variables -node: "homeserver1" -net0: "virtio,bridge=vmbr0" -# disk_name: "local:1000/vm-1000-disk-0.raw,discard=on" -disk_path: "/var/lib/vz/images/1000" -ide2: "local:cloudinit,format=qcow2" -boot_order: "order=scsi0" -scsi_hw: "virtio-scsi-pci" diff --git a/ansible/inventory/host_vars/proxmox2.yaml b/ansible/inventory/host_vars/proxmox2.yaml deleted file mode 100644 index e0bf2bd..0000000 --- a/ansible/inventory/host_vars/proxmox2.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# VM related variables -vm_list: - - id: 206 - name: "vm8" - memory: 4096 - cores: 2 - disk_size: 30G - ip: "192.168.1.161/24" - gateway: "192.168.1.1" - nameserver1: "192.168.1.145" - nameserver2: "1.1.1.1" - - id: 207 - name: "vm9" - memory: 4096 - cores: 2 - disk_size: 30G - ip: "192.168.1.162/24" - gateway: "192.168.1.1" - nameserver1: "192.168.1.145" - nameserver2: "1.1.1.1" - -# cloud-init template variables -node: "homeserver2" -net0: "virtio,bridge=vmbr0" -# disk_name: "local:2000/vm-2000-disk-0.raw,discard=on" -disk_path: "/var/lib/vz/images/2000" -ide2: "local:cloudinit,format=qcow2" -boot_order: "order=scsi0" -scsi_hw: "virtio-scsi-pci" diff --git a/ansible/inventory/hosts.yaml b/ansible/inventory/hosts.yaml deleted file mode 100644 index c184f8d..0000000 --- a/ansible/inventory/hosts.yaml +++ /dev/null @@ -1,51 +0,0 @@ -all: - children: - hypervisors: - vms: - -hypervisors: - children: - server1: - server2: - -server1: - hosts: - proxmox1: - ansible_host: 192.168.1.121 - ansible_user: "{{ ansible_proxmox_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - -server2: - hosts: - proxmox2: - ansible_host: 192.168.1.122 - ansible_user: "{{ ansible_proxmox_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - -vms: - children: - vm_group_1: - vm_group_2: - -vm_group_1: - hosts: - vm6: - ansible_host: 192.168.1.151 - ansible_user: "{{ ansible_vm_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - vm7: - ansible_host: 192.168.1.152 - ansible_user: "{{ ansible_vm_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - -vm_group_2: - hosts: - vm8: - ansible_host: 192.168.1.161 - ansible_user: "{{ ansible_vm_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - vm9: - ansible_host: 192.168.1.162 - ansible_user: "{{ ansible_vm_user }}" - ansible_ssh_private_key_file: "{{ ansible_ssh_private_key_file }}" - diff --git a/ansible/playbooks/configure-vms.yaml b/ansible/playbooks/configure-vms.yaml deleted file mode 100644 index 5b65de6..0000000 --- a/ansible/playbooks/configure-vms.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: Configure Proxmox VMs - hosts: vms - vars_files: - - ../secrets/vault.yaml # Load the encrypted vault file - roles: - - configure-vms \ No newline at end of file diff --git a/ansible/playbooks/create-kubernetes-cluster.yaml b/ansible/playbooks/create-kubernetes-cluster.yaml deleted file mode 100644 index 0dc1d29..0000000 --- a/ansible/playbooks/create-kubernetes-cluster.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: Create Kubernetes Cluster - hosts: vms - vars_files: - - ../secrets/vault.yaml - roles: - - create-kubernetes-cluster diff --git a/ansible/playbooks/create-vms.yaml b/ansible/playbooks/create-vms.yaml deleted file mode 100644 index a61b0b8..0000000 --- a/ansible/playbooks/create-vms.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: Create Proxmox VMs - hosts: hypervisors - vars_files: - - ../secrets/vault.yaml # Load the encrypted vault file - roles: - - create-vms diff --git a/ansible/playbooks/destroy-vms.yaml b/ansible/playbooks/destroy-vms.yaml deleted file mode 100644 index cb3e266..0000000 --- a/ansible/playbooks/destroy-vms.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: Destroy Proxmox VMs - hosts: hypervisors - vars_files: - - ../secrets/vault.yaml # Load the encrypted vault file - roles: - - destroy-vms \ No newline at end of file diff --git a/ansible/roles/configure-vms/tasks/main.yaml b/ansible/roles/configure-vms/tasks/main.yaml deleted file mode 100644 index 48026ba..0000000 --- a/ansible/roles/configure-vms/tasks/main.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Update apt cache - ansible.builtin.apt: - update_cache: yes - become: true - -- name: Install necessary packages - ansible.builtin.apt: - name: "{{ apt_packages }}" - state: present - become: true diff --git a/ansible/roles/create-kubernetes-cluster/tasks/main.yaml b/ansible/roles/create-kubernetes-cluster/tasks/main.yaml deleted file mode 100644 index 30ab720..0000000 --- a/ansible/roles/create-kubernetes-cluster/tasks/main.yaml +++ /dev/null @@ -1,97 +0,0 @@ -- name: Remove known_hosts file if it exists - delegate_to: localhost - run_once: true - ansible.builtin.file: - path: /home/taqi/.ssh/known_hosts - state: absent - -- name: Remove k0ctl lock file if it exists - ansible.builtin.file: - path: /run/lock/k0sctl - state: absent - become: true - -- name: Install k0sctl on host - delegate_to: localhost - ansible.builtin.command: - cmd: "go install github.com/k0sproject/k0sctl@latest" - -- name: Ensure k0sctl is installed on host - delegate_to: localhost - run_once: true - ansible.builtin.command: - cmd: "k0sctl version" - register: k0sctl_version - changed_when: false - -- name: Generate k0sctl configuration file - delegate_to: localhost - run_once: true - ansible.builtin.template: - src: k0sctl.yaml.j2 - dest: /tmp/k0sctl.yaml - when: k0sctl_version is defined - tags: - - generate-k0sctl-config - -- name: Generate MetalLB IP Address Pool configuration file - delegate_to: localhost - run_once: true - ansible.builtin.template: - src: ipAddressPool.yaml.j2 - dest: /tmp/ipAddressPool.yaml - when: k0sctl_version is defined - tags: - - generatemetallb-ippool - - metallb-ippool - -- name: Create Cluster using k0sctl from host - delegate_to: localhost - run_once: true - ansible.builtin.command: - cmd: "k0sctl apply --config /tmp/k0sctl.yaml" - when: k0sctl_version is defined - -- name: Save kubeconfig file on host - delegate_to: localhost - run_once: true - ansible.builtin.shell: - cmd: "cd /tmp && k0sctl kubeconfig > /home/taqi/.kube/k0s_config.yaml" - register: kubeconfig_result - retries: 3 - delay: 5 - until: kubeconfig_result.rc == 0 - when: k0sctl_version is defined - tags: - - generate-kubeconfig - -- name: Apply IP Pool for MetalLB from host - delegate_to: localhost - run_once: true - ansible.builtin.shell: - cmd: "kubectl apply -f /tmp/ipAddressPool.yaml --kubeconfig /home/taqi/.kube/k0s_config.yaml" - register: metallb_ippool_result - retries: 3 - delay: 5 - until: metallb_ippool_result.rc == 0 - when: k0sctl_version is defined - tags: - - metallb-ippool - -- name: Cleanup temporary files - delegate_to: localhost - run_once: true - block: - - name: Remove k0sctl.yaml temporary file - ansible.builtin.file: - path: /tmp/k0sctl.yaml - state: absent - - - name: Remove ipAddressPool.yaml temporary file - ansible.builtin.shell: - cmd: "rm -f /tmp/ipAddressPool.yaml" - delegate_to: localhost - run_once: true - tags: - - cleanup - when: k0sctl_version is defined \ No newline at end of file diff --git a/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 b/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 deleted file mode 100644 index c0d1ae7..0000000 --- a/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: metallb.io/v1beta1 -kind: IPAddressPool -metadata: - name: first-pool - namespace: metallb-system -spec: - addresses: - - "{{ metallb_ip_range }}" \ No newline at end of file diff --git a/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 b/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 deleted file mode 100644 index 60449e9..0000000 --- a/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: k0sctl.k0sproject.io/v1beta1 -kind: Cluster -metadata: - name: k0s-cluster -spec: - hosts: - - ssh: - address: "{{ master1_ip }}" - user: "{{ ansible_vm_user }}" - keyPath: "{{ ansible_ssh_private_key_file }}" - role: controller+worker - hostname: "{{ master1_hostname }}" - noTaints: true - - ssh: - address: "{{ master2_ip }}" - user: "{{ ansible_vm_user }}" - keyPath: "{{ ansible_ssh_private_key_file }}" - role: controller+worker - hostname: "{{ master2_hostname }}" - noTaints: true - - ssh: - address: "{{ worker1_ip }}" - user: "{{ ansible_vm_user }}" - keyPath: "{{ ansible_ssh_private_key_file }}" - role: worker - hostname: "{{ worker1_hostname }}" - - ssh: - address: "{{ worker2_ip }}" - user: "{{ ansible_vm_user }}" - keyPath: "{{ ansible_ssh_private_key_file }}" - role: worker - hostname: "{{ worker2_hostname }}" - k0s: - version: "{{ k0s_version }}" - config: - spec: - api: - address: "{{ master1_ip }}" - port: 6443 - k0sApiPort: 9443 - sans: - - "{{ master1_ip }}" - - "{{ master2_ip }}" - - k8s.local - - api.k8s.local - network: - kubeProxy: - mode: iptables - kuberouter: - disabled: false - podCIDR: "{{ pod_CIDR }}" - serviceCIDR: "{{ service_CIDR }}" - provider: kuberouter - extensions: - helm: - concurrencyLevel: 5 - repositories: - - name: metallb - url: https://metallb.github.io/metallb - - name: traefik - url: https://traefik.github.io/charts - charts: - - name: metallb - chartname: metallb/metallb - version: "{{ metallb_version }}" - namespace: metallb-system - - name: traefik - chartname: traefik/traefik - version: "{{ traefik_version }}" - namespace: traefik-system diff --git a/ansible/roles/create-vms/tasks/main.yaml b/ansible/roles/create-vms/tasks/main.yaml deleted file mode 100644 index 7503204..0000000 --- a/ansible/roles/create-vms/tasks/main.yaml +++ /dev/null @@ -1,70 +0,0 @@ ---- -- name: Download cloud image - get_url: - url: "{{ image_url }}" - dest: "{{ image_dest }}" - use_netrc: yes - -- name: create VMs - delegate_to: localhost - vars: - ansible_python_interpreter: /home/taqi/.venv/ansible/bin/python - community.general.proxmox_kvm: - api_host: "{{ proxmox_api_url }}" - api_user: "{{ proxmox_user }}" - api_token_id: "{{ proxmox_api_token_id }}" - api_token_secret: "{{ proxmox_api_token }}" - node: "{{ node }}" - vmid: "{{ item.id }}" - name: "{{ item.name }}" - memory: "{{ item.memory }}" - cores: "{{ item.cores }}" - scsihw: "{{ scsi_hw }}" - boot: "{{ boot_order }}" - net: - net0: "{{ net0 }}" - ipconfig: - ipconfig0: "ip={{ item.ip }},gw={{ item.gateway }}" - ide: - ide2: "{{ ide2 }}" - nameservers: "{{ item.nameserver1 }},{{ item.nameserver2 }}" - ciuser: "{{ ciuser }}" - cipassword: "{{ cipassword }}" - sshkeys: "{{ lookup('file', '/home/taqi/.ssh/homeserver.pub') }}" - loop: "{{ vm_list }}" - -- name: Import disk image - ansible.builtin.shell: | - qm importdisk "{{ item.id }}" "{{ image_dest }}" "{{ storage_name }}" --format "{{ image_format }}" - loop: "{{ vm_list }}" - -- name: Attach disk to VM - ansible.builtin.shell: | - qm set "{{ item.id }}" --scsi0 "{{ storage_name }}:{{ item.id }}/vm-{{ item.id }}-disk-0.{{ image_format }},discard=on" - loop: "{{ vm_list }}" - -- name: Resize disk - ansible.builtin.shell: | - qm resize {{ item.id }} scsi0 {{ item.disk_size }} - loop: "{{ vm_list }}" - -- name: Start VMs - delegate_to: localhost - vars: - ansible_python_interpreter: /home/taqi/.venv/ansible/bin/python - community.general.proxmox_kvm: - api_host: "{{ proxmox_api_url }}" - api_user: "{{ proxmox_user }}" - api_token_id: "{{ proxmox_api_token_id }}" - api_token_secret: "{{ proxmox_api_token }}" - node: "{{ node }}" - name: "{{ item.name }}" - state: started - loop: "{{ vm_list }}" - tags: - - start_vms - -- name: Clean up downloaded image - file: - path: "{{ image_dest }}" - state: absent \ No newline at end of file diff --git a/ansible/roles/destroy-vms/tasks/main.yaml b/ansible/roles/destroy-vms/tasks/main.yaml deleted file mode 100644 index bd4b9b3..0000000 --- a/ansible/roles/destroy-vms/tasks/main.yaml +++ /dev/null @@ -1,72 +0,0 @@ -- name: Get VM current state - delegate_to: localhost - vars: - ansible_python_interpreter: "{{ ansible_venv }}" - community.general.proxmox_kvm: - api_host: "{{ proxmox_api_url }}" - api_user: "{{ proxmox_user }}" - api_token_id: "{{ proxmox_api_token_id }}" - api_token_secret: "{{ proxmox_api_token }}" - name: "{{ item.name }}" - node: "{{ node }}" - state: current - register: vm_state - ignore_errors: yes - loop: "{{ vm_list }}" - loop_control: - index_var: vm_index - tags: - - vm_delete - -- name: Debug VM state - debug: - msg: "VM {{ item.name }} state: {{ vm_state.results[vm_index].status }}" - when: vm_state.results[vm_index] is defined and vm_state.results[vm_index] is succeeded - loop: "{{ vm_list }}" - loop_control: - index_var: vm_index - -- name: Stop VM - delegate_to: localhost - vars: - ansible_python_interpreter: "{{ ansible_venv }}" - community.general.proxmox_kvm: - api_host: "{{ proxmox_api_url }}" - api_user: "{{ proxmox_user }}" - api_token_id: "{{ proxmox_api_token_id }}" - api_token_secret: "{{ proxmox_api_token }}" - name: "{{ item.name }}" - node: "{{ node }}" - state: stopped - force: true - when: > - vm_state.results[vm_index] is defined and - vm_state.results[vm_index] is succeeded and - vm_state.results[vm_index].status != 'absent' - loop: "{{ vm_list }}" - loop_control: - index_var: vm_index - tags: - - vm_delete - -- name: Delete VM - delegate_to: localhost - vars: - ansible_python_interpreter: "{{ ansible_venv }}" - community.general.proxmox_kvm: - api_host: "{{ proxmox_api_url }}" - api_user: "{{ proxmox_user }}" - api_token_id: "{{ proxmox_api_token_id }}" - api_token_secret: "{{ proxmox_api_token }}" - name: "{{ item.name }}" - node: "{{ node }}" - state: absent - when: > - vm_state.results[vm_index] is defined and - vm_state.results[vm_index] is succeeded and - vm_state.results[vm_index].status != 'absent' - loop: "{{ vm_list }}" - loop_control: - index_var: vm_index - tags: - - vm_delete diff --git a/infra/terraform/README.md b/infra/terraform/README.md index b999854..c458860 100644 --- a/infra/terraform/README.md +++ b/infra/terraform/README.md @@ -23,3 +23,13 @@ minio as the storage backend. The Proxmox configuration is located in the `proxmox` directory. It uses the Proxmox provider to manage virtual machines and other resources. + +The workflow for managing Proxmox resources is as follows: + +```bash +cd proxmox +source .env +tofu init +tofu plan +tofu apply +```