ReplicaSets

Welcome to the ReplicaSets chapter. This section covers fundamental concepts and best practices necessary to master this topic in depth.

1. The Genesis of ReplicaSets

A Pod on its own is mortal. If the Node it runs on crashes, the Pod dies with it. To build a highly available system, you cannot rely on individual Pods.

The solution is the ReplicaSet. A ReplicaSet ensures that a specified number of pod replicas are running at any given time.

The Control Loop (The “Thermometer” Analogy)

Think of a ReplicaSet like a thermostat.

  1. Desired State: You set the thermostat to 72°F (e.g., replicas: 3).
  2. Current State: The thermostat reads the room temperature at 68°F (e.g., currently 2 Pods running).
  3. Reconciliation: The thermostat turns on the heater to reach 72°F (e.g., the Controller Manager starts 1 more Pod).

The Kubernetes Control Plane constantly runs this loop, comparing the Current State to the Desired State and taking action to reconcile them.


2. Labels and Ownership

How does a ReplicaSet know which Pods belong to it? It uses Labels and Selectors.

A ReplicaSet manifest contains a selector block. It actively scans the cluster for Pods matching those labels. If it finds too few, it creates more. If it finds too many, it deletes some.

[!WARNING] If you manually create a standalone Pod with labels that match an existing ReplicaSet’s selector, the ReplicaSet will “adopt” it. If the ReplicaSet already has its desired number of Pods, it will immediately terminate your manually created Pod!


3. Interactive: ReplicaSet Control Loop

Adjust the desired replicas and simulate node failures to see the control loop in action.

Desired Replicas: 3

Current Pods: 3


4. Implementation Details

You define the Desired State in YAML. Here is a standard ReplicaSet manifest. Note the selector that ties it to the Pod template.

YAML Manifest
Java (Fabric8)
Go (client-go)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend-rs
  labels:
    app: guestbook
    tier: frontend
spec:
  # 1. Desired State
  replicas: 3

  # 2. How to find the Pods
  selector:
    matchLabels:
      tier: frontend

  # 3. What to create if Pods are missing
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
// Using Fabric8 Kubernetes Client to scale a ReplicaSet
try (KubernetesClient client = new KubernetesClientBuilder().build()) {
    // Read current state
    ReplicaSet rs = client.apps().replicaSets()
        .inNamespace("default")
        .withName("frontend-rs")
        .get();

    System.out.println("Current replicas: " + rs.getSpec().getReplicas());

    // Update desired state
    client.apps().replicaSets()
        .inNamespace("default")
        .withName("frontend-rs")
        .scale(5, true); // Scale to 5 replicas

    System.out.println("Scaled successfully.");
}
// Using client-go to scale a ReplicaSet
import (
	"context"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

func scaleReplicaSet(clientset *kubernetes.Clientset, ns string, name string, replicas int32) error {
    // Get current ReplicaSet
    rs, err := clientset.AppsV1().ReplicaSets(ns).Get(context.TODO(), name, metav1.GetOptions{})
    if err != nil {
        return err
    }

    // Update desired replicas
    rs.Spec.Replicas = &replicas

    // Apply changes
    _, err = clientset.AppsV1().ReplicaSets(ns).Update(context.TODO(), rs, metav1.UpdateOptions{})
    if err != nil {
        return err
    }

    fmt.Printf("Scaled ReplicaSet %s to %d replicas\n", name, replicas)
    return nil
}