<p>I am trying to understand the Gitlab K8s agent. But it looks like it requires the developer to commit changes to a manifest file before it can deploy them to K8s. This is a challenge when trying to do auto deploys using Gitlab pipelines because those pipelines run after the commit. So how is the user supposed to create a new commit in an automated way that the Gitlab K8s agent can pick up?</p>
<p>I am wondering if anyone is using Gitlab and their K8s agent for auto deploying to K8s. Would really appreciate if you could throw some light on this.</p>

crossvalidator
<p>Note that the traditional <a href="https://docs.gitlab.com/ee/user/clusters/agent/gitops/agent.html" rel="nofollow noreferrer">GitOps with the agent for Kubernetes</a> has been deprecated with GitLab 16.2 (July 2023), and <a href="https://docs.gitlab.com/ee/user/clusters/agent/gitops.html" rel="nofollow noreferrer">replaced with Flux</a>, as shown <a href="https://docs.gitlab.com/ee/user/clusters/agent/gitops/flux_tutorial.html" rel="nofollow noreferrer">in this tutorial</a>.</p>
<p>But still, a traditional approach can still work, with a bridge between the CI/CD pipeline and the GitOps workflow:</p>
<p>As part of your CI/CD pipeline, whenever you merge a project file, create or update the manifest files accordingly. That could be based on templates, dynamic values, or any other logic appropriate for your application.</p>
<p>Once the manifests are generated or updated, you should commit them back to the repository. That step is crucial because the GitLab Kubernetes Agent is watching the repository for changes in manifest files.<br />
You should add <code>[skip ci]</code> to the commit messages for auto-commits to prevent infinite loops of CI/CD pipeline runs.</p>
<p>For instance:</p>
<pre class="lang-yaml prettyprint-override"><code>stages:
  - build
  - deploy

build:
  stage: build
  script:
    - echo &quot;Build steps for your application&quot;
    # Potentially other build steps ...

generate_and_commit_manifests:
  stage: deploy
  script:
    - echo &quot;Generating/Updating manifests for $CI_COMMIT_SHORT_SHA&quot;
    - ./generate-or-update-manifests.sh $CI_COMMIT_SHORT_SHA
    - git add path/to/manifests/*
    - git commit -m &quot;Auto-update manifests for $CI_COMMIT_SHORT_SHA [skip ci]&quot;
    - git push origin $CI_COMMIT_REF_NAME

deploy_stage:
  stage: deploy
  environment:
    name: stage
  script:
    - echo &quot;That is where you would traditionally deploy to staging, but it is now handled by the GitOps process&quot;
  when: manual

deploy_production:
  stage: deploy
  environment:
    name: production
  script:
    - echo &quot;That is where you would traditionally deploy to production, but it is now handled by the GitOps process&quot;
  when: manual
</code></pre>
<p>The build job will run, building your application.</p>
<p>The <code>generate_and_commit_manifests</code> job will run, updating the manifest files as necessary and committing them back to the repository. That commit will be noticed by the GitLab Kubernetes Agent, which will then apply the manifests to your Kubernetes cluster.</p>
<p>The <code>deploy_stage</code> and <code>deploy_production</code> jobs will be available to run manually, but they are more symbolic in this setup, since the actual deployment is handled by the GitLab Kubernetes Agent.</p>
<p>With this strategy, you are making use of both traditional CI/CD and GitOps workflows. The actual application build and preparation happens in the CI/CD pipeline, while the deployment is managed in a GitOps manner by the GitLab Kubernetes Agent.</p>
<hr />
<blockquote>
<p>On the other hand, as of today, this is what we are doing:</p>
<p>Let's suppose we need to merge a code change, by code change, I mean some feature code, as if we need to change <code>Payment.java</code> or <code>Payment.py</code> file, some project related code.</p>
<p>As of today, imagine an angry manager, who would force us:</p>
<blockquote>
<p>&quot;for each and every comit/merge on a code file, you also need to manually change the <code>kubernetes/staging/payment-staging-manifest.yml</code>&quot;.</p>
</blockquote>
<p>He would also say:</p>
<blockquote>
<p>&quot;if I see a commit, merge, without the manual change, fired!&quot;</p>
</blockquote>
</blockquote>
<p>Your hypothetical scenario with the &quot;angry manager&quot; makes the challenge clearer: essentially, your team is being asked to ensure that every commit or merge involving a code change must <em>also</em> involve a corresponding change to the Kubernetes manifest file, or else... there are consequences.</p>
<p>That requirement calls for automation, as the ideal way to address this requirement without increasing the manual overhead for developers.</p>
<p>A first good practice is to embed the version/commit info in the application: Each time the code is built (e.g., during a CI job), embed the commit hash or another unique identifier in the application. That could be an environment variable, a file in the build, etc.</p>
<p>Then, after the application is built and before it is deployed, have a step in your CI/CD pipeline that automatically updates the Kubernetes manifest to use this new version.</p>
<ul>
<li>For instance, if you are using Docker and Kubernetes, every build of your application could produce a new Docker image with a tag corresponding to the commit hash.</li>
<li>Your CI/CD pipeline would then automatically update the manifest to use this new image.</li>
</ul>
<p>And once the manifest is updated, auto-commit and push this change back to your repository. Ensure you use a commit message tag like <code>[skip ci]</code> to prevent infinite CI loops.</p>
<p>Since the GitLab Kubernetes Agent is already watching for changes in the manifest, it will pick up this auto-committed change and deploy it.</p>
<p>Something like:</p>
<pre class="lang-yaml prettyprint-override"><code>update-manifest:
  stage: deploy
  script:
    - COMMIT_HASH=$(git rev-parse --short HEAD)
    - docker build -t myapp:$COMMIT_HASH .
    - docker push myapp:$COMMIT_HASH
    - sed -i &quot;s/myapp:[a-z0-9]*/myapp:$COMMIT_HASH/&quot; kubernetes/staging/payment-staging-manifest.yml
    - git add kubernetes/staging/payment-staging-manifest.yml
    - git commit -m &quot;Auto-update manifest with image myapp:$COMMIT_HASH [skip ci]&quot;
    - git push origin $CI_COMMIT_REF_NAME
</code></pre>
<p>By using this approach, developers can continue their workflow of just committing code changes. The CI/CD pipeline handles the requirement of updating the Kubernetes manifest for each code change, ensuring you stay in the &quot;good books&quot; of the HAM (Hypothetical Angry Manager).</p>
<hr />
<blockquote>
<p>Some kind of:</p>
<pre class="lang-yaml prettyprint-override"><code>deploy_stage:
   stage: deploy
   environment:
     name: stage
     script: 
       - trigger the already configured gitlab kubernetes agent here without changing the manifest file.
</code></pre>
</blockquote>
<p>I understand the need: you want to trigger a deployment in the GitLab Kubernetes Agent without having to modify a manifest file or make any other changes in your repository.</p>
<p>I do not remember a GitLab Kubernetes Agent with an out-of-the-box &quot;trigger&quot; command or API call, as its design philosophy revolves around watching Git repositories for changes (&quot;pull&quot;).<br />
Still, as a workaround, you can use a GitLab CI/CD pipeline to force a synchronization.</p>
<p>Rather than making &quot;dummy&quot; changes to the manifest file, maintain an environment variable within the Kubernetes manifest that is set to be the commit hash (or some other unique value) of the pipeline.</p>
<p>Then modify the environment variable in the manifest file with the commit hash or a timestamp during the CI/CD pipeline run.<br />
Commit this change and push it back to the repository (again, use <code>[skip ci]</code> in the commit message to prevent an endless loop of pipelines). That ensures that the agent sees the change and gets &quot;triggered&quot;.</p>
<p>Something like:</p>
<pre class="lang-yaml prettyprint-override"><code>deploy_stage:
  stage: deploy
  environment: 
    name: stage
  script:
    - COMMIT_HASH=$(git rev-parse --short HEAD)
    - sed -i &quot;s/COMMIT_ENV_VAR=.*/COMMIT_ENV_VAR=$COMMIT_HASH/&quot; path/to/manifest.yml
    - git config user.email &quot;ci@mydomain.com&quot;
    - git config user.name &quot;GitLab CI&quot;
    - git add path/to/manifest.yml
    - git commit -m &quot;Update manifest with commit hash [skip ci]&quot;
    - git push origin $CI_COMMIT_REF_NAME
</code></pre>
<p>The downside is that you are still making a change to the repo, but it is now a meaningful change: recording the commit hash of the build triggering the deployment, which can be helpful for tracking purposes.</p>
