diff --git a/DevOps.md b/DevOps.md index f65a9ef..7635f4b 100644 --- a/DevOps.md +++ b/DevOps.md @@ -3248,126 +3248,385 @@ 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 -# 列出 Docker 本地镜像列表 -$ docker images -$ docker image ls -a +```shell +# 查看docker容器版本 +docker version +# 查看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 -$ docker container prune +```shell +# 启动一个或多个已经被停止的容器 +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 -$ docker volume create {数据卷名} +# 获取镜像redis的元信息 +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 -$ sudo docker cp {主机内文件路径} {容器ID}:{容器内文件存储路径} +```shell +# 从主机复制到容器 +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 +- 少量用户流量到新版本 +- 如果灰度服务器测试成功,升级剩余服务器 + + # Nginx diff --git a/images/DevOps/滚动发布示意图.jpg b/images/DevOps/滚动发布示意图.jpg new file mode 100644 index 0000000..5f16802 Binary files /dev/null and b/images/DevOps/滚动发布示意图.jpg differ diff --git a/images/DevOps/灰度发布.png b/images/DevOps/灰度发布.png new file mode 100644 index 0000000..77ca87d Binary files /dev/null and b/images/DevOps/灰度发布.png differ diff --git a/images/DevOps/灰度发布示意图.jpg b/images/DevOps/灰度发布示意图.jpg new file mode 100644 index 0000000..dea251c Binary files /dev/null and b/images/DevOps/灰度发布示意图.jpg differ diff --git a/images/DevOps/蓝绿发布示意图.jpg b/images/DevOps/蓝绿发布示意图.jpg new file mode 100644 index 0000000..f5882bf Binary files /dev/null and b/images/DevOps/蓝绿发布示意图.jpg differ