Ceph는 오픈 소스 분산 스토리지 소프트웨어로서 스토리지의 로컬 스토리지 리소스를 사용할 수 있으며 스토리지의 높은 신뢰성, 고성능 및 높은 확장성에 대한 기업의 요구를 충족하며 점점 더 많은 기업의 선호를 받고 있습니다. 다량의 생산 실습을 통해 Ceph는 고급 디자인 개념, 포괄적인 기능, 유연한 사용 및 높은 유연성을 갖추고 있음이 입증되었습니다. 그러나 이러한 Ceph의 장점은 기업에게는 양날의 검이기도 합니다. 잘 통제하면 기업에 도움이 될 수 있습니다. 숙련도가 부족하고 Ceph의 기질을 이해하지 못하면 때로는 많은 문제를 일으킬 수 있습니다. 아래에서는 그런 경우를 여러분과 공유하고 싶습니다.
A사는 Ceph 객체 스토리지 클러스터를 배포하여 외부 클라우드 스토리지 서비스를 제공하며, 고객이 사진, 동영상, APK 설치 패키지 등 비정형 데이터에 대한 클라우드 관리를 신속하게 달성할 수 있도록 SDK를 제공합니다. 사업이 공식적으로 시작되기 전에 Ceph에 대한 충분한 기능 테스트, 예외 테스트 및 성능 테스트가 수행되었습니다.
클러스터 크기는 그리 크지 않습니다. 커뮤니티 버전 0.80을 사용합니다. 총 30개의 서버가 있습니다. 각 서버는 32GB 메모리, 10개의 4T SATA 디스크 및 160G Intel S3700 SSD 디스크로 구성됩니다. 300개의 SATA 디스크는 개체 데이터를 저장하기 위한 데이터 리소스 풀(기본 구성은 .rgw.buckets라는 풀)을 형성하고, 30개의 SSD 디스크는 메타데이터 리소스 풀을 형성합니다(기본 구성은 .rgw.buckets.index 풀이라는 풀) , 객체 메타데이터를 저장합니다. Ceph 객체 스토리지 운영 및 유지 관리 배포 경험이 있는 친구는 Ceph 객체 스토리지가 멀티 테넌시를 지원하기 때문에 이 구성도 국제적인 관행이라는 것을 알고 있습니다. 여러 사용자가 동일한 버킷(사용자의 논리적 공간)에 객체를 PUT하면 메타데이터가 동일한 버킷 인덱스 객체가 공유되기 때문에 이 인덱스 객체는 접속 시 잠금이 필요하며, 버킷 인덱스 객체는 고성능 디스크 SSD로 구성된 리소스 풀에 저장됩니다. , 감소 각 인덱스 개체 액세스 시간이 향상되고 IO 성능이 향상되며 개체 저장소의 전체 동시성이 향상됩니다.
시스템이 온라인 상태가 된 후 고객 데이터가 Ceph 개체 스토리지 클러스터에 지속적으로 저장되기 시작했습니다. 처음 3개월 동안은 모든 것이 정상적으로 실행되었습니다. 이 기간 동안 SATA 디스크 오류도 발생했으며 Ceph 자체 오류 감지 및 복구 메커니즘을 사용하여 쉽게 해결되었습니다. 운영 및 유지 관리 형제는 매우 편안했습니다. 5월에 들어서면서 운영 및 유지 관리 형제들은 때때로 SSD 디스크에 해당하는 OSD가 매우 느려져 비즈니스 지연이 발생한다고 불평했습니다. 이러한 상황이 발생했을 때 간단하고 효과적인 방법은 OSD를 다시 시작하고 정상으로 돌아가는 것이었습니다. 이런 현상은 아마 몇 번 산발적으로 발생했을 텐데, 운영 및 유지보수 동생이 우리 SSD 사용에 문제가 있는 게 아니냐고 물었습니다. 분석 결과, SSD 디스크 적용에 있어서 특별한 점은 없다고 생각됩니다. 디스크 스케줄링 알고리즘을 데드라인으로 변경한 것 외에는 이미 수정된 부분이 있어 이 부분에 대해서는 별로 관심을 두지 않습니다.
5월 28일 저녁 21시 30분, 운영 및 유지보수 형제들은 휴대전화로 시스템 알람을 받았습니다. 일부 파일을 쓰지 못했습니다. 그들은 즉시 시스템에 로그인하여 확인했습니다. 서버의 SSD 디스크에 해당하는 OSD의 읽기 및 쓰기 속도가 느려서 발생했습니다. 이전 경험에 따르면 이러한 경우에는 OSD 프로세스를 다시 시작한 후 정상으로 복원할 수 있습니다. OSD 프로세스를 즉시 다시 시작하고 시스템이 정상으로 돌아올 때까지 기다리십시오. 그러나 이번에는 SSD의 OSD 프로세스가 매우 느리게 시작되어 동일한 서버에 있는 SATA 디스크의 OSD 프로세스가 정지되고 하트비트가 손실되는 현상이 발생했습니다. 일정 시간이 지난 후 다른 서버에서도 SSD 디스크의 OSD 프로세스가 느리게 정지되기 시작한 것으로 나타났습니다. 서버. 다른 서버의 SSD 디스크에 해당하는 OSD 프로세스를 계속 다시 시작하면 비슷한 상황이 발생합니다. SSD 디스크 OSD 프로세스를 반복적으로 다시 시작한 후에는 점점 더 많은 SSD 디스크 OSD 프로세스를 시작할 수 없습니다. 운영·유지보수 형제들은 즉시 기술연구개발부에 상황을 보고하고 즉각적인 지원을 요청했다.
사무실에 도착한 후 운영 및 유지 관리 형제의 피드백을 바탕으로 서버에 탑승하고 여러 SSD 디스크에 해당하는 OSD 프로세스를 시작하고 비교 프로세스의 시작 프로세스를 반복적으로 관찰했습니다.
1 . OSD 프로세스를 검색하려면 top 명령을 사용하십시오. 시작 후 최대 20GB, 때로는 30GB까지 메모리를 할당하기 시작합니다. 때로는 시스템 메모리가 고갈되어 때로는 최종 파티션인 경우에도 스왑을 사용하기 시작합니다. 프로세스가 성공적으로 풀업되더라도 OSD는 여전히 최대 10GB의 메모리를 차지합니다.
2. OSD 로그를 확인하여 FileJournal::_open 단계에 진입한 후 로그 출력이 중지되는지 확인합니다. 오랜 시간(30분 이상) 후에 출력은 load_pg 단계로 들어갑니다. load_pg 단계에 들어간 후 또 다른 긴 대기 시간이 발생합니다. 비록 load_pg가 완료되었지만 프로세스는 여전히 자살하고 종료됩니다.
3. 위의 긴 시작 프로세스 동안 pstack을 사용하여 프로세스 호출 스택 정보를 확인합니다. FileJournal::_open 단계에서 볼 수 있는 호출 스택은 OSD 로그 재생이며, 트랜잭션 처리 중에 levelDB 레코드 삭제가 실행됩니다. load_pg 단계에서는 가져온 호출 스택 정보를 levelDB 로그를 사용하여 levelDB 파일을 복구합니다.
4. 때때로 SSD 디스크 OSD 프로세스가 성공적으로 시작되지만 일정 시간 동안 실행된 후 다른 SSD 디스크 OSD 프로세스가 비정상적으로 종료됩니다.
이러한 현상으로 보면 모두 levelDB와 관련이 있는 것으로 보입니다. 메모리 할당량이 많은 것도 이와 관련이 있는 걸까요? levelDB 관련 코드를 추가로 확인한 결과, 트랜잭션에서 levelDB Iterator를 사용할 경우, Iterator가 레코드에 접근하는 동안 메모리가 계속 할당되며, Iterator가 모두 소진될 때까지 모든 메모리가 해제되지 않는 것으로 나타났습니다. 이러한 관점에서 보면, Iterator가 접근하는 레코드의 개수가 매우 많으면 Iteration 과정에서 많은 양의 메모리가 할당되게 된다. 이를 바탕으로 버킷에 있는 객체의 개수를 살펴본 결과 여러 버킷에 있는 객체의 개수가 2천만개, 3천만개, 5천만개에 이르렀고, 이러한 대형 버킷 인덱스 객체의 저장 위치가 우연히 발견된 것으로 나타났습니다. 문제가 발생한 곳. SSD 디스크 OSD. 메모리 소모량이 많은 이유는 이미 밝혀졌어야 했는데, 이미 지난 30일 21시가 되어서야 사용자들이 모두 불만을 토로하기 시작했습니다. 큰 문제다." 그들은 거의 48시간 동안 싸웠고, 형제들의 눈은 붉어지고 부어올랐습니다. 그들은 멈춰서 쉬어야 합니다. 그렇지 않으면 몇몇 형제들은 새벽이 되기 전에 쓰러질 것입니다.
31일 8시 30분, 형제들은 다시 전투에 나섰습니다.
또 다른 문제가 있습니다. 즉, 일부 OSD는 긴 시작 프로세스를 거쳐 결국 load_pg가 완료된 후 자살로 종료된다는 것입니다. ceph 코드를 읽어보니, 장기간 스케줄되지 않아(아마도 levelDB 스레드가 CPU를 오랫동안 점유했기 때문일 수도 있음) 타임아웃으로 인해 일부 스레드가 자살한 것으로 확인되었습니다. ceph 구성에는 filestore_op_thread_suicide_timeout 매개변수가 있습니다. 테스트 및 검증을 통해 이 매개변수를 큰 값으로 설정하면 이러한 종류의 자살을 방지할 수 있습니다. 우리는 다시 약간의 빛을 보았고 시계는 12시 30분을 가리켰습니다.
일부 프로세스가 시작된 후에도 최대 10GB의 메모리를 차지합니다. 이 문제가 해결되지 않으면 SSD 디스크 OSD를 풀업하더라도 동일한 서버에 있는 다른 SATA 디스크 OSD의 작동이 영향을 받습니다. 메모리가 부족해서. 형제 여러분, 계속해서 선한 일을 하십시오. 새벽이 오기 전의 어둠입니다. 여러분은 이겨내야 합니다. 어떤 사람은 정보를 확인하고, 어떤 사람은 코드를 살펴보더니 마침내 14시 30분에 ceph 정보 문서에서 메모리 해제를 강제하는 명령을 찾았습니다. ceph Tell osd.* heap release 프로세스가 해제되기 시작한 후에 이 명령을 실행할 수 있습니다. OSD 프로세스가 차지하는 과도한 메모리. 모두가 매우 흥분했고 즉시 테스트를 거쳐 효과가 있음을 확인했습니다.
SSD 디스크 OSD가 시작되고 잠시 동안 실행되면 다른 SSD 디스크의 OSD 프로세스가 종료됩니다. 위 분석 및 위치 지정에 따르면 이는 주로 데이터가 마이그레이션된 OSD가 관련 기록을 삭제하기 때문입니다. 데이터가 마이그레이션된 후 정보를 삭제하여 객체 메타데이터 레코드를 삭제하도록 levelDB를 트리거합니다. 지나치게 큰 버킷 인덱스 객체가 발견되면 levelDB는 반복기를 사용하여 객체의 메타데이터 레코드를 트래버스하므로 과도한 메모리 소비가 발생하고 OSD 프로세스가 중단됩니다. 서버가 비정상이군요.
위의 분석을 바탕으로 약 2시간에 걸친 반복적인 논의와 시연 끝에 다음과 같은 비상 조치를 마련했습니다.
1. PG 마이그레이션이 발생하면 클러스터에 noout 플래그를 설정하고 PG 마이그레이션을 허용하지 않습니다. PG가 외부로 마이그레이션될 수 있습니다. PG가 외부로 이동한 후 OSD는 PG의 객체 데이터를 삭제하여 객체 메타데이터 레코드를 삭제하도록 levelDB를 트리거합니다. PG에 지나치게 큰 버킷 인덱스 객체가 있으면 많은 양의 메모리가 삭제됩니다. 메타데이터 레코드를 순회하는 반복자로 인해 소비됩니다.
2. SSD에 해당하는 OSD를 저장하고 시스템을 최대한 빨리 복원하려면 SSD에 해당하는 OSD 프로세스를 시작할 때 시작 매개변수 filestore_op_thread_suicide_timeout을 추가하고 큰 값을 설정하세요. 결함이 있는 OSD가 풀업되면 일련의 LevelDB 프로세스가 CPU를 점유하여 스레드 예약이 차단됩니다. Ceph에는 스레드 교착 상태 감지 메커니즘이 이 매개변수로 구성된 시간 이후에도 예약되지 않습니다. 스레드 교착 상태로 판단됩니다. 스레드 교착 상태로 인한 프로세스 자살을 방지하려면 이 매개변수를 설정해야 합니다.
3. 메모리가 제한된 현재 상황에서는 비정상적인 OSD 시작이 스왑 파티션을 사용하여 OSD 프로세스 시작 속도를 높이려면 스왑 파티션을 SSD 디스크로 조정하세요.
4. 예약된 작업을 시작하고 ceph Tell osd.* heap release 명령을 정기적으로 실행하여 OSD가 차지하는 메모리를 강제로 해제하세요.
5. SSD에 해당하는 OSD에 문제가 있는 경우 다음 단계를 따르세요.
a) 먼저 서버의 모든 OSD 프로세스를 중지하여 모든 메모리를 확보합니다.
b) 그런 다음 OSD 프로세스를 시작하고 filestore_op_thread_suicide_timeout 매개변수를 전달하여 72000과 같은 큰 값을 제공합니다.
c) OSD의 시작 프로세스를 관찰합니다. load_pgs가 실행되면 즉시 ceph Tell osd.N heap release 명령을 수동으로 실행하여 점유된 메모리를 강제로 해제할 수 있습니다.
d) 클러스터 상태를 관찰합니다. 모든 PG의 상태가 정상으로 돌아오면 다른 SATA 디스크에 해당하는 OSD 프로세스를 시작합니다.
위 단계에 따라 17시 30분부터 OSD 프로세스를 하나씩 재개했습니다. 복구 프로세스 중에 여러 개의 매우 큰 버킷 인덱스 개체를 채우는 데 오랜 시간이 걸렸습니다. 차단되어 애플리케이션 비즈니스 요청 시간이 초과됩니다. 이는 단일 버킷에 많은 수의 객체를 저장함으로써 발생하는 부정적인 영향이기도 합니다.
5월 31일 23시, 드디어 모든 OSD 프로세스가 복구되었습니다. 실패부터 시스템 복구 성공까지, 우리는 모두가 서로를 바라보며 웃으며 지나치게 흥분하며 72시간 동안 열심히 일했습니다. 이 문제에 대한 완전한 해결책을 논의하고 공식화하기 위해 열심히 노력합니다. 해결책:
1. 서버 메모리를 64GB로 확장합니다.
2. 새 버킷의 경우 최대 저장 개체 수를 제한하세요.
3. Ceph 버전 0.94는 완전히 테스트된 후 지나치게 큰 단일 버킷 인덱스 개체 문제를 해결하기 위해 버전 0.94로 업그레이드되었습니다.
4. Ceph의 levelDB 반복자 사용 최적화. 분할된 반복을 통해 반복자는 특정 수의 레코드 순회를 완료한 후 현재 반복 위치를 기록하고 이를 해제한 다음 계속해서 순회하는 새 반복자를 생성합니다. 마지막 반복 위치에서 시작하여 반복자의 메모리 사용량을 제어합니다.
과거를 잊지 말고 미래에서 배우며, 경험과 교훈을 통해 다음 사항을 요약합니다.
1 온라인에 접속하기 전에 시스템을 완전히 테스트해야 합니다.
ceph는 온라인에 접속하기 전에 A사의 시스템을 기능, 성능, 예외 테스트는 완벽하게 이루어졌지만, 대용량 데이터에 대한 스트레스 테스트는 없었습니다. 이전에 단일 버킷에서 수천만 개의 객체를 테스트했다면 이러한 숨겨진 위험을 사전에 발견할 수 있습니다.
2. 운영 및 유지 관리 과정의 모든 이상은 적시에 주의를 기울여야 합니다
이 경우 문제가 발생하기 얼마 전에 운영 및 유지 관리 부서에서 이미 SSD 이상 문제를 보고했습니다. 당시에 행해졌더라면, 심층적인 분석을 통해 문제의 근본 원인을 찾아 사전에 방지책을 세울 수 있었을 것입니다.
3. ceph의 기질을 알아보세요
모든 소프트웨어 제품에는 해당 사양 제한이 있으며 ceph도 예외는 아닙니다. ceph 아키텍처와 그 구현 원리에 대해 사전에 심층적으로 이해하고, 단일 버킷에 많은 수의 객체를 과도하게 저장하는 것이 미치는 부정적인 영향을 이해하고 사전에 계획을 세울 수 있다면 이 경우에 직면하게 되는 문제는 다음과 같습니다. 발생하지 않습니다. RGW는 사용자 수준 및 버킷 수준 할당량을 포함하여 할당량을 매우 포괄적으로 지원합니다. 단일 버킷에 저장할 수 있는 최대 개체 수를 구성할 수 있습니다.
4. 커뮤니티의 최신 진행 상황을 항상 추적하세요
Ceph 버전 0.94에서는 버킷 인덱스 개체를 여러 개의 샤드 개체로 분할하여 저장할 수 있으므로 지나치게 큰 단일 버킷 인덱스 개체 문제.