国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

技術實踐 | Mesos 全方位“烹飪”指南

archieyang / 2362人閱讀

摘要:之前提到的文件即可利用以下模板生成請注意,其中的與就是占位符。如將某一特定部署至生產環境并運行個實例。而另一種方式則是使用等負載均衡器即服務器端發現。可重配置且能夠在變更發生后立即將請求路由至新實例。

如今與Mesos相關的文章可謂層出不窮,不過展示能夠直接用于生產的完整基礎設施的資料卻相當少見。在今天的文章中,我將介紹各組件的配置與使用方式,旨在幫助大家利用Mesos構建起持續交付且擁有容錯能力的運行時平臺。不過設備配置腳本屬于基礎設施當中的主體部分,因此在文章中無法完全公布——但值得大家了解的內容已經全部到位。

概述

我們不會具體探討設備的實際安裝與配置,不過大家可以通過下圖了解我們已經安裝的軟件:

目前,我們運行有3臺主節點與3臺從節點,并利用Saltstack進行配置。

下面讓我們從宏觀角度審視代碼構建與配置及執行的完整部署流程。


在以下章節中,我們將探討各組件是如何交互及運作的。

準備Docker鏡像

雖然Mesos能夠利用自身默認容器完美處理各類可執行文件,但我們仍然推薦運行Docker化應用。我們需要向每套Docker鏡像中添加一點內容,從而保證其能夠輕松同這套運行時平臺相集成。

首先,我們需要了解Docker宿主主機的實際IP地址。雖然人們一直要求支持特殊的Docker標記,可以很容易的通過定制化腳本輕松實現:

#!/bin/sh

set -e

DOCKERHOST=$(ip route show 0.0.0.0/0 | grep -Eo "via S+" | awk "{ print $2 }")
echo "$DOCKERHOST dockerhost" >> /etc/hosts

exec "$@"

現在容器化中的應用程序已經能夠可靠地引用“dockerhost”主機名稱,在必要時接入該Docker宿主主機。

接下來是服務配置管理(我們將在后文中詳盡討論),我們需要向Docker鏡像中添加一套名為service-wrapper的腳本。另外,我們還需要安裝其關聯性元素——jq。如果大家使用精簡化Linux鏡像(例如Alpine),請確保其中包含curl命令工具。這一切匯總起來,我們就擁有了以下面向Node.js應用程序的Docker鏡像:

FROM node:4

RUN apt-get update && apt-get install -y jq && 
  rm -rf /var/lib/apt/lists/*

ADD service-wrapper.sh /usr/bin/
ADD entrypoint.sh /usr/bin/

此鏡像應被推送至Docker 倉庫并由CI服務器進行訪問。在我們的示例中,將是可用的私有Docker倉庫在registry.local這臺宿主主機上。

構建與部署

我們利用Drone實現持續集成,其使用方式非常簡單但卻能夠在Docker容器當中很好地執行構建任務。另外,其全部插件也都是普通的Docker容器,其能夠獲取build信息載荷并能夠以獨特的插件方式加以處理。而且沒錯,甚至是克隆代碼庫也能夠通過多帶帶的Docker容器實現。

由于我們使用的技術相當多元化,因此需要利用Drone簡化很多我們的服務器構件設置——我們只需要為每種不同技術堆棧準備多帶帶的Docker鏡像,并要求其利用此鏡像進行構建。舉例來說,這些鏡像分別用于運行Node.js、Java以及Mono的構建。當然,它們同樣由Drone負責構建。

為了便于理解,我創建一款名為test-server的Node.js Web應用,其只負責顯示各項環境變量——大家可以 點擊此處在GitHub上查看源代碼。我們在后文中還將多次提到這款示例應用,了解如何利用test-server創建一套Docker鏡像并將其部署至Marathon。需要強調的是,該服務應當盡可能遵循十二因素應用原則,從而更好地與這套運行時平臺相集成。

在進行構建之前,需要注意的是,我們會利用Marathon調度自己的長期運行服務。它正是整套運行時平臺的基石,其負責控制服務可用性并用于實現服務發現。其擁有非常直觀的“可curl”API,我們可以利用它實現自動部署。為了利用Marathon部署服務,大家需要調用其API并發送JSON文件以進行服務描述,具體如下所示:

{
  "id": "/app/production/test-server",
  "labels": {
    "version": "master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56",
"environment": "production"
  },
  "env": {
"SERVICE_TAGS": "production,internal-listen-http-3000",
"SERVICE_NAME": "test-server"
  },
  "cpus": 0.05,
  "mem": 64.0,
  "instances": 4,
  "args": [
    "service-wrapper.sh", "dockerhost:18080", "dockerhost:18500", "app/production/test-server",
"node", "/app/server.js"
  ],
  "container": {
    "type": "DOCKER",
    "docker": {
      "image": "registry.local/test-server:master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56",
      "forcePullImage": true,
      "network": "BRIDGE",
      "portMappings": [{
        "containerPort": 3000
      }]
    }
      },
  "healthChecks": [{
    "protocol": "HTTP",
    "path": "/healthcheck",
    "gracePeriodSeconds": 2,
    "intervalSeconds": 10,
    "maxConsecutiveFailures": 3
  }],
  "upgradeStrategy": {
    "minimumHealthCapacity": 0.5,
    "maximumOverCapacity": 0.5
  }
}

它會指示Marathon調用4個Docker服務實例,來源則為來自registry.local/test-server且擁有master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56標簽的鏡像。我們將其稱為服務定義。我們不會對其規范進行具體討論,感興趣的朋友可以點擊此處查閱Marathon API參考。更重要的是,此文件能夠在構建過程中自動生成。對于每一項可部署服務,其服務定義模板中都包含一個以“$”開頭的占位符。之前提到的文件即可利用以下模板生成:

{
  "id": "/app/$environment/test-server",
  "labels": {
    "version": "$tag",
    "environment": "$environment"
  },
  "env": {
    "SERVICE_TAGS": "$environment,internal-listen-http-3000",
    "SERVICE_NAME": "test-server"
  },
  "cpus": 0.05,
  "mem": 64.0,
  "instances": $instances,
  "args": [
    "service-wrapper.sh", "dockerhost:18080",     "dockerhost:18500", "app/$environment/test-server",
    "node", "/app/server.js"
  ],
  "container": {
    "type": "DOCKER",
    "docker": {
      "image": "registry.local/test-server:$tag",
      "forcePullImage": true,
      "network": "BRIDGE",
      "portMappings": [{
        "containerPort": 3000
      }]
    }
  },
  "healthChecks": [{
    "protocol": "HTTP",
    "path": "/healthcheck",
    "gracePeriodSeconds": 2,
    "intervalSeconds": 10,
    "maxConsecutiveFailures": 3
  }],
  "upgradeStrategy": {
    "minimumHealthCapacity": 0.5,
    "maximumOverCapacity": 0.5
  }
}

請注意,其中的$tag、$environment與$instances就是占位符。$tag值會在構建過程中生成并被以下簡單腳本添加至service.json當中:

#!/bin/bash

set -e

VERSION="$CI_BRANCH-$CI_COMMIT-$CI_BUILD_NUMBER"
declare -A TARGETS=(
    [test-server]="."
)

# Set version in service.json
for i in "${!TARGETS[@]}"
do
    SERVICE=${TARGETS[$i]}/service.json
    TARGET=service-defs/${TARGETS[$i]}
    mkdir -p $TARGET
    echo "Setting version $VERSION for $SERVICE"
    sed "s/$tag/$VERSION/g" $SERVICE > $TARGET/service-$CI_BRANCH.json
    cp $TARGET/service-$CI_BRANCH.json $TARGET/service-$VERSION.json
done

它創建兩條服務定義:其一以完整版本命名,其二以分支版本命名,即service-master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56.json與service-master.json。在這兩個文件當中,$tag會被替換為master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56,但$environment與$instances則仍然保持不變,我們隨后還需要在部署階段使用它們。下面來看看Drone的build配置(其完整語法可點擊此處查看):

build:
  image: registry.local/buildimage-nodejs:latest
  commands:

tools/gen-service-defs.sh

publish:

 docker:
   image: plugins/drone-docker
   repo: registry.local/test-server
   tag:

latest

$$BRANCH

$$BRANCH-$$COMMIT-$$BUILD_NUMBER

 s3:
   image: plugins/drone-s3
   acl: public-read
   region: eu-west-1
   bucket: build-artifacts
   access_key: $$S3_ACCESS_KEY
   secret_key: $$S3_SECRET_KEY
   source: service-defs/
   target: test-server/
   recursive: true

而后,CI根據指令發布build構件:

創建一套Docker鏡像并將其推送至Docker倉庫

將生成的服務定義發送至S3

我們完全可以將一部分最新發布的Docker鏡像標簽存儲在Docker 倉庫當中,甚至可以在磁盤空間比較充裕時全部加以存儲。通過這種方式,我們就能在新近部署的版本出現問題時利用Marathon輕松回滾至原有版本。

現在我們已經可以部署自己的全新服務版本了。為了完成這項任務,我們需要將服務定義JSON發送至Marathon的/v2/apps API。不過首先,我們需要替換現有占位符,即$environment與$instances。盡管相關操作非常簡單,但我們仍然要利用marathon-deploy工具實現自動化處理。其能夠自動下載服務定義模板,利用對應值替換點位符并創建/更新Marathon中的應用。具體方式如下:

`marathon-deploy.sh   [instances-count]`

其中service-template-url為被發布至S3的服務定義構件的URL,而environment則可為任意其它運行時環境(例如分段、生產、A/B分組測試等),instances-count則允許指定需要啟動的服務實例數量,默認情況下為1。例如:

`marathon-deploy.sh https://build-artifacts.s3.amazonaws.com/test-server/service-master.json staging`

其將主分支的最新build部署至分段環境并運行單一實例。如:

`marathon-deploy.sh https://build-artifacts.s3.amazonaws.com/test-server/service-master-ef5a154e25b268c611006d08a78a3ec0a451e7ed-56.json production 4`

將某一特定build部署至生產環境并運行4個實例。

在本示例中,我們將marathon-deploy腳本復制到全部Mesos-slave 的宿主機當中,并通過Chronos進行配置與部署。因為我們已經將各關鍵服務預部署到了不同環境當中,因此這一部署流程只需要一次點擊即可完成。Chronos的最大優勢在于,它能夠將大量任務串聯起來,意味著大家能夠通過配置在實際部署前、后執行一次性任務以準備運行時環境。

服務發現與負載均衡

分布式系統中的服務總是出于種種原因而不斷上線、下線,例如服務啟動/停止,規模伸縮或者服務故障。與利用已知IP地址及主機名稱同服務器協作的靜態負載均衡器不同,Marathon中的負載均衡機制的實時性使得其需要以更為復雜的方式進行服務注冊與注銷。有鑒于此,我們需要利用某種服務注冊表以容納已注冊服務信息并將此信息提供給客戶端。這一概念也就是服務發現,且成為大多數分布式系統中的核心組件。

這里就要用到Consul了。正如其官方網站上所言,“Consul能夠輕松幫助服務進行自我注冊,同時通過DNS或者HTTP接口發現其它服務”。除此之外,它還擁有其它一些非常實用的功能,我們將在后文提到。現在我們已經擁有了服務注冊表,接下來要做的就是告知其哪些服務需要啟動、這些服務的具體位置(主機名稱與端口)并可選擇提供其它相關元信息。實現這一目標的方法之一在于讓服務本身直接使用Consul API,但這種作法會導致各項服務必須擁有內置通信邏輯。如果服務數量不多還好,面對大規模服務集時這將成為一場災難,特別是當它們由不同編程語言編寫而成時。另一種方式在于利用某些第三方工具對服務進行監控,并將服務報告給Consul。我們使用的程序名為marathon-registrator,它能夠與Marathon緊密集成并注冊Marathon所運行的任何服務類型。另一種選項則是使用Gliderlabs registrator,當然前提是大家的服務全部存在于Docker容器當中。選擇一種工具,將其實例運行在Mesos-slave宿主機上即可。

服務注冊完成之后,其它服務就能夠對其進行定位了。如此一來,它們就能夠利用Consul API或者DNS進行直接通信并獲取此類元信息(即客戶端發現)。而另一種方式則是使用HAProxy等負載均衡器(即服務器端發現)。

HAProxy服務發現較客戶端發現擁有多種優勢:

免費負載均衡機制。

能夠將服務注冊表中的變更即時傳播至消費方。HAProxy可重配置且能夠在變更發生后立即將請求路由至新實例。

配置更為靈活,例如:負載均衡策略、運行狀態檢查、ACL、A/B測試、日志記錄以及統計等等。

不需要由服務實現額外的發現邏輯。

不過HAProxy是如何在Consul中追蹤已注冊服務的?一般來講,其配置會利用全部已知后端以靜態方式完成。不過我們也可以例如consul-template等外部工具對其進行動態構建。這款工具能夠監控Consul中的變更并生成任意文本文件,因此其并不只限于配置HAProxy,亦可用于其它能夠利用文本文件實現配置的工具(例如nginx、varnish以及apache等等)。該模板語言的說明文檔非常全面,感興趣的朋友可以點擊此處查看。

大家可能已經注意到,我們在概覽圖中運行有兩套不同的HAProxy配置:一套用于內部負載均衡,另一套用于外部負載均衡。內部實例跨越各后端服務提供實際服務發現與負載流量。外部實例則額外將服務發現聲明至TCP 80端口并接收來自外部的請求,以此實現前端服務負載均衡。

在這些不同的HAProxy實例中,我們需要管理兩套獨立的consul-template模板文件——這兩個文件本身則由另一套模板引擎(即Jinja2)在Saltstack進行設備配置時構建完成。這種作法主要是為了保證流程清晰,同時將來自設備配置軟件的數據填充至其中的特定部分。讓我們首先來看外部負載均衡器配置模板。請注意,raw/endraw標記負責讓Jinja引擎忽略Go模板的大括號并按原樣使用初始內容:

global
  log /dev/log  local0
  log /dev/log  local1 notice
  chroot /var/lib/haproxy
  user haproxy
  group haproxy
  daemon
  maxconn {% raw %}{{key "service/haproxy/maxconn"}}{% endraw %}

  # Default SSL material locations
  ca-base /etc/ssl/certs
  crt-base /etc/ssl/private

  ssl-default-bind-options no-sslv3 no-tls-tickets
  ssl-default-bind-ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH

  tune.ssl.default-dh-param 2048

{% include "mesos/files/haproxy-defaults.ctmpl.jinja" %}
{% include "mesos/files/haproxy-internal-frontend.ctmpl.jinja" %}
{% include "mesos/files/haproxy-external-frontend.ctmpl.jinja" %}
{% include "mesos/files/haproxy-wellknown-services.ctmpl.jinja" %}
{% include "mesos/files/haproxy-backends.ctmpl.jinja" %}

其中還包含其它一些關聯性。haproxy-defaults.ctmpl.jinja屬于常見于各類HAProxy配置示例中的靜態部分,而haproxy-internal-frontend.ctmpl.jinja則比較有趣——它負責指定內部服務發現配置的實現位置。

其基本思路在于為每一項可發現服務匹配一條已知端口編號,同時創建一套HAProxy前端以監聽該端口。我們將使用與每項已注冊服務一同存儲的元信息。Consul允許用戶為服務指定一套關聯標簽列表,而marathon-registrator會通過名為SERVICE_TAGS的服務環境變量讀取這些標簽。查看test-server的service.json模板,其中包含兩個以逗號隔開的標簽,即$environment與internal-listen-http-3000。后者在consul-template模板中用于標記已聲明端口以實現服務發現的服務(在本示例中為3000)。以下代碼片段會自動生成必要的HTTP前端:

{% raw %}

{{range $service := services}}{{range $tag := $service.Tags}}
{{$servicePort := $service.Name | regexReplaceAll "^[w-]+?(d*)$" "$1"}}{{$tagPort := $tag | regexReplaceAll "^[w-]+?(d*)$" "$1"}}
{{if or (not $servicePort) (eq $servicePort $tagPort)}}
{{if $tag | regexMatch "internal-listen-http-d+"}}
##
# Production internal http frontend for {{$service.Name}}
##

frontend internal_http_in_production:{{$service.Name}}
  bind :{{$tag | replaceAll "internal-listen-http-" ""}}
  use_backend cluster_production:{{$service.Name}}

##
# Staging internal http frontend for {{$service.Name}}
##

frontend internal_http_in_staging:{{$service.Name}}
  bind :1{{$tag | replaceAll "internal-listen-http-" ""}}
  use_backend cluster_staging:{{$service.Name}}
{{end}}
{{end}}
{{end}}{{end}}

{% endraw %}

它的外環會列出全部Consul服務,內環則列出每項服務的標簽并嘗試找到與internal-listen-http-匹配的條目。每一次匹配成功,其都會創建對應的HTTP前端。這里的每項服務都擁有兩種硬編碼環境:production與staging,用于進行區分。其中分段環境的端口編號會以“1”開頭,因此如果生產前端監聽端口3000,那么分段則監聽端口13000。

另外,if語句允許我們為單一服務指定多個可發現端口。要實現這一效果,我們只需要在標簽列表當中額外添加internal-listen-http-標記,例如:

`$environment,internal-listen-http-3000,internal-listen-http-3010`

現在我們需要添加一個指向container.docker.portMappings服務定義文件組的聲明端口,從而保證Marathon能夠正確配置我們的容器網絡。請注意,本示例中的marathon-registrator將分別注冊兩項服務:test-server-3000與test-server-3010,對二者進行分別解析并避免名稱混淆。

大家也可以利用其它預定義標記在模板中實現其它邏輯類型,例如引入internal-listen-tcp-以生成TCP前端,或者利用balance-roundrobin或balance-leastconn控制均衡策略。

這套模板允許我們配置HAProxy,從而指定每臺設備通過接入localhost:以訪問每項Consul已知服務,最終解決服務發現問題。
在haproxy-wellknown-services.ctmpl.jinja當中,我們可以指定多種靜態管理服務,例如Marathon、Consul以及Chronos,這是因為它們較易于發現。它們會在設備配置過程中由systemd/upstart/etc啟動。舉例來說,以下代碼片段允許來自集群內任意設備的請求通過聯系localhost:18080 輕松訪問Marathon實例,而localhost:14400 與localhost:18500 則分別對應Chronos與Consul(在本示例中,集來自配置管理軟件):

frontend internal_http_in:marathon
  bind :18080
  use_backend cluster:marathon

frontend internal_http_in:chronos
  bind :14400
  use_backend cluster:chronos

listen internal_http_in:consul
  bind :18500
  timeout client 600000
  timeout server 600000
  server local 127.0.0.1:8500

backend cluster:marathon
  option forwardfor
  option httpchk GET /ping
  balance roundrobin
{%- for host, ip in master_nodes.iteritems() %}
  server {{ host }} {{ ip }}:8080 check inter 10s
{% endfor -%}

backend cluster:chronos
  option forwardfor
  option httpchk GET /ping
  balance roundrobin
{%- for host, ip in master_nodes.iteritems() %}
  server {{ host }} {{ ip }}:4400 check inter 10s
{% endfor -%}

haproxy-external-frontend.ctmpl.jinja用于描述HTTP與HTTPS前端。其中包含多套Jinja宏,用于為域名匹配定義ACL規則并將后端與這些規則相綁定:

{% macro hosts(environment, domain_prefix="") -%}
  # {{ environment }} hosts
  acl host_{{ environment }}:test-server  hdr_dom(host) -i -m str {{ domain_prefix }}mesos-test.domain.com
{%- endmacro %}

{% macro bind(service, environment) -%}
  use_backend cluster_{{ environment }}:{{ service }} if host_{{ environment }}:{{ service }}
{%- endmacro %}

frontend external_https_in
  bind :443 ssl crt domain_com.pem

  http-response set-header Strict-Transport-Security max-age=31536000; preload
  http-response set-header X-Frame-Options DENY
  http-response set-header X-Content-Type-Options nosniff

  {{ hosts("staging", "staging-") }}
  {{ hosts("production") }}

  # Staging bindings
  {{ bind("test-server", "staging") }}

  # Production bindings
  {{ bind("test-server", "production") }}

frontend external_http_in
  bind :80

  {{ hosts("staging", "staging-") }}
  {{ hosts("production") }}

  # Staging bindings
  {{ bind("test-server", "staging") }}

  # Production bindings
  {{ bind("test-server", "production") }}

最后,還有haproxy-backends.ctmpl.jinja文件。它會列出之前章節中提到的全部可用服務。所有后端都可以進行手動調整,因為用戶可能需要滿足運行狀態檢查或者負載均衡方面的特殊要求:

{% macro backends(environment) -%}

##
# {{ environment }} backends
##
{{ "{{" }}$environment := "{{ environment }}"{{ "}}" }}
backend cluster_{{ environment }}:test-server
  option forwardfor
  option httpchk GET /healthcheck
  balance roundrobin{% raw %}{{range $i, $s := service (print $environment ".test-server")}}
  server {{$s.Node}}-{{$i}} {{$s.Address}}:{{$s.Port}} check inter 10s fall 1 rise 1{{end}}{% endraw %}

{%- endmacro %}

{{ backends("production") }}
{{ backends("staging") }}

內部負載均衡配置文件要稍稍簡單一點,其只需要將連接路由至內部可訪問服務:

global
  log /dev/log  local0
  log /dev/log  local1 notice
  chroot /var/lib/haproxy
  user haproxy
  group haproxy
  daemon
  maxconn {% raw %}{{key "service/haproxy/maxconn"}}{% endraw %}

{% include "mesos/files/haproxy-defaults.ctmpl.jinja" %}
{% include "mesos/files/haproxy-internal-frontend.ctmpl.jinja" %}
{% include "mesos/files/haproxy-wellknown-services.ctmpl.jinja" %}
{% include "mesos/files/haproxy-backends.ctmpl.jinja" %}
零停機時間部署

動態運行時系統的一大共通優勢在于,其能夠以零停機時間為前提的實現服務部署。在實際部署過程中,我們往往希望確保服務的可用性不受影響。下面來看如何在自己的系統中實現這一效果。

其基本思路在于運行多個服務實例以支撐輸入請求,并在部署期間一一替換這些實例:只有新實例頂替上之后,我們才會關停舊實例。Marathon能夠完全搞定這樣的滾動重啟方式,但為了保證恒定的正常運行時間,我們還需要確保負載均衡器停止向已經被關停的實例路由流量。

下面要討論Mesos如何停止基于Docker的服務實例。與其它Unix進程控制系統一樣,它會嘗試以正常方式停止服務。首先,SIGTERM會被發送至目標進程,而后該進程預計將在掛起請求并清空后自行退出。如果其在指定時間內仍未退出,SIGKILL會強制將其關閉。Mesos的具體執行方式如下:

`docker stop -t= `

(詳見:https://docs.docker.com/engine/reference...

現在,我們的服務應該能夠正確處理終止信號了(其同樣也是十二因子應用原則之一)。在接收到SIGTERM后,其應該告知負載均衡器不再向其路由流量。要實現這一效果,最簡單的方式就是拒絕全部后續運行狀態檢查,但仍然正常處理其它潛在請求。一旦負載均衡器發現該實例運行狀態不正常,它將停止將流量路由至該處。為了確保這一流程正常實現,我們需要確保關停超時足夠長,使得負載均衡器能夠自行發現運行狀態變化并停止對掛起請求的處理。默認情況下,Mesos的配置超時為5秒,不過大家也可以利用以下命令行參數變更該值:

`--executor_shutdown_grace_period=60secs --docker_stop_timeout=30secs`

感興趣的朋友也可以參閱https://github.com/x-cray/test-server/bl... 示例以了解如何處理SIGTERM。

需要強調的是,docker化服務的處理方式有所不同。為了允許信號傳入Docker容器進程,我們應當在Dockerfile中使用ENTRYPOINT而非CMD以指定執行權限。在運行時,CMD執行會被打包至shell進程當中,而其不會轉發任何信號(詳見Docker說明文檔)。

基本上,到這里我們已經實現了零停機時間部署。不過對于HAProxy而言,這樣的配置只適用于BSD系統。在Linux系統當中還存在一個小問題:當其進行配置重載時,服務器會在一小段時間內(約20到50毫秒)無法監聽輸入連接。此時段內的全部輸入請求自然也將失敗。其根本原因在于Linux內核處理SO_REUSEPORT套接選項的方式身上(詳情可參閱http://lwn.net/Articles/542629/ )。要解決這個問題,大家不妨閱讀由Yelp發布的一篇文章。我們最終選擇了簡單的SYN數據包丟棄方案。這種作法對于我們目前的使用場景來講已經足夠了。以下為我們的consul-template如何重載HAProxy實例:

#!/bin/bash

iptables -I INPUT -p tcp --dport 80 --syn -j DROP
sleep 0.2
systemctl reload haproxy
iptables -D INPUT -p tcp --dport 80 --syn -j DROP
服務配置管理

我們運行的每項服務都需要擁有自己的配置,包括連接字符串以及API密鑰等等。一般來講,這些信息不應被硬編碼,也應該從構建來提供(調試/發布/其它),因為大家可能希望在不同環境(生產/分段/分組測試)下通過不同的配置實現同樣的執行效果。

服務配置通常有著不同的來源(各來源亦擁有自己的優先級排序):默認、文件、環境變量、argv等。如果該服務可通過環境變更進行配置,那么我們就能通過多種途徑以集中方式對其進行管理——我們要做的就是在服務正式啟動前為其準備正確的環境。好消息是,現在我們已經擁有了免費的集中化配置存儲方案。Consul提供內置鍵-值存儲(Consul KV)機制,可用于保存配置值——但我們還需要另一種手段將這些值轉發至服務環境。

專門用于解決這類需求的工具為envconsul,它會讀取Consul KV數據并將其傳遞至服務環境。而在KV數據更新時,它會重啟對應服務實例。不過,它在服務滾動重啟以實現服務可用性方面的表現并不好——它會一次性重啟全部實例,并因此造成請求失敗。作為后備選項,我們可以要求Marathon在KV數據更新時,確保一切已經部署到位并由調度器完成相關重啟工作。正因為如此,我們選擇了一套小型Shell腳本service-wrapper來代替envconsul,其能夠從Consul KV處讀取數據,設置服務環境并在KV變更發生時通過Marathon進行重啟。另外,它還能夠將接收到的SIGTERM轉發至底層進程以實現正常關閉。大家應該將這套腳本內置于Docker鏡像當中。它需要使用curl與jq,因此請確保二者同樣存在于Docker鏡像內。以下為具體使用方法:

`service-wrapper.sh    `

其中marathon-host:port 與consul-host:port 擁有自描述特性,prefix值按照慣例應為Marathon應用ID,而command則為包含相關參數的實際服務可執行文件。為了設定各服務環境變量,我們需要將值添加至Consul KV存儲內的prefix路徑下。以下為service-wrapper運行示例:

`service-wrapper.sh dockerhost:18080 dockerhost:18500 app/staging/test-server node /app/server.js`

請注意dockerhost:18080 與dockerhost:18500 ——二者為之前提到的服務器端內部服務發現示例。

現在如果我們添加/移除/修改prefix之下的任意值,該服務都將根據新配置進行正常重啟。

總結

基于Mesos的架構能夠幫助我們將多種不同組件加以混合與匹配,從而擁有一套符合實際需要的完整工作系統。舉例來說,要實現負載均衡,我們可以使用HAProxy或者Nginx并配合由consul-template生成的動態配置,甚至可以利用其它一些既能夠與Consul通信、又能夠配置IPVS負載均衡的其它方案替代consul-template。我們還可以利用Netflix Eureka替換整個服務發現/負載均衡層,或者基于Etcd乃至ZooKeeper編寫自己的定制化解決方案。構建這樣一套系統能夠幫助大家更好地了解分布式運行時平臺背后的各個進程及其核心組件。

這套平臺還具備良好的可移植性,其不僅可被托管至特定云/IaaS之上,也可以通過內部甚至是混合(云加內部)環境實現。目前甚至有一些項目能夠將Mesos移植至Windows平臺。

原文鏈接:
https://medium.com/@x_cray/how-we-cook-m...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/26575.html

相關文章

  • Container容器技術大會PPT分享

    摘要:大會是由國內容器社區組織的專為一線開發者和運維工程師設計的頂級容器技術會議,會議強調實踐和交流,話題設置圍繞容器運維云計算等技術領域,力求全方位多角度為參會者解讀容器技術。 @Container大會是由國內容器社區 DockOne 組織的專為一線開發者和運維工程師設計的頂級容器技術會議,會議強調實踐和交流,話題設置圍繞容器、運維、云計算等技術領域,力求全方位、多角度為參會者解讀容器技術...

    Zachary 評論0 收藏0
  • GIAC 2017全球互聯網架構大會最新日程

    摘要:月日至日,高可用架構和聯合主辦的全球互聯網架構大會將于上海光大會展中心舉行。全球互聯網架構大會是高可用架構技術社區推廣的面向架構師技術負責人及高端技術從業人員的技術架構大會。本次大會共有大板塊方向,場技術專題,個互聯網架構案例。 showImg(https://segmentfault.com/img/bVZ3Vh?w=600&h=375);12月22日至23日,高可用架構和msup聯...

    617035918 評論0 收藏0
  • GIAC 2017全球互聯網架構大會最新日程

    摘要:月日至日,高可用架構和聯合主辦的全球互聯網架構大會將于上海光大會展中心舉行。全球互聯網架構大會是高可用架構技術社區推廣的面向架構師技術負責人及高端技術從業人員的技術架構大會。本次大會共有大板塊方向,場技術專題,個互聯網架構案例。 showImg(https://segmentfault.com/img/bVZ3Vh?w=600&h=375);12月22日至23日,高可用架構和msup聯...

    Imfan 評論0 收藏0
  • 周末“干活”之 Mesos Meetup

    摘要:愛奇藝歷程采用的軟件棧服務現狀集群建設自動化部署經驗沒有采用嵌入式管理服務降低風險,對紅帽有一點擔憂。再次感謝和數人科技共同組織的,非常期待下一次的周末相聚。 周末兩天都是大霧霾天,作為運營也不能在家宅,告別了技術就得腿兒勤點兒。 非常感謝 Linker 的 Sam Chen 和 數人科技 的 CTO 共同組織的Mesos Meetup,OneAPM 最帥的 Docker 工程獅~陳亮...

    warmcheng 評論0 收藏0
  • 從小白程序員一路晉升為大廠高級技術專家我看過哪些書籍?(建議收藏)

    摘要:大家好,我是冰河有句話叫做投資啥都不如投資自己的回報率高。馬上就十一國慶假期了,給小伙伴們分享下,從小白程序員到大廠高級技術專家我看過哪些技術類書籍。 大家好,我是...

    sf_wangchong 評論0 收藏0

發表評論

0條評論

archieyang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<