1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 22354字,需瀏覽 45分鐘

         ·

        2022-06-28 21:55

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

        測試應(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

        為方便測試,我們這里使用 NodePort 類型的服務(wù)來暴露應(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

        我們可以通過如下命令來來模擬每隔10s訪問 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 中通過一系列 Pipeline 來處理日志,其中就包括一個(gè) metrics 的階段,可以根據(jù)我們的需求來增加一個(gè)監(jiān)控指標(biāo),這就是我們需要實(shí)現(xiàn)的基于日志的監(jiān)控報(bào)警的核心點(diǎn),通過結(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 集群,接下來我們需要重新配置 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á)式過濾出包含 GET 關(guān)鍵字的日志行。

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

        為了在 Prometheus 中能夠這個(gè)指標(biāo),我們通過 promtail.serviceMonitor.enable=true 開啟了一個(gè) ServiceMonitor。接下來重新更新 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)我們訪問測試應(yīng)用的時(shí)候,在 Loki 中是可以查看到日志數(shù)據(jù)的:

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

        因?yàn)楝F(xiàn)在已經(jīng)有監(jiān)控指標(biāo)了,所以我們就可以根據(jù)需求來創(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)警的閾值通過 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,比如可以通過 WebHook 來接收。我們在 AlertManager 中也是可以看到接收到的報(bào)警事件的。

        Ruler 組件

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

        首先我們需要開啟 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容器 -> 路由日志寫/讀的請(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

        我們首先通過 loki.structuredConfig.ruler 對(duì) Ruler 組件進(jìn)行配置,比如指定 Alertmanager 的地址,規(guī)則存儲(chǔ)方式等,然后通過 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ū)別在于查詢語句(LogQL)不同,在 Loki 中我們用 LogQL 來查詢?nèi)罩荆粋€(gè)典型的 rules 配置文件如下所示:

        groups:
          # 組名稱
          - name: xxxx
            rules:
              # Alert名稱
              - alert: xxxx
                # logQL查詢語句
                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 表示通過日志查到 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ù)超過閾值,則會(huì)真正觸發(fā)報(bào)警規(guī)則,觸發(fā)后我們在 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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产成在线观看免费视频 | 久久精品片 | 高端极品外围女酒店啪啪 | 97人人妻 | 精品国产久久久 | 四川XXXXXLmedjyf本电 | 色婷婷精品 | 久久亚洲AV午夜福利精品一区 | AAA国产高清视频在线观看 | 奇米av |