Home › CKAD › Topics › Practice tasks › Deployment Strategies
CKAD · Application Deployment

Run a Canary Release Behind an Existing Service

In namespace default, the following resources exist: Deployment web-app with 5 replicas, labels app=webapp, version=v1 Service web-service with selector app=webapp

Check live lab access → All CKAD tasks

Live lab access

This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.

Create an account to continue →

Read this week's free task →

On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.

The task

Task

In namespace default, the following resources exist:

Requirements

  1. Scale Deployment web-app to 8 replicas (80% of 10 total)
  2. Create a new Deployment web-app-canary with 2 replicas, labels app=webapp, version=v2
  3. Both Deployments should be selected by web-service
  4. Verify the traffic split using endpoints

Note: This is a manual canary pattern where traffic is split based on replica counts.

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster.

Split traffic by replica count: a manual canary behind one Service

Kubernetes has no built-in "send 10% to the new version" switch. What it does have is a Service that forwards to every ready Pod matching its selector. If two Deployments produce Pods that both match that selector, the share each version receives follows the share of Pods it owns. That is the whole canary trick, and the exam expects you to build it with labels and prove it with EndpointSlices.

Service quotes  (selector: app=quotes)
   |-- quotes-stable  3 Pods  app=quotes, release=stable
   '-- quotes-canary  1 Pod   app=quotes, release=canary   => about 1 in 4 requests

1. Give every Pod a shared label and a track label

Each Pod template carries two labels. app=quotes is the one the Service selects. release tells the tracks apart, and each Deployment includes it in its own spec.selector, so the two controllers never claim each other's Pods. The image is the small hostname server from the Kubernetes Service debugging guide; it answers on port 9376 with the Pod's name, which makes the split visible. Save this as canary-tracks.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: quotes-stable
  namespace: prepium-tutorial
spec:
  replicas: 3
  selector:
    matchLabels:
      app: quotes
      release: stable
  template:
    metadata:
      labels:
        app: quotes
        release: stable
    spec:
      containers:
      - name: server
        image: registry.k8s.io/serve_hostname
        ports:
        - containerPort: 9376
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: quotes-canary
  namespace: prepium-tutorial
spec:
  replicas: 1
  selector:
    matchLabels:
      app: quotes
      release: canary
  template:
    metadata:
      labels:
        app: quotes
        release: canary
    spec:
      containers:
      - name: server
        image: registry.k8s.io/serve_hostname
        ports:
        - containerPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: quotes
  namespace: prepium-tutorial
spec:
  selector:
    app: quotes
  ports:
  - port: 80
    targetPort: 9376
kubectl create namespace prepium-tutorial
kubectl apply -f canary-tracks.yaml
kubectl -n prepium-tutorial get pods -l app=quotes -L release

The -L release flag adds a RELEASE column, so you can count stable and canary Pods at a glance.

2. Prove both tracks sit behind the Service

The control plane builds EndpointSlices for any Service with a selector and labels them with kubernetes.io/service-name. Each endpoint has a targetRef naming the Pod and a conditions.ready flag:

kubectl -n prepium-tutorial get endpointslices -l kubernetes.io/service-name=quotes \
  -o jsonpath='{range .items[*].endpoints[*]}{.targetRef.name}{"\t"}{.conditions.ready}{"\n"}{end}'

You want four lines, three starting with quotes-stable- and one with quotes-canary-, all true. Now sample real traffic from inside the cluster:

kubectl -n prepium-tutorial run probe --image=busybox:1.36 --restart=Never --rm -it -- \
  sh -c 'for i in $(seq 1 20); do wget -qO- http://quotes; echo; done'

Roughly a quarter of the replies should name the canary Pod. In kube-proxy's iptables mode each new connection picks a backend at random, so the ratio is a tendency over many requests, not an exact rotation.

3. Move the dial by scaling

The canary share is canary Pods divided by all ready Pods. Promote the canary to half the traffic without touching any label:

kubectl -n prepium-tutorial scale deployment quotes-stable --replicas=2
kubectl -n prepium-tutorial scale deployment quotes-canary --replicas=2

Re-run the EndpointSlice query: two of each. Only ready endpoints count, so a canary Pod failing its readiness probe receives nothing, which is often exactly the safety net you want.

4. Contrast: blue-green switches the selector instead

Blue-green keeps both versions fully scaled and makes the Service choose one by adding the track label to its selector. The cut-over is a single selector change, all or nothing, and rollback is the same change in reverse:

kubectl -n prepium-tutorial patch service quotes --type=merge \
  -p '{"spec":{"selector":{"app":"quotes","release":"canary"}}}'

The EndpointSlice now lists only canary Pods. Canary trades that instant switch for gradual exposure.

Common mistakes

Example checkEvidence
Service matches both tracksspec.selector holds only the shared label
Replica ratio is as intendedREADY counts on both Deployments
Both tracks receive trafficEndpointSlice targetRef names from each Deployment, all ready
Tracks stay separateEach Deployment's selector includes its own track value

Cleanup: kubectl delete namespace prepium-tutorial. References: Deploy a release using a canary deployment, EndpointSlices, Virtual IPs and service proxies. Next, try rolling updates and rollback or Service selector troubleshooting.

Exam
CKAD
Domain
Application Deployment
Grading
Programmatic · partial credit

What this tests

Roll out and update deployments, run canary and blue-green strategies, and right-size workloads. On the CKAD exam, Application Deployment tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.

Practice it for real

The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.

Related CKAD tasks