# Kubernetes 部署配置文件
# 用于从私有 Harbor 仓库拉取 NGINX 镜像并部署
# 
# 使用方法:
# 1. 设置环境变量:
#    export HARBOR_REGISTRY=<你的Harbor仓库地址>
#    export HARBOR_USERNAME=<Harbor用户名>
#    export HARBOR_PASSWORD=<Harbor密码>
#    export NGINX_IMAGE_TAG=<镜像标签>
# 
# 2. 运行部署脚本:
#    ./deploy.sh

---
# 1. ConfigMap - NGINX 配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
data:
  nginx.conf: |
    # 由于以非root用户运行，user指令会被忽略，可以移除
    # user  nginx;
    worker_processes  auto;
    
    # 修改日志路径为我们已经挂载的目录
    error_log  /usr/local/nginx/logs/error.log notice;
    pid        /var/run/nginx.pid;
    
    events {
      worker_connections  1024;
    }
    
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
      
      # 修改访问日志路径
      access_log  /usr/local/nginx/logs/access.log  main;
      
      sendfile        on;
      keepalive_timeout  65;
      
      server {
        listen       8080;  # 修改为非特权端口
        server_name  localhost;
        
        # 为SPA应用添加特殊处理
        location / {
          root   /usr/local/nginx/html;
          index  index.html index.htm;
          
          # 支持HTML扩展名省略和SPA路由
          try_files $uri $uri.html $uri/ /index.html;
        }
        
        # 静态资源处理
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
          root /usr/local/nginx/html;
          expires 30d;
          add_header Cache-Control "public, max-age=2592000";
          access_log off;
        }
        
        # API代理配置 (如果需要)
        # location /api/ {
        #   proxy_pass http://backend-service:8080/;
        #   proxy_set_header Host $host;
        #   proxy_set_header X-Real-IP $remote_addr;
        # }
        
        # 健康检查端点
        location /health {
          return 200 'ok';
          add_header Content-Type text/plain;
        }
      }
    }

  mime.types: |
    types {
        text/html                                        html htm shtml;
        text/css                                         css;
        text/xml                                         xml;
        image/gif                                        gif;
        image/jpeg                                       jpeg jpg;
        application/javascript                           js;
        application/atom+xml                             atom;
        application/rss+xml                              rss;

        text/mathml                                      mml;
        text/plain                                       txt;
        text/vnd.sun.j2me.app-descriptor                 jad;
        text/vnd.wap.wml                                 wml;
        text/x-component                                 htc;

        image/avif                                       avif;
        image/png                                        png;
        image/svg+xml                                    svg svgz;
        image/tiff                                       tif tiff;
        image/vnd.wap.wbmp                               wbmp;
        image/webp                                       webp;
        image/x-icon                                     ico;
        image/x-jng                                      jng;
        image/x-ms-bmp                                   bmp;

        font/woff                                        woff;
        font/woff2                                       woff2;

        application/java-archive                         jar war ear;
        application/json                                 json;
        application/mac-binhex40                         hqx;
        application/msword                               doc;
        application/pdf                                  pdf;
        application/postscript                           ps eps ai;
        application/rtf                                  rtf;
        application/vnd.apple.mpegurl                    m3u8;
        application/vnd.google-earth.kml+xml             kml;
        application/vnd.google-earth.kmz                 kmz;
        application/vnd.ms-excel                         xls;
        application/vnd.ms-fontobject                    eot;
        application/vnd.ms-powerpoint                    ppt;
        application/vnd.oasis.opendocument.graphics      odg;
        application/vnd.oasis.opendocument.presentation  odp;
        application/vnd.oasis.opendocument.spreadsheet   ods;
        application/vnd.oasis.opendocument.text          odt;
        application/vnd.wap.wmlc                         wmlc;
        application/wasm                                 wasm;
        application/x-7z-compressed                      7z;
        application/x-cocoa                              cco;
        application/x-java-archive-diff                  jardiff;
        application/x-java-jnlp-file                     jnlp;
        application/x-makeself                           run;
        application/x-perl                               pl pm;
        application/x-pilot                              prc pdb;
        application/x-rar-compressed                     rar;
        application/x-redhat-package-manager             rpm;
        application/x-sea                                sea;
        application/x-shockwave-flash                    swf;
        application/x-stuffit                            sit;
        application/x-tcl                                tcl tk;
        application/x-x509-ca-cert                       der pem crt;
        application/x-xpinstall                          xpi;
        application/xhtml+xml                            xhtml;
        application/xspf+xml                             xspf;
        application/zip                                  zip;

        application/octet-stream                         bin exe dll;
        application/octet-stream                         deb;
        application/octet-stream                         dmg;
        application/octet-stream                         iso img;
        application/octet-stream                         msi msp msm;

        audio/midi                                       mid midi kar;
        audio/mpeg                                       mp3;
        audio/ogg                                        ogg;
        audio/x-m4a                                      m4a;
        audio/x-realaudio                                ra;

        video/3gpp                                       3gpp 3gp;
        video/mp2t                                       ts;
        video/mp4                                        mp4;
        video/mpeg                                       mpeg mpg;
        video/quicktime                                  mov;
        video/webm                                       webm;
        video/x-flv                                      flv;
        video/x-m4v                                      m4v;
        video/x-mng                                      mng;
        video/x-ms-asf                                   asx asf;
        video/x-ms-wmv                                   wmv;
        video/x-msvideo                                  avi;
    }

---
# 2. Deployment - NGINX 应用部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
    version: v1
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      # 使用私有仓库凭据
      imagePullSecrets:
        - name: harbor-registry-secret
      
      # 安全上下文
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
        fsGroup: 65534
        
      # 添加初始化容器来设置日志目录权限
      initContainers:
        - name: init-nginx-logs
          image: busybox
          command: ["/bin/sh", "-c"]
          args:
            - mkdir -p /usr/local/nginx/logs;
              chmod 777 /usr/local/nginx/logs;
              touch /usr/local/nginx/logs/error.log /usr/local/nginx/logs/access.log;
              chmod 666 /usr/local/nginx/logs/error.log /usr/local/nginx/logs/access.log;
          volumeMounts:
            - name: nginx-logs
              mountPath: /usr/local/nginx/logs
              
        # 添加初始化容器检查HTML目录权限
        - name: init-html-permissions
          image: busybox
          command: ["/bin/sh", "-c"]
          args:
            - |
              echo "检查HTML目录权限...";
              if [ ! -r /usr/local/nginx/html ]; then
                echo "警告: HTML目录不可读";
                chmod -R 755 /usr/local/nginx/html;
              fi;
              
              # 保留已存在的前端文件，不覆盖
              if [ -f /usr/local/nginx/html/index.html ]; then
                echo "找到现有index.html文件，将保留这些文件";
              else
                echo "警告: 没有找到index文件，创建默认页面";
                cat > /usr/local/nginx/html/index.html << 'EOF'
              <!DOCTYPE html>
              <html><head><title>Welcome to Nginx</title></head>
              <body><h1>Welcome to Nginx on Kubernetes!</h1>
              <p>If you see this page, the persistent volume is mounted but no HTML files were found.</p>
              </body></html>
              EOF
              fi;
              
              echo "设置目录权限...";
              chown -R 65534:65534 /usr/local/nginx/html || true;
              chmod -R 755 /usr/local/nginx/html || true;
              echo "HTML目录权限设置完成";
        
      containers:
        - name: nginx
          # 使用私有仓库中的镜像（需要根据实际情况修改）
          image: $HARBOR_REGISTRY/test/nginx:$NGINX_IMAGE_TAG
          imagePullPolicy: Always
          
          # 添加明确的启动命令，确保使用正确的配置文件
          command: ["/usr/local/nginx/sbin/nginx"]
          args: ["-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]
          
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
              
          # 环境变量
          env:
            - name: TZ
              value: "Asia/Shanghai"
              
          # 资源限制
          resources:
            requests:
              memory: "64Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "200m"
              
          # 健康检查
          livenessProbe:
            httpGet:
              path: /health
              port: 8080  # 修改端口
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
            
          readinessProbe:
            httpGet:
              path: /health
              port: 8080  # 修改端口
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
            
          # 启动探针
          startupProbe:
            httpGet:
              path: /health
              port: 8080  # 修改端口
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
            
          # 挂载配置文件 - 修改挂载方式
          volumeMounts:
            - name: nginx-config-volume
              mountPath: /etc/nginx  # 修改为目录挂载而非文件挂载
            - name: nginx-cache
              mountPath: /var/cache/nginx
            - name: nginx-run
              mountPath: /var/run
            # 添加日志目录挂载
            - name: nginx-logs
              mountPath: /usr/local/nginx/logs
            # 添加HTML内容挂载
            - name: nginx-html-content
              mountPath: /usr/local/nginx/html
              
      volumes:
        - name: nginx-config-volume
          configMap:
            name: nginx-config
            defaultMode: 0644
        - name: nginx-cache
          emptyDir: {}
        - name: nginx-run
          emptyDir: {}
        # 添加日志目录卷
        - name: nginx-logs
          emptyDir: {}
        # 添加HTML内容卷
        - name: nginx-html-content
          persistentVolumeClaim:
            claimName: nginx-html-pvc
            
      # 节点选择器（可选）
      nodeSelector:
        kubernetes.io/os: linux
        
      # 容忍度（可选）
      tolerations:
        - key: "node.kubernetes.io/not-ready"
          operator: "Exists"
          effect: "NoExecute"
          tolerationSeconds: 300
        - key: "node.kubernetes.io/unreachable"
          operator: "Exists"
          effect: "NoExecute"
          tolerationSeconds: 300

---
# 3. Service - 服务暴露
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: default
  labels:
    app: nginx
spec:
  type: NodePort  # 修改为NodePort类型
  ports:
    - name: http
      port: 8080  # 集群内部访问端口
      targetPort: 8080  # 容器端口
      nodePort: 32020  # 主机端口，必须在30000-32767范围内
      protocol: TCP
  selector:
    app: nginx

---
# 4. HorizontalPodAutoscaler - 自动扩缩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 50
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15

---
# 5. PodDisruptionBudget - Pod 中断预算
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: nginx-pdb
  namespace: default
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: nginx
