log-pilotは、動的スケーリングや動的構成などの機能を備えた、Alibabaのオープンソースコンテナログ収集プロジェクトです。そのコア原則は次のとおりです。Dockerイベントを監視し、filebeat / fluentdを自動的に構成および再ロードして、コンテナーの動的スケジューリングによるログ収集と自動スケーリングの効果を実現します。
プロジェクト全体の中核は次のとおりです。
政治構造
Politerインターフェース
政治
主にDockerコンテナイベントを監視し、コンテナログマウントディレクトリ、タグ、環境変数などの情報を取得し、filebeat / fluentd構成ファイルを動的に生成します
type Pilot struct { piloter Piloter //パイロット関連の mutexsync.Mutex //同時ロック、複数のコンテナーイベントがトリガーされ、最初にロックを取得した人、 テンプレートを処理した人* template.Template //ログコレクションクライアント構成ファイルテンプレート、log -pilot golangのテキスト/テンプレートモジュールを使用して、構成ファイル クライアントをレンダリングします* k8s.Client // dockerコンテナクライアント、 dockerイベントインターフェイスを介して関連するコンテナ情報を取得しますapi lastReload time.Time //最後の構成ファイルのリロード時間 reloadChanchan bool //リロード通知chan stopChan chan bool //通知を停止し ますchanbaseDir string //ホスト上の dockerlogPrefix [] string //環境変数が始まる文字を定義して、アプリケーションログが配置されているディレクトリを示し。log-pilotはで始まります環境変数を構成して、各コンテナー内のアプリケーションのログパスの場所を構成します Dockerデータの保存場所createSymlinkbool //収集するログファイルを関連付けるハードリンクを作成するかどうか }
ポリター Politerは、収集ツールが操作する必要のあるいくつかのメソッドを定義し、主に収集ツールの有効化、停止、および再読み込みの特定の操作を担当します。
type Piloter interface { Name()string // "filebeat"と "fluentd"は、それぞれ異なる収集ツール を示しますStart()エラー//収集ツールを開始します Reload()エラー//構成ファイルをリロードします Stop()エラー//収集を停止しますtool GetBaseConf()string // filebeatの/ etc / filebeatなどのログコレクションクライアント構成ファイルの場所 GetConfHome()string // filebeatのprospectors.dの場所などのログコレクションクライアント統合構成ファイルディレクトリ GetConfPath(container string)string //特定の構成ファイルパス OnDestroyEvent(container string)エラー//コンテナ停止イベントをリッスンします } |
メイン機能
プログラムエントリ、コマンドライン処理:ログ収集構成テンプレートの指定、ログパイロットログレベル構成など。
Plot.Run
- Politデータを初期化します。Politには、対応するfilebeat / fluentd構成テンプレート、dokcerクライアント、同時実行ロック、パイロットオブジェクトなどが含まれます。
- コンテナイベントモニタリングをオンにする
func Run(templ string, baseDir string) error { p, err := New(templ, baseDir) .... return p.watch() }
|
Pilot.watch
- 使用 docker api 连接 docker,并watch docker 事件
func (p *Pilot) watch() error { .... err := p.piloter.Start() // 启动收集工具 .... msgs, errs := p.client.Events(ctx, options) // 接受 docker 事件,返回 chan go func() { .... for { // 无限循环获取事件 select { case msg := <-msgs: if err := p.processEvent(msg); err != nil { // 处理 docker 事件 log.Errorf("fail to process event: %v, %v", msg, err) } ........ } }() .... }
|
Pilot.processEvent
docker event 的handler函数
func (p *Pilot) processEvent(msg events.Message) error { .... switch msg.Action { case "start", "restart": .... return p.newContainer(&containerJSON) case "destroy", "die": .... err := p.delContainer(containerId) return nil }
Pilot.newContainer
处理环境变量/tag标签/mount
渲染配置文键模板,生成新的配置文件并reload生效
func (p *Pilot) newContainer(containerJSON *types.ContainerJSON) error { .... // containerJSON 是 docker接口 Client.ContainerInspect 返回的数据类型 container := container(containerJSON) for _, e := range env { // 处理环境变量, env由containerJSON 得到 ..... } // 获取配置文件模板数据 logConfigs, err := p.getLogConfigs(jsonLogPath, mounts, labels) if err != nil { return err } .... // 关联 docker 容器中应用日志文件或目录 p.createVolumeSymlink(containerJSON) // 渲染配置文件模板数据,生成具体的配置文件 logConfig, err := p.render(id, container, logConfigs) if err != nil { return err } //TODO validate config before save //log.Debugf("container %s log config: %s", id, logConfig) if err = ioutil.WriteFile(p.piloter.GetConfPath(id), []byte(logConfig), os.FileMode(0644)); err != nil { return err } // 重载配置文件 p.tryReload() return nil }
|
Pilot.delContainer
- 渲染配置文键模板,删除配置文件
reload 配置文件
func (p *Pilot) delContainer(id string) error { p.removeVolumeSymlink(id) //fixme refactor in the future if p.piloter.Name() == PILOT_FLUENTD { clean := func() { log.Infof("Try removing log config %s", id) if err := os.Remove(p.piloter.GetConfPath(id)); err != nil { log.Warnf("removing %s log config failure", id) return } p.tryReload() } time.AfterFunc(15*time.Minute, clean) return nil } return p.piloter.OnDestroyEvent(id) }
LogConfig
动态渲染配置文件模板数据集
type LogConfig struct { Name string // 日志名 HostDir string // 日志文件在宿主机上的目录 ContainerDir string // 容器应用日志目录 Format string FormatConfig map[string]string File string // 具体的日志文件名 Tags map[string]string // 标签数据 Target string // 索引或者kafka主题 EstimateTime bool Stdout bool CustomFields map[string]string // 自定义添加日志字段 CustomConfigs map[string]string // 自定义配置文件项 }
|
getLogConfigs
- 获取配置文件模板渲染数据
parseLogConfig
- 接续容器数据获得配置文件模板渲染数据
最终生成的filebeat 配置文件
- type: log enabled: true paths: - /host/var/lib/docker/containers/b61b94c9f38eec70df32d45df408ea09ad05987bf4ff92d5d5f2eae3fd9e503d/b61b94c9f38eec70df32d45df408ea09ad05987bf4ff92d5d5f2eae3fd9e503d-json.log* scan_frequency: 10s fields_under_root: true docker-json: true fields: index: aaa-test topic: aaa-test docker_container: k8s_tomcat_tomcat_default_6cc39a2f-2a2b-45a2-94d8-a51faf68dd14_0 k8s_container_name: tomcat k8s_node_name: cn-hangzhou.172.16.179.195 k8s_pod: tomcat k8s_pod_namespace: default tail_files: false close_inactive: 2h close_eof: false close_removed: true clean_removed: true close_renamed: false |