精华内容
下载资源
问答
  • JVM虚拟 重新定义Java容器热部署的资源管理机制 陆传胜 2009~2015 IBM Java Technology Center 2015~ now 阿里巴巴基础架构 事业群JVM组 chuansheng.lcs@alibaba- 双十一就要到了 您准备好了吗 如果Java应用突然就...
  • Docker技术( 容器虚拟技术 )

    万次阅读 多人点赞 2019-10-18 19:59:21
    Docker虚拟化容器技术 第一章 Docker简介诞生背景Docker 介绍虚拟机技术容器虚拟技术官方网址第二章 Docker安装前提条件安装DockerDocker底层原理Docker结构图工作原理Docker为什么比VM快第三章 Docker常用命令...

    第一章 Docker介绍

    诞生背景

    一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。
    作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,
    特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验 .
    Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。

    环境配置如此麻烦,换一台机器,就要重来一次,费力费时。
    很多人想到,能不能从根本上解决问题,软件可以带环境安装?
    也就是说,安装的时候,把原始环境一模一样地复制过来。
    开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。

    开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。
    不过,即便如此,仍然常常发生部署失败的状况。
    Docker镜像的设计,使得Docker得以打破过去"程序即应用" 的观念。
    透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,
    由下而上打包,达到应用程式跨平台间的无缝接轨运作。

    在这里插入图片描述

    Docker 介绍

    Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,
    也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,
    使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。

    Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。
    将应用运行在 Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,
    这就实现了跨平台、跨服务器只需要一次配置好环境,换到别的机子上就可以一键部署好, 大大简化了操作

    总结:
    Docker是解决运行环境和配置问题的软件容器 , 方便做持续集中并有助于整体发布的容器虚拟化技术

    在这里插入图片描述

    虚拟机技术与容器虚拟化技术

    虚拟机技术

    虚拟机(virtual machine)就是带环境安装的一种解决方案。
    可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。
    应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样
    缺点 :1 资源占用多 2 冗余步骤多 3 启动慢

    在这里插入图片描述

    容器虚拟化技术

    Linux 容器(Linux Containers,缩写为 LXC)。
    Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。
    有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。
    容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置
    系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

    在这里插入图片描述
    二者区别

    1. 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
    2. 而容器内的应用进程直接运行于宿主机( 即:所在主机,下面统称宿主机 ) 的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
    3. 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。

    官方网址

    官方网址 : https://www.docker.com
    Docker社区官方:https://hub.docker.com/

    第二章 Docker安装

    Docker支持以下的CentOS版本:CentOS 7 (64-bit) ,CentOS 6.5 (64-bit) 或更高的版本

    前提条件

    目前,CentOS 仅发行版本中的内核支持 Docker。
    Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
    Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。

    # 查看内核版本
    uname -r 
    

    安装Docker

    Docker安装教程(CentOS 7)本人阿里云服务器装成功
    Docker安装教程(CentOS 7)本人腾讯云服务器装成功
    Docker安装教程(CentOS 6)

    Docker管理命令

    # 重新载入后台启动进程
    systemctl daemon-reload
    
    # 启动docker容器 ,每次关闭虚拟机/运服务器时需要启动( 重要!!! )
    sudo service docker start
    
    # 查看Docker容器状态
    sudo service docker status (should see active (running))
    
    # 运行hello-world镜像/测试Docker是否可以使用
    sudo docker run hello-world
    

    Docker底层原理

    Docker结构图

    在这里插入图片描述
    在这里插入图片描述

    工作原理

    Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,
    然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。
    容器,是一个运行时环境,就是我们前面说到的集装箱。

    在这里插入图片描述

    Docker为什么比VM快

    (1) docker有着比虚拟机更少的抽象层。
    由亍docker不需要Hypervisor实现硬件资源虚拟化,
    运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。
    因此在CPU、内存利用率上docker将会在效率上有明显优势。
    在这里插入图片描述

    (2) docker利用的是宿主机的内核,而不需要Guest OS。
    因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。
    因而避免引寻、加载操作系统内核返个比较费时费资源的过程,
    当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。
    而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。
    通过下图着重了解二者的比较( 图很重要!!!)
    在这里插入图片描述

    第三章 Docker常用命令

    帮助命令

    # 查看docker版本信息
    docker version
    
    # 查看docker所有安装信息
    docker info
    
    # 查看docker帮助 ( 最为重要,学会利用帮助文档来学习 ,这是成为高手的必经之路!!! )
    docker --help
    

    镜像命令

    # 1.列出本地镜像(图1)
    docker images
    
    # option说明
     -a :列出所有镜像
     -q:只列出镜像id
     -digests :显示镜像的摘要信息
    --no-trunc :显示相信信息
    
    
    # 2.搜索某个镜像名字 (会在docker社区搜索相关的镜像, 而我们配置的阿里源只是帮我们同步了docker社区的镜像,图2)
    docker search 
    
    # option说明
    	- s显示收藏数不小于指定值的镜像
        --no-trunc :显示相信信息
        - automated :只列出automated类型的镜像
    
    # 3. 下载镜像(图3)
    docker pull 镜像的名字:[TAG](不写默认为 lasted)
    
    # 4. 删除镜像
    docker rmi  -f 镜像名/镜像id
    docker rmi -f $(docker images -qa )
       
    

    各个选项说明:
    REPOSITORY:表示镜像的仓库源
    TAG:镜像的标签
    IMAGE ID:镜像ID
    CREATED:镜像创建时间
    SIZE:镜像大小
    同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
    如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

    图1
    在这里插入图片描述
    图2
    在这里插入图片描述

    图3
    在这里插入图片描述

    容器命令

    基本命令

    # 1. 新建并启动容器
    docker run [OPTIONS] IMAGE [COMMOND] [ARGS...]
    
    # OPTIONS 说明
    	--name="容器新名字": 为容器指定一个名称;
    	-d: 后台运行容器,并返回容器ID,也即启动守护式容器;
    	-i:以交互模式运行容器,通常与 -t 同时使用;
    	-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
    	-P: 随机端口映射;
    	-p: 指定端口映射,有以下四种格式
    	      ip:hostPort:containerPort
    	      ip::containerPort
    	      hostPort:containerPort
    	      containerPort
    	      
    # eg: 使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
    docker run -it centos /bin/bash 
    
     
    # 2. 查询当前正在运行的容器(类比虚拟中的查看进程)
    docker ps [OPTIONS] 
    
    # OPTIONS说明(常用):
    	-a :列出当前所有正在运行的容器+历史上运行过的
    	-l :显示最近创建的容器。
    	-n:显示最近n个创建的容器。
    	-q :静默模式,只显示容器编号。
    	--no-trunc :不截断输出。
    
    
    # 3. 退出容器
    exit  容器停止后退出
    ctrl+p+q  容器不停止退出
    
    # 4 .启动容器
    docker start 容器ID/容器名
    
    # 5. 重启容器 
    docker restart
    
    # 6. 停止容器
    docker stop 容器ID/容器名
    
    # 7. 强制停止容器
    docker kill 容器ID/容器名
    
    # 8. 删除已经停止的容器(如果没有停止,删除后悔停止)
    docker rm 容器ID
    删除多个容器(特别是第二种 ,先查询所有运行的进程, 然后通过管道传到后面的删除操作中)
    docker rm -f $(docker ps -a -q)
    docker ps -a -q | xargs docker rm
    

    重要命令

    # 1. 启动守护式容器(后台运行)
    docker -d 容器名
    
    # 使用镜像centos:latest以后台模式启动一个容器
    docker run -d centos
    
    问题:然后docker ps -a 进行查看, 会发现容器已经退出
    很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.
    容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
    
    这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start
    但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,
    这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.
    所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行
    
    # 2. 查看容器日志
    docker logs -f -t --tail 容器ID
    
    eg :(图1)
    docker run -d centos /bin/sh -c "while true;do echo hello testLogs;sleep 2;done"
    docker logs -tf --tail 10 02c81778b0e0
    
    -t 是加入时间戳
    -f 跟随最新的日志打印
    --tail 数字 显示最后多少条
    
    
    # 3. 查看容器内运行的进程(图2)
    docker top 容器ID
    
    # 4. 查看容器内部细节(图3)
    docker inspect 容器ID
    
    # 5.进入正在运行的容器并进行交互(图4)
    docker exec -it 容器ID bashShell
    
    # 6. 重新进入容器(图5)
    docker attach 容器ID bashShell(不写的话默认 /bin/bash下)
    
    # 比较5与6的区别
    attach 直接进入容器启动命令终端, 不会启动新的线程
    exec 是在容器中打开新的终端, 并且可以启动新的线程
    

    图1
    在这里插入图片描述

    图2
    在这里插入图片描述
    图3
    在这里插入图片描述
    图4
    在这里插入图片描述
    图5
    在这里插入图片描述

    Docker常用命令图解

    在这里插入图片描述

    第四章 Docker镜像

    镜像 / UnionFS(联合文件系统)

    Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统
    它支持对文件系统的修改作为一次提交来一层层的叠加,
    同时可以将不同目录挂载到同一个虚拟文件系统下。Union 文件系统是 Docker 镜像的基础。
    镜像可以通过分层来进行继承. 基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

    特性
    一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,
    联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

    在这里插入图片描述
    总结:
    镜像就像洋葱圈 ,就像莲花卷 ,一层套一层 ,对外只显示一个文件系统.
    而且, 这种分层镜像还可以复用

    特点

    Dcoker镜像都是只读的 , 当启动容器时, 一个新的可写层被加载到镜像的顶部
    这一层被称为"容器层", "容器层"执行的都称为"镜像层"

    Docker镜像加载原理:

    docker的镜像实际上由一层一层的文件系统组成,这种层级的文件构成文件系统UnionFS。
    在这里插入图片描述
    bootfs(boot file system) 主要包含bootloader和kernel,
    bootloader主要作用是引导加载kernel, Linux刚启动时会加载bootfs文件系统,Docker镜像的最底层是bootfs
    这一层与典型的Linux/Unix系统是一样的,包含boot加载器和内核。
    当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

    rootfs (root file system) ,在bootfs之上。
    包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。
    rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

    平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才220M

    在这里插入图片描述
    对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,
    因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。
    由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

    Docker镜像Commit操作

    # 提交容器副本实质成为一个新的镜像
    docker commit -m="提交的描述信息" -a="作者"	容器ID 要创建的目标镜像名:[标签名]
    
    
    eg: 同时docker运行tomcat案例
    # 1.  创建交互式界面 ( 相当于前台启动)
    docker run -it -p 8888:8080 tomcat   # 端口映射将8888作为docker的入口,映射到tomcat镜像的8080(图1,图2)
    docker run -it -P  tomcat  #自动端口映射(通过 docker ps查看端口, 图3)
    #后台启动(不会占用当前页面)
    docker run -d -p 8888:8080 tomcat 
    
    
    # 2. 进入tomcat (如果前置启动,另开一个窗口 ,后置启动则直接进入)
    # 查看运行容器ID
    docker ps  
    # 进入根目录
    docker exec -it 容器ID /bin/bash
    /usr/local/tomcat# rm -rf webapps/docs/ 
    # 删除后访问tomcat ,可以看到访问主页下的文档出现404(图4)
    
    # 3. 提交容器副本实使之为一个新的镜像
    # 查看运行容器ID
    docker ps  
    # 提交容器
    docker commit -m="del tomcat docs" -a="timepaus" 容器ID tomcat:v1.2
    # 查看镜像(图5)
    docker images
    
    # 4.同时启动新镜像并和原来的对比
    可以看到我们自己提交的新镜像也没有文档()
    但是我们重新下载的tomcat是有的
    

    图1
    在这里插入图片描述
    图2
    在这里插入图片描述
    图3
    在这里插入图片描述
    图4

    在这里插入图片描述
    图5
    在这里插入图片描述

    第五章 Docker容器数据卷

    简介

    类似Redis中的rdb文件和aof文件
    用于容器的持久化和荣期间的继承与共享数据

    容器内添加数据卷

    1.直接命令添加

    # 通过-v命令直接添加 (需要在根目录下创建 containerData  )
    # 创建后修改容器内containerData 会同步到hostData ,反之亦是如此
    docker run -it -v /hostData:/containerData  镜像名/ID
    
    # 创建只读权限的文件 , 容器内只能读取这个文件, 但是不能修改. ro: readonly
    docker run -it -v /宿主机绝路路径目录:/容器内目录:ro 镜像名
    

    2.Docker添加

    DockerFile的简单理解
    在这里插入图片描述

    # 1. 宿主机根目录下创建mydocker文件夹并进入
    
    
    # 2. 在mydocker文件想创建DockerFile文件并编辑,内容如下(图1)
    
    # volume test
    FROM centos
    VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
    CMD echo "finished,--------success1"
    CMD /bin/bash
    
    说明:
    出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
    由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
    
    
    3. 使用docker build命令创建一个镜像, 并挂载指定宿主机指定文件
    docker build -f /mydocker/DockerFile -t 定义的新镜像名称
    
    4. 查看镜像
    docker images
    
    5.运行新镜像
    docker run -it 定义的新镜像ID /bin/bash
    
    6.通过镜像运行后生成的容器ID查看 (图2), 对应的主机映射的数据卷地址
    docker ps
    docker inspect 容器ID
    
    7.测试添加卷和主机是否互通有无
    在容器中创建文件, 看看主机中是否创建对应的文件
    
    注意: 
    Docker挂载主机目录(第3步)Docker访问出现cannot open directory .: Permission denied
    解决办法:在挂载目录后多加一个--privileged=true参数即可
    

    图1
    在这里插入图片描述

    图2, 查看运行的容器id相关信息 docker inspect 容器ID
    在这里插入图片描述
    对比与总结
    在这里插入图片描述

    数据卷容器

    命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,
    挂载数据卷的容器,称之为数据卷容器

    实现步骤

    # 1. 以上一步所建镜像为模板 ,首先启动一个父容器dc01 ,在创建容器的数据卷文夹中创建一个文件(图1)
    docker run -it --name 	dc01 zzyy/centos
    touch dc01_add.txt
    
    # 2. 创建子容器dc02,dc03继承自dc01 , 在创建容器的数据卷文夹中创建一个文件(图2)
    docker run -it --name dc02 --volumes-from dc01 zzyy/centos
    touch dc02_add.txt
    docker run -it --name dc03 --volumes-from dc01 zzyy/centos
    touch dc01=3_add.txt
    
    
    # 3. 回到dc01可以看到所有数据都被共享了(图3)
    # 4. 删除dc01, dc02修改后dc03是否可访问,可以 (图4)
    # 5. 删除dc02dc03是否可以访问, 可以(图5)
    # 6. 新建dc04继承dc03是否可以访问, 可以(图6)
    
    结论
    容器之间配置信息的传递, 数据卷的生命周期一直持续到没有容器使用它为止
    

    图1
    在这里插入图片描述
    图2
    在这里插入图片描述
    图3
    在这里插入图片描述
    图4
    在这里插入图片描述

    图5
    在这里插入图片描述
    图6
    在这里插入图片描述

    第六章 DockerFile解析

    介绍

    Dockerfile是用来构建Docker镜像文件 ,是有一系列命令和参数构成的脚本

    构建步骤

    1.编写Dockerfile文件
    2.docker build
    3.docker run

    格式

    以centos的文件为例

    FROM scratch
    ADD centos-8-container.tar.xz /
    
    LABEL org.label-schema.schema-version="1.0" \
        org.label-schema.name="CentOS Base Image" \
        org.label-schema.vendor="CentOS" \
        org.label-schema.license="GPLv2" \
        org.label-schema.build-date="20190927"
    
    CMD ["/bin/bash"]
    

    语法

    1. 每条保留字指令都必须为答谢字母且后面至少跟一个参数
    2. 指令从上到下, 顺序执行
    3. #表示注释
    4. 每条指令都会创建一个一个新的镜像层, 并提交

    Docker执行DockerFile的大致流程

    1. docker从基础镜像运行一个容器
    2. 执行一条指令并对容器做出修改
    3. 执行类似docker commit 的操作提交一个新的镜像层
    4. docker 再基于刚提交的镜像运行一个新容器
    5. 执行dockerfile 中的下一条执行, 直至所有指令都完成

    从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

    • Dockerfile是软件的原材料
    • Docker镜像是软件的交付品
    • Docker容器则可以认为是软件的运行态。

    Dockerfile面向开发,Docker镜像成为交付标准,
    Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

    在这里插入图片描述

    1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
    2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
    3 Docker容器,容器是直接提供服务的

    DockerFile保留字指令

    查看tomcat的DockerFile文件 ,更好理解保留字
    在这里插入图片描述

    保留字整合案例

    自定义镜像

    我们安装的centos精简版是没有vim和ifconfig命令的支持的
    我们可以通过编写Dockerfile令其支持这些功能

    # 1.搜索centos镜像并下载
    docker search centos
    docker pull centos
    
    # 2.编写创建一个文件( /mydoker/dockerfile_centos ),编写Dockerfile ,内容如下
    --------------------------------------------------------------------
    FROM centos
    MAINTAINER timepause<qq_43371556@csdn.net>
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "install vim and ifconfig commond plug-in components success"
    CMD /bin/bash
    -----------------------------------------------------------------------
    
    
    
    # 3. 编译运行centos( 注意最后的空格和点号,图1 )
    docker build -f /mydoker/dockerfile_centos -t mycentos:1.3 .
    
    # 4. 测试功能( 图2 )
    # 查看是否新增镜像
    docker ps
    # 运行新镜像 
    docker run -it mycentos:1.3
    # 在容器中使用vim 与if config命令
    
    

    图1
    在这里插入图片描述

    图2
    在这里插入图片描述

    自定义tomcat9

    # 1. 创建存放生成镜像文件的目录
    mkdir -p /myuse/mydocker/tomcat9
    
    # 2.创建相关文件(c.txt用于测试)
    touch c.txt 
    
    
    # 3.上传tomcat和jdk(一定要注意版本, 根据版本修改Dockerfile文件, 图1)
    
    #. 4.创建并编辑Dockerfile(需要提前下载centos)
    vim Dockerfile
    ---------------------Dockerfile-------------------------------
    FROM         centos
    MAINTAINER    chy<chy@qq.com>
    #把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
    COPY c.txt /usr/local/cincontainer.txt
    #把java与tomcat添加到容器中
    ADD jdk-8u11-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.27.tar.gz /usr/local/
    #安装vim编辑器
    RUN yum -y install vim
    #设置工作访问时候的WORKDIR路径,登录落脚点
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    #配置java与tomcat环境变量
    ENV JAVA_HOME /usr/local/jdk1.8.0_11
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.27
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.27
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    #容器运行时监听的端口
    EXPOSE  8080
    #启动时运行tomcat
    # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
    # CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
    CMD /usr/local/apache-tomcat-9.0.27/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.27/bin/logs/catalina.out
    ---------------------Dockerfile-------------------------------
    
    
    
    
    # 5.构建镜像(在存放这些文件的目录下,图2)
    # 如果Dockerfile文件名称就是Dockerfile,可以省略参数 -f /Dockerfile所在位置的书写
    docker build -t mytomcat9 .
    
    # 6.查看镜像并运行镜像( 图3)
    docker images
    # 运行镜像 (后台启动, 成功后如图4)
    docker run -d -p 8080:8080 --name myt9 -v /myuse/mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.27/webapps/test -v /myuse/mydocker/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.27/logs --privileged=true  mytomcat9
    
    # 注意这里配置了容器卷的映射,宿主机的test文件夹映射到tomcat的webapps目录下的test文件,且二者可以互通有无. 
    docker exec -it 容器ID /bin/bash #进入容器根目录 ,可以访问相关页面
    
    # 7. 访问成功后, 添加jsp文件与web.xml文件( a.jsp用于访问测试 ,web.xml用于令jsp页面可以编译)
    vim a.jsp
    mkidr WEB-INF
    vim /WEB-INF/web.xml
    ------------------------------------------a.jsp---------------------------
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert title here</title>
      </head>
      <body>
    
        -----------welcome------------
        <="i am in docker tomcat self "%>
        <br>
        <br>
        <% System.out.println("=============docker tomcat self");%>
      </body>
    </html>
    ------------------------------------------a.jsp---------------------------
    
    
    
    ------------------------------------------web.xml-----------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
      version="4.0"
      metadata-complete="true">
    </web-app>
    ------------------------------------------web.xml-----------------------------------
    
    # 8. 重启服务, 访问a.jsp(图5)
    # 查看当前容器id
    docker ps (查看当前容器ID)
    docker ps -a (查看所有运行过的容器ID)
    # 重启服务
    docker restart 容器ID
    # 访问a.jsp页面
    

    图1
    在这里插入图片描述
    图2
    在这里插入图片描述

    图3
    在这里插入图片描述
    图4

    在这里插入图片描述
    图5

    在这里插入图片描述

    第七章 通过Docker安装软件

    MySQL

    # 1. 以安装mysql5.6为例(不知道什么原因5.7下不来)
    docker pull mysql:5.6
    
    # 2. 运行镜像,启动容器(端口3306,root用户密码:root,运行镜像:mysql5.6)
    docker run -p 3306:3306 --name mysql -v /datebase/mysql/conf:/etc/mysql/conf.d -v /datebase/mysql/logs:/logs -v /datebase/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.6
    
    # 3. 进入msql内部测试登陆
    docker ps
    ## 进入mysql的当前目录下
    docker exec -it MySQL运行成功后的容器ID/name     /bin/bash
    ## 输入账号密码
    mysql -u 账号 -p(然后根据提示输入密码)
    
    
    # 4.连接数据库的图形化界面
    ## Mysql 解决连接客户端时出现1251 client does not support ...问题
    ALTER USER  'root'@'%' IDENTIFIED WITH mysql_native_password BY 'mysql密码';
    ALTER USER  'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'mysql密码';
    
    # 5. 备份数据库数据,之后我们可以通过直接读取这个sql文件恢复数据
    docker exec myql服务容器ID sh -c ' exec mysqldump --all-databases -uroot -p"root" ' > /datebase/all-databases.sql
    

    在这里插入图片描述

    Redis

    # 1.下载最新版redis镜像
    docker pull redis
    
    # 2.运行镜像(redis端口2333, -d后的redis不加参数默认为redis:latest)
    # 注意本地数据卷与容器内数据卷目录的对应
    docker run -p 2333:6379 -v /myuse/myredis/data:/data -v /myuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf  -d redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
    
    # 3.上传redis.conf到本地数据卷所在目录
    本地数据卷坐在目录 : /myuse/myredis/conf
    文件地址(太大了 ,这里放不下) : https://download.csdn.net/download/qq_43371556/11889084
    
    # 4. 运行redis的cil----shell命令行
    docker exec -it 运行着Rediis服务的容器ID redis-cli
    # 远程连接 docker redis
    docker exec -it redis_s redis-cli -h 192.168.1.100 -p 6379 -a your_password //如果有密码 使用 -a参数
    
    

    RabbitMQ

    # 1.下载镜像
    docker pull rabbitmq:3.7.7-management
    
    # 2.运行镜像
    docker run -d --name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=/ -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin df80af9ca0c9
    
    -d 后台运行容器;
    --name 指定容器名;
    -p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
    -v 映射目录或文件;
    --hostname  主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名);
    -e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)
    
    
    # 3.访问 (如下图)
    http://ip:15672
    账号 :admin
    密码: admin
    

    在这里插入图片描述

    MongoDB

    # 1.查看docker+MongoDB版本(图1)
    docker search
    
    # 2.下载最新的MongoDB
    docker pull mongo
    
    # 3.将镜像运行成容器
    docker run -itd --name mongo -p 27017:27017 mongo --auth
    ## 参数说明:
    -p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。
    --auth:需要密码才能访问容器服务。
    
    # 4.使用以下命令添加用户和设置密码,并且尝试连接。
    $ docker exec -it mongo mongo admin
    # 创建一个名为 admin,密码为 123456 的用户。
    >  db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'}]});
    # 尝试使用上面创建的用户信息进行连接。
    > db.auth('admin', '123456')
    

    图1
    在这里插入图片描述

    安装vsftpd+Nignx(图片服务器)

    环境搭建

    通过搭建Nginx和vfstpd 实现文件服务器

    # 1. 安装docker-compose . 实现对相关软件的配置
    curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    chmod +x /usr/local/bin/docker-compose
    
    # 2. 编写docker-compose.yml 配置文件
    ## 需要需要修改的地方的是: 
    ## /data/ftp:/home/vsftpd/ftpuser(20行), /data/ftp 是ftp中图片存放的地址
    ## /data/ftp:/home/images(11行) , /data/ftp 是Nginx来对应ftp中图片存放的地址
    ## FTP_USER,FTP_PASS 代表ftp用户的账号和密码, 需要在Linux中提前添加用户 
    ## 添加用户命令 a. useradd ftpuser,b. passwd ftpuser 然后输入自定义密码  
    ## ~/pic/nginx/conf/nginx.conf(9行), 注意! 需要提前准备Nginx的配置文件nginx.conf, ~ 代表home目录
    ## PASV_ADDRESS: 192.168.40.21, PASV_ADDRESS后面填写的是ftp服务器的ip
    ----------------docker-compose.yml---------------------
    version: '2'
    services:
      nginx-image:
        image: nginx:1.15.8
        ports:
          - "80:80"
        volumes:
          - ~/pic/nginx/html:/usr/share/nginx/html
          - ~/pic/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
          - ~/pic/nginx/logs:/var/log/nginx
          - /data/ftp:/home/images
        restart: always
      vsftpd:
        image: fauria/vsftpd
        ports:
          - "20:20"
          - "21:21"
          - "21100-21110:21100-21110"
        volumes:
          - /data/ftp:/home/vsftpd/ftpuser
        environment:
          FTP_USER: ftpuser
          FTP_PASS: 1q2w3e4r
          PASV_ADDRESS: 192.168.40.21
          PASV_MIN_PORT: 21100
          PASV_MAX_PORT: 21110
          LOCAL_UMASK: 022
        restart: always
    -------------------------------------
    
    # 3. 分享上面需要nginx.conf文件放在下面了
    vim /home/pic/nginx/conf/nginx.conf
    
    # 4. docker-compose执行, 需要在docker-compose.yml所在的目录下执行
    docker-compose up -d
    
    # 5. docker ps(查看容器是否执行, 下图1)
    

    图1
    在这里插入图片描述

    上面第三步所需的nginx.conf配置文件

    # root   /data/ftp/, /data/ftp/代表的是我们上面配置的ftp图片存放的地址, 只需要修改这一处
    location / { root   /data/ftp/;i ..... }
    

    完整配置文件

    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        #gzip  on;
    
        server {
            listen       80;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                root   /data/ftp/; # /data/ftp/代表的是我们上面配置的ftp图片存放的地址, 只需要修改这一处
                index  index.html index.htm;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    
    
    
    }
    
    

    代码测试

    1. 添加依赖
    <!--文件上传与下载-->
             <dependency>
                 <groupId>commons-net</groupId>
                 <artifactId>commons-net</artifactId>
                 <version>3.3</version>
             </dependency>
             <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.7</version>
                <scope>compile</scope>
            </dependency>
    
    1. 工具类代码
    package com.clife.common.utils;
    
    import org.apache.commons.net.ftp.FTP;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPFile;
    import org.apache.commons.net.ftp.FTPReply;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    
    import java.io.*;
    
    /**
     * ftp上传下载工具类
     */
    public class FtpUtil {
    
    	private static   String hostname="192.168.40.21";
    	private static   int port=21;
    	private static   String ftpusername="ftpuser";
    	private static   String ftppassword="ftpuser";
    	private static   String basePath="/data/ftp";
    	private static   String filePath="";
    
    	//日志打印
    	private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);
    
    	/**
    	 * 文件上传封装方法
    	 * @param sourceFileName 本地文件绝对地址,目录+文件名, eg:D:\\1.jpg
    	 * @param targetFileName 上传到ftp服务器/data/ftp/目录下的文件名
    	 * @return
    	 * @throws FileNotFoundException
    	 */
    	public static boolean ftpUploadFile(String sourceFileName, String targetFileName) throws FileNotFoundException {
    		FileInputStream in=new FileInputStream(new File(sourceFileName));
    		boolean b = uploadFile(hostname, port, ftpusername, ftppassword, basePath, filePath, targetFileName, in);
    		return b;
    	}
    
    	/**
    	 * Description: 向FTP服务器上传文件
    	 * @param host FTP服务器hostname
    	 * @param port FTP服务器端口
    	 * @param username FTP登录账号
    	 * @param password FTP登录密码
    	 * @param basePath FTP服务器基础目录
    	 * @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
    	 * @param filename 上传到FTP服务器上的文件名
    	 * @param input 输入流
    	 * @return 成功返回true,否则返回false
    	 */
    public static boolean uploadFile(String host, int port, String username, String password, String basePath,
    			String filePath, String filename, InputStream input) {
    		boolean result = false;
    		FTPClient ftp = new FTPClient();
    		try {
    			int reply;
    			ftp.connect(host, port);// 连接FTP服务器
    			logger.info("连接ftp成功...");
    			// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
    			ftp.login(username, password);// 登录
    			logger.info("ftp用户登陆成功!!!");
    			reply = ftp.getReplyCode();
    			if (!FTPReply.isPositiveCompletion(reply)) {
    				ftp.disconnect();
    				return result;
    			}
    			//切换到上传目录
    			if (!ftp.changeWorkingDirectory(basePath+filePath)) {
    				//如果目录不存在创建目录
    				String[] dirs = filePath.split("/");
    				String tempPath = basePath;
    				for (String dir : dirs) {
    					if (null == dir || "".equals(dir)) {continue;}
    					tempPath += "/" + dir;
    					if (!ftp.changeWorkingDirectory(tempPath)) {
    						if (!ftp.makeDirectory(tempPath)) {
    							return result;
    						} else {
    							ftp.enterRemotePassiveMode();
    							ftp.changeWorkingDirectory(tempPath);
    						}
    					}
    				}
    			}
    			//设置上传文件的类型为二进制类型
    			ftp.setFileType(FTP.BINARY_FILE_TYPE);
    			//上传文件
    			if (!ftp.storeFile(filename, input)) {
    				logger.info("文件 {} 上传失败!",filename);
    				return result;
    			}
    			input.close();
    			ftp.logout();
    			result = true;
    			logger.info("文件 {} 上传成功!",filename);
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if (ftp.isConnected()) {
    				try {
    					ftp.disconnect();
    				} catch (IOException ioe) {
    				}
    			}
    		}
    		return result;
    	}
    
    
    
    	public static void main(String[] args) {
    		//FileInputStream in=new FileInputStream(new File("D:\\1.jpg"));
    		//boolean flag = uploadFile("192.168.40.21", 21, "ftpuser", "ftpuser", "/data/ftp","", "123.png", in);
    		boolean flag = false;
    		try {
    			flag = ftpUploadFile("D:\\11.jpg", "6666.jpg");
    			System.out.println(flag);
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}
    
    
    	}
    }
    
    
    1. 图片访问
      http://192.168.40.21/6666.jpg

    第八章 发布镜像到阿里云

    步骤

    # 1.登陆阿里云, 进入容器镜像服务(可以通过下方地址注册登录跳转到容器镜像服务)
    https://cr.console.aliyun.com/cn-hangzhou/instances/repositories
    
    # 2. 创建镜像仓库(图1)
    # 3. 在docker中登陆 ,根据图2,图3中的操作指南进行操作
    
    # 5. 将正在运行的容器创建成一个镜像(图4)
    docker commit 
    
    OPTIONS说明:
    -a :提交的镜像作者;
    -m :提交时的说明文字;
    
    # 4.将镜像推送到阿里云的镜像仓库(最好是根据阿里云上的操作指南)
    docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号]
    sudo docker push registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号]
    
    # 5. 搜索镜像 ,下载镜像(图5,图6)
    docker pull 复制的镜像地址
    

    图1
    在这里插入图片描述
    图2
    在这里插入图片描述
    图3

    在这里插入图片描述

    图4
    在这里插入图片描述
    图5
    在这里插入图片描述
    图6
    在这里插入图片描述


    点击本博客相关学习视频地址
    图片服务器参考博客

    展开全文
  • 一方面,业务线的主要诉求是在市场上实现差异性竞争优势,其具体体现包括更出色的应用程序、客户服务以及始终领先于竞争对手的实际方案。而在另一方面,大家还拥有自己的IT运维和安全团队,他们的任务则主要集中在...
    概要简述

    时至今日,企业IT领域中最主要的问题在于如何解决不同功能部门之间的固有摩擦。一方面,业务线的主要诉求是在市场上实现差异性竞争优势,其具体体现包括更出色的应用程序、客户服务以及始终领先于竞争对手的实际方案。而在另一方面,大家还拥有自己的IT运维和安全团队,他们的任务则主要集中在可用性、安全性、合规性以及相关治理工作层面。在多数组织成员看来,容器技术能够切实解决双方之间所存在的各类矛盾。容器机制将带来一场革命性的转变,最终让IT组织中的这两大阵营真正实现顺畅对接与通力协作。 在本文博客中,我将向大家讲解: •容器加速应用交付 •何谓Linux容器 • Linux容器的优势 • 对容器的误解 • Docker与Kubernetes概览。

    发展阐述

    Google云平台的高级软件工程师Joe Beda在Gluecon上做了一个关于Google如何使用Linux容器技术的报告。他在报告中声称现在Google所有的应用都是运行在容器中的。这导致的结果就是Google每周要启动超过20亿个容器,每秒钟要启动超过3000个容器,这还不包括那些长期运行的容器。

    Google自从2004年起就已经开始使用容器技术了,于2006年发布了cgroups,并在去年创建了名为Let Me Contain That For You (lmctfy)的项目。Imctfy是Google开源版本的容器栈,它提供了用来代替LXC的Linux应用容器。当在单台机器上运行多个应用时,这些容器支持应用间的资源隔离,而且这会给人感觉这些应用是独自占用机器而运行的。这些应用可以知道容器的存在,这样它们就可以创建和管理它们自己的子容器了。

    应用案例

    进入2016年以后,容器技术早已经从最初的牛逼满天飞到了脚踏实地的大规模铺开。很多企业都已经在实际项目中或深或浅的使用着容器技术,享受到新技术带来的简洁和高效。作为国内最早研究和使用Docker技术的企业,ThoughtWorks在2013年底就在实际项目中将Docker用于测试环境的资源复用,并在之后的许多项目中逐渐总结出许多有用的实践和经验。在这篇文章里,我将聊聊Docker在我经历过项目中的一些比较有代表性的运用场景。

      现实中的容器技术运用方式非常广泛而灵活,时常让人觉得脑洞大开,概括来说是『可小可大,可远可近』。下面用四个案例来阐示容器在非特定领域里的运用场景。

      容器之小:小而美的容器DevOps架构栈

      

    图片描述

     

      图1基于容器和DevOps理念的运维架构

      这张架构图来自于一个规模不到20人的小型产品团队,团队的结构十分精巧,由两名开发人员兼任主要的运维工作。这两位开发人员,花了几周时间通过Ansible陆陆续续搭建起了这套由上百个服务器节点组成的集群,并由团队所有开发人员共同维护。整体套集群系统高度自动化,使得团队的每个人都能够十分快速而安全的完成业务功能的部署、获取线上业务的运行状况、以及对出现问题的故障点进行快速的日志错误定位。

      麻雀虽小,五脏俱全。这套技术方案包含了集群管理、网络管理、服务发现、日志管理、性能监控等许多方面的设计,从架构的角度上看,已经俨然是一个小型私有PaaS平台。

      Swarm作为集群的管理工具,具有与Docker原生命令良好的一致性,在学习曲线比较缓和,在DevOps文化比较好的团队中很容易让开发人员快速上手。在这个架构方案中使用了Consul作为集群元数据存储的方案,Swarm的主、从节点信息以及Docker的跨节点网络划分的信息都存放在这里。Consul除了作为集群信息的存储,还可以用于应用服务的配置存储和服务发现,以及作为内网的DNS服务使用。不过出于安全性和可维护性的考虑,应该为应用服务单独搭建独立的Consul节点,与存储集群配置的Consul分开,防止由于数据干扰和意外修改引起大规模系统故障。

      使用Swarm的另一个潜在好处是它能够充分利用Docker内置的跨节点网络功能,这套基于VxLAN的SDN实现十分简洁易用,通信效率也很不错。

      容器集群的的性能监控和日志管理是使得这个小团队得以驾驭比团队人数更多的服务节点的关键要素,任凭运行的服务在机器漫漫海洋中随意穿行,这两件工具就是开发人员的罗盘和风向标,在关键时候为线上故障的定位争取宝贵时间,并能从中迅速找到每个服务当前运行的节点,从而采取必要的应急措施。cAdvisor+Influxdb+Grafana是一套为容器集群性能监控设计的开源解决方案,利用cAdvisor对容器信息的良好监控能力,Influxdb对时间序列数据的快速检索能力,以及Grafana的强大图表展示能力,形成性能数据的实时查看和历史回溯,并反馈到开发和运营的状态报表,形成完整闭环。不过,这个开源组合的缺陷在于缺乏现成的事件告警组件,在Influxdata公司的Telegraf项目逐渐成熟后,可以考虑使用它替代cAdvisor的功能,然后集成Kapacitor作为告警模块,提前预知服务的不正常状态。日志管理方面,这套系统使用了当下最主流的容器日志开源工具组合Fluentd+EslasticSearch+Kibana,在《程序员》2016年6月刊『容器的性能监控和日志管理』一文中已经对这个组合进行过比较深入的探讨。

      这是Docker集群化实践中运用得比较出色的一个案例,特别是对中小型产品团队,会有不少可借鉴和启发之处。在不用增加额外运维人员的情况下,这套系统可以比较轻松的扩容至几百上千的规模。然而,这个架构本身并没有考虑譬如多数据中心、租户隔离、访问授权、资源配额等复杂情景,它主要的设计初衷在于解决集群易用性的问题。试想在过去使用虚拟机管理服务的时代,让只有几个人的团队去维护上千个计算节点上运行的需要各种不同环境和配置的服务,这简直是不可完成的任务,然而通过容器化的部署、DevOps思维的团队、加上适当的集群辅助工具,他们做到了。

      容器之大:大型任务集群的容器化调度

      

    图片描述

     

      图2基于容器的多数据中心任务平台架构

      并不是所有的团队都愿意从头构建自己的整套运维架构和基础设施环境。在许多企业里,服务的运维管理是有专门的组织负责的。这些组织可能叫做平台部门、运维部门、或者环境支持部门,不论称呼如何,这些组织以及部门通常都需要管理数量相当庞大的计算资源。这些资源可能是跨机房,跨城市,甚至是分布在欧洲、美洲、非洲并且相互无法直接通信的数据中心里。他们所需要调度的作业数量和种类也远远超过一个自运维产品团队所需要考虑的规模。

      为这样的组织设计基于容器的任务调度平台需要对企业的需求和特定业务领域有充分的了解,越是大型的基础设施集群,所需要应对的风险和不确定也越大,设计一个面面俱到的通用大型集群也越困难。因此针对具体业务场景做出一定的取舍是不得已、但又是必要的。例如为了获得较高的响应速度而将集群划分为多个互不重叠的调度区域,因而限制了每个区域的容量;为了避免内网数据网络风暴而将节点数据分层处理并逐级减少数据汇总的维度,因而增加监控管理复杂度;或者为了增加系统规模而采用高度聚合而不适合多数据中心的方案。这些方案往往不需要具备普适性,而是会针对特定企业和业务场景进行恰到好处的修剪和优化。

      上面图中展示的是一个企业PaaS服务平台的结构,架构基于Kubernetes集群,需要应用在多个异地数据中心,并在统一的部署系统上对服务进行管理。由于单Kubernetes集群容量有限,这个方案实际上根据地域划分和租户的规模构建了多个几十到上千节点不等的子集群,集群直接互不重合,属于同一个任务组的服务只会在特定的某个集群内进行部署和调度,其实就是将集群和租户进行了绑定。在所有集群之上,通过自研的一个任务分发服务作为所有调度任务的入口,在这里处理服务的依赖关系、所属区域、以及其他元数据信息,然后调用Kubernetes的API完成任务的部署和调度,并通过额外的组件处理网络、存储等资源的配置。

      在图中省略了系统采用的其他自研模块,值得一提的是这个系统的性能数据管理使用了开源的Promethus软件。Promethus是SoundCloud公司维护的一款包含信息采集、处理、分析、展示和告警的性能监控整体解决方案,它提供了比较灵活的多数据中心级联能力和集中式的配置管理功能,因此特别适合规模较大的计算集群。不同于前一案例中Influxdb方案每个数据采集节点发数据给存储数据的中心节点的方式,Promethus的性能数据采集是由中心服务器主动向所有节点定时轮询的方式拉取的,因此所有与数据采集相关的配置全部在中心服务器上进行修改即可。而节点的数量和IP地址变动则通过服务发现机制来告知中心服务器,这大大简化了修改数据收集参数的流程。

      这个案例是一个比较典型的大规模容器集群,在大型容器集群方面许多企业都有着自己的实践沉淀。其中有两个比较明显的特点是从业务场景制定架构和系统中包含许多自研的组件,因此在借鉴的时候更需要广泛的收集信息,避免盲目照搬。

      容器之远:基于容器的持续集成实践

      

    图片描述

     

      图3基于容器的持续交付流水线示意

      接下来,让我们用广角镜头来审视一下软件发布的生命周期。通过持续交付的流水线,我们能够清晰的定义出软件从代码提交到上线发布之前所需要经过的每个环节,协助开发者发现工作流程中存在的瓶颈,并促使团队提升端到端的自动化程度,缩短独立功能上线的周期。

      那么容器在其中能扮演什么样的角色呢?首先是资源的隔离,为了确保每一次编译和测试的独立性,软件应该在干净的环境中分别进行构建、打包、并运行测试用例,而容器是非常合适用来提供这种虚拟环境的轻量级工具。其次是一致的软件打包方式,Docker的封装意味着不论运行的服务是用Java、Python、PHP还是Scala、Golang,平台可以用几乎相同的方式去完成部署,而不用考虑安装服务所需的环境,这些都在软件开发的时候就已经准备好了。最后是成熟的调度平台。基于容器有许多现成的任务调度框架,也正是由于前两个角色,容器使得任务的分发变得容易,由于应用不需要依赖主机的配置,这就让任务的灵活调度成为可能。

      基于容器的持续交付流水线和普通交付流水线很相似,包含构建、打包、测试、部署等环节。同时这其中也有许多技巧和专用于容器的优化手段。这个案例中我们选取其中两个比较具有启发性的来说。

      第一个例子是关于容器构建的优化。容器的构建通常都是由某个基础镜像开始,通过Dockerfile的描述自动化逐步执行,直至完成预期的状态。几乎所有项目的Dockerfile都不会每次从一个原始的Ubuntu或者CentOS的镜像做为基础,从头构建整个运行环境,因为那样会使得每次构建花费非常长的时间。制作用于继承的公共基础镜像是早已世人皆知的镜像构建提速优化的方法,这样可以让费时而又不常改变的步骤固定下来,每次构建时候就只需要基于这个镜像再进行增量修改就可以了。但这种方法其实也有潜在问题,那就是当我们需要升级基础镜像的时候,不得不重新构建所有基于它制作的所有服务镜像。

      这个问题被称为『脆弱的基础镜像』,该问题的应对策略有很多。例如简单的延迟子级镜像的升级时间,直到每个子镜像下次重新构建发布时自然会获得更新。又例如比较激进的方式,通过流水线建立镜像的依赖关系,在父级镜像一旦更新时,自动触发所有子级镜像的自动重建,这种方式要慎重采用,因为它很可能会导致同时产生大量的镜像构建任务,对网络和磁盘造成严重的压力。那么,有没有在一种办法既能获得具有时效性的更新,又不会产生短时间内的构建风暴呢?其实对于一些场景是可以有取巧方法的,通过Docker的外挂存储能力,将经常可能变化的内容做成单独的镜像,然后利用Docker的『–volume-from』参数在服务启动时覆盖掉运行容器的特定目录。典型的场景就是用于编译其他服务的容器,这些容器中一般都会有一些编译服务时所需的时依赖库,这些依赖库随着项目所需依赖的变化也要跟着变,像Maven的~/.m2/repository目录,Node的全局node_module目录等就很适合这样管理。当这个目录下面的内容需要更新时,只需重新构建提供目录内容的一个镜像,而不会产生镜像构建的链式反应,服务下次启动时候就会获得新的依赖库目录了。

      第二个例子是流水线中的测试环节。进行自动化测试的时候,容器的优势发挥尤其明显。对于外部服务的依赖,比如与数据库相关的测试,由于测试过程需要反复运行,过去时候,如果测试运行完没有正确的清理留下的数据,特别容易影响后续测试的运行结果。容器恰恰是提供这种即用即弃基础设施最佳的方式,完全可以在测试脚本中先启动一个全新的MySQL服务,然后测试完就销毁,保证了每次测试的独立性。关于这方面的应用在下个案例中再介绍更多细节。

      类似的技巧还有很多。持续交付流水线是最能体现容器在软件领域带来各方面改进的大观园。许多现成的工具可以最大化的避免手工操作对流程的干扰,让软件发布开上高速公路。

      容器之近:容器在自动化测试平台的运用

      

    图片描述

     

      图4基于容器的自动化测试平台架构

      最后这个案例是一个针对软件自动化测试环节的容器化基础设施设计。它是软件持续交付流水线上的一个重要环节,让我们带上长焦镜,近距离审视容器在软件测试场景中能解决怎样的问题。

      容器快速启动、快速销毁的特性与软件测试时所需的每次干净独立的临时运行环境十分匹配。使得在这方面容器可以大有作为。特别是在集成测试和功能性测试的阶段,被测系统的运行往往会需要涉及多个要独立运行的子组件或子模块。还有外部模块的依赖,如果进行的是界面相关的测试用例,往往还会用到Selenium和浏览器的组件。而运行数据库相关的测试则会需要MySQL、Mongodb等组件。手工为每个测试用例准备并维护这些环节依赖是十分让人抓狂的事情。过去做这类测试时候为了解决依赖问题,通常做法是额外部署一套专用于测试依赖的环境,所有模块测试需要别的模块时都统一指向这套测试环境作为目标。由于过于频繁的升级这个依赖环境可能会打断正在运行的测试用例,因此只能对它进行定期的更新,这种无形中限制了的时效性和可靠性。

      特别是一些比较重要并且耗时较短的回归测试和冒烟测试用例,理想情况下应该在每次代码提交后都全量的更新并执行,以便第一时间发现一些潜在的功能缺陷。但为每次提交创建一套测试环境不论是手工操作还是过去基于虚拟机的自动化方式都过于繁琐。

      案例中的测试平台正是意图通过容器和简单的依赖描述,来解决测试环境管理的问题。它基于所有被测组件和所依赖的组件都使用Docker镜像来提供的前提之上,将所有组件抽象成一致的模型写成描述文件,描述文件的主要内容就是整个测试环境所需的镜像和启动顺序。

      示意图中的『运行调度器模块』是接入持续交付流水线的调用入口,可以采用譬如Jenkins的形式插件实现,它用来创建和保存特定测试用例所需的环境描述文件内容。在流水线触发该测试环节时,这个模块调用『测试执行器模块』,将描述模型用特定的结构体传递给后者,后者解析这个数据模型,转化为接近Kubernetes服务模型的形式,然后在『服务依赖管理模块』的协助下,通过Kubernetes创建临时的Namespace,并依次创建每个服务。当测试环境就绪后,『测试执行器模块』就开始执行测试用例,最后又通过『服务依赖管理模块』通知Kubernetes销毁整套环境。

      整个过程对于平台的用户而言,仅仅是增加了一个测试环境描述的内容,写在持续交付流水线测试步骤的定义(例如Jenkins插件配置)里。而这套系统内部颇为复杂的执行过程,能够有效的利用整个集群的资源,恰到好处的为测试的过程提供支持。

      总结

      这四个案例由浅入深、由远及近的展现了容器在现代软件和基础设施设计中举足轻重的作用。有些技术会直接改变人们的生活,而另一些技术则会改变技术本身以及技术的发展方向,容器技术属于后者。

      随着容器运用的普及,当下的主流媒体对容器周边技术的关注还在持续升温。不仅是《程序员》推出了本期的容器技术专刊,在最新一期的ThoughtWorks公开刊物《技术雷达【1】》中,容器和Docker相关的关键词同样占据了大量版面。在越来越多的技术领域里,无论是移动设备、物联网、大数据,都能看到容器技术各种形式的延伸,作为现实容器运用的一道缩影,此文可作为窥斑见豹、抛砖引玉之用。

      参考链接:

      【1】https://assets.thoughtworks.com/assets/technology-radar-apr-2016-cn.pdf

    Docker&MeSOS
    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。
      在docker的网站上提到了docker的典型场景:
      Automating the packaging and deployment of applications
      Creation of lightweight, private PAAS environments
      Automated testing and continuous integration/deployment
      Deploying and scaling web apps, databases and backend services
      由于其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku), 构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。
      构建标准化的运行环境,现有的方案大多是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者需要base OS许多前提条件,后者几乎不可以修改(因为copy on write 的文件格式在运行时rootfs是read only的)。并且后者文件体积大,环境管理和版本控制本身也是一个问题。
      PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其作为PaaS产品的环境基础
      因为其标准化构建方法(buildfile)和良好的REST API,自动测试和持续集成/部署能够很好的集成进来
      因为LXC轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小,能够在单机环境下与KVM之类的虚拟化方案相比能够更加快速和占用更少资源
      虚拟化是一个广义的术语,在计算机方面通常是指计算元件在虚拟的基础上而不是真实的基础上运行。
      虚拟化,原本是指资源的抽象化,也就是单一物理资源的多个逻辑表示,或者多个物理资源的单一逻辑表示。具体到服务器虚拟化,就是多个物理资源的单一逻辑表示。
      虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程。CPU的虚拟化技术可以单CPU模拟多CPU并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。  
      在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件。

    容器技术虚拟化技术提升效率



    容器技术已经引起了业内的广泛关注,有充分的证据表明,容器技术能够大大提升工作效率。
      现在,
      首先,每种容器技术操作系统和应用程序堆栈都需要使用DRAM。容器技术对于多个运行简单应用程序的小型虚拟机实例来说,这种容器技术方式可能产生很大的系统开销,降低性能表现。容器技术加载并卸载这些堆栈镜像需要花费很长时间,并且还会增加容器技术服务器的网络连接数量。容器技术对于极端情况来说,如果用户在上午9点同时启动上千台虚拟桌面,容器技术还有可能导致网络风暴的发生。
      部署容器技术虚拟服务器容器技术的目的之一在于快速创建新的容器技术虚拟机实例。然而从容器技术网络存储当中复制镜像需要花费大量时间,这些容器技术操作会延长启动过程,无疑会限制系统灵活性。
      因此我们可以选择使用容器技术。只需要通过简单的观察我们便能够发现容器技术的出现是为了解决多操作系统/应用程序堆栈的问题:
    • 在容器技术单台服务器当中为所有虚拟机实例使用相同的操作系统对于大部分数据中心来说都不算是真正的限制。流程管理可以轻松处理这种变化
    • 许多容器技术应用程序堆栈都是相同的
    • 对于容器技术大规模集群来说,在本地硬盘当中存储操作系统副本将会使得更新过程变得更为复杂

      最为重要的是,容器技术可以同时将操作系统镜像和应用程序加载到内存当中。容器技术还可以从网络磁盘进行加载,因为容器技术同时启动几十台镜像不会对网络和存储带来很大负载。之后的镜像创建过程只需要指向通用镜像,容器技术大大减少了所需内存。
      容器技术能够在同一台服务器上创建相比于之前两倍的虚拟机实例数量,因此无疑容器技术将会降低系统总投入。但是必须容器技术认真进行规划,因为双倍的容器技术实例数量同样意味着对于运行这些容器技术实例的服务器带来了双倍的I/O负载。
      我们需要了解除了避免可能发生的容器技术启动风暴之外,容器技术是否还有任何其他性能方面的优势。能否改进IOPS?容器技术能够提升网络连接效率并且降低容器间的延迟,容器技术解决伴随实例数量增加而产生的问题?
      容器技术实验室完成了至今为止大部分权威实验,其研究结果表明容器技术相比于hypervisor,容器技术的许多关键指标都有重大改进。在进行的容器技术所有测试当中,容器技术几乎拥有和本地平台一样的运行速度,尽管网络延迟测试还没有完成。
      研究表明容器技术在多个领域当中都比hypervisor拥有更好的性能表现。容器技术的运行速度几乎是hypervisor的两倍,在评分当中非常接近于本地操作系统。在和KVM的对比当中,容器技术在硬盘随机读取(84,000 vs 48,000 IOPS)和写入(110,000 vs 60,000 IOPS )方面拥有非常优秀的表现,如果使用本地固态硬盘可以实现更好的SQL性能表现。
      即便是hypervisor虚拟化领域的领导者,VMware也针对容器技术进行了一系列评测对比。容器技术研究结果印证了容器技术拥有接近本地系统的性能表现,尽管容器技术没有针对VMware hypervisor发布非常详细的测试报告。而这项报告的容器技术结果有可能促使VMware做出调整,以降低hypervisor的系统开销。VMware的报告当中没有提及硬盘I/O问题。
      为了扩展容器技术适用范围,容器技术仍然需要在安全方面不断改进。但是现在,我们可以看到的是这种容器技术方式可以解决hypervisor虚拟化当中的大多数性能问题。再加上更加轻松和快捷的容器技术部署方式,容器技术将会在不久的将来占据虚拟化市场。 [1]  

    虚拟化 VS 容器化

    以 Docker 为代表的容器技术一度被认为是虚拟化技术的替代品,然而这两种技术之间并不是不可调和的。作者分别列举了容器技术以及虚拟化技术的优缺点,并提出将两者结合取长补短的解决方案。

    容器为应用程序提供了隔离的运行空间:每个容器内都包含一个独享的完整用户环境空间,并且一个容器内的变动不会影响其他容器的运行环境。为了能达 到这种效果,容器技术使用了一系列的系统级别的机制诸如利用Linux namespaces来进行空间隔离,通过文件系统的挂载点来决定容器可以访问哪些文件,通过cgroups来确定每个容器可以利用多少资源。此外容器之 间共享同一个系统内核,这样当同一个库被多个容器使用时,内存的使用效率会得到提升。

    对于系统虚拟化技术来说,虚拟层为用户提供了一个完整的虚拟机:包括内核在内的一个完整的系统镜像。CPU虚拟化技术可以为每个用户提供一个独享且和其他用户隔离的系统环境,虚拟层可以为每个用户分配虚拟化后的CPU、内存和IO设备资源。

    哪家强?

    通常来说,这取决于你的需求。如果你只是希望将应用运行的实例进行隔离,那么对于管理应用运行环境、启动应用实例以及控制资源 开销方面容器将是一个极为高效的工具。像Docker这一类的容器,其设计原则就是为了解决这种应用环境的修改以及应用部署的问题,并且这十分符合 DevOps理念(你可能希望知道更多关于DevOps理念的内容)。

    如果你从服务器虚拟化的角度来寻找最好的环境隔离方案,那么系统级的虚拟化是更好的方案:和容器相比,邻居租户(Noisy neighbours )对系统的影响在虚拟化的方案下将不是一个问题。尽管现在很多容器都在专注于提高其隔离能力,但是虚拟机的隔离还是要优于容器。从物理服务器过渡到虚拟服 务器是一个很自然的过程,并且现在针对虚拟服务器的管理的生态系统也很完善。

    在z系统中,Linux具有很好的伸缩性(运行容器),但是z是一个极度高效虚拟化(运行虚拟服务器)的平台,它继承了整个系统架构。尽管没有精确的测量,将虚拟化和容器技术相结合,在z系统中会比其他平台要容易。

    还有第三条路:两者兼而有之。

    有多种方式可以将系统虚拟化及容器技术相结合:

    1.一个容器中运行一个虚拟机

    kvm-in-docker.png

    Docker在部署容器方面十分灵活。其中一个选择(execution driver)是利用KVM镜像。这样就可以在最好的隔离性情况下发挥DevOps所擅长的使用Docker各种方式。但是这也付出了需要在启动容器时启 动整个操作系统实例的代价。这也就意味着较长的启动时间以及低效的内存使用,只能通过内核共享内存(KSM)来提升内存利用率。这种方法效果和效率都不理 想,但是这是一个好的开始。

    2.一个虚拟机中运行一个容器

    docker-in-vm.png

    与之相反的,你一可以在虚拟机中启动一个容器。这里的虚拟机并不是由Docker控制,而是通过现有的虚拟化管理设施来控制。一旦系统实例启动, 就可以通过Docker来运行容器而武器其他特殊的设置。同时,由于不同容器运行在不同的虚拟机上,容器之间也能有很好的隔离。而内存的使用率需要通过虚 拟层的内存共享来提升。

    2b.一个虚拟机中运行多个容器

    docker-tenant-in-vm.png

    对于多租户的情况,可以用另一种形式在虚拟机中运行Docker。这种情况下,我们假设在不同租户的容器之间需要强隔离,而对于同一用户的不同容 器,简单的Linux容器隔离已经足够。这样我们就可以在减少虚拟机个数的情况下保证租户之间的隔离,同时可以利用Docker带来的各种便利。

    总结来说:需要根据实际需求进行选择。

    【参考应用资料】

    1、企业级Docker镜像仓库的管理和运维 - 极客头条 - CSDN.NET http://geek.csdn.net/news/detail/109110

    2、Docker+Rally实现OpenStack性能测试自动化 - 极客头条 - CSDN.NET http://geek.csdn.net/news/detail/107981


    展开全文
  • 应用容器化之Kubernetes实践

    万次阅读 2016-08-15 08:34:09
    主要以ZooKeeper、Redis、Kafka、MongoDB等应用容器化在Kubernetes平台上面实践。从计算、网络、存储方面解析应用在集成中的问题,以及部分传统应用在容器化过程中设计的应用二次开发等问题。首先介绍应用Docker化的...
    容器是一种轻量级的虚拟化技术,拥有持续集成、版本控制、可移植性、隔离性和安全性等优点,越来越多的应用跑在容器里面。但也有其缺陷,并不是所有场景都适合如高性能计算,已经满负荷运行的应用没有必要虚拟化,一些对IO等运行环境要求比较高应用不适合容器化如Oracle数据库。
    

    容器给应用程序提供了一个独立的运行环境,并不是像虚拟机那样提供一套完整的操作系统,这是容器和虚拟机最大的区别,所以在用户在使用虚拟化如KVM、Vmware时候很少会担心到应用能不能跑到虚拟机里面,通常只是针对虚拟化环境做性能调优,如KVM的CPU绑定、内存气球以及巨型页等。但应用Docker化更加复杂,除了解决虚拟机存在的计算、存储、网络以外问题,还需要解决Docker自身的问题,如:Docker相对与虚拟机的脆弱性、应用程序依赖的系统调用在Docker中没有做限制,还有Docker镜像制作以及应用Docker化之后日志和性能采集等问题。

    Docker通过cgroup限制CPU和内存的使用,CPU限定通常是设置权重,并不能让一个容器获得确定1Ghz的CPU,当然你也可以使用cpuset绑定到指定的物理核上,内存使用中不仅要设置内存大小还要限定交换分区的大小,这点很重要,譬如MongoDB在内存不足时大量使用交换分区。

    Docker相对短暂的生命周期决定了不会使用持久存储,容器挂了,存储的数据也会相应的丢失。如果数据需要持久化如MySQL的DBData数据,则需要把数据输出到外部的存储设备上,可以通过挂载NFS或者GlusterFS或者AWS存储等,在Kubernetes的PV的后端存储已经可以支持上述文件系统。用户也可以根据不同存储去实现Docker volume plugin,比较流行有Rancher/Convoy和Flocker,后者支持数据迁移,这为容器的迁移奠定了数据基础。

    容器应用之间相互依赖:Web应用访问数据库,API接口调用等,所以网络必须能够互通并且支持多租户隔离,当前Docker网络有两大阵营,CNM和CNI。其中Calico可以算是脚踏两只船的,它可以与Kubernetes集成,相比Overlay网络在网络传输过程还是有明显优势的,如下图所示,减少了包封装提高了网络传输和包处理效率。
    calico-package.png

    Docker OVS SDN的方式达到容器和容器以及容器和主机之间的网络互通也是非常好的设计思想,通过实现Docker的Network Drivers接口将容器挂到OVS上,通过ryu、Floodlight或者OpenDaylight等SDN控制器动态下发流表的达到网络互通;再结合iptables实现网络隔离。如果想实现大二层跨机房网络互通,可以集合Vxlan等Overlay技术。
    sdn_ovs.png

    天云skyform ECP平台是基于Kubernetes Calico的容器管理平台,具有日志采集分析、性能监控、镜像管理等一套完整的容器管理平台。上面介绍了Docker相关的一些相关知识,下面介绍具体的应用在Kubernetes平台上的集成。我把应用集成难度分三个等级:最容易是应用本身具有服务发现机制如Dubbo,天然的支持自动扩缩容,那么在Kubernetes集成将会变的非常简单;大部分应用属于需要修改配置就能在容器里面运行,最困难的是需要对应用进行二次开发或者对平台二次开发的应用。

    ZooKeeper

    ZooKeeper是一个高性能、高可用的分布式协调服务。整个ZooKeeper集群的对外提供2181服务端口,节点之间数据同步和选主分别使用的2888和3888端口。每一个ZooKeeper节点都需要个其他节点通信,所以都需要一个固定的IP地址,通过Kubernetes服务提供的虚IP(如果使用集群内已经部署DNS则配置域名即可)互相通信,结构如下图所示:
    zookeepr-service.png

    Yaml文件如下
    zookeeper-yaml.png

    存储使用nfs共享存储,这样ZooKeeper容器重建后就能恢复数据。
    zookeeper-nfs.png

    Kafka

    Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Apache Storm、Spark都支持与Kafka集成。整个结构图如下所示:
    kafka-arch.png

    Yaml文件如下,这里面有三个地方需要注意:
    1. 每一个Kafka的broker都有一个集群内唯一的broker_id,所以不能把整个Kafka集群放到一个RC里面,而必须通过不同RC去分别定义每一个broker;
    2. Kafka依赖ZooKeeper,在这里我们通过环境变量的方式将域名传递到容器内;
    3. 这里没有配置Kafka的持久化存储,因为每个Topic包含一个或多个partition,如果单个broker宕调不会影响集群,并且当broker重建后会自动同步数据,速度非常快。
      kafka-yaml.png

    Redis

    Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis容器测试过程中,有几点性能问题需要注意,第一是Redis最大内存,如果不设置可能会出现将内存耗尽的现象,第二是数据ttl时间设定以及清理keys策略,这些都是为了避免内存不足时使用交换分区导致性能下降,第三是数据持久化使用RBD,相对于较大文件aof持久化,RBD更适合快照恢复。如果是业务量不大的场景可以使用redis主从结构,如下图所示:
    redis-arch.png

    Resis Master的Yaml文件如下,其中为了数据的迁移恢复和重建使用Glusterfs存储,当然你也可以换成其他存储,单个主从集群可能无法承载过多的请求,可以通过当前比较成熟的一个方案Twemproxy,通过代理实现数据分片,也能达到一个不错的效果:
    redis-yaml.png

    当前我们正在测试的是Redis 3.x的集群功能,每一个Redis都是一个service(slave默认不接受读写,需要执行readonly才能读),省去proxy代理提高效率。这个集群方案通过redis-trib.rb的create子命令构建, 在客户端配置所有service地址就可以操作集群里面的数据,但整个操作过程有两个地方必须通过手工完成,尚待完善:
    1. 整个集群创建redis-trib.rb是通过手动完成,没有服务发现和自动化;
    2. 增加加点必须手动执行redis-trib.rb reshard分配slot。

    redis-cluster.png

    MongoDB

    MongoDB是由C 语言编写的,是一个基于分布式文件存储的开源数据库系统。MongoDB已经不推荐使用主从,集群可以选择副本集或者分片。下图展示的每一个MongoDB对外是一个service,组成副本集的集群,类似mongodb这种对磁盘IO要求比较高的可以使用SSD加速,通过标签选择创建到有SSD机器上面提高性能。
    mongodb-yaml.png

    如果是MongoDB的分片集群,结构如下所示:
    mongos.png

    每一个configsvr配置服务和Mongos路由服务都是通过service提供固定的访问接口。mongos通过configsvr域名配置。通过服务发现的脚本动态配置将副本集转成分片,这个分片的功能测试已经通过,但性能测试还在进行中。

    上面一些应用都是通过容器外部传递配置参数或者启动脚本修改应用的配置,但有的应用通过这种方式是无法完成的,必须通过对应用或者对平台的改造才能完成,譬如IBM的任务调度平台OpenLava,它通过/proc/meminfo和/proc/cpuinfo获取内存和CPU,Docker这部分通过是挂载的主机proc文件系统,导致应用在容器内读取是主机的CPU和内存,此时通过修改OpenLava代码使其从/sys/fs/cgroup/cpu/cpu.shares 获取CPU核数从/sys/fs/cgroup/memory/memory.limit_in_byte获取内存值,有的应用(多个pod)之间需要共享IPC,这部分功能Kubernetes是没有的,需要通过平台改造去达到应用需求,还有应用需要根据IO去调度,这些都是我们ECP平台基于Kubernetes添加的功能。

    Q&A

    Q:请问在Kubernetes架构下 搭建分布式服务框架如Dubbo 需要将主机地址和暴露端口注册到ZooKeeper上,这个主机地址和暴露的端口你们是怎么处理的,即容器内的应用如何获取Docker宿主机地址?

    A:Dubbo服务不需要暴露主机的IP和地址,只需要知道容器地址即可。这些服务都是注册到ZooKeeper上面,通过ZooKeeper完成服务发现,Kubernetes能够根据暴露端口进行调度,当然有些应用要求容器能获取到宿主机的IP地址,这块我们对Kubernetes做了一些修改,可以动态注入诸如宿主机IP,宿主机主机名信息到容器的环境变量中。
    Q:ECP的定位和解决目标相比较目前大家在用传统的云平台解决方案来讲下?
    A:ECP产品定位是一套完整的容器解决方案,从容器生命周期管理,资源监控到日志分析处理,相比与云平台解决方案管理的对象不再是虚拟机,而是容器,面向的对象是服务。
    Q:关于容器本身的资源性能监控,是用的cAdvisor+Heapster吗,如何能保持pod重启(重启后pod名称变化)后的数据连续性,谢谢。
    A:资源监控用的不是Heapster,ECP的资源监控是用cAdvisor+我们自己研发的采集Agent+Ceilometer+MongoDB+HBase等技术。复用了我们在做CMP产品时的技术,rc中的pod重建后会重命名,这块对于单一pod数据的连续性还没有考虑,我们是把rc当做一个整体考虑的 。
    Q:你们对外服务的负载均衡如何做的?是直接用Kubernetes的service吗?
    A:对外负载均衡现阶段用的是Kubernetes的service,考虑到iptables带来的性能损耗,后续我们会考虑使用别的方案,在集群内部直接把流量转发到对于的pod上。
    Q:请问Kubernetes容器和在其中运行的应用程序监控是如何做的?能介绍下吗?谢谢!
    A:ECP的资源监控是用cAdvisor+我们自己研发的采集Agent+Ceilometer+MongoDB+HBase等技术。复用了我们在做CMP产品时的技术。简单来说就是用cAdvisor采集原始数据,然后通过Ceilometer持久化,提供实时数据查询、告警等功能。数据会定期转存到hbase做历史数据分析。
    Q:请问,有基于Kubernetes的多租户和用户配额开源实现嘛?
    A:现在开源的方案比较少,我们的ECP产品是结合Keystone实现的多租户管理以及租户的配额管理。
    展开全文
  • 容器化ICT融合初体验

    万次阅读 2016-08-19 13:03:42
    【编者的话】本次将分享的容器化ICT融合平台是一种面向未来ICT系统的新型云计算PaaS平台,它基于容器这一轻量级的虚拟化技术以及自动化的“微服务”管理架构,能够有效支撑应用快速上线和自动扩缩容,最大化IT基础...
    【编者的话】本次将分享的容器化ICT融合平台是一种面向未来ICT系统的新型云计算PaaS平台,它基于容器这一轻量级的虚拟化技术以及自动化的“微服务”管理架构,能够有效支撑应用快速上线和自动扩缩容,最大化IT基础设施资源利用率并降低总体拥有成本(TCO)。未来的网络正在向IT化、云化方向发展,容器与微服务技术,完美契合“网络即服务”、网络切片等发展理念,将有助于实现更加灵活、智能、高效和开放的5G新型网络。
    
    灯泡.png

    2015年,NFV和容器无疑都是最热门的技术,被很多业内人士认为是未来的发展趋势;2016年,当NFV遇上容器,会碰撞出什么新的火花?当容器化的CT/IT业务在同一平台内融合部署,又会产生怎样新的体验?下面和大家分享一下,从2015年到2016年,我们做的容器化CT-IT融合方面的工作。IT我就不解释了,CT这里主要指的是电信业务。

    容器化CT-IT融合系统是一种面向未来ICT系统的新型云计算PaaS平台,它基于容器这一轻量级的虚拟化技术以及自动化的微服务管理架构,能够有效支撑应用快速上线和自动扩缩容,最大化IT基础设施资源利用率并降低总体TCO。未来的网络正在向IT化、云化方向发展,容器与微服务技术,完美契合“网络即服务”、网络切片等发展理念,将有助于实现更加灵活、智能、高效和开放的5G新型网络。

    下面是从2015年到2016年,我们做的容器化CT-IT融合方面的工作:
    • 2015年,我们首次提出容器化ICT融合方案
    • 2016年初,我们完成容器化ICT融合原型系统
    • 2016年4月8日~4月9日,中国移动召开2016年度技术工作会,容器化ICT融合原型系统首次亮相技术工作会精品展。
    • 2016年6月20日~6月23日,OPNFV Summit在德国柏林召开。在OPNFV PoC战区,中国移动和红帽公司联合展示了容器化ICT融合平台
    • 2016年6月29日,由GSMA主办的2016世界移动大会-上海(Mobile World Congress,简称MWC)在上海新国际博览中心盛大开幕,在中国移动研究院5G展区,我们为参会专家演示了容器化ICT融合原型系统。

    最初产生将网元容器化的想法来源于2015年,我们正在进行NFV IMS测试,同时也正在进行容器和DCOS的相关技术研究和验证性工作,关于应用场景,最适合容器化的应用无疑是所谓的云原生应用,或者说是微服务,其主要特点是分布式、无单点失效、无状态,这和我们测试的某些厂商的IMS网元的特征竟然如此地一致,而容器的轻量级、高性能、快速启动等优势,也恰好是网元所需要的,几分钟部署一套核心网元或许真的会从梦想变成现实。于是,一对新的组合诞生了,NFV Container=NFC。

    理论+实践才能创造出真理,在理论分析的基础上,可行性验证必不可少,而惊喜总是无处不在,尝试创新的道路也不是总那么孤独,开源的IMS项目Clearwater也在做和我们类似的工作。Clearwater是IMS网元的一个开源实现,其主要目标是开发一套适合在云上(如aws)部署的IMS网元,提供语音、视频、消息服务。Clearwater在架构上就以微服务的方式设计各个组件,并且提供了docker格式的容器镜像,我们将它移植到Kubernetes平台上,平台具有负载均衡、容灾恢复、支持资源监控等特点使其更适合服务化

    测试环境

    硬件

    Red Hat 3D打印演示系统,内含3台服务器。
    小红.png

    软件

    • 操作系统:Red Hat Enterprise Linux Server release 7.2 (Maipo)
    • 容器引擎:docker-1.8.2-10.el7.x86_64
    • 容器编排:kubenetesv1.1.0-origin-1107-g4c8e6f4

    架构.png

    Clearwater架构

    Clearwater架构主要分为六大组件,Bono、Ralf、Sprout、Homer、Homestead、Ellis,如下图所示,其中Sprout作为SIP Router,是核心业务处理模块,也是业务量增加时,需要做动态扩容的主要部分。
    clearwater.png

    NFC测试方案

    针对Clearwater中每个组件,定义一个Kubernetes Service,每个服务中包含一个或多个POD,可以通过增加POD个数进行横向扩展。

    Kubernetes中服务列表如下图所示:
    service.png

    Kubernetes中POD列表如下图所示。测试过程中,通过基于SIPP的clearwater组件增加并发用户量,系统压力增加,触发sprout服务中POD个数增加。
    podslist.png

    为实现POD的动态扩展,一方面,利用Kubernetes本身的replication controllers,根据负载增加或减少POD副本数量,另一方面,clearwater sprout是微服务架构,分布式,无状态,数据和应用分离,可通过集群配置,让集群中各个容器共享数据库。

    在并发用户数为300个时,sprout模块POD数量一般为2~3个,在并发用户数增加到2000个时,sprout模块POD数量达到11个,如果继续增加并发用户数到3000个,sprout模块POD数量达到15个左右。

    CT-IT融合测试方案

    在大数据应用中,容器的轻量级、高性能、快速启动等特点同样具有优势,而CT和IT业务融合部署,也是未来发展的一个趋势,在本次测试中,我们在同一个容器平台上,部署了IMS网元和大数据应用。

    在CT应用负载比较低的时候,系统主要用于进行大数据应用计算,大数据应用所占系统CPU资源比例较高。如下图资源监控界面所示。
    监控.png

    当CT业务量增加,系统负载增大,为满足在线CT业务要求,增加CT业务容器数量,同时减少大数据离线业务占用资源。资源使用情况变化如下图所示。
    监控pods.png

    总结

    容器作为轻量级的虚拟化技术,可以降低系统开销,提升系统性能。
    • CT/IT融合部署:CT和IT应用在同一平台内混合部署,共享资源,提高资源利用率。
    • 统一资源调度:打破应用竖井,统一建设,统一运维,降低TCO
    • 系统性能提升:采用容器技术,轻量级的虚拟化,降低系统开销
    • 微服务架构:分布式、无状态的云原生应用,实现应用于数据的分离
    • 弹性伸缩、自动扩容:支持自定义的资源调度策略,实现根据业务量变化的资源动态调度。

    Q&A

    Q:网络转发有没有遇到瓶颈?有没有尝试一些加速技术,比如DPDK?
    A:因为是控制面网元,目前没有遇到瓶颈,没有用DPDK,我们之前测试过虚拟机的,因为网元特点,也是没有配置DPDK,目前的测试上看,性能上没有问题。
    Q:现在数据库也放在容器中吗?
    A:是的,但是也是数据库集群,我们正在做将数据库分离的工作。
    Q:你们实测的容器运行于虚拟机环境,性能如何,你们容器网络如何实现NFV互联?
    A:容器没有基于虚拟机环境,因为是控制面网元,性能没有遇到瓶颈。
    Q:容器不会包打天下,与虚机,物理机并存可能是一段时间内的一种常态,我们有没有分析哪些业务适合容器化,哪些业务不宜改变?并且在利用Kubernetes作为容器的编排调度工具时,如何实现容器与虚机应用的互通?
    A:其实业务不宜改变不仅仅是技术问题,也和业务厂商是否愿意改变有关,毕竟一些遗留的业务已经在现网运行很久了,很难短期内容器化。另外,我们确实碰到了需要内核优化的业务。我们系统中还没有做容器和虚拟机应用互通。
    Q:传统CT网络不仅仅是IMS吧,对于CS、PS,SDN/NFV化,你们有什么思路吗?
    A:IMS使我们容器化的第一个尝试,其他的网元也正在研究中,后续也会做相关的测试,如果有兴趣,也欢迎参加我们后面的测试。
    Q:你们的资源池,有路由器,安全组,负载均衡之类的功能嘛?路由器,负载均衡器可以被分配公网IP吗?
    A:指的是容器的资源池还是我们已有的私有云资源池,已有的私有云资源池是有的,但是容器这个原型系统还没有。
    Q:类似Clearwater的开源项目还有哪些?
    A:NFV方面的吗,如果是IMS,Clearwater业界用的比较多,NFV其他网元开源项目很多。
    Q:你们的虚拟机底层使用什么虚拟化技术支撑?
    A:这次演示,底层用的就是Docker,我们的私有云资源池有VMware、KVM也有Xen。
    以上内容根据2016年8月16日晚微信群分享内容整理。分享人 马轶慧,中国移动通信有限公司研究院私有云项目经理,之前曾任VMware研发中心研发工程师。一直关注并致力于虚拟化、容器、云计算等相关领域。
    展开全文
  •  容器使用沙箱机制,互相隔离,优势在于让各个部署在容器的里的应用互不影响,独立运行,提供更高的安全性。本文主要介绍python应用(django)跑在docker容器里,编写dockerfile实现镜像构建自动以及docker神器...
  • 容器和云原生(一):初识容器化和云原生

    千次阅读 多人点赞 2021-01-29 15:49:45
    目前亟待增加裸金属服务器配置相关知识和云原生相关内容,那就从容器化和云原生下手,本节把基于k8s的容器化知识挂载到自己的知识树上,然后在测试环境进行开发测试; 一、理解容器化 什么是容器 容器是云原生...
  • Docker 容器化技术介绍(一) 之 虚拟化技术 Docker 容器化技术介绍(二) 之 Docker 简介 Docker 容器化技术介绍(三) 之 Docker 组件 Docker 容器化技术介绍(四) 之 Docker的安装与启动 Docker 容器化技术...
  • 容器概念、优势及其发展

    千次阅读 2020-06-08 21:48:29
    容器概念、优势及其发展 毕设内容做的是和容器镜像相关的内容,整理了一下发出来,欢迎批评指正~ 容器概念 容器技术是一种基于操作系统能力的隔离技术,是当下大规模集群中资源共享和隔离的重要解决方案。容器的本质...
  • 这篇文章主要介绍了Docker实践之python应用容器化小编觉得挺不错的现在分享给大家也给大家做个参 考一 跟随小编过来看看吧 一一前前言言 容器使用沙箱机制互相隔离优势在于让各个部署在容器的里的应用互不影响独立...
  • 随着Devops深入人心,现在docker势头强劲,但是mac和windows都不支持docker,相比较而言,虚拟化比较成熟。容器化和虚拟化哪个才是未来的主流?
  • Docker---大型项目容器化改造

    千次阅读 多人点赞 2019-01-17 17:49:59
    容器化相对于虚拟化的优势也相当明显,运行于裸机性能高,秒级启停容器,更不用说开发、测试、布署一致的环境(DevOps理念),以及上篇提到的微服务的能力。大家还可以找到各种文章来介绍容器化(Dock...
  • 外卖客户端容器化架构的演进

    千次阅读 2020-09-30 20:01:48
    总第413篇2020年 第37篇好的架构要不断演变,进而去适应业务的发展。美团在移动端上的架构,也经历了组件化、平台化、RN混合化,到现在开始向容器化变迁。容器化架构充分地利用了现在的跨...
  • 一、为什么要做无状态化和容器化 很多应用拆分成微服务,是为了承载高并发,往往一个进程扛不住这么大的量,因而需要拆分成多组进程,每组进程承载特定的工作,根据并发的压力用多个副本公共承担流量。 将一个进程...
  • 云计算、虚拟化、容器化杂谈

    千次阅读 2017-11-20 18:56:52
    虚拟机技术已经发展了很多年,虚拟机和虚拟层间的接口、虚拟机镜像格式等都已经标准了,相应的管理工具、分布式集群管理工具都有比较完善的解决方案,而容器最近几年才兴起,配套技术和标准还在完善中;...
  • 传统单体架构存在各种各样的问题,如加载编译耗时长、代码管理复杂、横向扩展难、各模块之间的耦合程度高等,与之相比,微服务架构则具一系列优势。1.模块可以独立提供服务,边界清晰、易于维护,可以促成新的开发...
  • 应用容器化 对于微服务架构来说,服务拆分的越多,运维的成本也就越高,以前的一个系统只需要部署一次就可以了,但拆分成多个服务后,就需要多次部署了,为了简化部署流程,容器化成了该问题的最佳解决方案。 制作...
  • ring0-3②操作系统工作在ring0③应用程序使用ring3④驱动程序使用ring1-2(3)虚拟优势①减少服务器数量,降低硬件采购成本②资源利用率最大③降低机房空间、散热、电耗成本④硬件资源可动态调整,提高企业IT...
  • docker容器化下的JVM参数调优

    千次阅读 2020-12-22 17:14:50
    docker容器化下的JVM参数调优. 1、JVM堆内存设置 2、GC日志打印以及OOM自动dump
  • 电信行业的容器化改造之道

    万次阅读 2016-08-19 13:07:14
    容器化优势 容器技术作为目前一项炙手可热的新技术,具有以下优势: 极其轻量级的虚拟化技术,大大提高IT资源的利用率; 标准化的打包、封装、搬运机制,有效提高开发运维效率,降低成本; 秒级启动...
  • 容器相比虚拟机的优势

    千次阅读 2018-05-05 20:17:00
    1、容器的尺寸更小,只关心应用程序,而虚拟机将程序和虚拟机代码一起打包,这样同一台物理机上可以放置更多的容器; 2、容器的启动速度,其实就是启动应用程序的过程, 启动时间是毫秒级;而虚拟机要启动一个虚拟...
  • 马蜂窝容器化平台前端赋能实践

    千次阅读 2019-06-21 15:03:43
    容器对前端开发真的有用吗?答案是肯定的。 最初当我向公司的前端同学「安利」容器技术的时候,很多人都会说:「容器?这不是用在后端的技术吗?我不懂啊,而且前端开发用不上吧。」 但其实,今天我们讨论的「前端...
  • Spring Cloud Kubernetes容器化实践

    千次阅读 2018-11-12 08:50:28
    近年来Docker统一了容器标准,对于软件开发流程产生了深远的影响,Docker可以一次打包,处处运行。过去几年Kubernetes平台发展日新月益,Kubernetes统一了容器编排王者的地位,我个人认为kubernetes可以说是对普通...
  • 容器化与无状态微服务等

    千次阅读 2018-11-09 17:09:03
    写在前面: 本来不想太多转载东西,但这篇文章写的极有章法,把一些核心的东西,来龙去脉表达的很...一、为什么要做无状态化和容器化 很多应用拆分成微服务,是为了承载高并发,往往一个进程扛不住这么大的量,...
  • docker4dotnet #2 容器化主机

    千次阅读 2016-07-20 18:15:16
    #1 前世今生&世界你好》中给大家介绍了如何在Windows上面配置Docker for Windows和Docker Tools for Visual Studio来使用docker协助.NET Core应用的开发,这篇我们来看看如何创建和管理容器化主机。 所谓容器...
  • 在移动互联网时代,企业需要寻找新的软件交付流程和IT架构,从而实现架构平台,交付持续,业务服务容器将成为新一代应用的标准交付件,容器云将帮助企业用户构建研发...容器是一种轻量级的虚拟技术,拥有持
  • 目前,使用docker部署机器学习或深度学习模型正在成为企业大规模部署的一种常规操作。基于目前工作的情况,刚好可以使用现成的模型尝试使用...Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协...
  • 边缘计算容器化是否有必要?

    千次阅读 2019-06-27 10:20:00
    戳蓝字“CSDN云计算”关注我们哦!作者 |Steve来源|边缘计算中文社区简要由于容器有轻量级、安全性、秒级启动等优秀的特性,容器天然的轻量和可移植性,非常适合...
  • 容器管理解决方案可以帮助降低复杂性并获得优势,包括简化和自动的应用程序交付,优化的资源利用率以及业务管理以及应用业务策略和整体数据中心集成。 Admiral是用Java编写的服务,基于VMware的。 该服务使...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 111,624
精华内容 44,649
关键字:

容器化优势