Kubernetes에 Nacos 클러스터 배포하기

필수 구성 요건 및 실행 환경

Nacos를 쿠버네티스(Kubernetes) 클러스터에 안정적으로 배포하려면 다음 두 가지 핵심 요소가 필요합니다:

  • 외부 MySQL 데이터베이스: 버전 5.7 이상 권장
  • ReadWriteMany (RWX) 지원 스토리지 클래스: NAS 기반 스토리지 사용 필수

지원하는 플랫폼 정보

환경버전/설정
클러스터 관리阿里云 ACK (Alibaba Cloud Container Service)
Kubernetes 버전1.24
Nacos 이미지nacos/nacos-server:v2.2.3
네임스페이스default (사용자 정의 가능)

MySQL 데이터베이스 초기화 절차

Nacos 운영을 위한 메타데이터 저장소를 설정합니다. 공식 GitHub 저장소에서 제공하는 스키마 파일을 활용합니다.

wget https://raw.githubusercontent.com/alibaba/nacos/develop/distribution/conf/mysql-schema.sql

# MySQL CLI 접속 후 아래 명령어 실행
mysql -u root -p

CREATE DATABASE IF NOT EXISTS nacos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE nacos;
SOURCE /root/mysql-schema.sql;

CREATE USER 'nacos'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON nacos.* TO 'nacos'@'%';
FLUSH PRIVILEGES;
EXIT;

쿠버네티스 ConfigMap을 통한 DB 연결 정보 등록

외부 MySQL 인스턴스 접속 정보를 구성 객체로 관리합니다. 민감 정보는 추후 Secret으로 전환 권장.

apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-config
  namespace: default
data:
  mysql.host: "your-rds-endpoint.mysql.rds.aliyuncs.com"
  mysql.db.name: "nacos"
  mysql.port: "3306"
  mysql.user: "nacos"
  mysql.password: "your_secure_password"

Headless 서비스 리소스 생성

StatefulSet 내 Pod 간 직접 통신을 위해 `clusterIP: None` 설정이 필수입니다. Nacos 2.x 버전은 gRPC 기반 통신을 위해 별도 포트를 사용합니다.

apiVersion: v1
kind: Service
metadata:
  name: nacos-headless-svc
  namespace: default
  labels:
    app: nacos-cluster
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  selector:
    app: nacos-cluster
  ports:
    - name: http-api
      port: 8848
      targetPort: 8848
    - name: grpc-client
      port: 9848
      targetPort: 9848
    - name: raft-internal
      port: 9849
      targetPort: 9849
    - name: legacy-raft
      port: 7848
      targetPort: 7848

StatefulSet 기반 클러스터 배포

영구적 식별자와 스토리지 유지가 필요한 Nacos 노드에 적합한 워크로드 유형입니다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos-node
  namespace: default
spec:
  serviceName: nacos-headless-svc
  replicas: 3
  podManagementPolicy: Parallel
  selector:
    matchLabels:
      app: nacos-cluster
  template:
    metadata:
      labels:
        app: nacos-cluster
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8848"
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - nacos-cluster
              topologyKey: kubernetes.io/hostname
      initContainers:
        - name: install-peer-plugin
          image: nacos/nacos-peer-finder-plugin:1.1
          volumeMounts:
            - name: storage-volume
              mountPath: /home/nacos/plugins/peer-finder
              subPath: peer-finder
      containers:
        - name: server
          image: nacos/nacos-server:v2.2.3
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8848
              name: api
            - containerPort: 9848
              name: rpc
            - containerPort: 9849
              name: raft
          env:
            - name: NACOS_REPLICAS
              value: "3"
            - name: SERVICE_NAME
              value: "nacos-headless-svc"
            - name: DOMAIN_NAME
              value: "cluster.local"
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: MYSQL_SERVICE_HOST
              valueFrom:
                configMapKeyRef:
                  name: nacos-config
                  key: mysql.host
            - name: MYSQL_SERVICE_DB_NAME
              valueFrom:
                configMapKeyRef:
                  name: nacos-config
                  key: mysql.db.name
            - name: MYSQL_SERVICE_PORT
              valueFrom:
                configMapKeyRef:
                  name: nacos-config
                  key: mysql.port
            - name: MYSQL_SERVICE_USER
              valueFrom:
                configMapKeyRef:
                  name: nacos-config
                  key: mysql.user
            - name: MYSQL_SERVICE_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: nacos-config
                  key: mysql.password
            - name: SPRING_DATASOURCE_PLATFORM
              value: "mysql"
            - name: NACOS_SERVER_PORT
              value: "8848"
            - name: PREFER_HOST_MODE
              value: "hostname"
            - name: NACOS_AUTH_ENABLE
              value: "true"
            - name: NACOS_AUTH_IDENTITY_KEY
              value: "nacosAuthKey"
            - name: NACOS_AUTH_IDENTITY_VALUE
              value: "nacosSecurtyValue"
            - name: NACOS_AUTH_TOKEN
              value: "SecretKey012345678901234567890123456789012345678901234567890123456789"
            - name: NACOS_AUTH_TOKEN_EXPIRE_SECONDS
              value: "18000"
          volumeMounts:
            - name: storage-volume
              mountPath: /home/nacos/data
              subPath: data
            - name: storage-volume
              mountPath: /home/nacos/logs
              subPath: logs
            - name: storage-volume
              mountPath: /home/nacos/plugins/peer-finder
              subPath: peer-finder
          resources:
            requests:
              memory: 2Gi
              cpu: 500m
      volumes: []
  volumeClaimTemplates:
    - metadata:
        name: storage-volume
        annotations:
          volume.beta.kubernetes.io/storage-class: alicloud-disk-nas
      spec:
        accessModes: [ ReadWriteMany ]
        resources:
          requests:
            storage: 20Gi

클러스터 구성 상태 확인 방법

모든 인스턴스가 동일한 클러스터 멤버십 정보를 공유하고 있는지 검증합니다.

for idx in 0 1 2; do
  echo "=== nacos-node-$idx 클러스터 구성 ==="
  kubectl exec nacos-node-$idx -c server -- cat conf/cluster.conf
done

외부 접근을 위한 Ingress 설정

HTTPS 기반 외부 엔드포인트를 제공하여 UI 및 API 접근을 활성화합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nacos-ui
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  tls:
    - hosts:
        - nacos.example.com
      secretName: example-com-tls-secret
  rules:
    - host: nacos.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nacos-headless-svc
                port:
                  number: 8848

태그: kubernetes nacos MySQL statefulset ingress

5월 22일 09:57에 게시됨