arrow_backAll Posts·5 Min Read·2025-04-07

GitLab Kubernetes Agent

KubernetesGitLab CI/CDHelmDevOps

In modern software delivery, automating deployments to production is a core priority. GitLab provides an all-in-one DevOps platform, while Kubernetes orchestrates container workloads. Combining the two is common, but secure integration and access management still require careful design.

GitLab addresses this need with the GitLab Kubernetes Agent, which establishes encrypted communication between GitLab and a Kubernetes cluster without storing a kubeconfig or long-lived cluster token in the CI/CD repository.

What Is the GitLab Kubernetes Agent? The GitLab Kubernetes Agent runs inside the Kubernetes cluster and establishes an encrypted, bidirectional connection to GitLab through the Kubernetes Agent Server (KAS). This enables features such as:

  • Automated deployments from GitLab pipelines to Kubernetes
  • Pull-based GitOps synchronization, where the agent pulls configuration from GitLab and applies it to the cluster
  • Flexible, secure, centralized access management through GitLab and Kubernetes

KAS Architecture at a Glance

  • GitLab Kubernetes Agent (gitlab-agent) is deployed as a pod inside the Kubernetes cluster.
  • Kubernetes Agent Server (KAS) is the server-side component operated by GitLab.
  • The agent and KAS communicate over gRPC (Google Remote Procedure Call) to protect communication integrity.

Advantages

  • Stronger security: The Kubernetes API server does not need to be exposed publicly; the agent creates a tunnel to KAS.
  • Fewer dependencies: GitLab provides the workflow without requiring additional tools such as Flux or Argo CD.
  • Centralized access control: Use GitLab and Kubernetes RBAC rather than managing credentials in multiple systems.
  • Straightforward operations: The setup focuses on GitLab and Kubernetes without an additional GitOps control plane.

Trade-offs

  • More limited GitOps features: Without tools such as Flux or Argo CD, the built-in feature set is narrower.
  • GitLab dependency: The agent is designed to operate within the GitLab ecosystem.
  • More involved initial setup: Operators need a solid understanding of both GitLab and Kubernetes.
  • Smaller community footprint: Flux and Argo CD have broader independent communities.

name img

How It Works: When a user pushes code to a GitLab project, the CI/CD pipeline is triggered after the agent authenticates with KAS. The Kubernetes GitLab Runner then executes the jobs defined in .gitlab-ci.yaml, such as creating a pod or inspecting existing workloads.

  • Kubernetes Cluster
  • GitLab Project
  • Helm
  • glab
  • Docker

1. Create a Kubernetes Cluster

For a multinode cluster, see the Kubernetes guide. This example uses minikube because it runs Kubernetes on a single, lower-specification node. Follow the official minikube documentation for the setup; the workflow is similar to a multinode environment.

2. Create a GitLab Project and Kube Agent

  • Open the GitLab dashboard and select "New project". name img

  • Select "Create blank project". name img

  • Enter a project name, such as kubernetes-agent. name img

  • Choose the appropriate Visibility Level. Set the project to public or private, then select "Create project". name img

Create the Kube Agent in GitLab
  • Open Operate -> Kubernetes cluster. name img

  • Select "Connect a cluster" to connect the Kubernetes cluster from GitLab. name img

  • Select "Option 2" and enter a name, such as kube-agent. name img

  • GitLab displays an "Agent access token". Store it securely; it is required to connect to the cluster. name img

  • Create the agent configuration directory in the project. Use the path shown in GitLab, such as .gitlab/agent/<name-cluster>/config.yaml; the name depends on the cluster configuration. name img

  • Configure config.yaml as follows:

    • user_access controls which GitLab users can access Kubernetes.
    • agent: {} grants the agent unrestricted access in this example.
    • The first project entry defines the GitLab project allowed to use the agent.
    • ci_access controls which projects can use the CI/CD integration.
    • The second project entry defines the CI project.
    • default_namespace sets the namespace used by the pipeline.
    yaml
    user_access:
      access_as:
          agent: {}
      projects:
          - id: vian/kube-agent
    ci_access:
      projects:
        - id: vian/kube-agent
          default_namespace: gitlab-agent
    
Create an Access Token
  • Open Settings -> Access Token in the left sidebar. name img

  • Select "Add new token" to create a token for CLI access to GitLab and the Kubernetes workflow. name img

  • Give the access token a descriptive name. name img

  • Under "Select scopes", grant api and write_repository. In this example, I also enable:

    • "read_api"
    • "k8s_proxy"
    • "read_repository"

    name img

  • Select "Create project access token". name img

  • GitLab displays the token once. Copy it and store it securely; it will be used to authenticate the CLI. name img

3. Log in to GitLab through the CLI

  • Run the GitLab CLI login flow and select "GitLab Self-hosted Instance" for this example.

    bash
    $ glab auth login
    ? What GitLab instance do you want to log into?  [Use arrows to move, type to filter]
      gitlab.com
    > GitLab Self-hosted Instance
    
    • Enter the GitLab hostname. This example uses gitlab.adinusa.id; replace it with your own host.
    bash
    ? What GitLab instance do you want to log into? GitLab Self-hosted Instance
    ? GitLab hostname: gitlab.adinusa.id
    
    • Choose "Token" as the authentication method.
    bash
    ? How would you like to sign in?  [Use arrows to move, type to filter]
    > Token
      Web
    
    • Paste the GitLab access token when prompted.
    bash
    Tip: generate a Personal Access Token at https://gitlab.adinusa.id/-/profile/personal_access_tokens?scopes=api,write_repository.
    The minimum required scopes are 'api' and 'write_repository'.
    ? Paste your authentication token:
    
    • Select "HTTPS" as the default Git protocol.
    bash
    ? Choose default Git protocol:  [Use arrows to move, type to filter]
      SSH
    > HTTPS
      HTTP
    
    • Select "HTTPS" for the API protocol as well.
    bash
    ? Authenticate Git with your GitLab credentials? Yes
    ? Choose host API protocol:  [Use arrows to move, type to filter]
    > HTTPS
      HTTP
    
    • A successful response confirms that the CLI is authenticated to the GitLab project.
    bash
    - glab config set -h gitlab.adinusa.id git_protocol https
    ✓ Configured Git protocol.
    - glab config set -h gitlab.adinusa.id api_protocol https
    ✓ Configured API protocol.
    ✓ Logged in as project_765_bot_ce6b24221b39aa6436b1ca36dc8bfb1c
    

4. Create a Kubernetes ServiceAccount

The GitLab CI/CD pipeline needs a ServiceAccount bound to the GitLab Runner. Use one of the following access patterns.

  • For namespace-scoped access, use the configuration below and replace <namespace> with the target namespace.

    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: gitlab-runner
      namespace: <nama_namespace>
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: gitlab-runner
      namespace: <nama_namespace>
    rules:
      - apiGroups: [""]
        resources: ["pods", "services", "configmaps", "secrets"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: ["apps"]
        resources: ["deployments", "replicasets"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: ["networking.k8s.io"]
        resources: ["ingresses"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: gitlab-runner-binding
      namespace: <nama_namespace>
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: gitlab-runner
    subjects:
      - kind: ServiceAccount
        name: gitlab-runner
        namespace: <nama_namespace>
    
  • For access across every namespace in the cluster, use the configuration below.

    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: gitlab-runner
      namespace: kube-system
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: gitlab-runner-binding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
      - kind: ServiceAccount
        name: gitlab-runner
        namespace: kube-system
    

5. Create the Kube Agent with Helm

  • Add the GitLab Helm repository and update the local index.

    bash
    helm repo add gitlab https://charts.gitlab.io
    helm repo update
    
  • Install the GitLab Kube Agent with these settings:

    • Set the target namespace with --namespace <namespace>. Add --create-namespace if Helm should create it.
    • Change --set image.tag= to use a different agent image tag.
    • Set --set config.token= to the token that connects the cluster to GitLab.
    • Set --set config.kasAddress= to the KAS address for the GitLab instance.
    • Set --set serviceAccount.name= to the existing ServiceAccount.
    • Use --set serviceAccount.create=false and --set rbac.create=false so Helm reuses the existing access configuration.

    Example:

    bash
    helm upgrade --install test gitlab/gitlab-agent \
      --namespace gitlab-agent \
      --create-namespace \
      --set image.tag=v17.9.2 \
      --set config.token=glagent-GD-********** \
      --set config.kasAddress=wss://gitlab.adinusa.id/-/kubernetes-agent/ \
      --set rbac.create=false \
      --set serviceAccount.name=gitlab-runner \
      --set serviceAccount.create=false 
    

6. Create the GitLab Runner with Helm

  • Install the GitLab Runner and adjust the following values:

    • Set --namespace to the target namespace, such as gitlab-runner.
    • Set --set gitlabUrl= to the GitLab URL, such as https://gitlab.adinusa.id.
    • Replace <RUNNER-TOKEN> with the runner token created in GitLab.
    • Set --set serviceAccount.name= to the existing ServiceAccount, such as gitlab-runner.
    • Set --set serviceAccount.create=false and --set rbac.create=false to reuse the existing permissions.

    Example:

    bash
    helm upgrade --install gitlab-runner gitlab/gitlab-runner \
      --namespace gitlab-runner \
      --set gitlabUrl=https://gitlab.adinusa.id \
      --set runnerToken=<RUNNER-TOKEN> \
      --set runners.executor="kubernetes" \
      --set rbac.create=false \
      --set serviceAccount.name=gitlab-runner \
      --set serviceAccount.create=false
    

7. Verify the GitLab Runner

  • Check the ServiceAccount used by the runner pod. Adjust the -n namespace if your deployment uses a different one.

    bash
    kubectl get pod -n gitlab-runner -l app=gitlab-runner -o jsonpath="{.items[*].spec.serviceAccountName}"
    
  • Check the ServiceAccount in the Helm manifest. Adjust the namespace if necessary.

    bash
    helm get manifest gitlab-runner -n gitlab-runner | grep serviceAccountName -A 2
    
  • Test the ServiceAccount permissions. The expected output is yes, which confirms that the runner can access pods.

    bash
    kubectl auth can-i get pods --as=system:serviceaccount:gitlab-agent-test:gitlab-runner -n gitlab-runner
    

8. Test the Kube Agent and GitLab Runner

  • Run a simple GitLab CI pipeline to list the pods in the target namespace.

    yaml
    deploy:
      stage: deploy
      image: bitnami/kubectl
      script:
        - kubectl get pods -n gitlab-agent-test
      tags: <runner_tags>
    
  • A successful pipeline produces the following result. name img

Conclusion

Integrating the GitLab Kube Agent with KAS gives Kubernetes teams a secure way to manage clusters without exposing the API server publicly. It supports isolated network topologies, near-real-time configuration synchronization, and GitOps workflows through a single CI/CD platform.

Cloud-native adoption is not only about using the newest tools; it is about choosing solutions that match the team's security and operational requirements. GitLab Kube Agent and KAS demonstrate how a CI/CD platform and Kubernetes can work together to make DevOps delivery more efficient.