github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/ring_config.go (about) 1 package util 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 "time" 8 9 "github.com/go-kit/log" 10 11 "github.com/go-kit/log/level" 12 "github.com/grafana/dskit/flagext" 13 "github.com/grafana/dskit/kv" 14 "github.com/grafana/dskit/netutil" 15 "github.com/grafana/dskit/ring" 16 17 util_log "github.com/grafana/loki/pkg/util/log" 18 ) 19 20 // RingConfig masks the ring lifecycler config which contains 21 // many options not really required by the distributors ring. This config 22 // is used to strip down the config to the minimum, and avoid confusion 23 // to the user. 24 type RingConfig struct { 25 KVStore kv.Config `yaml:"kvstore"` 26 HeartbeatPeriod time.Duration `yaml:"heartbeat_period"` 27 HeartbeatTimeout time.Duration `yaml:"heartbeat_timeout"` 28 TokensFilePath string `yaml:"tokens_file_path"` 29 ZoneAwarenessEnabled bool `yaml:"zone_awareness_enabled"` 30 31 // Instance details 32 InstanceID string `yaml:"instance_id"` 33 InstanceInterfaceNames []string `yaml:"instance_interface_names" doc:"default=[<private network interfaces>]"` 34 InstancePort int `yaml:"instance_port"` 35 InstanceAddr string `yaml:"instance_addr"` 36 InstanceZone string `yaml:"instance_availability_zone"` 37 38 // Injected internally 39 ListenPort int `yaml:"-"` 40 41 ObservePeriod time.Duration `yaml:"-"` 42 } 43 44 // RegisterFlagsWithPrefix adds the flags required to config this to the given FlagSet 45 // storePrefix is used to set the path in the KVStore and should end with a / 46 func (cfg *RingConfig) RegisterFlagsWithPrefix(flagsPrefix, storePrefix string, f *flag.FlagSet) { 47 hostname, err := os.Hostname() 48 if err != nil { 49 level.Error(util_log.Logger).Log("msg", "failed to get hostname", "err", err) 50 os.Exit(1) 51 } 52 53 // Ring flags 54 cfg.KVStore.RegisterFlagsWithPrefix(flagsPrefix+"ring.", storePrefix, f) 55 f.DurationVar(&cfg.HeartbeatPeriod, flagsPrefix+"ring.heartbeat-period", 15*time.Second, "Period at which to heartbeat to the ring. 0 = disabled.") 56 f.DurationVar(&cfg.HeartbeatTimeout, flagsPrefix+"ring.heartbeat-timeout", time.Minute, "The heartbeat timeout after which compactors are considered unhealthy within the ring. 0 = never (timeout disabled).") 57 f.StringVar(&cfg.TokensFilePath, flagsPrefix+"ring.tokens-file-path", "", "File path where tokens are stored. If empty, tokens are not stored at shutdown and restored at startup.") 58 f.BoolVar(&cfg.ZoneAwarenessEnabled, flagsPrefix+"ring.zone-awareness-enabled", false, "True to enable zone-awareness and replicate blocks across different availability zones.") 59 60 // Instance flags 61 cfg.InstanceInterfaceNames = netutil.PrivateNetworkInterfacesWithFallback([]string{"eth0", "en0"}, util_log.Logger) 62 f.Var((*flagext.StringSlice)(&cfg.InstanceInterfaceNames), flagsPrefix+"ring.instance-interface-names", "Name of network interface to read address from.") 63 f.StringVar(&cfg.InstanceAddr, flagsPrefix+"ring.instance-addr", "", "IP address to advertise in the ring.") 64 f.IntVar(&cfg.InstancePort, flagsPrefix+"ring.instance-port", 0, "Port to advertise in the ring (defaults to server.grpc-listen-port).") 65 f.StringVar(&cfg.InstanceID, flagsPrefix+"ring.instance-id", hostname, "Instance ID to register in the ring.") 66 f.StringVar(&cfg.InstanceZone, flagsPrefix+"ring.instance-availability-zone", "", "The availability zone where this instance is running. Required if zone-awareness is enabled.") 67 } 68 69 // ToLifecyclerConfig returns a LifecyclerConfig based on the compactor ring config. 70 func (cfg *RingConfig) ToLifecyclerConfig(numTokens int, logger log.Logger) (ring.BasicLifecyclerConfig, error) { 71 instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger) 72 if err != nil { 73 return ring.BasicLifecyclerConfig{}, err 74 } 75 76 instancePort := ring.GetInstancePort(cfg.InstancePort, cfg.ListenPort) 77 78 return ring.BasicLifecyclerConfig{ 79 ID: cfg.InstanceID, 80 Addr: fmt.Sprintf("%s:%d", instanceAddr, instancePort), 81 Zone: cfg.InstanceZone, 82 HeartbeatPeriod: cfg.HeartbeatPeriod, 83 TokensObservePeriod: 0, 84 NumTokens: numTokens, 85 }, nil 86 } 87 88 func CortexLifecyclerConfigToRingConfig(cfg ring.LifecyclerConfig) RingConfig { 89 return RingConfig{ 90 KVStore: kv.Config{ 91 Store: cfg.RingConfig.KVStore.Store, 92 Prefix: cfg.RingConfig.KVStore.Prefix, 93 StoreConfig: cfg.RingConfig.KVStore.StoreConfig, 94 }, 95 HeartbeatPeriod: cfg.HeartbeatPeriod, 96 HeartbeatTimeout: cfg.RingConfig.HeartbeatTimeout, 97 TokensFilePath: cfg.TokensFilePath, 98 ZoneAwarenessEnabled: cfg.RingConfig.ZoneAwarenessEnabled, 99 InstanceID: cfg.ID, 100 InstanceInterfaceNames: cfg.InfNames, 101 InstancePort: cfg.Port, 102 InstanceAddr: cfg.Addr, 103 InstanceZone: cfg.Zone, 104 ListenPort: cfg.ListenPort, 105 ObservePeriod: cfg.ObservePeriod, 106 } 107 } 108 109 func (cfg *RingConfig) ToRingConfig(replicationFactor int) ring.Config { 110 rc := ring.Config{} 111 flagext.DefaultValues(&rc) 112 113 rc.KVStore = cfg.KVStore 114 rc.HeartbeatTimeout = cfg.HeartbeatTimeout 115 rc.ZoneAwarenessEnabled = cfg.ZoneAwarenessEnabled 116 rc.ReplicationFactor = replicationFactor 117 118 return rc 119 }