This commit is contained in:
Eric Meehan 2024-10-25 10:25:04 -04:00
parent 2f3f4a8d2c
commit 160ffca2ee
55 changed files with 1201 additions and 349 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
vault
*.tar.gz
*.qcow2

9
alpha-cluster.yaml Normal file
View File

@ -0,0 +1,9 @@
---
# Playbook for alpha-cluster
- name: Deploy services to Alpha Cluster
hosts: alpha-control-plane
become: true
vars_files:
secrets.yaml
roles:
- role: ericomeehan.gondwanamc

13
files/01_debian_cloud.cfg Normal file
View File

@ -0,0 +1,13 @@
apt:
generate_mirrorlists: true
system_info:
default_user:
name: debian
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: True
gecos: Debian
groups: [adm, audio, cdrom, dialout, dip, floppy, plugdev, sudo, video]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/bash

71
files/05_logging.cfg Normal file
View File

@ -0,0 +1,71 @@
## This yaml formated config file handles setting
## logger information. The values that are necessary to be set
## are seen at the bottom. The top '_log' are only used to remove
## redundency in a syslog and fallback-to-file case.
##
## The 'log_cfgs' entry defines a list of logger configs
## Each entry in the list is tried, and the first one that
## works is used. If a log_cfg list entry is an array, it will
## be joined with '\n'.
_log:
- &log_base |
[loggers]
keys=root,cloudinit
[handlers]
keys=consoleHandler,cloudLogHandler
[formatters]
keys=simpleFormatter,arg0Formatter
[logger_root]
level=DEBUG
handlers=consoleHandler,cloudLogHandler
[logger_cloudinit]
level=DEBUG
qualname=cloudinit
handlers=
propagate=1
[handler_consoleHandler]
class=StreamHandler
level=WARNING
formatter=arg0Formatter
args=(sys.stderr,)
[formatter_arg0Formatter]
format=%(asctime)s - %(filename)s[%(levelname)s]: %(message)s
[formatter_simpleFormatter]
format=[CLOUDINIT] %(filename)s[%(levelname)s]: %(message)s
- &log_file |
[handler_cloudLogHandler]
class=FileHandler
level=DEBUG
formatter=arg0Formatter
args=('/var/log/cloud-init.log', 'a', 'UTF-8')
- &log_syslog |
[handler_cloudLogHandler]
class=handlers.SysLogHandler
level=DEBUG
formatter=simpleFormatter
args=("/dev/log", handlers.SysLogHandler.LOG_USER)
log_cfgs:
# Array entries in this list will be joined into a string
# that defines the configuration.
#
# If you want logs to go to syslog, uncomment the following line.
# - [ *log_base, *log_syslog ]
#
# The default behavior is to just log to a file.
# This mechanism that does not depend on a system service to operate.
- [ *log_base, *log_file ]
# A file path can also be used.
# - /etc/log.conf
# This tells cloud-init to redirect its stdout and stderr to
# 'tee -a /var/log/cloud-init-output.log' so the user can see output
# there without needing to look on the console.
output: {all: '| tee -a /var/log/cloud-init-output.log'}

1
group_vars/alpha.yaml Normal file
View File

@ -0,0 +1 @@
nfs_path: alpha

1
group_vars/beta.yaml Normal file
View File

@ -0,0 +1 @@
nfs_path: beta

View File

@ -20,3 +20,6 @@ open_ports:
- interface: any
protocol: tcp
port: 10259
memory:
unit: MiB
value: 8192

1
group_vars/gamma.yaml Normal file
View File

@ -0,0 +1 @@
nfs_path: gamma

View File

@ -0,0 +1,6 @@
---
# Group vars for hypervisors
open_ports:
- interface: any
protocol: tcp
port: 22

111
group_vars/vms.yaml Normal file
View File

@ -0,0 +1,111 @@
---
# Group vars for virtual machines
type: kvm
name: my_vm_name
instance_id: "iid-{{ name }}"
packages:
- openssh-server
- prometheus-node-exporter
- qemu-guest-agent
open_ports:
- interface: any
protocol: tcp
port: 22
memory:
unit: MiB
value: 4096
vcpu:
placement: static
value: 2
os:
type:
arch: x86_64
machine: pc-q35-5.2
value: hvm
boot:
dev: hd
cpu:
mode: host-model
check: none
emulator: /usr/bin/qemu-system-x86_64
disks:
- type: file
device: disk
driver:
name: qemu
type: qcow2
source:
file: /var/lib/libvirt/images/{{ name }}.qcow2
target:
dev: vda
bus: virtio
- type: file
device: cdrom
driver:
name: qemu
type: raw
source:
file: /var/lib/libvirt/images/{{ name }}.iso
target:
dev: sda
bus: sata
interfaces:
- type: network
source:
network: wan
model:
type: virtio
channels:
- type: unix
target:
type: virtio
name: org.qemu.guest_agent.0
address:
type: virtio-serial
controller: 0
bus: 0
port: 1
inputs:
- type: tablet
bus: usb
address:
type: usb
bus: 0
port: 1
- type: mouse
bus: ps2
- type: keyboard
bus: ps2
graphics:
type: spice
autoport: 'yes'
listen:
type: address
image:
compression: 'off'
video:
model:
type: qxl
ram: 65536
vram: 65536
vgamem: 16384
heads: 1
primary: yes
memballoon:
model: virtio
rng:
model: virtio
backend:
model: random
value: /dev/urandom
devices:
emulator: "{{ emulator }}"
disks: "{{ disks }}"
filesystems: "{{ filesystems }}"
interfaces: "{{ interfaces }}"
channels: "{{ channels }}"
inputs: "{{ inputs }}"
graphics: "{{ graphics }}"
video: "{{ video }}"
memballoon: "{{ memballoon }}"
rng: "{{ rng }}"

View File

@ -14,3 +14,6 @@ open_ports:
- interface: any
protocol: tcp
port: 30000-32767
memory:
unit: MiB
value: 16384

View File

@ -0,0 +1 @@
name: alpha-control-plane

View File

@ -1,2 +0,0 @@
---
# Host vars for alpha-control-plane

View File

@ -0,0 +1 @@
name: alpha-worker-0

View File

@ -1,53 +0,0 @@
---
# Host vars for alpha-worker-0
nvidia_driver_needed: true
nvidia_driver_tesla: true
qemu_cluster_networks:
- name: lan
bridge: br1
interfaces:
- eno2np1
address: 10.0.0.2
netmask: 255.255.255.0
gateway: 10.0.0.254
qemu_cluster_machines:
- name: nfs
ram_mb: 4096
vcpus: 1
networks:
- lan
- name: control-plane
ram_mb: 4096
vcpus: 1
networks:
- lan
- name: worker-0
ram_mb: 16384
vcpus: 1
networks:
- lan
- name: worker-1
ram_mb: 16384
vcpus: 1
networks:
- lan
- name: worker-2
ram_mb: 16384
vcpus: 1
networks:
- lan
- name: worker-3
ram_mb: 16384
vcpus: 1
networks:
- lan
- name: worker-4
ram_mb: 16384
vcpus: 1
networks:
- lan
- name: worker-5
ram_mb: 16384
vcpus: 1
networks:
- lan

View File

@ -0,0 +1 @@
name: alpha-worker-1

View File

@ -0,0 +1 @@
name: alpha-worker-2

View File

@ -0,0 +1 @@
name: alpha-worker-3

0
host_vars/alpha.yaml Normal file
View File

View File

@ -0,0 +1 @@
name: beta-control-plane

View File

@ -0,0 +1 @@
name: beta-worker-0

View File

@ -0,0 +1 @@
name: beta-worker-1

View File

@ -0,0 +1 @@
name: beta-worker-2

View File

@ -0,0 +1 @@
name: beta-worker-3

View File

@ -0,0 +1 @@
name: gamma-control-plane

View File

@ -0,0 +1 @@
name: gamma-worker-0

View File

@ -0,0 +1 @@
name: gamma-worker-1

View File

@ -0,0 +1 @@
name: gamma-worker-2

View File

@ -0,0 +1 @@
name: gamma-worker-3

59
host_vars/gateway.yaml Normal file
View File

@ -0,0 +1,59 @@
---
# Host vars for gateway
name: gateway
interfaces:
- type: network
source:
network: lan
model:
type: virtio
address:
type: pci
domain: 0x0000
bus: 0x01
slot: 0x00
function: 0x0
- type: network
source:
network: wan
model:
type: virtio
address:
type: pci
domain: 0x0000
bus: 0x02
slot: 0x00
function: 0x0
- type: network
source:
network: alpha
model:
type: virtio
address:
type: pci
domain: 0x0000
bus: 0x03
slot: 0x00
function: 0x0
- type: network
source:
network: beta
model:
type: virtio
address:
type: pci
domain: 0x0000
bus: 0x04
slot: 0x00
function: 0x0
- type: network
source:
network: gamma
model:
type: virtio
address:
type: pci
domain: 0x0000
bus: 0x08
slot: 0x00
function: 0x0

View File

@ -0,0 +1,35 @@
name: network-file-system
nfs_exports: ["/data *(rw,sync,no_root_squash)"]
mounts:
- [ vdb, /data ]
disks:
- type: file
device: disk
driver:
name: qemu
type: qcow2
source:
file: /var/lib/libvirt/images/{{ name }}.qcow2
target:
dev: vda
bus: virtio
- type: block
device: disk
driver:
name: qemu
type: raw
source:
dev: /dev/poweredge-t640-vg1/store-0
target:
dev: vdb
bus: virtio
- type: file
device: cdrom
driver:
name: qemu
type: raw
source:
file: /var/lib/libvirt/images/{{ name }}.iso
target:
dev: sda
bus: sata

View File

@ -1,36 +1,16 @@
# Host vars for poweredge-r350
qemu_network_networks:
libvirt_networks:
- name: wan
bridge: br0
interfaces:
- eno1np0
use_dhcp: true
forward:
mode: bridge
bridge:
name: wan
dev: eno8303
- name: lan
bridge: br1
interfaces:
- eno2np1
use_dhcp: false
address: 10.0.0.1
netmask: 255.0.0.0
gateway: 10.0.0.254
qemu_network_machines:
- name: gateway
ram_mb: 2048
vcpus: 1
networks:
- wan
- lan
disks:
- filename: gateway-vda
type: qcow2
target_dev: vda
- name: vpn
ram_mb: 2048
vcpus: 1
networks:
- wan
- lan
disks:
- filename: vpn-vda
type: qcow2
target_dev: vda
forward:
mode: bridge
bridge:
name: lan
dev: eno8403
libvirt_guests:
- vpn

View File

@ -1,90 +1,26 @@
---
# Host vars for poweredge-t640
nvidia_driver_needed: true
nvidia_driver_tesla: true
qemu_network_networks:
- name: lan
bridge: br1
interfaces:
- eno2np1
use_dhcp: false
address: 10.0.0.0
netmask: 255.255.0.0
gateway: 10.0.0.1
qemu_network_disks:
- name: nfs-vda
type: qcow2
from: eom-base.qcow2
- name: nfs-vdb
type: qcow2
size: 16T
- name: control-plane-vda
type: qcow2
from: eom-base.qcow2
- name: worker-0-vda
type: qcow2
from: eom-base.qcow2
- name: worker-1-vda
type: qcow2
from: eom-base.qcow2
- name: worker-2-vda
type: qcow2
from: eom-base.qcow2
qemu_network_machines:
- name: nfs
ram_mb: 4096
vcpus: 1
networks:
- lan
disks:
- filename: nfs-vda
type: qcow2
target_dev: vda
- filename: nfs-vdb
type: qcow2
target_dev: vda
- name: control-plane
ram_mb: 4096
vcpus: 1
networks:
- lan
disks:
- filename: control-plane-vda
type: qcow2
target_dev: vda
- name: worker-0
ram_mb: 16384
vcpus: 1
networks:
- lan
disks:
- filename: worker-0-vda
type: qcow2
target_dev: vda
- name: worker-1
ram_mb: 16384
vcpus: 1
networks:
- lan
disks:
- filename: worker-1-vda
type: qcow2
target_dev: vda
- name: worker-2
ram_mb: 16384
vcpus: 1
networks:
- lan
disks:
- filename: worker-2-vda
type: qcow2
target_dev: vda
- name: worker-3
ram_mb: 16384
vcpus: 1
networks:
- lan
disks:
- filename: worker-3-vda
type: qcow2
target_dev: vda
libvirt_networks:
- name: wan
forward:
mode: bridge
bridge:
name: wan
dev: eno1np0
libvirt_guests:
- network-file-system
- alpha-control-plane
- alpha-worker-0
- alpha-worker-1
- alpha-worker-2
- alpha-worker-3
- beta-control-plane
- beta-worker-0
- beta-worker-1
- beta-worker-2
- beta-worker-3
- gamma-control-plane
- gamma-worker-0
- gamma-worker-1
- gamma-worker-2
- gamma-worker-3

18
host_vars/vpn.yaml Normal file
View File

@ -0,0 +1,18 @@
---
# Host vars for vpn
name: vpn
packages:
- openssh-server
- openvpn
- prometheus-node-exporter
interfaces:
- type: network
source:
network: wan
model:
type: virtio
- type: network
source:
network: lan
model:
type: virtio

251
hypervisors.yaml Normal file
View File

@ -0,0 +1,251 @@
---
# Playbook for hypervisors
- name: Initialize hypervisors
hosts: hypervisors
become: true
roles:
- role: ericomeehan.debian
- role: ericomeehan.ericomeehan
- name: Deploy virtual machines
hosts: hypervisors
become: true
vars_files:
- ../secrets.yaml
pre_tasks:
- name: Install packages for virtualization
apt:
update_cache: yes
name:
- bridge-utils
- genisoimage
- qemu-utils
- qemu-system-x86
- libvirt-daemon-system
- python3-libvirt
- python3-lxml
state: present
- name: Enable IPv4 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv4.ip_forward = 1'
state: present
- name: Enable IPv6 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.forwarding = 1'
state: present
- name: Reload sysctl configuration
command: sysctl --system
- name: Define libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
command: define
xml: "{{ lookup('template', 'libvirt-network.xml.j2') }}"
loop: "{{ libvirt_networks }}"
- name: Create libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
command: create
loop: "{{ libvirt_networks }}"
- name: Autostart libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
autostart: true
loop: "{{ libvirt_networks }}"
- name: Download base image
get_url:
url: https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2
dest: /var/lib/libvirt/images/debian-12-generic-amd64.qcow2
force: true
- name: Copy base image
copy:
src: /var/lib/libvirt/images/debian-12-generic-amd64.qcow2
remote_src: true
dest: "/var/lib/libvirt/images/{{ item }}.qcow2"
force: true
loop: "{{ libvirt_guests }}"
- name: Resize images
command: "qemu-img resize -f qcow2 /var/lib/libvirt/images/{{ item }}.qcow2 16G"
loop: "{{ libvirt_guests }}"
- name: Create cloud-config directory
file:
path: "/tmp/{{ item }}"
state: directory
loop: "{{ libvirt_guests }}"
- name: Copy cloud-config user-data template
template:
src: user-data.j2
dest: "/tmp/{{ domain.name }}/user-data"
force: true
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Copy cloud-config meta-data template
template:
src: meta-data.j2
dest: "/tmp/{{ domain.name }}/meta-data"
force: true
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Generate iso
command: "genisoimage -output /var/lib/libvirt/images/{{ item }}.iso -volid cidata -joliet -rock /tmp/{{ item }}/user-data /tmp/{{ item }}/meta-data"
loop: "{{ libvirt_guests }}"
- name: Define libvirt virtual machine
community.libvirt.virt:
command: define
xml: "{{ lookup('template', 'libvirt-vm.xml.j2') }}"
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Create libvirt virtual machine
community.libvirt.virt:
name: "{{ item }}"
command: create
loop: "{{ libvirt_guests }}"
- name: Autostart libvirt virtual machines
community.libvirt.virt:
name: "{{ item }}"
autostart: true
loop: "{{ libvirt_guests }}"
- name: Wait for guest initialization
wait_for:
timeout: 300
- name: Reset libvirt virtual machines for filesystem resize
command: "virsh reset {{ item }}"
loop: "{{ libvirt_guests }}"
- name: Copy SSH keys
hosts: localhost
tasks:
- name: Wait for manual tasks
pause:
prompt: "Press Enter to continue..."
- name: Initialize virtual machines
hosts: vms
become: true
pre_tasks:
- name: Append text from files/motd to the beginning of remote motd file
blockinfile:
path: /etc/motd
marker: ""
block: |
{{ lookup('file', 'motd') }}
roles:
- role: ericomeehan.ericomeehan
- name: Initialize Network File Systems
hosts: network-file-system
become: true
roles:
- role: geerlingguy.nfs
- name: Initialize Kubernetes clusters
hosts: clusters
become: true
pre_tasks:
- name: Enable IPv4 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv4.ip_forward = 1'
state: present
- name: Enable IPv6 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.forwarding = 1'
state: present
- name: Reload sysctl configuration
command: sysctl --system
- name: Enable br_netfilter kernel module
command: modprobe br_netfilter
- name: Add the module to a configuration file for persistence
lineinfile:
path: /etc/modules-load.d/modules.conf
line: "br_netfilter"
- name: Install kubernetes library
apt:
name: python3-kubernetes
state: present
roles:
- role: geerlingguy.containerd
- name: Alpha Cluster
hosts: alpha
become: true
roles:
- role: geerlingguy.kubernetes
- name: Beta Cluster
hosts: beta
become: true
roles:
- role: geerlingguy.kubernetes
- name: Gamma Cluster
hosts: gamma
become: true
roles:
- role: geerlingguy.kubernetes
- name: Install Helm
hosts: control_planes
become: true
roles:
- role: geerlingguy.helm
- name: Install NFS Common
hosts: workers
become: true
tasks:
- name: Install nfs-common
apt:
name: nfs-common
state: present
- name: Configure default storage class
hosts: control-planes
become: true
tasks:
- name: Install helm repo
kubernetes.core.helm_repository:
name: nfs-subdir-external-provisioner
repo_url: https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
- name: Deploy nfs provisioner
kubernetes.core.helm:
name: nfs-subdir-external-provisioner
chart_ref: nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
release_namespace: default
values:
nfs:
server: network-file-system
path: "/data/{{ nfs_path }}"
storageClass:
defaultClass: true

View File

@ -4,40 +4,58 @@ all:
workstations:
hosts:
latitude-7230:
ansible-host: 192.168.1.123
inspiron-3670:
ansible-host: 192.168.1.210
imac:
ansible-host: 192.168.1.139
servers:
hypervisors:
hosts:
poweredge-r350:
ansible-host: 192.168.1.137
poweredge-t640:
ansible-host: 192.168.1.138
vms:
hosts:
gateway:
ansible-host: 10.0.0.1
network-file-system:
vpn:
ansible-host: 10.0.0.2
nfs:
ansible-host: 10.0.0.3
load_balancers:
children:
alpha:
hosts:
alpha-load-balancer:
ansible-host: 10.0.1.0
children:
clusters:
children:
control_planes:
hosts:
alpha-control-plane:
beta-control-plane:
gamma-control-plane:
workers:
hosts:
alpha-worker-0:
alpha-worker-1:
alpha-worker-2:
alpha-worker-3:
beta-worker-0:
beta-worker-1:
beta-worker-2:
beta-worker-3:
gamma-worker-0:
gamma-worker-1:
gamma-worker-2:
gamma-worker-3:
alpha:
hosts:
alpha-control-plane:
ansible-host: 10.0.1.1
alpha-worker-0:
ansible-host: 10.0.1.2
alpha-worker-1:
ansible-host: 10.0.1.3
alpha-worker-2:
ansible-host: 10.0.1.4
alpha-worker-3:
beta:
hosts:
beta-control-plane:
beta-worker-0:
beta-worker-1:
beta-worker-2:
beta-worker-3:
gamma:
hosts:
gamma-control-plane:
gamma-worker-0:
gamma-worker-1:
gamma-worker-2:
gamma-worker-3:

60
kubernetes.yaml Normal file
View File

@ -0,0 +1,60 @@
---
# Playbook for Kubernetes
- name: Initialize Kubernetes clusters
hosts: clusters
become: true
pre_tasks:
- name: Enable IPv4 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv4.ip_forward = 1'
state: present
- name: Enable IPv6 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.forwarding = 1'
state: present
- name: Reload sysctl configuration
command: sysctl --system
- name: Enable br_netfilter kernel module
command: modprobe br_netfilter
- name: Add the module to a configuration file for persistence
lineinfile:
path: /etc/modules-load.d/modules.conf
line: "br_netfilter"
- name: Install kubernetes library
apt:
name: python3-kubernetes
state: present
roles:
- role: geerlingguy.containerd
- name: Alpha Cluster
hosts: alpha
become: true
roles:
- role: geerlingguy.kubernetes
- name: Beta Cluster
hosts: beta
become: true
roles:
- role: geerlingguy.kubernetes
- name: Gamma Cluster
hosts: alpha
become: true
roles:
- role: geerlingguy.kubernetes
- name: Install Helm
hosts: control_planes
become: true
roles:
- role: geerlingguy.helm

5
nfs.yaml Normal file
View File

@ -0,0 +1,5 @@
- name: Configure NFS
hosts: network-file-system
become: true
roles:
- role: geerlingguy.nfs

110
poweredge-r350.yaml Normal file
View File

@ -0,0 +1,110 @@
---
# Playbook for poweredge-r350
# This is being used to test vm deployments
- name: Deploy virtual machines
hosts: poweredge-r350
become: true
vars_files:
- ../secrets.yaml
pre_tasks:
- name: Install packages for virtualization
apt:
update_cache: yes
name:
- bridge-utils
- genisoimage
- qemu-utils
- qemu-system-x86
- libvirt-daemon-system
- python3-libvirt
- python3-lxml
state: present
- name: Enable IPv4 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv4.ip_forward = 1'
state: present
- name: Enable IPv6 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.forwarding = 1'
state: present
- name: Reload sysctl configuration
command: sysctl --system
- name: Define libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
command: define
xml: "{{ lookup('template', 'libvirt-network.xml.j2') }}"
loop: "{{ libvirt_networks }}"
- name: Create libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
command: create
loop: "{{ libvirt_networks }}"
- name: Autostart libvirt networks
community.libvirt.virt_net:
name: "{{ item.name }}"
autostart: true
loop: "{{ libvirt_networks }}"
- name: Download base image for guests
get_url:
url: https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2
dest: "/var/lib/libvirt/images/{{ item }}.qcow2"
force: true
loop: "{{ libvirt_guests }}"
- name: Create cloud-config directory for guests
file:
path: "/var/lib/libvirt/configs/{{ item }}"
state: directory
loop: "{{ libvirt_guests }}"
- name: Copy cloud-config templates for guests
template:
src: eom_cloud.cfg.j2
dest: "/var/lib/libvirt/configs/{{ domain.name }}/user-data"
force: true
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Copy cloud-config templates for guests
template:
src: meta-data.j2
dest: "/var/lib/libvirt/configs/{{ domain.name }}/meta-data"
force: true
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Generate iso for guests
command: "genisoimage -output /var/lib/libvirt/images/{{ item }}.iso -volid cidata -joliet -rock /var/lib/libvirt/configs/{{ item }}/user-data /var/lib/libvirt/configs/{{ item }}/meta-data"
loop: "{{ libvirt_guests }}"
- name: Copy logging config for guests
copy:
src: 05_logging.cfg
dest: "/var/lib/libvirt/configs/{{ item }}/05_logging.cfg"
loop: "{{ libvirt_guests }}"
- name: Define libvirt virtual machine
community.libvirt.virt:
command: define
xml: "{{ lookup('template', 'libvirt-vm.xml.j2') }}"
loop: "{{ libvirt_guests }}"
vars:
domain: "{{ hostvars[item] }}"
- name: Create libvirt virtual machine
community.libvirt.virt:
name: "{{ item }}"
command: create
loop: "{{ libvirt_guests }}"

5
poweredge-t640.yaml Normal file
View File

@ -0,0 +1,5 @@
- name: Install nvidia
hosts: poweredge-t640
become: true
roles:
- role: ericomeehan.nvidia_driver

12
qemu-base.yaml Normal file
View File

@ -0,0 +1,12 @@
---
# Create base image for QEMU
- name: Install dependencies
- name: Download Debian installation image
- name: Create virtual disk for image
- name: Boot installation media with preseed
- name: Wait for installation completion
- name: Initialize base image
roles:
- role: ericomeehan.debian
- role: ericomeehan.ericomeehan
- name: Shut down base image

View File

@ -1,28 +1,20 @@
---
# Playbook for QEMU
- name: Prepare virtualization environment
hosts: alpha-worker-0
- name: Test QEMU
hosts: localhost
become: true
vars:
qemu_network_networks:
- name: lan
bridge: br1
interfaces:
- eno2np1
use_dhcp: false
address: 10.0.0.2
netmask: 255.255.255.0
gateway: 10.0.0.254
qemu_network_machines:
- name: nfs
ram_mb: 4096
tasks:
- name: Deploy test vm
community.libvirt.virt:
name: test
state: running
persistent: true
memory: 4096
vcpus: 1
networks:
- lan
os_type: linux
disks:
- filename: nfs-vda
type: qcow2
target_dev: vda
- filename: nfs-vdb
type: qcow2
target_dev: vda
- name: test
size: 8
format: qcow2
cdrom:
- url: https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.7.0-amd64-netinst.iso

View File

@ -0,0 +1 @@
/home/eric/Desktop/ansible-role-libvirt-vm

@ -1 +1 @@
Subproject commit 8946eefeb5442761edef6853665074e1306391a0
Subproject commit 4b9534a27ef2c7a096f58959d9762647f524b96d

21
templates/interfaces.j2 Normal file
View File

@ -0,0 +1,21 @@
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# Libvirt networks
{% for network in libvirt_networks %}
{% if network.bridge.dev is defined %}
auto {{ network.bridge.dev }}
iface {{ network.bridge.dev }} inet manual
auto {{ network.bridge.name }}
iface {{ network.bridge.name }} inet dhcp
bridge_ports {{ network.bridge.dev }}
{% endif %}
{% endfor %}

View File

@ -0,0 +1,14 @@
<network>
<name>{{ item.name }}</name>
<forward mode='{{ item.forward.mode }}'/>
{% if item.bridge.dev is defined %}
<bridge name='{{ item.bridge.name }}' dev='{{ item.bridge.dev }}'/>
{% else %}
<bridge name='{{ item.bridge.name }}'/>
<ip address='{{ item.ip.address }}' netmask='{{ item.ip.netmask }}'>
<dhcp>
<range start='{{ item.ip.dhcp.range.start }}' end='{{ item.ip.dhcp.range.end }}'/>
</dhcp>
</ip>
{% endif %}
</network>

108
templates/libvirt-vm.xml.j2 Normal file
View File

@ -0,0 +1,108 @@
<domain type='{{ domain.type }}'>
<name>{{ domain.name }}</name>
<memory unit='{{ domain.memory.unit }}'>{{ domain.memory.value }}</memory>
<vcpu placement='{{ domain.vcpu.placement }}'>{{ domain.vcpu.value }}</vcpu>
<os>
<type arch='{{ domain.os.type.arch }}' machine='{{ domain.os.type.machine }}'>{{ domain.os.type.value }}</type>
<boot dev='{{ domain.os.boot.dev }}'/>
</os>
<cpu mode='{{ domain.cpu.mode }}' check='{{ domain.cpu.check }}'/>
<devices>
<emulator>{{ domain.devices.emulator }}</emulator>
{% if domain.devices.disks is defined %}
{% for disk in domain.devices.disks %}
<disk type='{{ disk.type }}' device='{{ disk.device }}'>
<driver name='{{ disk.driver.name }}' type='{{ disk.driver.type }}'/>
{% if disk.source.protocol is defined %}
<source protocol='{{ disk.source.protocol }}' name='{{ disk.source.name }}'>
<host name='{{ disk.source.host.name }}' port='{{ disk.source.host.port }}'/>
</source>
{% elif disk.source.dev is defined %}
<source dev='{{ disk.source.dev }}'/>
{% else %}
<source file='{{ disk.source.file }}'/>
{% endif %}
<target dev='{{ disk.target.dev }}' bus='{{ disk.target.bus }}'/>
{% if disk.address is defined %}
<address type='{{ disk.address.type }}' domain='{{ disk.address.domain }}' bus='{{ disk.address.bus }}' slot='{{ disk.address.slot }}' function='{{ disk.address.function }}'/>
{% endif %}
</disk>
{% endfor %}
{% endif %}
{% if domain.filesystems is defined %}
{% for filesystem in domain.filesystems %}
<filesystem type='{{ filesystem.type }}' accessmode='{{ filesystem.accessmode }}'>
<source dir='{{ filesystem.source.dir }}'/>
<target dir='{{ filesystem.target.dir }}'/>
</filesystem>
{% endfor %}
{% endif %}
{% if domain.devices.interfaces is defined %}
{% for interface in domain.devices.interfaces %}
<interface type='{{ interface.type }}'>
<source network='{{ interface.source.network }}'/>
<model type='{{ interface.model.type }}'/>
{% if interface.address is defined %}
<address type='{{ interface.address.type }}' domain='{{ interface.address.domain }}' bus='{{ interface.address.bus }}' slot='{{ interface.address.slot }}' function='{{ interface.address.function }}'/>
{% endif %}
</interface>
{% endfor %}
{% endif %}
{% if domain.devices.channels is defined %}
{% for channel in domain.devices.channels %}
<channel type='{{ channel.type }}'>
<target type='{{ channel.target.type }}' name='{{ channel.target.name }}'/>
{% if channel.address is defined %}
<address type='{{ channel.address.type }}' controller='{{ channel.address.controller }}' bus='{{ channel.address.bus }}' port='{{ channel.address.port }}'/>
{% endif %}
</channel>
{% endfor %}
{% endif %}
{% if domain.devices.inputs is defined %}
{% for input in domain.devices.inputs %}
<input type='{{ input.type }}' bus='{{ input.bus }}'>
{% if input.address is defined %}
<address type='{{ input.address.type }}' bus='{{ input.address.bus }}' port='{{ input.address.port }}'/>
{% endif %}
</input>
{% endfor %}
{% endif %}
{% if domain.devices.graphics is defined %}
<graphics type='{{ domain.devices.graphics.type }}' autoport='{{ domain.devices.graphics.autoport }}'>
<listen type='{{ domain.devices.graphics.listen.type }}'/>
<image compression='{{ domain.devices.graphics.image.compression }}'/>
</graphics>
{% endif %}
{% if domain.devices.video is defined %}
<video>
<model type='{{ domain.devices.video.model.type }}' ram='{{ domain.devices.video.model.ram }}' vram='{{ domain.devices.video.model.vram }}' vgamem='{{ domain.devices.video.model.vgamem }}' heads='{{ domain.devices.video.model.heads }}' primary='{{ domain.devices.video.model.primary }}'/>
{% if domain.devices.video.address is defined %}
<address type='{{ domain.devices.video.address.type }}' domain='{{ domain.devices.video.address.domain }}' bus='{{ domain.devices.video.address.bus }}' slot='{{ domain.devices.video.address.slot }}' function='{{ domain.devices.video.address.function }}'/>
{% endif %}
</video>
{% endif %}
{% if domain.devices.memballoon is defined %}
<memballoon model='{{ domain.devices.memballoon.model }}'>
{% if domain.devices.memballoon.address is defined %}
<address type='{{ domain.devices.memballoon.address.type }}' domain='{{ domain.devices.memballoon.address.domain }}' bus='{{ domain.devices.memballoon.address.bus }}' slot='{{ domain.devices.memballoon.address.slot }}' function='{{ domain.devices.memballoon.address.function }}'/>
{% endif %}
</memballoon>
{% endif %}
{% if domain.devices.rng is defined %}
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
{% if domain.devices.rng.address is defined %}
<address type='{{ domain.devices.rng.address.type }}' domain='{{ domain.devices.rng.address.domain }}' bus='{{ domain.devices.rng.address.bus }}' slot='{{ domain.devices.rng.address.slot }}' function='{{ domain.devices.rng.address.function }}'/>
{% endif %}
</rng>
{% endif %}
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
</devices>
</domain>

2
templates/meta-data.j2 Normal file
View File

@ -0,0 +1,2 @@
instance-id: {{ domain.instance_id }}
local-hostname: {{ domain.name }}

54
templates/qemu-vm.xml.j2 Normal file
View File

@ -0,0 +1,54 @@
<domain type='{{ item.domain.type }}'>
<name>{{ item.domain.name }}</name>
<memory unit='{{ item.domain.memory.unit }}'>{{ item.domain.memory.value }}</memory>
<vcpu placement='{{ item.domain.vcpu.placement }}'>{{ item.domain.bcpu.value }}</vcpu>
<os>
<type arch='{{ item.domain.os.type.arch }}' machine='{{ item.domain.os.type.machine }}'>{{ item.domain.os.type.value }}</type>
<boot dev='{{ item.domain.os.boot.dev }}'/>
</os>
<cpu mode='{{ item.domain.cpu.mode }}' check='{{ item.domain.cpu.check }}'/>
<devices>
<emulator>{{ item.domain.devices.emulator }}</emulator>
{% for disk in item.domain.devices.disks %}
<disk type='{{ disk.type }}' device='{{ disk.device }}'>
<driver name='{{ disk.driver.name }}' type='{{ disk.driver.type }}'/>
<source file='{{ disk.source.file }}'/>
<target dev='{{ disk.target.dev }}' bus='{{ disk.target.bus }}'/>
<address type='{{ disk.target.address.type }}' domain='{{ disk.target.address.domain }}' bus='{{ disk.target.address.bus }}' slot='{{ disk.target.address.slot }}' function='{{ disk.target.address.function }}'/>
</disk>
{% endfor %}
{% for interface in item.domain.devices.interfaces %}
<interface type='{{ interface.type }}'>
<source network='{{ interface.source.network }}'/>
<model type='{{ interface.model.type }}'/>
<address type='{{ interface.target.address.type }}' domain='{{ interface.target.address.domain }}' bus='{{ interface.target.address.bus }}' slot='{{ interface.target.address.slot }}' function='{{ interface.target.address.function }}'/>
</interface>
{% endfor %}
{% for channel in item.domain.devices.channels %}
<channel type='channel.type'>
<target type='{{ channel.target.type }}' name='{{ channel.target.name }}'/>
<address type='{{ channel.address.type }}' controller='{{ channel.address.controller }}' bus='{{ channel.address.bus }}' port='{{ channel.address.port }}'/>
</channel>
{% end for %}
{% for input in item.domain.devices.inputs %}
<input type='{{ input.type }}' bus='{{ input.bus }}'>
<address type='{{ input.address.type }}' bus='{{ input.address.bus }}' port='{{ input.address.port }}'/>
</input>
{% end for %}
<graphics type='{{ item.domain.devices.graphics.type }}' autoport='{{ item.domain.devices.graphics.autoport }}'>
<listen type='{{ item.domain.devices.graphics.listen.type }}'/>
<image compression='{{ item.domain.devices.graphics.image.compression }}'/>
</graphics>
<video>
<model type='{{ item.domain.devices.video.model.type }}' ram='{{ item.domain.devices.video.model.ram }}' vram='{{ item.domain.devices.video.model.vram }}' vgamem='{{ devices.video.model.vgamem }}' heads='{{ devices.video.model.heads }}' primary='{{ devices.video.model.primary }}'/>
<address type='{{ item.domain.devices.video.address.type }}' domain='{{ item.domain.devices.video.address.domain }}' bus='{{ item.domain.devices.video.address.bus }}' slot='{{ item.domain.devices.video.address.slot }}' function='{{ item.domain.devices.video.address.function }}'/>
</video>
<memballoon model='{{ item.domain.devices.memballoon.model }}'>
<address type='{{ item.domain.devices.memballoon.address.type }}' domain='{{ item.domain.devices.memballoon.address.domain }}' bus='{{ item.domain.devices.memballoon.address.bus }}' slot='{{ item.domain.devices.memballoon.address.slot }}' function='{{ item.domain.devices.memballoon.address.function }}'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='{{ item.domain.devices.rng.address.type }}' domain='{{ item.domain.devices.rng.address.domain }}' bus='{{ item.domain.devices.rng.address.bus }}' slot='{{ item.domain.devices.rng.address.slot }}' function='{{ item.domain.devices.rng.address.function }}'/>
</rng>
</devices>
</domain>

View File

@ -1,52 +0,0 @@
<domain type='kvm'>
<name>{{ vm_name }}</name>
<memory unit='MiB'>{{ vm_ram_mb }}</memory>
<vcpu placement='static'>{{ vm_vcpus }}</vcpu>
<os>
<type arch='x86_64' machine='pc-q35-5.2'>hvm</type>
<boot dev='hd'/>
</os>
<cpu mode='host-model' check='none'/>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='{{ libvirt_pool_dir }}/{{ vm_name }}.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</disk>
<interface type='network'>
<source network='{{ vm_net }}'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
<channel type='unix'>
<target type='virtio' name='org.qemu.guest_agent.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='2'/>
</channel>
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'>
<listen type='address'/>
<image compression='off'/>
</graphics>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</rng>
</devices>
</domain>

41
templates/user-data.j2 Normal file
View File

@ -0,0 +1,41 @@
#cloud-config
hostname: {{ domain.name }}
create_hostname_file: true
fqdn: {{ domain.name }}.eom.dev
apt:
generate_mirrorlists: true
package_reboot_if_required: true
package_update: true
package_upgrade: true
packages: {{ domain.packages }}
users:
- name: eric
lock_passwd: True
gecos: Eric O'Neill Meehan
groups: [adm, audio, cdrom, dialout, dip, floppy, netdev, plugdev, sudo, video]
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys: {{ eric_ssh_keys }}
chpasswd:
expire: false
users:
- name: eric
type: text
password: 123abc
ssh_pwauth: false
growpart:
mode: auto
devices: ['/']
resize_rootfs:
type: 'growpart'
resizefs: true
{% if mounts is defined %}
mounts: {{ mounts }}
{% endif %}

View File

@ -1,52 +0,0 @@
<domain type='kvm'>
<name>{{ vm_name }}</name>
<memory unit='MiB'>{{ vm_ram_mb }}</memory>
<vcpu placement='static'>{{ vm_vcpus }}</vcpu>
<os>
<type arch='x86_64' machine='pc-q35-5.2'>hvm</type>
<boot dev='hd'/>
</os>
<cpu mode='host-model' check='none'/>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='{{ libvirt_pool_dir }}/{{ vm_name }}.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</disk>
<interface type='network'>
<source network='{{ vm_net }}'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
<channel type='unix'>
<target type='virtio' name='org.qemu.guest_agent.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='2'/>
</channel>
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'>
<listen type='address'/>
<image compression='off'/>
</graphics>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</rng>
</devices>
</domain>

View File

@ -1,13 +1,6 @@
---
- name: Create a copy of an existing qcow2 image
hosts: localhost
gather_facts: no
tasks:
- name: Create a new qcow2 image from an existing one
libvirt_volume:
name: new-image.qcow2
source: /home/eric/Downloads/debian-12-nocloud-amd64.qcow2
pool: default
format: qcow2
state: present
- name: Execute test
hosts: gamma-control-plane
become: true
roles:
- ericomeehan.gondwana

66
vms.yaml Normal file
View File

@ -0,0 +1,66 @@
---
# Playbook for virtual machines
- name: Initialize virtual machines
hosts: vms
become: true
roles:
- role: ericomeehan.ericomeehan
- name: Initialize Kubernetes clusters
hosts: clusters
become: true
pre_tasks:
- name: Enable IPv4 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv4.ip_forward = 1'
state: present
- name: Enable IPv6 packet forwarding
lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.forwarding = 1'
state: present
- name: Reload sysctl configuration
command: sysctl --system
- name: Enable br_netfilter kernel module
command: modprobe br_netfilter
- name: Add the module to a configuration file for persistence
lineinfile:
path: /etc/modules-load.d/modules.conf
line: "br_netfilter"
- name: Install kubernetes library
apt:
name: python3-kubernetes
state: present
roles:
- role: geerlingguy.containerd
- name: Alpha Cluster
hosts: alpha
become: true
roles:
- role: geerlingguy.kubernetes
- name: Beta Cluster
hosts: beta
become: true
roles:
- role: geerlingguy.kubernetes
- name: Gamma Cluster
hosts: gamma
become: true
roles:
- role: geerlingguy.kubernetes
- name: Install Helm
hosts: control_planes
become: true
roles:
- role: geerlingguy.helm

View File

@ -1,40 +1,35 @@
---
# Playbook for workstations
- name: Initialize system
- name: Initialize workstations
hosts: workstations
become: true
roles:
- role: ericomeehan.debian
- role: ericomeehan.ericomeehan
- role: geerlingguy.docker
when: docker_needed == true
tasks:
- name: Add contrib repository
replace:
dest: /etc/apt/sources.list
regexp: '^(deb(?!.* contrib).*)'
replace: '\1 contrib'
- name: Update apt
- name: Install packages for user environment
become: yes
apt:
update_cache: yes
- name: Install additional packages
apt:
name:
- certbot
- ansible
- curl
- davfs2
- gimp
- git
- gnome-boxes
- gphoto2
- gpsd
- latexml
- neovim
- passwordsafe
- python3-venv
- texlive-full
- thunderbird
- tmux
- torbrowser-launcher
- w3m
state: present