|
|
@ -3248,124 +3248,383 @@ nohup java -Xloggc:${logging_file_location}gc.log -XX:+PrintGCDetails -jar app.j
|
|
|
|
|
|
|
|
|
|
|
|
## 安装
|
|
|
|
## 安装
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 检查服务器的内核版本,必须是3.10及以上:
|
|
|
|
|
|
|
|
uname -r
|
|
|
|
|
|
|
|
# 安装docker
|
|
|
|
|
|
|
|
yum install docker
|
|
|
|
|
|
|
|
# 输入y确认
|
|
|
|
|
|
|
|
# 启动docker
|
|
|
|
|
|
|
|
systemctl start docker
|
|
|
|
|
|
|
|
# 查看docker的版本:
|
|
|
|
|
|
|
|
[root@izwz9ib5he33fx3jnuis2xz ~]# docker -v
|
|
|
|
|
|
|
|
Docker version 1.13.1, build 94f4240/1.13.1
|
|
|
|
|
|
|
|
# 设置开机启动docker
|
|
|
|
|
|
|
|
systemctl enable docker
|
|
|
|
|
|
|
|
# 停止docker
|
|
|
|
|
|
|
|
systemctl stop docker
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 常用命令
|
|
|
|
## 常用命令
|
|
|
|
|
|
|
|
|
|
|
|
### 镜像命令
|
|
|
|
### 容器信息
|
|
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
```shell
|
|
|
|
# 列出 Docker 本地镜像列表
|
|
|
|
# 查看docker容器版本
|
|
|
|
$ docker images
|
|
|
|
docker version
|
|
|
|
$ docker image ls -a
|
|
|
|
# 查看docker容器信息
|
|
|
|
|
|
|
|
docker info
|
|
|
|
|
|
|
|
# 查看docker容器帮助
|
|
|
|
|
|
|
|
docker --help
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
# 运行 Docker 镜像(守护态方式)
|
|
|
|
|
|
|
|
$ docker run -d {镜像名}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 删除指定 Docker 镜像
|
|
|
|
|
|
|
|
$ docker image rm {镜像名}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 镜像操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
提示:对于镜像的操作可使用镜像名、镜像长ID和短ID。
|
|
|
|
|
|
|
|
|
|
|
|
### 容器命令
|
|
|
|
#### 镜像查看
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 列出本地images
|
|
|
|
|
|
|
|
docker images
|
|
|
|
|
|
|
|
# 含中间映像层
|
|
|
|
|
|
|
|
docker images -a
|
|
|
|
|
|
|
|
# 只显示镜像ID
|
|
|
|
|
|
|
|
docker images -q
|
|
|
|
|
|
|
|
# 含中间映像层
|
|
|
|
|
|
|
|
docker images -qa
|
|
|
|
|
|
|
|
# 显示镜像摘要信息(DIGEST列)
|
|
|
|
|
|
|
|
docker images --digests
|
|
|
|
|
|
|
|
# 显示镜像完整信息
|
|
|
|
|
|
|
|
docker images --no-trunc
|
|
|
|
|
|
|
|
# 显示指定镜像的历史创建;参数:-H 镜像大小和日期,默认为true;--no-trunc 显示完整的提交记录;-q 仅列出提交记录ID
|
|
|
|
|
|
|
|
docker history -H redis
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
# 列出正在运行的容器
|
|
|
|
|
|
|
|
$ docker ps -a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 列出所有容器(包括已停止容器)
|
|
|
|
#### 镜像搜索
|
|
|
|
$ docker ps -l
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 搜索仓库MySQL镜像
|
|
|
|
|
|
|
|
docker search mysql
|
|
|
|
|
|
|
|
# --filter=stars=600:只显示 starts>=600 的镜像
|
|
|
|
|
|
|
|
docker search --filter=stars=600 mysql
|
|
|
|
|
|
|
|
# --no-trunc 显示镜像完整 DESCRIPTION 描述
|
|
|
|
|
|
|
|
docker search --no-trunc mysql
|
|
|
|
|
|
|
|
# --automated :只列出 AUTOMATED=OK 的镜像
|
|
|
|
|
|
|
|
docker search --automated mysql
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
#### 镜像下载
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 下载Redis官方最新镜像,相当于:docker pull redis:latest
|
|
|
|
|
|
|
|
docker pull redis
|
|
|
|
|
|
|
|
# 下载仓库所有Redis镜像
|
|
|
|
|
|
|
|
docker pull -a redis
|
|
|
|
|
|
|
|
# 下载私人仓库镜像
|
|
|
|
|
|
|
|
docker pull bitnami/redis
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker exec -it {容器ID} /bin/bash
|
|
|
|
#### 镜像删除
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 单个镜像删除,相当于:docker rmi redis:latest
|
|
|
|
|
|
|
|
docker rmi redis
|
|
|
|
|
|
|
|
# 强制删除(针对基于镜像有运行的容器进程)
|
|
|
|
|
|
|
|
docker rmi -f redis
|
|
|
|
|
|
|
|
# 多个镜像删除,不同镜像间以空格间隔
|
|
|
|
|
|
|
|
docker rmi -f redis tomcat nginx
|
|
|
|
|
|
|
|
# 删除本地全部镜像
|
|
|
|
|
|
|
|
docker rmi -f $(docker images -q)
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
停止 Docker 容器:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker stop {容器ID}
|
|
|
|
#### 镜像构建
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 编写dockerfile
|
|
|
|
|
|
|
|
cd /docker/dockerfile
|
|
|
|
|
|
|
|
vim mycentos
|
|
|
|
|
|
|
|
# 构建docker镜像
|
|
|
|
|
|
|
|
docker build -f /docker/dockerfile/mycentos -t mycentos:1.1
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
删除指定 Docker 容器:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker rm -f {容器ID}
|
|
|
|
### 容器操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
提示:对于容器的操作可使用CONTAINER ID 或 NAMES。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 容器启动
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 新建并启动容器,参数:-i 以交互模式运行容器;-t 为容器重新分配一个伪输入终端;--name 为容器指定一个名称
|
|
|
|
|
|
|
|
docker run -i -t --name mycentos
|
|
|
|
|
|
|
|
# 后台启动容器,参数:-d 已守护方式启动容器
|
|
|
|
|
|
|
|
docker run -d mycentos
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
删除停止的 Docker 容器:
|
|
|
|
注意:此时使用"docker ps -a"会发现容器已经退出。这是docker的机制:要使Docker容器后台运行,就必须有一个前台进程。解决方案:将你要运行的程序以前台进程的形式运行。
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
```shell
|
|
|
|
$ docker container prune
|
|
|
|
# 启动一个或多个已经被停止的容器
|
|
|
|
|
|
|
|
docker start redis
|
|
|
|
|
|
|
|
# 重启容器
|
|
|
|
|
|
|
|
docker restart redis
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
查看 Docker 容器历史运行日志:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker logs {容器名}
|
|
|
|
#### 容器进程
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# top支持 ps 命令参数,格式:docker top [OPTIONS] CONTAINER [ps OPTIONS]
|
|
|
|
|
|
|
|
# 列出redis容器中运行进程
|
|
|
|
|
|
|
|
docker top redis
|
|
|
|
|
|
|
|
# 查看所有运行容器的进程信息
|
|
|
|
|
|
|
|
for i in `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i; done
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
实时监听 Docker 容器运行日志:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker logs -f {容器名}
|
|
|
|
#### 容器日志
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
$ docker logs [OPTIONS] CONTAINER
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
|
|
|
--details 显示更多的信息
|
|
|
|
|
|
|
|
-f, --follow 跟踪实时日志
|
|
|
|
|
|
|
|
--since string 显示自某个timestamp之后的日志,或相对时间,如42m(即42分钟)
|
|
|
|
|
|
|
|
--tail string 从日志末尾显示多少行日志, 默认是all
|
|
|
|
|
|
|
|
-t, --timestamps 显示时间戳
|
|
|
|
|
|
|
|
--until string 显示自某个timestamp之前的日志,或相对时间,如42m(即42分钟)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 查看redis容器日志,默认参数
|
|
|
|
|
|
|
|
docker logs rabbitmq
|
|
|
|
|
|
|
|
# 查看redis容器日志,参数:-f 跟踪日志输出;-t 显示时间戳;--tail 仅列出最新N条容器日志;
|
|
|
|
|
|
|
|
docker logs -f -t --tail=20 redis
|
|
|
|
|
|
|
|
# 查看容器redis从2019年05月21日后的最新10条日志。
|
|
|
|
|
|
|
|
docker logs --since="2019-05-21" --tail=10 redis
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 查看指定时间后的日志,只显示最后100行
|
|
|
|
|
|
|
|
$ docker logs -f -t --since="2018-02-08" --tail=100 CONTAINER_ID
|
|
|
|
|
|
|
|
# 查看最近30分钟的日志
|
|
|
|
|
|
|
|
$ docker logs --since 30m CONTAINER_ID
|
|
|
|
|
|
|
|
# 查看某时间之后的日志
|
|
|
|
|
|
|
|
$ docker logs -t --since="2018-02-08T13:23:37" CONTAINER_ID
|
|
|
|
|
|
|
|
# 查看某时间段日志
|
|
|
|
|
|
|
|
$ docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37" CONTAINER_ID
|
|
|
|
|
|
|
|
# 查看最后100行,并过滤关键词Exception
|
|
|
|
|
|
|
|
$ docker logs -f --tail=100 CONTAINER_ID | grep "Exception"
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 容器的进入与退出
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 使用run方式在创建时进入
|
|
|
|
|
|
|
|
docker run -it centos /bin/bash
|
|
|
|
|
|
|
|
# 关闭容器并退出
|
|
|
|
|
|
|
|
exit
|
|
|
|
|
|
|
|
# 仅退出容器,不关闭
|
|
|
|
|
|
|
|
快捷键:Ctrl + P + Q
|
|
|
|
|
|
|
|
# 直接进入centos 容器启动命令的终端,不会启动新进程,多个attach连接共享容器屏幕,参数:--sig-proxy=false 确保CTRL-D或CTRL-C不会关闭容器
|
|
|
|
|
|
|
|
docker attach --sig-proxy=false centos
|
|
|
|
|
|
|
|
# 在 centos 容器中打开新的交互模式终端,可以启动新进程,参数:-i 即使没有附加也保持STDIN 打开;-t 分配一个伪终端
|
|
|
|
|
|
|
|
docker exec -i -t centos /bin/bash
|
|
|
|
|
|
|
|
# 以交互模式在容器中执行命令,结果返回到当前终端屏幕
|
|
|
|
|
|
|
|
docker exec -i -t centos ls -l /tmp
|
|
|
|
|
|
|
|
# 以分离模式在容器中执行命令,程序后台运行,结果不会反馈到当前终端
|
|
|
|
|
|
|
|
docker exec -d centos touch cache.txt
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 数据卷命令
|
|
|
|
#### 查看容器
|
|
|
|
|
|
|
|
|
|
|
|
创建 Docker 数据卷:
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 查看正在运行的容器
|
|
|
|
|
|
|
|
docker ps
|
|
|
|
|
|
|
|
# 查看正在运行的容器的ID
|
|
|
|
|
|
|
|
docker ps -q
|
|
|
|
|
|
|
|
# 查看正在运行+历史运行过的容器
|
|
|
|
|
|
|
|
docker ps -a
|
|
|
|
|
|
|
|
# 显示运行容器总文件大小
|
|
|
|
|
|
|
|
docker ps -s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 显示最近创建容器
|
|
|
|
|
|
|
|
docker ps -l
|
|
|
|
|
|
|
|
# 显示最近创建的3个容器
|
|
|
|
|
|
|
|
docker ps -n 3
|
|
|
|
|
|
|
|
# 不截断输出
|
|
|
|
|
|
|
|
docker ps --no-trunc
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# 获取镜像redis的元信息
|
|
|
|
$ docker volume create {数据卷名}
|
|
|
|
docker inspect redis
|
|
|
|
|
|
|
|
# 获取正在运行的容器redis的 IP
|
|
|
|
|
|
|
|
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
列出所有 Docker 数据卷:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker volume ls
|
|
|
|
#### 容器的停止与删除
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
#停止一个运行中的容器
|
|
|
|
|
|
|
|
docker stop redis
|
|
|
|
|
|
|
|
#杀掉一个运行中的容器
|
|
|
|
|
|
|
|
docker kill redis
|
|
|
|
|
|
|
|
#删除一个已停止的容器
|
|
|
|
|
|
|
|
docker rm redis
|
|
|
|
|
|
|
|
#删除一个运行中的容器
|
|
|
|
|
|
|
|
docker rm -f redis
|
|
|
|
|
|
|
|
#删除多个容器
|
|
|
|
|
|
|
|
docker rm -f $(docker ps -a -q)
|
|
|
|
|
|
|
|
docker ps -a -q | xargs docker rm
|
|
|
|
|
|
|
|
# -l 移除容器间的网络连接,连接名为 db
|
|
|
|
|
|
|
|
docker rm -l db
|
|
|
|
|
|
|
|
# -v 删除容器,并删除容器挂载的数据卷
|
|
|
|
|
|
|
|
docker rm -v redis
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
删除指定 Docker 数据卷:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker volume rm {数据卷名}
|
|
|
|
#### 生成镜像
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 基于当前redis容器创建一个新的镜像;参数:-a 提交的镜像作者;-c 使用Dockerfile指令来创建镜像;-m :提交时的说明文字;-p :在commit时,将容器暂停
|
|
|
|
|
|
|
|
docker commit -a="DeepInThought" -m="my redis" [redis容器ID] myredis:v1.1
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
删除未关联(失效) Docker 数据卷:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ docker volume prune
|
|
|
|
#### 容器与主机间的数据拷贝
|
|
|
|
$ docker volume rm $(docker volume ls -qf dangling=true)
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
# 将rabbitmq容器中的文件copy至本地路径
|
|
|
|
|
|
|
|
docker cp rabbitmq:/[container_path] [local_path]
|
|
|
|
|
|
|
|
# 将主机文件copy至rabbitmq容器
|
|
|
|
|
|
|
|
docker cp [local_path] rabbitmq:/[container_path]/
|
|
|
|
|
|
|
|
# 将主机文件copy至rabbitmq容器,目录重命名为[container_path](注意与非重命名copy的区别)
|
|
|
|
|
|
|
|
docker cp [local_path] rabbitmq:/[container_path]
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 文件操作命令
|
|
|
|
## 其它常用操作
|
|
|
|
|
|
|
|
|
|
|
|
从主机复制文件到 Docker 容器中:
|
|
|
|
### 文件拷贝
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
```shell
|
|
|
|
$ sudo docker cp {主机内文件路径} {容器ID}:{容器内文件存储路径}
|
|
|
|
# 从主机复制到容器
|
|
|
|
|
|
|
|
sudo docker cp host_path containerID:container_path
|
|
|
|
|
|
|
|
# 从容器复制到主机
|
|
|
|
|
|
|
|
sudo docker cp containerID:container_path host_path
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
从 Docker 容器中复制文件到主机中:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
$ sudo docker cp {容器ID}:{容器内文件路径} {主机内文件存储路径}
|
|
|
|
# CI/CD
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 发布方式
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
应用程序升级面临最大挑战是新旧业务切换,将软件从测试的最后阶段带到生产环境,同时要保证系统不间断提供服务。长期以来,业务升级渐渐形成了几个发布策略:蓝绿发布、灰度发布和滚动发布,目的是尽可能避免因发布导致的流量丢失或服务不可用问题。三种方式均可以做到平滑式升级,在升级过程中服务仍然保持服务的连续性,升级对外界是无感知的。那生产上选择哪种部署方法最合适呢?这取决于哪种方法最适合你的业务和技术需求。如果你们运维自动化能力储备不够,肯定是越简单越好,建议蓝绿发布,如果业务对用户依赖很强,建议灰度发布。如果是K8S平台,滚动更新是现成的方案,建议先直接使用。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 蓝绿发布:两套环境交替升级,旧版本保留一定时间便于回滚
|
|
|
|
|
|
|
|
- 滚动发布:按批次停止老版本实例,启动新版本实例
|
|
|
|
|
|
|
|
- 灰度发布:根据比例将老版本升级,例如80%用户访问是老版本,20%用户访问是新版本
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 蓝绿发布
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
蓝绿部署中,一共有两套系统:一套是正在提供服务系统(也就是上面说的旧版),标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的,并且正在运行的系统,只是系统版本和对外服务情况不同。正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
![蓝绿发布示意图](images/DevOps/蓝绿发布示意图.jpg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
蓝色系统不对外提供服务,用来做啥?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统, 切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**特点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 蓝绿部署的目的是减少发布时的中断时间、能够快速撤回发布
|
|
|
|
|
|
|
|
- 发布策略简单
|
|
|
|
|
|
|
|
- 用户无感知,平滑过渡
|
|
|
|
|
|
|
|
- 升级/回滚速度快
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**缺点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 需要准备正常业务使用资源的两倍以上服务器,防止升级期间单组无法承载业务突发
|
|
|
|
|
|
|
|
- 短时间内浪费一定资源成本
|
|
|
|
|
|
|
|
- 基础设施无改动,增大升级稳定性
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 滚动发布
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
![滚动发布示意图](images/DevOps/滚动发布示意图.jpg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**特点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 用户无感知,平滑过渡
|
|
|
|
|
|
|
|
- 节约资源
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**缺点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 部署时间慢,取决于每阶段更新时间
|
|
|
|
|
|
|
|
- 发布策略较复杂
|
|
|
|
|
|
|
|
- 无法确定OK的环境,不易回滚
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**部署过程**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 先升级1个副本,主要做部署验证
|
|
|
|
|
|
|
|
- 每次升级副本,自动从LB上摘掉,升级成功后自动加入集群
|
|
|
|
|
|
|
|
- 事先需要有自动更新策略,分为若干次,每次数量/百分比可配置
|
|
|
|
|
|
|
|
- 回滚是发布的逆过程,先从LB摘掉新版本,再升级老版本,这个过程一般时间比较长
|
|
|
|
|
|
|
|
- 自动化要求高
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 灰度发布
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
灰度发布, 也叫金丝雀发布。是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀部署也就是灰度发布的一种方式。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
![灰度发布示意图](images/DevOps/灰度发布示意图.jpg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
灰度发布是通过切换线上并存版本之间的路由权重,逐步从一个版本切换为另一个版本的过程。灰度发布只升级部分服务,即让一部分用户继续用老版本,一部分用户开始用新版本,如果用户对新版本没什么意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
![灰度发布](images/DevOps/灰度发布.png)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**特点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 保证整体系统稳定性,在初始灰度的时候就可以发现、调整问题,影响范围可控
|
|
|
|
|
|
|
|
- 新功能逐步评估性能,稳定性和健康状况,如果出问题影响范围很小,相对用户体验也少
|
|
|
|
|
|
|
|
- 用户无感知,平滑过渡
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**缺点**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 自动化要求高
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**部署过程**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 从LB摘掉灰度服务器,升级成功后再加入LB
|
|
|
|
|
|
|
|
- 少量用户流量到新版本
|
|
|
|
|
|
|
|
- 如果灰度服务器测试成功,升级剩余服务器
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|