From 4d376c353f83bef7df819a612cbc42cc351be0c4 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 12 Sep 2025 09:58:37 -0500 Subject: [PATCH] update --- home/ansible/create-postgres-debian13.yml | 216 ++++++++++++++++++++++ home/ansible/fix-k3s-workers.yml | 143 ++++++++++++++ home/ansible/forgejo_db_credentials.txt | 23 +++ home/ansible/recreate-worker2.yml | 161 ++++++++++++++++ home/cluster/k3s_vars.yml | 1 + 5 files changed, 544 insertions(+) create mode 100644 home/ansible/create-postgres-debian13.yml create mode 100644 home/ansible/fix-k3s-workers.yml create mode 100644 home/ansible/forgejo_db_credentials.txt create mode 100644 home/ansible/recreate-worker2.yml create mode 100644 home/cluster/k3s_vars.yml diff --git a/home/ansible/create-postgres-debian13.yml b/home/ansible/create-postgres-debian13.yml new file mode 100644 index 0000000..15c09d5 --- /dev/null +++ b/home/ansible/create-postgres-debian13.yml @@ -0,0 +1,216 @@ +--- +- name: Create PostgreSQL 17 LXC Container with Debian 13 on lab02 + hosts: lab02 + become: true + vars: + ct_id: 300 + ct_name: postgres + ct_template: "local:vztmpl/debian-13-standard_13.1-1_amd64.tar.zst" + ct_memory: 8192 # 8GB RAM + ct_disk_size: 512 # 512GB storage as requested + ct_cores: 4 + ct_ip: "10.0.19.5/22" + ct_gateway: "10.0.19.254" + ct_storage: "ceph" # Use Ceph RBD storage + aprs_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits length=16') }}" + + tasks: + - name: Check if container already exists + command: pct status {{ ct_id }} + register: ct_exists + failed_when: false + changed_when: false + + - name: Stop and destroy existing container if it exists + shell: | + pct stop {{ ct_id }} || true + pct destroy {{ ct_id }} --purge || true + when: ct_exists.rc == 0 + + - name: List available templates + command: pveam list local + register: template_list + changed_when: false + + - name: Show available templates + debug: + msg: "Available templates: {{ template_list.stdout_lines | select('match', '.*debian.*') | list }}" + + - name: Create PostgreSQL LXC container + command: | + pct create {{ ct_id }} {{ ct_template }} \ + --hostname {{ ct_name }} \ + --memory {{ ct_memory }} \ + --cores {{ ct_cores }} \ + --net0 name=eth0,bridge=vmbr0,ip={{ ct_ip }},gw={{ ct_gateway }} \ + --storage {{ ct_storage }} \ + --rootfs {{ ct_storage }}:{{ ct_disk_size }} \ + --unprivileged 1 \ + --features nesting=1 \ + --onboot 1 \ + --startup order=10 + + - name: Start container + command: pct start {{ ct_id }} + + - name: Wait for container to boot + pause: + seconds: 30 + + - name: Update container packages + shell: pct exec {{ ct_id }} -- apt update && pct exec {{ ct_id }} -- apt upgrade -y + + - name: Install PostgreSQL 17 repository + shell: | + pct exec {{ ct_id }} -- bash -c " + apt-get install -y wget ca-certificates + sh -c 'echo \"deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main\" > /etc/apt/sources.list.d/pgdg.list' + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - + apt-get update + " + + - name: Install PostgreSQL 17 and PostGIS + shell: | + pct exec {{ ct_id }} -- bash -c " + export DEBIAN_FRONTEND=noninteractive + apt-get install -y postgresql-17 postgresql-contrib-17 postgresql-17-postgis-3 postgis + " + + - name: Start and enable PostgreSQL + shell: | + pct exec {{ ct_id }} -- bash -c " + systemctl enable postgresql + systemctl start postgresql + " + + - name: Configure PostgreSQL for network access + shell: | + pct exec {{ ct_id }} -- bash -c " + # Configure postgresql.conf + sed -i \"s/#listen_addresses = 'localhost'/listen_addresses = '*'/g\" /etc/postgresql/17/main/postgresql.conf + + # Configure pg_hba.conf + echo '# TYPE DATABASE USER ADDRESS METHOD' > /etc/postgresql/17/main/pg_hba.conf + echo 'local all postgres peer' >> /etc/postgresql/17/main/pg_hba.conf + echo 'local all all peer' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all 127.0.0.1/32 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all ::1/128 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all 10.0.19.0/24 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all 10.0.16.0/22 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all 10.42.0.0/16 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + echo 'host all all 10.43.0.0/16 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf + + # Restart PostgreSQL + systemctl restart postgresql + " + + - name: Create APRS user and database + shell: | + pct exec {{ ct_id }} -- su - postgres -c "psql << 'EOF' + -- Create APRS user and database + CREATE USER aprs WITH PASSWORD '{{ aprs_password }}'; + CREATE DATABASE aprs OWNER aprs; + \c aprs + CREATE EXTENSION IF NOT EXISTS postgis; + GRANT ALL PRIVILEGES ON DATABASE aprs TO aprs; + GRANT ALL ON SCHEMA public TO aprs; + ALTER DATABASE aprs SET search_path TO public, postgis; + EOF" + + - name: Test APRS database connection + shell: | + pct exec {{ ct_id }} -- su - postgres -c "psql -d aprs -c 'SELECT version(); SELECT PostGIS_full_version();'" + register: db_test + + - name: Save APRS password to file + copy: + content: "{{ aprs_password }}" + dest: "./aprs_db_password.txt" + mode: '0600' + delegate_to: localhost + + - name: Display connection info + debug: + msg: | + PostgreSQL 17 with PostGIS installed successfully on Debian 13! + + Container details: + - Container ID: {{ ct_id }} + - Host: lab02 + - IP: 10.0.19.5 + - Storage: {{ ct_disk_size }}GB on {{ ct_storage }} + + Database details: + - PostgreSQL version: 17 + - PostGIS: Installed + - Database: aprs + - User: aprs + - Password: {{ aprs_password }} + - Password saved to: ./aprs_db_password.txt + + Connection string: + postgresql://aprs:{{ aprs_password }}@10.0.19.5:5432/aprs + + Test output: + {{ db_test.stdout }} + +- name: Create K8s secret for APRS database + hosts: home-k3s-control-1 + become: true + vars: + aprs_password: "{{ hostvars['lab02']['aprs_password'] }}" + tasks: + - name: Create aprs namespace if it doesn't exist + command: | + /usr/local/bin/k3s kubectl create namespace aprs --dry-run=client -o yaml | /usr/local/bin/k3s kubectl apply -f - + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Delete existing database secret if it exists + command: | + /usr/local/bin/k3s kubectl delete secret aprs-db-secret -n aprs --ignore-not-found=true + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Create database secret + command: | + /usr/local/bin/k3s kubectl create secret generic aprs-db-secret \ + --from-literal=DATABASE_URL="ecto://aprs:{{ aprs_password }}@10.0.19.5:5432/aprs" \ + --from-literal=DB_HOST="10.0.19.5" \ + --from-literal=DB_PORT="5432" \ + --from-literal=DB_NAME="aprs" \ + --from-literal=DB_USER="aprs" \ + --from-literal=DB_PASSWORD="{{ aprs_password }}" \ + -n aprs + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Verify secret was created + command: | + /usr/local/bin/k3s kubectl get secret aprs-db-secret -n aprs -o yaml + register: secret_verify + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Display secret creation result + debug: + msg: | + Kubernetes secret created successfully! + + Secret name: aprs-db-secret + Namespace: aprs + + To use in your deployment, add: + + envFrom: + - secretRef: + name: aprs-db-secret + + Or individual env vars: + + env: + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: aprs-db-secret + key: DATABASE_URL \ No newline at end of file diff --git a/home/ansible/fix-k3s-workers.yml b/home/ansible/fix-k3s-workers.yml new file mode 100644 index 0000000..5b1a6dd --- /dev/null +++ b/home/ansible/fix-k3s-workers.yml @@ -0,0 +1,143 @@ +--- +- name: Fix K3s worker nodes + hosts: k3s_workers + become: true + tasks: + - name: Stop k3s-agent service + systemd: + name: k3s-agent + state: stopped + enabled: no + ignore_errors: yes + + - name: Remove k3s node password + file: + path: /etc/rancher/node/password + state: absent + + - name: Remove k3s data directory + file: + path: /var/lib/rancher/k3s + state: absent + + - name: Remove k3s config + file: + path: /etc/rancher/k3s + state: absent + + - name: Ensure k3s binary exists + stat: + path: /usr/local/bin/k3s + register: k3s_binary + + - name: Download k3s binary if missing + get_url: + url: https://github.com/k3s-io/k3s/releases/download/{{ k3s_version | default('v1.28.5+k3s1') }}/k3s + dest: /usr/local/bin/k3s + mode: '0755' + when: not k3s_binary.stat.exists + + - name: Create k3s config directory + file: + path: /etc/rancher/k3s + state: directory + mode: '0755' + + - name: Get token from control node + delegate_to: home-k3s-control-1 + slurp: + src: /var/lib/rancher/k3s/server/node-token + register: node_token + run_once: true + + - name: Create k3s agent config + copy: + content: | + server: https://{{ hostvars['home-k3s-control-1']['ansible_host'] }}:6443 + token: {{ node_token.content | b64decode | trim }} + with-node-id: true + dest: /etc/rancher/k3s/config.yaml + + - name: Ensure k3s-agent service exists + copy: + content: | + [Unit] + Description=Lightweight Kubernetes + Documentation=https://k3s.io + Wants=network-online.target + After=network-online.target + + [Service] + Type=notify + EnvironmentFile=-/etc/default/%N + EnvironmentFile=-/etc/sysconfig/%N + KillMode=process + Delegate=yes + LimitNOFILE=1048576 + LimitNPROC=infinity + LimitCORE=infinity + TasksMax=infinity + TimeoutStartSec=0 + Restart=always + RestartSec=5s + ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service' + ExecStartPre=-/sbin/modprobe br_netfilter + ExecStartPre=-/sbin/modprobe overlay + ExecStart=/usr/local/bin/k3s agent + + [Install] + WantedBy=multi-user.target + dest: /etc/systemd/system/k3s-agent.service + + - name: Start k3s-agent service + systemd: + name: k3s-agent + daemon_reload: yes + enabled: yes + state: started + +- name: Remove stale nodes from cluster + hosts: home-k3s-control-1 + become: true + tasks: + - name: Get list of nodes + command: /usr/local/bin/k3s kubectl get nodes -o json + register: nodes_json + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Parse node list + set_fact: + nodes: "{{ nodes_json.stdout | from_json }}" + + - name: Remove NotReady worker nodes + command: /usr/local/bin/k3s kubectl delete node {{ item.metadata.name }} + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + loop: "{{ nodes['items'] }}" + when: + - item.metadata.name is match("home-k3s-worker-.*") + - item.status.conditions | selectattr('type', 'equalto', 'Ready') | selectattr('status', 'equalto', 'Unknown') | list | length > 0 + +- name: Verify worker nodes + hosts: home-k3s-control-1 + become: true + tasks: + - name: Wait for worker nodes to join + shell: /usr/local/bin/k3s kubectl get nodes | grep -E "home-k3s-worker-[0-9]+.*Ready" | wc -l + register: ready_workers + until: ready_workers.stdout | int >= 3 + retries: 30 + delay: 10 + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Display cluster status + command: /usr/local/bin/k3s kubectl get nodes + register: final_status + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Show cluster status + debug: + var: final_status.stdout_lines \ No newline at end of file diff --git a/home/ansible/forgejo_db_credentials.txt b/home/ansible/forgejo_db_credentials.txt new file mode 100644 index 0000000..a9bd9c3 --- /dev/null +++ b/home/ansible/forgejo_db_credentials.txt @@ -0,0 +1,23 @@ +Forgejo Database Credentials +============================ + +PostgreSQL Container: 300 on lab02 +Host: 10.0.19.5 +Port: 5432 +Database: forgejo +Username: forgejo +Password: 6Cj1BR1zgutXn0LzDCvanw + +Connection String: +postgresql://forgejo:6Cj1BR1zgutXn0LzDCvanw@10.0.19.5:5432/forgejo + +For Forgejo app.ini configuration: +[database] +DB_TYPE = postgres +HOST = 10.0.19.5:5432 +NAME = forgejo +USER = forgejo +PASSWD = 6Cj1BR1zgutXn0LzDCvanw +SSL_MODE = disable + +Note: The password has also been saved to /tmp/forgejo_db_password.txt \ No newline at end of file diff --git a/home/ansible/recreate-worker2.yml b/home/ansible/recreate-worker2.yml new file mode 100644 index 0000000..26b1459 --- /dev/null +++ b/home/ansible/recreate-worker2.yml @@ -0,0 +1,161 @@ +--- +- name: Recreate K3s Worker-2 VM on Proxmox + hosts: lab02 + gather_facts: no + vars: + template_vmid: 9000 + network_gateway: "10.0.19.254" + ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHLyVSEEAEbGZZqwPwEup0XrlTpu3x3iF9ExvvQPA4xN graham@mcintire.me" + + worker2: + vmid: 1201 + name: "home-k3s-worker-2" + ip: "10.0.19.111/24" + cores: 4 + memory: 8192 + disk: "64G" + target_node: "lab03" + + tasks: + - name: Clone template to create worker-2 + command: | + qm clone {{ template_vmid }} {{ worker2.vmid }} \ + --name {{ worker2.name }} \ + --full true \ + --target {{ worker2.target_node }} + register: clone_result + + - name: Configure worker-2 VM + delegate_to: lab03 + command: | + qm set {{ worker2.vmid }} \ + --cores {{ worker2.cores }} \ + --memory {{ worker2.memory }} \ + --ipconfig0 ip={{ worker2.ip }},gw={{ network_gateway }} \ + --sshkeys /root/.ssh/authorized_keys \ + --onboot 1 + + - name: Resize disk if needed + delegate_to: lab03 + command: | + qm resize {{ worker2.vmid }} scsi0 {{ worker2.disk }} + ignore_errors: yes + + - name: Start worker-2 VM + delegate_to: lab03 + command: qm start {{ worker2.vmid }} + + - name: Wait for VM to boot + pause: + seconds: 90 + + - name: Test SSH connectivity + delegate_to: localhost + wait_for: + host: 10.0.19.111 + port: 22 + timeout: 300 + +- name: Configure K3s on worker-2 + hosts: home-k3s-worker-2 + become: true + tasks: + - name: Wait for SSH to be ready + wait_for_connection: + delay: 30 + timeout: 300 + + - name: Gather facts + setup: + + - name: Install curl + package: + name: curl + state: present + + - name: Download k3s binary + get_url: + url: https://github.com/k3s-io/k3s/releases/download/v1.28.5+k3s1/k3s + dest: /usr/local/bin/k3s + mode: '0755' + + - name: Create k3s config directory + file: + path: /etc/rancher/k3s + state: directory + mode: '0755' + + - name: Get token from control node + delegate_to: home-k3s-control-1 + slurp: + src: /var/lib/rancher/k3s/server/node-token + register: node_token + + - name: Create k3s agent config + copy: + content: | + server: https://10.0.19.100:6443 + token: {{ node_token.content | b64decode | trim }} + with-node-id: true + dest: /etc/rancher/k3s/config.yaml + + - name: Create k3s-agent systemd service + copy: + content: | + [Unit] + Description=Lightweight Kubernetes + Documentation=https://k3s.io + Wants=network-online.target + After=network-online.target + + [Service] + Type=notify + EnvironmentFile=-/etc/default/%N + EnvironmentFile=-/etc/sysconfig/%N + KillMode=process + Delegate=yes + LimitNOFILE=1048576 + LimitNPROC=infinity + LimitCORE=infinity + TasksMax=infinity + TimeoutStartSec=0 + Restart=always + RestartSec=5s + ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service' + ExecStartPre=-/sbin/modprobe br_netfilter + ExecStartPre=-/sbin/modprobe overlay + ExecStart=/usr/local/bin/k3s agent + + [Install] + WantedBy=multi-user.target + dest: /etc/systemd/system/k3s-agent.service + + - name: Start k3s-agent service + systemd: + name: k3s-agent + daemon_reload: yes + enabled: yes + state: started + +- name: Verify worker-2 joined cluster + hosts: home-k3s-control-1 + become: true + tasks: + - name: Wait for worker-2 to join + shell: /usr/local/bin/k3s kubectl get nodes | grep -E "home-k3s-worker-2.*Ready" + register: worker2_status + until: worker2_status.rc == 0 + retries: 30 + delay: 10 + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Display cluster status + command: /usr/local/bin/k3s kubectl get nodes + register: final_status + environment: + KUBECONFIG: /etc/rancher/k3s/k3s.yaml + + - name: Show cluster status + debug: + var: final_status.stdout_lines \ No newline at end of file diff --git a/home/cluster/k3s_vars.yml b/home/cluster/k3s_vars.yml new file mode 100644 index 0000000..68c1285 --- /dev/null +++ b/home/cluster/k3s_vars.yml @@ -0,0 +1 @@ +k3s_token: "K1006c65c6d4e2ab336de2a35dc7c5e026895fa439ce083fe5b0155678c72dd8a4e::server:c60eed71d179e902fbce39ad6866fb07" \ No newline at end of file