# Technical Documentation: opendevops-cn/opendevops

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/opendevops-cn/opendevops)

### Overview (README.md)

<p align="center">
    <a href="https://www.opendevops.cn/">
        <img width="200" src="https://www.opendevops.cn/images/head_logo.png">
    </a>
</p>

[](README.md)
[](http://gitee.com/opendevops)
[](https://www.python.org/)
[](https://golang.google.cn/)
[](https://www.tornadoweb.org)
[](https://cn.vuejs.org)
[](https://ant-design.antgroup.com/)
[](https://www.iviewui.com/)
[](https://996.icu)
[](https://github.com/996icu/996.ICU/blob/master/LICENSE)

----

### 项目介绍

CODO 是一款专为企业设计的开源全球一站式运维平台，支持多混合云环境和自动化运维，为企业提供跨地域、跨云的统一管理能力。

### 技术架构与优势

- **前端**：基于 Vue + iView 和 React + Ant Design 开发，提供直观友好的操作界面，显著提升用户体验和工作效率。
- **后端**：采用 Python Tornado 和 Golang Gin，具备轻量级、简洁清晰和异步非阻塞的特点，实现高并发和快速响应。
- **微服务网关**：基于 OpenResty + Lua，提供统一的 API 网关和服务治理能力，其优势在于高性能、灵活扩展和优秀的负载均衡支持。
- **微前端基座**：基于阿里乾坤框架，负责统一纳管前端应用，支持微前端架构，具备模块化管理、动态加载及高效集成的能力。

### 项目亮点

- **高效统一管理**：支持跨地域、跨云环境，简化多云资源运维。
- **可观测与智能化**：全面覆盖实时监控、预警与性能分析。
- **强大自动化能力**：一站式自动化工具提升运维效率，降低操作复杂性。
- **云原生支持**：优化容器化与微服务管理，为企业数字化转型赋能。

众多功能模块我们一直在不停的调研和开发，如果你对此项目感兴趣可以加入我们的社区交流群，

同时也希望你能给我们项目一个，为贡献者加油⛽️！为运维干杯🍻！

----

### 语言

[English](README_EN.md) | [中文](README.md)

### 产品架构



### 产品功能



### Demo

我们提供了Demo供使用者体验,可点击Try Online Demo快速进行体验。

<a href="https://demo.opendevops.cn/user/login" target="api_explorer">
  <img src="https://img.alicdn.com/tfs/TB12GX6zW6qK1RjSZFmXXX0PFXa-744-122.png" width="180" />
</a>

`PS: Demo权限正在调试中，目前Demo用户只有查看权限，且暂不开放用户列表,Demo订单日志我们暂时清空了`

- 地址：https://demo.opendevops.cn/user/login
- 用户：demo
- 密码：2ZbFYNv9WibWcR7GB6kcEY



### 开始使用

> 当前版本支持docker compose和kubernetes helm 一键快速部署。

- [Document](http://docs.opendevops.cn/)
- [Quick Experience](https://demo.opendevops.cn/user/login)
- [Deployment Document](https://github.com/opendevops-cn/codo-deploy-docs)

### 视频教程

> 视频会在业余时间持续录制，更多视频可以参考Up主空间：https://space.bilibili.com/388245257/

- [部署安装教程](https://www.bilibili.com/video/BV1BL4y1a7TU/)
- [快速了解视频](https://www.bilibili.com/video/BV1rp4y1v7fa/)
- [二次开发教程](https://www.bilibili.com/video/BV1Sy4y137md/)

### 模块链接

> CODO 项目我们是使用模块化、微服务化，以下为各个模块地址，同时也欢迎业界感兴趣各位大佬前来贡献

- 前端代码：[codo](https://github.com/opendevops-cn/codo)
- 管理后端：[codo-admin](https://github.com/opendevops-cn/codo-admin)
- 配置管理平台：[codo-cmdb](https://github.com/opendevops-cn/codo-cmdb)
- 任务调度：[codo-flow](https://github.com/opendevops-cn/codo-flow)
- 配置中心：[codo-kerrigan](https://github.com/opendevops-cn/kerrigan)
- 通知中心：[codo-notice](https://github.com/opendevops-cn/codo-notice)
- 灵云-kubernetes管理 ：[codo-cnmp](https://github.com/opendevops-cn/codo-cnmp)
- 管控中心 ：[codo-agent-server](https://github.com/opendevops-cn/codo-agent-server)
- 前端基座 ：[codo-home-index](https://github.com/opendevops-cn/codo-home-index)
- 天门网关 ：[codo-gateway](https://github.com/opendevops-cn/codo-gateway)

### 感谢贡献者

感谢以下贡献着为CODO(CloudOpenDevOps)的贡献;  
感谢各位的付出，让维护因你们变的不再枯燥、世界因你们而美丽，此排名不分前后，谢谢大家!

| Name                                          | Github Avatar                                                   | Name                                          | GitHub Avatar                                                    | Name                                              | Github Avatar                                                   |
|-----------------------------------------------|-----------------------------------------------------------------|-----------------------------------------------|------------------------------------------------------------------|---------------------------------------------------|-----------------------------------------------------------------|
| [laoxu](https://github.com/rootman-xjj)       |  | [shenshuo](https://github.com/ss1917)         |   | [laowang](https://github.com/cyancow)             |  |
| [yanghongfei](https://github.com/yanghongfei) |  | [shenyingzhi](https://github.com/shenyingzhi) |   | [biantingting](https://github.com/biantingting94) |  |
| [zhirenyongnan](https://github.com/Aaronzryn) |  | [libo](https://github.com/alexbolee)          |   | [liuchunyu](https://github.com/liuchunyu007)      |  |
| [ops-coffee](https://github.com/ops-coffee)   |  | [yangmingwei](https://github.com/yangmv)      |   | [punk](https://github.com/it-sos)                 |   |
| [radius2136](https://github.com/radius2136)   |  | [ccheers](https://github.com/ccheers)         |  | [Sean Chen](https://github.com/fengmengqiu)       |    |

**[⬆ 返回顶部](#产品架构)**

### QQ交流群

> 感兴趣的同学可以加入我们的QQ交流群,代码我们也会不断进行更新，感谢大家的支持。

-
一键加入QQ群：<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=69f5e118727c7ea925cc8d2f0eef0d729898cb8a24eae47e2b3ca3dd048de9d9"><img border="0" src="images/join_qq_group.png" alt="CoDo  CloudOpenDevOps" title="OpenDevOps用户交流群"></a>

- 扫描二维码加群



## License

Everything is [GPL v3.0](https://www.gnu.org/licenses/gpl-3.0.html).


### 友情链接

[运维咖啡吧 - 一杯咖啡轻松运维](https://blog.ops-coffee.cn/)

[WeRSS - 微信公众号订阅助手](https://github.com/rachelos/we-mp-rss)


## 写在最后

感谢以下同学为Demo环境进行赞助。

| Name                                              | Github Avatar                                                   | 贡献金额  |
|---------------------------------------------------|-----------------------------------------------------------------|-------|
| [shenshuo](https://github.com/ss1917)             |  | ￥500  |
| [laowang](https://github.com/cyancow)             |  | ￥300  |
| [ops-coffee](https://github.com/ops-coffee)       |  | ￥300  |
| [yanghongfei](https://github.com/yanghongfei)     |  | ￥300  |
| [panda-yo](https://github.com/panda-yo)           |  | ￥200  |
| [yanshuanglong](https://github.com/yanshuanglong) |  | ￥200  |
| [Victor](https://github.com/victor)               |      | ￥200  |
| [DsinV](https://github.com/ywl913)                |   | ￥200  |
| [lixiaozheng](https://github.com/si7eka)          |  | ￥200  |
| [pcghost](https://github.com/q48775533q/)         |  | ￥100  |
| [ca7dEm0n](https://github.com/ca7dEm0n)           |  | ￥100  |
| [jiangming](https://github.com/jiangming1)        |  | ￥100  |
| [金额共计](https://github.com/opendevops-cn)          |  | ￥2700 |

---

### README (`docs/README.md`)

---
home: true
# heroImage: /logo.png
actionText: 快速上手 →
actionLink: /zh/guide-v2/
features:
- title: 介绍
  details: CODO是一款为用户提供企业多混合云、一站式DevOps、自动化运维、完全开源的云管理平台、自动化运维平台
- title: 环境
  details: 前后端分离、前端基于Vue iview 后端Python Tornado进行开发
- title: 权限
  details: 用户权限基于RBAC角色管理访问控制，用户登陆鉴权，支持开启用户MFA认证,支持LDAP 邮箱登录等
- title: 任务
  details: 强大的作业调度系统支持自定义模板、脚本、自由编排，且任务可干预，可定时、可重做
- title: API网关
  details: 系统模板化，前后端分离，自由开发新模板注册即可快速接入
- title: 微服务
  details: 采用微服务设计理念，服务之间，开发人员协同开发互不影响
footer: MIT Licensed | Copyright © 2025-present CoDo Groups
---

---

### Zh Ad README (`docs/zh/ad/README.md`)

::: tip
借位置打个广告，招聘游戏运维、运维开发
:::


**介绍**
- 作者目前在一家游戏公司社畜，感兴趣的同学可以找我内推
- 对，就是崩坏+原神那家，（什么，没听过？ 不了解？ 可以简单了解一下。

  - [崩坏3 Bilibili](https://space.bilibili.com/27534330) 
  - [原神 Bilibili](https://space.bilibili.com/401742377)
  - [miHoYo其他游戏](https://www.mihoyo.com/#/)

- 感兴趣的同学请联系我。

**福利**

- 六险一金
- 每年旅游
- 年会大奖
- 体检团餐（个人+家人）
- 10点上班，睡眠充足
- 节假日福利
- 游戏周边
- 二次元氛围
- 此处省略一万字...


**内推内推**

社招，内推二维码



校招，内推二维码



**联系我**




::: tip
感兴趣的同学可自行内推 / 联系作者
:::

::: warning
感兴趣的同学可自行内推 / 联系作者
:::

::: danger
感兴趣的同学可自行内推 / 联系作者
:::



**写在最后**

借位打个广告，一定删！项目大家维护的，我只是其中一名开发者；

缺人 缺人 缺人，希望感兴趣大佬们可以投份简历，Thanks♪(･ω･)ﾉ

---

### Zh Guide V2 README (`docs/zh/guide-v2/README.md`)

# OpenDevOps

<p align="center">
    <a href="http://www.opendevops.cn/">
        
    </a>
</p>

[](https://www.python.org/)
[](https://golang.google.cn/)
[](https://www.tornadoweb.org)
[](https://cn.vuejs.org)
[](https://ant-design.antgroup.com/)
[](https://www.iviewui.com/)
[](https://github.com/996icu/996.ICU/blob/master/LICENSE)

[](https://www.bilibili.com/video/BV1rp4y1v7fa/)

## 架构总图



----

### 项目概述

CODO 是一款专为企业设计的开源全球一站式运维平台，支持多混合云环境和自动化运维，为企业提供跨地域、跨云的统一管理能力。

### 技术架构与优势

- **前端**：基于 Vue + iView 和 React + Ant Design 开发，提供直观友好的操作界面，显著提升用户体验和工作效率。
- **后端**：采用 Python Tornado 和 Golang Gin，具备轻量级、简洁清晰和异步非阻塞的特点，实现高并发和快速响应。
- **微服务网关**：基于 OpenResty + Lua，提供统一的 API 网关和服务治理能力，其优势在于高性能、灵活扩展和优秀的负载均衡支持。
- **微前端基座**：基于阿里乾坤框架，负责统一纳管前端应用，支持微前端架构，具备模块化管理、动态加载及高效集成的能力。

### 核心功能模块

1. **自动化运维**：支持任务调度、批量操作和流程编排，提升工作效率。
2. **实时观测与预警**：跨地域、跨云实时监控，保障稳定性。
3. **配置管理**：集中管理云资源配置，减少人为错误，提升合规性。
4. **云原生管理**：支持容器化与云原生技术，简化 Kubernetes 和微服务管理。
5. **日志与审计**：提供统一的日志存储、分析及审计能力，确保安全性与可追溯性。
6. **安全管理**：强化权限控制与访问管理。
7. **多云管理**：整合多云环境，实现资源优化与高效管理。

### 项目亮点

- **高效统一管理**：支持跨地域、跨云环境，简化多云资源运维。
- **可观测与智能化**：全面覆盖实时监控、预警与性能分析。
- **强大自动化能力**：一站式自动化工具提升运维效率，降低操作复杂性。
- **云原生支持**：优化容器化与微服务管理，为企业数字化转型赋能。

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

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

## 模块介绍

```plaintext
codo
├── codo-admin               # 管理后台  
├── codo-agent-server        # 底层管控  
├── codo-cloud-agent-operator # 云原生任务执行  
├── codo-cmdb                # 多云资源管理  
├── codo-cnmp                # 云原生管理平台  
├── codo-flow-servers        # 任务调度与流程管理  
├── codo-monitor             # 可观测平台  
├── codo-notice              # 通知中心  
├── codo-frontend            # 前端流量入口  
├── codo-gateway             # API网关  
└── codo-kerrigan            # 配置中心  
```  

1. [**codo-admin**](https://github.com/opendevops-cn/codo-admin/blob/main/README.md)
   用于管理后台的操作平台，提供高效的管理界面和用户友好的操作体验。

2. [**codo-agent-server**](https://github.com/opendevops-cn/codo-agent-server/blob/main/README.md)
   底层管控模块，负责与主机或环境进行通信，实现资源的统一管理。

3. [**codo-cloud-agent-operator**](https://github.com/opendevops-cn/codo-agent-server/blob/main/README.md)
   负责执行云原生相关任务，支持 Kubernetes 等容器化任务的操作和调度。

4. [**codo-cmdb**](https://github.com/opendevops-cn/codo-cmdb/blob/main/README.md)
   数据资产管理平台，提供多云资源管理、CMDB 数据整合及资产统一视图。

5. [**codo-cnmp**](https://github.com/opendevops-cn/codo-cnmp/blob/main/README.md)
   云原生管理平台，专注于容器化、微服务及 Kubernetes 集群的管理。

6. [**codo-flow-servers**](https://github.com/opendevops-cn/codo-flow/blob/main/README.md)
   任务平台模块，支持任务调度、流程管理及批量作业执行。

7. [**codo-monitor**](https://github.com/opendevops-cn/codo-monitor/blob/main/README.md)
   可观测平台模块，提供实时监控、预警和性能分析能力，保障系统稳定性。

8. [**codo-notice**](https://github.com/opendevops-cn/codo-notice/blob/main/README.md)
   通知中心模块，支持多渠道通知推送，实现高效的事件响应。

1. [**codo-frontend**](https://github.com/opendevops-cn/codo-frontend/blob/main/README.md)
   前端应用和流量入口模块，处理 API 流量并路由至网关，支持模块化前端开发。

2.  [**codo-gateway**](https://github.com/opendevops-cn/codo-gateway/blob/main/README.md)
    API 网关模块，负责统一流量入口和服务治理，提供高性能路由与认证支持。

3.  [**codo-kerrigan**](https://github.com/opendevops-cn/codo-kerrigan/blob/main/README.md)
    配置中心模块，用于集中管理配置项，实现动态配置更新和分布式配置下发。

## 使用指南
- [系统架构](./1-architectures/README.md) 
- [安装说明](./2-install/README.md) 
  - [docker安装说明](./2-install/docker.md)
  - [k8s安装说明](./2-install/k8s.md)
- [admin - 管理用户权限](./3-admin/README.md) 
  - [使用admin配置权限](./3-admin/role-auth.md)
- [CMDB - 管理数据资源](./4-cmdb/README.md) 
  - [使用CMDB管理云上数据资产](./4-cmdb/cloud-asset.md)
  - [使用CMDB管理业务树](./4-cmdb/biz-tree.md) 
- [flow - 编排自动化工作流](./5-codo-flow/README.md) 
  - [安装 codo-agent](./5-codo-flow/codo-agent.md) 
  - [案例 - 使用 codo-flow 实现 golang 应用自动化CI/CD](./5-codo-flow/example-cicd.md) 
  - [案例 - 使用 codo-flow + cmdb 实现 跨地区应用部署](./5-codo-flow/example-distribute-deploy.md) 
  - [案例 - 使用 codo-flow + notice 实现 高效流程审批](./5-codo-flow/example-flow-audit.md)
- [配置中心 - 管理配置](./6-config-center/README.md) 
- [通知中心 - 完成高效率告警](./7-notice/README.md) 
- [云原生管理平台 - 管理多地集群](./8-cloud-native-management/README.md)

---

### Zh Guide README (`docs/zh/guide/README.md`)

# OpenDevOps

<p align="center">
    <a href="http://www.opendevops.cn/">
        
    </a>
</p>

[](https://www.python.org/)
[](https://golang.google.cn/)
[](https://www.tornadoweb.org)
[](https://cn.vuejs.org)
[](https://ant-design.antgroup.com/)
[](https://www.iviewui.com/)
[](https://github.com/996icu/996.ICU/blob/master/LICENSE)

[](https://www.bilibili.com/video/BV1rp4y1v7fa/)

## 架构总图



----

### 项目概述  

CODO 是一款专为企业设计的开源全球一站式运维平台，支持多混合云环境和自动化运维，为企业提供跨地域、跨云的统一管理能力。

### 技术架构与优势

- **前端**：基于 Vue + iView 和 React + Ant Design 开发，提供直观友好的操作界面，显著提升用户体验和工作效率。  
- **后端**：采用 Python Tornado 和 Golang Gin，具备轻量级、简洁清晰和异步非阻塞的特点，实现高并发和快速响应。
- **微服务网关**：基于 OpenResty + Lua，提供统一的 API 网关和服务治理能力，其优势在于高性能、灵活扩展和优秀的负载均衡支持。
- **微前端基座**：基于阿里乾坤框架，负责统一纳管前端应用，支持微前端架构，具备模块化管理、动态加载及高效集成的能力。

### 核心功能模块  

1. **自动化运维**：支持任务调度、批量操作和流程编排，提升工作效率。  
2. **实时观测与预警**：跨地域、跨云实时监控，保障稳定性。  
3. **配置管理**：集中管理云资源配置，减少人为错误，提升合规性。  
4. **云原生管理**：支持容器化与云原生技术，简化 Kubernetes 和微服务管理。  
5. **日志与审计**：提供统一的日志存储、分析及审计能力，确保安全性与可追溯性。  
6. **安全管理**：强化权限控制与访问管理。  
7. **多云管理**：整合多云环境，实现资源优化与高效管理。  

### 项目亮点  

- **高效统一管理**：支持跨地域、跨云环境，简化多云资源运维。  
- **可观测与智能化**：全面覆盖实时监控、预警与性能分析。  
- **强大自动化能力**：一站式自动化工具提升运维效率，降低操作复杂性。  
- **云原生支持**：优化容器化与微服务管理，为企业数字化转型赋能。  

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

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

## 模块介绍  

```plaintext
codo
├── codo-admin               # 管理后台  
├── codo-agent-server        # 底层管控  
├── codo-cloud-agent-operator # 云原生任务执行  
├── codo-cmdb                # 多云资源管理  
├── codo-cnmp                # 云原生管理平台  
├── codo-flow-servers        # 任务调度与流程管理  
├── codo-monitor             # 可观测平台  
├── codo-notice              # 通知中心  
├── codo-frontend            # 前端流量入口  
├── codo-gateway             # API网关  
└── codo-kerrigan            # 配置中心  
```  

1. [**codo-admin**](https://github.com/opendevops-cn/codo-admin/blob/main/README.md) 
   用于管理后台的操作平台，提供高效的管理界面和用户友好的操作体验。  

2. [**codo-agent-server**](https://github.com/opendevops-cn/codo-agent-server/blob/main/README.md) 
   底层管控模块，负责与主机或环境进行通信，实现资源的统一管理。  

3. [**codo-cloud-agent-operator**](https://github.com/opendevops-cn/codo-agent-server/blob/main/README.md) 
   负责执行云原生相关任务，支持 Kubernetes 等容器化任务的操作和调度。  

4. [**codo-cmdb**](https://github.com/opendevops-cn/codo-cmdb/blob/main/README.md) 
   数据资产管理平台，提供多云资源管理、CMDB 数据整合及资产统一视图。  

5. [**codo-cnmp**](https://github.com/opendevops-cn/codo-cnmp/blob/main/README.md) 
   云原生管理平台，专注于容器化、微服务及 Kubernetes 集群的管理。  

6. [**codo-flow-servers**](https://github.com/opendevops-cn/codo-flow/blob/main/README.md) 
   任务平台模块，支持任务调度、流程管理及批量作业执行。  

7. [**codo-monitor**](https://github.com/opendevops-cn/codo-monitor/blob/main/README.md) 
   可观测平台模块，提供实时监控、预警和性能分析能力，保障系统稳定性。  

8. [**codo-notice**](https://github.com/opendevops-cn/codo-notice/blob/main/README.md) 
  通知中心模块，支持多渠道通知推送，实现高效的事件响应。  

1. [**codo-frontend**](https://github.com/opendevops-cn/codo-frontend/blob/main/README.md) 
   前端应用和流量入口模块，处理 API 流量并路由至网关，支持模块化前端开发。  

2.  [**codo-gateway**](https://github.com/opendevops-cn/codo-gateway/blob/main/README.md) 
    API 网关模块，负责统一流量入口和服务治理，提供高性能路由与认证支持。  

3.  [**codo-kerrigan**](https://github.com/opendevops-cn/codo-kerrigan/blob/main/README.md) 
    配置中心模块，用于集中管理配置项，实现动态配置更新和分布式配置下发。  

## Architecture

---

### Zh Swagger Ui README (`docs/zh/swagger-ui/README.md`)

[](https://www.opendevops.cn/)
[](https://www.python.org/)
[](https://www.tornadoweb.org)
[](https://github.com/guokr/swagger-py-codegen)
[](https://pypi.python.org/pypi/swagger-py-codegen/)


----

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

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

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

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

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

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

----

### 简单描述
- 该内容应位于codo安装步骤中vue和静态文件部分。
- 通过 swagger-py-codegen 生成swagger-ui文件，生成静态文件，复制到静态目录文件夹，即可使用swagger。

### 基于 CODO 的 swagger-py-codegen 步骤（快速使用）
*请按着CODO文档，完成操作后再进行该操作，该操作在文档中也同样存在。*

```bash
# 就是这么简单
cd /opt/codo/codo
\cp -r swagger-ui/ /var/www/codo/ 
``` 


### swagger-py-codegen 的简单使用
- python3
- pip3

__1、安装swagger-py-codegen__
```bash
pip3 install swagger-py-codegen
``` 

__2、准备or编辑yml文件__
*官方的在线编辑工具*

__https://editor.swagger.io/__

__3、swagger_py_codegen命令参考__

__https://github.com/guokr/swagger-py-codegen__
```bash
# 生成静态文件
swagger_py_codegen -tpl=tornado  -s api.yml example-app-ui -p codo --ui --spec

``` 

__4、修改index.html文件__
首次生成，需要修改html文件 之后每次替换json文件即可让swagger生效

大概是77行左右 将“url: "/swagger-ui/swagger.json",” 的 json地址，改成真实可访问地址即可
```bash
vim example-app-ui/codo/static/swagger-ui/index.html
```

__5、复制swagger文件到网站的静态文件夹目录，注意json文件位置__
```bash
\cp -r example-app-ui/codo/static/swagger-ui/ /var/www/codo/
```


__6、每次重新生成静态文件后，替换json即可__
```bash
\cp -r example-app-ui/codo/static/swagger.json /var/www/codo/swagger-ui
```

---

### Zh Guide V2 1 Architectures README (`docs/zh/guide-v2/1-architectures/README.md`)

# 架构介绍

**系统组件**
codo 主要由以下组件组成

- 前端代码：[codo](https://github.com/opendevops-cn/codo)
- 管理后端：[codo-admin](https://github.com/opendevops-cn/codo-admin)
- 配置管理平台：[codo-cmdb](https://github.com/opendevops-cn/codo-cmdb)
- 任务调度：[codo-flow](https://github.com/opendevops-cn/codo-flow)
- 配置中心：[codo-kerrigan](https://github.com/opendevops-cn/kerrigan)
- 通知中心：[codo-notice](https://github.com/opendevops-cn/codo-notice)
- 灵云-kubernetes管理 ：[codo-cnmp](https://github.com/opendevops-cn/codo-cnmp)
- 管控中心 ：[codo-agent-server](https://github.com/opendevops-cn/codo-agent-server)
- 前端基座 ：[codo-home-index](https://github.com/opendevops-cn/codo-home-index)
- 天门网关 ：[codo-gateway](https://github.com/opendevops-cn/codo-gateway)

**系统架构**


**业务拓扑**


**流量拓扑**

---

### Zh Guide V2 2 Install README (`docs/zh/guide-v2/2-install/README.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 2.服务部署

## codo docker 部署

参考文档: [codo docker 部署](./docker.md) (demo推荐)

## codo k8s 部署

参考文档: [codo k8s 部署](./docker.md) (生产环境推荐)

---

### Zh Guide V2 3 Admin README (`docs/zh/guide-v2/3-admin/README.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 3.0 使用admin管理用户权限

## 管理应用

在 CODO 中预制了自身系统的应用, 同时, 用户也可以添加自己开发的应用集成到 CODO 中来



### 参数说明

- 应用编码: 作为应用的后端标识, 在权限配置中有作用
- 前端编码: 作为应用的前端标识, 在权限配置中有作用
- 名称: 应用的中文名称
- 外链: 应用的跳转链接
- 备注: 应用的解释说明

## 管理业务

业务是一种全局分类, 在 codo 的系统中起到资源隔离的作用



### 参数说明

- 业务ID: 作为全局参数参与到大量的业务隔离当中
- 英文名: 业务的英文名
- 中文名: 业务的中文名

## 管理权限(接口权限)

这里权限指接口权限, 用户也可以将自己需要的鉴权的权限注册进来



### 参数说明

- 应用编码: 对应上文的应用
- 权限名称: 权限的简单说明, 建议格式为 {应用}-{模块}-{权限范围}
- 请求方法: 接口的实际请求方法
- 请求路径: 请求的 URL 地址

> 建议:
>
> 权限的分类建议
>
> - GET 单独一类(只读)
> - 其他 method 一类 (管理)

## 管理菜单(前端权限)



### 参数说明

- 应用编码: 对应上文的应用
- 菜单名称: 菜单的英文, 与前端路由匹配
- 备注名: 菜单的展示名称

## 管理角色

角色是权限和用户的交集表示.



### 基础角色

基础角色类似权限包, 是一组一组的权限集合



### 通用角色

用于将 基础角色(权限包) 和 用户 进行关联

---

### Zh Guide V2 5 Codo Flow README (`docs/zh/guide-v2/5-codo-flow/README.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 5.使用flow编排自动化工作流

## 工作台

工作台主要用于操作流程订单



## 任务中心

任务中心主要用于快速发起任务

### 常用流程

#### 流程列表

可以多选常用流程组, 在右边触发任务



#### 流程编辑

点击 `编辑标签` 编辑常用流程





### 脚本执行

用于快速下发物理机作业任务到 agent



### 文件分发

用于快速下发文件分发任务, 将一个机器上的文件分发到各个机器上(需要 安装 codo-agent)





### 无服务执行

用于快速下发云原生任务到 k8s 集群中执行



## 流程设计

用于配置 标准化工作流(SOP) , 进行日常作业.



## 脚本管理

用于配置 物理机作业 的脚本. 用于 快速执行 或者 流程引用





## 接口管理

用于配置 自动化接口请求, 可以被流程引用来执行



## 凭证管理

凭证是一种特殊的常量, 配置之后会端到端的加密传输到 agent 最终以环境变量的形式暴露给脚本任务





## 构建机组管理

主要用于 CI 场景, 给一组构建机编组, CI 时会派发任务到其中一台



## 无服务声明

新一代的 serverless 脚本任务, 整体任务运行在容器上, 可以脱离虚拟机, 只需要 k8s 的算力资源即可运行



## 数据字典

用于固化业务流程的数据枚举, 以及用户可见性(数据权限)





## 节点管理

主要用于管理 codo-agent , 以及 agent 扩展

### 节点列表(定时同步)

agent 基础信息展示, 可以在这里给 agent 升级 & 安装插件.



### 组网列表

agent 和 server 之间开辟的一条 专属信道可以 跨网络、跨区域 运输任意 TCP 流量到对端



### 业务映射

将云原生agent与业务绑定, 从而实现 业务的 serverless 任务可以派发到对应的集群执行





### 实时节点(实时连接信息)

agent 实时的连接信息表

---

### Zh Guide V2 7 Notice README (`docs/zh/guide-v2/7-notice/README.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 7.使用通知中心完成高效率告警
## 项目结构



```text
.
├── docs
├── etc
├── internal
│   ├── biz
│   ├── conf
│   ├── dep
│   ├── ievents
│   ├── imiddleware
│   ├── impl
│   │   ├── alerts
│   │   └── data
│   │       └── models
│   ├── pkg
│   │   └── istr
│   ├── server
│   └── service
├── meta
├── pb
│   ├── channel
│   ├── healthy
│   ├── router
│   ├── templates
│   └── user
├── scripts
└── third_party
    ├── google
    │   ├── api
    │   └── protobuf
    │       └── compiler
    ├── khttp
    ├── openapi
    │   └── v3
    └── validate
```

## 术语解释

- 消息模板(无状态): 一个消息的模板定义, 负责定义渲染引擎 & 发出渠道
- 通知通道(有状态): 一组通知的集合, 在不同的通知级别中, 发向不同的 **消息模板**, 同时在这里配置 **消息模板** 的渠道方的配置(密钥等)
- 通知路由(有状态): 一个消息解析&路由器, 作为一个 http 回调端点, 对回调的内容进行解析, 并将消息路由到对应配置的 **通知通道**.
    - labels: 通知进行路由的数据依据, 从回调的 httpQuery 和 jsonBody 两处取值进行合并, 相同key 时, jsonBody 优先
    - data: 用于消息模板的数据渲染, 从 jsonBody 取值



## 快速入门

### 配置消息模板

在 消息模板 页签, 点击 创建, 即可进行配置.

模板用途 用于在配置通知通道时, 与对应的通道通途对应.

目前支持:

- 飞书机器人(飞书 webhook 机器人)
- 飞书应用(飞书bot 单聊)
- 钉钉机器人(钉钉 webhook 机器人)
- 钉钉应用(钉钉bot 单聊)
- 企业微信机器人(企业微信 webhook 机器人)
- 企业微信应用(企业微信bot 单聊)
- 阿里云短信
- 阿里云电话
- 腾讯云短信
- 腾讯云电话
- 邮件
- webhook



### 快速调试(飞书webhook机器人为例)

在填入 **模板内容** 之后, 点击 **保存** 之后, 可以对模板进行快速调试, 在 **地址** + **密钥** 上填入 **飞书webhook机器人** 的配置

关于添加自定义机器人, 可以查看: [飞书自定义机器人指南](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot?lang=zh-CN)





### 配置通知通道

注意事项:

- 选中对应的 **通道用途** 之后, 后续只能选择 **对应通道用途** 的 **消息模板**
- **通知用户** 为默认通知用户, 可以在通知路由回调接口时, body 中传入 key 为 “noticer”, value 为 “英文逗号分隔的用户名”, 用于替换
- 默认提供两个固定模板(作为简单使用, 无需配置 **通知模板**), 如果不需要可以 告警级别设置为空(电话告警), webhook 设置为空(飞书机器人告警)

配置基础信息:



配置固定模板:



配置自定义模板:



#### 回调配置

还可以配置回调用于信息交互



展示



### 配置通知路由

注意:

- 通知路由地址: **网关地址/api/noc/v1/router-alert** ( 支持 POST | GET )
- http post 中的 jsonBody 会用作消息模板的数据渲染
- jsonBody 和 httpQuery 部份会一起作为 **labels数据** 进行通知路由匹配
- 如果 severity 为空, 则默认级别为 “警告”

特殊业务意义字段:

```golang
FieldsMessage     = "message"      // 通用消息字段 (从 jsonBody 取值)
FieldsManager     = "codo_manager" // 业务负责人 (从 httpQuery + jsonBody 取值)
FieldsNoticer     = "codo_noticer" // 内置通知人 (从 httpQuery + jsonBody 取值)
FieldsSeverity    = "severity"     // 告警等级 [fatal | error | warn | info] (从 httpQuery + jsonBody 取值)
FieldsTitle       = "title"        // 告警标题 (从 httpQuery + jsonBody 取值)
FieldsNativeTitle = "codo_title"   // 原生标题 不做其他处理 (从 httpQuery + jsonBody 取值)
FieldsStatus      = "status"       // 告警状态 [resolved | firing | resolving | inactive] (从 httpQuery + jsonBody 取值)
FieldsAppCn       = "cmdb_bizcn"   // 业务中文描述 (从 httpQuery + jsonBody 取值)
FieldsCallbackArgs = "codo_callback_args" // 回调参数, 只能是个字符串 (从 httpQuery + jsonBody 取值)
```

---

### Zh Guide V2 8 Cloud Native Management README (`docs/zh/guide-v2/8-cloud-native-management/README.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 8.使用云原生管理平台管理多地集群



## 集群接入

填入kubeconfig 即可完成接入

- 需要注意服务器和 kubeconfig 的 api 地址网络联通性
- 使用最高权限的 kubeconfig 导入







## 凭证导出

权限配置好之后, 可以导出访问凭证, 导出的凭证用户流量会先进入到 灵息 平台, 由 灵息 平台代理到目标集群

从而可以无感实现

- 操作审计
- 权限控制





## 权限配置

### 配置角色

一般来说不需要特别配置角色, 预置的管理员以及只读足够了



### 用户组授权

**用户组授权需要需要先在 [后台管理 配置好角色](../3-admin/role-auth.md)**





## 操作审计

---

### Zh Guide Used README (`docs/zh/guide/used/README.md`)

# 如何使用
[[toc]]

::: tip
这部分主要是使用文档
:::


## 任务模版

> 这部分文档主要用来介绍任务模板，任务模板：可以帮助你实现一个很强大、很复杂、可干预、自定义的任务流程模板；  
> 任务模板功能主要分为：命令管理、模板管理、参数管理、执行用户等部分，由于这块稍微有点难理解，我们提供了[示例文档](https://docs.opendevops.cn/zh/guide/more/example/)和[视频演示](https://www.bilibili.com/video/av53424572/)



**命令管理**
> 主要用于创建你的自定义命令，后续供平台执行使用

**功能特点**
- 支持`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请参考`执行用户`文档）




示例图：




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

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


**如何使用**  

点开`任务模板`->`模板管理`
- 创建模板
  - 模板名称： 建议输入一个有意义的名称，注意：`此名称不可更改`



**如何对模板赋权**
> 模板赋权是☞哪些用户可以对此模板有权限（编辑、删除、修改等），管理员默认拥有所有权限。

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


**自定义你的模板流程**

首先我们已经创建了一个新的模板，接下来我们向模板里面添加一些自定义的内容
- 1、选中你的模板
- 2、下拉选择你的命令进行提交（支持同时选择多个哦~）
- 3、修改模板流程中的字段信息
- 4、最后记得保存编辑

示例：



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


单组配置示例：



多组配置示例：




**参数管理**
> 参数名称类似于别名的概念，订单显示时参数值会被参数名称替代

多组配置示例：

​                        

**执行用户**

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

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

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

若你的机器没有私钥，你可以手动生成一堆公钥私钥进行放置到服务器~/.ssh/目录下，参考命令：
```shell
#生成密钥对
$ 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
```

新建执行用户示例：







## 任务发布

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

**操作教学视频**：[https://www.bilibili.com/video/av53424572/](https://www.bilibili.com/video/av53424572/ ) 

**应用发布**

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

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

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

**创建应用发布**

点开`应用发布`

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



**SQL审核**

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

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

点开`SQL审核`

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



**SQL优化**

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

**注意**

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

点开`SQL优化`

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



**资源申购**

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

**节点添加**

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

**自定义任务**

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

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

点开`自定义任务`

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



**自定义任务-代理**

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

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

点开`自定义任务-代理`

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



**自定义任务-JSON**

>该模块提供了自定义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格式，请严格按照说明提交)
- 执行时间：选择一个执行时间，用来触发模板中的定时触发




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


## 定时任务

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


**定时任务特点**

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



**用户使用说明**

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





- 编辑任务





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





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










## 代码仓库

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

**创建代码仓库**

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

**填写对应git_url、[private_token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)、deploy_key**

- git_url： https://gitlab.domain.com/
- [private_token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html): Gitlab申请的Access Token





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





至此，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`脚本中修改成以下内容：

```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

```
示例图：




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

注意： 一定要修改脚本中`accept_task_url` 、`git_url`、`auth_key`内容

```
/* Detailed source-code truncated for AI context efficiency. */
```



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

> 针对单个项目进行配置钩子规则，当你打Tag/brach中提交的的时候，根据你的匹配规则，正则匹配、来触发你所定义的任务


- 选择其中一个项目，点击对应的编辑按钮





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




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












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

示例命令：

```shell
#基于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

```

**平台查看钩子日志**  





**注意**

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



## 监控告警


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


**ZABBIX**

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


**功能简介**

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


**首先，点击ZABBIX配置，配置你的地址**



**刷新地址，将已配置的ZABBIX组/主机Hostname拉取下来**




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



至此，到这一步，已经将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/  

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




**配置钩子**

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


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

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






**测试钩子**

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

  







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


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



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




**钩子日志**


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

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







**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  只要是触发脚本类型的都在这里


```shell
#让我们查一下你的配置是什么？

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

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

```

ZABBIX2.0版本

官方示例脚本：

```python
#!/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**





**配置一个Action**

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

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

```

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

```










以上，是ZABBIX 2.0版本的配置


**ZABBIX3.0配置webhook**

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




**先将脚本放到服务器上**

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


```shell
#让我们查一下你的配置是什么？

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

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

```

ZABBIX3.0版本

官方示例脚本：

```python

#!/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配置







**配置一个Action**

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

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

```

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

```









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




## 资产管理

> 这部分主要介绍CMDB资产管理一期，更多新功能正在开发中，现版本详细操作也可观看[视频示例](https://www.bilibili.com/video/av53408299/)



**添加主机**

- 管理用户： 例如AWS的`ec2-user`

- 其余字段不做多解释，从字面可以看出意思



**资产更新**

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





**同步标签树**

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





**机器状态**

CMDB中的几种状态

- New：表示手动新增的机器
- Auto：表示自动从云厂商拉取过来的主机，这个时候主机详情的信息都是云上获取到的一些基础信息
- True：表示已经手动点了资产更新的操作，这时候资产信息都是从主机系统上脚本获取到的信息

- False：表示更新资产失败，这个状态下是可以查看错误日志的



**DB管理**

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



**标签管理**

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



**管理用户**

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





**资产配置**

这一块主要用来用户给我配置一些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不等，因为请求接口都在国外



## 配置中心

> 这部分主要介绍下配置中心使用说明


**新建项目**  



**填写环境-服务等信息**


**对项目授权**

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



**对单个环境授权**

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



**如何获取配置**

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

- 简单示例，也可[参考复杂示例](https://github.com/opendevops-cn/kerrigan/blob/master/libs/get_config.py)

Python版本 

```
/* Detailed source-code truncated for AI context efficiency. */
```



Go版本    

`go run write_conf.go -p code-v1 -e dev -s codo-admin -f settings.py -r /tmp/settings.py1`
```
/* Detailed source-code truncated for AI context efficiency. */
```



## 用户管理

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



**用户列表**

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

**功能支持**

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


**展示界面**







**权限列表**

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



**注意事项**

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



**功能说明**

- 支持多种搜索方式，如：权限名称、请求路径、请求方法、时间等
- 支持新增、编辑、关闭、删除等操作权限的管理

- 支持新增自定义权限功能，适用于开发人员编写的API接口能很方便的接入进来权限管理划分

- 一些详细的API及使用文档正在支持更新中............







**菜单组件**

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



**注意事项**

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



**功能介绍**

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

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

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





**角色管理**

基于[RBAC](https://baike.baidu.com/item/RBAC/1328788?fr=aladdin)角色管理访问控制权限，可以很精细/方便的管理你的用户权限



**功能介绍**

- 角色的搜索、编辑、关闭、删除
- 自定义角色名字，自定义赋权组件、菜单、权限管理

- 列表可搜索赋权设计，方便用户可视化操作







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

**创建普通用户示例**

**新建用户**  

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

**用户赋权**








**创建管理员用户示例**

**新增用户**

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



**用户赋权**

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









**获取长期Token**

>本系统使用token进行身份验证，当用户需要API进行访问的时候就需要获取token，并把token放入cookie里或者 访问的url参数里 

- 从用户管理 > 菜单组件里面找到 get_token_btn 这个代表获取token的按钮 要存在并且启用 
- 从用户管理 >角色管理里面找到你要赋值的角色，点击组件把get_token_btn 添加进去 



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



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

```python
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/域名，必填项.



**邮件设置**

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

不同运营商配置可参考`FAQ`中[邮箱设置问题](https://docs.opendevops.cn/zh/guide/more/faq/)


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





**短信接口**
> 这块主要配置短信接口信息，短信接口只支持阿里云`阿里大鱼`，后续平台所涉及到发短信会调用此接口

- 短信区域： `cn-hangzhou` 目前阿里官方给出必须是这个
- API名称： `Dysmsapi` 目前官方给出一般都是这个名称
- API域名：`dysmsapi.aliyuncs.com` 目前官方给出必须是这个地址
- KEY_ID： 你的IAM访问控制密钥ID
- KEY_SECRET： 你的access_secret密钥，备注：`这里需要必须有SMS的权限`
- 点击测试端口系统会向阿里大鱼进行发送查询接口，如果配置验证不通过则提示报错信息



**LDAP设置**

>这块主要用于配置LDAP认证

实例图如下：

​    

**邮箱登陆**
> 这块主要是支持第三方邮箱登陆，当你想要使用邮箱登陆此平台时，你可以在此进行配置
比如我们企业邮箱是腾讯的,域名就是`opendevops.cn`，SMTP就是腾讯的`stmp.exmail.qq.com`,这样配置完成后我就可以使用我`yanghongfei@opendevops.cn`邮箱+密码登陆此平台了。


- 邮箱SMTP： 这里输入你邮箱服务商的SMTP地址
- 邮箱域名：这里是你的邮箱后缀名字





**存储配置**

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




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








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

---

### Zh Guide Install Distribute README (`docs/zh/guide/install/distribute/README.md`)

# Kubenetes Helm部署

## 项目简介

- 本项目采用微服务架构，完成全球一站式运维体系建设。

- Demo 地址：https://demo.opendevops.cn/user/login  `用户：demo 密码：2ZbFYNv9WibWcR7GB6kcEY`

```text
codo
├── codo-admin # 管理后台
├── codo-agent-server # 底层管控
├── codo-cloud-agent-operator # 执行云原生任务
├── codo-cmdb # 数据资产、多云资源管理
├── codo-cnmp # 云原生管理平台
├── codo-flow-servers # 任务平台、作业调度执行
├── codo-monitor # 可观测平台
├── codo-notice #  通知中心
├── codo-frontend # 前端应用、流量入口(API流量 先进这里再路由到 gateway)
├── codo-gateway # API网关
└── codo-kerrigan # 配置中心
```

## 一键安装

```shell
git clone https://github.com/opendevops-cn/codo-deploy-docs.git
cd helm-deploy
bash ./quick_start/all_in_one.sh


# [optional]
# 业务参数文件
export local_biz_values_file=./data/biz.values.yaml
# 业务镜像文件
export local_biz_images_file=./data/biz.images.yaml
# 中间件参数文件
export local_mid_value_file=./data/mid.values.yaml
# 部署 cloud-agent-operator (默认不部署)
export local_deploy_crd=true
```

## 配置转发

```shell
kubectl -n codo-test port-forward services/codo-biz-frontend 8888:80
```

## 进入控制台
- 账号: admin
- 密码: 1qazXSW@

---

### Zh Guide Install Local README (`docs/zh/guide/install/local/README.md`)

# Docker Compose部署

::: tip
完全抽象出来的本地部署方式，不理解Docker的同学可以使用本文的进行参考

部署视频参考：

视频会在业余时间持续录制，更多视频可以参考Up主空间：https://space.bilibili.com/388245257/

- [部署安装教程](https://www.bilibili.com/video/BV1BL4y1a7TU/)
- [快速了解视频](https://www.bilibili.com/video/BV1rp4y1v7fa/)
- [二次开发教程](https://www.bilibili.com/video/BV1Sy4y137md/)

:::

## 项目简介

- 本项目采用微服务架构，完成全球一站式运维体系建设。

- Demo 地址：https://demo.opendevops.cn/user/login  `用户：demo 密码：2ZbFYNv9WibWcR7GB6kcEY`

```text
codo
├── codo-admin # 管理后台
├── codo-agent-server # 底层管控
├── codo-cloud-agent-operator # 执行云原生任务
├── codo-cmdb # 数据资产、多云资源管理
├── codo-cnmp # 云原生管理平台
├── codo-flow-servers # 任务平台、作业调度执行
├── codo-monitor # 可观测平台
├── codo-notice #  通知中心
├── codo-frontend # 前端应用、流量入口(API流量 先进这里再路由到 gateway)
├── codo-gateway # API网关
└── codo-kerrigan # 配置中心

```

## 环境依赖

- 操作系统：Rocky Linux 9.1以上 x86_64
- Docker版本：最新稳定版本
- Docker Compose版本：最新稳定版本

**优化系统**  

注意：

- 如果你的系统是新的，我们建议你先优化下系统，同样我们也提供了[优化系统脚本](https://github.com/opendevops-cn/opendevops/tree/master/scripts/system_init_v1.sh)
- 以下基础环境中，若你的系统中已经存在可跳过，直接配置，建议使用我们推荐的版本

## 快速部署

- 开发环境使用docker-compose方式, 完成管理后台、网关服务、前端项目、任务平台、配置中心、Agent-server的部署.
- 部署时先部署中间件, 中间件正常运行后部署应用.
- 安装 Docker 和 Docker-compose
  
> Docker安装命令参考 **[Rocky Linux 9 操作系统]**

```shell
sudo dnf install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
  ```

> docker-compose安装命令参考 **[Rocky Linux 9 操作系统]**

```shell
sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```

---

**克隆仓库**  

```shell
mkdir -p /opt/codo/ && cd /opt/codo/
git clone https://github.com/opendevops-cn/codo-deploy-docs.git
cd codo-deploy-docs/docker-deploy
```

- 配置文件修改【可选】[.env](https://github.com/opendevops-cn/codo-deploy-docs/blob/main/docker-deploy/.env) <span style="color: red;">
  中已经配置项目中所需的账密信息，不修该则使用默认配置</span>
- 数据库初始化【可选】：[db_init.sql](https://github.com/opendevops-cn/codo-deploy-docs/blob/main/docker-deploy/db_init.sql) <span style="color: red;"> 在 Docker 部署 MySQL 时默认导入。

---

- 部署中间件 如需依赖已有中间件则需要修改[.env](.env)配置

```shell
sh ./deploy_middleware.sh
```

--- 

- 启动服务并初始化

```shell
sh ./init_app.sh
```

- 管理后台创建超级用户

> 默认的admin 密码为 1qazXSW@

```shell
docker exec -it codo_mg python3 manage.py createsuperuser
```

---

### Zh Guide More Contributor README (`docs/zh/guide/more/contributor/README.md`)

# 贡献者

**写在前面**  

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


核心贡献人员

- **老徐 (James Xu)：** 项目组织，发起者、项目运营
- **赵高：** 安全大佬，核心架构和流程贡献者
- **硕哥：** 小卡拉米，设计平台架构，贡献核心代码和文档
- **青牛踏雪：** SRE专家，项目管理和首席项目运营
- **小飞(Fred Yang)：** SRE大佬，产品设计和核心代码贡献者
- **ops-office：** 神秘大佬，运维咖啡吧、一杯咖啡、轻松运维，贡献配置中心等模块
- **D神：** 神秘大佬，核心代码贡献者
- **蔡程：** 开发大佬，核心代码贡献者，项目核心维护者
- **南哥(Sean Chen)：** 前端开发工程师，代码贡献者
- **punk：** 神秘大佬，代码贡献者
- **勇男：** SRE大佬，平台测试、项目运营
- **智哥：** SRE大佬, 贡献容器化支持、SQL审核优化、文档，功能测试验收
- **王帅：** 神秘大佬，API文档维护者

文档贡献人员

- **liuchunyun** 高级运维工程师, 贡献文档、功能测试，并提供了很多建议
- **yangmingwei** 高级运维开发工程师，核心文档贡献者
- **zhirenyongnan**  运维工程师，贡献文档、项目运营
- **libo** 运维工程师, 贡献文档、功能测试
- **jiangming** 淘宝运维, 贡献文档、功能测试，并提供了很多建议

**为开源OpenDevOps贡献代码**  

贡献可以有很多

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

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


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

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

---

### Zh Guide More Example README (`docs/zh/guide/more/example/README.md`)

# 最佳实践

[[toc]]

::: tip

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

[戳这里观看OpenDevOps任务平台示例视频](https://www.bilibili.com/video/av53424572/)
:::

::: details 点我展开
- 示例1. 平台上提交一个最简单的任务，不带参数的（视频）

- 示例2. 平台上提交一个带参数的任务。(PARAMETER)（视频）

- 示例3. 平台上基于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. 不登陆平台的情况下怎么提交一个任务（POST API提交）
```
/* Detailed source-code truncated for AI context efficiency. */
```

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

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

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


**配置钩子**

[GitLab Hooks](https://docs.gitlab.com/ee/administration/custom_hooks.html)分为2种：

- Hooks：全局钩子，适用于所有项目
- Custom Hooks： 项目钩子，针对项目来做钩子触发任务

如何使用？

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

```shell

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

```
  
 
创建[Update](http://yanghongfei.me/2019/03/25/git-hooks/)钩子


```
/* Detailed source-code truncated for AI context efficiency. */
```


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


```shell

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推送上去

```
:::




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

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

::: details 点我展开

你需要具备以下环境：

- [GitLab](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/README.md)
- [GitLab Hooks](http://yanghongfei.me/2019/03/25/git-hooks/)
- [GitLab Depoly Keys](http://yanghongfei.me/2019/03/19/gitlab-api-enable-depoly-key/)
- [OpenDevOps 开源自动化运维平台](http://www.opendevops.cn/)


**发布为什么选择过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~`，平台历史记录可查看发布信息


**创建模板**

- 记下模板ID
- 模板执行顺序自行排版
- [opendevops模板使用说明](https://docs.opendevops.cn/zh/guide/used/#%E4%BB%BB%E5%8A%A1%E6%A8%A1%E7%89%88)



**配置钩子**

[GitLab Hooks](https://docs.gitlab.com/ee/administration/custom_hooks.html)分为2种：

- Hooks：全局钩子，适用于所有项目
- Custom Hooks： 项目钩子，针对项目来做钩子触发任务

如何使用？

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

```shell

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

```
  
 
创建[Update](http://yanghongfei.me/2019/03/25/git-hooks/)钩子


> 这里我有已经运行2年的脚本供各位参考。

```
/* Detailed source-code truncated for AI context efficiency. */
```


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


```shell

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推送上去

```

最终的结果


:::




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

::: details 点我展开

**环境说明**

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

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



**如何使用**

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

[Youtube](https://www.youtube.com/watch?v=jM8DSbUh0Rs&t=47s) | [BiliBili](https://www.bilibili.com/video/av53460519/)



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



**对项目进行赋权**

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



**获取一个用户的长期Token**

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





**服务器上拉取配置**

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

这里提供一个配置脚本示例(dnsmasq)，更详情的脚本可参考[配置中心](https://github.com/opendevops-cn/kerrigan/blob/master/libs/get_config.py)

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

```
/* Detailed source-code truncated for AI context efficiency. */
```

运行查看结果：

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

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


**配置DNS发布**



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



**新建命令和模板配置**

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





**提交一个自定义任务**





**审批任务**





**执行结果**



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


:::








### 基于私有对象存储管理示例
::: tip
本文档用来讲解如何使用私有读写的对象存储通过网关做鉴权（阿里云OSS示例）
:::

::: details 点我展开

**设置Bucket**
阿里云创建对象存储Bucket，权限设置为私有。



**设置CDN**
OSS私有读访问鉴权比较复杂，经过测试我们选型通过CDN做访问鉴权，

这样既可以使用CDN加速访问降低选型走内网传输对网络造成的压力，并且可以不改变访问URL的情况下做鉴权。

配置阿里云OSS私有Bucket回源。



**配置远程鉴权**

最简单的处理，只判断是否登录，没登陆的状态码是401，

所以我们只用配置鉴权失败状态码为401，超时动作设置为拒绝；

后续我们也可以在鉴权接口上配置是否有权限，并做日志记录。





因为鉴权都在网关，后端接口可以不用做什么改动

```python
class  CDNAuth(BaseHandler):
    def get(self):
        # 记录CDN日志,暂不需要
        pass 
```


**上传接口使用**
- 请求URL：`/api/mg/v1/storage/file/private/`
- 请求方式：`POST`
- 表头：`Content-Type:"multipart/form-data"，file-dir=""` file-dir 代表上传的目录，需要放入header，如果没有则默认为file目录
- 参数： 

  | 参数名   | 必选 | 类型 | 说明     |
  | -------- | ---- | ---- | -------- |
  | filename | 是   | str  | 文件名称 |
  | body     | 是   |      | 文件内容 |
  

- 输入示例

```json
[
        ('field1', ('foo.png', open("/tmp/filePath1", 'rb'), 'image/png')),
        ('field2', ('bar.png', open('/tmp/filePath1', 'rb'), 'image/png'))
]
  ```

- `r = requests.post(url, data, files=files)` 使用requests.post的files参数
- 返回：
```
  {
      "code":0,
      "msg":"上传成功"
  }
```

**前端访问**

上述已经讲解如何上传和CDN配置，下面我们讲怎么访问：

- 鉴权交互图

  

- 用户通过CDN访问OSS资源的时候会带着访问的headers（我们统一登录的时候会把JWT数据写入前端的headers），CDN会使用携带的headers数据去我们的天门网关鉴权（天门网关需开启jwt auth 或者codo rbac插件），如果headers数据正常则可以访问，否则返回401状态，CDN则返回用户403。

  
  

- 示例在我们的自定义表单的上传组件中使用

  

- 上传成功可以直接预览  

  


:::

---

### Zh Guide More Faq README (`docs/zh/guide/more/faq/README.md`)

### FAQ

[[toc]]

### 邮箱设置问题
> 由于常见的Email有很多，这里列举下最常见的Email设置
::: details 详细信息

- Q: QQ邮箱怎么设置？
- A: QQ邮箱主要注意使用网页生成授权码进行作为密码登陆
    - [SMTP地址](https://service.mail.qq.com/cgi-bin/help?id=28&no=167&subtype=1)：smtp.qq.com
    - SMTP端口：465
    - SSL加密：True, 开启
    - 用   户: <your_qq>@qq.com
    - 密   码： 授权码（一般为16位）



- Q: 腾讯企业邮箱如何设置？
- A: 腾讯企业邮箱同QQ邮箱，唯一一点SMTP服务器不同
    - [SMTP地址](https://service.exmail.qq.com/cgi-bin/help?subtype=1&id=28&no=1000585)：smtp.exmail.qq.com
    - SMTP端口：465
    - SSL加密：True, 开启
    - 用   户: <your_name>@domain.com
    - 密   码： 授权码（一般为16位）



- Q: 网易163邮箱如何设置？
- A: 同上，唯一一点SMTP服务器不同
    - [SMTP地址](http://help.163.com/09/1223/14/5R7P3QI100753VB8.html)：smtp.163.com
    - SMTP端口：465
    - SSL加密：True, 开启
    - 用   户: <your_name>@163.com
    - 密   码： 授权码（一般为16位）



- Q: Gmail邮箱如何设置？
- A: Gmail邮箱考虑到安全，需要注意以下2步
  -  首先开启Google 二步认证
  -  [生成Google 应用专用密码](https://support.google.com/mail/answer/185833?hl=zh-Hans)
  - [SMTP地址](https://support.google.com/mail/answer/7126229?hl=zh-Hans&visit_id=636771670247559816-1235179449&rd=2)：smtp.gmail.com
  - SMTP端口：465
  - SSL加密：True, 开启
  - 用   户: <your_name>@gmail.com
  - 密   码： 授权码（一般为16位）
:::



### Docker Bulid 报错问题
::: details 详细信息
- 安装依赖报错：`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
```


- 解决办法：
```shell

Python3x版本后Docker里面需要加入--user的参数，修改Dockerfile, 加上--user参数， 如：pip3 install --user --upgrade pip
```
:::



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

::: details 详细信息

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

### Google Authenticator怎么使用?
> 安全一定是最重要的，相信很多人都知道谷歌身份验证器，这里简单说下Google身份验证器怎么使用, 本平台Google验证码密钥是发送到用户邮箱的。
::: details 详细信息
**下载谷歌验证器**
- iOS用户登录AppStore搜索"Authenticator"
- 安卓用户登录应用商店或利用手机浏览器搜索“谷歌验证器”下载,也可[点击下载](https://www.wandoujia.com/apps/com.google.android.apps.authenticator2)

**添加所需网站验证码**

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

- 扫描条形码  



- 手动输入密钥  




**手机丢失怎么办**

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

:::

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

::: details 详细信息
Q：可以登陆进去，但是一直闪屏刷新/退出？
  
A：出现这个问题是因为网关`token_secret`和`codo-admin`里面`token_secret`配置不一样，改成一样即可。
请仔细阅读网关配置中的注册API网关文件 `configs.lua`这块
:::
  
###  Docker内部的MySQL、Redis无法连接问题  

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


:::

### 网关提示域名gw.opendevops.cn找不到，或者网络不通
```
iptables -F
### 这个是环境准备时候部署的dnsmasq所在的地址，请睁大眼睛不要写错了
echo "nameserver 127.0.0.1" > /etc/resolv.conf   
service dnsmasq restart
systemctl restart docker.service
ntpdate ntp1.aliyun.com
```
### 新部署的系统无法创建User？没办法看到创建/重置/获取Token？  

::: details 详细信息
Q：新部署的时候登陆进去，点击用户列表没办法创建/看不到重置密码/重置MFA按钮等问题？ 

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

操作步骤可参考：https://docs.opendevops.cn/zh/guide/more/permission/

:::

### 如何在 CODO 上开发新应用

> 基于CODO的开发框架进行开发新应用，前端、后端怎么开发和注册
::: details 详细信息

Q：前端怎么开发接入？

1. CODO 使用 qiankun 微前端架构进行模块集成。
2. 使用CODO官方模板：[codo-subapp-tpl 前端模板]((https://github.com/opendevops-cn/codo-subapp-tpl))
3. 开发完成后，将子应用注册到 CODO 主框架中，关于注册和通信方式，详见：[微前端开发文档]((https://github.com/opendevops-cn/codo-subapp-tpl)) 
   
Q：后端怎么开发接入？

1. 后端服务应提供标准 RESTful 接口，并通过 天门网关 接入 CODO。
2. 使用任意后端框架（如 SpringBoot / Node.js / Flask）
3. 接口路径规范化，并配置到天门网关中
4. 配置参考文档 [天门文档](https://github.com/opendevops-cn/codo-gateway)

Q：应用展示与注册？
> 将你的应用注册到 CODO 管理后台即可在主界面展示。

1. 登录 CODO 管理后台
2. 进入 应用管理 页面，添加你的应用信息
3. 具体配置字段详见： [用户手册]((https://github.com/opendevops-cn/codo-admin/blob/main/docs/codo-admin.md))。

**📚 其他参考资料** 

- 🔧 [qiankun 微前端框架](https://github.com/umijs/qiankun)

::: 

### Docker compose 的部署如何更新最新版本
::: details 详细信息

1. 更新镜像并重启

```bash
docker compose -f docker-compose-app.yaml pull
docker compose -f docker-compose-app.yaml up -d
```

2. 更新后报500错误，一般是字段发生变更需要删表重建或者自己补齐字段 

推荐把错误信息发给AI（GPT、Gemini、DS）让AI 告诉你怎么补齐新加的字段即可。

:::



### 如何获取参数与上下文传递变量

在流程自动化和脚本执行中，获取参数与传递变量是常见需求。以下介绍从不同来源获取参数并在上下文中传递变量的方法。
::: details 详细信息

#### 1. 生成流程过程变量

通过脚本输出标准化的格式，以便后续从日志中提取变量。约定格式为： 

- 以 ###SOF### 开头，###EOF### 结尾。
- 内容为合法的 JSON 字符串。

**示例代码（Python）:**
```python 
#!/usr/bin/env python

import json

# 定义变量
data = {
    "name": "John Doe",
    "age": 30,
    "is_employee": True
}

# 输出标准化数据
print(f"###SOF###{json.dumps(data)}###EOF###")
```
注意:

- 日志处理程序需提取最后一组匹配 ###SOF### 和 ###EOF### 的内容。

- 确保输出为合法 JSON 格式，使用双引号以符合 JSON 标准。

#### 2. 无论使用何种语言，都可以从环境变量或上一步输出中获取上下文数据。以下是不同场景的实现方式：

> FLOW_ID 和 NODE_ID 属于系统内置的变量可以直接获取
> 环境变量 需要加codo_前缀

**示例代码（Shell/Bash）:**
```bash
#!/bin/bash

# 打印所有环境变量
echo "==== 环境变量 ===="
printenv

echo -e "------------\n\n"
# 系统内置的可以直接取
echo "订单的ID: ${FLOW_ID}"
echo "当前任务节点的ID: ${NODE_ID}"
echo "当前任务执行的agent的crc32之后agent_id: ${crc32_agent_id}"
echo -e "------------\n\n"
# 环境变量 需要加codo_前缀
echo "上个节点输出的名称: ${codo_name}"

```

**示例代码（Python）:**
```python
import os

# 获取环境变量
flow_id = os.getenv("FLOW_ID")
node_id = os.getenv("NODE_ID")
crc32_agent_id = os.getenv("crc32_agent_id")
codo_name = os.getenv("codo_name")

# 输出环境变量信息
print("==== 环境变量 ====")
print(f"订单的 ID: {flow_id}")
print(f"当前任务节点的 ID: {node_id}")
print(f"Agent 的 CRC32 编码后 ID: {crc32_agent_id}")
print(f"上个节点输出的名称: {codo_name}")

```


#### **tips: 在自动化流程中，生成唯一标识很重要。以下组合能确保标识的唯一性：**

- FLOW_ID + NODE_ID：保证全局唯一性，用于标识同一流程中不同节点。
- FLOW_ID + NODE_ID + crc32_agent_id：在批量执行场景中，可进一步区分任务实例。
  

:::

---

### Zh Guide More Permission README (`docs/zh/guide/more/permission/README.md`)

# 权限文档

[[toc]]

::: tip
这部分主要讲解关于系统中权限相关的说明
:::

::: warning
注意：超级管理员用户不受权限限制，默认拥有所有权限  
:::


### 关于User用户管理


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

在数据库`codo-admin`中`codo_a_users`表字段 superuser
- 0：代表超级管理员
- 10：代表普通用户 

## 业务、用户、权限配置
https://github.com/opendevops-cn/codo-admin/blob/main/docs/codo-admin.md


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

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

- 点击菜单栏`用户管理`-`用户列表`-`新建用户`， MFA使用参考[FAQ](https://docs.opendevops.cn/zh/guide/more/faq/)







### 关于Mail邮箱注册


> 管理员一个个创建用户太过麻烦，我们支持邮箱注册，比如你是企业邮箱，你只需轻松2步，你就可以实现邮箱注册，让企业用户自己注册，管理员只管赋权就Ok，是不是很方便。

- 首先用超级管理员账户在平台上填写邮箱相关信息



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




### 关于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密码来登陆`





#### 关于menu菜单组件

> 注意： 菜单组件都是我们内置好的，基于角色关联赋权的时候用到，详细请参考图

  




### 关于Role角色管理

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










### 关于CMDB资产管理授权

> 资产管理是支持针对Tag标签对普通用户授权 展示不同的资产

- 选择一个新建/已存在的标签，选择授权用户  

  



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





#### 关于Tag标签树授权

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



- 授权操作

  



### 关于Task任务模板授权

> 我们的任务模板都是有权限之分的，当管理创建好了一个任务模板需要相关用户进行授权，否则其余用户是不能对模板操作/显示此模板的任务的

- 模板授权很简单，选择你创建好的模板，授权相关用户即可 


  



### 关于Config配置中心授权

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

- 对整个项目进行授权，可以管理此项目

  

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

---

### Zh Guide More Qgroup README (`docs/zh/guide/more/qgroup/README.md`)

# 加入交流群

::: tip
感兴趣的同学可以加入我们的QQ和微信交流群,代码我们也会不断进行更新，感谢大家的支持。
:::

- 一键加入QQ群：<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=69f5e118727c7ea925cc8d2f0eef0d729898cb8a24eae47e2b3ca3dd048de9d9"><img border="0" src="/join_qq_group.png" alt="CoDo  CloudOpenDevOps" title="OpenDevOps用户交流群"></a>

- 扫描二维码进QQ群



- 扫描二维码进微信群

---

### Zh Guide More Update README (`docs/zh/guide/more/update/README.md`)

# 如何更新

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

```sh
# 进入部署目录，例如：
cd  ./codo-deploy-docs/docker-deploy
docker-compose  -f docker-compose-app.yaml pull
```

### 重新生成token

```sh
TOKEN=$(docker exec codo_mg python3 manage.py token_init | tr -d '\n' | tr -d '\r')
sed -i "s/^CODO_AUTH_KEY\s*=.*/CODO_AUTH_KEY=\"$TOKEN\"/" .env

sed -i.bak "s/^CODO_AUTH_KEY=.*/CODO_AUTH_KEY=\"$TOKEN\"/" .env # 如果是mac
```

## 重新加载镜像

```sh
docker compose -f docker-compose-app.yaml up -d
```

## 数据库表结构变更

- 假如后端修改了表结构我怎么更新呢？

> 如果后端修改了表结构，我们的更新文档都会说明哪些需要`ALTER TABLE`,比如CMDB资产配置新增了华为云的支持，

- 问题1：我不想重新初始化，里面有数据，想直接改表结构  

```mysql  

#进到你的数据库，每个模块都是对应一个版本库的

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 ;  

```

- 问题2：我不想改表结构怎么办？  

> 如果你是新部署的用户/没数据的用户，你完全可以给这个库/表删除了执行初始化操作  

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

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

---

### Zh Ad README Copy (`docs/zh/ad/README copy.md`)

::: tip
招募CoDo的资深使用者作为导师
:::

**条件**
 - 熟练部署和在生产中使用codo
 - 帮助一位新用户成功部署，教会简单使用，直到用户满意即可

**导师福利**

- 导师无需付费即可进入VIP群，享有VIP用户的所有权利
- 优先体验最新版本
- 优先参与CoDo开发规划，且优先接受开发建议
- 优先参与维护组以及开发者，
- 优先参与技术分享
- 优先指导定制开发中遇到的问题
- 如能成为导师一对一指导新用户直到用户满意，则可全额获得用户入群费用
- 更多群福利进群后看公告

::: tip
有意者请联系管理人员
:::

::: warning
有意者请联系管理人员
:::

::: danger
有意者请联系管理人员
:::

---

### Zh Guide V2 2 Install Docker (`docs/zh/guide-v2/2-install/docker.md`)

# Docker Compose 部署

## 部署方式
- 开发环境使用docker-compose方式, 完成管理后台、网关服务、前端项目、任务平台、配置中心、Agent-server的部署.
- 部署时先部署中间件, 中间件正常运行后部署应用.

## 快速部署

推荐使用 root 用户进行部署

### 1. 准备 docker 环境

安装 Docker 和 Docker-compose

- Docker 安装命令参考 **[Rocky Linux 9 操作系统]**

```shell
sudo dnf install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
```

- docker-compose 安装命令参考 **[Rocky Linux 9 操作系统]**

  ```shell
  sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  sudo chmod +x /usr/local/bin/docker-compose
  ```

### 2. 克隆仓库

```shell
git clone https://github.com/opendevops-cn/codo-deploy-docs.git
cd ./codo-deploy-docs/docker-deploy
```

### 3. 修改配置 [可跳过]

[.env](.env)   中已经配置项目中所需的账密信息，不修改则使用默认配置

### 4. 数据库初始化 [可跳过]

[db_init.sql](db_init.sql) 在 Docker 部署 MySQL 时默认导入。

### 5. 部署中间件

如需依赖已有中间件则需要修改 [.env](.env) 配置

```shell
sh ./deploy_middleware.sh
```

### 6. 启动服务并初始化

```shell
sh ./init_app.sh
```

### 7. 管理后台创建超级用户

默认: **admin**

密码: **1qazXSW@**

```shell
docker exec -it codo_mg python3 manage.py createsuperuser
```

---

### Zh Guide V2 2 Install K8s (`docs/zh/guide-v2/2-install/k8s.md`)

# Kubernetes Helm 部署

**一键安装CODO**
```shell
bash ./quick_start/all_in_one.sh


# [optional]
# 业务参数文件
export local_biz_values_file=./data/biz.values.yaml
# 业务镜像文件
export local_biz_images_file=./data/biz.images.yaml
# 中间件参数文件
export local_mid_value_file=./data/mid.values.yaml
# 部署 cloud-agent-operator (默认不部署)
export local_deploy_crd=true
```
**使用**
```shell
kubectl -n codo-test port-forward services/codo-biz-frontend 8888:80
```
**进入控制台**
- 账号: admin
- 密码: 1qazXSW@

---

### Zh Guide V2 3 Admin Biz Auth (`docs/zh/guide-v2/3-admin/biz-auth.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 3.1 配置用户的业务权限

## 1. 在业务中配置角色

配置角色之后, 关联的用户即可在业务列表看到对应的业务





## 2. 在天门网关, 给相关接口配置业务鉴权插件

---

### Zh Guide V2 3 Admin Role Auth (`docs/zh/guide-v2/3-admin/role-auth.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 3.2 配置角色权限

## 权限流



## 配置基础角色(权限包)

### 进入权限配置菜单



### 配置对应的菜单+接口权限







## 配置通用角色(业务角色)

### 切换通用角色页



### 关联用户和权限包



## [可选] 点击刷新缓存

将权限信息立刻刷入ETCD中, 这一步有异步任务定时同步, 所以可选

---

### Zh Guide V2 4 Cmdb Biz Tree (`docs/zh/guide-v2/4-cmdb/biz-tree.md`)

# 手把手教你玩转 一站式运维平台(CODO) - CMDB 4.2 服务树

## 服务树概念

服务树主要用于管理物理资源, 将业务与物理资源进行关联



- 业务: 通常是一个职能组织
- 环境: 生产、测试
- 集群: 运行的实际应用
- 模块: 应用的模块

---

### Zh Guide V2 4 Cmdb Cloud Asset (`docs/zh/guide-v2/4-cmdb/cloud-asset.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 4.1 使用CMDB管理数据资源



## 云账号导入

---

### Zh Guide V2 5 Codo Flow Codo Agent (`docs/zh/guide-v2/5-codo-flow/codo-agent.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 5.1 安装 codo-agent

# codo-agent入门到精通

## 简单使用

### codo-agent



#### 启动 agnet

```shell
curl -L -o ./codo-agent https://github.com/opendevops-cn/codo-agent-server/releases/download/v1.8.6/codo-agent-linux-amd64
chmod +x ./codo-agent
./codo-agent --config-file ./config.yaml
```

#### 配置详情

以下是简单配置:

```yaml
# 日志等级(必填, 默认 info)
# - DEBUG
# - INFO
# - WARN
# - ERROR
LOG-LEVEL: info
# 业务ID(必填, 默认 502)
BIZ-ID: "504"
# 连接服务地址(必填, agent-server 的地址, clientId 需要全局唯一)
# SERVER-ADDRESS: "ws://127.0.0.1:8002/api/v1/codo/agent?clientId=huaweibook1"
# 也可以是 AGENT-PROXY 的地址
# SERVER-ADDRESS: "ws://127.0.0.1:9999/api/v1/codo/agent?clientId=huaweibook1"
# 也可以填 demo 的地址
SERVER-ADDRESS: "ws://demo.opendevops.cn/api/agent-ws/v1/codo/agent?clientId=cctest"
```

以下是全量配置:

```yaml
# 日志等级(必填, 建议 info)
# - DEBUG
# - INFO
# - WARN
# - ERROR
LOG-LEVEL: info
# RootPath 日志保存路径(选填, 默认是 工作目录)
# 用于：
# - 存储脚本文件
# - 存储密钥文件
# - 存储执行日志文件
# - 存储agent日志文件
ROOT-PATH: "./data/agent"
# 连接服务地址(必填, agent-server/proxy 的地址, clientId 需要全局唯一)
SERVER-ADDRESS: "ws://127.0.0.1:9999/api/v1/codo/agent?clientId=huaweibook1"
# 节点类型(选填)
# - normal(默认值)
# - master(当节点为master时，自动开启AGENT代理模式, 用于将多个 AGENT 的连接归并起来一起转发到 AGENT-SERVER)(生产环境推荐使用)
NODE-TYPE: "normal"
# 业务ID(必填, 默认 502)
BIZ-ID: "525"
# 本地绑定ip（master模式），本地上报ip地址(选填, 默认取第一张非loppback网卡的ip)
BIND-IP: ""
# 本地绑定端口（master模式下有效）(选填, 默认 20800)
BIND-PORT: 20800
# 日志行数限制(选填, 默认 800)
ROW-LIMIT: 2000
# 最大执行命令数(选填, 默认 100)
MAX-EXEC-CMD: 100
# 以脚本路径作为工作目录(选填, 默认 false)
SCRIPT-PATH-AS-WD: false
# 强指脚本的工作目录(选填, 默认 工作目录)
WORK-DIR: "./data/wd"
# 日志清理间隔(单位：天)(选填, 默认 30)
LOG-CLEAN-INTERVAL: 30
# 实验性参数：WINDOWS 强杀子进程进程树(选填, 默认 false)
EXPR-FORCE-KILL-SUB-PROC: false
```

#### 修改 AGENT ID
agent-id 新版本自动生成, 一旦生成, 一般来说禁止修改.
如果有必须要修改的需求, 可以在 codo-agent 的工作目录下修改
```shell 
echo -n "cctest1" > ./codo_status/.agent_id
```



#### AGENT 绑定业务

agent 连接上之后会默认进入到 CMDB 的 Agent 列表页面.

点击 **生成主机** 用来在业务树上 绑定 agent 机器





> 注意:
>
> 只有集群和模块可以绑定资源, 需要右键业务树节点多创建几层子节点







### codo-agent-server

#### 数据库 migrate

```
./codo-agent-server migrate --config-file ./config.yaml
```

#### 启动 agent-server

```
./codo-agent-server --config-file ./config.yaml
```

#### 配置详情

```yaml
# HTTP 服务端口(用于接收codo-flow的请求)
PORT: 9996
# GRPC 通信端口(暂时没用, 用于服务注册)
RPC-PORT: 9997
# websocket 连接专用端口(用于codo-agent建立 ws 连接)
WS-PORT: 9999
# 性能采集端口(用于提供 metrics )
PPROF-PORT: 9995
# 本机服务监听地址(监听地址, 建议 0.0.0.0)
BIND-ADDRESS: 0.0.0.0


# 日志存放地址(存放 agent-server 打印的运行日志)
ROOT-PATH: E:\go\src\agent-server
# 日志等级(默认 DEBUG)
# - DEBUG
# - INFO
# - WARN
# - ERROR
LOG-LEVEL: DEBUG


# RabbitMQ 配置 (用于将 agent 的日志上报到 codo-flow)
MQCONFIG:
  ENABLED: true
  SCHEMA: "amqp"
  HOST: "127.0.0.1"
  PORT: 5672
  USERNAME: "admin"
  PASSWORD: "123456"
  VHOST: "codo"


# MYSQL 配置, 用于存储 agent-server 的数据
DB-CONFIG:
  DB-TYPE: mysql
  DB-USER: root
  DB-PASSWORD: 123456
  DB-HOST: 127.0.0.1
  DB-NAME: codo_agent_server
  DB-TABLE-PREFIX: codo_
  DB-FILE: ""
  DB-PORT: 3306


# REDIS 配置
# 用于:
#  存储 codo-agent 的心跳
REDIS:
  R-HOST: 127.0.0.1
  R-PORT: 6379
  R-PASSWORD: ""
  R-DB: 1
# REDIS 发布订阅配置
# 用于:
#  CDMB 任务同步
#  CODO 任务分发
PUBLISH:
  P-HOST: 127.0.0.1
  P-PORT: 6379
  P-PASSWORD: ""
  P-DB: 1
  P-ENABLED: true
```

#### 接口

##### 下发任务(异步)

```bash
curl -X POST 127.0.0.1:9996/api/v1/agent/task/batch \
  -H 'Content-Type: application/json' \
  -d '[
    {
      "taskId": "task123",
      "taskType": "ExecCmd",
      "agentId": "agent456",
      "args": {
        "cmd": "sh ${script_path}",
        "timeout": 300,
        "scriptInfo": "#!/bin/bash\n echo helloworld",
				"scriptParams": "{\"a\":1}"
      }
    },
    {
      "taskId": "task124",
      "taskType": "RevokeTask",
      "agentId": "agent789",
      "args": {"taskId": "11asd"}
    }
  ]'
  
不同的 task-type 对应的 args 参数不同
====================================================
GetRunningTask: 获取正在执行的任务
{}

RevokeTask: 取消任务
{"taskId": "11asd"}

ExecCmd: 执行任务
{
"cmd": "sh ${script_path}", // 执行的命令(必填), ${script_path} 是一个魔术变量, 当 scriptInfo 有内容时, 会替换成 scriptInfo 存储的路径
"timeout": 300, // 任务超时时间
“scriptInfo”: “#!/bin/bash\n echo helloworld”, // 脚本模式下, 脚本的内容(选填)
"scriptParams": "{\"a\":1}" // 额外注入的环境变量信息(选填)
}

```



##### 下发任务(同步)

```bash
# 获取正在执行的任务

curl -X POST http://127.0.0.1:9996/api/v1/codo/call \
-H 'Content-Type: application/json' \
-d '{"TaskID": "xxx", "AgentID": "huaweibook1:6666", "TaskType": "GetRunningTask"}'


# 下发任务
curl -X POST http://127.0.0.1:9996/api/v1/codo/call \
-H 'Content-Type: application/json' \
-d '{"TaskID": "abc---huaweibook1:6666", "AgentID": "huaweibook1:6666", "TaskType": "ExecCmd", "args":{"cmd":"echo helloworld","scriptParams":"{}"}}'
```



##### 如果  TaskType 是 ExecCmd, 可以获取实时日志

```bash
# 获取任务 abc---huaweibook1:6666 的日志
curl "http://127.0.0.1:9996/api/v1/manager/agent/task/logv2?task_id=abc---huaweibook1:6666"
```



##### 获取在线的 agent 列表

```
curl 127.0.0.1:9996/api/v1/agent/info
```



## 网络拓扑

在不同网络分区建立 PROXY 节点，收敛网络流量，由 PROXY 节点统一向外部中心调度服务进行流量传输。


## 任务调度

> 之所以推送任务到 redis , 是 因为 agent-server 本身多副本, 对应需要执行任务的 agent 的 ws连接 不一定在 接受到任务下发的 agent-server 上



### 在 ExecCmd 时的调度

---

### Zh Guide V2 5 Codo Flow Example Cicd (`docs/zh/guide-v2/5-codo-flow/example-cicd.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 5.2 使用 codo-flow 实现 应用自动化CI/CD

## [持续集成] 配置打包机组

### 新建打包机组



### 添加打包机







## [持续集成] 配置凭证信息用于拉取代码仓库

- 长文本在脚本中变量指向一个文件路径(文件内容为 实际数据)
- 短文本在脚本中变量直接指向 实际数据

**凭证key 在 脚本中使用 `$CODO_{keyname}` 读取**



## [持续集成] 编写构建脚本



## [持续集成] 配置CI流程

### 选择打包机



### 选择脚本类型节点, 用于执行脚本任务





### 选择全局节点



### 选择构建脚本



### 配置自定义参数表单

这里的 branch 在 脚本中使用 `codo_branch` 读取



### 配置仓库触发





### 点击发布





## [持续部署] 配置云原生任务进行部署作业

因为是云原生部署, 并不需要很重的执行环境, 所以我们选择云原生任务来执行部署作业





## [持续部署] 配置CD流程

### 添加云原生任务节点



### 选择执行任务的集群 和 任务



### 配置执行参数



### 发布&触发

---

### Zh Guide V2 5 Codo Flow Example Distribute Deploy (`docs/zh/guide-v2/5-codo-flow/example-distribute-deploy.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 5.3 使用 codo-flow + cmdb 实现 跨地区应用部署



## CMDB 配置动态分组





### 通用类型

可以匹配所有业务下的资源, 但是只有运维组可以引用



### 业务类型

直接拉取服务树下的资源





### 预览动态分组下的机器







## 流程配置使用动态分组









## 配置发布脚本 & 使用全局节点





## 配置参数



## 点击执行

---

### Zh Guide V2 5 Codo Flow Example Flow Audit (`docs/zh/guide-v2/5-codo-flow/example-flow-audit.md`)

# 手把手教你玩转 一站式运维平台(CODO) - 5.4 codo-flow 配置流程审批

## 通知中心配置

1. ### 配置消息模板

如何获取消息

流程系统会把所有消息回调给消息中心

```Plain
codo_callback_args 系统间回调信息，不用管
codo_flow_creator  订单发起者
title： 订单名称
codo_noticer：通知人
flow_bpm_name：当前审批节点的名称
其他变量都可以直接在通知模板中取用
```



1. ### 配置通知通道





配置回调地址

```Plain
# 同意
https://{补上网关地址}/api/f2-acc/public/v1/flow/approval/agree/
# 拒绝
https://{补上网关地址}/api/f2-acc/public/v1/flow/approval/reject/
```

1. ### 编辑通知路由

> 固定用法 创建 flow_approval=yes   user_task=type1 的路由条件



## 流程配置

1. ### 创建流程



1. ### 使用用户类型的任务



1. ### 发布流程



1. ### 点击触发即可

---

### Zh Guide Plugin Bind (`docs/zh/guide/plugin/Bind.md`)

# DNS Bind

>opendevops平台所用组件[域名管理](https://github.com/opendevops-cn/codo-dns)Bind部署文档， 部分文档会因为版本迭代不可用，此文档只作为参考文档，谢谢。

**安装配置**
```bash
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为我们提供了配置文件模板，我们可以直接拷贝过来：
```bash
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参数
```bash
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文件 如下
```bash
# 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方式启动。命令如下：
```bash
/usr/libexec/setup-named-chroot.sh /var/named/chroot on
systemctl stop named
systemctl disable named
systemctl start named-chroot
systemctl enable named-chroot
```
- 检查语法
```bash
named-checkzone ss.com /var/named/ss.com.zone
zone ss.com/IN: loaded serial 20190426
OK
named-checkconf
```
- 查看是否启动，命令：
```bash
ps -ef|grep named
```
- 测试DNS服务，命令如下：
```bash
### 编辑dns解析文件 并写入你的DNS服务器地址
vim /etc/resolv.conf 
nameserver 172.16.0.111
dig ftp.ss.com
```

**参考文档**

[参考文档1](https://blog.csdn.net/bbwangj/article/details/82079405)

[参考文档2](https://blog.51cto.com/liqingbiao/2093064)

[参考文档3](https://blog.csdn.net/bpingchang/article/details/38377053)

---

### Zh Guide Plugin Inception (`docs/zh/guide/plugin/Inception.md`)

# Inception

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

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

> docker pull ss1917/inception:latest

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

```bash
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配置文件参数简要说明**

```
/* Detailed source-code truncated for AI context efficiency. */
```
**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**

```bash
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 '测试';\

```bash
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自动生成的回滚语句

---

### Zh Guide Plugin SQLAdvisor (`docs/zh/guide/plugin/SQLAdvisor.md`)

# SQLAdvisor

[[toc]]

::: tip
插件部署提供参考
:::

###  SQLAdvisor部署文档

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


**简介**

>SQLAdvisor是一个分析SQL给出索引优化建议的工具。它基于MySQL原生态词法解析，结合分析SQL中的where条件、聚合条件、多表Join关系 给出索引优化建议。  主要功能：输出SQL索引优化建议,[更多介绍](https://github.com/Meituan-Dianping/SQLAdvisor/blob/master/doc/THEORY_PRACTICES.md)


**安装使用**

```bash
#编译依赖项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。

---

### Zh Guide Plugin Bak Old (`docs/zh/guide/plugin/bak_old.md`)

# 插件文档

[[toc]]

::: tip
插件部署提供参考
:::

###  SQLAdvisor部署文档

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


**简介**

>SQLAdvisor是一个分析SQL给出索引优化建议的工具。它基于MySQL原生态词法解析，结合分析SQL中的where条件、聚合条件、多表Join关系 给出索引优化建议。  主要功能：输出SQL索引优化建议,[更多介绍](https://github.com/Meituan-Dianping/SQLAdvisor/blob/master/doc/THEORY_PRACTICES.md)


**安装使用**

```bash
#编译依赖项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部署文档， 部分文档会因为版本迭代不可用，此文档只作为参考文档，谢谢。

[官网](https://www.sonarqube.org/)


**简介**

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

**基础的架构**
- Database
- SonarQube Server
- SonarQube Scanner
- Project
- Nginx （如果不需要通过nginx转发则不需要Nginx模块）

**SonarQube服务端** 


直接拉取仓库中的docker镜像启动服务, docker、docker-compose安装参考[初始化脚本](https://github.com/opendevops-cn/opendevops/tree/master/scripts)

```bash
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



SonarQube配置安装插件，汉化。




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



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



**主要配置项：**

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

**smtp安全协议**
- SMTP host
- SMTP password
- SMTP port

配置完成后测试发送



**配置邮件提醒**

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




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


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


**此处我们使用sonar-scanner**

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

```shell
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
```


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


**简介**

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

**功能特点**

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


**下载二进制安装包**
```bash
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的下载目录执行
```bash
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:**  当表结构变更时，使用\*通配符选择所有列将导致查询的含义和行为会发生更改，可能导致查询返回更多的数据。

```



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

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

> docker pull ss1917/inception:latest

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

```bash
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配置文件参数简要说明**

```
/* Detailed source-code truncated for AI context efficiency. */
```
**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**

```bash
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 '测试';\

```bash
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自动生成的回滚语句



### DNS Bind部署文档

>opendevops平台所用组件[域名管理](https://github.com/opendevops-cn/codo-dns)Bind部署文档， 部分文档会因为版本迭代不可用，此文档只作为参考文档，谢谢。

**安装配置**
```bash
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为我们提供了配置文件模板，我们可以直接拷贝过来：
```bash
# 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参数
```bash
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文件 如下
```bash
# 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方式启动。命令如下：
```bash
/usr/libexec/setup-named-chroot.sh /var/named/chroot on
systemctl stop named
systemctl disable named
systemctl start named-chroot
systemctl enable named-chroot
```
- 检查语法
```bash
# named-checkzone ss.com /var/named/ss.com.zone
zone ss.com/IN: loaded serial 20190426
OK
# named-checkconf
```
- 查看是否启动，命令：
```bash
ps -ef|grep named
```
- 测试DNS服务，命令如下：
```bash
### 编辑dns解析文件 并写入你的DNS服务器地址
vim /etc/resolv.conf 
nameserver 172.16.0.111
dig ftp.ss.com
```

**参考文档**

[参考文档1](https://blog.csdn.net/bbwangj/article/details/82079405)

[参考文档2](https://blog.51cto.com/liqingbiao/2093064)

[参考文档3](https://blog.csdn.net/bpingchang/article/details/38377053)

---

### Zh Guide Plugin SonarQube (`docs/zh/guide/plugin/sonarQube.md`)

# sonarQube

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

[官网](https://www.sonarqube.org/)


**简介**

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

**基础的架构**
- Database
- SonarQube Server
- SonarQube Scanner
- Project
- Nginx （如果不需要通过nginx转发则不需要Nginx模块）

**SonarQube服务端** 


直接拉取仓库中的docker镜像启动服务, docker、docker-compose安装参考[初始化脚本](https://github.com/opendevops-cn/opendevops/tree/master/scripts)

```bash
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



SonarQube配置安装插件，汉化。




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



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



**主要配置项：**

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

**smtp安全协议**
- SMTP host
- SMTP password
- SMTP port

配置完成后测试发送



**配置邮件提醒**

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




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


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


**此处我们使用sonar-scanner**

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

```bash
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
```

---

### Zh Guide Plugin Middleware Etcd Cluster (`docs/zh/guide/plugin/middleware/etcd/cluster.md`)

# 集群部署

- `作者：青牛踏雪御苍穹（CoDo老王)`
- 部署 ETCD 集群（自签证书）

### 准备工作

操作系统：Ubuntu 18.04.3 LTS （本地环境） 集群部署（自签证书）

自行打通服务器之间的SSH免密，或者自己输入密码来完成复制操作。

###  配置环境变量

```bash
ETCD_DIR='${ETCD_DIR}'
mkddir ${ETCD_DIR}
cat > ${ETCD_DIR}/environment.sh <<EOF
#!/usr/bin/bash
# etcd 版本
export ETCD_VERSION='3.4.14'

# 集群节点
export ETCD0='192.168.1.220'
export ETCD1='192.168.1.221'
export ETCD2='192.168.1.222'

# ETCD集群各机器 IP 数组
export NODE_IPS=(${ETCD0} ${ETCD1} ${ETCD2})

# 集群各 IP 对应的主机名数组
export NODE_NAMES=(etcd-0 etcd-1 etcd-2)

# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://${ETCD0}:2379,https://${ETCD1}:2379,https://${ETCD2}:2379"

# etcd 集群间通信的 IP 和端口
export ETCD_NODES="etcd-0=https://${ETCD0}:2380,etcd-1=https://${ETCD1}:2380,etcd-2=https://${ETCD2}:2380"

# etcd 目录
export ETCD_DIR="/data/etcd"

# etcd 数据目录
export ETCD_DATA_DIR="/data/etcd/data"

# etcd WAL 目录，建议是 SSD 磁盘分区，或者和 ETCD_DATA_DIR 不同的磁盘分区
export ETCD_WAL_DIR="/data/etcd/wal"

# etcd 自签证书存放目录
export ETCD_CA_DIR='/data/etcd/ca'

# etcd 各个节点证书存放目录
export ETCD_ETC_DIR='/etc/etcd/cert'
EOF
chmod +x environment.sh
# 创建存放数据、证书、WAl目录
mkdir ${ETCD_DATA_DIR} ${ETCD_CA_DIR} ${ETCD_WAL_DIR}
```

配置本地hosts

```bash
# 配置本地host
source ${ETCD_DIR}/environment.sh
cat >> /etc/hosts <<EOF
${ETCD0} etcd-1
${ETCD1} etcd-2
${ETCD2} etcd-3
EOF
```

### 下载和分发 etcd 二进制文件

[release](https://github.com/coreos/etcd/releases) 查找自己需要的版本。

```bash
source ${ETCD_DIR}/environment.sh
cd ${ETCD_DIR}
wget https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
tar xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
```

### 分发二进制文件到各个主机

```bash
cd ${ETCD_DIR}
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp -r /data/etcd/etcd-v${ETCD_VERSION}-linux-amd64/etcd* root@${node_ip}:/usr/local/bin/
    ssh root@${node_ip} "chmod +x /usr/local/bin/etcd*"
done
# 输出结果
>>> 192.168.1.220
etcd                                                                                                  100%   23MB  51.1MB/s   00:00
etcdctl                                                                                               100%   17MB  44.5MB/s   00:00
>>> 192.168.1.221
etcd                                                                                                  100%   23MB  39.1MB/s   00:00
etcdctl                                                                                               100%   17MB  34.4MB/s   00:00
>>> 192.168.1.222
etcd                                                                                                  100%   23MB  52.0MB/s   00:00
etcdctl                                                                                               100%   17MB  45.8MB/s   00:00  
```

### 安装 cfssl 工具集

```bash
# 安装cfssl
cd ${ETCD_DIR}
wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl_1.4.1_linux_amd64
mv cfssl_1.4.1_linux_amd64 /usr/local/bin/cfssl

# cfssljson
wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssljson_1.4.1_linux_amd64
mv cfssljson_1.4.1_linux_amd64 /usr/local/bin/cfssljson

# cfssl-certinfo
wget https://github.com/cloudflare/cfssl/releases/download/v1.4.1/cfssl-certinfo_1.4.1_linux_amd64
mv cfssl-certinfo_1.4.1_linux_amd64 /usr/local/bin/cfssl-certinfo

# 添加执行权限
chmod +x /usr/local/bin/cfssl*
```

### 创建证书

CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage，过期时间、服务端认证、客户端认证、加密等)：


```bash
cd ${ETCD_CA_DIR} 
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "etcd-cluster": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "876000h"
      }
    }
  }
}
EOF
```

创建证书签名请求文件

```bash
cat > ca-csr.json <<EOF
{
  "CN": "kubernetes-ca",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "etcd",
      "OU": "opsnull"
    }
  ],
  "ca": {
    "expiry": "876000h"
 }
}
EOF
```

- `signing`：表示该证书可用于签名其它证书（生成的 `ca.pem` 证书中 `CA=TRUE`）；
- `server auth`：表示 client 可以用该该证书对 server 提供的证书进行验证；
- `client auth`：表示 server 可以用该该证书对 client 提供的证书进行验证；
- `"expiry": "876000h"`：证书有效期设置为 100 年；

### 创建证书签名请求文件

```bash
cat > ca-csr.json <<EOF
{
  "CN": "kubernetes-ca",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "etcd",
      "OU": "opsnull"
    }
  ],
  "ca": {
    "expiry": "876000h"
 }
}
EOF
```

- `CN：Common Name`：etcd 从证书中提取该字段作为请求的**用户名 (User Name)**，浏览器使用该字段验证网站是否合法；
- `O：Organization`：etcd 从证书中提取该字段作为请求用户所属的**组 (Group)**； kube-apiserver 将提取的 `User、Group` 作为 `RBAC` 授权的用户标识；

### 生成证书文件和私钥

```bash
cd ${ETCD_CA_DIR} 
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
输出结果：
2020/12/17 09:54:25 [INFO] generating a new CA key and certificate from CSR
2020/12/17 09:54:25 [INFO] generate received request
2020/12/17 09:54:25 [INFO] received CSR
2020/12/17 09:54:25 [INFO] generating key: rsa-2048
2020/12/17 09:54:26 [INFO] encoded CSR
2020/12/17 09:54:26 [INFO] signed certificate with serial number 437386317969465523284385845194090172491501571515
$ ls ca*
# 输出结果：
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem
```

### 分发证书文件

```bash
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p ${ETCD_ETC_DIR}"
    scp ca*.pem ca-config.json root@${node_ip}:${ETCD_ETC_DIR}
done
# 输出结果：
>>> 192.168.1.220
ca-key.pem                                                                                            100% 1679     1.2MB/s   00:00
ca.pem                                                                                                100% 1326     1.2MB/s   00:00
ca-config.json                                                                                        100%  293   221.9KB/s   00:00
>>> 192.168.1.221
ca-key.pem                                                                                            100% 1679     1.1MB/s   00:00
ca.pem                                                                                                100% 1326     1.2MB/s   00:00
ca-config.json                                                                                        100%  293   180.2KB/s   00:00
>>> 192.168.1.222
ca-key.pem                                                                                            100% 1679   973.5KB/s   00:00
ca.pem                                                                                                100% 1326   972.0KB/s   00:00
ca-config.json  
```

注意：

1. 不同证书 csr 文件的 CN、C、ST、L、O、OU 组合必须不同，否则可能出现 PEER'S CERTIFICATE HAS AN INVALID SIGNATURE 错误；
2. 后续创建证书的 csr 文件时，CN 都不相同（C、ST、L、O、OU 相同），以达到区分的目的；

etcd-csr证书签名

- `hosts`：指定授权使用该证书的 etcd 节点 IP 列表，**需要将 etcd 集群所有节点 IP 都列在其中**

```bash
cd ${ETCD_CA_DIR} 
cat > /data/etcd/ca/etcd-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "${ETCD0}",
    "${ETCD1}",
    "${ETCD2}"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "etcd",
      "OU": "opsnull"
    }
  ]
}
EOF
```

生成证书和私钥：

```bash
cfssl gencert -ca=${ETCD_CA_DIR}/ca.pem \
    -ca-key=${ETCD_CA_DIR}/ca-key.pem \
    -config=${ETCD_CA_DIR}/ca-config.json \
    -profile=etcd-cluster ${ETCD_CA_DIR}/etcd-csr.json | cfssljson -bare etcd
# 输出结果：
2020/12/17 10:03:52 [INFO] generate received request
2020/12/17 10:03:52 [INFO] received CSR
2020/12/17 10:03:52 [INFO] generating key: rsa-2048
2020/12/17 10:03:53 [INFO] encoded CSR
2020/12/17 10:03:53 [INFO] signed certificate with serial number 290666497635689555552442344139619956527112356386    
```

### 分发证书

```bash
cd ${ETCD_CA_DIR}
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp etcd*.pem root@${node_ip}:${ETCD_ETC_DIR}
done
# 输出结果
>>> 192.168.1.220
etcd-key.pem                                                                                          100% 1679   279.6KB/s   00:00
etcd.pem                                                                                              100% 1448     1.3MB/s   00:00
>>> 192.168.1.221
etcd-key.pem                                                                                          100% 1679   763.6KB/s   00:00
etcd.pem                                                                                              100% 1448     1.0MB/s   00:00
>>> 192.168.1.222
etcd-key.pem                                                                                          100% 1679     1.0MB/s   00:00
etcd.pem
```

### 创建 etcd 的 systemd unit 模板文件

模板不需要做任何改动，所有需要替换的地方后续都会替换掉：

```bash
cd ${ETCD_DIR}
source ${ETCD_DIR}/environment.sh
cat > etcd.service.template <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=${ETCD_DATA_DIR}
ExecStart=/usr/local/bin/etcd \\
  --data-dir=${ETCD_DATA_DIR} \\
  --wal-dir=${ETCD_WAL_DIR} \\
  --name=##NODE_NAME## \\
  --cert-file=${ETCD_ETC_DIR}/etcd.pem \\
  --key-file=${ETCD_ETC_DIR}/etcd-key.pem \\
  --trusted-ca-file=${ETCD_ETC_DIR}/ca.pem \\
  --peer-cert-file=${ETCD_ETC_DIR}/etcd.pem \\
  --peer-key-file=${ETCD_ETC_DIR}/etcd-key.pem \\
  --peer-trusted-ca-file=${ETCD_ETC_DIR}/ca.pem \\
  --peer-client-cert-auth \\
  --client-cert-auth \\
  --listen-peer-urls=https://##NODE_IP##:2380 \\
  --initial-advertise-peer-urls=https://##NODE_IP##:2380 \\
  --listen-client-urls=https://##NODE_IP##:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://##NODE_IP##:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=${ETCD_NODES} \\
  --initial-cluster-state=new \\
  --auto-compaction-mode=periodic \\
  --auto-compaction-retention=1 \\
  --max-request-bytes=33554432 \\
  --quota-backend-bytes=6442450944 \\
  --heartbeat-interval=250 \\
  --election-timeout=2000
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
```

参数说明：

- `WorkingDirectory`、`--data-dir`：指定工作目录和数据目录为 `${ETCD_DATA_DIR}`，需在启动服务前创建这个目录；
- `--wal-dir`：指定 wal 目录，为了提高性能，一般使用 SSD 或者和 `--data-dir` 不同的磁盘；
- `--name`：指定节点名称，当 `--initial-cluster-state` 值为 new 时，`--name` 的参数值必须位于 `--initial-cluster` 列表中；
- `--cert-file、--key-file`：etcd server 与 client 通信时使用的证书和私钥；
- `--trusted-ca-file`：签名 client 证书的 CA 证书，用于验证 client 证书；
- `--peer-cert-file`、`--peer-key-file`：etcd 与 peer 通信使用的证书和私钥；
- `--peer-trusted-ca-file`：签名 peer 证书的 CA 证书，用于验证 peer 证书；

### 创建和分发 etcd systemd unit 文件

替换模板文件中的变量，为各节点创建 systemd unit 文件：

```bash
# 生成
source ${ETCD_DIR}/environment.sh
for (( i=0; i < 3; i++ ))
  do
    sed -e "s/##NODE_NAME##/${NODE_NAMES[i]}/" -e "s/##NODE_IP##/${NODE_IPS[i]}/" etcd.service.template > etcd-${NODE_IPS[i]}.service 
done
# 验证
ls *.service
# 输出结果：
etcd-192.168.1.220.service  etcd-192.168.1.221.service  etcd-192.168.1.222.service
```

- NODE_NAMES 和 NODE_IPS 为相同长度的 bash 数组，分别为节点名称和对应的 IP；

分发生成的 systemd unit 文件：

```bash
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service
done
```

### 启动服务测试

```bash
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p ${ETCD_DATA_DIR} ${ETCD_WAL_DIR}"
    ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd " &
done
# 输出结果：
>>> 192.168.1.220
[7] 26642
>>> 192.168.1.221
[8] 26729
>>> 192.168.1.222
[9] 26840
```

- 命令首先创建 etcd 数据目录和工作目录
- etcd 进程首次启动时会等待其它节点的 etcd 加入集群，命令 `systemctl start etcd` 会卡住一段时间，为正常现象

### 检查启动结果

```bash
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "systemctl status etcd|grep Active"
done

输出结果：
>>> 192.168.1.220
   Active: active (running) since Thu 2020-12-17 10:15:02 UTC; 31s ago
>>> 192.168.1.221
   Active: active (running) since Thu 2020-12-17 10:15:02 UTC; 36s ago
>>> 192.168.1.222
   Active: active (running) since Thu 2020-12-17 10:15:02 UTC; 40s ago  
```


### 验证ETCD集群服务状态

部署完 etcd 集群后，在任一 `etcd` 节点上执行如下命令，我是etcd-0执行的部署操作。

```bash
source ${ETCD_DIR}/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    /usr/local/bin/etcdctl \
    --endpoints=https://${node_ip}:2379 \
    --cacert=${ETCD_ETC_DIR}/ca.pem \
    --cert=${ETCD_ETC_DIR}/etcd.pem \
    --key=${ETCD_ETC_DIR}/etcd-key.pem endpoint health
done
# 输出结果：
>>> 192.168.1.220
https://192.168.1.220:2379 is healthy: successfully committed proposal: took = 99.689319ms
>>> 192.168.1.221
https://192.168.1.221:2379 is healthy: successfully committed proposal: took = 47.262066ms
>>> 192.168.1.222
https://192.168.1.222:2379 is healthy: successfully committed proposal: took = 49.330772ms
```

ok, etcd集群已经部署完成.

---

### Zh Guide Plugin Middleware Etcd Simple (`docs/zh/guide/plugin/middleware/etcd/simple.md`)

# 单机部署

操作系统：CentOS Linux release 7.7.1908 （阿里云） （单机部署）（无证书）

### 下载 etcd 二进制文件

[release](https://github.com/coreos/etcd/releases) 查找自己需要的版本。

```bash
# 修改你需要的版本
ETCD_VERSION='3.4.14'
# 创建目录
mkdir -p /data/etcd/{data,wal}
# 下载
cd /data/etcd/
wget https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
# 解压
tar xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
# 复制到/usr/local/bin/下，默认已经有可执行权限了，无需在使用chmod +x。
mv etcd-v${VER}-linux-amd64/etcd* /usr/local/bin/
```

### 使用Systemd管理服务

```bash
# 设置变量
NODE_NAME='etcd-single'
NODE_IP='172.25.1.93'
ETCD_DATA_DIR='/data/etcd/data'
ETCD_WAL_DIR='/data/etcd/wal'

# 创建Systemd Unit管理文件
cat >  /etc/systemd/system/etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=${ETCD_DATA_DIR}
ExecStart=/usr/local/bin/etcd \\
  --data-dir=${ETCD_DATA_DIR} \\
  --wal-dir=${ETCD_WAL_DIR} \\
  --name=${NODE_NAME} \\
  --listen-peer-urls=http://${NODE_IP}:2380 \\
  --initial-advertise-peer-urls=http://${NODE_IP}:2380 \\
  --listen-client-urls=http://${NODE_IP}:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=http://${NODE_IP}:2379 \\
  --auto-compaction-mode=periodic \\
  --auto-compaction-retention=1 \\
  --max-request-bytes=33554432 \\
  --quota-backend-bytes=6442450944 \\
  --heartbeat-interval=250 \\
  --election-timeout=2000
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
```

### 启动服务

```bash
systemctl enable etcd
systemctl start etcd
systemctl status etcd
```

### 验证ETCD服务状态

```bash
# 验证IP
etcdctl --endpoints=http://${NODE_IP}:2379 endpoint health
输出结果：
http://172.25.1.93:2379 is healthy: successfully committed proposal: took = 1.632444ms

# 验证本地
etcdctl --endpoints=http://127.0.0.1:2379 endpoint health
输出结果：
127.0.0.1:2379 is healthy: successfully committed proposal: took = 1.716469ms
```

---

--- METRICS ---
- Files Extracted: 39
- Estimated Token Budget: ~27298 tokens
- Canonical Reference: https://codewiki.google/github.com/opendevops-cn/opendevops
