재부팅 후 Discourse Bad Gateway 오류

저희 서버는 주요 클라우드 제공업체 중 하나에서 호스팅되는 가상 머신에서 실행됩니다.
discourse를 성공적으로 설치했고, 지난 한 달 동안 정상적으로 작동해 왔습니다.
오늘, VM 사양을 원래 설정(*)으로 되돌리고 재부팅했습니다. 부팅 후 서버의 다른 모든 것이 정상적으로 작동하지만, discourse 포럼에 접근하려고 할 때 502 Bad Gateway 오류가 발생합니다. Docker 인스턴스가 자동으로 시작되지 않은 것 같아 SSH로 서버에 접속하여 ./launcher start app을 실행해 보았으나, 사용 가능한 공간이 부족하다는 메시지(5GB 사용 가능)가 표시되었습니다. 그래서 df -h를 실행해 보니 실제로는 14GB가 사용 가능한 것으로 나타났습니다. 다시 ./launcher start app을 실행해 보았는데, 이번에는 Docker가 데이터를 다운로드할 것이니 인내심을 갖고 기다려 달라는 경고가 나타났습니다. 처리가 잠시 진행된 후 Nothing to do, your container has already started!라는 메시지가 표시되었습니다. 하지만 여전히 포럼에 접근하려고 하면 502 Bad Gateway 오류가 반환됩니다.
이 포럼을 참고한 후 ./launcher rebuild app을 실행해 보았는데, PostgreSQL과 관련된 다음과 같은 오류가 발생했습니다:

    user@host:[16:48]:/var/discourse# ./launcher rebuild app
    Ensuring launcher is up to date
    Fetching origin
    Launcher is up-to-date
    Stopping old container
    + /usr/bin/docker stop -t 60 app
    app
    cd /pups && git pull && /pups/bin/pups --stdin
    Already up to date.
    I, [2020-07-01T07:19:42.821347 #1]  INFO -- : Loading --stdin
    I, [2020-07-01T07:19:42.831806 #1]  INFO -- : > locale-gen $LANG && update-locale
    I, [2020-07-01T07:19:42.879007 #1]  INFO -- : Generating locales (this might take a while)...
    Generation complete.
    
    I, [2020-07-01T07:19:42.879431 #1]  INFO -- : > mkdir -p /shared/postgres_run
    I, [2020-07-01T07:19:42.885054 #1]  INFO -- :
    I, [2020-07-01T07:19:42.885734 #1]  INFO -- : > chown postgres:postgres /shared/postgres_run
    I, [2020-07-01T07:19:42.891655 #1]  INFO -- :
    I, [2020-07-01T07:19:42.892269 #1]  INFO -- : > chmod 775 /shared/postgres_run
    I, [2020-07-01T07:19:42.898103 #1]  INFO -- :
    I, [2020-07-01T07:19:42.898942 #1]  INFO -- : > rm -fr /var/run/postgresql
    I, [2020-07-01T07:19:42.905607 #1]  INFO -- :
    I, [2020-07-01T07:19:42.906463 #1]  INFO -- : > ln -s /shared/postgres_run /var/run/postgresql
    I, [2020-07-01T07:19:42.912617 #1]  INFO -- :
    I, [2020-07-01T07:19:42.913233 #1]  INFO -- : > socat /dev/null UNIX-CONNECT:/shared/postgres_run/.s.PGSQL.5432 || exit 0 && echo postgres already running stop container ; exit 1
    2020/07/01 07:19:42 socat[26] E connect(6, AF=1 "/shared/postgres_run/.s.PGSQL.5432", 36): No such file or directory
    I, [2020-07-01T07:19:42.925688 #1]  INFO -- :
    I, [2020-07-01T07:19:42.926081 #1]  INFO -- : > rm -fr /shared/postgres_run/.s*
    I, [2020-07-01T07:19:42.931174 #1]  INFO -- :
    I, [2020-07-01T07:19:42.931649 #1]  INFO -- : > rm -fr /shared/postgres_run/*.pid
    I, [2020-07-01T07:19:42.938152 #1]  INFO -- :
    I, [2020-07-01T07:19:42.938850 #1]  INFO -- : > mkdir -p /shared/postgres_run/12-main.pg_stat_tmp
    I, [2020-07-01T07:19:42.943575 #1]  INFO -- :
    I, [2020-07-01T07:19:42.944331 #1]  INFO -- : > chown postgres:postgres /shared/postgres_run/12-main.pg_stat_tmp
    I, [2020-07-01T07:19:42.949159 #1]  INFO -- :
    I, [2020-07-01T07:19:42.961190 #1]  INFO -- : File > /etc/service/postgres/run  chmod: +x  chown:
    I, [2020-07-01T07:19:42.973345 #1]  INFO -- : File > /etc/service/postgres/log/run  chmod: +x  chown:
    I, [2020-07-01T07:19:42.983929 #1]  INFO -- : File > /etc/runit/3.d/99-postgres  chmod: +x  chown:
    I, [2020-07-01T07:19:42.994843 #1]  INFO -- : File > /root/upgrade_postgres  chmod: +x  chown:
    I, [2020-07-01T07:19:42.995487 #1]  INFO -- : > chown -R root /var/lib/postgresql/12/main
    I, [2020-07-01T07:19:44.012812 #1]  INFO -- :
    I, [2020-07-01T07:19:44.013656 #1]  INFO -- : > [ ! -e /shared/postgres_data ] && install -d -m 0755 -o postgres -g postgres /shared/postgres_data && sudo -E -u postgres /usr/lib/postgresql/12/bin/initdb -D /shared/postgres_data || exit 0
    I, [2020-07-01T07:19:44.019545 #1]  INFO -- :
    I, [2020-07-01T07:19:44.019872 #1]  INFO -- : > chown -R postgres:postgres /shared/postgres_data
    I, [2020-07-01T07:19:44.064432 #1]  INFO -- :
    I, [2020-07-01T07:19:44.065186 #1]  INFO -- : > chown -R postgres:postgres /var/run/postgresql
    I, [2020-07-01T07:19:44.071385 #1]  INFO -- :
    I, [2020-07-01T07:19:44.072196 #1]  INFO -- : > /root/upgrade_postgres
    I, [2020-07-01T07:19:44.084004 #1]  INFO -- :
    I, [2020-07-01T07:19:44.084662 #1]  INFO -- : > rm /root/upgrade_postgres
    I, [2020-07-01T07:19:44.090399 #1]  INFO -- :
    I, [2020-07-01T07:19:44.092280 #1]  INFO -- : Replacing data_directory = '/var/lib/postgresql/12/main' with data_directory = '/shared/postgres_data' in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.093969 #1]  INFO -- : Replacing (?-mix:#?listen_addresses *=.*) with listen_addresses = '*' in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.095204 #1]  INFO -- : Replacing (?-mix:#?synchronous_commit *=.*) with synchronous_commit = $db_synchronous_commit in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.095937 #1]  INFO -- : Replacing (?-mix:#?shared_buffers *=.*) with shared_buffers = $db_shared_buffers in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.096695 #1]  INFO -- : Replacing (?-mix:#?work_mem *=.*) with work_mem = $db_work_mem in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.097554 #1]  INFO -- : Replacing (?-mix:#?default_text_search_config *=.*) with default_text_search_config = '$db_default_text_search_config' in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.101971 #1]  INFO -- : > install -d -m 0755 -o postgres -g postgres /shared/postgres_backup
    I, [2020-07-01T07:19:44.112672 #1]  INFO -- :
    I, [2020-07-01T07:19:44.113831 #1]  INFO -- : Replacing (?-mix:#?max_wal_senders *=.*) with max_wal_senders = $db_max_wal_senders in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.114973 #1]  INFO -- : Replacing (?-mix:#?wal_level *=.*) with wal_level = $db_wal_level in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.116047 #1]  INFO -- : Replacing (?-mix:#?checkpoint_segments *=.*) with checkpoint_segments = $db_checkpoint_segments in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.117033 #1]  INFO -- : Replacing (?-mix:#?logging_collector *=.*) with logging_collector = $db_logging_collector in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.118051 #1]  INFO -- : Replacing (?-mix:#?log_min_duration_statement *=.*) with log_min_duration_statement = $db_log_min_duration_statement in /etc/postgresql/12/main/postgresql.conf
    I, [2020-07-01T07:19:44.119352 #1]  INFO -- : Replacing (?-mix:^#local +replication +postgres +peer$) with local replication postgres  peer in /etc/postgresql/12/main/pg_hba.conf
    I, [2020-07-01T07:19:44.120299 #1]  INFO -- : Replacing (?-mix:^host.*all.*all.*127.*$) with host all all 0.0.0.0/0 md5 in /etc/postgresql/12/main/pg_hba.conf
    I, [2020-07-01T07:19:44.121038 #1]  INFO -- : > HOME=/var/lib/postgresql USER=postgres exec chpst -u postgres:postgres:ssl-cert -U postgres:postgres:ssl-cert /usr/lib/postgresql/12/bin/postmaster -D /etc/postgresql/12/main
    I, [2020-07-01T07:19:44.126334 #1]  INFO -- : > sleep 5
    2020-07-01 07:19:44.157 UTC [49] LOG:  starting PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
    2020-07-01 07:19:44.158 UTC [49] LOG:  listening on IPv4 address "0.0.0.0", port 5432
    2020-07-01 07:19:44.158 UTC [49] LOG:  listening on IPv6 address "::", port 5432
    2020-07-01 07:19:44.161 UTC [49] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
    2020-07-01 07:19:44.162 UTC [49] FATAL:  could not map anonymous shared memory: Cannot allocate memory
    2020-07-01 07:19:44.162 UTC [49] HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 4423172096 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.
    2020-07-01 07:19:44.162 UTC [49] LOG:  database system is shut down
    I, [2020-07-01T07:19:49.141762 #1]  INFO -- :
    I, [2020-07-01T07:19:49.142221 #1]  INFO -- : > su postgres -c 'createdb discourse' || true
    createdb: error: could not connect to database template1: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
    I, [2020-07-01T07:19:49.227852 #1]  INFO -- :
    I, [2020-07-01T07:19:49.228226 #1]  INFO -- : > su postgres -c 'psql discourse -c "create user discourse;"' || true
    psql: error: could not connect to server: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
    I, [2020-07-01T07:19:49.330486 #1]  INFO -- :
    I, [2020-07-01T07:19:49.330822 #1]  INFO -- : > su postgres -c 'psql discourse -c "grant all privileges on database discourse to discourse;"' || true
    psql: error: could not connect to server: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
    I, [2020-07-01T07:19:49.425970 #1]  INFO -- :
    I, [2020-07-01T07:19:49.426356 #1]  INFO -- : > su postgres -c 'psql discourse -c "alter schema public owner to discourse;"'
    psql: error: could not connect to server: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
    I, [2020-07-01T07:19:49.506638 #1]  INFO -- :
    I, [2020-07-01T07:19:49.507202 #1]  INFO -- : Terminating async processes
    
    
    FAILED
    --------------------
    Pups::ExecError: su postgres -c 'psql discourse -c "alter schema public owner to discourse;"' failed with return #<Process::Status: pid 75 exit 2>
    Location of failure: /pups/lib/pups/exec_command.rb:112:in `spawn'
    exec failed with the params "su postgres -c 'psql $db_name -c \"alter schema public owner to $db_user;\"'"
    eb41679f76cd749ccd8c84a7543365d093619b80df6fc6750b9349fb63565fa1
    ** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
    ./discourse-doctor may help diagnose the problem.
    user@host:[17:19]:/var/discourse#

이상하게도, 위의 오류에도 불구하고 ./launcher start app을 실행하면 오류가 발생하지 않습니다:

starting up existing container
+ /usr/bin/docker start app
app

인스턴스가 실행 중인 상태에서 컨테이너에 진입하기 위해 ./launcher enter app을 사용해 보았습니다. (솔직히 말하자면, 컨테이너 내에서 사용할 수 있는 도구들은 매우 빈약합니다. 저는 nano 사용자로 다양한 별칭을 매핑하는 것을 좋아합니다. 예: ll). Docker 인스턴스 내부 폴더의 물리적 경로를 찾을 수 없습니다. (FTP 클라이언트를 사용하여 다운로드하고 싶기 때문입니다.)

/var/log/nginx/error.log에는 브라우저를 새로 고칠 때마다 다음과 같은 오류 항목이 기록되어 있습니다:

2020/07/01 07:44:16 [error] 646#646: *3 connect() failed (111: Connection refused) while connecting to upstream, client: xxx.xx.0.1, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: "discourse.myDomain.com"

제 문제의 원인이 무엇일 수 있을까요? 왜 PostgreSQL이 갑자기 작동하지 않는 것일까요?

(*) Discourse를 설치한 지 일주일 후, 제가 주최한 화상 회의를 진행하기 위해 서버를 더 많은 CPU와 메모리로 업그레이드했습니다. 회의가 끝나자 원래의 일반적인 구성으로 되돌렸습니다. 사양 변경 과정에서 디스크 크기는 변경하지 않았습니다.

이것은 현재 컨테이너 재빌드(rebuild)가 실패했기 때문이며, app의 이전 버전을 시작하고 있기 때문입니다. 이는 일반적인 동작입니다. 재빌드가 성공하지 않으면 원래 컨테이너는 삭제되지 않으며(일반적으로), 원래 이미지 역시 사용 가능한 상태로 남아 있습니다.

PG 문제와 관련하여, 최적의 지원을 받으려면 팀에게 앱 및 컨테이너 구성에 대한 더 자세한 정보를 제공해야 합니다.

@neounix : 감사합니다.

나는 디스커스 포럼을 호스팅하는 것이 처음이라 어디를 봐야 하고 무엇을 주의 깊게 살펴봐야 하는지 잘 모르겠습니다. 플러그인이나 기타 수정 사항이 없는 거의 기본 설치 상태입니다. app.yml에 몇 가지 변수를 정의해 두었고, 기존 Apache2 데몬을 리버스 프록시로 사용하여 별도의 가상 호스트(virtualhost)를 통해 디스커스 트래픽을 디스커스가 수신하도록 설정한 로컬호스트 포트(localhost port)로 전달하고 있습니다.

어떤 정보가 유용할지 좀 더 자세히 설명해 주실 수 있을까요? 제 상황을 디버깅하는 데 도움이 되는 자료를 읽을 수 있을까요?

핵심 오류는 위의 로그 파일 실행 결과에 있습니다.

2020-07-01 07:19:44.162 UTC [49] FATAL:  could not map anonymous shared memory: Cannot allocate memory

2020-07-01 07:19:44.162 UTC [49] HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 4423172096 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

그 에러는 확인했지만 app.yml 파일에는 아무런 변경 사항을 넣지 않았습니다.
shared_buffers나 max_connections 값을 어디서 줄일 수 있을까요? 이 항목들은 app.yml에 없거든요. app.yml에는 db_shared_buffers라는 파라미터만 있는데, 서버 메모리를 늘리기 전후를 막론하고 늘 그랬듯이 기본값인 "4096MB"로 설정되어 있습니다.

메모리와 관련된 통계를 게시하는 것을 고려해 볼 수 있습니다.

예를 들어, Linux의 경우:

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          64299       12955        9678         361       41664       50265
Swap:          7807          69        7738

그리고 docker stats의 경우, 다음 명령어의 출력을 게시하십시오:

docker stats

등입니다.

해당 에러는 메모리 부족과 관련이 있습니다.

서버 메모리 통계는 다음과 같습니다:

              total        used        free      shared  buff/cache   available
Mem:           3951        2236         414          86        1299        1308
Swap:           511         415          96

enter app 실행 후 메모리 통계:

              total        used        free      shared  buff/cache   available
Mem:           3951        2363         321          86        1266        1215
Swap:           511         415          96

docker stats > output.txt 실행 결과:

        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 15.86%              6.48MiB / 3.859GiB   0.16%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 15.86%              6.48MiB / 3.859GiB   0.16%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 2.83%               6.539MiB / 3.859GiB   0.17%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 2.83%               6.539MiB / 3.859GiB   0.17%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 3.30%               6.477MiB / 3.859GiB   0.16%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 3.30%               6.477MiB / 3.859GiB   0.16%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 2.45%               6.535MiB / 3.859GiB   0.17%               20.3kB / 12.6kB     0B / 0B             25
        CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
       ca4c5f37894c        app                 2.45%               6.535MiB / 3.859GiB   0.17%               20.3kB / 12.6kB     0B / 0B             25

안녕하세요 @nap

기존의 오래된 app 컨테이너들을 중지한 뒤 삭제하면 메모리를 많이 확보할 수 있습니다.

예를 들어:

docker stop <container_id>
docker rm <container_id>

해당 컨테이너들이 사용 중이 아니라면요?

모든 컨테이너가 사용 중이라면, 이 서버의 메모리를 4GB 이상으로 늘리는 것을 고려해 보세요. 8GB로 늘리는 것도 좋은 방법입니다 :slight_smile:

앱을 ./launcher stop app으로 중지한 후 docker stats를 다시 실행했습니다. 컨테이너 목록이 표시되지 않았습니다.
불행히도 메모리를 늘리면 비용이 더 듭니다. 지금은 지난 달에는 4GB로 잘 작동했는데 지금은 그렇지 않다는 점이 가장 답답합니다.

그리고 지금은 재빌드조차 할 수 없는데, 그렇게 많은 메모리를 소비할 수 없거든요.

컨테이너가 실행되지 않은 상태에서의 메모리 통계는 다음과 같습니다:

              total        used        free      shared  buff/cache   available
Mem:           3951        2207         169          91        1574        1332
Swap:           511         446          65

./var/lib/docker/overlay2/ 디렉터리 안에 몇 가지 흥미로운 디렉터리가 있습니다.

e3e6cdfcc62c2e0b68ec91efxxxxx6c69212c95b5070f7b6b84e97edcb473ea2
64a04d1b97a18f51a5fdc536xxxxxf9473de0c2ccd1a2cc0d62e830164b5f2d8
355303c6af7bebff1163195c5xxxxx8fd1de6333e39adbcb573c7365673b6c85

이것들을 삭제해도 될까요?

맞아요.

아, 그렇군요. 다른 작업을 하느라 바빠서, 출력 결과가 여러 컨테이너가 아니라 같은 컨테이너의 통계를 표시하고 있다는 걸 놓쳤네요.

컨테이너가 실행되지 않는 지금, free -m 명령을 실행하면 어떤 결과가 나오나요?

한 컨테이너에 4GB RAM은 충분히 괜찮다고 생각합니다.

아니요.

그 도커 파일들은 삭제하지 마세요.

에러 메시지에 따르면 문제는 Discourse의 PG 12 설정과 관련이 있습니다. Discourse용 PG 12 설정 파일을 수정하는 것은 지원되지 않는다고 생각하므로, 어떻게 해결해야 할지 정확히 알지 못합니다.

메타 사이트의 상위 관리자들이나 전문 호스팅 팀이 저보다 더 좋은 해결책을 제시해 줄 것입니다.

말씀하신 것은 이것이 docker 설정 내부의 파일들과 관련이 있다는 뜻인가요? 그리고 수동으로 수정하면 컨테이너가 시작되거나 업데이트될 때 문제가 발생하게 된다는 건가요?

@nap

위의 오류 메시지를(따옴표 포함) 구글에서 검색해 보면, 이 특정 PostgreSQL 오류 메시지와 직접적으로 관련 있는 여러 토론을 찾을 수 있습니다.

도움이 되길 바랍니다.

그 작업을 한 후 ./discourse-setup을 다시 실행했거나 app.yml에서 메모리 설정을 수동으로 수정하셨나요? db_shared_buffers, unicorn_workers, db_work_mem의 값은 어떻게 되어 있나요?

다만 리버스 프록시 뒤에 실행하고 있어 상황이 더 복잡합니다. 리버스 프록시가 문제의 원인이라고 단정할 수는 없지만, 상황이 복잡해지기는 합니다.

여러 파티션을 사용하고 계신가요? 도커가 이미지를 생성하는 파티션이 가득 차 있는 것은 아닌지 확인해 보셨나요?

@pfaffman : 확인해 주셔서 감사합니다.

아니요, 제가 한 것은 사이트 이름과 태그 사용에 관한 일련의 변수 정의만 추가한 것입니다.

db_shared_buffers는 "4096MB"입니다.
unicorn_workers는 8입니다.
db_work_mem은 주석 처리되어 있습니다.

40GB의 메인 파티션(14GB 여유), 512MB의 스왑, 그리고 백업을 위한 8GB 파티션(마운트되지 않음)이 있습니다.

문제를 해결한 것 같습니다. 처음에는 버퍼를 2GB로, 워커를 4로 줄여 보았지만 동일한 오류가 발생했습니다. 그 후 버퍼를 1GB로 줄였더니 rebuild가 성공했고 이제 포럼이 다시 복구되었습니다.

모두 감사합니다!!