日志之Loki详细讲解
文章目录
- 1 Loki
- 1.1 引言
- 1.2 Loki工作方式
- 1.2.1 日志解析格式
- 1.2.2 日志搜集架构模式
- 1.2.3 Loki部署模式
- 1.3 服务端部署
- 1.3.1 AllInOne部署模式
- 1.3.1.1 k8s部署
- 1.3.1.2 创建configmap
- 1.3.1.3 创建持久化存储
- 1.3.1.4 创建应用
- 1.3.1.5 验证部署结果
- 1.3.2 裸机部署
- 1.4 Promtail部署
- 1.4.1 k8s部署
- 1.4.1.1 创建配置文件
- 1.4.1.2 创建DaemonSet文件
- 1.4.1.3 创建promtail应用
- 1.4.2 裸机部署
- 1.5 数据源
- 1.6 其他客户端配置
- 1.6.1 Logstash作为日志收集客户端
- 1.7 Helm安装
- 1.8 故障解决方案
- 1.8.1 502 BadGateWay
- 1.8.2 Ingester not ready: instance xx:9095 in state JOINING
- 1.8.3 too many unhealthy instances in the ring
- 1.8.4 Data source connected
1 Loki
1.1 引言
Loki
是一个轻量级的日志收集、分析的应用,采用的是promtail
的方式来获取日志内容并送到loki里面进行存储,最终在grafana
的datasource
里面添加数据源进行日志的展示、查询。
官方文档:https://kubernetes.io/docs/concepts/security/pod-security-policy
loki
的持久化存储支持azure、gcs、s3、swift、local
这5中类型,其中常用的是s3、local
。另外,它还支持很多种日志搜集类型,像最常用的logstash、fluentbit
也在官方支持的列表中。
优点:
- 支持的客户端,如
Promtail,Fluentbit,Fluentd,Vector,Logstash和Grafana Agent
- 首选代理
Promtail
,可以多来源提取日志,包括本地日志文件,systemd,Windows
事件日志,Docker
日志记录驱动程序等 - 没有日志格式要求,包括
JSON,XML,CSV,logfmt
,非结构化文本 - 使用与查询指标相同的语法查询日志
- 日志查询时允许动态筛选和转换日志行
- 可以轻松地计算日志中的需要的指标
- 引入时的最小索引意味着您可以在查询时动态地对日志进行切片和切块,以便在出现新问题时回答它们
- 云原生支持,使用
Prometheus
形式抓取数据
各日志收集组件简单对比
名称 | 安装的组件 | 优点 |
---|---|---|
ELK/EFK | elasticsearch、logstash, kibana、filebeat、kafka/redis | 支持自定义grok正则解析复杂日志内容;dashboard支持主富的可视化展示 |
Loki | grafana、loki、promtail | 占用资源小;grafana原生支持;查询速度快 |
1.2 Loki工作方式
1.2.1 日志解析格式
从上面的图中我们可以看到,它在解析日志的时候是以index
为主的,index
包括时间戳和pod
的部分label
(其他label
为filename
、containers
等),其余的是日志内容。具体查询效果如下:
{app="loki",namespace="kube-public"}
为索引
1.2.2 日志搜集架构模式
在使用过程中,官方推荐使用promtail
做为agent
以DaemonSet
方式部署在kubernetes
的worker
节点上搜集日志。另外也可以用上面提到的其他日志收集工具来收取,这篇文章在结尾处会附上其他工具的配置方式。
1.2.3 Loki部署模式
Loki
由许多组件微服务构建而成,微服务组件有5个。在这5个里面添加缓存用来把数据放起来加快查询。数据放在共享存储里面配置memberlist_config
部分并在实例之间共享状态,将Loki
进行无限横向扩展。
在配置完memberlist_config
部分后采用轮询的方式查找数据。为了使用方便官方把所有的微服务编译成一个二进制,可以通过命令行参数-target
控制,支持all、read、write
,我们在部署时根据日志量的大小可以指定不同模式
all
(读写模式)
服务启动后,我们做的数据查询、数据写入都是来自这一个节点
read/write
(读写分离模式)
在读写分离模式下运行时fronted-query
查询会将流量转发到read
节点上。读节点上保留了querier、ruler、fronted
,写节点上保留了distributor、ingester
- 微服务模式运行
微服务模式运行下,通过不同的配置参数启动为不同的角色,每一个进程都引用它的目标角色服务。
组件名称 | 功能 |
---|---|
分发器/调度器(distributor) | 验证数据合规:数据排序; hash一致性, QPS限制, 转发,数据副本保证不丢失 |
收集器(ingester) | 时间戳排序: 文件系统支持: WAL预写 |
查询前端 (query frontend) | 提供页面操作,向后端存储发出数据查询;查询队列 (query-queueing) 能够防止大数据量查询时触发0OM;查询分割 (query-split) 可以分割大批量查询最后进行数据聚台 |
查询器Querier | 使用loggl语言在后端存储中查询日志 |
缓存 | 将查询到的日志缓存起来共后续使用,如果数据不完整重新查询缺失的数据 |
1.3 服务端部署
在部署之前需要准备好一个k8s集群才行哦
应用 | 镜像 |
---|---|
loki | grafana/loki:2.5.0 |
promtail | grafana/promtail:2.5.0 |
1.3.1 AllInOne部署模式
1.3.1.1 k8s部署
我们从github上下载的程序是没有配置文件的,需要提前将文件准备一份。这里提供了一份完整的allInOne
配置文件,部分内容进行了优化。
配置文件内容如下所示
auth_enabled: false
target: all
ballast_bytes: 20480
server:grpc_listen_port: 9095http_listen_port: 3100graceful_shutdown_timeout: 20sgrpc_listen_address: "0.0.0.0"grpc_listen_network: "tcp"grpc_server_max_concurrent_streams: 100grpc_server_max_recv_msg_size: 4194304grpc_server_max_send_msg_size: 4194304http_server_idle_timeout: 2mhttp_listen_address: "0.0.0.0"http_listen_network: "tcp"http_server_read_timeout: 30shttp_server_write_timeout: 20slog_source_ips_enabled: true# http_path_prefix如果需要更改,在推送日志的时候前缀都需要加指定的内容# http_path_prefix: "/"register_instrumentation: truelog_format: jsonlog_level: info
distributor:ring:heartbeat_timeout: 3skvstore:prefix: collectors/store: memberlist# 需要提前创建好consul集群# consul:# http_client_timeout: 20s# consistent_reads: true# host: 127.0.0.1:8500# watch_burst_size: 2# watch_rate_limit: 2
querier:engine:max_look_back_period: 20s timeout: 3m0s extra_query_delay: 100ms max_concurrent: 10 multi_tenant_queries_enabled: truequery_ingester_only: falsequery_ingesters_within: 3h0m0squery_store_only: falsequery_timeout: 5m0stail_max_duration: 1h0s
query_scheduler:max_outstanding_requests_per_tenant: 2048grpc_client_config:max_recv_msg_size: 104857600max_send_msg_size: 16777216grpc_compression: gziprate_limit: 0rate_limit_burst: 0backoff_on_ratelimits: falsebackoff_config:min_period: 50msmax_period: 15smax_retries: 5 use_scheduler_ring: truescheduler_ring:kvstore:store: memberlistprefix: "collectors/"heartbeat_period: 30sheartbeat_timeout: 1m0s# 默认第一个网卡的名称# instance_interface_names# instance_addr: 127.0.0.1# 默认server.grpc-listen-portinstance_port: 9095
frontend:max_outstanding_per_tenant: 4096querier_forget_delay: 1h0scompress_responses: truelog_queries_longer_than: 2m0smax_body_size: 104857600query_stats_enabled: truescheduler_dns_lookup_period: 10s scheduler_worker_concurrency: 15
query_range:align_queries_with_step: truecache_results: trueparallelise_shardable_queries: truemax_retries: 3results_cache:cache:enable_fifocache: falsedefault_validity: 30s background:writeback_buffer: 10000redis:endpoint: 127.0.0.1:6379timeout: 1sexpiration: 0s db: 9pool_size: 128 password: 1521Qyx6^tls_enabled: falsetls_insecure_skip_verify: trueidle_timeout: 10s max_connection_age: 8h
ruler:enable_api: trueenable_sharding: truealertmanager_refresh_interval: 1mdisable_rule_group_label: falseevaluation_interval: 1m0sflush_period: 3m0sfor_grace_period: 20m0sfor_outage_tolerance: 1h0snotification_queue_capacity: 10000notification_timeout: 4spoll_interval: 10m0squery_stats_enabled: trueremote_write:config_refresh_period: 10senabled: falseresend_delay: 2m0srule_path: /rulerssearch_pending_for: 5m0sstorage:local:directory: /data/loki/rulerstype: configdbsharding_strategy: defaultwal_cleaner:period: 240hmin_age: 12h0m0swal:dir: /data/loki/ruler_walmax_age: 4h0m0smin_age: 5m0struncate_frequency: 1h0m0sring:kvstore:store: memberlistprefix: "collectors/"heartbeat_period: 5sheartbeat_timeout: 1m0s# instance_addr: "127.0.0.1"# instance_id: "miyamoto.en0"# instance_interface_names: ["en0","lo0"]instance_port: 9500num_tokens: 100
ingester_client:pool_config:health_check_ingesters: falseclient_cleanup_period: 10s remote_timeout: 3sremote_timeout: 5s
ingester:autoforget_unhealthy: truechunk_encoding: gzipchunk_target_size: 1572864max_transfer_retries: 0sync_min_utilization: 3.5sync_period: 20sflush_check_period: 30s flush_op_timeout: 10m0schunk_retain_period: 1m30schunk_block_size: 262144chunk_idle_period: 1h0smax_returned_stream_errors: 20concurrent_flushes: 3index_shards: 32max_chunk_age: 2h0m0squery_store_max_look_back_period: 3h30m30swal:enabled: truedir: /data/loki/wal flush_on_shutdown: truecheckpoint_duration: 15mreplay_memory_ceiling: 2GBlifecycler:ring:kvstore:store: memberlistprefix: "collectors/"heartbeat_timeout: 30s replication_factor: 1num_tokens: 128heartbeat_period: 5s join_after: 5s observe_period: 1m0s# interface_names: ["en0","lo0"]final_sleep: 10s min_ready_duration: 15s
storage_config:boltdb:directory: /data/loki/boltdb boltdb_shipper:active_index_directory: /data/loki/active_indexbuild_per_tenant_index: truecache_location: /data/loki/cache cache_ttl: 48hresync_interval: 5mquery_ready_num_days: 5index_gateway_client:grpc_client_config:filesystem:directory: /data/loki/chunks
chunk_store_config:chunk_cache_config:enable_fifocache: truedefault_validity: 30sbackground:writeback_buffer: 10000redis:endpoint: 192.168.3.56:6379timeout: 1sexpiration: 0s db: 8 pool_size: 128 password: 1521Qyx6^tls_enabled: falsetls_insecure_skip_verify: trueidle_timeout: 10s max_connection_age: 8hfifocache:ttl: 1hvalidity: 30m0smax_size_items: 2000max_size_bytes: 500MBwrite_dedupe_cache_config:enable_fifocache: truedefault_validity: 30s background:writeback_buffer: 10000redis:endpoint: 127.0.0.1:6379timeout: 1sexpiration: 0s db: 7pool_size: 128 password: 1521Qyx6^tls_enabled: falsetls_insecure_skip_verify: trueidle_timeout: 10s max_connection_age: 8hfifocache:ttl: 1hvalidity: 30m0smax_size_items: 2000max_size_bytes: 500MBcache_lookups_older_than: 10s
# 压缩碎片索引
compactor:shared_store: filesystemshared_store_key_prefix: index/working_directory: /data/loki/compactorcompaction_interval: 10m0sretention_enabled: trueretention_delete_delay: 2h0m0sretention_delete_worker_count: 150delete_request_cancel_period: 24h0m0smax_compaction_parallelism: 2# compactor_ring:
frontend_worker:match_max_concurrent: trueparallelism: 10dns_lookup_duration: 5s
# runtime_config 这里没有配置任何信息
# runtime_config:
common:storage:filesystem:chunks_directory: /data/loki/chunksfules_directory: /data/loki/rulersreplication_factor: 3persist_tokens: false# instance_interface_names: ["en0","eth0","ens33"]
analytics:reporting_enabled: false
limits_config:ingestion_rate_strategy: globalingestion_rate_mb: 100ingestion_burst_size_mb: 18max_label_name_length: 2096max_label_value_length: 2048max_label_names_per_series: 60enforce_metric_name: truemax_entries_limit_per_query: 5000reject_old_samples: truereject_old_samples_max_age: 168hcreation_grace_period: 20m0smax_global_streams_per_user: 5000unordered_writes: truemax_chunks_per_query: 200000max_query_length: 721hmax_query_parallelism: 64 max_query_series: 700cardinality_limit: 100000max_streams_matchers_per_query: 1000 max_concurrent_tail_requests: 10 ruler_evaluation_delay_duration: 3s ruler_max_rules_per_rule_group: 0ruler_max_rule_groups_per_tenant: 0retention_period: 700hper_tenant_override_period: 20s max_cache_freshness_per_query: 2m0smax_queriers_per_tenant: 0per_stream_rate_limit: 6MBper_stream_rate_limit_burst: 50MBmax_query_lookback: 0ruler_remote_write_disabled: falsemin_sharding_lookback: 0ssplit_queries_by_interval: 10m0smax_line_size: 30mbmax_line_size_truncate: falsemax_streams_per_user: 0# memberlist_conig模块配置gossip用于在分发服务器、摄取器和查询器之间发现和连接。
# 所有三个组件的配置都是唯一的,以确保单个共享环。
# 至少定义了1个join_members配置后,将自动为分发服务器、摄取器和ring 配置memberlist类型的kvstore
memberlist:randomize_node_name: truestream_timeout: 5s retransmit_factor: 4join_members:- 'loki-memberlist'abort_if_cluster_join_fails: trueadvertise_addr: 0.0.0.0advertise_port: 7946bind_addr: ["0.0.0.0"]bind_port: 7946compression_enabled: truedead_node_reclaim_time: 30sgossip_interval: 100msgossip_nodes: 3gossip_to_dead_nodes_time: 3# join:leave_timeout: 15sleft_ingesters_timeout: 3m0s max_join_backoff: 1m0smax_join_retries: 5message_history_buffer_bytes: 4096min_join_backoff: 2s# node_name: miyamotopacket_dial_timeout: 5spacket_write_timeout: 5s pull_push_interval: 100msrejoin_interval: 10stls_enabled: falsetls_insecure_skip_verify: true
schema_config:configs:- from: "2020-10-24"index:period: 24hprefix: index_object_store: filesystemschema: v11store: boltdb-shipperchunks:period: 168hrow_shards: 32
table_manager:retention_deletes_enabled: falseretention_period: 0sthroughput_updates_disabled: falsepoll_interval: 3m0screation_grace_period: 20mindex_tables_provisioning:provisioned_write_throughput: 1000provisioned_read_throughput: 500inactive_write_throughput: 4inactive_read_throughput: 300inactive_write_scale_lastn: 50 enable_inactive_throughput_on_demand_mode: trueenable_ondemand_throughput_mode: trueinactive_read_scale_lastn: 10 write_scale:enabled: truetarget: 80# role_arn:out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800inactive_write_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800read_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800inactive_read_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800chunk_tables_provisioning:enable_inactive_throughput_on_demand_mode: trueenable_ondemand_throughput_mode: trueprovisioned_write_throughput: 1000provisioned_read_throughput: 300inactive_write_throughput: 1inactive_write_scale_lastn: 50inactive_read_throughput: 300inactive_read_scale_lastn: 10write_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800inactive_write_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800read_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800inactive_read_scale:enabled: truetarget: 80out_cooldown: 1800min_capacity: 3000max_capacity: 6000in_cooldown: 1800
tracing:enabled: true
注意
:
ingester.lifecycler.ring.replication_factor
的值在单实例的情况下为1ingester.lifecycler.min_ready_duration
的值为15s,在启动后默认会显示15秒将状态变为ready
memberlist.node_name
的值可以不用设置,默认是当前主机的名称memberlist.join_members
是一个列表,在有多个实例的情况下需要添加各个节点的主机名/IP地址
。在k8s
里面可以设置成一个service绑定到StatefulSets
query_range.results_cache.cache.enable_fifocache
建议设置为false,我这里设置成了trueinstance_interface_names
是一个列表,默认的为["en0","eth0"]
,可以根据需要设置对应的网卡名称,一般不需要进行特殊设置。
1.3.1.2 创建configmap
将上面的内容写入到一个文件——>loki-all.yaml
,把它作为一个configmap
写入k8s
集群。可以使用如下命令创建:
kubectl create configmap --from-file ./loki-all.yaml loki-all
可以通过命令查看到已经创建好的configmap
,具体操作详见下图
1.3.1.3 创建持久化存储
在k8s里面我们的数据是需要进行持久化的。Loki
收集起来的日志信息对于业务来说是至关重要的,因此需要在容器重启的时候日志能够保留下来。
那么就需要用到pv、pvc
,后端存储可以使用nfs、glusterfs、hostPath、azureDisk、cephfs
等20种支持类型,这里因为没有对应的环境就采用了hostPath
方式。
apiVersion: v1
kind: PersistentVolume
metadata:name: lokinamespace: default
spec:hostPath:path: /glusterfs/lokitype: DirectoryOrCreatecapacity:storage: 1GiaccessModes:- ReadWriteMany
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: lokinamespace: default
spec:accessModes:- ReadWriteManyresources:requests:storage: 1GivolumeName: loki
1.3.1.4 创建应用
准备好k8s的StatefulSet
部署文件后就可以直接在集群里面创建应用了。
apiVersion: apps/v1
kind: StatefulSet
metadata:labels:app: lokiname: lokinamespace: default
spec:podManagementPolicy: OrderedReadyreplicas: 1selector:matchLabels:app: lokitemplate:metadata:annotations:prometheus.io/port: http-metricsprometheus.io/scrape: "true"labels:app: lokispec:containers:- args:- -config.file=/etc/loki/loki-all.yamlimage: grafana/loki:2.5.0imagePullPolicy: IfNotPresentlivenessProbe:failureThreshold: 3httpGet:path: /readyport: http-metricsscheme: HTTPinitialDelaySeconds: 45periodSeconds: 10successThreshold: 1timeoutSeconds: 1name: lokiports:- containerPort: 3100name: http-metricsprotocol: TCP- containerPort: 9095name: grpcprotocol: TCP- containerPort: 7946name: memberlist-portprotocol: TCPreadinessProbe:failureThreshold: 3httpGet:path: /readyport: http-metricsscheme: HTTPinitialDelaySeconds: 45periodSeconds: 10successThreshold: 1timeoutSeconds: 1resources:requests:cpu: 500mmemory: 500Milimits:cpu: 500mmemory: 500MisecurityContext:readOnlyRootFilesystem: truevolumeMounts:- mountPath: /etc/lokiname: config- mountPath: /dataname: storagerestartPolicy: AlwayssecurityContext:fsGroup: 10001runAsGroup: 10001runAsNonRoot: truerunAsUser: 10001serviceAccount: lokiserviceAccountName: lokivolumes:- emptyDir: {}name: tmp- name: configconfigMap:name: loki- persistentVolumeClaim:claimName: lokiname: storage
---
kind: Service
apiVersion: v1
metadata:name: loki-memberlistnamespace: default
spec:ports:- name: loki-memberlistprotocol: TCPport: 7946targetPort: 7946selector:kubepi.org/name: loki
---
kind: Service
apiVersion: v1
metadata:name: lokinamespace: default
spec:ports:- name: lokiprotocol: TCPport: 3100targetPort: 3100selector:kubepi.org/name: loki
在上面的配置文件中我添加了一些pod
级别的安全策略,这些安全策略还有集群级别的PodSecurityPolicy
,防止因为漏洞的原因造成集群的整个崩溃
1.3.1.5 验证部署结果
当看到上面的Running
状态时可以通过API的方式看一下分发器是不是正常工作,当显示Active
时正常才会正常分发日志流到收集器(ingester
)
1.3.2 裸机部署
将loki
放到系统的/bin/
目录下,准备grafana-loki.service
控制文件重载系统服务列表
[Unit]
Description=Grafana Loki Log Ingester
Documentation=https://grafana.com/logs/
After=network-online.target[Service]
ExecStart=/bin/loki --config.file /etc/loki/loki-all.yaml
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID[Install]
WantedBy=multi-user.target
重载系统列表命令,可以直接系统自动管理服务:
systemctl daemon-reload
# 启动服务
systemctl start grafana-loki
# 停止服务
systemctl stop grafana-loki
# 重载应用
systemctl reload grafana-loki
1.4 Promtail部署
部署客户端收集日志时也需要创建一个配置文件,按照上面创建服务端的步骤创建。不同的是需要把日志内容push
到服务端
1.4.1 k8s部署
1.4.1.1 创建配置文件
server:log_level: infohttp_listen_port: 3101
clients:- url: http://loki:3100/loki/api/v1/push
positions:filename: /run/promtail/positions.yaml
scrape_configs:- job_name: kubernetes-podspipeline_stages:- cri: {}kubernetes_sd_configs:- role: podrelabel_configs:- source_labels:- __meta_kubernetes_pod_controller_nameregex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})?action: replacetarget_label: __tmp_controller_name- source_labels:- __meta_kubernetes_pod_label_app_kubernetes_io_name- __meta_kubernetes_pod_label_app- __tmp_controller_name- __meta_kubernetes_pod_nameregex: ^;*([^;]+)(;.*)?$action: replacetarget_label: app- source_labels:- __meta_kubernetes_pod_label_app_kubernetes_io_instance- __meta_kubernetes_pod_label_releaseregex: ^;*([^;]+)(;.*)?$action: replacetarget_label: instance- source_labels:- __meta_kubernetes_pod_label_app_kubernetes_io_component- __meta_kubernetes_pod_label_componentregex: ^;*([^;]+)(;.*)?$action: replacetarget_label: component- action: replacesource_labels:- __meta_kubernetes_pod_node_nametarget_label: node_name- action: replacesource_labels:- __meta_kubernetes_namespacetarget_label: namespace- action: replacereplacement: $1separator: /source_labels:- namespace- apptarget_label: job- action: replacesource_labels:- __meta_kubernetes_pod_nametarget_label: pod- action: replacesource_labels:- __meta_kubernetes_pod_container_nametarget_label: container- action: replacereplacement: /var/log/pods/*$1/*.logseparator: /source_labels:- __meta_kubernetes_pod_uid- __meta_kubernetes_pod_container_nametarget_label: __path__- action: replaceregex: true/(.*)replacement: /var/log/pods/*$1/*.logseparator: /source_labels:- __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash- __meta_kubernetes_pod_annotation_kubernetes_io_config_hash- __meta_kubernetes_pod_container_nametarget_label: __path__
用上面的内容创建一个configMap,方法同上
1.4.1.2 创建DaemonSet文件
Promtail
是一个无状态应用不需要进行持久化存储只需要部署到集群里面就可以了,还是同样的准备DaemonSets
创建文件。
kind: DaemonSet
apiVersion: apps/v1
metadata:name: promtailnamespace: defaultlabels:app.kubernetes.io/instance: promtailapp.kubernetes.io/name: promtailapp.kubernetes.io/version: 2.5.0
spec:selector:matchLabels:app.kubernetes.io/instance: promtailapp.kubernetes.io/name: promtailtemplate:metadata:labels:app.kubernetes.io/instance: promtailapp.kubernetes.io/name: promtailspec:volumes:- name: configconfigMap:name: promtail- name: runhostPath:path: /run/promtail- name: containershostPath:path: /var/lib/docker/containers- name: podshostPath:path: /var/log/podscontainers:- name: promtailimage: docker.io/grafana/promtail:2.3.0args:- '-config.file=/etc/promtail/promtail.yaml'ports:- name: http-metricscontainerPort: 3101protocol: TCPenv:- name: HOSTNAMEvalueFrom:fieldRef:apiVersion: v1fieldPath: spec.nodeNamevolumeMounts:- name: configmountPath: /etc/promtail- name: runmountPath: /run/promtail- name: containersreadOnly: truemountPath: /var/lib/docker/containers- name: podsreadOnly: truemountPath: /var/log/podsreadinessProbe:httpGet:path: /readyport: http-metricsscheme: HTTPinitialDelaySeconds: 10timeoutSeconds: 1periodSeconds: 10successThreshold: 1failureThreshold: 5imagePullPolicy: IfNotPresentsecurityContext:capabilities:drop:- ALLreadOnlyRootFilesystem: falseallowPrivilegeEscalation: falserestartPolicy: AlwaysserviceAccountName: promtailserviceAccount: promtailtolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedule- key: node-role.kubernetes.io/control-planeoperator: Existseffect: NoSchedule
1.4.1.3 创建promtail应用
kubectl apply -f promtail.yaml
使用上面这个命令创建后就可以看到服务已经创建好了。接下来就是在Grafana
里面添加DataSource
查看数据了。
1.4.2 裸机部署
如果是裸机部署的情况下,需要对上面的配置文件做一下稍微的改动,更改clients
的地址就可以,文件存放到/etc/loki/
下,例如改成:
clients:- url: http://ipaddress:port/loki/api/v1/push
添加系统开机启动配置,service配置文件存放位置/usr/lib/systemd/system/loki-promtail.service
内容如下
[Unit]
Description=Grafana Loki Log Ingester
Documentation=https://grafana.com/logs/
After=network-online.target[Service]
ExecStart=/bin/promtail --config.file /etc/loki/loki-promtail.yaml
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID[Install]
WantedBy=multi-user.target
启动方式同上面服务端部署内容
1.5 数据源
添加数据源,具体步骤: Grafana->Setting->DataSources->AddDataSource->Loki
注意
:http
的URL
地址,应用、服务部署在哪个namespace
下,就需要指定它的FQDN
地址,它的格式是ServiceName.namespace
。如果默认在default
下、创建的端口号是3100,就需要填写为http://loki:3100,这里为什么不写IP地址而写成服务的名字,是因为在k8s集群里面有个dns服务器会自动解析这个地址。
查找日志信息
1.6 其他客户端配置
1.6.1 Logstash作为日志收集客户端
在启动Logstash
后我们需要安装一个插件,可以通过这个命令安装loki
的输出插件,安装完成之后可以在logstash
的output
中添加信息。
bin/logstash-plugin install logstash-output-loki
添加配置进行测试
完整的logstash
配置信息,可以参考官网给出的内容LogstashConfigFile
output {loki {[url => "" | default = none | required=true][tenant_id => string | default = nil | required=false][message_field => string | default = "message" | required=false][include_fields => array | default = [] | required=false][batch_wait => number | default = 1(s) | required=false][batch_size => number | default = 102400(bytes) | required=false][min_delay => number | default = 1(s) | required=false][max_delay => number | default = 300(s) | required=false][retries => number | default = 10 | required=false][username => string | default = nil | required=false][password => secret | default = nil | required=false][cert => path | default = nil | required=false][key => path | default = nil| required=false][ca_cert => path | default = nil | required=false][insecure_skip_verify => boolean | default = false | required=false]}
}
或者采用logstash
的http
输出模块,配置如下:
output {http {format => "json"http_method => "post"content_type => "application/json"connect_timeout => 10url => "http://loki:3100/loki/api/v1/push"message => '"message":"%{message}"}'}
}
1.7 Helm安装
如果想简便安装的话,可以采用helm
来安装。helm
将所有的安装步骤都进行了封装,简化了安装步骤。
对于想详细了解k8s的人来说,helm不太适合。因为它封装后自动执行,k8s
管理员不知道各组件之间是如何依赖的,可能会造成误区。
废话不多说,下面开始helm安装:
- 添加repo源
helm repo add grafana https://grafana.github.io/helm-charts
- 更新源
helm repo update
- 部署
默认配置
helm upgrade --install loki grafana/loki-simple-scalable
自定义namespace
helm upgrade --install loki --namespace=loki grafana/loki-simple-scalable
自定义配置信息
helm upgrade --install loki grafana/loki-simple-scalable --set "key1=val1,key2=val2,..."
1.8 故障解决方案
1.8.1 502 BadGateWay
loki的地址填写不正确
在k8s里面,地址填写错误造成了502。检查一下loki的地址是否是以下内容:
http://LokiServiceName
http://LokiServiceName.namespace
http://LokiServiceName.namespace:ServicePort
grafana和loki
在不同的节点上,检查一下节点间网络通信状态、防火墙策略
1.8.2 Ingester not ready: instance xx:9095 in state JOINING
耐心等待一会,因为是allInOne
模式程序启动需要一定的时间。
1.8.3 too many unhealthy instances in the ring
将ingester.lifecycler.replication_factor
改为1,是因为这个设置不正确造成的。这个在启动的时候会设置为多个复制源,但当前只部署了一个所以在查看label
的时候提示这个
1.8.4 Data source connected
Data source connected, but no labels received. Verify that Loki and Promtail is configured properly
promtail
无法将收集到的日志发送给loki,许可检查一下promtail
的输出是不是正常promtail
在loki还没有准备就绪的时候把日志发送过来了,但loki没有接收到。如果需要重新接收日志,需要删除positions.yaml文件,具体路径可以用find查找一下位置promtail
忽略了目标日志文件或者配置文件错误造成的无法正常启动promtail
无法在指定的位置发现日志文件
相关文章:

日志之Loki详细讲解
文章目录 1 Loki1.1 引言1.2 Loki工作方式1.2.1 日志解析格式1.2.2 日志搜集架构模式1.2.3 Loki部署模式 1.3 服务端部署1.3.1 AllInOne部署模式1.3.1.1 k8s部署1.3.1.2 创建configmap1.3.1.3 创建持久化存储1.3.1.4 创建应用1.3.1.5 验证部署结果 1.3.2 裸机部署 1.4 Promtail…...
Mongodb投射中的$slice,正向反向跳过要搞清楚
在投射中,使用$操作符和$elemMatch返回数组中第一个符合查询条件的元素。而在投射中使用$slice, 能够返回指定数量的数组元素。 定义 投射中使用$slice命令,指定查询结果中返回数组元素的数量。 语法 db.collection.find(<query>,{<arrayFi…...

类和对象 第六部分 继承 第一部分:继承的语法
一.继承的概念 继承是面向对象的三大特性之一 有些类与类之间存在特殊的关系,例如下图: 我们可以发现,下级别的成员除了拥有上一级的共性,还有自己的特性,这个时候,我们可以讨论利用继承的技术,…...

githacker安装详细教程,linux添加环境变量详细教程(见标题三)
笔者是ctf小白,这两天也是遇到.git泄露的题目,需要工具来解决问题,在下载和使用的过程中也是遇到很多问题,写此篇记录经验,以供学习 在本篇标题三中有详细介绍了Linux系统添加环境变量的操作教程,以供学习 …...

2401Idea用GradleKotlin编译Java控制台中文出乱码解决
解决方法 解决方法1 在项目 build.gradle.kts 文件中加入 tasks.withType<JavaCompile> {options.encoding "UTF-8" } tasks.withType<JavaExec> {systemProperty("file.encoding", "utf-8") }经测试, 只加 tasks.withType<…...

Day39 62不同路径 63不同路径II 343整数拆分 96不同的二叉搜索树
62 不同路径 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径&#…...

JavaScript 的 ~~ 运算和floor 的性能差异
在JavaScript中,~~(双波浪号)和Math.floor()都可以用于向下取整,但它们在行为和性能上有一些差异。要测试这两者之间的性能差异,你可以使用JavaScript的performance.now()方法来进行基准测试。 行为差异 Math.floor()…...
AtCoder Beginner Contest 338F - Negative Traveling Salesman【floyd+状态压缩dp】
原题链接:https://atcoder.jp/contests/abc338/tasks/abc338_f Time Limit: 6 sec / Memory Limit: 1024 MB Score: 500 points、 问题陈述 有一个有N个顶点和M条边的加权简单有向图。顶点的编号为 1 到 N,i/th 边的权重为 Wi,从顶点 U…...

UDP/TCP协议特点
1.前置知识 定义应用层协议 1.确定客户端和服务端要传递哪些信息 2.约定传输格式 网络上传输的一般是二进制数据/字符串 结构化数据转二进制/字符串 称为序列化 反之称之为反序列化 下面就是传输层了 在TCP/IP协议中,我们以 目的端口,目的IP 源端口 源IP 协议号这样一个五…...
编程笔记 html5cssjs 059 css多列
编程笔记 html5&css&js 059 css多列 一、CSS3 多列属性二、实例小结 CSS3 可以将文本内容设计成像报纸一样的多列布局. 一、CSS3 多列属性 下表列出了所有 CSS3 的多列属性: 属性 描述 column-count 指定元素应该被分割的列数。 column-fill 指定如何填充…...

Facebook的元宇宙探索:虚拟社交的新时代
近年来,科技的飞速发展推动着人类社交方式的翻天覆地的改变。在这场数字化革命的浪潮中,社交媒体巨头Facebook正积极探索并引领着一个被誉为“元宇宙”的全新领域,试图为用户打造更为真实、丰富的虚拟社交体验。 元宇宙的崛起 元宇宙这个概念…...

用React给XXL-JOB开发一个新皮肤(四):实现用户管理模块
目录 一. 简述二. 模块规划 2.1. 页面规划2.2. 模型实体定义 三. 模块实现 3.1. 用户分页搜索3.2. Modal 配置3.3. 创建用户表单3.4. 修改用户表单3.5. 删除 四. 结束语 一. 简述 上一篇文章我们实现登录页面和管理页面的 Layout 骨架,并对接登录和登出接口。这篇…...
某赛通电子文档安全管理系统 hiddenWatermark/uploadFile 文件上传漏洞复现
0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…...

Redis五种数据类型及应用场景
1、数据类型 String(字符串,整数,浮点数):做简单的键值对缓存 List(列表):储存一些列表类型的数据结构 Hash(哈希):包含键值对的无序散列表,结构化的数据 Set(无序集合):交集,并集…...

测试环境搭建整套大数据系统(一:基础配置,修改hostname,hosts,免密)
一:使用服务器配置。 二:修改服务器名称hostname,hosts。 在 Linux 系统中,hostname 和 /etc/hosts 文件分别用于管理主机名和主机名解析。 在三台服务器上,分别执行以下命令。 vim /etc/hostnamexdso-hadoop-test-0…...

maven helper 解决jar包冲突方法
一 概要说明 1.1 说明 首先,解决idea中jar包冲突,使用maven的插件:maven helper插件,它能够给我们罗列出来同一个jar包的不同版本,以及他们的来源,但是对不同jar包中同名的类没有办法。 1.2 依赖顺序 …...
AppSrv-文件共享(23国赛真题)
2023全国职业院校技能大赛网络系统管理赛项–模块B:服务部署(WindowServer2022) 文章目录 AppSrv-文件共享题目配置步骤创建用户主目录共享文件夹:本地目录为d:\share\users\,允许所有域用户可读可写。在本目录下为所有用户添加一个以名称命名的文件夹,该文件夹将设置为所…...

AsyncLocal是如何实现在Thread直接传值的?
一:背景 1. 讲故事 这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候,有朋友提出了AsyncLocal是如何实现的,虽然做了口头上的表述,但总还是会不具体,所以觉得有必要用文字图表的方式来系统…...

Flask 入门1:一个简单的 Web 程序
1. 关于 Flask Flask诞生于2010年, Armin Ronacher的一个愚人节玩笑。不过现在已经是一个用python语言基于Werkzeug工具箱编写的轻量级web开发框架,它主要面向需求简单,项目周期短的小应用。 Flask本身相当于一个内核,其他几乎所…...

维护管理Harbor,docker容器的重启策略
维护管理Harbor 通过HarborWeb创建项目 在 Harbor 仓库中,任何镜像在被 push 到 regsitry 之前都必须有一个自己所属的项目。 单击“项目”,填写项目名称,项目级别若设置为"私有",则不勾选。如果设置为公共仓库&#…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...