Delivery to Kubernetes¶
The workflow stores manifests in Git and applies them from a GitLab job through the selected cluster's agent. The versioned mechanism is CI-driven delivery. There is no continuous GitOps controller reconciliation or simultaneous deployment to both clouds.
Step 1: update desired state¶
update-k8s-manifests clones CD_PROJECT_PATH, checks out main and replaces the image reference in deployment.yaml. When changes exist, it creates a commit whose message is the application SHA and pushes it to main; otherwise it exits without creating an empty commit.
Credentials are supplied through CD_DEPLOY_USER and CD_DEPLOY_TOKEN. That variable name does not identify the token type: pushing requires a token/identity with write permission to the manifest repository and its protected branch. A GitLab Deploy Token with read_repository is insufficient for writes. Actual permissions are not versioned.
The branch is hardcoded to main. Replacement uses sed and matches a reference starting with CI_REGISTRY_IMAGE; if the registry is renamed or the manifest structure changes, inspect the diff before assuming the image was updated.
Step 2: select one target¶
| Value | Template's default context |
|---|---|
eks |
gabriel-canals-tfm/terraform-modules:eks-agent |
gke |
gabriel-canals-tfm/terraform-modules:gke-agent |
The template defaults to eks, but both application projects override it with gke. Infrastructure pipeline CLOUD_PROVIDER and application pipeline DEPLOY_TARGET are independent. Creating AWS does not automatically change the destination of an application delivery.
The job uses the kubeconfig injected by GitLab Agent. It lists contexts, selects one and checks whether namespace app exists, attempting creation if needed. This requires the GitLab and Kubernetes authorization described in agent access.
Step 3: apply manifests¶
The deploy job installs tools and downloads the Kubernetes stable kubectl available at that time. It clones the manifest repository's main again and runs kubectl apply over all its YAML in the namespace. It finishes by listing resources with kubectl get all.
sequenceDiagram
participant A as Application pipeline
participant M as Manifest repository
participant G as GitLab Agent
participant K as Kubernetes API
A->>M: Update image and push commit
A->>M: Clone main for the deploy job
A->>G: Select context and apply YAML
G->>K: Create or update resources
K-->>A: Command response
The apply response confirms object acceptance. It does not guarantee a completed RollingUpdate or a healthy application. The snapshot does not run rollout status or smoke tests and declares no environment: block in these jobs.
Kubernetes contracts¶
Each manifest project contains a Deployment, Service and ServiceAccount. Services rest and web are ClusterIP on port 8080. Both Deployments require imagePullSecrets: registry, but none of the reviewed repositories creates that registry Secret. Supply it through the chosen bootstrap mechanism, with suitable read permissions and rotation.
The frontend adds an alb Ingress with ACM TLS, a specific domain and routes for both services. AWS Terraform installs the ALB controller; GCP declares no equivalent implementation. Applying this YAML to GKE does not establish a functioning public URL. The GCP chapter defines that unconfirmed boundary.
Limitations and proposed improvements¶
| Area | Snapshot | Proposed improvement |
|---|---|---|
| Manifest revision | Second job reads main again |
Propagate the exact SHA created by the first job |
| Concurrency | No application resource_group |
Serialize per service and target |
| Health | apply and resource listing |
Timeout-bound rollout and HTTP/API test |
| Helm | Chart.yaml is detected, but deployment exits with failure |
Implement Helm before advertising support |
| Kubernetes client | Downloads unpinned stable release | Pin a client compatible with each cluster |
| Object deletion | apply does not delete objects removed from Git |
Explicit retirement and ownership procedure |
Concurrent pipelines may update the same main or apply a revision newer than the initial pipeline's change. A revert in the manifest repository does not deploy automatically either, since that repository has no CI. The rollback runbook explains how to complete the process.