Apollo 配置中心的部署與使用經驗

前言

Apollo(阿波羅)是攜程開源的分佈式配置管理中心。

本文主要介紹其基於 Docker-Compose 的部署安裝和一些使用的經驗

特點

  • 成熟,穩定
  • 支持管理多環境/多集羣/多命名空間的配置
  • 配置修改發佈實時(1s)通知到應用程序
  • 支持權限控制、配置繼承,版本管理,灰度發佈,使用監控等
  • 官方提供了 。NET/Java/Go 的 SDK 以及 Http 接口
  • 國產中文,文檔友好,大廠背書,使用方案成熟
  • 使用簡單,支持 Docker , K8S,官方也提供多種高可用方案參考

使用情況

  • 目前在微服務項目中做爲配置中心,表現穩定,體驗良好
  • 內存情況:新安裝啓動在 100M 左右,工作中實際 20 項目,80 客戶端使用時,三個服務佔 1.5G 左右
  • 測試環境和生產環境分開,安全及避免錯誤操作
  • 爲什麼選擇 Apollo:穩定&簡單,雖然比不上 Nacos 的性能,也沒有服務發現功能,但是穩定啊!!!
  • 在我自己部署前,會覺得這個東西好難,好重,好麻煩。寫這篇文章的時候的感受只有兩個字:牛*

實踐

準備

  • 當前版本:v2.1

  • apollo-db:mysql 5.6.6+ 數據庫

    • 默認端口:3306
    • 依賴兩個數據庫:ApolloPortalDB,ApolloConfigDB
    • 默認賬號/密碼:apollo/admin
  • apollo-configservice:Config Service 提供配置的讀取、推送等功能。

    • 默認端口:8080
    • 應用程序端連接到此服務使用
  • apollo-adminservice: Admin Service 提供配置的修改、發佈等功能

    • 默認端口:8090
    • 管理界面使用此服務
  • apollo-portal:Portal 提供 Web 界面用來管理配置

    • 默認端口:8070
    • Web 管理界面
    • 默認賬號/密碼:apollo/admin
  • Deureka:提供服務註冊和發現

    • Config Service 和 Admin Service 會向 Eureka 註冊服務,並保持心跳
    • 在 Admin Service 需要指定 eureka.service.url
  • 服務配置方式的優先級從高到低分別爲:系統參數>環境變量>外部配置文件

使用 Docker Compose 安裝

本篇文章基於 Docker V24 及 Docker Compose V2,安裝可以參考之前的文章

配置說明

  • 掛載了日誌文件到。/logs 目錄
  • 固定了鏡像版本 mysql v5.7 , apollo v2.1.0
  • 指定 MySql 賬號密碼: root devops666 ,修改了端口映射 13306:3306
  • 掛載 MySql 數據,初始化腳本文件夾 。/initsql(v2.1 腳本
  • Apollo 服務中使用服務名 apollo-db 連接 MySql:SPRING_DATASOURCE_URL:'...apollo-db:3306/...'
  • 設置先啓動數據庫:depends_on:apollo-db
  • apollo-configservice 服務中指定向 Deureka(Apollo 服務發現組件)註冊的地址:http://192.168.123.214:8080
  • apollo-adminservice 服務中指定向 Deureka 註冊的服務地址:http://192.168.123.214:809
  • apollo-adminservice 服務需指定 Deureka 服務地址-Deureka.service.url=``http://192.168.123.214:8080/eureka/
  • 指定網絡:devopsnetwork (docker network create devopsnetwork)
  • web 管理端默認賬號密碼:apollo admin,登錄後修改!!!

配置文件 compose.yml

  • 準備好 compose.yml 及 。/initsql/初始化腳本,修改其中的 IP

  • 拷貝到服務器

  • 然後運行docker compose up -d即可

     version: '3.1'
     services:
       # Apollo數據庫
       apollo-db:
         image: mysql:5.7
         container_name: apollo_db_5_7
         restart: always
         environment:
           TZ: Asia/Shanghai
           MYSQL_ROOT_PASSWORD: 'devops666'
         ports:
           - "13306:3306"
         volumes:
           - ./initsql:/docker-entrypoint-initdb.d
           - ./data:/var/lib/mysql
         networks:
           - devopsnetwork
    
       # Apollo 服務發現註冊中心
       apollo-configservice:
         container_name: apollo_configservice_2_1
         image: apolloconfig/apollo-configservice:2.1.0
         restart: always
         depends_on:
           - apollo-db
         environment:
           SPRING_DATASOURCE_URL: 'jdbc:mysql://apollo-db:3306/ApolloConfigDB?characterEncoding=utf8'
           SPRING_DATASOURCE_USERNAME: 'root'
           SPRING_DATASOURCE_PASSWORD: 'devops666'
           JAVA_OPTS: "-Deureka.instance.homePageUrl=http://192.168.123.214:8080"
           # EUREKA_INSTANCE_HOME_PAGE_URL: http://192.168.123.214:8080
           # EUREKA_INSTANCE_PREFER_IP_ADDRESS: false
         volumes:
           - ./logs:/opt/logs
         ports:
           - "8080:8080"
         networks:
           - devopsnetwork
    
       #核心接口服務
       apollo-adminservice:
         container_name: apollo_adminservice_2_1
         image: apolloconfig/apollo-adminservice:2.1.0
         restart: always
         environment:
           SPRING_DATASOURCE_URL: 'jdbc:mysql://apollo-db:3306/ApolloConfigDB?characterEncoding=utf8'
           SPRING_DATASOURCE_USERNAME: 'root' 
           SPRING_DATASOURCE_PASSWORD: 'devops666'
           JAVA_OPTS: "-Deureka.instance.homePageUrl=http://192.168.123.214:8090 -Deureka.service.url=http://192.168.123.214:8080/eureka/ "
         depends_on:
           - apollo-db
         ports:
           - "8090:8090"
         volumes:
           - ./logs/:/opt/logs      
         networks:
           - devopsnetwork
           
      
       apollo-portal:
         image: apolloconfig/apollo-portal:2.1.0
         container_name: apollo_portal_2_1
         restart: always
         environment:
           SPRING_DATASOURCE_URL: 'jdbc:mysql://apollo-db:3306/ApolloPortalDB?characterEncoding=utf8'
           SPRING_DATASOURCE_USERNAME: 'root'
           SPRING_DATASOURCE_PASSWORD: 'devops666'
           APOLLO_PORTAL_ENVS: 'dev'      
           DEV_META: 'http://192.168.123.214:8080'
           # 默認賬號 apollo admin
         depends_on:
           - apollo-db
         ports:
           - "8070:8070"
         volumes:
           - ./logs/:/opt/logs         
         networks:
           - devopsnetwork
    
     networks:
       devopsnetwork:
         external: true
     ```
    
    

部署成功

部署機器IP:192.168.123.214

使用 K8S 安裝

跟着官方文檔一步步來即可,helm 的文件可以從 apolloconfig/apollo-helm-chart 獲取,這裏只分享下步驟和些注意的地方

  1. 初始化數據庫

    1. 可以使用已有或者部署 mysql 服務,並創建 apollo 專門的賬號密碼
    2. 執行 Apollo 對應版本的 v2.1 默認初始化腳本 創建 ApolloConfigDB,ApolloPortalDB
    3. 生產環境 記得修改 ServerConfig 表的 環境和組織apollo.portal.envs:pro organizations:[{"orgId":"xxx","orgName":"xxx公司"}]
  2. 使用 helm 添加 apollo repo

  3. 安裝 apollo-service

  4. 安裝 apollo-portal

  5. k8s 使用

    • 可以將 Apollo 相關配置存儲到 k8s 的 ConfigMap 中方便 k8s 服務中使用

使用

.NET SDK

官方:Com.Ctrip.Framework.Apollo.Configuration

  1. 添加包:Com.Ctrip.Framework.Apollo.Configuration

  2. appsetting.json 中添加 apollo 配置

    1. MetaServer:Apollo 服務地址,系統信息中也可以查看到
    2. AppId:應用 Id
    3. Namespaces:命名空間默認是 application
  3. 獲取參數註冊:可以是配置,也可以是從環境變量中

    builder.Configuration.AddApollo(builder.Configuration.GetSection("apollo"));

  4. 注入 IConfiguration 使用即可

連接配置

  "apollo": {
    "MetaServer": "http://192.168.123.214:8080",
    "AppId": "devops.test",
    "Namespaces": [ "application" ]
  }

Demo 示例

dotnet v7.0

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddApollo(builder.Configuration.GetSection("apollo"));
app.MapGet("/config", context =>
{
    context.Response.Headers["Content-Type"] = "text/html; charset=utf-8";
    //配置服務
    var configService = context.RequestServices.GetRequiredService<IConfiguration>();
    string? key = context.Request.Query["key"];
    if (string.IsNullOrWhiteSpace(key))
    {
        return context.Response.WriteAsync("獲取配置:/config?key=test");
    }
    var value = configService[key];
    return context.Response.WriteAsync(value ?? "undefined");
});

完整 Demo 示例 :Github 地址

踩過的坑

  • 數據庫配置連接,使用服務名,而不是容器名
  • -Deureka.instance.homePageUrl 和 -Deureka.service.url 參數一開始沒有理解到是做什麼的,只知道配置健康檢查失敗,看了文檔才理解到是 Deureka.instance.homePageUrl 是註冊的服務地址,-Deureka.service.url 是註冊中心的接口地址

相關文檔

後語

時間充裕的情況最好是過一遍文檔,知道是怎麼設計的,遇到問題真會一頭霧水。

每天進步一點,哪怕只是一點!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章