chore: remove obsolete Nomad/Consul/Terraform/Ansible skeleton
These files were from the original IaC setup placeholder and no longer reflect the actual infrastructure (Docker Swarm + Compose, no Nomad/Consul). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,117 +0,0 @@
|
|||||||
# Hobbs.farm Infrastructure as Code
|
|
||||||
|
|
||||||
Enterprise-grade infrastructure management using HashiCorp stack + Ansible.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ HOBBS.FARM IaC │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
|
|
||||||
│ │ TERRAFORM │────▶│ ANSIBLE │────▶│ NOMAD │ │
|
|
||||||
│ │ │ │ │ │ │ │
|
|
||||||
│ │ • Infra │ │ • Config │ │ • Deploy │ │
|
|
||||||
│ │ • State │ │ • Install │ │ • Scale │ │
|
|
||||||
│ │ • DNS │ │ • Secure │ │ • Monitor │ │
|
|
||||||
│ └───────────┘ └───────────┘ └───────────┘ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ └────────────────┴────────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌───────────────────────┴───────────────────────┐ │
|
|
||||||
│ │ HASHICORP STACK │ │
|
|
||||||
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
|
||||||
│ │ │ NOMAD │ │ CONSUL │ │ VAULT │ │ │
|
|
||||||
│ │ │ orchest │◄─┤ service │◄─┤ secrets │ │ │
|
|
||||||
│ │ │ ration │ │ mesh │ │ mgmt │ │ │
|
|
||||||
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
|
|
||||||
│ └───────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────────────────┐ │
|
|
||||||
│ │ HOSTS │ │
|
|
||||||
│ │ hf-pdocker-01 (primary) hf-pdocker-02 (secondary) │
|
|
||||||
│ │ 192.168.86.192 192.168.86.45 │
|
|
||||||
│ └─────────────────────────────────────────────────┘ │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Directory Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
hobbs-iac/
|
|
||||||
├── terraform/ # Infrastructure provisioning
|
|
||||||
│ ├── environments/ # Per-environment configs
|
|
||||||
│ │ └── prod/
|
|
||||||
│ ├── modules/ # Reusable modules
|
|
||||||
│ └── nomad-jobs/ # Nomad job definitions (HCL)
|
|
||||||
├── ansible/ # Configuration management
|
|
||||||
│ ├── inventory/ # Host inventory
|
|
||||||
│ ├── playbooks/ # Automation playbooks
|
|
||||||
│ ├── roles/ # Ansible roles
|
|
||||||
│ └── group_vars/ # Variables
|
|
||||||
├── nomad/ # Nomad-specific configs
|
|
||||||
│ ├── jobs/ # Job specifications
|
|
||||||
│ ├── policies/ # ACL policies
|
|
||||||
│ └── templates/ # Job templates
|
|
||||||
├── consul/ # Consul configs
|
|
||||||
│ ├── config/ # Consul configuration
|
|
||||||
│ └── policies/ # ACL policies
|
|
||||||
├── vault/ # Vault configs
|
|
||||||
│ ├── policies/ # Access policies
|
|
||||||
│ └── secrets/ # Secret definitions (encrypted)
|
|
||||||
└── scripts/ # Utility scripts
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### 1. Bootstrap Hosts (Ansible)
|
|
||||||
```bash
|
|
||||||
cd ansible
|
|
||||||
ansible-playbook -i inventory/hosts.yml playbooks/bootstrap.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Install HashiCorp Stack
|
|
||||||
```bash
|
|
||||||
ansible-playbook -i inventory/hosts.yml playbooks/hashicorp-stack.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Initialize Terraform
|
|
||||||
```bash
|
|
||||||
cd terraform/environments/prod
|
|
||||||
terraform init
|
|
||||||
terraform plan
|
|
||||||
terraform apply
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Deploy Services
|
|
||||||
```bash
|
|
||||||
# Deploy all Nomad jobs
|
|
||||||
nomad job run ../nomad-jobs/traefik.nomad
|
|
||||||
nomad job run ../nomad-jobs/monitoring.nomad
|
|
||||||
# ... etc
|
|
||||||
```
|
|
||||||
|
|
||||||
## Naming Convention
|
|
||||||
|
|
||||||
See [Naming Convention Standard](docs/naming-convention.md)
|
|
||||||
|
|
||||||
| Type | Format | Example |
|
|
||||||
|------|--------|---------|
|
|
||||||
| Physical | `hf-p<function>-##` | `hf-pdocker-01` |
|
|
||||||
| Virtual | `hf-v<function>-##` | `hf-vapp-01` |
|
|
||||||
| Container | `hf-c<function>-##` | `hf-cproxy-01` |
|
|
||||||
| Network | `hf-n<function>-##` | `hf-nfw-01` |
|
|
||||||
| Storage | `hf-s<function>-##` | `hf-snas-01` |
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- Ansible 2.15+
|
|
||||||
- Terraform 1.5+
|
|
||||||
- Nomad 1.6+
|
|
||||||
- Consul 1.16+
|
|
||||||
- Vault 1.15+
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Private - Hobbs.farm internal use only
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
---
|
|
||||||
# Hobbs.farm Infrastructure Inventory
|
|
||||||
# Naming: <location>-<type><function>-<sequence>
|
|
||||||
|
|
||||||
all:
|
|
||||||
vars:
|
|
||||||
ansible_python_interpreter: /usr/bin/python3
|
|
||||||
domain: hobbs.farm
|
|
||||||
timezone: America/Chicago
|
|
||||||
|
|
||||||
# HashiCorp versions
|
|
||||||
nomad_version: "1.7.3"
|
|
||||||
consul_version: "1.17.2"
|
|
||||||
vault_version: "1.15.4"
|
|
||||||
|
|
||||||
# Cluster settings
|
|
||||||
datacenter: hf-dc1
|
|
||||||
|
|
||||||
# Data paths
|
|
||||||
nomad_data_dir: /opt/nomad
|
|
||||||
consul_data_dir: /opt/consul
|
|
||||||
vault_data_dir: /opt/vault
|
|
||||||
|
|
||||||
children:
|
|
||||||
# =========================================
|
|
||||||
# Nomad Cluster
|
|
||||||
# =========================================
|
|
||||||
nomad_servers:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
nomad_server: true
|
|
||||||
nomad_client: true
|
|
||||||
nomad_bootstrap_expect: 1
|
|
||||||
|
|
||||||
nomad_clients:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
nomad_client: true
|
|
||||||
nomad_node_class: "primary"
|
|
||||||
hf-pdocker-02:
|
|
||||||
nomad_client: true
|
|
||||||
nomad_node_class: "secondary"
|
|
||||||
|
|
||||||
# =========================================
|
|
||||||
# Consul Cluster
|
|
||||||
# =========================================
|
|
||||||
consul_servers:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
consul_server: true
|
|
||||||
consul_bootstrap_expect: 1
|
|
||||||
|
|
||||||
consul_clients:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
hf-pdocker-02:
|
|
||||||
|
|
||||||
# =========================================
|
|
||||||
# Vault Cluster
|
|
||||||
# =========================================
|
|
||||||
vault_servers:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
vault_server: true
|
|
||||||
|
|
||||||
# =========================================
|
|
||||||
# Physical Hosts
|
|
||||||
# =========================================
|
|
||||||
physical:
|
|
||||||
children:
|
|
||||||
docker_hosts:
|
|
||||||
hosts:
|
|
||||||
hf-pdocker-01:
|
|
||||||
ansible_host: 192.168.86.192
|
|
||||||
ansible_user: glyptic
|
|
||||||
ansible_become_password: "{{ vault_sudo_password }}"
|
|
||||||
legacy_name: hobbs
|
|
||||||
role: primary
|
|
||||||
|
|
||||||
hf-pdocker-02:
|
|
||||||
ansible_host: 192.168.86.45
|
|
||||||
ansible_user: glyptic
|
|
||||||
ansible_ssh_private_key_file: ~/.ssh/id_docker_server
|
|
||||||
legacy_name: peggy
|
|
||||||
role: secondary
|
|
||||||
status: degraded
|
|
||||||
|
|
||||||
nvr_hosts:
|
|
||||||
hosts:
|
|
||||||
hf-pnvr-01:
|
|
||||||
ansible_host: 192.168.86.181
|
|
||||||
ansible_user: glyptic
|
|
||||||
ansible_ssh_private_key_file: ~/.ssh/id_docker_server
|
|
||||||
legacy_name: bart
|
|
||||||
|
|
||||||
# =========================================
|
|
||||||
# Network & Storage (reference only)
|
|
||||||
# =========================================
|
|
||||||
network:
|
|
||||||
hosts:
|
|
||||||
hf-nfw-01:
|
|
||||||
ansible_host: 192.168.86.1
|
|
||||||
legacy_name: firewalla
|
|
||||||
|
|
||||||
storage:
|
|
||||||
hosts:
|
|
||||||
hf-snas-01:
|
|
||||||
ansible_host: 192.168.86.30
|
|
||||||
legacy_name: nas
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
---
|
|
||||||
# Install HashiCorp Stack (Nomad, Consul, Vault)
|
|
||||||
# Run: ansible-playbook -i inventory/hosts.yml playbooks/hashicorp-stack.yml
|
|
||||||
|
|
||||||
- name: Install Consul
|
|
||||||
hosts: consul_servers:consul_clients
|
|
||||||
become: yes
|
|
||||||
roles:
|
|
||||||
- consul
|
|
||||||
tags: [consul]
|
|
||||||
|
|
||||||
- name: Install Vault
|
|
||||||
hosts: vault_servers
|
|
||||||
become: yes
|
|
||||||
roles:
|
|
||||||
- vault
|
|
||||||
tags: [vault]
|
|
||||||
|
|
||||||
- name: Install Nomad
|
|
||||||
hosts: nomad_servers:nomad_clients
|
|
||||||
become: yes
|
|
||||||
roles:
|
|
||||||
- nomad
|
|
||||||
tags: [nomad]
|
|
||||||
|
|
||||||
- name: Bootstrap Nomad cluster
|
|
||||||
hosts: nomad_servers[0]
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Wait for Nomad to be ready
|
|
||||||
ansible.builtin.uri:
|
|
||||||
url: "http://{{ ansible_host }}:4646/v1/status/leader"
|
|
||||||
method: GET
|
|
||||||
status_code: 200
|
|
||||||
register: nomad_leader
|
|
||||||
until: nomad_leader.status == 200
|
|
||||||
retries: 30
|
|
||||||
delay: 5
|
|
||||||
|
|
||||||
- name: Display Nomad leader
|
|
||||||
ansible.builtin.debug:
|
|
||||||
msg: "Nomad leader: {{ nomad_leader.json }}"
|
|
||||||
tags: [nomad, bootstrap]
|
|
||||||
|
|
||||||
- name: Verify cluster health
|
|
||||||
hosts: nomad_servers[0]
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Check Nomad node status
|
|
||||||
ansible.builtin.command: nomad node status
|
|
||||||
register: nomad_nodes
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Display nodes
|
|
||||||
ansible.builtin.debug:
|
|
||||||
var: nomad_nodes.stdout_lines
|
|
||||||
|
|
||||||
- name: Check Consul members
|
|
||||||
ansible.builtin.command: consul members
|
|
||||||
register: consul_members
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Display Consul members
|
|
||||||
ansible.builtin.debug:
|
|
||||||
var: consul_members.stdout_lines
|
|
||||||
tags: [verify]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Restart Consul
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: consul
|
|
||||||
state: restarted
|
|
||||||
daemon_reload: yes
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
---
|
|
||||||
# Consul Installation Role
|
|
||||||
|
|
||||||
- name: Add HashiCorp GPG key
|
|
||||||
ansible.builtin.apt_key:
|
|
||||||
url: https://apt.releases.hashicorp.com/gpg
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Add HashiCorp repository
|
|
||||||
ansible.builtin.apt_repository:
|
|
||||||
repo: "deb https://apt.releases.hashicorp.com {{ ansible_distribution_release }} main"
|
|
||||||
state: present
|
|
||||||
filename: hashicorp
|
|
||||||
|
|
||||||
- name: Install Consul
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name: "consul={{ consul_version }}-1"
|
|
||||||
state: present
|
|
||||||
update_cache: yes
|
|
||||||
|
|
||||||
- name: Create Consul directories
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
owner: consul
|
|
||||||
group: consul
|
|
||||||
mode: '0755'
|
|
||||||
loop:
|
|
||||||
- "{{ consul_data_dir }}"
|
|
||||||
- "{{ consul_data_dir }}/data"
|
|
||||||
- /etc/consul.d
|
|
||||||
|
|
||||||
- name: Configure Consul
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: consul.hcl.j2
|
|
||||||
dest: /etc/consul.d/consul.hcl
|
|
||||||
owner: consul
|
|
||||||
group: consul
|
|
||||||
mode: '0640'
|
|
||||||
notify: Restart Consul
|
|
||||||
|
|
||||||
- name: Configure Consul server (if server)
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: server.hcl.j2
|
|
||||||
dest: /etc/consul.d/server.hcl
|
|
||||||
owner: consul
|
|
||||||
group: consul
|
|
||||||
mode: '0640'
|
|
||||||
when: consul_server | default(false)
|
|
||||||
notify: Restart Consul
|
|
||||||
|
|
||||||
- name: Enable and start Consul
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: consul
|
|
||||||
enabled: yes
|
|
||||||
state: started
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Consul Configuration
|
|
||||||
# Managed by Ansible
|
|
||||||
|
|
||||||
datacenter = "{{ datacenter }}"
|
|
||||||
data_dir = "{{ consul_data_dir }}/data"
|
|
||||||
node_name = "{{ inventory_hostname }}"
|
|
||||||
|
|
||||||
bind_addr = "{{ ansible_host }}"
|
|
||||||
client_addr = "0.0.0.0"
|
|
||||||
|
|
||||||
ui_config {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# DNS settings
|
|
||||||
dns_config {
|
|
||||||
allow_stale = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Service mesh
|
|
||||||
connect {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Telemetry
|
|
||||||
telemetry {
|
|
||||||
prometheus_retention_time = "24h"
|
|
||||||
disable_hostname = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Performance
|
|
||||||
performance {
|
|
||||||
raft_multiplier = 1
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Consul Server Configuration
|
|
||||||
|
|
||||||
server = true
|
|
||||||
bootstrap_expect = {{ consul_bootstrap_expect | default(1) }}
|
|
||||||
|
|
||||||
# Raft settings
|
|
||||||
raft_protocol = 3
|
|
||||||
|
|
||||||
# Autopilot
|
|
||||||
autopilot {
|
|
||||||
cleanup_dead_servers = true
|
|
||||||
last_contact_threshold = "200ms"
|
|
||||||
max_trailing_logs = 250
|
|
||||||
server_stabilization_time = "10s"
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Restart Nomad
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: nomad
|
|
||||||
state: restarted
|
|
||||||
daemon_reload: yes
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
---
|
|
||||||
# Nomad Installation Role
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name:
|
|
||||||
- curl
|
|
||||||
- gnupg
|
|
||||||
- lsb-release
|
|
||||||
- apt-transport-https
|
|
||||||
state: present
|
|
||||||
update_cache: yes
|
|
||||||
|
|
||||||
- name: Add HashiCorp GPG key
|
|
||||||
ansible.builtin.apt_key:
|
|
||||||
url: https://apt.releases.hashicorp.com/gpg
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Add HashiCorp repository
|
|
||||||
ansible.builtin.apt_repository:
|
|
||||||
repo: "deb https://apt.releases.hashicorp.com {{ ansible_distribution_release }} main"
|
|
||||||
state: present
|
|
||||||
filename: hashicorp
|
|
||||||
|
|
||||||
- name: Install Nomad
|
|
||||||
ansible.builtin.apt:
|
|
||||||
name: "nomad={{ nomad_version }}-1"
|
|
||||||
state: present
|
|
||||||
update_cache: yes
|
|
||||||
|
|
||||||
- name: Create Nomad directories
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
owner: nomad
|
|
||||||
group: nomad
|
|
||||||
mode: '0755'
|
|
||||||
loop:
|
|
||||||
- "{{ nomad_data_dir }}"
|
|
||||||
- "{{ nomad_data_dir }}/data"
|
|
||||||
- /etc/nomad.d
|
|
||||||
|
|
||||||
- name: Configure Nomad
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: nomad.hcl.j2
|
|
||||||
dest: /etc/nomad.d/nomad.hcl
|
|
||||||
owner: nomad
|
|
||||||
group: nomad
|
|
||||||
mode: '0640'
|
|
||||||
notify: Restart Nomad
|
|
||||||
|
|
||||||
- name: Configure Nomad server (if server)
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: server.hcl.j2
|
|
||||||
dest: /etc/nomad.d/server.hcl
|
|
||||||
owner: nomad
|
|
||||||
group: nomad
|
|
||||||
mode: '0640'
|
|
||||||
when: nomad_server | default(false)
|
|
||||||
notify: Restart Nomad
|
|
||||||
|
|
||||||
- name: Configure Nomad client
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: client.hcl.j2
|
|
||||||
dest: /etc/nomad.d/client.hcl
|
|
||||||
owner: nomad
|
|
||||||
group: nomad
|
|
||||||
mode: '0640'
|
|
||||||
when: nomad_client | default(false)
|
|
||||||
notify: Restart Nomad
|
|
||||||
|
|
||||||
- name: Enable and start Nomad
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: nomad
|
|
||||||
enabled: yes
|
|
||||||
state: started
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Nomad Client Configuration
|
|
||||||
|
|
||||||
client {
|
|
||||||
enabled = true
|
|
||||||
|
|
||||||
node_class = "{{ nomad_node_class | default('default') }}"
|
|
||||||
|
|
||||||
# Resource reservations
|
|
||||||
reserved {
|
|
||||||
cpu = 500
|
|
||||||
memory = 512
|
|
||||||
}
|
|
||||||
|
|
||||||
# Host volumes for persistent data
|
|
||||||
host_volume "docker-data" {
|
|
||||||
path = "/mnt/nas/docker"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
|
|
||||||
host_volume "media" {
|
|
||||||
path = "/mnt/nas/media"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
|
|
||||||
# Meta information
|
|
||||||
meta {
|
|
||||||
"rack" = "{{ rack | default('rack-1') }}"
|
|
||||||
"datacenter" = "{{ datacenter }}"
|
|
||||||
"legacy_name" = "{{ legacy_name | default('unknown') }}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Network interface
|
|
||||||
network_interface = "{{ ansible_default_ipv4.interface | default('eth0') }}"
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
# Nomad Configuration
|
|
||||||
# Managed by Ansible - Do not edit manually
|
|
||||||
|
|
||||||
datacenter = "{{ datacenter }}"
|
|
||||||
data_dir = "{{ nomad_data_dir }}/data"
|
|
||||||
bind_addr = "0.0.0.0"
|
|
||||||
|
|
||||||
advertise {
|
|
||||||
http = "{{ ansible_host }}"
|
|
||||||
rpc = "{{ ansible_host }}"
|
|
||||||
serf = "{{ ansible_host }}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enable ACLs (after bootstrap)
|
|
||||||
# acl {
|
|
||||||
# enabled = true
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Consul integration
|
|
||||||
consul {
|
|
||||||
address = "127.0.0.1:8500"
|
|
||||||
|
|
||||||
server_service_name = "nomad"
|
|
||||||
client_service_name = "nomad-client"
|
|
||||||
|
|
||||||
auto_advertise = true
|
|
||||||
server_auto_join = true
|
|
||||||
client_auto_join = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Vault integration (after Vault setup)
|
|
||||||
# vault {
|
|
||||||
# enabled = true
|
|
||||||
# address = "http://127.0.0.1:8200"
|
|
||||||
# }
|
|
||||||
|
|
||||||
telemetry {
|
|
||||||
collection_interval = "10s"
|
|
||||||
disable_hostname = true
|
|
||||||
prometheus_metrics = true
|
|
||||||
publish_allocation_metrics = true
|
|
||||||
publish_node_metrics = true
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin "docker" {
|
|
||||||
config {
|
|
||||||
allow_privileged = true
|
|
||||||
volumes {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
extra_labels = ["job_name", "task_group_name", "task_name", "namespace", "node_name"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Nomad Server Configuration
|
|
||||||
|
|
||||||
server {
|
|
||||||
enabled = true
|
|
||||||
bootstrap_expect = {{ nomad_bootstrap_expect | default(1) }}
|
|
||||||
|
|
||||||
# Raft settings
|
|
||||||
raft_protocol = 3
|
|
||||||
|
|
||||||
# Server join (for multi-server setup)
|
|
||||||
# server_join {
|
|
||||||
# retry_join = ["hf-pdocker-01.hobbs.farm"]
|
|
||||||
# }
|
|
||||||
}
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
job "monitoring" {
|
|
||||||
datacenters = ["hf-dc1"]
|
|
||||||
type = "service"
|
|
||||||
|
|
||||||
group "prometheus" {
|
|
||||||
count = 1
|
|
||||||
|
|
||||||
network {
|
|
||||||
port "prometheus" {
|
|
||||||
static = 9095
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service {
|
|
||||||
name = "prometheus"
|
|
||||||
port = "prometheus"
|
|
||||||
|
|
||||||
tags = [
|
|
||||||
"traefik.enable=true",
|
|
||||||
"traefik.http.routers.prometheus.rule=Host(`prometheus.hobbs.farm`)",
|
|
||||||
]
|
|
||||||
|
|
||||||
check {
|
|
||||||
type = "http"
|
|
||||||
path = "/-/healthy"
|
|
||||||
interval = "10s"
|
|
||||||
timeout = "2s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task "prometheus" {
|
|
||||||
driver = "docker"
|
|
||||||
|
|
||||||
config {
|
|
||||||
image = "prom/prometheus:v2.48.0"
|
|
||||||
ports = ["prometheus"]
|
|
||||||
|
|
||||||
args = [
|
|
||||||
"--config.file=/etc/prometheus/prometheus.yml",
|
|
||||||
"--storage.tsdb.path=/prometheus",
|
|
||||||
"--web.listen-address=:9095",
|
|
||||||
"--web.enable-lifecycle",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
data = <<-EOF
|
|
||||||
global:
|
|
||||||
scrape_interval: 15s
|
|
||||||
evaluation_interval: 15s
|
|
||||||
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: 'prometheus'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['localhost:9095']
|
|
||||||
|
|
||||||
- job_name: 'nomad'
|
|
||||||
consul_sd_configs:
|
|
||||||
- server: '{{ env "NOMAD_IP_prometheus" }}:8500'
|
|
||||||
services: ['nomad-client', 'nomad']
|
|
||||||
relabel_configs:
|
|
||||||
- source_labels: ['__meta_consul_tags']
|
|
||||||
regex: '.*,metrics,.*'
|
|
||||||
action: keep
|
|
||||||
|
|
||||||
- job_name: 'consul'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['{{ env "NOMAD_IP_prometheus" }}:8500']
|
|
||||||
EOF
|
|
||||||
|
|
||||||
destination = "local/prometheus.yml"
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
cpu = 200
|
|
||||||
memory = 512
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
volume = "docker-data"
|
|
||||||
destination = "/prometheus"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume "docker-data" {
|
|
||||||
type = "host"
|
|
||||||
source = "docker-data"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group "grafana" {
|
|
||||||
count = 1
|
|
||||||
|
|
||||||
network {
|
|
||||||
port "grafana" {
|
|
||||||
static = 3001
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service {
|
|
||||||
name = "grafana"
|
|
||||||
port = "grafana"
|
|
||||||
|
|
||||||
tags = [
|
|
||||||
"traefik.enable=true",
|
|
||||||
"traefik.http.routers.grafana.rule=Host(`grafana.hobbs.farm`)",
|
|
||||||
]
|
|
||||||
|
|
||||||
check {
|
|
||||||
type = "http"
|
|
||||||
path = "/api/health"
|
|
||||||
interval = "10s"
|
|
||||||
timeout = "2s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task "grafana" {
|
|
||||||
driver = "docker"
|
|
||||||
|
|
||||||
config {
|
|
||||||
image = "grafana/grafana:10.2.2"
|
|
||||||
ports = ["grafana"]
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
GF_SERVER_HTTP_PORT = "3001"
|
|
||||||
GF_SECURITY_ADMIN_PASSWORD = "admin" # TODO: Use Vault
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
cpu = 200
|
|
||||||
memory = 256
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
volume = "docker-data"
|
|
||||||
destination = "/var/lib/grafana"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume "docker-data" {
|
|
||||||
type = "host"
|
|
||||||
source = "docker-data"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group "alertmanager" {
|
|
||||||
count = 1
|
|
||||||
|
|
||||||
network {
|
|
||||||
port "alertmanager" {
|
|
||||||
static = 9093
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service {
|
|
||||||
name = "alertmanager"
|
|
||||||
port = "alertmanager"
|
|
||||||
|
|
||||||
check {
|
|
||||||
type = "http"
|
|
||||||
path = "/-/healthy"
|
|
||||||
interval = "10s"
|
|
||||||
timeout = "2s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task "alertmanager" {
|
|
||||||
driver = "docker"
|
|
||||||
|
|
||||||
config {
|
|
||||||
image = "prom/alertmanager:v0.26.0"
|
|
||||||
ports = ["alertmanager"]
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
cpu = 100
|
|
||||||
memory = 128
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
job "traefik" {
|
|
||||||
datacenters = ["hf-dc1"]
|
|
||||||
type = "service"
|
|
||||||
|
|
||||||
# Run on primary node
|
|
||||||
constraint {
|
|
||||||
attribute = "${node.class}"
|
|
||||||
value = "primary"
|
|
||||||
}
|
|
||||||
|
|
||||||
group "traefik" {
|
|
||||||
count = 1
|
|
||||||
|
|
||||||
network {
|
|
||||||
port "http" {
|
|
||||||
static = 80
|
|
||||||
}
|
|
||||||
port "https" {
|
|
||||||
static = 443
|
|
||||||
}
|
|
||||||
port "api" {
|
|
||||||
static = 8080
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service {
|
|
||||||
name = "traefik"
|
|
||||||
port = "https"
|
|
||||||
|
|
||||||
tags = [
|
|
||||||
"traefik.enable=true",
|
|
||||||
"traefik.http.routers.api.rule=Host(`traefik.hobbs.farm`)",
|
|
||||||
"traefik.http.routers.api.service=api@internal",
|
|
||||||
]
|
|
||||||
|
|
||||||
check {
|
|
||||||
type = "http"
|
|
||||||
path = "/ping"
|
|
||||||
port = "api"
|
|
||||||
interval = "10s"
|
|
||||||
timeout = "2s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task "traefik" {
|
|
||||||
driver = "docker"
|
|
||||||
|
|
||||||
config {
|
|
||||||
image = "traefik:v3.0"
|
|
||||||
|
|
||||||
ports = ["http", "https", "api"]
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"local/traefik.yml:/etc/traefik/traefik.yml:ro",
|
|
||||||
"local/dynamic:/etc/traefik/dynamic:ro",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Mount Docker socket for provider
|
|
||||||
mount {
|
|
||||||
type = "bind"
|
|
||||||
source = "/var/run/docker.sock"
|
|
||||||
target = "/var/run/docker.sock"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
data = <<-EOF
|
|
||||||
api:
|
|
||||||
dashboard: true
|
|
||||||
insecure: true
|
|
||||||
|
|
||||||
entryPoints:
|
|
||||||
web:
|
|
||||||
address: ":80"
|
|
||||||
http:
|
|
||||||
redirections:
|
|
||||||
entryPoint:
|
|
||||||
to: websecure
|
|
||||||
scheme: https
|
|
||||||
websecure:
|
|
||||||
address: ":443"
|
|
||||||
|
|
||||||
providers:
|
|
||||||
consulCatalog:
|
|
||||||
prefix: traefik
|
|
||||||
exposedByDefault: false
|
|
||||||
endpoint:
|
|
||||||
address: "{{ env "NOMAD_IP_http" }}:8500"
|
|
||||||
file:
|
|
||||||
directory: /etc/traefik/dynamic
|
|
||||||
watch: true
|
|
||||||
|
|
||||||
certificatesResolvers:
|
|
||||||
letsencrypt:
|
|
||||||
acme:
|
|
||||||
email: jeremy@hobbs.farm
|
|
||||||
storage: /data/acme.json
|
|
||||||
dnsChallenge:
|
|
||||||
provider: cloudflare
|
|
||||||
|
|
||||||
ping:
|
|
||||||
entryPoint: api
|
|
||||||
|
|
||||||
log:
|
|
||||||
level: INFO
|
|
||||||
EOF
|
|
||||||
|
|
||||||
destination = "local/traefik.yml"
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
cpu = 200
|
|
||||||
memory = 256
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
volume = "docker-data"
|
|
||||||
destination = "/data"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume "docker-data" {
|
|
||||||
type = "host"
|
|
||||||
source = "docker-data"
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# Hobbs.farm Production Environment
|
|
||||||
# Terraform configuration for Nomad job management
|
|
||||||
|
|
||||||
terraform {
|
|
||||||
required_version = ">= 1.5.0"
|
|
||||||
|
|
||||||
required_providers {
|
|
||||||
nomad = {
|
|
||||||
source = "hashicorp/nomad"
|
|
||||||
version = "~> 2.0"
|
|
||||||
}
|
|
||||||
consul = {
|
|
||||||
source = "hashicorp/consul"
|
|
||||||
version = "~> 2.18"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Backend configuration for state storage
|
|
||||||
# Uncomment when ready to use remote state
|
|
||||||
# backend "consul" {
|
|
||||||
# address = "hf-pdocker-01.hobbs.farm:8500"
|
|
||||||
# scheme = "http"
|
|
||||||
# path = "terraform/hobbs-iac/prod"
|
|
||||||
# }
|
|
||||||
}
|
|
||||||
|
|
||||||
# Provider configurations
|
|
||||||
provider "nomad" {
|
|
||||||
address = "http://hf-pdocker-01.hobbs.farm:4646"
|
|
||||||
# secret_id = var.nomad_token # Uncomment after ACL setup
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "consul" {
|
|
||||||
address = "hf-pdocker-01.hobbs.farm:8500"
|
|
||||||
datacenter = "hf-dc1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
variable "environment" {
|
|
||||||
default = "prod"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "datacenter" {
|
|
||||||
default = "hf-dc1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Deploy Nomad jobs
|
|
||||||
resource "nomad_job" "traefik" {
|
|
||||||
jobspec = file("${path.module}/../../nomad-jobs/traefik.nomad")
|
|
||||||
|
|
||||||
hcl2 {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "nomad_job" "monitoring" {
|
|
||||||
jobspec = file("${path.module}/../../nomad-jobs/monitoring.nomad")
|
|
||||||
|
|
||||||
hcl2 {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
depends_on = [nomad_job.traefik]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Consul KV for configuration
|
|
||||||
resource "consul_keys" "config" {
|
|
||||||
datacenter = var.datacenter
|
|
||||||
|
|
||||||
key {
|
|
||||||
path = "hobbs/config/environment"
|
|
||||||
value = var.environment
|
|
||||||
}
|
|
||||||
|
|
||||||
key {
|
|
||||||
path = "hobbs/config/datacenter"
|
|
||||||
value = var.datacenter
|
|
||||||
}
|
|
||||||
|
|
||||||
key {
|
|
||||||
path = "hobbs/config/domain"
|
|
||||||
value = "hobbs.farm"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Outputs
|
|
||||||
output "nomad_address" {
|
|
||||||
value = "http://hf-pdocker-01.hobbs.farm:4646"
|
|
||||||
}
|
|
||||||
|
|
||||||
output "consul_address" {
|
|
||||||
value = "http://hf-pdocker-01.hobbs.farm:8500"
|
|
||||||
}
|
|
||||||
|
|
||||||
output "traefik_job_id" {
|
|
||||||
value = nomad_job.traefik.id
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user