写在最前

Apollo 是携程开源的配置管理平台,帮助分布式应用轻松管理配置。它能实时推送配置更新,还支持版本回滚、灰度发布和多环境设置,让配置变更更安全、更灵活,适合多团队协作的场景。

1. 前置要求

1.1 配置 eureak

导入两个SQL后进入 ApolloConfigDBServerConfig 表,将 eureka.service.url 的服务名称修改为域名或 IP 地址。

图片-vyxm.png
# 域名方式
http://apollo-dev.basic.tanqidi.com:8000/eureka/

# IP方式
http://172.31.0.100:8000/eureka/

# 外部eureka集群与密码方式
http://admin:密码@app-eureka1.basic.tanqidi.com:8000/eureka/,http://admin:密码@app-eureka2.basic.tanqidi.com:8000/eureka/,http://admin:密码@app-eureka3.basic.tanqidi.com:8000/eureka/

1.2 配置 envs(多环境)

如果你希望通过一个门户来连接多个环境,这时需要在 ApolloPortalDBServerConfig 表中,将 devuat 用逗号分隔填写,以便实现环境的统一访问。

图片-pupz.png

1.3 配置域名 (可选)

# apollo
address=/apollo-dev.basic.tanqidi.com/172.31.0.100
address=/apollo.dev.tanqidi.com/172.31.0.100

2. docker 部署

2.1 域名方式

# 此篇章就部署2.2.0版本
mkdir -p /log/apollo

# 注意! 8080端口太常见了运行时间请注意检查,我换成8000
docker run -p 8000:8080 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://app-mysql1.basic.tanqidi.com:3306/ApolloConfigDB?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -d -v /log/apollo/:/opt/logs --name apollo-configservice apolloconfig/apollo-configservice:2.2.0

docker run -p 8090:8090 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://app-mysql1.basic.tanqidi.com:3306/ApolloConfigDB?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -d -v /log/apollo/:/opt/logs --name apollo-adminservice apolloconfig/apollo-adminservice:2.2.0

# 前端域名就配为 apollo.dev.tanqidi.com,重点是DEV_META=http://apollo-dev.basic.tanqidi.com:8000
docker run -p 8070:8070 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://app-mysql1.basic.tanqidi.com:3306/ApolloPortalDB?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e APOLLO_PORTAL_ENVS=dev \
    -e DEV_META=http://apollo-dev.basic.tanqidi.com:8000 \
    -d -v /log/apollo:/opt/logs --name apollo-portal apolloconfig/apollo-portal:2.2.0

2.2 ip方式

# apollo-configservice,apollo-adminservice和域名部署方式一样的

# IP方式主要是DEV_META要修改为ip
docker run -p 8070:8070 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloPortalDB?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e DEV_META=http://172.31.0.100:8000 \
    -d -v /log/apollo:/opt/logs --name apollo-portal apolloconfig/apollo-portal:2.2.0

2.3 多环境

在实现多环境合一时,需要在数据库中创建两个独立的实例,分别命名为 ApolloConfigDB_DEVApolloConfigDB_UAT。接着,请进入各自数据库的 ServerConfig 表,将 eureka.service.url 分别修改为 http://172.31.0.100:8000/eureka/http://172.31.0.101:8000/eureka/,确保每个实例的服务能够正确注册和发现。

2.3.1 DEV

# dev, 运行在172.31.0.100
docker run -p 8000:8080 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloConfigDB_DEV?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e EUREKA_INSTANCE_IP_ADDRESS=172.31.0.100 \
    -d -v /log/apollo/:/opt/logs --name apollo-configservice apolloconfig/apollo-configservice:2.2.0

docker run -p 8090:8090 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloConfigDB_DEV?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e EUREKA_INSTANCE_IP_ADDRESS=172.31.0.100 \
    -d -v /log/apollo/:/opt/logs --name apollo-adminservice apolloconfig/apollo-adminservice:2.2.0

2.3.2 UAT

# dev, 运行在172.31.0.101
docker run -p 8000:8080 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloConfigDB_UAT?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e EUREKA_INSTANCE_IP_ADDRESS=172.31.0.101 \
    -d -v /log/apollo/:/opt/logs --name apollo-configservice apolloconfig/apollo-configservice:2.2.0

docker run -p 8090:8090 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloConfigDB_UAT?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e EUREKA_INSTANCE_IP_ADDRESS=172.31.0.101 \
    -d -v /log/apollo/:/opt/logs --name apollo-adminservice apolloconfig/apollo-adminservice:2.2.0

2.3.3 配置 Portal

# 请注意,DEV_META 和 UAT_META 分别对应两个不同的环境 IP 地址,同时门户连接的数据库应为 ApolloPortalDB。
docker run -p 8070:8070 \
    -e SPRING_DATASOURCE_URL="jdbc:mysql://172.31.0.100:3306/ApolloPortalDB?characterEncoding=utf8" \
    -e SPRING_DATASOURCE_USERNAME=apollo \
    -e SPRING_DATASOURCE_PASSWORD=123456 \
    -e APOLLO_PORTAL_ENVS=dev,uat \
    -e DEV_META=http://172.31.0.100:8000 \
    -e UAT_META=http://172.31.0.101:8000 \
    -d -v /log/apollo:/opt/logs --name apollo-portal apolloconfig/apollo-portal:2.2.0

3. kubernetes 部署

3.1 secret

kind: Secret
apiVersion: v1
metadata:
  name: apollo-portal-secret
  namespace: default
  annotations:
    kubesphere.io/creator: admin
data:
  APOLLO_PORTAL_ENVS: cHJvZA==
  PROD_META: aHR0cDovL2Fwb2xsby5ieDo4MDgw
  SPRING_DATASOURCE_PASSWORD: MTIzNDU2
  SPRING_DATASOURCE_URL: >-
    amRiYzpteXNxbDovL3Byb3h5c3FsLmJ4LnN2Yy5jbHVzdGVyLmxvY2FsOjYwMzMvYXBvbGxvcG9ydGFsZGI/Y2hhcmFjdGVyRW5jb2Rpbmc9dXRmOA==
  SPRING_DATASOURCE_USERNAME: YXBvbGxvcG9ydGFsZGI=
type: Opaque
kind: Secret
apiVersion: v1
metadata:
  name: apollo-config-secret
  namespace: default
  annotations:
    kubesphere.io/creator: admin
data:
  SPRING_DATASOURCE_PASSWORD: MTIzNDU2
  SPRING_DATASOURCE_URL: >-
    amRiYzpteXNxbDovL3Byb3h5c3FsLmJ4LnN2Yy5jbHVzdGVyLmxvY2FsOjYwMzMvYXBvbGxvY29uZmlnZGI/Y2hhcmFjdGVyRW5jb2Rpbmc9dXRmOA==
  SPRING_DATASOURCE_USERNAME: YXBvbGxvY29uZmlnZGI=
type: Opaque

3.2 deployment

kind: Deployment
apiVersion: apps/v1
metadata:
  name: apollo
  namespace: default
  labels:
    velero.io/backup-name: bx-schedule-20251124000037
    velero.io/restore-name: bx-schedule-20251124000037-20251124170139
  annotations:
    deployment.kubernetes.io/revision: '47'
    kubesphere.io/creator: admin
    kubesphere.io/description: 'apolloconfig/apollo:2.2.0'
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apollo
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: apollo
      annotations:
        kubesphere.io/creator: admin
        kubesphere.io/imagepullsecrets: '{}'
        kubesphere.io/restartedAt: '2026-01-05T03:23:20.476Z'
    spec:
      volumes:
        - name: apollo-logs
          hostPath:
            path: /log/apollo
            type: DirectoryOrCreate
      containers:
        - name: configservice
          image: >-
            apolloconfig/apollo-configservice:2.2.0
          ports:
            - name: http-0
              containerPort: 8080
              protocol: TCP
          env:
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_PASSWORD
            - name: SPRING_DATASOURCE_URL
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_URL
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_USERNAME
          resources: {}
          volumeMounts:
            - name: apollo-logs
              mountPath: /opt/logs
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 120
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
        - name: portal
          image: 'apolloconfig/apollo-portal:2.2.0'
          ports:
            - name: http-0
              containerPort: 8070
              protocol: TCP
          env:
            - name: APOLLO_PORTAL_ENVS
              valueFrom:
                secretKeyRef:
                  name: apollo-portal-secret
                  key: APOLLO_PORTAL_ENVS
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: apollo-portal-secret
                  key: SPRING_DATASOURCE_PASSWORD
            - name: SPRING_DATASOURCE_URL
              valueFrom:
                secretKeyRef:
                  name: apollo-portal-secret
                  key: SPRING_DATASOURCE_URL
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: apollo-portal-secret
                  key: SPRING_DATASOURCE_USERNAME
            - name: PROD_META
              valueFrom:
                secretKeyRef:
                  name: apollo-portal-secret
                  key: PROD_META
          resources: {}
          volumeMounts:
            - name: apollo-logs
              mountPath: /opt/logs
          livenessProbe:
            httpGet:
              path: /health
              port: 8070
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health
              port: 8070
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health
              port: 8070
              scheme: HTTP
            initialDelaySeconds: 120
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
        - name: adminservice
          image: >-
            apolloconfig/apollo-adminservice:2.2.0
          ports:
            - name: http-0
              containerPort: 8090
              protocol: TCP
          env:
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_PASSWORD
            - name: SPRING_DATASOURCE_URL
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_URL
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: apollo-config-secret
                  key: SPRING_DATASOURCE_USERNAME
          resources: {}
          volumeMounts:
            - name: apollo-logs
              mountPath: /opt/logs
          livenessProbe:
            httpGet:
              path: /health
              port: 8090
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health
              port: 8090
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health
              port: 8090
              scheme: HTTP
            initialDelaySeconds: 120
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      schedulerName: default-scheduler
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

4. Apollo开放平台

有时我们需要在前端或第三方应用中拉取 Apollo 配置,可以在此创建应用并生成 Token。如果不对 App ID 和 Namespace 做限制,则默认可访问所有应用和命名空间的配置。

https://github.com/apolloconfig/apollo/wiki/Apollo%E5%BC%80%E6%94%BE%E5%B9%B3%E5%8F%B0

#!/bin/bash
echo 'window.RPConfig = '`curl -L --request GET \
  --url ${APOLLO_URL}/openapi/v1/envs/${ENV}/apps/${APP_ID}/clusters/default/namespaces/application \
  --header 'Authorization: '${APOLLO_TOKEN} \
  --header 'Cache-Control: no-cache' \
  --header 'Content-Type: application/json'` > /app/web-slb/nginx/html/config.js

5. 试验结果

默认账号密码是apollo:admin

首先创建一个应用后,可以看到已经出现了 devuat 两个环境。接着分别为这两个环境添加不同的title标题值结果完全隔离和正确,接下来只需提供给 Java 程序相应的连接信息就能正常使用了。

图片-ceeg.png
图片-tmft.png
图片-veai.png