diff --git a/.github/workflows/instana-gitops-update.yml b/.github/workflows/instana-gitops-update.yml index d663a4a..e0be0c0 100644 --- a/.github/workflows/instana-gitops-update.yml +++ b/.github/workflows/instana-gitops-update.yml @@ -9,22 +9,25 @@ ### For more information on the Instana GitHub action for GitOps update, refer to: ### https://github.com/instana/github-action-update-agent-configurations -name: Instana GitOps update +name: Instana GitOps update - Prod on: push: + paths-ignore: + - 'renovate.json' + - 'README.md' branches: [ main ] jobs: - build: + push-gitops-config: runs-on: ubuntu-latest steps: - uses: instana/github-action-update-agent-configurations@v1.0.0 with: # At least one of 'agent_zone' and 'agent_tags' should be set - agent_zone: my_zone - agent_tags: 'gitops_environment=prod' + agent_zone: gitops-demo + agent_tags: gitops_environment=prod env: INSTANA_API_ENDPOINT: ${{ secrets.INSTANA_API_ENDPOINT }} INSTANA_API_TOKEN: ${{ secrets.INSTANA_API_TOKEN }} diff --git a/.github/workflows/sync-agent-version-to-main.yml b/.github/workflows/sync-agent-version-to-main.yml new file mode 100644 index 0000000..e963af1 --- /dev/null +++ b/.github/workflows/sync-agent-version-to-main.yml @@ -0,0 +1,66 @@ +# This workflow is used to create a PR with the existing agent version from the test branch to main + +name: Sync Agent Version to main + +# Controls when the workflow will run +on: + push: + branches: [ "test" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + open-pr: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a set of commands using the runners shell + - name: Copy AgentBootrap to main + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: | + echo "Showing content of current AgentBootstrap" + cat instana/com.instana.agent.bootstrap.AgentBootstrap.cfg + rm -f /tmp/com.instana.agent.bootstrap.AgentBootstrap.cfg + echo "Create temporary copy of the configuration file" + cp instana/com.instana.agent.bootstrap.AgentBootstrap.cfg /tmp/ + echo "Checking out main branch" + git fetch origin main + git checkout main + echo "Creating new branch from main" + git checkout -b promote-test-to-main + echo "Replace config file on main" + rm -f instana/com.instana.agent.bootstrap.AgentBootstrap.cfg + cp -f /tmp/com.instana.agent.bootstrap.AgentBootstrap.cfg instana/com.instana.agent.bootstrap.AgentBootstrap.cfg + echo "Check if file was changed" + if [[ `git status --porcelain` ]]; then + echo "The file has changed, continue to commit and push" + else + echo "The file is unchanged, main is already in sync with test branch, no further action needed" + exit 0 + fi + + echo "Setting git author" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git config --global user.name "${GITHUB_ACTOR}" + echo "Commiting change" + git add instana/com.instana.agent.bootstrap.AgentBootstrap.cfg + git commit -m "chore: Sync AgentBootstrap from current test branch" + echo "Push change to feature branch" + git push origin -f promote-test-to-main + UPDATED_VERSION=$(cat instana/com.instana.agent.bootstrap.AgentBootstrap.cfg | grep "version = " | grep -v "#" | cut -c11-) + PR_TITLE="chore(deps): Update Instana Agent Production to v${UPDATED_VERSION}" + echo "Automated sync of instana/com.instana.agent.bootstrap.AgentBootstrap.cfg from branch \"test\" to \"main\"." > body-file.txt + echo "Make sure that the test environment works as expected before approving and merging the change." >> body-file.txt + echo "Merging will **trigger an production update including an agent restart**." >> body-file.txt + echo "" >> body-file.txt + echo "This update was driven by [this GitHub Action Workflow](https://github.com/instana/gitops-demo/blob/test/.github/workflows/sync-agent-version-to-main.yml)." >> body-file.txt + echo "Available Instana Agent tags can be found on the [instana/agent-updates](https://github.com/instana/agent-updates/tags) repository." >> body-file.txt + gh pr create -B main --title "${PR_TITLE}" --body-file "body-file.txt" --label "production" || \ + gh pr edit -B main --title "${PR_TITLE}" --body-file "body-file.txt" --add-label "production" diff --git a/README.md b/README.md index 56ee66a..fb35553 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,122 @@ The [.github/workflows/instana-gitops-update.yml](.github/workflows/instana-gito * [Instana's Git-based Configuration Management documentation](https://www.instana.com/docs/setup_and_manage/host_agent/configuration/git_ops#with-the-api) * [Instana GitHub action for GitOps](https://github.com/instana/github-action-update-agent-configurations) * [Githooks documentation](https://git-scm.com/docs/githooks) + + +## Quickstart + +### Preparing the repository + +Fork this repository to get started or copy files as desired to a new git repository. + +Change files in the [instana](./instana) folder to match the new target environment. Ensure to change files on branches `main` for production and on branch `test` for the test environment. + +To be able to run the GitHub Actions Workflows, define credentials for the Instana backend and a GitHub personal access token. + +To generate an Instana backend token, login into the Instana UI and navigate to `Settings > Team Settings > API Tokens > New API Token` and select the `Configuration of agents` permission and `Save`. + +![](./images/generate-api-token-instana-backend.png) + +The GitHub workflow which promotes changes from the `test` branch to `main` requires access to the GitHub repository via GitHub Personal Access Token which can be generated in GitHub's Developer Settings > [New personal access token (classic)](https://github.com/settings/tokens/new). +The access token requires permission on the forked repository and the following repository permissions: + +- repo > public repo + +If the repository is not public, permission to access a private repository is also required. + +In the GitHub settings of the gitops repository navigate to `Secrets and variables > Actions` and define the following entries as repository secrets: + +- `GH_TOKEN`: Personal access token for the GitHub API +- `INSTANA_API_ENDPOINT`: URL used for the Instana login, e.g.: https://qa-instana.instana.io +- `INSTANA_API_TOKEN`: API token for the Instana API + +To receive updates via renovate, install the [Renovate GitHub App](https://github.com/apps/renovate) on this repository. + +### Installing the agents + +Installing and configuring new agents to pull updates from this repository can be performed during installation or by changing configuration of existing agents. + +By defining `main` as branch name new agents will be onboarded with production configuration, choosing `test` will apply the configuration of the test branch from this repository. + +**Linux Host agents via One-Line-Installer**: + +```#!/bin/bash +curl -o setup_agent.sh https://setup.instana.io/agent && chmod 700 ./setup_agent.sh && sudo ./setup_agent.sh \ + -a xxx \ + -d xxx \ + -t dynamic \ + -e ingress-red-saas.instana.io:443 \ + -s \ + -g https://github.com/instana/gitops-demo.git \ + -b test +``` + +**Docker based installation** + +```#!/bin/bash +docker run \ + --detach \ + --name instana-agent \ + --volume /var/run:/var/run \ + --volume /run:/run \ + --volume /dev:/dev:ro \ + --volume /sys:/sys:ro \ + --volume /var/log:/var/log:ro \ + --privileged \ + --net=host \ + --pid=host \ + --env="INSTANA_AGENT_ENDPOINT=ingress-red-saas.instana.io" \ + --env="INSTANA_AGENT_ENDPOINT_PORT=443" \ + --env="INSTANA_AGENT_KEY=xxx" \ + --env="INSTANA_DOWNLOAD_KEY=xxx" \ + --env="INSTANA_GIT_REMOTE_BRANCH=test" \ + --env="INSTANA_GIT_REMOTE_REPOSITORY=https://github.com/instana/gitops-demo.git" \ + icr.io/instana/agent +``` + +**Manual mode** + +Export the environment variables `INSTANA_GIT_REMOTE_BRANCH`, `INSTANA_GIT_REMOTE_REPOSITORY` and optional credentials (`INSTANA_GIT_REMOTE_USERNAME`, `INSTANA_GIT_REMOTE_PASSWORD`) in case of a private repository to the instana agent process. This can e.g. be achieved via systemd, see also the [Instana Documentation](https://www.ibm.com/docs/en/instana-observability/current?topic=agents-git-based-configuration-management) for more details. + +The examples above onboard a new agent to the test environment, if the agent should join the production group, define `main` instead of `test` as `INSTANA_GIT_REMOTE_REPOSITORY`. + +**Configuring Git-based configuration management on existing agents** + +An existing host agent can be configured to pull changes from a git repository. Navigate into the Instana UI and open the Agent Dashboard. Click on the `Initialize` button shown in the `Configuration Management` section. After entering the details and clicking on `Initialize & Restart` the configuration will be loaded and applied. + +![enable-git-configuration-on-existing-agent](./images/enable-git-configuration-on-existing-agent.png) + +Note: After applying new agent versions, it can take up to a few minutes before the new version is shown correctly in the Agent Dashboard view, as values are cached. + +## Update Workflow + +This project uses [renovate](https://github.com/apps/renovate) to automatically watch the [instana/agent-updates](https://github.com/instana/agent-updates/tags) repositories for new tags and to create a pull request (PR) against the `test` branch. + +![renovate-pr](./images/renovate-pull-request.png) + +Once the PR was reviewed and merged, GitHub Actions will run a workflow to send an update request to the configured Instana backend. +A second workflow is triggered to open a PR with changes from the `test` branch against the `main` branch. + +![pr-sync-test-to-main](./images/pr-sync-test-to-main.png) + +This is meant to be a quality gate which provides an option for customers to validate a new agent version in their given environment before pushing it out to production. When the new agent version is validated the PR against `main` can be merged and the update gets promoted by a GitHub Actions workflow which notifies the Instana backend to send update requests to the selected agent groups. + +In the given example, it is assumed that all systems in the test or production group will receive updates at once. If a staged rollout is desired, more detailed tags can be defined or more branches can be used so that update requests could be send in batches via additional steps in the GitHub Actions workflow. + +The intial update PRs against the `test` branch are raised by [renovate](https://github.com/renovatebot/renovate). It is parsing the comment defined in [instana-gitops-update.yml](.github/workflows/instana-gitops-update.yml) to detect where to search for new instana agent tags in GitHub: + +``` +# renovate: datasource=github-tags depName=instana/agent-updates versioning=loose +version = 2024.08.20.0843 +``` + +The [renovate configuration](./renovate.json) defines a regular expression to match the version number and to replace it with the new tags on a feature branch. The feature branch is used in a PR against the `test` branch. Renovate will always check the `renovate.json` found on the main branch, but it can define base branches to update (in this example, it only proposes updates to branch `test`). For more details see the [renovate documentation](https://docs.renovatebot.com/modules/manager/regex/). + +GitHub Actions will use the workflow definitions of the branch which currently triggered the action. A push to the `test` branch will therefore trigger the GitHub workflow store in the `test` branch rather than the definition stored in `main`. + +## Usage of different tooling + +This repository uses GitHub Actions to send agent update requests to the Instana Backend and uses a reusable GitHub Action for that purpuse. If other CI tools like Jenkins or Tekton should be used, any HTTP client can be leveraged to send a request, see the usage of `curl` in the [GitHub Action definition](https://github.com/instana/github-action-update-agent-configurations/blob/master/entrypoint.sh) for more details. + +To get automatic update notifications, renovate was used in this example. Renovate can be installed as GitHub app, but it can be self-hosted on own infrastructure if prefered. +If renovate should not be used at all, tags can be updates manually or by running scripts periodically. diff --git a/images/enable-git-configuration-on-existing-agent.png b/images/enable-git-configuration-on-existing-agent.png new file mode 100644 index 0000000..02f8db8 Binary files /dev/null and b/images/enable-git-configuration-on-existing-agent.png differ diff --git a/images/generate-api-token-instana-backend.png b/images/generate-api-token-instana-backend.png new file mode 100644 index 0000000..4bbc5b3 Binary files /dev/null and b/images/generate-api-token-instana-backend.png differ diff --git a/images/pr-sync-test-to-main.png b/images/pr-sync-test-to-main.png new file mode 100644 index 0000000..fcf22f4 Binary files /dev/null and b/images/pr-sync-test-to-main.png differ diff --git a/images/renovate-pull-request.png b/images/renovate-pull-request.png new file mode 100644 index 0000000..7974ae8 Binary files /dev/null and b/images/renovate-pull-request.png differ diff --git a/instana/com.instana.agent.bootstrap.AgentBootstrap.cfg b/instana/com.instana.agent.bootstrap.AgentBootstrap.cfg new file mode 100644 index 0000000..f3129b5 --- /dev/null +++ b/instana/com.instana.agent.bootstrap.AgentBootstrap.cfg @@ -0,0 +1,10 @@ +# This field specifies which version set of components should be used by the agent; +# its value must be a valid tag from https://github.com/instana/agent-updates/tags +# version = +# renovate: datasource=github-tags depName=instana/agent-updates versioning=loose +version = 2024.08.20.0843 + +# This field controls which set of components is used by the agent at runtime. +productName = ${env:INSTANA_PRODUCT_NAME} + +origin = package dynamic diff --git a/instana/configuration-test.yaml b/instana/configuration-test.yaml deleted file mode 100644 index 4dad782..0000000 --- a/instana/configuration-test.yaml +++ /dev/null @@ -1,3 +0,0 @@ -com.instana.plugin.host: - tags: - - gitops_environment=prod diff --git a/instana/configuration.yaml b/instana/configuration.yaml new file mode 100644 index 0000000..e7366aa --- /dev/null +++ b/instana/configuration.yaml @@ -0,0 +1,6 @@ +com.instana.plugin.host: + tags: + - gitops_environment=prod +com.instana.plugin.generic.hardware: + enabled: true + availability-zone: gitops-demo diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..6c06953 --- /dev/null +++ b/renovate.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended", ":dependencyDashboard"], + "baseBranches": ["test"], + "customManagers": [ + { + "customType": "regex", + "fileMatch": ["instana/com.instana.agent.bootstrap.AgentBootstrap.cfg"], + "matchStrings": [ + "# renovate: datasource=(?[a-z-]+?)(?: depName=(?.*?))(?: versioning=(?[a-z-]+?))?\\sversion\\s=\\s(?.+?)\\s" + ], + "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}" + } + ] +}