github.com/grafana/pyroscope@v1.18.0/pkg/storegateway/gateway_ring.go (about)

     1  package storegateway
     2  
     3  import (
     4  	"flag"
     5  	"net"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/grafana/dskit/ring"
    11  
    12  	"github.com/grafana/pyroscope/pkg/util"
    13  )
    14  
    15  const (
    16  	// RingKey is the key under which we store the store gateways ring in the KVStore.
    17  	RingKey = "store-gateway"
    18  
    19  	// RingNameForServer is the name of the ring used by the store gateway server.
    20  	RingNameForServer = "store-gateway"
    21  
    22  	// RingNameForClient is the name of the ring used by the store gateway client (we need
    23  	// a different name to avoid clashing Prometheus metrics when running in single-binary).
    24  	RingNameForClient = "store-gateway-client"
    25  
    26  	// We use a safe default instead of exposing to config option to the user
    27  	// in order to simplify the config.
    28  	RingNumTokens = 512
    29  
    30  	// sharedOptionWithRingClient is a message appended to all config options that should be also
    31  	// set on the components running the store-gateway ring client.
    32  	sharedOptionWithRingClient = " This option needs be set both on the store-gateway and querier when running in microservices mode."
    33  )
    34  
    35  var (
    36  	// BlocksOwnerSync is the operation used to check the authoritative owners of a block
    37  	// (replicas included).
    38  	BlocksOwnerSync = ring.NewOp([]ring.InstanceState{ring.JOINING, ring.ACTIVE, ring.LEAVING}, nil)
    39  
    40  	// BlocksOwnerRead is the operation used to check the authoritative owners of a block
    41  	// (replicas included) that are available for queries (a store-gateway is available for
    42  	// queries only when ACTIVE).
    43  	BlocksOwnerRead = ring.NewOp([]ring.InstanceState{ring.ACTIVE}, nil)
    44  
    45  	// BlocksRead is the operation run by the querier to query blocks via the store-gateway.
    46  	BlocksRead = ring.NewOp([]ring.InstanceState{ring.ACTIVE}, func(s ring.InstanceState) bool {
    47  		// Blocks can only be queried from ACTIVE instances. However, if the block belongs to
    48  		// a non-active instance, then we should extend the replication set and try to query it
    49  		// from the next ACTIVE instance in the ring (which is expected to have it because a
    50  		// store-gateway keeps their previously owned blocks until new owners are ACTIVE).
    51  		return s != ring.ACTIVE
    52  	})
    53  )
    54  
    55  type RingConfig struct {
    56  	Ring                 util.CommonRingConfig `yaml:",inline"`
    57  	ReplicationFactor    int                   `yaml:"replication_factor" category:"advanced"`
    58  	TokensFilePath       string                `yaml:"tokens_file_path"`
    59  	ZoneAwarenessEnabled bool                  `yaml:"zone_awareness_enabled"`
    60  
    61  	// Wait ring stability.
    62  	WaitStabilityMinDuration time.Duration `yaml:"wait_stability_min_duration" category:"advanced"`
    63  	WaitStabilityMaxDuration time.Duration `yaml:"wait_stability_max_duration" category:"advanced"`
    64  
    65  	// Instance details
    66  	InstanceZone string `yaml:"instance_availability_zone"`
    67  
    68  	UnregisterOnShutdown bool `yaml:"unregister_on_shutdown"`
    69  
    70  	// Injected internally
    71  	RingCheckPeriod time.Duration `yaml:"-"`
    72  }
    73  
    74  func (cfg *RingConfig) ToRingConfig() ring.Config {
    75  	ringCfg := cfg.Ring.ToRingConfig()
    76  	ringCfg.ReplicationFactor = cfg.ReplicationFactor
    77  	return ringCfg
    78  }
    79  
    80  // RegisterFlags adds the flags required to config this to the given FlagSet
    81  func (cfg *RingConfig) RegisterFlags(f *flag.FlagSet, logger log.Logger) {
    82  	ringFlagsPrefix := "store-gateway.sharding-ring."
    83  
    84  	// Ring flags
    85  	cfg.Ring.RegisterFlags(ringFlagsPrefix, "collectors/", "store-gateways", f, logger)
    86  	f.IntVar(&cfg.ReplicationFactor, ringFlagsPrefix+"replication-factor", 1, "The replication factor to use when sharding blocks."+sharedOptionWithRingClient)
    87  	f.StringVar(&cfg.TokensFilePath, ringFlagsPrefix+"tokens-file-path", "", "File path where tokens are stored. If empty, tokens are not stored at shutdown and restored at startup.")
    88  	f.BoolVar(&cfg.ZoneAwarenessEnabled, ringFlagsPrefix+"zone-awareness-enabled", false, "True to enable zone-awareness and replicate blocks across different availability zones."+sharedOptionWithRingClient)
    89  
    90  	// Wait stability flags.
    91  	f.DurationVar(&cfg.WaitStabilityMinDuration, ringFlagsPrefix+"wait-stability-min-duration", 0, "Minimum time to wait for ring stability at startup, if set to positive value.")
    92  	f.DurationVar(&cfg.WaitStabilityMaxDuration, ringFlagsPrefix+"wait-stability-max-duration", 5*time.Minute, "Maximum time to wait for ring stability at startup. If the store-gateway ring keeps changing after this period of time, the store-gateway will start anyway.")
    93  
    94  	// Instance flags
    95  	f.StringVar(&cfg.InstanceZone, ringFlagsPrefix+"instance-availability-zone", "", "The availability zone where this instance is running. Required if zone-awareness is enabled.")
    96  
    97  	f.BoolVar(&cfg.UnregisterOnShutdown, ringFlagsPrefix+"unregister-on-shutdown", true, "Unregister from the ring upon clean shutdown.")
    98  
    99  	// Defaults for internal settings.
   100  	cfg.RingCheckPeriod = 5 * time.Second
   101  }
   102  
   103  func (cfg *RingConfig) ToLifecyclerConfig(logger log.Logger) (ring.BasicLifecyclerConfig, error) {
   104  	instanceAddr, err := ring.GetInstanceAddr(cfg.Ring.InstanceAddr, cfg.Ring.InstanceInterfaceNames, logger, cfg.Ring.EnableIPv6)
   105  	if err != nil {
   106  		return ring.BasicLifecyclerConfig{}, err
   107  	}
   108  
   109  	instancePort := ring.GetInstancePort(cfg.Ring.InstancePort, cfg.Ring.ListenPort)
   110  
   111  	return ring.BasicLifecyclerConfig{
   112  		ID:                              cfg.Ring.InstanceID,
   113  		Addr:                            net.JoinHostPort(instanceAddr, strconv.Itoa(instancePort)),
   114  		Zone:                            cfg.InstanceZone,
   115  		HeartbeatPeriod:                 cfg.Ring.HeartbeatPeriod,
   116  		HeartbeatTimeout:                cfg.Ring.HeartbeatTimeout,
   117  		TokensObservePeriod:             0,
   118  		NumTokens:                       RingNumTokens,
   119  		KeepInstanceInTheRingOnShutdown: !cfg.UnregisterOnShutdown,
   120  	}, nil
   121  }