G
GuideDevOps
Lesson 10 of 12

Serverless Computing

Part of the Cloud Computing tutorial series.

What is Serverless?

No servers to manage. You write code, cloud provider handles:

  • Provisioning
  • Scaling
  • Patching
  • Monitoring

You pay only for execution time/invocations.


Functions as a Service (FaaS)

AWS Lambda

Write functions, triggered by events. Pay per invocation + GB-seconds.

# Create function
cat > lambda_function.py << 'EOF'
def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': 'Hello from Lambda!'
    }
EOF
 
zip function.zip lambda_function.py
 
aws lambda create-function \
  --function-name hello-world \
  --runtime python3.9 \
  --role arn:aws:iam::ACCOUNT:role/lambda-role \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://function.zip
 
# Invoke
aws lambda invoke \
  --function-name hello-world \
  --payload '{"key": "value"}' response.json
 
cat response.json

Triggers

# Trigger from S3 upload
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:s3:::my-bucket \
  --function-name my-function \
  --enabled
 
# Trigger from API Gateway
aws apigateway create-rest-api --name myapi
 
# Trigger from CloudWatch (schedule)
aws events put-rule --name my-schedule --schedule-expression "rate(5 minutes)"
aws events put-targets --rule my-schedule --targets "Id"="1","Arn"="arn:aws:lambda:..."

Azure Functions

# Create function app
az functionapp create \
  --name myapp \
  --resource-group myRG \
  --runtime python \
  --runtime-version 3.9 \
  --functions-version 4
 
# Create HTTP function
az functionapp function create \
  --name myapp \
  --function-name hello \
  --template "HTTP trigger" \
  --resource-group myRG

GCP Cloud Functions

# Create function
cat > main.py << 'EOF'
def hello_world(request):
    return 'Hello from Cloud Functions!'
EOF
 
gcloud functions deploy hello-world \
  --runtime python39 \
  --trigger-http \
  --allow-unauthenticated

Containers (Serverless)

Run containers without managing Kubernetes

AWS Fargate (ECS)

# Create task definition
aws ecs register-task-definition \
  --family hello-world \
  --network-mode awsvpc \
  --requires-compatibilities FARGATE \
  --cpu 256 \
  --memory 512 \
  --container-definitions '[{"name": "hello", "image": "nginx:latest", "portMappings": [{"containerPort": 80}]}]'
 
# Create service
aws ecs create-service \
  --cluster my-cluster \
  --service-name hello \
  --task-definition hello-world \
  --desired-count 1 \
  --launch-type FARGATE

Azure Container Instances

# Create container
az container create \
  --resource-group myRG \
  --name mycontainer \
  --image nginx \
  --ports 80
 
# Get IP
az container show --resource-group myRG --name mycontainer --query ipAddress.ip

GCP Cloud Run

# Deploy container
gcloud run deploy hello \
  --image gcr.io/my-project/hello \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated
 
# Scales to zero when unused

Serverless Databases

AWS DynamoDB (Serverless)

Pay per request, scales automatically

aws dynamodb create-table \
  --table-name Users \
  --attribute-definitions AttributeName=UserID,AttributeType=S \
  --key-schema AttributeName=UserID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST  # Serverless!

Firestore (Serverless)

# Full serverless - no infrastructure
gcloud firestore databases create --location=us-central1 --type=DATASTORE_MODE

API Gateway

Build stateless APIs

AWS API Gateway

# Create REST API
aws apigateway create-rest-api \
  --name my-api \
  --description "My serverless API"
 
# Create resource
aws apigateway create-resource \
  --rest-api-id xxxxx \
  --parent-id rrrr \
  --path-part users
 
# Create method
aws apigateway put-method \
  --rest-api-id xxxxx \
  --resource-id rrrr \
  --http-method GET \
  --authorization-type NONE
 
# Integrate with Lambda
aws apigateway put-integration \
  --rest-api-id xxxxx \
  --resource-id rrrr \
  --http-method GET \
  --type AWS_PROXY \
  --integration-http-method POST \
  --uri arn:aws:apigateway:...:lambda:path/2015-03-31/functions/arn:aws:lambda:.../invocations
 
# Deploy
aws apigateway create-deployment --rest-api-id xxxxx --stage-name prod

GCP API Gateway

# openapi.yaml
openapi: 3.0.0
info:
  title: My API
servers:
  - url: https://api.example.com
paths:
  /users:
    get:
      x-google-backend:
        address: https://region-project.cloudfunctions.net/getUsers
gcloud api-gateway apis create my-api
gcloud api-gateway api-configs create prod --api my-api --openapi-spec openapi.yaml

Monitoring Serverless

AWS CloudWatch

# View logs
aws logs tail /aws/lambda/my-function --follow
 
# Get metrics
aws cloudwatch get-metric-statistics \
  --namespace AWS/Lambda \
  --metric-name Duration \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-02T00:00:00Z \
  --period 3600 \
  --statistics Average
 
# Create alarm
aws cloudwatch put-metric-alarm \
  --alarm-name lambda-errors \
  --metric-name Errors \
  --namespace AWS/Lambda \
  --statistic Sum \
  --period 300 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold

GCP Cloud Logging

# Tail logs
gcloud functions logs read hello-world --limit 100 --follow
 
# Query logs
gcloud logging read "resource.type=cloud_function AND resource.labels.function_name=hello-world"

Pricing Comparison

AWS Lambda

$0.20 per 1 million requests
$0.0000166667 per GB-second (usually $0.50 per GB-month)
Free tier: 1 million requests + 400,000 GB-seconds/month

Azure Functions

$0.20 per million invocations
$0.000016667 per GB-second (usually $0.500 per GB-month)
First 1 million invocations free

GCP Cloud Functions

$0.40 per million invocations
$0.0000025 per GB-second
First 2 million invocations free

Best Practices

✅ Keep functions small and focused ✅ Use managed services (no self-managed infrastructure) ✅ Monitor cold start times ✅ Set timeout appropriately ✅ Use environment variables for configuration ✅ Version your functions ✅ Test locally before deploying ✅ Set resource limits (memory, concurrency)

❌ Don't assume functions are fast (cold starts) ❌ Don't store state in function code ❌ Don't forget to set timeouts ❌ Don't debug in production