Oracle Cloud Free Tier - PostgreSQL 서버 구축

지난번 생성한 프리티어 서버에 PostgreSQL 서버를 구축해보자.

서버 접속

우리는 생성한 서버에서 ssh를 설정하여 해당 값에 맞는 private key 파일이 있어야 서버에 접근이 가능하다.
터미널에서 ssh 명령어를 통해 접속하는 방식으로 사용할 것이기에 putteygen을 통해 ppk 파일을 pem 형식의 파일로 변환 시켰다.
이렇게 까지 진행 했으면 이젠 접속을 할 때,

$ ssh -i {#키파일명}.pem {#계정명}@{#IP} -p {#PORT}

해당 방식으로 접속하면 된다.

서버 설치

접속까지 완료 했으면 이제 PostgreSQL을 설치 해보자.
PostgrSQL 공식 사이트 - 설치 가이드

해당 페이지를 들어가 보면 yum 명령어를 사용한 설치 가이드가 있다.

PostgreSQL 1

위 이미지 처럼

  1. PostgreSQL 버전 선택
  2. 플랫폼 선택
  3. 아키텍쳐 선택을 하면

자동으로 설치 스크립트가 생긴다. 해당 스크립트를 하나씩 천천히 복사 - 실행을 해주면
쭈루루루룩 설치가 되며 마지막에 yum list installed *postgres*를 입력해주면 현재 설치된 PostgreSQL 패키지가 나온다.

PostgreSQL 2

그리고 설치 스크립트 아래에 이런 패키지가 중요하다고 설명을 해준다.

The repository contains many different packages including third party addons.
The most common and important packages are (substitute the version number as required):

패키지 설명
postgresql-client 라이브러리 및 클라이언트 바이너리
postgresql-server 코어 데이터베이스 서버
postgresql-contrib 추가 제공 모듈
postgresql-devel C 언어 개발을 위한 라이브러리 헤더

중요한 패키지라고 하는데 우선은 나중에 설치하고… 아래 명령어를 입력해 주면?

$ su - postgres

postgres 계정으로 접속이 된다. 여기 까지되면 정상적으로 설치까진 성공이다.

PostgreSQL 3

접속 환경 설정

이제 해당 DB서버를 외부에서도 접속하기 위해 설정을 변경해 줘야한다. psql 버전이 13이니까 경로에 13 폴더가 더 추가 된 것 같다.

$ vi /var/lib/pgsql/13/data/pg_hba.conf

pg_hba.conf 파일부터 수정을 해야하는데 우선 인증방식의 종류부터 간단하게 확인해보고 작업을 설계해보자 여러가지 방식이 있지만 우선 설정파일에 기본적으로 설정되어있는 METHOD들만 정리하였다. 다른 방식들은 아래의 공식 문서를 참조해서 더 알아볼 수 있다.
PostgreSQL 공식 문서 - 인증 방식 참조

인증방식 설명
peer 피어(peer) 인증 방법은 클라이언트의 운영 체제 사용자 이름을 커널로부터 획득하고, 허용된 데이터베이스 사용자 이름으로 사용함으로써 작동된다 (선택적 사용자 이름 매핑 사용 ex: all, postgres 등으로 사용자 매핑 ) 이 방법은 로컬 연결에만 지원된다.
md5 암호 스니핑을 방지하고 일반 텍스트로 서버에 암호를 저장하는 것을 방지(암호화)하지만 공격자가 서버에서 암호 해시를 훔치는 경우 보호 기능을 제공하지 않는다. 또한 MD5 해시 알고리즘은 이제 더 이상 결정된 공격에 대해 안전한 것으로 간주되지 않는다.
scram-sha-256 신뢰할 수없는 연결에서 암호 스니핑을 방지하고 안전한 것으로 간주되는 암호화 해시 된 형식으로 서버에 암호를 저장하는 것을 지원하는 시도 응답 체계다. 이것은 현재 제공되는 방법 중 가장 안전하지만 이전 클라이언트 라이브러리에서는 지원되지 않는다.

정리한 것 처럼 현재 가장 안전한 scram-sha-256 방식을 사용한다. 해당 인증 방식은 PostgreSQL 버전 10부터 사용 가능하다.

1. pg_hba.conf 가장 아래쪽을 보면 인증방식 세팅 부분이 있다. 우선 로컬에서도 다른 계정으로도 psql 명렁어로 접속할 수 있게 peer 로 되어있던 부분을 scram-sha_256으로 세팅한다.

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     scram-sha-256 # peer에서 변경
# IPv4 local connections:
#host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             0.0.0.0/0            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege. 미사용 설정 주석 처리
#local   replication     all                                     peer
#host    replication     all             127.0.0.1/32            scram-sha-256
#host    replication     all             ::1/128                 scram-sha-256

2. 이후에 postgresql.conf 에서 listen_address 주소값을 변경해 줘야 한다.

vi /var/lib/pgsql/13/data/postgresql.conf

들어가 보면 해당 설정값이 있는데 기존에는 IP adress 값이 있지만 난 모든것을 허용할 것이기에 ‘*‘ 로 변경해준다.

#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

# - Connection Settings -

listen_addresses = '*'                  # what IP address(es) to listen on;

3. 여기 까지 설정이 완료되었으면 PostgreSQL을 재시작 한번 해준다. 정상적으로 재시작 되었는지 확인하려면 status 명령어로 확인해본다. 정상이라면 Active 에 러닝 타임이 재시작 시간을 찍힌 것을 확인할 수 있을 것이다.

$ systemctl restart postgresql-13
$ systemctl status postgresql-13

postgresql-13.service - PostgreSQL 13 database server
  Loaded: loaded (/usr/lib/systemd/system/postgresql-13.service; enabled; vendor preset: disabled)
  Active: active (running) since Wed 2021-07-07 04:25:19 GMT; 8s ago
    Docs: https://www.postgresql.org/docs/13/static/
 Process: 119391 ExecStartPre=/usr/pgsql-13/bin/postgresql-13-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
Main PID: 119396 (postmaster)
   Tasks: 8 (limit: 4563)
  Memory: 18.0M
  CGroup: /system.slice/postgresql-13.service
          ├─119396 /usr/pgsql-13/bin/postmaster -D /var/lib/pgsql/13/data/
          ├─119399 postgres: logger
          ├─119401 postgres: checkpointer
          ├─119402 postgres: background writer
          ├─119403 postgres: walwriter
          ├─119404 postgres: autovacuum launcher
          ├─119405 postgres: stats collector
          └─119406 postgres: logical replication launcher

와 이제 그럼 외부에서 접속이 가능한건가 하고 해봤지만 안된다. connection timeout이 된다. 방화벽 문제였던 것이다.

방화벽 설정

1. 우선 # firewall-cmd --list-all 명렁어를 통해 현재 방화벽 설정 상태를 조회 할 수 있다. 아래는 가장 기본 상태이다.

$ firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

2. 방화벽 오픈할 포트를 추가 해 주자. postgresql은 5432 포트니까 5432를 열어주면 된다.

$ firewall-cmd --permanent --add-port=5432/tcp

3. 추가한 이후에는 반드시 reload 처리를 해줘야 적용이 되니 reload를 시켜준다.

$ firewall-cmd --reload

4. 그리고 다시 방화벽 상태를 조회해 보면 5432포트가 추가가 된 것을 확인 할 수 있다.
만약 잘못 추가 되었다면 firewall-cmd --zone=public --permanent --remove-port=5432/tcp 의 형식으로 PORT값을 맞춰 제거 하고 다시 reload 해준다.

$ firewall-cmd --list-all
public
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 5432/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

5. 이젠 패킷에 대한 동작을 설정하기 위해 iptables를 설정해야 한다.

iptables : 패킷에 대한 동작을 등록된 순서로 부터 검사하고, 그 규칙과 일치하는 패킷에 대하여 ACCEPT, REJECT, DROP 등의 동작을 한다.

그래서 처음 iptables --list로 구성된 설정을 조회해 보면 아래와 같이 설정되어 있다.

$ iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
BareMetalInstanceServices  all  --  anywhere             169.254.0.0/16
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain BareMetalInstanceServices (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             169.254.0.2          owner UID match root tcp dpt:iscsi-target /* See the Oracle-Provided Images section in the Oracle Bare ...

여기서 내가 허용할 port를 설정하자. 옵션을 줄때는 이렇게 주었다.

  • -I INPUT : 신규규칙으로 INPUT에 넣겠다.
  • -p tcp : 패킷의 프로토콜은 tcp로 한다
  • –dport 5432 : 포트는 5432로 설정한다.
  • -j ACCEPT : 이 패킷을 어떻게 처리할 것인가 설정한다. 나는 INPUT 규칙으로 프로토콜은 TCP로 PORT는 5432로 패킷을 허용한다.
$ iptables -I INPUT -p tcp --dport 5432 -j ACCEPT

여기서 주의 할 점은 현재 설정된 list를 보면 가장 아래에 REJECT 처리로 reject-with icmp-host-prohibited 가 있다. 해당 처리 아래로 새로운 규칙을 추가하면 옵션을 추가하더라도 패킷에 대한 처리를 진행하지 않는다.

그리고 패킷 규칙을 잘못 설정 하였다면 iptables -D INPUT -p tcp --dport 5432 -j ACCEPT 의 형식으로 PORT값을 확인해서 제거 해주면 된다.

6. 그럼 이제 준비가 끝났다 외부에서 되는지 확인을 해보자 우선 간단한 테이블과 데이터를 넣는다.

CREATE TABLE member (
  id bigserial null PRIMARY KEY,
  name varchar(50) NULL,
  phone varchar(30) NULL
);

COMMENT ON COLUMN member.id IS 'member_ID';
COMMENT ON COLUMN member.name IS '이름';
COMMENT ON COLUMN member.phone IS '전화번호';

INSERT INTO member VALUES (NEXTVAL('member_id_seq'), '테스터', '010-1234-1234');

7. 내부적으로 테스트 파일을 만들어 테스트 해본다

1
2
3
4
5
6
7
8
9
10
11
12
13
public class JpaApplicationTest {

    @Autowired
    private MemberDao memberDao;

    @Test
    public void memberJpa() {
        for (Member member : memberDao.findAll()) {
            System.out.println(member.getName());
        }
    }

}

성공이다.

PostgreSQL 4

나만의 DB 서버까지 구축을 마무리 하였다. 앞으로 써먹을 일이 많을 것 같다.


작성자, DevInSpace