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 }