chore: add CLAUDE.md, kubectl notes, and settings/gitignore tweaks
Document the repo for Claude Code, note a couple of handy kubectl one-liners, allow a few more Bash/WebFetch/WebSearch permissions used during this session, and ignore the relocated zot sync-credentials.json. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,11 @@
|
|||||||
"Bash(for f:*)",
|
"Bash(for f:*)",
|
||||||
"Bash(do echo:*)",
|
"Bash(do echo:*)",
|
||||||
"Read(//Users/jan.novak/srv/personal/home-kubernetes/**)",
|
"Read(//Users/jan.novak/srv/personal/home-kubernetes/**)",
|
||||||
"Bash(done)"
|
"Bash(done)",
|
||||||
|
"Bash(ssh docker-30 *)",
|
||||||
|
"Bash(git add *)",
|
||||||
|
"WebSearch",
|
||||||
|
"WebFetch(domain:cert-manager.io)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,4 +11,5 @@ tmp/
|
|||||||
vms/utility-101-shadow/docker/monitoring/smtp_password
|
vms/utility-101-shadow/docker/monitoring/smtp_password
|
||||||
|
|
||||||
docker-30/zot/sync-credentials.json
|
docker-30/zot/sync-credentials.json
|
||||||
|
vms-home/docker-30/zot/sync-credentials.json
|
||||||
kubernetes-kvm-terraform/gke_gcloud_auth_plugin_cache
|
kubernetes-kvm-terraform/gke_gcloud_auth_plugin_cache
|
||||||
|
|||||||
105
CLAUDE.md
Normal file
105
CLAUDE.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Repository Purpose
|
||||||
|
|
||||||
|
Home Kubernetes lab infrastructure-as-code. Manages VM provisioning (Terraform/KVM), Kubernetes cluster configuration, and application deployments via Flux GitOps — all pointing at a self-hosted Gitea instance.
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Terraform (kubernetes-kvm-terraform/)
|
||||||
|
```bash
|
||||||
|
cd kubernetes-kvm-terraform
|
||||||
|
tofu init
|
||||||
|
tofu plan
|
||||||
|
tofu apply
|
||||||
|
tofu destroy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flux GitOps
|
||||||
|
```bash
|
||||||
|
# Check reconciliation status
|
||||||
|
kubectl get kustomizations -A
|
||||||
|
kubectl get helmreleases -A
|
||||||
|
|
||||||
|
# Force reconcile
|
||||||
|
flux reconcile kustomization flux-system --with-source
|
||||||
|
flux reconcile helmrelease <name> -n <namespace>
|
||||||
|
|
||||||
|
# Watch logs
|
||||||
|
flux logs --follow
|
||||||
|
|
||||||
|
# Check source sync
|
||||||
|
flux get sources git
|
||||||
|
```
|
||||||
|
|
||||||
|
### kubectl — common ops
|
||||||
|
```bash
|
||||||
|
export KUBECONFIG=kubernetes-kvm-terraform/kubeconfig
|
||||||
|
kubectl get nodes
|
||||||
|
kubectl get pods -A
|
||||||
|
kubectl get secrets -A
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose (docker-30/ services)
|
||||||
|
```bash
|
||||||
|
# These run on 192.168.0.30 (docker-30), accessed via SSH
|
||||||
|
ssh novakj@192.168.0.30
|
||||||
|
cd /path/to/service && docker compose up -d
|
||||||
|
docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Infrastructure Layer
|
||||||
|
- **Hypervisors**: homer (192.168.0.7) and beelink (192.168.0.6) run KVM/libvirt
|
||||||
|
- **Terraform provider**: primary `qemu+ssh://novakj@192.168.0.7/system`, secondary alias `kvm-beelink` for 192.168.0.6
|
||||||
|
- **Kubernetes master**: kube-master-31 @ 192.168.0.31:6443, bootstrapped via kubeadm
|
||||||
|
- **OS**: Ubuntu 24.04 Noble cloud images, network bridge `br0`, subnet 192.168.0.0/24
|
||||||
|
|
||||||
|
### GitOps Layer (`gitops/home-kubernetes/`)
|
||||||
|
Flux syncs from Gitea (`https://gitea.home.hrajfrisbee.cz`, main branch, every 10 minutes). The reconciliation order is enforced via `dependsOn` in `flux-system/extra-kustomizations.yaml`:
|
||||||
|
|
||||||
|
```
|
||||||
|
00-crds → 00-rbac → cilium → cert-manager → external-secrets → everything else
|
||||||
|
```
|
||||||
|
|
||||||
|
Each application lives in its own subdirectory under `gitops/home-kubernetes/` and is referenced as a Flux `Kustomization` resource. Prune is enabled — removing a manifest from git removes it from the cluster.
|
||||||
|
|
||||||
|
### Secrets Flow
|
||||||
|
Vault (docker-30) → External-Secrets controller (in-cluster) → Kubernetes `Secret` objects. Applications reference `ExternalSecret` CRs that pull from Vault paths. Do not put real secrets in git.
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
- **CNI**: Cilium 1.19.x with Gateway API and Hubble UI enabled
|
||||||
|
- **L2 LB**: Cilium `CiliumL2AnnouncementPolicy` + `CiliumLoadBalancerIPPool` for bare-metal load-balancer IPs (defined in `gitops/home-kubernetes/cilium/`)
|
||||||
|
- **Ingress**: ingress-nginx for HTTP(S) workloads; Gateway API for newer apps
|
||||||
|
- **TLS**: cert-manager issues wildcard cert (`*.home.hrajfrisbee.cz`) referenced by apps
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
- **democratic-CSI**: iSCSI volumes backed by FreeNAS at 192.168.0.40
|
||||||
|
- **Longhorn**: configured but disabled in Flux (directory present, not in `extra-kustomizations.yaml`)
|
||||||
|
|
||||||
|
### Supporting Services on docker-30 (192.168.0.30)
|
||||||
|
All managed with Docker Compose:
|
||||||
|
- **Gitea** — Git server + act_runner (GitHub Actions-compatible CI)
|
||||||
|
- **Vault** — secrets backend for External Secrets
|
||||||
|
- **Zot** — private OCI/container registry
|
||||||
|
- **Kanidm** — identity management / OIDC provider
|
||||||
|
- **nginx** — reverse proxy for docker-30 services
|
||||||
|
|
||||||
|
## Key Conventions
|
||||||
|
|
||||||
|
- **New application**: create a directory under `gitops/home-kubernetes/<app-name>/`, add a `Kustomization` entry in `flux-system/extra-kustomizations.yaml` with appropriate `dependsOn`.
|
||||||
|
- **Helm apps**: use a `HelmRepository` + `HelmRelease` pair; pin chart versions explicitly.
|
||||||
|
- **Secrets**: add an `ExternalSecret` CR pointing to the Vault path; never commit actual secret values.
|
||||||
|
- **Terraform state**: `kubernetes-kvm-terraform/terraform.tfstate*` is gitignored/sensitive; treat it carefully.
|
||||||
|
- **kubeconfig**: `kubernetes-kvm-terraform/kubeconfig` is gitignored; obtain it from the master node after provisioning.
|
||||||
|
|
||||||
|
|
||||||
|
## Plans
|
||||||
|
|
||||||
|
When Claude Code's plan mode is used, save the plan file inside the repo at
|
||||||
|
`docs/plans/YYYY-MM-DD-HHMM-<slug>.md` instead of the default `~/.claude/plans/`
|
||||||
|
location. Get the timestamp with `date "+%Y-%m-%d-%H%M"` (matches the changelog
|
||||||
|
convention). The `<slug>` should be a short kebab-case summary of the plan's topic.
|
||||||
14
docs/kubernetes-extras.md
Normal file
14
docs/kubernetes-extras.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
## kubectl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# condensed -o wide
|
||||||
|
kubectl get pods -A -o wide --watch | awk '
|
||||||
|
/NOMINATED NODE/ { sub(/[[:space:]]+NOMINATED NODE[[:space:]]+READINESS GATES[[:space:]]*$/,""); print; fflush(); next }
|
||||||
|
{ sub(/[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]*$/,""); print; fflush() }
|
||||||
|
'
|
||||||
|
|
||||||
|
# condensed -o wide
|
||||||
|
kubectl get pods -A --watch -o custom-columns=\
|
||||||
|
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase,RESTARTS:.status.containerStatuses[0].restartCount,IP:.status.podIP,NODE:.spec.nodeName'
|
||||||
|
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user