Docker|Docker 自动化运维实践

背景 随着项目的深入,项目变得越来越大。为了应对更加复杂的业务和提高迭代速度。所以对项目进行了一次拆分,由此产生了我们需要在同一台服务器上要部署多个项目,为了保持项目与项目之间的独立性,我们打算使用docker对项目进行隔离
Docker 是什么? Docker|Docker 自动化运维实践
文章图片
Paste_Image.png
这是Docker的logo图,直观上看是一只鲸鱼拖着好多箱子在海上游走。那么在深入的思考下,对应到我们现实生活中不就是一只货船载着许多集装箱么。现实生活中集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。
这也就是Docker的核心思想“集装箱思想”。
Docker 能做什么? 1.不同的应用程序可能会有不同的应用环境,比如.net开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上就要调试很久,而且很麻烦,还会造成一些冲突。比如IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来讲,我们可以在服务器上创建不同的虚拟机在不同的虚拟机上放置不同的应用,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小,小就意味着省钱了。
2.你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程当中运维就得想办法解决这样的问题。这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。
3.在服务器负载方面,如果你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。
Docker vs 虚拟机 上文中我们多次提到了虚拟机,相信大家对虚拟机也有一定的了解,也有的人这样说:“在一个机器上运行成百上千个虚拟机不可能,但运行成百上千个容器已经实现”。那么,虚拟机和Docker的不同点是什么呢?
Docker|Docker 自动化运维实践
文章图片
Paste_Image.png
比较两图的差异,左图虚拟机的Guest OS层和Hypervisor层在docker中被Docker Engine层所替代。虚拟机的Guest OS即为虚拟机安装的操作系统,它是一个完整操作系统内核;虚拟机的Hypervisor层可以简单理解为一个硬件虚拟化平台,它在Host OS是以内核态的驱动存在的。
虚拟机实现资源隔离的方法是利用独立的OS,并利用Hypervisor虚拟化CPU、内存、IO设备等实现的。例如,为了虚拟CPU,Hypervisor会为每个虚拟的CPU创建一个数据结构,模拟CPU的全部寄存器的值,在适当的时候跟踪并修改这些值。需要指出的是在大多数情况下,虚拟机软件代码是直接跑在硬件上的,而不需要Hypervisor介入。只有在一些权限高的请求下,Guest OS需要运行内核态修改CPU的寄存器数据,Hypervisor会介入,修改并维护虚拟的CPU状态。
对比虚拟机实现资源和环境隔离的方案,docker就显得简练很多。docker Engine可以简单看成对Linux的NameSpace、Cgroup、镜像管理文件系统操作的封装。docker并没有和虚拟机一样利用一个完全独立的Guest OS实现环境隔离,它利用的是目前Linux内核本身支持的容器方式实现资源和环境隔离。简单的说,docker利用namespace实现系统环境的隔离;利用Cgroup实现资源限制;利用镜像实现根目录环境的隔离。
Docker 实践 我们一我们拆分出来的搜索服务为例,来让读者更加了解Docker的使用
1、Docker 安装
读者可以阅读官方的安装文档,但是笔者认为这些操作有些繁琐,读者可以使用如下命令进行安装

curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -

验证下是否安装成功
docker -v

Docker|Docker 自动化运维实践
文章图片
Paste_Image.png 2、Docker 相关概念
Docker|Docker 自动化运维实践
文章图片
Paste_Image.png 1、Docker daemon 接受并处理Docker Client发送的请求,它是运行在宿主机上的系统进程
2、Docker client Docker的用户接口,用户通过执行 docker 命令操作 daemon
3、Docker镜像是一个只读的模板。举个例子,一个镜像可以包含一个运行在Apache上的Web应用和其使用的Ubuntu操作系统。
4、Docker仓库用来保存镜像。可以理解为代码控制中的代码仓库。
5、Docker容器和文件夹很类似。一个Docker容器包含了所有的某个应用运行所需要的环境。每一个Docker容器都是从Docker镜像创建的
3、创建Dockerfile
我们先创建一个带有java环境的干净的系统,让它作为我们的base 镜像,之后我们镜像都去继承这个base镜像
base Dockerfile
# # MAINTAINERshiwei # DOCKER-VERSION17.03.0-ce # # Dockerizing ubuntu: Dockerfile for building ubuntu images #FROM ubuntu:latest MAINTAINER shiwei ENV TZ "Asia/Shanghai" ENV TERM xtermADD sources.list /etc/apt/sources.list# Install. RUN \ apt-get update && \ apt-get -y upgrade && \ apt-get install -y build-essential && \ apt-get install -y software-properties-common && \ apt-get install -y byobu curl git htopunzip vim wget && \ rm -rf /var/lib/apt/lists/*# java file RUN mkdir /home/software/ COPY jdk-7u80-linux-x64.tar.gz /home/software/WORKDIR /home/software/ RUN tar -zxf jdk-7u80-linux-x64.tar.gz#加密解密包 COPY local_policy.jar /home/software/jdk1.7.0_80/jre/lib/security/ COPY US_export_policy.jar /home/software/jdk1.7.0_80/jre/lib/security/#WORKDIR /home/software/jdk1.7.0_80/RUN update-alternatives --install /usr/bin/javac javac /home/software/jdk1.7.0_80/bin/javac 100 RUN update-alternatives --install /usr/bin/java java /home/software/jdk1.7.0_80/bin/java 100 RUN update-alternatives --display java RUN java -version RUN rm -rf jdk-7u80-linux-x64.tar.gz# expose port EXPOSE 22# Define default command. CMD ["bash"]

搜索项目的镜像
# # MAINTAINERshiwei # DOCKER-VERSION17.03.0-ce # # Dockerizing ubuntu: Dockerfile for building resin images #FROM base:latest MAINTAINER shiwei#create dir RUN mkdir /home/app/log -p RUN mkdir /home/app/workspace/searchit -p#resin COPY resin-4.0.40.tar.gz /home/software/ WORKDIR /home/software/ RUN tar -zxf resin-4.0.40.tar.gz RUN rm -rf resin-4.0.40.tar.gz COPY resin.xml /home/software/resin-4.0.40/conf/#测试 COPY index.html /home/app/workspace/searchit# expose port EXPOSE 8080CMD ["/home/software/resin-4.0.40/bin/resin.sh", "console"]

去文件所在目录执行下如下命令,就可以产生镜像了
docker build -t searchit .

然后运行
docker run --name gym -p 8888:8080 -d -v /home/gym:/home/app/workspace/gym --add-host hbbusiness_db_r.hotbody.com:121.42.xx.xx --add-host hbbusiness_db_w.hotbody.com:121.42.xx.xx --add-host hbbusiness_koubei.hotbody.com:121.42.xx.xx --add-host hbbusiness_db_r_f_s.hotbody.com:121.42.xx.xx searchit:latest

但是目前还没有达到我们对资源隔离的目的。那么我们如何对内存和CPU进行隔离呢?
1、Docker 资源隔离之CUP#### docker 的cpu 控制 整体上来说,都是docker 自带的,而按功能来分的话 ,可以分为:
共享:--cpu-shares, 通过设置对应的权重参数来控制CPU的分配,
例如 A --cpu-shares 1024B --cpu-shares 512

那么如果都跑满 A 将占有2/3 cpu时间 ,B是 1/3 ,但是 当A不使用时 ,B是能用使用全部的 CPU 资源的
独占:--cpuset-cpus 可以设置容器执行在具体 的 某个或者某几个核上。core 编号 从0 开始
2、Docker 资源隔离之内存#### 设置内存 -m, --memory 如果只 设置这个参数的话, 当容器中程序使用内存超过这个值,则程序死,但是容器不会死
【Docker|Docker 自动化运维实践】限制内存 --memory-swap :如果使用内存超过 设置的值 ,则容器也会被kill
Jenkins 自动化# 笔者上文陈述这么长的篇幅,但是目前和自动化还未沾边。Docker 并不会帮我们做自动化的部分工作,所以我们需要Jenkins
Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
首先Jenkins并不是必不可少的,使用它笔者主要从以下几个方面考虑:
1、去除手工操作,这意味着部署项目不需要再登录到服务器了,减少服务器上的操作就提高了安全性,手残执行 rm -rf * 的也是比比皆是,都是血的教训
2、提高测试效率 。部署速度快,提交效率
3、上线不一定由开发或运维人员完成。
4、完善的历史记录和回退功能
由于本文并不是详细介绍jenkins 的文章,所以不会讲解jenkins如何配置,如果需要请google,只贴出核心脚本
docker stop searchit docker start searchit

存在的问题 1、目前这个方案并没有完全实现自动化,如果有一台新的机器,我们需要为其产生镜像,或者执行Dockerfile 或者从我们的私服拉取镜像
2、还未有一个分布式的监控方案
3、分布式的Docker管理
4、日志处理
最后给大家推荐一本书吧
《Docker in Action》

    推荐阅读