Claude-skill-registry kubernetes-manifests
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/kubernetes-manifests" ~/.claude/skills/majiayu000-claude-skill-registry-kubernetes-manifests && rm -rf "$T"
manifest:
skills/data/kubernetes-manifests/SKILL.mdsource content
Kubernetes / OpenShift Manifest Generator
Generate production-ready YAML manifests following security best practices and operational excellence.
Current Versions & CLI (January 2026)
| Platform | Current Version | CLI | Documentation |
|---|---|---|---|
| Kubernetes | 1.31.x | | https://kubernetes.io/docs/ |
| OpenShift | 4.17.x | | https://docs.openshift.com/ |
| EKS | 1.31 | | https://docs.aws.amazon.com/eks/ |
| AKS | 1.31 | | https://learn.microsoft.com/azure/aks/ |
| GKE | 1.31 | | https://cloud.google.com/kubernetes-engine/docs |
Command Usage Convention
IMPORTANT: This skill uses
kubectl in examples. When working with:
- OpenShift/ARO clusters: Replace
withkubectloc - Standard Kubernetes (AKS, EKS, GKE): Use
as shownkubectl
Core Principles
- Security by Default: Always include security contexts, never run as root
- Resource Management: Always specify resource requests/limits
- High Availability: Multiple replicas with anti-affinity for production
- Observability: Include health probes, annotations for monitoring
- GitOps Ready: Generate manifests suitable for version control
Manifest Generation Workflow
- Identify resource type and target platform
- Gather requirements (replicas, resources, networking, storage)
- Apply security best practices
- Generate YAML with appropriate labels and annotations
- Validate against best practices checklist
Resource Templates
Deployment (Production-Ready)
apiVersion: apps/v1 kind: Deployment metadata: name: ${APP_NAME} namespace: ${NAMESPACE} labels: app.kubernetes.io/name: ${APP_NAME} app.kubernetes.io/instance: ${INSTANCE} app.kubernetes.io/version: "${VERSION}" app.kubernetes.io/component: ${COMPONENT} app.kubernetes.io/part-of: ${PART_OF} app.kubernetes.io/managed-by: cluster-skills spec: replicas: ${REPLICAS:-3} revisionHistoryLimit: 5 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/name: ${APP_NAME} app.kubernetes.io/instance: ${INSTANCE} template: metadata: labels: app.kubernetes.io/name: ${APP_NAME} app.kubernetes.io/instance: ${INSTANCE} annotations: prometheus.io/scrape: "true" prometheus.io/port: "${METRICS_PORT:-8080}" spec: serviceAccountName: ${SERVICE_ACCOUNT:-default} securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: ${APP_NAME} topologyKey: kubernetes.io/hostname topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: ${APP_NAME} containers: - name: ${APP_NAME} image: ${IMAGE}:${TAG} imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL ports: - name: http containerPort: ${PORT:-8080} protocol: TCP env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace envFrom: - configMapRef: name: ${APP_NAME}-config optional: true - secretRef: name: ${APP_NAME}-secrets optional: true resources: requests: cpu: ${CPU_REQUEST:-100m} memory: ${MEMORY_REQUEST:-128Mi} limits: cpu: ${CPU_LIMIT:-500m} memory: ${MEMORY_LIMIT:-512Mi} livenessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 15 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 3 startupProbe: httpGet: path: /healthz port: http initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 30 volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {} terminationGracePeriodSeconds: 30
Service
apiVersion: v1 kind: Service metadata: name: ${APP_NAME} namespace: ${NAMESPACE} labels: app.kubernetes.io/name: ${APP_NAME} spec: type: ${SERVICE_TYPE:-ClusterIP} ports: - name: http port: ${SERVICE_PORT:-80} targetPort: http protocol: TCP selector: app.kubernetes.io/name: ${APP_NAME} app.kubernetes.io/instance: ${INSTANCE}
Ingress (Kubernetes)
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ${APP_NAME} namespace: ${NAMESPACE} annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" cert-manager.io/cluster-issuer: ${CLUSTER_ISSUER:-letsencrypt-prod} spec: ingressClassName: ${INGRESS_CLASS:-nginx} tls: - hosts: - ${HOST} secretName: ${APP_NAME}-tls rules: - host: ${HOST} http: paths: - path: / pathType: Prefix backend: service: name: ${APP_NAME} port: name: http
OpenShift Route
apiVersion: route.openshift.io/v1 kind: Route metadata: name: ${APP_NAME} namespace: ${NAMESPACE} annotations: haproxy.router.openshift.io/timeout: 60s spec: host: ${HOST} to: kind: Service name: ${APP_NAME} weight: 100 port: targetPort: http tls: termination: edge insecureEdgeTerminationPolicy: Redirect
ConfigMap
apiVersion: v1 kind: ConfigMap metadata: name: ${APP_NAME}-config namespace: ${NAMESPACE} data: APP_ENV: "${ENVIRONMENT:-production}" LOG_LEVEL: "${LOG_LEVEL:-info}"
Secret
apiVersion: v1 kind: Secret metadata: name: ${APP_NAME}-secrets namespace: ${NAMESPACE} type: Opaque stringData: DATABASE_URL: "${DATABASE_URL}"
PersistentVolumeClaim
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ${APP_NAME}-data namespace: ${NAMESPACE} spec: accessModes: - ${ACCESS_MODE:-ReadWriteOnce} storageClassName: ${STORAGE_CLASS:-standard} resources: requests: storage: ${STORAGE_SIZE:-10Gi}
StatefulSet
apiVersion: apps/v1 kind: StatefulSet metadata: name: ${APP_NAME} namespace: ${NAMESPACE} spec: serviceName: ${APP_NAME}-headless replicas: ${REPLICAS:-3} podManagementPolicy: Parallel updateStrategy: type: RollingUpdate selector: matchLabels: app.kubernetes.io/name: ${APP_NAME} template: metadata: labels: app.kubernetes.io/name: ${APP_NAME} spec: securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault containers: - name: ${APP_NAME} image: ${IMAGE}:${TAG} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL ports: - name: http containerPort: ${PORT:-8080} resources: requests: cpu: ${CPU_REQUEST:-100m} memory: ${MEMORY_REQUEST:-256Mi} limits: cpu: ${CPU_LIMIT:-1000m} memory: ${MEMORY_LIMIT:-1Gi} volumeMounts: - name: data mountPath: /data volumeClaimTemplates: - metadata: name: data spec: accessModes: - ReadWriteOnce storageClassName: ${STORAGE_CLASS:-standard} resources: requests: storage: ${STORAGE_SIZE:-10Gi}
NetworkPolicy
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: ${APP_NAME}-netpol namespace: ${NAMESPACE} spec: podSelector: matchLabels: app.kubernetes.io/name: ${APP_NAME} policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: ${INGRESS_NAMESPACE:-ingress-nginx} ports: - protocol: TCP port: ${PORT:-8080} egress: - to: - namespaceSelector: {} ports: - protocol: UDP port: 53 # DNS - to: - podSelector: matchLabels: app.kubernetes.io/name: ${EGRESS_TARGET} ports: - protocol: TCP port: ${EGRESS_PORT}
HorizontalPodAutoscaler
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: ${APP_NAME} namespace: ${NAMESPACE} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: ${APP_NAME} minReplicas: ${MIN_REPLICAS:-2} maxReplicas: ${MAX_REPLICAS:-10} metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: ${CPU_TARGET:-70} - type: Resource resource: name: memory target: type: Utilization averageUtilization: ${MEMORY_TARGET:-80} behavior: scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 10 periodSeconds: 60 scaleUp: stabilizationWindowSeconds: 0 policies: - type: Percent value: 100 periodSeconds: 15
ServiceAccount with RBAC
apiVersion: v1 kind: ServiceAccount metadata: name: ${APP_NAME} namespace: ${NAMESPACE} automountServiceAccountToken: false --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: ${APP_NAME} namespace: ${NAMESPACE} rules: - apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: ${APP_NAME} namespace: ${NAMESPACE} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ${APP_NAME} subjects: - kind: ServiceAccount name: ${APP_NAME} namespace: ${NAMESPACE}
CronJob
apiVersion: batch/v1 kind: CronJob metadata: name: ${JOB_NAME} namespace: ${NAMESPACE} spec: schedule: "${SCHEDULE}" concurrencyPolicy: ${CONCURRENCY:-Forbid} successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 startingDeadlineSeconds: 300 jobTemplate: spec: backoffLimit: 3 activeDeadlineSeconds: ${TIMEOUT:-3600} template: spec: securityContext: runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault restartPolicy: OnFailure containers: - name: ${JOB_NAME} image: ${IMAGE}:${TAG} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL resources: requests: cpu: ${CPU_REQUEST:-100m} memory: ${MEMORY_REQUEST:-128Mi} limits: cpu: ${CPU_LIMIT:-500m} memory: ${MEMORY_LIMIT:-512Mi}
PodDisruptionBudget
apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: ${APP_NAME}-pdb namespace: ${NAMESPACE} spec: minAvailable: ${MIN_AVAILABLE:-1} # OR use maxUnavailable # maxUnavailable: 1 selector: matchLabels: app.kubernetes.io/name: ${APP_NAME}
Best Practices Checklist
Security
-
runAsNonRoot: true -
andrunAsUser
set (non-zero)runAsGroup -
allowPrivilegeEscalation: false -
readOnlyRootFilesystem: true -
capabilities.drop: ["ALL"] -
seccompProfile.type: RuntimeDefault -
(unless needed)automountServiceAccountToken: false
Reliability
- Resource requests and limits defined
- Liveness probe configured
- Readiness probe configured
- Startup probe for slow-starting apps
- PodDisruptionBudget defined
- Multiple replicas for production
Observability
- Standard labels applied (
)app.kubernetes.io/* - Prometheus annotations for metrics
- Structured logging configured
Networking
- NetworkPolicy defined (zero-trust)
- Service defined for pod exposure
- Ingress/Route for external access