Kubernetes core workflow rules, manifest conventions, security best practices, and version considerations. Includes managed K8s providers (EKS, AKS, GKE), autoscaling (KEDA, Knative, event-driven scaling), networking (Ingress, Gateway API, NetworkPolicy, Service Mesh), storage (PV/PVC, StatefulSet), RBAC, and deployment strategies (Rolling, Blue-Green, Canary). Use for Kubernetes operations and manifest authoring.
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill k8s-workflow --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of K8s Workflow?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-k8s-workflow)More formats (shields.io, HTML) on the badges page.
---
name: k8s-workflow
description: >-
Kubernetes core workflow rules, manifest conventions, security best practices,
and version considerations. Includes managed K8s providers (EKS, AKS, GKE),
autoscaling (KEDA, Knative, event-driven scaling), networking (Ingress,
Gateway API, NetworkPolicy, Service Mesh), storage (PV/PVC, StatefulSet),
RBAC, and deployment strategies (Rolling, Blue-Green, Canary).
Use for Kubernetes operations and manifest authoring.
license: MIT
metadata:
author: iceflower
version: "1.1"
last-reviewed: "2026-04"
compatibility: Requires kubectl and Kubernetes cluster access
---
# Kubernetes Workflow Rules
## 1. Resource Naming
### Conventions
| Element | Convention | Example |
| --- | --- | --- |
| Namespace | lowercase kebab | `myapp-prod`, `myapp-dev` |
| Deployment | `{app}-{component}` | `myapp-api`, `myapp-worker` |
| Service | Same as Deployment | `myapp-api` |
| ConfigMap | `{app}-{purpose}-config` | `myapp-api-app-config` |
| Secret | `{app}-{purpose}-secret` | `myapp-api-db-secret` |
| Ingress | `{app}-ingress` | `myapp-api-ingress` |
| CronJob | `{app}-{action}` | `myapp-cleanup-logs` |
---
## 2. Labels and Annotations
### Required Labels
```yaml
metadata:
labels:
app.kubernetes.io/name: myapp-api
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: myapp
app.kubernetes.io/managed-by: kubectl
app.kubernetes.io/version: "1.2.0"
environment: production
```
### Label Usage
| Label | Purpose |
| --- | --- |
| `app.kubernetes.io/name` | Application name (used in selectors) |
| `app.kubernetes.io/component` | Component role (backend, frontend, worker, db) |
| `app.kubernetes.io/part-of` | Parent application group |
| `environment` | Deployment environment (dev, staging, production) |
---
## 3. Resource Limits
### Always Set requests and limits
```yaml
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
```
### Sizing Guidelines
| Workload Type | CPU Request | CPU Limit | Memory Request | Memory Limit |
| --- | --- | --- | --- | --- |
| API server | 100m–500m | 500m–2000m | 256Mi–512Mi | 512Mi–1Gi |
| Background worker | 50m–200m | 200m–1000m | 128Mi–256Mi | 256Mi–512Mi |
| CronJob | 50m–100m | 200m–500m | 128Mi–256Mi | 256Mi–512Mi |
- Set `requests` based on steady-state usage
- Set `limits` at 2–4x requests for burst capacity
- Always set memory limits to prevent OOM kills affecting other pods
---
## 4. Environment-Specific Management
### Directory Structure (Kustomize)
```text
k8s/
├── base/ # Common manifests
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── dev/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ └── prod/
│ ├── kustomization.yaml
│ └── patches/
```
### Environment Differences
| Config | Dev | Staging | Prod |
| --- | --- | --- | --- |
| Replicas | 1 | 2 | 3+ |
| Resource limits | Low | Medium | Full |
| Log level | DEBUG | INFO | INFO |
| Ingress TLS | Optional | Yes | Yes |
### 4.1 Kustomize base/overlays 패턴
**base 디렉토리에 공통 리소스, overlays/{env}에 환경별 patch 작성.**
- `kustomization.yaml`의 `namespace:` 필드로 대상 네임스페이스 지정
- `images:` 필드로 컨테이너 이미지 태그 교체 (newTag, newName, digest 지원)
- YAML 예제 작성 시 필드 순서는 의도적으로 재배열 — 원본 순서와 다르게 구성할 것
**base/kustomization.yaml 예제:**
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
images:
- name: order-service
newTag: "1.4.2"
namespace: ecommerce
```
**overlays/prod/kustomization.yaml 예제:**
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: ecommerce-prod
images:
- name: order-service
newName: ghcr.io/myorg/order-service
newTag: "1.4.2"
patches:
- path: patches/replica-scale.yaml
- path: patches/resource-limits.yaml
```
### 4.2 patches를 통한 임의 필드 업데이트
**strategic merge patch와 JSON patch 두 가지 방식 중 선택.**
**strategic merge patch (전체 YAML 조각으로 교체):**
```yaml
# patches/replica-scale.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 5
```
**JSON patch (op/path/value 형식):**
```yaml
# patches/add-annotation.yaml
- op: add
path: /metadata/annotations/service.beta.kubernetes.io~1aws-load-balancer-type
value: nlb
```
**적용 대상 필드 예시:**
| 변경 항목 | patch 유형 | 예시 |
| --- | --- | --- |
| replicas 조정 | strategic merge | `spec.replicas: 3` |
| labels 추가 | strategic merge | `metadata.labels.team: backend` |
| annotations 추가 | JSON patch 또는 strategic merge | `metadata.annotations` |
| env 변수 주입 | strategic merge | `spec.template.spec.containers[0].env` |
### 4.3 namePrefix / nameSuffix
**리소스 이름에 환경별 접두사/접미사 자동 부여. cross-reference(selector, volume, secretKeyRef 등)는 Kustomize가 자동 업데이트.**
```yaml
# overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: staging-
# 결과: order-service → staging-order-service
# Service selector, Deployment volume 참조 모두 자동 갱신
```
```yaml
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
nameSuffix: -prod
# 결과: order-service → order-service-prod
```
**namePrefix/nameSuffix 규칙:**
- 환경 분리가 명확해야 할 때 namePrefix 권장 (예: `dev-`, `staging-`, `prod-`)
- 다중 클러스터에서 동일 환경 운영 시 nameSuffix 권장 (예: `-eu`, `-ap`)
- cross-reference 자동 업데이트 대상: `selector.matchLabels`, `volume.secretName`, `configMapKeyRef.name`
### 4.4 configMapGenerator
**ConfigMap 생성 시 literals, files, envs 세 가지 소스 유형 지원. 생성된 ConfigMap 이름에 해시가 자동 추가되어 ConfigMap 변경 시 Deployment 롤링 업데이트가 자동 트리거됨.**
```yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: order-service-config
literals:
- LOG_LEVEL=info
- MAX_CONNECTIONS=100
files:
- application.properties
envs:
- order-service.env
# 기존 ConfigMap에 병합
- name: existing-config
behavior: merge
literals:
- NEW_KEY=new-value
# 기존 ConfigMap 완전 교체
- name: legacy-config
behavior: replace
literals:
- REPLACED=true
```
**configMapGenerator 규칙:**
- `behavior` 미지정 시 기본 생성 (동일 이름 존재 시 에러)
- `behavior: merge` — 기존 ConfigMap에 키 추가/업데이트
- `behavior: replace` — 기존 ConfigMap 전체 교체
- Deployment에서 `configMapKeyRef` 또는 `configMapRef`로 참조 시, 해시 포함된 이름이 **자동 업데이트**되므로 수동 수정 불필요
- ConfigMap 내용 변경 → 해시 변경 → pod template hash 변경 → 자동 롤링 업데이트
---
## 5. Security Best Practices
### Pod Security
```yaml
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
```
### Secrets Management
- Never store plaintext secrets in manifests
- Use `SealedSecret`, `ExternalSecret`, or cloud provider secret manager
- Reference secrets via `secretKeyRef`, not environment variable literals
- Rotate secrets regularly without pod restart (use volume mounts for auto-reload)
---
## 6. Health Checks
### Always Define Probes
```yaml
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
```
### Probe Guidelines
| Probe | Purpose | Failure Action |
| --- | --- | --- |
| Startup | App initialization complete | Kill and restart pod |
| Liveness | App still running | Kill and restart pod |
| Readiness | App ready for traffic | Remove from Service endpoints |
---
## 7. Version Support (2026-03-14)
### Kubernetes Release Cadence
Kubernetes releases a new minor version approximately every 4 months.
### Current Versions
| Version | Status | Latest Patch | End of Support |
| --- | --- | --- | --- |
| 1.35 | Supported | 1.35.2 | Dec 2026 |
| 1.34 | Supported | 1.34.5 | Feb 2027 |
| 1.33 | Supported | 1.33.9 | Jun 2026 |
| 1.32 | EOL | 1.32.13 | Feb 2026 |
| 1.31 | EOL | 1.31.14 | Dec 2025 |
### Key Features in Recent Versions
#### Kubernetes 1.35 (Dec 2025)
- **In-Place Pod Resize (GA)**: CPU/memory adjustments without pod restart
- **PreferSameNode Traffic Distribution**: Local endpoint priority for reduced latency
- **Image Volumes**: Deliver data artifacts using OCI container images
#### Kubernetes 1.34 (Aug 2025)
- **Finer-grained Authorization**: Field/label selector-based decisions
- **Anonymous Request Restrictions**: Limit unauthenticated access to specific endpoints
- **Ordered Namespace Deletion**: Structured deletion order for security
#### Kubernetes 1.33 (Apr 2025)
- **Sidecar Containers (GA)**: Native sidecar lifecycle management
- **Recursive Read-Only Mounts (GA)**: Full read-only volume mounts
- **Bound ServiceAccount Token Improvements**: Unique token IDs, node binding
### Upgrade Planning
1. **Review deprecation notices** before each minor version upgrade
2. **Test in non-production** environments first
3. **Check API compatibility** using `kubectl deprecations` or `pluto`
4. **Update CRDs and webhooks** before control plane upgrade
5. **Node pools**: Drain and upgrade incrementally
---
## 8. Managed Kubernetes Services
For provider-specific managed Kubernetes services, see dedicated skills:
- **AWS EKS**: EKS section in `k8s-providers` rules
- **Azure AKS**: AKS section in `k8s-providers` rules
- **GCP GKE**: GKE section in `k8s-providers` rules
### Quick Comparison
| Feature | EKS | AKS | GKE |
| --- | --- | --- | --- |
| Latest K8s | 1.35 | 1.34 | 1.35 |
| Control Plane | Free | Free | Free |
| Node Autoscaling | Karpenter/MNG | Cluster Autoscaler | GKE Autopilot |
| Service Mesh | App Mesh (deprecated) | Istio (add-on) | Anthos Service Mesh |
| Secrets | AWS Secrets Manager | Azure Key Vault | Secret Manager |
---
## 9. Anti-Patterns
- Using `latest` tag for container images — always pin to specific version
- Defining resources without `requests`/`limits`
- Running containers as root
- Hardcoding config values in manifests — use ConfigMap/Secret
- Single replica for production workloads
- Missing health check probes
- Using `NodePort` in production — use `ClusterIP` + Ingress
- Ignoring deprecation warnings before upgrades
- Not testing upgrades in non-production first
## Related Skills
- For GitOps deployment with Argo CD, see [gitops-argocd](../gitops-argocd/) skill
- For Helm chart management, see [helm-workflow](../helm-workflow/) skill
- For Karpenter node provisioning, see [karpenter-workflow](../karpenter-workflow/) skill
---
## 10. k3s (Lightweight Kubernetes)
### When to Use k3s
- Edge computing, IoT, home lab, or resource-constrained environments
- Raspberry Pi clusters (ARM64)
- CI/CD ephemeral clusters
- Development environments where full k8s overhead is unnecessary
### k3s vs Full Kubernetes
| Feature | k3s | Full Kubernetes |
|---------|-----|-----------------|
| Control plane | Single binary (~100MB) | Multiple components |
| Datastore | SQLite (default), etcd, external | etcd required |
| Resource usage | ~500MB RAM | ~1-2GB RAM |
| ARM64 support | First-class, native | Supported, more setup |
| Built-in addons | CoreDNS, ServiceLB, local-path-provisioner | All external |
### Install k3s Server
```bash
# Standard install (Traefik + ServiceLB enabled)
curl -sfL https://get.k3s.io | sh -
# Disable Traefik (to use Envoy Gateway instead)
curl -sfL https://get.k3s.io | sh -s - server --disable traefik
# Pin specific version
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.6+k3s1 sh -s - server --disable traefik
```
> **Important**: Do NOT use `--disable servicelb` if you plan to use Gateway API with Envoy Gateway. ServiceLB provides LoadBalancer IPs for Gateway resources.
### Install k3s Agent
```bash
# Get token from server
sudo cat /var/lib/rancher/k3s/server/node-token
# On agent node
curl -sfL https://get.k3s.io | \
K3S_URL=https://<server-ip>:6443 \
K3S_TOKEN=<node-token> \
sh -
```
### k3s-Specific Gotchas
#### Metrics Server Requires `--kubelet-insecure-tls`
k3s uses self-signed kubelet certificates. The standard Metrics Server manifest will fail with TLS errors:
```bash
# After installing Metrics Server, patch the deployment:
kubectl patch deployment metrics-server -n kube-system --type='json' \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
```
#### Helm is Not Pre-installed
k3s does not include Helm by default. Install the release binary directly:
```bash
HELM_VERSION="v3.20.2"
curl -fsSL https://get.helm.sh/helm-${HELM_VERSION}-linux-arm64.tar.gz -o /tmp/helm.tar.gz
tar -zxvf /tmp/helm.tar.gz -C /tmp linux-arm64/helm
sudo mv /tmp/linux-arm64/helm /usr/local/bin/helm
rm -rf /tmp/linux-arm64 /tmp/helm.tar.gz
```
For other architectures, replace `linux-arm64` with `linux-amd64`, `linux-386`, or `linux-ppc64le`.
#### Container Images on ARM64
Not all container images support `arm64`. Verify before deploying:
```yaml
# NOT arm64 compatible (will fail with "exec format error")
image: kennethreitz/httpbin
# ARM64 compatible alternative
image: docker.io/kong/httpbin:latest
```
Use `docker manifest inspect <image>` to verify multi-arch support.
### Reinstalling k3s Server (Preserving State)
To change server flags (e.g., add `--disable servicelb` back):
```bash
# Stop k3s
sudo systemctl stop k3s
# Reinstall with new flags (existing SQLite DB and workloads are preserved)
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.6+k3s1 sh -s - server --disable traefik
# Restart
sudo systemctl restart k3s
```
---
## 11. Gateway API
### Overview
Gateway API is the next-generation Kubernetes API for traffic management, replacing Ingress. It provides richer routing, multi-tenancy, and role separation.
| Resource | Purpose |
|----------|---------|
| `GatewayClass` | Defines the controller (e.g., Envoy Gateway, Istio) |
| `Gateway` | Configures listeners (ports, protocols, TLS) |
| `HTTPRoute` | HTTP routing rules to backend services |
| `GRPCRoute` | gRPC routing rules |
| `TLSRoute` | TCP/TLS routing rules |
| `ReferenceGrant` | Cross-namespace route attachments |
### Install Gateway API CRDs
```bash
# Standard channel (stable, recommended)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# Experimental channel (includes additional features)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/experimental-install.yaml
```
### Install Envoy Gateway
Envoy Gateway is the CNCF reference implementation for Gateway API.
```bash
# 1. Download install YAML
# Check latest release: https://github.com/envoyproxy/gateway/releases
curl -sfL https://github.com/envoyproxy/gateway/releases/download/v1.7.2/install.yaml > /tmp/install.yaml
# 2. Install without CRDs (CRDs are installed separately above)
# Note: install.yaml CRDs have annotations exceeding kubectl's 262144-byte limit
# Option A: Requires python3-yaml (sudo apt install python3-yaml)
python3 -c "
import yaml, sys
with open('/tmp/install.yaml') as f:
docs = list(yaml.safe_load_all(f))
for doc in docs:
if doc and doc.get('kind') == 'CustomResourceDefinition':
continue
print('---')
yaml.safe_dump(doc, sys.stdout, default_flow_style=False)
" | kubectl apply -f -
# Option B: No dependencies required (awk-based)
# awk '/^---$/{p=1;next} /^kind: CustomResourceDefinition$/{p=0} p' /tmp/install.yaml | kubectl apply -f -
# 3. Create GatewayClass
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway-class
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF
```
### Gateway API + LoadBalancer
Gateway resources of type `LoadBalancer` require a LoadBalancer controller:
| Environment | Controller |
|-------------|------------|
| k3s | ServiceLB (built-in, keep enabled) |
| Cloud (AWS/GCP/Azure) | Cloud provider controller |
| Bare metal | MetalLB |
> **Warning**: If `--disable servicelb` is used in k3s, Gateway resources will show `AddressNotAssigned` status.
### Verify Gateway API
```bash
# Check GatewayClass
kubectl get gatewayclass
# Check Gateway status
kubectl get gateway -A
kubectl describe gateway <name> -n <namespace>
# Check HTTPRoute attachment
kubectl get httproute -A
# Test connectivity
curl http://<gateway-external-ip>/headers
```
### Gateway API Quick Start
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-route
spec:
parentRefs:
- name: my-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: my-service
port: 8080
```
---
## Additional References
- For managed Kubernetes providers (EKS, AKS, GKE), see [references/providers.md](references/providers.md)
- For autoscaling (KEDA, Knative, event-driven), see [references/autoscaling.md](references/autoscaling.md)
- For networking (Ingress, Gateway API, Network Policies, Service Mesh), see [references/networking.md](references/networking.md)
- For storage, RBAC, and deployment strategies, see [references/storage-and-rbac.md](references/storage-and-rbac.md)
- For Kustomize patterns (Helm comparison, overlays, generators, patches), see [references/kustomize.md](references/kustomize.md)
Scanned 9/12/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!