반응형

문제

root 권한이 없는 계정을 통해 ubuntu를 운용하면, code deploy시 생성된 코드의 directory가 'root'로 변경되어 code deploy가 실패하거나(code deploy 후, build 디렉토리 소유자가 root로 변경되었다.), 해당 디렉토리 내의 특정 작업들이 제한된다. 

이에 따라, codedeploy >> appspec.yml >> hooks 부분 script >> 해당 디렉토리에서 추가 작업(ex. log directory 생성)이 있을 경우, code deploy가 실패된다.

메시지
Script at specified location: ./script/start.sh run as user jane failed with exit code 1

왜?? start.sh에는 ecosystem.json을 호출하여 nodejs 코드를 띄워주는데 

ecosystem.json에서 error와 out log를 쌓는 디렉토리를 생성한다.

그런데, /home/jane/build 디렉토리 소유자는 root이므로, 'jane' 권한은 폴더를 만들 수 없기 때문에 실패한다.

 

원리

답은 service codedeploy-agent status에 있다.

이 코드는 아래 Loaded와 같이 /etc/init.d/codedeploy-agent에서 돌아가는데,

/etc/init.d/codedeploy-agent 소유자(그룹)는 2450, users다.

codedeploy-agent

하지만 이런 건 다른 데에도 분명 영향이 있어서 함부로 바꾸면 안된다.

구글링을 통해 찾자.

찾았다.

루트 프로파일 이외의 사용자 프로파일을 사용하여 CodeDeploy 에이전트를 실행하려면 어떻게 해야 하나요?

https://aws.amazon.com/ko/premiumsupport/knowledge-center/codedeploy-agent-non-root-profile/

 

루트 이외의 프로파일로 CodeDeploy 에이전트 실행

6.    다음 명령을 실행하여 어떤 프로세스가 실행 중이며, 어느 사용자가 해당 프로세스를 실행 중인지 확인합니다.

aws.amazon.com

 

해결

ubuntu@ip-192-168-23-61:/etc/init.d$ sudo service codedeploy-agent stop

 

// /etc/init.d/codedeploy/agent에 있는 ""를 "jane"으로 변경. (CodeDeploy agent를 수행할 non-root 계정)

ubuntu@ip-192-168-23-61:/etc/init.d$ sudo sed -i 's/""/"jane"/g' /etc/init.d/codedeploy-agent

 

// 변경 여부 확인. CODEDEPLOY_USER에 "jane"이 추가되었다.

ubuntu@ip-192-168-23-61:/etc/init.d$ vi /etc/init.d/codedeploy-agent

// /opt/codedeploy/agent에 있는 모든 파일들의 소유자/그룹을 jane:jane으로 변경한다.

ubuntu@ip-192-168-23-61:/usr/lib/systemd/system$ sudo chown jane:jane -R /opt/codedeploy-agent

ubuntu@ip-192-168-23-61:/usr/lib/systemd/systemsudo chown jane:jane -R /var/log/aws/

 

// 확인해보자. 진짜 다 바뀌었다.

ubuntu@ip-192-168-23-61:/usr/lib/systemd/system$ cd /opt/codedeploy-agent/

ubuntu@ip-192-168-23-61:/opt/codedeploy-agent$ ll

total 56

drwxr-xr-x 8 jane jane  4096 Jul  5 14:29 ./

drwxr-xr-x 4 root root  4096 Jul  4 15:35 ../

-r--r--r-- 1 jane jane    38 Apr 16  2021 .version

-rw-r--r-- 1 jane jane   353 Mar 23  2021 Gemfile

-rw-r--r-- 1 jane jane 10174 Mar 23  2021 LICENSE

drwxr-xr-x 2 jane jane  4096 Jul  4 15:35 bin/

drwxr-xr-x 2 jane jane  4096 Jul  4 15:35 certs/

-rw-r--r-- 1 jane jane  1158 Mar 23  2021 codedeploy_agent.gemspec

drwxr-xr-x 6 jane jane  4096 Jul  5 18:13 deployment-root/

drwxr-xr-x 4 jane jane  4096 Jul  4 15:35 lib/

drwxr-xr-x 3 jane jane  4096 Jul  4 15:35 state/

drwxr-xr-x 4 jane jane  4096 Jul  4 15:35 vendor/

 

jane@ip-192-168-23-61:/var/log$ cd aws

jane@ip-192-168-23-61:/var/log/aws$ ll

total 12

drwxr-xr-x  3 jane jane   4096 Jul  4 15:35 ./

drwxrwxr-x 10 root syslog 4096 Jul  6 15:25 ../

drwxr-xr-x  2 jane jane   4096 Jul  6 00:00 codedeploy-agent/

 

그리고 /etc/init.d의 codedeploy-agent.service 또한 User를 jane으로 입력해주자. 

(그렇지 않으면, 서비스는 여전히 root로 돈다)

 

이제 codedeploy-agent를 다시 실행하면 된다. (sudo는 빼자)

sudo service codedeploy-agent start
sudo service codedeploy-agent status

 

여기까지 하면, ps aux를 통해 codedeploy-agent가 띄워지는 권한이 root -> jane으로 변경된 것을 확인할 수 있다.

 

 

+ 그리고, appspec.yml에서 hook쪽에 runas가 있다면 이번엔 아래와 같은 에러가 발생한다.
[stderr]su: must be run from a terminal

 

이는 appspec.yml의 hooks 쪽에 있는 runas를 빼주면 된다

(runas가 실행권한과 다르면 상관없는데, agent를 동작시키는 권한과 같을 경우 에러가 발생한다)

 

반응형
반응형

지난 포스팅에 이어, 이번에는 Codedeploy 설정을 진행한다.

1. CodeBuild 설정

2. Codedeploy 설정: 이번 포스팅

3. EC2 Ubuntu 설정

 

 

Codedeploy에서 deploy에 사용할 애플리케이션(Jane-codedeploy)을 생성한다. 

플랫폼은 EC2/온프레미스를 설정하면 끝난다.

 

애플리케이션 생성 후엔 '배포 그룹'에서 실제로 이 code deploy가 어떤 인스턴스에 배포될지 설정한다.

나는 EC2에 배포를 할 것이고, EC2 중에서도 어떤 인스턴스에 배포할지는 인스턴스에 설정된 '태그'를 통해 코드가 배포된다.

(난 Service:Test 태그를 설정했다.)

codedeploy의 배포그룹 구성
코드를 배포할 ec2 인스턴스의 태그

 

 

그리고, codedeploy-agent를 ec2에 설치하면 된다.

나는 ubuntu용 ec2이므로 아래 링크를 참고했고, 들어가보면 윈도우 등 다양한 옵션이 있다.

 

* Codedeploy agent 설치

1. ruby 설치: Codedeploy agent는 ruby로 작성되었으므로 이를 설치한다.

$ sudo apt-get install ruby  // (ubuntu 16.04)

 

2. wget 설치 (agent 설치파일을 들고오기 위해 쓰인다)

$ sudo apt-get install wget

 

3. Codedeploy Agent 설치

# 나는 jane계정을 사용하므로 /home/jane이며, ubuntu 계정을 사용한다면 /home/ubuntu로 가면 된다.

$ cd /home/jane

 

# 설치파일 다운로드 (Seoul region) 

$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install

 

# 실행권한 추가 및 설치

$ chmod +x ./install

$ sudo ./install auto

 

하다가 막힌다면 아래 aws docs를 참고한다.

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html

 

Ubuntu Server용 CodeDeploy 에이전트 설치 - AWS CodeDeploy

출력을 임시 로그 파일에 쓰는 것은 Ubuntu 20.04에서 install 스크립트를 사용하여 알려진 버그를 해결하는 동안 사용해야 하는 해결 방법입니다.

docs.aws.amazon.com

 

* Codedeploy agent 서비스 확인

$ sudo service codedeploy-agent status

* ubuntu 계정이 아닌, jane과 같이 별도의 root권한이 아닌 계정을 사용한다면 추가 설정이 필요하다. 

그렇지 않으면, codedeploy-agent가 root로 돌기 때문에(위 캡쳐본에 /etc/init.d/codedeploy/agent에서 돌고 있다),

코드가 배포되는 디렉토리가 root가 되어 추후 다른 문제들을 야기시킨다. 이는 별도로 포스팅 했으니 여기 참고!

https://countrymouse.tistory.com/entry/awscodedeployerr

 

[AWS] root 이외 계정에서 codedeploy 실행, codedeploy 'run as user jane failed with exit code 1', '[stderr]su: must be ru

문제 root 권한이 없는 계정을 통해 ubuntu를 운용하면, code deploy시 생성된 코드의 directory가 'root'로 변경되어 code deploy가 실패하거나(code deploy 후, build 디렉토리 소유자가 root로 변경되었다.),..

countrymouse.tistory.com

 

 

그리고, codedeploy 설정을 끝냈으니 codepipeline으로 돌아와서, '배포'부분에 codedeploy에서 만든 deploy를 추가해준다.

입력 아티팩트는 codebuild의 output이었던 BuildArifact이고, 애플리케이션은 codedeploy에서 만들었던 Jane-codedeploy,

배포 그룹은, jane-codedeploy에서 만들어줬던 jane-codedeploy이다.

 

 

그리고, codedeploy에는 appspec.yml이 필요한데, 이는 아래와 같이 작성했다.

appspec.yml

files: source, destination, runas

files은 source: / 내 파일들을 ec2의 destination( /home/jane/build/)로 옮긴다.

즉, build에서 산출된 artifacts의 모든 것들을 ec2의 /home/jane/build/로 옮긴다. (/home/jane/build/ 디렉토리는 생성시켜두자)

그리고, 그 동작은 'jane'이 run 한다.

 

permissions: 

복사한 파일들의 객체들은 모두(pattern: "**") owner/grp을 'jane'으로 준다.

근데, 이미 위에서 말한  "jane과 같이 별도의 root권한이 아닌 계정을 사용한다면 추가 설정이 필요하다. " 를 했으므로,

이 permission은 생략해도 된다.

 

hooks:

deploy는 아래 각 절차(hooks)마다 하나 이상의 스크립트를 통해 변수선언, 환경설정 등을 할 수 있는데

나는 간단한 코드를 올렸으므로 applicationStart에만 code를 실행시키는 간단한 event를 만들었다.

https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html

 

start.sh

pm2로 nodejs 코드를 띄우는 sh이다. (pm2 reload ecosystem.json이 메인)

6번째 줄까지는 안 해도 된다. 나는 각 절차가 궁금해서 찍어봤다.

ecosystem.json

/home/jane/build 디렉토리에 있는 index.js를 실행한다. 

코드가 변경되는지 watch==true를 통해 확인하며, error_file, out_file이 쌓이는 위치를 지정해주었다.

 

이 모든 파일은(appspec,yml, scosystem.json, start.sh 등) 코드와 같이 git에 올리면 된다 :)

 

반응형
반응형

CI/CD 구축을 위한 단계

  0. ECS fargate 생성 (Cluster, Service, task-definition, task)

1-1. Bitbucket에 코드 업로드 (git)

1-2. Bitbucket <-> slack 연동 (PR 알람 노티를 위함)

2-1. Bitbucket <-> AWS API Gateway 연동 with Webhook

2-2. API gateway -> Lambda 호출

3. Lambda -> S3로 패키지 업로드

4. AWS Codepipeline: S3 -> Codebuild + ECR 연동

5. Codebuild -> Deploy(ECS fargate)

6. ECS <-> LB(ALB) 연동하여 동작 테스트


다 왔다. 이제 마지막 단계인 Deploy 단계이다.

이전 포스팅 (4. Codebuild + ECR 연동)에서 빌드 스테이지까진 만들어 두었으므로, 이번엔 배포 스테이지를 만들어 본다 :)

 

 

이전 포스팅에서 만들어 두었던 코드 파이프라인을 편집해서 Deploy 작업 그룹을 추가한다.

 

작업공급자는, Codedeploy가 아닌 Amazon ECS를 사용한다.

왜냐면, ECS의 fargate에 배포를 할 거고, container를 관리해주는 서비스 자체가 ECS이므로.

 

그래서, Deploy의 입력 아티팩트는, Build에서 저장했던 imagedefinitions.json이 되므로 BuildArtifact로 설정한다.

그리고 클러스터 및 서비스는 이 포스팅 0편에서 다뤘던, ECS의 클러스터/서비스를 선택한다.

이미지 정의 파일은 codebuild에서 buildspec.yml으로 언급한 imagedefinitions.json으로 설정한다.

 

그럼 codepipeline 작업은 다 끝났다.

이제 소스코드가 정말 pr merge 되었을 때 cicd pipeline이 동작하는지 테스트를 해보자.

 

 

1. bitbucket에서 PR Merge를 호출한다.

 

2. slack으로 PR merge에 대한 webhook이 수신된다.

 

 

3. API gateway -> Lambda -> S3에 source 코드가 업로드 되고, Build가 진행된다.

 

 

 

4. Codebuild가 완료된다.

 

 

5. Deploy가 진행된다.

 

 

ECS 컨테이너로 와 보면, 기존엔 컨테이너가 1개 였는데 2개가 되었다가, 다시 1개가 된다.

 

 

해당 ECS의 서비스에서 이벤트를 봐보면,  새로운 task가 실행된 것이다.

(08:38:35, service Jane-service2 has started 1 tasks task d0~~)

 

롤링 업데이트를 포스팅 0번에서 설정했기 때문에,

새로운 컨테이너가 띄워지고 새 컨테이너가 정상 기동되면 이전 컨테이너가 종료된다.

 

그렇게 Deploy까지 완료되고, slack에서 aws chatbot을 통해 결과까지 받아보았다.

이 결과에 대한 리포트는, 코드 파이프라인의 '알림 규칙 생성'에서 만들 수 있다.

 

Succeeded와 Failed만 선택해야 알람이 깔끔하게 온다.

started까지 선택하면, 절차마다 started 라는 알람이 한 번 더 오기 때문에

그냥 결과에 대해서만(succeeded, failed) 설정하는 게 깔끔하다.

 

 

여기까지 ci/cd Pipeline 구축 완료!

반응형

+ Recent posts