【3.工程开发】-docker/k8s/云

https://segmentfault.com/a/11... 容器,隔离,云的概述。这篇对其中用途普遍的docker,k8s作详细介绍,并给出云搭建的生态环境体系。mysql

docker

1.与其余VM等对比

容器发展,详见上面提到的文章linux

chroot 1979
Linux Vserver 2001
process container 2006
LXC 2008
Docker 2013
windows container 2017

典型图:VM与container对比,差别在于OSgit

clipboard.png

VM container
隔离 OS kernel namespace
可配额,可度量 硬件页映射 cgroups
移动性 snapshot,image AUFS
安全 gresc patch

缺点github

隔离性相比KVM之类的虚拟化方案仍是有些欠缺,全部container公用一部分的运行库
网络管理相对简单,主要是基于namespace隔离
cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(因此dotcloud主要是安内存收费)
docker对disk的管理比较有限(disk quota)
container随着用户进程的中止而销毁,container中的log等用户数据不便收集

优势:sql

轻量级的特色,其启动快,并且docker可以只加载每一个container变化的部分,这样资源占用小
docker不仅是容器,高级容器引擎,应用部署平台,应用镜像商店

2.docker生态圈————不仅是容器

clipboard.png

  • Image 一个包含运行环境的只读 模板
  • Container 镜像的运行态,docker利 用容器运行应用
  • Registry 存储容器镜像的仓库
  • Dockerfile 包含构建镜像一系列命令 和参数的脚本

3.执行过程

clipboard.png

  • Docker Daemon 能够认为是经过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,而后根据请求类型,建立出指定的 Job 并运行。 Docker Daemon 运行在 Docker host 上,负责建立、运行、监控容器,构建、存储镜像。
  • job运行过程的做用有如下几种可能:
    向 Docker Registry 获取镜像
    经过 graphdriver 执行容器镜像的本地化操做
    启动容器
  • graph
    Graph在Docker架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。
    一方面,Graph存储着本地具备版本信息的文件系统镜像,另外一方面也经过GraphDB记录着全部文件系统镜像彼此之间的关系。
    GraphDB是一个构建在SQLite之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,可是提供了简单的接口表示节点之间的关系。
    Graph的本地目录中,关于每个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所表明的具体rootfs。
  • networkdriver 执行容器网络环境的配置
    networkdriver的用途是完成Docker容器网络环境的配置,其中包括Docker启动时为Docker环境建立网桥;Docker容器建立时为其建立专属虚拟网卡设备;以及为Docker容器分配IP、端口并与宿主机作端口映射,设置容器防火墙策略等。
  • execdriver 执行容器内部运行的执行工做
    execdriver做为Docker容器的执行驱动,负责建立容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在execdriver的实现过程当中,原先可使用LXC驱动调用LXC的接口,来操纵容器的配置以及生命周期,而如今execdriver默认使用native驱动,不依赖于LXC。具体体如今Daemon启动过程当中加载的ExecDriverflag参数,该参数在配置文件已经被设为"native"。这能够认为是Docker在1.2版本上一个很大的改变,或者说Docker实现跨平台的一个先兆
  • libcontainer
    Docker架构中一个使用Go语言设计实现的库,设计初衷是但愿该库能够不依靠任何依赖,直接访问内核中与容器相关的API。
    正是因为libcontainer的存在,Docker能够直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操做的完成都不须要依赖LXC或者其余包。
    libcontainer提供了一整套标准的接口来知足上层对容器管理的需求。docker

    docker run过程
    (1) Docker Client接受docker run命令,解析完请求以及收集完请求参数以后,发送一个HTTP请求给Docker Server,HTTP请求方法为POST,请求URL为/containers/create? +xxx;
    (2) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router经过URL以及请求方法来肯定执行该请求的具体handler;
    (3) mux.Router将请求路由分发至相应的handler,具体为PostContainersCreate;
    (4) 在PostImageCreate这个handler之中,一个名为"create"的job被建立,并开始让该job运行;
    (5) 名为"create"的job在运行过程当中,执行Container.Create操做,该操做须要获取容器镜像来为Docker容器建立rootfs,即调用graphdriver;
    (6) graphdriver从Graph中获取建立Docker容器rootfs所须要的全部的镜像;
    (7) graphdriver将rootfs全部镜像,加载安装至Docker容器指定的文件目录下;
    (8) 若以上操做所有正常执行,没有返回错误或异常,则Docker Client收到Docker Server返回状态以后,发起第二次HTTP请求。请求方法为"POST",请求URL为"/containers/"+container_ID+"/start";
    (9) Docker Server接受以上HTTP请求,并交给mux.Router,mux.Router经过URL以及请求方法来肯定执行该请求的具体handler;
    (10) mux.Router将请求路由分发至相应的handler,具体为PostContainersStart;
    (11) 在PostContainersStart这个handler之中,名为"start"的job被建立,并开始执行;
    (12) 名为"start"的job执行完初步的配置工做后,开始配置与建立网络环境,调用networkdriver;
    (13) networkdriver须要为指定的Docker容器建立网络接口设备,并为其分配IP,port,以及设置防火墙规则,相应的操做转交至libcontainer中的netlink包来完成;
    (14) netlink完成Docker容器的网络环境配置与建立;
    (15) 返回至名为"start"的job,执行完一些辅助性操做后,job开始执行用户指令,调用execdriver;
    (16) execdriver被调用,初始化Docker容器内部的运行环境,如命名空间,资源控制与隔离,以及用户命令的执行,相应的操做转交至libcontainer来完成;
    (17) libcontainer被调用,完成Docker容器内部的运行环境初始化,并最终执行用户要求启动的命令。

4.docker技术

clipboard.png

隔离 命名空间

一、进程命名空间:每一个命名空间独立维护本身的进程号,父子关系结构,子空间的进程对父空间是可见的,新fork出的进程 在父命名空间和子命名空间都会生成一个进程号
 二、网络命名空间:实现网络隔离 彻底独立的网络协议视图,包括网络设备接口、IPV4 IPV6协议栈,路由表,防火墙规则,sockers等,采用虚拟网络设备,将容器中的虚拟网卡绑定在本地主机的docker0的网桥上
 三、ipc命名空间 进程间交互,信号量、消息队列,和共享内存,同一个IPC空间的能够交互,不一样的不能够
 四、挂载命名空间 相似chroot, 将一个进程放到一个特定的目录执行。容许不一样命名空间的进程看到的文件结构不一样,文件目录被隔离 chroot(PATH)这个function必须具备 root的身份才能执行,执行后会将根目录切换到PATH 所指定的地方。
五、 UTS命名空间 UNIX Time-sharing System 容许每一个容器拥有独立的主机名和域名,默认主机名为容器ID
 六、用户命名空间 每一个容器能够有不一样的用户和组id,能够在容器内使用特定的内部用户执行程序。每一个容器都有root帐号数据库

可配额,可度量

1.cpu,io,mem等等:cgroups
2.网卡
docker建立容器的过程:
     一、建立一对虚拟接口 veth pair ,分别放在本地主机和新容器的命名空间中
     二、本地主机一端的虚拟接口 链接到默认的docker0网桥上,或指定网桥,并具备一个veth开头的惟一名字
     三、容器一端的虚拟接口,放到新的容器中,修更名字为eth0,只在容器中可见
     四、从网桥可用地址中 分配一个空闲的给 eth0,(172.17.0.2/16) 并设置默认路由网卡为 docker0的ip (172.17.42.1/16)
clipboard.png
Veth pair 是一对虚拟网卡,从一张veth网卡发出的数据包能够直接到达它的peer veth,二者之间存在着虚拟链路。不一样网络命名空间之间交互
Veth 网卡和常规的以太网区别仅在于xmit接口:将数据发送到其peer,触发peer的Rx 过程。
3.disk/network quota
虽然cgroup提供IOPS之类的限制机制,可是从限制用户能使用的磁盘大小和网络带宽上仍是很是有限的。
Disk/network的quota如今有两种思路:
1).经过docker run -v命令将外部存储mount到container的目录下,quota从Host方向限制,在device mapper driver中更采用实际的device所以更好控制。
2).经过使用disk quota来限制AUFS的可操做文件大小。维护一个UID池,每次建立container都从中取一个user name, 在container里和Host上用这个username建立用户,在Host上用set quota限制该username的UID的disk. 网络上因为docker采用veth的方式,能够采用tc来控制host上的veth的设备。segmentfault

移植 portable

REDHAT实现AFUS的driver(RHEL DEVIDE MAPPER)windows

  • 功能 采用AUFS做为docker的container的文件系统,可以提供以下好处:
    1)节省存储空间 - 多个container能够共享base image存储
    2)快速部署 - 若是要部署多个container,base image能够避免屡次拷贝
    3)内存更省 - 由于多个container共享base image, 以及OS的disk缓存机制,多个container中的进程命中缓存内容的概率大大增长
    4)升级更方便 - 相比于 copy-on-write 类型的FS,base-image也是能够挂载为可writeable的,能够经过更新base image而一次性更新其之上的container
    5)容许在不更改base-image的同时修改其目录中的文件 - 全部写操做都发生在最上层的writeable层中,这样能够大大增长base image能共享的文件内容。
    以上5条 1-3 条能够经过 copy-on-write 的FS实现, 4能够利用其余的union mount方式实现, 5只有AUFS实现的很好。这也是为何Docker一开始就创建在AUFS之上。
  • AUFS工做过程:
    1.启动:bootfs+rootfs
    bootfs (boot file system) 主要包含 bootloader 和 kernel, bootloader主要是引导加载kernel, 当boot成功后 kernel 被加载到内存中后 bootfs就被umount了。
    rootfs (root file system) 包含的就是典型 Linux 系统中的 /dev, /proc,/bin, /etc 等标准目录和文件。
    2.典型的Linux在启动后,首先将 rootfs 设置为 readonly, 进行一系列检查, 而后将其切换为 "readwrite" 供用户使用。在Docker中,初始化时也是将 rootfs 以readonly方式加载并检查,然而接下来利用 union mount 的方式将一个 readwrite 文件系统挂载在 readonly 的rootfs之上,而且容许再次将下层的 FS(file system) 设定为readonly 而且向上叠加, 这样一组readonly和一个writeable的结构构成一个container的运行时态, 每个FS被称做一个FS层。
    3.得益于AUFS的特性, 每个对readonly层文件/目录的修改都只会存在于上层的writeable层中。这样因为不存在竞争, 多个container能够共享readonly的layer。 因此docker将readonly的层称做 "image" - 对于container而言整个rootfs都是read-write的,但事实上全部的修改都写入最上层的writeable层中, image不保存用户状态,能够用于模板、重建和复制。

5.部署平台

用户每次向Git服务器的push提交都会通知给Jenkins(基于Java开发的一种持续集成工具),Jenkins触发build。Maven(是一个采用Java编写的开源项目管理工具,咱们最经常使用的就是该工具的构建功能)构建全部的相关代码,包括Docker镜像。
Maven会把完成的镜像推送到私有的Registry保存
最后Jenkins会触发Docker Registry pull下载镜像到宿主机本地,并自动启动应用容器。后端

k8s

k8s是一个容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用 Kubernetes 能方便地管理跨机器运行容器化的应用。其架构图以下:
clipboard.png

  • Labels 是用于区分 Pod、Service、Replication Controller 的 key/value 键值对
  • master 包含Replication Controller,API Server
  • Replication Controller:
    会确保 Kubernetes 集群中指定的 pod 副本 (replicas) 在运行, 即便在节点出错时。经过修改 Replication Controller 的副本 (replicas) 数量来水平扩展或者缩小运行的pods,一个一个地替换pods来 rolling updates 服务,labels维度的Multiple release tracks
  • API Server 的主要声明,包括 Pod Registry、Controller Registry、Service Registry、Endpoint Registry、Minion Registry、Binding Registry、RESTStorage 以及 Client

    clipboard.png

    Minion Registry 负责跟踪 Kubernetes 集群中有多少 Minion(Host):能够对 Minion Registry Create、Get、List、Delete
    Pod Registry 负责跟踪 Kubernetes 集群中有多少 Pod 在运行,以及这些 Pod 跟 Minion 是如何的映射关系,对 Pod 进行 Create、Get、List、Update、Delete 操做。
    ……
    Endpoints Registry 负责收集 Service 的 endpoint,好比 Name:"mysql",Endpoints: ["10.10.1.1:1909","10.10.2.2:8834"],Create、Get、List、Update、Delete 以及 watch
    Binding Registry 绑定的 Pod 被绑定到一个 host
    Scheduler 收集和分析当前 Kubernetes 集群中全部 Minion 节点的资源 (内存、CPU) 负载状况,而后依此分发新建的 Pod 到 Kubernetes 集群中可用的节点

  • Kubelet
    是 Kubernetes 集群中每一个 Minion 和 Master API Server 的链接点,Kubelet 运行在每一个 Minion 上,是 Master API Server 和 Minion 之间的桥梁,接收 Master API Server 分配给它的 commands 和 work,与持久性键值存储 etcd、file、server 和 http 进行交互,读取配置信息。Kubelet 的主要工做是管理 Pod 和容器的生命周期,其包括 Docker Client、Root Directory、Pod Workers、Etcd Client、Cadvisor Client 以及 Health Checker 组件
  • Proxy
    是为了解决外部网络可以访问跨机器集群中容器提供的应用服务而设计的,从上图 3-3 可知 Proxy 服务也运行在每一个 Minion 上。Proxy 提供 TCP/UDP sockets 的 proxy,每建立一种 Service,Proxy 主要从 etcd 获取 Services 和 Endpoints 的配置信息,或者也能够从 file 获取,而后根据配置信息在 Minion 上启动一个 Proxy 的进程并监听相应的服务端口,当外部请求发生时,Proxy 会根据 Load Balancer 将请求分发到后端正确的容器处理。

交互:
clipboard.png
http://tiewei.github.io/cloud...

公司云架构图:
clipboard.png

容器

  • 静态容器
    固定可访问IP,不能动态漂移,容器中无代码,扩容较快,轻量虚拟机,支持共享卷/块设备,日志收集与物理机同样。
  • 有状态容器
    k8s的statefulstes模型,能够较好弹性伸缩,能够动态漂移,有代码,扩容很快,支持共享卷/块设备(带云盘),固定ip。适用于对程序数据有持久化需求的服务。
  • 无状态容器
    k8s的deployment模型,开箱即用,能够动态漂移,急速扩容,弹性伸缩极好,只支持共享卷(ceph这种网络分布式磁盘),日志远程收集,容器名和ip不固定,适用于无状态微服务。只支持云平台变动(直接的上线系统不行),不挂载云盘

数据

小的放ceph,大的物理机映射=>网络抖动全换成本地磁盘(不管日志仍是数据,数据须要单独迁移,两种方案均可以)

网络

docker的虚拟网络不少种实现,原生或者插件,通常原生的overlay用的较多
sdn overlay网络 稳定性差(ip不受限制,所以漂移也不受限制) =》物理网络(ip受限于tor[交换机]的网络分配,ip只能tor切换,扩容后资源不均衡)
流量到LB后,若采起sdn,会到sdn中心节点,虚拟ip和物理ip的映射,找到物理ip的宿主机器,宿主机器经过overlay与docker通讯
若物理网络,直接到docker,docker的ip就是分配的物理ip。漂移受tor的影响指的是在ip不变的状况下漂移。ip变化会致使日志等问题

  • 物理网络
    容器ip2直接到物理机(ip1,ip2=》mac1。物理机再转发给ip
  • docker虚拟网络原理
    1.同host:bridge的ip模式为例
    建立虚拟网卡。同一网卡之间均可以互相通讯
    不一样网卡之间即便配了ip路由也会隔离,用的iptable的drop
    与外网:先默认连docker0,若是网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理(iptable NAT)。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即作了一次网络地址转换(NAT)
    外网反向:ip:port(不一样虚拟ip绑定不一样端口),docker-proxy监听全部port,换ip1发给docker0,与ip1通讯

    clipboard.png
    2.跨主机overlay
    Docerk overlay 网络须要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件,咱们这里使用 Consul。
    不一样host:基于VxLAN。VxLAN 可将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,可是拥有更强的扩展性和灵活性。
    clipboard.png
    外网:为每一个建立了eth1能够链接外网。其过程和bridge的docker0访问外网同样
    host内部 br0仍是直接endpoint链接着,另外加了一个vxlan设备,与其余host链接

  • VXLAN原理
    vxlan在二层包上封装vxlan header放在UDP中发到VTEP设备上解封(header中包含24位的ID,同一ID的能够互相通讯)
    clipboard.pngLinux vxlan 建立一个 UDP Socket,默认在 8472 端口监听。接收到 vxlan 包后,解包,而后根据其中的 vxlan ID 将它转给某个 vxlan interface,而后再经过它所链接的 linux bridge 转给虚机。Linux vxlan 在收到虚机发来的数据包后,将其封装为多播 UDP 包,从网卡发出。
相关文章
相关标签/搜索