Ports
marathon中應用的端口配置可能被混淆,並有一個懸而未決的問題,需要重新設計 ports API。這個頁面試圖更清楚地解釋它們是如何工作的。
定義
containerPort:在容器內部,是一個容器端口。在使用docker容器的時候,當我們使用BRIDGE網絡模式,這是端口映射的一部分,必須設置。
hostPort:主機上的端口。當使用BRIDGE網絡模式的時候,你需要指定從主機端口到容器的端口的映射。在HOST網絡模式中,默認請求端口是主機端口。
BRIDGE networking:BRIDGE模式的網絡使用在docker應用中。在這模式中,容器端口(容器內部的端口)會被映射到主機的端口上,應用在容器內部綁定一個指定端口,docker網絡在主機上綁定一個指定端口。
HOST networking:HOST網絡使用在非docker的marathon應用和docker應用上。在這種模式下,應用直接綁定一個或多個端口在主機上。
portMapping:對docker應用來說端口映射是必須的,docker應用需要使用BRIDGE網絡模式,它包含一組host port、container port、service port和protocol。多個端口映射可能會被一個marathon應用指定。
ports:ports數組用來定義端口。它必須定義成數組,如果你使用的是HOST網絡模式,並且沒有指定端口映射。ports和portDefinitions可以同時定義。
portDefinitions:portDefinition數組用來定義端口。它必須定義成數組,如果你使用的是HOST網絡模式,並且沒有指定端口映射。portDefinition這個數組可以替代ports數組,它可以指定端口名稱、協議和標籤。ports和portDefinitions可以同時定義。
protocol:指定端口的協議(如tcp、udp、或者是tcp和udp)。在docker容器中使用BRIDGE網絡模式時,端口映射是必須的。
requirePorts: requirePorts是一個屬性,指定marathon是否需要指定端口。這樣可以確保在mesos代理上綁定端口。這個屬性不支持BRIDGE網絡模式。
servicePort:服務端口是一個端口用於描述服務應該可用的端口。marathon不綁定到指定的服務端口,但確保你不能有多個應用程序使用相同的服務端口相同的主機上運行。服務端口通常只使用外部應用程序(例如HAProxy)使應用程序可以在指定的端口。更多請參考服務發現和負載均衡
隨機端口分配
設置端口是使用0這個值,marathon會爲應用分配隨機端口。但是如果在端口映射portMapping中containerPort設置成0,containerPort的端口將會hostPort一樣。
環境變量
每個主機的端口號可以通過環境變量$PORT0,$PORT1暴露。默認情況下每個marathon應用分配一個端口,所以$PORT0總是有效的。運行在marathon上運行的docker容器中,這些環境變量也是有效的。
當使用BRIDGE網絡模式的時候,確保在portMapping端口映射中設置containerPort容器端口號。但是,如果你設置containerPort爲0,那麼它和hostPort是一樣的,並且你可以使用$PORT環境變量。
配置實例
Host模式
host網絡模式是默認的網絡模式,docker和非docker容器應用都可以使用。注意在你的Dockerfile中EXPOSE不是必須的。
開啓Host模式
對容器來說Host模式是默認開啓的。如果希望顯示配置,可以通過network屬性指定。
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "HOST"
}
},
對於非docker應用,你不需要指定任何東西。
指定端口
通過ports數組指定端口。
"ports": [
0, 0, 0
],
或者通過portDefinitions數組指定:
"portDefinitions": [
{"port": 0}, {"port": 0}, {"port": 0}
],
在這個例子中,我們指定3個隨機分配的主機端口號,可以通過環境變量$PORT0,$PORT1,$PORT2使用這個三個端口號。marathon將隨機分配三個服務端口號service port。
指定服務端口號service port:
"ports": [
2001, 2002, 3000
],
或者:
"portDefinitions": [
{"port": 2001}, {"port": 2002}, {"port": 3000}
],
在這個例子中,主機端口$PORT0,$PORT1,$PORT2任然是隨機分配的。但是服務端口號service port是2001,2002,3000。使用一個服務發現的解決方案,如HAProxy,代理請求從服務端口service port到主機端口host port,需要按照上面的方式配置。
如果想讓服務端口service port和主機端口host port一樣,你需要設置requirePorts爲true,默認情況下這個值是false。
"ports": [
2001, 2002, 3000
],
"requirePorts" : true
如果你不適用服務發現方案,這個屬性是非常有用的。
定義portDefinitions數組,你可以爲每個端口指定協議,名稱和標籤。當開始一個新任務,marathon向mesos發送元數據。mesos將在任務的discovery字段暴露這個信息。自定義網絡發現方案會使用這個字段。
下面是定義portDefinitions的實例:
"portDefinitions": [
{
"port": 0,
"protocol": "tcp",
"name": "http",
"labels": {"VIP_0": "10.0.0.1:80"}
}
],
port字段是必填的。protocol,name,labels是可選的。如果portDefinitions數組只設置端口port,那麼和設置ports數組是一樣的。
注意ports和portDefinitions不能一起使用。
引用端口
你可以在Dockerfile文件中引用主機的端口:
CMD ./my-app --http-port=$PORT0 --https-port=$PORT1 --monitoring-port=$PORT2
另外,如果你不使用docker或者使用在你的marathon應用中定義cmd,方式都是一樣的:
"cmd": "./my-app --http-port=$PORT0 --https-port=$PORT1 --monitoring-port=$PORT2"
Bridge模式
Bridge網絡模式可以映射主機端口到容器內部端口,目前只支持docker容器。如果你使用容器鏡像並且端口是固定的,這個模式是非常有用的。注意在Dockerfile中EXPOSE端口不是必須的。
開啓Bridge模式
通過network屬性指定bridge模式:
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "BRIDGE"
}
},
指定端口
端口映射類似於docker命令中的參數-p。它指定在容器內的主機和端口的映射管理。
在container中配置端口映射portMappings:
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 0, "hostPort": 0 },
{ "containerPort": 0, "hostPort": 0 },
{ "containerPort": 0, "hostPort": 0 }
]
}
},
這個實例中,主機端口是隨機的,並且容器端口號和主機端口號是一致的。此處定義了三個端口映射,在容器內部可以使用環境變量$PORT0、$PORT1、$PORT2引用端口號。
另外,固定容器端口號,配置如下:
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 80, "hostPort": 0 },
{ "containerPort": 443, "hostPort": 0 },
{ "containerPort": 4000, "hostPort": 0 }
]
}
},
在這個例子中,marathon會隨機分配主機端口映射到80,443,4000端口。環境變量$PORT是很重要的,在上面的例子中,$PORT0表示第一個映射中的hostPort值。
指定協議
你也可以爲端口指定協議,默認爲tcp:
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp" },
{ "containerPort": 443, "hostPort": 0, "protocol": "tcp" },
{ "containerPort": 4000, "hostPort": 0, "protocol": "udp" }
]
}
},
指定服務端口
默認情況下,marathon隨機創建服務端口service port。服務端口用做服務發現,將服務端口設置成常用端口是一個可取的方案。使用servicePort設置服務端口:
"container": {
"type": "DOCKER",
"docker": {
"image": "my-image:1.0",
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp", "servicePort": 2000 },
{ "containerPort": 443, "hostPort": 0, "protocol": "tcp", "servicePort": 2001 },
{ "containerPort": 4000, "hostPort": 0, "protocol": "udp", "servicePort": 3000}
]
}
},
在這個例子中$PORT0、$PORT1、$PORT2任然是隨機分配的。但是服務端口後被設置爲2001、2002和3000。外部代理,如HAProxy,負責服務端口到主機端口的路由。
引用端口
如果containerPort設置爲0,你應該在Dockerfile指定端口:
CMD ./my-app --http-port=$PORT0 --https-port=$PORT1 --monitoring-port=$PORT2
但是,如果你已經指定的containerPort的值,你只要在Dockerfile中使用這些端口值:
CMD ./my-app --http-port=80 --https-port=443 --monitoring-port=4000
另外,在你的marathon應用定義中指定了cmd,你可以使用相同的方式定義端口:
"cmd": "./my-app --http-port=$PORT0 --https-port=$PORT1 --monitoring-port=$PORT2"
或是使用固定值:
"cmd": "./my-app --http-port=80 --https-port=443 --monitoring-port=4000"