[ AWS Terraform ] Terraform 코드 실행 후 할 일

2024. 7. 22. 15:51·🌥️Cloud Study🌥️/AWS

이 문서에서는 `terraform apply`이후 할 일들에 대해서 서술한다.

 

먼저 AWS 콘솔에 접속 후 로그인한 뒤, Terraform으로 만들어진 인스턴스들의 IP 주소를 확인한다.

(근데 귀찮으니까 `연결`클릭해서 ` ssh -i "KDT_Project2_AWS.pem" ubuntu@52.78.100.13 `코드를 복붙 하자)

 

1. SSH 접속 포트 변경

user_data = <<-EOF
              #!/bin/bash
              ...
              hostnamectl set-hostname jenkins-instance
              echo "127.0.1.1 jenkins-instance" >> /etc/hosts

              # SSH 포트 변경
              sed -i 's/#Port 22/Port 51228/' /etc/ssh/sshd_config
              systemctl restart ssh

              ...

이런 식으로 Terraform 코드로 포트를 변경하는 코드를 짰었는데, 막상 접속하려고 보니 접속이 안 되어서(이거 왜 이런지 모르겠다...)

그냥 수동으로 작성해주기로 했다.

 

sudo nano /etc/ssh/sshd_config
# 포트 번호 변경 진행
sudo systemctl restart ssh

 

띠용; 그래도 안 되네.. 일단 이건 빼두고

애초에 특정 IP로만 접속 가능하게 해뒀으니 다음 과정으로 넘어가자.

 


# Java 설치
sudo apt update
sudo apt install -y openjdk-17-jdk

2. Jenkins 세팅

sudo cat /var/lib/jenkins/secrets/initialAdminPassword
  • 초기 관리자 비밀번호 출력하여 초기 설정 설치 진행
  • Jenkins 관리 - Tools - Gradle 설치 (ID는 임의로 'GRADLE'로 설정)
  • Jenkins 관리 - Plugins - Available plugins에서 SSH Agent, Pipeline: Stage View 설치
  • Jenkins 관리  - Credentials - Github 웹 훅 토큰과 AWS에서 인스턴스 생성 시 지정한 .pem 설정
  • 깃허브 레포지토리 - webhook의 주소를 Jenkins 인스턴스의 Public IP로 변경
    (ex: http://`52.78.100.13:8080`/github-webhook/)
  • 파이프라인 코드 입력
def deployApp(targetServerIp, targetServerPort) {
    def jarPath = 'build/libs/inclass-spring-security-0.0.1-SNAPSHOT.jar'
    def deployPath = '/home/ubuntu'
    def runAppCommand = "nohup java -jar $deployPath/inclass-spring-security-0.0.1-SNAPSHOT.jar > nohup.log 2>&1 &"
    def checkLogCommand = "grep -q 'Started inclass-spring-security in' $deployPath/nohup.log"
    def checkProcessCommand = "pgrep -f inclass-spring-security-0.0.1-SNAPSHOT.jar"
        
    // 서버에 파일을 SCP로 전송
    sshagent(['KDT_Project2_AWS']) { // 이 부분에서 'KDT_Project2_AWS'는 Jenkins에 등록한 Credential ID (AWS에서 발급한 키 페어)
        // Terminate any existing application process
        sh "ssh -o StrictHostKeyChecking=no -p $targetServerPort ubuntu@$targetServerIp 'ps -ef | grep java | grep -v grep | awk \'{print \$2}\' | sudo xargs kill -9 || echo \"No process found\"'"

        
        // Deploy the new JAR file and start the application
        sh "scp -o StrictHostKeyChecking=no -P $targetServerPort $jarPath ubuntu@$targetServerIp:$deployPath/"
        sh "ssh -o StrictHostKeyChecking=no -p $targetServerPort ubuntu@$targetServerIp '$runAppCommand'"
    }
}

pipeline {
    tools {
        gradle "GRADLE" // Jenkins에서 설정한 Gradle의 이름
    }

    agent any
    stages {
        stage('Clone') {
            steps { // main인지 master인지 확인하고 Pipeline Syntax 돌려서 이중으로 확인해보기
                git 'https://github.com/lcl1380/KDT_Project2.git'
            }
        }

        stage('Build') {
            steps {
                sh 'chmod +x ./gradlew'
                sh './gradlew clean build'
            }
        }
        
        stage('Test') {
            steps {
                script {
                    sh './gradlew test'
                }
            }
        }
        
        stage('Deploy A-Private Instance') {
            steps {
                script {
                    deployApp('10.0.2.56', 22)
                }
            }
        }
        
        stage('Deploy B-Private Instance') {
            steps {
                script {
                    deployApp('10.0.5.193', 22)
                }
            }
        }
    }
    post {
        success {
            echo "This will run when the run finished successfully"
        }
        failure {
            echo "This will run if failed"
        }
    }
}

3. DB 관련 세팅

Caused by: java.sql.SQLException: null,  message from server: "Host '10.0.2.207' is not allowed to connect to this MySQL server"
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:438) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:189) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
        at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100) ~[HikariCP-5.0.1.jar!/:na]
        at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar!/:na]
        at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160) ~[spring-jdbc-6.1.6.jar!/:6.1.6]
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118) ~[spring-jdbc-6.1.6.jar!/:6.1.6]
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81) ~[spring-jdbc-6.1.6.jar!/:6.1.6]
        ... 44 common frames omitted

다음과 같은 오류 메시지가 출력되었다.

 

해당 오류 메시지는 MySQL 서버가 `10.0.2.207` IP주소를 가진 호스트의 연결을 허용하지 않기 때문에 발생한 것이다.

주 원인은 다음과 같다.

  1. 사용자 권한 문제 : MySQL 서버에서 특정 사용자에게 특정 호스트에서의 접속을 허용하지 않았을 경우
  2. 방화벽 설정 : MySQl 서버로의 외부 접근을 방지하는 방화벽이 설정되어 있을 경우
  3. MySQL 설정 문제 : MySQL 서버의 설정 파일에서 외부 접속을 허용하지 않도록 설정되어 있을 경우
// 특정 IP에서의 접속을 허용 (예: '10.0.2.207'에서 접속 허용)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'10.0.2.207' IDENTIFIED BY 'password';

// MySQL 8.0 이상 부터는 IDENTIFIED BY 대신 CREATE USER 명령어를 사용하여 비밀번호를 설정해야 한다

// 데이터베이스 생성
CREATE DATABASE spring_security_inclass;

// 사용자 생성
CREATE USER 'username'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'username'@'%';
FLUSH PRIVILEGES;

// 기존 사용자 변경
ALTER USER 'username'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'cherish'@'%';
FLUSH PRIVILEGES;

MySQL 서버에 접속하여 사용자에게 외부 접속 권한을 부여해주자.

 

output.log
0.16MB

 

이후 로컬에서 직접 Jenkins를 통하지 않고 하드 빌드 해 봤는데, 오류 로그는 위 파일에 올려두었다.

오류를 분석해보니 MySQL DB 연결과 관련된 오류를 확인할 수 있었다.

 

오류 분석 내용 (더보기)

더보기

로그 파일에서 주요 예외 메시지를 분석한 결과, 가장 두드러지는 문제는 MySQL 데이터베이스 연결과 관련된 오류입니다. 다음과 같은 예외가 발견되었습니다:

  1. java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
  2. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jdbcSessionDataSourceScriptDatabaseInitializer'

문제 1: Public Key Retrieval is not allowed

이 오류는 MySQL 서버에 연결할 때 "Public Key Retrieval"이 허용되지 않아서 발생하는 문제입니다. 이는 MySQL 8.0 이상 버전에서 SSL 연결 또는 RSA 기반의 암호화된 비밀번호 사용 시 발생할 수 있습니다.

해결 방법:

  1. JDBC URL 수정: JDBC URL에 allowPublicKeyRetrieval=true 옵션을 추가합니다. 예를 들어, application.properties 또는 application.yml 파일에서 JDBC URL을 다음과 같이 수정합니다.
    `spring.datasource.url=jdbc:mysql://your-database-host:3306/your-database-name?allowPublicKeyRetrieval=true&useSSL=false`

  2. SSL 설정: useSSL=false를 추가하여 SSL 사용을 비활성화할 수 있습니다. 보안이 중요한 환경에서는 SSL 설정을 다시 고려해야 합니다.

문제 2: Failed to determine DatabaseDriver

이 오류는 Spring Boot 애플리케이션이 데이터베이스 드라이버를 찾을 수 없어서 발생하는 문제입니다. 이는 데이터베이스 연결 설정이 올바르게 구성되지 않았기 때문에 발생할 수 있습니다.

해결 방법:

1. 데이터베이스 드라이버 의존성 확인: pom.xml 또는 build.gradle 파일에 MySQL 커넥터 의존성이 추가되어 있는지 확인합니다.

<!-- For Maven -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>
// For Gradle
implementation 'mysql:mysql-connector-java:8.0.30'

 

2. 애플리케이션 설정 확인: application.properties 또는 application.yml 파일에서 데이터베이스 설정을 올바르게 구성합니다.

spring.datasource.url=jdbc:mysql://your-database-host:3306/your-database-name
spring.datasource.username=your-username
spring.datasource.password=your-password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

요약

  • Public Key Retrieval 오류: JDBC URL에 allowPublicKeyRetrieval=true와 useSSL=false 옵션을 추가합니다.
  • DatabaseDriver 문제: MySQL 커넥터 의존성이 제대로 추가되었는지 확인하고, 데이터베이스 설정을 올바르게 구성합니다.

저번에 접속할 때에는 DB생성하고 유저 생성만 하면 됐었는데, 이번에는 좀 헤매다 된 거라 뭐가 뭔지 모르겠다.

일단 한 것들 정리해보자 ...

1. DB 생성함

2. 사용자 생성함

3. 권한 부여함


 

4. nginx 리버스 프록시 설정

sudo nano /etc/nginx/nginx.conf

# ----------------------------------------------------------------------------
http {
    upstream inclass-spring-security {
        server 10.0.2.67:8080 weight=100 max_fails=3 fail_timeout=3s;
    }

    upstream grafana {
        server 10.0.2.192:3000 weight=100 max_fails=3 fail_timeout=3s;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://inclass-spring-security;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }

        location /grafana/ {
            proxy_pass http://grafana;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
}
# ----------------------------------------------------------------------------

sudo systemctl restart nginx

+ 24. 07. 24 : 모니터링 인스턴스로 접속하는 부분 추가.

 

Nginx 전체 코드 백업 (더보기)

더보기
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    upstream inclass-spring-security {
        server 10.0.2.67:8080 weight=100 max_fails=3 fail_timeout=3s;
    }

    upstream grafana {
        server 10.0.2.192:3000 weight=100 max_fails=3 fail_timeout=3s;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://inclass-spring-security;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }

        location /grafana/ {
            proxy_pass http://grafana;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

5. sudo 권한 설정

젠킨스는 기본적으로 jenkins라는 계정으로 스크립트 명령을 내리는데, ubuntu계정의 소유 요소에는 쓰기 작업 등에 대해 허가가 나지 않는 경우가 있다.

이 때, jenkins 계정으로 sudo 명령을 비밀번호 없이 사용할 수 있도록 사전에 권한을 부여해보자.

 

단순 파일 전송을 진행하는 경우엔 jenkins 인스턴스에만 설정해주면 되고, 접속해서 sudo 권한이 필요한 행동을 할 경우에는 행위대상 인스턴스에도 설정해주자.

혹시 jenkins쪽에서 사용하는 계정명이 jenkins가 아닐 수도 있으니 파이프라인 실행시 `sh "whoami"`로 계정명을 꼭 확인해주자!

# Jenkins 인스턴스에서
sudo visudo

# root 권한 밑에 추가
jenkins ALL=(ALL) NOPASSWD: ALL

'🌥️Cloud Study🌥️ > AWS' 카테고리의 다른 글

[ AWS ] 파이프라인을 이용한 무중단 배포  (0) 2024.07.23
[ AWS ] 아틸러리를 이용한 부하 테스트 및 부하 분산 확인(I/O bound)  (1) 2024.07.23
[ AWS-Terraform ] 테라폼을 이용한 아키텍처 구축  (0) 2024.07.18
[ AWS ] 배포 파이프라인 만들기  (0) 2024.07.17
[ AWS ] 보안그룹-인바운드 규칙 편집, 개별 인스턴스 설정  (0) 2024.07.16
'🌥️Cloud Study🌥️/AWS' 카테고리의 다른 글
  • [ AWS ] 파이프라인을 이용한 무중단 배포
  • [ AWS ] 아틸러리를 이용한 부하 테스트 및 부하 분산 확인(I/O bound)
  • [ AWS-Terraform ] 테라폼을 이용한 아키텍처 구축
  • [ AWS ] 배포 파이프라인 만들기
L_Chae
L_Chae
🎮😻🤓🖥✨
  • L_Chae
    Cherish
    L_Chae
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 🌥️Cloud Study🌥️
        • AWS
        • NHN
        • KT
        • Microsoft (Azure 900)
        • TroubleShooting
        • IaC
        • Etc
      • STUDY
        • English
        • Japanese
        • 개인정보보호 관련
      • 초등학교 AI 교육 진행
        • 2024학년도 1학년-2학년
        • 2025학년도 4학년
      • 2024 KDT 📕
        • Lecture
        • Study 📗
        • Study-JAVA
        • Project
        • etc
      • INTERLUDE ✦
        • 2022 SYSTEM STUDY
        • 2022 Winter Study
        • 2023 AutoMobility STUDY
        • 2023 Summer Study (CPPG)
        • 2023 Reversing STUDY
        • etc
      • Private🔒
        • MacBook 💻
        • Screenshot 🩷
        • Photo 🖼️
        • FFXIV - Backup 🎮
        • Tistory
      • PBL 📗
        • 논문 스터디
        • Backup
      • Project 🖤
        • 2022-2) 개인정보보호 소학회
        • 2022-2) winter GURU2 - iOS
        • 2023-1) PBL 3
        • 2023-2) PBL 4
        • 2024-1) SW-AI교육 실습 일지
      • CTF 🚩
        • 2022
        • 2023
      • News scrap 📰
        • 2022
        • 2023
      • 2022 공부 로그 🐯
      • 2023 공부 로그🐰
  • 블로그 메뉴

    • 글쓰기
    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    멱등성
    deprecation warning
    jlpt n1 도전기
    ansible
    JLPT N1
    N1
    ansible galaxy
    JLPT
    content collection
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
L_Chae
[ AWS Terraform ] Terraform 코드 실행 후 할 일
상단으로

티스토리툴바