<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)現(xiàn)基于 Grafana Loki 的日志報(bào)警

          共 22354字,需瀏覽 45分鐘

           ·

          2022-06-28 21:55

          對(duì)于生產(chǎn)環(huán)境以及一個(gè)有追求的運(yùn)維人員來(lái)說(shuō),哪怕是毫秒級(jí)別的宕機(jī)也是不能容忍的。對(duì)基礎(chǔ)設(shè)施及應(yīng)用進(jìn)行適當(dāng)?shù)娜罩居涗浐捅O(jiān)控非常有助于解決問(wèn)題,還可以幫助優(yōu)化成本和資源,以及幫助檢測(cè)以后可能會(huì)發(fā)生的一些問(wèn)題。前面我們學(xué)習(xí)使用了 Prometheus 來(lái)進(jìn)行監(jiān)控報(bào)警,但是如果我們使用 Loki 收集日志是否可以根據(jù)采集的日志來(lái)進(jìn)行報(bào)警呢?答案是肯定的,而且有兩種方式可以來(lái)實(shí)現(xiàn):Promtail 中的 metrics 階段和 Loki 的 ruler 組件。

          測(cè)試應(yīng)用

          比如現(xiàn)在我們有一個(gè)如下所示的 nginx 應(yīng)用用于 Loki 日志報(bào)警:

          # nginx-deploy.yaml
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: nginx
          spec:
            selector:
              matchLabels:
                app: nginx
            template:
              metadata:
                labels:
                  app: nginx
              spec:
                containers:
                - name: nginx
                  image: nginx:1.7.9
                  ports:
                  - containerPort: 80
          ---
          apiVersion: v1
          kind: Service
          metadata:
            name: nginx
            labels:
              app: nginx
          spec:
            ports:
            - name: nginx
              port: 80
              protocol: TCP
            selector:
              app: nginx
            type: NodePort

          為方便測(cè)試,我們這里使用 NodePort 類(lèi)型的服務(wù)來(lái)暴露應(yīng)用,直接安裝即可:

          $ kubectl apply -f nginx-deploy.yaml
          $  kubectl get pods
          NAME                           READY   STATUS    RESTARTS      AGE
          nginx-5d59d67564-ll9xf         1/1     Running   0             16s
          $ kubectl get svc
          NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
          kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        91d
          nginx        NodePort    10.99.153.32   <none>        80:31313/TCP   22s

          我們可以通過(guò)如下命令來(lái)來(lái)模擬每隔10s訪(fǎng)問(wèn) Nginx 應(yīng)用:

          $ while truedo curl --silent --output /dev/null --write-out '%{http_code}' http://192.168.0.106:31313; sleep 10; echodone
          200
          200

          metrics 階段

          前面我們提到在 Promtail 中通過(guò)一系列 Pipeline 來(lái)處理日志,其中就包括一個(gè) metrics 的階段,可以根據(jù)我們的需求來(lái)增加一個(gè)監(jiān)控指標(biāo),這就是我們需要實(shí)現(xiàn)的基于日志的監(jiān)控報(bào)警的核心點(diǎn),通過(guò)結(jié)構(gòu)化日志,增加監(jiān)控指標(biāo),然后使用 Prometheus 結(jié)合 Alertmanager 完成之前我們非常熟悉的監(jiān)控報(bào)警。

          首先我們需要安裝 Prometheus 與 Alertmanager,可以手動(dòng)安裝,也可以使用 Prometheus Operator 的方式,可以參考監(jiān)控報(bào)警章節(jié)相關(guān)內(nèi)容,比如這里我們選擇使用 Prometheus Operator 的方式。

          前面我們介紹了幾種 Loki 的部署方式,這里我們就保留上節(jié)微服務(wù)模式的 Loki 集群,接下來(lái)我們需要重新配置 Promtail,為其添加一個(gè) metrics 處理階段,使用如下所示的 values 文件重新安裝。

          # ci/metrics-values.yaml
          rbac:
            pspEnabled: false
          config:
            clients:
              - url: http://loki-loki-distributed-gateway/loki/api/v1/push
            snippets:
              pipelineStages:
              - cri: {}
              - match:
                  selector: '{app="nginx"}'
                  stages:
                  - regex:
                      expression: '.*(?P<hits>GET /.*)'
                  - metrics:
                      nginx_hits:
                        type: Counter
                        description: "Total nginx requests"
                        source: hits
                        config:
                          action: inc
          serviceMonitor:
            enabled: true
            additionalLabels:
              app: prometheus-operator
              release: prometheus

          上面最重要的部分就是為 Promtail 添加了 pipelineStages 配置,用于對(duì)日志行進(jìn)行轉(zhuǎn)換,在這里我們添加了一個(gè) match 的階段,會(huì)去匹配具有 app=nginx 這樣的日志流數(shù)據(jù),然后下一個(gè)階段是利用正則表達(dá)式過(guò)濾出包含 GET 關(guān)鍵字的日志行。

          在 metrics 指標(biāo)階段,我們定義了一個(gè) nginx_hits 的指標(biāo),Promtail 通過(guò)其 /metrics 端點(diǎn)暴露這個(gè)自定義的指標(biāo)數(shù)據(jù)。這里我們定義的是一個(gè) Counter 類(lèi)型的指標(biāo),當(dāng)從 regex 階段匹配上后,這個(gè)計(jì)數(shù)器就會(huì)遞增。

          為了在 Prometheus 中能夠這個(gè)指標(biāo),我們通過(guò) promtail.serviceMonitor.enable=true 開(kāi)啟了一個(gè) ServiceMonitor。接下來(lái)重新更新 Loki 應(yīng)用,使用如下所示的命令即可:

          $ helm upgrade --install loki -n logging -f ci/metrics-values.yaml .

          更新完成后會(huì)創(chuàng)建一個(gè) ServiceMonitor 對(duì)象用于發(fā)現(xiàn) Promtail 的指標(biāo)數(shù)據(jù):

          $ kubectl get servicemonitor -n logging
          NAME            AGE
          loki-promtail   10s

          如果你使用的 Prometheus-Operator 默認(rèn)不能發(fā)現(xiàn) logging 命名空間下面的數(shù)據(jù),則需要?jiǎng)?chuàng)建如下所示的一個(gè) Role 權(quán)限:

          apiVersion: rbac.authorization.k8s.io/v1
          kind: Role
          metadata:
            labels:
              app.kubernetes.io/component: prometheus
              app.kubernetes.io/name: prometheus
              app.kubernetes.io/part-of: kube-prometheus
              app.kubernetes.io/version: 2.26.0
            name: prometheus-k8s
            namespace: logging
          rules:
          - apiGroups:
            - ""
            resources:
            - services
            - endpoints
            - pods
            verbs:
            - get
            - list
            - watch
          - apiGroups:
            - extensions
            resources:
            - ingresses
            verbs:
            - get
            - list
            - watch
          - apiGroups:
            - networking.k8s.io
            resources:
            - ingresses
            verbs:
            - get
            - list
            - watch
          ---
          apiVersion: rbac.authorization.k8s.io/v1
          kind: RoleBinding
          metadata:
            name: prometheus-k8s
            namespace: logging
          roleRef:
            apiGroup: rbac.authorization.k8s.io
            kind: Role
            name: prometheus-k8s
          subjects:
          - kind: ServiceAccount
            name: prometheus-k8s
            namespace: monitoring

          正常在 Prometheus 里面就可以看到 Promtail 的抓取目標(biāo)了:

          如果你使用的是 Prometheus Operator 自帶的 Grafana,則需要手動(dòng)添加上 Loki 的數(shù)據(jù)源,前面微服務(wù)模式中我們已經(jīng)在 Grafana 中配置了 Loki 的數(shù)據(jù)源,現(xiàn)在當(dāng)我們?cè)L問(wèn)測(cè)試應(yīng)用的時(shí)候,在 Loki 中是可以查看到日志數(shù)據(jù)的:

          而且現(xiàn)在在 Prometheus 中還可以查詢(xún)到我們?cè)? Promtail 中添加的 metrics 指標(biāo)數(shù)據(jù):

          因?yàn)楝F(xiàn)在已經(jīng)有監(jiān)控指標(biāo)了,所以我們就可以根據(jù)需求來(lái)創(chuàng)建報(bào)警規(guī)則了,我們這里使用的 Prometheus Operator,所以可以直接創(chuàng)建一個(gè) PrometheusRule 資源對(duì)象即可:

          # nginx-prometheus-rule.yaml
          apiVersion: monitoring.coreos.com/v1
          kind: PrometheusRule
          metadata:
            labels:
              prometheus: k8s
              role: alert-rules
            name: promtail-nginx-hits
            namespace: logging
          spec:
            groups:
              - name: nginx-hits
                rules:
                  - alert: LokiNginxHits
                    annotations:
                      summary: nginx hits counter
                      description: 'nginx_hits total insufficient count ({{ $value }}).'
                    expr: |
                      sum(increase(promtail_custom_nginx_hits[1m])) > 2
                    for: 2m
                    labels:
                      severity: critical

          這里我們配置了名為 nginx_hits 的報(bào)警規(guī)則,這些規(guī)則在同一個(gè)分組中,每隔一定的時(shí)間間隔依次執(zhí)行。觸發(fā)報(bào)警的閾值通過(guò) expr 表達(dá)式進(jìn)行配置。我們這里表示的是1分鐘之內(nèi)新增的總和是否大于2,當(dāng) expor 表達(dá)式的條件持續(xù)了2分鐘時(shí)間后,報(bào)警就會(huì)真正被觸發(fā),報(bào)警真正被觸發(fā)之前會(huì)保持為 Pending 狀態(tài)。

          然后具體想要把報(bào)警發(fā)送到什么地方去,可以根據(jù)標(biāo)簽去配置 receiver,比如可以通過(guò) WebHook 來(lái)接收。我們?cè)?AlertManager 中也是可以看到接收到的報(bào)警事件的。

          Ruler 組件

          上面的方式雖然可以實(shí)現(xiàn)我們的日志報(bào)警功能,但是還是不夠直接,需要通過(guò) Promtail 去進(jìn)行處理,那么我們能否直接通過(guò) Loki 來(lái)實(shí)現(xiàn)報(bào)警功能呢?其實(shí)在 Loki2.0 版本就提供了報(bào)警功能,其中有一個(gè) Ruler 組件可以持續(xù)查詢(xún)一個(gè) rules 規(guī)則,并將超過(guò)閾值的事件推送給 AlertManager 或者其他 Webhook 服務(wù),這也就是 Loki 自帶的報(bào)警功能了,而且是兼容 AlertManager 的。

          首先我們需要開(kāi)啟 Loki Ruler 組件,更新 loki-distributed 安裝的 Values 文件,在前面微服務(wù)模式的基礎(chǔ)上增加 ruler 組件配置:

          # ci/alert-values.yaml
          loki:
            structuredConfig:
              ingester:
                max_transfer_retries: 0
                chunk_idle_period: 1h
                chunk_target_size: 1536000
                max_chunk_age: 1h
              storage_config: # 存儲(chǔ)的配置,定義其他組件可能用到的存儲(chǔ)
                aws: # s3 / s3 兼容的對(duì)象存儲(chǔ)
                  endpoint: minio.logging.svc.cluster.local:9000
                  insecure: true
                  bucketnames: loki-data
                  access_key_id: myaccessKey
                  secret_access_key: mysecretKey
                  s3forcepathstyle: true
                boltdb_shipper:
                  shared_store: s3
              schema_config:
                configs:
                  - from: 2022-06-21
                    store: boltdb-shipper # index
                    object_store: s3  # chunks
                    schema: v12
                    index:
                      prefix: loki_index_
                      period: 24h
              ruler:
                storage:
                  type: local
                  local:
                    directory: /etc/loki/rules
                ring:
                  kvstore:
                    store: memberlist
                rule_path: /tmp/loki/scratch
                alertmanager_url: http://alertmanager-main.monitoring.svc.cluster.local:9093
                external_url: http:/192.168.0.106:31918

          distributor:
            replicas: 2

          ingester: # WAL(replay)
            replicas: 2
            persistence:
              enabled: true
              size: 1Gi
              storageClass: local-path

          querier:
            replicas: 2
            persistence:
              enabled: true
              size: 1Gi
              storageClass: local-path

          queryFrontend:
            replicas: 2

          gateway: # nginx容器 -> 路由日志寫(xiě)/讀的請(qǐng)求
            nginxConfig:
              httpSnippet: |-
                client_max_body_size 100M;
              serverSnippet: |-
                client_max_body_size 100M;

          # Configuration for the ruler
          ruler:
            enabled: true
            kind: Deployment
            replicas: 1
            persistence:
              enabled: true
              size: 1Gi
              storageClass: local-path
            # -- Directories containing rules files
            directories:
              tenant_no:
                rules1.txt: |
                  groups:
                    - name: nginx-rate
                      rules:
                      - alert: LokiNginxRate
                        expr: sum(rate({app="nginx"} |= "error" [1m])) by (job)
                              /
                            sum(rate({app="nginx"}[1m])) by (job)
                              > 0.01
                        for: 1m
                        labels:
                          severity: critical
                        annotations:
                          summary: loki nginx rate
                          description: high request latency

          我們首先通過(guò) loki.structuredConfig.ruler 對(duì) Ruler 組件進(jìn)行配置,比如指定 Alertmanager 的地址,規(guī)則存儲(chǔ)方式等,然后通過(guò) ruler 屬性配置了組件的相關(guān)信息以及報(bào)警規(guī)則,重新使用上面的 values 文件安裝 Loki:

          $ helm upgrade --install loki -n logging -f ci/alert-values.yaml .
          $ kubectl get pods -n logging
          NAME                                                   READY   STATUS    RESTARTS      AGE
          grafana-55d8779dc6-gkgpf                               1/1     Running   2 (66m ago)   3d21h
          loki-loki-distributed-distributor-56959cc548-xpv6d     1/1     Running   0             3m36s
          loki-loki-distributed-distributor-56959cc548-zjfsb     1/1     Running   0             2m52s
          loki-loki-distributed-gateway-6f4cfd898c-p9xxf         1/1     Running   0             21m
          loki-loki-distributed-ingester-0                       1/1     Running   0             2m32s
          loki-loki-distributed-ingester-1                       1/1     Running   0             3m34s
          loki-loki-distributed-querier-0                        1/1     Running   0             2m48s
          loki-loki-distributed-querier-1                        1/1     Running   0             3m29s
          loki-loki-distributed-query-frontend-5bcc7949d-brzg6   1/1     Running   0             3m30s
          loki-loki-distributed-query-frontend-5bcc7949d-g2wwd   1/1     Running   0             3m35s
          loki-loki-distributed-ruler-5d4b8cd889-m2vbd           1/1     Running   0             3m35s
          minio-548656f786-mjd4c                                 1/1     Running   2 (66m ago)   3d21h
          promtail-ddz27                                         1/1     Running   0             19m
          promtail-lzr6v                                         1/1     Running   0             20m
          promtail-nldqx                                         1/1     Running   0             20m

          Loki 的 rulers 規(guī)則和結(jié)構(gòu)與 Prometheus 是完全兼容,唯一的區(qū)別在于查詢(xún)語(yǔ)句(LogQL)不同,在 Loki 中我們用 LogQL 來(lái)查詢(xún)?nèi)罩荆粋€(gè)典型的 rules 配置文件如下所示:

          groups:
            # 組名稱(chēng)
            - name: xxxx
              rules:
                # Alert名稱(chēng)
                - alert: xxxx
                  # logQL查詢(xún)語(yǔ)句
                  expr: xxxx
                  # 產(chǎn)生告警的持續(xù)時(shí)間 pending.
                  [ for:  | default = 0s ]
                  # 自定義告警事件的label
                  labels:
                  [ :  ]
                  # 告警時(shí)間的注釋
                  annotations:
                  [ :  ]

          比如我們這里配置的規(guī)則 sum(rate({app="nginx"} |= "error" [1m])) by (job) / sum(rate({app="nginx"}[1m])) by (job) > 0.01 表示通過(guò)日志查到 nginx 日志的錯(cuò)誤率大于1%就觸發(fā)告警,同樣重新使用上面的 values 文件更新 Loki:

          更新完成后我們查看 Ruler 組件的日志可以看到一些關(guān)于上面我們配置的報(bào)警規(guī)則的信息:

          $ kubectl logs -f loki-loki-distributed-ruler-5d4b8cd889-m2vbd -n logging
          ......
          level=info ts=2022-06-25T10:10:07.445554993Z caller=metrics.go:122 component=ruler org_id=tenant_no latency=fast query="((sum by(job)(rate({app=\"nginx\"} |= \"error\"[1m])) / sum by(job)(rate({app=\"nginx\"}[1m]))) > 0.01)" query_type=metric range_type=instant length=0s step=0s duration=25.306079ms status=200 limit=0 returned_lines=0 throughput=0B total_bytes=0B queue_time=0s subqueries=1
          level=info ts=2022-06-25T10:11:03.196836972Z caller=pool.go:171 msg="removing stale client" addr=10.244.2.165:9095
          level=info ts=2022-06-25T10:11:07.423644116Z caller=metrics.go:122 component=ruler org_id=tenant_no latency=fast query="((sum by(job)(rate({app=\"nginx\"} |= \"error\"[1m])) / sum by(job)(rate({app=\"nginx\"}[1m]))) > 0.01)" query_type=metric range_type=instant length=0s step=0s duration=3.234499ms status=200 limit=0 returned_lines=0 throughput=0B total_bytes=0B queue_time=0s subqueries=1

          同樣在 1m 之內(nèi)如果持續(xù)超過(guò)閾值,則會(huì)真正觸發(fā)報(bào)警規(guī)則,觸發(fā)后我們?cè)?Alertmanager 也可以看到對(duì)應(yīng)的報(bào)警信息了:

          到這里我們就完成了使用 Loki 基于日志的監(jiān)控報(bào)警。

          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久精品久久久 | 免费看无码一级A片在线播放男男 | 中文字幕精品无码一区二区 | 亚洲中文大香蕉 | 九九精品在线观看 |