Lambda로 EC2 컨트롤하기 (2) 쉘 스크립트 전송하기

Yihoon·2024년 6월 7일
0

AWS활용기

목록 보기
7/7

지난 시간에 이어서 Lambda로 EC2를 컨트롤해 보자.

인스턴스를 시작하고 중지하는 방법은 1편에서 만나볼 수 있다.

2편에서는 이렇게 시작/중지가 가능해진 인스턴스에 쉘 스크립트를 직접 전달해 볼 것이다.
보통 외부에서 인스턴스에 접근하려면 SSH를 많이 사용하지만,
이번에는 SSM이라는 AWS의 관리형 서비스를 이용할 것이다.

간단히 요약하자면 Lambda 함수에서 스크립트를 Systems Manager에 전달하고, 이를 다시 인스턴스에 넘겨주는 방식.

1편보다 좀 더 복잡한 내용이므로 차근차근 따라와 주기 바란다.

IAM

일단 Lambda함수가 SSM을 컨트롤할 수 있도록 적절한 정책을 만든다.
lambda-ssm이라는 정책을 아래와 같이 선언하였다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand",
                "iam:PassRole",
                "ssm:CreateAssociation",
                "ssm:GetDocument",
                "ssm:ListDocuments",
                "ssm:ListAssociations",
                "ssm:CreateDocument"
            ],
            "Resource": "*"
        }
    ]
}

이렇게 만들어진 정책을 역할에 할당한다.

다음으로 EC2가 SSM으로부터 명령을 받아올 수 있도록 또 다른 역할을 구성한다.
이번에는 기본 정책 중에서 AmazonEC2RoleforSSM 을 선택한다.

IAM 세팅은 이렇게 마무리한다.

Lambda

이어서 스크립트를 실행하는 함수를 만든다.
1편과 마찬가지로 boto3 레이어가 필요하며, python 3.9환경을 기준으로 서술한다.

먼저 boto3를 로드한다.

import boto3

이어서 각 서비스 개체들을 정의한다. EC2와 SSM을 사용할 것이기 때문에 두 가지를 모두 정의해야 한다.

def define_instances(self):
        self.ec2=boto3.client("ec2",region_name='ap-northeast-2')
        self.ssm=boto3.client("ssm")

다음으로 실행할 스크립트를 정의한다.

def set_script(self, taskname):
        """
        태스크별 스크립트 세팅
        Args:
            taskname (str): 태스크 유형
                - test: 테스트 스크립트
                - main: 메인 태스크 실행
                - delete: 메인 태스크 실행 후 생성된 엑셀 파일 삭제
        """
        
        if taskname=='test':
            self.script=[
                        'echo "Hello World!" > /home/ec2-user/helloword.txt'
                        ]
        elif taskname=='listing':
            self.script=[
                        'python3 /home/ec2-user/l_module.py'
                        ]
        elif taskname=='search':
            self.script=[
                        'python3 /home/ec2-user/n_module.py'
                        ]            
        elif taskname=='main':
            self.script=[
                        'sudo python3 /home/ec2-user/Main.py'
                        ]
        elif taskname=='delete':
            self.script=[
                        'sudo find . -name "*.xlsx" -delete'
                        ]

참고로 스크립트는 인스턴스로 바로 전달되는 것이 아니라 SSM을 통해서 전달되며, 따라서 별도의 디렉토리 세팅을 하지 않는 이상 사용자 경로가 아닌 루트 경로에서부터 명령어를 작성해야 하는 점 유의하기 바란다.
또 스크립트를 여러 줄 사용하고 싶을 경우 문자열 안에서 \n으로 구분하거나, 혹은 리스트에 문자열을 추가해 주어도 된다.

스크립트를 준비했다면 이 스크립트를 실행하는 function을 정의한다.

    def run_script(self, id):
        for line in self.script: #스크립트를 리스트로 여러 개 정의하는 경우에 대비
            print(line) #스크립트 출력
            self.ssm.send_command(
                    DocumentName='AWS-RunShellScript',
                    Parameters={'commands':[line]}, #반드시 리스트로
                    InstanceIds=[id] #반드시 리스트로	
                )      

참고로 이 함수들을 아우르는 __main__ 함수는

    def __main__(self):
        self.define_instances()
        self.set_script(taskname='search')
        self.run_script(id='i-************')

이렇게 되어 있다.

또 런타임 유형을 스크립트 실행이 가능하도록 좀 더 넉넉하게 잡아 주자. 나의 경우는 일부러 좀 더 넉넉하게 잡아 뒀는데, 테스트 결과 한 줄 스크립트를 전달하려면 10초 정도의 시간을 주면 충분한 것 같다.

세팅을 마쳤다면 앞에서 만들어 둔 역할을 연결해 준다.

EC2

1편에서 인스턴스가 준비되었다는 것을 전제로 설명을 진행한다.
일단 나의 경우 파이썬 파일을 실행하는 것이 목적이기 때문에, 각 인스턴스의 볼륨에다가 py 파일들을 넣어 두었다. 각 파일의 용도와 기능은 여기서 언급하지 않겠다.
타겟팅할 인스턴스에도 만들어 둔 IAM 역할을 연결한다.

SSM

EC2에서 권한 설정을 올바르게 했다면, SSM의 Fleet Manager로 이동하여 해당 인스턴스가 표시되는지, 즉 관리형 노드로 설정되어 있는지 확인한다. 타겟 인스턴스가 정상적으로 노출된다면 SSM으로부터 스크립트를 받아올 수 있다는 의미이다.

이렇게 Lambda-SSM-EC2 간의 연결까지 모두 마치면 스크립트를 전송할 준비가 끝난다. 실무에 적용하기 전 echo "Hello World"와 같은 간단한 스크립트를 통해 테스트를 수행해 보자.

profile
딴짓 좋아하는 데이터쟁이

0개의 댓글

관련 채용 정보