Kubernetes 部署 Spring Cloud 微服务方案

吴书松
吴书松
发布于 2025-09-04 / 24 阅读
1
0

Kubernetes 部署 Spring Cloud 微服务方案

集群架构规划

  • Kubernetes 集群:已存在的集群(包含多个节点)

  • 公网服务器:用于暴露 Spring Gateway 服务到外网

  • 服务部署

    • Nacos:单例部署,仅集群内部访问

    • Spring Gateway、Admin、Order:各3个副本,配置资源限制和HPA

1. 准备工作

1.1 创建命名空间

kubectl create namespace spring-cloud

1.2 准备 Docker 镜像

确保以下镜像已构建并推送到镜像仓库:

  • nacos-server:latest (单机模式)

  • spring-gateway:latest

  • admin-service:latest

  • order-service:latest

2. 部署 Nacos(单例模式)

创建 nacos-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nacos
  namespace: spring-cloud
  labels:
    app: nacos
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nacos
  template:
    metadata:
      labels:
        app: nacos
    spec:
      containers:
      - name: nacos
        image: nacos/nacos-server:latest
        env:
        - name: MODE
          value: standalone
        ports:
        - containerPort: 8848
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /nacos/actuator/health
            port: 8848
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /nacos/actuator/health
            port: 8848
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: nacos-service
  namespace: spring-cloud
spec:
  selector:
    app: nacos
  ports:
    - protocol: TCP
      port: 8848
      targetPort: 8848
  type: ClusterIP  # 内部服务,无法从集群外直接访问

应用配置:

kubectl apply -f nacos-deployment.yaml

3. 部署 Spring Gateway、Admin 和 Order 服务

3.1 创建通用部署模板

创建 microservice-deployment.yaml

# Spring Gateway 部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-gateway
  namespace: spring-cloud
  labels:
    app: spring-gateway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: spring-gateway
  template:
    metadata:
      labels:
        app: spring-gateway
    spec:
      containers:
      - name: spring-gateway
        image: spring-gateway:latest
        ports:
        - containerPort: 8080
        env:
        - name: NACOS_SERVER_ADDR
          value: "nacos-service.spring-cloud:8848"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
---
# Admin 服务部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin-service
  namespace: spring-cloud
  labels:
    app: admin-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: admin-service
  template:
    metadata:
      labels:
        app: admin-service
    spec:
      containers:
      - name: admin-service
        image: admin-service:latest
        ports:
        - containerPort: 8081
        env:
        - name: NACOS_SERVER_ADDR
          value: "nacos-service.spring-cloud:8848"
        - name: SERVER_PORT
          value: "8081"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8081
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8081
          initialDelaySeconds: 30
          periodSeconds: 10
---
# Order 服务部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: spring-cloud
  labels:
    app: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: order-service:latest
        ports:
        - containerPort: 8082
        env:
        - name: NACOS_SERVER_ADDR
          value: "nacos-service.spring-cloud:8848"
        - name: SERVER_PORT
          value: "8082"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8082
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8082
          initialDelaySeconds: 30
          periodSeconds: 10

3.2 创建服务

创建 microservice-services.yaml

# Spring Gateway 服务
apiVersion: v1
kind: Service
metadata:
  name: spring-gateway-service
  namespace: spring-cloud
spec:
  selector:
    app: spring-gateway
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP
---
# Admin 服务
apiVersion: v1
kind: Service
metadata:
  name: admin-service
  namespace: spring-cloud
spec:
  selector:
    app: admin-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8081
  type: ClusterIP
---
# Order 服务
apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: spring-cloud
spec:
  selector:
    app: order-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8082
  type: ClusterIP

应用配置:

kubectl apply -f microservice-deployment.yaml
kubectl apply -f microservice-services.yaml

4. 配置 Horizontal Pod Autoscaler (HPA)

为 Admin 和 Order 服务创建 HPA:

创建 hpa-config.yaml

# Admin 服务 HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: admin-service-hpa
  namespace: spring-cloud
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: admin-service
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      policies:
      - type: Pods
        value: 1
        periodSeconds: 60
      stabilizationWindowSeconds: 300
      selectPolicy: Min
    scaleUp:
      policies:
      - type: Pods
        value: 2
        periodSeconds: 60
      stabilizationWindowSeconds: 0
      selectPolicy: Max
---
# Order 服务 HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
  namespace: spring-cloud
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      policies:
      - type: Pods
        value: 1
        periodSeconds: 60
      stabilizationWindowSeconds: 300
      selectPolicy: Min
    scaleUp:
      policies:
      - type: Pods
        value: 2
        periodSeconds: 60
      stabilizationWindowSeconds: 0
      selectPolicy: Max

应用配置:

kubectl apply -f hpa-config.yaml

5. 配置外部访问(使用公网服务器)

5.1 安装和配置 Nginx Ingress Controller

在公网服务器上安装 Nginx,并配置为反向代理到 Kubernetes 集群的 Spring Gateway 服务。

创建 nginx-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: spring-cloud
data:
  nginx.conf: |
    events {
      worker_connections 1024;
    }
    
    http {
      upstream spring-gateway {
        server spring-gateway-service.spring-cloud.svc.cluster.local:80;
      }
      
      server {
        listen 80;
        
        location / {
          proxy_pass http://spring-gateway;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
        }
      }
    }

5.2 创建 Nginx 部署和服务

创建 nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: spring-cloud
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: spring-cloud
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

应用配置:

kubectl apply -f nginx-config.yaml
kubectl apply -f nginx-deployment.yaml

5.3 配置公网服务器

在公网服务器上配置 Nginx 作为反向代理,将流量转发到 Kubernetes 集群的 Nginx 服务:

# 在公网服务器上安装 Nginx
sudo apt update
sudo apt install nginx -y

# 配置 Nginx
sudo tee /etc/nginx/sites-available/k8s-proxy << EOF
server {
    listen 80;
    server_name your-domain.com; # 替换为你的域名或IP
    
    location / {
        proxy_pass http://<nginx-service-external-ip>:80; # 替换为 Kubernetes Nginx 服务的外部IP
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }
}
EOF

# 启用配置
sudo ln -s /etc/nginx/sites-available/k8s-proxy /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

6. 验证部署

6.1 检查所有资源状态

# 查看所有部署
kubectl get deployments -n spring-cloud

# 查看所有服务
kubectl get services -n spring-cloud

# 查看所有 Pods
kubectl get pods -n spring-cloud

# 查看 HPA 状态
kubectl get hpa -n spring-cloud

6.2 测试服务访问

# 获取 Nginx 服务的外部 IP
kubectl get service nginx-service -n spring-cloud -o wide

# 测试外部访问(使用公网服务器的 IP 或域名)
curl http://<public-server-ip>

# 测试内部服务访问
kubectl exec -it <pod-name> -n spring-cloud -- curl http://nacos-service:8848

6.3 监控 HPA 行为

# 查看 HPA 详情
kubectl describe hpa admin-service-hpa -n spring-cloud
kubectl describe hpa order-service-hpa -n spring-cloud

# 查看资源使用情况
kubectl top pods -n spring-cloud

7. 注意事项

  1. Metrics Server:确保 Kubernetes 集群已安装 Metrics Server,HPA 需要它来获取资源使用指标:

    kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    
    components.yaml内容
    
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        k8s-app: metrics-server
        rbac.authorization.k8s.io/aggregate-to-admin: "true"
        rbac.authorization.k8s.io/aggregate-to-edit: "true"
        rbac.authorization.k8s.io/aggregate-to-view: "true"
      name: system:aggregated-metrics-reader
    rules:
    - apiGroups:
      - metrics.k8s.io
      resources:
      - pods
      - nodes
      verbs:
      - get
      - list
      - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        k8s-app: metrics-server
      name: system:metrics-server
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes/metrics
      verbs:
      - get
    - apiGroups:
      - ""
      resources:
      - pods
      - nodes
      verbs:
      - get
      - list
      - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server-auth-reader
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: extension-apiserver-authentication-reader
    subjects:
    - kind: ServiceAccount
      name: metrics-server
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server:system:auth-delegator
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:auth-delegator
    subjects:
    - kind: ServiceAccount
      name: metrics-server
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      labels:
        k8s-app: metrics-server
      name: system:metrics-server
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:metrics-server
    subjects:
    - kind: ServiceAccount
      name: metrics-server
      namespace: kube-system
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server
      namespace: kube-system
    spec:
      ports:
      - appProtocol: https
        name: https
        port: 443
        protocol: TCP
        targetPort: https
      selector:
        k8s-app: metrics-server
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        k8s-app: metrics-server
      name: metrics-server
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          k8s-app: metrics-server
      strategy:
        rollingUpdate:
          maxUnavailable: 0
      template:
        metadata:
          labels:
            k8s-app: metrics-server
        spec:
          containers:
          - args:
            - --cert-dir=/tmp
            - --secure-port=10250
            - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
            - --kubelet-use-node-status-port
            - --metric-resolution=15s
            image: registry.k8s.io/metrics-server/metrics-server:v0.8.0
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /livez
                port: https
                scheme: HTTPS
              periodSeconds: 10
            name: metrics-server
            ports:
            - containerPort: 10250
              name: https
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /readyz
                port: https
                scheme: HTTPS
              initialDelaySeconds: 20
              periodSeconds: 10
            resources:
              requests:
                cpu: 100m
                memory: 200Mi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                - ALL
              readOnlyRootFilesystem: true
              runAsNonRoot: true
              runAsUser: 1000
              seccompProfile:
                type: RuntimeDefault
            volumeMounts:
            - mountPath: /tmp
              name: tmp-dir
          nodeSelector:
            kubernetes.io/os: linux
          priorityClassName: system-cluster-critical
          serviceAccountName: metrics-server
          volumes:
          - emptyDir: {}
            name: tmp-dir
    ---
    apiVersion: apiregistration.k8s.io/v1
    kind: APIService
    metadata:
      labels:
        k8s-app: metrics-server
      name: v1beta1.metrics.k8s.io
    spec:
      group: metrics.k8s.io
      groupPriorityMinimum: 100
      insecureSkipTLSVerify: true
      service:
        name: metrics-server
        namespace: kube-system
      version: v1beta1
      versionPriority: 100
    
  2. Spring Boot Actuator:确保 Spring Boot 应用包含 Actuator 依赖,以便提供健康检查端点。

  3. Nacos 配置:确保微服务应用配置中正确设置了 Nacos 服务器地址:

    spring:
      cloud:
        nacos:
          discovery:
            server-addr: nacos-service.spring-cloud:8848
  4. 资源限制:根据实际应用需求调整 CPU 和内存的请求和限制值。

  5. 网络策略:如果需要更严格的网络隔离,可以创建 NetworkPolicy 资源限制服务间的通信。

这个部署方案满足了您的所有要求:

  • Nacos 单例部署,仅内部访问

  • 其他服务初始副本数为 3

  • 设置了每个副本的 CPU 和内存资源限制

  • 配置了 HPA,在 CPU 和内存使用率达到 80% 时扩容,下降到 60% 时缩容

  • 通过公网服务器暴露 Spring Gateway 服务到外网


评论