内容简介:大致一下分为三种方案来做日志采集:因为方案一在业界使用更为广泛,所以下面基于方案一来做k8s的日志采集。详见:
一、日志采集方案
image.png
image.png
大致一下分为三种方案来做日志采集:
- 在节点上运行一个 agent 来收集日志
- 在 Pod 中包含一个 sidecar 容器来收集应用日志
- 直接在应用程序中将日志信息推送到采集后端
因为方案一在业界使用更为广泛,所以下面基于方案一来做k8s的日志采集。
二、架构选型
-
存储层: Elasticsearch 是一个实时的、分布式的可扩展的搜索引擎,允许进行全文、结构化搜索,它通常用于索引和搜索大量日志数据,也可用于搜索许多不同类型的文档。
-
展示层:Kibana 是 Elasticsearch 的一个功能强大的数据可视化 Dashboard,Kibana 允许你通过 web 界面来浏览 Elasticsearch 日志数据。
-
缓存层: 需要收集大数据量的日志一般使用 Redis 、kafka做为中间缓存层来缓冲数据。
-
采集层:
- Fluentd:是一个流行的开源数据收集器, 具有众多插件,通过获取容器日志文件、过滤和转换日志数据,然后将数据传递到 Elasticsearch 集群,在该集群中对其进行索引和存储。
-
Fluentd-bit: 更适用于嵌入设备等资源受限的场景。占用系统资源较少,在插件可以满足需求的同时,无疑是更好的选择。另外Fluent Bit 提供了输出插件,可以把数据发给 Fluentd,因此他们可以在系统中作为独立服务互相协作。对比如下
在这里插入图片描述
- Logstash:ES官方推荐,使用它有很多插件,灵活性很高,但由于是 java 语言编写,占用资源较高,一般作为过滤格式使用,当然也可以单独使用。
- Filebeat: ES官方新一代采集工具,是一个轻量级的日志传输工具,使用Golang语言编写,占用资源低,一般作为采集日志使用,当然也可以单独使用,同样它和Logstash可以互相协作。
详见: 详解日志采集工具--Logstash、Filebeat、Fluentd、Logagent对比
相关架构图如下:
image.png
image.jpg
本文所使用架构
Fluentd(采集),Elasticsearch (存储),kibana(展示)
三、部署Elasticsearch 集群
使用3个 Elasticsearch Pod 来避免高可用下多节点集群中出现的“脑裂”问题
创建一个名为 logging 的 namespace
$ kubectl create namespace logging
1. 创建无头服务
编写elasticsearch-svc.yaml
kind: Service apiVersion: v1 metadata: name: elasticsearch namespace: logging labels: app: elasticsearch spec: selector: app: elasticsearch clusterIP: None ports: - port: 9200 name: rest - port: 9300 name: inter-node
创建服务资源对象
$ kubectl create -f elasticsearch-svc.yaml $ kubectl get svc -n logging NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 13d
2. 部署StorageClass持久化存储
集群使用NFS 作为后端存储资源,在主节点安装NFS,共享/data/k8s/目录。
$ systemctl stop firewalld.service $ yum -y install nfs-utils rpcbind $ mkdir -p /data/k8s $ chmod 755 /data/k8s $ vim /etc/exports /data/k8s *(rw,sync,no_root_squash) $ systemctl start rpcbind.service $ systemctl start nfs.service
创建nfs-client 的自动配置程序Provisioner, nfs-client.yaml
kind: Deployment apiVersion: extensions/v1beta1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs - name: NFS_SERVER value: 172.16.1.100 - name: NFS_PATH value: /data/k8s volumes: - name: nfs-client-root nfs: server: 172.16.1.100 path: /data/k8s
创建ServiceAccount,然后绑定集群对应的操作权限:nfs-client-sa.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-client-provisioner-runner rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["endpoints"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io
创建StorageClass,elasticsearch-storageclass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: es-data-db provisioner: fuseim.pri/ifs
部署服务资源对象
$ kubectl create -f nfs-client.yaml $ kubectl create -f nfs-client-sa.yaml $ kubectl create -f elasticsearch-storageclass.yaml $ kubectl get pods NAME READY STATUS RESTARTS AGE nfs-client-provisioner-5b486d9c65-9fzjz 1/1 Running 9 13d $ kubectl get storageclass NAME PROVISIONER AGE es-data-db fuseim.pri/ifs 13d
3. 使用StatefulSet 创建Es Pod
Elasticsearch 需要稳定的存储来保证 Pod 在重新调度或者重启后的数据依然不变,所以我们需要使用 StatefulSet 控制器来管理 Pod。
编写elasticsearch-statefulset.yaml
apiVersion: apps/v1 kind: StatefulSet metadata: name: es #定义了名为 es 的 StatefulSet 对象 namespace: logging spec: serviceName: elasticsearch #和前面创建的 Service 相关联,这可以确保使用以下 DNS 地址访问 StatefulSet 中的每一个 Pod:es-[0,1,2].elasticsearch.logging.svc.cluster.local,其中[0,1,2]对应于已分配的 Pod 序号。 replicas: 3 #3个副本 selector: #设置匹配标签为app=elasticsearch matchLabels: app: elasticsearch template: #定义Pod模板 metadata: labels: app: elasticsearch spec: initContainers: #初始化容器,在主容器执行前运行 - name: increase-vm-max-map #第一个Init容器用来增加操作系统对mmap计数的限制 image: busybox command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true - name: increase-fd-ulimit #第二个Init容器用来执行ulimit命令,增加打开文件描述符的最大数量 image: busybox command: ["sh", "-c", "ulimit -n 65536"] securityContext: privileged: true containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2 ports: - name: rest containerPort: 9200 - name: inter containerPort: 9300 resources: limits: cpu: 1000m requests: cpu: 1000m volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data env: #声明变量 - name: cluster.name # #Elasticsearch 集群的名称 value: k8s-logs - name: node.name #节点的名称, valueFrom: fieldRef: fieldPath: metadata.name - name: cluster.initial_master_nodes value: "es-0,es-1,es-2" - name: discovery.zen.minimum_master_nodes #将其设置为(N/2) + 1,N是我们的群集中符合主节点的节点的数量。我们有3个 Elasticsearch 节点,因此我们将此值设置为2(向下舍入到最接近的整数)。 value: "2" - name: discovery.seed_hosts #设置在 Elasticsearch 集群中节点相互连接的发现方法。 value: "elasticsearch" - name: ES_JAVA_OPTS #设置为-Xms512m -Xmx512m,告诉JVM使用512 MB的最小和最大堆。您应该根据群集的资源可用性和需求调整这些参数。 value: "-Xms512m -Xmx512m" - name: network.host value: "0.0.0.0" volumeClaimTemplates: #持久化模板 - metadata: name: data labels: app: elasticsearch spec: accessModes: [ "ReadWriteOnce" ] #只能被 mount 到单个节点上进行读写 storageClassName: es-data-db resources: requests: storage: 100Gi
创建服务资源对象
$ kubectl create -f elasticsearch-statefulset.yaml statefulset.apps/es-cluster created $ kubectl get pods -n logging NAME READY STATUS RESTARTS AGE es-cluster-0 1/1 Running 0 20h es-cluster-1 1/1 Running 0 20h es-cluster-2 1/1 Running 0 20h
验证ES服务是否正常
将本地端口9200转发到 Elasticsearch 节点(如es-cluster-0)对应的端口:
$ kubectl port-forward es-cluster-0 9200:9200 --namespace=logging Forwarding from 127.0.0.1:9200 -> 9200 Forwarding from [::1]:9200 -> 9200
打开另一个终端请求es,出现以下内容则为部署成功。
$ curl http://localhost:9200/_cluster/state?pretty { "cluster_name" : "k8s-logs", "cluster_uuid" : "z9Hz1q9OS0G6GQBlWkOjuA", "version" : 19, "state_uuid" : "fjeJfNjjRkmFnX_1x_kzpg", "master_node" : "zcRrv4jnTfKFWGGdORpZKg", "blocks" : { }, "nodes" : { "cqZH5iFOTYCKkNHiZK6uoQ" : { "name" : "es-0", "ephemeral_id" : "l3VAgaBYSLeY0wA9_CdWkw", "transport_address" : "192.168.85.195:9300", "attributes" : { "ml.machine_memory" : "8202764288", "ml.max_open_jobs" : "20", "xpack.installed" : "true" } }, "zcRrv4jnTfKFWGGdORpZKg" : { "name" : "es-1", "ephemeral_id" : "LrD2UIReRfuIlGEArmwYuw", "transport_address" : "192.168.148.77:9300", "attributes" : { "ml.machine_memory" : "14543122432 -------
四、部署Kibana服务
Kibana作为前端展示层应用,不需要存储大量数据,所以我们使用Deployment控制器来管理Kibana的Pod。
编写 kibana.yaml
apiVersion: v1 kind: Service metadata: name: kibana namespace: logging labels: app: kibana spec: ports: - port: 5601 type: NodePort selector: app: kibana --- apiVersion: apps/v1 kind: Deployment metadata: name: kibana namespace: logging labels: app: kibana spec: selector: matchLabels: app: kibana template: metadata: labels: app: kibana spec: containers: - name: kibana image: docker.elastic.co/kibana/kibana:7.6.2 resources: limits: cpu: 1000m requests: cpu: 1000m env: - name: ELASTICSEARCH_HOSTS value: http://elasticsearch:9200 ports: - containerPort: 5601
使用 kubectl 工具创建:
$ kubectl create -f kibana.yaml service/kibana created deployment.apps/kibana created $ kubectl get pods --namespace=logging NAME READY STATUS RESTARTS AGE es-0 1/1 Running 0 42h es-1 1/1 Running 1 42h es-2 1/1 Running 0 42h kibana-945bc5c69-gkb58 1/1 Running 1 16h $ kubectl get svc --namespace=logging NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 42h kibana NodePort 10.97.4.21 <none> 5601:32230/TCP 16h
在浏览器中访问:http://<任意节点IP>:32230
在这里插入图片描述
五、部署Fluentd采集插件
由于我们使用的采集方案,只需要在每台节点上部署一个采集器即可,对资源没有过大的消耗,所以选择对插件支持更多,使用更加广泛的Fluentd 来作为日志收集工具。下面我们使用DasemonSet 控制器来部署 Fluentd 应用,以确保在集群中的每个节点上始终运行一个 Fluentd 收集容器。
1. 编写fluentd的ConfigMap文件
编写Fluentd的配置文件:fluentd-configmap.yaml
kind: ConfigMap apiVersion: v1 metadata: name: fluentd-config namespace: logging data: system.conf: |- <system> root_dir /tmp/fluentd-buffers/ </system> containers.input.conf: |- # 日志源配置 <source> @id fluentd-containers.log # 日志源唯一标识符,后面可以使用该标识符进一步处理 @type tail # Fluentd 内置的输入方式,其原理是不停地从源文件中获取新的日志。 path /var/log/containers/*.log # 挂载的服务器 Docker 容器日志地址 pos_file /var/log/es-containers.log.pos # 检查点 Fluentd重启后会从该文件中的位置恢复日志采集 tag raw.kubernetes.* # 设置日志标签 read_from_head true <parse> # 多行格式化成JSON @type multi_format # 使用 multi-format-parser 解析器插件 <pattern> format json # JSON解析器 time_key time # 指定事件时间的时间字段 time_format %Y-%m-%dT%H:%M:%S.%NZ # 时间格式 </pattern> <pattern> format /^(?<time>.+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/ time_format %Y-%m-%dT%H:%M:%S.%N%:z </pattern> </parse> </source> <match raw.kubernetes.**> # 匹配tag为raw.kubernetes.**日志信息 @id raw.kubernetes @type detect_exceptions # 使用detect-exceptions插件处理异常栈信息 remove_tag_prefix raw # 移除 raw 前缀 message log stream stream multiline_flush_interval 5 max_bytes 500000 max_lines 1000 </match> <filter **> # 拼接日志 @id filter_concat @type concat # Fluentd Filter 插件,用于连接多个事件中分隔的多行日志。 key message multiline_end_regexp /\n$/ # 以换行符“\n”拼接 separator "" </filter> <filter kubernetes.**> # 添加 Kubernetes metadata 数据 @id filter_kubernetes_metadata @type kubernetes_metadata </filter> <filter kubernetes.**> # 修复ES中的JSON字段 @id filter_parser @type parser # multi-format-parser多格式解析器插件 key_name log # 在要解析的记录中指定字段名称。 reserve_data true # 在解析结果中保留原始键值对。 remove_key_name_field true # key_name 解析成功后删除字段。 <parse> @type multi_format <pattern> format json </pattern> <pattern> format none </pattern> </parse> </filter> <filter kubernetes.**> # 删除一些多余的属性 @type record_transformer remove_keys $.docker.container_id,$.kubernetes.container_image_id,$.kubernetes.pod_id,$.kubernetes.namespace_id,$.kubernetes.master_url,$.kubernetes.labels.pod-template-hash </filter> <filter kubernetes.**> # 只采集具有logging=true标签的Pod日志 @id filter_log @type grep <regexp> key $.kubernetes.labels.logging pattern ^true$ </regexp> </filter> forward.input.conf: |- # 监听配置,一般用于日志聚合用 <source> @id forward @type forward </source> output.conf: |- # 路由配置,将处理后的日志数据发送到ES <match **> # 标识一个目标标签,后面是一个匹配日志源的正则表达式,我们这里想要捕获所有的日志并将它们发送给 Elasticsearch,所以需要配置成** @id elasticsearch # 目标的一个唯一标识符 @type elasticsearch # 支持的输出插件标识符,输出到 Elasticsearch @log_level info # 指定要捕获的日志级别,我们这里配置成 info,表示任何该级别或者该级别以上(INFO、WARNING、ERROR)的日志都将被路由到 Elsasticsearch。 include_tag_key true host elasticsearch # 定义 Elasticsearch 的地址 port 9200 logstash_format true # Fluentd 将会以 logstash 格式来转发结构化的日志数据 logstash_prefix k8s # 设置 index 前缀为 k8s request_timeout 30s <buffer> # Fluentd 允许在目标不可用时进行缓存 @type file path /var/log/fluentd-buffers/kubernetes.system.buffer flush_mode interval retry_type exponential_backoff flush_thread_count 2 flush_interval 5s retry_forever retry_max_interval 30 chunk_limit_size 2M queue_limit_length 8 overflow_action block </buffer> </match>
在上面的文件中我们首先定义了日志源,然后经过滤和组装获得我们需要的格式,最后将数据输出到Elasticsearch集群中。
2. 使用Daemonset部署Fluentd Pod
新建一个 fluentd-daemonset.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: fluentd-es namespace: logging labels: k8s-app: fluentd-es kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd-es labels: k8s-app: fluentd-es kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - "" resources: - "namespaces" - "pods" verbs: - "get" - "watch" - "list" --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd-es labels: k8s-app: fluentd-es kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile subjects: - kind: ServiceAccount name: fluentd-es namespace: logging apiGroup: "" roleRef: kind: ClusterRole name: fluentd-es apiGroup: "" --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-es namespace: logging labels: k8s-app: fluentd-es version: v2.0.4 kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: selector: matchLabels: k8s-app: fluentd-es version: v2.0.4 template: metadata: labels: k8s-app: fluentd-es kubernetes.io/cluster-service: "true" version: v2.0.4 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: serviceAccountName: fluentd-es containers: - name: fluentd-es image: cnych/fluentd-elasticsearch:v2.0.4 env: - name: FLUENTD_ARGS value: --no-supervisor -q resources: limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true - name: config-volume mountPath: /etc/fluent/config.d nodeSelector: #节点选择 beta.kubernetes.io/fluentd-ds-ready: "true" #节点需有这个标签才会部署收集 tolerations: #添加容忍 - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers - name: config-volume configMap: name: fluentd-config
刚才我们使用ConfigMap对象编写的Fluentd的配置文件,也已经通过volumes 挂载到了Fluentd 容器中。我们也可以通过给节点打标签的方式,灵活控制哪些节点的日志可以被收集。在上面文件中我们定义了 nodeSelector
字段,来收集集群中含有这个 beta.kubernetes.io/fluentd-ds-ready: "true"
标签的节点日志。
为需要收集日志的节点添加标签
$ kubectl label nodes k8s-node01 beta.kubernetes.io/fluentd-ds-ready=true $ kubectl label nodes kubesphere beta.kubernetes.io/fluentd-ds-ready=true $ kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS k8s-node01 Ready <none> 200d v1.15.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/os=linux,es=log,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux kubesphere Ready master 203d v1.15.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/os=linux,es=log,kubernetes.io/arch=amd64,kubernetes.io/hostname=kubesphere,kubernetes.io/os=linux,node-role.kubernetes.io/master=
部署资源对象
$ kubectl create -f fluentd-configmap.yaml configmap "fluentd-config" created $ kubectl create -f fluentd-daemonset.yaml serviceaccount "fluentd-es" created clusterrole.rbac.authorization.k8s.io "fluentd-es" created clusterrolebinding.rbac.authorization.k8s.io "fluentd-es" created daemonset.apps "fluentd-es" created $ kubectl get pods -n logging NAME READY STATUS RESTARTS AGE es-0 1/1 Running 1 2d es-1 1/1 Running 1 2d es-2 1/1 Running 1 2d fluentd-es-7rf2v 1/1 Running 0 82m fluentd-es-bm974 1/1 Running 0 82m kibana-5b7f674fd8-z6k6h 1/1 Running 1 3h59m $ kubectl get svc -n logging NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 18d kibana NodePort 10.111.51.138 <none> 5601:31284/TCP 18d
3. 测试应用日志收集
在上面Fluentd的配置文件中,我们指定了只收集具有 logging=true
标签的Pod日志, 现在我们部署一个简单的测试应用, 新建 dummylogs.yaml文件
apiVersion: apps/v1 kind: Deployment metadata: name: dummylogs spec: replicas: 3 selector: matchLabels: app: dummylogs template: metadata: labels: app: dummylogs logging: "true" # 要采集日志需要加上该标签 spec: containers: - name: dummy image: cnych/dummylogs:latest args: - msg-processor --- apiVersion: apps/v1 kind: Deployment metadata: name: dummylogs2 spec: replicas: 3 selector: matchLabels: app: dummylogs2 template: metadata: labels: app: dummylogs2 logging: "true" # 要采集日志需要加上该标签 spec: containers: - name: dummy image: cnych/dummylogs:latest args: - msg-receiver-api
使用 kubectl 工具创建该 Pod:
$ kubectl create -f dummylogs.yaml $ kubectl get pod NAME READY STATUS RESTARTS AGE dummylogs-59677dd44d-44z9c 1/1 Running 21 2d8h dummylogs-59677dd44d-s64rj 1/1 Running 19 2d8h dummylogs2-67498f8b6d-dgz7c 1/1 Running 21 2d8h dummylogs2-67498f8b6d-v6db5 1/1 Running 18 2d8h $ kubectl logs -f dummylogs-59677dd44d-44z9c {"LOGLEVEL":"INFO","serviceName":"msg-processor","serviceEnvironment":"staging","message":"Information event from service msg-processor staging - events received and processed.","eventsNumber":25} {"LOGLEVEL":"INFO","serviceName":"msg-processor","serviceEnvironment":"staging","message":"Information event from service msg-processor staging - events received and processed.","eventsNumber":49}
这个 Pod将日志信息打印到 stdout,所以正常来说 Fluentd 会收集到这个日志数据,在 Kibana 中也就可以找到对应的日志数据了,现在我们到kibana上去添加这个索引。
在这里插入图片描述
可以使用过滤器筛选一些日志进行分析
在这里插入图片描述
六、实现基于日志的报警
在应用层面我们可以使用 Promethus 对应用的各项指标进行监控,但是在业务层面,应用的日志中也会产生一些错误日志,影响业务的正常运行,所以我们还需要对错误日志进行监控报警,可以使用 elastalert 组件来完成这个工作。
ElastAlert 支持以下方式报警:
- Command
- JIRA
- OpsGenie
- SNS
- HipChat
- Slack
- Telegram
- Debug
- Stomp
下面我们使用邮件方式报警,编写资源文件elastalert.yaml
apiVersion: v1 kind: ConfigMap metadata: name: elastalert-config namespace: logging labels: app: elastalert data: elastalert_config: |- # elastalert配置文件 --- rules_folder: /opt/rules # 指定规则的目录 scan_subdirectories: false run_every: # 多久从 ES 中查询一次 minutes: 1 buffer_time: minutes: 15 es_host: elasticsearch es_port: 9200 writeback_index: elastalert use_ssl: False verify_certs: True alert_time_limit: # 失败重试限制 minutes: 2880 --- apiVersion: v1 kind: ConfigMap metadata: name: elastalert-rules namespace: logging labels: app: elastalert data: rule_config.yaml: |- # elastalert规则文件 name: dummylogs error # 规则名字,唯一值 es_host: elasticsearch es_port: 9200 type: any # 报警类型 index: k8s-* # es索引 filter: # 过滤 - query: query_string: query: "LOGLEVEL:ERROR" # 报警条件 alert: # 报警类型 - "email" smtp_host: smtp.qq.com smtp_port: 587 smtp_auth_file: /opt/auth/smtp_auth_file.yaml email_reply_to: 123456789@qq.com #发送邮箱 from_addr: 123456789qq.com email: # 接受邮箱 - "xxxxx@163.com" --- apiVersion: apps/v1 kind: Deployment metadata: name: elastalert namespace: logging labels: app: elastalert spec: selector: matchLabels: app: elastalert template: metadata: labels: app: elastalert spec: containers: - name: elastalert image: jertel/elastalert-docker:0.2.4 imagePullPolicy: IfNotPresent volumeMounts: - name: config mountPath: /opt/config - name: rules mountPath: /opt/rules - name: auth mountPath: /opt/auth resources: limits: cpu: 50m memory: 256Mi requests: cpu: 50m memory: 256Mi volumes: - name: auth secret: secretName: smtp-auth - name: rules configMap: name: elastalert-rules - name: config configMap: name: elastalert-config items: - key: elastalert_config path: elastalert_config.yaml
使用邮件进行报警的时候,需要指定一个 smtp_auth_file
的文件,文件中包含用户名和密码:(smtp_auth_file.yaml)
user: "xxxxx@qq.com" # 发送的邮箱地址 password: "exawdasqq12" # 不是qq邮箱的登录密码,是授权码
然后使用上面的文件创建一个对应的 Secret 资源对象:
$ kubectl create secret generic smtp-auth --from-file=smtp_auth_file.yaml -n logging
创建资源对象
$ kubectl apply -f elastalert.yaml $ kubectl get pods -n logging -l app=elastalert NAME READY STATUS RESTARTS AGE elastalert-ff5f7c9c-4948j 1/1 Running 0 9m17s $ kubectl logs -f elastalert-ff5f7c9c-4948j -n logging Elastic Version: 7.6.2 Reading Elastic 6 index mappings: Reading index mapping 'es_mappings/6/silence.json' Reading index mapping 'es_mappings/6/elastalert_status.json' Reading index mapping 'es_mappings/6/elastalert.json' Reading index mapping 'es_mappings/6/past_elastalert.json' Reading index mapping 'es_mappings/6/elastalert_error.json' Index elastalert already exists. Skipping index creation.
我们的示例应用会隔一段时间就产生 ERROR 级别的错误日志,所以正常情况下我们就可以收到如下所示的邮件信息了:
在这里插入图片描述
上篇文章: k8s七 | 服务守护进程DaemonSet
系列文章: 深入理解Kuerneters
参考资料: 从Docker到Kubernetes进阶-阳明
关注公众号回复【k8s】关键词获取视频教程及更多资料:
前行技术圈
欢迎关注我们的微信公众号,每天学习 Go 知识
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ajax Design Patterns
Michael Mahemoff / O'Reilly Media / 2006-06-29 / USD 44.99
Ajax, or Asynchronous JavaScript and XML, exploded onto the scene in the spring of 2005 and remains the hottest story among web developers. With its rich combination of technologies, Ajax provides a s......一起来看看 《Ajax Design Patterns》 这本书的介绍吧!