Skip to content

Artifact Registry: Architecture & Repository Types

Tại sao quan trọng

Nơi bạn lưu trữ artifacts (Docker images, npm packages, Maven JARs, Python wheels) ảnh hưởng tới:

  • Deployment latency: Image pull time từ registry
  • Cost: Storage, egress bandwidth
  • Security: Access control, vulnerability scanning, artifact governance
  • Scalability: Registry performance khi push/pull hàng ngàn images

Artifact Registry là successor của Container Registry — nó cấp rộng hơn: support multiple package formats, tốt hơn governance, tích hợp sâu với Cloud Build.

Chương này dạy bạn architecture bên trong, repository types, cost optimization, và security posture.


Architecture: Artifact Registry Model

Storage Layer

Artifact Registry (logical service)
  └─ Regional repositories
     ├─ us-central1: repo1, repo2
     ├─ us-east1: repo3
     └─ europe-west1: repo4
     
     ↓ (backed by)
     
     GCS buckets (internal, managed by Google)
     ├─ gs://artifacts-us-central1-xxxxx/ (repo1 data)
     ├─ gs://artifacts-us-central1-xxxxy/ (repo2 data)
     └─ ...

Key insight: Mỗi repository được backed bởi một managed GCS bucket. Bạn không directly access bucket, nhưng understanding cơ chế này giúp understand storage model.

Regional Architecture

Global Artifact Registry Service (API endpoint)
  ├─ Repository: us-central1/docker (backing GCS bucket at us-central1)
  ├─ Repository: us-east1/docker (backing GCS bucket at us-east1)
  └─ Repository: europe-west1/docker

Push/Pull traffic:
  - Developer ở us-central1 → us-central1 repo (local, fast)
  - Developer ở us-east1 → us-east1 repo (local, fast)
  - developer ở europe → europe-west1 repo (local, fast)

Why regional?

  1. Data locality: Images stored ở region gần consumers → faster pulls
  2. Compliance: Dữ liệu stays ở specific geography
  3. Cost: Egress charges nếu pull từ different region

Repository Types

Artifact Registry supports multiple package formats:

1. Docker (Container Images)

bash
gcloud artifacts repositories create docker-repo \
  --repository-format=docker \
  --location=us-central1

Used for: OCI container images, Docker images

2. Maven (Java)

bash
gcloud artifacts repositories create maven-repo \
  --repository-format=maven \
  --location=us-central1

Used for: Java JAR files, Maven projects

3. npm (JavaScript/Node.js)

bash
gcloud artifacts repositories create npm-repo \
  --repository-format=npm \
  --location=us-central1

Used for: npm packages, Node.js dependencies

4. Python (PyPI)

bash
gcloud artifacts repositories create python-repo \
  --repository-format=python \
  --location=us-central1

Used for: Python wheels, PyPI packages

5. Go

bash
gcloud artifacts repositories create go-repo \
  --repository-format=go \
  --location=us-central1

Used for: Go modules

6. APT/YUM (OS Packages)

bash
gcloud artifacts repositories create apt-repo \
  --repository-format=apt \
  --location=us-central1

Used for: Debian, Ubuntu packages

7. Generic

bash
gcloud artifacts repositories create generic-repo \
  --repository-format=generic \
  --location=us-central1

Used for: Any binary artifact (executables, tarballs, etc.)


Repository Configuration & Organization

Single Project, Multiple Repositories

Best practice: Organize theo type hoặc team:

bash
# Organize by type
gcloud artifacts repositories create docker-prod \
  --repository-format=docker --location=us-central1

gcloud artifacts repositories create npm-prod \
  --repository-format=npm --location=us-central1

# Or organize by team
gcloud artifacts repositories create team-backend \
  --repository-format=docker --location=us-central1

gcloud artifacts repositories create team-frontend \
  --repository-format=docker --location=us-central1

Naming Convention

{artifact-type}-{environment}[-{team}]

Examples:
- docker-prod
- docker-staging
- npm-internal
- maven-java-services
- python-ml-platform

Access Control (IAM)

bash
# Allow specific service account to push images
gcloud artifacts repositories add-iam-policy-binding docker-prod \
  --location=us-central1 \
  --member=serviceAccount:cloud-build-pusher@PROJECT.iam.gserviceaccount.com \
  --role=roles/artifactregistry.writer

# Allow service to pull images
gcloud artifacts repositories add-iam-policy-binding docker-prod \
  --location=us-central1 \
  --member=serviceAccount:gke-puller@PROJECT.iam.gserviceaccount.com \
  --role=roles/artifactregistry.reader

Integration with Cloud Build

Automatic Authentication

Cloud Build automatically authenticates to Artifact Registry:

yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'push'
      - 'us-central1-docker.pkg.dev/PROJECT_ID/docker-repo/app:latest'
      # Authentication handled automatically by Cloud Build

How?

Cloud Build service account has artifactregistry.writer role → can push/pull automatically.

Multi-Repository Push

yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'app:latest', '.']
  
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'push'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/prod/app:latest'
      - 'us-east1-docker.pkg.dev/$PROJECT_ID/prod/app:latest'
      # Push to both regions

Virtual Repositories (Aggregation)

Virtual repository groups multiple repositories:

bash
gcloud artifacts repositories create aggregated \
  --repository-format=docker \
  --location=us-central1 \
  --mode=virtual \
  --upstream-repositories='docker-prod,docker-staging'

Use case: Single pull endpoint serving images từ multiple repositories


Cost Model & Optimization

Storage Cost

$0.026 per GB per month (as of 2026)

Example:
- 10 Docker images @ 500 MB each = 5 GB
- Cost = 5 * $0.026 = $0.13/month

Egress Cost

$0.12 per GB (same region): Free
$0.12 per GB (different region): Paid egress
$0.50+ per GB (to internet): Most expensive

Optimization strategies:

  1. Collocate images và consumers: If GKE cluster ở us-central1, store images ở us-central1 repo
  2. Reuse base images: Large base images pulled frequently → cache locally
  3. Clean up old images: Implement retention policies (see Chapter 6)

Example Cost Scenario

Scenario: 100 deployments per day

Option A: Single large image (1 GB)
- Store ở us-central1
- GKE pulls from us-central1
- Cost: 1 GB storage * $0.026 = $0.026/month
- Egress: Free (same region)
- Total: ~$0.026/month

Option B: Large images spread across 5 regions
- Each region: 1 GB image
- Cost: 5 GB * $0.026 = $0.13/month
- Egress: 100 deployments * 1 GB * $0.12 (cross-region) = $12/month
- Total: ~$12/month

Conclusion: Consolidate images to regions where consumers are.


Real-World: Multi-Environment Repository Setup

Scenario

  • Backend services: 20+ microservices
  • Environments: dev, staging, prod
  • Regions: us-central1 (primary), us-east1 (failover), europe-west1

Repository Design

Artifact Registry Repositories:

1. docker-prod-us-central1 (primary production)
   ├─ Images: app-api, app-worker, app-scheduler
   └─ Retention: 30 days

2. docker-staging-us-central1
   ├─ Images: all services (staging versions)
   └─ Retention: 7 days

3. docker-dev-us-central1
   ├─ Images: developer builds
   └─ Retention: 3 days

4. docker-prod-us-east1 (DR replica)
   └─ Replicated from docker-prod-us-central1

5. docker-prod-europe-west1 (EMEA region)
   └─ Replicated from docker-prod-us-central1

Setup Script

bash
# Create primary prod repo
gcloud artifacts repositories create docker-prod \
  --repository-format=docker \
  --location=us-central1

# Create staging
gcloud artifacts repositories create docker-staging \
  --repository-format=docker \
  --location=us-central1

# Create dev
gcloud artifacts repositories create docker-dev \
  --repository-format=docker \
  --location=us-central1

# For DR: replica to us-east1
gcloud artifacts repositories create docker-prod-dr \
  --repository-format=docker \
  --location=us-east1

IAM Setup

bash
# Cloud Build can push to all repos
for repo in docker-prod docker-staging docker-dev; do
  gcloud artifacts repositories add-iam-policy-binding $repo \
    --location=us-central1 \
    --member=serviceAccount:cloud-build@PROJECT.iam.gserviceaccount.com \
    --role=roles/artifactregistry.writer
done

# GKE prod can pull from prod repo
gcloud artifacts repositories add-iam-policy-binding docker-prod \
  --location=us-central1 \
  --member=serviceAccount:gke-prod@PROJECT.iam.gserviceaccount.com \
  --role=roles/artifactregistry.reader

# GKE staging can pull from staging
gcloud artifacts repositories add-iam-policy-binding docker-staging \
  --location=us-central1 \
  --member=serviceAccount:gke-staging@PROJECT.iam.gserviceaccount.com \
  --role=roles/artifactregistry.reader

Advanced: Remote Repositories & Caching

Remote Repository (Upstream Caching)

bash
gcloud artifacts repositories create docker-remote \
  --repository-format=docker \
  --location=us-central1 \
  --mode=remote \
  --remote-repository-config-enabled

Use case: Act as cache for Docker Hub / public registries

yaml
# Instead of pulling directly from Docker Hub
# docker pull ubuntu:22.04

# Pull from your remote repo (cached)
# docker pull us-central1-docker.pkg.dev/PROJECT/docker-remote/ubuntu:22.04

# First pull: fetches from Docker Hub, caches ở Artifact Registry
# Subsequent pulls: fast (from local cache)

Benefits:

  • Control upstream sources
  • Cache public images locally
  • Faster pulls for frequently used images
  • Compliance: All pulls go through your registry

Constraints & Failure Modes

Image Push Fails

ERROR: (gcloud.builds.submit) User does not have permission [artifactregistry.files.create]

Solution: Grant service account write permission

bash
gcloud artifacts repositories add-iam-policy-binding docker-repo \
  --location=us-central1 \
  --member=serviceAccount:builder@PROJECT.iam.gserviceaccount.com \
  --role=roles/artifactregistry.writer

Image Pull Slow

Possible causes:

  1. Image pulled from different region
  2. Image not cached locally
  3. Network latency

Solution:

  • Store images ở region close to consumers
  • Use remote repositories for frequently pulled public images

Repository Quota Exceeded

ERROR: Repository quota exceeded

Limits: Default 1000 repositories per project

Solution: Delete unused repositories

bash
gcloud artifacts repositories delete docker-old --location=us-central1

References