ฉันจะปรับใช้อิมเมจ Docker ที่อัปเดตแล้วกับงาน Amazon ECS ได้อย่างไร


114

แนวทางที่ถูกต้องในการทำให้งานAmazon ECSของฉันอัปเดตอิมเมจ Docker ของพวกเขาคืออะไรเมื่อกล่าวว่ารูปภาพได้รับการอัปเดตในรีจิสทรีที่เกี่ยวข้องแล้ว


ฉันอยากจะแนะนำให้เรียกใช้ฟังก์ชัน Lambda อัตโนมัติ / ตามกำหนดเวลา วิธีนี้จะอยู่นอกอินสแตนซ์ คุณลองแล้วหรือยัง? คุณยังสามารถใช้ SWF เพื่อทำทีละขั้นตอนได้
iSkore

ฉันไม่จำเป็นต้องทำให้มันเป็นอัตโนมัติ @iSkore ฉันอยากจะเขียนสคริปต์สำหรับมันในที่สุด แต่เลือกด้วยตัวเองว่าจะเรียกใช้เมื่อใด
aknuds1

อ่า gotcha ไม่แน่ใจเกี่ยวกับเรื่องนั้น คุณสามารถให้ข้อมูลเพิ่มเติมเล็กน้อยได้หรือไม่?
iSkore

1
@iSkore ฉันไม่รู้จะอธิบายยังไงดีกว่าที่ฉันทำไปแล้ว ขั้นตอนคือ 1. พุชอิมเมจ Docker เวอร์ชันใหม่ไปยังรีจิสตรี 2. ปรับใช้อิมเมจเวอร์ชันใหม่กับ ECS คำถามคือวิธีการใช้หลัง
aknuds1

นี่ไม่ใช่เรื่องง่ายหรือชัดเจนสำหรับ EKS เช่นกัน ... F เป็นงานที่พบบ่อยที่สุดในการใช้คลัสเตอร์ปรับใช้ภาพใหม่อย่างไรจึงไม่ชัดเจนในเอกสาร?

คำตอบ:


94

หากงานของคุณกำลังทำงานภายใต้บริการคุณสามารถบังคับให้ปรับใช้ใหม่ได้ ซึ่งจะบังคับให้นิยามงานได้รับการประเมินใหม่และดึงอิมเมจคอนเทนเนอร์ใหม่

aws ecs update-service --cluster <cluster name> --service <service name> --force-new-deployment

1
ฉันคิดว่าเพื่อให้ได้ผลคุณต้องตรวจสอบให้แน่ใจว่ามีทรัพยากรเพียงพอในอินสแตนซ์ ECS ของคุณเพื่อปรับใช้งานเพิ่มเติมที่มีขนาดเท่ากัน ฉันคิดว่า AWS พยายามดำเนินการ hotswap เป็นหลักโดยรอให้อินสแตนซ์งานใหม่ถูกบูตล่วงหน้าก่อนที่จะยุติอินสแตนซ์เก่า เพียงแค่เพิ่มรายการ "การปรับใช้" โดยมีอินสแตนซ์ที่รันอยู่ 0 อินสแตนซ์หากคุณไม่ทำ
Alex Fedulov

3
@AlexFedulov ใช่ฉันคิดว่าคุณถูกต้อง เพื่อไม่ให้เกิดการหยุดทำงานเมื่อสร้างการปรับใช้งานใหม่คุณสามารถ 1) จัดเตรียมอินสแตนซ์ให้เพียงพอสำหรับใช้งานเวอร์ชันใหม่ควบคู่ไปกับเวอร์ชันเก่า สามารถทำได้ด้วยการปรับขนาดอัตโนมัติ 2) ใช้ประเภทการปรับใช้ Fargate คุณสามารถหลีกเลี่ยงการจัดสรรทรัพยากรเพิ่มเติมได้โดยตั้งค่าพารามิเตอร์ "เปอร์เซ็นต์สุขภาพขั้นต่ำ" ของบริการเป็น 0 เพื่อให้ ECS นำบริการเก่าของคุณออกก่อนที่จะปรับใช้บริการใหม่ ซึ่งจะทำให้เกิดการหยุดทำงานบางอย่าง
Dima

3
ตัวเลือกที่ไม่รู้จัก: --force-new-deployment
user4674453

1
ตัวเลือกที่ไม่รู้จัก: --force-new-deployment: upgrade awscli
Kyle Parisi

1
ฉันลองใช้คำสั่งนี้มันไม่ได้อัปเดตคอนเทนเนอร์ด้วยอิมเมจใหม่มันหมุนคอนเทนเนอร์อื่นด้วยอิมเมจเก่าเดียวกัน ดังนั้นฉันจึงมีสองคอนเทนเนอร์ที่ทำงานแม้ว่าในบริการฉันมี specifid ที่ต้องการ count = 1
คณิตศาสตร์

63

ทุกครั้งที่คุณเริ่มงาน (ไม่ว่าจะผ่านการเรียกStartTaskและRunTaskAPI หรือเริ่มโดยอัตโนมัติโดยเป็นส่วนหนึ่งของบริการ) ตัวแทน ECS จะดำเนินdocker pullการimageคุณระบุในนิยามงานของคุณ หากคุณใช้ชื่อรูปภาพเดียวกัน (รวมถึงแท็ก) ทุกครั้งที่คุณพุชไปยังรีจิสตรีของคุณคุณจะสามารถเรียกใช้รูปภาพใหม่ได้โดยการรันงานใหม่ โปรดทราบว่าหาก Docker ไม่สามารถเข้าถึงรีจิสทรีไม่ว่าด้วยเหตุผลใด ๆ (เช่นปัญหาเครือข่ายหรือปัญหาการตรวจสอบสิทธิ์) ECS Agent จะพยายามใช้ภาพแคช หากคุณต้องการหลีกเลี่ยงไม่ให้ใช้รูปภาพแคชเมื่อคุณอัปเดตรูปภาพของคุณคุณจะต้องพุชแท็กอื่นไปยังรีจิสตรีของคุณทุกครั้งและอัปเดตข้อกำหนดของงานให้สอดคล้องกันก่อนที่จะเรียกใช้งานใหม่

อัปเดต: ขณะนี้สามารถปรับพฤติกรรมนี้ผ่านECS_IMAGE_PULL_BEHAVIORตัวแปรสภาพแวดล้อมที่ตั้งค่าบนเอเจนต์ ECS ดูรายละเอียดในเอกสารประกอบ ในขณะที่เขียนรองรับการตั้งค่าต่อไปนี้:

ลักษณะการทำงานที่ใช้ในการปรับแต่งกระบวนการดึงอิมเมจสำหรับอินสแตนซ์คอนเทนเนอร์ของคุณ ต่อไปนี้จะอธิบายถึงพฤติกรรมทางเลือก:

  • หากdefaultระบุไว้ภาพจะถูกดึงจากระยะไกล หากการดึงรูปภาพล้มเหลวคอนเทนเนอร์จะใช้รูปภาพแคชบนอินสแตนซ์

  • หากalwaysระบุไว้รูปภาพจะถูกดึงจากระยะไกลเสมอ หากการดึงภาพล้มเหลวแสดงว่างานนั้นล้มเหลว ตัวเลือกนี้ช่วยให้แน่ใจว่ามีการดึงรูปภาพเวอร์ชันล่าสุดเสมอ รูปภาพที่แคชไว้จะถูกละเว้นและอยู่ภายใต้กระบวนการล้างข้อมูลรูปภาพอัตโนมัติ

  • หากonceระบุไว้รูปภาพจะถูกดึงจากระยะไกลก็ต่อเมื่อไม่ได้ดึงโดยงานก่อนหน้าบนอินสแตนซ์คอนเทนเนอร์เดียวกันหรือหากอิมเมจที่แคชถูกลบออกโดยกระบวนการล้างข้อมูลอิมเมจอัตโนมัติ มิฉะนั้นจะใช้รูปภาพแคชบนอินสแตนซ์ เพื่อให้แน่ใจว่าไม่มีการพยายามดึงภาพที่ไม่จำเป็น

  • หากprefer-cachedระบุไว้รูปภาพจะถูกดึงจากระยะไกลหากไม่มีรูปภาพแคช มิฉะนั้นจะใช้รูปภาพแคชบนอินสแตนซ์ การล้างข้อมูลอิมเมจอัตโนมัติถูกปิดใช้งานสำหรับคอนเทนเนอร์เพื่อให้แน่ใจว่ารูปภาพที่แคชจะไม่ถูกลบออก


5
คุณแน่ใจไหม? ฉันเคยเห็นกรณีที่อิมเมจนักเทียบท่าเก่าทำงานแม้ว่าฉันจะพุชอิมเมจใหม่ไปที่ Dockerhub (โดยใช้ชื่อแท็กเดียวกัน) ฉันเดาว่าบางทีฉันควรจะชนชื่อแท็กทุกครั้งที่สร้างภาพใหม่ อย่างไรก็ตามสิ่งนี้ค่อนข้างหายากในประสบการณ์ของฉันดังนั้นอาจเป็นเพียงปัญหาเครือข่ายชั่วขณะ (ฉันรู้ว่าคุณทำงานกับ ECS ดังนั้นคุณจึงเป็นคนที่ตอบคำถามนี้ได้ดีที่สุด แต่นี่ไม่ใช่สิ่งที่ฉันเคยเจอมาทั้งหมดขออภัยหากสิ่งนี้ดูหยาบคายไม่ใช่ความตั้งใจของฉัน!)
อิบราฮิม

1
ใช่พฤติกรรมปัจจุบันคือจะพยายามดึงทุกครั้ง หากการดึงล้มเหลว (ปัญหาเครือข่ายการขาดสิทธิ์ ฯลฯ ) จะพยายามใช้รูปภาพที่แคชไว้ คุณสามารถดูรายละเอียดเพิ่มเติมได้ในไฟล์บันทึกของเอเจนต์ซึ่งโดยปกติจะอยู่ในไฟล์/var/log/ecs.
Samuel Karp

@SamuelKarp โปรดดูคำตอบของฉัน
Jwf

ฉันเห็นด้วยกับ @Ibrahim ในหลาย ๆ กรณีรูปภาพใหม่ (แม้ว่าจะโหลดลงใน ECR อย่างถูกต้อง) จะไม่ถูกดึงและใช้เมื่อเรียกด้วย run_task () จาก Lambda บันทึก CloudWatch ไม่แสดงข้อผิดพลาด เพียงแค่ยืนยันที่จะใช้ภาพเก่า น่าผิดหวังมาก!
Hephaestus

26

การลงทะเบียนข้อกำหนดงานใหม่และการอัปเดตบริการเพื่อใช้นิยามงานใหม่เป็นแนวทางที่ AWS แนะนำ วิธีที่ง่ายที่สุดคือ:

  1. ไปที่คำจำกัดความของงาน
  2. เลือกงานที่ถูกต้อง
  3. เลือกสร้างการแก้ไขใหม่
  4. หากคุณกำลังดึงอิมเมจคอนเทนเนอร์เวอร์ชันล่าสุดที่มีแท็กล่าสุดอยู่แล้วให้คลิกสร้าง มิฉะนั้นให้อัปเดตหมายเลขเวอร์ชันของอิมเมจคอนเทนเนอร์จากนั้นคลิกสร้าง
  5. ขยายการดำเนินการ
  6. เลือก Update Service (สองครั้ง)
  7. จากนั้นรอให้บริการเริ่มต้นใหม่

บทแนะนำนี้มีรายละเอียดเพิ่มเติมและอธิบายว่าขั้นตอนข้างต้นเหมาะสมกับกระบวนการพัฒนาผลิตภัณฑ์แบบ end-to-end อย่างไร

การเปิดเผยข้อมูลทั้งหมด: บทช่วยสอนนี้มีคอนเทนเนอร์จาก Bitnami และฉันทำงานให้กับ Bitnami อย่างไรก็ตามความคิดที่แสดงในที่นี้เป็นของฉันเองไม่ใช่ความคิดเห็นของ Bitnami


3
วิธีนี้ใช้งานได้ แต่คุณอาจต้องแก้ไขค่าต่ำสุด / สูงสุดของบริการ หากคุณมีอินสแตนซ์ EC2 เพียงอินสแตนซ์เดียวคุณต้องตั้งค่าเปอร์เซ็นต์ที่มีประสิทธิภาพต่ำสุดเป็นศูนย์มิฉะนั้นจะไม่ฆ่างาน (ทำให้บริการของคุณออฟไลน์ชั่วคราว) เพื่อปรับใช้คอนเทนเนอร์ที่อัปเดต
Malvineous

3
@Malvineous จุดดี! ในส่วนการตั้งค่า ECS ของบทช่วยสอนฉันอธิบายอย่างนั้น นี่คือการกำหนดค่าที่แนะนำจากส่วนนั้น: จำนวนงาน - 1, เปอร์เซ็นต์สุขภาพขั้นต่ำ - 0, เปอร์เซ็นต์สูงสุด - 200
Neal

@Neal ฉันลองใช้แนวทางของคุณตามที่ระบุไว้ที่นี่ ... ยังไม่มีความสุข
Hafiz

@Hafiz หากคุณต้องการความช่วยเหลือในการหาข้อมูลนี้คุณควรอธิบายว่าคุณไปได้ไกลแค่ไหนและเกิดข้อผิดพลาดอะไร
Neal

สิ่งนี้ใช้ได้กับบริการเท่านั้นไม่ใช่งานที่ไม่มีบริการ
zaitsman

10

มีสองวิธีในการทำเช่นนี้

ขั้นแรกให้ใช้ AWS CodeDeploy คุณสามารถกำหนดค่าส่วนการปรับใช้สีน้ำเงิน / เขียวในข้อกำหนดบริการ ECS ซึ่งรวมถึง CodeDeployRoleForECS, TargetGroup อื่นสำหรับสวิตช์และ Listener ทดสอบ (ไม่บังคับ) AWS ECS จะสร้างแอปพลิเคชัน CodeDeploy และกลุ่มการปรับใช้และเชื่อมโยงทรัพยากร CodeDeploy เหล่านี้กับคลัสเตอร์ / บริการ ECS ของคุณและ ELB / TargetGroups ให้กับคุณ จากนั้นคุณสามารถใช้ CodeDeploy เพื่อเริ่มการปรับใช้ซึ่งคุณต้องป้อน AppSpec ที่ระบุว่าใช้งาน / คอนเทนเนอร์ใดเพื่ออัปเดตบริการใด ที่นี่คุณระบุงาน / คอนเทนเนอร์ใหม่ของคุณ จากนั้นคุณจะเห็นอินสแตนซ์ใหม่หมุนขึ้นใน TargetGroup ใหม่และ TargetGroup เก่าถูกตัดการเชื่อมต่อกับ ELB และในไม่ช้าอินสแตนซ์เก่าที่ลงทะเบียนกับ TargetGroup เก่าจะถูกยกเลิก

ฟังดูซับซ้อนมาก อันที่จริงเนื่องจาก / ถ้าคุณเปิดใช้งานการปรับขนาดอัตโนมัติในบริการ ECS ของคุณวิธีง่ายๆในการทำก็คือบังคับให้ใช้งานใหม่โดยใช้คอนโซลหรือ cli เช่นสุภาพบุรุษที่นี่ชี้ให้เห็น:

aws ecs update-service --cluster <cluster name> --service <service name> --force-new-deployment

ด้วยวิธีนี้คุณยังคงสามารถใช้ประเภทการปรับใช้ "การอัปเดตแบบต่อเนื่อง" ได้และ ECS จะหมุนอินสแตนซ์ใหม่และระบายอินสแตนซ์เก่าโดยไม่ต้องหยุดให้บริการหากทุกอย่างเรียบร้อย ด้านที่ไม่ดีคือคุณสูญเสียการควบคุมที่ดีในการปรับใช้และคุณไม่สามารถย้อนกลับไปใช้เวอร์ชันก่อนหน้าได้หากมีข้อผิดพลาดและจะทำให้บริการที่กำลังดำเนินอยู่เสียหาย แต่นี่เป็นวิธีง่ายๆที่จะไป

BTW อย่าลืมกำหนดตัวเลขที่เหมาะสมสำหรับเปอร์เซ็นต์สุขภาพขั้นต่ำและเปอร์เซ็นต์สูงสุดเช่น 100 และ 200


มีวิธีทำโดยไม่ต้องเปลี่ยน IP หรือไม่? ในของฉันเมื่อฉันรันมันใช้งานได้ แต่มันเปลี่ยน IP ส่วนตัวที่ฉันใช้อยู่
Migdotcom

@Migdotcom ฉันมีปัญหาคล้ายกันเมื่อต้องการพร็อกซี NLB ในระยะสั้นวิธีเดียวที่จะทำให้ IP อินสแตนซ์ EC2 เหมือนเดิมคือการใช้ที่อยู่ IP แบบยืดหยุ่นหรือใช้วิธีการอื่น ฉันไม่ทราบกรณีการใช้งานของคุณ แต่การเชื่อมโยง Global Accelerator กับ ECS ที่เชื่อมโยง ALB ทำให้ฉันมีที่อยู่ IP แบบคงที่ซึ่งจะช่วยแก้ปัญหาการใช้งานของฉันได้ หากคุณต้องการทราบ IP ภายในแบบไดนามิกคุณจะต้องสอบถาม ALB ด้วยแลมด้า นี่เป็นความพยายามอย่างมาก ลิงค์ด้านล่าง: aws.amazon.com/blogs/networking-and-content-delivery/…
Marcus

aws ecs update-service - คลัสเตอร์ <ชื่อคลัสเตอร์> - บริการ <ชื่อบริการ> - บังคับใช้งานใหม่สำหรับฉัน!
gvasquez

4

ฉันสร้างสคริปต์สำหรับปรับใช้อิมเมจ Docker ที่อัปเดตกับบริการการจัดเตรียมบน ECS เพื่อให้ข้อกำหนดงานที่เกี่ยวข้องอ้างอิงถึงเวอร์ชันปัจจุบันของอิมเมจ Docker ฉันไม่แน่ใจว่าฉันปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดหรือไม่ดังนั้นเรายินดีรับข้อเสนอแนะ

เพื่อให้สคริปต์ทำงานได้คุณต้องมีอินสแตนซ์ ECS สำรองหรือไฟล์ deploymentConfiguration.minimumHealthyPercentค่าเพื่อให้ ECS สามารถขโมยอินสแตนซ์เพื่อปรับใช้นิยามงานที่อัปเดต

อัลกอริทึมของฉันเป็นดังนี้:

  1. อิมเมจแท็ก Docker ที่สอดคล้องกับคอนเทนเนอร์ในนิยามงานด้วยการแก้ไข Git
  2. ดันแท็กอิมเมจ Docker ไปยังรีจิสเตอร์ที่เกี่ยวข้อง
  3. ยกเลิกการลงทะเบียนนิยามงานเก่าในตระกูลนิยามงาน
  4. ลงทะเบียนนิยามงานใหม่ตอนนี้อ้างถึงอิมเมจ Docker ที่ติดแท็กด้วยการแก้ไข Git ปัจจุบัน
  5. อัปเดตบริการเพื่อใช้นิยามงานใหม่

รหัสของฉันวางด้านล่าง:

ปรับใช้ ecs

#!/usr/bin/env python3
import subprocess
import sys
import os.path
import json
import re
import argparse
import tempfile

_root_dir = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
sys.path.insert(0, _root_dir)
from _common import *


def _run_ecs_command(args):
    run_command(['aws', 'ecs', ] + args)


def _get_ecs_output(args):
    return json.loads(run_command(['aws', 'ecs', ] + args, return_stdout=True))


def _tag_image(tag, qualified_image_name, purge):
    log_info('Tagging image \'{}\' as \'{}\'...'.format(
        qualified_image_name, tag))
    log_info('Pulling image from registry in order to tag...')
    run_command(
        ['docker', 'pull', qualified_image_name], capture_stdout=False)
    run_command(['docker', 'tag', '-f', qualified_image_name, '{}:{}'.format(
        qualified_image_name, tag), ])
    log_info('Pushing image tag to registry...')
    run_command(['docker', 'push', '{}:{}'.format(
        qualified_image_name, tag), ], capture_stdout=False)
    if purge:
        log_info('Deleting pulled image...')
        run_command(
            ['docker', 'rmi', '{}:latest'.format(qualified_image_name), ])
        run_command(
            ['docker', 'rmi', '{}:{}'.format(qualified_image_name, tag), ])


def _register_task_definition(task_definition_fpath, purge):
    with open(task_definition_fpath, 'rt') as f:
        task_definition = json.loads(f.read())

    task_family = task_definition['family']

    tag = run_command([
        'git', 'rev-parse', '--short', 'HEAD', ], return_stdout=True).strip()
    for container_def in task_definition['containerDefinitions']:
        image_name = container_def['image']
        _tag_image(tag, image_name, purge)
        container_def['image'] = '{}:{}'.format(image_name, tag)

    log_info('Finding existing task definitions of family \'{}\'...'.format(
        task_family
    ))
    existing_task_definitions = _get_ecs_output(['list-task-definitions', ])[
        'taskDefinitionArns']
    for existing_task_definition in [
        td for td in existing_task_definitions if re.match(
            r'arn:aws:ecs+:[^:]+:[^:]+:task-definition/{}:\d+'.format(
                task_family),
            td)]:
        log_info('Deregistering task definition \'{}\'...'.format(
            existing_task_definition))
        _run_ecs_command([
            'deregister-task-definition', '--task-definition',
            existing_task_definition, ])

    with tempfile.NamedTemporaryFile(mode='wt', suffix='.json') as f:
        task_def_str = json.dumps(task_definition)
        f.write(task_def_str)
        f.flush()
        log_info('Registering task definition...')
        result = _get_ecs_output([
            'register-task-definition',
            '--cli-input-json', 'file://{}'.format(f.name),
        ])

    return '{}:{}'.format(task_family, result['taskDefinition']['revision'])


def _update_service(service_fpath, task_def_name):
    with open(service_fpath, 'rt') as f:
        service_config = json.loads(f.read())
    services = _get_ecs_output(['list-services', ])[
        'serviceArns']
    for service in [s for s in services if re.match(
        r'arn:aws:ecs:[^:]+:[^:]+:service/{}'.format(
            service_config['serviceName']),
        s
    )]:
        log_info('Updating service with new task definition...')
        _run_ecs_command([
            'update-service', '--service', service,
            '--task-definition', task_def_name,
        ])


parser = argparse.ArgumentParser(
    description="""Deploy latest Docker image to staging server.
The task definition file is used as the task definition, whereas
the service file is used to configure the service.
""")
parser.add_argument(
    'task_definition_file', help='Your task definition JSON file')
parser.add_argument('service_file', help='Your service JSON file')
parser.add_argument(
    '--purge_image', action='store_true', default=False,
    help='Purge Docker image after tagging?')
args = parser.parse_args()

task_definition_file = os.path.abspath(args.task_definition_file)
service_file = os.path.abspath(args.service_file)

os.chdir(_root_dir)

task_def_name = _register_task_definition(
    task_definition_file, args.purge_image)
_update_service(service_file, task_def_name)

_common.py

import sys
import subprocess


__all__ = ['log_info', 'handle_error', 'run_command', ]


def log_info(msg):
    sys.stdout.write('* {}\n'.format(msg))
    sys.stdout.flush()


def handle_error(msg):
    sys.stderr.write('* {}\n'.format(msg))
    sys.exit(1)


def run_command(
        command, ignore_error=False, return_stdout=False, capture_stdout=True):
    if not isinstance(command, (list, tuple)):
        command = [command, ]
    command_str = ' '.join(command)
    log_info('Running command {}'.format(command_str))
    try:
        if capture_stdout:
            stdout = subprocess.check_output(command)
        else:
            subprocess.check_call(command)
            stdout = None
    except subprocess.CalledProcessError as err:
        if not ignore_error:
            handle_error('Command failed: {}'.format(err))
    else:
        return stdout.decode() if return_stdout else None

@ แอนดริสขอบคุณแก้ไขแล้ว
aknuds1

5
นี่คือ overkill ควรเป็นไปได้ที่จะปรับใช้ผ่าน Terraform หรือเพียงบรรทัดเดียว ecs-cli
Holms

@holms ฉันใช้ Terraform เพื่ออัปเดตอิมเมจงาน ECS นั่นคือ overkill เหมือนกับ python-code ด้านบน ขั้นตอนที่ต้องการมีความซับซ้อน
Jari Turkia

มากเกินไปจริงๆฉันใส่สคริปต์ง่ายๆในคำตอบของฉันทำในสิ่งที่คำตอบที่ได้รับคะแนนสูงสุดเสนอ ได้ดู.
Jwf

3

AWS CodePipeline

คุณสามารถตั้งค่า ECR เป็นแหล่งที่มาและ ECS เป็นเป้าหมายเพื่อปรับใช้


3
คุณสามารถเชื่อมโยงไปยังเอกสารใด ๆ สำหรับสิ่งนี้ได้หรือไม่
BenDog

3

พบปัญหาเดียวกัน หลังจากใช้เวลาหลายชั่วโมงได้สรุปขั้นตอนที่เรียบง่ายเหล่านี้สำหรับการปรับใช้อิมเมจที่อัปเดตโดยอัตโนมัติ:

1. การเปลี่ยนแปลงนิยามงาน ECS: เพื่อความเข้าใจที่ดีขึ้นสมมติว่าคุณได้สร้างนิยามงานโดยมีรายละเอียดด้านล่าง (หมายเหตุ: ตัวเลขเหล่านี้จะเปลี่ยนไปตามนิยามงานของคุณ):

launch_type = EC2

desired_count = 1

จากนั้นคุณต้องทำการเปลี่ยนแปลงต่อไปนี้:

deployment_minimum_healthy_percent = 0  //this does the trick, if not set to zero the force deployment wont happen as ECS won't allow to stop the current running task

deployment_maximum_percent = 200  //for allowing rolling update

2.Tag ภาพของคุณเป็น < ของคุณภาพชื่อ>: ล่าสุด คีย์ล่าสุดดูแลการดึงโดยงาน ECS ที่เกี่ยวข้อง

sudo docker build -t imageX:master .   //build your image with some tag
sudo -s eval $(aws ecr get-login --no-include-email --region us-east-1)  //login to ECR
sudo docker tag imageX:master <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/<your-image-name>:latest    //tag your image with latest tag

3. ดันภาพไปที่ ECR

sudo docker push  <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/<your-image-name>:latest

4. ใช้การบังคับใช้

sudo aws ecs update-service --cluster <your-cluster-name> --service <your-service-name> --force-new-deployment --region us-east-1

หมายเหตุ: ผมได้เขียนคำสั่งทั้งหมดสมมติภูมิภาคที่จะให้เราตะวันออก-1 เพียงแค่แทนที่ด้วยภูมิภาคของคุณในขณะที่ใช้งาน


ฉันสังเกตว่าพารามิเตอร์เป็นพารามิเตอร์พื้นผิว ความคิดใด ๆ ในการบรรลุสิ่งเดียวกันสำหรับ CloudFormation: ฉันมี AutoScalingGroup MinSize: 0 และ MaxSize: 1; ต้องตั้งค่าอะไรอีก
Wayne

1

สิ่งต่อไปนี้ใช้ได้ผลสำหรับฉันในกรณีที่แท็กรูปภาพนักเทียบท่าเหมือนกัน:

  1. ไปที่คลัสเตอร์และบริการ
  2. เลือกบริการและคลิกอัปเดต
  3. กำหนดจำนวนงานเป็น 0 และอัปเดต
  4. หลังจากการปรับใช้เสร็จสิ้นให้ปรับขนาดจำนวนงานใหม่เป็น 1

0

การใช้ AWS cli ฉันลองใช้บริการอัปเดต ecs ของ AWS ตามที่แนะนำข้างต้น ไม่ได้รับนักเทียบท่ารุ่นล่าสุดจาก ECR ในท้ายที่สุดฉันเปิดใช้งาน Ansible playbook ของฉันที่สร้างคลัสเตอร์ ECS อีกครั้ง เวอร์ชันของนิยามงานถูกชนเมื่อ ecs_taskdefinition รัน แล้วทั้งหมดเป็นสิ่งที่ดี ภาพนักเทียบท่าใหม่ถูกหยิบขึ้นมา

ไม่แน่ใจจริงๆว่าการเปลี่ยนแปลงเวอร์ชันของงานบังคับให้ใช้งานซ้ำหรือไม่หรือว่าเพลย์บุ๊กที่ใช้ ecs_service ทำให้งานโหลดซ้ำ

หากใครสนใจฉันจะได้รับอนุญาตให้เผยแพร่ Playbook เวอร์ชันที่ผ่านการฆ่าเชื้อแล้ว


ฉันเชื่อว่าจำเป็นต้องมีการแก้ไขข้อกำหนดงานเมื่อคุณอัปเดตการกำหนดค่าข้อกำหนดงานจริงเท่านั้น ในกรณีนี้หากคุณใช้รูปภาพที่มีแท็กล่าสุดไม่จำเป็นต้องแก้ไข config? แน่นอนว่าการกำหนดรหัสเป็นแท็กเป็นสิ่งที่ดีและมีการแก้ไขข้อกำหนดงานแยกต่างหากดังนั้นคุณสามารถย้อนกลับได้ แต่ CI ของคุณจะเห็นข้อมูลรับรองทั้งหมดที่คุณใช้สำหรับคอนเทนเนอร์ซึ่งไม่ใช่วิธีที่ฉันต้องการใช้
Holms

0

ฉันกำลังพยายามหาวิธีอัตโนมัติในการทำนั่นคือการผลักดันการเปลี่ยนแปลงไปยัง ECR จากนั้นควรเลือกแท็กล่าสุดโดยบริการ คุณสามารถทำได้ด้วยตนเองโดยการหยุดงานสำหรับบริการของคุณจากคลัสเตอร์ของคุณ งานใหม่จะดึงคอนเทนเนอร์ ECR ที่ปรับปรุงแล้ว


ดูคำตอบของฉันด้านล่าง
Jwf

0

เนื่องจากยังไม่มีความคืบหน้าใด ๆ ที่ฝั่ง AWS ฉันจะให้คุณหลามสคริปต์ง่ายๆที่ว่าทำตามขั้นตอนที่อธิบายไว้ในคำตอบที่สูงจัดอันดับของDimaและซามูเอลคาร์พ

ขั้นแรกให้พุชรูปภาพของคุณไปยัง AWS Registry ECR จากนั้นเรียกใช้สคริปต์:

import boto3, time

client = boto3.client('ecs')
cluster_name = "Example_Cluster"
service_name = "Example-service"
reason_to_stop = "obsolete deployment"

# Create new deployment; ECS Service forces to pull from docker registry, creates new task in service
response = client.update_service(cluster=cluster_name, service=service_name, forceNewDeployment=True)

# Wait for ecs agent to start new task
time.sleep(10)

# Get all Service Tasks
service_tasks = client.list_tasks(cluster=cluster_name, serviceName=service_name)

# Get meta data for all Service Tasks
task_meta_data = client.describe_tasks(cluster=cluster_name, tasks=service_tasks["taskArns"])

# Extract creation date
service_tasks = [(task_data['taskArn'], task_data['createdAt']) for task_data in task_meta_data["tasks"]]

# Sort according to creation date
service_tasks = sorted(service_tasks, key= lambda task: task[1])

# Get obsolete task arn
obsolete_task_arn = service_tasks[0][0]
print("stop ", obsolete_task_arn)

# Stop obsolete task
stop_response = client.stop_task(cluster=cluster_name, task=obsolete_task_arn, reason=reason_to_stop)

รหัสนี้ทำ:

  1. สร้างงานใหม่ด้วยอิมเมจใหม่ในบริการ
  2. หยุดงานเก่าที่ล้าสมัยด้วยภาพเก่าในบริการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.