既然是一文玩转,自然要讲些背景
Cloud Native
1.1. 什么是 iLogtail 采集配置
-
SLS:阿里云日志服务,一站式提供数据采集、加工、查询与分析、可视化、告警、消费与投递等功能,全面提升您在研发、运维、运营、安全等场景的数字化能力。 -
iLogtail:SLS 推出的一款可观测数据采集器,拥有轻量级、高性能、自动化配置等特性,可以将它部署于物理机,虚拟机,Kubernetes 等多种环境中来采集可观测数据,例如 logs、traces 和 metrics。 -
iLogtail 采集配置:iLogtail 采集数据的流水线是通过采集配置定义的,一个采集配置里包含数据的输入、处理、输出等信息。
在 SLS 控制台,一个简单的采集配置长这样:
1.2. 为什么我们需要 CRD 来管理采集配置
通过控制台管理采集配置,终究是不够自动化。
试想:若是每次发布,都需要手动上控制台修改一批采集配置,岂不是太麻烦了?更何况可能改错。
在云原生时代,我们需要更方便的方式,来管理采集配置。这种方式,它最好是可灵活扩展的,不与业务耦合;它最好是可以集中管理和监控的,来简化运维的操作;它最好是方便集成与自动化部署的,来降低部署的难度……
基于以上需求,CRD 就这样进入了我们的视线。
在 Kubernetes 环境中,CRD 是一种扩展 K8s API 的方法,允许用户定义和管理自己的资源。使用 CRD,可以将采集配置作为 Kubernetes 对象进行管理,使其与其他 Kubernetes 资源(如 Pod、Service、Deployment)保持一致。
1.3. 你说得对,但是我们不是已经有一种 CRD 了吗?
1.3.1. 聊聊 AliyunLogConfig
让我们先看一个简单的 AliyunLogConfig 配置示例:
apiVersion: log.alibabacloud.com/v1alpha1
kind: AliyunLogConfig
metadata:
# 设置资源名,在当前Kubernetes集群内唯一。
name: example-k8s-file
namespace: kube-system
spec:
# 【可选】目标project
project: k8s-log-xxxx
# 设置Logstore名称。如果您所指定的Logstore不存在,日志服务会自动创建。
logstore: k8s-file
# 【可选】Logstore shard数
shardCount: 10
# 【可选】Logstore存储时间
lifeCycle: 30
# 【可选】Logstore热存储时间
logstoreHotTTL: 7
# 设置iLogtail采集配置。
logtailConfig:
# 设置采集的数据源类型。采集文本日志时,需设置为file。
inputType: file
# 设置iLogtail采集配置的名称,必须与资源名(metadata.name)相同。
configName: example-k8s-file
inputDetail:
# 指定通过极简模式采集文本日志。
logType: common_reg_log
# 设置日志文件所在路径。
logPath: /data/logs/app_1
# 设置日志文件的名称。支持通配符星号(*)和半角问号(?),例如log_*.log。
filePattern: test.LOG
# 采集容器的文本日志时,需设置dockerFile为true。
dockerFile: true
# 设置容器过滤条件。
advanced:
k8s:
K8sNamespaceRegex: ^(default)$
K8sPodRegex: '^(demo-0.*)$'
K8sContainerRegex: ^(demo)$
IncludeK8sLabel:
job-name: "^(demo.*)$"
AliyunLogConfig 会把 CR 的处理结果反馈到 Status 字段中,内有 statusCode 与 statu 两个字段。
status:
statusCode: 200
status: OK
1.3.2. 英雄迟暮,AliyunLogConfig 的局限性
随着 SLS 不断发展,AliyunLogConfig 的局限性也不断凸显出来。
-
结构混乱 -
SLS 资源描述不清晰,CRD 管理的 SLS 资源有:project,logstore,machingroup,config,这些都平铺在 spec 中。 -
字段值含义不清:例如 Logstore 的属性,有的有 logstore 前缀(logstoreHotTTL),有的没有前缀(shardCount),而且这些参数名与 API 不一致(lifeCycle 与 ttl)。
-
功能不完善 -
资源的 create,update,delete 应该明确统一,project,logstore 相关的配置只有首次创建生效,不允许更新,config 可以更新。 -
多个 CR 指向一个配置,会出现冲突覆盖,尤其是跨集群场景,很容易出现该问题。
全体目光向我看齐, 全新 CRD 来了!
Cloud Native
我们全新的 CRD——AliyunPipelineConfig,来了!
2.1. 你是不知道 AliyunPipelineConfig 的配置有多简洁
AliyunPipelineConfig 的整体结构如下:
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
name: test-config
spec:
project: # 目标project
name: k8s-your-project # project名
uid: 11111 #【选填】账号
endpoint: cn-hangzhou-intranet.log.aliyuncs.com # 【选填】endpoint
logstores: #【选填】需要创建的 logstore 列表,与 CreateLogstore 接口基本一致
- name: your-logstore # logstore名
ttl: 30 #【选填】数据保存时间
shardCount: 10 #【选填】shard 数
... #【选填】其他 Logstore 参数
machineGroups: #【选填】需要与采集配置关联的机器组列表
- name: machine-group-1 # 机器组名
- name: machine-group-2 # 机器组名
config: # 采集配置,格式与 CreateLogtailPipelineConfig 接口基本一致
sample: #【选填】日志样例
global: #【选填】全局配置
inputs: # 输入插件,必须有且只有一个
...
processors: #【选填】处理插件,可以自由组合
...
aggregators: #【选填】聚合插件
...
flushers: # 输出插件,只能有一个flusher_sls
...
enableUpgradeOverride: false #【选填】用于升级 AliyunLogConfig
-
结构清晰 -
按 sls 资源类型分类,有 project、logstore、machineGroup、config。 -
必填项少 -
必填项只有 project.name、config.inputs 和 config.flushers,其他字段都可以灵活填写。 -
贴合 API -
logstore、config 的数据结构、参数命名与 SLS API 一致。
2.1.1. project 字段详解与配置指南
project 字段列表如下:
有一些注意点:
-
project 字段在 CR 创建后无法修改,如果需要切换 project 需要创建新的 CR。 -
name 字段为必填,采集到的日志会发到这里。 -
endpoint 字段仅在有跨地域的需求时填写,否则会默认在集群所在的地域。 -
uid 字段仅在有跨账号的需求时填写,其他场景不用关心这个参数。 -
如果指定的 project 不存在的话,会尝试创建,创建 project 时如果填写了endpoint、uid,则会创建到对应的地域/账号下
2.1.2. config 字段详解与配置指南
config 字段列表如下:
这里需要注意:
-
当前 Inputs 插件列表只支持配置一个(API 层面限制)。 -
当前 Flushers 插件列表只支持配置一个,且只能是 flusher_sls(API 层面限制)。 -
configTags 是打在采集配置上的标签,不是写到日志里的 tag。
2.1.3. logstores 字段详解与配置指南
这里的注意点有:
-
一般场景下创建 Logstore,只需要填写 name 即可,其他参数不必关心,它们的默认值与在控制台创建 Logstore 是一样的。 -
所有的参数仅在创建 Logstore 时有效,已有的 Logstore 不会被该参数修改。
2.1.4. machineGroups 字段详解与配置指南
machineGroups 字段,里面支持配置多个机器组。下面是单个机器组的参数列表:
需要注意:
-
machineGroups 字段默认不需要填写,使用默认的日志组件自动创建的机器组就可以了。 -
已有的机器组的属性不会被覆盖,即原本有一个 ip 机器组叫 a,这里配置 a 的话,不会把 a 机器组改为标识型的。 -
采集配置的机器组会与这里配置的机器组严格一致,如果需要添加机器组,需要编辑这个参数。
2.2. 你只需要填参数就可以,但 AliyunPipelineConfig 要考虑的事情就很多了
相信大家都有遇到过,面对一个不熟悉的配置,乱填一通参数,提交上去,发现又没有成功,又没有报错,整个流程卡死在那了。
AliyunPipelineConfig 不会让你受这样的委屈!你只管填写参数,其他的事情,AliyunPipelineConfig 全兜了!
2.2.1. 假如,我是说假如,你填错了参数格式
AliyunPipelineConfig 具有详细的 CRD 格式规范,同时搭配了 webhook 进行校验,让格式问题无所遁形!
-
CRD 的格式校验由 K8s 进行,保证整体结构不出差错
-
webhook 会校验更细节的 固定参数 的值,例如: -
metadata.name 需要作为采集配置名使用,需要符合采集配置名的要求 -
spec.project.name 需要符合 project 名规范 -
spec.config.inputs 必须要有插件 -
……
2.2.2. 假如,我是说假如,你遇到了报错
虽然有参数值的校验,但参数内容也还是可能填错的,就比如我们的 Logstore,创建的时候参数那么多,难免填错一个;或者,机器组配额超限了,写了一些机器组怎么都创建不出来;或者,填写的 uid 错了,没有获取到跨账号的权限……
这些情况,可以由我们 AliyunPipelineConfig 的 Status 字段,全部展示出来!下面是一段采集配置,在配置时指定错了 project,使用了其他用户的 project,那么这里就会有报错:
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
finalizers:
- finalizer.pipeline.alibabacloud.com
name: example-k8s-file
# 预期的配置
spec:
config:
flushers:
- Endpoint: cn-hangzhou.log.aliyuncs.com
Logstore: k8s-file
Region: cn-hangzhou
TelemetryType: logs
Type: flusher_sls
inputs:
- EnableContainerDiscovery: true
FilePaths:
- /data/logs/app_1/**/test.LOG
Type: input_file
logstores:
- encryptConf: {}
name: k8s-file
project:
name: k8s-log-clusterid
# CR的应用状态
status:
# CR 是否应用成功
success: false
# CR 当前的状态信息,应用失败会展示报错详情
message: |-
{
"httpCode": 401,
"errorCode": "Unauthorized",
"errorMessage": "The project does not belong to you.",
"requestID": "xxxxxx"
}
# 当前 status 的更新时间
lastUpdateTime: '2024-06-19T09:21:34.215702958Z'
# 上次成功应用的配置信息,该配置信息为填充默认值后实际生效的配置。本次没有应用成功,所以这里为空
lastAppliedConfig:
config:
flushers: null
global: null
inputs: null
project:
name: ""
另外,AliyunPipelineConfig 会进行失败重试,如果是临时发生的报错(例如某个project 的 logstore 额度不够,很快调整好了),后续都会重试到正常为止(重试间隔指数增长)。
2.2.3. 假如,我是说假如,你多个配置冲突了
在 AliyunLogConfig 时代,我们可能会遇到这样的问题:一不小心好几个 CR 指向了同一个 project/config,导致整个采集配置被几个 CR 相互覆盖,日志采集被影响。
眼睛:懂了。手:我不会!
Cloud Native
你可能会说了:你 balabala 说了这么一大堆,我好像看懂了但还是不会配置啊!
别急,下面来几个例子,实操练手。
3.1. 经典场景,采集并解析 nginx-ingress 日志
我们现在用 AliyunPipelineConfig 来实现它:
-
下面的 需要替换成你实际的 project -
下面的 需要替换成你的实际 endpoint,例如 cn-hangzhou.log.aliyuncs.com -
下面的
需要替换成你的实际 region,例如 cn-hangzhou
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
name: k8s-nginx-ingress
spec:
# 指定目标 project
project:
name:
logstores:
# 创建 Logstore,用于存储Ingress日志
- name: nginx-ingress
# 产品Code,请勿更改。
productCode: k8s-nginx-ingress
# 添加采集配置
config:
# 定义输入插件
inputs:
# 使用service_docker_stdout插件采集容器内文本日志
- Type: service_docker_stdout
Stdout: true
Stderr: true
# 过滤目标容器,这里是容器label。
IncludeLabel:
io.kubernetes.container.name: nginx-ingress-controller
# 定义解析插件
processors:
- Type: processor_regex
KeepSource: false
Keys:
- client_ip
- x_forward_for
- remote_user
- time
- method
- url