github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/alertmanager_ring.go (about)

     1  package alertmanager
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/go-kit/log/level"
    11  	"github.com/grafana/dskit/flagext"
    12  	"github.com/grafana/dskit/kv"
    13  	"github.com/grafana/dskit/ring"
    14  
    15  	util_log "github.com/cortexproject/cortex/pkg/util/log"
    16  )
    17  
    18  const (
    19  	// RingKey is the key under which we store the alertmanager ring in the KVStore.
    20  	RingKey = "alertmanager"
    21  
    22  	// RingNameForServer is the name of the ring used by the alertmanager server.
    23  	RingNameForServer = "alertmanager"
    24  
    25  	// RingNumTokens is a safe default instead of exposing to config option to the user
    26  	// in order to simplify the config.
    27  	RingNumTokens = 128
    28  )
    29  
    30  // RingOp is the operation used for reading/writing to the alertmanagers.
    31  var RingOp = ring.NewOp([]ring.InstanceState{ring.ACTIVE}, func(s ring.InstanceState) bool {
    32  	// Only ACTIVE Alertmanager get requests. If instance is not ACTIVE, we need to find another Alertmanager.
    33  	return s != ring.ACTIVE
    34  })
    35  
    36  // SyncRingOp is the operation used for checking if a user is owned by an alertmanager.
    37  var SyncRingOp = ring.NewOp([]ring.InstanceState{ring.ACTIVE, ring.JOINING}, func(s ring.InstanceState) bool {
    38  	return s != ring.ACTIVE
    39  })
    40  
    41  // RingConfig masks the ring lifecycler config which contains
    42  // many options not really required by the alertmanager ring. This config
    43  // is used to strip down the config to the minimum, and avoid confusion
    44  // to the user.
    45  type RingConfig struct {
    46  	KVStore              kv.Config     `yaml:"kvstore" doc:"description=The key-value store used to share the hash ring across multiple instances."`
    47  	HeartbeatPeriod      time.Duration `yaml:"heartbeat_period"`
    48  	HeartbeatTimeout     time.Duration `yaml:"heartbeat_timeout"`
    49  	ReplicationFactor    int           `yaml:"replication_factor"`
    50  	ZoneAwarenessEnabled bool          `yaml:"zone_awareness_enabled"`
    51  
    52  	// Instance details
    53  	InstanceID             string   `yaml:"instance_id" doc:"hidden"`
    54  	InstanceInterfaceNames []string `yaml:"instance_interface_names"`
    55  	InstancePort           int      `yaml:"instance_port" doc:"hidden"`
    56  	InstanceAddr           string   `yaml:"instance_addr" doc:"hidden"`
    57  	InstanceZone           string   `yaml:"instance_availability_zone"`
    58  
    59  	// Injected internally
    60  	ListenPort      int           `yaml:"-"`
    61  	RingCheckPeriod time.Duration `yaml:"-"`
    62  
    63  	// Used for testing
    64  	SkipUnregister bool `yaml:"-"`
    65  }
    66  
    67  // RegisterFlags adds the flags required to config this to the given FlagSet
    68  func (cfg *RingConfig) RegisterFlags(f *flag.FlagSet) {
    69  	hostname, err := os.Hostname()
    70  	if err != nil {
    71  		level.Error(util_log.Logger).Log("msg", "failed to get hostname", "err", err)
    72  		os.Exit(1)
    73  	}
    74  
    75  	// Prefix used by all the ring flags
    76  	rfprefix := "alertmanager.sharding-ring."
    77  
    78  	// Ring flags
    79  	cfg.KVStore.RegisterFlagsWithPrefix(rfprefix, "alertmanagers/", f)
    80  	f.DurationVar(&cfg.HeartbeatPeriod, rfprefix+"heartbeat-period", 15*time.Second, "Period at which to heartbeat to the ring. 0 = disabled.")
    81  	f.DurationVar(&cfg.HeartbeatTimeout, rfprefix+"heartbeat-timeout", time.Minute, "The heartbeat timeout after which alertmanagers are considered unhealthy within the ring. 0 = never (timeout disabled).")
    82  	f.IntVar(&cfg.ReplicationFactor, rfprefix+"replication-factor", 3, "The replication factor to use when sharding the alertmanager.")
    83  	f.BoolVar(&cfg.ZoneAwarenessEnabled, rfprefix+"zone-awareness-enabled", false, "True to enable zone-awareness and replicate alerts across different availability zones.")
    84  
    85  	// Instance flags
    86  	cfg.InstanceInterfaceNames = []string{"eth0", "en0"}
    87  	f.Var((*flagext.StringSlice)(&cfg.InstanceInterfaceNames), rfprefix+"instance-interface-names", "Name of network interface to read address from.")
    88  	f.StringVar(&cfg.InstanceAddr, rfprefix+"instance-addr", "", "IP address to advertise in the ring.")
    89  	f.IntVar(&cfg.InstancePort, rfprefix+"instance-port", 0, "Port to advertise in the ring (defaults to server.grpc-listen-port).")
    90  	f.StringVar(&cfg.InstanceID, rfprefix+"instance-id", hostname, "Instance ID to register in the ring.")
    91  	f.StringVar(&cfg.InstanceZone, rfprefix+"instance-availability-zone", "", "The availability zone where this instance is running. Required if zone-awareness is enabled.")
    92  
    93  	cfg.RingCheckPeriod = 5 * time.Second
    94  }
    95  
    96  // ToLifecyclerConfig returns a LifecyclerConfig based on the alertmanager
    97  // ring config.
    98  func (cfg *RingConfig) ToLifecyclerConfig(logger log.Logger) (ring.BasicLifecyclerConfig, error) {
    99  	instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger)
   100  	if err != nil {
   101  		return ring.BasicLifecyclerConfig{}, err
   102  	}
   103  
   104  	instancePort := ring.GetInstancePort(cfg.InstancePort, cfg.ListenPort)
   105  
   106  	return ring.BasicLifecyclerConfig{
   107  		ID:                  cfg.InstanceID,
   108  		Addr:                fmt.Sprintf("%s:%d", instanceAddr, instancePort),
   109  		HeartbeatPeriod:     cfg.HeartbeatPeriod,
   110  		TokensObservePeriod: 0,
   111  		Zone:                cfg.InstanceZone,
   112  		NumTokens:           RingNumTokens,
   113  	}, nil
   114  }
   115  
   116  func (cfg *RingConfig) ToRingConfig() ring.Config {
   117  	rc := ring.Config{}
   118  	flagext.DefaultValues(&rc)
   119  
   120  	rc.KVStore = cfg.KVStore
   121  	rc.HeartbeatTimeout = cfg.HeartbeatTimeout
   122  	rc.ReplicationFactor = cfg.ReplicationFactor
   123  	rc.ZoneAwarenessEnabled = cfg.ZoneAwarenessEnabled
   124  
   125  	return rc
   126  }