배포를 배포답게! - 배포 시스템 개선하기 (4)
안녕하세요, 렌딧 Engineering 팀의 Sam입니다.
배포를 배포답게 시리즈 마지막 글에서는 앞서 소개했던 문제점 중 5번을 해결한 방법에 대해 적어보려고 합니다.
- 1편 - 렌딧의 기존 배포 시스템: Travis + CodeDeploy
- 2편 - 배포 서버 도입 및 편의 기능 추가: Lendit Portal + Nyang Bot
- 3편 - Batch 서버 배포 차단: 마법의 Reflection
- 4편 - CodeDeploy in IDC
이번 글과 AWS CodeDeploy > Register On-Premises Instance 문서를 같이 읽으시면 좋습니다.
문제점 5 - IDC 서버
렌딧 서버는 주로 AWS EC2를 사용합니다. 하지만, 대한민국에서는 법률 규제로 인해 주민등록번호 등 민감한 개인 식별정보나 신용 정보는 AWS에 저장할 수 없습니다. 또한, 신용정보평가사 및 신탁 은행 등과의 시스템 연동 역시 전용 회선이 필요합니다. 따라서, 렌딧은 AWS 외에도 IDC의 서버를 사용하고 있습니다. IDC 서버는 CodeDeploy을 통한 배포 설정이 되어있지 않아 mvn package
와 scp
등의 명령어를 직접 손으로 입력하여 배포하였습니다.
이 귀찮은 문제를 해결하기 위해 IDC에도 CodeDeploy를 도입하였습니다. CodeDeploy agent를 설치하고, 적절한 권한을 가진 사용자의 세션으로 로그인해놓으면 해당 region의 EC2와 같이 CodeDeploy를 사용할 수 있습니다. CodeDeploy agent는 일정 시간마다 AWS에서 polling 하는 방식으로 동작하므로, 대상 서버가 public ip를 가지고 있지 않아도, inbound traffic이 모두 차단되어 있어도 outbound 443/tcp port만 열려있으면 사용할 수 있습니다.
AWS 도움말에서는 다음과 같은 3가지 등록 방법을 소개하고 있습니다.
- register 명령을 사용하는 방법: 편리한 자동화, 한 개의 instance를 등록하는 데 적합합니다.
- register-on-premises-instance 명령을 사용하는 방법: 적은 instance를 등록하는 데 적합하며 instance 당 1개의 user 필요합니다.
- register-on-premises-instance 명령을 STS (Security Token Service)와 함께 사용하는 방법: 많은 instance를 등록하는 데 적합합니다.
렌딧에서는 마지막 방법을 사용하여 IDC에 CodeDeploy를 구성하였습니다. 이 글에서도 마지막 방법으로 진행합니다.
예시로 serial-ABCDEFG이라는 서버를 ap-northeast-2 지역에 등록시키고, idc-01 태그를 붙여보겠습니다. 서버 식별자를 정할 때는 장비의 사용 목적이 변경될 수 있으므로 admin-01이나 web-01과 같이 정하는 것보다 변하지 않는 값을 사용하는 것이 좋습니다. 서버 식별자는 Name 태그와는 달리 한 번 정하면 deregister 후 다시 등록하지 않으면 변경할 수 없으며, deregister는 몇 시간 이상 소요되기 때문입니다.
User, Role 및 Policy 생성
먼저, 배포에 사용할 Role과 Policy를 생성합니다. 이미 CodeDeploy가 EC2에 설정되어 있다면 Role을 그대로 사용할 수 있습니다.
- 다음과 같은 Policy를 생성합니다. 이름은 CodeDeployIDC-Permission으로 하겠습니다.
1
{
2
"Version": "2012-10-17",
3
"Statement": [{
4
"Action": [
5
"s3:Get*",
6
"s3:List*"
7
],
8
"Effect": "Allow",
9
"Resource": "*"
10
}]
11
}
- 위에서 생성한 CodeDeployIDC-Permission을 가진 Role을 생성합니다. 이름은 CodeDeployIDC-Instance-Profile로 하겠습니다.
- 생성된 Role의 ARN이 arn:aws:iam::12345678901:role/CodeDeploy-Instance-Profile이라 가정하겠습니다.
- 이번에는 사용자를 생성하는데 필요한 Policy를 생성합니다. 이름은 CodeDeployIDC-User-Profile로 하겠습니다.
1
{
2
"Version": "2012-10-17",
3
"Statement": [{
4
"Effect": "Allow",
5
"Action": [
6
"codedeploy:*",
7
"iam:CreateAccessKey",
8
"iam:CreateUser",
9
"iam:DeleteAccessKey",
10
"iam:DeleteUser",
11
"iam:DeleteUserPolicy",
12
"iam:ListAccessKeys",
13
"iam:ListUserPolicies",
14
"iam:PutUserPolicy",
15
"iam:GetUser",
16
"tag:GetTags",
17
"tag:GetResources",
18
"s3:*",
19
"sts:AssumeRole"
20
],
21
"Resource": "*"
22
}]
23
}
- 위에서 생성한 CodeDeployIDC-User-Profile을 가진 사용자를 생성합니다. 이름은 CodeDeployIDC-User로 하겠습니다.
- Access key를 발급받습니다. 이 사용자는 on-premises instance를 등록하고 STS 토큰을 요청하는 데 사용됩니다.
- CodeDeployIDC-Instance-Profile의 trust relationship에 생성한 CodeDeployIDC-User를 추가합니다.
CodeDeploy Agent 및 라이브러리 설치
CodeDeploy agent와 on-premises instance 등록 및 세션 발급에 필요한 각종 도구를 설치합니다.
- ruby 및 wget 설치:
yum install ruby wget
- aws-cli 및 boto 설치:
pip install awscli boto3 --user
- aws-cli 설정:
aws configure
(CodeDeployIDC-User의 access token 입력) - CodeDeploy agent 설치:
1
$ wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
2
$ chmod +x ./install
3
$ sudo AWS_REGION=ap-northeast-2 ./install auto
STS 토큰 발급 및 설정
- 토큰을 업데이트하는 스크립트 /home/lendit/credential-update.py를 작성합니다.
1
import boto3
2
3
sts = boto3.client('sts')
4
resp = sts.assume_role(
5
RoleArn='arn:aws:iam::12345678901:role/CodeDeployIDC-Instance-Profile',
6
RoleSessionName='serial-ABCDEFG',
7
)
8
with open('/home/lendit/.aws/credential-codedeploy', 'w') as f:
9
f.write('[default]\n')
10
f.write('aws_access_key_id = ' + resp['Credentials']['AccessKeyId'] + '\n')
11
f.write('aws_secret_access_key = ' + resp['Credentials']['SecretAccessKey'] + '\n')
12
f.write('aws_session_token = ' + resp['Credentials']['SessionToken'] + '\n')
- 주기적으로 위 스크립트가 실행되도록 cron에 등록합니다. 세션의 기본 유효시간은 1시간으로 30분 간격으로 등록하면 충분합니다.
- CodeDeploy가 토큰을 사용하여 작동하도록 /etc/codedeploy-agent/conf/codedeploy.onpremises.yml 설정을 수정합니다.
1
2
iam_session_arn: arn:aws:sts::12345678901:assumed-role/CodeDeployIDC-Instance-Profile/serial-ABCDEFG
3
aws_credentials_file: /home/lendit/.aws/credential-codedeploy
4
region: ap-northeast-2
- CodeDeploy agent를 재시작합니다.
서버 등록
- 마침내 register-on-premises-instance를 사용하여 instance를 등록합니다. –instance-name은 변경할 수 없습니다.
1
$ aws deploy register-on-premises-instance
2
--instance-name serial-ABCDEFG
3
--iam-session-arn arn:aws:sts::12345678901:assumed-role/CodeDeployIDC-Instance-Profile/serial-ABCDEFG
- 등록된 on-premises instance에 태그를 붙입니다. 태그의 값은 EC2 태그와 마찬가지로 언제든지 변경할 수 있습니다.
1
$ aws deploy add-tags-to-on-premises-instances
2
--instance-names serial-ABCDEFG
3
--tags Key=Name,Value=idc-01
배포를 배포답게! 시리즈를 마치며
JSP와 Vue가 섞여있던 프로젝트에서 프론트엔드를 분리했을 때의 배포 과정, 롤백 과정, (2) 편에서 배포 시스템을 설명하며 소개한 Lendit Portal의 다른 기능 등등 아직 할 이야기가 많이 남아있지만, 이 시리즈는 여기서 마칩니다. 렌딧에 입사하고 AWS를 처음 다루게 되어 많은 검색과 삽질을 했지만, 많이 배울 수 있어서 재미있었고, 다른 개발자분들이 잘 사용해주셔서 뿌듯했습니다. 이 글이 누군가에게 도움이 되었으면 좋겠습니다. 감사합니다.