以下内容已屏蔽图片优化访问速度 |
---|
看来容器编排系统的争夺已经白热化了,乱花渐欲迷人眼,最近老是有各种文章比较这三个框架,这篇文章不谈信仰,不对比优劣,只谈技术,甚至会谈如果从一个平台转向另一个平台,都要了解些啥。 一、架构 啥都不说,先上三个架构图 Docker Swarm Mode [IMG] DCOS [IMG] 这张图主要显示了一些组件,还是上一张Mesos的图 [IMG] 最后是Kubernetes [IMG] 这三个架构都很复杂,但是还是能够一眼看出是一个老大,多个干活的这种结构,基本上所有的分布式系统都是这样,但是里面的组件名称就纷繁复杂,我们来一一解析。 二、元数据存储与集群维护 作为一个集群系统,总要有一个统一的地方维护整个集群以及任务的元数据。而且作为集群系统的控制节点,为了高可用性,往往存在多个Master,在多个Master中间,总要有一个Leader。 在Docker Swarm Mode里面,多个Manager之间需要选出一个Leader,而且整个集群的状态也需要在一个统一的地方存储,从而任何一个Manager挂了之后,其他的Manager能够马上接替上,Swarm Node通过Raft协议,自己实现了一个内部的统一存储和集群一致性管理系统。在传统的Swarm里面,推荐的使用consul,在Swarm Mode里面则自己实现了。 在docker swarm init的参数里面有--advertise-addr声明swarm manager会通过这个地址和端口让其他组件来连接。 在DCOS里面,Mesos的多个进程也需要选择一个Leader,容器的编排多通过Marathon进行,Marathon需要一个地方存储所有Task的信息,在DCOS里面,多通过Zookeeper来实现。 在Mesos Master的启动有参数--zk=VALUE。 当然也能看到熟悉的--advertise_ip=VALUE和--advertise_port=VALUE。 Marathon启动的时候,也有参数--zk zk://1.2.3.4:2181,2.3.4.5:2181,3.4.5.6:2181/marathon。 在Kubernetes里面,统一的存储使用etcd来保存,Leader的选举也是通过etcd进行,因而有apiserver有参数--etcd-servers,controller和scheduler都有参数--master string指向apiserver,并且有参数--leader-elect选举出Leader,也会有熟悉的--address ip。 三、API层与命令行 作为一个分布式系统,每一层都会有自己的API,但是对外往往需要一个统一的API接口层,一般除了酷酷的界面之外,为了自动化,往往会有一个命令行可以执行操作,其实命令里面封装的也是对API的调用。 对于Docker Swarm Mode来讲,API层是集成在Manager里面的,而命令行其实就是Docker的命令行,只不过调用的时候,原来是Docker Daemon本地把事情做了,现在Manager需要让Work去做事情。 这一点也是Docker的优势所在,也即使用本地的Docker和使用Swarm Mode集群,不需要学习成本,一样的命令,同样的味道。 对于DCOS来讲,API层是有一个单独的组件,叫做Admin Router,后端的很多API都是通过Admin Router经过封装暴露给外面的。 对于命令行,有一个dcos cli,可以调用admin router暴露出来的api进行操作。 dcos命令行可以有一些子命令,例如marathon子命令,就是用来创建容器的,node可以管理节点。 dcos里面很有特色的一点就是可以安装package,这源于mesos是一个双层调度系统,上面可以跑多个framework,例如spark,cassandra等,都可以通过package进行安装,这点会另外一节说明。 对于Kubernetes,API层是一个单独的进程apiserver提供,认证和鉴权也是在这一层实现的,所有对于kubernetes的管理平台的访问都是通过apiserver这一层进行的。 对于命令行,kubernetes是kubectl,通过向apiserver调用执行操作,例如pod,service,deployment等。 kubernetes也有自己的类似package的管理,Kubernetes Helm,但是命令就变成了helm了。 四、调度 当运行一个容器的时候,放在哪台节点上,这个过程是调度。 Swarm Mode 的调度的默认规则是spread,也即尽量让容器平均分配到整个集群当中。 当然也可以设置一些调度策略,例如使用constraint,每个节点可以配置一些label,并在创建容器的时候通过指定constraint,来使得容器运行或者不运行在某些节点上。 docker node update --label-add 'com.acme.server=db' node-03 docker service create --name redis --constraint 'node.labels.com.acme.server==db' redis 也可以使用placement-pref,使得容器优先调度在某些节点上。 docker service create --name nginx --placement-pref 'spread=node.labels.com.acme.zone' --replicas 12 nginx 对于DCOS来讲,Mesos的调度是双层调度,首先一层是Mesos Master的Allocator将节点资源提供给框架,例如Marathon,第二层是Marathon里面也有一个调度器,真正分配某个容器放在某个节点上。 Mesos的调度策略参考文章号称了解mesos双层调度的你,先来回答下面这五个问题! Marathon的调度也可以有constraints。 "constraints": [["hostname", "UNIQUE"]]表示每个节点只能跑一个。 "constraints": [["rack_id", "CLUSTER", "rack-1"]]容器跑着有attribute为rack_id并且值为rack-1的节点上。 "constraints": [["rack_id", "GROUP_BY", "3"]]将容器分布在三个rack上以实现高可用。 "constraints": [["rack_id", "LIKE", "rack-[1-3]"]]和"constraints": [["rack_id", "UNLIKE", "rack-[7-9]"]]表示容器要跑在哪些节点上和不能跑在哪些节点上。 "constraints": [["rack_id", "MAX_PER", "2"]]表示每个rack最多能跑两个容器。 对于Kubernetes,调度是由一个单独的进程scheduler负责的。 Kubernetes也支持通过对Node设置Label,从而将pod放在某些节点上。 kubectl label nodes apiVersion: v1kind: Podmetadata: name: nginx labels: env: testspec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd 另外kubernetes还有NodeAffinity: RequiredDuringSchedulingRequiredDuringExecution:在调度的时候必须部署到某些节点,运行期如果条件不满足则重新调度 RequiredDuringSchedulingIgnoredDuringExecution :在调度的时候必须部署到某些节点,运行期就算了。 PreferredDuringSchedulingIgnoredDuringExecution :在调度的时候最好部署到某些节点,运行期就算了。 五、副本与弹性伸缩 容器如果部署无状态服务,一个好处就是可以多副本,并且可以弹性伸缩。 在Swarm Mode里面,可以通过scale数字指定副本数目。 docker service scale frontend=50 在DCOS里面,通过instances指定副本的数目。 { "id": "nginx", "container": { "type": "DOCKER", "docker": { "image": "mesosphere/simple-docker", "network": "BRIDGE", "portMappings": [ { "hostPort": 80, "containerPort": 80, "protocol": "tcp"} ] } }, "acceptedResourceRoles": ["slave_public"], "instances": 1, "cpus": 0.1, "mem": 64 } 修改数目的时候使用以下的命令 dcos marathon app update basic-0 instances=6 在最新版本的DCOS中,已经支持的pod的概念了。 { "containers": [ { "artifacts": [], "endpoints": [], "environment": {}, "exec": { "command": { "shell": "sleep 1000" } }, "healthCheck": null, "image": null, "labels": {}, "lifecycle": null, "name": "sleep1", "resources": { "cpus": 0.1, "disk": 0, "gpus": 0, "mem": 32 }, "user": null, "volumeMounts": [] } ], "environment": {}, "id": "/simplepod2", "labels": {}, "networks": [ { "labels": {}, "mode": "host", "name": null } ], "scaling": { "instances": 2, "kind": "fixed", "maxInstances": null }, "scheduling": { "backoff": { "backoff": 1, "backoffFactor": 1.15, "maxLaunchDelay": 3600 }, "placement": { "acceptedResourceRoles": [], "constraints": [] }, "upgrade": { "maximumOverCapacity": 1, "minimumHealthCapacity": 1 } }, "secrets": {}, "user": null, "volumes": [] } 在DCOS里面可以实现自动弹性伸缩,通过使用marathon-lb-autoscale,通过监控marathon-lb的情况进行弹性伸缩。 在Kubernetes里面,副本数目是以pod为单位的,由controller进程控制,可以通过创建一个Deployment来控制副本数。 apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 Kubernetes也可以实现autoscaling。 有一个组件Horizontal Pod Autoscaling,可以通过监控CPU的使用情况动态调整Pod的数量。 六、编排 为了能够通过编排文件一键创建整个应用,需要有编排功能。 Swarm Mode的编排 docker stack deploy --compose-file docker-compose.yml vossibility version: "2" services: foo: image: foo volumes_from: ["bar"] network_mode: "service:baz" environment: - "constraint:node==node-1" bar: image: bar environment: - "constraint:node==node-1" baz: image: baz environment: - "constraint:node==node-1" Marathon的编排是基于json文件 { "id": "/product", "groups": [ { "id": "/product/database", "apps": [ { "id": "/product/database/mongo", ... }, { "id": "/product/database/mysql", ... } ] },{ "id": "/product/service", "dependencies": ["/product/database"], "apps": [ { "id": "/product/service/rails-app", ... }, { "id": "/product/service/play-app", ... } ] } ] } Kubernetes的编排是基于yml文件 为redis-master服务新建一个名为redis-master-controller.yaml的RC定义文件 apiVersion: v1 kind: ReplicationController metadata: name: redis-master labels: name: redis-master spec: replicas: 1 selector: name: redis-master template: metadata: labels: name: redis-master spec: containers: - name: master image: kubeguide/redis-master ports: - containerPort: 6379 创建一个Service apiVersion: v1 kind: Service metadata: name: redis-master labels: name: redis-master spec: ports: - port: 6379 targetPort: 6379 selector: name: redis-master 七、服务发现与DNS 容器平台的一个重要的功能是服务发现,也即当容器的地址改变的时候,可以自动进行服务之间的关联。 一般的服务发现首先要通过DNS将服务名和应用关联起来,可以基于DNS对一个服务的多个应用进行内部负载均衡,也有直接加一个内部负载均衡器来做这件事情。 Swarm Mode有一个内置的DNS组件,并且负载均衡也是根据DNS名来做的。 DCOS的DNS组件是通过Mesos-DNS实现的,负载均衡有两种方式,一种是直接通过Mesos-DNS根据域名进行负载均衡。另一种方式是将DNS转化为VIP,然后有个内置的负载均衡器,DCOS有个组件minuteman是做这个事情的。 Kubernetes的DNS组件是通过skyDNS实现的,负载均衡是通过将DNS转化为VIP,有个内置的负载均衡器kube-proxy来完成这件事情。 八、容器 Swarm Mode通过runC运行容器 [IMG] DCOS对于多种容器的支持Unified Container,可以支持Docker容器和Mesos容器。 [IMG] Kubernetes也是支持多种容器格式的。 [IMG] [IMG] 九、网络 容器的网络配置两种: Docker Libnetwork Container Network Model(CNM)阵营 ● Docker Swarm overlay ● Macvlan & IP network drivers ● Calico ● Contiv(from Cisco) Docker Libnetwork的优势就是原生,而且和Docker容器生命周期结合紧密;缺点也可以理解为是原生,被Docker“绑架”。 Container Network Interface(CNI)阵营 ● Kubernetes ● Weave ● Macvlan ● Flannel ● Calico ● Contiv ● Mesos CNI CNI的优势是兼容其他容器技术(e.g. rkt)及上层编排系统(Kuberneres & Mesos),而且社区活跃势头迅猛,缺点是非Docker原生。 十、存储 Swarm Mode的存储是通过Volume Plugin,可以在集群中接入外部的统一存储,可以支持Ceph,NFS,GlusterFS等。 DCOS可以创建External Persistent Volumes,dvdi driver其实使用的也是Docker的volume driver,目前支持的是rexray,可以接入EC2,OpenStack等。 Kubernetes可以创建Persistent Volumes,支持GCE,AWS,NFS,GlusterFS,Ceph等。 十一、监控 无论是Swarm Mode,还是Mesos,还是Kubernetes,容器的监控中Prometheus +cadvisor都是主流的方案,而cadvisor来自Kubernetes的一个组件。 十二、大数据与包管理 跑大数据是Mesos的强项,Spark就有一个依赖于Mesos部署,让Mesos作为调度器的方案。 [IMG] 对于Swarm Mode和Kubernetes来讲,不会用自己的Scheduler来做大数据调用。 但是Swarm Mode和Kubernetes是可以部署大数据框架的,但是大数据框架之间的任务的调度和通信,就与Swarm Mode和Kubernetes无关了。 在kubernetes里面部署大数据可以参考[IMG]Mode中,swarm manager通过ingress负载均衡,通过published port将服务端口暴露在Node上面,如果有外部云平台的负载均衡器,通过连接Node上的端口,可以对服务进行外部负载均衡。 在DCOS中,外部负载均衡通过marathon-lb来实现。 [IMG] 在kubernetes中,外部负载均衡器是通过一个ingress controller根据请求进行创建,如果在云平台例如GCE,可创建云平台的负载均衡器,云平台的负载均衡器可通过NodePort连接到后端的Service。 [IMG]Mode的Node上面部署的是Swarm的worker,其实还是Docker Daemon,相对保持一致性。 DCOS的Node上面干活的是Mesos-Agent,其实它还不是直接干活的,还有一层Executor真正的干活。 kubernetes的Node上跑的是kubelet。 十五、升级与回滚 所有的容器平台对于容器多副本的升级全部都是要滚动升级。 在Swarm Node里面可以配置rolling update策略 docker service create --name=my_redis \ --replicas=5 \ --rollback-parallelism=2 \ --rollback-monitor=20s \ --rollback-max-failure-ratio=.2 \ redis:latest 在DCOS里面,rolling update也是默认的行为。 在Kubernetes里面,同样有对rolling update的支持。 kubectl rolling-update foo [foo-v2] --image=myimage:v2 总而言之:三大平台的区别,大概相当于麦当劳和肯德基的区别,看你的口味,掌控能力,社区热度了。 |