自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用 OpenTelemetry Collector 收集 Kubernetes 日志數(shù)據(jù)

云計算 云原生
首先我們需要部署 Loki 來收集日志數(shù)據(jù),同樣我們這里使用 Helm Chart 來快速部署,不過需要注意同樣不需要部署任何日志采集器,因?yàn)槲覀儗⑹褂?OpenTelemetry Collector 來收集日志數(shù)據(jù),然后再將其發(fā)送到 Loki 中。

前面我們介紹了如何通過 OpenTelemetry Collector 來收集 Kubernetes 集群的指標(biāo)數(shù)據(jù),接下來我們再來了解下如何收集集群的日志記錄數(shù)據(jù)。

安裝 Loki

首先我們需要部署 Loki 來收集日志數(shù)據(jù),同樣我們這里使用 Helm Chart 來快速部署,不過需要注意同樣不需要部署任何日志采集器,因?yàn)槲覀儗⑹褂?OpenTelemetry Collector 來收集日志數(shù)據(jù),然后再將其發(fā)送到 Loki 中。

$ helm repo add grafana https://grafana.github.io/helm-chart
$ helm repo update

我們這里創(chuàng)建一個 loki-values.yaml 文件來配置 Loki Helm Chart:

# loki-values.yaml
loki:
  commonConfig:
    replication_factor: 1
  auth_enabled: false
  storage:
    type: "filesystem"
singleBinary:
  replicas: 1
  persistence:
    enabled: true
    size: 10Gi
    storageClass: cfsauto
monitoring:
  lokiCanary:
    enabled: false
  selfMonitoring:
    grafanaAgent:
      installOperator: false
test:
  enabled: false
gateway:
  ingress:
    enabled: true
    ingressClassName: nginx
    tls: []
    hosts:
      - host: loki.k8s.local
        paths:
          - path: /
            pathType: Prefix

然后直接使用下面的命令一鍵部署 Loki 即可:

$ helm upgrade --install loki grafana/loki -f loki-values.yaml --namespace kube-otel
$ kubectl get pods -n kube-otel -l app.kubernetes.io/instance=loki
NAME                            READY   STATUS    RESTARTS   AGE
loki-0                          1/1     Running   0          3m52s
loki-gateway-5ffc9fbbf5-m5q75   1/1     Running   0          8m42s
$ kubectl get ingress -n kube-otel
NAME                 CLASS   HOSTS               ADDRESS       PORTS   AGE
loki-gateway         nginx   loki.k8s.local      10.98.12.94   80      11m

啟用 filelog 接收器

接下來我們就需要配置 OpenTelemetry Collector 來將日志數(shù)據(jù)發(fā)送到 Loki 中,首先更新 otel-collector-ds-values.yaml 文件,我們需要添加一個 Loki 的導(dǎo)出器,并開啟 filelogreceiver 接收器:

# otel-collector-ds-values.yaml
mode: daemonset

presets:
  hostMetrics:
    enabled: true
  kubernetesAttributes:
    enabled: true
  kubeletMetrics:
    enabled: true
  # 啟用 filelogreceiver 收集器
  logsCollection:
    enabled: true

config:
  exporters:
    loki:
      endpoint: http://loki-gateway/loki/api/v1/push
      timeout: 10s # 超時時間
      read_buffer_size: 200
      write_buffer_size: 100
      retry_on_failure: # 配置重試
        enabled: true
        initial_interval: 10s # 初始間隔
        max_interval: 60s # 最大間隔
        max_elapsed_time: 10m # 最大時間
      default_labels_enabled:
        exporter: false

  processors:
    resource:
      attributes:
        - action: insert
          key: loki.resource.labels
          value: k8s.namespace.name,k8s.pod.name,k8s.container.name

  service:
    pipelines:
      logs:
        exporters:
          - loki
        processors:
          - memory_limiter
          - k8sattributes
          - resource
          - batch

然后重新更新 OpenTelemetry Collector DaemonSet:

$ helm upgrade --install opentelemetry-collector ./opentelemetry-collector -f otel-ds-values.yaml --namespace kube-otel --create-namespace

同樣更新后查看完整的配置信息,使用命令 kubectl get cm -n opentelemetry-collector-agent -oyaml:

exporters:
  logging:
    loglevel: debug
  loki:
    endpoint: http://loki-gateway/loki/api/v1/push
    timeout: 10s # 超時時間
    read_buffer_size: 200
    write_buffer_size: 100
    retry_on_failure: # 配置重試
      enabled: true
      initial_interval: 10s # 初始間隔
      max_interval: 60s # 最大間隔
      max_elapsed_time: 10m # 最大時間
    default_labels_enabled:
      exporter: false
extensions:
  health_check: {}
  memory_ballast:
    size_in_percentage: 40
processors:
  batch: {}
  k8sattributes:
    extract:
      metadata:
        - k8s.namespace.name
        - k8s.deployment.name
        - k8s.statefulset.name
        - k8s.daemonset.name
        - k8s.cronjob.name
        - k8s.job.name
        - k8s.node.name
        - k8s.pod.name
        - k8s.pod.uid
        - k8s.pod.start_time
    filter:
      node_from_env_var: K8S_NODE_NAME
    passthrough: false
    pod_association:
      - sources:
          - from: resource_attribute
            name: k8s.pod.ip
      - sources:
          - from: resource_attribute
            name: k8s.pod.uid
      - sources:
          - from: connection
  memory_limiter:
    check_interval: 5s
    limit_percentage: 80
    spike_limit_percentage: 25
  resource:
    attributes:
      - action: insert
        key: loki.resource.labels
        value: k8s.namespace.name,k8s.pod.name,k8s.container.name
receivers:
  filelog:
    exclude:
      - /var/log/pods/kube-otel_opentelemetry-collector*_*/opentelemetry-collector/*.log
    include:
      - /var/log/pods/*/*/*.log
    include_file_name: false
    include_file_path: true
    operators:
      - id: get-format
        routes:
          - expr: body matches "^\\{"
            output: parser-docker
          - expr: body matches "^[^ Z]+ "
            output: parser-crio
          - expr: body matches "^[^ Z]+Z"
            output: parser-containerd
        type: router
      - id: parser-crio
        regex: ^(?P<time>[^ Z]+) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$
        timestamp:
          layout: 2006-01-02T15:04:05.999999999Z07:00
          layout_type: gotime
          parse_from: attributes.time
        type: regex_parser
      - combine_field: attributes.log
        combine_with: ""
        id: crio-recombine
        is_last_entry: attributes.logtag == 'F'
        max_log_size: 102400
        output: extract_metadata_from_filepath
        source_identifier: attributes["log.file.path"]
        type: recombine
      - id: parser-containerd
        regex: ^(?P<time>[^ ^Z]+Z) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$
        timestamp:
          layout: "%Y-%m-%dT%H:%M:%S.%LZ"
          parse_from: attributes.time
        type: regex_parser
      - combine_field: attributes.log
        combine_with: ""
        id: containerd-recombine
        is_last_entry: attributes.logtag == 'F'
        max_log_size: 102400
        output: extract_metadata_from_filepath
        source_identifier: attributes["log.file.path"]
        type: recombine
      - id: parser-docker
        output: extract_metadata_from_filepath
        timestamp:
          layout: "%Y-%m-%dT%H:%M:%S.%LZ"
          parse_from: attributes.time
        type: json_parser
      - id: extract_metadata_from_filepath
        parse_from: attributes["log.file.path"]
        regex: ^.*\/(?P<namespace>[^_]+)_(?P<pod_name>[^_]+)_(?P<uid>[a-f0-9\-]+)\/(?P<container_name>[^\._]+)\/(?P<restart_count>\d+)\.log$
        type: regex_parser
      - from: attributes.stream
        to: attributes["log.iostream"]
        type: move
      - from: attributes.container_name
        to: resource["k8s.container.name"]
        type: move
      - from: attributes.namespace
        to: resource["k8s.namespace.name"]
        type: move
      - from: attributes.pod_name
        to: resource["k8s.pod.name"]
        type: move
      - from: attributes.restart_count
        to: resource["k8s.container.restart_count"]
        type: move
      - from: attributes.uid
        to: resource["k8s.pod.uid"]
        type: move
      - from: attributes.log
        to: body
        type: move
    start_at: beginning
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317
      http:
        endpoint: ${env:MY_POD_IP}:4318
service:
  extensions:
    - health_check
    - memory_ballast
  pipelines:
    logs:
      exporters:
        - loki
      processors:
        - memory_limiter
        - k8sattributes
        - resource
        - batch
      receivers:
        - otlp
        - filelog
# 同樣只保留了和 logs 相關(guān)的配置,其他省略......

我們新增加了一個 loki 的導(dǎo)出器以及 filelog 接收器。

loki 導(dǎo)出器

該導(dǎo)出器是通過 HTTP 將數(shù)據(jù)導(dǎo)出到 Loki。該導(dǎo)出器可以做以下一些配置:

  • endpoint:Loki 的 HTTP 端點(diǎn)地址(如 http://loki:3100/loki/api/v1/push)。
  • default_labels_enabled(可選):允許禁用默認(rèn)標(biāo)簽的映射:exporter、job、instance、level。如果省略default_labels_enabled,則會添加默認(rèn)標(biāo)簽。如果在 default_labels_enabled 中省略了其中一個標(biāo)簽,則會添加該標(biāo)簽。

如果禁用了所有默認(rèn)標(biāo)簽,并且沒有添加其他標(biāo)簽,則日志條目將被丟棄,因?yàn)橹辽傩枰嬖谝粋€標(biāo)簽才能成功將日志記錄寫入 Loki 中。指標(biāo) otelcol_lokiexporter_send_failed_due_to_missing_labels 將會顯示由于未指定標(biāo)簽而被丟棄的日志記錄數(shù)量。

Loki 導(dǎo)出器可以將 OTLP 資源和日志屬性轉(zhuǎn)換為 Loki 標(biāo)簽,并對其進(jìn)行索引。為此,需要配置提示,指定應(yīng)將哪些屬性設(shè)置為標(biāo)簽。提示本身就是屬性,在導(dǎo)出到 Loki 時將被忽略。以下示例使用 attributes 處理器提示 Loki 導(dǎo)出器將 event.domain 屬性設(shè)置為標(biāo)簽,并使用 resource 處理器提示 Loki 導(dǎo)出器將 service.name 設(shè)置為標(biāo)簽。

processors:
  attributes:
    actions:
      - action: insert
        key: loki.attribute.labels
        value: event.domain

  resource:
    attributes:
      - action: insert
        key: loki.resource.labels
        value: service.name

除非通過 default_labels_enabled 設(shè)置禁用,默認(rèn)標(biāo)簽始終會被設(shè)置。

  • job=service.namespace/service.name
  • instance=service.instance.id
  • exporter=OTLP
  • level=severity

如果 service.name 和 service.namespace 存在,那么設(shè)置 job=service.namespace/service.name。如果 service.name 存在且 service.namespace 不存在,則會設(shè)置 job=service.name。如果 service.name 不存在且 service.namespace 存在,則不會設(shè)置 job 標(biāo)簽。如果存在 service.instance.id 則設(shè)置 instance=service.instance.id。如果 service.instance.id 不存在,則不設(shè)置 instance 標(biāo)簽。

我們這里的完整配置如下:

loki:
  endpoint: http://loki-gateway/loki/api/v1/push
  timeout: 10s # 超時時間
  read_buffer_size: 200
  write_buffer_size: 100
  retry_on_failure: # 配置重試
    enabled: true
    initial_interval: 10s # 初始間隔
    max_interval: 60s # 最大間隔
    max_elapsed_time: 10m # 最大時間

我們這里配置了超時時間,讀寫緩沖區(qū)大小,發(fā)送隊列,重試等。

read_buffer_size 和 write_buffer_size 字段分別指定了 OpenTelemetry 導(dǎo)出器的讀取和寫入緩沖區(qū)的大小。這些緩沖區(qū)用于在發(fā)送數(shù)據(jù)之前緩存數(shù)據(jù),以提高發(fā)送效率和可靠性。

read_buffer_size 字段指定了導(dǎo)出器從數(shù)據(jù)源讀取數(shù)據(jù)時使用的緩沖區(qū)大小。如果數(shù)據(jù)源產(chǎn)生的數(shù)據(jù)量超過了緩沖區(qū)的大小,導(dǎo)出器將分批讀取數(shù)據(jù)并將其緩存到緩沖區(qū)中,直到緩沖區(qū)被填滿或數(shù)據(jù)源沒有更多數(shù)據(jù)為止。

write_buffer_size 字段指定了導(dǎo)出器將指標(biāo)數(shù)據(jù)寫入目標(biāo)時使用的緩沖區(qū)大小。如果導(dǎo)出器產(chǎn)生的數(shù)據(jù)量超過了緩沖區(qū)的大小,導(dǎo)出器將分批將數(shù)據(jù)寫入目標(biāo),并將其緩存到緩沖區(qū)中,直到緩沖區(qū)被填滿或目標(biāo)不可用為止。

通過配置這些緩沖區(qū)的大小,您可以控制 OpenTelemetry 導(dǎo)出器的性能和可靠性。如果您的數(shù)據(jù)源產(chǎn)生的數(shù)據(jù)量很大,可以增加 read_buffer_size 和 write_buffer_size 的大小,以提高導(dǎo)出器的吞吐量和效率。如果您的目標(biāo)不太穩(wěn)定或網(wǎng)絡(luò)不太可靠,可以減小 write_buffer_size 的大小,以減少數(shù)據(jù)丟失的風(fēng)險。

另外添加了一個resource的處理器,將 k8s.namespace.name、k8s.pod.name、k8s.container.name 轉(zhuǎn)換為 Loki 標(biāo)簽,這樣我們就可以在 Loki 中對其進(jìn)行索引了。

resource:
  attributes:
    - action: insert
      key: loki.resource.labels
      value: k8s.namespace.name,k8s.pod.name,k8s.container.name

filelog 接收器

該接收器用于從文件中收集并解析日志數(shù)據(jù),它會從指定的文件中讀取日志數(shù)據(jù),然后將其發(fā)送到 OpenTelemetry Collector 中。

我們這里對該接收器的配置如下所示:

filelog:
  exclude:
    - /var/log/pods/kube-otel_opentelemetry-collector*_*/opentelemetry-collector/*.log
  include:
    - /var/log/pods/*/*/*.log
  include_file_name: false
  include_file_path: true
  operators:
    - id: get-format
      routes:
        - expr: body matches "^\\{"
          output: parser-docker
        - expr: body matches "^[^ Z]+ "
          output: parser-crio
        - expr: body matches "^[^ Z]+Z"
          output: parser-containerd
      type: router
    - id: parser-crio
      regex: ^(?P<time>[^ Z]+) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$
      timestamp:
        layout: 2006-01-02T15:04:05.999999999Z07:00
        layout_type: gotime
        parse_from: attributes.time
      type: regex_parser
    - combine_field: attributes.log
      combine_with: ""
      id: crio-recombine
      is_last_entry: attributes.logtag == 'F'
      max_log_size: 102400
      output: extract_metadata_from_filepath
      source_identifier: attributes["log.file.path"]
      type: recombine
    - id: parser-containerd
      regex: ^(?P<time>[^ ^Z]+Z) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$
      timestamp:
        layout: "%Y-%m-%dT%H:%M:%S.%LZ"
        parse_from: attributes.time
      type: regex_parser
    - combine_field: attributes.log
      combine_with: ""
      id: containerd-recombine
      is_last_entry: attributes.logtag == 'F'
      max_log_size: 102400
      output: extract_metadata_from_filepath
      source_identifier: attributes["log.file.path"]
      type: recombine
    - id: parser-docker
      output: extract_metadata_from_filepath
      timestamp:
        layout: "%Y-%m-%dT%H:%M:%S.%LZ"
        parse_from: attributes.time
      type: json_parser
    - id: extract_metadata_from_filepath
      parse_from: attributes["log.file.path"]
      regex: ^.*\/(?P<namespace>[^_]+)_(?P<pod_name>[^_]+)_(?P<uid>[a-f0-9\-]+)\/(?P<container_name>[^\._]+)\/(?P<restart_count>\d+)\.log$
      type: regex_parser
    - from: attributes.stream
      to: attributes["log.iostream"]
      type: move
    - from: attributes.container_name
      to: resource["k8s.container.name"]
      type: move
    - from: attributes.namespace
      to: resource["k8s.namespace.name"]
      type: move
    - from: attributes.pod_name
      to: resource["k8s.pod.name"]
      type: move
    - from: attributes.restart_count
      to: resource["k8s.container.restart_count"]
      type: move
    - from: attributes.uid
      to: resource["k8s.pod.uid"]
      type: move
    - from: attributes.log
      to: body
      type: move
  start_at: beginning

可以看到配置非常長,首先通過 exclude 排除一些不需要收集的日志文件,然后通過 include 指定了需要收集的日志文件,由于我們的 Kubernetes 集群是基于 Containerd 容器運(yùn)行時的,所以采集的日志目錄為 /var/log/pods/*/*/*.log,然后通過 include_file_path 來指定是否將文件路徑添加為屬性 log.file.path,include_file_name 指定是否將文件名添加為屬性 log.file.name。

start_at 表示在啟動時,從文件的哪個位置開始讀取日志。選項(xiàng)有 beginning 或 end,默認(rèn)為 end。

然后就是最重要的 operators 屬性,用來指定如何處理日志文件,運(yùn)算符是日志處理的最基本單元。每個運(yùn)算符都完成一個單一的責(zé)任,比如從文件中讀取行,或者從字段中解析 JSON。然后,這些運(yùn)算符被鏈接在一起,形成一個管道,以實(shí)現(xiàn)所需的結(jié)果。

例如用戶可以使用 file_input 操作符從文件中讀取日志行。然后,這個操作的結(jié)果可以發(fā)送到 regex_parser 操作符,根據(jù)正則表達(dá)式創(chuàng)建字段。最后,這些結(jié)果可以發(fā)送到 file_output 操作符,將日志寫入到磁盤上的文件中。

我們這里首先配置了一個 router 操作符:

id: get-format
routes:
  - expr: body matches "^\\{"
    output: parser-docker
  - expr: body matches "^[^ Z]+ "
    output: parser-crio
  - expr: body matches "^[^ Z]+Z"
    output: parser-containerd
type: router

該操作符允許根據(jù)日志內(nèi)容動態(tài)路由日志,我們這里是 Containerd 的容器運(yùn)行時,產(chǎn)生的日志數(shù)據(jù)可以匹配 body matches "^[^ Z]+Z",然后將數(shù)據(jù)路由到 parser-containerd 操作符。

id: parser-containerd
regex: ^(?P<time>[^ ^Z]+Z) (?P<stream>stdout|stderr) (?P<logtag>[^ ]*) ?(?P<log>.*)$
timestamp:
  layout: "%Y-%m-%dT%H:%M:%S.%LZ"
  parse_from: attributes.time
type: regex_parser

parser-containerd 是一個 regex_parser 操作符,它使用指定的正則表達(dá)式來解析前面路由過來的日志數(shù)據(jù),然后會將結(jié)果存儲在 time、stream、logtag、log 等屬性中,并格式化 timestamp 時間戳。

接下來再通過 recombine 操作符將連續(xù)的日志組合成單個日志。

combine_field: attributes.log
combine_with: ""
id: containerd-recombine
is_last_entry: attributes.logtag == 'F'
max_log_size: 102400
output: extract_metadata_from_filepath
source_identifier: attributes["log.file.path"]
type: recombine

經(jīng)過上面處理后進(jìn)入 extract_metadata_from_filepath 這個操作符,該操作符使用正則表達(dá)式從文件路徑中提取元數(shù)據(jù),然后將其存儲在 namespace、pod_name、uid、container_name、restart_count 等屬性中。

id: extract_metadata_from_filepath
parse_from: attributes["log.file.path"]
regex: ^.*\/(?P<namespace>[^_]+)_(?P<pod_name>[^_]+)_(?P<uid>[a-f0-9\-]+)\/(?P<container_name>[^\._]+)\/(?P<restart_count>\d+)\.log$
type: regex_parser

接下來就是通過 move 操作符將一個字段從一個位置移動(或重命名)到另一個位置。

- from: attributes.stream
  to: attributes["log.iostream"]
  type: move
- from: attributes.container_name
  to: resource["k8s.container.name"]
  type: move
- from: attributes.namespace
  to: resource["k8s.namespace.name"]
  type: move
- from: attributes.pod_name
  to: resource["k8s.pod.name"]
  type: move
- from: attributes.restart_count
  to: resource["k8s.container.restart_count"]
  type: move
- from: attributes.uid
  to: resource["k8s.pod.uid"]
  type: move
- from: attributes.log
  to: body
  type: move

最后我們可以將 Loki 數(shù)據(jù)源添加到 Grafana 中:

Loki 數(shù)據(jù)源

然后在 Explorer 頁面切換到 Loki 數(shù)據(jù)源下面就可以看到 Loki 中的日志數(shù)據(jù)了:

Loki 日志

啟用 k8sobject 接收器

同樣對于 Gateway 模式的采集器我們還可以去開啟 k8sobject 接收器來采集 Kubernetes Events 數(shù)據(jù),然后更新 otel-collector-deploy-values.yaml 文件:

# otel-collector-deploy-values.yaml
mode: deployment

# 我們只需要一個收集器 - 多了就會產(chǎn)生重復(fù)數(shù)據(jù)
replicaCount: 1

presets:
  clusterMetrics:
    enabled: true
  kubernetesEvents:
    enabled: true

config:
  exporters:
    loki:
      endpoint: http://loki-gateway/loki/api/v1/push
      timeout: 10s # 超時時間
      read_buffer_size: 200
      write_buffer_size: 100
      retry_on_failure: # 配置重試
        enabled: true
        initial_interval: 10s # 初始間隔
        max_interval: 60s # 最大間隔
        max_elapsed_time: 10m # 最大時間

  service:
    pipelines:
      logs:
        exporters:
          - loki

然后重新更新 OpenTelemetry Collector Deployment:

$ helm upgrade --install opentelemetry-collector-cluster ./opentelemetry-collector -f otel-collector-deploy-values.yaml --namespace kube-otel --create-namespace

這里我們開啟了 kubernetesEvents 預(yù)設(shè),對應(yīng)的配置如下所示:

k8sobjects:
  objects:
    - group: events.k8s.io
      mode: watch
      name: events

k8sobjects 接收器可以用來拉取或 Watch Kubernetes API 服務(wù)器中的對象,我們這里通過 group、mode、name 來指定要拉取的 Kubernetes Events 對象。

最后我們也可以在 Loki 中查找到對應(yīng)的 Events 日志數(shù)據(jù)。

責(zé)任編輯:姜華 來源: k8s技術(shù)圈
相關(guān)推薦

2023-08-30 07:20:58

2021-07-19 09:18:07

KubernetesELK Stackk8s

2021-07-20 08:32:16

Kubernetes日志平臺

2023-04-28 17:53:09

Kubernetes沙盒Signadot

2022-06-20 11:15:08

日志容器Kubernetes

2024-03-05 08:05:37

2022-05-11 10:58:11

MetricKitiOS13系統(tǒng)崩潰診斷

2022-06-12 21:28:26

Fluentd開源

2022-12-29 08:00:26

Loki網(wǎng)絡(luò)設(shè)備

2023-12-25 11:18:12

OpenTeleme應(yīng)用日志Loki

2024-03-11 00:01:00

PromtailLoki服務(wù)器

2023-08-07 18:53:24

Collector云原生CPU

2024-09-11 08:10:46

2023-09-06 07:51:19

KubernetesOperator

2024-02-23 14:57:40

2023-12-07 07:23:39

APIsSDKs

2023-09-24 23:35:46

云原生Kubernetes

2010-06-12 08:53:19

2017-05-16 14:48:24

WhatsApp數(shù)據(jù)安全

2018-03-09 09:15:16

Linuxsyslog-ng日志
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號