팀장 님 께서 EC2 서버 하나 구축해 보라고 하셨다. 기존에 있던 테스트 서버를 기준 삼아서 만들던 와중 RedHat으로 되어 있던 기존 꺼에서 aws linux 바꾸기로 해서 다시 만들려고 하던 와중 실수로 기존 테스트 서버를 터미네이트 시켜 버렸다...
이렇게 터미네이트 되어버린 인스턴스 는 기존에 가지고 있던 root ebs까지 모두 날려버리기 때문에 기존에 스냅샷 이 없다면.. 복구할 방법이 존재하지 않는다.... ㅠㅠ
설정이 완벽하게 끝난 서버라면 ebs 를 인스턴스 와 분리하던가 아니면 스냅샷 을 찍어 태그네임 박아서 기록해 두고, AMI까지 생성해서 관리한다면 보다 완벽하다. 꼭꼭 꼭 해두자.
어쨌든 구축하면서 했던 삽질 모든 걸 기록해보고자 한다.
EC2의 기본 세팅은 기존 ami를 사용하지 않고 aws에서 제공해 주는 이미지 템플릿을 사용했다.
ssh 키 같은거는 기존 pem 파일을 사용하기로 하였으며 docker를 이용해서 기존 디비들을 구축하려고 했다.
- sudo yum update -y
- sudo yum install -y docker
- sudo service docker start
위 스탭 으로 기존 데이터를 업데이트해주고 도커 설치 후 서비스 시작해 주면 된다.
docker pull [mysql,redis,kafka]
docker run --name mysql -e MYSQL_ROOT_PASSWORD=plea2018 -p 3306:3306 -d mysql
docker run -d --name redis -p 6379:6379 redis
docker run --name some-kafka -d -p 9092:9092 confluentinc/cp-kafka:latest
하다 보니 거지 같은 sudo 커맨드를 계속 써야 한다. sudo 코드를 없애기 위해 아래 명령어를 실행해 그룹에 추가해 주자.
sudo usermod -aG docker $USER
mysql부터 외부에서 접속 테스트를 실행하던 중 자꾸 kafka 도커가 상태가 계속 떨어진다... 로그를 확인해 보자.
KAFKA_ZOOKEEPER_CONNECT is required.
Command [/usr/local/bin/dub ensure KAFKA_ZOOKEEPER_CONNECT] FAILED!
위와 같은 에러가 나오고 알아보니 zookeeper의 추가적인 설치와 설정이 필요하다. 왜?
Apache ZooKeeper는 Kafka가 클러스터 환경에서 효율적으로 작동하는 데 필요한 분산 조정 및 관리를 제공하므로 Apache Kafka의 중요한 구성 요소이다.
그래서 추가적인 zookeper 설치가 필요하다.
그전에 먼저 docker network create kafka-net을 이용해 카프카 용 별도의 네트워크를 설정해 준다.
이렇게 생성된 네트워크를 이용해 주키퍼 컨테이너 와 통신이 가능해진다. 그렇기에 네트워크 를 생성해서 주키퍼와 연결해 준다.
docker run -d --name zookeeper --network kafka-net -p 2181:2181 confluentinc/cp-zookeeper
실행해 주키퍼를 실행해 주면 역시나 바로 죽어버린다. 로그를 확인해 보면
Command [/usr/local/bin/dub ensure-atleast-one ZOOKEEPER_CLIENT_PORT ZOOKEEPER_SECURE_CLIENT_PORT] FAILED!
주키퍼 클라이언트 포트를 설정해 달라고 한다. 그냥 넣어주자. 한 번에 실행이 되는 적이 없다 아주
docker run -d --name zookeeper -p 2181:2181 -e ZOOKEEPER_CLIENT_PORT=2181 zookeeper:latest
주키퍼 실행 이 되었다면 이제 카프카를 켜주자.
docker run -d --name kafka --network kafka-net -p 9092:9092 e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 confluentinc/cp-kafka
음 또 죽는다.
Command [/usr/local/bin/dub ensure KAFKA_ADVERTISED_LISTENERS] FAILED!
카프카 리스너 설정이 안 되어 있어 에러가 발생했다.
docker run -d --name kafka --network kafka-net -p 9092:9092 -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 confluentinc/cp-kafka
이렇게 로컬호스트로 추가 해주었지만 실질적인 연결을 위해서는 hostname or IP address를 저기 로컬호스트에 대신 넣어주어야 하지만 일단 실행이 목표이기 때문에 로컬호스트로 박아주었다.
PLAINTEXT://ec2-xx-xx-xxx-xxx.compute-1.amazonaws.com:9092 이런 식의 주소를 써주어야 한다고 하는데 나중에 테스트가 필요한 부분 같다.
이렇게 실행이 되는가 싶었는데 또 죽는다. ㅋㅋㅋㅋ
이번에 로그를 까보면 가관이다. 용량이 부족하단다 ㅎㅎ
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000 c0000000, 1073741824, 0) failed; error='Not enough
이걸 해결하기 위해 처음 컨테이너 가 실행될 때 메모리를 제한하는 방법이 있다. "KAFKA_HEAP_OPTS="-Xms100 M"" 100M 만 힙메모리로 지정하겠다는 의미이다.
docker run -d --name kafka --network kafka-net -p 9092:9092 -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 -e KAFKA_HEAP_OPTS="-Xms100M" confluentinc/cp-kafka
메모리가 아슬아슬하게 도달하고
이렇게 실행이 되는 걸 볼 수 있다.
팀장님 이 말하시기를 주키퍼 내장된 컴포즈가 있을 텐데 왜 이렇게 어렵게 하냐라고 하신다.... ㅠㅠ 컴포즈 버전으로 다시 해보자.
저위에 주키퍼 다운로드하는 저 명령어 다필요 없이
카프카 로그를 보면 이렇게 성공적으로 실행이 된다.
자 이제 팀장님의 추가적인 지시사항으로 이 서버는 오전 09 시에 켜지고 18시에 내려가는 서버이다 즉 이 서비스 들을 데몬에 등록해서 실행시켜주어 한다. 이런 팀장님의 의도를 모르고 aws lambda와 aws event bus , cloud formation이나 알아보고 있으니 그냥 하루를 아무것도 하지 않고 날렸다.
먼저 데몬에 대해 알아보자.
리눅스 시스템이 처음 가동될 때 실행되는 백그라운드 프로세스 일종으로 메모리에 상주하면서 특정 요청이 오면 즉시 대응할 수 있도록 대기 중인 프로세스이다. 바로 가보자.
서비스 작성
이렇게 적어주고
서비스 등록 을 해주자. 도커도 다운로드한 거기 때문에 이렇게 서비스 등록이 필요하다.
systemctl start docker.service
systemctl start docker-init.service
위와 같이 작성하면 서버를 끄고 킬떄 마다 매번 명령어 실행 필요 없이 백그라운드에서 자동화 실행이 된다.
명령어를 실행해 등록이 되었는지 다시 한번 확인해 준다.
자 이제 시간에 맞춰 켜지고 꺼지는 자동화를 설정해 주자.
먼저 구조 가 어떻게 되는지 알아야 한다.
aws_event_bridge에서 특정시간에 이벤트를 발행시키는데 그 이벤트의 대상이 aws_lambda 함수가 된다. 그래서 우리는
람다 함수에 원하는 기능을 작성하고
이벤트 브리지 에는 이벤트 발행 규칙을 정해주면 된다.
aws_lambda를 생성해서 키고 끄는 것을 설정해 보자.
aws_lambda를 가서 생성한다. 노드 파이썬을 권장한다. 웹에서 수정이 가능하기 때문에 편하다.
이렇게 생성하면 자동으로 역할 이 생기게 되는데 iam 으로 가서 json 으로 역할 수정을 해준다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Start*",
"ec2:Stop*"
],
"Resource": "*"
}
]
}
태그도 ec2_instance_run_close로 달아주자.
// Ec2 start
import boto3
region = 'ap-northeast-2'
instances = ['당신의 ec2 인스턴스 아이디']
ec2 = boto3.client('ec2', region_name=region)
def lambda_handler(event, context):
ec2.start_instances(InstanceIds=instances)
print('started your instances: ' + str(instances))
// EC2 stop
import boto3
region = 'ap-northeast-2'
instances = ['당신의 ec2 인스턴스 아이디']
ec2 = boto3.client('ec2', region_name=region)
def lambda_handler(event, context):
ec2.stop_instances(InstanceIds=instances)
print('stopped your instances: ' + str(instances))
이렇게 시작과 중지 함수를 각각 생성해서 테스트까지 모두 마무리해야 한다. 실제로 테스트해서 인스턴스 가 켜고 꺼지는지 확인하자.
모두 제대로 동작한다면 이제 aws_eventbridge로 가자
규칙생성에 rule type을 일정으로 정하고 크론으로 지정해주자.
instance _close = 0 18 ? * MON-FRI *
instance_open = 0 0 ? * MON-FRI *
UTC로 표기되기 때문에 현지 시간에 맞게 잘 조정하자 ㅠㅠ
이후 대상 선정을 aws_lambda로 선정하고, 검토 및 생성으로 건너뛰어서 생성해 주자.
각가의 시작과 종료가 각각 설정되어 있는 모습이다.
슬랙에 알림 메시지 보내주는 것도 설정해 주자.
슬랙에 가서 incoming webhook을 추가한다. (https://api.slack.com/apps/A04T3RM5WNT/incoming-webhooks?success=1)
커스텀하게 앱 만들어서 추가해도 된다.
import boto3
import json
import urllib.request
region = 'ap-northeast-2'
instances = ['당신의 인스턴스 주소']
ec2 = boto3.client('ec2', region_name=region)
webhook_url = '웹훅 url'
def post_slack(argStr):
message = argStr
send_data = {
"text": message,
}
send_text = json.dumps(send_data)
request = urllib.request.Request(
webhook_url,
data=send_text.encode('utf-8'),
)
with urllib.request.urlopen(request) as response:
slack_message = response.read()
def lambda_handler(event, context):
ec2.start_instances(InstanceIds=instances)
post_slack('started your instances: ' + str(instances))
이렇게 작성하고 배포하고 테스트를 눌러보면?
요렇게 서버 다운 하고 올라올 때 이렇게 메시지 가 전송 되는 모습이다.
긴글 읽어주셔서 감사합니다.
'자꾸 검색하는 내용' 카테고리의 다른 글
[Java] LinkedList 알아보기 (0) | 2023.01.02 |
---|---|
[Java] ArrayList 알아보기 (0) | 2023.01.01 |
Sql Antipatterns 스키마 및 erd (0) | 2022.12.03 |
[디자인 패턴] 싱글턴 패턴을 알아보자. (0) | 2022.09.01 |
코드 시간측정 (0) | 2022.07.25 |