如何获取游戏日志数据(游戏日志是什么意思)
为什么使用 Loki
Loki 是一个轻量级的日志收集、分析的应用,采用的是 promtail 的方式来获取日志内容并送到 loki 里面进行存储,最终在 grafana 的 datasource 里面添加数据源进行日志的展示、查询。
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 形式抓取数据
云原生支持,使用 Prometheus 形式抓取数据
各日志收集组件简单对比:
Loki 的工作方式
展开全文
从上面的图中我们可以看到,它在解析日志的时候是以 index为主的,index 包括时间戳和 pod 的部分 label(其他 label 为 filename、containers 等),其余的是日志内容。具体查询效果如下:
{app=”loki”,namespace=”kube-public”}为索引。
日志搜集架构
在使用过程中,官方推荐使用 promtail 做为 agent 以 DaemonSet 方式部署在 kubernetes 的 worker 节点上搜集日志。另外也可以用上面提到的其他日志收集工具来收取,这篇文章在结尾处会附上其他工具的配置方式。
Loki 部署模式有哪些
all(读写模式)
服务启动后,我们做的数据查询、数据写入都是来自这一个节点。请看下面的这个图解:
read/write(读写分离模式)
在读写分离模式下运行时 fronted-query 查询会将流量转发到 read 节点上。读节点上保留了 querier、ruler、fronted,写节点上保留了 distributor、ingester。
微服务模式运行
微服务模式运行
微服务模式运行下,通过不同的配置参数启动为不同的角色,每一个进程都引用它的目标角色服务。
大显身手之服务端部署
上面讲了那么多关于 loki 的介绍和它的工作模式,你一定期待它是怎么部署的吧?!该怎么部署、部署在哪里、部署后怎么使用等等问题都会出现在你的脑海里。在部署之前你需要准备好一个 k8s 集群才行哦。那好,接下来耐着性子往下看……
AllInOne 部署模式
k8s部署
我们从 github 上下载的程序是没有配置文件的,需要提前将文件准备一份。这里提供了一份完整的 allInOne 配置文件,部分内容进行了优化。
以下配置文件内容特别长:
## memberlist_conig模块配置gossip用于在分发服务器、摄取器和查询器之间发现和连接。## 所有三个组件的配置都是唯一的,以确保单个共享环。## 至少定义了1个join_members配置后,将自动为分发服务器、摄取器和ring 配置memberlist类型的kvstorememberlist: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: trueschema_config:configs:- from: "2020-10-24"index:period: 24hprefix: index_object_store: filesystemschema: v11store: boltdb-shipperchunks:period: 168hrow_shards: 32table_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: 1800tracing:enabled: true
注意 :
ingester.lifecycler.ring.replication_factor的值在单实例的情况下为 1
ingester.lifecycler.min_ready_duration的值为 15s,在启动后默认会显示 15 秒将状态变为 ready
ingester.lifecycler.ring.replication_factor的值在单实例的情况下为 1
ingester.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,我这里设置成了 true
instance_interface_names是一个列表,默认的为["en0","eth0"],可以根据需要设置对应的网卡名称,一般不需要进行特殊设置。
memberlist.node_name的值可以不用设置,默认是当前主机的名称
memberlist.join_members是一个列表,在有多个实例的情况下需要添加各个节点的主机名 /IP 地址。
在 k8s 里面可以设置成一个 service绑定到 StatefulSets。
query_range.results_cache.cache.enable_fifocache建议设置为 false,我这里设置成了 true
instance_interface_names是一个列表,默认的为["en0","eth0"],可以根据需要设置对应的网卡名称,一般不需要进行特殊设置。
说明:将上面的内容写入到一个文件 loki-all.yaml,把它作为一个 configmap写入 k8s 集群。可以使用如下命令创建:
可以通过命令查看到已经创建好的 configmap,具体操作详见下图
创建持久化存储
在 k8s 里面我们的数据是需要进行持久化的。Loki 收集起来的日志信息对于业务来说是至关重要的,因此需要在容器重启的时候日志能够保留下来。那么就需要用到 pv、pvc,后端存储可以使用 nfs、glusterfs、hostPath、azureDisk、cephfs 等 20 种支持类型,这里因为没有对应的环境就采用了 hostPath 方式。
以下配置文件也特别长:
apiVersion: apps/v1kind: StatefulSetmetadata:labels:app: lokiname: lokinamespace: defaultspec: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: ServiceapiVersion: v1metadata:name: loki-memberlistnamespace: defaultspec:ports:- name: loki-memberlistprotocol: TCPport: 7946targetPort: 7946selector:kubepi.org/name: loki---kind: ServiceapiVersion: v1metadata:name: lokinamespace: defaultspec:ports:- name: lokiprotocol: TCPport: 3100targetPort: 3100selector:kubepi.org/name: loki
验证部署结果
当看到上面的 Running状态时可以通过 API 的方式看一下分发器是不是正常工作,当显示 Active时正常才会正常分发日志流到收集器(ingester)。
限于篇幅,更多部署方式,就不介绍了。
故障解决方案502 BadGateWay
loki 的地址填写不正确 http://LokiServiceName http://LokiServiceName.namespace http://LokiServiceName.namespace:ServicePort 在 k8s 里面,地址填写错误造成了 502。 检查一下 loki 的地址是否是以下内容: grafana 和 loki 在不同的节点上,检查一下节点间网络通信状态、防火墙策略
耐心等待一会,因为是 allInOne 模式程序启动需要一定的时间。
将 ingester.lifecycler.replication_factor改为 1,是因为这个设置不正确造成的。 这个在启动的时候会设置为多个复制源,但当前只部署了一个所以在查看 label 的时候提示这个。
将 ingester.lifecycler.replication_factor改为 1,是因为这个设置不正确造成的。 这个在启动的时候会设置为多个复制源,但当前只部署了一个所以在查看 label 的时候提示这个。
promtail 无法将收集到的日志发送给 loki,许可检查一下 promtail 的输出是不是正常;
promtail 在 loki 还没有准备就绪的时候把日志发送过来了,但 loki 没有接收到。 如果需要重新接收日志,需要删除 positions.yaml 文件,具体路径可以用 find 查找一下位置;
promtail 忽略了目标日志文件或者配置文件错误造成的无法正常启动;
promtail 无法在指定的位置发现日志文件 配置文件参考 1[3]。
629 DOIS DevOps 国际峰会 2023 · 北京站,6月29日就要举行啦~~
各界大佬齐聚,超强阵容震撼上线!主会场门票限时福利,扫码立即得,仅限前 20 名
↑ ↑一定要记得扫码哦
K8s CPU Limits 造成的事故,竟让 Prometheus 轻松解决了? “高效运维”公众号诚邀广大技术人员投稿
投稿邮箱:jiachen@greatops.net,或添加联系人微信:greatops1118。
点个“在看”,一年不宕机