日志之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绑定到StatefulSetsquery_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 之前都必须有一个自己所属的项目。 单击“项目”,填写项目名称,项目级别若设置为"私有",则不勾选。如果设置为公共仓库&#…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
