diff --git a/Dockerfile b/Dockerfile index 40a8846..395e6e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,45 @@ +############################################################################################################ +# BUILD +############################################################################################################ + FROM golang:1.21.0-alpine as builder ARG VERSION=development ENV VERSION=$VERSION -WORKDIR /opt/jenkins-autoscaler/ +WORKDIR /opt/jenkins-autoscaler + COPY . . -RUN apk add --no-cache git make \ - && make install + +RUN apk add --no-cache git make && make install + +############################################################################################################ +# RELEASE +############################################################################################################ FROM alpine:3.18 + LABEL maintainer "Bringg DevOps " -ENV JAS_CONFIG=/dev/null +ENV JAS_CONFIG=/opt/jenkins-autoscaler/config.yml RUN apk add --no-cache ca-certificates tzdata +# Envplate to dynamically change configurations +RUN wget -q https://github.com/kreuzwerker/envplate/releases/download/v1.0.2/envplate_1.0.2_$(uname -s)_$(uname -m).tar.gz -O - \ + | tar xz \ + && mv envplate /usr/local/bin/ep \ + && chmod +x /usr/local/bin/ep + +WORKDIR /opt/jenkins-autoscaler + COPY --from=builder /go/bin/jas /usr/local/bin +COPY --from=builder --chown=nobody:nobody /opt/jenkins-autoscaler/docker.config.yml /opt/jenkins-autoscaler/config.yml USER nobody EXPOSE 8080 -ENTRYPOINT ["jas"] + +ENTRYPOINT [ "sh", "-c", "/usr/local/bin/ep /opt/jenkins-autoscaler/config.yml && /usr/local/bin/jas --backend=${BACKEND}" ] + +############################################################################################################ \ No newline at end of file diff --git a/Dockerfile.development b/Dockerfile.development new file mode 100644 index 0000000..18e356f --- /dev/null +++ b/Dockerfile.development @@ -0,0 +1,23 @@ +FROM golang:1.21.0-alpine as builder + +ARG VERSION=development +ENV VERSION=$VERSION + +WORKDIR /opt/jenkins-autoscaler/ +COPY . . +RUN apk add --no-cache git make \ + && make install + +FROM alpine:3.18 +LABEL maintainer "Bringg DevOps " + +ENV JAS_CONFIG=/dev/null + +RUN apk add --no-cache ca-certificates tzdata + +COPY --from=builder /go/bin/jas /usr/local/bin + +USER nobody + +EXPOSE 8080 +ENTRYPOINT ["jas"] \ No newline at end of file diff --git a/README.md b/README.md index 71ff734..3b41309 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,60 @@ backend: jas --backend=gce -c ./configs/my-jenkins-autoscaler.yaml ``` +## Docker + +The following configurations can be used when running this in Docker or Kubernetes. + +**DOCKER BUILD** + +```bash +docker build --platform linux/amd64 -t jenkins-autoscaler:latest . +``` + +**DOCKER RUN** + +```bash +docker run -it \ + -e BACKEND='aws' \ + -e JENKINS_URL='https://jenkins.example.com' \ + -e JENKINS_USER='jenkins@example.com' \ + -e JENKINS_TOKEN='ed5054431488809e8cb6b35f2e9a7bc3' \ + -e CONTROLLER_NODE_NAME='master' \ + -e AWS_AUTOSCALING_GROUP_NAME='jenkins-slaves' \ + jenkins-autoscaler:latest +``` + +**DOCKER ENVIRONMENT VARIABLES** + +| Name | Description | Default | Required | +| -------------------------------------------- | ------------------------------------------------------------ | :------------: | :------: | +| BACKEND | Backend type. Accepted values are either **gce** or **aws** | N/A | YES | +| DRY_RUN | Enable dry-run mode | true | NO | +| LOG_LEVEL | Log level | error | NO | +| RUN_INTERVAL | Interval of the main scaler loop | 1m | NO | +| GC_RUN_INTERVAL | Interval of the gc loop | 1h | NO | +| JENKINS_URL | Jenkins server base url | N/A | YES | +| JENKINS_USER | Jenkins username | N/A | NO | +| JENKINS_TOKEN | Jenkins api token | N/A | NO | +| NODES_WITH_LABEL | Target nodes that have the specified label | N/A | NO | +| METRICS_SERVER_ADDR | Address of http metrics server | :8080 | NO | +| CONTROLLER_NODE_NAME | The built-in Jenkins node name (aka master) | Built-In Node | NO | +| MAX_NODES | Maximum number of nodes at any given time | 1 | NO | +| NODE_NUM_EXECUTORS | Number of executors per node | 1 | NO | +| MIN_NODES_DURING_WORKING_HOURS | The minimum number of nodes to maintain during working hours | 2 | NO | +| SCALE_UP_THRESHOLD | The threshold usage percentage for triggering a scale-up | 70 | NO | +| SCALE_DOWN_THRESHOLD | The threshold usage percentage for triggering a scale-down | 30 | NO | +| SCALE_UP_GRACE_PERIOD | The duration to wait before performing another scale-up | 5m | NO | +| SCALE_DOWN_GRACE_PERIOD | The duration to wait before performing another scale-down | 10m | NO | +| SCALE_DOWN_GRACE_PERIOD_DURING_WORKING_HOURS | The cooldown timer duration in minutes for scale-down during working hours | 10m | NO | +| WORKING_HOURS_CRON_EXPRESSIONS | The specified cron expression representing the range of working hours | * 5-17 * * 1-5 | NO | +| DISABLE_WORKING_HOURS | Do not consider working hours for scaling down | true | NO | +| AWS_AUTOSCALING_GROUP_NAME | The AWS autoscaling group name for the jenkins slave nodes. This field is **mandatory** only when the backend is set to **aws** | N/A | YES | +| AWS_REGION | AWS region | us-east-1 | NO | +| GCE_PROJECT | The GCE project name. This field is **mandatory** only when the backend is set to **gce** | N/A | YES | +| GCE_REGION | GCE region | us-east1 | NO | +| GCE_INSTANCE_GROUP_MANAGER | The GCE instance group manager name for the jenkins slave nodes. This field is **mandatory** only when the backend is set to **gce** | N/A | YES | + ## Contribution Feel free to open Pull-Request for small fixes and changes. For bigger changes and new backends please open an issue first to prevent double work and discuss relevant stuff. diff --git a/docker.config.yml b/docker.config.yml new file mode 100644 index 0000000..30c74a5 --- /dev/null +++ b/docker.config.yml @@ -0,0 +1,30 @@ +scaler: + dry_run: ${DRY_RUN:-false} + log_level: ${LOG_LEVEL:-error} + run_interval: ${RUN_INTERVAL:-1m} + gc_run_interval: ${GC_RUN_INTERVAL:-1h} + jenkins_url: ${JENKINS_URL} + jenkins_user: ${JENKINS_USER:-""} + jenkins_token: ${JENKINS_TOKEN:-""} + nodes_with_label: ${NODES_WITH_LABEL:-} + metrics_server_addr: ${METRICS_SERVER_ADDR:-:8080} + controller_node_name: ${CONTROLLER_NODE_NAME:-Built-In Node} + max_nodes: ${MAX_NODES:-1} + node_num_executors: ${NODE_NUM_EXECUTORS:-1} + min_nodes_during_working_hours: ${MIN_NODES_DURING_WORKING_HOURS:-2} + scale_up_threshold: ${SCALE_UP_THRESHOLD:-70} + scale_down_threshold: ${SCALE_DOWN_THRESHOLD:-30} + scale_up_grace_period: ${SCALE_UP_GRACE_PERIOD:-5m} + scale_down_grace_period: ${SCALE_DOWN_GRACE_PERIOD:-10m} + scale_down_grace_period_during_working_hours: ${SCALE_DOWN_GRACE_PERIOD_DURING_WORKING_HOURS:-10m} + working_hours_cron_expressions: ${WORKING_HOURS_CRON_EXPRESSIONS:-* 5-17 * * 1-5} + disable_working_hours: ${DISABLE_WORKING_HOURS:-true} + +backend: + gce: + project: ${GCE_PROJECT:-} + region: ${GCE_REGION:-us-east1} + instance_group_manager: ${GCE_INSTANCE_GROUP_MANAGER:-} + aws: + autoscaling_group_name: ${AWS_AUTOSCALING_GROUP_NAME:-} + region: ${AWS_REGION:-us-east-1}