# Strip your local environment entirely
-weight: 500;">docker run --env-file /dev/null myapp:latest # Or explicitly pass only what Kubernetes will provide
-weight: 500;">docker run \ -e DB_HOST=localhost \ -e APP_ENV=production \ myapp:latest
# Strip your local environment entirely
-weight: 500;">docker run --env-file /dev/null myapp:latest # Or explicitly pass only what Kubernetes will provide
-weight: 500;">docker run \ -e DB_HOST=localhost \ -e APP_ENV=production \ myapp:latest
# Strip your local environment entirely
-weight: 500;">docker run --env-file /dev/null myapp:latest # Or explicitly pass only what Kubernetes will provide
-weight: 500;">docker run \ -e DB_HOST=localhost \ -e APP_ENV=production \ myapp:latest
# External Secrets Operator pattern for EKS
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: name: app-secrets
spec: refreshInterval: 1h secretStoreRef: name: aws-secrets-manager kind: ClusterSecretStore target: name: app-secrets data: - secretKey: DB_PASSWORD remoteRef: key: prod/myapp/db property: password
# External Secrets Operator pattern for EKS
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: name: app-secrets
spec: refreshInterval: 1h secretStoreRef: name: aws-secrets-manager kind: ClusterSecretStore target: name: app-secrets data: - secretKey: DB_PASSWORD remoteRef: key: prod/myapp/db property: password
# External Secrets Operator pattern for EKS
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: name: app-secrets
spec: refreshInterval: 1h secretStoreRef: name: aws-secrets-manager kind: ClusterSecretStore target: name: app-secrets data: - secretKey: DB_PASSWORD remoteRef: key: prod/myapp/db property: password
apiVersion: v1
kind: ServiceAccount
metadata: name: myapp-sa annotations: eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/myapp-role
apiVersion: v1
kind: ServiceAccount
metadata: name: myapp-sa annotations: eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/myapp-role
apiVersion: v1
kind: ServiceAccount
metadata: name: myapp-sa annotations: eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/myapp-role
# Watch resource consumption in real time
-weight: 500;">kubectl top pod myapp-pod --containers # Get historical metrics if you have metrics-server
-weight: 500;">kubectl top pods -l app=myapp --sort-by=memory
# Watch resource consumption in real time
-weight: 500;">kubectl top pod myapp-pod --containers # Get historical metrics if you have metrics-server
-weight: 500;">kubectl top pods -l app=myapp --sort-by=memory
# Watch resource consumption in real time
-weight: 500;">kubectl top pod myapp-pod --containers # Get historical metrics if you have metrics-server
-weight: 500;">kubectl top pods -l app=myapp --sort-by=memory
resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" # Consider not setting CPU limits — only requests # CPU limits cause throttling; CPU requests cause scheduling
resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" # Consider not setting CPU limits — only requests # CPU limits cause throttling; CPU requests cause scheduling
resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" # Consider not setting CPU limits — only requests # CPU limits cause throttling; CPU requests cause scheduling
-weight: 500;">kubectl describe pod myapp-pod | grep -A 10 "Last State"
# Look for: Reason: OOMKilled
-weight: 500;">kubectl describe pod myapp-pod | grep -A 10 "Last State"
# Look for: Reason: OOMKilled
-weight: 500;">kubectl describe pod myapp-pod | grep -A 10 "Last State"
# Look for: Reason: OOMKilled
<-weight: 500;">service-name>.<namespace>.svc.cluster.local
<-weight: 500;">service-name>.<namespace>.svc.cluster.local
<-weight: 500;">service-name>.<namespace>.svc.cluster.local
env: - name: DB_HOST value: "postgres--weight: 500;">service" # same namespace - name: AUTH_SERVICE_URL value: "http://auth--weight: 500;">service.auth-namespace.svc.cluster.local" # cross-namespace
env: - name: DB_HOST value: "postgres--weight: 500;">service" # same namespace - name: AUTH_SERVICE_URL value: "http://auth--weight: 500;">service.auth-namespace.svc.cluster.local" # cross-namespace
env: - name: DB_HOST value: "postgres--weight: 500;">service" # same namespace - name: AUTH_SERVICE_URL value: "http://auth--weight: 500;">service.auth-namespace.svc.cluster.local" # cross-namespace
# Exec into the pod and test DNS directly
-weight: 500;">kubectl exec -it myapp-pod -- nslookup postgres--weight: 500;">service
-weight: 500;">kubectl exec -it myapp-pod -- -weight: 500;">curl -v http://postgres--weight: 500;">service:5432 # If nslookup fails, check CoreDNS
-weight: 500;">kubectl logs -n kube-system -l k8s-app=kube-dns
# Exec into the pod and test DNS directly
-weight: 500;">kubectl exec -it myapp-pod -- nslookup postgres--weight: 500;">service
-weight: 500;">kubectl exec -it myapp-pod -- -weight: 500;">curl -v http://postgres--weight: 500;">service:5432 # If nslookup fails, check CoreDNS
-weight: 500;">kubectl logs -n kube-system -l k8s-app=kube-dns
# Exec into the pod and test DNS directly
-weight: 500;">kubectl exec -it myapp-pod -- nslookup postgres--weight: 500;">service
-weight: 500;">kubectl exec -it myapp-pod -- -weight: 500;">curl -v http://postgres--weight: 500;">service:5432 # If nslookup fails, check CoreDNS
-weight: 500;">kubectl logs -n kube-system -l k8s-app=kube-dns
# Explicit ingress policy — don't rely on default-allow
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: name: allow-myapp-ingress
spec: podSelector: matchLabels: app: myapp ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 8080
# Explicit ingress policy — don't rely on default-allow
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: name: allow-myapp-ingress
spec: podSelector: matchLabels: app: myapp ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 8080
# Explicit ingress policy — don't rely on default-allow
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: name: allow-myapp-ingress
spec: podSelector: matchLabels: app: myapp ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 8080
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 # give the app time to -weight: 500;">start periodSeconds: 10 failureThreshold: 3 timeoutSeconds: 5 readinessProbe: httpGet: path: /ready # separate endpoint from liveness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 # give the app time to -weight: 500;">start periodSeconds: 10 failureThreshold: 3 timeoutSeconds: 5 readinessProbe: httpGet: path: /ready # separate endpoint from liveness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 # give the app time to -weight: 500;">start periodSeconds: 10 failureThreshold: 3 timeoutSeconds: 5 readinessProbe: httpGet: path: /ready # separate endpoint from liveness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3
securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 # ensures volume mounts are group-writable readOnlyRootFilesystem: true # force explicit volume declarations
securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 # ensures volume mounts are group-writable readOnlyRootFilesystem: true # force explicit volume declarations
securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 # ensures volume mounts are group-writable readOnlyRootFilesystem: true # force explicit volume declarations
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
RUN chown -R appuser:appgroup /app
USER appuser
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
RUN chown -R appuser:appgroup /app
USER appuser
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
RUN chown -R appuser:appgroup /app
USER appuser
-weight: 500;">docker run --user 1000:1000 --read-only myapp:latest
-weight: 500;">docker run --user 1000:1000 --read-only myapp:latest
-weight: 500;">docker run --user 1000:1000 --read-only myapp:latest - Environment audit — run locally with clean environment, no inherited shell variables
- IAM/credentials — no local credential files; use IRSA or Workload Identity
- Resource profiling — measure actual CPU and memory under load before setting limits
- DNS references — replace all localhost with Kubernetes -weight: 500;">service DNS names
- Probe configuration — separate liveness/readiness endpoints, generous initialDelaySeconds
- Security context — test with runAsNonRoot: true and readOnlyRootFilesystem: true locally
- Volume permissions — set fsGroup on all writable volume mounts