migrate from flux to argocd
- install argocd at home/cluster/argocd/, app-of-apps via root-app.yaml - 4 child Applications: aprs, gridmap, prop, towerops - argo.w5isp.com via cloudflared tunnel (CNAME + ingress_rule in tofu) - update CLAUDE.md: drop K3s/Wavelog/n8n/Node-RED, document GitOps + ArgoCD
This commit is contained in:
parent
c3ae90aff0
commit
ae5ceebf44
10 changed files with 24704 additions and 64 deletions
89
CLAUDE.md
89
CLAUDE.md
|
|
@ -28,7 +28,7 @@ ansible-playbook playbook.yml --tags provision,bind9
|
|||
# - Storage: local-lvm (for BIND9 and general infrastructure VMs)
|
||||
# - Network: vmbr0
|
||||
#
|
||||
# Note: Talos K3s nodes use different template and Longhorn for persistent storage
|
||||
# Note: Talos nodes use a different template and Longhorn for persistent storage
|
||||
```
|
||||
|
||||
### Ansible Operations
|
||||
|
|
@ -62,20 +62,6 @@ tofu apply
|
|||
tofu fmt
|
||||
```
|
||||
|
||||
### Kubernetes Operations (K3s cluster at 204.110.191.2)
|
||||
```bash
|
||||
# Set kubeconfig
|
||||
export KUBECONFIG=/Users/graham/dev/infra/home/ansible/kubeconfig
|
||||
|
||||
# Deploy APRS.me application
|
||||
cd home/cluster/aprs
|
||||
./deploy.sh
|
||||
|
||||
# Check deployment status
|
||||
kubectl get pods -n aprs
|
||||
kubectl get svc -n aprs
|
||||
```
|
||||
|
||||
### Talos Operations (Home Cluster)
|
||||
```bash
|
||||
# Change to talos directory
|
||||
|
|
@ -117,8 +103,8 @@ talosctl --talosconfig talosconfig logs -f kubelet
|
|||
|
||||
- `home/` - Home lab configurations
|
||||
- `cluster/` - Kubernetes application deployments
|
||||
- `aprs/` - APRS.me deployment with PostgreSQL/PostGIS and Redis
|
||||
- `wavelog/` - Wavelog amateur radio logging application
|
||||
- `argocd/` - ArgoCD install + Application manifests (app-of-apps via `root-app.yaml`)
|
||||
- `aprs/` - APRS.me deployment manifests (legacy; live manifests in the `aprs.me` repo's `k8s/`)
|
||||
|
||||
### Key Infrastructure Services
|
||||
|
||||
|
|
@ -201,35 +187,25 @@ tofu plan
|
|||
- `controlplane.yaml` / `worker.yaml` - Base node configs
|
||||
- `configs/talos-worker{1,2,3}.yaml` - Per-node worker configs (with disk/extension settings)
|
||||
- `configs/talos-cp{1,2,3}.yaml` - Per-node control plane configs
|
||||
- **Applications**: `/cluster/` directory contains Kubernetes manifests
|
||||
- **APRS.me** (namespace `aprs`): Amateur radio APRS tracking app (https://aprs.me)
|
||||
- Deployment `aprs` (2 replicas), PostgreSQL 17 + PostGIS, Redis
|
||||
- **Managed by Flux**: Kustomization `aprs-app` in `flux-system`, sourced from `https://git.mcintire.me/graham/aprs.me.git` — scaling won't stick unless Flux is suspended first
|
||||
- Deploy manifests in `home/cluster/aprs/`
|
||||
- **Status: stopped** (2026-04-19): Flux Kustomization `aprs-app` suspended and deployment scaled to 0
|
||||
- Restart: `flux resume kustomization aprs-app -n flux-system` (Flux reconciles replicas back to 2)
|
||||
- **GitOps**: ArgoCD (replaced Flux on 2026-04-29). See `home/cluster/argocd/` and the GitOps section below.
|
||||
- **Applications**: deployed via ArgoCD `Application` manifests in `home/cluster/argocd/apps/`
|
||||
- **APRS.me** (namespace `aprs`, https://aprs.me) — sourced from `git.mcintire.me/graham/aprs.me.git` `./k8s`
|
||||
- **gridmap** (namespace `gridmap`) — sourced from `git.mcintire.me/graham/gridmap.git` `./k8s`
|
||||
- **prop** (namespace `prop`) — sourced from `git.mcintire.me/graham/prop.git` `./k8s`
|
||||
- **towerops** (namespace `towerops`) — sourced from `git.mcintire.me/graham/towerops-web.git` `./k8s`
|
||||
- **Documentation**: See `/talos/README.md` and `/cluster/README.md` for detailed operations
|
||||
- **Config Notes**:
|
||||
- `install.extraKernelArgs` and `install.grubUseUKICmdline` cannot be used together
|
||||
- Worker disks with existing data (e.g. old Ceph LVM) must be wiped before Talos will partition them: `talosctl reset --user-disks-to-wipe /dev/sdb --wipe-mode user-disks --reboot`
|
||||
|
||||
### K3s Cluster at 204.110.191.2
|
||||
- **Purpose**: Home lab Kubernetes cluster
|
||||
- **Node1 IPs**:
|
||||
- Public: 204.110.191.2
|
||||
- Tailscale: 100.102.235.20
|
||||
- Internal: 10.0.101.21
|
||||
- **API Access**: Currently only available on 10.0.101.21:6443 (not on Tailscale)
|
||||
- **Context**: Use `kubectl config use-context homelab` to access
|
||||
- **Storage**: Longhorn for persistent volumes
|
||||
- **Applications**:
|
||||
- **Wavelog**: Amateur radio logging application (https://log.w5isp.com)
|
||||
- MariaDB 11 database (10GB storage)
|
||||
- 20GB storage for configs, backups, uploads, QSL cards
|
||||
- PHP application with custom limits (50MB uploads, 256MB memory)
|
||||
- Deploy with: `cd home/cluster/wavelog && ./deploy.sh`
|
||||
### GitOps via ArgoCD (home-cluster)
|
||||
- **Install**: `home/cluster/argocd/install/` — upstream ArgoCD manifests + a Kustomize patch enabling `server.insecure=true` (cloudflared terminates TLS) and `reposerver.git.modules.enabled=false` (the `aprs.me` repo has a stale submodule pin that breaks fetch otherwise)
|
||||
- **App-of-apps**: `home/cluster/argocd/root-app.yaml` watches `home/cluster/argocd/apps/` in this repo and reconciles all child Applications. Add a new YAML to `apps/` and push — Argo picks it up.
|
||||
- **Repo creds**: `forgejo-mcintire-creds` Secret in `argocd` ns is a credential template for `https://git.mcintire.me/graham` — username/password copied from `flux-system/forgejo-git-credentials`.
|
||||
- **UI**: `argo.w5isp.com` via cloudflared tunnel → `argocd-server.argocd.svc.cluster.local:80`. Initial admin password is in `argocd/argocd-initial-admin-secret`.
|
||||
- **Image auto-update**: Flux's `ImagePolicy`/`ImageUpdateAutomation` is gone. Annotations like `# {"$imagepolicy": "flux-system:prop"}` in app repo manifests are inert. To restore, install `argocd-image-updater`.
|
||||
|
||||
### New Server: w5isp.w5isp.com (204.110.191.200)
|
||||
### Caddy server: w5isp.w5isp.com (204.110.191.200)
|
||||
- **Purpose**: Single-node server running Debian 13
|
||||
- **Features**:
|
||||
- Web services with automatic SSL
|
||||
|
|
@ -252,35 +228,22 @@ tofu plan
|
|||
### Notes for Claude
|
||||
- As you learn new things, keep claude.md updated
|
||||
|
||||
## Clusters
|
||||
- **Talos Home Cluster**: 10.0.15.1-6 (primary home lab cluster)
|
||||
- **K3s Cluster**: 204.110.191.2 (legacy, see above for details)
|
||||
## Cluster
|
||||
- **home-cluster** (Talos): 10.0.15.1-6 — only Kubernetes cluster. External traffic enters via the `cloudflared` tunnel deployment in the `cloudflared` namespace; per-hostname routing rules live in Cloudflare's dashboard, not in the cluster.
|
||||
|
||||
## Application Deployment Patterns
|
||||
|
||||
### Standard App Deployment Process
|
||||
1. **Check for existing manifests** in `/home/cluster/[app-name]/`
|
||||
2. **Set namespace security policy**: `kubectl label namespace [app] pod-security.kubernetes.io/enforce=privileged --overwrite`
|
||||
3. **Use ClusterIP services** (internal only) with Traefik for external access
|
||||
4. **Deploy via existing deploy.sh** scripts when available
|
||||
5. **Use Longhorn storage** for persistent volumes
|
||||
6. **Configure Traefik IngressRoute** for SSL and routing
|
||||
|
||||
### Deployed Applications
|
||||
- **APRS.me**: https://aprs.me (Talos home-cluster, namespace `aprs`, currently scaled to 0)
|
||||
- **Node-RED**: https://nodered.w5isp.com (automation platform)
|
||||
- **n8n**: https://n8n.w5isp.com (workflow automation, PostgreSQL backend)
|
||||
- **Wavelog**: https://log.w5isp.com (amateur radio logging, MariaDB backend)
|
||||
1. App repos contain their own k8s manifests in `./k8s/`
|
||||
2. ArgoCD `Application` in `home/cluster/argocd/apps/<name>.yaml` points at the repo
|
||||
3. Push the app repo → Argo auto-syncs (when `automated.selfHeal=true` is set)
|
||||
4. Use Longhorn for persistent volumes (default StorageClass)
|
||||
5. Use ClusterIP services + Cloudflare tunnel for external access
|
||||
|
||||
### Common Issues & Solutions
|
||||
- **PodSecurity violations**: Set namespace to privileged security policy
|
||||
- **PodSecurity violations**: Set namespace to privileged: `kubectl label namespace [ns] pod-security.kubernetes.io/enforce=privileged --overwrite`
|
||||
- **Database connectivity**: Use short service names (`postgres` not `postgres.namespace.svc.cluster.local`)
|
||||
- **Init container permissions**: Required for volume ownership fixes
|
||||
- **SSL certificates**: cert-manager with Let's Encrypt, handled automatically via Traefik
|
||||
- **Service DNS**: Services accessible via `service-name` within same namespace
|
||||
|
||||
### Traefik Configuration
|
||||
- **Host-based routing**: Multiple apps on same IP (204.110.191.2)
|
||||
- **Automatic SSL**: cert-manager integration with Let's Encrypt
|
||||
- **HTTP to HTTPS redirect**: Configured in IngressRoute manifests
|
||||
- **ClusterIP backend**: All apps use ClusterIP, Traefik provides external access
|
||||
- **Argo can't fetch a repo with a submodule**: confirm `reposerver.git.modules.enabled=false` is set on `argocd-cmd-params-cm` (the `aprs.me` repo had a stale submodule pin that broke clones)
|
||||
- **Argo refuses repo for "out-of-bounds symlinks"**: the repo has a tracked symlink pointing outside the working tree (e.g. into `/nix/store/...`). Fix in the source repo — Argo has no override.
|
||||
19
home/cluster/argocd/apps/aprs.yaml
Normal file
19
home/cluster/argocd/apps/aprs.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: aprs
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://git.mcintire.me/graham/aprs.me.git
|
||||
targetRevision: main
|
||||
path: k8s
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: aprs
|
||||
syncPolicy:
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
22
home/cluster/argocd/apps/gridmap.yaml
Normal file
22
home/cluster/argocd/apps/gridmap.yaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: gridmap
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://git.mcintire.me/graham/gridmap.git
|
||||
targetRevision: main
|
||||
path: k8s
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: gridmap
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
22
home/cluster/argocd/apps/prop.yaml
Normal file
22
home/cluster/argocd/apps/prop.yaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: prop
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://git.mcintire.me/graham/prop.git
|
||||
targetRevision: main
|
||||
path: k8s
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: prop
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
19
home/cluster/argocd/apps/towerops.yaml
Normal file
19
home/cluster/argocd/apps/towerops.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: towerops
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://git.mcintire.me/graham/towerops-web.git
|
||||
targetRevision: main
|
||||
path: k8s
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: towerops
|
||||
syncPolicy:
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
24541
home/cluster/argocd/install/argocd-install.yaml
Normal file
24541
home/cluster/argocd/install/argocd-install.yaml
Normal file
File diff suppressed because it is too large
Load diff
20
home/cluster/argocd/install/kustomization.yaml
Normal file
20
home/cluster/argocd/install/kustomization.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: argocd
|
||||
|
||||
resources:
|
||||
- argocd-install.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: ConfigMap
|
||||
name: argocd-cmd-params-cm
|
||||
patch: |-
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: argocd-cmd-params-cm
|
||||
data:
|
||||
server.insecure: "true"
|
||||
reposerver.git.modules.enabled: "false"
|
||||
22
home/cluster/argocd/root-app.yaml
Normal file
22
home/cluster/argocd/root-app.yaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: root
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://git.mcintire.me/graham/infra.git
|
||||
targetRevision: main
|
||||
path: home/cluster/argocd/apps
|
||||
directory:
|
||||
recurse: true
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: argocd
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
|
|
@ -539,6 +539,10 @@ resource "cloudflare_zero_trust_tunnel_cloudflared_config" "towerops" {
|
|||
hostname = "prop.w5isp.com"
|
||||
service = "http://prop.prop.svc.cluster.local:5000"
|
||||
}
|
||||
ingress_rule {
|
||||
hostname = "argo.w5isp.com"
|
||||
service = "http://argocd-server.argocd.svc.cluster.local:80"
|
||||
}
|
||||
ingress_rule {
|
||||
service = "http_status:404"
|
||||
}
|
||||
|
|
@ -688,6 +692,14 @@ resource "cloudflare_record" "w5isp_cname_prop" {
|
|||
proxied = true
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "w5isp_cname_argo" {
|
||||
zone_id = cloudflare_zone.w5isp_com.id
|
||||
type = "CNAME"
|
||||
name = "argo"
|
||||
content = "d3d819ba-925c-4d84-8052-68ed32b686bb.cfargotunnel.com"
|
||||
proxied = true
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# w5isp.com - MX records
|
||||
# =============================================================================
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue