看來容器編排系統的爭奪已經白熱化了,亂花漸欲迷人眼,最近老是有各種文章比較這三個框架,這篇文章不談信仰,不對比優劣,只談技術,甚至會談如果從一個平臺轉向另一個平臺,都要了解些啥。
一、架構
啥都不說,先上三個架構圖
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 /<your-node-name>
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
總而言之:三大平臺的區別,大概相當於麥當勞和肯德基的區別,看你的口味,掌控能力,社區熱度了。
原址:https://mp.weixin.qq.com/s/EDPK9i97lK_6Zn_fpnBszw