# Exercise 3: Production Kubernetes Deployment
# Complete deployment for Account Service with all production features

apiVersion: v1
kind: Namespace
metadata:
  name: financial-platform
  labels:
    name: financial-platform
    module: "11"

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: account-service
  namespace: financial-platform
  labels:
    app: account-service

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: account-service-role
  namespace: financial-platform
rules:
  - apiGroups: [""]
    resources: ["configmaps", "secrets"]
    verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: account-service-rolebinding
  namespace: financial-platform
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: account-service-role
subjects:
  - kind: ServiceAccount
    name: account-service
    namespace: financial-platform

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: account-service-config
  namespace: financial-platform
data:
  application.yaml: |
    server:
      port: 8000
      shutdown: graceful
    
    service:
      name: account-service
      version: 1.0.0
    
    database:
      pool_size: 20
      max_overflow: 40
      pool_timeout: 30
    
    cache:
      default_ttl: 300
      max_entries: 10000
    
    circuit_breaker:
      failure_threshold: 5
      recovery_timeout: 30
      half_open_requests: 3
    
    monitoring:
      metrics_enabled: true
      tracing_enabled: true
      log_level: INFO

---
apiVersion: v1
kind: Secret
metadata:
  name: account-service-secrets
  namespace: financial-platform
type: Opaque
stringData:
  database-url: "postgresql://account_user:SecurePass123!@postgres-service:5432/accounts"
  jwt-secret: "your-super-secret-jwt-key-change-in-production"
  encryption-key: "AES256-encryption-key-for-sensitive-data"

---
apiVersion: v1
kind: Secret
metadata:
  name: account-service-tls
  namespace: financial-platform
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTi... # Base64 encoded certificate
  tls.key: LS0tLS1CRUdJTi... # Base64 encoded private key

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: account-service
  namespace: financial-platform
  labels:
    app: account-service
    version: v1
    module: "11"
spec:
  replicas: 3
  revisionHistoryLimit: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: account-service
  template:
    metadata:
      labels:
        app: account-service
        version: v1
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"
        # Force pod restart on config change
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
    spec:
      serviceAccountName: account-service
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
        seccompProfile:
          type: RuntimeDefault
      
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - account-service
            topologyKey: kubernetes.io/hostname
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            preference:
              matchExpressions:
              - key: node-type
                operator: In
                values:
                - compute-optimized
      
      initContainers:
      - name: wait-for-postgres
        image: busybox:1.35
        command: ['sh', '-c', 'until nc -z postgres-service 5432; do echo waiting for postgres; sleep 2; done']
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL
      
      containers:
      - name: account-service
        image: financial-platform/account-service:latest
        imagePullPolicy: Always
        
        ports:
        - name: http
          containerPort: 8000
          protocol: TCP
        - name: metrics
          containerPort: 8080
          protocol: TCP
        
        env:
        - name: SERVICE_NAME
          value: "account-service"
        - name: ENVIRONMENT
          value: "production"
        - name: LOG_LEVEL
          value: "INFO"
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: account-service-secrets
              key: database-url
        - name: JWT_SECRET
          valueFrom:
            secretKeyRef:
              name: account-service-secrets
              key: jwt-secret
        - name: ENCRYPTION_KEY
          valueFrom:
            secretKeyRef:
              name: account-service-secrets
              key: encryption-key
        - name: JAEGER_AGENT_HOST
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: JAEGER_AGENT_PORT
          value: "6831"
        
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
            ephemeral-storage: "1Gi"
          limits:
            memory: "512Mi"
            cpu: "500m"
            ephemeral-storage: "2Gi"
        
        livenessProbe:
          httpGet:
            path: /health/live
            port: http
            scheme: HTTP
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        
        readinessProbe:
          httpGet:
            path: /health/ready
            port: http
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 3
        
        startupProbe:
          httpGet:
            path: /health/startup
            port: http
            scheme: HTTP
          initialDelaySeconds: 0
          periodSeconds: 10
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 30
        
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 15"]
        
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
          capabilities:
            drop:
            - ALL
        
        volumeMounts:
        - name: config
          mountPath: /etc/config
          readOnly: true
        - name: tls-certs
          mountPath: /etc/tls
          readOnly: true
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /app/cache
      
      volumes:
      - name: config
        configMap:
          name: account-service-config
      - name: tls-certs
        secret:
          secretName: account-service-tls
      - name: tmp
        emptyDir: {}
      - name: cache
        emptyDir:
          sizeLimit: 1Gi

---
apiVersion: v1
kind: Service
metadata:
  name: account-service
  namespace: financial-platform
  labels:
    app: account-service
    monitoring: "true"
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
  ports:
  - name: http
    port: 80
    targetPort: http
    protocol: TCP
  - name: metrics
    port: 8080
    targetPort: metrics
    protocol: TCP
  selector:
    app: account-service

---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: account-service-hpa
  namespace: financial-platform
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: account-service
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "1000"
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
      - type: Pods
        value: 1
        periodSeconds: 60
      selectPolicy: Min
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
      - type: Pods
        value: 2
        periodSeconds: 60
      selectPolicy: Max

---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: account-service-pdb
  namespace: financial-platform
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: account-service
  maxUnavailable: 1

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: account-service-netpol
  namespace: financial-platform
spec:
  podSelector:
    matchLabels:
      app: account-service
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: financial-platform
    - podSelector:
        matchLabels:
          app: api-gateway
    ports:
    - protocol: TCP
      port: 8000
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: financial-platform
    ports:
    - protocol: TCP
      port: 5432  # PostgreSQL
    - protocol: TCP
      port: 6379  # Redis
    - protocol: TCP
      port: 5672  # RabbitMQ
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: jaeger-agent
    ports:
    - protocol: UDP
      port: 6831
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 53   # DNS
    - protocol: UDP
      port: 53   # DNS