add global resource limmits

This commit is contained in:
Brad Rydzewski
2019-10-29 13:08:42 -07:00
parent 3c1ae23a1e
commit 3761bd0df4
10 changed files with 49 additions and 64 deletions

View File

@@ -183,13 +183,10 @@ func registerCompile(app *kingpin.Application) {
Int64Var(&c.Resources.CPUShares) Int64Var(&c.Resources.CPUShares)
cmd.Flag("memory", "container memory limit"). cmd.Flag("memory", "container memory limit").
Int64Var(&c.Resources.MemLimit) Int64Var(&c.Resources.Memory)
cmd.Flag("memory-swap", "container memory swap limit"). cmd.Flag("memory-swap", "container memory swap limit").
Int64Var(&c.Resources.MemSwapLimit) Int64Var(&c.Resources.MemorySwap)
cmd.Flag("shmsize", "container shm size").
Int64Var(&c.Resources.ShmSize)
cmd.Flag("docker-config", "path to the docker config file"). cmd.Flag("docker-config", "path to the docker config file").
StringVar(&c.Config) StringVar(&c.Config)

View File

@@ -73,6 +73,15 @@ type Config struct {
Trusted bool `envconfig:"DRONE_LIMIT_TRUSTED"` Trusted bool `envconfig:"DRONE_LIMIT_TRUSTED"`
} }
Resources struct {
Memory int64 `envconfig:"DRONE_MEMORY_LIMIT"`
MemorySwap int64 `envconfig:"DRONE_MEMORY_SWAP_LIMIT"`
CPUQuota int64 `envconfig:"DRONE_CPU_QUOTA"`
CPUPeriod int64 `envconfig:"DRONE_CPU_PERIOD"`
CPUShares int64 `envconfig:"DRONE_CPU_SHARES"`
CPUSet []string `envconfig:"DRONE_CPU_SET"`
}
Secret struct { Secret struct {
Endpoint string `envconfig:"DRONE_SECRET_PLUGIN_ENDPOINT"` Endpoint string `envconfig:"DRONE_SECRET_PLUGIN_ENDPOINT"`
Token string `envconfig:"DRONE_SECRET_PLUGIN_TOKEN"` Token string `envconfig:"DRONE_SECRET_PLUGIN_TOKEN"`

View File

@@ -123,7 +123,14 @@ func (c *daemonCommand) run(*kingpin.ParseContext) error {
Privileged: append(config.Runner.Privileged, compiler.Privileged...), Privileged: append(config.Runner.Privileged, compiler.Privileged...),
Networks: config.Runner.Networks, Networks: config.Runner.Networks,
Volumes: config.Runner.Volumes, Volumes: config.Runner.Volumes,
// Resources: nil, Resources: compiler.Resources{
Memory: config.Resources.Memory,
MemorySwap: config.Resources.MemorySwap,
CPUQuota: config.Resources.CPUQuota,
CPUPeriod: config.Resources.CPUPeriod,
CPUShares: config.Resources.CPUShares,
CPUSet: config.Resources.CPUSet,
},
Registry: registry.Combine( Registry: registry.Combine(
registry.File( registry.File(
config.Docker.Config, config.Docker.Config,

View File

@@ -313,13 +313,10 @@ func registerExec(app *kingpin.Application) {
Int64Var(&c.Resources.CPUShares) Int64Var(&c.Resources.CPUShares)
cmd.Flag("memory", "container memory limit"). cmd.Flag("memory", "container memory limit").
Int64Var(&c.Resources.MemLimit) Int64Var(&c.Resources.Memory)
cmd.Flag("memory-swap", "container memory swap limit"). cmd.Flag("memory-swap", "container memory swap limit").
Int64Var(&c.Resources.MemSwapLimit) Int64Var(&c.Resources.MemorySwap)
cmd.Flag("shmsize", "container shm size").
Int64Var(&c.Resources.ShmSize)
cmd.Flag("public-key", "public key file path"). cmd.Flag("public-key", "public key file path").
ExistingFileVar(&c.PublicKey) ExistingFileVar(&c.PublicKey)

View File

@@ -41,13 +41,12 @@ var Privileged = []string{
// Resources defines container resource constraints. These // Resources defines container resource constraints. These
// constraints are per-container, not per-pipeline. // constraints are per-container, not per-pipeline.
type Resources struct { type Resources struct {
MemLimit int64 Memory int64
MemSwapLimit int64 MemorySwap int64
ShmSize int64 CPUQuota int64
CPUQuota int64 CPUPeriod int64
CPUPeriod int64 CPUShares int64
CPUShares int64 CPUSet []string
CPUSet []string
} }
// Args provides compiler arguments. // Args provides compiler arguments.
@@ -373,9 +372,8 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
// append global resource limits to steps // append global resource limits to steps
for _, step := range spec.Steps { for _, step := range spec.Steps {
step.MemSwapLimit = c.Resources.MemSwapLimit step.MemSwapLimit = c.Resources.MemorySwap
step.MemLimit = c.Resources.MemLimit step.MemLimit = c.Resources.Memory
step.ShmSize = c.Resources.ShmSize
step.CPUPeriod = c.Resources.CPUPeriod step.CPUPeriod = c.Resources.CPUPeriod
step.CPUQuota = c.Resources.CPUQuota step.CPUQuota = c.Resources.CPUQuota
step.CPUShares = c.Resources.CPUShares step.CPUShares = c.Resources.CPUShares

View File

@@ -42,7 +42,6 @@ func createStep(spec *resource.Pipeline, src *resource.Step) *engine.Step {
// //
Networks: nil, // set in compiler.go Networks: nil, // set in compiler.go
Files: nil, // set below
Volumes: nil, // set below Volumes: nil, // set below
Devices: nil, // see below Devices: nil, // see below
// Resources: toResources(src), // TODO // Resources: toResources(src), // TODO

View File

@@ -73,19 +73,16 @@ func toHostConfig(spec *Spec, step *Step) *container.HostConfig {
if len(step.ExtraHosts) > 0 { if len(step.ExtraHosts) > 0 {
config.ExtraHosts = step.ExtraHosts config.ExtraHosts = step.ExtraHosts
} }
// if step.Resources != nil { if isUnlimited(step) == false {
// config.Resources = container.Resources{} config.Resources = container.Resources{
// if limits := step.Resources.Limits; limits != nil { CPUPeriod: step.CPUPeriod,
// config.Resources.Memory = limits.Memory CPUQuota: step.CPUQuota,
// // TODO(bradrydewski) set config.Resources.CPUPercent CpusetCpus: strings.Join(step.CPUSet, ","),
CPUShares: step.CPUShares,
// // IMPORTANT docker and kubernetes use Memory: step.MemLimit,
// // different units of measure for cpu limits. MemorySwap: step.MemSwapLimit,
// // we need to figure out how to convert from }
// // the kubernetes unit of measure to the docker }
// // unit of measure.
// }
// }
if len(step.Volumes) != 0 { if len(step.Volumes) != 0 {
config.Devices = toDeviceSlice(spec, step) config.Devices = toDeviceSlice(spec, step)
@@ -259,6 +256,16 @@ func toEnv(env map[string]string) []string {
return envs return envs
} }
// returns true if the container has no resource limits.
func isUnlimited(res *Step) bool {
return len(res.CPUSet) == 0 &&
res.CPUPeriod == 0 &&
res.CPUQuota == 0 &&
res.CPUShares == 0 &&
res.MemLimit == 0 &&
res.MemSwapLimit == 0
}
// returns true if the volume is a bind mount. // returns true if the volume is a bind mount.
func isBindMount(volume *Volume) bool { func isBindMount(volume *Volume) bool {
return volume.HostPath != nil return volume.HostPath != nil

View File

@@ -214,19 +214,6 @@ func (e *Docker) create(ctx context.Context, spec *Spec, step *Step, output io.W
return err return err
} }
// // use the default user-defined network if network_mode
// // is not otherwise specified.
// if step.Network == "" {
// for _, net := range step.Networks {
// err = e.client.NetworkConnect(ctx, net, step.ID, &network.EndpointSettings{
// Aliases: []string{net},
// })
// if err != nil {
// return nil
// }
// }
// }
return nil return nil
} }

View File

@@ -13,8 +13,6 @@ var (
_ manifest.PlatformResource = (*Pipeline)(nil) _ manifest.PlatformResource = (*Pipeline)(nil)
) )
// TODO(bradrydzewski) add resource limits
// Defines the Resource Kind and Type. // Defines the Resource Kind and Type.
const ( const (
Kind = "pipeline" Kind = "pipeline"
@@ -108,8 +106,6 @@ type (
Volumes []*VolumeMount `json:"volumes,omitempty"` Volumes []*VolumeMount `json:"volumes,omitempty"`
When manifest.Conditions `json:"when,omitempty"` When manifest.Conditions `json:"when,omitempty"`
WorkingDir string `json:"working_dir,omitempty" yaml:"working_dir"` WorkingDir string `json:"working_dir,omitempty" yaml:"working_dir"`
// Resources *Resources `json:"resources,omitempty"`
} }
// Volume that can be mounted by containers. // Volume that can be mounted by containers.

View File

@@ -10,7 +10,6 @@ type (
// execution. // execution.
Spec struct { Spec struct {
Platform Platform `json:"platform,omitempty"` Platform Platform `json:"platform,omitempty"`
Files []*File `json:"files,omitempty"`
Steps []*Step `json:"steps,omitempty"` Steps []*Step `json:"steps,omitempty"`
Volumes []*Volume `json:"volumes,omitempty"` Volumes []*Volume `json:"volumes,omitempty"`
Network Network `json:"network"` Network Network `json:"network"`
@@ -33,7 +32,6 @@ type (
Entrypoint []string `json:"entrypoint,omitempty"` Entrypoint []string `json:"entrypoint,omitempty"`
Envs map[string]string `json:"environment,omitempty"` Envs map[string]string `json:"environment,omitempty"`
ExtraHosts []string `json:"extra_hosts,omitempty"` ExtraHosts []string `json:"extra_hosts,omitempty"`
Files []*File `json:"files,omitempty"`
IgnoreErr bool `json:"ignore_err,omitempty"` IgnoreErr bool `json:"ignore_err,omitempty"`
IgnoreStdout bool `json:"ignore_stderr,omitempty"` IgnoreStdout bool `json:"ignore_stderr,omitempty"`
IgnoreStderr bool `json:"ignore_stdout,omitempty"` IgnoreStderr bool `json:"ignore_stdout,omitempty"`
@@ -54,16 +52,6 @@ type (
WorkingDir string `json:"working_dir,omitempty"` WorkingDir string `json:"working_dir,omitempty"`
} }
// File defines a file that should be uploaded or
// mounted somewhere in the step container or virtual
// machine prior to command execution.
File struct {
Path string `json:"path,omitempty"`
Mode uint32 `json:"mode,omitempty"`
Data []byte `json:"data,omitempty"`
IsDir bool `json:"is_dir,omitempty"`
}
// Platform defines the target platform. // Platform defines the target platform.
Platform struct { Platform struct {
OS string `json:"os,omitempty"` OS string `json:"os,omitempty"`