github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  
    11  	log "github.com/hashicorp/go-hclog"
    12  	"github.com/hashicorp/nomad/client/state"
    13  	"github.com/hashicorp/nomad/helper"
    14  	"github.com/hashicorp/nomad/helper/pluginutils/loader"
    15  	"github.com/hashicorp/nomad/nomad/structs"
    16  	structsc "github.com/hashicorp/nomad/nomad/structs/config"
    17  	"github.com/hashicorp/nomad/plugins/base"
    18  	"github.com/hashicorp/nomad/version"
    19  )
    20  
    21  var (
    22  	// DefaultEnvDenylist is the default set of environment variables that are
    23  	// filtered when passing the environment variables of the host to a task.
    24  	// duplicated in command/agent/host, update that if this changes.
    25  	DefaultEnvDenylist = strings.Join([]string{
    26  		"CONSUL_TOKEN",
    27  		"CONSUL_HTTP_TOKEN",
    28  		"VAULT_TOKEN",
    29  		"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN",
    30  		"GOOGLE_APPLICATION_CREDENTIALS",
    31  	}, ",")
    32  
    33  	// DefaultUserDenylist is the default set of users that tasks are not
    34  	// allowed to run as when using a driver in "user.checked_drivers"
    35  	DefaultUserDenylist = strings.Join([]string{
    36  		"root",
    37  		"Administrator",
    38  	}, ",")
    39  
    40  	// DefaultUserCheckedDrivers is the set of drivers we apply the user
    41  	// denylist onto. For virtualized drivers it often doesn't make sense to
    42  	// make this stipulation so by default they are ignored.
    43  	DefaultUserCheckedDrivers = strings.Join([]string{
    44  		"exec",
    45  		"qemu",
    46  		"java",
    47  	}, ",")
    48  
    49  	// A mapping of directories on the host OS to attempt to embed inside each
    50  	// task's chroot.
    51  	DefaultChrootEnv = map[string]string{
    52  		"/bin":            "/bin",
    53  		"/etc":            "/etc",
    54  		"/lib":            "/lib",
    55  		"/lib32":          "/lib32",
    56  		"/lib64":          "/lib64",
    57  		"/run/resolvconf": "/run/resolvconf",
    58  		"/sbin":           "/sbin",
    59  		"/usr":            "/usr",
    60  
    61  		// embed systemd-resolved paths for systemd-resolved paths:
    62  		// /etc/resolv.conf is a symlink to /run/systemd/resolve/stub-resolv.conf in such systems.
    63  		// In non-systemd systems, this mount is a no-op and the path is ignored if not present.
    64  		"/run/systemd/resolve": "/run/systemd/resolve",
    65  	}
    66  )
    67  
    68  // RPCHandler can be provided to the Client if there is a local server
    69  // to avoid going over the network. If not provided, the Client will
    70  // maintain a connection pool to the servers
    71  type RPCHandler interface {
    72  	RPC(method string, args interface{}, reply interface{}) error
    73  }
    74  
    75  // Config is used to parameterize and configure the behavior of the client
    76  type Config struct {
    77  	// DevMode controls if we are in a development mode which
    78  	// avoids persistent storage.
    79  	DevMode bool
    80  
    81  	// EnableDebug is used to enable debugging RPC endpoints
    82  	// in the absence of ACLs
    83  	EnableDebug bool
    84  
    85  	// StateDir is where we store our state
    86  	StateDir string
    87  
    88  	// AllocDir is where we store data for allocations
    89  	AllocDir string
    90  
    91  	// LogOutput is the destination for logs
    92  	LogOutput io.Writer
    93  
    94  	// Logger provides a logger to thhe client
    95  	Logger log.InterceptLogger
    96  
    97  	// Region is the clients region
    98  	Region string
    99  
   100  	// Network interface to be used in network fingerprinting
   101  	NetworkInterface string
   102  
   103  	// Network speed is the default speed of network interfaces if they can not
   104  	// be determined dynamically.
   105  	NetworkSpeed int
   106  
   107  	// CpuCompute is the default total CPU compute if they can not be determined
   108  	// dynamically. It should be given as Cores * MHz (2 Cores * 2 Ghz = 4000)
   109  	CpuCompute int
   110  
   111  	// MemoryMB is the default node total memory in megabytes if it cannot be
   112  	// determined dynamically.
   113  	MemoryMB int
   114  
   115  	// MaxKillTimeout allows capping the user-specifiable KillTimeout. If the
   116  	// task's KillTimeout is greater than the MaxKillTimeout, MaxKillTimeout is
   117  	// used.
   118  	MaxKillTimeout time.Duration
   119  
   120  	// Servers is a list of known server addresses. These are as "host:port"
   121  	Servers []string
   122  
   123  	// RPCHandler can be provided to avoid network traffic if the
   124  	// server is running locally.
   125  	RPCHandler RPCHandler
   126  
   127  	// Node provides the base node
   128  	Node *structs.Node
   129  
   130  	// ClientMaxPort is the upper range of the ports that the client uses for
   131  	// communicating with plugin subsystems over loopback
   132  	ClientMaxPort uint
   133  
   134  	// ClientMinPort is the lower range of the ports that the client uses for
   135  	// communicating with plugin subsystems over loopback
   136  	ClientMinPort uint
   137  
   138  	// A mapping of directories on the host OS to attempt to embed inside each
   139  	// task's chroot.
   140  	ChrootEnv map[string]string
   141  
   142  	// Options provides arbitrary key-value configuration for nomad internals,
   143  	// like fingerprinters and drivers. The format is:
   144  	//
   145  	//	namespace.option = value
   146  	Options map[string]string
   147  
   148  	// Version is the version of the Nomad client
   149  	Version *version.VersionInfo
   150  
   151  	// ConsulConfig is this Agent's Consul configuration
   152  	ConsulConfig *structsc.ConsulConfig
   153  
   154  	// VaultConfig is this Agent's Vault configuration
   155  	VaultConfig *structsc.VaultConfig
   156  
   157  	// StatsCollectionInterval is the interval at which the Nomad client
   158  	// collects resource usage stats
   159  	StatsCollectionInterval time.Duration
   160  
   161  	// PublishNodeMetrics determines whether nomad is going to publish node
   162  	// level metrics to remote Telemetry sinks
   163  	PublishNodeMetrics bool
   164  
   165  	// PublishAllocationMetrics determines whether nomad is going to publish
   166  	// allocation metrics to remote Telemetry sinks
   167  	PublishAllocationMetrics bool
   168  
   169  	// TLSConfig holds various TLS related configurations
   170  	TLSConfig *structsc.TLSConfig
   171  
   172  	// GCInterval is the time interval at which the client triggers garbage
   173  	// collection
   174  	GCInterval time.Duration
   175  
   176  	// GCParallelDestroys is the number of parallel destroys the garbage
   177  	// collector will allow.
   178  	GCParallelDestroys int
   179  
   180  	// GCDiskUsageThreshold is the disk usage threshold given as a percent
   181  	// beyond which the Nomad client triggers GC of terminal allocations
   182  	GCDiskUsageThreshold float64
   183  
   184  	// GCInodeUsageThreshold is the inode usage threshold given as a percent
   185  	// beyond which the Nomad client triggers GC of the terminal allocations
   186  	GCInodeUsageThreshold float64
   187  
   188  	// GCMaxAllocs is the maximum number of allocations a node can have
   189  	// before garbage collection is triggered.
   190  	GCMaxAllocs int
   191  
   192  	// LogLevel is the level of the logs to putout
   193  	LogLevel string
   194  
   195  	// NoHostUUID disables using the host's UUID and will force generation of a
   196  	// random UUID.
   197  	NoHostUUID bool
   198  
   199  	// ACLEnabled controls if ACL enforcement and management is enabled.
   200  	ACLEnabled bool
   201  
   202  	// ACLTokenTTL is how long we cache token values for
   203  	ACLTokenTTL time.Duration
   204  
   205  	// ACLPolicyTTL is how long we cache policy values for
   206  	ACLPolicyTTL time.Duration
   207  
   208  	// DisableRemoteExec disables remote exec targeting tasks on this client
   209  	DisableRemoteExec bool
   210  
   211  	// TemplateConfig includes configuration for template rendering
   212  	TemplateConfig *ClientTemplateConfig
   213  
   214  	// RPCHoldTimeout is how long an RPC can be "held" before it is errored.
   215  	// This is used to paper over a loss of leadership by instead holding RPCs,
   216  	// so that the caller experiences a slow response rather than an error.
   217  	// This period is meant to be long enough for a leader election to take
   218  	// place, and a small jitter is applied to avoid a thundering herd.
   219  	RPCHoldTimeout time.Duration
   220  
   221  	// PluginLoader is used to load plugins.
   222  	PluginLoader loader.PluginCatalog
   223  
   224  	// PluginSingletonLoader is a plugin loader that will returns singleton
   225  	// instances of the plugins.
   226  	PluginSingletonLoader loader.PluginCatalog
   227  
   228  	// StateDBFactory is used to override stateDB implementations,
   229  	StateDBFactory state.NewStateDBFunc
   230  
   231  	// CNIPath is the path used to search for CNI plugins. Multiple paths can
   232  	// be specified with colon delimited
   233  	CNIPath string
   234  
   235  	// CNIConfigDir is the directory where CNI network configuration is located. The
   236  	// client will use this path when fingerprinting CNI networks.
   237  	CNIConfigDir string
   238  
   239  	// CNIInterfacePrefix is the prefix to use when creating CNI network interfaces. This
   240  	// defaults to 'eth', therefore the first interface created by CNI inside the alloc
   241  	// network will be 'eth0'.
   242  	CNIInterfacePrefix string
   243  
   244  	// BridgeNetworkName is the name to use for the bridge created in bridge
   245  	// networking mode. This defaults to 'nomad' if not set
   246  	BridgeNetworkName string
   247  
   248  	// BridgeNetworkAllocSubnet is the IP subnet to use for address allocation
   249  	// for allocations in bridge networking mode. Subnet must be in CIDR
   250  	// notation
   251  	BridgeNetworkAllocSubnet string
   252  
   253  	// HostVolumes is a map of the configured host volumes by name.
   254  	HostVolumes map[string]*structs.ClientHostVolumeConfig
   255  
   256  	// HostNetworks is a map of the conigured host networks by name.
   257  	HostNetworks map[string]*structs.ClientHostNetworkConfig
   258  
   259  	// BindWildcardDefaultHostNetwork toggles if the default host network should accept all
   260  	// destinations (true) or only filter on the IP of the default host network (false) when
   261  	// port mapping. This allows Nomad clients with no defined host networks to accept and
   262  	// port forward traffic only matching on the destination port. An example use of this
   263  	// is when a network loadbalancer is utilizing direct server return and the destination
   264  	// address of incomming packets does not match the IP address of the host interface.
   265  	//
   266  	// This configuration is only considered if no host networks are defined.
   267  	BindWildcardDefaultHostNetwork bool
   268  }
   269  
   270  type ClientTemplateConfig struct {
   271  	FunctionDenylist []string
   272  	DisableSandbox   bool
   273  }
   274  
   275  func (c *ClientTemplateConfig) Copy() *ClientTemplateConfig {
   276  	if c == nil {
   277  		return nil
   278  	}
   279  
   280  	nc := new(ClientTemplateConfig)
   281  	*nc = *c
   282  	nc.FunctionDenylist = helper.CopySliceString(nc.FunctionDenylist)
   283  	return nc
   284  }
   285  
   286  func (c *Config) Copy() *Config {
   287  	nc := new(Config)
   288  	*nc = *c
   289  	nc.Node = nc.Node.Copy()
   290  	nc.Servers = helper.CopySliceString(nc.Servers)
   291  	nc.Options = helper.CopyMapStringString(nc.Options)
   292  	nc.HostVolumes = structs.CopyMapStringClientHostVolumeConfig(nc.HostVolumes)
   293  	nc.ConsulConfig = c.ConsulConfig.Copy()
   294  	nc.VaultConfig = c.VaultConfig.Copy()
   295  	nc.TemplateConfig = c.TemplateConfig.Copy()
   296  	return nc
   297  }
   298  
   299  // DefaultConfig returns the default configuration
   300  func DefaultConfig() *Config {
   301  	return &Config{
   302  		Version:                 version.GetVersion(),
   303  		VaultConfig:             structsc.DefaultVaultConfig(),
   304  		ConsulConfig:            structsc.DefaultConsulConfig(),
   305  		LogOutput:               os.Stderr,
   306  		Region:                  "global",
   307  		StatsCollectionInterval: 1 * time.Second,
   308  		TLSConfig:               &structsc.TLSConfig{},
   309  		LogLevel:                "DEBUG",
   310  		GCInterval:              1 * time.Minute,
   311  		GCParallelDestroys:      2,
   312  		GCDiskUsageThreshold:    80,
   313  		GCInodeUsageThreshold:   70,
   314  		GCMaxAllocs:             50,
   315  		NoHostUUID:              true,
   316  		DisableRemoteExec:       false,
   317  		TemplateConfig: &ClientTemplateConfig{
   318  			FunctionDenylist: []string{"plugin"},
   319  			DisableSandbox:   false,
   320  		},
   321  		RPCHoldTimeout:     5 * time.Second,
   322  		CNIPath:            "/opt/cni/bin",
   323  		CNIConfigDir:       "/opt/cni/config",
   324  		CNIInterfacePrefix: "eth",
   325  		HostNetworks:       map[string]*structs.ClientHostNetworkConfig{},
   326  	}
   327  }
   328  
   329  // Read returns the specified configuration value or "".
   330  func (c *Config) Read(id string) string {
   331  	return c.Options[id]
   332  }
   333  
   334  // ReadDefault returns the specified configuration value, or the specified
   335  // default value if none is set.
   336  func (c *Config) ReadDefault(id string, defaultValue string) string {
   337  	return c.ReadAlternativeDefault([]string{id}, defaultValue)
   338  }
   339  
   340  // ReadAlternativeDefault returns the specified configuration value, or the
   341  // specified value if none is set.
   342  func (c *Config) ReadAlternativeDefault(ids []string, defaultValue string) string {
   343  	for _, id := range ids {
   344  		val, ok := c.Options[id]
   345  		if ok {
   346  			return val
   347  		}
   348  	}
   349  
   350  	return defaultValue
   351  }
   352  
   353  // ReadBool parses the specified option as a boolean.
   354  func (c *Config) ReadBool(id string) (bool, error) {
   355  	val, ok := c.Options[id]
   356  	if !ok {
   357  		return false, fmt.Errorf("Specified config is missing from options")
   358  	}
   359  	bval, err := strconv.ParseBool(val)
   360  	if err != nil {
   361  		return false, fmt.Errorf("Failed to parse %s as bool: %s", val, err)
   362  	}
   363  	return bval, nil
   364  }
   365  
   366  // ReadBoolDefault tries to parse the specified option as a boolean. If there is
   367  // an error in parsing, the default option is returned.
   368  func (c *Config) ReadBoolDefault(id string, defaultValue bool) bool {
   369  	val, err := c.ReadBool(id)
   370  	if err != nil {
   371  		return defaultValue
   372  	}
   373  	return val
   374  }
   375  
   376  // ReadInt parses the specified option as a int.
   377  func (c *Config) ReadInt(id string) (int, error) {
   378  	val, ok := c.Options[id]
   379  	if !ok {
   380  		return 0, fmt.Errorf("Specified config is missing from options")
   381  	}
   382  	ival, err := strconv.Atoi(val)
   383  	if err != nil {
   384  		return 0, fmt.Errorf("Failed to parse %s as int: %s", val, err)
   385  	}
   386  	return ival, nil
   387  }
   388  
   389  // ReadIntDefault tries to parse the specified option as a int. If there is
   390  // an error in parsing, the default option is returned.
   391  func (c *Config) ReadIntDefault(id string, defaultValue int) int {
   392  	val, err := c.ReadInt(id)
   393  	if err != nil {
   394  		return defaultValue
   395  	}
   396  	return val
   397  }
   398  
   399  // ReadDuration parses the specified option as a duration.
   400  func (c *Config) ReadDuration(id string) (time.Duration, error) {
   401  	val, ok := c.Options[id]
   402  	if !ok {
   403  		return time.Duration(0), fmt.Errorf("Specified config is missing from options")
   404  	}
   405  	dval, err := time.ParseDuration(val)
   406  	if err != nil {
   407  		return time.Duration(0), fmt.Errorf("Failed to parse %s as time duration: %s", val, err)
   408  	}
   409  	return dval, nil
   410  }
   411  
   412  // ReadDurationDefault tries to parse the specified option as a duration. If there is
   413  // an error in parsing, the default option is returned.
   414  func (c *Config) ReadDurationDefault(id string, defaultValue time.Duration) time.Duration {
   415  	val, err := c.ReadDuration(id)
   416  	if err != nil {
   417  		return defaultValue
   418  	}
   419  	return val
   420  }
   421  
   422  // ReadStringListToMap tries to parse the specified option(s) as a comma separated list.
   423  // If there is an error in parsing, an empty list is returned.
   424  func (c *Config) ReadStringListToMap(keys ...string) map[string]struct{} {
   425  	val := c.ReadAlternativeDefault(keys, "")
   426  
   427  	return splitValue(val)
   428  }
   429  
   430  // ReadStringListToMap tries to parse the specified option as a comma separated list.
   431  // If there is an error in parsing, an empty list is returned.
   432  func (c *Config) ReadStringListToMapDefault(key, defaultValue string) map[string]struct{} {
   433  	return c.ReadStringListAlternativeToMapDefault([]string{key}, defaultValue)
   434  }
   435  
   436  // ReadStringListAlternativeToMapDefault tries to parse the specified options as a comma sparated list.
   437  // If there is an error in parsing, an empty list is returned.
   438  func (c *Config) ReadStringListAlternativeToMapDefault(keys []string, defaultValue string) map[string]struct{} {
   439  	val := c.ReadAlternativeDefault(keys, defaultValue)
   440  
   441  	return splitValue(val)
   442  }
   443  
   444  // splitValue parses the value as a comma separated list.
   445  func splitValue(val string) map[string]struct{} {
   446  	list := make(map[string]struct{})
   447  	if val != "" {
   448  		for _, e := range strings.Split(val, ",") {
   449  			trimmed := strings.TrimSpace(e)
   450  			list[trimmed] = struct{}{}
   451  		}
   452  	}
   453  	return list
   454  }
   455  
   456  // NomadPluginConfig produces the NomadConfig struct which is sent to Nomad plugins
   457  func (c *Config) NomadPluginConfig() *base.AgentConfig {
   458  	return &base.AgentConfig{
   459  		Driver: &base.ClientDriverConfig{
   460  			ClientMinPort: c.ClientMinPort,
   461  			ClientMaxPort: c.ClientMaxPort,
   462  		},
   463  	}
   464  }