Docker 이미지 업데이트: Redis 6 및 이미지 크기 25% 축소

다음 ./launcher rebuild app 명령에 사용될 완전히 새로운 컨테이너 이미지를 출시했습니다. 항상 그렇듯, Discourse 공식 표준 설치 지침을 따랐다면 제공한 구성을 변경할 필요가 없습니다. 그럼에도 불구하고, 일부 설치 환경에 도움이 될 새로운 기능들이 추가되었습니다.

Redis 6

Discourse의 캐시, Sidekiq, MessageBus, 분산 잠금(Distributed Locks), 레이트 리밋(Rate Limits) 등 다양한 곳에서 Redis를 대규모로 사용하고 있습니다. 전반적으로 우리에게 매우 안정적이고 견고한 선택이었습니다.

그러나 특정 워크로드에서는 Redis가 병목 현상의 원인이 될 수 있었습니다. Redis의 단일 스레드 특성상, 그리고 LUA 스크립트 때문에 여러 인스턴스를 사용할 수 없었던 점까지 겹쳐서, 이 병목 현상을 우회하기가 매우 어려웠습니다.

다행히도 Redis 6에서는 I/O 작업을 위한 스레드 풀 지원이 추가되었고, 테스트 결과 Redis로 인해 병목 현상이 발생하던 Discourse 클러스터에서 매우 잘 작동하는 것으로 확인되었습니다.

따라서 많은 CPU 코어를 가진 머신을 사용하고 있으며, 메트릭스에서 Redis가 부하를 처리하는 데 어려움을 겪는 것으로 나타나고 있다면, 이제 app.yml의 params 섹션을 통해 쓰기 작업에 스레드를 사용하는 옵션을 활성화할 수 있습니다:

params:
  redis_io_threads: "4" # 1이면 비활성화, n>1이면 IO 쓰기에 n-1개의 추가 스레드 사용

더 작은 이미지

프로젝트 초기 단계에서 비기술적인 사용자들이 Discourse를 쉽게 실행할 수 있도록 하고, 필요한 모든 의존성, 버전 관리, 업그레이드 등을 처리하기 위해 크기가 큰 컨테이너 이미지를 출시하는 것을 선택했습니다.

그럼에도 불구하고, 최근 압축된 이미지 크기가 1GB를 넘어섰고, 이는 다소 과도한 수준이었습니다.

따라서 이미지의 끊임없이 증가하는 크기를 완화하기 위해, 이미지 내부의 Discourse 소스 코드를 소스 코드의 완전한 복사본에서 최신 버전의 코드만 포함하는 "얕은 클론(shallow clone)"으로 변경했습니다.

이 변경으로 인해 압축된 이미지 크기가 25% 작아졌으며, 이는 필요한 서버 공간을 줄이고 새로운 이미지가 출시될 때 재빌드 속도를 높이는 데 기여합니다. 또한 시간이 지남에 따른 이미지 크기 증가를 제어하는 데에도 도움이 될 것입니다.

tests-passed/beta/stable 환경에서 재빌드와 웹 업데이트를 모두 테스트하여 표준 경로가 깨지지 않는 것을 확인했습니다. 하지만 app.yml의 훅에서 더 이례적인 git 작업을 수행하는 사용자들은 사용자 지정 설정을 조정해야 할 수 있습니다.

42개의 좋아요

이러한 Redis 업그레이드 이후 브라우저 경험에 어떤 변화가 발생합니까? 캐시된 자산에 영향을 미치나요? 업그레이드 결과로 인해 캐시가 비워지나요?

3개의 좋아요

아무것도 없습니다.

자산은 로컬 디스크나 객체 저장소에 저장되고 CDN에 캐시됩니다. Redis는 이에 영향을 미치지 않습니다.

Redis 데이터는 업그레이드 중에 유지됩니다.

10개의 좋아요

기본값은 무엇인가요? 1인가요?

5개의 좋아요

네. 이는 Redis 자체의 설정 파일에서 유래한 것으로, 1은 이전 버전처럼 단일 스레드를 의미합니다.

8개의 좋아요

다음과 같이 추가한 인스턴스가 있습니다:

after_redis:
  - replace:
      filename: "/etc/redis/redis.conf"
      from: /^databases.*/
      to: "databases 50"

하지만 다음 오류로 인해 재구축이 실패하고 있습니다:

25:M 01 Dec 2020 20:21:08.830 # FATAL: Data file was created with a Redis server configured to handle
 more than 16 databases. Exiting

마이그레이션 등을 시도하기 전에 데이터베이스 수를 업데이트할 수 있는 다른 훅(hook)이 있을까요?

음. 그리고 겉보기에 실패한 재구축 이후, 도커 로그에서 이것을 확인했습니다:

chgrp: invalid group: ‘syslog’

2개의 좋아요

왜 데이터베이스가 1개 이상 필요합니까?

3개의 좋아요

멀티사이트. 단일 Redis를 사용하여 여러 인스턴스를 실행합니다. 더 일반적인 Redis 컨테이너를 사용했어야 했는데, 당신의 것을 그대로 사용하기로 했습니다.

2개의 좋아요

:face_with_raised_eyebrow:

멀티사이트가 단일 데이터베이스와 표준 Redis 키네임 공간을 사용하지 않나요? AFAIK에 따르면 Redis 데이터베이스는 얇은 계층이며, 그 경계를 넘는 명령어가 있으므로 그 부분에 의존하지 않는 것이 좋습니다.

6개의 좋아요

네, 멀티사이트는 데이터베이스를 1개 사용합니다

3개의 좋아요

아. 그렇다면 멀티사이트가 아니라, 한 대의 머신에서 각각 별도의 redis가 필요한 여러 인스턴스를 실행하는 거군요. 사용 중인 redis 데이터베이스를 꼼꼼히 관리하기가 귀찮아서 기본값인 16을 50으로 올렸을 뿐입니다.

그러면 각 인스턴스마다 별도의 redis 컨테이너를 실행해야 하나요?

2개의 좋아요

네, 그렇지 않으면 서로 간섭이 생길 수 있습니다.

5개의 좋아요

아, 당황.

다행히도 테스트용으로만 사용하는 서버에서 이 문제를 알게 되었습니다.

다른 사이트들의 경우, 새 redis를 제공하고 예약된 작업들을 그냥 삭제하면 될까요? 백업/복원을 해야 하나요?

참고로, 지난 1년 정도는 크로스톡(crosstalk) 관련 문제를 발견하지 못했습니다. :man_shrugging: 그리고 DB를 설정하는 방법이 있습니다. .

수정: 좋은 소식은 컨테이너에 진입하여 redis.conf를 편집하고 재시작하면 다시 정상 작동한다는 것입니다.

한 redis 컨테이너의 DISCOURSE_REDIS_DB: 12에서 다른 redis 컨테이너로 사이트를 이동하는 방법에 대한 힌트가 있다면 듣고 싶습니다. 아니면 예약된 작업은 신경 쓰지 않아도 될까요?

3개의 좋아요

이 말에 동의합니다. Discourse는 Redis가 플러시되어도 합리적으로 작동해야 합니다. 일부 데이터는 손실되지만, 중요한 것은 아닙니다.

7개의 좋아요

저도 그렇게 생각했어요. 백업이 복원을 시도하는 방식을 아는 방법이 없거든요 (하지만 제가 모르는 것이 많기도 합니다). 방금 테스트해 본 결과, 이 링크의 방법처럼 하면 되는 것 같고 실제로 작동하는 것 같긴 해요: https://stackoverflow.com/questions/23222616/copy-all-keys-from-one-db-to-another-in-redis. 하지만 플레이북을 수정해서 새 redis 컨테이너를 만들고 그것을 사용하는 쪽이 훨씬 쉬울 것 같습니다.

감사합니다.

이제 그 redis들을 데이터베이스 서버에서 돌릴지 웹 서버에서 돌릴지 결정해야 하는데…

3개의 좋아요

그렇다면 멀티사이트 설정에서 db_id: 2는 무엇을 가리키는 건가요?

2개의 좋아요

더 이상 사용되지 않는 설정입니다:

5개의 좋아요

ㅋㅋ. 정말로 헷갈리네요!

감사합니다. ‘레트스엔크립트 사용, 외부 리버스 프록시 없는 멀티사이트 설정’ 관련 작업을 진행 중인데, 그 작업을 마치면 다른 것도 함께 정리할 예정입니다.

4개의 좋아요

그 직후에 unicorn을 재시작하여 예약된 작업들이 다시 생성되도록 하세요.
큐에 있는 작업들은 모두 사라지므로, 이 작업을 수행하기에 적절한 시점을 잘 찾아야 합니다.

6개의 좋아요

이것이 여전히 의도대로 작동하고 있습니까? 압축 이미지가 얼마나 큰지 확인할 수 있는 간단한 한 줄 명령어가 있을까요?

1개의 좋아요