diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 12850e00..0751929d 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -23,6 +23,8 @@ env: AGENT_VERSION: 3.218.0 # https://github.com/PowerShell/PowerShell/releases POWERSHELL_VERSION: 7.2.10 + # https://github.com/krallin/tini/releases + TINI_VERSION: 0.19.0 # https://github.com/mikefarah/yq/releases YQ_VERSION: 4.33.2 @@ -186,6 +188,7 @@ jobs: build-args: | "AGENT_VERSION=${{ env.AGENT_VERSION }}" "POWERSHELL_VERSION=${{ env.POWERSHELL_VERSION }}" + "TINI_VERSION=${{ env.TINI_VERSION }}" "YQ_VERSION=${{ env.YQ_VERSION }}" cache-from: type=gha cache-to: type=gha,mode=max diff --git a/README.md b/README.md index 740e3191..74c8dacb 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,9 @@ helm upgrade --install agent clemlesne-azure-pipelines-agent/azure-pipelines-age Capabilities are declarative variables you can add to the agents, to allow developers to select the right agent for their pipeline ([official documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/demands?view=azure-devops&tabs=yaml)). -Note, you can add multiple Helm instances to the same agent pool. Then, disctinct them by capabilities. For examples: +> Note, you can add multiple Helm instances to the same agent pool. It will result in a single pool with multiple capabilities. Be warning, if a capability is not unique accross the pool, all the agents will scale. This will create "zoombies" agents, scaled for nothing, waiting their timeout. + +Disctinct the agents by capabilities. For examples: - A pool of AMD64 agents, and a pool of ARM64 agents - A pool of agents with GPU, and a pool of agents without GPU @@ -84,6 +86,8 @@ Take the assumption we want to host a specific instance pool to ARM servers. # values.yaml pipelines: pool: Kubernetes + capabiliies: + - arch-arm64 affinity: nodeAffinity: @@ -110,7 +114,7 @@ pool: name: Kubernetes demands: - Agent.OS -equals Linux - - Agent.OSArchitecture -equals ARM64 + - arch-arm64 stages: ... diff --git a/src/docker/Dockerfile-bullseye b/src/docker/Dockerfile-bullseye index 750130fa..b5985bfa 100644 --- a/src/docker/Dockerfile-bullseye +++ b/src/docker/Dockerfile-bullseye @@ -75,6 +75,14 @@ RUN curl -LsSf https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/ && chmod +x /usr/bin/yq \ && yq --version +# Install Tini, then verify installation +ARG TINI_VERSION +ENV TINI_VERSION ${TINI_VERSION} +RUN curl -LsSf https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$(ARCH_AMD64=amd64 bash arch.sh) -o /tini \ + && chmod +x /tini \ + && /tini --version +ENTRYPOINT ["/tini", "--"] + # Cleanup helper script RUN rm arch.sh @@ -84,5 +92,4 @@ WORKDIR ${AGENT_HOME} # Install Azure Pipelines Agent startup script COPY start.sh . RUN chmod +x start.sh - CMD bash start.sh diff --git a/src/docker/Dockerfile-focal b/src/docker/Dockerfile-focal index fa4427b6..2b1a02e8 100644 --- a/src/docker/Dockerfile-focal +++ b/src/docker/Dockerfile-focal @@ -75,6 +75,14 @@ RUN curl -LsSf https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/ && chmod +x /usr/bin/yq \ && yq --version +# Install Tini, then verify installation +ARG TINI_VERSION +ENV TINI_VERSION ${TINI_VERSION} +RUN curl -LsSf https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$(ARCH_AMD64=amd64 bash arch.sh) -o /tini \ + && chmod +x /tini \ + && /tini --version +ENTRYPOINT ["/tini", "--"] + # Cleanup helper script RUN rm arch.sh @@ -84,5 +92,4 @@ WORKDIR ${AGENT_HOME} # Install Azure Pipelines Agent startup script COPY start.sh . RUN chmod +x start.sh - CMD bash start.sh diff --git a/src/docker/Dockerfile-jammy b/src/docker/Dockerfile-jammy index 47b211c2..587dc4be 100644 --- a/src/docker/Dockerfile-jammy +++ b/src/docker/Dockerfile-jammy @@ -75,6 +75,14 @@ RUN curl -LsSf https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/ && chmod +x /usr/bin/yq \ && yq --version +# Install Tini, then verify installation +ARG TINI_VERSION +ENV TINI_VERSION ${TINI_VERSION} +RUN curl -LsSf https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$(ARCH_AMD64=amd64 bash arch.sh) -o /tini \ + && chmod +x /tini \ + && /tini --version +ENTRYPOINT ["/tini", "--"] + # Cleanup helper script RUN rm arch.sh @@ -84,5 +92,4 @@ WORKDIR ${AGENT_HOME} # Install Azure Pipelines Agent startup script COPY start.sh . RUN chmod +x start.sh - CMD bash start.sh diff --git a/src/docker/Dockerfile-ubi8 b/src/docker/Dockerfile-ubi8 index 04bd98ea..9c4b918e 100644 --- a/src/docker/Dockerfile-ubi8 +++ b/src/docker/Dockerfile-ubi8 @@ -73,6 +73,14 @@ RUN curl -LsSf https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/ && chmod +x /usr/bin/yq \ && yq --version +# Install Tini, then verify installation +ARG TINI_VERSION +ENV TINI_VERSION ${TINI_VERSION} +RUN curl -LsSf https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$(ARCH_AMD64=amd64 bash arch.sh) -o /tini \ + && chmod +x /tini \ + && /tini --version +ENTRYPOINT ["/tini", "--"] + # Cleanup helper script RUN rm arch.sh @@ -82,5 +90,4 @@ WORKDIR ${AGENT_HOME} # Install Azure Pipelines Agent startup script COPY start.sh . RUN chmod +x start.sh - CMD bash start.sh diff --git a/src/docker/start.sh b/src/docker/start.sh index 533210fb..ed2bebf9 100644 --- a/src/docker/start.sh +++ b/src/docker/start.sh @@ -6,18 +6,11 @@ if [ -z "$AZP_URL" ]; then exit 1 fi -if [ -z "$AZP_TOKEN_FILE" ]; then - if [ -z "$AZP_TOKEN" ]; then - echo 1>&2 "error: missing AZP_TOKEN environment variable" - exit 1 - fi - - AZP_TOKEN_FILE=/azp/.token - echo -n $AZP_TOKEN >"$AZP_TOKEN_FILE" +if [ -z "$AZP_TOKEN" ]; then + echo 1>&2 "error: missing AZP_TOKEN environment variable" + exit 1 fi -unset AZP_TOKEN - if [ -n "$AZP_WORK" ]; then mkdir -p "$AZP_WORK" fi @@ -25,36 +18,23 @@ fi print_header() { lightcyan='\033[1;36m' nocolor='\033[0m' - echo -e "${lightcyan}$1${nocolor}" + echo -e "${lightcyan}➡️ $1${nocolor}" } print_header "Configuring agent..." -# Allow the agent to run as root (only feasible because the agent is running in a not-reused container) -export AGENT_ALLOW_RUNASROOT="1" -# Let the agent ignore the token env variables -export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE - bash config.sh \ --acceptTeeEula \ --agent "${AZP_AGENT_NAME:-$(hostname)}" \ --auth PAT \ --pool "${AZP_POOL:-Default}" \ --replace \ - --token $(cat "$AZP_TOKEN_FILE") \ + --token "$AZP_TOKEN" \ --unattended \ --url "$AZP_URL" \ - --work "${AZP_WORK:-_work}" & - -# Fake the exit code of the agent for the prevent Kubernetes to detect the pod as failed (this is intended) -# See: https://stackoverflow.com/a/62183992/12732154 -wait $! + --work "${AZP_WORK:-_work}" print_header "Running agent..." # Running it with the --once flag at the end will shut down the agent after the build is executed -bash run-docker.sh "$@" --once & - -# Fake the exit code of the agent for the prevent Kubernetes to detect the pod as failed (this is intended) -# See: https://stackoverflow.com/a/62183992/12732154 -wait $! +bash run-docker.sh "$@" --once diff --git a/src/helm/azure-pipelines-agent/templates/deployment.yaml b/src/helm/azure-pipelines-agent/templates/deployment.yaml index ada394bb..9692d30b 100644 --- a/src/helm/azure-pipelines-agent/templates/deployment.yaml +++ b/src/helm/azure-pipelines-agent/templates/deployment.yaml @@ -39,7 +39,15 @@ spec: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository | required "A value for .Values.image.repository is required" }}:{{ .Values.image.flavor | required "A value for .Values.image.flavor is required" }}-{{ .Values.image.version | default .Chart.Version }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + lifecycle: + preStop: + exec: + command: [bash, -c, "./config.sh remove --auth PAT --token $AZP_TOKEN"] env: + - name: VSO_AGENT_IGNORE + value: AZP_TOKEN + - name: AGENT_ALLOW_RUNASROOT + value: "1" - name: AZP_AGENT_NAME valueFrom: fieldRef: diff --git a/src/helm/azure-pipelines-agent/templates/hpa.yaml b/src/helm/azure-pipelines-agent/templates/hpa.yaml index 81802f87..4e9e254d 100644 --- a/src/helm/azure-pipelines-agent/templates/hpa.yaml +++ b/src/helm/azure-pipelines-agent/templates/hpa.yaml @@ -47,7 +47,15 @@ spec: {{- toYaml .Values.securityContext | nindent 14 }} image: "{{ .Values.image.repository | required "A value for .Values.image.repository is required" }}:{{ .Values.image.flavor | required "A value for .Values.image.flavor is required" }}-{{ .Values.image.version | default .Chart.Version }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + lifecycle: + preStop: + exec: + command: [bash, -c, "./config.sh remove --auth PAT --token $AZP_TOKEN"] env: + - name: VSO_AGENT_IGNORE + value: AZP_TOKEN + - name: AGENT_ALLOW_RUNASROOT + value: "1" - name: AZP_AGENT_NAME valueFrom: fieldRef: