6.0 KiB
| stage | group | info |
|---|---|---|
| Configure | Configure | To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers |
GitOps with the Kubernetes Agent (PREMIUM SELF)
The GitLab Kubernetes Agent supports the pull-based version of GitOps. To be useful, the feature must be able to perform these tasks:
-
Connect one or more Kubernetes clusters to a GitLab project or group.
-
Synchronize cluster-wide state from a Git repository.
-
Synchronize namespace-scoped state from a Git repository.
-
Control the following settings:
- The kinds of objects an agent can manage.
- Enabling the namespaced mode of operation for managing objects only in a specific namespace.
- Enabling the non-namespaced mode of operation for managing objects in any namespace, and managing non-namespaced objects.
-
Synchronize state from one or more Git repositories into a cluster.
-
Configure multiple agents running in different clusters to synchronize state from the same repository.
GitOps architecture
In this architecture, the Kubernetes cluster (agentk) periodically fetches
configuration from (kas), spawning a goroutine for each configured GitOps
repository. Each goroutine makes a streaming GetObjectsToSynchronize() gRPC call.
kas accepts these requests, then checks if this agent is authorized to access
this GitLab repository. If authorized, kas polls Gitaly for repository updates
and sends the latest manifests to the agent.
Before each poll, kas verifies with GitLab that the agent's token is still valid.
When agentk receives an updated manifest, it performs a synchronization using
gitops-engine.
If a repository is removed from the list, agentk stops the GetObjectsToSynchronize()
calls to that repository.
graph TB
agentk -- fetch configuration --> kas
agentk -- fetch GitOps manifests --> kas
subgraph "GitLab"
kas[kas]
GitLabRoR[GitLab RoR]
Gitaly[Gitaly]
kas -- poll GitOps repositories --> Gitaly
kas -- authZ for agentk --> GitLabRoR
kas -- fetch configuration --> Gitaly
end
subgraph "Kubernetes cluster"
agentk[agentk]
end
Architecture considered but not implemented
As part of the implementation process, this architecture was considered, but ultimately not implemented.
In this architecture, agentk periodically fetches configuration from kas. For each
configured GitOps repository, it spawns a goroutine. Each goroutine then spawns a
copy of git-sync. It polls a particular
repository and invokes a corresponding webhook on agentk when it changes. When that
happens, agentk performs a synchronization using
gitops-engine.
For repositories no longer in the list, agentk stops corresponding goroutines
and git-sync copies, also deleting their cloned repositories from disk:
graph TB
agentk -- fetch configuration --> kas
git-sync -- poll GitOps repositories --> GitLabRoR
subgraph "GitLab"
kas[kas]
GitLabRoR[GitLab RoR]
kas -- authZ for agentk --> GitLabRoR
kas -- fetch configuration --> Gitaly[Gitaly]
end
subgraph "Kubernetes cluster"
agentk[agentk]
git-sync[git-sync]
agentk -- control --> git-sync
git-sync -- notify about changes --> agentk
end
Comparing implemented and non-implemented architectures
Both architectures attempt to answer the same question: how to grant an agent access to a non-public repository?
In the implemented architecture:
- Favorable: Fewer moving parts, as
git-syncandgitare not used, making this design more reliable. - Favorable: Uses existing connectivity and authentication mechanisms are used (gRPC +
agentktoken). - Favorable: No polling through external infrastructure. Saves traffic and avoids noise in access logs.
In the unimplemented architecture:
-
Favorable:
agentkusesgit-syncto access repositories with standard protocols (either HTTPS, or SSH and Git) with accepted authentication and authorization methods.- Unfavorable: The user must put credentials into a
secret. GitLab doesn't have a mechanism for per-repository tokens for robots. - Unfavorable: Rotating all credentials is more work than rotating a single
agentktoken.
- Unfavorable: The user must put credentials into a
-
Unfavorable: A dependency on an external component (
git-sync) that can be avoided. -
Unfavorable: More network traffic and connections than the implemented design
Ideas considered for the unimplemented design
As part of the design process, these ideas were considered, and discarded:
-
Running
git-syncandgitops-engineas part ofkas.- Favorable: More code and infrastructure under our control for GitLab.com
- Unfavorable: Running an arbitrary number of
git-syncprocesses would require an unbounded amount of RAM and disk space. - Unfavorable: Unclear which
kasreplica is responsible for which agent and repository synchronization. If done as part ofagentk, leader election can be done using client-go.
-
Running
git-syncand a "gitops-enginedriver" helper program as a separate KubernetesDeployment.-
Favorable: Better isolation and higher resiliency. For example, if the node with
agentkdies, not all synchronization stops. -
Favorable: Each deployment has its own memory and disk limits.
-
Favorable: Per-repository synchronization identity (distinct
ServiceAccount) can be implemented. -
Unfavorable: Time consuming to implement properly:
- Each
Deploymentneeds CRUD (create, update, and delete) permissions. - Users may want to customize a
Deployment, or add and remove satellite objects likePodDisruptionBudget,HorizontalPodAutoscaler, andPodSecurityPolicy. - Metrics, monitoring, logs for the
Deployment.
- Each
-