Problema de firewall ao executar vários contêineres após a atualização

Tive alguns problemas com a atualização: o primeiro fórum falhou na primeira tentativa (via painel) e falhou novamente ao ser reconstruído, mas parece que funcionou na segunda tentativa de reconstrução, embora eu tenha precisado reconstruir mais uma vez. Isso me lembrou que precisava parar todas as instâncias do Discourse ao fazer a atualização com a versão do PG12 (há três fóruns do Discourse neste servidor, cada um com seu próprio container), e, portanto, o seguinte funcionou para os outros dois fóruns:

No entanto, por algum motivo, o primeiro fórum não está mais acessível; o Safari diz que o servidor encerrou a conexão inesperadamente. A reconstrução parece ocorrer sem problemas, mas o fórum não fica acessível. Consigo entrar no app e no console do Rails, e o banco de dados parece intacto.

As únicas mensagens de aviso que vejo na reconstrução que podem ser relevantes:

168:M 31 Jan 2021 21:39:22.459 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
168:M 31 Jan 2021 21:39:22.459 # Server initialized
168:M 31 Jan 2021 21:39:22.459 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
168:M 31 Jan 2021 21:39:22.459 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
168:M 31 Jan 2021 21:39:22.459 * Loading RDB produced by version 6.0.9
168:M 31 Jan 2021 21:39:22.459 * RDB age 21 seconds
168:M 31 Jan 2021 21:39:22.459 * RDB memory usage when created 4.03 Mb
168:M 31 Jan 2021 21:39:22.466 * DB loaded from disk: 0.006 seconds
168:M 31 Jan 2021 21:39:22.466 * Ready to accept connections

production.log:


Job exception: Error connecting to Redis on localhost:6379 (Errno::ENETUNREACH)

Error connecting to Redis on localhost:6379 (Errno::ENETUNREACH) subscribe failed, reconnecting in 1 second. Call stack /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.2.5/lib/redis/client.rb:367:in `rescue in establish_connection'

Mensagens semelhantes aparecem em unicorn.stderr.log e unicorn.stdout.log.

Ao entrar no container e executar redis-cli ping, recebo um PONG de volta. O Redis está em execução no servidor (mas não nos containers individuais — embora, pelo que sei, isso sempre tenha sido assim).

Alguma ideia do que possa estar acontecendo?

(Também reiniciei o servidor e criei um novo certificado letsencrypt para este domínio, para evitar problemas, mas a situação continua a mesma.)

1 curtida

Parece que tudo deveria estar funcionando… você já tentou em outro navegador ou limpou o cache? Se isso não ajudar, poderia postar a saída do:

curl -vv -o /dev/null <url do fórum>
2 curtidas

Tentei em vários navegadores, mas obtenho o mesmo erro. Aqui está a saída desse comando:

~$ curl -vv -o /dev/null https://metaruby.com
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 78.46.110.60...
* TCP_NODELAY set
* Connected to metaruby.com (78.46.110.60) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [226 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [93 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [2473 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [333 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [70 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=metaruby.com
*  start date: Jan 31 03:33:05 2021 GMT
*  expire date: May  1 03:33:05 2021 GMT
*  subjectAltName: host "metaruby.com" matched cert's "metaruby.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: metaruby.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0* TLSv1.2 (IN), TLS alert, close notify (256):
{ [2 bytes data]
* Empty reply from server
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
* Connection #0 to host metaruby.com left intact
curl: (52) Empty reply from server
* Closing connection 0
1 curtida

Algumas coisas que podem ser a causa do erro de resposta vazia:

  1. O servidor está em uma VPN e não há acesso à porta.
  2. Se você tiver várias instâncias do Discourse no mesmo servidor, presumo que haja um proxy reverso na frente. Certifique-se de que ele aponte para o contêiner do Discourse (talvez você precise reiniciá-lo).
  3. Não há espaço suficiente no servidor (você pode executar df -hT /).

Eu começaria verificando o espaço livre em disco primeiro (3).

2 curtidas

O uso do disco estava em 31%, mas executei ./launcher cleanup mesmo assim:

docker container ls
(Para garantir que os três contêineres do fórum estejam em execução)

./launcher cleanup

AVISO! Isso removerá todos os contêineres parados.
Tem certeza de que deseja continuar? [y/N] y
Espaço total recuperado: 0B
AVISO! Isso removerá todas as imagens sem pelo menos um contêiner associado a elas.
Tem certeza de que deseja continuar? [y/N] y
Imagens excluídas:
...
Espaço total recuperado: 32,56GB

Usamos o HAProxy e verifiquei (e reiniciei) e ele está ativo e em execução (também fazemos o redirecionamento de http para https por meio dele e isso funciona bem para o domínio também, então não acho que seja um problema ali — além disso, estava funcionando até esta atualização).

Posso ainda entrar no contêiner e acessar o console do Rails, e o banco de dados ainda está lá/conectado ao contêiner — então isso é extremamente estranho — alguém tem outras ideias ou mais etapas para solucionar isso?

1 curtida

Se você não conseguiu depurar o que está acontecendo, uma opção pode ser fazer um backup pela linha de comando e restaurá-lo em um novo site limpo rodando no PG13. Alternativamente, se você precisa que seu site volte a funcionar, pode reverter a versão para PG12, mover o diretório existente shared/postgres_data_old de volta para shared/postgres_data e reconstruir. No entanto, recomendo tentar o backup/restauração primeiro, pois o problema não parece estar relacionado à própria atualização do banco de dados.

3 curtidas

Você está um pouco além de uma instalação padrão suportada aqui. :slight_smile:

Cada Discourse tem seu próprio PostgreSQL, ou você tem um único PostgreSQL para os três?

Se você tiver um único container de PostgreSQL/dados, então você deve PARAR todos os Discourses antes de tentar atualizar o PostgreSQL.

O HaProxy não tem nada a ver com o PostgreSQL, então não acho que isso importe.

3 curtidas

Se você tiver outras ideias para investigar isso, ficarei feliz em experimentá-las, Michael. Felizmente, não é um grande problema ter este fórum offline, pois ele já estava no modo somente leitura (sendo substituído por outro fórum).

Se você não tiver mais ideias, vou prosseguir e tentar restaurar um backup, mas, se possível, gostaria de solucionar este problema, pois estou interessado em aprender por que isso aconteceu (assim como você, imagino) — então, definitivamente, estou disposto a investigar isso mais a fundo, se você também estiver.

Para ser honesto, isso me deixou um pouco preocupado em converter alguns dos meus outros fóruns para o Discourse, e saber o que deu errado pode ser útil para todos nós.

É uma instalação padrão com múltiplos contêineres, onde cada fórum possui seu próprio arquivo app.yml e uma configuração de contêiner baseada em host: discourse/shared-site-name/standalone e host: discourse/shared-site-name/standalone/log/var-log (conforme as perguntas que fiz e os posts neste fórum).

Ao entrar em cada contêiner e executar o psql (sudo -u postgres psql discourse) e o comando \l+, mostra-se apenas um banco de dados chamado discourse por contêiner (e cada um tem tamanhos diferentes), então imagino que sejam instâncias independentes do Discourse.

Você tem um link para a maneira padrão de rodar múltiplos fóruns independentes do Discourse em um servidor? Posso verificar se isso é igual ao que tenho aqui, embora eu tenha certeza de que o que possuo é baseado em posts e orientações da equipe do Discourse.

2 curtidas

Você está executando o nginx dentro do contêiner? O próximo passo que eu tentaria seguir é verificar para onde as requisições estão sendo direcionadas. Pelo que entendi, você tem o HAProxy realizando a terminação SSL e, em seguida, fazendo o proxy das requisições para os respectivos contêineres?

3 curtidas

Ah. OK. Então, para cada um, você deve executar ./launcher rebuild YOUR-APP-NAME duas vezes. Acho que não é possível fazer isso pela interface web.

E os contêineres yml têm todos os modelos de SSL e Let’s Encrypt comentados (ou removidos)?

2 curtidas

Até onde eu sei, os containers em si são todos ‘padrão’ (então, deduzo que cada um esteja rodando o nginx) e, sim, o HAProxy lida com todo o SSL e direciona as requisições para cada container.

Minha configuração está de acordo com o artigo aqui: Set up Discourse on a server with existing Apache sites (com a versão SSL da configuração do HAProxy aqui).

Houve um problema com a configuração do HAProxy:

backend main_apache_sites
  server server1 127.0.0.1:8080 cookie A check
  cookie JSESSIONID prefix nocache

backend discourse_docker
  server server2 127.0.0.1:8888 cookie A check
  cookie JSESSIONID prefix nocache

backend discourse_docker_2
  server server2 127.0.0.1:8889 cookie A check
  cookie JSESSIONID prefix nocache

backend discourse_docker_3
  server server2 127.0.0.1:8890 cookie A check
  cookie JSESSIONID prefix nocache

backend letsencrypt-backend
  server letsencrypt 127.0.0.1:54321

Onde, por algum motivo, todos os backends do Discourse tinham server2 na segunda linha — eu mudei esses para server2, server3 ontem, etc., mas não fez nenhuma diferença (e estava funcionando bem assim anteriormente).

Existem arquivos de log específicos que eu poderia verificar que possam fornecer mais pistas? Talvez arquivos de log do Docker?

Sim, esses estão comentados:

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## Descomente essas duas linhas se quiser adicionar o Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"
1 curtida

Os logs do nginx dentro dos contêineres do aplicativo devem ser capazes de confirmar se as requisições estão chegando ao aplicativo. Você pode verificá-los? O nginx no contêiner proxya as requisições para 127.0.0.1:3000, que é para o processo unicorn.

1 curtida

Olhando em /var/log/nginx e /shared/log/rails, nada realmente se destaca; na verdade, nenhum dos logs foi atualizado hoje (dia 4), exceto /shared/log/rails/production.log, que contém apenas alguns Jobs como este:

Logs do Rails:

Logs do Nginx:

Também alterei a porta no HAProxy e, como esperado, obtive um erro de “servidor não encontrado”. Em seguida, atualizei o container para a mesma porta e ele voltou ao mesmo comportamento (então acho que isso elimina um problema no HAProxy).

Há algum log do Docker para verificar? Ou posso salvar/exportar este container e enviá-lo para você para que possa dar uma olhada? Imagino que você esteja se perguntando o que deu errado tanto quanto eu :blush:

1 curtida

Na verdade, acabei de olhar novamente (o acima era de ontem à noite) e agora há alguns registros em:

unicorn.stderr.log

(Desculpe, não deixa copiar o texto)

Nenhum dos logs do nginx foi alterado hoje, embora o último log de 30 de janeiro mostre um erro do tipo: 7: limiting requests by zone “flood” client: my.ip.address, POST /mini-profiler-resources.

Edição: não sei se isso ajuda, mas executando docker logs APP:

Para o fórum que não está funcionando:

# docker logs metaruby
run-parts: executando /etc/runit/1.d/00-ensure-links
run-parts: executando /etc/runit/1.d/00-fix-var-logs
run-parts: executando /etc/runit/1.d/01-cleanup-web-pids
run-parts: executando /etc/runit/1.d/anacron
run-parts: executando /etc/runit/1.d/cleanup-pids
Limpeza de arquivos PID obsoletos
run-parts: executando /etc/runit/1.d/copy-env
runsvdir iniciado, PID é 43
ok: run: redis: (pid 55) 0s
ok: run: postgres: (pid 56) 0s
chgrp: grupo inválido: 'syslog'
supervisor pid: 50 unicorn pid: 89

Para o fórum 2 (funcionando corretamente):

# docker logs f2

run-parts: executando /etc/runit/1.d/00-ensure-links

run-parts: executando /etc/runit/1.d/00-fix-var-logs

run-parts: executando /etc/runit/1.d/01-cleanup-web-pids

run-parts: executando /etc/runit/1.d/anacron

run-parts: executando /etc/runit/1.d/cleanup-pids

Limpeza de arquivos PID obsoletos

run-parts: executando /etc/runit/1.d/copy-env

runsvdir iniciado, PID é 42

ok: run: redis: (pid 55) 0s

ok: run: postgres: (pid 54) 0s

chgrp: grupo inválido: 'syslog'

supervisor pid: 51 unicorn pid: 82

(51) Reabrindo logs

(51) Reabrindo logs

(51) Reabrindo logs

(51) Parando Sidekiq

(51) Recarregando unicorn (82)

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn... 22039

(51) PID antigo é: 82 Novo PID é: 22039

(51) Parando Sidekiq

(51) Recarregando unicorn (22039)

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn...

(51) Aguardando novo PID do mestre do unicorn... 23358

(51) PID antigo é: 22039 Novo PID é: 23358

(51) Reabrindo logs

(51) Reabrindo logs

Para o fórum três (também funcionando corretamente):

# docker logs f3

run-parts: executando /etc/runit/1.d/00-ensure-links

run-parts: executando /etc/runit/1.d/00-fix-var-logs

run-parts: executando /etc/runit/1.d/01-cleanup-web-pids

run-parts: executando /etc/runit/1.d/anacron

run-parts: executando /etc/runit/1.d/cleanup-pids

Limpeza de arquivos PID obsoletos

run-parts: executando /etc/runit/1.d/copy-env

runsvdir iniciado, PID é 42

ok: run: redis: (pid 54) 0s

chgrp: grupo inválido: 'syslog'

ok: run: postgres: (pid 55) 0s

supervisor pid: 56 unicorn pid: 88

(56) Reabrindo logs

(56) Reabrindo logs

(56) Reabrindo logs

(56) Reabrindo logs

(56) Reabrindo logs
1 curtida

Analisando os logs e relendo suas respostas anteriores, a aplicação está tentando acessar o Redis em localhost:6379 dentro do contêiner. Parece que o Redis está iniciando corretamente, mas, por algum motivo, não consegue se conectar (puzzling). No entanto, é possível que essas mensagens de erro tenham ocorrido quando o message_bus tentou se conectar antes do Redis iniciar ou após ele parar, no caso de uma reinicialização.

Você mencionou que o Redis está rodando no servidor, mas não em contêineres individuais. Poderia explicar melhor isso?

Com essa configuração, o Redis será executado dentro do contêiner (como você pode ver na saída dos logs do Docker).

Outro ponto: quando você navega até a URL do site que não está funcionando, o que aparece nos logs do nginx? O error.log deve estar vazio, e o access.log deve conter várias solicitações HTTP. Estou tentando identificar em que ponto algo está dando errado.

1 curtida

Desculpe, eu misturei as coisas. Na verdade, o Redis está funcionando em cada contêiner, verificado executando o seguinte no próprio servidor e, em seguida, em cada um dos três contêineres do Discourse, com a mesma saída para todos:

$ redis-cli ping
PONG
$ redis-server
# Creating Server TCP listening socket *:6379: bind: Address already in use (means it's already started)
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get mykey
(nil)
127.0.0.1:6379> set mykey somevalue
OK
127.0.0.1:6379> get mykey
"somevalue"

O mesmo ocorre com os três (vale destacar: o primeiro get mykey sempre retorna nil), portanto, é seguro afirmar que o Redis está ativo e rodando independentemente em todos os contêineres.

Está vazio e nada foi escrito nesse diretório hoje:

drwxr-xr-x 2 www-data www-data  4096 Feb  4 21:26 .
drwxrwxr-x 9 root     root      4096 Feb  2 08:03 ..
-rw-r--r-- 1 www-data www-data     0 Feb  3 07:38 access.log
-rw-r--r-- 1 www-data www-data     0 Feb  2 08:03 access.log.1
-rw-r--r-- 1 www-data www-data   294 Feb  1 09:43 access.log.2.gz
-rw-r--r-- 1 www-data www-data 37598 Jan 30 23:56 access.log.3.gz
-rw-r--r-- 1 www-data www-data 58059 Jan 30 07:36 access.log.4.gz
-rw-r--r-- 1 www-data www-data 55988 Jan 29 07:34 access.log.5.gz
-rw-r--r-- 1 www-data www-data 73964 Jan 28 07:49 access.log.6.gz
-rw-r--r-- 1 www-data www-data 78069 Jan 27 07:53 access.log.7.gz
-rw-r--r-- 1 www-data www-data     0 Feb  3 07:38 error.log
-rw-r--r-- 1 www-data www-data     0 Feb  2 08:03 error.log.1
-rw-r--r-- 1 www-data www-data    20 Feb  1 00:31 error.log.2.gz
-rw-r--r-- 1 www-data www-data   632 Jan 30 23:46 error.log.3.gz
-rw-r--r-- 1 www-data www-data   265 Jan 29 09:07 error.log.4.gz
-rw-r--r-- 1 www-data www-data    20 Jan 28 07:50 error.log.5.gz
-rw-r--r-- 1 www-data www-data  3107 Jan 28 07:41 error.log.6.gz
-rw-r--r-- 1 www-data www-data    20 Jan 26 07:53 error.log.7.gz

Verifiquei os logs de acesso de outro contêiner e está tudo certo, então o problema é apenas neste.

Parece que o HAProxy está enviando a solicitação, mas o contêiner não consegue processá-la ou aceitá-la. Será que há algo que possa ser reiniciado nesse ponto? (O que eu pensaria que reconstruir o contêiner já faria, não é?)

1 curtida

Parece mesmo isso. Você pode confirmar quais são as associações de portas presentes para cada contêiner ao executar docker ps no host?

1 curtida

Claro:

IMAGE                   COMMAND             CREATED             STATUS              PORTS                                     
local_discourse/1      	"/sbin/boot"        20 horas atrás        Up 20 horas         0.0.0.0:2225->22/tcp, 0.0.0.0:8892->80/tcp
local_discourse/2   	"/sbin/boot"        4 dias atrás          Up 4 dias           0.0.0.0:2223->22/tcp, 0.0.0.0:8889->80/tcp
local_discourse/3       "/sbin/boot"        4 dias atrás          Up 4 dias           0.0.0.0:2224->22/tcp, 0.0.0.0:8890->80/tcp

Minha intuição diz que isso tem a ver com a tentativa falha via painel — normalmente, para atualizações do PostgreSQL ou principais, o painel informa que é necessário fazer uma reconstrução e que a atualização está desabilitada via painel, mas, por algum motivo, isso não ocorreu (talvez porque eu não atualizasse aquele fórum há algum tempo — daí a ideia de tentar primeiro pelo painel) ou é possível que ele não tenha sido encerrado ou iniciado corretamente antes de realizar a reconstrução :confused:

2 curtidas

Na configuração do HAProxy, vejo que os backends estão configurados para encaminhar para as portas 8888, 8889 e 8890:

No entanto, os containers do aplicativo estão escutando nas portas 8892, 8889 e 8890 — parece haver uma discrepância no backend discourse_docker. Isso foi algo que você atualizou na configuração desde a postagem?

1 curtida

Sim, as portas do HAProxy correspondem às portas corretas dos containers :smiley: Tenho quase certeza de que não está relacionado a isso, pois estava funcionando perfeitamente — isso só aconteceu após essa atualização/reconstrução.

Entrar no container, abrir as estatísticas do Top e depois acessar o site também não parece fazer diferença. Caso ajude, aqui está uma captura de tela:

Se for mais fácil para você, posso ‘salvar’ o container e enviá-lo (isso é até possível com containers Docker? haha!) :slight_smile:

1 curtida