이 포스트는 실시간으로 “Fetch & Run” 포스트를 따라하고 일부를 번역하며 작성한 글입니다.

해당 포스트 이후 AWS의 변경점들이 있어 진행방식이 다를 수 있습니다.

진행방식 변경에 따라 해당포스트 대로 진행하면 수많은 에러를 볼 수 있습니다…

해당 포스트를 따라하기 위해서는 AWS계정이 필요하며 비용이 발생할 수 있음을 알려드립니다.

이 포스트는 결과적으로 batch기능을 이용하여 Docker의 실행까지는 성공하지만 Credential제공문제로 실패합니다

라고 적었지****만 결국엔 원인을 찾아서 성공합니다

AWS Batch란

AWS Batch는 Batch방식의 프로그램 실행을 도와주기 위한 서비스입니다.
Batch 처리에 필요한 유동적 계산 Capacity와 Job manager 를 제공합니다.

근데 솔직히 이렇게 봐서는 몰라먹겠어서 역시 직접 해보는게 필요하여 해당 데모를 찾아서 진행하였습니다.

저도 처음 진행하면서 작성하는 포스트다보니 중간에 모르는 용어가 나와도 뒤에 직접 해보면서 과정을 적도록 하겠습니다.

“Fetch & run"의 과정

  • fetch & run스크립트의 도커이미지를 작성한다
  • 이 도커 이미지를 위한 ECR(컨테이너 관리소) 레포지토리를 작성한다.
  • ECR에 도커이미지를 올린다
  • Job script를 작성하여 S3(AWS의 저장고)에 올린다
  • S3접속에 필요한 IAM role(AWS 인스턴스 들의 권한을 관리하기 위한 장치)을 작성한다
  • 만들어진 이미지를 사용하는 Job definition을 작성
  • S3의 Job script를 보내서 실행한다

S3로부터 Job script를 받아와서 실행시켜주는 docker이다.

사전조건

  • Docker 환경 구축
  • AWS CLI의 설치
  • AWS CLI의 profile 작성

Docker image 작성

Docker에 필요한 파일은 깃허브링크 의 압축을 풀어서 ‘fetch-and-run’ 폴더 내부에 있다.

  • Dockerfile
  • fetch_and_run.sh
  • myjob.sh

의 파일이 있다.

WSL2 + Docker 환경에서 다음과 같은 명령어를 입력한다.

docker build -t awsbatch/fetch_and_run .
[+] Building 29.0s (5/8)
 => [internal] load build definition from Dockerfile                                                               0.0s
[+] Building 31.6s (9/9) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 233B                                                                               0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/amazonlinux:latest                                             10.5s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 4.41kB                                                                                0.0s
 => [1/4] FROM docker.io/library/amazonlinux:latest@sha256:05c170879b6dec01ee51dd380d4d63cfb9ba59e738a03531c7ab59  6.3s
 => => resolve docker.io/library/amazonlinux:latest@sha256:05c170879b6dec01ee51dd380d4d63cfb9ba59e738a03531c7ab59  0.0s
 => => sha256:05c170879b6dec01ee51dd380d4d63cfb9ba59e738a03531c7ab5923515af3b4 547B / 547B                         0.0s
 => => sha256:05295e83275444cae0e55601f6a545b548fd3e03e8ef9a4ab9c38a52071519b8 529B / 529B                         0.0s
 => => sha256:d99c40d6547efd6328851315f5bcf7e6a8e0a96c200583a445fc0cdcd2146b81 1.48kB / 1.48kB                     0.0s
 => => sha256:5263c4cb36ce7acd05658a221ec502b376a281d7a6075ad09beb23ac02a7668c 61.98MB / 61.98MB                   3.0s
 => => extracting sha256:5263c4cb36ce7acd05658a221ec502b376a281d7a6075ad09beb23ac02a7668c                          2.7s
 => [2/4] RUN yum -y install which unzip aws-cli                                                                  12.8s
 => [3/4] ADD fetch_and_run.sh /usr/local/bin/fetch_and_run.sh                                                     0.0s
 => [4/4] WORKDIR /tmp                                                                                             0.0s
 => exporting to image                                                                                             1.9s
 => => exporting layers                                                                                            1.9s
 => => writing image sha256:0d521eee532a293289bd4c32ad97efd92906de0096d21493f5523eedbcac5224                       0.0s
 => => naming to docker.io/awsbatch/fetch_and_run                                                                  0.0s

환경에 따라 다를 수는 있는데 다음과 같이 build가 완료된다.

확인을 위해서는

docker images

를 입력 후 awsbatch/fetch_and_run 이라는 image가 있는지 확인

ECR 만들기

Amazon Elastic Container Registry 콘솔에 접속하여 Get Started를 누른다

다른설정은 그대로 두고 ( 또는 필요에 따라 바꾸고 ) Repository name에 awsbatch/fetch_and_run 또는 docker build시 사용한 태그 명을 입력하여 만든다.

해당 Repository로 부터 View push commands를 확인하여 해당 command대로 진행한다

! 설치후 profile이 설정된 aws cli환경이 필요하다.

Docker는 이미 build되어있는 이름을 쓰면 괜찮다.

ecr.ap-northeast-1.amazonaws.com/aws_batch_test]
5f70bf18a086: Pushed
848391deae52: Pushed
852e9b5e7cd8: Pushing [===============================>                   ]  221.5MB/355.5MB
f490e82668a1: Pushing [============================================>      ]  145.9MB/163.7MB

열심히 docker image파일이 올라가고있다. 역시 이 작업들도 귀찮으니 나중에 포스트 정리하면서 serverless frame work를 활용하여 자동화 하는 방법을 공부해야겠다.

Repository에 image가 추가되었다.

S3에 Job script 업로드하기

s3 bucket을 생성하자

이름만 설정하고 나머지 설정들은 default상태로 bucket을 작성한다. Bucket name이 유니크해야 하기에 뒤에 숫자를 추가하였다. 6자리라고 제 은행비밀번호거나 그런건 아니다 진짜 랜덤이다.

aws CLI를 활용하여 다음 명령어로 옮겨도 좋고 직접 upload해도 좋다

aws s3 cp myjob.sh s3://<bucket_name>/myjob.sh

IAM 작성

Job 을 정의하기에 앞서 그 Job이 외부 인스턴스에 어떠한 권한을 가지는지 정의하는 IAM role의 작성이 필요하다.

이번에는 S3로 부터 Job script를 가져와야한다.

IAM -> Roles -> Create Role을 통해 Role생성화면에 접속한다. ( 회사 계정이라 이 과정을 캡쳐할 수는 없었다.)

이 화면에서 아래 Or select a service… 부분에서 Elastic Container Service를 선택한 후 case에서 Elastic Container Service Task를 선택한다.

이후 S3ReadOnlyAccess를 부여한다.

그리고 AWS Cloud watch 권한을 부연한다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ]
        }
    ]
}

IAM 권한부여는 최소한이면 좋다.

Tag는 스킵하고 이름을 부여하여 role작성을 완료했다.

Job 정의하기

드디어 batch콘솔에 들어 갈 단계다. 왼쪽의 Job definitions에서 Create 를 들어가 원하는 이름 Platform은 아주 단순한 작업이기에 일단은 Fargate를 사용한다. 정확한 사용의 구별은 유튜브 에 나오나 일본어영상이다.. 자동 자막도 퀄리티가 괜찮다.

Job attempts 는 1 timeout 60

중요한 부분은 Container properties이다.

우선 image에다가는 ECR에서 작성한 이미지의 링크를 첨부한다.

ECR에서 이렇게 복사가 가능하다.

다음 Command syntax는 Bash에서 myjob.sh 60 vCpu와 Memory할당은 최소로 줄여서 비용을 최소화하자. 이건 Test용이니 많은 성능을 줄 필요가 없다. Execution Role에는 전에 작성한 S3 ReadOnly가 있는 IAM을 선택한다.

우선 Assign public IP도 활성화 시킬 필요가 있다.

fetch_and_run.sh 의 코드를 보면 다음 2가지의 환경변수가 지정이 필요한 것을 알 수 있다

  • BATCH_FILE_TYPE
  • BATCH_FILE_S3_URL

이 환경 변수는 Additional configuration에서 Environment variables에 입력해줘야한다.

Job role에 아래 사진에는 비어있지만 꼭 S3권한이 있는 IAM role을 추가해주자

Job생성이 완료되었다.

Compute environments 생성

기본 설정에서 이름만 지정한 뒤에 혹시 모를 폭주를 막기 위해 vCPUs를 1로 하고 적당히 subnet을 지정해서 생성하자

Job definition을 fargate로 했기 때문에 여기서도 그대로 Fargate를 사용하면 된다.

Job queues 생성

Job definition처럼 Job queues 에 들어가서 이름만 지정해서 생성하면 된다.

compute environment에는 앞서 작성한 환경을 입력한다.

Submit new job! 일해라 일!!

드디어 실행시킬 때다. Job definition에서 작성한 Job definition을 선택 후 Submit new job을 누른다.

이름을 입력하고 Job queue와 timeout과 Job attempts를 설정한다.

다른 설정들이 definition대로 들어와 있는 것을 확인 한 후 submit을 한다.

처음 Computing 환경의 기동에 시간이 걸리니 기다리면 된다.

----- 사실 여기까지는 비교적 금방 진행했다 문제는 에러들이였다—-

물론 그냥 바로 된 분들도 있겠지만 계정이 특수하여 모든 네트워크 제한이 강하게 걸려있어서 당연히 실패했다.

수정하면서 일부 요소들은 위의 포스트에 미리 포함해 뒀으니 만약 그래도 에러가 난다면 점검해보자.

1번에러 : ResourceInitializationError: unable to pull secrets or registry auth: pull command failed: : signal: killed

  • Job definition에서 public ip를 부여했는가?
  • Compute environment가 HTTP통신 (80번포트) 가 열린 security gruop을 사용중인가?
  • 사용 subnet이 public ip를 가지고 있는가?
  • subnet안의 route table이 internet gateway에대한 routing이 되어있는가?
    • internet gateway작성 후 vpc에 부착하여 subnet에서 부착해주자

이 결과! 다음 에러를 만날 수 있었다.

2번에러 : ResourceInitializationError: failed to validate logger args: create stream has been retried 1 times: failed to create Cloudwatch log stream: AccessDeniedException:

사용 IAM에 해당 링크 를 따라 cloudwatch log 권한을 부여했다

3번에러 : Essential container in task exited - 환경변수

Q. 맨날 그렇게 에러나면 안 짜증나요? A. 에러코드가 바뀌는게 어디에요 그것만으로도 행복합니다

일단 여기서는 status가 running으로 빛나줬다. 이것만으로도 너무 기뻤다 ㅜㅜ

Docker를 가져와서 실행해서 그 안에서 에러가 발생했다는 뜻이다. 거의 다 왔다는게 느껴졌다.

이런 모호한 에러에서 가장먼저 확인해야할 것은 로그이다.

Cloud watch 에서 로그를 보니 실행은 했으니 환경변수의 위치가 틀렸는지 적용이 안되어있었다.\

처음에는 Parameters 에 입력했으나 여기는 환경변수를 입력하는 곳이 아니다.

시즌 7호 revision 등장~

4번에러 : Essential container in task exited - s3 credential 오류

download failed: s3://awsbatchtest134679/myjob.sh to - Unable to locate credentials

error_exit "Failed to download S3 script.
fetch_and_run.sh - Failed to download S3 script.

아무래도 스크립트의 이 부분인 것 같다. docker 내부에서 aws cli의 credential을 다시한번 설정할 필요가 있어보인다

8호 revision!

실패

이럴꺼면 IAM에 S3는 왜 넣은거야!!!

해서 포기하려 했지만

Execution Role과 Job role이 별개라서 Job role에 IAM을 추가하여 해결했다