Log-Pilot 源码简析
简单介绍
Log-Pilot是阿里开源的一款容器日志收集项目,他的基本流程是动态监听容器的事件变化,然后依据容器的标签来进行解析,然后生成filebeat/fluentd
的配置文件交由filebeat/fluentd
采集插件来进行日志采集,来达到日志收集随容器的动态调度而自动伸缩的效果。
源码简析
Pilot结构体
- 主要监听
docker
容器事件并获取容器日志挂载目录、标签、环境变量等信息,动态生成filebeat/fluentd
配置文件
// Pilot entry point
type Pilot struct {
piloter Piloter // Piloter 相关
mutex sync.Mutex // 并发锁,多个容器事件触发,谁先抢到锁,谁先处理
templ *template.Template // 日志采集客户端配置文件模板,log-pilot 使用 golang 的 text/template 模块渲染配置文件
client *k8s.Client // docker 容器客户端,通过docker 事件接口 api 获取相关容器信息
lastReload time.Time // 最后一次配置文件重载时间
reloadChan chan bool // 重载通知 chan
stopChan chan bool // 停止通知 chan
baseDir string // docker 在宿主机上面的数据存储位置
logPrefix []string // 定义环境变量以什么字符开头来表示应用日志所在目录,log-pilot 以配置环境变量的方式配置定每个容器中应用程序的日志路径位置,默认为aliyun
createSymlink bool // 是否创建硬连接的方式关联要搜集的日志文件
}
Piloter接口
log-pilot
支持filebeat
和fluentd
两种日志收集器。 Piloter定义了收集器需要操作的一些方法,主要负责收集工具的启用、停止、重载的具体操作。
type Piloter interface {
Name() string // "filebeat" 与 "fluentd",分别表示不同的搜集工具
Start() error // 启动搜集工具
Reload() error // 重载配置文件
Stop() error // 停止搜集工具
GetBaseConf() string // 日志采集客户端配置文件位置,如 filebeat 的 /etc/filebeat
GetConfHome() string // 日志采集客户端统一配置文件目录,如 filebeat 的 prospectors.d 位置
GetConfPath(container string) string // 具体配置文件路径
OnDestroyEvent(container string) error // 监听容器停止事件
}
main函数
- 程序的入口、命令行处理:指定日志收集配置模板、收集日志等级、Docker日志路径等。
- [
pilot.Run
]( # Pilot.Run) 启动程序
func main() {
// 指定配置模板
template := flag.String("template", "", "Template filepath for fluentd or filebeat.")
// 指定docker日志所在目录
base := flag.String("base", "", "Directory which mount host root.")
// 指定收集日志等级
level := flag.String("log-level", "INFO", "Log level")
// ....
// 读取模板文件
b, err := ioutil.ReadFile(*template)
// 启动程序入口
log.Fatal(pilot.Run(string(b), baseDir))
}
Pilot.Run
- [
pilot.New
](# pilot.New) 初始化 Pilot 数据,Polit 中包含了对应filebeat/fluentd
配置模版、dokcer client
、并发锁、piloter
对象等 - [
pilot.watch
](# pilot.watch) 开启容器事件监控
func Run(templ string, baseDir string) error {
// 初始化Pilot数据
p, err := New(templ, baseDir)
if err != nil {
panic(err)
}
// 开启监听
return p.watch()
}
Pilot.New
- 初始化Pilot数据
func New(tplStr string, baseDir string) (*Pilot, error) {