개발/프로젝트

[aws alb | jenkins] 오토스케일링으로 인해 변경된 Private IP로의 접속

prpn97 2024. 6. 4. 13:34

문제점

 

현재 디폴트로 만들어둔 ami 이미지를 통해 private 인스턴스를 오토스케일링하고 있고, 배포시 다음과 같은 과정중에 있다. 

 

- 소스코드 github push

- Jenkins에서 ssh 스크립트로 Bastion Host 접속

- Bastion에서 각각의 ssh 스크립트로 Private Host 접속

- 각각의 Private에서 소스코드 git pull 후 서버 실행 스크립트~~ 

 

 

그리고 aws에서는 서버가 죽게 되면 이를 체크하고 만들어둔 ami 이미지를 그대로 새로운 인스턴스로 복각하여 aws에 입력해둔 명령어를 포함해서 작동하면서 서버가 열리게 되어 정상적으로 오토스케일링은 가동되고 있다. 

 

문제는 배포시에 ssh스크립트로 직접 bastion에서 private로 접근할 때 ip주소를 알아야 하여 새로 인스턴스가 생성되면 ip가 변경되기 때문에 접근할 수가 없어 자동으로 배포할 수가 없었다. 아래는 당시 로그인데, 어차피 다른 인스턴스를 열게되어 편하게 주소를 공개해보겠다..

나는 10.0.168.49, 10.0.145.22 즉, private2,3에 각각 접속하려고 시도하지만 그 주소는 이미 죽었고, 새로운 인스턴스는 주소가 다르기 때문에 timeout이 나온다. 


해결 방법

  기존에는 Jenkins의 환경변수로 각 Private의 주소를 입력하여 Jenkins에서 받아와서 주소가 입력되고 있었기 때문에 변경된 인스턴스를 수동으로 바꿔주지 않는 이상 기존 방법대로의 진행은 불가했다. 

 

  그렇다면 새로 오픈된 서버의 주소를 알아내어 ssh 스크립트에 삽입할 수 있다면 이 문제를 해결할 수 있겠다. 

 

해결 과정

1. 스크립트 작성

cat << 'EOF' > get-asg-instances.sh

# 이 사이에 아래 스크립트를 붙여넣기 한 후 실행하면 파일이 생성된다.

EOF
# AWS Auto Scaling Group Name
ASG_NAME="오토스케일링 설정한 그룹 이름"

# Get instance IDs from the Auto Scaling Group
INSTANCE_IDS=$(aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names ${ASG_NAME} --query "AutoScalingGroups[0].Instances[*].InstanceId" --out>

# Get IP addresses of the instances
for INSTANCE_ID in ${INSTANCE_IDS}
do
    IP_ADDRESS=$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID} --query "Reservations[0].Instances[0].PrivateIpAddress" --output text)
    echo "Instance ID: ${INSTANCE_ID}, Private IP Address: ${IP_ADDRESS}"
done

 

작동시킬 인스턴스의 id와 인스턴스의 주소를 for문으로 전부 출력하도록 한다. 

 

2. private ip주소를 얻어낼 권한을 가진 iam 사용자 생성 (이미 있다면 3번으로)

권한에는 아래와 같이 autoscaling, ec2의 인스턴스와 오토스케일링그룹에 대해 허용하면 된다. 

 

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "autoscaling:DescribeAutoScalingGroups",
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        }
    ]
}

 

*사용자 생성 / aws cli 설치 참고

https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-AWS-CLI-%EC%84%A4%EC%B9%98-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%89%BD%EA%B3%A0-%EB%B9%A0%EB%A5%B4%EA%B2%8C

 

[AWS] 📚 AWS CLI 설치 & 등록 방법 - 쉽고 빠르게 설명

AWS CLI (Command Line) AWS Command Line Interface는 쉘 커맨드를 사용하여 AWS 서비스와 상호 작용할 수 있는 도구이다. 우리가 브라우저로 아마존 웹 서비스 홈페이지(콘솔 홈)에 가서 서비스를 이용한 것

inpa.tistory.com

 

3. aws cli 로그인

만약 설치되어있지 않다면 먼저 설치해주자. 

이후 aws configure 입력시 id, pw, Region name, output format을 입력하라고 확인된다. 

Default output format(기본 출력 포맷)은 API를 호출한 결과를 출력할 포맷을 지정.
이 값은 명령어를 실행할 때 --output <FORMAT> 옵션으로 덮어쓸 수 있다.

여기서 region name까지 입력하고, output format은 엔터치고 넘어가도 상관은 없었다.

 

4. 스크립트 실행

chmod +x get-asg-instances.sh
./get-asg-instances.sh

 

스크립트를 실행했을 때, 처음에 권한 문제로 실패하여 다음과 같이 에러가 확인되었다. 

An error occurred (AccessDenied) when calling the DescribeAutoScalingGroups operation

그런데 나는 이미 해당 권한을 적용시켰고, 혹시 적용하면 새로고침해야할까 싶어 다시 aws configure로 로그인했는데 정상작동하였다. 

 

 

다시 실행시켰을 때 이런 에러가 확인되었다.

에러 아래에는 echo로 출력하려던 내용에 None 과 빈 값으로 출력됨을 알 수 있다. 

An error occurred (InvalidInstanceID.Malformed) when calling the DescribeInstances operation: Invalid id: "None"
Instance ID: None, Private IP Address:

 

 

생성된 파일을 확인했더니, ASG_NAME="오토스케일링 그룹명" 변수에 오타가 있었다...^^

 

수정한 후 작동시켰을 때 정상적으로 인스턴스id와 private ip 주소를 얻어낼 수 있었다. 

 

Jenkins 스크립트 (bastion 호스트 접속 후 private ip 주소 체크 스크립트)

 

1. export ~ aws 로그인 키 삽입

2. private ip주소 저장 쉘스크립트

3. bastion호스트인 상태에서 ssh private ip주소 삽입

	export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
	export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
	export AWS_DEFAULT_REGION="ap-northeast-2"

	echo "Bastion 호스트에서 Private 3 IP 가져오는 중"
	PRIVATE_HOST_3_IP=\$(./get-asg-instances.sh | grep "Private IP Address" | awk '{print \$NF}')
if [ -z "\$PRIVATE_HOST_3_IP" ]; then
	echo "ERROR: Private 3 IP를 가져오지 못했습니다."
	exit 1
fi
echo "PRIVATE_HOST_3_IP: \${PRIVATE_HOST_3_IP}"

echo "Private 3 호스트에 연결 중: \${PRIVATE_HOST_3_IP}"
ssh ${USERNAME}@\${PRIVATE_HOST_3_IP} 'bash -s' << 'ENDSSH2'
	echo "Private 3 호스트에 연결되었습니다: \${PRIVATE_HOST_3_IP}"
728x90