AWS에서 기본적으로 제공하는 Code 시리즈 (CodeCommit, CodeBuild, CodePipeline)을 이용한 OS 이미지가 지속적이고 정기적으로 배포될 수 있는 환경을 구성해보았다. 기본적으로는 Jenkins와 같은 CI툴과 Spinnaker와 같은 CD툴을 사용해서 구현할 것으로 보이나, 그런 시스템이 구축되지 않은 소규모 환경에서는 위와 같이 AWS Native한 서비스를 사용해도 기본적인 구현은 충분히 가능할 것으로 보인다.
위에는 추가하지 않았으나, SNS를 활용한 Notification을 추가할 수도 있고, AWS Pipeline에 추가적인 스텝을 구현하는 것도 가능하여 추가적으로 확장이 가능하며, Packer를 이용한다는 점은 동일하므로 ansible과 같은 솔루션도 사용이 가능하다. 참고로 AWS에서 제공하는 서비스 중 EC2 Image Builder라는 위와 동일한 기능을 제공하는 서비스가 있으나, Packer가 타 클라우드에서도 사용이 가능하며 범용적이기 때문에 위 방식으로 구현을 하였다.
0. Prerequisite
Packer, Python, Shell Script, 기초적인 CI/CD의 이해
1. Repository directory structure
CodeCommit Repository를 tree했을 시 표시되는 구조이다.
디렉토리 기반으로 확장하는 것을 전제로 구성하였다.
├── README.md
├── DirectoryA → 디렉토리를 확장하여 만들 이미지를 추가할 수 있다.
│ ├── inspec_profile → inspec profile
│ │ ├── controls
│ │ │ └── proxy.rb
│ │ └── inspec.yml
│ ├── packer_template.pkr.hcl
→ packer template. hcl format일 경우 파일 확장자는 .pkr.hcl 이다.
│ ├── scripts → packer에서 사용하는 스크립트가 있는 디렉토리
│ │ ├── xxx.sh
│ │ ├── xxx.sh
│ │ └── xxx.sh
│ └── scriptsB
│ └── xxxx.sh
└── buildspec.yml → codebuild에서 참조하는 설정파일.
2. Workflow
2.1. CodePipeline
AWS Code Pipeline은 다음과 같이 정의하였다.
- Source: CodeCommit의 Repository가 변경되면 Pipeline이 실행된다.
- PreBuild: Lambda함수를 실행한다. Lambda 함수는 어떤 디렉토리가 변경되었는 지 판별하며
해당 디렉토리 명은 이후에 실행될 Build Step에서 환경변수에 저장된다. - Build: CodeBuild를 실행한다.
2.2. CodeBuild
phase 단위로 구분된다. install → build → post_build의 phase로 구분하였으며, Build를 실행할 OS를 초기화하고 packer를 실행하는 부분으로 이루어져 있다. 주의하여 보아야 할 부분은, 환경변수로 $TargetDir를 가져와서 for loop를 돌면서 해당하는 디렉토리로 이동하면서 packer build를 수행한다는 점이다.
2.3. Lambda
Lambda 코드는 gist에 공개하였다. AWS에서 example로 제공한 코드를 참조하였다.
이 Lambda의 용도는 변경된 파일의 리스트를 모두 추출하여 최상위 디렉토리만을 추출하기 위함이다. (예: ABC/DEF → ABC)
이는 Branch 기반이 아니라 main branch의 Directory Level을 기반으로 이미지를 구성하도록 하였기 때문이다.
3. 기타
3.1. Chef Inspec
위 설정하는 부분 외에는 어려운 부분은 없다. 여기서는 추가로 Chef Inspec이라는 점검 및 감사용 툴을 적용하였다. Ansible에도 assert라는 비슷한 기능을 하는 구문이 있는 것으로 보이는데, 위 예에서는 shell script를 사용하였으므로 별도의 inspec profile을 적용하였다.
inspec은 packer에서 기본적으로 제공하는 provider이므로, 아래와 같이 쉽게 사용이 가능하다.
provisioner "inspec" { inspec_env_vars = [ "CHEF_LICENSE=accept" ] profile = "inspec_profile" } |
inspec의 profile 구성부분은 여기를, 제공하는 리소스는 여기를 참조한다. control 부분의 예시는 아래와 같다.
매우 직관적이므로 관련된 설명은 생략한다.
control 'mariadb_running' do
impact 'critical'
title 'check whether mariadb service is running well'
describe service('mariadb') do
it { should be_installed }
it { should be_enabled }
it { should be_running }
end
describe port(3306) do
it { should be_listening }
end
end
'Devops > CI, CD' 카테고리의 다른 글
[용어정리] CI/CD, BDD (0) | 2020.04.28 |
---|---|
[DEVOPS] 빌드 자동화 환경 구축 일지 I (0) | 2020.04.26 |