01.23 微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術

作者:劉超原址:https://mp.weixin.qq.com/s/EDPK9i97lK_6Zn_fpnBszw

看來容器編排系統的爭奪已經白熱化了,亂花漸欲迷人眼,最近老是有各種文章比較這三個框架,這篇文章不談信仰,不對比優劣,只談技術,甚至會談如果從一個平臺轉向另一個平臺,都要了解些啥。

一、架構

啥都不說,先上三個架構圖

Docker Swarm Mode

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


DCOS

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


這張圖主要顯示了一些組件,還是上一張Mesos的圖

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


最後是Kubernetes

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


這三個架構都很複雜,但是還是能夠一眼看出是一個老大,多個幹活的這種結構,基本上所有的分佈式系統都是這樣,但是裡面的組件名稱就紛繁複雜,我們來一一解析。

二、元數據存儲與集群維護

作為一個集群系統,總要有一個統一的地方維護整個集群以及任務的元數據。而且作為集群系統的控制節點,為了高可用性,往往存在多個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運行容器

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


DCOS對於多種容器的支持Unified Container,可以支持Docker容器和Mesos容器。

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


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

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


九、網絡

容器的網絡配置兩種:

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作為調度器的方案。

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


對於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來實現。

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


在kubernetes中,外部負載均衡器是通過一個ingress controller根據請求進行創建,如果在雲平臺例如GCE,可創建雲平臺的負載均衡器,雲平臺的負載均衡器可通過NodePort連接到後端的Service。

https://github.com/kubernetes/ingress

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


可以通過service連接後端的Pod.

微服務:關於Docker, Kubernetes, DCOS 仨框架平臺,只談技術


也可以不用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


分享到:


相關文章: