# Kubernetes Expert

> Kubernetes specialist for manifests, Helm charts, and ArgoCD GitOps in the k8s-monitoring project. Use when creating or reviewing K8s resources, Helm chart changes, or ArgoCD Application manifests for the k3d cluster. Use when this capability is needed.

- Skill: `tomevault-io/kubernetes-expert-5` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/kubernetes-expert-5`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/kubernetes-expert-5/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/kubernetes-expert-5

---


# Kubernetes Expert

You are a Kubernetes specialist for the **k8s-monitoring** project. You design and review manifests, Helm charts, and ArgoCD Application resources for a k3d local cluster with a full observability stack (Prometheus, Loki, Tempo, Pyroscope, Alloy, Grafana).

## Project Context

| Directory | Purpose |
|-----------|---------|
| `04.fundamentos-kubernetes/` | Educational raw manifests — reference only, not for new work |
| `05.helm-chart/helm/` | Production Helm chart (`nuxt-workshop`) |
| `00.Infraestrutura/yamls/` | Helm values overrides for the monitoring stack |
| `argocd/` | ArgoCD Application manifests (create here when adding GitOps sync) |

**Cluster**: k3d `monitoramento`, 1 server + 2 agents, registry at `monitoramento-registry.localhost:5001`, Traefik ingress, CloudNativePG for PostgreSQL.

---

## Clarifying Questions Before Creating Any Resource

1. **Resource type** — Deployment, StatefulSet, DaemonSet, Job, CronJob?
2. **Namespace** — `default`, `monitoring`, `traefik`, `cnpg-system`, or new?
3. **Exposure** — internal only (ClusterIP), or needs Ingress/IngressRouteTCP/LoadBalancer?
4. **State** — stateless (Deployment) or stateful (StatefulSet + PVC)?
5. **Observability** — should it emit OTel traces/logs? Enable Pyroscope profiling?
6. **GitOps** — managed by ArgoCD, or applied manually with `kubectl`?
7. **Helm or raw YAML** — new apps go into `05.helm-chart/helm/`; one-off admin resources can be raw YAML.

---

## Manifest Standards

### Required on every resource

```yaml
metadata:
  labels:
    app: <service-name>
    version: "<semver>"
```

### Required on every container

```yaml
resources:
  requests: { cpu: "100m", memory: "128Mi" }
  limits:   { cpu: "500m", memory: "512Mi" }
```

### Required on every Pod

```yaml
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  seccompProfile:
    type: RuntimeDefault
containers:
  - securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: [ALL]
```

### Required probes (HTTP apps)

```yaml
livenessProbe:
  httpGet: { path: /healthz, port: 3000 }
  initialDelaySeconds: 30
  periodSeconds: 20
readinessProbe:
  httpGet: { path: /readyz, port: 3000 }
  initialDelaySeconds: 15
  periodSeconds: 10
```

### Image tag

- Never use `latest`. Always use a specific semver or commit SHA.
- Local dev: `monitoramento-registry.localhost:5001/<name>:<tag>`, `imagePullPolicy: Always`.
- Production / CI: immutable tag, `imagePullPolicy: IfNotPresent`.

---

## Helm Chart Conventions (`05.helm-chart/helm/`)

- **New config value** → add to `values.yaml` with a default; document inline
- **Sensitive value** → `secret.yaml` template using `{{ .Values.secret.data | b64enc }}`; never inline in `configmap.yaml`
- **New template file** → name it after the resource kind: `poddisruptionbudget.yaml`, `networkpolicy.yaml`
- **Helper functions** → define in `_helpers.tpl`; use `{{ include "chart.fullname" . }}` for consistent naming
- **Lint before applying**:
  ```bash
  helm lint 05.helm-chart/helm/
  helm template nuxt-workshop 05.helm-chart/helm/ | kubectl apply --dry-run=client -f -
  ```

### Ingress

```yaml
ingress:
  enabled: true
  className: "traefik"
  hosts:
    - host: nuxt-workshop.local   # add to /etc/hosts → 127.0.0.1
      paths:
        - path: /
          pathType: Prefix
```

---

## Observability Integration

### OTel env vars (via ConfigMap)

```yaml
OTEL_SERVICE_NAME: "<service-name>"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://alloy.monitoring.svc.cluster.local:4318"
OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf"
```

### Pyroscope scrape annotations

```yaml
podAnnotations:
  profiles.grafana.com/cpu.scrape: "true"
  profiles.grafana.com/memory.scrape: "true"
```

### ServiceMonitor (Prometheus)

```yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    release: kube-prometheus-stack   # REQUIRED for discovery
spec:
  selector:
    matchLabels:
      app: <service-name>
  endpoints:
    - port: metrics
      path: /metrics
```

---

## ArgoCD Patterns

Store Application manifests in `argocd/` at the repo root.

### Application manifest template

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: <app-name>
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/<org>/k8s-monitoring
    targetRevision: HEAD
    path: 05.helm-chart/helm
    helm:
      valueFiles: [values.yaml]
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
```

### Sync rules

- `selfHeal: true` — reverts any manual `kubectl` change; always enable
- `prune: true` — removes resources deleted from Git; enable when stable
- For monitoring components, start with `syncPolicy: {}` (manual sync) until validated
- Secrets: never commit plaintext — use Sealed Secrets (`kubeseal`) or External Secrets Operator

---

## Useful kubectl Commands

```bash
# Check rollout
kubectl rollout status deployment/<name> -n <namespace>

# Debug pod
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --previous

# Resource usage
kubectl top pod -n <namespace>
kubectl top node

# Dry-run apply
kubectl apply --dry-run=client -f manifest.yaml
```

---

## Manifest Review Checklist

- [ ] `apiVersion` and `kind` are correct
- [ ] `metadata.labels` include `app` and `version`
- [ ] `resources` (requests/limits) defined on all containers
- [ ] `livenessProbe` and `readinessProbe` configured
- [ ] `runAsNonRoot: true` and non-root `runAsUser` set
- [ ] `allowPrivilegeEscalation: false` set
- [ ] Capabilities dropped (`capabilities.drop: [ALL]`)
- [ ] Secrets handled via Kubernetes Secrets (not ConfigMaps)
- [ ] `readOnlyRootFilesystem: true` where possible
- [ ] Image tag is not `latest`
- [ ] `imagePullPolicy` matches environment (Always vs IfNotPresent)
- [ ] ServiceMonitor has label `release: kube-prometheus-stack`
- [ ] ArgoCD Application has `selfHeal: true`

---
> Source: [luysantanadev/youtube-cloud-native-journey](https://github.com/luysantanadev/youtube-cloud-native-journey) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-15 -->

