Deploy
Deploy是一个高效的、面向配置的部署工具,可以快速地构建、发布服务到Docker集群中。
功能
- 快速的搭建部署环境
- 多环境隔离部署
- 基于git仓库或标准包的镜像和服务发布
安装
环境依赖
- Git
- Python 2.x -> 传送门
- Ansible 2.7.5 或更新版本 -> 传送门
- Make (Linux、Mac OS自带,Windows用户请移步Windows用户如何使用部署工程)
验证环境是否满足要求
# 查看python是否为2.x版本
python --version
# 查看是否安装git
git --version
# 查看是否安装ansible,同时也会输出当前使用的python版本
ansible --version
# 查看是否安装make
make --version
获取最新的部署工程
git clone --recursive ssh://git@git.ascs.tech/tool/deploy.git deploy
cd deploy
# 目前工具还没走发布流程,新的功能都在develop分支,还没并入master分支
git checkout develop
工程结构介绍
deploy
├── config
├── environment # 存放部署配置的目录,以目录来区分多不同环境
│ ├── wushan # 乌山环境的部署配置
│ │ ├── group_vars # 组变量
│ │ ├── service_conf # 服务配置目录
│ │ ├── ssh # 环境的公私钥,隔离各环境对git仓库的访问
│ │ ├── hosts # 主机列表
│ │ └── images.json # 环境的镜像仓库配置
│ ├── baoan # 宝安环境的部署配置
│ │ ├── ...
│ ├── id_rsa & id_rsa.pub # 通用的deploy公私钥,用于访问通用的仓库
│ └── images.json # 各个环境通用的镜像仓库配置
├── files # 存放离线包
├── filter_plugins # ansible中的过滤器插件
├── inventories # ansible框架使用的配置目录,以目录来区分多不同环境
│ ├── full
│ └── wushan
├── library # ansible的自定义插件
├── roles # ansible角色
│ ├── auth
│ ├── ...
├── scripts
├── tasks
├── Makefile # make指令的集合
├── auth.yml # ansible的剧本
└── xxx.yml # 其他xxx剧本
不同环境的配置可以存放在对应的Bitbucket project里,进行版本控制
原理阐述
流程说明
上图为简易的一个部署架构和流程,包含了两个命令:make images-publish
为触发镜像发布的命令make service
为触发服务发布的命令
部署场景的角色主要分以下几种:
- 部署工具:就是运行deploy工程make命令的主机,一般就是自己的机器
- ansible(build-server):被控制机中会有一台被选为构建服务器,构建服务器主要负责从git仓库中拉取代码进行构建(因此需要给这台机器额外安装jdk、node、go等)、将标准包解压进行构建等工作
- 其他被控制机器:无特殊角色,按照Docker Swarm集群内的角色进行服务,承载容器
make images-publish service_name=monitor-history后发生了什么
images-publish
依赖于service_conf
下的配置和environment下的images.json
的配置
执行命令的具体流程如下:
- 根据service_name在service_conf下寻找服务的配置文件monitor-history.json
- 读取配置文件的image节点的内容”upm/monitor-history:develop”,在images.json中寻找upm节点下的monitor-history节点。
- 找到该节点后,判断是否有source节点,如果有,执行第4步,如果没有,执行第5步
- 判断是git仓库还是dockerhub,如果是dockerhub,则直接docker pull即可,如果是git仓库,就克隆仓库的develop分支做构建工作
- 在ansible主机上的/root/.cityworks/packages/upm节点下寻找monitor-history-develop.tar.gz包,找到后开始构建工作
make service service_name=monitor-history后发生了什么
- 根据service_name在service_conf下寻找服务的配置文件monitor-history.json
- 读取配置文件的内容,组装启动容器的所有参数
- 启动容器
服务配置文件书写规则
均遵守Docker for Python SDK的参数格式
对主要的几种属性说明如下:
属性名称 | 说明 | 备注 |
---|---|---|
args | 对应上面的ARG… | |
env | 标识环境变量 | 此处为针对不同部署环境可以特定设置,达到镜像复用的效果 |
mounts | 数据持久化挂载 | /开头的绝对路径标识bind的模式,纯字母标识数据卷 |
mode | 部署模式 | replicated 副本模式需要设置副本数replicas,global代表全局模式 |
networks | 挂载网络 | 挂载同一个网络的服务,可以通过dns做服务发现 |
endpoint_spec | 标识端口的设置 | |
constraints | 约束条件 | 约束容器只能运行在特定节点上 |
images.json的覆盖规则
- 环境内部的私有
images.json
会覆盖通用的images.json
- 以深度为1的节点为单位进行覆盖,比如两个json文件中都有public节点,环境私有的
images.json
里的pubic节点会覆盖通用的images.json
里的public节点。
服务配置文件中image的书写规则和images.json的映射关系
基于git仓库或标准包进行发布时
[category]/[image-name]:[branch | tag]
基于公网镜像进行发布时
[category]/[image-name]:[tag] 其中category一般为public
image和images.json的映射关系
- category对应images.json中的深度为1的节点
- image-name对应images.json中category节点下的一个子节点
- image-name内会配置source节点,代表镜像在git或docker仓库的位置,如果基于标准包进行部署,则没有source节点
- branch | tag 是针对git仓库或标准包而言的,公网镜像里的tag则就是针对docker image的
使用场景
实际搭建一个Docker Swarm的部署环境
首先在environment目录下,新建一个文件夹代表环境,环境名即为目录名。
# 这里假设环境名为demo
cd environment
mkdir demo
从full中复制一份完整的环境配置文件到demo环境,并进行修改
- 如果使用docker-register的话,需要修改
group_vars/base
中的registry字段 - 如果使用ntp同步时间的话,需要修改
group_vars/ntpd.yml
中的restricts字段 - 在
service_conf
目录下存放服务的配置文件 - 在ssh目录下执行
ssh-keygen -t rsa -C 'demo' -f 'id_rsa' -P ''
,-C后为环境名,此处为demo - 修改
images.json
,加入环境相关服务的仓库配置 - 修改
hosts
文件,配置主机列表 ```shell [ansible] 192.168.56.201 ansible_ssh_user=root
- 如果使用docker-register的话,需要修改
[base:children] docker
[docker] 192.168.56.201 ansible_ssh_user=root hostname=docker-1-manager host_type=leader 192.168.56.202 ansible_ssh_user=root hostname=docker-2-manager host_type=manager 192.168.56.203 ansible_ssh_user=root hostname=docker-3-manager host_type=manager 192.168.56.204 ansible_ssh_user=root hostname=docker-4-worker host_type=worker 192.168.56.205 ansible_ssh_user=root hostname=docker-5-worker host_type=worker [docker:vars] leader_host=192.168.56.201
[ntpd:children] docker [ntpd:vars] server_host=192.168.56.201
3. 开始从零构建环境,后续步骤的命令默认都是在deploy工程的根目录执行
4. 执行`export ENVIRONMENT_NAME=demo`,设置当前的部署环境,其中demo为你配置的环境名
5. 执行`make auth`,根据提示输入被控制机器的密码,免密登录被控制机器,避免每次都需要输入密码
6. 执行`make infra`,修改公用的基础环境配置
7. 执行`make hostname`,根据主机列表中的配置的hostname,修改被控机器的hostname
8. 执行`make base-vm`,为base组安装基础软件,包括docker及一些常用命令,可以在`group_vars/software.yml`中进行配置
9. 执行`make manager-vm`,为ansible组安装构建需要的环境,包括jdk、node、go等,这些包需要提前放置在 files 目录下
10. 执行`make build-server`,初始化ansible组的主机的ssh公司钥
11. 执行`make ntpd`,同步ntpd组内主机的时间,`server_host`向公网同步,其他机器向`server_host`同步
12. 执行`make docker-daemon`,修改docker的register源
13. 执行`make docker-cluster`,按照主机列表中的配置组建docker集群
14. 至此,一个基本的部署环境就已经有了
<a name="d8d13d07"></a>
### 实际部署一个k8s环境
基础host文件如下
[docker] 192.168.100.68 ansible_ssh_user=root hostname=k8s-node-1 host_type=leader keepalived_role=MASTER keepalived_priority=100 192.168.100.69 ansible_ssh_user=root hostname=k8s-node-2 host_type=master keepalived_role=BACKUP keepalived_priority=80 192.168.100.70 ansible_ssh_user=root hostname=k8s-node-3 host_type=master keepalived_role=BACKUP keepalived_priority=80 192.168.100.71 ansible_ssh_user=root hostname=k8s-node-4 host_type=worker [docker:vars] leader_host=192.168.100.68
变量描述:
- leader_host: 会作为集群初始化的节点, 该节点keepalived_priority需要最大, 初始化集群会通过vip请求kube api
- host_type: host_type为master的会作为contro plane 加入集群, 此时配合keepalived_role和keepalived_priority, worker会作为工作节点加入, 其他值会被忽略
<a name="91010747"></a>
#### 变量配置说明
base的文件配置
cluster_mode: k8s #部署模式为k8s集群方式 k8s: pod_network_cidr: 10.244.0.0/16 #pod 的网络划分, 需要和cni的网络池对应 control_plane_endpoint: 192.168.100.72:6443 #pod ha部署的时候的上层入口 clean_taints: false # 是否清理master的污点 mode: ha # 待定,暂时无用 ha_model: keepalived # 暂时只有通过keepalived的方式部署 nodePortRange: 30000-32767 # 开放的端口
addon.yml文件
用于插件的变量配置, 目前支持的插件有`helm`
helm: repo: #用于添加安装插件的时候,默认添加的repo
- name: stable-azure url: http://mirror.azure.cn/kubernetes/charts/
- name: incubator url: http://mirror.azure.cn/kubernetes/charts-incubator/ ```
开始部署
新建虚拟机在可以联网的情况下, 直接执行make k8s-auto-cluster hosts=docker
执行一键安装
如果基础环境已经配置好, 可以使用make k8s-cluster hosts=docker
直接进行集群组建
扩展集群, 目前可以按顺序执行make base-vm hosts=docker
, make keepalived hosts=docker
, make firewalld hosts=docker
进行基础配置
然后根据需要执行make k8s-control-plane-join hosts=docker
来添加控制平面, 或者make k8s-worker-join hosts=docker
来添加worker节点
部署一个符合标准的微服务
基于公网镜像的部署
需求:以demo环境为例,在集群中部署一个postgres数据库
操作:
在
service_conf
下创建pg.json
文件,内容如下{
"image": "public/postgres:9.6.1",
"networks": [
"cw"
],
"mode": {
"replicated": {
"replicas": 1
}
},
"mounts": [
"pg-dev:/var/lib/postgresql/data"
],
"env": {
"POSTGRES_USER" : "ascs",
"POSTGRES_PASSWORD" : "ascs.tech"
},
"endpoint_spec": {
"ports":{
"5432":5432
}
}
}
修改environment目录下的images.json文件,在public节点下添加如下记录,修改后的文件如下所示
{
"public": {
"postgres": {
"sources": "postgres"
}
}
}
在deploy工程的根目录,执行
make images-publish service_name=pg
发布镜像,其中,service_name就是service_conf
下postgres配置文件pg.json
的文件名pg。如果没有部署docker-register的话,最后可能会有一个被忽略的错误,是没有影响的- 在deploy工程的根目录,执行
make service service_name=pg
发布服务,这条命令会基于刚才发布的镜像启动容器
基于git仓库的部署
需求:以demo环境为例,发布upm中的monitor-history服务,git仓库地址为ssh://git@git.ascs.tech/man/monitor-history.git
操作:
在
service_conf
下创建monitor-history.json
文件,内容如下{
"image": "upm/monitor-history:develop",
"env": {
"SWAGGER.HOST": "192.168.2.30:10202",
"SPRING.DATA.MONGODB.HOST": "mongo-dev",
"SPRING.DATA.MONGODB.PORT": "27017",
"SPRING.DATA.MONGODB.DATABASE": "docker_monitor"
},
"mode": {
"replicated": {
"replicas": 1
}
},
"networks": [
"cw"
],
"endpoint_spec": {
"ports": {
"10202": 8080
}
}
}
修改环境内的images.json文件,在upm节点下添加如下记录,修改后的文件如下所示
{
"upm": {
"monitor-history": {
"sources": "ssh://git@git.ascs.tech/man/monitor-history.git"
}
}
}
需要将demo环境中的公钥添加到monitor-history仓库的access_keys,保证可以拉取代码
- 在deploy工程的根目录,执行
make images-publish service_name=monitor-history
发布镜像,其中,service_name就是service_conf
下monitor-history配置文件monitor-history.json
的文件名monitor-history。如果没有部署docker-register的话,最后可能会有一个被忽略的错误,是没有影响的 - 在deploy工程的根目录,执行
make service service_name=monitor-history
发布服务,这条命令会基于刚才发布的镜像启动容器
基于标准包的部署
需求:以demo环境为例,基于标准包发布upm中的monitor-histor服务(以develop分支为例),git仓库地址为ssh://git@git.ascs.tech/man/monitor-history.git
操作:
克隆代码到本地,并进行打包,最终会得到monitor-history-develop.tar.gz
git clone --recursive ssh://git@git.ascs.tech/man/monitor-history.git monitor-history
cd monitor-history && git checkout develop
make package -m OUT_DIR=.
复制monitor-history-develop.tar.gz到ansible组的主机文件系统 ```shell
在root@192.168.56.201上新建文件夹(如果不存在的话)
mkdir -p /root/.cityworks/package/upm
在本地执行,将monitor-history-develop.tar.gz复制到ansible组的主机文件系统
scp monitor-history-develop.tar.gz root@192.168.56.201:/root/.cityworks/package/upm
3. 在`service_conf`下创建`monitor-history.json`文件,内容如下
```json
{
"image": "upm/monitor-history:develop",
"env": {
"SWAGGER.HOST": "192.168.2.30:10202",
"SPRING.DATA.MONGODB.HOST": "mongo-dev",
"SPRING.DATA.MONGODB.PORT": "27017",
"SPRING.DATA.MONGODB.DATABASE": "docker_monitor"
},
"mode": {
"replicated": {
"replicas": 1
}
},
"networks": [
"cw"
],
"endpoint_spec": {
"ports": {
"10202": 8080
}
}
}
修改环境内的images.json文件,在upm节点下添加如下记录,修改后的文件如下所示
{
"upm": {
"monitor-history": {
}
}
}
在deploy工程的根目录,执行
make images-publish service_name=monitor-history
发布镜像,其中,service_name就是service_conf
下monitor-history配置文件monitor-history.json
的文件名monitor-history。如果没有部署docker-register的话,最后可能会有一个被忽略的错误,是没有影响的- 在deploy工程的根目录,执行
make service service_name=monitor-history
发布服务,这条命令会基于刚才发布的镜像启动容器
三种方式的异同
服务的配置文件
均遵守Docker for Python SDK的参数格式
images.json
- 公网镜像:在public节点下添加postgres子节点,source写docker hub中的镜像名称即可,一般在environment下的通用images.json中添加
- git仓库:在upm节点下添加monitor-history子节点,source写git仓库地址即可,一般在环境内的私有images.json中添加
- 标准包:在upm节点下添加monitor-history子节点,节点内留空(留空的情况会在ansible主机的/root/.cityworks/package/upm/寻找对应规则的tar.gz)
跨网络环境进行部署
前提及准备工作
- 已经创建好-R及-L的通道,可以通过
ssh root@localhost -p xxx
的形式连接到跳板机 - 执行
ssh-copy-id root@localhost -p xxx
,使ansible控制机免密登录跳板机 - 跳板机可以连通被控制机
全局生效
在根路径下的ansible.cfg
文件中添加如下参数,替换root@localhost -p xxx
为跳板机的连接信息,所有主机均通过隧道远程部署
[ssh_connection]
ssh_args = -o ProxyCommand="ssh -W %h:%p root@localhost -p xxx"
主机组生效
假设主机组为[tunnel]
,给主机组添加如下参数,替换root@localhost -p xxx
为跳板机的连接信,当前主机组即可通过隧道远程部署
[tunnel:vars]
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p root@localhost -p xxx"'
命令级别生效
ansible
及 ansible-playbook
命令均支持如下参数,执行命令时,添加此参数即可
--ssh-common-args=SSH_COMMON_ARGS specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)
小技巧
覆盖剧本默认的组
默认每个剧本都是指定了对应的组的,但有时我们可能需要对其他组使用这个剧本,因此可以通过传入hosts
来覆盖剧本默认的组,如
make hostname hosts=docker
当前支持覆盖的剧本包括
make指令 | 默认组 |
---|---|
auth | all |
hostname | all |
base-vm | base |
jdk | jdk |
nifi | nifi |
zookeeper-cluster | zookeeper |
firewalld | docker |
keepalived | docker |
storage | storage |
反馈
Bug Report
如果在使用中遇到了问题,请通过邮件的形式进行反馈,我们将尽快处理。
点我反馈缺陷
Feature Request
如果你对deploy工程有什么好的想法或者需求,欢迎通过邮件的形式向我们阐述,我们将对它进行评估,决定是否进行支持。
点我提个需求
FAQ
反馈部分的链接失效
请手动发送邮件到zhaowei@ascs.tech
,并抄送renjie@ascs.tech
及yuetongshu@ascs.tech
,主题写清楚反馈的类型即可。
Windows用户如何使用部署工程
windows下的配合修改,包括准备make等