Packer를 사용하여 CloudWatch 에이전트가 설치되고 설정된 AMI를 생성합니다. 이 AMI를 사용하면 생성된 모든 인스턴스가 CloudWatch 에이전트가 설정된 상태로 시작됩니다.
Packer 템플릿 작성
{
"variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
"aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}",
"region": "ap-northeast-2",
"instance_type": "t2.micro",
"source_ami": "ami-0fd54cba47d6e98dc",
"ssh_username": "ec2-user"
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "{{user `region`}}",
"instance_type": "{{user `instance_type`}}",
"source_ami": "{{user `source_ami`}}",
"ssh_username": "{{user `ssh_username`}}",
"ami_name": "cloudwatch-agent-ami-{{timestamp}}"
}
],
"provisioners": [
{
"type": "shell",
"inline": [
"sudo apt-get update",
"sudo apt-get install -y amazon-cloudwatch-agent",
"sudo mkdir -p /opt/aws/amazon-cloudwatch-agent/etc"
]
},
{
"type": "file",
"source": "amazon-cloudwatch-agent.json",
"destination": "/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json"
},
{
"type": "shell",
"inline": [
"sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s"
]
}
]
}
각 항목의 설명과 수정해야 할 부분
Region 설정 (region)
사용할 AWS 리전을 지정합니다.
예: "region": "us-east-1"
주의사항: 사용하려는 리전으로 변경해야 합니다.
인스턴스 유형 (instance_type)
사용할 인스턴스 유형을 지정합니다.
예: "instance_type": "t2.medium"
주의사항: 필요에 따라 적절한 인스턴스 유형으로 변경합니다.
Source AMI (source_ami)
베이스로 사용할 AMI의 ID를 지정합니다.
예: "source_ami": "ami-12345678"
주의사항: 사용할 베이스 AMI의 ID로 변경합니다. 이는 운영체제와 지역에 따라 다릅니다.
SSH 사용자 이름 (ssh_username)
SSH 접속에 사용할 사용자 이름을 지정합니다.
예: "ssh_username": "ec2-user" (Amazon Linux) 또는 "ssh_username": "ubuntu" (Ubuntu)
주의사항: 사용할 AMI에 맞는 사용자 이름으로 변경합니다.
AMI 이름 (ami_name)
생성될 AMI의 이름을 지정합니다.
예: "ami_name": "my-cloudwatch-agent-ami-{{timestamp}}"
주의사항: 원하는 이름으로 변경할 수 있습니다. {{timestamp}}는 생성 시간으로 AMI 이름이 유일하도록 합니다.
CloudWatch 에이전트 설정 파일 (source)
source는 로컬 파일 경로를 지정하며, destination은 인스턴스 내 경로를 지정합니다.
예: "source": "path/to/your/amazon-cloudwatch-agent.json"
주의사항: amazon-cloudwatch-agent.json 파일이 Packer 템플릿과 동일한 디렉토리에 있는 경우 상대 경로를 사용합니다. 그렇지 않으면 파일의 정확한 경로를 지정합니다.
AWS 자격 증명 설정
Packer는 AWS 자격 증명을 필요로 합니다. 이는 환경 변수나 Packer 변수로 설정할 수 있습니다.
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
Packer 변수로 설정:
packer build -var 'aws_access_key=your-access-key' -var 'aws_secret_key=your-secret-key' cloudwatch-agent.json
업로드된 amazon-cloudwatch-agent.json 파일을 사용합니다. 이 파일은 CloudWatch 에이전트가 모니터링할 지표들을 정의합니다.
{
"agent": {
"metrics_collection_interval": 60,
"logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
},
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"InstanceId": "${aws:InstanceId}"
},
"metrics_collected": {
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 60
},
"disk": {
"measurement": [
"disk_used_percent"
],
"metrics_collection_interval": 60,
"resources": [
"*"
]
},
"swap": {
"measurement": [
"swap_used_percent"
],
"metrics_collection_interval": 60
},
"cpu": {
"measurement": [
"cpu_usage_idle",
"cpu_usage_iowait",
"cpu_usage_user",
"cpu_usage_system"
],
"metrics_collection_interval": 60
},
"net": {
"measurement": [
"bytes_sent",
"bytes_recv"
],
"metrics_collection_interval": 60,
"resources": [
"eth0"
]
}
}
}
}
# Packer 템플릿 파일과 설정 파일이 동일 디렉토리에 있는지 확인
packer validate cloudwatch-agent.json
packer build cloudwatch-agent.json
AWS 콘솔을 사용하여 생성된 AMI를 기반으로 인스턴스를 시작합니다.
AWS 콘솔에서 EC2 인스턴스 시작
AWS Management Console에 로그인합니다.
EC2 대시보드로 이동합니다.
"인스턴스 시작"을 클릭합니다.
"My AMIs" 탭에서 생성한 AMI를 선택합니다.
인스턴스 유형을 선택합니다.
네트워크 설정 및 키 페어를 선택합니다.
필요한 다른 설정을 완료하고 인스턴스를 시작합니다.
이 방법을 사용하면 생성된 AMI(골드 이미지)를 기반으로 시작된 모든 EC2 인스턴스는 CloudWatch 에이전트가 미리 설정된 상태로 시작되며, 별도의 추가 설정 없이 자동으로 모니터링을 시작합니다. 이 과정에서 SSH로 직접 접속할 필요가 없습니다.
curl -O https://releases.hashicorp.com/packer/1.7.8/packer_1.7.8_linux_amd64.zip
unzip packer_1.7.8_linux_amd64.zip
sudo mv packer /usr/local/bin/
packer build -var 'aws_access_key=YOUR_AWS_ACCESS_KEY' -var 'aws_secret_key=YOUR_AWS_SECRET_KEY' cloudwatch-agent.json
packer를 사용할 때의 이미지는 Amazon Linux 2023 AMI 사용
이때 access key와 secret key의 외부노출 방지를 위해 ec2에 private link 또는 역할을 지정하여 packer 빌드 가능
- AmazonEC2FullAccess:
이 정책은 EC2 인스턴스와 관련된 대부분의 작업을 수행할 수 있는 권한을 제공합니다.
정책은 인스턴스를 시작하고 종료하며, AMI를 생성하고 볼륨을 관리하는 등의 작업을 수행할 수 있습니다.- packer build cloudwatch-agent.json
packer 정책 연결
- EC2InstanceProfileForImageBuilder:
이 정책은 EC2 Image Builder를 위한 인스턴스 프로파일에 사용됩니다.
인스턴스 프로파일은 이미지 빌드를 위한 EC2 인스턴스에 필요한 최소한의 권한을 포함합니다.
packer 유효성 검사
- packer validate cloudwatch-agent.json
파일을 다른 경로로 업로드한 후 이동시키는 방법 ( 권한 문제 )
- 먼저 파일을 업로드할 수 있는 경로로 업로드한 후, 해당 파일을 대상 디렉토리로 이동합니다.
- "destination": "/tmp/amazon-cloudwatch-agent.json" // 임시 경로로 업로드
- "sudo mv /tmp/amazon-cloudwatch-agent.json /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json", // 파일 이동
골드 이미지 생성 확인

이미지를 통해 설정된 cloud agent 확인

terraform으로 설정해서 apply 실행 시 지표가 자동으로 생성되는 것 확인

nginx-A 태그
nginx-C 태그
tomcat-A 태그
tomcat-C 태그
DB-A 태그
DB-C 태그
[defaults]
inventory = ./inventory.yml
remote_user = ec2-user
private_key_file = ~/.ssh/soldesk.pem.pem
host_key_checking = False
plugin: aws_ec2
regions:
- ap-northeast-2
filters:
instance-state-name: running
hostnames:
- private-ip-address
keyed_groups:
- key: tags.Name
prefix: name
- key: tags.aws:autoscaling:groupName
prefix: group
compose:
ansible_host: private_ip_address
private_ip: private_ip_address
인벤토리 그룹 생성
위 설정을 통해 인벤토리는 다음과 같이 그룹화됩니다:
Name 태그 기반 그룹:
aws:autoscaling 태그 기반 그룹:
예시 Ansible 플레이북
이제 각 그룹을 대상으로 하는 Ansible 플레이북을 작성할 수 있습니다. 예를 들어, nginx, tomcat, db 그룹에 대해 각각 다른 작업을 수행하는 플레이북은 다음과 같습니다.
Nginx 설치 플레이북 (install_nginx.yaml)
---
- name: Install Nginx on Nginx servers
hosts: group_VEC-PRD-VPC-NGINX-PUB-2A:group_VEC-PRD-VPC-NGINX-PUB-2C
become: yes
tasks:
- name: Update and install Nginx
apt:
name: nginx
state: present
update_cache: yes
플레이북 실행
ansible-playbook -i aws_ec2.yaml install_nginx.yaml
ansible-playbook -i aws_ec2.yaml install_tomcat.yaml
ansible-playbook -i aws_ec2.yaml setup_db.yaml
boto3 및 botocore 설치
- Python과 pip가 설치된 후, boto3와 botocore를 설치합니다. 이는 Ansible이 AWS API와 상호작용할 수 있게 합니다.
- sudo yum install pip -y
- sudo yum install python3 python3-pip
- pip install boto3 botocore
- pip3 install boto3 botocore
pip와 pip3를 통해 boto3 botocore 설치
ansible-inventory -i /home/ec2-user/aws_ec2.yml --graph로 확인
name 접두사 확인
remote_user = ec2-user 사용
ec2 IAM 권한 확인
dynamic inventory를 통해 ansible 실행 확인

리소스 그룹 생성
그룹 유형: 태그 유형
그룹화 기준
리소스 유형: AWS::EC2::Instance
태그: 키 ( Name ), 태그 값: EC2-mywebserver-deploy
그룹 이름: EC2-mywebserver-deploy
리소스 그룹을 생성하여 SSM에 전달
SSM 빠른 설정
Host Management 기반 생성
구성 옵션
Systems Manager ( 생략 가능 )
2주마다 Systems Manager(SSM) 에이전트를 업데이트합니다
30분마다 인스턴스로부터 인벤토리 수집
매일 인스턴스에 누락된 패치가 있는지 검사합니다.
대상
현재 리전
인스턴스를 타겟팅할 방법 선택
위의 방법을 통해 Fleet 관리를 통해 인스턴스 관리 가능하다
SSM run command
sudo yum install -y amazon-ssm-agent
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent
IAM 역할 생성:
AWS Management Console에서 IAM 역할을 생성하고 AmazonSSMManagedInstanceCore 정책을 연결합니다.
생성된 역할을 EC2 인스턴스에 연결합니다.
AWS-RunShellScript 문서 선택:
SSM Run Command를 통해 Ansible 설치:
SSM 콘솔에서 "Run Command"로 이동하여 "Run a command"를 클릭합니다.
AWS-RunShellScript 문서를 선택하고 다음 스크립트를 사용하여 Ansible과 boto3를 설치합니다.
#!/bin/bash
sudo yum install -y python3
pip3 install ansible boto3
aws_ec2.yaml 파일 준비:
nginx_playbook.yaml 작성:
S3 버킷에 파일 업로드:
aws s3 cp /path/to/nginx-deploy.yml s3://my-ansible-bucket/nginx-deploy.yml
aws s3 cp /path/to/aws_ec2.yml s3://my-ansible-bucket/aws_ec2.yml
SSM 콘솔에서 명령 실행:
SSM 콘솔에서 "Run Command"로 이동하여 "Run a command"를 클릭합니다.
AWS-RunShellScript 문서를 선택하고 다음 스크립트를 사용하여 Ansible 플레이북을 실행합니다.
버킷 이름: aws-ssm-managed-bucket
객체 업로드:
IAM 콘솔로 이동:
AWS Management Console에서 "IAM"으로 이동합니다.
좌측 메뉴에서 "Roles"를 클릭하고, EC2 인스턴스에 연결된 역할을 선택합니다.
정책 추가:
"Permissions" 탭에서 "Add permissions" 버튼을 클릭합니다.
"Attach policies"를 선택하고 AmazonS3ReadOnlyAccess 정책을 검색하여 추가합니다.
S3 콘솔로 이동:
AWS Management Console에서 "S3"로 이동합니다.
버킷을 선택합니다.
버킷 정책 확인:
"Permissions" 탭을 클릭하고, "Bucket Policy"를 확인합니다.
버킷 정책이 SSM Agent가 실행되는 인스턴스의 역할을 허용하는지 확인합니다.
예제 버킷 정책:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::aws-ssm-managed-bucket/*"
}
]
}
#!/bin/bash
# S3 버킷 이름 및 파일 경로
BUCKET_NAME="aws-ssm-managed-bucket"
FILES=("ansible.cfg" "aws_ec2.yml" "dynamodb-deploy.yml" "nginx-deploy.yml" "soldesk.pem.pem" "tomcat-deploy.yml" "html/create-survey.html" "html/list-survey.html" "html/start-survey.html" "html/take-survey.html" "html/view-survey.html")
# 파일 다운로드 경로
DEST_DIR="/home/ec2-user"
# S3에서 파일 다운로드
for FILE in "${FILES[@]}"; do
aws s3 cp s3://$BUCKET_NAME/$FILE $DEST_DIR/$FILE
done
# Ansible 플레이북 실행
ansible-playbook -i $DEST_DIR/aws_ec2.yml $DEST_DIR/nginx-deploy.yml
이름: EC2-mywebserver-deploy
user data 수정 ( ansible 설치, ansible plugin을 위한 boto3, botocore 설치 )
#!/bin/bash
sudo yum update -y
sudo amazon-linux-extras install epel -y
sudo yum install -y ansible
sudo yum install pip -y
sudo pip3 install boto3 botocore
sudo pip install boto3 botocore
sudo ansible-playbook -i /home/ec2-user/aws_ec2.yml /home/ec2-user/nginx-deploy.yml /home/ec2-user/tomcat-deploy.yml /home/ec2-user/dynamodb-deploy.yml
명령 스크립트 입력:
#!/bin/bash
cd /home/ec2-user
chmod 400 /home/ec2-user/soldesk.pem.pem
cp /home/ec2-user/soldesk.pem.pem ~/.ssh/soldesk.pem.pem
ansible-playbook -i /home/ec2-user/aws_ec2.yml /home/ec2-user/nginx-deploy.yml /home/ec2-user/tomcat-deploy.yml /home/ec2-user/dynamodb-deploy.yml
이후에 ansible이 제대로 실행되어 호스팅 구성을 확인

필요한 권한:
- AmazonSSMManagedInstanceCore
- AmazonS3ReadOnlyAccess
EC2-mywebserver-deploy user data 수정 및 역할(권한) 추가
#!/bin/bash
sudo yum update -y
sudo amazon-linux-extras install epel -y
sudo yum install -y ansible
sudo yum install pip -y
sudo pip3 install boto3 botocore
sudo pip install boto3 botocore
필요한 역할
AmazonEC2FullAccess
AmazonSSMManagedInstanceCore
AmazonS3ReadOnlyAccess
AWS Resource Groups에서 리소스 그룹 생성
AWS 시스템스 매니저 dynamic inventory
사전 준비
리소스 그룹을 생성( EC2-mywebserver-deploy )
빠른 설정을 통해 Host Management 기반 생성
S3 버킷에 다운로드하고자 하는 파일 업로드
SSM run command
AWS-RunShellScript 문서 선택:
스크립트 실행
#!/bin/bash
# S3 버킷 이름 및 파일 경로
BUCKET_NAME="aws-ssm-managed-bucket"
FILES=("ansible.cfg" "aws_ec2.yml" "dynamodb-deploy.yml" "nginx-deploy.yml" "soldesk.pem.pem" "tomcat-deploy.yml" "html/create-survey.html" "html/list-survey.html" "html/start-survey.html" "html/take-survey.html" "html/view-survey.html")
# 파일 다운로드 경로
DEST_DIR="/home/ec2-user"
# S3에서 파일 다운로드
for FILE in "${FILES[@]}"; do
aws s3 cp s3://$BUCKET_NAME/$FILE $DEST_DIR/$FILE
done
# Ansible 플레이북 실행
ansible-playbook -i $DEST_DIR/aws_ec2.yml $DEST_DIR/nginx-deploy.yml
cd /home/ec2-user
chmod 400 /home/ec2-user/soldesk.pem.pem
cp /home/ec2-user/soldesk.pem.pem ~/.ssh/soldesk.pem.pem
ansible-playbook -i /home/ec2-user/aws_ec2.yml /home/ec2-user/nginx-deploy.yml /home/ec2-user/tomcat-deploy.yml /home/ec2-user/dynamodb-deploy.yml
terraform 내용은 파일 참고
ansible의 inventory의 hosts를 private-ip-address로 지정하여 해당 오토스케일링 그룹의 모든 인스턴스에 적용되는 것을 확인 ( 서브넷을 통해 구분 )
