Docker, Kubernetes, DCOS 不谈信仰谈技术

勿忘初心2018-11-08 13:07

此文已由作者刘超授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验


看来容器编排系统的争夺已经白热化了,乱花渐欲迷人眼,最近老是有各种文章比较这三个框架,这篇文章不谈信仰,不对比优劣,只谈技术,甚至会谈如果从一个平台转向另一个平台,都要了解些啥。


一、架构


啥都不说,先上三个架构图


Docker Swarm Mode



DCOS

这张图主要显示了一些组件,还是上一张Mesos的图


最后是Kubernetes


这三个架构都很复杂,但是还是能够一眼看出是一个老大,多个干活的这种结构,基本上所有的分布式系统都是这样,但是里面的组件名称就纷繁复杂,我们来一一解析。


二、元数据存储与集群维护


作为一个集群系统,总要有一个统一的地方维护整个集群以及任务的元数据。而且作为集群系统的控制节点,为了高可用性,往往存在多个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 <your-node-name> disktype=ssd 

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运行容器



DCOS对于多种容器的支持Unified Container,可以支持Docker容器和Mesos容器。



Kubernetes也是支持多种容器格式的。




九、网络


容器的网络配置两种:


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作为调度器的方案。



对于Swarm Mode和Kubernetes来讲,不会用自己的Scheduler来做大数据调用。


但是Swarm Mode和Kubernetes是可以部署大数据框架的,但是大数据框架之间的任务的调度和通信,就与Swarm Mode和Kubernetes无关了。


在kubernetes里面部署大数据可以参考https://github.com/kubernetes/examples


十三、负载均衡


这里的负载均衡指的是外部负载均衡。


在Swarm Mode中,swarm manager通过ingress负载均衡,通过published port将服务端口暴露在Node上面,如果有外部云平台的负载均衡器,通过连接Node上的端口,可以对服务进行外部负载均衡。


在DCOS中,外部负载均衡通过marathon-lb来实现。

在kubernetes中,外部负载均衡器是通过一个ingress controller根据请求进行创建,如果在云平台例如GCE,可创建云平台的负载均衡器,云平台的负载均衡器可通过NodePort连接到后端的Service。


https://github.com/kubernetes/ingress


可以通过service连接后端的Pod.


也可以不用service直接连接。


十四、节点


Swarm 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


总而言之:三大平台的区别,大概相当于麦当劳和肯德基的区别,看你的口味,掌控能力,社区热度了。


容器服务是网易云提供的无服务器容器服务,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。点击可免费试用


免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击