본문 바로가기
Server

GitLab CI/CD + SSH 공개키를 이용한 자동배포

by 평범한 개발자... 2021. 9. 14.

Start

Gitlab + AWS 연동에 관한 글을 참 많지만.. 저처럼 IDC 서버를 사용하는 사람들에겐 해당하지 않는 내용이라..

자료도 많지 않고, 설명이 부실한 글들이 많아서 직접 정리해봅니다.

무작정 따라하는것 보다, 공개키를 이용한 SSH 접속의 전체적인 흐름을 이해하고 읽는 것이 훨씬 더 도움됩니다.

SSH 공개키 인증을 사용하여 접속하기

Process

  1. 클라이언트 키쌍 생성 (공개키-비밀키)
    • 패스워드 입력 없이 SSH 접속하기 위함.
    • 패스워드 대신 공개키 및 비밀키 사용.
  2. Gitlab Variables 등록
    • 배포할 서버의 IP 혹은 도메인 주소 (노출돼도 상관없으면 스크립트에 직접 넣어도 됩니다.)
    • SSH 비밀키 (생성한 키의 비밀키)
    • (옵션) 배포 서버의 SSH 공개키 (주의: 생성한 키의 공개키가 아님)
      • known_hosts로 등록하기 위함
      • 서버의 SSH 공개키는 /etc/ssh 경로에 있으며, ssh 설치 시 생성됨
  3. 배포 서버에 공개키 등록 (생성한 키의 공개키)
    • ~.ssh/authorized_keys 파일에 등록.
    • SSH 클라이언트 접속 시, 등록되어있는 공개키의 해당하는 비밀키를 가지고 있다면 접속을 허용해줍니다.
  4. Gitlab 스크립트 작성
  5. 자동 배포 확인

1. 클라이언트 키쌍 생성

  • ssh-keygen 명령어를 이용하여 키쌍을 생성합니다.
    • Windows 10이나 대부분 리눅스는 기본적으로 설치가 되어있는데, 없으면 설치하면 됩니다.
    • cmd 창에 ssh-keygen 명령어를 입력하고, 엔터를 쭉쭉 눌러주면 C:Users\계정\.ssh\ 경로에 키쌍이 생성됩니다.
    • ssh-keygen 명령어의 기본 값은 아래와 같습니다.
      • RSA 3072 비트 (SHA256)
      • 키 생성 경로: ~.ssh\
        • 윈도우, 리눅스 동일
        • 비밀키 (id_rsa)
        • 공개키 (id_rsa.pub)
      • 키에 패스워드를 지정하지 않음.

2. Gitlab Variables 등록

  • Settings -> CI/CI -> Variables -> Add variable
  • 저는 이미 변수를 등록해놓은 상태입니다.

  1. 비밀키 등록
    • Key
      • 스크립트에서 사용할 변수명
    • Value
      • 아까 생성한 비밀키(id_rsa)를 붙여넣습니다.
    • Type
      • File로 변경

  1. 서버 IP or 도메인 등록

  1. (Option) 배포 서버의 SSH 공개키 등록
  • 서버에 접속하여, /etc/ssh/ssh_host_*.pub 파일들을 확인합니다.
  • 보통 ssh-server를 설치하면 3개의 키쌍이 생성되는데, 이 중 아무 공개키를 사용해도 무관합니다.

  • 아래와 같이 변수로 등록해줍니다. (서버 IP주소 입력 후 한칸 띄어야 합니다.)
  • 만약 포트가 22번이 아니라면 [IP주소]:포트 형태로 입력합니다.
    • ex) [111.111.111.111]:2243 ssh-ed25519 AAAA.........JJJ
  • 이 과정은 하지 않아도 되지만, 하는 이유와 하지않으면 어떤 문제가 있는지 설명합니다.

키를 등록하는 이유

  • 서버에 처음 SSH 접속 시 아래와 같은 메시지를 많이 보셨을겁니다.

  • 로컬에 서버의 키가 등록 되어있지 않은데, 이 서버를 신뢰할 수 있다면 로컬에 서버키를 추가 후 SSH 접속을 하고, 그렇지 않다면 접속하지 않습니다.
  • 키를 추가하게 되면 다음부터 이 서버에 접속할 때 마다, 서버에 대한 인증을 위해 로컬에 저장되어있는 키를 이용하여 인증하는 과정을 거칩니다.
  • 이런 과정을 통해 중간자 공격을 예방하여 안전하게 SSH 접속이 가능합니다.

Gitlab 변수로 등록하는 이유

  • SSH 클라이언트를 사용하는 우리 입장에서는, 엔터를 치거나 마우스 클릭으로 등록을 하면 됩니다.
  • 그러나, 빌드 할 때마다 매번 새로운 도커 이미지가 생성되고 콘솔에서 조작이 불가능한 Gitlab에서는 스크립트를 통해 서버키를 미리 등록함으로써 해당 과정을 생략할 수 있습니다.

이 과정을 하지 않으면?

  • 공개키 등록 대신에, ssh 설정으로 이 서버키 등록 과정을 생략하고 SSH 접속을 할 수 있습니다.
  • 바로 Host Key Checking을 비활성화 하는 것인데요,
  • 이 옵션을 추가하게 되면, 처음 접속할 때 공개키 등록 없이 바로 SSH 접속이 가능하게 되지만, 중간자 공격에 취약할 수 있습니다.

3. 배포 서버에 공개키 등록

  • 키쌍으로 생성한 공개키를 서버의 ~/.ssh/authorized_keys 파일에 등록합니다.
    • 많이 실수하는 부분인데, SSH로 접속할 계정의 홈디렉토리/.ssh 폴더입니다.
    • 일반 유저계정으로 SSH 접속할건데, /root/.ssh/authorized_keys 파일을 수정하면 안됩니다.
  • 공개키 등록 방법
    1. 직접 등록
      • vi와 같은 편집기를 통해 공개키 복사 및 붙여넣기 합니다.
    2. ssh-copy-id 명령어 이용
      • 윈도우
        • 윈도우는 ssh-copy-id 명령어가 없기 때문에, 다른 명령어로 대체합니다.
        • type $env:공개키위치 | ssh 계정@IP "cat >> .ssh/authorized_keys"
        • 만약 Windows에서 키쌍을 생성했다면 공개키의 경로는 C:\Users\계정\.ssh\id_rsa.pub 입니다.
        • 위 명령어를 수행하면 공개키값을 변수에 담아서 SSH 접속 후, .ssh/authorized_keys에 붙여 넣게됩니다.
        • 서버에 접속 후 authorized_keys을 확인해보면 공개키값이 잘 들어가있는 것을 확인 할수 있습니다.
      • 리눅스계열
        • 리눅스는 간단합니다. ssh-copy-id 계정@IP
        • 해당 명령어를 입력하면 ~/.ssh 폴더에 있는 공개키를 해당 서버에 등록합니다.

4. 스크립트 작성

  • 프로젝트 최상위 폴더에 .gitlab-ci.yml 파일을 생성합니다.
  • 아래 스크립트 내용 붙여넣습니다.
stages:
    - build
    - deploy

image: java:8-jdk # jdk8 도커 이미지 사용 (배포환경에 따라 변경할 것)

cache:
    paths: # .gradle 캐시 적용
        - .gradle/wrapper
        - .gradle/caches

build:
    stage: build
    before_script:
        - chmod +x ./gradlew # gradlew 실행권한 부여 (초기 권한 666 [-rw-rw-rw-])
    script:
        - ./gradlew build
    artifacts: 
        paths:
            - build/libs/*.jar    # build의 결과물인 jar파일을 artifacts로 지정. 
        expire_in: 1 week    # 1주일 동안 보관

deploy-to-server:
    stage: deploy
    before_script:
        - mkdir -p ~/.ssh
        - eval $(ssh-agent -s) # ssh-agent 백그라운드 실행

        ###############################################
        # 공개키 등록을 안했다면 Host Key Checking 비활성화 옵션 추가 (중간자 공격 위험)       
        # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'    

        # 공개키 등록을 했다면 known_hosts 등록 및 권한 변경
        # - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
        # - chmod 644 ~/.ssh/known_hosts
        ###############################################

        - chmod 600 "$SSH_KEY" # 개인키 파일 권한변경 
        - ssh-add "$SSH_KEY"   # SSH 개인키 추가
    script:
        # SSH를 이용한 원격 파일 업로드
        - scp build/libs/*.jar 계정명@"$DEPLOY_SERVER_IP":~/BUILD_PATH/build.jar
        # 원격 스크립트 실행
        - ssh 계정명@"$DEPLOY_SERVER_IP" /BUILD_PATH/start.sh
  • 아래는 서버에서 실행 할 원격 스크립트 파일 내용입니다.
  • 단순히 기존 프로세스가 있으면 kill 후 재실행, 없으면 그냥 실행합니다.
    #!/bin/sh
    cd ~/BUILD_PATH
    PID=$(ps -ef|grep build.jar|grep -v grep|awk '{print $2}')
    if [ "$PID" == "" ]; then
      echo "no process exist"
    else
      echo "process id (${PID}) killed"
      kill -9 ${PID}
    fi
    echo "Program Start"
    nohup java -jar build.jar 1 > /dev/null 2>&1 &

5. 자동 배포 확인

  • Gitlab으로 Push 하여 CI/CD를 동작시킵니다.
  • 별다른 문제 없이 성공하였다면, 서버에 접속하여 프로세스가 동작하는지 확인합니다.
반응형

댓글