Tag Archives: performance

Ceph Read/Write Throughput per RBD (feat. ElasticSearch/Filebeat)

Intro

Ceph은 OpenStack과 같은 IaaS 솔루션으로부터 On-Demand 타입으로 요구되는 Block-Device를 제공/운영 하기에 적합한 분산 오브젝트 스토리지인다.

다만, 현제 도입한 Ceph 버전인 Luminous의 경우, 각 RBD별로, Read/Write 현황을 파악하기가 쉽지 않다. 차기 버전은 Mimic에서는 Ceph 클러스터 Side에서 이 값을 지원 할 것이라고 하나, 어느정도 완성도 있게 지원할지는 파악이 되지 않은 상태라, Luminous에서 부가 솔루션들을 활용해 측정 해보려 한다.

(Note)

Ceph 클러스터는 분산 오브젝트 기반으로서, RBD 서비스의 경우, 단일 Data이동 지점이 없다.(있으면 안되겠지만,) 따라서, 한 지점에서 RBD에 대한 데이터 이동량을 측정하는 것이 사실상 불가능하다. 물론, 전체 노드에서 하나의 RBD에 대한 입출력을 debug메세지를 통해, 취합/합산 하면 가능하였으나, debug_osd 나 debug_filestore, debut_bluestore의 20로그 레벨(최소 10레벨)이 발생시키는 로그 양이 방대해, 중앙 로그 버서(elasticsearch)로 수집(filebeat)량이 로그가 쌓이는 양을 따라 잡지 못해 Time Delay가 발생하는 등 방법적으로는 가능하였으나, 현실적으로 실현 가능성이 0%라 결론 냄.

 

Concepts

RBD의 In/Out(Read/Write) 데이터 수집에 대한 간략한 방식에 대한 설명이다.

Instance는 /var/run/ceph/guest에 생성된 admin-socket을 통해, RBD debug로그를 /var/log/qemu/qemu-guest-$pid.log 파일에 기록하며, filebeat에 의해 이 데이터가 ElasticSearch로 전송되며, ElasticSearch는 사전에 등록된 Pipeline에 의해 데이터를 재가공하여 이용가능한 데이터화 하여 저장하고, kibana로 시각화 할 수 있다.

(Note)

Ceph Cluster Size에서 측정 되지 않으며, Ceph Client Side(OpenStack Compute노드)에서 측정.

 

RBD Debug로그

Logging 위치는 Ceph 클러스터가 아닌 OpenStack Compute노드이다.

Qemu 에뮬레어터가 가상서버에서 RBD를 사용할때, Ceph의 admin-socket을 생성하도록 하고, debug_rbd 레벨을 20으로 활성화 하여, RBD에 대한 Read/Write 작업에 대한 기록을 하도록 설정.

Filebeat :: 원시 로그 선별 및 전송

Filebeat으로 Qemu가 생성한 RBD Read/Write로그중 필요한 Line을 수집하여 중앙 ElasticSearch로 전송.

EalsticSearch :: 원시 로그 데이터 재처리/가공

Raw데이터에서 중요 컬럼 분해 및 Json 문서화 (by Pipeline)

 

Setup

OpenStack Compute Nodes 설정

admin-socket 활성화

 
[root@pub-compute-001 ~]# cat /etc/ceph/ceph.conf
————————————————————
[client]
(중략…..)
admin_socket = /var/run/ceph/guests/$cluster-$type.$id.$pid.$cctid.asok
log_file = /var/log/qemu/qemu-guest-$pid.log
————————————————————
 
 
[root@pub-compute-001 ~]# mkdir -p /var/run/ceph/guests/ /var/log/qemu/
[root@pub-compute-001 ~]# chmod -R 777 /var/run/ceph/
[root@pub-compute-001 ~]# chown qemu:qemu /var/log/qemu/

admin-socker의 debug_rbd 로깅 활성화

Instance는 탄력적으로 생성/삭제(또는 Shutdown/Reboot) 되므로, Socket 목록을 주기적으로 확인하여 debug_rbd 로깅 기능을 활성화 해준다.

  • 간단한 bash 스크립트와, 이를 cron을 이용해 5분에 한번씩 실행 → 5분마다, 생성된 모든 Instance들의 Ceph admin-socket에 대해 debug_rbd 로깅 기능을 20레벨로 활성화 처리 함.

(Note) 추후, Socket생성시, debug_rbd 기능을 활성화를 Default로 할 수 있는 방법이 확인되면, 본 과정은 불필요.

[root@pub-compute-001 ~]# cat /root/enable-ceph-admin-socket.sh

————————————————————

#!/bin/bash

 

for socket in `ls -1 /var/run/ceph/guests/*.asok`

do

    ceph –admin-daemon $socket config set debug_rbd 20/20

done

————————————————————

 

 

 

 

[root@pub-compute-001 ~]# crontab -l

# enable ceph admin-socket

*/5 * * * * /root/enable-ceph-admin-socket.sh > /dev/null 2>&1

 

Filebeat 로그 수집 설정

Filebeat의 기존 설정에서, 아래 내용을 기반으로 debug_rbd로그와 관련된 내용 추가 설정.

(RBD와 관련된 추가 설정만 기술 하였으며, 각 섹션에서 기존 개별 설정은 그대로 유지 한다.)

[root@pub-compute-001 ~]# cat /etc/filebeat/filebeat.yml

————————————————————

(중략……)

 

 

filebeat:

  prospectors:

  – fields:

      type: system-ceph-rbd-io

    ## Debug 로그중 Read/Write에 관련된 Line만 선별적으로 ES로 전송하도록 한다.

    include_lines: [‘send_request: oid rbd_data’, ‘send: write rbd_data’]

    paths:

    – /var/log/qemu/*.log

    type: log

 

 

(중략……)

 

 

output:

  elasticsearch:

    bulk_max_size: 2048

    pipelines:

    ## prospectors에 의해 선별된 로그에 대해, ES가 “system-ceph-rbd-io”라는 이름의 pipeline 데이터 가공룰을 적용하도록 알려준다.

    – pipeline: system-ceph-rbd-io

      when:

        regexp:

          fields:

            type: ^system-ceph-rbd-io$

 


 

 

Sample 로그

[root@pub-compute-001 ~]# tail -F /var/log/qemu/qemu-guest-[0-9]*.log | egrep “send_request: oid rbd_data|send: write rbd_data”
(Write 로그)
2019-01-18 14:51:49.375845 7f3ea008a700 20 librbd::io::ObjectRequest: 0x56437fb2ed20 send: write rbd_data.82fd5253296fe2.0000000000000401 2569728~3072
Write-Size: 3072 byte
(Read 로그)
2019-01-18 14:51:53.008165 7f3ea008a700 20 librbd::io::ImageRequest: 0x564364f1fdb0 send_request: oid rbd_data.82fd5253296fe2.000000000000026c 3915776~278528 from [0,278528]
Read-Size: 278528 byte

Logrotate 설정

debug_rbd 20/20 로그도 I/O가 많을 때는, 무시 하지 못할 정도의 Log량이 된다.

특히, /var/log/qemu에 생성되는 log파일들은 instance의 종류나 폐기와 무관하게 삭제 또는 Rotation되지 않는다.

이를 관리 하기 위해, 하기 내용과 같인 linux 기본 패키지인 logrotate를 활용해 log를 적절히 순환 및 정리해준다.

(Note)

로그파일을 rename하지 않고, 동적으로 생성/삭제 되는 qemu프로세스 특성상 copytruncate로 처리 하였음. 따라서, copy에 따른 overhead가 클수 있어, 너무 비대해지기 전에(100M초과시) 바로 Rotation 처리 하도록 하였음.

(참고) 1시간 동안 쌓이 로그도 너무 크다면, 2번째 방안인 cron.d에서 직접 주기(예제는 10분)를 지정하여 수행되도록 한다.

[root@pub-compute-001 ]# cat /etc/logrotate.d/qemu-ceph-rbd

——————————————————

/var/log/qemu/*.log {

        hourly

        missingok

        rotate 0

        size 100M

        copytruncate

}

——————————————————

 

 

<선택 사항>

 

 

(매시간 수행)

[root@pub-compute-001 ]# cat /etc/cron.hourly/logrotate-qemu-ceph-rbd

——————————————————

#!/bin/bash

test -x /usr/sbin/logrotate || exit 0

/usr/sbin/logrotate /etc/logrotate.hourly.conf

——————————————————

 

[root@pub-compute-001 ]# chmod 755 /etc/cron.hourly/logrotate-qemu-ceph-rbd

 

 

(10분 주기 수행:수동설정)

[root@pub-compute-001 ~]# cat /etc/cron.d/logrotate-qemu-ceph-rbd

——————————————————

*/5 * * * * root /usr/sbin/logrotate /etc/logrotate.d/qemu-ceph-rbd

 


 

 

ElasticSearch 설정

Filebeat으로부터 수신된 Raw데이터를 수집하고, 사용하기 쉽게 재처리하는 역할 담당.

 

Pipeline

grok 패턴에 Read와 Write 두가지 종류의 로그 분석 패턴을 등록해 두었으며, 각각에 따라 매칭되어 라인을 컬럼별로 분석하여 중요 자료를 json형식으로 데이터화 한다.

PUT _ingest/pipeline/system-ceph-rbd-io

{

  “processors” : [

    {  

      “rename”: {

        “field”: “@timestamp”,

        “target_field”: “event.created”

      }

    },

    {

      “grok”: {

        “field”: “message”,

        “patterns”: [

          “%{TIMESTAMP_ISO8601:call518.ceph.rbd_io.timestamp} %{GREEDYDATA:call518.ceph.rbd_io.tmp_contents}”

        ]

      }

    },

    {

      “grok”: {

        “field”: “call518.ceph.rbd_io.tmp_contents”,

        “patterns”: [

          “%{NOTSPACE:call518.ceph.rbd_io.code1} %{NUMBER:call518.ceph.rbd_io.code2} %{GREEDYDATA:call518.ceph.rbd_io.tmp_contents}”

        ]

      }

    },

    {

      “grok”: {

        “field”: “call518.ceph.rbd_io.tmp_contents”,

        “patterns”: [

          “%{NOTSPACE:call518.ceph.rbd_io.request}: %{NOTSPACE:call518.ceph.rbd_io.request_code} %{JOB_STRING_READ:call518.ceph.rbd_io.job_string} %{NOTSPACE:call518.ceph.rbd_io.object_id_prefix}\\.%{NOTSPACE:call518.ceph.rbd_io.object_id_uniq} %{NUMBER}~%{NUMBER:call518.ceph.rbd_io.operation_size} from \\[%{NUMBER},%{NUMBER}\\]”,

          “%{NOTSPACE:call518.ceph.rbd_io.request}: %{NOTSPACE:call518.ceph.rbd_io.request_code} %{JOB_STRING_WRITE:call518.ceph.rbd_io.job_string} %{NOTSPACE:call518.ceph.rbd_io.object_id_prefix}\\.%{NOTSPACE:call518.ceph.rbd_io.object_id_uniq} %{NUMBER}~%{NUMBER:call518.ceph.rbd_io.operation_size}”

        ],

        “pattern_definitions” : {

          “JOB_STRING_READ”: “send_request: oid”,

          “JOB_STRING_WRITE”: “send: write”

        }

      }

    },

    {

      “set”: {

        “if”: “ctx.call518.ceph.rbd_io.job_string == ‘send_request: oid'”,

        “field”: “call518.ceph.rbd_io.operation”,

        “value”: “read”

      }

    },

    {

      “set”: {

        “if”: “ctx.call518.ceph.rbd_io.job_string == ‘send_request: oid'”,

        “field”: “call518.ceph.rbd_io.object_legend”,

        “value”: “Read-{{call518.ceph.rbd_io.object_id_prefix}}”

      }

    },

    {

      “set”: {

        “if”: “ctx.call518.ceph.rbd_io.job_string == ‘send: write'”,

        “field”: “call518.ceph.rbd_io.operation”,

        “value”: “write”

      }

    },

    {

      “set”: {

        “if”: “ctx.call518.ceph.rbd_io.job_string == ‘send: write'”,

        “field”: “call518.ceph.rbd_io.object_legend”,

        “value”: “Write-{{call518.ceph.rbd_io.object_id_prefix}}”

      }

    },

    {

      “set”: {

        “field”: “call518.ceph.rbd_io.object_id_full”,

        “value”: “{{call518.ceph.rbd_io.object_id_prefix}}.{{call518.ceph.rbd_io.object_id_uniq}}”

      }

    },

    {

      “convert”: {

        “field” : “call518.ceph.rbd_io.operation_size”,

        “type”: “long”,

        “ignore_missing”: true

      }

    },

    {

      “remove”: {

        “field”: [ “call518.ceph.rbd_io.tmp_contents” ],

        “ignore_missing”: true

      }

    },

    {

      “date”: {

        “field”: “call518.ceph.rbd_io.timestamp”,

        “target_field”: “@timestamp”,

        “formats”: [ “yyyy-MM-dd HH:mm:ss.SSSSSS” ],

        “timezone” : “Asia/Seoul”

      }

    }

  ],

  “on_failure”: [

    {

      “set”: {

        “field”: “error.message”,

        “value”: “{{ _ingest.on_failure_message }}”

      }

    }

  ]

}

 

ElasticSearch 데이터 샘플

{

  “_index”: “filebeat-2019.01.18”,

  “_type”: “doc”,

  “_id”: “ZbaJX2gBxAU6Jfe0LC9G”,

  “_version”: 1,

  “_score”: null,

  “_source”: {

    “offset”: 5762354617,

    “prospector”: {

      “type”: “log”

    },

    “call518”: {

      “ceph”: {

        “rbd_io”: {

          “request”: “librbd::io::ImageRequest”,

          “code2”: “20”,

          “code1”: “7f3ea008a700”,

          “object_id_prefix”: “rbd_data.82fd5253296fe2”,

          “request_code”: “0x564365b5a6e0”,

          “object_id_uniq”: “0000000000000254”,

          “operation”: “read”,

          “job_string”: “send_request: oid”,

          “timestamp”: “2019-01-18 14:57:33.123447”,

          “operation_size”: 1048576

        }

      }

    },

    “source”: “/var/log/qemu/qemu-guest-21399.log”,

    “message”: “2019-01-18 14:57:33.123447 7f3ea008a700 20 librbd::io::ImageRequest: 0x564365b5a6e0 send_request: oid rbd_data.82fd5253296fe2.0000000000000254 2850816~1048576 from [0,1048576]”,

    “input”: {

      “type”: “log”

    },

    “@timestamp”: “2019-01-18T14:57:33.123+09:00”,

    “beat”: {

      “hostname”: “pub-compute-004.hanpda.com”,

      “name”: “pub-compute-004.hanpda.com”,

      “version”: “6.4.1”

    },

    “host”: {

      “name”: “pub-compute-004.hanpda.com”

    },

    “fields”: {

      “type”: “system-ceph-rbd-io”

    },

    “event”: {

      “created”: “2019-01-18T05:57:34.320Z”

    }

  },

  “fields”: {

    “@timestamp”: [

      “2019-01-18T05:57:33.123Z”

    ],

    “event.created”: [

      “2019-01-18T05:57:34.320Z”

    ]

  },

  “highlight”: {

    “fields.type”: [

      “@kibana-highlighted-field@system-ceph-rbd-io@/kibana-highlighted-field@”

    ]

  },

  “sort”: [

    1547791053123

  ]

}

 

Appendix

Kibana 시각화 샘플

시각화는, 원하는 목적에 따라 다양해질 수 있으며, 그중 하나의 샘플이다.

아래 샘플은, RBD당 Read(+), Write(-)를 하나의 시간축 그래프로 나타낸 것임. 데이터 값은 단위 시간동안의 총합(Sum)을 표시 하는 것으로 진행 하였음.

Continue reading

Advertisements