2017-09-02 107 views
5

我目前正在嘗試設置一個簡單的CI,它將重建我的項目,創建一個新的Docker鏡像,將新鏡像推送到亞馬遜ecr倉庫,創建一個新的修訂版本使用最新的Docker鏡像的現有任務定義,使用任務定義的新修訂更新正在運行的服務,並最終停止運行舊版本的現有任務,並啓動運行新版本的任務。更新AWS ECS服務任務的最佳實踐

除了開始任務的新版本以外,一切正常。

從bash腳本,最後的命令我打電話是:

aws ecs update-service --cluster "$CLUSTER" --service "$SERVICE" --task-definition "$TASK_DEFINITION":"$REVISION" 

這導致的事件錯誤:

(service rj-api-service) was unable to place a task because no container instance met all of its requirements. The closest matching (container-instance bbbc23d5-1a09-45e7-b344-e68cc408e683) is already using a port required by your task. 

而且因爲我更換容器正是這是有道理的與新的一樣,並且將在同一個端口上運行,它只包含我的應用程序的最新版本。

我的印象是,update-service命令會停止現有任務,並啓動新任務,但它看起來像是首先啓動新任務,並且如果成功則停止舊任務。

處理此問題的最佳做法是什麼?我應該先停止舊任務嗎?我應該先刪除腳本中的服務並重新創建每個更新的整個服務?

目前我只需要運行任務的1個實例,但如果我需要這個能夠自動縮放到多個實例,我不想將自己的自己裝箱。有關解決此問題的最佳方法的任何建議?

回答

8

您收到的消息是因爲ECS正在嘗試執行藍綠色部署。這意味着它正試圖分配新的任務修訂版而不停止當前的任務,以避免服務中的停機。一旦最新的任務準備就緒(穩定狀態),舊的任務將被最終移除。

這種部署類型的問題是,您需要在羣集中有足夠的免費資源,以便在一段時間內維護並運行2個任務(舊的和新的)。例如,如果您正在部署具有2GB內存和2個CPU的任務,則您的集羣需要擁有足夠的可用資源,才能使用新的任務修訂更新服務。

你有2種選擇:

  1. 擴展羣集添加一個新的EC2實例,所以你可以有足夠的可用資源,並進行部署。
  2. 更改您的服務配置以便不執行藍綠色部署(羣集中只允許同時執行一項任務)。

爲了執行選項號2,你只需要設置以下值:

  • Minimun健康百分之:0
  • Maximun%的:100

示例

Example

這意味着你只想擁有你想要的任務100%運行(並沒有更多的!),並同時部署新版本(健康服務的0%)你願意有一個停機。

在這個例子中,我假設你只想1個所需的任務,但Minimun健康百分之Maximun%的值會爲你想所需的任何任務的工作量。

希望它有幫助!如果您有任何其他疑問,請告知我。

+1

這是一個完美的描述。非常感謝。我將健康百分比設置爲50/200的默認值。我沒有做藍綠部署,所以將健康百分比設置爲0/100是可行的,我最初的預期是,我必須調用的是更新,而不用更多的步驟來停止正在運行的任務。 – on3al

+0

太棒了!我很高興它按照你的預期工作。 –

0

所以我現在有這個工作。

在我用新任務定義呼叫aws ecs update service之後,我呼叫aws ecs list-tasks,然後在服務的每個正在運行的任務上運行「aws stop task」。由於該服務的期望計數爲1,因此它立即嘗試啓動備份任務並使用新的服務定義。

這不是很漂亮,但它現在似乎運作良好。

1

您可以在構建環境中使用shell腳本通過以下步驟啓動新任務修訂。

  1. 存放在一個文件中構建環境的tasks definition json template(用於e.g模板文件是web-server.json和任務定義家庭是web-server)。

  2. 使用文件目錄作爲當前目錄並執行寄存器任務定義(會發生第一次運行,如果不存在的話)

    aws ecs register-task-definition --cli-input-json file://web-server.json

  3. 獲取正在運行的任務ID(TASK_ID)在外殼的變量腳本。

    TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'`

  4. 獲取任務修訂(TASK_REVISION)在shell腳本變量。

    TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`

  5. 停止當前任務運行

    aws ecs stop-task --cluster default --task ${TASK_ID}

  6. 立即啓動一個新的任務

    aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1

作爲最佳實踐,您可以使用以下腳本(對多個容器的以上步驟的擴展)爲2個任務(服務內部運行的兩個任務)保留期望數最小值並執行滾動更新(一次更新一個任務)零停機時間(確保在第一次容器更新之後保持足夠的時間e。g睡眠30,準備好接受新的請求)。

cd /<directory-containing-web-server.json> 
aws ecs register-task-definition --cli-input-json file://web-server.json 
OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'` 

TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'` 
aws ecs stop-task --cluster default --task ${OLD_TASK_ID} 

OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'` 
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1 

sleep 30 
aws ecs stop-task --task ${OLD_TASK_ID} 
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 2 

注意:您需要相應地配置任務定義系列,實例所需計數和任務定義模板。

+0

您可以簡化OLD_TASK_ID = ...使用「jq」 ... OLD_TASK_ID ='aws ecs list-tasks --cluster default --desired-status RUNNING - 家族Web服務器| jq --raw-output「.taskArns |。[]」' 當然你必須安裝JQ'apt-get install jq' – AlexS