CertNote/ Commute Study Notes
Roadmap
KOEN
CLF-C02 · FoundationalCloud Practitioner - Foundational
DVA-C02 · AssociateDeveloper - Associate
SAA-C03 · AssociateSolutions Architect - Associate
SOA-C02 · AssociateCloudOps Engineer - Associate
SAP-C02 · ProfessionalSolutions Architect - Professional
DOP-C02 · ProfessionalDevOps Engineer - Professional
  • Week 1
    • 1.DevOps as an Operating Model: The Five Axes of CALMS and the Truth DORA Proved Through Measurement
    • 2.Well-Architected Framework: Rereading It Through the Six Lenses of DevOps
    • 3.The AWS DevOps Tool Map: The Code* Series and the Real Picture Beyond It
    • 4.Multi-Account Strategy: The Real Picture of Organizations, Control Tower, and IAM Identity Center
    • 5.Week 1 Wrap-Up: Cementing the DevOps Thinking Frame with Scenarios
  • Week 2
  • Week 3
    • 1.The Real Meaning of buildspec.yml: The Moment a Pipeline Specification Becomes Code
    • 2.The Physics of Build Speed: Trade-offs Among Cache, Parallelism, and Compute
    • 3.Design Principles of Secret Management: The Criteria That Separate Secrets Manager from Parameter Store
    • 4.VPC CodeBuild, Custom Images, ARM/Graviton: Expanding the Boundary of the Build Environment
    • 5.Week 3 Review: Integrated CodeBuild Scenarios and Practical Judgment
  • Week 4
  • Week 5
  • Week 6
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
  • Week 14
  • Week 15
  • Week 16
Linux Master 2 · 2급KAIT Linux Master - Level 2
SCS-C03 · SpecialtySecurity - Specialty
Linux Master 1 · 1급KAIT Linux Master - Level 1
MLA-C01 · AssociateMachine Learning Engineer - Associate
AIF-C01 · FoundationalAI Practitioner - Foundational
DEA-C01 · AssociateData Engineer - Associate
MLS-C01 · SpecialtyMachine Learning - Specialty
SQLD · 개발자SQL Developer (SQLD)

© CertNote · 주간랩스

  • About
  • Changelog
  • Contact
  • Terms
  • Privacy
← DOP-C02/Week 3/Day 5

Based on the DOP-C02 exam guide·Report an error

DOP-C02· ProWeek 3 · Day 5~45 min read

Day 5 - Week 3 Review: Integrated CodeBuild Scenarios and Practical Judgment

The single question running through this week was "how much do you treat the build environment like code?" buildspec.yml expresses the build procedure, cache strategy expresses build speed, secrets configuration expresses the security boundary, and VPC mode expresses the network boundary — all as code. Add ARM builds and even architecture selection moves inside the build pipeline.

The DOP-C02 exam does not ask about these elements separately. It asks in integrated form: "given these constraints at this company, which configuration is correct?" Today we practice that integrated judgment. First we lay out the core comparison structures at a glance, then point out the trap patterns, then verify judgment with 12 scenario questions.

A weekly review must not become a mere summary. The goal is a level where you can explain to yourself "why A and why not B." If you can't explain it, you'll freeze in the exam room in front of two options that both look 90% right.

💡 The purpose of review: You learned the content of each Day of Week 3 independently, but real problems mix that knowledge. A problem like "there's a network error when using Secrets Manager in a VPC mode build" is only solvable if you know VPC + Secrets Manager + endpoints at the same time. Today is the day we build those connections.


Reconstructing the Core Concepts of Week 3

The Structure of buildspec.yml: Phases and Flow

The four phases of buildspec.yml (install → pre_build → build → post_build) have meaning in their order. install prepares the runtime itself, pre_build handles login and environment checks, build does the actual compilation and tests, and post_build handles image push, tagging, and notifications. The finally block runs even if the phase fails — use it for cleanup work (deleting temporary files, sending failure notifications).

version: 0.2
phases:
  install:
    runtime-versions:
      java: corretto17
    commands:
      - echo "installing tools"
  pre_build:
    commands:
      - aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
  build:
    commands:
      - mvn test
      - docker build -t $IMAGE_TAG .
  post_build:
    commands:
      - docker push $IMAGE_TAG
    finally:
      - echo "build finished (regardless of success/failure)"
env:
  secrets-manager:
    DB_PASS: prod/myapp:db_password
  exported-variables:
    - IMAGE_TAG
reports:
  JUnitResults:
    files:
      - '**/surefire-reports/*.xml'
    file-format: JUNITXML
cache:
  paths:
    - '/root/.m2/**/*'

🔍 Going deeper: exported-variables matters when integrating with CodePipeline. It lets a variable produced by CodeBuild (e.g., IMAGE_TAG) be referenced by the next Action. The pattern where, in an ECS Blue/Green pipeline, CodeBuild exports the image URI via exported-variables and the Deploy Action receives it and injects it into the Task Definition appears frequently on the exam.

💡 Related theory: The finally block applies the try-finally pattern from programming languages to build phases. Putting "cleanup work" that must run even on failure into finally is in the same spirit as the Resource Acquisition Is Initialization (RAII) principle — resources (logs, temporary files, external service state) must always be cleaned up after use.


Comparing Cache Strategies: When to Use What

Caching divides into "where you store it" and "what you cache."

Cache typeStorage locationOn host changeSuitable targetsCaution
Local Sourcebuild host diskmissreducing Git source clone timeeffective only in host-pinned environments
Local Docker Layerbuild host Dockermissreusing Dockerfile layersprivilegedMode: true required
S3 CustomS3 buckethitnode_modules, .m2, .gradlewatch object size (500MB+)
BuildKit + ECR RegistryECRhitDocker layers (including npm install)combine with ECR Pull Through Cache
# S3 cache example
cache:
  type: S3
  location: my-codebuild-cache/java-build
  paths:
    - '/root/.m2/**/*'
    - '/root/.gradle/caches/**/*'
# Local Docker Layer cache (requires privilegedMode)
cache:
  type: LOCAL
  modes:
    - LOCAL_DOCKER_LAYER_CACHE
    - LOCAL_SOURCE_CACHE

⚠️ Pitfall: When you push node_modules into the S3 cache and the directory exceeds 500MB, S3 upload/download overhead becomes longer than the npm install time — a counterproductive result. In that case, splitting the npm install layer in the Dockerfile and using BuildKit + ECR Registry Cache is more efficient.

📚 Case study: In a large Java project (3GB+ of Maven dependencies), applying the S3 cache actually made builds slower. The cause was that the 3GB S3 download time (2 minutes) exceeded Maven dependency resolution (40 seconds). The fix was narrowing the S3 cache paths to include only internal artifacts, like ~/.m2/repository/com/mycompany/**/*.


Secrets Manager vs Parameter Store: The Selection Decision Tree

Is it a secret value?
  ├─ Automatic rotation needed?
  │   └─ YES → Secrets Manager ($0.40/secret/month)
  │           ├─ RDS credentials: RDS Rotation Lambda auto-generated
  │           ├─ Custom values: write your own Rotation Lambda
  │           └─ buildspec: env.secrets-manager
  └─ Simple configuration value, no rotation needed?
      ├─ Free tier sufficient? → Parameter Store Standard (free)
      │                       └─ buildspec: env.parameter-store
      └─ Need TPS > 40? → Parameter Store Advanced ($0.05 per 10,000 API calls)

Cross-account scenario: for CodeBuild to read a secret in another account's Secrets Manager, you need

  1. A resource-based policy added to the secret (allowing the build account's Role ARN)
  2. A grant added on the KMS key that encrypted the secret
  3. secretsmanager:GetSecretValue + kms:Decrypt permissions on the CodeBuild Service Role

💡 Related theory: Secrets Manager's automatic rotation is structured so that a Rotation Lambda performs the actual replacement. It's a 4-step protocol in which the Lambda creates the new secret (createSecret) → applies it to the DB (setSecret) → verifies it (testSecret) → activates it (finishSecret). Understanding this protocol explains "why there is no service downtime during rotation" — the new version under the AWSPENDING label is promoted to AWSCURRENT only after it has been prepared and verified.

🔍 Going deeper: Parameter Store's 40 TPS limit becomes a real bottleneck in large-scale Lambda environments. When hundreds of Lambdas read configuration from Parameter Store simultaneously during cold starts, ThrottlingException occurs. Remedies: (1) upgrade to Parameter Store Advanced (higher TPS limit), (2) cache the configuration in memory at Lambda initialization (the same execution environment is reused), (3) use Secrets Manager (higher TPS limit).


VPC Mode Architecture: Endpoint Design

CodeBuild in VPC mode cannot directly reach the general internet. Each external service needs an appropriate path.

[CodeBuild Container in Private Subnet]
    │
    ├─ S3 (artifact, cache) → S3 Gateway Endpoint (free, route table)
    ├─ Secrets Manager → Interface Endpoint ($0.01/hour)
    ├─ KMS → Interface Endpoint ($0.01/hour)
    ├─ ECR API → Interface Endpoint ($0.01/hour)
    ├─ ECR DKR (Docker layers) → Interface Endpoint ($0.01/hour)
    ├─ CloudWatch Logs → Interface Endpoint or NAT Gateway
    └─ External internet (npm, Maven Central, etc.) → NAT Gateway required

⚠️ Pitfall: "I turned on VPC mode and now I get S3 permission errors" is almost always caused by a missing S3 Gateway Endpoint. A Gateway Endpoint is not added to the route table automatically — you must attach it in the VPC configuration yourself and include it in the build subnet's route table. Unlike Interface Endpoints it's free, so always configure it for VPC builds.

📚 Case study: After one team migrated CodeBuild to VPC mode, build costs increased by $200 per month. Tracing the cause revealed data transfer costs for reaching S3 through the NAT Gateway. Adding an S3 Gateway Endpoint brought that cost down to $0. They also added an ECR Interface Endpoint to cut Docker layer pull costs. In VPC mode, network path optimization translates directly into cost.


Custom Docker Image vs AWS Managed Image

ItemAWS Managed ImageCustom Image (ECR)
MaintenanceAWS patches itthe team builds and pushes it
Build start speedfast (pre-prepared)can be slower (image pull)
Tool customizationlimitedfully free
imagePullCredentialsTypeCODEBUILDSERVICE_ROLE
privilegedModeusually unnecessaryrequired for Docker builds
CostnoneECR storage + transfer

A Custom Image's imagePullCredentialsType: SERVICE_ROLE means the CodeBuild Service Role's permissions are used to pull the image from ECR. That Role needs ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, and ecr:GetAuthorizationToken.

💡 Related theory: The core reason to use a Custom Image is build reproducibility. An image the team manages itself guarantees "the same tool versions and the same result no matter when you build." With an AWS Managed Image, build results can change when AWS updates it (e.g., Python 3.11.1 → 3.11.4 patch). In environments requiring audit trails, such as finance and healthcare, Custom Image + specifying the image digest (SHA256, not a tag) is the standard.


Build Batch: Parallelization Strategies

Batch typeStructureSuitable cases
build-listindependent builds run in parallelmulti-architecture (x86/ARM), multi-service
build-matrixevery combination of variablesmulti-runtime × multi-OS combinations
build-grapha DAG with dependenciesguaranteeing common-build → dependent-build ordering
# build-matrix example: Python 3.9/3.10/3.11 × Linux/ARM
batch:
  build-matrix:
    static:
      ignore-failure: false
    dynamic:
      buildspec:
        - buildspec_linux.yml
        - buildspec_arm.yml
      env:
        variables:
          PYTHON_VERSION:
            - "3.9"
            - "3.10"
            - "3.11"

This configuration runs 2 × 3 = 6 builds in parallel.

🔍 Going deeper: build-graph supports DAG (Directed Acyclic Graph) dependencies. It's the pattern of "build the shared library first, and on success build services A/B/C in parallel using that artifact." It's especially useful in monorepos. When you declare dependencies with the depend-on field, CodeBuild performs the topological sort automatically.


Reserved Capacity Fleet vs On-Demand: The Economics

ItemOn-DemandReserved Capacity Fleet
Billing modelper build minuteper hour the Fleet is maintained (regardless of builds)
Provisioning wait10-30 secondsnearly 0 seconds
Suitable environmentsporadic buildscontinuous, high-frequency builds
Minimum Fleet sizeN/A1 instance

An example break-even calculation:

  • Provisioning waste: 300 builds/day × 30 seconds = 2.5 hours/day
  • If the Fleet's fixed cost is lower than the On-Demand cost of those 2.5 hours, the Fleet wins

💡 Related theory: The economics of a Fleet is a choice between fixed cost and variable cost. When demand is predictable and continuous, fixed cost (Fleet) wins; when demand is irregular, variable cost (On-Demand) wins. It's the same logic as AWS Reserved Instances. If your build pattern "concentrates in specific hours of the day," consider setting different Fleet sizes per time window, or a Fleet that supports Auto Scaling.


Trap Patterns, Consolidated

Trap 1: "To go faster, raise the Compute Type" Always wrong. I/O-bound builds (package downloads, S3 uploads, ECR pushes) don't get faster with more CPU. Measure CloudWatch's BuildDuration and per-phase times first, then apply the means appropriate to the bottleneck phase (cache, parallelism, network path).

Trap 2: "Secrets are fine in env.variables as long as they're KMS-encrypted" env.variables is written in plaintext in buildspec.yml and exposed in build logs. Regardless of KMS encryption, writing the value directly into the buildspec risks leakage. Always use env.secrets-manager or env.parameter-store.

Trap 3: "Local Cache is always faster" If the build host changes, you get a cache miss. The S3 cache is more reliable. That said, the S3 cache also backfires when the object is too large due to download overhead.

Trap 4: "ARM builds are fine with QEMU" It works, but it's slow, and compiling native code (C/C++/Rust) can hit emulation instability. ARM_CONTAINER + native builds is the standard.

Trap 5: "In VPC mode, every AWS service is automatically reachable" Wrong. VPC mode only attaches the build container to the VPC. To reach each AWS service, you must configure a VPC Endpoint (Gateway or Interface) separately. If you need the internet, you also need a NAT Gateway.

Trap 6: "Secrets Manager is always better than Parameter Store" The costs differ. Using Secrets Manager for 95 simple configuration values that need no rotation costs $38/month, whereas Parameter Store Standard costs $0. Choose the tool according to the requirement (whether rotation is needed).

⚠️ Traps, consolidated: The common pattern in these traps is "picking an answer by tool name without looking at the requirements." The essential habit is to find the requirement keyword in the exam question first. "Automatic rotation" → Secrets Manager, "host-pinned" → Local Cache, "ARM workload" → ARM_CONTAINER, "private resources" → VPC mode + endpoints.

🎯 Scenario: A team reported "builds are slow." Looking at CloudWatch, of the total 8-minute build, DOWNLOAD_SOURCE was 2 minutes + PRE_BUILD (npm install) 4 minutes + actual BUILD 2 minutes. Where do you optimize first? The answer is that PRE_BUILD (npm install) is the biggest bottleneck, so applying an S3 Cache or BuildKit + ECR Cache comes first. DOWNLOAD_SOURCE can be reduced with a Local Source Cache, but that's ineffective when the build host changes, so also consider configuring a Git shallow clone. Upgrading the Compute Type has no effect in this case.


Wrapping Up: Connecting Week 3's Knowledge

Connecting what we learned over the week into a single flow:

buildspec.yml → expresses the build procedure as code. Each phase has a clear role, and finally is for cleanup work.

Cache → the practical improvement to build speed. Whether the host is pinned and how large the objects are determine the strategy.

Secrets → secret values must always go through env.secrets-manager or env.parameter-store. Whether rotation is needed is what separates Secrets Manager from Parameter Store.

VPC mode → the only way to reach private resources. Endpoint design and subnet size determine operational quality.

Build Batch → the parallelization strategy. Independent builds use build-list, combinations use build-matrix, dependencies use build-graph.

Custom Image → used instead of an AWS Managed Image in environments where reproducibility matters. The SERVICE_ROLE credentials type is required.

Reserved Fleet → removes provisioning overhead in high-frequency builds. Calculating the break-even point between fixed and variable costs drives the adoption decision.

📚 Week 3 end-to-end case: A company builds 10 microservices in a monorepo. Each service needs x86 and ARM images (20 builds), it must also run DB migration SQL, and every password rotates every 30 days. The network is inside a private VPC. The correct combination for this scenario: Build Batch build-list (20 in parallel) + VPC mode (private DB access) + S3 Gateway Endpoint (artifact upload) + Secrets Manager with Rotation (DB passwords) + a mix of ARM_CONTAINER and LINUX_CONTAINER (multi-architecture) + Reserved Fleet (dozens of builds per day) + ECR Pull Through Cache (avoiding the Docker Hub rate limit).

📝 Practice Questions

Click a choice to reveal the answer and explanation.

Question 1

npm install takes 4 minutes on every build. The build host may differ every time. What is the most effective improvement?

Question 2

The build must run migration SQL against an Aurora PostgreSQL instance in a private subnet. What is the most appropriate configuration?

Question 3

The DB password rotates automatically every 30 days. The build must always run the DB migration with the currently valid password. What is the most appropriate configuration?

Question 4

Builds fail every morning due to the Docker Hub rate limit. What is the most effective long-term fix?

Question 5

You must build Java and Python services simultaneously and produce ARM/x86 images for each. Four build combinations are needed in total. What is the most efficient configuration?

Question 6

Provisioning takes 30 seconds per build and you run 300 builds per day. That's 150 hours per month wasted on provisioning. What is the most direct fix?

Question 7

Of 100 secrets, only 5 need rotation. What configuration minimizes monthly cost?

Question 8

Starting a VPC build produces the error The maximum number of network interfaces has been reached for subnet. What is the most appropriate response?

Question 9

You need to connect directly into the build container to debug a failure. What is the most appropriate method?

Question 10

How do you visualize JUnit test results in the CodeBuild console and send an SNS notification on failure?

Question 11

In a multi-account environment, CodeBuild tries to read a Secrets Manager secret in Account B. CodeBuild is in Account A. What two configurations are required?

Question 12

You want to generate an SBOM (Software Bill of Materials) in a CodeBuild build to strengthen supply chain security. What is the most suitable implementation?

PreviousVPC CodeBuild, Custom Images, ARM/Graviton: Expanding the Boundary of the Build EnvironmentWeek 3 · Day 4Next In-place vs Blue/Green, AppSpec: The Physics of Deployment StrategiesWeek 4 · Day 1

Official references

  • DOP-C02 official exam page(opens in a new tab)
  • Amazon VPC documentation(opens in a new tab)
  • AWS CodeBuild documentation(opens in a new tab)
  • AWS Secrets Manager documentation(opens in a new tab)
  • Amazon S3 documentation(opens in a new tab)
  • Amazon RDS · Aurora documentation(opens in a new tab)

On this page

  • Reconstructing the Core Concepts of Week 3
  • The Structure of buildspec.yml: Phases and Flow
  • Comparing Cache Strategies: When to Use What
  • Secrets Manager vs Parameter Store: The Selection Decision Tree
  • VPC Mode Architecture: Endpoint Design
  • Custom Docker Image vs AWS Managed Image
  • Build Batch: Parallelization Strategies
  • Reserved Capacity Fleet vs On-Demand: The Economics
  • Trap Patterns, Consolidated
  • Wrapping Up: Connecting Week 3's Knowledge
  • Practice Questions