运维咖啡吧

享受技术带来的乐趣,体验生活给予的感动

开源|维易CMDB详解之安装部署及常见问题处理

之前介绍过一个灵活多变功能强大的开源CMDB系统,设计精巧,可玩性高,经过一段时间的深度使用,发现了许多可取之处,无论是构建系统内部的资产管理数据库,还是学习它的设计方式都有不少的可取之处,接下来我准备写一系列的文章来系统的介绍一下它,从使用到设计,全面深入了解下

这个系列第一篇就从部署开始,详细介绍下VECMDB的安装、启动、访问以及系统的详细管理方式和常见错误的处理等

安装

在开始之前你只需要准备一台主机,Linux或MacOS系统,只要能安装docker即可。以下操作环境基于CentOS7

安装Docker

1.更新系统包

yum update -y

2.安装必要的依赖

yum install -y yum-utils

3.添加 Docker 的官方存储库

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

4.安装 Docker 引擎

yum install -y docker-ce docker-ce-cli containerd.io

5.启动 Docker 并将其设置为开机启动

systemctl start docker
systemctl enable docker

安装 Docker Compose v2

1.安装 Docker Compose 插件

yum install -y docker-compose-plugin

2.验证 Docker Compose 是否安装成功

docker compose version

安装GIT

yum install git

启动

1.创建项目目录

mkdir /data
cd /data

2.拉项目代码并启动

git clone https://github.com/veops/cmdb.git
cd cmdb/
docker compose up -d

访问

浏览器打开,输入http://ip:8000访问,默认账号密码分别为:

详解

通过以上内容可以简单方便的部署起来VECMDB服务,但我们不仅要知其然还要知其所以然,以下这部分将会详细的讲解下CMDB的启动方式及各个服务,以及一些简单的排错方法,能更深入的了解VECMDB服务

Docker Compose

Docker-Compose是一个用于定义和运行多容器Docker应用程序的工具。通过一个名为docker-compose.yml的YAML文件,用户可以配置应用程序所需的所有服务。然后,只需一个命令就可以创建并启动这些服务。VECMDB是通过Docker-Compose做服务管理的,那首先我们就需要详细的了解下VECMDB的docker-compose.yml配置文件,配置文件位于仓库的根目录,内容如下:

services: # 第一部分为服务定义
  cmdb-db: # 定义了一个名为cmdb-db的服务
    image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-db:2.3 # 镜像地址,MySQL数据库容器
    container_name: cmdb-db  # 容器名称为cmdb-db
    env_file: # 从当前目录下的.env文件中加载环境变量
      - .env
    environment: # 环境变量配置
      TZ: Asia/Shanghai # 配置时区为Asia/Shanghai
    volumes: # 挂载三个卷
      - db-data:/var/lib/mysql # 第一个卷为db-data,用来持久化MySQL数据
      - ./docs/mysqld.cnf:/etc/mysql/conf.d/mysqld.cnf # 本地配置文件mysqld.cnf挂载到MySQL配置目录
      - ./docs/cmdb.sql:/docker-entrypoint-initdb.d/cmdb.sql # 初始化SQL文件cmdb.sql挂载到MySQL容器的初始化目录
    healthcheck: # 健康命令检查,检查MySQL服务是否正常
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-p$MYSQL_ROOT_PASSWORD"] # 健康检查命令,检查MySQL服务是否正常
      interval: 10s
      timeout: 5s
      retries: 5
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # 设置MySQL字符集和排序规则
    networks: # 网络配置,使用名字为new的自定义网络,同时设置别名为mysql
      new:
        aliases:
          - mysql
    ports: # 端口配置,将宿主机的23306端口映射到容器的3306端口
      - '23306:3306'

  cmdb-cache: # 定义一个名为cmdb-cache的服务
    image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-cache:2.3 # 镜像地址,Redis缓存容器
    container_name: cmdb-cache # 容器名称为cmdb-cache
    environment: # 环境变量配置
      TZ: Asia/Shanghai # 配置时区为Asia/Shanghai
    volumes: # 挂载一个卷
      - cache-data:/data # 卷为cache-data,用来持久化Redis数据
    healthcheck: # 健康检查命令,检查Redis服务是否正常
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks: # 网络配置,使用名字为new的自定义网络,同时设置别名为redis
      new:
        aliases:
          - redis

  cmdb-api: # 定义一个名为cmdb-api的服务
    image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-api:2.4.5 # 镜像地址,CMDB API容器
    container_name: cmdb-api # 容器名称为cmdb-api
    env_file: # 从当前目录下的.env文件中加载环境变量
      - .env
    environment: # 环境变量配置
      TZ: Asia/Shanghai # 配置时区为Asia/Shanghai
      WAIT_HOSTS: cmdb-db:3306, cmdb-cache:6379 # 配置WAIT_HOSTS用来等待cmdb-db和cmdb-cache服务健康后再启动
    depends_on: # 定义依赖关系
      cmdb-db: # 确保cmdb-db服务启动健康后再启动
        condition: service_healthy
      cmdb-cache: # 确保cmdb-cache服务启动健康后再启动
        condition: service_healthy
    command: # 多行启动命令
      - /bin/sh
      - -c
      - |
        sed -i "s#USE_ACL = False#USE_ACL = True#g" settings.py # 修改settings.py中的USE_ACL为True
        /wait # 使用/wait脚本等待服务依赖启动
        flask db-setup # 初始化数据库
        flask common-check-new-columns # 检查数据库新列
        gunicorn --workers=4 autoapp:app -b 0.0.0.0:5000 -D # 启动gunicorn服务

        celery -A celery_worker.celery worker -E -Q one_cmdb_async --autoscale=4,1 --logfile=one_cmdb_async.log -D # 启动celery服务,队列one_cmdb_async
        celery -A celery_worker.celery worker -E -Q acl_async --logfile=one_acl_async.log --autoscale=2,1 -D # 启动celery服务,队列acl_async

        nohup flask cmdb-trigger > trigger.log 2>&1 &
        flask cmdb-init-cache
        flask cmdb-init-acl
        flask init-import-user-from-acl
        flask init-department
        flask cmdb-counter > counter.log 2>&1 # 执行一系列的flash命令用来初始化系统
    healthcheck: # 健康检查命令,检查API服务是否启动正常
      timeout: 3s
      interval: 5s
      retries: 10
      test: "ps aux|grep -v grep|grep -v '1 root'|grep gunicorn || exit 1"        
    networks: # 网络配置,使用名字为new的自定义网络,同时设置别名为cmdb-api
      new:
        aliases:
          - cmdb-api

  cmdb-ui: # 定义一个名为cmdb-ui的服务
    image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-ui:2.4.5 # 镜像地址,CMDB UI容器
    container_name: cmdb-ui # 容器名称为cmdb-api
    depends_on: # 定义依赖关系
      - cmdb-api # 确保cmdb-api服务启动成功后再启动
        condition: service_healthy
    environment: # 环境变量配置
      TZ: Asia/Shanghai # 配置时区为Asia/Shanghai
      CMDB_API_HOST: cmdb-api:5000 # CMDB_API_HOST指向到cmdb-api服务的地址
      NGINX_PORT: 80 # 设置NGINX的端口为80
    volumes: # 挂载一个卷
      - ./docs/nginx.cmdb.conf.example:/etc/nginx/conf.d/nginx.cmdb.conf.example # 挂载本地的nginx配置文件
    command: # 多行启动命令
      - /bin/sh
      - -c
      - |
        envsubst '$$CMDB_API_HOST  $$NGINX_PORT' < /etc/nginx/conf.d/nginx.cmdb.conf.example > /etc/nginx/conf.d/cmdb.conf # 使用envsubst替换nginx配置文件中的环境变量
        nginx -g  'daemon off;' # 启动nginx,使用daemon off模式,前台运行
    networks: # 网络配置,使用名字为new的自定义网络
      - new
    ports: # 端口配置,将宿主机的8000端口映射到容器的80端口
      - "8000:80"

volumes: # 第二部分为卷定义
  db-data: # 定义一个db-data本地卷,用来持久化MySQL数据,cmdb-db容器使用
    driver: local
    name: cmdb_db-data
  cache-data: # 定一个cache-data本地卷,用来持久化Redis数据,cmdb-cache容器使用
    driver: local
    name: cmdb_cache-data

networks: # 第三部分为网络定义
  new: # 定义一个new桥接网络,用于各服务之间通信
    driver: bridge
    name: cmdb_network

总结以下就是启动了四个容器,分别是MySQL、Reids、后端API和前端UI,后端API启动前需要MySQL和Reids启动成功,而前端UI启动前需要后端API启动成功。定义了一个公共的网络保证四个容器之间可以互相通信,同时还定义了两个本地卷,保证MySQL和Reids数据的持久化,以确保容器在重启之后数据也不会丢失,对系统升级也十分友好

本地卷

数据是持久化在宿主机上的本地卷里,本地卷的查看可以直接执行volume命令,例如查看MySQL的本地卷,就可以用如下命令:

# docker volume inspect cmdb_db-data
[
    {
        "CreatedAt": "2024-06-03T17:59:36+08:00",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "cmdb",
            "com.docker.compose.version": "2.27.0",
            "com.docker.compose.volume": "db-data"
        },
        "Mountpoint": "/var/lib/docker/volumes/cmdb_db-data/_data",
        "Name": "cmdb_db-data",
        "Options": null,
        "Scope": "local"
    }
]

其中Mountpoint就是数据在宿主机本地的挂载点,可以直接查看其中的数据

# ls /var/lib/docker/volumes/cmdb_db-data/_data/
auto.cnf  ca-key.pem  ca.pem  client-cert.pem  client-key.pem  cmdb  ib_buffer_pool  ib_logfile0  ib_logfile1  ibdata1  ibtmp1  mysql  performance_schema  private_key.pem  public_key.pem  server-cert.pem  server-key.pem  sys

而Redis持久化在本地的数据也同样可以通过以上的方法查看

# docker volume inspect cmdb_cache-data
[
    {
        "CreatedAt": "2024-06-03T17:59:36+08:00",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "cmdb",
            "com.docker.compose.version": "2.27.0",
            "com.docker.compose.volume": "cache-data"
        },
        "Mountpoint": "/var/lib/docker/volumes/cmdb_cache-data/_data",
        "Name": "cmdb_cache-data",
        "Options": null,
        "Scope": "local"
    }
]
#
# ls /var/lib/docker/volumes/cmdb_cache-data/_data/
dump.rdb

只有一个rdb数据文件。如果你在部署时遇到数据方面的问题,可以通过以上方法来查看本地的数据,或是直接命令行进入MySQL或者Reids去检查数据,当然更多的时候可能是数据初始化问题,所以更为有效的方法或许是使用如下命令重启docker-compose服务

# 关闭docker compose服务
# docker compose down

# 启动docker compose服务
# docker compose up -d

# 可选:查看docker compose服务状态
# docker compose ps

# 可选:检查docker compose容器日志
# docker compose logs

自定义网络

docker-compose服务启动后,可以通过network命令查看Docker的网络列表

# docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
17ec43fa34f8   bridge         bridge    local
5dd2f0dd8033   cmdb_network   bridge    local
75376eee7d8b   host           host      local
deb75486f151   none           null      local

此时能看到一个名为cmdb_network的网络,如果你遇到了网络连通性问题,例如API连不上数据库等等,可以通过network命令查看网络的详细信息

# docker network inspect cmdb_network
[
    {
        "Name": "cmdb_network",
        "Id": "5dd2f0dd8033f7c99d4a8e5371356b41e087c71eb9f35c4fdacaccdfa280e3d1",
        "Created": "2024-06-12T13:42:35.923873631+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "176d8a248ecde36d46205e03ff19879cd2a6c6325e3e8622ca48033ae55a0e5b": {
                "Name": "cmdb-api",
                "EndpointID": "0619481c0a6241b445ea6daead002c39f82aae56ba77390b67d73779d56c7221",
                "MacAddress": "02:42:ac:13:00:04",
                "IPv4Address": "172.19.0.4/16",
                "IPv6Address": ""
            },
            "3387071f980e26a399350f8a6fda0587edccb25319ec040945896228671616c4": {
                "Name": "cmdb-db",
                "EndpointID": "234d64c1858fb5933defe84b13aaf071426324959f0331abec4e1dd29c4c1a09",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "a2df35da575fa289b4b2cc3dd0d7370c1003a47fe84b894a41751adef4d56dd4": {
                "Name": "cmdb-ui",
                "EndpointID": "a403699251326f92e391b4aa38f9d80cf14153053e4f2307d133b4ff9f167182",
                "MacAddress": "02:42:ac:13:00:05",
                "IPv4Address": "172.19.0.5/16",
                "IPv6Address": ""
            },
            "aaf5d23ee24bd9719f9231369649fceac7a1fe8bb1bb9421ca12f35c3faade49": {
                "Name": "cmdb-cache",
                "EndpointID": "efe4eff06148e463a8b9a1af0ef15e81701e0bec39f9cfa25fb9613005b32148",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "new",
            "com.docker.compose.project": "cmdb",
            "com.docker.compose.version": "2.27.0"
        }
    }
]

这里输出了网络的详细信息,包括网络的配置、连接到该网络到容器等等,其中的Containers字段就记录了所有连接到此网络到容器,正常情况下会有四个,包含cmdb-dbcmdb-cachecmdb-apicmdb-ui,它们都被分配了合适的IP地址

容器

如果以上都没有问题,那就可以通过docker命令查看到容器的状态都正常

# docker compose ps
NAME         IMAGE                                                    COMMAND                  SERVICE      CREATED          STATUS                    PORTS
cmdb-api     registry.cn-hangzhou.aliyuncs.com/veops/cmdb-api:2.4.5   "/bin/sh -c 'sed -i …"   cmdb-api     10 minutes ago   Up 10 minutes             
cmdb-cache   registry.cn-hangzhou.aliyuncs.com/veops/cmdb-cache:2.3   "docker-entrypoint.s…"   cmdb-cache   10 minutes ago   Up 10 minutes (healthy)   6379/tcp
cmdb-db      registry.cn-hangzhou.aliyuncs.com/veops/cmdb-db:2.3      "docker-entrypoint.s…"   cmdb-db      10 minutes ago   Up 10 minutes (healthy)   33060/tcp, 0.0.0.0:23306->3306/tcp, :::23306->3306/tcp
cmdb-ui      registry.cn-hangzhou.aliyuncs.com/veops/cmdb-ui:2.4.5    "/docker-entrypoint.…"   cmdb-ui      10 minutes ago   Up 10 minutes             0.0.0.0:8000->80/tcp, :::8000->80/tcp

最后就可以正常通过Web访问部署的CMDB服务了

注意事项

前文的docker-compose.yml配置文件中有配置从代码根目录下加载.env文件内容作为环境变量,.env文件主要记录了MySQL数据库配置信息,如下:

 MYSQL_ROOT_PASSWORD='123456'
 MYSQL_HOST='mysql'
 MYSQL_PORT=3306
 MYSQL_USER='cmdb'
 MYSQL_DATABASE='cmdb'
 MYSQL_PASSWORD='123456'

可以看到默认的账号密码比较简单,如果我们想要修改的话,最好在第一次初始化之前就修改.env文件里的配置,这样的话在系统初始化时就会设置成新设置的账号密码,以提高系统安全性

若你已经初始化了系统,还想要再修改账号密码的话,那就只能进入MySQL数据库进行修改了,同时修改过之后也要同时修改.env配置文件里的相关配置

常见问题

数据库连接失败

数据库的配置记录在.env配置文件中,先检查数据库配置和环境变量是否正确,其次确认数据库服务正常启动并能接受连接

# docker exec -it cmdb-db mysql -u root -p$MYSQL_ROOT_PASSWORD

最后检查自定义网络是否正常,通过之前给的network命令

缓存连接失败

检查Redis服务是否正常运行并能接受连接

# docker exec -it cmdb-cache redis-cli ping

其次也是检查自定义网络状态

API服务启动失败

先检查以来的MySQL和Reids服务是否正常,然后检查是否能正常连通MySQL和Redis

# docker exec -it cmdb-api /bin/sh -c "ping cmdb-db"
# docker exec -it cmdb-api /bin/sh -c "ping cmdb-cache"

如果正常则检查API服务容器状态

# docker compose ps | grep cmdb-api

容器状态正常则检查gunicorn服务是否正常

# docker exec -it cmdb-api /bin/sh -c "ps aux|grep -v grep|grep -v '1 root'|grep gunicorn"

最后查看日志是否有报错

# docker compose logs cmdb-api

UI服务无法访问

先确认依赖的API容器状态正常,然后检查依赖的API服务日志无报错,再然后检查是否能正常连通API容器

# docker exec -it cmdb-ui /bin/sh -c "ping cmdb-api"

如果都没有问题,则查看UI服务容器状态

# docker compose ps | grep cmdb-ui

最后查看nginx配置及容器日志是否有报错

# docker exec -it cmdb-ui /bin/sh -c "cd /etc/init.d && nginx -t"
# docker compose logs cmdb-ui

对于成熟的开源项目,只要不是刚刚更新的新版本,那大概率都已经经过了许多用户的实际验证,项目本身出现问题的概率较低,如果我们遇到错误先考虑自己的环境及配置,按照以上解决思路,大概率能找到问题并解决。如果不行的话那就重启下docker-compose服务,还不行的话就重装吧