K8s Migration Phase 1: Infrastructure Setup #29
7 changed files with 195 additions and 30 deletions
Add ArgoCD self-management and app-of-apps pattern
- Add argocd CLI to Brewfile - Create argocd.yaml for ArgoCD self-management (manual sync) - Create apps.yaml app-of-apps root (auto-sync for Application resources) - Convert tailscale-operator to kustomize - Update READMEs with bootstrap steps and ArgoCD CLI commands - Change all workload Applications to manual sync policy App-of-apps auto-syncs to pick up new Application manifests, but child apps require manual sync for actual workload deployments. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
commit
32d5927838
1
Brewfile
1
Brewfile
|
|
@ -1,4 +1,5 @@
|
|||
# CLI tools for blumeops management
|
||||
brew "argocd" # ArgoCD CLI for GitOps management
|
||||
brew "bat" # Syntax-highlighted file concatenation
|
||||
brew "tea" # Gitea/Forgejo CLI for forge.tail8d86e.ts.net
|
||||
brew "podman" # Container CLI (uses VM on macOS, for building/pushing images)
|
||||
|
|
|
|||
24
argocd/apps/apps.yaml
Normal file
24
argocd/apps/apps.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# App-of-apps root Application
|
||||
# Watches argocd/apps/ and creates/manages all Application resources
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: apps
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
|
||||
targetRevision: feature/k8s-phase1-kickoff
|
||||
path: argocd/apps
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: argocd
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
# Auto-sync enabled: new/changed Application manifests appear automatically
|
||||
# but child apps still require manual sync (they have manual sync policy)
|
||||
20
argocd/apps/argocd.yaml
Normal file
20
argocd/apps/argocd.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# ArgoCD self-management Application
|
||||
# After bootstrap, ArgoCD manages its own deployment
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: argocd
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
|
||||
targetRevision: feature/k8s-phase1-kickoff
|
||||
path: argocd/manifests/argocd
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: argocd
|
||||
syncPolicy:
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
# Manual sync only - no automated sync on git push
|
||||
|
|
@ -7,6 +7,12 @@ metadata:
|
|||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
# Tailscale operator mutates externalName from "placeholder" to actual proxy service
|
||||
ignoreDifferences:
|
||||
- group: ""
|
||||
kind: Service
|
||||
jsonPointers:
|
||||
- /spec/externalName
|
||||
source:
|
||||
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
|
||||
targetRevision: feature/k8s-phase1-kickoff
|
||||
|
|
@ -15,8 +21,6 @@ spec:
|
|||
server: https://kubernetes.default.svc
|
||||
namespace: tailscale
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
# Manual sync only - no automated sync on git push
|
||||
|
|
|
|||
|
|
@ -1,28 +1,99 @@
|
|||
# ArgoCD
|
||||
|
||||
GitOps continuous delivery for Kubernetes.
|
||||
GitOps continuous delivery for Kubernetes, with self-management via ArgoCD.
|
||||
|
||||
## Installation
|
||||
## Prerequisites
|
||||
|
||||
Uses kustomize with remote base from upstream ArgoCD.
|
||||
- Tailscale operator deployed (see `argocd/manifests/tailscale-operator/README.md`)
|
||||
- Deploy key added to forge for SSH access to blumeops repo
|
||||
|
||||
## Manual Bootstrap
|
||||
|
||||
Bootstrap is required when setting up a new cluster. After bootstrap, ArgoCD manages itself.
|
||||
|
||||
```bash
|
||||
# Create namespace
|
||||
# 1. Create namespace
|
||||
kubectl create namespace argocd
|
||||
|
||||
# Apply manifests
|
||||
# 2. Apply ArgoCD manifests via kustomize
|
||||
kubectl apply -k argocd/manifests/argocd/
|
||||
|
||||
# 3. Wait for ArgoCD to be ready
|
||||
kubectl wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s
|
||||
|
||||
# 4. Get initial admin password
|
||||
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
|
||||
|
||||
# 5. Login and change password
|
||||
argocd login argocd.tail8d86e.ts.net --username admin --grpc-web
|
||||
argocd account update-password
|
||||
|
||||
# 6. Apply repo-forge secret for SSH access to forge
|
||||
PRIV_KEY=$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/csjncynh6htjvnh2l2da65y32q/private key?ssh-format=openssh")$'\n' && \
|
||||
kubectl create secret generic repo-forge -n argocd \
|
||||
--from-literal=type=git \
|
||||
--from-literal=url='ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git' \
|
||||
--from-literal=insecure=true \
|
||||
--from-literal=sshPrivateKey="$PRIV_KEY" && \
|
||||
kubectl label secret repo-forge -n argocd argocd.argoproj.io/secret-type=repository
|
||||
|
||||
# 7. Apply ArgoCD Applications (self-management + app-of-apps)
|
||||
kubectl apply -f argocd/apps/argocd.yaml
|
||||
kubectl apply -f argocd/apps/apps.yaml
|
||||
```
|
||||
|
||||
After step 7, ArgoCD manages itself and all applications defined in `argocd/apps/`.
|
||||
|
||||
## Access
|
||||
|
||||
- URL: https://argocd.tail8d86e.ts.net
|
||||
- Username: `admin`
|
||||
- Password: Get from secret (see below)
|
||||
- Password: Stored in 1Password after initial setup
|
||||
|
||||
## ArgoCD CLI Commands
|
||||
|
||||
```bash
|
||||
# Get initial admin password
|
||||
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
|
||||
# Check all applications
|
||||
argocd app list
|
||||
|
||||
# Sync a specific application
|
||||
argocd app sync <app-name>
|
||||
|
||||
# Check application status
|
||||
argocd app get <app-name>
|
||||
|
||||
# Hard refresh (clear git cache)
|
||||
argocd app get <app-name> --hard-refresh
|
||||
```
|
||||
|
||||
## Adding New Applications
|
||||
|
||||
1. Create an Application manifest in `argocd/apps/<app-name>.yaml`
|
||||
2. Commit and push to forge
|
||||
3. ArgoCD (via app-of-apps) automatically picks it up
|
||||
|
||||
Example Application:
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: my-app
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git
|
||||
targetRevision: main
|
||||
path: argocd/manifests/my-app
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: my-app
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
```
|
||||
|
||||
## Files
|
||||
|
|
@ -32,10 +103,12 @@ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.pas
|
|||
| `kustomization.yaml` | References upstream install.yaml + local customizations |
|
||||
| `service-tailscale.yaml` | Tailscale Ingress for external access with Let's Encrypt TLS |
|
||||
| `argocd-cmd-params-cm.yaml` | Patch to disable HTTPS redirect (TLS terminates at Ingress) |
|
||||
| `repo-forge-secret.yaml.tpl` | Template documenting the forge SSH secret (manual) |
|
||||
| `README.md` | This file |
|
||||
|
||||
## Post-Setup
|
||||
## Notes
|
||||
|
||||
1. Login and change the admin password
|
||||
2. Store new password in 1Password
|
||||
3. Configure git repository connection to `github.com/eblume/blumeops`
|
||||
- **TODO:** Secrets (`repo-forge`) are not managed by ArgoCD and must be applied manually.
|
||||
Future improvement: integrate with a secrets operator (e.g., External Secrets).
|
||||
- ArgoCD uses Tailscale Ingress with Let's Encrypt for TLS termination.
|
||||
- The `--grpc-web` flag is required for CLI access through the Tailscale ingress.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
# Tailscale Kubernetes Operator
|
||||
|
||||
Manifests for the Tailscale Kubernetes Operator, sourced from Tailscale's official repository.
|
||||
|
||||
**Note:** These are currently raw manifests from Tailscale, not yet kustomized. Once kustomized, this directory will include a `kustomization.yaml` and any necessary patches.
|
||||
Manifests for the Tailscale Kubernetes Operator, managed via ArgoCD.
|
||||
|
||||
## Source
|
||||
|
||||
|
|
@ -18,26 +16,43 @@ Manifests for the Tailscale Kubernetes Operator, sourced from Tailscale's offici
|
|||
- Services: Write
|
||||
2. ACL with `tag:k8s-operator` owning `tag:k8s` (so operator can tag resources it creates)
|
||||
|
||||
## Deployment
|
||||
## Manual Bootstrap (Before ArgoCD)
|
||||
|
||||
Tailscale operator must be deployed before ArgoCD since ArgoCD uses Tailscale for ingress.
|
||||
|
||||
```bash
|
||||
# 1. Create namespace
|
||||
kubectl create namespace tailscale
|
||||
|
||||
# 2. Apply the OAuth secret (uses 1Password for credential resolution)
|
||||
# 2. Apply OAuth secret (uses 1Password)
|
||||
op inject -i argocd/manifests/tailscale-operator/secret.yaml.tpl | kubectl apply -f -
|
||||
|
||||
# 3. Apply the operator
|
||||
kubectl apply -f argocd/manifests/tailscale-operator/operator.yaml
|
||||
|
||||
# 4. Apply the ProxyClass (required for CRI-O image compatibility)
|
||||
kubectl apply -f argocd/manifests/tailscale-operator/proxyclass.yaml
|
||||
# 3. Apply manifests via kustomize
|
||||
kubectl apply -k argocd/manifests/tailscale-operator/
|
||||
```
|
||||
|
||||
**Important:** Services using the Tailscale LoadBalancer must reference the ProxyClass:
|
||||
```yaml
|
||||
annotations:
|
||||
tailscale.com/proxy-class: "default"
|
||||
## Ongoing Management (After ArgoCD)
|
||||
|
||||
Once ArgoCD is running, the operator is managed by the `tailscale-operator` ArgoCD Application.
|
||||
ArgoCD pulls manifests from forge and applies them automatically.
|
||||
|
||||
## ArgoCD CLI Commands
|
||||
|
||||
```bash
|
||||
# Check application status
|
||||
argocd app get tailscale-operator
|
||||
|
||||
# Trigger a sync (pull latest from forge and apply)
|
||||
argocd app sync tailscale-operator
|
||||
|
||||
# Preview what would change without applying
|
||||
argocd app diff tailscale-operator
|
||||
|
||||
# View deployment history
|
||||
argocd app history tailscale-operator
|
||||
|
||||
# Hard refresh (clear cache and re-fetch from git)
|
||||
argocd app get tailscale-operator --hard-refresh
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
|
@ -54,7 +69,22 @@ kubectl logs -n tailscale -l app.kubernetes.io/name=operator
|
|||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `kustomization.yaml` | Kustomize configuration for all manifests |
|
||||
| `operator.yaml` | Operator deployment, CRDs, RBAC (secret removed) |
|
||||
| `proxyclass.yaml` | ProxyClass with fully-qualified images for CRI-O |
|
||||
| `secret.yaml.tpl` | 1Password template for OAuth credentials |
|
||||
| `dnsconfig.yaml` | DNSConfig for cluster-to-tailnet name resolution |
|
||||
| `egress-forge.yaml` | Egress proxy for accessing forge on indri |
|
||||
| `secret.yaml.tpl` | 1Password template for OAuth credentials (manual) |
|
||||
| `README.md` | This file |
|
||||
|
||||
## Notes
|
||||
|
||||
- **TODO:** The OAuth secret (`operator-oauth`) is not managed by ArgoCD and must be applied
|
||||
manually. Future improvement: integrate with a secrets operator (e.g., External Secrets).
|
||||
- Services using the Tailscale LoadBalancer must reference the ProxyClass:
|
||||
```yaml
|
||||
annotations:
|
||||
tailscale.com/proxy-class: "default"
|
||||
```
|
||||
- The egress proxy for forge targets `indri.tail8d86e.ts.net` directly (not `forge.tail8d86e.ts.net`)
|
||||
because Tailscale Serve hostnames are virtual and only work via the Tailscale client.
|
||||
|
|
|
|||
13
argocd/manifests/tailscale-operator/kustomization.yaml
Normal file
13
argocd/manifests/tailscale-operator/kustomization.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: tailscale
|
||||
|
||||
resources:
|
||||
- operator.yaml
|
||||
- proxyclass.yaml
|
||||
- dnsconfig.yaml
|
||||
- egress-forge.yaml
|
||||
|
||||
# Note: OAuth secret (operator-oauth) is NOT included here.
|
||||
# It must be manually applied before deploying - see README.md
|
||||
Loading…
Add table
Add a link
Reference in a new issue