홈으로 돌아가기

ClickHouse 구성: config.xml 및 users.xml의 프로덕션 설정

프로덕션 환경을 위한 ClickHouse 구성 실용 가이드. config.xml의 주요 섹션을 다룹니다: 크기 기반 로테이션(각 1GB 파일 10개)이 있는 logger, 데이터 및 스왑 경로, MergeTree 매개변수(min_bytes_for_wide_part, parts_to_throw_insert=300). 세 가지 사용자 유형에 대한 users.xml 구조: 분석가(readonly=1, 메모리 및 시간 제한), 애플리케이션(제한된 리소스), 관리자(로컬 액세스). 프로필 설정: max_memory_usage, max_execution_time, max_rows_to_read. 쿼리 수 및 읽은 행 수에 대한 할당량. LZ4(속도) vs ZSTD(공간 절약) 압축. 보안 액세스를 위한 TLS/SSL. 업데이트 중 설정을 유지하기 위한 config.d/를 통한 구성 원칙. 최소 보안 체크리스트: 기본 비밀번호 변경, UFW/iptables로 포트 차단, users.xml에서 네트워크 제한, query_log 활성화.

ClickHouse: 데이터 손실 없이 프로덕션 설정하는 방법
Advertisement 728x90

ClickHouse 설정: 운영 환경을 구성하면서 실수하지 않는 방법

오타 하나가 만든 대참사: 300GB 로그와 다운된 서버

기본적으로 ClickHouse는 로그를 /var/log/clickhouse-server/에 기록하며 로테이션을 하지 않습니다. 출시 2주 후, 로그 파일이 300GB로 불어나 루트 파티션을 가득 채웠습니다. 서버가 다운되었고, 분석가들은 SELECT를 실행할 수 없었으며, 운영이 중단되었습니다.

ClickHouse 문서는 방대하지만, 운영 환경에서 실제로 변경해야 할 파라미터는 약 20개에 불과합니다. 아래는 1노드에서 12노드까지 클러스터를 운영하며 5년간 쌓은 체크리스트입니다.

1. config.xml: 운영 설정의 뼈대

주 설정 파일은 /etc/clickhouse-server/config.xml에 있습니다. 모든 프로젝트에서 건드리는 섹션은 다음과 같습니다.

Google AdInline article slot
<clickhouse>
    <!-- 로깅 — 로테이션을 추가하여 실수 반복 방지 -->
    <logger>
        <level>information</level>
        <log>/var/log/clickhouse-server/clickhouse-server.log</log>
        <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
        <size>1000M</size>
        <count>10</count>
        <!-- 디스크를 절약합니다. 각각 1GB 파일 10개 — 크기 기반 로테이션 -->
    </logger>

    <!-- 포트 — 표준이지만 운영 환경에서는 변경 -->
    <tcp_port>9000</tcp_port>           <!-- 네이티브 클라이언트 -->
    <http_port>8123</http_port>         <!-- HTTP API -->
    <interserver_http_port>9009</interserver_http_port>  <!-- 복제 -->
    
    <!-- 수신 인터페이스 — 운영 환경에서는 방화벽 없이 0.0.0.0 설정 금지 -->
    <listen_host>0.0.0.0</listen_host>  <!-- 모든 인터페이스 — 주의 -->
    <!-- <listen_host>::</listen_host>   IPv6 -->

0.0.0.0을 무분별하게 사용하지 말아야 하는 이유: 공인 IP를 가진 운영 환경에서 ClickHouse는 포트 스캐닝의 대상이 됩니다. VPN이나 방화벽을 사용하는 것이 좋습니다.

2. 데이터 경로: ClickHouse가 모든 것을 저장하는 곳

<path>/var/lib/clickhouse/</path>           <!-- 주요 데이터 -->
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
<user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
<format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>

내가 당한 문제: 시스템의 /tmp가 메모리(tmpfs)에 마운트되어 용량이 2GB에 불과했습니다. ClickHouse가 대규모 GROUP BY 쿼리를 위해 임시 파일을 쓰려다 오류와 함께 다운되었습니다. tmp_path를 50GB 디스크로 옮겼습니다:

<tmp_path>/data/clickhouse_tmp/</tmp_path>

3. MergeTree 설정: 재앙 방지

모든 운영 서버에 다음 파라미터를 설정합니다:

Google AdInline article slot
<merge_tree>
    <!-- 파트가 10GB 누적될 때까지 병합하지 않음 — 백그라운드 부하 감소 -->
    <min_bytes_for_wide_part>10000000000</min_bytes_for_wide_part>
    
    <!-- 병합할 최대 파트 크기 (100GB) -->
    <max_bytes_to_merge_at_max_space_in_pool>107374182400</max_bytes_to_merge_at_max_space_in_pool>
    
    <!-- 파트가 300개 초과 시 새 INSERT 거부 -->
    <parts_to_throw_insert>300</parts_to_throw_insert>
    
    <!-- 파트 200개에서 경고 -->
    <parts_to_delay_insert>200</parts_to_delay_insert>
    
    <!-- 파티션 내 최대 파트 수 -->
    <max_parts_in_total>10000</max_parts_in_total>
</merge_tree>

parts_to_throw_insert = 300인 이유: 파트가 300개 이상이면 SELECT가 느려지고 INSERT는 상황을 악화시킵니다. INSERT를 거부하고 원인을 조사하는 것이 낫습니다.

4. users.xml: 사용자, 프로필, 할당량

/etc/clickhouse-server/users.xml 파일은 접근 제어입니다. 세 명의 사용자를 생성합니다:

<clickhouse>
    <!-- 1. 분석가용 사용자 (읽기 전용) -->
    <analyst>
        <password>analyst_secure_password</password>
        <networks>
            <ip>10.0.0.0/8</ip>   <!-- 내부 네트워크만 -->
        </networks>
        <profile>readonly_profile</profile>
        <quota>analyst_quota</quota>
    </analyst>

    <!-- 2. 애플리케이션 (리소스 제한) -->
    <app_user>
        <password>${CLICKHOUSE_APP_PASSWORD}</password>  <!-- 환경 변수에서 -->
        <networks>
            <ip>::/0</ip>  <!-- 주의, 특정 서브넷 사용 권장 -->
        </networks>
        <profile>app_profile</profile>
    </app_user>

    <!-- 3. 관리자 (전체 접근) -->
    <admin>
        <password>admin_strong_password</password>
        <networks>
            <host>localhost</host>
            <host>10.0.0.50</host>  <!-- 배스천 호스트만 -->
        </networks>
        <profile>admin_profile</profile>
    </admin>
</clickhouse>

중요한 세부사항: 기본 사용자의 비밀번호는 기본적으로 비어 있습니다. 설치 후 가장 먼저 변경하는 부분입니다.

Google AdInline article slot

5. 설정 프로필: 무분별한 쿼리로부터 보호

프로필은 SELECT * FROM huge_table CROSS JOIN 같은 쿼리로부터 클러스터를 보호하는 제약 조건 집합입니다.

<profiles>
    <!-- 분석가: 무거운 쿼리 가능하지만 제한 있음 -->
    <readonly_profile>
        <readonly>1</readonly>   <!-- SELECT만 -->
        <max_memory_usage>10000000000</max_memory_usage>  <!-- 10GB -->
        <max_execution_time>300</max_execution_time>      <!-- 5분 -->
        <max_rows_to_read>50000000000</max_rows_to_read>  <!-- 500억 행 -->
        <max_bytes_to_read>107374182400</max_bytes_to_read> <!-- 100GB -->
        <prefer_global_in_and_join>1</prefer_global_in_and_join>
    </readonly_profile>

    <!-- 애플리케이션: 빠른 쿼리, 작은 제한 -->
    <app_profile>
        <readonly>0</readonly>
        <max_memory_usage>1000000000</max_memory_usage>   <!-- 1GB -->
        <max_execution_time>10</max_execution_time>        <!-- 10초 -->
        <max_rows_to_read>100000000</max_rows_to_read>     <!-- 1억 -->
        <timeout_before_checking_execution_speed>0</timeout_before_checking_execution_speed>
    </app_profile>

    <!-- 관리자: 거의 제한 없음 (주의) -->
    <admin_profile>
        <readonly>0</readonly>
        <max_memory_usage>0</max_memory_usage>  <!-- 제한 없음 -->
        <max_execution_time>0</max_execution_time>
    </admin_profile>
</profiles>

할당량 — 한 분석가가 모두를 죽이지 않도록:

<quotas>
    <analyst_quota>
        <interval>
            <duration>3600</duration>      <!-- 시간당 -->
            <queries>100</queries>         <!-- 최대 100개 쿼리 -->
            <errors>0</errors>             <!-- 오류 없음 -->
            <result_rows>100000000</result_rows>  <!-- 1억 결과 행 -->
            <read_rows>10000000000</read_rows>    <!-- 100억 읽기 -->
        </interval>
    </analyst_quota>
</quotas>

6. 기본 압축 설정

ClickHouse는 LZ4(빠름) 또는 ZSTD(강력)로 데이터를 압축합니다. 데이터 유형에 따라 선택합니다:

<compression>
    <!-- 신규 데이터는 LZ4 (속도) -->
    <case>
        <last_level>1</last_level>  <!-- 압축 레벨 -->
        <method>LZ4</method>
    </case>
    
    <!-- 30일 이상 된 파티션은 ZSTD (공간 절약) -->
    <case>
        <min_part_size>10737418240</min_part_size>  <!-- 10GB -->
        <method>ZSTD</method>
        <level>3</level>
    </case>
</compression>

운영 환경에서의 선택: 모든 데이터에 LZ4를 사용합니다. ZSTD는 20-30% 공간을 절약하지만 쿼리 속도가 최대 10% 느려집니다.

7. TLS/SSL — 격리된 네트워크가 아니라면

<https_port>8443</https_port>
<tcp_port_secure>9440</tcp_port_secure>

<openSSL>
    <server>
        <certificateFile>/etc/clickhouse-server/ssl/server.crt</certificateFile>
        <privateKeyFile>/etc/clickhouse-server/ssl/server.key</privateKeyFile>
        <verificationMode>none</verificationMode>
        <caConfig>/etc/clickhouse-server/ssl/CA.pem</caConfig>
        <cacheSessions>true</cacheSessions>
        <disableProtocols>sslv2,sslv3,tlsv1,tlsv1_1</disableProtocols>
        <preferServerCiphers>true</preferServerCiphers>
    </server>
</openSSL>

내가 당한 문제: 검증 없는 자체 서명 인증서는 신뢰할 수 있는 네트워크 내에서만 안전합니다. 외부 접근에는 Let's Encrypt 또는 유료 인증서를 사용하세요.

8. config.d/ — 고통 없는 오버라이드

config.xml을 직접 편집하지 마세요. 모든 변경 사항은 /etc/clickhouse-server/config.d/에 넣으세요.

config.d/memory.xml 파일:

<clickhouse>
    <max_server_memory_usage>0.75</max_server_memory_usage>  <!-- 전체 RAM의 75% -->
    <max_concurrent_queries>100</max_concurrent_queries>
</clickhouse>

config.d/networks.xml 파일:

<clickhouse>
    <listen_host>0.0.0.0</listen_host>
    <max_connections>4096</max_connections>
</clickhouse>

장점: ClickHouse 업데이트 시 config.xml이 덮어쓰이지 않고 오버라이드가 유지됩니다. 22.x에서 23.x로 업그레이드할 때 설정을 잃어버린 경험으로 배웠습니다.

9. 베팅 플랫폼을 위한 보안 체크리스트

ClickHouse를 외부에 열기 전에 다음을 확인합니다:

✅ 기본 사용자 비밀번호 변경

clickhouse-client --password
ALTER USER default IDENTIFIED BY 'new_strong_password';

✅ 기본 사용자 제거 또는 제한

<!-- users.xml에서 default 섹션을 주석 처리 -->
<!-- <default>
    <password></password>
</default> -->

✅ 외부 접근 포트 차단 (UFW)

sudo ufw default deny incoming
sudo ufw allow from 10.0.0.0/8 to any port 9000 proto tcp  # 내부 네트워크만
sudo ufw allow from 10.0.0.0/8 to any port 8123 proto tcp
sudo ufw allow ssh

✅ 호스트 수준 방화벽 활성화

sudo iptables -A INPUT -p tcp --dport 9000 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9000 -j DROP

✅ 하나의 쿼리가 서버를 죽이지 않도록 max_memory_usage 설정

<max_memory_usage>10000000000</max_memory_usage>  <!-- 10GB -->

✅ 실험적 기능 비활성화 (필요하지 않은 경우)

<allow_experimental_geo_types>0</allow_experimental_geo_types>
<allow_experimental_window_functions>1</allow_experimental_window_functions> <!-- 23.8+ -->

✅ 모니터링을 위한 query_log 및 slow_log 활성화

<query_log>
    <database>system</database>
    <table>query_log</table>
    <partition_by>toYYYYMM(event_date)</partition_by>
    <flush_interval_milliseconds>7500</flush_interval_milliseconds>
</query_log>

<query_thread_log>
    <database>system</database>
    <table>query_thread_log</table>
</query_thread_log>

✅ IP로 접근 제한 (화이트리스트)

<analyst>
    <networks>
        <ip>10.0.0.100</ip>   <!-- 특정 분석가 IP만 -->
        <ip>10.0.0.101</ip>
        <ip>192.168.1.0/24</ip>
    </networks>
</analyst>

다음은?

이제 ClickHouse가 전투 준비를 마쳤습니다. 다음 글은 운영 환경에서의 모니터링과 백업에 관한 것입니다.


이전 글: 다음 글: ReplacingMergeTree: ClickHouse에서 중복을 고통 없이 제거하는 방법

— Editorial Team

Advertisement 728x90

다음 읽기