diff --git a/api/v1/softwarefactory_types.go b/api/v1/softwarefactory_types.go index 50f38cf8..8e1d55a7 100644 --- a/api/v1/softwarefactory_types.go +++ b/api/v1/softwarefactory_types.go @@ -257,6 +257,10 @@ type ZuulExecutorSpec struct { // When set the Control plane is not deployed. // The standalone executor must be able to connect to the control plane Standalone *StandaloneZuulExecutorSpec `json:"standalone,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } type ZuulWebSpec struct { @@ -268,6 +272,10 @@ type ZuulWebSpec struct { // Changing this value will restart the service. // +optional LogLevel LogLevel `json:"logLevel,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } // Spec for the scheduler microservice @@ -284,6 +292,10 @@ type ZuulSchedulerSpec struct { // Changing this value will restart the service. // +optional LogLevel LogLevel `json:"logLevel,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } // Zuul Merger Configuration, see [Zuul's documentation](https://zuul-ci.org/docs/zuul/latest/configuration.html#merger) @@ -313,6 +325,10 @@ type ZuulMergerSpec struct { // Changing this value will restart the service. // +optional LogLevel LogLevel `json:"logLevel,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } // TODO: make sure to update the GetConnectionsName when adding new connection type. @@ -435,6 +451,10 @@ type NodepoolLauncherSpec struct { // Changing this value will restart the service. // +optional LogLevel LogLevel `json:"logLevel,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } type NodepoolBuilderSpec struct { @@ -446,6 +466,10 @@ type NodepoolBuilderSpec struct { // "WARN", // "DEBUG". LogLevel LogLevel `json:"logLevel,omitempty"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } type NodepoolSpec struct { @@ -459,6 +483,17 @@ type NodepoolSpec struct { type ZookeeperSpec struct { Storage StorageSpec `json:"storage"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` +} + +type LimitsSpec struct { + // +kubebuilder:default:="2Gi" + Memory resource.Quantity `json:"memory"` + // +kubebuilder:default:="2000m" + CPU resource.Quantity `json:"cpu"` } type MariaDBSpec struct { @@ -466,6 +501,10 @@ type MariaDBSpec struct { DBStorage StorageSpec `json:"dbStorage"` // Storage parameters related to the database's logging LogStorage StorageSpec `json:"logStorage"` + // Memory/CPU Limit + // +kubebuilder:validation:Optional + // +kubebuilder:default={"memory": "2Gi", "cpu": "2000m"} + Limits *LimitsSpec `json:"limits"` } type GitServerSpec struct { diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 1d57350d..4acda3c9 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -205,6 +205,23 @@ func (in *LetsEncryptSpec) DeepCopy() *LetsEncryptSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LimitsSpec) DeepCopyInto(out *LimitsSpec) { + *out = *in + out.Memory = in.Memory.DeepCopy() + out.CPU = in.CPU.DeepCopy() +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LimitsSpec. +func (in *LimitsSpec) DeepCopy() *LimitsSpec { + if in == nil { + return nil + } + out := new(LimitsSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LogServerSpec) DeepCopyInto(out *LogServerSpec) { *out = *in @@ -226,6 +243,11 @@ func (in *MariaDBSpec) DeepCopyInto(out *MariaDBSpec) { *out = *in in.DBStorage.DeepCopyInto(&out.DBStorage) in.LogStorage.DeepCopyInto(&out.LogStorage) + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MariaDBSpec. @@ -242,6 +264,11 @@ func (in *MariaDBSpec) DeepCopy() *MariaDBSpec { func (in *NodepoolBuilderSpec) DeepCopyInto(out *NodepoolBuilderSpec) { *out = *in in.Storage.DeepCopyInto(&out.Storage) + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodepoolBuilderSpec. @@ -257,6 +284,11 @@ func (in *NodepoolBuilderSpec) DeepCopy() *NodepoolBuilderSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodepoolLauncherSpec) DeepCopyInto(out *NodepoolLauncherSpec) { *out = *in + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodepoolLauncherSpec. @@ -272,7 +304,7 @@ func (in *NodepoolLauncherSpec) DeepCopy() *NodepoolLauncherSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodepoolSpec) DeepCopyInto(out *NodepoolSpec) { *out = *in - out.Launcher = in.Launcher + in.Launcher.DeepCopyInto(&out.Launcher) in.Builder.DeepCopyInto(&out.Builder) } @@ -484,6 +516,11 @@ func (in *StorageSpec) DeepCopy() *StorageSpec { func (in *ZookeeperSpec) DeepCopyInto(out *ZookeeperSpec) { *out = *in in.Storage.DeepCopyInto(&out.Storage) + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZookeeperSpec. @@ -510,6 +547,11 @@ func (in *ZuulExecutorSpec) DeepCopyInto(out *ZuulExecutorSpec) { *out = new(StandaloneZuulExecutorSpec) **out = **in } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZuulExecutorSpec. @@ -526,6 +568,11 @@ func (in *ZuulExecutorSpec) DeepCopy() *ZuulExecutorSpec { func (in *ZuulMergerSpec) DeepCopyInto(out *ZuulMergerSpec) { *out = *in in.Storage.DeepCopyInto(&out.Storage) + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZuulMergerSpec. @@ -557,6 +604,11 @@ func (in *ZuulOIDCAuthenticatorSpec) DeepCopy() *ZuulOIDCAuthenticatorSpec { func (in *ZuulSchedulerSpec) DeepCopyInto(out *ZuulSchedulerSpec) { *out = *in in.Storage.DeepCopyInto(&out.Storage) + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZuulSchedulerSpec. @@ -613,7 +665,7 @@ func (in *ZuulSpec) DeepCopyInto(out *ZuulSpec) { } in.Executor.DeepCopyInto(&out.Executor) in.Scheduler.DeepCopyInto(&out.Scheduler) - out.Web = in.Web + in.Web.DeepCopyInto(&out.Web) in.Merger.DeepCopyInto(&out.Merger) } @@ -630,6 +682,11 @@ func (in *ZuulSpec) DeepCopy() *ZuulSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ZuulWebSpec) DeepCopyInto(out *ZuulWebSpec) { *out = *in + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(LimitsSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZuulWebSpec. diff --git a/cli/cmd/dev/gerrit/gerrit.go b/cli/cmd/dev/gerrit/gerrit.go index 13db05c9..3602a845 100644 --- a/cli/cmd/dev/gerrit/gerrit.go +++ b/cli/cmd/dev/gerrit/gerrit.go @@ -37,6 +37,7 @@ import ( batchv1 "k8s.io/api/batch/v1" apiv1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -242,6 +243,8 @@ func configureGerritContainer(sts *appsv1.StatefulSet, volumeMounts []apiv1.Volu sts.Spec.Template.Spec.Containers[0].Env = []apiv1.EnvVar{ base.MkEnvVar("HOME", "/gerrit"), base.MkEnvVar("FQDN", fqdn), + base.MkEnvVar("JVM_XMS", "128m"), + base.MkEnvVar("JVM_XMX", "512m"), base.MkSecretEnvVar("GERRIT_ADMIN_SSH", "admin-ssh-key", "priv"), } sts.Spec.Template.Spec.Containers[0].ReadinessProbe = base.MkReadinessCMDProbe([]string{"bash", "/gerrit/ready.sh"}) @@ -309,8 +312,16 @@ func createInitContainers(volumeMounts []apiv1.VolumeMount, fqdn string) []apiv1 container.Env = []apiv1.EnvVar{ base.MkSecretEnvVar("GERRIT_ADMIN_SSH_PUB", "admin-ssh-key", "pub"), base.MkEnvVar("FQDN", fqdn), + base.MkEnvVar("JVM_XMS", "128m"), + base.MkEnvVar("JVM_XMX", "512m"), } container.VolumeMounts = volumeMounts + base.SetContainerLimits( + &container, + resource.MustParse("256Mi"), + resource.MustParse("512Mi"), + resource.MustParse("100m"), + resource.MustParse("1000m")) return []apiv1.Container{ container, } @@ -342,6 +353,12 @@ func (g *GerritCMDContext) ensureStatefulSetOrDie() { b, _ := g.getStatefulSetOrDie(name) if !b { container := base.MkContainer(name, gerritImage) + base.SetContainerLimits( + &container, + resource.MustParse("256Mi"), + resource.MustParse("512Mi"), + resource.MustParse("100m"), + resource.MustParse("1000m")) storageConfig := controllers.BaseGetStorageConfOrDefault(v1.StorageSpec{}, "") pvc := base.MkPVC(name, g.env.Ns, storageConfig, apiv1.ReadWriteOnce) sts := base.MkStatefulset( diff --git a/cli/cmd/dev/gerrit/static/entrypoint.sh b/cli/cmd/dev/gerrit/static/entrypoint.sh index 6128a2aa..b6556d7e 100644 --- a/cli/cmd/dev/gerrit/static/entrypoint.sh +++ b/cli/cmd/dev/gerrit/static/entrypoint.sh @@ -3,7 +3,7 @@ set -ex # The /dev/./urandom is not a typo. https://stackoverflow.com/questions/58991966/what-java-security-egd-option-is-for -JAVA_OPTIONS="-Djava.security.egd=file:/dev/./urandom" +JAVA_OPTIONS="-Djava.security.egd=file:/dev/./urandom -Xms${JVM_XMS} -Xmx${JVM_XMX}" echo "Set local git config for gerrit admin" cat << EOF > ~/.gitconfig diff --git a/cli/cmd/dev/gerrit/static/init.sh b/cli/cmd/dev/gerrit/static/init.sh index 6f2c3059..f6ae283f 100755 --- a/cli/cmd/dev/gerrit/static/init.sh +++ b/cli/cmd/dev/gerrit/static/init.sh @@ -1,10 +1,10 @@ #!/bin/bash set -ex -export HOME=/gerrit +export HOME=/gerrit # The /dev/./urandom is not a typo. https://stackoverflow.com/questions/58991966/what-java-security-egd-option-is-for -JAVA_OPTIONS="-Djava.security.egd=file:/dev/./urandom" +JAVA_OPTIONS="-Djava.security.egd=file:/dev/./urandom -Xms${JVM_XMS} -Xmx${JVM_XMX}" echo "Initializing Gerrit site ..." java ${JAVA_OPTIONS} -jar /var/gerrit/bin/gerrit.war init -d ~/ --batch --no-auto-start --skip-plugins diff --git a/config/crd/bases/sf.softwarefactory-project.io_softwarefactories.yaml b/config/crd/bases/sf.softwarefactory-project.io_softwarefactories.yaml index 51195dcb..00e80b0e 100644 --- a/config/crd/bases/sf.softwarefactory-project.io_softwarefactories.yaml +++ b/config/crd/bases/sf.softwarefactory-project.io_softwarefactories.yaml @@ -218,6 +218,30 @@ spec: required: - size type: object + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logStorage: description: Storage parameters related to the database's logging properties: @@ -248,6 +272,30 @@ spec: builder: description: Nodepool-builder related settings properties: + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the nodepool launcher process. @@ -284,6 +332,30 @@ spec: launcher: description: Nodepool-launcher related settings properties: + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the nodepool launcher service. @@ -310,6 +382,30 @@ spec: zookeeper: description: Zookeeper service spec properties: + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object storage: properties: className: @@ -373,6 +469,30 @@ spec: description: If set to false, the zuul-executor deployment won't be applied type: boolean + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the zuul-executor service. @@ -632,6 +752,30 @@ spec: description: the [git_user_name](https://zuul-ci.org/docs/zuul/latest/configuration.html#attr-merger.git_user_name) parameter type: string + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the nodepool launcher service. @@ -791,6 +935,30 @@ spec: scheduler: description: Configuration of the scheduler microservice properties: + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the zuul-scheduler service. @@ -832,6 +1000,30 @@ spec: web: description: Configuration of the web microservice properties: + limits: + default: + cpu: 2000m + memory: 2Gi + description: Memory/CPU Limit + properties: + cpu: + anyOf: + - type: integer + - type: string + default: 2000m + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + memory: + anyOf: + - type: integer + - type: string + default: 2Gi + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - cpu + - memory + type: object logLevel: description: |- Specify the Log Level of the zuul-web launcher service. diff --git a/controllers/git_server.go b/controllers/git_server.go index d878849b..ed6ed905 100644 --- a/controllers/git_server.go +++ b/controllers/git_server.go @@ -14,7 +14,6 @@ import ( sfv1 "github.com/softwarefactory-project/sf-operator/api/v1" "github.com/softwarefactory-project/sf-operator/controllers/libs/base" "github.com/softwarefactory-project/sf-operator/controllers/libs/conds" - sfmonitoring "github.com/softwarefactory-project/sf-operator/controllers/libs/monitoring" "github.com/softwarefactory-project/sf-operator/controllers/libs/utils" "github.com/softwarefactory-project/sf-operator/controllers/libs/zuulcf" "gopkg.in/yaml.v3" @@ -272,7 +271,7 @@ func (r *SFController) DeployGitServer() bool { "system-config": utils.Checksum([]byte(preInitScript)), "image": base.GitServerImage(), "fqdn": r.cr.Spec.FQDN, - "serial": "2", + "serial": "3", } if r.isConfigRepoSet() { @@ -298,9 +297,13 @@ func (r *SFController) DeployGitServer() bool { } sts.Spec.Template.Spec.Containers[0].VolumeMounts = GSVolumeMountsRO sts.Spec.Template.Spec.Containers[0].Command = []string{"git", "daemon", "--base-path=/git", "--export-all"} + var probeCmd = []string{"git", "ls-remote", "git://localhost:" + strconv.Itoa(gsGitPort) + "/system-config"} + sts.Spec.Template.Spec.Containers[0].ReadinessProbe = base.MkReadinessCMDProbe(probeCmd) + sts.Spec.Template.Spec.Containers[0].StartupProbe = base.MkStartupCMDProbe(probeCmd) + base.SetContainerLimitsLowProfile(&sts.Spec.Template.Spec.Containers[0]) // Add a second container to serve the git-server with RW access (should not be exposed) - containerRW := base.MkContainer("git-daemon-rw", base.GitServerImage()) + containerRW := base.MkContainer(GitServerIdentRW, base.GitServerImage()) containerRW.Command = []string{"git", "daemon", "--base-path=/git", "--enable=receive-pack", "--export-all", "--port=" + strconv.Itoa(gsGitPortRW)} containerRW.VolumeMounts = []apiv1.VolumeMount{ @@ -310,6 +313,11 @@ func (r *SFController) DeployGitServer() bool { }, } + var probeCmdCRW = []string{"git", "ls-remote", "git://localhost:" + strconv.Itoa(gsGitPortRW) + "/system-config"} + containerRW.ReadinessProbe = base.MkReadinessCMDProbe(probeCmdCRW) + containerRW.StartupProbe = base.MkStartupCMDProbe(probeCmdCRW) + base.SetContainerLimitsLowProfile(&containerRW) + sts.Spec.Template.Spec.Containers = append(sts.Spec.Template.Spec.Containers, containerRW) sts.Spec.Template.Spec.Volumes = []apiv1.Volume{ base.MkVolumeCM(GitServerIdent+"-pi", GitServerIdent+"-pi-config-map"), @@ -345,13 +353,6 @@ func (r *SFController) DeployGitServer() bool { sts.Spec.Template.Spec.InitContainers = []apiv1.Container{initContainer} - // Create readiness probes - // Note: The probe is causing error message to be logged by the service - // dep.Spec.Template.Spec.Containers[0].ReadinessProbe = create_readiness_tcp_probe(GS_GIT_PORT) - - statsExporter := sfmonitoring.MkNodeExporterSideCarContainer(GitServerIdent, GSVolumeMountsRO) - sts.Spec.Template.Spec.Containers = append(sts.Spec.Template.Spec.Containers, statsExporter) - current, changed := r.ensureStatefulset(sts) if changed { return false diff --git a/controllers/libs/base/base.go b/controllers/libs/base/base.go index 24c0cf78..b0ed5223 100644 --- a/controllers/libs/base/base.go +++ b/controllers/libs/base/base.go @@ -8,6 +8,7 @@ import ( "fmt" apiroutev1 "github.com/openshift/api/route/v1" + v1 "github.com/softwarefactory-project/sf-operator/api/v1" "github.com/softwarefactory-project/sf-operator/controllers/libs/utils" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" @@ -42,14 +43,70 @@ func MkSecurityContext(privileged bool) *apiv1.SecurityContext { } } +// SetContainerLimits sets the Resource limit according to +// https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +func SetContainerLimits(container *apiv1.Container, memRequest resource.Quantity, memLimit resource.Quantity, cpuRequest resource.Quantity, cpuLimit resource.Quantity) { + var ( + defaultResources = apiv1.ResourceRequirements{ + Requests: map[apiv1.ResourceName]resource.Quantity{ + apiv1.ResourceMemory: memRequest, + apiv1.ResourceCPU: cpuRequest, + }, + Limits: map[apiv1.ResourceName]resource.Quantity{ + apiv1.ResourceMemory: memLimit, + apiv1.ResourceCPU: cpuLimit, + }, + } + ) + container.Resources = defaultResources +} + // MkContainer produces a Container with the default settings func MkContainer(name string, image string) apiv1.Container { - return apiv1.Container{ + var container = apiv1.Container{ Name: name, Image: image, ImagePullPolicy: "IfNotPresent", SecurityContext: MkSecurityContext(false), } + setContainerLimitsDefaultProfile(&container) + return container +} + +func setContainerLimitsDefaultProfile(container *apiv1.Container) { + SetContainerLimits( + container, + resource.MustParse("128Mi"), + resource.MustParse("256Mi"), + resource.MustParse("100m"), + resource.MustParse("500m")) +} + +func SetContainerLimitsLowProfile(container *apiv1.Container) { + SetContainerLimits( + container, + resource.MustParse("32Mi"), + resource.MustParse("64Mi"), + resource.MustParse("10m"), + resource.MustParse("100m")) +} + +func SetContainerLimitsHighProfile(container *apiv1.Container) { + SetContainerLimits( + container, + resource.MustParse("128Mi"), + resource.MustParse("2Gi"), + resource.MustParse("100m"), + resource.MustParse("2000m")) +} + +func UpdateContainerLimit(limits *v1.LimitsSpec, container *apiv1.Container) string { + if limits != nil { + container.Resources.Limits[apiv1.ResourceCPU] = limits.CPU + container.Resources.Limits[apiv1.ResourceMemory] = limits.Memory + return limits.CPU.String() + "-" + limits.Memory.String() + } + return "" } // MkContainerPort produces a TCP ContainerPort diff --git a/controllers/libs/monitoring/monitoring.go b/controllers/libs/monitoring/monitoring.go index e487217d..3db36ba3 100644 --- a/controllers/libs/monitoring/monitoring.go +++ b/controllers/libs/monitoring/monitoring.go @@ -56,6 +56,7 @@ func MkNodeExporterSideCarContainer(serviceName string, volumeMounts []apiv1.Vol base.MkContainerPort(NodeExporterPort, GetTruncatedPortName(serviceName, NodeExporterPortNameSuffix)), } container.VolumeMounts = volumeMounts + base.SetContainerLimitsLowProfile(&container) return container } @@ -160,7 +161,6 @@ func MkStatsdExporterSideCarContainer(serviceName string, configVolumeName strin var seExposePortName = GetStatsdExporterPort(serviceName) var configFile = StatsdExporterConfigFile var configPath = "/tmp/" + configFile - // var configVolumeName = serviceName + "-statsd-conf" volumeMounts := []apiv1.VolumeMount{ { @@ -186,7 +186,7 @@ func MkStatsdExporterSideCarContainer(serviceName string, configVolumeName strin sidecar.Args = args sidecar.VolumeMounts = volumeMounts sidecar.Ports = ports - + base.SetContainerLimitsLowProfile(&sidecar) return sidecar } diff --git a/controllers/logserver.go b/controllers/logserver.go index 5648c2da..796459ff 100644 --- a/controllers/logserver.go +++ b/controllers/logserver.go @@ -273,7 +273,7 @@ func (r *SFController) DeployLogserver() bool { // Increase serial each time you need to enforce a deployment change/pod restart between operator versions sts.Spec.Template.ObjectMeta.Annotations = map[string]string{ "fqdn": r.cr.Spec.FQDN, - "serial": "5", + "serial": "6", "httpd-conf": utils.Checksum([]byte(logserverConf)), "purgeLogConfig": "retentionDays:" + strconv.Itoa(r.cr.Spec.Logserver.RetentionDays) + " loopDelay:" + strconv.Itoa(r.cr.Spec.Logserver.LoopDelay), diff --git a/controllers/mariadb.go b/controllers/mariadb.go index c48d94eb..32748b74 100644 --- a/controllers/mariadb.go +++ b/controllers/mariadb.go @@ -88,6 +88,7 @@ func (r *SFController) CreateDBInitContainer(username string, password string, d c := "CREATE DATABASE IF NOT EXISTS " + dbname + " CHARACTER SET utf8 COLLATE utf8_general_ci; " g := "GRANT ALL PRIVILEGES ON " + dbname + ".* TO '" + username + "'@'%' IDENTIFIED BY '${USER_PASSWORD}' WITH GRANT OPTION; FLUSH PRIVILEGES;" container := base.MkContainer("mariadb-client", base.MariaDBImage()) + base.SetContainerLimitsLowProfile(&container) container.Command = []string{"sh", "-c", ` echo 'Running: mysql --host=" ` + MariaDBIdent + `" --user=root --password="$MYSQL_ROOT_PASSWORD" -e "` + c + g + `"' ATTEMPT=0 @@ -192,6 +193,9 @@ func (r *SFController) DeployMariadb() bool { sts := r.mkStatefulSet(MariaDBIdent, base.MariaDBImage(), r.getStorageConfOrDefault(r.cr.Spec.MariaDB.DBStorage), apiv1.ReadWriteOnce) + base.SetContainerLimitsHighProfile(&sts.Spec.Template.Spec.Containers[0]) + limitstr := base.UpdateContainerLimit(r.cr.Spec.MariaDB.Limits, &sts.Spec.Template.Spec.Containers[0]) + sts.Spec.VolumeClaimTemplates = append( sts.Spec.VolumeClaimTemplates, // TODO redirect logs to stdout so we don't need a volume @@ -236,7 +240,8 @@ func (r *SFController) DeployMariadb() bool { } annotations := map[string]string{ - "serial": "4", + "serial": "5", + "limits": limitstr, } if r.cr.Spec.FluentBitLogForwarding != nil { fbVolume, fbSidecar := createLogForwarderSidecar(r, annotations) diff --git a/controllers/nodepool.go b/controllers/nodepool.go index 297d2946..ce8f76fd 100644 --- a/controllers/nodepool.go +++ b/controllers/nodepool.go @@ -532,7 +532,7 @@ func (r *SFController) DeployNodepoolBuilder(statsdExporterVolume apiv1.Volume, "statsd_mapping": utils.Checksum([]byte(nodepoolStatsdMappingConfig)), "image": base.NodepoolBuilderImage(), "nodepool-providers-secrets": getSecretsVersion(providersSecrets, providerSecretsExists), - "serial": "14", + "serial": "15", "corporate-ca-certs-version": getCMVersion(corporateCM, corporateCMExists), } @@ -541,6 +541,7 @@ func (r *SFController) DeployNodepoolBuilder(statsdExporterVolume apiv1.Volume, } initContainer := base.MkContainer("nodepool-builder-init", base.NodepoolBuilderImage()) + base.SetContainerLimitsLowProfile(&initContainer) initContainer.Command = []string{"/usr/local/bin/init-container.sh"} initContainer.Env = append(r.getNodepoolConfigEnvs(), @@ -583,6 +584,10 @@ func (r *SFController) DeployNodepoolBuilder(statsdExporterVolume apiv1.Volume, nb.Spec.Template.Spec.Containers[0].VolumeMounts = volumeMounts nb.Spec.Template.Spec.Containers[0].Env = r.getNodepoolConfigEnvs() + base.SetContainerLimitsHighProfile(&nb.Spec.Template.Spec.Containers[0]) + limitstr := base.UpdateContainerLimit(r.cr.Spec.Nodepool.Builder.Limits, &nb.Spec.Template.Spec.Containers[0]) + annotations["limits"] = limitstr + extraLoggingEnvVars := logging.SetupLogForwarding("nodepool-builder", r.cr.Spec.FluentBitLogForwarding, nodepoolFluentBitLabels, annotations) nb.Spec.Template.Spec.Containers[0].Env = append(nb.Spec.Template.Spec.Containers[0].Env, extraLoggingEnvVars...) if r.cr.Spec.FluentBitLogForwarding != nil { @@ -709,7 +714,7 @@ func (r *SFController) DeployNodepoolLauncher(statsdExporterVolume apiv1.Volume, "nodepool.yaml": utils.Checksum([]byte(generateConfigScript)), "nodepool-logging.yaml": utils.Checksum([]byte(loggingConfig)), "statsd_mapping": utils.Checksum([]byte(nodepoolStatsdMappingConfig)), - "serial": "8", + "serial": "10", // When the Secret ResourceVersion field change (when edited) we force a nodepool-launcher restart "image": base.NodepoolLauncherImage(), "nodepool-providers-secrets": getSecretsVersion(providersSecrets, providerSecretsExists), @@ -721,6 +726,7 @@ func (r *SFController) DeployNodepoolLauncher(statsdExporterVolume apiv1.Volume, } initContainer := base.MkContainer("nodepool-launcher-init", base.NodepoolLauncherImage()) + base.SetContainerLimitsLowProfile(&initContainer) initContainer.Command = []string{"/usr/local/bin/init-container.sh"} initContainer.Env = r.getNodepoolConfigEnvs() @@ -760,6 +766,9 @@ func (r *SFController) DeployNodepoolLauncher(statsdExporterVolume apiv1.Volume, "/usr/local/bin/nodepool-launcher -f -l /etc/nodepool-logging/logging.yaml", } container.Env = r.getNodepoolConfigEnvs() + base.SetContainerLimitsHighProfile(&container) + limitstr := base.UpdateContainerLimit(r.cr.Spec.Nodepool.Launcher.Limits, &container) + annotations["limits"] = limitstr launcherFluentBitLabels := append(nodepoolFluentBitLabels, logging.FluentBitLabel{Key: "CONTAINER", Value: LauncherIdent}) extraLoggingEnvVars := logging.SetupLogForwarding("nodepool-launcher", r.cr.Spec.FluentBitLogForwarding, launcherFluentBitLabels, annotations) diff --git a/controllers/zookeeper.go b/controllers/zookeeper.go index 68b1b09f..70881485 100644 --- a/controllers/zookeeper.go +++ b/controllers/zookeeper.go @@ -101,7 +101,7 @@ func (r *SFController) DeployZookeeper() bool { annotations := map[string]string{ "configuration": utils.Checksum([]byte(configChecksumable)), "image": base.ZookeeperImage(), - "serial": "3", + "serial": "4", } volumeMountsStatsExporter := []apiv1.VolumeMount{ @@ -168,6 +168,8 @@ func (r *SFController) DeployZookeeper() bool { zk.Spec.Template.Spec.Containers[0].Ports = []apiv1.ContainerPort{ base.MkContainerPort(zkSSLPort, zkSSLPortName), } + base.SetContainerLimitsHighProfile(&zk.Spec.Template.Spec.Containers[0]) + annotations["limits"] = base.UpdateContainerLimit(r.cr.Spec.Zookeeper.Limits, &zk.Spec.Template.Spec.Containers[0]) if r.cr.Spec.FluentBitLogForwarding != nil { fbVolume, fbSidecar := createZKLogForwarderSidecar(r, annotations) diff --git a/controllers/zuul.go b/controllers/zuul.go index 5beaa799..493922b9 100644 --- a/controllers/zuul.go +++ b/controllers/zuul.go @@ -146,7 +146,7 @@ func getZuulImage(service string) string { } } -func (r *SFController) mkZuulContainer(service string, corporateCMExists bool) []apiv1.Container { +func (r *SFController) mkZuulContainer(service string, corporateCMExists bool) apiv1.Container { volumeMounts := []apiv1.VolumeMount{ { Name: "zuul-config", @@ -229,6 +229,8 @@ func (r *SFController) mkZuulContainer(service string, corporateCMExists bool) [ VolumeMounts: volumeMounts, } + base.SetContainerLimitsHighProfile(&container) + if service == "zuul-scheduler" { // For the scheduler we do not run the update-ca-trust because the initContainer // already handles that task. @@ -236,7 +238,7 @@ func (r *SFController) mkZuulContainer(service string, corporateCMExists bool) [ "/usr/local/bin/zuul-scheduler -f -d"} } - return []apiv1.Container{container} + return container } func mkZuulVolumes(service string, r *SFController, corporateCMExists bool) []apiv1.Volume { @@ -427,7 +429,7 @@ func (r *SFController) EnsureZuulScheduler(cfg *ini.File) bool { "zuul-component-config": utils.IniSectionsChecksum(cfg, sections), "zuul-image": getZuulImage("zuul-scheduler"), "statsd_mapping": utils.Checksum([]byte(zuulStatsdMappingConfig)), - "serial": "8", + "serial": "9", "zuul-logging": utils.Checksum([]byte(r.getZuulLoggingString("zuul-scheduler"))), "zuul-extra": utils.Checksum([]byte(sshConfig)), "zuul-connections": utils.IniSectionsChecksum(cfg, utils.IniGetSectionNamesByPrefix(cfg, "connection")), @@ -445,11 +447,12 @@ func (r *SFController) EnsureZuulScheduler(cfg *ini.File) bool { relayAddress = &r.cr.Spec.Zuul.Scheduler.StatsdTarget } - zuulContainers := r.mkZuulContainer(ZuulSchedulerIdent, corporateCMExists) + zuulContainer := r.mkZuulContainer(ZuulSchedulerIdent, corporateCMExists) + annotations["limits"] = base.UpdateContainerLimit(r.cr.Spec.Zuul.Scheduler.Limits, &zuulContainer) zsFluentBitLabels := append(zuulFluentBitLabels, logging.FluentBitLabel{Key: "CONTAINER", Value: "zuul-scheduler"}) extraLoggingEnvVars := logging.SetupLogForwarding("zuul-scheduler", r.cr.Spec.FluentBitLogForwarding, zsFluentBitLabels, annotations) - zuulContainers[0].Env = append(zuulContainers[0].Env, extraLoggingEnvVars...) + zuulContainer.Env = append(zuulContainer.Env, extraLoggingEnvVars...) statsdSidecar := monitoring.MkStatsdExporterSideCarContainer("zuul", "statsd-config", relayAddress) nodeExporterSidecar := monitoring.MkNodeExporterSideCarContainer( @@ -461,7 +464,7 @@ func (r *SFController) EnsureZuulScheduler(cfg *ini.File) bool { }, }) - zuulContainers = append(zuulContainers, statsdSidecar, nodeExporterSidecar) + zuulContainers := append([]apiv1.Container{}, zuulContainer, statsdSidecar, nodeExporterSidecar) initContainer := base.MkContainer("init-scheduler-config", getZuulImage("zuul-scheduler")) initContainer.Command = []string{"/usr/local/bin/init-container.sh"} @@ -495,6 +498,7 @@ func (r *SFController) EnsureZuulScheduler(cfg *ini.File) bool { if corporateCMExists { initContainer.VolumeMounts = AppendCorporateCACertsVolumeMount(initContainer.VolumeMounts, "zuul-scheduler-corporate-ca-certs") } + base.SetContainerLimitsLowProfile(&initContainer) schedulerToolingData := make(map[string]string) schedulerToolingData["init-container.sh"] = zuulSchedulerInitContainerScript @@ -544,7 +548,7 @@ func (r *SFController) EnsureZuulExecutor(cfg *ini.File) bool { "zuul-common-config": utils.IniSectionsChecksum(cfg, commonIniConfigSections), "zuul-component-config": utils.IniSectionsChecksum(cfg, sections), "zuul-image": getZuulImage("zuul-executor"), - "serial": "6", + "serial": "7", "zuul-logging": utils.Checksum([]byte(r.getZuulLoggingString("zuul-executor"))), "zuul-connections": utils.IniSectionsChecksum(cfg, utils.IniGetSectionNamesByPrefix(cfg, "connection")), "corporate-ca-certs-version": getCMVersion(corporateCM, corporateCMExists), @@ -552,7 +556,9 @@ func (r *SFController) EnsureZuulExecutor(cfg *ini.File) bool { // TODO Add the zk-port-forward-kube-config secret resource version in the annotation if enabled ze := r.mkHeadlessSatefulSet("zuul-executor", "", r.getStorageConfOrDefault(r.cr.Spec.Zuul.Executor.Storage), apiv1.ReadWriteOnce) - ze.Spec.Template.Spec.Containers = r.mkZuulContainer("zuul-executor", corporateCMExists) + zuulContainer := r.mkZuulContainer("zuul-executor", corporateCMExists) + annotations["limits"] = base.UpdateContainerLimit(r.cr.Spec.Zuul.Executor.Limits, &zuulContainer) + ze.Spec.Template.Spec.Containers = []apiv1.Container{zuulContainer} ze.Spec.Template.Spec.Volumes = mkZuulVolumes("zuul-executor", r, corporateCMExists) zeFluentBitLabels := append(zuulFluentBitLabels, logging.FluentBitLabel{Key: "CONTAINER", Value: "zuul-executor"}) @@ -617,13 +623,15 @@ func (r *SFController) EnsureZuulMerger(cfg *ini.File) bool { "zuul-common-config": utils.IniSectionsChecksum(cfg, commonIniConfigSections), "zuul-component-config": utils.IniSectionsChecksum(cfg, sections), "zuul-image": getZuulImage(service), - "serial": "4", + "serial": "5", "zuul-connections": utils.IniSectionsChecksum(cfg, utils.IniGetSectionNamesByPrefix(cfg, "connection")), "corporate-ca-certs-version": getCMVersion(corporateCM, corporateCMExists), } zm := r.mkHeadlessSatefulSet(service, "", r.getStorageConfOrDefault(r.cr.Spec.Zuul.Merger.Storage), apiv1.ReadWriteOnce) - zm.Spec.Template.Spec.Containers = r.mkZuulContainer(service, corporateCMExists) + zuulContainer := r.mkZuulContainer(service, corporateCMExists) + annotations["limits"] = base.UpdateContainerLimit(r.cr.Spec.Zuul.Merger.Limits, &zuulContainer) + zm.Spec.Template.Spec.Containers = []apiv1.Container{zuulContainer} zm.Spec.Template.Spec.Volumes = mkZuulVolumes(service, r, corporateCMExists) zmFluentBitLabels := append(zuulFluentBitLabels, logging.FluentBitLabel{Key: "CONTAINER", Value: "zuul-merger"}) @@ -679,7 +687,9 @@ func (r *SFController) EnsureZuulWeb(cfg *ini.File) bool { } zw := base.MkDeployment("zuul-web", r.ns, "") - zw.Spec.Template.Spec.Containers = r.mkZuulContainer("zuul-web", false) + zuulContainer := r.mkZuulContainer("zuul-web", false) + annotations["limits"] = base.UpdateContainerLimit(r.cr.Spec.Zuul.Web.Limits, &zuulContainer) + zw.Spec.Template.Spec.Containers = []apiv1.Container{zuulContainer} zw.Spec.Template.Spec.Volumes = mkZuulVolumes("zuul-web", r, false) zwFluentBitLabels := append(zuulFluentBitLabels, logging.FluentBitLabel{Key: "CONTAINER", Value: "zuul-web"}) diff --git a/doc/deployment/zuul.md b/doc/deployment/zuul.md index 73473c3c..bb711575 100644 --- a/doc/deployment/zuul.md +++ b/doc/deployment/zuul.md @@ -17,12 +17,47 @@ but addresses specificities and idiosyncrasies induced by deploying Zuul with th Zuul is deployed by SF-Operator as micro-services: -| Service | Kubernetes resource type | Scalable Y/N | +| Component | Kubernetes resource type | Scalable Y/N | |---------|--------------------------|-------------| | zuul-scheduler | statefulset | N | | zuul-executor | statefulset | Y | +| zuul-merger | statefulset | Y | | zuul-web | deployment | N | + +### Zuul-scheduler Pod + +| Container | Type | R.Request (Mem/CPU) | R.Limit (Mem/CPU) | R.Limit Upgrade (Y/N) | +|---------|--------------------------|-------------|-----| --- | +| zuul-scheduler | normal | 128Mi/0.1CPU | 2Gi/2CPU | Y | +| zuul-scheduler-nodeexporter | normal | 32Mi/0.01CPU | 64Mi/0.1CPU | N | +| zuul-statsd | normal | 32Mi/0.01CPU | 64Mi/0.1CPU | N | +| init-scheduler-config | init | 32Mi/0.01CPU | 64Mi/0.1CPU | N | + +### Zuul-executor Pod + +| Container | Type | R.Request (Mem/CPU) | R.Limit (Mem/CPU) | R.Limit Upgrade (Y/N) | +|---------|--------------------------|-------------|-----| --- | +| zuul-executor | privileged | 128Mi/0.1CPU | 2Gi/2CPU | Y | +| zuul-executor-nodeexporter | normal | 32Mi/0.01CPU | 64Mi/0.1CPU | N | + +### Zuul-merger Pod + +| Container | Type | R.Request (Mem/CPU) | R.Limit (Mem/CPU) | R.Limit Upgrade (Y/N) | +|---------|--------------------------|-------------|-----| --- | +| zuul-merger | normal | 128Mi/0.1CPU | 2Gi/2CPU | Y | +| zuul-merger-nodeexporter | normal | 32Mi/0.01CPU | 64Mi/0.1CPU | N | + +### Zuul-web Pod + +| Container | Type | R.Request (Mem/CPU) | R.Limit (Mem/CPU) | R.Limit Upgrade (Y/N) | +|---------|--------------------------|-------------|-----| --- | +| zuul-web | normal | 128Mi/0.1CPU | 2Gi/2CPU | Y | + +## Resource limits + +For each component the main container's resource limits can be changed via the `SoftwareFactory` Custom Resource. + ## Services configuration Configuring the Zuul micro-services is done through the SoftwareFactory deployment's manifest. Many configuration parameters are exposed by The [SoftwareFactory Custom Resource spec](../deployment/crds.md#softwarefactory). diff --git a/doc/reference/CHANGELOG.md b/doc/reference/CHANGELOG.md index fd7dae24..9a844a40 100644 --- a/doc/reference/CHANGELOG.md +++ b/doc/reference/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [in development] ### Added + +- Default containers resources (requests and limits) +- A Limits Spec in the CRD for Zookeeper, MariaDB, Nodepool and Zuul components + ### Changed ### Deprecated ### Removed diff --git a/doc/reference/api/index.md b/doc/reference/api/index.md index f4780ed6..d35257dc 100644 --- a/doc/reference/api/index.md +++ b/doc/reference/api/index.md @@ -203,6 +203,28 @@ _Appears in:_ | `server` _[LEServer](#leserver)_ | Specify the Lets encrypt server. Valid values are: "staging", "prod" | -| +#### LimitsSpec + + + + + +_Appears in:_ +- [MariaDBSpec](#mariadbspec) +- [NodepoolBuilderSpec](#nodepoolbuilderspec) +- [NodepoolLauncherSpec](#nodepoollauncherspec) +- [ZookeeperSpec](#zookeeperspec) +- [ZuulExecutorSpec](#zuulexecutorspec) +- [ZuulMergerSpec](#zuulmergerspec) +- [ZuulSchedulerSpec](#zuulschedulerspec) +- [ZuulWebSpec](#zuulwebspec) + +| Field | Description | Default Value | +| --- | --- | --- | +| `memory` _[Quantity](https://pkg.go.dev/k8s.io/apimachinery@v0.28.2/pkg/api/resource#Quantity)_ | | {2Gi}| +| `cpu` _[Quantity](https://pkg.go.dev/k8s.io/apimachinery@v0.28.2/pkg/api/resource#Quantity)_ | | {2000m}| + + #### LogLevel _Underlying type:_ _string_ @@ -248,6 +270,7 @@ _Appears in:_ | --- | --- | --- | | `dbStorage` _[StorageSpec](#storagespec)_ | Storage parameters related to mariaDB's data | -| | `logStorage` _[StorageSpec](#storagespec)_ | Storage parameters related to the database's logging | -| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### NodepoolBuilderSpec @@ -263,6 +286,7 @@ _Appears in:_ | --- | --- | --- | | `storage` _[StorageSpec](#storagespec)_ | Storage related settings | -| | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the nodepool launcher process. Valid values are: "INFO" (default), "WARN", "DEBUG". | INFO| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### NodepoolLauncherSpec @@ -277,6 +301,7 @@ _Appears in:_ | Field | Description | Default Value | | --- | --- | --- | | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the nodepool launcher service. Valid values are: "INFO" (default), "WARN", "DEBUG". Changing this value will restart the service. | INFO| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### NodepoolSpec @@ -442,6 +467,7 @@ _Appears in:_ | Field | Description | Default Value | | --- | --- | --- | | `storage` _[StorageSpec](#storagespec)_ | | -| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### ZuulExecutorSpec @@ -459,6 +485,7 @@ _Appears in:_ | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the zuul-executor service. Valid values are: "INFO" (default), "WARN", "DEBUG". Changing this value will restart the service. | INFO| | `enabled` _boolean_ | If set to false, the zuul-executor deployment won't be applied | {true}| | `standalone` _[StandaloneZuulExecutorSpec](#standalonezuulexecutorspec)_ | When set the Control plane is not deployed. The standalone executor must be able to connect to the control plane | -| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### ZuulMergerSpec @@ -479,6 +506,7 @@ _Appears in:_ | `gitTimeout` _integer_ | the [git_timeout](https://zuul-ci.org/docs/zuul/latest/configuration.html#attr-merger.git_timeout) parameter | -| | `storage` _[StorageSpec](#storagespec)_ | Storage-related settings | -| | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the nodepool launcher service. Valid values are: "INFO" (default), "WARN", "DEBUG". Changing this value will restart the service. | INFO| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### ZuulOIDCAuthenticatorSpec @@ -520,6 +548,7 @@ _Appears in:_ | `storage` _[StorageSpec](#storagespec)_ | Storage-related settings | -| | `statsdTarget` _string_ | The address to forward statsd metrics to (optional), in the form "host:port" | -| | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the zuul-scheduler service. Valid values are: "INFO" (default), "WARN", "DEBUG". Changing this value will restart the service. | INFO| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}| #### ZuulSpec @@ -559,5 +588,6 @@ _Appears in:_ | Field | Description | Default Value | | --- | --- | --- | | `logLevel` _[LogLevel](#loglevel)_ | Specify the Log Level of the zuul-web launcher service. Valid values are: "INFO" (default), "WARN", "DEBUG". Changing this value will restart the service. | INFO| +| `limits` _[LimitsSpec](#limitsspec)_ | Memory/CPU Limit | {map[cpu:2000m memory:2Gi]}|