# Complete Kubernetes Application Example # This file contains all resources needed for a production web application --- apiVersion: v1 kind: Namespace metadata: name: example-app labels: name: example-app environment: production --- apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: example-app data: APP_ENV: "production" LOG_LEVEL: "info" PORT: "8080" DATABASE_HOST: "postgres.example-app.svc.cluster.local" DATABASE_PORT: "5432" DATABASE_NAME: "appdb" --- apiVersion: v1 kind: Secret metadata: name: app-secrets namespace: example-app type: Opaque stringData: DATABASE_PASSWORD: "changeme-use-sealed-secrets" API_KEY: "changeme-use-external-secrets" --- apiVersion: v1 kind: ServiceAccount metadata: name: app namespace: example-app --- apiVersion: apps/v1 kind: Deployment metadata: name: app namespace: example-app labels: app: example-app tier: frontend spec: replicas: 3 revisionHistoryLimit: 10 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: example-app template: metadata: labels: app: example-app tier: frontend version: v1.0.0 annotations: prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" spec: serviceAccountName: app securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 2000 containers: - name: app image: nginx:1.25-alpine imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 protocol: TCP envFrom: - configMapRef: name: app-config - secretRef: name: app-secrets resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 3 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp - name: cache mountPath: /var/cache/nginx volumes: - name: tmp emptyDir: {} - name: cache emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: app namespace: example-app labels: app: example-app spec: type: ClusterIP selector: app: example-app ports: - name: http port: 80 targetPort: 8080 protocol: TCP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app namespace: example-app annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/rate-limit: "100" spec: tls: - hosts: - app.example.com secretName: app-tls rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: app port: number: 80 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: app namespace: example-app spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: app minReplicas: 3 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: app namespace: example-app spec: minAvailable: 2 selector: matchLabels: app: example-app