上一次,我们讲了如何采集tke/eks集群的事件日志,具体可以参考文档 如何将TKE/EKS集群事件日志持久化
之前我们是通过eventrouter这个开源组件来实现对集群事件日志持久化的,这个组件存在下面2个问题:
- 日志格式不方便检索,因为每条日志加了时间戳,无法通过json格式解析日志,然后投递到es。
- 对于warn级别的异常报错事件,不能告警提示。
为了能更好的检索日志,并配置事件日志告警,下面我们通过阿里的开源组件kube-eventer来实现对tke/eks多集群的事件日志采集。并配置下事件告警发送到钉钉。
kube-eventer的github地址:https://github.com/AliyunContainerService/kube-eventer
kube-eventer 是一个事件发射器,将 kubernetes 事件发送到 sinks(例如 dingtalk、sls、kafka 等)。Kubernetes的核心设计理念是状态机。所以当转移到期望状态时会有正常事件,当转移到意外状态时会发生警告事件。kube-eventer 可以帮助诊断、分析和报警问题。
kube-eventer的架构如下
下面我们配置下如何将腾讯云的tke和eks集群的事件日志采集到es,并给tke和eks配置下warn级别的事件告警发送到钉钉。
1. 部署es和kibana存储事件日志
首先部署下Elasticsearch和kibana用来存储和检索事件日志,这里可以参考之前的文档,这里就不一一演示了https://cloud.tencent.com/developer/article/1990549 。 因为这里是需要同时采集tke和eks集群的事件日志,本次测试的tke和eks集群都是在腾讯云的同一个vpc内,而Elasticsearch
是部署在tke集群上,为了能让eks集群能直接访问到es,这里需要将es的service设置为内网clb类型,同一个vpc内内网互通,这样eks就可以内网访问tke集群上部署的Elasticsearch,如果你的多个集群内网不通,就将Elasticsearch的serivce设置为公网类型clb,走公网将多个集群的事件日志采集到同一个es。
代码语言:javascript复制[root@VM-0-4-centos ~]# kubectl get svc -n weixnie | grep -i Elasticsearch
elasticsearch-master LoadBalancer 10.55.254.57 172.16.0.20 9200:31403/TCP,9300:31323/TCP 10d
elasticsearch-master-headless ClusterIP None <none> 9200/TCP,9300/TCP 10d
这里172.16.0.20就是vpc内网访问的地址。
2. 创建钉钉机器人接受告警
因为我们需要将事件告警发送到钉钉,所以需要提前创建好一个接受告警的机器人,首先需要有一个钉钉群,并且是管理员,点击群管理,然后点击智能群助手
添加机器人
选择自定义
创建好之后复制下对应的webhook地址。
3. tke集群部署kube-eventer
为了避免token和集群信息泄漏,下面集群id个token信息都进行了删减,如果部署的话,需要根据实际修改yaml里面配置。
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: kube-eventer
name: kube-eventer
namespace: weixnie
spec:
replicas: 1
selector:
matchLabels:
app: kube-eventer
template:
metadata:
labels:
app: kube-eventer
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
dnsPolicy: ClusterFirstWithHostNet
serviceAccount: kube-eventer
containers:
- image: registry.aliyuncs.com/acs/kube-eventer-amd64:v1.1.0-63e7f98-aliyun
name: kube-eventer
command:
- "/kube-eventer"
- "--source=kubernetes:https://kubernetes.default"
## .e.g,dingtalk sink demo
- --sink=dingtalk:https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxx&label=cls-tke&label=event&level=Warning&msg_type=markdown
- --sink=elasticsearch:http://172.16.0.20:9200?ver=7&index=cls-tke-event&cluster_name=cls-tke
env:
# If TZ is assigned, set the TZ value as the time zone
- name: TZ
value: Asia/Shanghai
volumeMounts:
- name: localtime
mountPath: /etc/localtime
readOnly: true
- name: zoneinfo
mountPath: /usr/share/zoneinfo
readOnly: true
volumes:
- name: localtime
hostPath:
path: /etc/localtime
- name: zoneinfo
hostPath:
path: /usr/share/zoneinfo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-eventer
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
name: kube-eventer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kube-eventer
subjects:
- kind: ServiceAccount
name: kube-eventer
namespace: weixnie
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-eventer
namespace: weixnie
下面我们来分别对dingtalk和elasticsearch这2个sink的参数讲解下:
- dingtalk
--sink=dingtalk:<DINGTALK_WEBHOOK_URL>&label=<your_cluster_id>&level=<Normal or Warning, Warning default> 可以使用以下选项:
- label - 警报消息上的自定义标签。(例如 clusterId)
- level - 事件级别(默认:警告。选项:警告和正常)
- namespaces - 要过滤的命名空间(默认:所有命名空间,使用逗号分隔多个命名空间)
- kind - 要过滤的种类(默认:所有种类,使用逗号分隔多种。选项:Node、Pod 等。)
- msg_type - 消息类型(默认:文本。选项:文本和降价)
- sign - 签名密钥(如果钉钉使用签名的安全机制,可以通过该字段传入密钥。)[可选]
--sink=dingtalk:https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxx&label=cls-tke&label=event&level=Warning&msg_type=markdown
这里我们将事件基本设置为Warning,表示只发送Warning级别的事件告警,告警格式为markdown,同时配置下label,第一个label为集群id,第二个是对应机器人设置的关键字。
- elasticsearch
--sink=elasticsearch:<ES_SERVER_URL>[?<OPTIONS>]
- index - 指标和事件的索引。默认值为heapster
- esUserName - 启用身份验证时的用户名
- esUserSecret - 启用身份验证时的密码
- maxRetries - Elastic 客户端在放弃并返回错误之前将对单个请求执行的重试次数。默认为 0,因此默认禁用重试。
- healthCheck - 指定是否默认启用 healthCheck。默认情况下启用。要禁用,请提供一个负布尔值,如 0 或 false。
- sniff - 指定默认情况下是否启用嗅探器。默认情况下启用。要禁用,请提供一个负布尔值,如 0 或 false。
- startupHealthcheckTimeout - healthCheck 在启动时(即创建客户端时)等待 Elasticsearch 响应的时间(以秒为单位)。默认值为 1。
- ver - ElasticSearch 集群版本,可以是 2、5、6 或 7。默认为 5
- bulkWorkers - 批量处理的工人数量。默认值为 5。
- cluster_name - 不同 Kubernetes 集群的集群名称。默认值为default。
- pipeline - (可选;>ES5)摄取管道以处理文档。默认为禁用(空值)
--sink=elasticsearch:http://172.16.0.20:9200?ver=7&index=cls-tke-event&cluster_name=cls-tke
里我们配置下es的地址为内网clb的vip地址172.16.0.20,并设置下es的版本,本次使用的es是7.x版本,设置下es索引名称cls-tke-event,索引名称尽可能用集群id,这样方便后续区分检索,然后配置下集群id,用来在日志区分不同集群。
4. eks集群部署kube-eventer
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: kube-eventer
name: kube-eventer
namespace: weixnie
spec:
replicas: 1
selector:
matchLabels:
app: kube-eventer
template:
metadata:
labels:
app: kube-eventer
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
dnsPolicy: ClusterFirstWithHostNet
serviceAccount: kube-eventer
containers:
- image: registry.aliyuncs.com/acs/kube-eventer-amd64:v1.1.0-63e7f98-aliyun
name: kube-eventer
command:
- "/kube-eventer"
- "--source=kubernetes:https://kubernetes.default"
## .e.g,dingtalk sink demo
- --sink=dingtalk:https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxx&label=cls-eks&label=event&level=Warning&msg_type=markdown
- --sink=elasticsearch:http://172.16.0.20:9200?ver=7&index=cls-eks-event&cluster_name=cls-eks
env:
# If TZ is assigned, set the TZ value as the time zone
- name: TZ
value: Asia/Shanghai
volumeMounts:
- name: localtime
mountPath: /etc/localtime
readOnly: true
- name: zoneinfo
mountPath: /usr/share/zoneinfo
readOnly: true
volumes:
- name: localtime
hostPath:
path: /etc/localtime
- name: zoneinfo
hostPath:
path: /usr/share/zoneinfo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-eventer
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
name: kube-eventer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kube-eventer
subjects:
- kind: ServiceAccount
name: kube-eventer
namespace: weixnie
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-eventer
namespace: weixnie
eks上的部署和tke一样,修改下对应的集群id即可
代码语言:javascript复制- --sink=dingtalk:https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxx&label=cls-eks&label=event&level=Warning&msg_type=markdown
- --sink=elasticsearch:http://172.16.0.20:9200?ver=7&index=cls-eks-event&cluster_name=cls-eks
5. kibana配置索引检索不同集群日志
pod运行后,可以看下es是否生成了对应的索引,如果索引文件生成正常,则说明日志采集es正常
代码语言:javascript复制[root@VM-55-14-tlinux ~]# curl 172.16.0.20:9200/_cat/indices | grep cls
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1564 100 1564 0 0 142k 0 --:--:-- --:--:-- --:--:-- 152k
green open cls-tke-event-2022.05.10 gtc-bQ-vTS-Bmm7cZWMhXA 1 1 1275 0 1.4mb 967.9kb
green open cls-eks-event-2022.05.10 zmxIBxpEQkShBxX-o4CCmQ 1 1 144 0 439.1kb 219.5kb
green open cls-tke-event-2022.05.09 rOsASOsVSFeTtMpoWTjxXQ 1 1 4070 0 4.3mb 2.2mb
green open cls-eks-event-2022.05.09 afnL19eXSgeqeTkdQ0QITA 1 1 347 0 427.4kb 166.7kb
然后我们到kibana分别创建下索引来检索tke和eks日志
注意这里创建索引的时候,选择Metadata.managedFields.time这个字段过滤,这样就能检索实时刷新的事件。索引创建好之后,直接检索就行
可以发现,日志格式被解析成了json字段,这样方便检索。这里只配置了一个集群,如果有多个集群配置多个索引即可,当然,也可以配置为一个索引,检索的时候通过集群名称来检索对应集群的事件日志即可。
6. 钉钉查看告警
从上面的检索看,pod的事件日志是一条Warning类型,这里到钉钉群里看下,是否有这条事件的告警,如果有收到告警,则说明告警配置正常
告警群里收到了事件的告警,说明集群的告警配置正常。