본문 바로가기

카테고리 없음

[Github] git action SSM, EC2 명령어 실행 및 AWS Credentials 설정 + ssh vs ssm 의 삽질

반응형

 

Github Action 요소

  • workflows : 워크 플로우는 하나 이상의 job으로 구성되고 event에 의해 트리거될 수 있는 자동화된 프로세스이며, YAML으로 작성되고 Github Repository의 .github/workflows 폴더 아래에 저장한다. repository에는 여러 workflow를 가질 수 있으며 각 workflow는 서로 다른 작업을 수행할 수 있다. (워크 플로우는 다양한 job으로 구성되어 있고 병렬 수행)
  • actions : 워크 플로우의 가장 작은 블럭으로 jobs를 만들기 위해 step 들을 연결할 수 있으며, 재사용이 가능한 컴포넌트로서 반복적인 코드의 양을 줄일 수 있고 git repository를 가져오거나 클라우드 공급자에게 인증을 설정할 수도 있다.
  • events : 워크 플로우의 실행을 트리거하는 특정 활동이나 규칙
  • jobs : 여러 step으로 구성되고 가상 환경의 인스턴스에서 실행되며, 다른 job에 의존 관계를 가질 수 있고 독립적으로 병렬 실행도 가능
  • steps : task들의 집합으로 커맨드를 날리거나 쉘(터미널) 스크립트 실행하는 것처럼 action을 실행
  • runners : 워크 플로우가 트리거될 때 실행하는 서버이며, 각 runner는 1번에 1개의 job을 실행할 수 있음. Github에서 호스팅해주는 Github-hosted runner와 직접 호스팅하는 Self-hosted runner로 나뉜다.

 

깃허브 액션을 사용해서 main 브랜치가 푸쉬되면 환경 세팅이 되도록 한다.

우선 .github/workflows/init_and_deploy.yaml 파일생성

 

github 의 actions 탭에 들어가면 아래처럼 뜬다.

나는 ec2 instance 에 올려진 것에

ssm(ssh) 연결을 해서 git pull 만 해주면 되기 때문에

그냥 "Skip thit and set up a workflow yourself"를 클릭해주었다.

 

그러면 아래와 같이 해당 repo에 .github/workflows 에 .yml 파일을 세팅할 수 있다.

 

 

주요 구성 요소

어떤 상황에서 git action을 실행시키는지를 나타내는 부분

아래는 [ 브랜치 이름 ] push 라는 이벤트를 했을 경우에 job 을 실행시킨다는 뜻이다.

- 여러 구조의 

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

 

아래 코드는 GitHub Actions 워크 플로에서 AWS 자격 증명을 설정하는 것이다.

이 설정은 AWS 리소스와 상호작용하는 작업을 수행할 때 필요하다.

  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v2
    with:
      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      aws-region: ap-northeast-2

 

uses: aws-actions/configure-aws-credentials@v2

- AWS 리소스와 통신하기 위한 공식 GitHub Action 사용

 

with:

aws-region : AWS 리소스가 위치한 리전으로, ap-northeast-2는 서울 리전을 나타냄
aws-access-key-id, aws-secret-access-key: AWS 인증에 필요한 자격 증명, Github Secrets 에 저장된 키를 참조하여 보안 유지

 

 

보안 주의 사항은
- github secrets 사용하여 aws-access-key-id, aws-secret-access-key 는 GitHub Repository 의 Secrets에 저장하고 참고해야 한다.
- Secrets 설정은 Github Repo > Settings > Secrets and variables > Actions 메뉴에서 추가 가능

 

그리고 이후에 name, run 에 대한 step 들을 추가해주면 된다.

 


 

AWS EC2 명령어 

현재 상황은 ec2의 태그를 가지고, ec2 instance id 를 가져오는 코드를 작성하고자 한다.

왜냐면, ec2 instance 의 id가 언제나 고정되어있지 않고,

변경이 될 가능성을 고려한 것이다.

 

그러면 그것을 tag를 사용하여, 원하는 태그에 존재하는 값을 가져와서 인스턴스 id를 특정지을 수 있다.

  - name: Get EC2 Instance ID by Tag
    id: get_instance
    run: |
      INSTANCE_ID=$(aws ec2 describe-instances \
        --filters "Name=tag:Name,Values=[찾고자 하는 인스턴스의 태그 값]" "Name=instance-state-name,Values=running" \
        --query "Reservations[].Instances[].InstanceId" \
        --output text)
      echo "INSTANCE_ID=$INSTANCE_ID" >> "$GITHUB_ENV"

 

1. aws ec2 describe-instances

 

aws ec2 describe-instance 명령어는 AWS CLI를 사용하여 EC2 인스턴스의 정보를 조회하는 명령어

 

 

2. --filters

필터링을 통해 특정 태그를 가진 실행 중인 인스턴스만 조회가 가능하다.

 

조회할 인스턴스를 특정 조건으로 필터링

  • - Name=tag:Name,Values=[찾고자 하는 인스턴스의 태그 값]
    • : 태그 키가 Name이고 값이 [찾고자 하는 인스턴스의 태그 값]인 인스턴스를 필터링
  • - Name=instance-state-name,Values=running
    • : 현재 상태가 running인 인스턴스를 필터링

3. --query

출력 결과에서 원하는 정보만 추출

Reservations[].Instances[].InstanceId

: 조회된 인스턴스들의 ID만 추출합니다.

 

4. --output text

출력 형식을 텍스트로 지정하여, 추출된 인스턴스 ID를 텍스트 형식으로 출력

 

5. echo "INSTANCE_ID=$INSTANCE_ID" >> "$GITHUB_ENV"

조회된 인스턴스 ID를 GitHub Actions의 환경 변수로 설정하여, 후속 단계에서 $INSTANCE_ID로 참조할 수 있도록 함

 


 

AWS SSM 명령어 실행

AWS Systems Manager (SSM)의 Run Command 기능을 사용하여 특정 EC2 인스턴스에서 쉘 명령어 실행

이를 통해 SSH 접속 없이도 원격으로 명령을 실행 가능

- name: Run command on EC2 via SSM
  run: |
    aws ssm send-command \
      --instance-ids "$INSTANCE_ID" \
      --document-name "AWS-RunShellScript" \
      --comment "Deploying" \
      --parameters 'commands=[
        "sudo -u ec2-user bash -c '\[원하는 명령어 실행]'\''"
      ]' \
      --region ap-northeast-2 \
      --output text \
      --query "Command.CommandId"

 

상세 설명

  • --instance-ids "$INSTANCE_ID": 명령을 실행할 대상 EC2 인스턴스의 ID를 지정한다. 이전 단계에서 환경 변수로 설정된 INSTANCE_ID 값 사용
  • --document-name "AWS-RunShellScript": 실행할 SSM 문서의 이름을 지정, AWS-RunShellScript는 AWS에서 제공하는 기본 문서로, 리눅스 인스턴스에서 쉘 스크립트를 실행할 때 사용됩니다.
  • --comment "Deploying": 명령 기록에서 식별할 수 있도록 함
  • --parameters 'commands=[...]': 실행할 명령어를 배열 형태로 지정
  • --region ap-northeast-2: 명령을 실행할 AWS 서울 리전 지정(사실 없어도 되는 부분이지만, 명시적으로 해줌)
  • --output text: 명령의 출력 형식을 텍스트 지정
  • --query "Command.CommandId": 명령 실행 결과에서 CommandId만 추출하여 출력

추가로, 명령어 실행 결과를 확인하고 싶으면 

CommandId를 사용하여 명령의 실행 상태나 출력 확인 가능

aws ssm list-command-invocations --command-id <CommandId> --details

 


삽질 에피소드

재미있었던건, 원래 기존에는 SSH를 사용하고 있었다.

그러나 GitHub Actions를 사용하여 AWS EC2 인스턴스에 SSH로 연결할 때, GitHub Actions의 실행 환경은 동적으로 할당되며, 매번 다른 IP 주소를 사용한다.

이로 인해 EC2 인스턴스의 보안 그룹에서 GitHub Actions의 IP를 허용하는 것이 어려운 상황이었는데,

- 그렇다고 매번 바뀌는 그 GitHub Actions의 IP를 계속 할당해줄 수 없고

- 그렇다고 다 열어놓을 수도 없고,,

- 해서 변경될 수 있는게 SSM으로 퍼블릭하지 않게 처리를 해줄 수 있는 것이다.

이러한 문제를 해결하기 위해 AWS Systems Manager (SSM)를 사용했다.

 

그러나 내가 생각하기로는, ssh를 ssm으로 다 치환해줄 수 있다고 생각했고,

ssh를 위해 열려있는 22번 포트를 닫을 수 있도록 할 수 있지 않을까 싶었다.

 

그래서 git pull 을 해주어야 했었는데, 그것이 ssh로 설정되어있어서, 인바운드 아웃바운드 모드 port 22를 닫아버리자!

이제 git pull https 도 보안이 아이디비번을 입력하는게 아니라 token을 생성해서 해당 리소스 접근 권한을 관리할 수 있으며,

속도는 ssh가 더 빠르다고는 하지만, 유의미한 차이가 안느껴진다고 하니

https로 아예 바꿔버리자는 생각을 호기롭게 하여

생각보다 https token을 직접 url 로 보이면 토큰이 log 때문에 유출되기 때문에 이것저것 설정해주고,,,

 

보안 신경쓰겠다고 이것저것 했는데, 아무리 그래도 git pull은 ssh의 장점이 더 있다고 한다.

 

간결함도 더 증가했는데

아래와 같이 처리해주던 것을 ssh로 하면 그냥 한줄로 해주면 된다.

  "export HOME=/home/ec2-user",
  "GITHUB_TOKEN=$(aws ssm get-parameter --name \"" --with-decryption --query \"Parameter.Value\" --output text)",
  "echo \"https://x-access-token:${GITHUB_TOKEN}@github.com\" > /home/ec2-user/.git-credentials",
  "chmod 600 /home/ec2-user/.git-credentials",
  "git config --global credential.helper store",
  "git config --global --add safe.directory /home/ec2-user/[repo이름]",
  "cd /home/ec2-user/[repo이름]",
  "git pull https://github.com/featuring-corp/[repo이름].git main",

위에로 해야 됐던 것이

아래처럼 하면 된다.

"sudo -u ec2-user bash -c '\''[command 명령어]'\''"

 

끝!

 


[TMI] 내가 놓친 부분이 뭐였을까?

HTTPS로 git pull을 하면 매번 GitHub Personal Access Token (PAT)을 넣어서, 토큰이 노출되거나 만료되면 매번 갱신이 필요하고 보안이 취약해질 수 있다고 해서, 일부로 home/ec2-user/.git-credentials에 넣어주는 것이었는데,,, 사실 안에 미리 넣어두면 필요는 없는 명령어 같기도 하고, 그러나 git pull 시에는 https 로 작성해주어야 함

- SSH는 한 번 키를 등록해 두면 해당 키만 있으면 인증이 자동으로 되기 때문에 편리하고 안전

=> EC2 인스턴스에서 ~/.ssh/id_rsa 형태로 private key를 두고, GitHub에 해당 키의 public key를 등록

 

다시보면 상황이

기존 github action에서 airflow ec2로의 SSH 연결 -> 외부 네트워크에서 EC2 인스턴스에 연결 시도
: 안전하게 처리하기 위해선 github action을 실행하는 github 내부 인스턴스의 IP를 알고 연결을 허용

airflow ec2 instance에서 git pull 요청 -> EC2 인스턴스에서 private github repository로의 접근
: 기본 허용 X -> 안전한 연결을 위해 SSH 연결
github repository 자체에 deploy key (공개키)를 넣고, 이에 대한 pem key (비밀키)를 airflow 인스턴스에서 git에 연결할 때 사용하도록 함

HTTPS 연결에서는 특정 repo에 대한 권한 관리가 쉽지 않다 -> 비동의하려고 하다가, HTTPS에서 인증은 보통 PAT(Personal Access Token) 로 하는데, GitHub 사용자 계정 단위로 발급되기 때문에, 계정 전체 권한을 가질 수 있지만, 단일 repo에 주기는 어렵다!!
deploy key를 설정해 확실하게 관리할 수 있는 SSH 요청이 더 안전 -> 인정
우리팀 리더님 GOD

github action에서 airflow ec2에 ssh 연결할시, 외부네트워크->EC2인스턴스 연결

-> ip는 github action에서 동적 할당이 되기 때문에,, self-hosted runner나 SSM을 사용해야 됐는데

self-hosted runner 는 따로 서버를 관리해주는 불편함이 있기 때문에 SSM을 선택했다.

 

[main] 가장 크게 놓친 것은 ssm으로 ssh 사용을 아예 치환이 가능하네!?, ssm이 더 advanced 한 skill! 이라고 생각했기 때문에, 

그냥 "ssh"? 다 치환! 이런식으로 생각해서 이것저것 찾아봤던 것 같다.

생각해보면, Github Actions 에서는 EC2 내부의 git pull 이기 때문에 SSM 과 무관한데,

ssm으로 ec2에 명령을 전달할 뿐,

실제 git pull은 EC2 내에 수행되기 때문에 그 순간은 EC2가 GitHub에 접속하는 것

즉, EC2 → GitHub 방향의 접속이라, GitHub Actions의 IP나 인증은 전혀 상관없었을 지도,,

굳이 https 로 써주었던 것 같다,, SSM이 https로 통신을 하기 때문에 다 https로 바꿔주려고 했던 나

이제 보니까 그냥 삽질을 했던 것 같다,,

 

 

 

[solution]

이러한 삽질을 안하려면,, 삽질을 많이 해보고

경험치가 쌓어야 스스로 알 것 같다는 생각이 든다.

+ 문제 상황을 제대로 파악하고 들어가야 할 것 같다.!

 

 

참고 및 출처

- https://mane-datalab.tistory.com/entry/Github-Actions-GitHub-Actions-AWS-Credentials-설정?utm_source=chatgpt.com

- https://velog.io/@rlatjdgh9612/Github-Action-Checkout%EC%BD%94%EB%93%9C-%EB%82%B4%EB%A0%A4%EB%B0%9B%EA%B8%B0

- docker images 삭제 https://brunch.co.kr/@hopeless/10

- AWS SSM EC2 인스턴스에 접근 https://musma.github.io/2019/11/29/about-aws-ssm.html

- Github Action의 Self hosted Runner https://danawalab.github.io/common/2022/08/24/Self-Hosted-Runner.html

- LG CNS https://www.lgcns.com/blog/cns-tech/aws-ambassador/40899/

- https://docs.github.com/en/actions

반응형