데이터가치연구소 공식 블로그

기관공유데이터 관리시스템(단독형) 설치기

공공데이터포털 고도화 사업의 기관공유데이터 관리시스템(단독형) 을 구축했습니다. NIA가 제공하는 설치 패키지로 배포하는 방식인데, 가이드 16쪽에 담기지 않은 내용이 꽤 많았습니다.

특히 사전조사 단계에서 예상한 구조와 실제가 완전히 달랐던 것이 시작이었습니다. 같은 길을 가실 분들을 위해 정리해 둡니다.


환경 요약

공식 설치가이드 기준으로 아래와 같이 필요한 환경을 준비합니다.

항목대상
배포 방식Podman 컨테이너 (compose)
DBMSPostgreSQL 17
WEB/WAS컨테이너 13종
Node.js / Python / JDK컨테이너 이미지에 포함

개별 미들웨어를 설치하지 않습니다. NIA가 주는 v2.1.0.tar 하나에 이미지와 스크립트가 다 들어 있고, install.sh가 배포합니다. 담당자가 할 일은 OS 준비 → 반입물 배치 → 스크립트 실행 → 검증 네 단계입니다.

어느 가이드를 따라야 하나

3티어용과 4티어용 가이드가 따로 옵니다. 차이는 Web(frontend)을 WAS에서 분리하느냐입니다. 저희는 서버 2대(WAS+연계 통합 / DB)라 3티어 가이드를 기준으로 하되, 연계서버 설치 절만 WAS 서버에서 함께 수행했습니다.


환경

  • OS: RHEL 8.10 (가이드는 Rocky Linux 8.10 기준)
  • 서버: WAS+연계 통합 1대, DB 1대
  • 컨테이너: podman 4.9 + podman-compose 1.6
  • 작업 계정: was_user (uid 1000 고정)

1. OS 준비

설치 스크립트 실행 전에 해결해야 하는 것들입니다. 미리 잡지 않으면 재설치·재작업으로 이어집니다.

함정 ① UID 1000이 이미 점유

모든 컨테이너가 uid 1000으로 기동하고 볼륨 파일 소유권이 해당 ID에 묶여 있어서, was_user는 반드시 uid 1000이어야 합니다. 그런데 OS 설치 시 만든 첫 계정이 1000번을 이미 갖고 있었습니다.

id 1000                              # 누가 쓰고 있나
# root 로, 해당 계정이 아닌 세션에서
pkill -u <기존계정>
groupmod -g 1100 <기존계정>
usermod -u 1100 -g 1100 <기존계정>
find / -xdev \( -uid 1000 -o -gid 1000 \) -exec chown 1100:1100 {} \; 2>/dev/null

groupadd -g 1000 was_user
useradd -u 1000 -g 1000 -m -s /bin/bash was_user

자기 자신이 로그인한 상태에서는 UID를 못 바꿉니다. 콘솔에서 root로 직접 들어가서 하세요. 실서버 신규 설치라면 OS 설치 때 첫 계정을 아예 was_user로 만드는 게 제일 깔끔합니다.

함정 ② sudo가 안 됨

was_user은(는) sudoers 설정 파일에 없습니다.

설치 스크립트 전부가 sudo를 쓰므로 첫 단계에서 멈춥니다. wheel 그룹에 넣었는데 재로그인하면 풀리는 증상이 있어서 sudoers.d 방식으로 갔습니다.

echo 'was_user ALL=(ALL) ALL' > /etc/sudoers.d/was_user
chmod 440 /etc/sudoers.d/was_user
visudo -c                            # ★ "parsed OK" 확인 필수

visudo -c를 꼭 돌리세요. sudoers 문법이 깨지면 sudo 자체를 못 쓰게 되어 복구가 매우 번거롭습니다.


2. 반입 매체 — FAT32면 못 옮깁니다

v2.1.0.tar가 약 6.7GB입니다. FAT32는 단일 파일 4GB 제한이 있어 복사 자체가 안 됩니다. exFAT로 포맷하세요. 기관 지정 보안 USB라 포맷을 못 바꾸면 split -b 3G로 나눠서 옮기고 서버에서 cat으로 합친 뒤 sha256sum으로 대조하면 됩니다.


3. 패키지 추출 — 경로 중첩

cd /home/was_user && tar -xf /tmp/v2.1.0.tar -C /home/was_user

반드시 /home/was_user에서 푸세요. 이미 만들어진 v2.1.0 안에서 풀면 v2.1.0/v2.1.0/으로 중첩되어 이후 모든 명령의 기준 경로가 어긋납니다. 아래 파일들이 함께 보이는 곳이 진짜 루트입니다.

ls VERSION install.sh compose.runtime.yml install_prereqs.sh

4. install_prereqs.sh — 번들 RPM 버전 차이

podman·python3.9·podman-compose를 오프라인 설치하는 스크립트입니다. 그런데 번들 RPM과 서버 설치본의 버전이 어긋나 여러 형태로 실패했습니다.

판정 기준부터. 스크립트 종료 메시지가 아니라 결과물로 판단하세요. 오류로 끝나도 아래 셋이 동작하면 목적은 달성된 것입니다.

podman --version                     # 4.9.x
python3.9 --version
/usr/local/bin/podman-compose --version   # 1.6.0

사례 ① post-GA 차이

cannot install both iptables-1.8.5-11.el8.x86_64 from @commandline
 and iptables-1.8.5-11.el8_9.x86_64 from @System

버전은 같은데 릴리스 태그가 다릅니다(.el8 GA vs .el8_9 업데이트). dnf가 다운그레이드로 판단해 거부하고, firewalld까지 연쇄로 막힙니다. 충돌 RPM만 번들에서 빼면 됩니다.

cd v2.1.0/deps/rpms
mv iptables-1.8.5-11.el8.x86_64.rpm iptables-libs-*.rpm ../rpms_excluded/

사례 ② 서버가 더 최신

하향설치 중: podman 4:4.9.4-30 ... (4.9.4-34 보다 최신의 패키지는 이미 설치되어 있습니다)

서버 것이 더 새것이면 번들을 넣을 이유가 없습니다. 부족한 것만 골라 설치하세요. 대개 python39만 빠져 있습니다.

sudo dnf install -y --disablerepo='*' python39*.rpm

사례 ③ Rocky 번들 ↔ RHEL

containers-common ... /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release 파일은
 redhat-release 패키지의 파일과 충돌합니다

번들이 Rocky 기준으로 수집된 것이라 RHEL에서 GPG 키 파일이 충돌합니다. containers-common이 이미 설치돼 있으면 건너뛰면 됩니다.

⚠ 절대 쓰지 말 것

--allowerasing 금지. 오류 메시지가 이 옵션을 제안하지만, 실행하면 firewalld·nftables 같은 핵심 패키지를 지우려 듭니다. 방화벽과 네트워크가 통째로 망가집니다. --skip-broken·--nobest도 부분 설치로 더 애매한 상태를 만들 뿐입니다.

무시해도 되는 경고

경고: ...rpm: Header V4 RSA/SHA256 Signature, key ID ...: NOKEY

GPG 키 미등록 경고입니다. 폐쇄망 로컬 RPM 설치 시 정상이고, 실패 원인이 아닙니다.


5. DB 서버 — install_pg17.sh가 OS를 바꾸려 합니다

rocky-release-8.10 에서 설치되는 /etc/redhat-release 파일은
 redhat-release 패키지의 파일과 충돌합니다
하향설치 중: openssl ... coreutils ... glib2 ...

번들에 Rocky의 OS 정체성 패키지가 들어 있어서, 강행하면 RHEL이 반쯤 Rocky가 됩니다. dnf가 막아주는 게 정상 동작입니다. PostgreSQL만 개별 설치했습니다.

cd db_set/pg17_rpms
sudo dnf install -y --disablerepo='*' \
  postgresql17-17.*.rpm postgresql17-libs-*.rpm postgresql17-server-*.rpm \
  libicu*.rpm libxslt*.rpm perl-*.rpm
sudo dnf install -y --disablerepo='*' postgresql17-contrib-*.rpm   # 확장 필요
sudo /usr/pgsql-17/bin/postgresql-17-setup initdb
sudo systemctl enable --now postgresql-17

contrib를 빠뜨리면 스키마 적재 때 pgcrypto, uuid-ossp, postgres_fdw 없다는 오류가 납니다.

원격 접속 — refused와 timeout은 원인이 다릅니다

설치 직후 PostgreSQL은 127.0.0.1만 듣습니다. WAS에서 접속하려면 두 파일을 고쳐야 합니다.

# postgresql.conf
listen_addresses = '*'
# pg_hba.conf — WAS IP만 허용
host all all <WAS_IP>/32 scram-sha-256
sudo systemctl restart postgresql-17

WAS에서 도달 확인:

timeout 3 bash -c 'echo > /dev/tcp/<DB_IP>/5432' && echo OPEN || echo BLOCKED
결과원인
refused서버까지 갔는데 듣는 프로그램이 없음 → listen_addresses
timeout방화벽 차단

증상만으로 방화벽인지 설정인지 갈립니다. 이거 모르면 엉뚱한 데서 한참 헤맵니다.


6. Petra는 install.sh보다 먼저

암복호화 키서버 Petra는 유일하게 컨테이너가 아니라 호스트에 물리 설치됩니다. common 컨테이너가 호스트의 6603 포트에 접속하므로 먼저 있어야 합니다.

sudo bash install_petra_full.sh --host-ip <WAS_IP> --soha-src /tmp/soha/NIA_KEYSVR --systemd

검증은 readlink가 관문

sudo ss -ltnp | grep 6603                                   # 0.0.0.0:6603
PID=$(sudo ss -ltnpH 'sport = :6603' | grep -oP 'pid=\K[0-9]+' | head -1)
sudo readlink -f /proc/$PID/exe
# → .../NIA_KEYSVR/bin/listener 여야 정답

crypto 호출이 200을 반환해도 검증이 아닙니다. 레거시 엔진(KEY_SVR)으로 서빙돼도 200이 나오기 때문에, readlink 결과 경로에 NIA_KEYSVR이 들어 있는지가 유일한 판정 기준입니다. 127.0.0.1:6603으로 뜨면 컨테이너에서 접근 못 하니 --host-ip를 실제 IP로 다시 주세요.


7. install.sh — 같은 서버에서 두 번

통합 구성이라도 env 파일이 역할별로 생성되므로 두 번 실행합니다. 어떤 프로파일을 쓸지 임의로 정하지 마세요. 생성된 env 첫 줄에 정답이 주석으로 있습니다.

bash gen-site-env.sh
head -1 box1.env link.env
# → sudo bash install.sh --profiles web,was,prcs --env-file box1.env
# → sudo bash install.sh --profiles link,egress-proxy --env-file link.env

egress-proxy를 빠뜨리지 마세요. --profiles link만 주면 국가공유 우회 프록시가 안 떠서 실시간 연계가 조용히 실패합니다.

실행 전에 CRYPTO_TOKEN이 양쪽 env에서 같은지 확인하세요. 다르면 연계 시 503으로 암복호화가 실패합니다.


8. 방화벽 reload가 컨테이너 포트를 죽입니다

sudo firewall-cmd --reload           # 이걸 하면 Podman DNAT 규칙이 지워짐
sudo podman network reload --all     # ★ 반드시 이어서

포트 개방했는데 갑자기 불통이면 십중팔구 이것입니다. 컨테이너는 멀쩡한데 밖에서 접속이 안 되는 형태로 나타납니다. 포트 개방은 설치·기동 전에 다 끝내두는 게 좋습니다.


9. 재부팅하면 컨테이너가 안 뜹니다 ★

이게 제일 오래 걸린 문제입니다. 설치 직후엔 멀쩡한데 재부팅하면 podman ps가 비어 있습니다.

원인은 정책과 필터의 불일치입니다. Podman은 상주 데몬이 없어 podman-restart.service가 부팅 시 컨테이너를 되살리는데:

구분값
compose.runtime.yml의 정책restart: unless-stopped
podman-restart.service의 필터restart-policy=always

필터에 걸리는 컨테이너가 0개라 서비스는 status=0/SUCCESS로 성공한 척 끝나고 아무것도 안 띄웁니다. enable 해도 소용없습니다.

NIA 파일을 건드리지 않고, 부팅 유닛을 추가해 해결했습니다.

# /etc/systemd/system/orgstd-boot.service
[Unit]
After=network-online.target orgstd-podman-netreload.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c '/usr/bin/podman start --all --filter restart-policy=unless-stopped'
[Install]
WantedBy=multi-user.target

절대 하지 말 것

sudo podman compose -f compose.runtime.yml up -d     # 프로파일 없이 실행하면
# WARNING: No services defined  → 기존 컨테이너가 제거될 수 있음

컨테이너가 통째로 사라진 원인이 이것으로 추정됩니다. 복구는 install.sh --profiles ...로 하세요.

저널 영구화도 먼저

RHEL은 기본적으로 저널을 메모리에만 두어 재부팅하면 이전 로그가 사라집니다. 원인을 못 찾게 되니 미리 켜두세요.

sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald

10. 검증 — “오류처럼 보이는 정상”

sudo podman inspect orgstd-petra orgstd-postgres
# → no such object

정상입니다. Petra는 호스트 설치, DB는 다른 서버라 컨테이너가 아닙니다. 컨테이너 헬스체크 대상은 orgstd-rabbitmq 하나입니다. 이걸 모르면 있지도 않은 장애를 쫓게 됩니다.

같은 이유로 DB 백업도 podman exec가 아닙니다.

sudo -u postgres pg_dump isdmsdb > isdmsdb_$(date +%Y%m%d).sql   # DB 서버에서

crypto 라운드트립

TOKEN=$(grep '^CRYPTO_TOKEN=' site.conf | cut -d= -f2)
curl -s -X POST http://127.0.0.1:38095/common/internal/crypto/encrypt \
  -H "X-Orgstd-Internal-Token: $TOKEN" -H 'Content-Type: application/json' \
  -d '{"value":"test","colId":100}'

기동 직후 첫 호출이 500/421이면 Petra 지연 초기화 레이스라 정상입니다. podman restart orgstd-common 한 번 하고 재시도하세요.


마치며

함정증상해결
UID 1000 점유was_user 생성 불가기존 계정 UID 이동
sudo 없음첫 단계 중단sudoers.d + visudo -c
RPM 스큐.el8 vs .el8_9 충돌충돌분만 제외, --allowerasing 금지
Rocky 번들redhat-release 충돌PostgreSQL만 개별 설치
DB refusedlisten_addresses'*' + pg_hba
Petra 검증200이어도 레거시 엔진readlink 경로 확인
방화벽 reload포트 불통podman network reload --all
재부팅 미기동정책·필터 불일치부팅 유닛 추가

가이드는 Rocky 8.10 기준이고 저희는 RHEL이었던 게 함정의 절반쯤을 만들었습니다. OS를 Rocky로 통일하거나, RHEL용 번들을 NIA에 요청하는 게 가장 깔끔한 예방책입니다.

그리고 “설치 직후 동작”과 “재부팅 후 동작”은 별개라는 것 — 이건 어느 시스템이든 마찬가지겠지만, 컨테이너 환경에서는 특히 그렇습니다. 검증 마지막에 꼭 재부팅 한 번 하세요.

ESB 에이전트 설치는 다음 글에서 이어집니다.

행정정보공동이용 ESB 에이전트 설치기

guest
0 Comments
Oldest
Newest Most Voted