Amazon ECS에서 서비스 컨테이너 업데이트


32

Amazon ECS에서 실행중인 서비스 컨테이너를 업데이트하는 데 어떤 종류의 접근 방식이 권장됩니까?

AWS 문서는 말한다 : "당신이 응용 프로그램의 도커 이미지를 업데이트 한 경우, 해당 이미지와 새 작업 정의를 생성하고 서비스를 한 번에 하나 개의 작업에 배포 할 수 있습니다." 이것은 현재 문서 (2015 년 4 월 13 일)에서 사용할 수있는 거의 모든 것입니다.

Amazon ECS에서 애플리케이션 컨테이너를 업데이트 할 수있는 유일한 방법은 새 작업을 생성 한 다음 이전 작업을 중지하고 새 작업을 시작하는 것입니다.

Core OS & Fleetctl과 함께 "최신"태그를 성공적으로 사용했습니다. 서비스를 다시로드하면 새로운 변경 사항이 표시되고 컨테이너가 "최신"같은 태그를 사용하여 업데이트되므로 Docker 이미지의 태그를 변경할 필요가 없다는 이점이 있습니다.

Amazon ECS에서 업데이트 된 도커 이미지로 서비스를 업데이트하는 데 사용한 접근 방식은 무엇입니까?


또한 프로덕션 환경에서 지속적으로 실행해야하는 다양한 데몬을 배포하기 위해 ECS를 사용하고자하므로이를 파악하려고 노력하고 있습니다.
parent5446

1
확인하기 위해 ecs 서비스를 다시 시작하면 최신 버전의 이미지가 다운된다고 말했습니까? 나는 이것에 관한 문서를 찾고 있었고 그것을 어디서나 찾을 수 없다.
mmilleruva

1
이것에 대한 확인?
Lior Ohana

@LiorOhana 슬프게도 사실입니다. 자세한 내용은 내 답변을 참조하십시오.
hamx0r

아래에 새로운 자세한 답변을 게시했지만 여기에서 명확하게 설명합니다. 서비스에서 설정 한 태그를 기준으로 항상 리포지토리에서 컨테이너의 새로운 사본을 가져 오려고 시도합니다. 작업이 살해되면 서비스가 다시 배포 할 때, 그것은 무엇을 전혀 기억이 없습니다 했다 만 무엇 REPO에 있다 REPO에 있습니다.
MrDuk

답변:


18

이것이 버려진 질문으로 간주되는지 확실하지 않습니다-내 문제를 해결하고 이제 해결 된 솔루션을 추가하는 동안이 문제가 발생했습니다.

새 컨테이너로 서비스를 업데이트하려면 다음을 수행해야합니다.

  1. 저장소에 새 컨테이너를 업로드하십시오.
  2. 작업 정의 업데이트 트리거;
  3. 컨테이너 업데이트 트리거;
  4. 중요 : 서비스 규칙이 새 버전의 작업을 시작할 수 있도록하십시오.

서비스 작업이 최신 버전으로 업데이트되지 않은 경우 "이벤트"탭에서 오류를 확인하십시오. 예를 들어 ECS에서 새 버전의 서비스를 시작할 수 없었을 수 있습니다. 클러스터에 하나의 ec2 인스턴스 만 있고 응용 프로그램 포트가 이미 호스트에서 사용되었습니다. 이 경우 "최소 건전성 / 최대 건전성"제한을 "0 %, 100 %"로 설정하십시오. 이렇게하면 ECS가 새 컨테이너를 배포하기 전에 기존 컨테이너를 종료하도록 선택합니다. 이 과정은 몇 분에 걸쳐 이루어집니다. 즉각적인 피드백이 없다면 서두르지 마십시오.

아래는 사전 구성된 클러스터 및 서비스에서 컨테이너를 업데이트하는 배포 스크립트의 예입니다. "가족으로부터 최신 사용"을 의미하는 경우 버전을 지정할 필요가 없습니다.

awsRegion=us-east-1
containerName=..
containerRepository=..
taskDefinitionFile=...
taskDefinitionName=...
serviceName=...


echo 'build docker image...'
docker build -t $containerName .

echo 'upload docker image...'
docker tag $containerName:latest $containerRepository:$containerName
docker push $containerRepository:$containerName

echo 'update task definition...'
aws ecs register-task-definition --cli-input-json file://$taskDefinitionFile --region $awsRegion > /dev/null

echo 'update our service with that last task..'
aws ecs update-service --service $serviceName --task-definition $taskDefinitionName --region $awsRegion  > /dev/null

2
이것은 로컬로 파일로 작업 정의를 갖도록 강요하며 올바르게 이해하면 환경 변수를 정의 할 수있는 유일한 곳입니다. 환경 변수를 로컬로하지 않고이를 수행 할 수있는 방법이 있습니까? 이상적으로 나는 작업 / 서비스 / 컨테이너 등에 대한 다른 정보를 보내지 않고 새로운 도커 이미지 태그를 가리 키도록 명령을 내리고 싶습니다.
rmac

1
에 대한 의견 set "min health/max health" limits to "0%, 100%"은 황금입니다. 정말 고맙습니다!
sivabudh

1
여기주의의 말씀, 당신은 당신이 설정 한 경우 min0%당신이 작업 정의를 서비스 전개함에을 변경하면, 당신은 기본적으로 아래로 가지고 그것을 전체 권한을 부여하고 모든 것을 배포 동시에 작업을.
MrDuk


1

개선 사항으로 ecs-deploy 스크립트의 일부를 사용합니다 (모든 컨테이너 설명에서 이미지를 가져 와서 태그 부분을 $ TAG_PURE로 바꿉니다) : https://gist.github.com/Forever-Young/e939d9cc41bc7a105cdcf8cd7ab9d714

# based on ecs-deploy script
TASK_DEFINITION_NAME=$(aws ecs describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition)
TASK_DEFINITION=$(aws ecs describe-task-definition --task-def "$TASK_DEFINITION_NAME" | jq '.taskDefinition')
NEW_CONTAINER_DEFINITIONS=$(echo "$TASK_DEFINITION" | jq --arg NEW_TAG $TAG_PURE 'def replace_tag: if . | test("[a-zA-Z0-9.]+/[a-zA-Z0-9]+:[a-zA-Z0-9]+") then sub("(?<s>[a-zA-Z0-9.]+/[a-zA-Z0-9]+:)[a-zA-Z0-9]+"; "\(.s)" + $NEW_TAG) else . end ; .containerDefinitions | [.[] | .+{image: .image | replace_tag}]')
TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq ".+{containerDefinitions: $NEW_CONTAINER_DEFINITIONS}")
# Default JQ filter for new task definition
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions"
# Some options in task definition should only be included in new definition if present in
# current definition. If found in current definition, append to JQ filter.
CONDITIONAL_OPTIONS=(networkMode taskRoleArn)
for i in "${CONDITIONAL_OPTIONS[@]}"; do
  re=".*${i}.*"
  if [[ "$TASK_DEFINITION" =~ $re ]]; then
    NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
  fi
done

# Build new DEF with jq filter
NEW_DEF=$(echo $TASK_DEFINITION | jq "{${NEW_DEF_JQ_FILTER}}")
NEW_TASKDEF=`aws ecs register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`

echo "New task definition registered, $NEW_TASKDEF"

aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition "$NEW_TASKDEF" > /dev/null

echo "Service updated"

링크 로트를 제공하기 위해 답변의 링크에서 유용한 정보를 제공하는 것이 좋습니다. 당신은 그렇게 할 수 있습니까?
BE77Y

1
내 답변을 업데이트
ForeverYoung

1

새 Docker 이미지를 업로드 한 후 작업에 사용 된 것과 동일한 태그가 있더라도 최신 작업을 복사 한 다음 새 작업을 사용하도록 서비스를 구성해야합니다. 선택적으로 Docker Image가 업데이트 될 때마다 두 개의 중복 작업을 수행하고 서비스가 서로 전환되도록 구성 할 수 있습니다.

기본적으로 ECS에서 새 Docker 컨테이너를 만들려면 서비스를 업데이트하여 서비스를 트리거해야하며 서비스 트리거를 만드는 유일한 방법은 서비스를 사용하도록 지시하는 것과 같은 방식으로 서비스를 업데이트하는 것입니다. 다른 작업 번호.

기존에 실행중인 컨테이너는 서비스가 업데이트 되었기 때문에 자동으로 중지되지 않을 수 있습니다. 작업 목록을보고 수동으로 중지해야 할 수도 있습니다.


이것은 실제로 사실이 아닙니다 . 서비스에 의존하는 대신 항상 수동으로 작업을 종료 할 수 있습니다. 서비스가 종료 된 것을 발견하면 서비스를 다시 가져 와서 다시 가져 오려고 시도합니다.tag
MrDuk

1

나에게 맞는 접근법은 위와 비슷합니다. 서비스 및 작업을 생성하고 모든 작업을 시작한 후 Auto-Scaling 그룹을 편집하고 min , maxdesired1 로 설정되어 있는지 확인하십시오 .

그룹이 기본 그룹 일 수 있습니다. 확실하지 않은 경우 클러스터에서 ECS 인스턴스 탭 을 선택하여 액세스 할 수 있습니다 . 작업 드롭 다운에서 클러스터 리소스를 선택 하고 열리는 대화 상자의 하단 근처에있는 링크를 클릭하십시오.

모든 것이 완료되면 업데이트 된 컨테이너 이미지를 배포 할 때마다 클러스터 의 작업 영역으로 이동하여 작업중지 하십시오 . 경고 메시지가 표시되지만 자동 확장이 설정되면 서비스는 최신 푸시로 다시 시작됩니다.

서비스 또는 작업의 새 버전을 만들 필요가 없습니다.

서비스 / 태스크는 즉시 1 분 정도 이내에 어디서나 업데이트됩니다. 필사적으로 기다리는 경우 새 작업을 수동으로 실행하면됩니다. 이 서비스는 서비스를 소유하지 않으므로 이상적이지는 않지만 서비스가 중단되면 새로운 서비스가 계속 제공됩니다.


1

나는 이것이 오래된 스레드라는 것을 알고 있지만 해결책은 여기의 대부분의 대답보다 훨씬 쉽습니다.

실행중인 컨테이너를 두 단계로 업데이트하는 방법 :

아래는 컨테이너가 태그 된 컨테이너 latest(또는 전체 컨테이너 업데이트를 변경하지 않는 다른 정적 태그)를 참조하는 작업을 실행하는 서비스가 있다고 가정합니다 .

  1. 새 컨테이너를 저장소에 업로드
  2. 작업을 수동으로 종료

목표가 우리가 야생에 새로운 빌드를 제공하는 것이라면, 우리는 실제로 그것을 위해 우리의 서비스에 의존 할 필요가 없습니다 (그리고 나는 그것에 의존 해서는 안된다고 주장 합니다). 작업을 종료하면 서비스에서 Desired Count실행중인 작업 이 없음을 인식 하고 새 작업을 시작합니다. 동일한 태그를 기준으로 컨테이너가 다시 당겨집니다.

ECS 서비스는 CD / CI 파이프 라인을 대체 하지 않고 HA 보안 네트워크 입니다.


보너스 : 목표가 태그에 관계없이 새 컨테이너가 푸시되었다는 것을 서비스에 알리는 것이 목표 인 경우 그 의미를 고려해야합니다. 배포 파이프 라인을 제어하는 ​​기본 서비스를 원하십니까? 아마 아닐 것입니다. 이상적으로는 릴리스 버전 등을 기반으로 다른 태그로 컨테이너를 푸시합니다. 이 경우 배포의 장벽은 서비스에 새로운 무언가를 통보해야한다는 것입니다. 다시 말해서 서비스의 안전망이자 그 이상은 아닙니다.


세 단계로 새 태그를 배포하는 방법 :

  1. 새로운 container:tag저장소에 업로드
  2. 새로운 것을 참조하는 새로운 작업 정의를 만듭니다 tag
  3. 새 작업 정의를 참조하도록 서비스를 업데이트하십시오.
    • 조심해! 다른 답변에서 제안한대로 minimum healthy설정 한 경우 0%새 작업 정의를 배포하기 위해 전체 서비스를 종료 할 수있는 전체 권한을 AWS에 부여합니다. 롤링 / 점진적 배포를 선호하는 경우 최소값을 무언가로 설정하십시오 >0%.
    • 또는 이전 작업을 종료하기 전에 서비스에서 작업 을 배포 할 수 있도록 minimum healthyto 100%와 your maximum healthy를 설정하십시오 (사용자에게 미치는 영향 최소화).>100%

이 시점에서 서비스는 사용자가 새 작업을 지정했음을 자동으로 인식하고 구성한 minimum/ maximum정상 임계 값을 기반으로 해당 작업을 배포 합니다.


좋은, 감사,보다 더 나은 다른 답변
Olegzandr 덴만
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.