บริการลงทะเบียนและชำระเงิน AWSบริการลงทะเบียนและชำระเงิน AWS

在Amazon EKS上构建生产级高可用Nacos架构

2025-01-14 · 阅读 25 分钟 · By AWS架构师

详细介绍如何在Amazon EKS上部署高可用的Nacos服务发现和配置管理系统,包括多可用区设置、RDS集成和企业级弹性配置

引言

在云原生微服务架构时代,拥有一个强大的服务发现和配置管理系统对于企业应用至关重要。Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开发的开源解决方案,提供服务发现、配置管理和服务管理功能。本文将详细介绍如何在Amazon Elastic Kubernetes Service (EKS)上构建生产级的高可用Nacos架构。

架构概述

我们的Amazon EKS高可用Nacos架构包括:

  • 多可用区EKS集群:抵御可用区故障
  • 3节点以上的Nacos集群:使用StatefulSet部署确保数据一致性
  • Amazon RDS MySQL/PostgreSQL:持久化配置存储
  • Amazon EFS:跨Pod的共享文件存储
  • 应用负载均衡器(ALB):提供健康检查的外部访问
  • 网络负载均衡器(NLB):内部服务通信
  • Prometheus和Grafana:全面监控

前置条件

开始之前,请确保您具备:

  • 配置了适当权限的AWS CLI
  • 已安装并配置kubectl
  • 用于EKS集群管理的eksctl
  • Helm 3.x用于Kubernetes包管理
  • 基本的Kubernetes概念理解
  • 具有必要IAM权限的AWS账户

设置EKS集群

1. 创建多可用区EKS集群

首先,创建一个跨多个可用区分布节点的生产级EKS集群:

# eks-cluster-config.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: nacos-production
  region: us-west-2
  version: "1.28"

availabilityZones:
  - us-west-2a
  - us-west-2b
  - us-west-2c

nodeGroups:
  - name: nacos-nodes
    instanceType: m5.xlarge
    desiredCapacity: 6
    minSize: 3
    maxSize: 9
    privateNetworking: true
    availabilityZones:
      - us-west-2a
      - us-west-2b
      - us-west-2c
    labels:
      workload: nacos
    tags:
      Environment: production
      Application: nacos
    iam:
      withAddonPolicies:
        ebs: true
        efs: true
        albIngress: true

部署集群:

eksctl create cluster -f eks-cluster-config.yaml

2. 安装必要的附加组件

安装AWS负载均衡控制器以支持ALB/NLB:

# 安装cert-manager(前提条件)
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml

# 安装AWS负载均衡控制器
helm repo add eks https://aws.github.io/eks-charts
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=nacos-production \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

为Nacos设置Amazon RDS

Nacos需要持久化数据库来存储配置。我们将使用Amazon RDS实现高可用:

1. 创建RDS MySQL实例

aws rds create-db-instance \
  --db-instance-identifier nacos-mysql \
  --db-instance-class db.r5.xlarge \
  --engine mysql \
  --engine-version 8.0.35 \
  --master-username nacosadmin \
  --master-user-password <安全密码> \
  --allocated-storage 100 \
  --storage-type gp3 \
  --storage-encrypted \
  --multi-az \
  --backup-retention-period 7 \
  --preferred-backup-window "03:00-04:00" \
  --preferred-maintenance-window "sun:04:00-sun:05:00" \
  --vpc-security-group-ids sg-xxxxxx \
  --db-subnet-group-name nacos-subnet-group

2. 初始化Nacos数据库架构

连接到RDS实例并创建Nacos数据库:

CREATE DATABASE nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'nacos'@'%' IDENTIFIED BY '安全密码';
GRANT ALL PRIVILEGES ON nacos_config.* TO 'nacos'@'%';
FLUSH PRIVILEGES;

执行Nacos架构初始化脚本(从Nacos GitHub仓库下载):

mysql -h nacos-mysql.xxxxx.rds.amazonaws.com -u nacos -p nacos_config < nacos-mysql.sql

设置Amazon EFS共享存储

创建EFS文件系统用于Nacos Pod之间的共享存储:

# 创建EFS文件系统
aws efs create-file-system \
  --creation-token nacos-efs \
  --performance-mode generalPurpose \
  --throughput-mode bursting \
  --encrypted \
  --tags "Key=Name,Value=nacos-efs" "Key=Environment,Value=production"

# 在每个可用区创建挂载目标
for subnet in subnet-xxxxx subnet-yyyyy subnet-zzzzz; do
  aws efs create-mount-target \
    --file-system-id fs-xxxxxx \
    --subnet-id $subnet \
    --security-groups sg-xxxxxx
done

安装EFS CSI驱动:

kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.5"

创建StorageClass和PersistentVolume:

# efs-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-xxxxxx
  directoryPerms: "700"

在EKS上部署Nacos

1. 创建Nacos命名空间和ConfigMap

# nacos-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: nacos
  labels:
    name: nacos
---
# nacos-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-config
  namespace: nacos
data:
  mysql.host: "nacos-mysql.xxxxx.rds.amazonaws.com"
  mysql.port: "3306"
  mysql.db: "nacos_config"
  mysql.user: "nacos"
  nacos.core.auth.enabled: "true"
  nacos.core.auth.server.identity.key: "nacosSecretKey"
  nacos.core.auth.server.identity.value: "nacosSecretValue"
  nacos.core.auth.plugin.nacos.token.secret.key: "SecretKey012345678901234567890123456789012345678901234567890123456789"

2. 创建Nacos StatefulSet

# nacos-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
  namespace: nacos
spec:
  serviceName: nacos-headless
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: nacos
  template:
    metadata:
      labels:
        app: nacos
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8848"
        prometheus.io/path: "/nacos/actuator/prometheus"
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nacos
            topologyKey: "topology.kubernetes.io/zone"
      initContainers:
      - name: peer-finder-plugin-install
        image: nacos/nacos-peer-finder-plugin:1.1
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /home/nacos/plugins/peer-finder
          name: data
          subPath: peer-finder
      containers:
      - name: nacos
        image: nacos/nacos-server:v2.3.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8848
          name: client-port
        - containerPort: 9848
          name: client-rpc
        - containerPort: 9849
          name: raft-rpc
        - containerPort: 7848
          name: old-raft-rpc
        env:
        - name: NACOS_REPLICAS
          value: "3"
        - name: SERVICE_NAME
          value: "nacos-headless"
        - name: DOMAIN_NAME
          value: "cluster.local"
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        - name: MYSQL_SERVICE_HOST
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: mysql.host
        - name: MYSQL_SERVICE_PORT
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: mysql.port
        - name: MYSQL_SERVICE_DB_NAME
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: mysql.db
        - name: MYSQL_SERVICE_USER
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: mysql.user
        - name: MYSQL_SERVICE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: nacos-mysql-secret
              key: password
        - name: MODE
          value: "cluster"
        - name: NACOS_SERVER_PORT
          value: "8848"
        - name: PREFER_HOST_MODE
          value: "hostname"
        - name: NACOS_SERVERS
          value: "nacos-0.nacos-headless.nacos.svc.cluster.local:8848 nacos-1.nacos-headless.nacos.svc.cluster.local:8848 nacos-2.nacos-headless.nacos.svc.cluster.local:8848"
        - name: SPRING_DATASOURCE_PLATFORM
          value: "mysql"
        - name: NACOS_AUTH_ENABLE
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: nacos.core.auth.enabled
        - name: NACOS_AUTH_TOKEN_SECRET_KEY
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: nacos.core.auth.plugin.nacos.token.secret.key
        - name: NACOS_AUTH_IDENTITY_KEY
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: nacos.core.auth.server.identity.key
        - name: NACOS_AUTH_IDENTITY_VALUE
          valueFrom:
            configMapKeyRef:
              name: nacos-config
              key: nacos.core.auth.server.identity.value
        - name: JVM_XMS
          value: "2g"
        - name: JVM_XMX
          value: "2g"
        - name: JVM_XMN
          value: "1g"
        - name: JVM_MS
          value: "128m"
        - name: JVM_MMS
          value: "256m"
        resources:
          requests:
            cpu: "1000m"
            memory: "2Gi"
          limits:
            cpu: "2000m"
            memory: "4Gi"
        livenessProbe:
          httpGet:
            path: /nacos/v1/console/health/liveness
            port: client-port
            scheme: HTTP
          initialDelaySeconds: 180
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /nacos/v1/console/health/readiness
            port: client-port
            scheme: HTTP
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        volumeMounts:
        - name: data
          mountPath: /home/nacos/plugins/peer-finder
          subPath: peer-finder
        - name: data
          mountPath: /home/nacos/data
          subPath: data
        - name: data
          mountPath: /home/nacos/logs
          subPath: logs
  volumeClaimTemplates:
  - metadata:
      name: data
      namespace: nacos
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "gp3"
      resources:
        requests:
          storage: 20Gi

3. 为Nacos创建服务

# nacos-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nacos-headless
  namespace: nacos
  labels:
    app: nacos
  annotations:
    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
  - port: 8848
    name: server
    targetPort: 8848
  - port: 9848
    name: client-rpc
    targetPort: 9848
  - port: 9849
    name: raft-rpc
    targetPort: 9849
  - port: 7848
    name: old-raft-rpc
    targetPort: 7848
  selector:
    app: nacos
---
apiVersion: v1
kind: Service
metadata:
  name: nacos-service
  namespace: nacos
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  type: LoadBalancer
  ports:
  - port: 8848
    name: server
    targetPort: 8848
  - port: 9848
    name: client-rpc
    targetPort: 9848
  - port: 9849
    name: raft-rpc
    targetPort: 9849
  selector:
    app: nacos

4. 配置外部访问的Ingress

# nacos-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nacos-ingress
  namespace: nacos
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxxx:certificate/xxxxx
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    alb.ingress.kubernetes.io/healthcheck-path: /nacos/v1/console/health/liveness
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '30'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '3'
spec:
  rules:
  - host: nacos.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nacos-service
            port:
              number: 8848

高级配置

1. 启用认证和授权

配置Nacos认证以保护您的部署:

# nacos-auth-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-auth-config
  namespace: nacos
data:
  custom.properties: |
    nacos.core.auth.enabled=true
    nacos.core.auth.caching.enabled=true
    nacos.core.auth.enable.userAgentAuthWhite=false
    nacos.core.auth.server.identity.key=nacosKey
    nacos.core.auth.server.identity.value=nacosValue
    nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
    nacos.core.auth.plugin.nacos.token.expire.seconds=18000
    nacos.istio.mcp.server.enabled=false

2. 配置资源限制和自动扩缩容

实施水平Pod自动扩缩容器进行动态扩展:

# nacos-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nacos-hpa
  namespace: nacos
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: StatefulSet
    name: nacos
  minReplicas: 3
  maxReplicas: 9
  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: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
      - type: Pods
        value: 2
        periodSeconds: 60
      selectPolicy: Max

3. 实施网络策略

使用Kubernetes NetworkPolicies保护网络通信:

# nacos-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: nacos-network-policy
  namespace: nacos
spec:
  podSelector:
    matchLabels:
      app: nacos
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: microservices
    - podSelector:
        matchLabels:
          app: nacos
    ports:
    - protocol: TCP
      port: 8848
    - protocol: TCP
      port: 9848
    - protocol: TCP
      port: 9849
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: nacos
    ports:
    - protocol: TCP
      port: 8848
    - protocol: TCP
      port: 9848
    - protocol: TCP
      port: 9849
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 3306  # MySQL
    - protocol: TCP
      port: 53    # DNS
    - protocol: UDP
      port: 53    # DNS

监控和可观测性

1. 部署Prometheus和Grafana

# prometheus-values.yaml
prometheus:
  prometheusSpec:
    serviceMonitorSelectorNilUsesHelmValues: false
    additionalScrapeConfigs:
    - job_name: 'nacos'
      kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
          - nacos
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__

使用Helm安装:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
  -n monitoring \
  --create-namespace \
  -f prometheus-values.yaml

2. 创建Grafana仪表板

导入Nacos监控仪表板(Dashboard ID: 13224)并配置数据源:

{
  "dashboard": {
    "title": "Nacos集群监控",
    "panels": [
      {
        "title": "服务注册数量",
        "targets": [
          {
            "expr": "nacos_monitor_service_count"
          }
        ]
      },
      {
        "title": "配置数量",
        "targets": [
          {
            "expr": "nacos_monitor_config_count"
          }
        ]
      },
      {
        "title": "HTTP请求速率",
        "targets": [
          {
            "expr": "rate(http_server_requests_seconds_count[5m])"
          }
        ]
      },
      {
        "title": "JVM内存使用",
        "targets": [
          {
            "expr": "jvm_memory_used_bytes{area=\"heap\"}"
          }
        ]
      }
    ]
  }
}

3. 配置CloudWatch Container Insights

为EKS集群监控启用Container Insights:

# 安装CloudWatch代理
curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluentd-quickstart.yaml | \
  sed "s/{{cluster_name}}/nacos-production/" | \
  kubectl apply -f -

灾难恢复和备份

1. 自动化数据库备份

配置RDS自动备份和时间点恢复:

aws rds modify-db-instance \
  --db-instance-identifier nacos-mysql \
  --backup-retention-period 30 \
  --backup-window "03:00-04:00" \
  --preferred-maintenance-window "sun:04:00-sun:05:00" \
  --apply-immediately

2. 实施Velero进行Kubernetes备份

安装Velero进行集群状态备份:

# 安装Velero
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.6.0 \
  --bucket nacos-velero-backup \
  --backup-location-config region=us-west-2 \
  --snapshot-location-config region=us-west-2 \
  --secret-file ./credentials-velero

# 创建备份计划
velero schedule create nacos-daily \
  --schedule="0 2 * * *" \
  --include-namespaces nacos \
  --ttl 720h

3. 跨区域复制

设置跨区域复制以实现灾难恢复:

# dr-replication.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nacos-dr-replication
  namespace: nacos
spec:
  schedule: "0 */6 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: replication
            image: amazon/aws-cli:latest
            command:
            - /bin/sh
            - -c
            - |
              # 创建RDS快照
              aws rds create-db-snapshot \
                --db-instance-identifier nacos-mysql \
                --db-snapshot-identifier nacos-mysql-$(date +%Y%m%d%H%M%S)

              # 复制快照到灾难恢复区域
              aws rds copy-db-snapshot \
                --source-db-snapshot-identifier nacos-mysql-latest \
                --target-db-snapshot-identifier nacos-mysql-dr-latest \
                --source-region us-west-2 \
                --target-region us-east-1
          restartPolicy: OnFailure

性能优化

1. JVM调优

优化JVM参数以获得更好的性能:

env:
- name: JAVA_OPTS
  value: >-
    -Xms2g -Xmx2g -Xmn1g
    -XX:+UseG1GC
    -XX:MaxGCPauseMillis=200
    -XX:+ParallelRefProcEnabled
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=/home/nacos/logs/heap_dump.hprof
    -XX:+PrintGCDetails
    -XX:+PrintGCDateStamps
    -XX:+PrintGCTimeStamps
    -Xloggc:/home/nacos/logs/gc.log
    -Dnacos.use.cloud.namespace.parsing=true
    -Dnacos.use.endpoint.parsing.rule=true

2. 连接池优化

配置数据库连接池设置:

db.num=1
db.url.0=jdbc:mysql://nacos-mysql.xxxxx.rds.amazonaws.com:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=true
db.pool.config.connectionTimeout=30000
db.pool.config.validationTimeout=10000
db.pool.config.maximumPoolSize=20
db.pool.config.minimumIdle=5

3. 缓存配置

启用并配置缓存层:

# nacos-cache-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-cache-config
  namespace: nacos
data:
  application.properties: |
    # 启用配置缓存
    nacos.config.cache.enabled=true
    nacos.config.cache.size=10000
    nacos.config.cache.ttl=3600

    # 启用命名缓存
    nacos.naming.cache.enabled=true
    nacos.naming.cache.size=20000
    nacos.naming.cache.ttl=1800

    # 启用认证缓存
    nacos.core.auth.caching.enabled=true
    nacos.core.auth.caching.ttl=3600

安全最佳实践

1. 启用TLS/SSL

为所有Nacos通信配置TLS:

# nacos-tls-config.yaml
apiVersion: v1
kind: Secret
metadata:
  name: nacos-tls
  namespace: nacos
type: kubernetes.io/tls
data:
  tls.crt: <base64编码的证书>
  tls.key: <base64编码的密钥>
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-tls-config
  namespace: nacos
data:
  application.properties: |
    server.ssl.enabled=true
    server.ssl.key-store=/home/nacos/cert/keystore.jks
    server.ssl.key-store-password=changeit
    server.ssl.key-store-type=JKS
    server.ssl.key-alias=nacos

2. 实施RBAC

为Nacos服务账户配置Kubernetes RBAC:

# nacos-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nacos-sa
  namespace: nacos
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nacos-role
  namespace: nacos
rules:
- apiGroups: [""]
  resources: ["pods", "services", "endpoints"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: nacos-rolebinding
  namespace: nacos
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nacos-role
subjects:
- kind: ServiceAccount
  name: nacos-sa
  namespace: nacos

3. 密钥管理

使用AWS Secrets Manager管理敏感数据:

# external-secrets-config.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: nacos-mysql-secret
  namespace: nacos
spec:
  secretStoreRef:
    name: aws-secrets-manager
    kind: SecretStore
  target:
    name: nacos-mysql-secret
    creationPolicy: Owner
  data:
  - secretKey: password
    remoteRef:
      key: nacos/mysql
      property: password

故障排除指南

常见问题和解决方案

1. Pod停留在Pending状态

# 检查Pod事件
kubectl describe pod nacos-0 -n nacos

# 检查PVC状态
kubectl get pvc -n nacos

# 检查节点资源
kubectl top nodes

2. 集群脑裂场景

# 检查集群成员
kubectl exec -it nacos-0 -n nacos -- curl -X GET "http://localhost:8848/nacos/v1/core/cluster/nodes"

# 强制重新选举
kubectl delete pod nacos-1 -n nacos

3. 数据库连接问题

# 测试数据库连接
kubectl run mysql-test --image=mysql:8.0 --rm -it --restart=Never -- \
  mysql -h nacos-mysql.xxxxx.rds.amazonaws.com -u nacos -p

# 检查安全组
aws ec2 describe-security-groups --group-ids sg-xxxxx

性能诊断

# 生成堆转储
kubectl exec -it nacos-0 -n nacos -- jmap -dump:format=b,file=/tmp/heap.hprof 1

# 检查GC日志
kubectl exec -it nacos-0 -n nacos -- tail -n 100 /home/nacos/logs/gc.log

# 监控CPU和内存
kubectl top pod -n nacos --containers

成本优化

1. 合理调整实例大小

监控实际资源使用并调整:

# 分析资源利用率
kubectl top pod -n nacos --containers --sum=true

# 推荐实例类型
aws ec2 describe-instance-type-offerings \
  --filters "Name=instance-type,Values=m5.*" \
  --query "InstanceTypeOfferings[*].[InstanceType,Location]" \
  --output table

2. 非生产环境使用Spot实例

为开发环境配置Spot实例:

nodeGroups:
  - name: nacos-spot-nodes
    instancesDistribution:
      instanceTypes:
        - m5.xlarge
        - m5a.xlarge
      onDemandPercentageAboveBaseCapacity: 0
      spotAllocationStrategy: "capacity-optimized"

3. 实施成本分配标签

tags:
  Environment: production
  Application: nacos
  CostCenter: platform-team
  Owner: devops@company.com

从自管理迁移到EKS

分步迁移过程

  1. 从现有Nacos导出数据
# 导出配置
curl -X GET "http://old-nacos:8848/nacos/v1/cs/configs/export?group=DEFAULT_GROUP" > config-backup.zip

# 导出服务注册表
curl -X GET "http://old-nacos:8848/nacos/v1/ns/service/list" > service-backup.json
  1. 数据库迁移
# 创建数据库转储
mysqldump -h old-mysql-host -u nacos -p nacos_config > nacos_backup.sql

# 导入到RDS
mysql -h nacos-mysql.xxxxx.rds.amazonaws.com -u nacos -p nacos_config < nacos_backup.sql
  1. 渐进式流量迁移
# 在ALB中使用加权目标组
alb.ingress.kubernetes.io/target-group-attributes: |
  stickiness.enabled=true,
  stickiness.lb_cookie.duration_seconds=86400,
  deregistration_delay.timeout_seconds=300

总结

在Amazon EKS上构建生产级高可用Nacos架构需要仔细规划和实施各种组件。本指南涵盖了:

  • 多可用区EKS集群设置以实现高可用性
  • 与Amazon RDS集成进行持久化存储
  • 实施安全最佳实践
  • 全面的监控和可观测性
  • 灾难恢复和备份策略
  • 性能优化技术
  • 成本优化方法

通过遵循本指南,您将拥有一个强大、可扩展和高可用的Nacos部署,可以作为AWS上微服务架构的支柱。请记住根据不断变化的需求和AWS服务更新定期审查和更新您的配置。

其他资源


本文代表了在Amazon EKS上部署Nacos的生产测试配置和最佳实践。在部署到生产环境之前,请务必在您的特定环境中进行充分测试。

常见问题解答

什么是 AWS Savings Plans?

AWS Savings Plans 是一种灵活的定价模型,通过承诺一定的计算使用量(以美元/小时计),可以获得高达 72% 的折扣。它比 Reserved Instances 更加灵活,可以跨实例类型、操作系统和区域使用。

Savings Plans 和 Reserved Instances 有什么区别?

主要区别在于灵活性:Savings Plans 按照承诺的支出金额计费,可以跨实例族和区域使用;而 Reserved Instances 绑定特定的实例类型。SP 更适合变化的工作负载,RI 适合稳定的工作负载。

如何计算 Savings Plans 的投资回报率?

ROI = (节省金额 - 承诺成本) / 承诺成本 × 100%。通常,如果您的基线使用率超过 60%,Savings Plans 就能带来正向回报。建议使用 AWS Cost Explorer 的推荐功能进行精确计算。

购买 Savings Plans 有风险吗?

主要风险包括:过度承诺导致浪费、业务缩减导致无法使用、技术架构变更(如迁移到 Serverless)。建议从保守的承诺开始,逐步增加覆盖率。

如何监控 Savings Plans 的使用情况?

可以通过 AWS Cost Explorer 查看覆盖率和利用率报告,设置 CloudWatch 告警监控利用率低于阈值的情况,并定期(建议每月)审查和调整策略。

Online