$ kubectl get all -A
Cloud Backend
What is it?
One example backend where common cloud, DevOps and security tools each have a single job: code reaches two clouds through Git only, infrastructure changes go through reviewed pull requests, the website sits behind Cloudflare, every log lands in one S3 archive, people sign in once and reach production through audited doors, no cloud access key lives longer than a few hours, and clusters run only images that CI signed.
// git push --> production
The architecture
Five flows share the platform: shipping an app, changing the infrastructure, serving the website, collecting logs and detecting threats, and operating it. The diagrams after this one zoom in on traffic, logs, identity and secrets, and the supply chain; the page ends with the Kubernetes vocabulary.
Ship an app
- 1
Push. An engineer builds and runs the image locally with Docker, pushes a branch to the app repo in Azure Repos and opens a pull request. Branch policies require a review and a green build before anything merges, and push protection rejects any push that contains a detected secret.
- 2
Trigger CI. An Azure DevOps service hook starts a Jenkins pipeline on every push.
- 3
Build and publish. Jenkins agents build the image with Podman, rootless and without a daemon, run the tests, scan the image with Trivy, sign it with Cosign, push it to ECR and ACR, and publish the Helm chart to JFrog Artifactory. Builds fetch their npm, PyPI and Maven dependencies through Artifactory's remote repositories, a cached proxy of the public registries that JFrog Curation filters. The supply chain section below shows each gate.
- 4
Bump the tag. After a merge to main, Jenkins commits the new image tag to the Helm values in the gitops repo. Nobody deploys by hand: a deployment is a commit.
- 5
Detect. Argo CD polls the gitops repo, every three minutes by default, or gets a webhook, and compares what Git describes with what runs in each cluster.
- 6
Sync. Argo CD pulls the chart from Artifactory, renders it with the values from the gitops repo and applies it to every cluster: the app clusters on EKS and AKS, and the website's own EKS cluster. The same mechanism installs the add-ons each cluster runs: Prometheus, the Datadog Agent, the OpenTelemetry Collector, the EDR sensor, the Teleport agent, Kyverno and the External Secrets Operator. Kyverno admits a pod only if its image carries a valid signature.
- 7
Pull. Each cluster pulls the image from the registry of its own cloud. The External Secrets Operator copies the app's passwords and API keys from Secrets Manager or Key Vault into Kubernetes Secrets, so they never sit in Git.
Change the infrastructure
- 8
Plan. Infrastructure changes are pull requests to the infra repo. Atlantis receives the webhook, runs terraform plan, checks the plan against Conftest policies and posts both results as comments on the PR.
- 9
Apply. Once the PR is approved, commenting atlantis apply runs terraform apply: networks, identities, clusters, registries, VMs and the S3 log archive. The Terraform state lives in S3 or Azure Blob Storage, with locking, so two applies never race.
- 10
Configure. Ansible configures what is not in Kubernetes: the VMs for the Jenkins controller and agents, the OpenVPN server and the Teleport SSH service, including their EDR sensor and syslog forwarding. Its inventory plugins list the VMs from the AWS and Azure APIs, and its roles are first tested on the laptop, on Vagrant VMs, through Vagrant's Ansible provisioner.
Serve the website
- 11
Visit. Visitors resolve the website through Cloudflare DNS and reach Cloudflare's edge, which caches static content, filters requests through its WAF and absorbs DDoS attacks.
- 12
Origin. Cloudflare forwards the remaining requests to an AWS Network Load Balancer in front of Envoy Gateway, the Kubernetes Gateway API implementation built on Envoy, in the website's EKS cluster. Envoy accepts only Cloudflare's client certificate (authenticated origin pulls) and routes each request to the website pods.
Collect logs, detect threats
- 13
Collect. Apps and Envoy send traces, metrics and logs in OTLP, OpenTelemetry's protocol, to the Collector in their cluster. The Collector writes logs to the S3 archive, metrics to Prometheus, and traces and metrics to Datadog.
- 14
Archive. VMs and the OpenVPN server send syslog over the private network, through an internal load balancer, to the Collector's syslog receiver, which archives it in S3 too. Cloudflare writes its logs to the same archive with Logpush, and AWS writes CloudTrail and VPC flow logs there.
- 15
Index. Splunk, the SIEM, reads the archive through the AWS add-on's SQS-based S3 input: S3 announces each new object on a queue, and Splunk fetches and indexes it.
- 16
Analyse. The Datadog Forwarder, a Lambda function triggered by new objects, ships the same logs into Datadog, next to the metrics and traces. Datadog also watches Argo CD through its Agent check, and JFrog Artifactory Cloud through its integration.
- 17
Scan. Wiz connects to both clouds with read-only roles, plus permission to snapshot disks, and scans those snapshots instead of running agents, then reports misconfigurations and vulnerabilities. Its findings reach Splunk through the Wiz add-on.
- 18
Detect. The EDR sensor on laptops, VMs and cluster nodes streams process, file and network events to the EDR console, which detects attacks and can isolate a machine. Its detections are forwarded to Splunk, where they meet the cloud logs.
Operate
- 19
Page. Datadog monitors page the on-call engineer, and so does Alertmanager for the Prometheus rules. Splunk alerts go to the security team.
- 20
VPN. The internal UIs of Jenkins, Argo CD and Atlantis are not open to the internet: the engineer reaches them with OpenVPN, through the server in each cloud's network. Only the webhook endpoints that Azure DevOps calls are exposed, limited to its IP ranges.
- 21
Log in. For production, the engineer runs tsh login, signs in through Entra ID and gets short-lived certificates instead of long-lived SSH keys or kubeconfigs.
- 22
Access. Teleport's proxy forwards kubectl to the agent in each cluster and ssh to the VMs. Agents dial out to the proxy through reverse tunnels, so clusters and VMs need no open inbound port, and every session is recorded.
// who gets in, and how
Traffic and access
Three doors, one per audience. Visitors only ever reach Cloudflare; engineers use OpenVPN for internal tools and Teleport for production, so nothing else listens on the internet.
// everything lands in S3
Logs, metrics and security
Logs go to one S3 archive first, and the monitoring tools read from it, so no tool owns the only copy and a new tool can replay history. Metrics and traces go straight to the tools that graph them, and security findings to the SIEM.
// no long-lived keys
Identity and secrets
People sign in once, through Entra ID, and machines never use a stored cloud key: every credential is issued on demand and expires within hours, so a copied file or a leaked log line stops working by itself. Leaving someone's Entra group removes their access everywhere within hours.
// only signed images run
Supply chain
Every change passes a row of gates, and any gate can stop it: a secret never lands in Git, a risky package never enters the cache, and a cluster runs only images that CI signed. Infrastructure has its own gates, and Wiz checks afterwards for what got through or was changed by hand.
// one job each
Who does what
| Tool | Job in this model | Talks to |
|---|---|---|
| Configures the VMs that are not in Kubernetes. | VMs, Vagrant | |
| CD: keeps every cluster equal to the gitops repo. | Azure Repos, JFrog, Kubernetes | |
| Runs Terraform from pull requests, so every infrastructure change is reviewed with its plan. | Azure Repos, Terraform | |
| Runs one copy of the platform (EKS, ECR, EC2, VPC, IAM), the website's own EKS cluster and the S3 log archive. | Terraform, Argo CD, Wiz | |
| Runs the other copy: AKS, ACR, Azure VMs, VNet and Entra ID. | Terraform, Argo CD, Wiz | |
| Hosts the three Git repos behind branch policies and push protection, and Boards for work items. | Jenkins, Atlantis, Argo CD | |
| DNS, CDN, WAF and DDoS protection in front of the website; pushes its logs to S3. | visitors, Envoy, S3 | |
| Checks every Terraform plan against Rego policies before Atlantis may apply it. | Atlantis | |
| Signs each image and attests its SBOM with a key kept in AWS KMS or Key Vault. | Jenkins, ECR, ACR, Kyverno | |
| Dashboards, APM and monitors for the apps, Argo CD and JFrog. | the Collector, S3, on-call | |
| Builds and runs images on the laptop. | nothing in production | |
| Sensors on laptops, VMs and nodes that detect and contain attacks on the machine. | EDR console, Splunk | |
| The one login for people: MFA and Conditional Access, single sign-on into the clouds and tools, groups mapped to roles. | AWS, Teleport, the web tools | |
| Envoy Gateway is the website cluster's ingress; it sends access logs and traces in OTLP. | Cloudflare, the Collector | |
| Copies secrets from the cloud stores into Kubernetes Secrets, using the pod identity of its cloud. | Secrets Manager, Key Vault | |
| Packages each app and each add-on as a chart, with values per environment. | Argo CD, JFrog | |
| CI: tests, builds, scans, signs and pushes images, publishes charts, bumps the tag in the gitops repo. | Azure DevOps, Podman, JFrog | |
| Artifactory hosts the Helm charts and proxies npm, PyPI and Maven; Curation blocks risky packages, Xray scans what is stored. | Jenkins, Argo CD, Datadog | |
| Runs the apps, the website and the add-ons, on EKS and AKS. | Argo CD, the registries | |
| Admission policies in every cluster: only signed images from our registries may run. | Kubernetes, Cosign | |
| One protocol, OTLP, and one Collector per cluster for traces, metrics and logs. | apps, Envoy, S3, Datadog | |
| VPN from engineers' laptops to the private subnets that hold the internal UIs. | laptops, VMs | |
| Builds images on the Jenkins agents, rootless and without a daemon. | Jenkins, ECR, ACR | |
| Stores cluster metrics and evaluates alert rules; Alertmanager pages on-call. | the Collector | |
| AWS Secrets Manager and Azure Key Vault hold passwords, API keys and the signing keys. | External Secrets, Cosign | |
| SIEM: indexes the S3 archive and correlates it with EDR and Wiz findings. | S3, EDR, Wiz | |
| The standard log protocol of VMs and network appliances such as the VPN server. | the Collector | |
| The one way into production: SSO, short-lived certificates, kubectl and ssh, recorded sessions. | clusters, VMs, engineers | |
| Declares the resources in both clouds; keeps state in S3 or Blob Storage. | AWS, Azure | |
| Scans each image for known vulnerabilities in Jenkins and writes its SBOM. | Jenkins, Cosign | |
| Local VMs to test Ansible roles before they reach the cloud. | Ansible | |
| Agentless cloud security: scans both clouds for misconfigurations and vulnerabilities. | AWS, Azure, Splunk |
Other choices. This is one coherent model, not the only one. The comparisons below cover the Git host, CI, monitoring and VPN. Docker and Podman build the same OCI images, so the laptop and CI can differ. EDR is a category: CrowdStrike Falcon, Microsoft Defender for Endpoint and SentinelOne all fit that box. HashiCorp Vault could replace both cloud secret stores with one, and issue database passwords on demand. gitleaks in a pre-commit hook catches a secret before it even leaves the laptop. OPA Gatekeeper can replace Kyverno, Checkov can replace Conftest, and Grype and Syft can replace Trivy. Sources: Azure DevOps to Jenkins, Atlantis Git hosts, Argo CD clusters, Artifactory remote repositories, kube-prometheus-stack, Alertmanager, teleport-kube-agent, azurerm backend, Azure inventory, Vault database secrets, gitleaks.
// pick one per row
Interchangeable pieces
Four places in the overview carry a slash: either tool fits there, and the rest of the model stays the same. The first column is the one the steps above describe; for monitoring they use both.
Git host: Azure DevOps or GitHub
This model uses Azure DevOps because Repos, Boards and Entra ID live in one Microsoft tenant. GitHub takes the same place: Argo CD, Atlantis and Jenkins work with both.
| Hosting | Azure DevOps Services, or Azure DevOps Server on your own machines | GitHub.com, or GitHub Enterprise Server on your own machines |
| Merge rules | Branch policies: reviewers, build validation, linked work items | Rulesets and branch protection: reviews, status checks |
| Work tracking | Boards: backlogs, sprints, work items linked to commits | Issues and Projects |
| Built-in CI | Azure Pipelines | GitHub Actions |
| Secret scanning | GitHub Secret Protection for Azure DevOps, with push protection | GitHub Secret Protection, with push protection |
| Sign-in | Each organization is connected to an Entra ID tenant | Entra ID through Enterprise Managed Users or SAML, on GitHub Enterprise |
| Open source | Public projects are retired; they turn private in 2027 | Public repositories, where most open source lives |
Sources: branch policies, rulesets, Azure DevOps and Entra ID, Enterprise Managed Users, push protection, public projects retirement.
CI: Jenkins or Azure Pipelines
Jenkins is here because it runs anywhere and its agents sit on our own VMs, next to the registries. Azure Pipelines removes the controller you would otherwise run and patch.
| Who runs it | You: the controller, its agents, upgrades and plugin updates | Microsoft runs the service; agents are Microsoft-hosted or your own |
| Pipeline file | Jenkinsfile, in Groovy | azure-pipelines.yml, in YAML |
| Extensions | Plugins, each with its own releases and security advisories | Tasks from the Visual Studio Marketplace |
| Trigger from Azure Repos | An Azure DevOps service hook | Built in, including build validation on pull requests |
| Cloud credentials | The agent VM's instance profile or managed identity | Service connections with workload identity federation; AWS through the AWS Toolkit's OIDC option |
| Cost | Free software; you pay for the VMs and the time to run them | Free tier of one Microsoft-hosted job (1,800 minutes a month) and one self-hosted job, then per parallel job |
Sources: Jenkins pipelines, Jenkins security advisories, Azure DevOps to Jenkins, parallel jobs, workload identity service connections, Azure DevOps to AWS with OIDC.
Monitoring: Datadog or Prometheus
The model runs both: Prometheus in each cluster for metrics and alert rules, Datadog for dashboards, APM and logs across everything. Either one can also work alone.
| Who runs it | Datadog, as a service that stores and scales the data | You: one Prometheus per cluster, Grafana for dashboards |
| Signals | Metrics, traces, logs and APM in one place | Metrics only; Loki adds logs and Tempo adds traces |
| Alerting | Monitors, with paging integrations | Rules in Prometheus; Alertmanager routes and pages |
| Retention | Set by your plan, kept by Datadog | Local disk, 15 days by default; Thanos or Mimir for long-term |
| OpenTelemetry | The Collector's Datadog exporter, or OTLP into the Agent | A native OTLP receiver since Prometheus 3, or remote write from the Collector |
| Argo CD and JFrog | The Agent's Argo CD check and the JFrog Cloud integration | Scrape Argo CD's metrics endpoint and Artifactory's OpenMetrics API |
| Cost | Priced per host and by data volume, so it grows with the fleet | Free software; you pay for storage and the people who run it |
Sources: Datadog OTLP ingestion, Datadog pricing, Prometheus storage, Prometheus and OpenTelemetry, Thanos, Loki, Argo CD metrics, JFrog Open Metrics.
VPN: OpenVPN, AWS Client VPN and others
The VPN only opens the internal UIs; production goes through Teleport. A self-run server works the same in both clouds, while the managed options trade that for one service per cloud.
| Who runs it | You, on a VM in each cloud | AWS, as a managed endpoint | Azure, as a gateway in the VNet | You, on a VM in each cloud |
| Protocol | OpenVPN, over TLS | OpenVPN-based, over TLS | OpenVPN, IKEv2 or SSTP | WireGuard, over UDP |
| Sign-in | Certificates, plus plugins for LDAP or RADIUS | Certificates, Active Directory, or SAML with Entra ID | Certificates, RADIUS, or Entra ID through the Azure VPN Client (Windows, macOS) | One key pair per device; no users or SSO |
| Reach | Both clouds, one server each | AWS VPCs only | Azure VNets only | Both clouds, one server each |
| Price | The VM | Per endpoint-hour plus per connection-hour | Per gateway-hour, by SKU | The VM |
| Logs | syslog to the Collector | Connection logs to CloudWatch Logs | Diagnostic logs to Azure Monitor | Almost none, by design |
Tailscale and NetBird add users, SSO and access rules on top of WireGuard. Zero-trust proxies such as Cloudflare Access or Teleport's application access can replace the VPN entirely, by putting each internal UI behind a login.
Sources: OpenVPN manual, Client VPN authentication, Client VPN pricing, Client VPN logging, Azure point-to-site VPN, WireGuard, Tailscale, Cloudflare Access, Teleport application access.
// kubectl api-resources
Kubernetes vocabulary
A cluster has two halves: the control plane, which stores what you asked for and decides where it runs, and the nodes, which run it. On EKS and AKS the cloud runs the control plane; you get its API and bring the nodes, unless you pick EKS Auto Mode or AKS Automatic, where the cloud manages them too. The first diagram shows the parts of a cluster, the second the objects you write into it, and the table defines each word.
The parts of a cluster
The objects you write
Glossary
| Term | What it is | In this model |
|---|---|---|
| Admission webhook | A call the API server makes before it saves an object; the webhook can reject or change it. | Kyverno rejects pods whose image is not signed. |
| cloud-controller-manager | Control plane loops that talk to the cloud: load balancers, routes, node details. | Run by AWS and Azure inside the managed control plane. |
| CNI plugin | Gives each pod an IP address and connects it to the network. | Amazon VPC CNI on EKS, Azure CNI on AKS. |
| ConfigMap | Settings that are not secret, read by pods as files or environment variables. | Per-environment settings rendered from the Helm values. |
| Container runtime | Pulls images and runs containers on behalf of the kubelet, through the CRI. | containerd on EKS and AKS nodes. |
| Control plane | The API server, etcd, the scheduler and the controllers: the half that decides. | Run by EKS and AKS; you only see the API. |
| CustomResourceDefinition | Adds a new object type to the API. | Argo CD's Application, Kyverno's ClusterPolicy, External Secrets' ExternalSecret. |
| DaemonSet | Runs one copy of a pod on every node, or on chosen nodes. | The Datadog Agent and the EDR sensor. |
| Deployment | Declares a stateless app: image, replica count, rollout strategy. | Each app and the website; Jenkins changes the image tag through Git. |
| etcd | The key-value database that stores every object. | Hidden inside EKS and AKS. EKS encrypts its data with KMS by default; AKS can, with Key Vault. |
| Gateway, HTTPRoute | Gateway API objects: a Gateway opens a listener, HTTPRoutes send hosts and paths to Services. They succeed Ingress, which is frozen. | Envoy Gateway in the website cluster. |
| HorizontalPodAutoscaler | Changes a Deployment's replica count from CPU, memory or custom metrics. | Scales the website pods with CPU load or request rate. |
| Job, CronJob | Pods that run to completion, once or on a schedule. | Not used in this model; typical for database migrations and nightly reports. |
| kube-apiserver | The REST API in front of the cluster; every component and every client goes through it. | kubectl reaches it through Teleport; Argo CD applies Git through it. |
| kube-controller-manager | Control loops that turn objects into more objects: a Deployment into ReplicaSets, a ReplicaSet into Pods. | Run by EKS and AKS. |
| kube-proxy | Programs each node so that a Service IP reaches one of its pods, with iptables rules by default. | A DaemonSet on EKS and AKS nodes. |
| kube-scheduler | Picks a node for each new pod, from its resource requests, affinity rules and taints. | Run by EKS and AKS. |
| kubeconfig | A file with the API server address and the credentials that kubectl uses. | tsh kube login writes one with short-lived certificates. |
| kubectl | The command-line client of the API. | Engineers, through Teleport. |
| kubelet | The agent on each node: registers it, starts its pods through the runtime, reports their health. | On every EKS and AKS node. |
| Label, selector | Key-value tags on objects, and the queries that match them. | app=web ties the website's Service and ReplicaSet to its pods. |
| Namespace | A folder for objects, with its own access rules and quotas. | One per app, and one per add-on. |
| Node | A machine that runs pods, with a kubelet, a runtime and kube-proxy. | EC2 or Azure VMs in managed node groups or node pools; Karpenter or the Cluster Autoscaler adds more when pods do not fit. |
| Operator | A controller and its custom resources, that runs a piece of software for you. | The External Secrets Operator; Argo CD works the same way. |
| PersistentVolume, PVC | A PersistentVolumeClaim asks for storage; the cluster binds it to a PersistentVolume that its StorageClass creates. | EBS volumes on EKS and Azure Disks on AKS, through their CSI drivers. |
| Pod | The smallest unit: one or more containers sharing an IP, volumes and a lifecycle. | Every app instance, the website, every add-on. |
| RBAC | Roles and ClusterRoles list allowed actions; RoleBindings grant them to users, groups or ServiceAccounts. | Teleport maps Entra ID groups to Kubernetes groups. |
| ReplicaSet | Keeps a fixed number of identical pods running; a Deployment creates one per version. | Created by Deployments, never by hand. |
| Secret | A ConfigMap for sensitive values. Base64 is only an encoding: the protection comes from RBAC and etcd encryption. | Written by External Secrets from Secrets Manager and Key Vault. |
| Service | A stable virtual IP and DNS name in front of a set of pods. Types: ClusterIP, NodePort, LoadBalancer. | One per app; the website's HTTPRoute points to its Service. |
| ServiceAccount | The identity of a pod inside the cluster. | EKS Pod Identity and AKS Workload ID map it to a cloud role. |
| StatefulSet | Like a Deployment, but each pod keeps a stable name and its own volume. | Databases and queues, when they run in the cluster. |