Every cloud provider offers hundreds of services, and that catalogue is what makes the cloud feel overwhelming. Underneath it, all three major providers are built from the same five ideas: identity, networking, compute, storage and managed databases. Learn those properly on one provider and the other two become a vocabulary exercise. This module teaches the concepts provider-neutrally, uses AWS for concrete examples, and gives you the mapping to Azure and Google Cloud.
- Explain the shared responsibility model, and regions and availability zones as units of failure
- Design IAM access using roles, policies and least privilege instead of long-lived user keys
- Lay out a virtual network with public and private subnets, routing, NAT and security groups
- Choose between virtual machines, containers and functions, and between object, block and file storage
- Decide when a managed database is worth it, and configure it for availability and recovery
The ground rules
The shared responsibility model draws the line between you and the provider. The provider secures the cloud itself: buildings, hardware, the hypervisor and the managed service's internals. You secure what you put in it: identities, network exposure, data, operating system patches on your VMs and application code. Nearly every cloud breach you read about is on the customer's side of that line, typically a public storage bucket or a leaked access key.
A region is a geographic area, such as Ireland or Virginia. Each region contains several availability zones (AZs), which are physically separate data centres with independent power and networking, linked by low-latency connections. An AZ is your unit of failure: a production system runs in at least two. Regions are your unit of data residency, latency to users, and disaster recovery.
| Concept | AWS | Azure | Google Cloud |
|---|---|---|---|
| Identity | IAM | Microsoft Entra ID + RBAC | Cloud IAM |
| Virtual network | VPC | Virtual Network (VNet) | VPC |
| Virtual machines | EC2 | Virtual Machines | Compute Engine |
| Managed Kubernetes | EKS | AKS | GKE |
| Functions | Lambda | Functions | Cloud Run functions |
| Object storage | S3 | Blob Storage | Cloud Storage |
| Managed SQL | RDS | Azure SQL / Database for PostgreSQL | Cloud SQL |
| Secrets | Secrets Manager | Key Vault | Secret Manager |
Pick one provider and go deep before going broad. Depth transfers: once you understand how IAM, networks and managed databases fit together on one cloud, learning a second takes weeks, not months.
Identity and access management
IAM answers one question for every API call: is this principal allowed to perform this action on this resource? A principal is a human user, a service, or a workload. Permissions are written as policies and attached to principals. Everything is denied by default, an explicit Allow grants access, and an explicit Deny always wins.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::acme-prod-artifacts",
"arn:aws:s3:::acme-prod-artifacts/*"
]
}
]
}The most important distinction is between users and roles. A user has long-lived credentials: a password or an access key that works until someone revokes it. A role has no credentials of its own. A trusted principal assumes it and receives temporary credentials that expire, usually within an hour. Roles are how workloads should get access: a VM, a Kubernetes pod or a CI job is granted a role, and the platform delivers short-lived credentials to it automatically. There is no key to leak, rotate or find in a Git history.
- Least privilege. Grant specific actions on specific resources.
"Action": "*"on"Resource": "*"is administrator access, whatever the policy is called. - No root, no shared accounts. Protect the account's root identity with MFA and do not use it. Humans sign in through single sign-on and assume roles.
- Separate accounts per environment. A production account and a development account give you a hard boundary that no policy mistake can cross. Azure calls the equivalent a subscription, and Google Cloud a project.
- Audit everything. API activity logs (CloudTrail on AWS) record who did what. Turn them on before you need them.
aws sts get-caller-identity # who am I right now? run this first, always
aws configure list-profiles
aws s3 ls --profile prod-readonly
aws iam list-attached-role-policies --role-name orders-apiNetworking: the virtual private cloud
A VPC is your own isolated network inside the provider, defined by a CIDR block from the networking module, for example 10.20.0.0/16. You divide it into subnets, each living in one availability zone. What makes a subnet public or private is nothing more than its route table.
| Subnet | Default route goes to | What lives there |
|---|---|---|
| Public | An internet gateway | Load balancers, NAT gateways, bastion hosts |
| Private | A NAT gateway, for outbound traffic only | Application servers, Kubernetes nodes |
| Isolated | Nowhere outside the VPC | Databases |
VPC 10.20.0.0/16
AZ a AZ b
public 10.20.0.0/24 10.20.1.0/24 <- load balancer, NAT
private 10.20.10.0/24 10.20.11.0/24 <- app servers / k8s nodes
isolated 10.20.20.0/24 10.20.21.0/24 <- databases
internet -> load balancer (public) -> app (private) -> database (isolated)Only the load balancer has a public address. Application servers can reach out through the NAT gateway, for example to download packages, but nothing on the internet can start a connection to them. Databases have no route out at all.
Security groups are stateful firewalls attached to resources. Stateful means that if a request is allowed in, its reply is automatically allowed out. The strongest pattern is to reference other security groups instead of IP ranges: the database's group allows port 5432 only from the application's group, so the rule stays correct however many app servers come and go.
An inbound rule allowing 0.0.0.0/0 on port 22, 3389 or a database port exposes it to the entire internet, and automated scanners will find it within minutes. Reach private machines through a session manager service, a VPN or a bastion, never by opening them to the world.
Compute: VMs, containers, functions
| Model | You manage | Good for | Watch out for |
|---|---|---|---|
| Virtual machines | OS, patches, runtime, scaling | Legacy software, special hardware, full control | The most operational work |
| Managed Kubernetes | Workloads, node pools, upgrades | Many services, portability, a platform team | Complexity; too much for a single app |
| Serverless containers | Just the image | HTTP services and jobs without cluster work | Less control over networking and runtime |
| Functions | Just the code | Event handlers, glue, spiky or rare workloads | Cold starts, time limits, hard local testing |
Whatever you choose, treat instances as cattle, not pets: built from an image or a template, never configured by hand, and replaced instead of repaired. Run them in an auto scaling group or its equivalent across at least two AZs, behind a load balancer whose health checks remove failed instances. That combination is what turns "a server died" from an incident into a non-event.
Pricing models matter as much as instance size. On-demand is flexible and the most expensive. Commitments (reserved capacity, savings plans, committed use) trade a one to three year promise for a substantial discount on steady load. Spot or preemptible capacity is heavily discounted but can be reclaimed at short notice, which suits stateless, fault-tolerant work such as CI runners and batch jobs. The FinOps module goes deeper.
Storage
| Type | Access | Use for | AWS example |
|---|---|---|---|
| Object | HTTP API; whole objects by key | Backups, logs, images, static sites, data lakes | S3 |
| Block | A disk attached to one VM | Boot volumes, self-managed databases | EBS |
| File | A shared network filesystem | Legacy apps that need a shared directory | EFS |
Object storage is the cloud's workhorse: effectively unlimited, extremely durable, cheap, and reachable from anywhere. It is not a filesystem: you cannot modify part of an object, only replace it. It is the right home for the "uploaded files" that the twelve-factor module told you to keep off local disk.
aws s3 mb s3://acme-dev-uploads-7f3a # bucket names are globally unique
aws s3 cp report.pdf s3://acme-dev-uploads-7f3a/2026/report.pdf
aws s3 ls s3://acme-dev-uploads-7f3a/2026/
aws s3 sync ./site s3://acme-dev-site --delete
aws s3 presign s3://acme-dev-uploads-7f3a/2026/report.pdf --expires-in 3600- Block all public access at the account level and make exceptions deliberately. Share private objects with time-limited presigned URLs.
- Turn on versioning for anything important, so that an overwrite or delete can be undone, and encryption at rest, which is now the default on the major providers.
- Use lifecycle rules to move old objects to colder, cheaper storage classes and to expire what you no longer need.
- Block volumes live in one AZ. Snapshot them on a schedule, because a snapshot is what survives the loss of that zone.
Managed databases
A managed database service runs PostgreSQL, MySQL and others for you. The provider handles provisioning, patching, backups, replication and failover; you keep responsibility for schema design, queries, indexes and access control. For most teams this is the clearest win in the whole cloud, because operating a database well by yourself takes real expertise and a lot of on-call time.
- Multi-AZ keeps a synchronous standby in a second zone and fails over automatically. It is for availability, and the standby does not serve traffic.
- Read replicas are asynchronous copies that serve read queries. They are for scale, and they can lag behind the primary.
- Automated backups with point-in-time recovery let you restore to any second within the retention window. That is what saves you from a bad migration or an accidental
DELETE, which replication would faithfully copy. - Place the database in isolated subnets, with a security group that admits only the application's security group, and take credentials from a secret manager.
- A backup you have never restored is a hope, not a backup. Practise the restore, and time it.
Two numbers frame every recovery conversation. RPO, the recovery point objective, is how much data you can afford to lose, measured in time. RTO, the recovery time objective, is how long you can afford to be down. Multi-AZ gives an RPO of roughly zero and an RTO of a minute or two for a zone failure. Restoring from last night's backup gives an RPO of up to a day. Choose by asking the business, not by guessing.
All of this should be created with Terraform from the earlier module, not in the console. The console is for learning and for looking; code is for anything that has to exist tomorrow.