OpenDevOps 文档

介绍

OpenDevOps

https://img.shields.io/badge/Python-3.6-green.svg?style=plasticPython3 https://img.shields.io/badge/Tornado-5.0-brightgreen.svg?style=plasticTornado https://img.shields.io/badge/Vuejs-2.5-brightgreen.svg?style=plasticVue.js https://img.shields.io/badge/iview-3.2.0-blue.svg?style=plasticiview


CODO是一款为用户提供企业多混合云、自动化运维、完全开源的云管理平台。

CODO前端基于Vue iview开发、为用户提供友好的操作界面,增强用户体验。

CODO后端基于Python Tornado开发,其优势为轻量、简洁清晰、异步非阻塞。

CODO开源多云管理平台为用户提供多功能:ITSM、基于RBAC权限系统、Web Terminnal登陆日志审计、录像回放、强大的作业调度系统、CMDB、监控报警系统等

众多功能模块我们一直在不停的调研和开发,如果你对此项目感兴趣可以加入我们的社区QQ交流群:18252156

同时也希望你能给我们项目一个star,为贡献者加油⛽️!为运维干杯🍻!


Microservice

  • codo
    • 功能:项目前端
    • 端口:80/443
    • 安装:必须
    • 检测:openresty -t
  • codo-admin
    • 功能:管理后端
    • 端口:8010
    • 安装:必须
    • 检测:curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://mg.opendevops.cn:8010/are_you_ok/
  • codo-cmdb
    • 功能:资产管理
    • 端口:8050
    • 安装:必须
    • 检测:curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://cmdb2.opendevops.cn:8050/are_you_ok/
  • codo-task
    • 功能:任务系统
    • 端口:8020
    • 安装:必须
    • 检测: curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://task.opendevops.cn:8020/are_you_ok/
  • codo-cron
    • 功能:定时任务
    • 端口:9900
    • 安装:必须
    • 备注: 单进程,可使用本机IP
    • 检测: curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://cron.opendevops.cn:9900/are_you_ok/
  • kerrigan
    • 功能:配置中心
    • 端口:8030
    • 安装:必须
    • 检测: curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://kerrigan.opendevops.cn:8030/are_you_ok/
  • codo-tools
    • 功能:运维工具
    • 端口:8040
    • 安装:必须
    • 检测: curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://tools.opendevops.cn:8040/are_you_ok/
  • codo-dns
    • 功能:域名管理
    • 端口:8060
    • 安装:必须
    • 检测: curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://dns.opendevops.cn:8060/are_you_ok/
  • codo-scripts
    • 功能:一些示例脚本库,将提供提供示例脚本
    • 端口:N/A,示例脚本没有端口
    • 安装:N/A

Architecture

  • Apigateway代理前端文件
  • ApigateWay依赖DNS服务,需要安装Dnsmasq
  • 微服务部署完成后,需在Apigateway进行注册
  • 一台MySQL Master示例,不同的微服务使用单独的库

_images/architecture.png

安装文档

分布式安装

环境准备

部署安装之前,你应该了解下每个模块的用途 > 传送门

部署视频

近期有部分同学反应说部署太麻烦了,为什么不做成一个Docker,其实我们这里单项目已经是Docker部署了,为了更好的让用户更快的了解我们的平台,我们准备了部署视频,视频入口

建议配置

  • 系统: CentOS7+
  • CPU: 4Core+
  • 内存: 8G+
  • 磁盘: 50G+

基础环境

  • 版本约束
    • Python3.6
    • Redis3.2
    • MySQl5.7
    • RabbitMQ
    • Docker
    • Docker-compose

优化系统

注意:

  • 如果你的系统是新的,我们建议你先优化下系统,同样我们也提供了优化系统脚本
  • 以下基础环境中,若你的系统中已经存在可跳过,直接配置,建议使用我们推荐的版本

环境变量

创建项目目录
$ mkdir -p /opt/codo/ && cd /opt/codo/
以下内容贴入到vim /opt/codo/env.sh文件,主要修改配置地址和密码信息
echo -e "\033[31m 注意:token_secret一定要做修改,防止网站被攻击!!!!!!! \033[0m"
echo -e "\033[32m 注意:token_secret一定要做修改,防止网站被攻击!!!!!!! \033[0m"
echo -e "\033[33m 注意:token_secret一定要做修改,防止网站被攻击!!!!!!! \033[0m"

#部署的IP地址
export LOCALHOST_IP="10.10.10.12"

#设置你的MYSQL密码
export MYSQL_PASSWORD="m9uSFL7duAVXfeAwGUSG"

### 设置你的redis密码
export REDIS_PASSWORD="cWCVKJ7ZHUK12mVbivUf"

### RabbitMQ用户密码信息
export MQ_USER="ss"
export MQ_PASSWORD="5Q2ajBHRT2lFJjnvaU0g"


#codo-admin用到的cookie和token
export cookie_secret="nJ2oZis0V/xlArY2rzpIE6ioC9/KlqR2fd59sD=UXZJ=3OeROB"
# 这里codo-admin和gw网关都会用到,一定要修改。可生成随意字符
export token_secret="pXFb4i%*834gfdh963df718iodGq4dsafsdadg7yI6ImF1999aaG7"


##如果要进行读写分离,Master-slave主从请自行建立,一般情况下都是只用一个数据库就可以了
# 写数据库
export DEFAULT_DB_DBHOST="10.10.10.12"
export DEFAULT_DB_DBPORT='3306'
export DEFAULT_DB_DBUSER='root'
export DEFAULT_DB_DBPWD=${MYSQL_PASSWORD}
#export DEFAULT_DB_DBNAME=${mysql_database}

# 读数据库
export READONLY_DB_DBHOST='10.10.10.12'
export READONLY_DB_DBPORT='3306'
export READONLY_DB_DBUSER='root'
export READONLY_DB_DBPWD=${MYSQL_PASSWORD}
#export READONLY_DB_DBNAME=${mysql_database}

# 消息队列
export DEFAULT_MQ_ADDR='10.10.10.12'
export DEFAULT_MQ_USER=${MQ_USER}
export DEFAULT_MQ_PWD=${MQ_PASSWORD}

# 缓存
export DEFAULT_REDIS_HOST='10.10.10.12'
export DEFAULT_REDIS_PORT=6379
export DEFAULT_REDIS_PASSWORD=${REDIS_PASSWORD}

==最后一定不要忘记source:== source /opt/codo/env.sh

关闭SELINUX

  • 若已关闭请跳过
#临时关闭
$ setenforce 0

#或修改配置文件关闭,需要重启

$ vi /etc/selinux/config  

将SELINUX=enforcing改为SELINUX=disabled 
设置后需要重启才能生效  

清空防火墙规则

注意,不要关闭防火墙,Docker需要用到NAT

#只清空filter链即可
$ iptables -F

安装Python3

建议使用Python36,若你的系统里面已经存在Python36可以跳过此步骤。
echo -e "\033[32m [INFO]: Start install python3 \033[0m"
yum update -y
yum groupinstall Development tools -y
yum -y install zlib-devel
yum install -y openssl-devel libxslt-devel libxml2-devel libcurl-devel
yum install python3 -y 

安装docker

若已安装可跳过
echo -e "\033[32m [INFO]: Start install docker,docker-compose \033[0m"
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager --enable docker-ce-edge
yum install -y docker-ce
#启动和开机自启
/bin/systemctl start docker.service

/bin/systemctl enable docker.service

安装docker-compose编排工具

#curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python3 get-pip.py 如果没有pip3 请安装
pip3 install docker-compose

安装MySQL

一般来说一个MySQL实例即可,如果有需求可以自行搭建主从,微服务每个服务都可以有自己的数据库

我们这里示例是用Docker部署的MySQL,如果你要用已有的数据库请修改/opt/codo/env.sh

source /opt/codo/env.sh
mkdir -p /opt/codo/codo-mysql&& cd /opt/codo/codo-mysql
cat >docker-compose.yml <<EOF
mysql:
  restart: unless-stopped
  image: registry.cn-shanghai.aliyuncs.com/ss1917/mysql:5.7
  volumes:
    - /data/mysql:/var/lib/mysql
    - /data/mysql_conf:/etc/mysql/conf.d
  ports:
    - "3306:3306"
  environment:
    - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
EOF

#启动 
docker-compose up -d
# 安装MySQL客户端
yum install mysql -y  

if [ $? == 0 ];then
    echo -e "\033[32m [INFO]: mysql install success. \033[0m"
    echo -e "\033[32m [INFO]: 最好提高下MySQL的最大链接数. \033[0m"
    echo -e "\033[32m [INFO]: mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} \033[0m"
else
    echo -e "\033[31m [ERROR]: mysql57 install faild \033[0m"
    exit -3
fi
  • 测试 mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD}

安装Redis

  • 创建 docker-compose.yml
source /opt/codo/env.sh
mkdir -p /opt/codo/codo-redis && cd /opt/codo/codo-redis
cat >docker-compose.yml <<EOF
redis:
    image: registry.cn-shanghai.aliyuncs.com/ss1917/redis:4
    ports:
      - 6379:6379
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
EOF

#启动
docker-compose up -d
  • 没有cli的同学,请yum install redis -y
  • 测试 redis-cli -h 127.0.0.1 -p 6379 -a ${REDIS_PASSWORD}

安装RabbitMQ

  • 创建 docker-compose.yml
source /opt/codo/env.sh
mkdir -p /opt/codo/codo-mq && cd /opt/codo/codo-mq 
cat >docker-compose.yml <<EOF
rabbitmq:
    restart: unless-stopped
    image: registry.cn-shanghai.aliyuncs.com/ss1917/rabbitmq:3-management
    environment:
      - RABBITMQ_DEFAULT_USER=${MQ_USER}
      - RABBITMQ_DEFAULT_PASS=${MQ_PASSWORD}
    ports:
      - "15672:15672"
      - "5672:5672"
EOF

#启动
docker-compose up -d

安装DNS

  • 注意,这里如果你内部有自己DNS,你也可以选择使用你自己的
部署内部DNS dnsmasq 用于服务间内部通信,API网关需要配置,切记
echo -e "\033[32m [INFO]: Start install dnsmasq \033[0m"
yum install dnsmasq -y

# 设置上游DNS,毕竟你的Dns只是个代理
cat >/etc/resolv.dnsmasq <<EOF
nameserver 114.114.114.114
nameserver 8.8.8.8
EOF

# 设置host解析
echo -e "\033[32m [INFO]: 如果你是单机部署,那么你就将你的本机IP+模块域名解析即可,如果你是分布式部署的,那么每个模块对应的机器IP一定不要搞错,这个很重要,后面网关也要依赖此DNS去解析你的域名,帮你做服务转发的,切记!!!!
 \033[0m"
cat >/etc/dnsmasqhosts <<EOF
$LOCALHOST_IP demo-init.opendevops.cn
$LOCALHOST_IP mg.opendevops.cn
$LOCALHOST_IP task.opendevops.cn
$LOCALHOST_IP gw.opendevops.cn
$LOCALHOST_IP cmdb2.opendevops.cn
$LOCALHOST_IP kerrigan.opendevops.cn
$LOCALHOST_IP tools.opendevops.cn
$LOCALHOST_IP cron.opendevops.cn
$LOCALHOST_IP dns.opendevops.cn
EOF

# 添加配置
echo -e "\033[32m [INFO]: 刚装完DNS可以先不用改本机的DNS,有一部分人反应Docker Build时候会报连不上mirrors,装不了依赖。部署到API网关的时候,需要将本机DNS改成自己,不然没办法访问以上mg,cron,cmdb等内网域名
\033[0m"

# 注意下一步是覆盖你本机的DNS,建议把你的DNS地址加在/etc/resolv.dnsmasq 里面 
cp -rp /etc/resolv.conf /etc/resolv.conf-`date +%F`
# echo "nameserver $LOCALHOST_IP" > /etc/resolv.conf  
sed "1i\nameserver ${LOCALHOST_IP}" /etc/resolv.conf -i 
###注意注意, 这里修改完后,请你一定要确定你nameserver ${LOCALHOST_IP} 内部DNS在第一条、第一条、第一条,放在下面是不能正常解析的.

echo "resolv-file=/etc/resolv.dnsmasq" >> /etc/dnsmasq.conf
echo "addn-hosts=/etc/dnsmasqhosts" >> /etc/dnsmasq.conf

## 启动
/bin/systemctl enable dnsmasq.service
/bin/systemctl start dnsmasq.service
systemctl status dnsmasq
if [ $? == 0 ];then
    echo -e "\033[32m [INFO]: dnsmasq install success. \033[0m"
else
    echo -e "\033[31m [ERROR]: dnsmasq install faild \033[0m"
    exit -6
fi

基础依赖部署完毕

管理后端

codo-admin是基于tornado框架 restful风格的API 实现后台管理,codo详细参考,搭配使用codo前端(iView+ vue)组成的一套后台用户 权限以及系统管理的解决方案(提供登录,注册 密码修改 鉴权 用户管理 角色管理 权限管理 前端组件管理 前端路由管理 通知服务API 系统基础信息接口)

获取代码

if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-admin.git && cd codo-admin

修改相关配置

修改settings.py配置

注意:这里的cookie_secrettoken_secret必须和你的env.sh里面的保持一致,后续网关也要用到这个。若不保持一直登陆后校验不通过回被自动踢回,会导致页面一直不停的刷新

注意:这里的token_secret必须要和你的网关保持一致,这个值是从env.sh拿来的,一定要做修改,防止网站被攻击,如果secret包含正则符号会导致sed失败,请仔细检查

#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh

sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py  
sed -i "s#token_secret = .*#token_secret = '${token_secret}'#g" settings.py     


#mysql配置信息
##我们项目支持取env环境变量,但是还是建议修改下。
DEFAULT_DB_DBNAME='codo_admin'
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${DEFAULT_DB_DBNAME}')#g" settings.py

#只读MySQL配置,若是单台也直接写成Master地址即可
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${DEFAULT_DB_DBNAME}')#g" settings.py


#redis配置
sed -i "s#DEFAULT_REDIS_HOST = .*#DEFAULT_REDIS_HOST = os.getenv('DEFAULT_REDIS_HOST', '${DEFAULT_REDIS_HOST}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PORT = .*#DEFAULT_REDIS_PORT = os.getenv('DEFAULT_REDIS_PORT', '${DEFAULT_REDIS_PORT}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PASSWORD = .*#DEFAULT_REDIS_PASSWORD = os.getenv('DEFAULT_REDIS_PASSWORD', '${DEFAULT_REDIS_PASSWORD}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-admin

ADD settings.py /var/www/codo-admin/

# COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
# COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译,启动

#bulid 镜像
docker build . -t do_mg_image
#启动
docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database codo_admin default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

 docker exec -ti codo-admin_do_mg_1  /usr/local/bin/python3 /var/www/codo-admin/db_sync.py

导入数据

主要是菜单,组件,权限列表,内置的用户等

#导入数据
mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} codo_admin < ./doc/codo_admin_beta0.3.sql

重启

docker-compose  restart 

测试codo-admin

### 01.日志
tailf  /var/log/supervisor/mg.log  #确认没有报错

codo-admin 部署完毕

任务系统

CODO任务系统,负责整个系统中任务调度,此功能是必须要安装的

下载代码

echo -e "\033[32m [INFO]: codo-task(任务系统) Start install. \033[0m"
if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-task.git
cd codo-task

修改配置

同样,这里codo-task也支持取env环境变量,建议还是修改下默认配置
#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh

#修改配置
TASK_DB_DBNAME='codo_task' 

#任务系统的域名
sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py

#mysql配置
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${TASK_DB_DBNAME}')#g" settings.py

#只读MySQL配置
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${TASK_DB_DBNAME}')#g" settings.py

#redis配置
sed -i "s#DEFAULT_REDIS_HOST = .*#DEFAULT_REDIS_HOST = os.getenv('DEFAULT_REDIS_HOST', '${DEFAULT_REDIS_HOST}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PORT = .*#DEFAULT_REDIS_PORT = os.getenv('DEFAULT_REDIS_PORT', '${DEFAULT_REDIS_PORT}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PASSWORD = .*#DEFAULT_REDIS_PASSWORD = os.getenv('DEFAULT_REDIS_PASSWORD', '${DEFAULT_REDIS_PASSWORD}')#g" settings.py

#MQ配置
sed -i "s#DEFAULT_MQ_ADDR = .*#DEFAULT_MQ_ADDR = os.getenv('DEFAULT_MQ_ADDR', '${DEFAULT_MQ_ADDR}')#g" settings.py
sed -i "s#DEFAULT_MQ_USER = .*#DEFAULT_MQ_USER = os.getenv('DEFAULT_MQ_USER', '${DEFAULT_MQ_USER}')#g" settings.py
sed -i "s#DEFAULT_MQ_PWD = .*#DEFAULT_MQ_PWD = os.getenv('DEFAULT_MQ_PWD', '${DEFAULT_MQ_PWD}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-task

#修改应用配置
ADD settings.py /var/www/codo-task/

#修改nginx配置和守护配置
#COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
#COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译,启动

#编译镜像
docker build . -t codo_task_image
#启动
docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_task` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti codo-task_codo_task_1  /usr/local/bin/python3 /var/www/codo-task/db_sync.py

导入数据

暂无

重启

docker-compose  restart 

测试

日志文件位置统一:/var/log/supervisor/
01. 查看日志
tailf /var/log/supervisor/task_scheduler.log  #确认没报错
tailf /var/log/supervisor/exec_task.log   #执行任务的日志

任务系统部署完成

资产管理

下载代码

echo -e "\033[32m [INFO]: codo_cmdb(资产管理) Start install. \033[0m"
if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-cmdb.git
cd codo-cmdb

修改配置

  • 修改settings.py配置信息
#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh

#修改配置
#后端数据库名称,建议不要修改,初始化data.sql已经指定了数据库名字,若需改请一块修改
CMDB_DB_DBNAME='codo_cmdb' 

#任务系统的域名
sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py

#mysql配置
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${CMDB_DB_DBNAME}')#g" settings.py

#只读MySQL配置
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${CMDB_DB_DBNAME}')#g" settings.py

#redis配置
sed -i "s#DEFAULT_REDIS_HOST = .*#DEFAULT_REDIS_HOST = os.getenv('DEFAULT_REDIS_HOST', '${DEFAULT_REDIS_HOST}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PORT = .*#DEFAULT_REDIS_PORT = os.getenv('DEFAULT_REDIS_PORT', '${DEFAULT_REDIS_PORT}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PASSWORD = .*#DEFAULT_REDIS_PASSWORD = os.getenv('DEFAULT_REDIS_PASSWORD', '${DEFAULT_REDIS_PASSWORD}')#g" settings.py

#这里如果配置codo-task的数据库地址,则将数据同步到作业配置

TASK_DB_DBNAME='codo_task' 
sed -i "s#CODO_TASK_DB_HOST = .*#CODO_TASK_DB_HOST = os.getenv('CODO_TASK_DB_HOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#CODO_TASK_DB_PORT = .*#CODO_TASK_DB_PORT = os.getenv('CODO_TASK_DB_PORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#CODO_TASK_DB_USER = .*#CODO_TASK_DB_USER = os.getenv('CODO_TASK_DB_USER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#CODO_TASK_DB_PWD = .*#CODO_TASK_DB_PWD = os.getenv('CODO_TASK_DB_PWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#CODO_TASK_DB_DBNAME = .*#CODO_TASK_DB_DBNAME = os.getenv('CODO_TASK_DB_DBNAME', '${TASK_DB_DBNAME}')#g" settings.py
  • AWS事件和WebTerminnal配置
首先将webterminal部署上去
docker pull webterminal/webterminallte
docker run -itd -p 8080:80 webterminal/webterminallte

修改settings.py文件

# Aws Events 事件邮件通知人
AWS_EVENT_TO_EMAIL = '1111@qq.com,2222@gmail.com'

#Web Terminal 地址,请填写你部署的webterminal地址
#注意这里是填写你上面docker run的机器外网IP
WEB_TERMINAL = 'http://1.1.1.1:8080'

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-cmdb

#修改应用配置
ADD settings.py /var/www/codo-cmdb/

#修改nginx配置和守护配置
#COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
#COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

打包镜像

docker build . -t codo_cmdb  

启动Docker

docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_cmdb` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti codo-cmdb_codo_cmdb_1 /usr/local/bin/python3 /var/www/codo-cmdb/db_sync.py

重启

docker-compose  restart 

日志文件

  • 服务日志:/var/log/supervisor/cmdb.log #主程序日志
  • 定时日志:/var/log/supervisor/cmdb_cron.log #一些后端守护自动运行的日志
tailf /var/log/supervisor/cmdb.log
tailf /var/log/supervisor/cmdb_cron.log 

资产管理系统部署完成

定时任务

CODO项目定时任务模块,定时任务完全兼容crontab,支持到秒级

备注:

Docker部署需要将你的脚本目录单独挂载出来,若不理解的同学参考:codo-cron本地部署方式

下载代码

echo -e "\033[32m [INFO]: codo_cron(定时任务) Start install. \033[0m"
if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-cron.git
cd codo-cron

修改配置

同样,这里codo-cron也支持取env环境变量,建议还是修改下默认配置
#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh
#后端数据库名称,建议不要修改,初始化data.sql已经指定了数据库名字,若需改请一块修改
CRON_DB_DBNAME='codo_cron' 

sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py

#mysql配置
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${CRON_DB_DBNAME}')#g" settings.py

#只读MySQL配置
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${CRON_DB_DBNAME}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-cron

#修改应用配置
ADD settings.py /var/www/codo-cron/

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译,启动

#编译镜像
docker build . -t codo_cron_image
#启动
docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_cron` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti codo-cron_codo_cron_1  /usr/local/bin/python3 /var/www/codo-cron/db_sync.py

重启

docker-compose  restart 

测试

日志文件位置统一:/var/log/supervisor/
01. 查看日志
tailf /var/log/supervisor/cron.log   #确认没报错

定时任务系统部署完成

配置中心

获取代码

if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/kerrigan.git && cd kerrigan

修改相关配置

修改settings.py配置

#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh
#修改管理后端域名
sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py 

#mysql配置信息
##我们项目支持取env环境变量,但是还是建议修改下。
DEFAULT_DB_DBNAME='codo_kerrigan'
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${DEFAULT_DB_DBNAME}')#g" settings.py

#只读MySQL配置,若是单台也直接写成Master地址即可
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${DEFAULT_DB_DBNAME}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-kerrigan

#修改应用配置
ADD settings.py /var/www/kerrigan/

#修改nginx配置和守护配置
#COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
#COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译,启动

#编译镜像
docker build . -t kerrigan_image
#启动
docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_kerrigan` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti  kerrigan_codo-kerrigan_1  /usr/local/bin/python3 /var/www/kerrigan/db_sync.py 

重启

docker-compose  restart 

测试kerrigan

### 01.日志
tailf /var/log/supervisor/kerrigan.log  #确认没有报错

配置中心系统部署完成

运维工具

CODO运维工具支持:告警管理、项目管理、事件管理、加密解密、随机密码、提醒管理等

获取代码

if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-tools.git && cd codo-tools

修改相关配置

修改settings.py 配置

#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh

sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py 

#mysql配置信息
##我们项目支持取env环境变量,但是还是建议修改下。
DEFAULT_DB_DBNAME='codo_tools'
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${DEFAULT_DB_DBNAME}')#g" settings.py

#redis配置
sed -i "s#DEFAULT_REDIS_HOST = .*#DEFAULT_REDIS_HOST = os.getenv('DEFAULT_REDIS_HOST', '${DEFAULT_REDIS_HOST}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PORT = .*#DEFAULT_REDIS_PORT = os.getenv('DEFAULT_REDIS_PORT', '${DEFAULT_REDIS_PORT}')#g" settings.py
sed -i "s#DEFAULT_REDIS_PASSWORD = .*#DEFAULT_REDIS_PASSWORD = os.getenv('DEFAULT_REDIS_PASSWORD', '${DEFAULT_REDIS_PASSWORD}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-tools

#修改应用配置
ADD settings.py /var/www/codo-tools/

#修改nginx配置和守护配置
#COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
#COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译镜像

docker build . -t codo_tools

启动

docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_tools` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti  codo-tools_codo_tools_1  /usr/local/bin/python3 /var/www/codo-tools/db_sync.py 

重启

docker-compose  restart 

测试codo-tools

### 01.日志
tailf /var/log/supervisor/tools.log  #服务日志,确认没有报错
tailf /var/log/supervisor/cron_jobs.log  #定时提醒日志

运维工具系统部署完成

域名管理

CODO域名管理模块,管理BIND 支持智能解析,多域名,多主。

下载代码

echo -e "\033[32m [INFO]: codo_dns(域名管理) Start install. \033[0m"
if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
if ! which git &>/dev/null; then yum install -y git >/dev/null 2>&1;fi
[ ! -d /opt/codo/ ] && mkdir -p /opt/codo
cd /opt/codo && git clone https://github.com/opendevops-cn/codo-dns.git
cd codo-dns

修改配置

同样,这里codo-dns也支持取env环境变量,建议还是修改下默认配置
#导入环境变量文件,最开始准备的环境变量文件
source /opt/codo/env.sh
#后端数据库名称
CRON_DB_DBNAME='codo_dns' 

sed -i "s#cookie_secret = .*#cookie_secret = '${cookie_secret}'#g" settings.py

#mysql配置
sed -i "s#DEFAULT_DB_DBHOST = .*#DEFAULT_DB_DBHOST = os.getenv('DEFAULT_DB_DBHOST', '${DEFAULT_DB_DBHOST}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPORT = .*#DEFAULT_DB_DBPORT = os.getenv('DEFAULT_DB_DBPORT', '${DEFAULT_DB_DBPORT}')#g" settings.py
sed -i "s#DEFAULT_DB_DBUSER = .*#DEFAULT_DB_DBUSER = os.getenv('DEFAULT_DB_DBUSER', '${DEFAULT_DB_DBUSER}')#g" settings.py
sed -i "s#DEFAULT_DB_DBPWD = .*#DEFAULT_DB_DBPWD = os.getenv('DEFAULT_DB_DBPWD', '${DEFAULT_DB_DBPWD}')#g" settings.py
sed -i "s#DEFAULT_DB_DBNAME = .*#DEFAULT_DB_DBNAME = os.getenv('DEFAULT_DB_DBNAME', '${CRON_DB_DBNAME}')#g" settings.py

#只读MySQL配置
sed -i "s#READONLY_DB_DBHOST = .*#READONLY_DB_DBHOST = os.getenv('READONLY_DB_DBHOST', '${READONLY_DB_DBHOST}')#g" settings.py
sed -i "s#READONLY_DB_DBPORT = .*#READONLY_DB_DBPORT = os.getenv('READONLY_DB_DBPORT', '${READONLY_DB_DBPORT}')#g" settings.py
sed -i "s#READONLY_DB_DBUSER = .*#READONLY_DB_DBUSER = os.getenv('READONLY_DB_DBUSER', '${READONLY_DB_DBUSER}')#g" settings.py
sed -i "s#READONLY_DB_DBPWD = .*#READONLY_DB_DBPWD = os.getenv('READONLY_DB_DBPWD', '${READONLY_DB_DBPWD}')#g" settings.py
sed -i "s#READONLY_DB_DBNAME = .*#READONLY_DB_DBNAME = os.getenv('READONLY_DB_DBNAME', '${CRON_DB_DBNAME}')#g" settings.py

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo-dns

#修改应用配置
ADD settings.py /var/www/codo-dns/

#修改nginx配置和守护配置
#COPY doc/nginx_ops.conf /etc/nginx/conf.d/default.conf
#COPY doc/supervisor_ops.conf  /etc/supervisord.conf

EXPOSE 80
CMD ["/usr/bin/supervisord"]
EOF

编译,启动

#编译镜像
docker build . -t codo_dns_image
#启动
docker-compose up -d

创建数据库

mysql -h127.0.0.1 -uroot -p${MYSQL_PASSWORD} -e 'create database `codo_dns` default character set utf8mb4 collate utf8mb4_unicode_ci;'

初始化表结构

docker exec -ti codo-dns_codo-dns_1  /usr/local/bin/python3 /var/www/codo-dns/db_sync.py

重启

docker-compose  restart 

测试

日志文件位置统一:/var/log/supervisor/
01. 查看日志
tailf /var/log/supervisor/codo_dns.log   #确认没报错

域名管理部署完成

项目前端

更新后的项目前端将不再让用户下载静态资源包,使用自动构建的方式,默认保持最新前端
[ ! -d /opt/codo/codo/ ] && mkdir -p /opt/codo/codo/ && cd /opt/codo/codo/

一、修改域名

下列为默认域名,如果要修改访问入口地址请修改server_name对应的demo-init.opendevops.cn,确保能DNS解析到此域名,或者自己绑定hosts来测试一下

cat >codo_frontend.conf <<\EOF
server {
        listen       80;
        server_name demo-init.opendevops.cn;
        access_log /var/log/nginx/codo-access.log;
        error_log  /var/log/nginx/codo-error.log;

        location / {
                    root /var/www/codo;
                    index index.html index.htm;
                    try_files $uri $uri/ /index.html;
        }
        location /api {
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                add_header 'Access-Control-Allow-Origin' '*';
                proxy_pass http://gw.opendevops.cn:8888;
        }

        location ~ /(.svn|.git|admin|manage|.sh|.bash)$ {
            return 403;
        }
}
EOF

创建Dockerfile

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/codo

#修改nginx配置
#ADD nginx.conf /etc/nginx/nginx.conf
ADD codo_frontend.conf /etc/nginx/conf.d/codo_frontend.conf

EXPOSE 80
EXPOSE 443

STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
EOF

创建 docker-compose.yml

cat >docker-compose.yml <<EOF
codo:
  restart: unless-stopped
  image: codo_image
  volumes:
    - /var/log/nginx/:/var/log/nginx/
    - /sys/fs/cgroup:/sys/fs/cgroup
  ports:
    - "80:80"
    - "443:443"
EOF

三、编译,启动

docker build . -t codo_image
docker-compose up -d

四、测试

curl  0.0.0.0:80
tailf  /var/log/nginx/codo-access.log

API网关(部署容易出问题的地方)

==重点仔细看==

由于此项目是模块化、微服务化,因此需要在借助API网关,需要在API网关注册,此步骤是必须的。

注意事项

开始之前,你需要确认以下2个事情

  • DNS服务是否正常,域名能否正常解析
  • 微服务的模块部署是否正常,进行检测

检查DNS思路

1. 确保你的dnsmasql服务是启动的,服务没有报错
2. 确保/etc/dnsmasqhosts文件有解析的IP
3. 确保你网关的这台机器/etc/resolv.conf DNS执行你刚部署的dnsmasq服务IP
4. 确保你网关所在的机器都能正常ping通所有的服务,比如:ping cmdb2.opendevops.cn
5. 确保你的防火墙规则是清空的`iptables -F`
6. 确保你的SELINUX是关闭的`setenforce 0`

服务健康检测

# 进行所有服务进行检测,返回200则正常
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://mg.opendevops.cn:8010/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://task.opendevops.cn:8020/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://cmdb2.opendevops.cn:8050/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://kerrigan.opendevops.cn:8030/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://cron.opendevops.cn:9900/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://tools.opendevops.cn:8040/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://dns.opendevops.cn:8060/are_you_ok/
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://0.0.0.0:80

下载网关

cd /opt/codo/ && git clone https://github.com/ss1917/api-gateway.git && cd /opt/codo/api-gateway

修改配置

主要修改nginx.conf配置信息和config.lua配置,具体参考API网关块:API网关修改配置

全局nginx配置

这里主要修改resolver 内部DNS服务器地址conf/nginx.conf ==一定要修改==

user root;
worker_processes auto;
worker_rlimit_nofile 51200;
error_log logs/error.log;
events {
    use epoll;
    worker_connections 51024;
}
http {
    #设置默认lua搜索路径
    lua_package_path '$prefix/lua/?.lua;/blah/?.lua;;';
    lua_code_cache on;      #线上环境设置为on, off时可以热加载lua文件
    lua_shared_dict user_info 1m;
    lua_shared_dict my_limit_conn_store 100m;   #100M可以放1.6M个键值对
    include             mime.types;    #代理静态文件

    client_header_buffer_size 64k;
    large_client_header_buffers 4 64k;

    init_by_lua_file lua/init_by_lua.lua;       # nginx启动时就会执行
    include ./conf.d/*.conf;                    # lua生成upstream
    resolver 10.10.10.12;                       # 内部DNS服务器地址 一定要修改 对应起来
}

网关配置 conf/conf.d/gw.conf

server {
    listen 80;
    server_name gw.opendevops.cn;
    lua_need_request_body on;           # 开启获取body数据记录日志

    location / {
        ### ws 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        ### 获取真实IP
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_by_lua_file lua/access_check.lua;
        set $my_upstream $my_upstream;
        proxy_pass http://$my_upstream;

        ### 跨域
        add_header Access-Control-Allow-Methods *;
        add_header Access-Control-Max-Age 3600;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Headers $http_access_control_request_headers;
        if ($request_method = OPTIONS){
            return 204;}
    }
}

注册API网关

请仔细阅读下面需要修改配置的地方vim lua/configs.lua ==这个配置基本上都要修改,请务必仔细==

json = require("cjson")


-- redis配置,一定要修改,并且和codo-admin保持一致,admin会把权限写进去提供网关使用
redis_config = {
    host = '10.10.10.12',
    port = 6379,
    auth_pwd = 'cWCVKJ7ZHUK12mVbivUf',
    db = 8,
    alive_time = 3600 * 24 * 7,
    channel = 'gw'
}


-- 注意:这里的token_secret必须要和codo-admin里面的token_secret保持一致
token_secret = "pXFb4i%*834gfdh96(3df&%18iodGq4ODQyMzc4lz7yI6ImF1dG"
logs_file = '/var/log/gw.log'

--刷新权限到redis接口
rewrite_cache_url = 'http://mg.opendevops.cn:8010/v2/accounts/verify/'

-- 注意:rewrite_cache_token要和codo-admin里面的secret_key = '8b888a62-3edb-4920-b446-697a472b4001'保持一致
rewrite_cache_token = '8b888a62-3edb-4920-b446-697a472b4001'  


--并发限流配置
limit_conf = {
    rate = 10, --限制ip每分钟只能调用n*60次接口
    burst = 10, --桶容量,用于平滑处理,最大接收请求次数
}

--upstream匹配规则,API网关域名
gw_domain_name = 'gw.opendevops.cn' 

--下面的转发一定要修改,根据自己实际数据修改
rewrite_conf = {
    [gw_domain_name] = {
        rewrite_urls = {
            {
                uri = "/dns",
                rewrite_upstream = "dns.opendevops.cn:8060"
            },
            {
                uri = "/cmdb2",
                rewrite_upstream = "cmdb2.opendevops.cn:8050"
            },
            {
                uri = "/tools",
                rewrite_upstream = "tools.opendevops.cn:8040"
            },
            {
                uri = "/kerrigan",
                rewrite_upstream = "kerrigan.opendevops.cn:8030"
            },
            {
                uri = "/cmdb",
                rewrite_upstream = "cmdb.opendevops.cn:8002"
            },
            {
                uri = "/k8s",
                rewrite_upstream = "k8s.opendevops.cn:8001"
            },
            {
                uri = "/task",
                rewrite_upstream = "task.opendevops.cn:8020"
            },
            {
                uri = "/cron",
                rewrite_upstream = "cron.opendevops.cn:9900"
            },
            {
                uri = "/mg",
                rewrite_upstream = "mg.opendevops.cn:8010"
            },
            {
                uri = "/accounts",
                rewrite_upstream = "mg.opendevops.cn:8010"
            },
        }
    }
}

修改Dockerfile

使用自动构建的镜像,默认使用最新版本,这一步的目的是把修改后的配置覆盖进去

cat >Dockerfile <<EOF
FROM registry.cn-shanghai.aliyuncs.com/ss1917/api-gateway

#修改配置
ADD . /usr/local/openresty/nginx/

EXPOSE 80
CMD ["/usr/bin/openresty", "-g", "daemon off;"]
EOF

编译,启动

#编译镜像
docker build . -t gateway_image
#启动
docker-compose up -d

启动后地址为http://gw.opendevops.cn:8888,这里是和前端的地址有对应,请勿修改

#测试一下
curl -I -X GET -m 10 -o /dev/null -s -w %{http_code} http://gw.opendevops.cn:8888/api/accounts/are_you_ok/
提醒:openresty服务器DNS必须指向--->最起初部署的DNS服务器地址,另外若你本机ping以上随便一个域名都不通的话,那你要确认下你本机DNS指向你最初部署了DNS服务器了? 修改vim /etc/resolv.conf

访问

注意: demo-init.opendevops.cn 建议修改成自己的域名,也可以绑定hosts来测试一下 可以再部署前端的时候修改

  • 地址:demo-init.opendevops.cn
  • 用户:admin
  • 密码:admin@opendevops

日志路径

若这里访问有报错,请看下日志,一般都是配置错误。
  • 日志路径:所有模块日志统一/var/log/supervisor/

特别感谢

感谢大佬 shenyingzhi 提供测试环境,特此致谢

使用文档

这部分是介绍OpenDevOps平台用户使用文档

任务模板

这部分文档主要用来介绍任务模板,任务模板:可以帮助你实现一个很强大、很复杂、可干预、自定义的任务流程模板; 任务模板功能主要分为:命令管理、模板管理、参数管理、执行用户等部分,由于这块稍微有点难理解,我们提供了示例文档视频演示

命令管理

主要用于创建你的自定义命令,后续供平台执行使用

功能特点

  • 支持Linux Bash命令
  • 支持自定义脚本命令(不限语言)
  • 全局命令统一管理、详细记录展示
  • 命令可视化编辑、搜索、新增、删除等操作

如何使用

点开任务模板->命令管理

  • 新建命令
    • 命令名称:输入你的名称(建议是有意义的名字,后续方便你勾选使用)
    • 执行命令:可以是Linux Bash命令,如:ls,free -m,也可以是一个执行脚本,如:python3 xxx.py
    • 命令参数:这里一般用于执行脚本传入参数,如:pytho3 xxx.py --host=127.0.0.1,这里就可以填入自身参数:--host=127.0.0.1, 可留空,也可后续使用到修改
    • 强制主机:默认可为空,用于你所填写的命令强制指定哪个主机上进行执行(注意:你所指定的这台机器IP,此平台必须可以登陆过去,否则无法执行,CODO平台如何登陆所指定的主机IP请参考执行用户文档)

_images/create_bash.png

示例图:

_images/bash_list.png

模板管理

模板管理是一个核心功能,这里逻辑稍有复杂、但功能极为强大,这里主要用于自定义你的任务流程。

功能特点

  • 支持自定义模板流程
  • 支持多组多优先级并发执行
  • 自定义流程可人工干预、可定时执行
  • 模板可搜索、可编辑、可删除、模板权限细分等

如何使用

点开任务模板->模板管理

  • 创建模板
    • 模板名称: 建议输入一个有意义的名称,注意:此名称不可更改

_images/template_create.png

如何对模板赋权

模板赋权是☞哪些用户可以对此模板有权限(编辑、删除、修改等),管理员默认拥有所有权限。

点开点开任务模板->模板管理->授权-选择关联的用户

自定义你的模板流程

首先我们已经创建了一个新的模板,接下来我们向模板里面添加一些自定义的内容

  • 1、选中你的模板
  • 2、下拉选择你的命令进行提交(支持同时选择多个哦~)
  • 3、修改模板流程中的字段信息
  • 4、最后记得保存编辑

示例:

_images/select_bash.png

下图字段说明:

  • 组:默认为:88, 请修改为:1, 默认从第一组开始执行(多组配置示例见下图)
  • 优先级: 执行命令的优先级,修改对应数字即可
  • 任务名称: 此任务名称是你命令管理命令名称,自动带出
  • 执行命令: 此执行命令是你命令管理执行命令,自动带出
  • 参数:此参数是你命令管理参数,自动带出,参数例如:--host=127.0.0.1 --group=game01空格隔离第二个参数
  • 执行用户: 此执行用户用于登陆你的执行主机,从任务模板->执行用户里面选择,详细见执行用户部分使用说明
  • 触发器:可选默认(默认直接执行)、定时(到达时间后开始执行,此时间是提交任务的时候指定的时间)、干预(需要手动触发执行)
  • 指定主机:指定那台主机执行此命令,IP地址形式,CODO平台需要能登陆此主机
  • 删除: 删除所选项

单组配置示例:

_images/template_edit.png

多组配置示例:

_images/s_group_template.png

参数管理

参数名称类似于别名的概念,订单显示时参数值会被参数名称替代

多组配置示例:

_images/parameter.png

执行用户

执行用户:主要用于登陆命令管理/模板管理里面指定的主机的验证,任务一般都是通过SSH进行远程执行、编排模板的时候需要选择一个用户进行登陆主机

如何使用 点开任务模板->执行用户

  • 新建用户
    • 用户名称:如:root, ops此系统用户,注意:此用户是Linux系统用户哦~
    • SSH端口:你的SSH端口,如:22
    • 备注:描述用途使用
    • 用户私钥:服务器机器的私钥,一般默认生成的为:id_rsa

若你的机器没有私钥,你可以手动生成一堆公钥私钥进行放置到服务器~/.ssh/目录下,参考命令:

#生成密钥对
$ ssh-keygen -t rsa
# 将公钥加到`authorized_keys`文件
$ [ ! -d /root/.ssh ] && mkdir /root/.ssh ; [ ! -f /root/.ssh/authorized_keys ] && touch /root/.ssh/authorized_keys ; cat /root/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && echo ok

新建执行用户示例:

_images/create_exec_user.png

_images/exec_user_list.png

任务发布

这部分主要介绍代码发布的配置和一些SQL相关配置(更新中),任务发布后续将会支持更多业务模块,目前以任务发布和SQL优化审核相关的配置为主;

操作教学视频https://www.bilibili.com/video/av53424572/

应用发布

该模块是任务发布主要功能,预先配置你代码发布的相关信息,设定时间自动执行。

例举例一个简单发布示例:

请选择你要发布的应用,具体配置参考【作业配置】-【应用配置】。发布权限关联代码仓库权限【作业配置】-【代码仓库】。

创建应用发布

点开应用发布

  • 选择应用:下拉选择在作业配置中配置的应用配置
  • 标签版本:输入你的TAG
  • 自定义参数:前面定义参数,后面填写对应值(例如:[IP] [203.167.11.100] )
  • 开始时间:选择一个执行时间,来触发模板中的定时触发器
  • 备注详情:填写你发布应用的标识

_images/app_publish_1.png

SQL审核

该模块用来将要执行的SQl语句的提交给审批人进行审批,审批通过后才会在指定时间执行该SQL语句

注意

  • 1.当前页面使用标签关联相关数据库,选取标签下的mysql的写库
  • 2.本服务多部署在内网,为了适配多云多区域,需要经过代理连接数据库,标签里面应配置代理主机,当前任务会跳转到代理主机执行数据库审核
  • 3.请使用标准的SQL语句,从语句上选择数据库。
  • 4.使用内建模板ID:9001主机组为1在没有熟悉模板的使用之前,不要随意更改相关任务模板

点开SQL审核

  • 目标标签:下拉选择你要关联的标签组
  • SQL语句:填写要执行的SQL语句
  • 审批人员:下拉选择你要提交审核的用户

_images/sql_auth.png

SQL优化

该模块用于优化SQL语句,输入要执行的SQL语句然后进行平分和优化等操作

注意

  • 1.当前页面使用标签关联相关数据库,选取标签下的mysql,SQL优化使用内建模板ID:9901主机组为1,在没有熟悉模板的使用之前,不要随意更改相关任务模板
  • 2.本服务多部署在内网,为了适配多云多区域,需要经过代理连接数据库,标签信息里面应配置代理主机,当前任务会跳转到代理主机执行

点开SQL优化

  • 目标标签:下拉选择你要关联的标签组(注意:目标库只能选择一个数据库)
  • 数据库名:输入要操作的数据库名称
  • 优化类型:选择优化类型SOARSQLAdvisor
  • SQL语句:填写要优化的SQL语句
  • 操作: 选择你要操作的选项SQL评分,SQL指纹,SQL美化,语法检查

_images/sql_opti.png

资源申购

该模块用于申购服务器,数据库,Redis,负载均衡等资源使用(更新中)

节点添加

用于横向扩展Kubernetes(K8S)节点(更新中)

自定义任务

该模块可以更灵活的添加自己要对服务器操作的任务模板

注意

  • 1.当前页面使用标签关联相关主机,选取标签下的主机, 系统直连主机并发执行选择模板的任务,为了减轻任务压力,限制并发100以内

点开自定义任务

  • 目标标签:下拉选择自定义的标签组
  • 选择模板:下拉选择自定义的模板
  • 参数1:填写上传的参数和对应参数值(可增加和删除参数选项)
  • 执行时间:选择一个执行时间,用来触发模板中的定时触发器

_images/custom_task.png

自定义任务-代理

该模块用于处理无法直连服务器需要通过代理连接来执行一些任务

注意

  • 1.当前页面使用标签关联相关主机,选取标签下的主机,在代理主机上执行选择模板的任务,并把主机名,IP地址传给任务,任务本身通过ansible、saltsatck、多线程、多进程等方法来进行并发。参数IP:SERVER_IP,主机名:SERVER_HOST一般可以作为salt name。

点开自定义任务-代理

  • 目标标签:下拉选择自定义的标签组(注意:标签可以多选,但是代理主机有且仅有一个,不可多选)
  • 选择模板:下拉选择自定义的模板
  • 参数:填写上传的参数和对应参数值(可增加和删除参数选项)
  • 执行时间:选择一个执行时间,用来触发模板中的定时触发

_images/custom_task_proxy.png

自定义任务-JSON

该模块提供了自定义JSON的方式更方便灵活的来进行自定义任务

注意:参数详解

{
	"task_name": "任务名称",
	"submitter": "提交人",
	"temp_id": "1",
	"schedule": "ready",
	"exec_time": "2018-11-27 14:09:50",
	"associated_user": "{'group-1': ['杨红飞']}",
	"args": "{'VERSION':'eeee', 'arg02': 'xxxx'}",
	"details": "这里是备注",
	"hosts": "{1: '127.0.0.1'}"
}
  • 1.task_name: 任务名字
  • 2.submitter: 提交人
  • 3.temp_id:模板ID,就是你上面创建模板时候生成的那个ID
  • 4.schedule:这是状态,常用的有ready和new ready:表示不通过人工审核,只要到了执行时间直接执行任务new:表示需要任何审核,管理员审核,选择执行时间,到时间后开始执行
  • 5.exec_time: 任务执行时间,状态为ready的情况下,到这个时间会进行执行
  • 6.args:这里是一个字典,里面的参数可以自行定义,如上,你模板参数里面用到了哪些你都可以在这里定义出来,当你的POST到这个接口时候,我们会自动接受此参数,并帮你运行脚本 解析你要传入的参数。
  • 7.details:描述,备注信息
  • 8.hosts:这个是执行主机,字典形式, 1表示第一组主机,也就是上面模板里面的组1,任务支持多组。主机IP,这个是执行主机,这个废话多一点,比如我以上模板的脚本在172.16.0.101这台主机上,我就想平台登陆我这个主机,来帮我执行这些脚本,至于怎么登陆,那么就是我最开始在平台里面配置了一个执行用户,我将我这个主机的私钥放到了平台上,公钥在我服务器上,这样子CODO平台就可以ssh -i xxxx.pem@{ip_address}远程到我的主机上帮我执行命令。

点开自定义任务-JSON

  • POST JSON:输入你的数据,参考上面的示例,你也可以二次开发对接自己的CMDB获取主机,时间字段从下面获取,方便处理(注意:提交的数据必须以JSON格式,请严格按照说明提交)
  • 执行时间:选择一个执行时间,用来触发模板中的定时触发

_images/custom_task_json.png

PS:已经文档会在后续过程中不断更新完善,感谢大家支持。

定时任务

通过定时任务可以进行添加你的定时任务

定时任务特点

  • restful api 简单易定制
  • 可接入可视化界面操作
  • 定时任务统一管理
  • 完全兼容 crontab
  • 支持秒级定时任务
  • 任务可搜索、暂停、编辑、删除

用户使用说明

  • 新增任务
    • job_id: 任务名称,建议为有意义的英文名称
    • 可执行命令: Linux Bash 命令,亦可将可执行程序放入指定的目录(使用docker 切记安装依赖)
    • 任务定时器: (秒、分、时、日、月、周)
      • 示例:每分钟的第20秒开始执行pwd命令

_images/timed_task01.png

  • 编辑任务

_images/timed_task02.png

  • 暂停恢复
    • 状态栏可以将任务暂停/恢复

_images/timed_task03.jpg

  • 任务日志
    • 每条任务执行都会记录日志
    • 日志可根据Job_id、状态、关键字、时间范围等搜索

_images/timed_logs.jpg

作业配置

这部分主要介绍作业配置(更新中),作业配置后续将会支持众多作业配置,目前只支持发布相关的配置;

发布配置

预先配置你发布的应用信息,如:环境、主机、Git库等,

例举例一个简单发布示例:

  • ①创建命令
  • ②配置模板
  • ③配置仓库
  • ④新建应用
  • ⑤提交发布

创建命令

我们提供了基于服务器Bucket基础发布脚本示例供你使用.

克隆代码

##将代码放到/opt/ops_scripts目录下,后续平台要使用到
mkdir -p /opt/ops_scripts
cd /opt/ops_scripts && git clone https://github.com/opendevops-cn/codo-publish.git
cd codo-publish && pip3 install -r requirements.txt

##修改对应settings里面API网关地址,用户密码信息
vim settings.py
api_gw = 'gw.opendevops.cn'

接着到平台添加命令,点开任务模块-命令管理

_images/publish_cmd_list.pngbash_list

配置模板 点开任务模块-模板管理

这里需要你创建一个模板,如:Server发布示例,添加你的命令,自由排版,模板管理文档参考:任务模板
  • 组:1的为第一组
  • 优先级: 按数字顺序执行
  • 参数:PUBLISH_NAME和FLOW_ID都是系统变量,不要修改
  • 执行用户: 默认127.0.0.1可不选,保持默认即可
  • 触发器:这里支持定时支持、人工干预、直接执行,默认是直接执行

_images/publish_server_temp.pngbash_list

配置代码仓库

点开作业配置-代码仓库

这里需要你配置一个git仓库地址,要发布的代码仓库。

_images/publish_code_repo.pngbash_list

新建应用 点开作业配置-发布配置

  • 发布应用:建议一个有意义的名称
  • 发布类型:选择发布类型,支持(服务器、存储桶、K8S CD)
  • 构建主机:哪台主机执行操作,默认(127.0.0.1)
  • 代码仓库:下拉选择你的代码库
  • 关联模板:下拉选择你要关联的模板
  • 排除文件:exclude排除,如图,多个按行隔开
  • 发布类型:目前只支持简单发布
  • 目标主机:ip port user password格式,多个按行隔开
  • 目标主机组:CMDB里面API主机组的信息,可通过CMDB组里面点击获取API地址
  • 发布目录: 服务器的代码目录如:/var/wwww/yanghongfei/

_images/publish_create_app.png

提交发布

最后提交发布,发布是基于git tag的,需要你在要发布的版本库上打上tag

_images/publish_server_commit.png

提交发布后会在订单列表里面显示出来你将要执行的任务, 当你点击到这个任务的时候,我们会把任务信息给展示出来方便你来确认,最后需要你进行审批,可选择时间执行。

_images/publish_audit.png

如下图示例有一个手工干预的,需要你点击终止全部旁边的干预名称进行执行。

_images/publish_commit.png

点击完审批后会进入等待执行,随后会按照你模板里面的顺序进行执行

_images/publish_wait.png 最后执行完成后会显示状态OK,

  • 若执行途中有报错,会暂停任务,可根据日志进行排错,进行重做
  • 若执行途中有报错,且你不希望本组服务器进行执行了,可以点击终止
  • 若整个任务都不想要了,可以点击终止全部

_images/publish_ok.png

标签树

预先配置好你要管理的主机和数据库,然后新建一个标签,将统一管理的主机和数据库规划在一个标签下,便于统一管理和操作。

列举一个简单创建标签的示例:

  • ①新建标签
  • ②新建server
  • ③新建DB

新建标签

点开标签树-root-新建标签

  • 标签名称:建议取一个简单明了的名字
  • 主机:下拉选择已创建的管理主机或者不填写,在后续创建server的时候也可关联该标签
  • 数据库:下拉选择已创建的数据库或者不填写,在后续创建DB的时候也可关联该标签
  • 代理:因为大部分线上DB或者Redis都没有外网,下拉选择已创建的代理主机或者后续创建DB时候也可关联
  • 授权用户:下拉授权用于操作该标签的用户

_images/create_tag.png

新建server

点开标签树-server-添加主机

  • 主机名称:建议取一个有特定意义的名字
  • IP地址:填写要管理的服务器IP地址
  • 区域:服务器的所在区域,例如(上海,新加坡等)
  • 标签:下拉选择上面创建的标签或者其他已有标签
  • 备注:记录其他你需要标识的文字

_images/create_server.png

新建DB

点开标签树-DB-添加数据库

  • 数据库名称:填写你要操作的数据库名字也可以是自定义的名字
  • 数据库地址:输入被管理数据库地址
  • 数据库端口:数据库连接端口(默认为3306)
  • 用户:对该数据库有操作权限的账号
  • 密码:上面账号对应的密码
  • 环境:下拉选择你要对应的环境
  • 代理:下拉选择可以外网连接到该数据库的代理地址
  • 类型:下拉选择你的数据库类型
  • 标记:下拉选择该数据库的操作权限
  • 标签:下来选择对应的管理标签
  • 备注:记录其他你需要标识的文字

_images/create_db.png

代理配置

预先配置好代理服务器地址,用于创建标签树下DB时可供选取,该代理是用来连接无外网状态下的数据库而存在的。

列举一个简单创建代理的示例:

  • ①添加代理
  • ②编辑inception
  • ③编辑salt

添加代理

点开代理配置-添加代理

  • 代理主机:填写你要用来代理连接数据库的IP地址
  • 备注信息:填写描述信息

_images/create_proxy.png

编辑inception

点开代理配置-选择对应的inception编辑

  • Inception主机:填写Inception服务的IP地址
  • Inception端口:填写Inception服务端口
  • 备份库主机:填写可以代理连接数据库的IP地址
  • 备份库端口:填写端口(默认3306)
  • 备份库用户:填写可操作备份的账号
  • 备份库密码:填写对应账号密码

_images/edit_inception.png

编辑salt

该字段为保留字段,用于后期开发处理
PS: 作业配置和任务模板编排作业任务,稍有点复杂,我们正在不断优化系统和文档,感谢你的支持。

代码仓库

列举一个平台上代码仓库部分的示例,让大家快速灵活的使用OpenDevOps平台,进行对接代码仓库的实战操作;

创建代码仓库

点开作业配置-代码仓库-GIT配置

填写对应git_url、private_token、deploy_key

  • git_url: https://gitlab.domain.com/
  • private_token: Gitlab申请的Access Token

_images/create_git01.png

_images/20190705172432.png

  • 添加保存后点击刷新地址,将同步所有该地址下的项目分支到平台

_images/create_git03.png

至此,Gitlab的仓库信息已经可以同步到平台上了,如果你需要基于Gitlab 钩子进行操作,你需要进行以下配置

  • Git服务器操作-->配置GitLab全局钩子
  • CODO平台操作--->配置单个仓库钩子匹配规则

第一步、配置Gitlab全局钩子

此步骤是监控GitLab所有提交事件,根据平台配置的钩子匹配规则进行触发你所定义的任务

注意:由于Gitlab版本存在CE版本和源码安装版本,全局update钩子配置不同

  • GitlabCE版本路径:/opt/gitlab/embedded/service/gitlab-shell/hooks
  • GitLab源码版本路径:/home/git/gitlab-shell/hooks/

此目录下的钩子都是为全局钩子,请慎重修改,本操作是不影响其余钩子/局部钩子的情况下添加的。

请修改update文件,在ruby脚本中修改成以下内容:

#!/opt/gitlab/embedded/bin/ruby --disable-gems
# Fix the PATH so that gitlab-shell can find git-upload-pack and friends.
ENV['PATH'] = '/opt/gitlab/bin:/opt/gitlab/embedded/bin:' + ENV['PATH']

#!/usr/bin/env ruby

# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.

ref_name  = ARGV[0]
old_value = ARGV[1]
new_value = ARGV[2]
repo_path = Dir.pwd
key_id    = ENV.delete('GL_ID')
#CODO TASK,只需要加下面2行即可
codo_task_script = '/opt/codo/codo-scripts/gitlab/codo_task.py'
system(codo_task_script, ref_name, old_value, new_value)

require_relative '../lib/gitlab_custom_hook'

if GitlabCustomHook.new(repo_path, key_id).update(ref_name, old_value, new_value)
  exit 0
else
  exit 1
end

示例图:

_images/20190705174524.png

/opt/codo/codo-scripts/gitlab/codo_task.py脚本内容

注意: 一定要修改脚本中accept_task_urlgit_urlauth_key内容

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/6/27 13:48
# @Author  : Fred Yangxiaofei
# @File    : codo_task.py
# @Role    : GitLab全局Hooks  update钩子


import sys
import os
import requests
import json


def post_codo_task():
    """
    监控全局钩子,CODO提交任务
    注意,Gitlab全局钩子调用此脚本的时候不能使用format
    :return:
    """
    # 修改你的钩子任务API接口
    accept_task_url = 'https://codo.opendevops.com/api/task/other/v1/git/hooks/'
    # 修改你的GIT地址
    git_url = 'http://gitlab.domain.com/'
    # 修改你的长期Token,从管理员获取, 此用户的Token需要对/task/other/v1/git/hooks/接口有权限
    auth_key = "eyJ0eXAiOiJeHAiOjE2NTY1NzgwOTUsIm5iZiI6MTU1Mjg5ODA3Nh"

    try:
        tag_name = sys.argv[1].split("/")[-1]  # tag/branch 名字
        repo_group = os.getcwd().split('/')[-2]  # 组名字
        repo_name = os.getcwd().split('/')[-1].replace('.git', '')  # git名字
        relative_path = repo_group + '/' + repo_name  # 组+git名字路径

        the_body = json.dumps({
            "git_url": git_url,
            "relative_path": relative_path,
            "tag_name": tag_name
        })

        req1 = requests.get(accept_task_url, cookies=dict(auth_key=auth_key))
        csrf_key = json.loads(req1.text)['csrf_key']
        cookies = dict(auth_key=auth_key, csrf_key=csrf_key)
        req = requests.post(accept_task_url, data=the_body, cookies=cookies)
        req_dict = json.loads(req.text)
        print('Hooks Log: ', req_dict.get('msg'))
    except Exception as e:
        print(e)


if __name__ == '__main__':
    post_codo_task()

第二步、CODO平台配置钩子规则

针对单个项目进行配置钩子规则,当你打Tag/brach中提交的的时候,根据你的匹配规则,正则匹配、来触发你所定义的任务
  • 选择其中一个项目,点击对应的编辑按钮

_images/create_git_hook01.png

_images/create_git_hook02.png

  • 提交测试钩子会在订单中心生成一个新订单,说明平台通道已经配置好

_images/create_git_hook03.png

  • 根据不同版本的gitlab有不同配置方式,老版本的gitlab由于API不完善,可以单独进行添加

_images/create_git04.png

_images/create_git05.png

_images/create_git_hook02.png

  • 都配置好之后可以自己打一个测试的tag进行测试

示例命令:

#基于branch
git touch test
git add --all
git commit -m "test"
git push -u origin master

#基于tag
git tag release-ftqqminigame-test01
git push -u origin release-ftqqminigame-test01

平台查看钩子日志

_images/20190705175739.png

注意

  • 填写的git仓库域名地址和对应参数必须真实有效,否则测试不通过将不会保存

监控告警

监控报警主要分为2部分,ZABBIX+Prometheus 都是基于Webhook做的

ZABBIX

本章主要介绍下CODO中的ZABBIX怎么使用,他能帮你做什么?

功能简介

  • 支持多ZABBIX配置
  • 支持多ZABBIX webhooks同时接入
  • 支持多ZABBIX webhook告警日志展示
  • 支持多ZABBIX 配置钩子实现故障自愈、自定义任务等
  • 获取多ZABBIX Last Issues统一展示,不再多个系统之间奔波

首先,点击ZABBIX配置,配置你的地址

_images/20190718170416.png 刷新地址,将已配置的ZABBIX组/主机Hostname拉取下来

_images/20190718175252.png

回到首页,你可以看到你多个ZABBIX Last Issues都统一展示出来了

_images/20190718175435.png

至此,到这一步,已经将ZABBIX的信息给获取下来了, 并且可以看到 Last ISSUES了

But,你如果觉得这些还不够,接下来想要对报警进行下一步的操作,比如我要故障自愈,那么你就要开始用钩子功能了

这部分的逻辑是配置权限--->配置ZABBIX webhook--->配置钩子---->根据告警tagger_name匹配--->故障自愈/自定义任务等操作

那么,让我们开始吧。

配置权限

  • 权限配置用于向平台提交任务的权限,需要用户输入对应的API接口和Auth_key
  • auth_key:是管理员生成的长期Token
  • task_url:https://codo-v1.domain.com/api/task/v2/task/accept/

测试保存,这里会进行权限认证,只有通过了认证才能保存成功。

_images/20190718175850.png

配置钩子

选择一台机器,进行配置钩子

新建一个钩子, 这里可以配置多个 那么这里是怎么匹配的呢? 简单记录下。

  • 收到告警后,开始根据告警的ZABBIX地址+ZABBIX 主机查询 这个主机有配置钩子
  • 如果有钩子规则,开始全匹配告警的tagger_name和你配置的tagger_name是不是一致的,一致的之间触发任务

_images/20190719095329.png

测试钩子

  • 模拟ZABBIX告警信息来测试告警是否匹配,从而触发钩子任务

./_static/images/.png

_images/20190719095734.png

_images/20190719095806.png

从上图可以看到,正常匹配到了,触发了任务, 数据也传了过来,接下来了有数据,用户可以实现自己的逻辑了。

那么如果告警没匹配怎么办, 我们来测试下

_images/20190719095806.png

可以看到,他会给我说匹配不到钩子

_images/20190719100136.png

钩子日志

我们通过刚来的测试看下钩子日志

  • 匹配到的会记录下来,并打出来执行的模板等信息
  • 接收到的告警,没匹配也会记录下来,但是不做任何操作

_images/20190719100312.png

ZABBIX webhook

到了这一步,我们都是平台配置和测试,那么如果想要接入ZABBIX告警信息,就必须要借助的ZABBIX 的webhook功能

这里我们接着操作,接入ZABBIX,实现全局监控ZABBIX告警,自动触发,故障自愈,自定义任务等操作

ZABBIX的版本迭代也是蛮快的,为了更好的让用户使用,不同的版本我写了不同的适配脚本来实现, 差别不大

谈一下ZABBIX配置, 这里只要是配置一个ZABBIX mediatype,和 Action触发器,将告警信息发到我的接口里面,我来帮你分析

先来讲一下ZABBIX2.0

ZABBIX 2.0 的版本是不支持mediaType里面传参的,但是他有三个默认参数,$3是邮件内容 $2 邮件标题 $1 发送给谁

既然他不支持自定义参数,那我们就借助他的默认参数,这里我用到了$2 第二个标题参数

先将脚本放到服务器上

脚本放在那? 这个要看你配置在那里了,不管是Mail\SMS\Webhooks 只要是触发脚本类型的都在这里

#让我们查一下你的配置是什么?

$ grep -r "AlertScriptsPath" /etc/zabbix/zabbix_server.conf

AlertScriptsPath=/usr/lib/zabbix/alertscripts   #脚本就放在这里

ZABBIX2.0版本

官方示例脚本:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/7/10 10:09
# @Author  : Fred Yangxiaofei
# @File    : send_alert.py
# @Role    : Zabbix webhooks 发送告警信息测试


# zabbix3.0+配置

import sys
import requests
import json


def send_alert(zabbix_url, webhook_url, messages):
    # 这里就是一个长期Token,管理员可以在用户列表选择一个用户进行生成一个长期Token, 但是需要对/tools/v1/zabbix/hooks/接口有权限
    params = {
        "auth_key": "eyJ0eXAiOiJKV1QiLCJhbGciSmW4m45L4w5XjDHPU3yBIzU0gfWeKnLH3SV4gFPLN6g"
    }
    # payload = "{\"data\": \"test\"}"
    payload = {"zabbix_url": zabbix_url, "messages": messages}
    headers = {'content-type': "application/json", 'cache-control': "no-cache"}
    response = requests.post(url=webhook_url, data=json.dumps(payload), headers=headers, params=params)
    print(response.text)


if __name__ == '__main__':
    # 你的ZABBIX地址,高版本ZABBIX你也可以从ZABBIX配置中传过来,请确保你和CODO平台上配置的一模一样
    zabbix_url = 'http://zabbixdoamin.com/zabbix'

    webhook_url = 'https://codo.domain.com/api/tools/v1/zabbix/hooks/'


    # ZABBIX的告警信息,这个我要用到,所以就要强规范:{HOSTNAME}___{HOST.IP}___{TRIGGER.NAME}___{TRIGGER.STATUS}___{TRIGGER.SEVERITY}
    messages = sys.argv[2]

    send_alert(zabbix_url, webhook_url, messages)

"""
如何使用:

pip install json
pip install requests

如何测试:

python send_alert_to_codo.py '' 'Zabbix server___127.0.0.1___Zabbix agent on Zabbix server is unreachable for 5 minutes___PROBLEM___Average'
"""

配置好了脚本,我们来配置2版本的ZABBIX

_images/20190719101037.png

配置一个Action

这里为了不影响你现有的,我们之间配置一个新的

但是这里切记标题是强规范,将我的标题给复制进去,其余的不重要


{HOSTNAME}___{HOST.IP}___{TRIGGER.NAME}___{TRIGGER.STATUS}___{TRIGGER.SEVERITY}

_images/20190719101654.png

_images/20190719101829.png

_images/20190719101943.png

以上,是ZABBIX 2.0版本的配置

ZABBIX3.0配置webhook

现在相信很多人也都用了最新的ZABBIX,那么我们必然也要支持以下了,ZABBIX 3.0+就支持自定义传参了,这个还是挺人性化的, ZABBIX3.0和2.0的配置思路一样,接下来让我们开始吧。

先将脚本放到服务器上

脚本放在那? 这个要看你配置在那里了,不管是Mail\SMS\Webhooks 只要是触发脚本类型的都在这里

#让我们查一下你的配置是什么?

$ grep -r "AlertScriptsPath" /etc/zabbix/zabbix_server.conf

AlertScriptsPath=/usr/lib/zabbix/alertscripts   #脚本就放在这里

ZABBIX3.0版本

官方示例脚本:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/7/10 10:09
# @Author  : Fred Yangxiaofei
# @File    : send_alert.py
# @Role    : Zabbix webhooks 发送告警信息


# zabbix3.0+配置

import sys
import requests
import json


def send_alert(zabbix_url, webhook_url, messages):
    # 这里就是一个长期Token,管理员可以在用户列表选择一个用户进行生成一个长期Token, 但是需要对/tools/v1/zabbix/hooks/接口有权限
    params = {
        "auth_key": "eyJ0eXAiOiJKV1QiLCJ.SmW4m45L4w5XjDHPU3yBIzU0gfWeKnLH3SV4gFPLN6g"
    }
    # payload = "{\"data\": \"test\"}"
    payload = {"zabbix_url": zabbix_url, "messages": messages}
    headers = {'content-type': "application/json", 'cache-control': "no-cache"}
    response = requests.post(url=webhook_url, data=json.dumps(payload), headers=headers, params=params)
    print(response.text)


if __name__ == '__main__':
    zabbix_url = 'http://xxxxx/zabbix'  # 你的ZABBIX地址,高版本ZABBIX你也可以从ZABBIX配置中传过来
    webhook_url = sys.argv[1]
    messages = sys.argv[2]

    send_alert(zabbix_url, webhook_url, messages)

"""
如何使用:

pip install json
pip install requests

如何测试:

python send_alert_to_codo.py https://codo.domain.com/api/tools/v1/zabbix/hooks/ alert_message_test
"""

ZABBIX3.0配置

_images/20190719101943.png

_images/20190719102304.png

配置一个Action

这里为了不影响你现有的,我们之间配置一个新的

但是这里切记标题是强规范,将我的标题给复制进去,其余的不重要


{HOSTNAME}___{HOST.IP}___{TRIGGER.NAME}___{TRIGGER.STATUS}___{TRIGGER.SEVERITY}

_images/20190719102659.png

_images/20190719102808.png

_images/20190719102916.png

接下来就完成了,你可以触发一个告警,进行测试了。

资产管理

这部分主要介绍CMDB资产管理一期,更多新功能正在开发中,现版本详细操作也可观看视频示例

添加主机

  • 管理用户: 例如AWS的ec2-user
  • 其余字段不做多解释,从字面可以看出意思

_images/cmdh_add_host.png

资产更新

选择主机进行资产更新,这里为手动更新,默认系统会每天进行后台自动更新

_images/cmdb_asset_update.png

_images/asset_server_detail.png

同步标签树

不需要选中主机,同步标签树是一个和作业配置中标签树进行了打通,如果需要CMDB的数据同步到标签树里面则点击此按钮即可同步,同步后数据以CMDB为主,标签树里面多出来的则会被删除,谨慎操作。

_images/cmdb_sync_tag.png

机器状态

CMDB中的几种状态

  • New:表示手动新增的机器
  • Auto:表示自动从云厂商拉取过来的主机,这个时候主机详情的信息都是云上获取到的一些基础信息
  • True:表示已经手动点了资产更新的操作,这时候资产信息都是从主机系统上脚本获取到的信息
  • False:表示更新资产失败,这个状态下是可以查看错误日志的

DB管理

这里DB管理第一版只是简单的记录,没有规划很多功能,很多字段也是预留字段,后续会做成自动相关的

_images/asset_db.png

标签管理

取消了组的概念,Tag设计的出发点就是伪组,这里也是将机器分类

_images/asset_tag.png

管理用户

  • 将私钥放在平台上,平台是根据这个私钥去连接你的主机的,例如:AWS的ec2-user

_images/asset_admin_user.png

资产配置

这一块主要用来用户给我配置一些Key信息,我去APi接口里面把机器给获取下来加到CMDB里面

自动拉取,后端日志统一在:tailf /var/log/supervisor/cmdb_cron.log

  • 只有状态按钮为开启状态,系统才会去你配置的区域里面去拉取主机信息
  • 请确保你填写的AccessID/AccessKey/Region区域信息的准确性,可点击测试按钮进行测试权限
  • 最好能够确保你机器的Hostname是唯一值,CMDB设计中Hostname是不允许重复的,自动必然要有一些规范
  • 默认管理用户:此用户是可以登陆机器的,若此处填写了默认管理用户,会自动给机器关联上此用户,用于后续资产更新连接使用,一般情况下管理用户一个账户里面OPS都是1-2个,毕竟太多OPS自己维护起来也很麻烦
  • 自动获取来的机器状态都是Auto状态,若不配置管理用户,默认资产详情信息都是从云平台获取的一些基本信息,若配置了管理用户并更新了资产,资产信息来源基于系统本身获取到的
  • 拉取资产按钮:手动触发云厂商主机更新到主机列表,默认情况下6小时会自动更新一次,请不要频繁点击,可能会产生调用接口费用(AWS)
  • 若此处配置了,系统会自动调用请求云厂商主机详情脚本(只要有查询实例的权限即可),将指定区域的配置自动拉取并写入CMDB中,另外AWS测试可能需要5~10s不等,因为请求接口都在国外

_images/asset_config.png

配置中心

这部分主要介绍下配置中心使用说明, 戳我参考最佳实践示例

新建项目

_images/configuration_center01.png

填写环境-服务等信息 _images/configuration_center02.png

对项目授权

对整个项目授权是可以看到整个项目里面的配置

_images/configuration_center03.png

对单个环境授权

对单个环境授权:项目下若有多个环境,授权的用户只能看到指定的环境

_images/configuration_center04.png

如何获取配置

那么我新建了一个配置,我怎么获取到他呢? 没关系我们提供了获取配置的示例

Python版本


class ConfApi:
    def __init__(self):
        # self.auth_key 是一个长期Token,基于用户管理里面,管理员选中用户生成长期Token,默认发送到用户邮箱
        self.auth_key = 'eyJ0eXAiOiJKV1QiLCJhbmZpZyIsIm5pY2XcFBbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTMwMzQyNzYsIm5iZiI6MTU1Nzk5NDI1NiwiaWF0IjoxNTU3OTk0Mj3ZjZlXHU3NTI4XHU2MjM3IY2LCJpc3MiOiJhdXRoOiBzcyIsInQiOiIxNTYxODcxODA2MCIsImRhdGEiOnsidXNlcl9pZCI6NjYsInVzZXJuYW1lIjoiZ2V0X2NvFOOo'
        self.conf_path ='/tmp'
        self.conf_config_api = "https://codo.domain.com/api/kerrigan/v1/conf/publish/config/"   #配置中心获取API



    def get_config_details(self, project_code, environment, service, filename):
        # 获取配置文件内容,  2019-04-28支持URL auth_key登陆,不需要再登陆进行获取auth_key,直接生成长期Token用
        #__token = self.login()

        __token = self.auth_key
        try:
            _params = {'project_code': project_code, 'environment': environment,'service':service,'filename':filename, 'auth_key': __token}
            res = requests.get(self.conf_config_api, params=_params)
            ret = json.loads(res.content)
            if ret['code'] == 0: return ret['data']
        except Exception as e:
            print('[Error:] 发布配置接口连接失败,错误信息:{}'.format(e))
            exit(-2)



    def create_config_file(self, project_code, environment, service, filename):
        # 生成配置文件
        config_data = self.get_config_details(project_code, environment, service, filename)
        for k,v in config_data.items():
            config_file = self.conf_path + k
            dir_name, _ = os.path.split(config_file)
            if not os.path.exists(dir_name):
                os.makedirs(dir_name)
            with open(config_file ,'w') as f:
                f.write(v)
        #     print('config file path is {}'.format(config_file))
        # print('success')
        return config_file  #返回文件路径

def main():
    obj = ConfApi()
    config_file = obj.create_config_file('DNS', 'release', 'dnsmasq', 'dnsmasq.conf')
    hosts_config_file = obj.create_config_file('DNS', 'release', 'dnsmasq', 'dnsmasq_hosts')

if __name__ == '__main__':
    main()

Go版本

go run write_conf.go -p code-v1 -e dev -s codo-admin -f settings.py -r /tmp/settings.py1

// 用golang编写,可以应付多种环境,并且可以对文件编译,防止密钥泄露
package main

import (
 "encoding/json"
 "flag"
 "fmt"
 "io/ioutil"
 "os"

 "github.com/kirinlabs/HttpRequest"
)

const (
 authKey = "eyJ0eXAiOiJKV1QiLCJ2MCIsImRhdGEiOnsidXNlcl9pZCI6MjgsInVzZXJuYW1lIjoic3MtdGVzdhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTQ4MjzdXBlcnVzZXIiOmZhbHNlfc2MDYsIm5iZiI6MTU1OTc4NzU4NiwiaWF0IjoxNTU5Nzg3NTk2LCJpc3MiOiJhdXRoOiBzcyIsInN1YiI6Im15IHRva2VuIiwiaWQiOiIxNTYxODcxODACIsIm5pY2tuYWJpc19X0.gMGMRKqtd_CM6rIzE8mxuwR8c8dz_hyH21FETOO4XbE"
 confURL = "https://codo.domain.com/api/kerrigan/v1/conf/publish/config/"
)

var (
 project_code string
 environment  string
 service      string
 filename     string
 realfilename string
 configData   string
)

func getArgs() error {
 flag.StringVar(&project_code, "p", "ss", "项目代号")
 flag.StringVar(&environment, "e", "dev", "环境")
 flag.StringVar(&service, "s", "app", "应用名称")
 flag.StringVar(&filename, "f", "settings.py", "文件名")
 flag.StringVar(&realfilename, "r", "/tmp/settings.py", "最终写入文件")
 flag.Parse()
 if project_code == "ss" {
  fmt.Println("[Error] 参数不正确,请使用参数 --help 查看帮助")
  os.Exit(-5)
 }
 return nil
}

func writeWithIoutil(name, content string) {
 data := []byte(content)
 if ioutil.WriteFile(name, data, 0644) == nil {
  fmt.Println("[Success] 修改配置成功")
 }
}

func main() {
 getArgs()
 req := HttpRequest.NewRequest()

 // 设置超时时间,不设置时,默认30s
 req.SetTimeout(30)

 // 设置Headers
 req.SetHeaders(map[string]string{
  "Content-Type": "application/x-www-form-urlencoded", //这也是HttpRequest包的默认设置
 })

 // 设置Cookies
 req.SetCookies(map[string]string{
  "auth_key": authKey,
 })

 // GET
 resp, err := req.Get(confURL, map[string]interface{}{
  "project_code": project_code,
  "environment":  environment,
  "service":      service,
  "filename":     filename,
 })

 if err != nil {
  fmt.Println("[Error]", err)
  // log.Println(err)
  os.Exit(-1)
 }

 if resp.StatusCode() == 200 {
  body, err := resp.Body()

  if err != nil {
   fmt.Println("[Error]", err)
   os.Exit(-2)
  }

  res := make(map[string]interface{})
  json.Unmarshal(body, &res)

  for _, v := range res["data"].(map[string]interface{}) {
   configData = fmt.Sprintf("%v", v)
  }
 } else {
  os.Exit(-3)
 }
 writeWithIoutil(realfilename, configData)
}

用户管理

这部分文档主要用来介绍用户管理,它可以很精细的管理你的用户权限

用户列表

用户列表:顾名思义,用来管理和展示用户的列表,记录用户的详细信息

功能支持

  • 搜索用户
  • 新建用户
  • 删除用户
  • 关闭用户
  • 重置密码
  • 重置MFA(Google Authenticator)
  • 生成长期Token(管理员)

展示界面

_images/user_list.pnguser_list

权限列表

用来详细配置管理每个接口的权限,默认不需修改。

注意事项

  • 系统默认已经配置了所有权限和方法,管理员默认拥有/权限,无需修改,以免造成系统请求某功能出错

功能说明

  • 支持多种搜索方式,如:权限名称、请求路径、请求方法、时间等
  • 支持新增、编辑、关闭、删除等操作权限的管理
  • 支持新增自定义权限功能,适用于开发人员编写的API接口能很方便的接入进来权限管理划分
  • 一些详细的API及使用文档正在支持更新中............

_images/permission_list.pnguser_list

菜单组件

菜单组件:顾名思义,也就是导航栏所看到的功能模块(如:用户管理、系统管理)和一些功能按钮(如:编辑、删除按钮),默认无需修改

注意事项

  • 系统默认已经配置了所有菜单功能模块及组件,无需修改此项,以免造成访问出错。

功能介绍

列举以下几个菜单和组件进行介绍,字面英语也可看出含义,如下:

  • home:家目录
  • usermanage:用户管理
  • cron:定时任务
  • edit_button:编辑按钮

由于代码层面不好直接使用中文,你可以选择平台语言English,如下图,很清晰看到每个作用。

_images/menusv2.pngmenus

角色管理

基于RBAC角色管理访问控制权限,可以很精细/方便的管理你的用户权限

功能介绍

  • 角色的搜索、编辑、关闭、删除
  • 自定义角色名字,自定义赋权组件、菜单、权限管理
  • 列表可搜索赋权设计,方便用户可视化操作

_images/rbac.pngrbac

示例介绍分为两部分,创建管理员用户赋权和创建普通用户赋权

创建普通用户示例

新建用户

同上,填写信息即可,详细权限管理全部在角色管理配置

用户赋权

_images/create_general_user.pngcreate_general_user

_images/general_user_epmv2.pnggeneral_user_epm

创建管理员用户示例

新增用户

点击用户列表---新增用户,输入信息

_images/create_user.pngcreate_user

用户赋权

点击角色管理---新建,输入角色信息,选择角色进行赋权

_images/create_rbac.pngcreate_rbac

_images/general_user_epmv2.pnguser_emp

_images/user_emp02.pnguser_emp02

_images/user_emp03.pnguser_emp03

获取长期Token

本系统使用token进行身份验证,当用户需要API进行访问的时候就需要获取token,并把token放入cookie里或者 访问的url参数里
  • 从用户管理 > 菜单组件里面找到 get_token_btn 这个代表获取token的按钮 要存在并且启用
  • 从用户管理 >角色管理里面找到你要赋值的角色,点击组件把get_token_btn 添加进去

https://raw.githubusercontent.com/opendevops-cn/codo-admin/master/doc/images/tianjiazujian.png

  • 从用户管理 > 用户列表 会看到这个长期token的按钮,如果你是超级管理员 你就可以选中用户点击,然后系统会通过邮件把这个用户的token 发送至当前用户以及被选中用户的邮箱,token 有效期为三年。强烈建议如果使用token进行操作的时候 使用单独用户,防止人员变动造成token不可用,要进行精确权限控制,做好备注,且不要给此用户菜单以及组件权限。

https://raw.githubusercontent.com/opendevops-cn/codo-admin/master/doc/images/get_token.png

  • 使用token 向 CODO 服务 API 提交安全的 REST 或 HTTP 查询协议请求。为了您的安全,请不要与任何人分享您的密钥。作为最佳做法,我们建议经常更换密钥
  • 简单python示例,当然你之前一定会检查这个token是否对这个接口有权限,对吧!
import requests
import json

auth_key= '这里就是你的token'
url = 'https://xxx.xxxx.cn/api/kerrigan/v1/conf/publish/config/?project_code=shenshuo&environment=dev&service=nginx&filename=demo.conf'
### 使用 cookie 传递
try:
    res = requests.get(url, cookies=dict(auth_key=auth_key))
    ret = json.loads(res.content)
    if ret['code'] == 0: return ret['data']
except Exception as e:
    print('[Error:] 接口连接失败,错误信息:{}'.format(e))
    exit(-1)

### 使用url 传递
try:
    _params = {'这里是参数名': '这里是参数值', 'auth_key': auth_key}
    res = requests.get(url, params=_params)
    ret = json.loads(res.content)
    if ret['code'] == 0: return ret['data']
except Exception as e:
    print('[Error:] 接口连接失败,错误信息:{}'.format(e))
    exit(-2)

系统管理

这部分主要介绍系统配置,系统管理模块主要分为:系统配置系统日志

系统配置

系统配置主要介绍系统参数配置,后续后陆续支持各种核心功能配置

系统配置

这块需要配置你的API地址,部署时你API网关服务所部署的服务器地址,只有确认了API网关,各个功能模块才可以正常通信。
  • API地址: 你的API网关地址,可以是IP/域名,必填项。 API网关部署

_images/api_addressv2.png

邮件设置

这块主要配置邮箱,配置了此邮箱信息后,后续平台内所涉及到邮件提醒都会使用此邮箱配置。

不同运营商配置可参考FAQ邮箱设置问题

  • SMTP主题: 邮件标题
  • SMTP主机: 服务器地址
  • SMTP端口: 服务器端口
  • SMTP账户: 邮箱账户名
  • SMTP密码: 邮箱账户密码
  • 如果SMTP端口是465,通常需要启用SSL
  • 如果SMTP端口是587,通常需要启用TLS
  • 点击测试邮件会给当前用户发送一封邮件用于测试

_images/system_email.png

短信接口

这块主要配置短信接口信息,短信接口只支持阿里云阿里大鱼,后续平台所涉及到发短信会调用此接口
  • 短信区域: cn-hangzhou 目前阿里官方给出必须是这个
  • API名称: Dysmsapi 目前官方给出一般都是这个名称
  • API域名:dysmsapi.aliyuncs.com 目前官方给出必须是这个地址
  • KEY_ID: 你的IAM访问控制密钥ID
  • KEY_SECRET: 你的access_secret密钥,备注:这里需要必须有SMS的权限
  • 点击测试端口系统会向阿里大鱼进行发送查询接口,如果配置验证不通过则提示报错信息

_images/system_smsv2.png

LDAP设置

这块主要用于配置LDAP认证

实例图如下:

_images/ldap.png

邮箱登陆

这块主要是支持第三方邮箱登陆,当你想要使用邮箱登陆此平台时,你可以在此进行配置 比如我们企业邮箱是腾讯的,域名就是opendevops.cn,SMTP就是腾讯的stmp.exmail.qq.com,这样配置完成后我就可以使用我yanghongfei@opendevops.cn邮箱+密码登陆此平台了。
  • 邮箱SMTP: 这里输入你邮箱服务商的SMTP地址
  • 邮箱域名:这里是你的邮箱后缀名字

_images/system_email_loginv2.png

存储配置

这块主要是配置Bucket信息,目前只支持阿里云的OSS,这里目前主要用于将跳板日志审计的内容存放到OSS目录里面,若不配置此项则存本地数据库(可能会很大,建议配置OSS)
  • 区域Region:阿里云的可用区域,如:cn-hangzhou
  • 存储桶名称: Bucket名称
  • SecretID: 密钥ID,需要有OSS权限
  • Secret Key: 密钥Key,需要有OSS权限

_images/system_bucketv2.png

系统日志

这里主要记录的本系统平台的所有请求日志,如:GET/POST/DELETE/PUT等,你的操作信息都会被记录,不要随意干坏事哟,管理员都可以看到的,安全我们还是会考虑进去的。

_images/system_log.png

最后,感谢你的支持,我们正在不断完善文档和平台功能,你也可以加入我们的的社区交流群进行反馈信息,给我们带来你的意见和建议。

权限文档

这部分主要讲解关于系统中权限相关的说明,注意:超级管理员用户不受权限限制,默认拥有所有权限

关于User用户管理

关于超级管理员

默认登陆用户admin已经是超级管理员权限了若想要其余用户也赋权超级管理员进行以下操作(不建议多个超管)

在数据库codo_adminmg_users表字段 superuser

  • 0:代表超级管理员
  • 10:代表普通用户

管理员如何创建一个带MFA的用户

注意: 平台设计的时候为了安全考虑创建/注册用户都是需要绑定MFA的,若你实在想要取消,需要自己去update数据库

  • 点击菜单栏用户管理-用户列表-新建用户, MFA使用参考FAQ _images/create_user01.png _images/create_user02.png _images/create_user03.png _images/create_user04.png _images/create_user05.png

关于Mail邮箱注册

管理员一个个创建用户太过麻烦,我们支持邮箱注册,比如你是企业邮箱,你只需轻松2步,你就可以实现邮箱注册,让企业用户自己注册,管理员只管赋权就Ok,是不是很方便。
  • 首先用超级管理员账户在平台上填写邮箱相关信息

_images/create_email01.png

  • 然后在登陆界面直接用设置后的邮箱后缀为结尾的有效邮箱进行登陆,密码为邮箱登陆密码,确认相关信息,关于邮箱设置相关的也可参考FAQ

_images/create_email02.png

关于LDAP认证

既然支持了邮箱注册,那么肯定也要支持LDAP认证方式
  • LDAP地址: 你的LDAP地址
  • LDAP端口: 默认389 SSL端口:636
  • 绑定DN: cn=Manager,DC=opendevops,DC=cn,这里是设置认证用户的信息, 系统会使用这个用户去校验ldap的信息是否正确
  • 密码: 上面认证用户的密码
  • 用户OU: ou=opendevops,dc=opendevops,dc=cn,这里是设置用来登录codo的组织单元, 比如我要用某个ou的用户来登录codo
  • 用户过滤器: cn 这里是设置认证用户的信息, 系统会使用这个用户去校验ldap的信息是否正确 一般使用cn 或者 sAMAccountName
  • LADP属性映射: {"username": "cn", "email": "mail"}或者{"username": "cn", "email": "email"}
    • 系统用户名 usernmae 映射LDAP的cn。 系统用户邮箱映射LDAP的email或者mail属性,取存在的,强制关联,如果缺失报错, 这里的意思是, 把ldap用户的属性映射到系统上,如果都不存在的 认证无法通过,系统用户的email是必填项
  • 启动LDAP认证:如果需要使用LDAP登录 codo, 则必选

最后配置好以上内容后,请切记先保存再测试,测试通过登陆请使用ldap映射来的cn用户名+你LDAP密码来登陆

_images/LDAP.png

关于Role角色管理

  • 基于RBAC角色管理,用来权限划分, 根据个人需求对创建的角色添加相对应的用户、菜单、组件和权限

_images/role-permission01.png _images/role-permission02.png _images/role-permission03.png _images/role-permission04.png _images/role-permission05.png _images/role-permission06.png

关于CMDB资产管理授权

资产管理是支持针对Tag标签对普通用户授权 展示不同的资产
  • 选择一个新建/已存在的标签,选择授权用户

_images/asset_management01.png

_images/asset_management0102.png

  • 最后,普通用拥有哪些标签的权限,主机就只能看到哪些

_images/asset_management03.png

关于Tag标签树授权

标签树里面的标签: 可以理解为任务标签,做任务的时候要用到的,这里需要对用户授权 用户才可以对此标签进行提交任务,举个例子:我要对xxx游戏的数据库执行SQL审核的操作,前提是我对这款游戏的数据库已经做好了Tag分类,我需要在这个Tag上授权上我的用户这样子我就可以通过自定义任务--->选择目标标签的时候就可以下拉看到你的标签,如果这时候你对xx标签没赋权,你是下拉看不到的。

_images/20190606134817.png

  • 授权操作

_images/task_tag01.png

_images/task_tag02.png

关于Task任务模板授权

我们的任务模板都是有权限之分的,当管理创建好了一个任务模板需要相关用户进行授权,否则其余用户是不能对模板操作/显示此模板的任务的
  • 模板授权很简单,选择你创建好的模板,授权相关用户即可

_images/task_template.png

关于Config配置中心授权

配置中心是支持多项目多环境的,那么如何针对一个用户对不同的项目/不同的环境进行授权呢? 这里我们授权设计的也很简单,点击项目/环境 即可授权
  • 对整个项目进行授权,可以管理此项目

_images/configuration_center03.png

  • 对单个环境授权(当项目下有多个环境,只想让指定用户查看指定的环境时候用)

_images/configuration_center04.png

示例文档

关于任务系统的一些视频示例

戳这里观看OpenDevOps任务平台示例视频

视频里简单介绍了以下几种示例,至于模板里面的最终逻辑需要使用人根据自己的需求进行排版,编写等,不限制语言。

  • 示例1. 平台上提交一个最简单的任务,不带参数的
  • 示例2. 平台上提交一个带参数的任务。(PARAMETER)
  • 示例3. 平台上基于JSON自定义提交一个任务
  • 示例4. 不登陆平台的情况下怎么提交一个任务(POST API提交)
  • 示例5. 怎么根据Git Hooks来提交一个任务
  • 示例6. 怎么借助定时任务系统每天进行提交一个任务,(比如:备份)

文档

视频中涉及到的相关文档

  • Git钩子
  • [任务模板](http://docs.opendevops.cn/zh/latest/task_template.html

脚本

视频中涉及到一些示例脚本

示例3. 平台上基于JSON自定义提交一个任务, JSON内容

{
	"task_name": "这是通过JSON提交的任务",
	"submitter": "yanghongfei", 
	"temp_id": "1", 
	"schedule": "ready",   
	"exec_time": "2019-5-24 09:09:50", 
	"associated_user": "{'group-1': ['杨红飞']}",
	"args": "{'VERSION':'你可以看到我这次传入的参数是VERSION,但是显示成了版本,是因为我在参数管理里面设置了别名'}",
	"details": "这里是备注",
	"hosts": "{1: '172.16.0.101'}"  
}

示例4. 不登陆平台的情况下怎么提交一个任务(脚本提交)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Fred Yangxiaofei
# @File    : codo_post_task.py
# @Role    : 利用脚本向平台提交一个任务

import json
import datetime
import requests


def post_task(temp_id, schedule):
    """
    :param temp_id:  模板ID,平台里面任务模板里面查看
    :param task_status: 提交任务的状态,常用的为:ready: 表示不需人工干预,平台直接执行,new: 平台需要选择审批。根据审批时间执行。
    :return:

    """

    #平台接口连接,这里只需要修改域名即可, 任务API连接都是我们内置进去的,在【用户管理】-【权限列表】 权限名称:钩子提交任务
    accept_task_url = 'https://<域名地址>/api/task/v2/task/accept/'

    #这里就是一个长期Token,管理员可以在用户列表选择一个用户进行生成一个长期Token,这个用户需要有权限名称:钩子提交任务的权限
    auth_key = "yODk4MDX19.BgP8UAoNiBkzJNSN1pa-eQVjlAxrKGxYZf0YgvXv39k"


    # 执行主机IP地址, 1代码第一组
    hosts = {1: '172.16.0.101'}
    #这里都是传入的参数
    args = {
        "TAG": 'codo-beta0.3',
        "GIT_URL": "git@gitlab.xxxxxxx.com:xxxxx/xxxxx.git",
        "APP_NAME": "Web"
    }
    the_body = json.dumps({
        "task_name": "脚本任务", #修改此项
        "temp_id": temp_id,
        "args": str(args),
        "details": "通过脚本提交一个自定义的任务",
        "hosts": str(hosts),
        "submitter": "yanghongfei",
        "exec_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        "schedule": schedule,
        "executor": "yanghongfei"
    })


    req1 = requests.get(accept_task_url, cookies=dict(auth_key=auth_key))
    csrf_key = json.loads(req1.text)['csrf_key']
    cookies = dict(auth_key=auth_key, csrf_key=csrf_key)
    req = requests.post(accept_task_url, data=the_body, cookies=cookies)
    req_code = json.loads(req.text)['code']
    if req_code != 0:
        # print(json.loads(req.text)['msg'])
        print('task commit failed Please contact  OPS Group')
        exit(-111)
    else:
        # print(json.loads(req.text)['msg'])
        print('Asynchronous task has been submitted successfully!!!')
        print('Please do not submit multiple times to prevent the task from jamming!!!')


if __name__ == '__main__':
    print(post_task('1', 'new'))

示例5. 怎么根据Git Hooks来提交一个任务 主要基于GitLab Custom HooksGitLab Tag借助opendevops平台实现自动化发布,以下为所用到的功能简单介绍。 这里基本上和上面一样,就是多一个怎么用update钩子获取Tag

为什么使用Git TAG发布,然后再接到平台里面呢?

  • 进度可视化
  • 平台发布记录
  • Git Tag 可快速回滚
  • 权限控制,可由PM登陆平台审核后发布
  • 可定时执行,报错可重装,不同项目需求可根据实际编写脚本进行排版任务等。

配置钩子

GitLab Hooks分为2种:

  • Hooks:全局钩子,适用于所有项目
  • Custom Hooks: 项目钩子,针对项目来做钩子触发任务

如何使用?

本章主要使用项目钩子,不建议使用全局钩子,这样会出问题,亲自尝试,毕竟我们的需求是针对xxx项目进行做自动化发布的。

登陆GitLab服务器操作

$ cd <project_name>.git/
$ mkdir -p custom_hooks ; chown -R git.git custom_hooks; chmod 777 custom_hooks

创建Update钩子


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/5/24 10:31
# @Author  : Fred Yangxiaofei
# @File    : git_tag_post_task.py
# @Role    : 基于Git Tag来提交一个任务



import sys
import json
import datetime
import requests
import re

def post_task(tag, temp_id, schedule):
    """
    :param temp_id:  模板ID,平台里面任务模板里面查看
    :param task_status: 提交任务的状态,常用的为:ready: 表示不需人工干预,平台直接执行,new: 平台需要选择审批。根据审批时间执行。
    :return:

    """

    #平台接口连接,这里只需要修改域名即可, 任务API连接都是我们内置进去的,在【用户管理】-【权限列表】 权限名称:钩子提交任务
    accept_task_url = 'https://<域名地址>/api/task/v2/task/accept/'

    #这里就是一个长期Token,管理员可以在用户列表选择一个用户进行生成一个长期Token,这个用户需要有权限名称:钩子提交任务的权限
    auth_key = "eyJ0eXAiOiTUyODk4MDg1LCJpc3McxODA2MCIsImRhdGEiOnsidXNlcl9pZCI6IWJsaXNoIiwibmlja25hbWUiOiJwdWJsaXNoIiwiaXNfc3VwZXJ1c2VyIjpmYWxzZX19.BgP8UAoNiBkzJNSN1pa-eQVjlAxrKGxYZf0YgvXv39k"


    # 执行主机IP地址, 1代码第一组
    hosts = {1: '172.16.0.101'}
    #这里都是传入的参数
    args = {
        "TAG": tag,
        "GIT_URL": "git@gitlab.xxxxxxx.com:xxxxx/xxxxx.git",
        "APP_NAME": "Web"
    }
    the_body = json.dumps({
        "task_name": "脚本任务", #修改此项
        "temp_id": temp_id,
        "args": str(args),
        "details": "通过脚本提交一个自定义的任务",
        "hosts": str(hosts),
        "submitter": "yanghongfei",
        "exec_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        "schedule": schedule,
        "executor": "yanghongfei"
    })


    req1 = requests.get(accept_task_url, cookies=dict(auth_key=auth_key))
    csrf_key = json.loads(req1.text)['csrf_key']
    cookies = dict(auth_key=auth_key, csrf_key=csrf_key)
    req = requests.post(accept_task_url, data=the_body, cookies=cookies)
    req_code = json.loads(req.text)['code']
    if req_code != 0:
        # print(json.loads(req.text)['msg'])
        print('task commit failed Please contact  OPS Group')
        exit(-111)
    else:
        # print(json.loads(req.text)['msg'])
        print('Asynchronous task has been submitted successfully!!!')
        print('Please do not submit multiple times to prevent the task from jamming!!!')


def main():
    '''获取TAG'''
    tag = sys.argv[1].split("/")[-1]
    qa = re.match(r'\Aqa-yanghongfei[\w]*',tag)     #测试 ,直接执行,ready
    release = re.match(r'\Arelease-yanghongfei[\w]*',tag)   #正式,需要审核,new

    if qa:
        print(post_task(tag, '1','ready'))
    elif release:
        print(post_task(tag, '1','new'))
    else:
         print(tag)



if __name__ == '__main__':
    main()

配置好钩子后,接下来克隆版本库进行提交测试

git clone git@gitlab.xxxxxx:xxx/xxx.git
git pull

echo "README" > README.md
git add --all
git commit -m "[Add] README,测试发布"
git push -u origin origin
git tag release-yanghongfei-v1  
git push -u origin release-yanghongfei-v1  #把tag推送上去

示例6. 怎么借助定时任务系统每天进行提交一个任务,(比如:备份)

这里的脚本和示例4一样,都是向平台提交一个任务,关于定时任务相关的

基于任务平台实现Git发布示例

环境

本章节实验环境主要基于GitLab Custom HooksGitLab Tag借助opendevops平台实现自动化发布,以下为所用到的功能简单介绍。

你需要具备以下环境:

发布为什么选择过OpenDevOps平台

  • 进度可视化
  • 平台发布记录
  • Git Tag 可快速回滚
  • 权限控制,可由PM登陆平台审核后发布
  • 可定时执行,报错可重装,不同项目需求可根据实际编写脚本进行排版任务等。

快速使用

这里废话不多说,直接上实践,至于Tag、Hooks、Depoly Keys不熟悉的请参考以上链接,也可自行百度。 发布流程:enable depoly keys->git clone–>git pull—>git checkout <tag>—>rsync_code—>code_backup—>publish code->publish OK~,平台历史记录可查看发布信息

创建模板

配置钩子

GitLab Hooks分为2种:

  • Hooks:全局钩子,适用于所有项目
  • Custom Hooks: 项目钩子,针对项目来做钩子触发任务

如何使用?

本章主要使用项目钩子,不建议使用全局钩子,这样会出问题,亲自尝试,毕竟我们的需求是针对xxx项目进行做自动化发布的。

登陆GitLab服务器操作

$ cd <project_name>.git/
$ mkdir -p custom_hooks ; chown -R git.git custom_hooks; chmod 777 custom_hooks

创建Update钩子

这里我有已经运行2年的脚本供各位参考。
 
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Fred Yangxiaofei
# @File    : new_hook_for_update.py
# @Role    : 利用gitlab Tag触发钩子像平台提交任务

import sys
import json
import datetime
import requests
import re


def post_task(tag, temp_id, schedule):
    """
    :param tag:      从gitlab钩子获取TAG信息
    :param temp_id:  模板ID,平台里面任务模板里面查看
    :param task_status: 提交任务的状态,常用的为:ready: 表示不需人工干预,平台直接执行,new: 平台需要选择审批。根据审批时间执行。
    :return:

    """
    #这里是浏览器Cookie里面auth_key,可使用超级管理员用户,平台获取长期auth_key
    auth_key = "va2VuIsImRhdGEiOnsi9.BgP8UAoNiBkzJNSN1pa-eQVjlAxrKGxYZf0YgvXv39k"  
    # 这里hosts必须是IP,CODO平台只走的是SSH协议,需要在执行用户配置链接主机的key,或者自行打通。
    hosts = {1: '118.25.xx.xx'}  # 上海Salt IP,执行主机IP。
    args = {
        "TAG": tag,
        "GIT_URL": "git@gitlab.xxxxxxx.com:xxxxx/xxxxx.git",  # 修改此项
        "APP_NAME": "DBTT"  # 修改此项
    }
    the_body = json.dumps({
        "task_name": "DBTT", #修改此项
        "temp_id": temp_id,
        "args": str(args),
        "details": "git hook auto exec",
        "hosts": str(hosts),
        "submitter": "githook",
        "exec_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        "schedule": schedule,
        "executor": "githook"
    })

    accept_task_url = 'https://codo-v1.domain.com/api/task/v2/task/accept/'
    req1 = requests.get(accept_task_url, cookies=dict(auth_key=auth_key))
    csrf_key = json.loads(req1.text)['csrf_key']
    cookies = dict(auth_key=auth_key, csrf_key=csrf_key)
    req = requests.post(accept_task_url, data=the_body, cookies=cookies)
    req_code = json.loads(req.text)['code']
    if req_code != 0:
        # print(json.loads(req.text)['msg'])
        print('task commit failed Please contact  OPS Group')
        exit(-111)
    else:
        # print(json.loads(req.text)['msg'])
        print('Asynchronous task has been submitted successfully!!!')
        print('Please do not submit multiple times to prevent the task from jamming!!!')

def get_tag():
    '''获取TAG'''
    tag = sys.argv[1].split("/")[-1]
    qa = re.match(r'\Aqa-dbtt[\w]*',tag)     #测试
    release = re.match(r'\Arelease-dbtt[\w]*',tag)   #正式

    if qa:
        print(post_task(tag, '32','ready'))  #这是模板ID
    elif release:
        print(post_task(tag, '32','ready'))  #这是模板ID
    else:
         print(tag)


if __name__ == '__main__':
    get_tag()

配置好钩子后,接下来克隆版本库进行提交测试

git clone git@gitlab.xxxxxx:xxx/xxx.git
git pull

echo "README" > README.md
git add --all
git commit -m "[Add] README,测试发布"
git push -u origin origin
git tag release-dbtt-server-20190320-02  #这里只要能让钩子里面正则匹配到dbtt-release都会被触发
git push -u origin release-dbtt-server-20190320-02  #把tag推送上去

最终的结果

_images/005X1wn0gy1g1exnc0cv9j30uc0iw75r.jpg

基于任务平台实现SQL优化示例

列举一个平台上任务发布里面SQL优化部分的实例,让大家快速灵活的使用OpenDevOps平台,进行实战操作;

**创建一个需要操作的数据库标签**

新建标签

点开作业配置-标签树-root-新建标签

  • 具体字段参数含义详见使用文档--作业配置--标签树

_images/create_new_tag_tree.png

注意

授权用户:只有授权过的用户,在创建任务发布时才有权限对该标签操作

代理配置

预先配置好代理服务器地址,用于创建标签树下DB时可供选取,该代理是用来连接无外网状态下的数据库而存在的。
  • 具体字段参数含义详见使用文档--作业配置--代理配置

_images/create_new_proxy.png

_images/create_new_inception.png

新建DB

点开作业配置-标签树-DB-添加数据库
  • 具体字段参数含义详见使用文档--作业配置--标签树

_images/create_new_db.png

创建一个SQL优化任务发布

点开任务发布--SQL优化

_images/create_new_optimization.png

注意

  • 截图右侧查询结果是在自动创建订单结束后回显得到的,生成的订单是自动执行,无需其他操作

会在任务列表自动创建一个订单

点开订单中心--订单列表

_images/optimization_task.png

基于任务平台实现SQL审核示例

列举一个平台上任务发布里面SQL审核部分的实例,让大家快速灵活的使用OpenDevOps平台,进行实战操作;

创建一个需要操作的数据库标签

新建标签

点开作业配置-标签树-root-新建标签

  • 具体字段参数含义详见使用文档--作业配置--标签树

_images/create_new_tag_tree.png

注意

授权用户:只有授权过的用户,在创建任务发布时才有权限对该标签操作

代理配置

预先配置好代理服务器地址,用于创建标签树下DB时可供选取,该代理是用来连接无外网状态下的数据库而存在的。
  • 具体字段参数含义详见使用文档--作业配置--代理配置

_images/create_new_proxy.png

_images/create_new_inception.png

新建DB

点开作业配置-标签树-DB-添加数据库
  • 具体字段参数含义详见使用文档--作业配置--标签树

_images/create_new_db.png

创建一个SQL审核任务发布

点开任务发布--SQL审核

_images/create_new_task.png

进行审核提交

点开订单中心--订单列表

_images/examine_task.png

注意

由于inception对于删除数据库语句的操作是进行过滤的,所以不能在SQL审核里面有删库语句出现;对于SQL语句不规范的也会有相应的报错提示,建议在执行SQL审核之前,先进行SQL优化操作;对于一些忽略的报错,可以进行手动干预。

基于配置中心管理内网Dnsmasq示例

基于配置中心管理dnsmasq示例

这是一篇关于如何基于配置中心来图形化管理你的内网DNS,一般来说互联网企业里面都会部署自己内部的DNS服务,来提升解析速度。本示例dnsmasq,关于bind DNS域名管理是平台的一个单独模块。

环境说明

Q: 为什么要配置到平台上?

A:假如你内网DNS有多台,即使是管理简单的dnsmasq服务,你也要手动登录机器进行编辑配置文件,很麻烦,机器上直接操作是非常危险的,且没有回滚功能,一不小心就可能导致出错,Server 挂掉等。所以在此借助配置中心模块简单记录下,配置中心支持图形化操作、对比、回滚等操作

  • OpenDevOps平台
  • 配置中心模块
  • 任务模板
  • 内网DNS服务(dnsmasq)

如何使用

开始之前你可以点击以下视频链接,看下最终效果,看此操作是否可以满足你的需求

Youtube | BiliBili

登录配置中心新建一个项目

_images/add_config.png

对项目进行赋权

新建的项目默认只有创建人才有权限, 需要赋权,其余用户才可以看到/拉取配置文件详情

_images/user_auth.png

获取一个用户的长期Token

这个用户必须有你这个项目的权限才可以,然后获取到这个用户的长期Token,后面脚本要用到

_images/get_token.png

服务器上拉取配置

这里需要在服务器上放一个拉取配置中心配置的一个脚本,逻辑就是,通过一个有权限的用户—拉取指定的配置信息—将配置同步到你的server上—-reload服务

这里提供一个配置脚本示例(dnsmasq),更详情的脚本可参考配置中心

示例脚本放到DNS服务器目录:/data1/shell/dns_publish.py

#!/usr/bin/env python
# -*-coding:utf-8-*-
"""
Contact : 191715030@qq.com
Author  : shenshuo
Date    : 2019/1/29
Desc    : 获取配置文件内容,
          要确保有全局权限 /kerrigan/v1/conf/publish/
          要确保有当前项目配置获取权限
"""

import os
import requests
import json
import subprocess



def exec_shell(cmd):
    '''执行shell命令函数'''
    sub2 = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    stdout, stderr = sub2.communicate()
    ret = sub2.returncode
    return ret,stdout.decode('utf-8').strip()



class ConfApi:
    def __init__(self):
        # self.auth_key 是一个长期Token,基于用户管理里面,管理员选中用户生成长期Token,默认发送到用户邮箱
        self.auth_key = 'eyJ0eXAiOiJKV1QiLCJhbmZpZyIsIm5pY2XcFBbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTMwMzQyNzYsIm5iZiI6MTU1Nzk5NDI1NiwiaWF0IjoxNTU3OTk0Mj3ZjZlXHU3NTI4XHU2MjM3IY2LCJpc3MiOiJhdXRoOiBzcyIsInN1YiI6Im15IHRva2VuIiwiaWQiOiIxNTYxODcxODA2MCIsImRhdGEiOnsidXNlcl9pZCI6NjYsInVzZXJuYW1lIjoiZ2V0X2NvFOOo'
        self.conf_path ='/tmp'
        self.conf_config_api = "https://codo.domain.com/api/kerrigan/v1/conf/publish/config/"   #配置中心获取API



    def get_config_details(self, project_code, environment, service, filename):
        # 获取配置文件内容,  2019-04-28支持URL auth_key登陆,不需要再登陆进行获取auth_key,直接生成长期Token用
        #__token = self.login()

        __token = self.auth_key
        try:
            _params = {'project_code': project_code, 'environment': environment,'service':service,'filename':filename, 'auth_key': __token}
            res = requests.get(self.conf_config_api, params=_params)
            ret = json.loads(res.content)
            if ret['code'] == 0: return ret['data']
        except Exception as e:
            print('[Error:] 发布配置接口连接失败,错误信息:{}'.format(e))
            exit(-2)



    def create_config_file(self, project_code, environment, service, filename):
        # 生成配置文件
        config_data = self.get_config_details(project_code, environment, service, filename)
        for k,v in config_data.items():
            config_file = self.conf_path + k
            dir_name, _ = os.path.split(config_file)
            if not os.path.exists(dir_name):
                os.makedirs(dir_name)
            with open(config_file ,'w') as f:
                f.write(v)
        #     print('config file path is {}'.format(config_file))
        # print('success')
        return config_file  #返回文件路径


    def rsync_file(self, config_file):
        """
        同步文件
        :return:
        """
        #目标文件名:
        target_file_name = config_file.split('/')[-1]
        cmd = 'rsync -avz {}  /etc/{}'.format(config_file,target_file_name)
        ret, stdout = exec_shell(cmd)
        if ret != 0:
            print('[ERROR]: 文件同步失败'.format(target_file_name))
            return False
        print('[Sucess]: {}文件同步成功'.format(target_file_name))

    def reload_service(self):
        cmd = 'service dnsmasq reload'
        ret, stdout = exec_shell(cmd)
        if ret != 0:
            print('[ERROR]: 服务启动失败')
            return False
        print('[Sucess]: 服务reload成功')


def main():
    obj = ConfApi()
    config_file = obj.create_config_file('DNS', 'release', 'dnsmasq', 'dnsmasq.conf')
    hosts_config_file = obj.create_config_file('DNS', 'release', 'dnsmasq', 'dnsmasq_hosts')
    if config_file:
        obj.rsync_file(config_file)

    if hosts_config_file:
        obj.rsync_file(hosts_config_file)

    obj.reload_service()

if __name__ == '__main__':
    main()

运行查看结果:

python3 /data1/shell/dns_publish.py
[Sucess]: dnsmasq.conf文件同步成功
[Sucess]: dnsmasq_hosts文件同步成功
[Sucess]: 服务reload成功

其实到了这一步,基本配置已经完成了,由于这个DNS每次修改后配置都要reload服务,所以不建议放到crontab里面进行轮训配置,接下来配置下发布,IT人员修改后配置,点下发布进行触发

配置DNS发布

新建一个Tag,将机器添加进去

_images/add_dns_tag.png

新建命令和模板配置

这里是发布的时候选择我们自己排序的模块任务

_images/add_dns_bash.png

_images/add_dns_temp.png

提交一个自定义任务

_images/commit_dns_task.png

审批任务

_images/approval_dns_task.png

执行结果

_images/dns_task_res.png

如果出错可以查看日志进排查,也可以重做,终止等操作

_images/dns_task_log.png

插件部署

Inception部署文档

opendevops平台所用插件Inception部署文档, 部分文档会因为版本迭代不可用,此文档只作为参考文档,谢谢。

1.在任何一台安装docker的主机上拉取镜像

docker pull ss1917/inception:latest

2.编辑inception配置文件,注意修改inception_remote四处配置项,指定一个数据库用以保存inception的备份及回滚语句

cat >/etc/inc.cnf <<EOF 
[inception]
general_log=1
general_log_file=/var/log/inception.log
port=6669
socket=/tmp/inc.socket
character-set-client-handshake=OFF
character-set-server=utf8
#config backup database
inception_remote_system_password=aabb1122
inception_remote_system_user=inception_web
inception_remote_backup_port=3306
inception_remote_backup_host=172.16.0.211

inception_check_dml_where=ON
inception_check_dml_limit=OFF
inception_check_dml_orderby=OFF
inception_enable_select_star=ON
inception_enable_orderby_rand=ON
inception_enable_nullable=ON
inception_enable_foreign_key=ON
inception_max_key_parts=5
inception_max_update_rows=MAX
inception_max_keys=6
inception_enable_not_innodb=ON
inception_support_charset=utf8mb4,utf8
inception_check_table_comment=OFF
inception_check_column_comment=OFF
inception_check_primary_key=OFF
inception_enable_partition_table=OFF
inception_enable_enum_set_bit=ON
inception_check_index_prefix=OFF
inception_enable_autoincrement_unsigned=ON
inception_max_char_length=16
inception_check_autoincrement_init_value=OFF
inception_check_autoincrement_datatype=OFF
inception_check_timestamp_default=OFF
inception_enable_column_charset=OFF
inception_check_autoincrement_name=OFF
inception_merge_alter_table=OFF
inception_check_column_default_value=ON
inception_enable_blob_type=ON
inception_enable_identifer_keyword=ON
bind_address=0.0.0.0
inception_check_identifier=ON
EOF

3.启动,主要参数为暴露容器6669端口,挂载本地inc.cnf文件到容器中的/etc目录下

docker run -itd -p 6669:6669 -v /etc/inc.cnf:/etc/inc.cnf --name=inception ss1917/inception:latest
在主机上测试连接6669端口成功,服务已正常启动。

inc.cnf配置文件参数简要说明

[inception]
general_log=1
general_log_file=/var/log/inception.log
port=6669
socket=/tmp/inc.socket
character-set-client-handshake=0
character-set-server=utf8

#备份相关
#需要开启binlog
inception_remote_system_password=123456
inception_remote_system_user=user
inception_remote_backup_port=3306
inception_remote_backup_host=10.0.0.24

#在DML语句中没有WHERE条件时,是不是要报错
inception_check_dml_where=1
#在DML语句中使用了LIMIT时,是不是要报错
inception_check_dml_limit=1
#在DML语句中使用了Order By时,是不是要报错
inception_check_dml_orderby
#Select*时是不是要报错
inception_enable_select_star=1
#order by rand时是不是报错
inception_enable_orderby_rand=1
#创建或者新增列时如果列为NULL,是不是报错
inception_enable_nullable=1
#是不是支持外键
inception_enable_foreign_key=1
#一个索引中,列的最大个数,超过这个数目则报错(1-64)
inception_max_key_parts=5
#在一个修改语句中,预计影响的最大行数,超过这个数就报错(1-max)
inception_max_update_rows=10000
#一个表中,最大的索引数目,超过这个数则报错(1-1024)
inception_max_keys=16
#建表指定的存储引擎不为Innodb,不报错
inception_enable_not_innodb=0
#表示在建表或者建库时支持的字符集,如果需要多个,则用逗号分隔,影响的范围是建表、设置会话字符集、修改表字符集属性等
inception_support_charset=utf8mb4
#建表时,表没有注释时报错
inception_check_table_comment=1
#建表时,列没有注释时报错
inception_check_column_comment=1
#建表时,如果没有主键,则报错
inception_check_primary_key=1
#是不是支持分区表
inception_enable_partition_table=0
#是不是支持enum,set,bit数据类型
inception_enable_enum_set_bit=0
#是不是要检查索引名字前缀为"idx_",检查唯一索引前缀是不是"uniq_"
inception_check_index_prefix=1
#自增列是不是要为无符号型
inception_enable_autoincrement_unsigned=1
#当char类型的长度大于这个值时,就提示将其转换为VARCHAR(1-max)
inception_max_char_length=16
#当建表时自增列的值指定的不为1,则报错
inception_check_autoincrement_init_value=1
#当建表时自增列的类型不为int或者bigint时报错
inception_check_autoincrement_datatype=1
#建表时,如果没有为timestamp类型指定默认值,则报错
inception_check_timestamp_default=0
#允许列自己设置字符集
inception_enable_column_charset=0
#建表时,如果指定的自增列的名字不为ID,则报错,说明是有意义的,给提示
inception_check_autoincrement_name=1
#在多个改同一个表的语句出现时,报错,提示合成一个
inception_merge_alter_table=1
#检查在建表、修改列、新增列时,新的列属性是不是要有默认值
inception_check_column_default_value=1
#检查是不是支持BLOB字段,包括建表、修改列、新增列操作
inception_enable_blob_type=1
#检查在SQL语句中,是不是有标识符被写成MySQL的关键字,默认值为报警。
inception_enable_identifer_keyword=1
#这个参数的作用是为了匹配Python客户端每次自动设置auto_commit=0的,如果取消则会报错,针对Inception本身没有实际意义
#auto_commit=0
#这个参数实际上就是MySQL数据库原来的参数,因为Incpetion没有权限验证过程,那么为了实现更安全的访问,可以给Inception服务器的这个参数设置某台机器(Inception上层的应用程序)不地址,这样
#其它非法程序是不可访问的,那么再加上Inception执行的选项中的用户名密码,对MySQL就更加安全
bind_address=127.0.0.1
#inception_user
#inception_password
#inception_enable_sql_statistic
#inception_read_only
#打开与关闭Inception对SQL语句中各种名字的检查,如果设置为ON,则如果发现名字中存在除数字字母下划线之外的字符时,报Identifier "invalidname" is invalid, valid options: [a-z,A-Z,0-9,_].
inception_check_identifier=1

#inception_osc_min_table_size=1
#inception_osc_bin_dir=/data/temp
#inception_osc_chunk_time=0.1

Inception使用方法

1.Inception规定,在语句的最开始位置,要加上inception_magic_start;语句,在执行语句块的最后加上inception_magic_commit;语句,这2个语句在 Inception 中都是合法的、具有标记性质的可被正确解析的 SQL 语句。被包围起来的所有需要审核或者执行的语句都必须要在每条之后加上分号,其实就是批量执行SQL语句。(包括use database语句之后也要加分号,这点与 MySQL 客户端不同),不然存在语法错误
2.目前执行只支持通过C/C++接口、Python接口来对Inception访问,这一段必须是一次性的通过执行接口提交给Inception,那么在处理完成之后,Inception会返回一个结果集,来告诉我们这些语句中存在什么错误,或者是完全正常等等。

下面是一个python脚本访问inception的简单例子,指定连接测试的mysql服务器为10.0.0.24

cat >inc-mysql.py <<EOF
#!/usr/bin/env python
#coding=utf8
import MySQLdb
sql='''/*--user=root;--password=123456;--host=10.0.0.24;--execute=1;--port=3306;*/\
    inception_magic_start;\
    use test;\
    CREATE TABLE shinezone(id int);\
    inception_magic_commit;'''
#print sql
try:
        conn=MySQLdb.connect(host='127.0.0.1',user='',passwd='',db='',port=6669)
        cur=conn.cursor()
        ret=cur.execute(sql)
        result=cur.fetchall()
        num_fields = len(cur.description)
        field_names = [i[0] for i in cur.description]
        print field_names
        for row in result:
                print row[0], "|",row[1],"|",row[2],"|",row[3],"|",row[4],"|",row[5],"|",row[6],"|",row[7],"|",row[8],"|",row[9],"|",row[10]
        cur.close()
        conn.close()
except MySQLdb.Error,e:
             print "Mysql Error %d: %s" % (e.args[0], e.args[1])
EOF

执行脚本

python inc-mysql.py
更改建表语句:
CREATE TABLE shinezone(id int comment 'test' primary key) engine=innodb DEFAULT CHARSET=utf8mb4 comment '测试';\
cat >inc-mysql.py <<EOF
#!/usr/bin/env python
#coding=utf8
import MySQLdb
sql='''/*--user=root;--password=123456;--host=10.0.0.24;--execute=1;--port=3306;*/\
    inception_magic_start;\
    use test;\
    CREATE TABLE shinezone(id int comment 'test' primary key) engine=innodb DEFAULT CHARSET=utf8mb4 comment '测试';\
    inception_magic_commit;'''
#print sql
try:
        conn=MySQLdb.connect(host='127.0.0.1',user='',passwd='',db='',port=6669)
        cur=conn.cursor()
        ret=cur.execute(sql)
        result=cur.fetchall()
        num_fields = len(cur.description)
        field_names = [i[0] for i in cur.description]
        print field_names
        for row in result:
                print row[0], "|",row[1],"|",row[2],"|",row[3],"|",row[4],"|",row[5],"|",row[6],"|",row[7],"|",row[8],"|",row[9],"|",row[10]
        cur.close()
        conn.close()
except MySQLdb.Error,e:
             print "Mysql Error %d: %s" % (e.args[0], e.args[1])
EOF
执行下脚本,同时生成回滚语句,记录在inception备份库中.
备份机器的库名组成是由线上机器的 IP 地址的点换成下划线,再加上端口号,再加上库名三部分,在生成的备份中,可以看到inception自动生成的回滚语句

SOAR部署文档

opendevops平台所用插件SOAR部署文档, 部分文档会因为版本迭代不可用,此文档只作为参考文档,谢谢。

简介

SOAR(SQL Optimizer And Rewriter)是一个对SQL进行优化和改写的自动化工具。 由小米人工智能与云平台的数据库团队开发与维护。SOAR 主要由语法解析器、集成环境、优化建议、重写逻辑、工具集五大模块组成,相比业内其他优秀产品有自己的优势。

功能特点

  • 跨平台支持(支持Linux, Mac环境,Windows环境理论上也支持,不过未全面测试)
  • 支持基于启发式算法的语句优化
  • 支持复杂查询的多列索引优化(UPDATE, INSERT, DELETE, SELECT)
  • 支持EXPLAIN信息丰富解读
  • 支持SQL指纹、压缩和美化
  • 支持同一张表多条ALTER请求合并
  • 支持自定义规则的SQL改写

下载二进制安装包

wget https://github.com/XiaoMi/soar/releases/download/0.9.0/soar.linux-amd64 -O soar
chmod a+x soar
cp soar /usr/bin/

安装验证

回到soar的下载目录执行

echo 'select * from film' | ./soar

回显如下

# Query: 687D590364E29465

★ ★ ★ ☆ ☆ 75分

``sql

SELECT  
  * 
FROM  
  film
``

##  最外层SELECT未指定WHERE条件

* **Item:**  CLA.001

* **Severity:**  L4

* **Content:**  SELECT语句没有WHERE子句,可能检查比预期更多的行(全表扫描)。对于SELECT COUNT(\*)类型的请求如果不要求精度,建议使用SHOW TABLE STATUS或EXPLAIN替代。

##  不建议使用SELECT * 类型查询

* **Item:**  COL.001

* **Severity:**  L1

* **Content:**  当表结构变更时,使用\*通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。

SQLAdvisor部署文档

opendevops平台所用插件SQLAdvisor部署文档, 部分文档会因为版本迭代不可用,此文档只作为参考文档,谢谢。

简介

SQLAdvisor是一个分析SQL给出索引优化建议的工具。它基于MySQL原生态词法解析,结合分析SQL中的where条件、聚合条件、多表Join关系 给出索引优化建议。 主要功能:输出SQL索引优化建议,更多介绍

安装使用

#编译依赖项sqlparser
git clone https://github.com/Meituan-Dianping/SQLAdvisor.git
cd SQLAdvisor
1.cmake -DBUILD_CONFIG=mysql_release -DCMAKE_BUILD_TYPE=debug -DCMAKE_INSTALL_PREFIX=/usr/local/sqlparser ./
2.make && make install

#安装SQLAdvisor源码
cd SQLAdvisor/sqladvisor/
cmake -DCMAKE_BUILD_TYPE=debug ./
make
cp sqladvisor  /usr/bin/

#使用帮助
sqladvisor  --help

#举个栗子
sqladvisor  -u root -p 123456 -P 3306 -h 10.0.0.24 -q "select permission_id from base_server_user_group_permission_relation;" -d work_permission_0 -v 1
编译完成后可删除整个sqladvisor目录,仅保留可执行文件sqladvisor。

sonarQube部署文档

opendevops平台所用插件SonarQube部署文档, 部分文档会因为版本迭代不可用,此文档只作为参考文档,谢谢。

官网

简介

SonarQube 是一个开源的代码分析平台, 用来持续分析和评测项目源代码的质量。 通过SonarQube我们可以检测出项目中重复代码, 潜在bug, 代码风格问题,缺乏单元测试等问题, 并通过一个web ui展示出来。

基础的架构

  • Database
  • SonarQube Server
  • SonarQube Scanner
  • Project
  • Nginx (如果不需要通过nginx转发则不需要Nginx模块)

SonarQube服务端

直接拉取仓库中的docker镜像启动服务, docker、docker-compose安装参考初始化脚本

mkdir -p /data/sonarqube/

cat >/data/sonarqube/docker-compose.yml <<EOF
version: "2"

services:
  sonarqube:
    image: ss1917/sonarqube:latest
    ports:
      - "9000:9000"
    networks:
      - sonarnet
    environment:
      - SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
    volumes:
      - /data/sonarqube/conf:/opt/sonarqube/conf
      - /data/sonarqube/data:/opt/sonarqube/data
      - /data/sonarqube/extensions:/opt/sonarqube/extensions
      - /data/sonarqube/bundled-plugins:/opt/sonarqube/lib/bundled-plugins

  db:
    image: postgres
    networks:
      - sonarnet
    environment:
      - POSTGRES_USER=sonar
      - POSTGRES_PASSWORD=sonar
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data

networks:
  sonarnet:
    driver: bridge

volumes:
  postgresql:
  postgresql_data:
EOF

cd /data/sonarqube
docker-compose up -d

启动docker后访问ip:9000,代表服务已启动,默认登录密码admin/admin

_images/login_sonar.pnglogin_sonar

SonarQube配置安装插件,汉化。

_images/chinese_plug.pngchinese_plug _images/sonarp_plug.pngsonarp_plug

如图进入marketplace,搜索汉化包,各类语言代码扫描依赖包, 安装完毕后自动重启。

_images/sonar_reboot.pngsonar_reboot

接下来开始配置sonarqube服务全局配置。

_images/sonar_global.pngsonar_global

主要配置项:

  • Server base URL (定义sonar服务访问地址,可用域名或ip)
  • Email prefix (发送邮件时的主题前缀)
  • From address
  • From name
  • Secure connection

smtp安全协议

  • SMTP host
  • SMTP password
  • SMTP port

配置完成后测试发送

_images/send_test.pngsend_test

配置邮件提醒

在 我的账号-提醒 下设置邮件提醒,也可针对特定项目设置提醒,发送邮件。

_images/sonar_mail01.pngsonar_mail01 _images/sonar_mail02.pngsonar_mail02

至此sonarqube服务端安装配置全部已完成。

SonarQube客户端(必装)

配置好sonar的服务端之后,接下来就要使用sonar检测我们的代码了,sonar主要是借助客户端检测工具来检测代码,所以要使用sonar必须要在我们本地配置好客户端检测工具 客户端可以通过IDE插件、Sonar-Scanner插件、Ant插件和Maven插件方式进行扫描分析,此处使用的是Sonar-Scanner,sonar的命令行分析端软件还有Sonar-Runner,和Scanner使用差不多

此处我们使用sonar-scanner

注意:这里客户端后续代码检查脚本会调用此客户端执行代码检查

wget https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.2.0.1227-linux.zip
unzip  sonar-scanner-cli-3.2.0.1227-linux.zip
mv sonar-scanner-3.2.0.1227-linux/ /usr/local/sonar-scanner
export SONAR_RUNNER_HOME=/usr/local/sonar-scanner
export PATH=$SONAR_RUNNER_HOME/bin:$PATH

DNS Bind部署文档

opendevops平台所用组件域名管理Bind部署文档, 部分文档会因为版本迭代不可用,此文档只作为参考文档,谢谢。

安装配置

yum install -y bind bind-chroot bind-utils
  • 如果安装了bind-chroot(其中chroot是 change root 的缩写),BIND会被封装到一个伪根目录内,配置文件的位置变为:/var/named/chroot/etc/named.conf
  • BIND服务主配置文件/var/named/chroot/var/named/
  • zone文件chroot是通过相关文件封装在一个伪根目录内,已达到安全防护的目的,一旦程序被攻破,将只能访问伪根目录内的内容,而不是真实的根目录
  • BIND安装好之后不会有预制的配置文件,但是在BIND的文档文件夹内(/usr/share/doc/bind-9.9.4),BIND为我们提供了配置文件模板,我们可以直接拷贝过来:
# cp -r /usr/share/doc/bind-9.9.4/sample/etc/* /var/named/chroot/etc/
# cp -r /usr/share/doc/bind-9.9.4/sample/var/* /var/named/chroot/var/
  • 配置BIND服务的主配置文件(/var/named/chroot/etc/named.conf,并加入zone参数
options {
        listen-on port 53       { 127.0.0.1; };
        listen-on-v6 port 53 { ::1; };
        allow-query     { any; };
        directory "/var/named";
        recursion yes;
        };

zone "ss.com"  {
        type master;
        file "ss.com.zone";
};
  • 新建ss.com.zone文件 如下
# vim /var/named/chroot/var/named/ss.com.zone
$TTL 86400
$ORIGIN ss.com.
@  IN SOA  ss.com. admin.ss.com. (
                    20190426; serial #更新序列号
                    1D  ; refresh #更新时间
                    1H  ; retry #重试延时
                    1W  ; expire #失效时间
                    3H  ; minimum #无效解析记录的缓存时间
)
    IN  NS  ns1.ss.com.

ns1 3600 IN   A   192.168.99.99
www 3600 IN   A   172.20.66.110
ftp 3600 IN   A  10.128.105.250
  • 禁用bind默认方式启动,改用bind-chroot方式启动。命令如下:
# /usr/libexec/setup-named-chroot.sh /var/named/chroot on
# systemctl stop named
# systemctl disable named
# systemctl start named-chroot
# systemctl enable named-chroot
  • 检查语法
# named-checkzone ss.com /var/named/ss.com.zone
zone ss.com/IN: loaded serial 20190426
OK
# named-checkconf
  • 查看是否启动,命令:
ps -ef|grep named
  • 测试DNS服务,命令如下:
### 编辑dns解析文件 并写入你的DNS服务器地址
vim /etc/resolv.conf 
nameserver 172.16.0.111
dig ftp.ss.com

参考文档

参考文档1

参考文档2

参考文档3

版本更新

主要介绍下前后端都是如何进行版本更新的

前端更新

由于前端都是静态文件,更新起来非常简单,直接下载最新的release包解压即可
rm -rf /var/www/codo/
CODO_VER="codo-beta-0.3.2"   #这里改为最新的relase版本
if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi
[ ! -d /var/www ] && mkdir -p /var/www
cd /var/www && wget https://github.com/opendevops-cn/codo/releases/download/${CODO_VER}/${CODO_VER}.tar.gz
tar zxf ${CODO_VER}.tar.gz

后端更新

后端都是微服务的,更新某个模块只需要对单个模块操作即可
  • 举个例子,没有修改表结构的更新
# 进到你的模块目录
cd /opt/codo/codo-cmdb  

#先给你自己的settings备份下,省的频繁修改
mv settings.py settings.py-bak    

#获取最新代码
git pull  

#覆盖回来
mv settings.py-bak settings.py    

 #重新打包镜像
docker build . -t codo_cmdb    

#compose启动
docker-compose up -d            

#查看日志是否有错误
tailf /var/log/supervisor/cmdb.log  
  • 假如后端修改了表结构我怎么更新呢?
如果后端修改了表结构,我们的更新文档都会说明哪些需要ALTER TABLE,比如CMDB资产配置新增了华为云的支持,
  • 问题1:我不想重新初始化,里面有数据,想直接改表结构
#先进到你的数据库,每个模块都是对应一个版本库的

ALTER TABLE `asset_configs` ADD `project_id` VARCHAR(120) NOT NULL ;
ALTER TABLE `asset_configs` ADD `huawei_cloud` VARCHAR(120) NOT NULL ;
ALTER TABLE `asset_configs` ADD `huawei_instance_id` VARCHAR(120) NOT NULL ;  
  • 然后更新你的代码
# 进到你的模块目录
cd /opt/codo/codo-cmdb  

#先给你自己的settings备份下,省的频繁修改
mv settings.py settings.py-bak    

#获取最新代码
git pull  

#覆盖回来
mv settings.py-bak settings.py    

 #重新打包镜像
docker build . -t codo_cmdb    

#compose启动
docker-compose up -d            

#查看日志是否有错误
tailf /var/log/supervisor/cmdb.log  
  • 问题2:我不想改表结构怎么办?
如果你是新部署的用户/没数据的用户,你完全可以给这个库/表删除了执行初始化操作
docker exec -ti cmdb_codo_cmdb_1 /usr/local/bin/python3 /var/www/codo-cmdb/db_sync.py

#最后同样,如上,更新最新代码即可

更新记录

Beta 0.3.0

2019-05

  • 新增了一些示例文档,传送门
  • 新增了一些系统所用插件部署文档,传送门
  • 新增了分布式部署文档的视频,传送门
  • 新增了任务系统的一些示例视频,传送门
  • 新增了系统配置里面LDAP的支持
  • 新增了API网关支持URL传参,Token支持
  • 新增了DNS域名管理模块,传送门
  • 新增了发短信、发邮件的接口文档传送门
  • 新增了CMDB和作业配置中的标签树进行数据打通
  • 优化了SQL审核的一些使用问题
  • 优化了运维工具提醒管理内容
  • 更新了前端Home首页展示
  • 更新了一些用户使用文档
  • 重构了CMDB资产管理第一期传送门

Beta 0.2.2

2019-04

  • 新增了显示登陆名
  • 优化了日志展示为抽屉效果,解决超长日志展示问题

Beta 0.2.0

2019-04

  • 新增了作业配置新增了标签树、代理使用文档
  • 新增了用户发布、SQL审核、SQL优化等
  • 新增了自定义任务,用户可在平台直接提交自定义任务(简单和复杂JSON提交)
  • 新增了代理配置(代理主机),你有多区域且复杂的情况下,你可以用这里的代理主机帮你实现
  • 新增了配置中心模块上线,用户复杂配置可基于配置中心,图形化操作传送门
  • 新增了运维工具模块,如:提醒、记录、随机密码、告警等传送门
  • 更新了用户权限列表,进行了Beta0.2的整理
  • 更新了任务模块里面的执行用户,可以添加多个用户
  • 优化了订单中心,分为订单列表和历史任务查询
  • 优化了订单列表中的任务详情展示,参数表格展示等

Beta 0.1.0

2018-11

  • 开源代码
  • 第一版Beta 0.1
  • 发布使用文档

贡献者

写在前面

非常感谢各位的贡献、感谢各位的付出,让维护因你们变的不再枯燥、世界因你们而美丽,此排名贡献不分前后,谢谢大家

核心贡献人员

  • laoxu 项目组织,发起者、项目运营
  • shenshuo 资深架构师,设计平台架构,贡献核心代码和文档
  • yangmingwei 高级运维开发工程师,核心代码贡献者
  • yanghongfei 高级运维工程师,产品经理,贡献核心代码和文档
  • shenyingzhi 资深运维工程师, 贡献Docker支持、SQL审核优化、文档,并测试了很多功能
  • biantingting 前端工程师,贡献前端官网代码、代码配置管理
  • ops-office 神秘大佬,运维咖啡吧、一杯咖啡、轻松运维,贡献配置中心模块,并提供了很多优化建议
  • laowang 小煜狼皇,高级运维工程师,贡献BBS社区管理,AWS服务模块贡献者

文档贡献人员

  • liuchunyun 高级运维工程师, 贡献文档、功能测试,并提供了很多建议
  • zhirenyongnan 运维工程师,贡献文档、项目运营
  • libo 运维工程师, 贡献文档、功能测试

为开源OpenDevOps贡献代码

贡献可以有很多

  • 贡献最佳实践文档,对贡献者署名
  • 贡献重要模块的人员纳入核心开发者
  • 对模块提出建议、贡献、修订者、纳入贡献

OpenDevOps是一款为用户提供企业多混合云、一站式DevOps、自动化运维、完全开源的云管理平台

我们深知自己能力有限,大家都是为了一个共同的目标不停的在努力,刚好有人不会,刚好这时你会,一点小小的贡献都可能会帮助很多人。

让我们大家一起做出贡献来帮助更多的人,让更多的同学告别运维996, 代码贡献人员可联系我们进入开发群,也可Fork,根据标准API提供你的代码,贡献不限制语言,都可对接。

_images/contribute.png

FAQ

邮箱设置问题

由于常见的Email有很多,这里列举下最常见的Email设置
  • Q: QQ邮箱怎么设置?
  • A: QQ邮箱主要注意使用网页生成授权码进行作为密码登陆
    • SMTP地址:smtp.qq.com
    • SMTP端口:465
    • SSL加密:True, 开启
    • 用 户: <your_qq>@qq.com
    • 密 码: 授权码(一般为16位)
  • Q: 腾讯企业邮箱如何设置?
  • A: 腾讯企业邮箱同QQ邮箱,唯一一点SMTP服务器不同
    • SMTP地址:smtp.exmail.qq.com
    • SMTP端口:465
    • SSL加密:True, 开启
    • 用 户: <your_name>@domain.com
    • 密 码: 授权码(一般为16位)
  • Q: 网易163邮箱如何设置?
  • A: 同上,唯一一点SMTP服务器不同
    • SMTP地址:smtp.163.com
    • SMTP端口:465
    • SSL加密:True, 开启
    • 用 户: <your_name>@163.com
    • 密 码: 授权码(一般为16位)
  • Q: Gmail邮箱如何设置?
  • A: Gmail邮箱考虑到安全,需要注意以下2步
    • 首先开启Google 二步认证
    • 生成Google 应用专用密码
    • SMTP地址:smtp.gmail.com
    • SMTP端口:465
    • SSL加密:True, 开启
    • 用 户: <your_name>@gmail.com
    • 密 码: 授权码(一般为16位)

Docker Bulid 报错问题

  • 安装依赖报错:Could not install packages due to an EnvironmentError'
错误信息:
Step 10/16 : RUN pip3 install --upgrade pip
---> Running in 83716c526776

Collecting pip
Downloading https://files.pythonhosted.org/packages/c2/d7/90f34cb0d83a6c5631cf71dfe64cc1054598c843a92b400e55675cc2ac37/pip-18.1-py2.py3-none-any.whl (1.3MB)
Installing collected packages: pip
Found existing installation: pip 10.0.1
Uninstalling pip-10.0.1:
Successfully uninstalled pip-10.0.1
Could not install packages due to an EnvironmentError: [Errno 2] No such file or directory: '/tmp/pip-uninstall-y8n2hlf9/usr/local/bin/pip3'

The command '/bin/sh -c pip3 install --upgrade pip' returned a non-zero code: 1
  • 解决办法:
Python3x版本后Docker里面需要加入--user的参数,修改Dockerfile, 加上--user参数, 如:pip3 install --user --upgrade pip

常见的错误码error code排错思路

  • 404: 一般都是自己修改了域名或者配置错误,导致网关转发的时候没办法找到
  • 500: 每个模块服务的后端报错,具体可参看报错模块日志: /var/log/supervisor/
  • 502: 502错误是网关配置错误,请仔细检查网关配置和DNS配置,确保域名正常解析,且能访问。

Google Authenticator怎么使用?

安全一定是最重要的,相信很多人都知道谷歌身份验证器,这里简单说下Google身份验证器怎么使用, 本平台Google验证码密钥是发送到用户邮箱的。

下载谷歌验证器

  • iOS用户登录AppStore搜索"Authenticator"
  • 安卓用户登录应用商店或利用手机浏览器搜索“谷歌验证器”下载,也可点击下载

添加所需网站验证码

PS 由于国内Android多数都被阉割了Google框架,不能扫码的输入手动贴入密钥

  • 扫描条形码

_images/google_auth01.jpg

  • 手动输入密钥

_images/google_auth02.jpg

手机丢失怎么办

  1. 你可以搜索你之前的邮件记录,或者自行记录保存下来
  2. 对于CODO超级管理员可以登陆数据库自行查看,SQL语法:select google_key from codo_admin.mg_users where username='codo_test';

Login界面/登陆后一直自动刷新/闪屏/退出?

Q:可以登陆进去,但是一直闪屏刷新/退出?

A:出现这个问题是因为网关token_secretcodo-admin里面token_secret配置不一样,改成一样即可。 请仔细阅读网关配置中的注册API网关文件 configs.lua这块

Docker内部的MySQL、Redis无法连接问题

有些同学发现在Docker内部无法连接到外面的MySQL,如下报错,一般都是防火墙引起的,防火墙不能关闭,因为NAT在用,清空掉Filter链 iptables -F或者添加上3306端口尝试下。

_images/243fb74c5a73af046696423d6ce7b92.png

新部署的系统无法创建User?没办法看到创建/重置/获取Token?

Q:新部署的时候登陆进去,点击用户列表没办法创建/看不到重置密码/重置MFA按钮等问题?

A:这个问题是因为没有创建角色,默认部署的时候权限/组件数据都是初始化进去的,但是角色需要用户自己创建,用户可以点击用户管理-->角色管理 新建一个角色,给所有组件/菜单/权限 然后退出,强刷下浏览器就可以了

操作步骤可参考:http://docs.opendevops.cn/zh/latest/permission_docs.html#role

Indices and tables