LogstashExample1: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 207: | Строка 207: | ||
} |
} |
||
</PRE> |
</PRE> |
||
− | В результате сообщение будет разобрано на поля - но в этом случае в поле host |
+ | В результате сообщение будет разобрано на поля - но в этом случае в поле host |
+ | <PRE> |
||
+ | "host": { |
||
+ | "hostname": "elk.domain.tld", |
||
+ | "id": "ec2385ad84aeea5eb425460c41a5b866", |
||
+ | "os": { |
||
+ | "type": "linux", |
||
+ | "codename": "focal", |
||
+ | "name": "Ubuntu", |
||
+ | "version": "20.04.2 LTS (Focal Fossa)", |
||
+ | "kernel": "5.4.0-1045-aws", |
||
+ | "platform": "ubuntu", |
||
+ | "family": "debian" |
||
+ | }, |
||
+ | </PRE> |
||
+ | будет записан заголовок HOST что не овсем то что надо |
||
+ | |||
+ | =Пример с дебагом= |
||
+ | Усложняем - добавляем максимальное количесво информации в логи |
||
+ | ==Nginx== |
||
+ | Пишем все что возможно: https://noname.com.ua/mediawiki/index.php/Nginx_Log_Post |
||
+ | <PRE> |
||
+ | |||
+ | </PRE> |
||
+ | <PRE> |
||
+ | server { |
||
+ | listen 443 ssl; |
||
+ | root /var/www/backend; |
||
+ | server_name elk.domain.tld; |
||
+ | access_log /var/log/nginx/elk.domain.tld-access.log.ssl nginxlog_json; |
||
+ | error_log /var/log/nginx/elk.domain.tld-error.log.ssl; |
||
+ | client_max_body_size 500M; |
||
+ | keepalive_timeout 0; |
||
+ | ssl_certificate ...; |
||
+ | ssl_certificate_key ...; |
||
+ | |||
+ | lua_need_request_body on; |
||
+ | |||
+ | set $response_body ""; |
||
+ | body_filter_by_lua ' |
||
+ | local response_body = string.sub(ngx.arg[1], 1, 1000) |
||
+ | ngx.ctx.buffered = (ngx.ctx.buffered or "") .. response_body |
||
+ | if ngx.arg[2] then |
||
+ | ngx.var.response_body = ngx.ctx.buffered |
||
+ | end |
||
+ | '; |
||
+ | |||
+ | set_by_lua_block $request_headers{ |
||
+ | local h = ngx.req.get_headers() |
||
+ | local request_headers_all = "" |
||
+ | for k, v in pairs(h) do |
||
+ | local rowtext = "" |
||
+ | rowtext = string.format(" %s='%s' ", k, v) |
||
+ | request_headers_all = request_headers_all .. rowtext |
||
+ | |||
+ | end |
||
+ | return request_headers_all |
||
+ | } |
||
+ | ... |
||
+ | </PRE> |
Версия 14:31, 8 августа 2021
Пример
Это продолжение статьи https://noname.com.ua/mediawiki/index.php?title=Logstash
nginx
Отправка логов nginx в Elastic (один из вариантов)
Тут рассматривается самый простой случай - когда Filebeat не делает преобразований
Nginx умеет писать логи в Json
Как логгировать хедеры https://stackoverflow.com/questions/24380123/how-to-log-all-headers-in-nginx
log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", ' '"remote_addr": "$remote_addr", ' '"body_bytes_sent": $body_bytes_sent, ' '"request": "$request", ' '"request_method": "$request_method", ' '"request_time": $request_time, ' '"response_status": $status, ' '"upstream_status": $upstream_status,' '"upstream_response_time": $upstream_response_time,' '"upstream_connect_time": $upstream_connect_time,' '"upstream_header_time": $upstream_header_time,' '"upstream_addr": "$upstream_addr",' '"host": "$host",' '"http_x_forwarded_for": "$http_x_forwarded_for",' '"http_referrer": "$http_referer", ' '"http_user_agent": "$http_user_agent", ' '"http_version": "$server_protocol", ' '"nginx_access": true }';
В лог попадает:
tail -1 /var/log/nginx/access.log.ssl | jq . { "timestamp": "2021-08-08T08:47:59+00:00", "remote_addr": "159.224.49.4", "body_bytes_sent": 361, "request": "POST /internal/bsearch HTTP/1.1", "request_method": "POST", "request_time": 0.152, "response_status": 200, "upstream_status": 200, "upstream_response_time": 0.028, "upstream_connect_time": 0, "upstream_header_time": 0.028, "upstream_addr": "127.0.0.1:5601", "host": "elk.domain.tld", "http_x_forwarded_for": "", "http_referrer": "https://elk.domain.tld/app/discover", "http_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", "http_version": "HTTP/1.1", "nginx_access": true }
Filebeat
filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/elk.domain.tld-access.log.ssl exclude_files: ['\.gz$'] filebeat.config.modules: reload.enabled: false setup.template.settings: index.number_of_shards: 1 setup.kibana: output.logstash: hosts: ["elk.domain.tld:5400"] ssl.certificate_authorities: ["/etc/elk-certs/elk-ssl.crt"] ssl.certificate: "/etc/elk-certs/elk-ssl.crt" ssl.key: "/etc/elk-certs/elk-ssl.key" processors: - add_host_metadata: when.not.contains.tags: forwarded - add_cloud_metadata: ~ - add_docker_metadata: ~ - add_kubernetes_metadata: ~ logging.level: debug logging.selectors: ["*"]
В примере мониторится всего один файл (исключение очевидно лишнее)
Результат пересылается на удаленный хост в Logstash
Важно Сертификат должен соответствовать хостнейму - тут нельзя указать IP адрес
hosts: ["elk.domain.tld:5400"]
Logstash
Базовый пример без преобразований
Минимальный конфиг - слушать Filebeat на порту 5400 (без сертификата - не будет работать)
Результат - писать в файл без всяких преобразований
input { beats { port => 5400 ssl => true ssl_certificate_authorities => ["/etc/elk-certs/elk-ssl.crt"] ssl_certificate => "/etc/elk-certs/elk-ssl.crt" ssl_key => "/etc/elk-certs/elk-ssl.key" ssl_verify_mode => "force_peer" } } output { file { flush_interval => 5 gzip => false path => "/var/log/logstash/logstash_debug.log" } }
Результат записи в файл не удовлетворительный
root@elk:/var/log/logstash# tail -1 logstash_debug.log | jq .
Сообщение не было разобрано на поля
{ "message": "{ \"timestamp\": \"2021-08-08T09:20:47+00:00\", \"remote_addr\": \"61.219.11.151\", \"body_bytes_sent\": 163, \"request\": \"GET / HTTP/1.1\", \"request_method\": \"GET\", \"request_time\": 0.213, \"response_status\": 400, \"upstream_status\": ,\"upstream_response_time\": ,\"upstream_connect_time\": ,\"upstream_header_time\": ,\"upstream_addr\": \"\",\"host\": \"elk.arturhaunt.ninja\",\"http_x_forwarded_for\": \"\",\"http_referrer\": \"\", \"http_user_agent\": \"\", \"http_version\": \"HTTP/1.1\", \"nginx_access\": true }", "cloud": { "availability_zone": "us-east-1f", "region": "us-east-1", "instance": { "id": "i-075866580c26fd42c" }, "service": { "name": "EC2" }, "machine": { "type": "t3.large" }, "image": { "id": "ami-09e67e426f25ce0d7" }, "account": { "id": "543591064633" }, "provider": "aws" }, "@timestamp": "2021-08-08T09:20:52.684Z", "agent": { "hostname": "elk.domain.tld", "id": "aef24fda-f14c-40cf-a388-fa0af443f5d7", "type": "filebeat", "version": "7.14.0", "ephemeral_id": "c53f02a8-0b37-4dae-a3c7-cbf03eabca6a", "name": "elk.arturhaunt.ninja" }, "@version": "1", "log": { "offset": 4126, "file": { "path": "/var/log/nginx/elk.domain.tld-access.log.ssl" } }, "host": { "hostname": "elk.domain.tld", "id": "ec2385ad84aeea5eb425460c41a5b866", "os": { "type": "linux", "codename": "focal", "name": "Ubuntu", "version": "20.04.2 LTS (Focal Fossa)", "kernel": "5.4.0-1045-aws", "platform": "ubuntu", "family": "debian" }, "ip": [ "172.31.91.220", "fe80::14b5:eff:feac:ae79" ], "name": "elk.domain.tld", "mac": [ "16:b5:0e:ac:ae:79" ], "architecture": "x86_64", "containerized": false }, "input": { "type": "log" }, "ecs": { "version": "1.10.0" }, "tags": [ "beats_input_codec_plain_applied" ] }
Базовый пример с JSON
Для того что бы разобрать на поля JSON
filter { json { source => "message" } }
В результате сообщение будет разобрано на поля - но в этом случае в поле host
"host": { "hostname": "elk.domain.tld", "id": "ec2385ad84aeea5eb425460c41a5b866", "os": { "type": "linux", "codename": "focal", "name": "Ubuntu", "version": "20.04.2 LTS (Focal Fossa)", "kernel": "5.4.0-1045-aws", "platform": "ubuntu", "family": "debian" },
будет записан заголовок HOST что не овсем то что надо
Пример с дебагом
Усложняем - добавляем максимальное количесво информации в логи
Nginx
Пишем все что возможно: https://noname.com.ua/mediawiki/index.php/Nginx_Log_Post
server { listen 443 ssl; root /var/www/backend; server_name elk.domain.tld; access_log /var/log/nginx/elk.domain.tld-access.log.ssl nginxlog_json; error_log /var/log/nginx/elk.domain.tld-error.log.ssl; client_max_body_size 500M; keepalive_timeout 0; ssl_certificate ...; ssl_certificate_key ...; lua_need_request_body on; set $response_body ""; body_filter_by_lua ' local response_body = string.sub(ngx.arg[1], 1, 1000) ngx.ctx.buffered = (ngx.ctx.buffered or "") .. response_body if ngx.arg[2] then ngx.var.response_body = ngx.ctx.buffered end '; set_by_lua_block $request_headers{ local h = ngx.req.get_headers() local request_headers_all = "" for k, v in pairs(h) do local rowtext = "" rowtext = string.format(" %s='%s' ", k, v) request_headers_all = request_headers_all .. rowtext end return request_headers_all } ...