데이터베이스(또는 일부)를 클라우드 데이터 처리자에게 접근 가능하게 하는 방법?

ETL 서비스인 Stitch Data나 Skyvia를 사용하여 다양한 데이터 소스(제 Discourse 데이터베이스 포함)를 통합하는 데 관심이 있었지만, Skyvia 측에서 이는 불가능하다고 들었습니다:

Skyvia는 SSH를 통해 PostgreSQL에 연결할 수 있지만, SSH 서버가 컨테이너 내부가 아니라 컨테이너 앞에 위치해 있을 경우, Docker 컨테이너 내부의 PostgreSQL에 연결하는 것은 불가능합니다.

이것은 Postgres에 연결하기 위한 그들의 요구 사항입니다.

명백한 우회 방법이 있을까요?

Discourse 컨테이너에서 SSH를 활성화(비표준 포트 사용)한 후, 해당 포트에 대한 접속을 허용할 수 있습니다. Discourse_docker의 samples 디렉터리에서 관련 예제를 찾을 수 있을 것 같습니다.

고마워, 제이. 결국 docker-ssh를 public key 인증과 함께 사용했어요. :+1:

어떤 핵심 개념을 놓치고 있는 것 같습니다. 커스텀 포트를 통해 ssh로 연결한 뒤 su postgres -c 'psql discourse'를 실행하면 아무 문제 없이 작동하기 때문입니다. 이 2단계 방식은 모두 정상적으로 작동하지만, pgAdmin과 같은 도구를 통해 직접 연결하려면 약간 다른 설정이 필요할 것 같습니다.

커스텀 포트를 노출하기 위해 사용 중인 명령은 다음과 같습니다:

docker run -d -p 2222:22 \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v ~/.ssh/authorized_keys:/authorized_keys \
        --name my-sshd \
        -e FILTERS={\"name\":[\"^/app$\"]} -e AUTH_MECHANISM=publicKey \
        -e AUTHORIZED_KEYS=/authorized_keys \
        jeroenpeeters/docker-ssh

이렇게 하면 나중에 launcher enter app을 실행하지 않고도 직접 다음을 수행할 수 있습니다:

ssh whatever@host -p 2222
su postgres -c 'psql discourse'

여러 가지를 시도해 보았지만 성공하지 못했습니다. ssh whatever@host -p XXXX를 실행하면 데이터베이스에 직접 연결될 수 있는 방법이 있을 것 같은데(아마도 pgAdmin이 기대하는 방식일 것입니다), 그러지 못하고 있습니다.

연결이 안 되는 건가요, 아니면 권한 문제인가요?

명령줄에서 ssh를 통해 접속한 후 psql로 연결할 수 있습니다. 하지만 pgAdmin으로는 연결할 수 없습니다.

pgAdmin을 통해 연결하려면 PostgreSQL 포트를 직접 노출해야 합니다.

app.yml 파일의 상단 근처에서 80번과 443번 포트가 열려 있는 것을 볼 수 있습니다. PostgreSQL용 5432 포트에 대한 한 줄을 더 추가할 수 있습니다.

그러나 이는 대부분 매우 나쁜 아이디어입니다. 데이터베이스가 로컬 연결만 허용하던 것에서 인터넷 전체에 노출되게 됩니다.

가끔씩 보고서를 작성할 필요가 있다면, Data Explorer에서 몇 가지 CSV 파일을 다운로드하여 좋아하는 도구에 로드하는 것만으로 충분할 수 있습니다. Discourse 백업(업로드 제외)을 다운로드할 수도 있으며, 이는 표준 PostgreSQL 덤프 형식입니다. 이를 손에 넣으면 로컬 PostgreSQL 인스턴스로 복원하여 분석할 수 있습니다.

감사합니다, Rafael

이렇게 하고 컨테이너를 다시 빌드했습니다. 하지만 여전히 작동하지 않습니다 (XX.XX.XX.XX 대신 실제 IP를 사용했습니다)

SSH 터널 탭에서는 다음과 같습니다:

다음과 같은 오류가 발생합니다.

이 부분에 대해선 보호 계층이 하나 줄어든다는 점은 이해하지만, 여전히 SSH 개인 키가 필요하지 않나요?

app.yml에 5432를 추가하면 SSH 터널 없이 직접 노출됩니다.

pgAdmin SSH 터널에 대한 조언은 드릴 수 없습니다. 저는 사용해 본 적이 없기 때문입니다. 로컬 연결을 수신하는 포트를 기대할 것이라 가정하며, 인터넷에 노출될 필요가 없다고 생각합니다.

다음과 같이 시도해 보세요:

expose:
  - "80:80"
  - "443:443"
  - "5432"

하지만 postgres 비밀번호가 없는 이유는 슈퍼유저 권한이 필요하기 때문입니다. pg_hba.conf 파일에서 “local” 연결 권한이 "peer"로 설정되어 있어 UNIX 사용자를 기반으로 하며, 이를 위해 SSH 로그인이 필요하지 않나요?

이것은 작동하지 않습니다: psql -h XX.XX.XX.XX -p 5432 -U postgres -d discourse

슈퍼유저로 psql에 연결할 수 있습니다.

./launcher enter app
su postgres
psql

그리고 보고를 위해 필요한 권한을 가진 사용자를 생성합니다.

네, 앱 도커 컨테이너에서 연결하는 데는 문제가 없습니다. 제 문제는 로컬 머신에서(예를 들어 pgAdmin을 사용하려고 할 때) 또는 Stitch와 같은 클라우드 데이터 프로세서에서 PostgreSQL DB에 직접 연결하는 것입니다. 이 두 가지 모두 호스트 IP 주소와 SSH 자격 증명을 요구하지만, 작동하게 만드는 데 실패했습니다(위에서 보여 드린 오류가 발생합니다).

제가 할 수 있는 유일한 방법은 docker-ssh를 사용하여 로컬 컴퓨터에서 launcher enter app을 실행하지 않고도 공개 키(publicKey)를 통해 앱 도커 컨테이너에 직접 접근하는 것입니다. 하지만 여전히 DB에 접근하려면 su postgres 'psql discourse'를 실행해야 하며, 이것이 pgAdmin/Stitch의 문제라고 추정합니다. 이 도구들은 직접 연결을 기대하기 때문입니다.

비밀번호를 지정하여 새 PostgreSQL을 생성한 뒤, 해당 비밀번호를 서비스에 전달해 보셨나요?

네, 꽤 긴 절차가 있습니다.

하지만 제 경우에도 로컬 컴퓨터에서 pgAdmin만 사용해도 동일한 문제가 발생합니다.

독립 컨테이너에서 웹과 데이터 컨테이너로 분리하는 방법(Move from standalone container to separate web and data containers)에 비밀번호 설정에 대한 설명이 있을 것 같습니다.

또한, postgres 포트는 127.0.0.1에만 바인딩할 수 있다고 생각합니다.

expose:
  - "80:80"
  - "443:443"
  - "127.0.0.1:5432:5432"

포트 노출 없이 DB에 연결할 수 있는지 확인해 보기 위해 한 발 물러서서 상황을 파악해 보려고 합니다. :grin:

컨테이너에 진입하면 다음과 같은 내용이 표시됩니다:

# netstat -lp | grep postgres
tcp        0      0 0.0.0.0:postgresql      0.0.0.0:*               LISTEN      -
tcp6       0      0 [::]:postgresql         [::]:*                  LISTEN      -
unix  2      [ ACC ]     STREAM     LISTENING     263612292 -                    /var/run/postgresql/.s.PGSQL.5432

컨테이너를 종료하고 원격 서버에 있는 경우(아직 로컬 컴퓨터가 아닌 상태), 다음 명령으로 연결할 수 있지 않나요?

/var/discourse# psql -h localhost -d discourse -U postgres

문제는 비밀번호 프롬프트가 표시된다는 것입니다. postgres 사용자는 비밀번호가 없으므로, 다른 사용자를 생성하고 비밀번호를 부여해 보았습니다:

CREATE USER whatever_user WITH ENCRYPTED PASSWORD '<whatever password>';
GRANT CONNECT ON DATABASE discourse TO whatever_user;
GRANT USAGE ON SCHEMA public TO whatever_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO whatever_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO whatever_user;

pg_hba.conf 파일에 해당 사용자를 위한 md5 인증 라인을 추가하고 service postgresql restart 명령으로 PG를 재시작했습니다.

# Database administrative login by Unix domain socket
local   all             postgres                                peer
local   all             whatever_user                      md5

그러나 원격 서버에서 연결을 시도하면 인증 실패가 발생합니다:

# psql -h localhost -d discourse -U whatever_user
Password for user whatever_user:
psql: FATAL:  password authentication failed for user "whatever_user"
FATAL:  password authentication failed for user "whatever_user"

무엇을 놓치고 있는 걸까요? 우선 같은 서버에서 DB에 연결할 수 있도록 하는 것이 목표입니다. 다음 단계로는 SSH 터널을 사용하여 동일한 작업을 수행할 계획이지만, 먼저 1단계부터 해결해야 할 것 같습니다. 도움이 주시면 감사하겠습니다.

음, 마침내 해결했어요 :tada:

다음 부분:

포트가 이미 사용 중이라는 오류가 발생해서 다음과 같이 변경했어요: - "127.0.0.1:5433:5432"

컨테이너를 다시 빌드하고 포트가 실제로 열려 있는지 확인했습니다:

$ sudo docker ps
CONTAINER ID        IMAGE                           COMMAND             CREATED             STATUS              PORTS                      NAMES
whatever_id        local_discourse/app             "/sbin/boot"        20 minutes ago      Up 20 minutes       127.0.0.1:5433->5432/tcp   app

이제 SSH 터널을 생성하고 비밀번호가 있는 사용자로 원격 서버에서 연결할 수 있습니다:

# 터널 생성 (ssh -f 옵션을 사용하면 백그라운드에서 실행할 수도 있습니다)
ssh -v -N -L 5433:localhost:5433 SERVER_IP_ADDRESS

# 다른 탭에서 연결하고 비밀번호 입력
psql -h localhost -d discourse -U whatever_user -p 5433

이 작업을 시도하다가 문제가 발생하면 알려주세요.