0
点赞
收藏
分享

微信扫一扫

grafana agent 动态配置内部机制简单说明

沈芏 2022-11-13 阅读 77

grafana agent 动态配置目前属于一个体验特性,但是设计上利用了gomplate 一个强大的模版引擎工具

参考配置

  • 运行配置参考

agentv2:

image: grafana/agent:main

ports:

- 12345:12345

- 12347:12347

entrypoint:

- /bin/agent

- -config.file.type=dynamic

- -server.http.address=0.0.0.0:12345

- -config.file=file:///etc/agent-config/agent.yaml # 动态配置默认加载地址

- -metrics.wal-directory=/tmp/agent/wal

- -enable-features=dynamic-config,integrations-next # 需要开启的特性

- -config.enable-read-api

volumes:

- ./agentv2.yaml:/etc/agent-config/agent.yaml

- ./agent-data:/etc/agent/data

- ./confs:/opt/confs # 挂载的配置文件

- ./logs:/var/log

  • 配置参考
    比如metrics ,需要移除metrics

 

global:

scrape_interval: 10s

remote_write:

- url: http://victoriametrics:8428/api/v1/write

configs:

- name: default

scrape_configs:

- job_name: avalanche

static_configs:

- targets: ['${AVALANCHE_HOST:-localhost:9001}']

log 配置

configs:

- name: default

positions:

filename: /tmp/positions.yaml

scrape_configs:

- job_name: varlogs

static_configs:

- targets: [localhost]

labels:

job: varlogs

__path__: /var/log/*log

clients:

- url: http://loki:3100/loki/api/v1/push

filter 配置 (agentv2.yaml)

template_paths:

- file:///opt/confs # 基于文件格式

# Filters allow you to override the default naming convention

 

agent_filter:            "agent-*.yml" # defaults to agent-*.yml

server_filter:           "server-*.yml" # defaults to server-*.yml

metrics_filter:          "metrics-*.yml" # defaults to metrics-*.yml

#metrics_instance_filter: string # defaults to metrics_instances-*.yml

integrations_filter:     "integrations-*.yml" # defaults to integrations-*.yml

logs_filter:             "logs-*.yml" # defaults to logs-*.yml

traces_filter:           "traces-*.yml" # defaults to traces-*.yml

内部机制

grafana agent 动态配置实际上上利用了gomplate,但是目前来说似乎只能是第一次加载的时候,并不能实时reload
处理机制上核心是开发的一些filter,如果需要加载其他数据源推荐配置datasource,默认可以通过本地文件
filter 处理部分

 

// ProcessConfigs loads the configurations in a predetermined order to handle functioning correctly.

func (c *DynamicLoader) ProcessConfigs(cfg *Config) error {

if c.cfg == nil {

return fmt.Errorf("LoadConfig or LoadConfigByPath must be called")

}

var returnErr error

 

err := c.processAgent(cfg)

returnErr = errorAppend(returnErr, err)

 

serverConfig, err := c.processServer()

returnErr = errorAppend(returnErr, err)

if serverConfig != nil {

cfg.Server = *serverConfig

}

 

metricConfig, err := c.processMetrics()

returnErr = errorAppend(returnErr, err)

if metricConfig != nil {

cfg.Metrics = *metricConfig

}

 

instancesConfigs, err := c.processMetricInstances()

returnErr = errorAppend(returnErr, err)

cfg.Metrics.Configs = append(cfg.Metrics.Configs, instancesConfigs...)

 

logsCfg, err := c.processLogs()

returnErr = errorAppend(returnErr, err)

if logsCfg != nil {

cfg.Logs = logsCfg

}

 

traceConfigs, err := c.processTraces()

returnErr = errorAppend(returnErr, err)

if traceConfigs != nil {

cfg.Traces = *traceConfigs

}

 

integrations, err := c.processIntegrations()

returnErr = errorAppend(returnErr, err)

 

cfg.Integrations.ExtraIntegrations = append(cfg.Integrations.ExtraIntegrations, integrations...)

 

return returnErr

}

不同filter 处理(log 参考)

func (c *DynamicLoader) processLogs() (*logs.Config, error) {

var returnError error

found := 0

var cfg *logs.Config

// 基于配置的模版进行模版数据的处理

for _, path := range c.cfg.TemplatePaths {

filesContents, err := c.retrieveMatchingFileContents(path, c.cfg.LogsFilter, "logs")

returnError = errorAppend(returnError, err)

found = len(filesContents) + found

if len(filesContents) == 1 {

cfg = &logs.Config{}

err = yaml.Unmarshal([]byte(filesContents[0]), cfg)

returnError = errorAppend(returnError, err)

}

}

// 只支持一个文件,实际上官方文档也说明了log 只支持一个

if found > 1 {

returnError = errorAppend(returnError, fmt.Errorf("found %d logs templates; expected 0 or 1", found))

}

return cfg, returnError

}

datasource 的加载(基于了gomplate的能力)

// DynamicLoader is used to load configs from a variety of sources and squash them together.

// This is used by the dynamic configuration feature to load configurations from a set of templates and then run them through

// gomplate producing an end result.

type DynamicLoader struct {

loader *loader.ConfigLoader

mux    fsimpl.FSMux

cfg    *LoaderConfig

}

 

// NewDynamicLoader instantiates a new DynamicLoader.

func NewDynamicLoader() (*DynamicLoader, error) {

// 此处基于了hairyhenderson 提供的vfs 能力,目前只支持本地以及对象存储文件,实际上hairyhenderson/go-fsimpl 还提供其他费事(git,http。。。。)

return &DynamicLoader{

mux: newFSProvider(),

}, nil

}

 

// LoadConfig loads an already created LoaderConfig into the DynamicLoader.

func (c *DynamicLoader) LoadConfig(cfg LoaderConfig) error {

sources := make(map[string]*data.Source)

for _, v := range cfg.Sources {

sourceURL, err := url.Parse(v.URL)

if err != nil {

return err

}

sources[v.Name] = &data.Source{

URL:   sourceURL,

Alias: v.Name,

}

}

// Set Defaults

if cfg.IntegrationsFilter == "" {

cfg.IntegrationsFilter = "integrations-*.yml"

}

if cfg.AgentFilter == "" {

cfg.AgentFilter = "agent-*.yml"

}

if cfg.ServerFilter == "" {

cfg.ServerFilter = "server-*.yml"

}

if cfg.MetricsFilter == "" {

cfg.MetricsFilter = "metrics-*.yml"

}

if cfg.MetricsInstanceFilter == "" {

cfg.MetricsInstanceFilter = "metrics_instances-*.yml"

}

if cfg.LogsFilter == "" {

cfg.LogsFilter = "logs-*.yml"

}

if cfg.TracesFilter == "" {

cfg.TracesFilter = "traces-*.yml"

}

cl := loader.NewConfigLoader(context.Background(), sources)

c.loader = cl

c.cfg = &cfg

return nil

}

说明

以上是一个简单的说明,详细的可以多看看源码

参考资料

​​https://github.com/grafana/agent/blob/987c214431af8abae7e13468468b99d21d2df3e3/pkg/config​​​
​​​https://github.com/hairyhenderson/gomplate​​​
​​​https://grafana.com/docs/agent/latest/configuration/dynamic-config/​​

举报

相关推荐

0 条评论