Learning Kubernetes - Episode 12 - Introduction and Explanation of ReplicaSet

Learning Kubernetes - Episode 12 - Introduction and Explanation of ReplicaSet

In this episode, we'll discuss the modern replacement for ReplicationController called ReplicaSet. We'll learn about set-based selectors, matchLabels, matchExpressions, and how ReplicaSet is used by Deployments.

Arman Dwi Pangestu
Arman Dwi PangestuMarch 15, 2026
0 views
7 min read

Introduction

Note

If you want to read the previous episode, you can click the Episode 11 thumbnail below

Episode 11Episode 11

In the previous episode, we learned about ReplicationController, the legacy controller for managing Pod replicas. In episode 12, we'll discuss the modern replacement: ReplicaSet.

Note: Here I'll be using a Kubernetes Cluster installed through K3s.

ReplicaSet is the next-generation ReplicationController with more flexible selector support. While you can use ReplicaSet directly, it's typically used as the underlying mechanism for Deployments, which provide additional features like rolling updates and rollback capabilities.

What Is ReplicaSet?

A ReplicaSet ensures that a specified number of Pod replicas are running at any given time. It's the successor to ReplicationController and provides the same core functionality with enhanced selector capabilities.

Key features of ReplicaSet:

  • Set-based selectors - More flexible label selection using matchLabels and matchExpressions
  • Maintains desired replica count - Ensures specified number of Pods are always running
  • Self-healing - Automatically replaces failed Pods
  • Scaling - Easily scale Pods up or down
  • Used by Deployments - The foundation for Deployment controllers

ReplicaSet vs ReplicationController

The main difference between ReplicaSet and ReplicationController is the selector support:

ReplicationController - Equality-based selectors only:

Kubernetesyml
selector:
    app: nginx
    tier: frontend

ReplicaSet - Set-based selectors with more flexibility:

Kubernetesyml
selector:
    matchLabels:
        app: nginx
    matchExpressions:
        - key: tier
          operator: In
          values:
              - frontend
              - backend

Why Use ReplicaSet?

ReplicaSet provides several advantages over ReplicationController:

  • More flexible selectors - Use set-based operations (In, NotIn, Exists, DoesNotExist)
  • Modern API - Uses apps/v1 API group
  • Better integration - Works seamlessly with Deployments
  • Future-proof - Actively maintained and recommended by Kubernetes
  • Backward compatible - Can do everything ReplicationController does, plus more

Important

Best Practice: While you can use ReplicaSet directly, it's recommended to use Deployment instead. Deployments manage ReplicaSets and provide additional features like rolling updates, rollback, and declarative updates.

ReplicaSet Components

A ReplicaSet consists of three main components:

1. Replica Count

The number of Pod replicas you want to run:

Kubernetesyml
spec:
    replicas: 3

2. Selector

Labels used to identify which Pods the ReplicaSet manages. ReplicaSet supports two types:

matchLabels - Equality-based matching:

Kubernetesyml
selector:
    matchLabels:
        app: nginx
        environment: production

matchExpressions - Set-based matching:

Kubernetesyml
selector:
    matchExpressions:
        - key: tier
          operator: In
          values:
              - frontend
              - backend

3. Pod Template

The template used to create new Pods:

Kubernetesyml
template:
    metadata:
        labels:
            app: nginx
    spec:
        containers:
            - name: nginx
              image: nginx:1.25

Creating a ReplicaSet

Let's create a basic ReplicaSet:

Example 1: Basic ReplicaSet with matchLabels

Create a file named replicaset-basic.yml:

Kubernetesreplicaset-basic.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: nginx-replicaset
    labels:
        app: nginx
        tier: frontend
spec:
    replicas: 3
    selector:
        matchLabels:
            app: nginx
            tier: frontend
    template:
        metadata:
            labels:
                app: nginx
                tier: frontend
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25
                  ports:
                      - containerPort: 80

Important

Important: The labels in the Pod template must match the selector. If they don't match, the ReplicaSet will fail to create.

Apply the configuration:

Kubernetesbash
sudo kubectl apply -f replicaset-basic.yml

Verify the ReplicaSet is created:

Kubernetesbash
sudo kubectl get replicaset

Or use the shorthand:

Kubernetesbash
sudo kubectl get rs

Output:

Kubernetesbash
NAME               DESIRED   CURRENT   READY   AGE
nginx-replicaset   3         3         3       30s

Check the Pods:

Kubernetesbash
sudo kubectl get pods

Output:

Kubernetesbash
NAME                     READY   STATUS    RESTARTS   AGE
nginx-replicaset-abc12   1/1     Running   0          30s
nginx-replicaset-def34   1/1     Running   0          30s
nginx-replicaset-ghi56   1/1     Running   0          30s

Set-Based Selectors

ReplicaSet's most powerful feature is set-based selectors using matchExpressions. Let's explore the operators:

Operator: In

Selects Pods where the label value is in the specified set:

Kubernetesreplicaset-in-operator.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: web-app-rs
spec:
    replicas: 3
    selector:
        matchExpressions:
            - key: environment
              operator: In
              values:
                  - production
                  - staging
    template:
        metadata:
            labels:
                app: web-app
                environment: production
        spec:
            containers:
                - name: web-app
                  image: nginx:1.25

This ReplicaSet manages Pods with environment: production OR environment: staging.

Operator: NotIn

Selects Pods where the label value is NOT in the specified set:

Kubernetesreplicaset-notin-operator.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: non-dev-rs
spec:
    replicas: 2
    selector:
        matchExpressions:
            - key: environment
              operator: NotIn
              values:
                  - development
    template:
        metadata:
            labels:
                app: myapp
                environment: production
        spec:
            containers:
                - name: myapp
                  image: nginx:1.25

This ReplicaSet manages Pods where environment is NOT development.

Operator: Exists

Selects Pods that have the specified label key (regardless of value):

Kubernetesreplicaset-exists-operator.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: labeled-rs
spec:
    replicas: 2
    selector:
        matchExpressions:
            - key: tier
              operator: Exists
    template:
        metadata:
            labels:
                app: myapp
                tier: frontend
        spec:
            containers:
                - name: myapp
                  image: nginx:1.25

This ReplicaSet manages Pods that have the tier label, regardless of its value.

Operator: DoesNotExist

Selects Pods that do NOT have the specified label key:

Kubernetesreplicaset-doesnotexist-operator.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: unlabeled-rs
spec:
    replicas: 2
    selector:
        matchExpressions:
            - key: deprecated
              operator: DoesNotExist
    template:
        metadata:
            labels:
                app: myapp
        spec:
            containers:
                - name: myapp
                  image: nginx:1.25

This ReplicaSet manages Pods that do NOT have the deprecated label.

Combining matchLabels and matchExpressions

You can combine both for more complex selection:

Kubernetesreplicaset-combined.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: complex-selector-rs
spec:
    replicas: 3
    selector:
        matchLabels:
            app: web-app
        matchExpressions:
            - key: environment
              operator: In
              values:
                  - production
                  - staging
            - key: tier
              operator: NotIn
              values:
                  - deprecated
    template:
        metadata:
            labels:
                app: web-app
                environment: production
                tier: frontend
        spec:
            containers:
                - name: web-app
                  image: nginx:1.25

This ReplicaSet selects Pods that:

  • Have app: web-app (matchLabels)
  • AND have environment as either production or staging
  • AND do NOT have tier: deprecated

Viewing ReplicaSet Details

To see detailed information about a ReplicaSet:

Kubernetesbash
sudo kubectl describe rs nginx-replicaset

Output:

Kubernetesbash
Name:         nginx-replicaset
Namespace:    default
Selector:     app=nginx,tier=frontend
Labels:       app=nginx
              tier=frontend
Annotations:  <none>
Replicas:     3 current / 3 desired
Pods Status:  3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
           tier=frontend
  Containers:
   nginx:
    Image:        nginx:1.25
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From                   Message
  ----    ------            ----  ----                   -------
  Normal  SuccessfulCreate  2m    replicaset-controller  Created pod: nginx-replicaset-abc12
  Normal  SuccessfulCreate  2m    replicaset-controller  Created pod: nginx-replicaset-def34
  Normal  SuccessfulCreate  2m    replicaset-controller  Created pod: nginx-replicaset-ghi56

Self-Healing Demonstration

ReplicaSet automatically replaces failed Pods, just like ReplicationController:

Step 1: Check Current Pods

Kubernetesbash
sudo kubectl get pods -l app=nginx

Step 2: Delete a Pod

Kubernetesbash
sudo kubectl delete pod nginx-replicaset-abc12

Step 3: Watch ReplicaSet Create a New Pod

Kubernetesbash
sudo kubectl get pods -l app=nginx -w

You'll see the ReplicaSet immediately creates a new Pod to maintain the desired count.

Scaling ReplicaSet

Scaling ReplicaSet works the same as ReplicationController:

Method 1: Using kubectl scale

Kubernetesbash
# Scale up to 5 replicas
sudo kubectl scale rs nginx-replicaset --replicas=5
 
# Scale down to 2 replicas
sudo kubectl scale rs nginx-replicaset --replicas=2

Method 2: Editing the ReplicaSet

Kubernetesbash
sudo kubectl edit rs nginx-replicaset

Change the replicas field and save.

Method 3: Updating the YAML File

Update your YAML file and apply:

Kubernetesbash
sudo kubectl apply -f replicaset-basic.yml

Practical Examples

Example 1: Web Application with Resource Limits

Kubernetesweb-app-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: web-app-rs
    labels:
        app: web-app
        tier: frontend
spec:
    replicas: 5
    selector:
        matchLabels:
            app: web-app
            tier: frontend
    template:
        metadata:
            labels:
                app: web-app
                tier: frontend
        spec:
            containers:
                - name: web-app
                  image: nginx:1.25
                  ports:
                      - containerPort: 80
                  resources:
                      requests:
                          memory: "128Mi"
                          cpu: "100m"
                      limits:
                          memory: "256Mi"
                          cpu: "200m"
                  livenessProbe:
                      httpGet:
                          path: /
                          port: 80
                      initialDelaySeconds: 3
                      periodSeconds: 10
                  readinessProbe:
                      httpGet:
                          path: /
                          port: 80
                      initialDelaySeconds: 5
                      periodSeconds: 5

Example 2: Multi-Environment ReplicaSet

Kubernetesmulti-env-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: multi-env-rs
spec:
    replicas: 4
    selector:
        matchLabels:
            app: myapp
        matchExpressions:
            - key: environment
              operator: In
              values:
                  - production
                  - staging
            - key: version
              operator: Exists
    template:
        metadata:
            labels:
                app: myapp
                environment: production
                version: v2.0
        spec:
            containers:
                - name: myapp
                  image: nginx:1.25
                  env:
                      - name: ENVIRONMENT
                        value: "production"
                      - name: VERSION
                        value: "v2.0"

Example 3: ReplicaSet with Node Affinity

Kubernetesreplicaset-affinity.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: affinity-rs
spec:
    replicas: 3
    selector:
        matchLabels:
            app: myapp
    template:
        metadata:
            labels:
                app: myapp
        spec:
            affinity:
                nodeAffinity:
                    requiredDuringSchedulingIgnoredDuringExecution:
                        nodeSelectorTerms:
                            - matchExpressions:
                                  - key: disktype
                                    operator: In
                                    values:
                                        - ssd
            containers:
                - name: myapp
                  image: nginx:1.25

This ReplicaSet schedules Pods only on nodes with disktype: ssd label.

ReplicaSet and Deployments

In practice, you rarely create ReplicaSets directly. Instead, you create Deployments, which manage ReplicaSets for you.

How Deployments Use ReplicaSets

When you create a Deployment:

  1. Deployment creates a ReplicaSet
  2. ReplicaSet creates Pods
  3. Deployment manages ReplicaSet lifecycle (updates, rollbacks)

Example Deployment:

Kubernetesdeployment-example.yml
apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    replicas: 3
    selector:
        matchLabels:
            app: nginx
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25

When you apply this Deployment:

Kubernetesbash
sudo kubectl apply -f deployment-example.yml

Check the ReplicaSet created by the Deployment:

Kubernetesbash
sudo kubectl get rs

Output:

Kubernetesbash
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5d59d67564   3         3         3       30s

The ReplicaSet name includes the Deployment name and a hash.

Why Use Deployment Instead of ReplicaSet?

Deployments provide additional features:

  • Rolling updates - Gradually update Pods with zero downtime
  • Rollback - Easily revert to previous versions
  • Revision history - Track deployment history
  • Declarative updates - Describe desired state, Kubernetes handles the rest
  • Pause and resume - Control update process

Tip

Recommendation: Always use Deployment for stateless applications instead of creating ReplicaSets directly. Use ReplicaSet only when you need fine-grained control or have specific requirements that Deployments don't support.

Deleting ReplicaSet

Method 1: Delete ReplicaSet and Pods

Kubernetesbash
sudo kubectl delete rs nginx-replicaset

This deletes the ReplicaSet and all its Pods.

Method 2: Delete ReplicaSet but Keep Pods

Kubernetesbash
sudo kubectl delete rs nginx-replicaset --cascade=orphan

This deletes only the ReplicaSet, leaving Pods running as orphans.

Common Mistakes and Pitfalls

Mistake 1: Mismatched Labels

Pod template labels must match the selector:

Wrong:

Kubernetesyml
selector:
    matchLabels:
        app: nginx
template:
    metadata:
        labels:
            app: web  # Doesn't match!

Correct:

Kubernetesyml
selector:
    matchLabels:
        app: nginx
template:
    metadata:
        labels:
            app: nginx  # Matches!

Mistake 2: Using ReplicaSet Instead of Deployment

Creating ReplicaSets directly when you should use Deployments.

Solution: Use Deployment for most use cases. It manages ReplicaSets and provides rolling updates.

Mistake 3: Complex Selectors Without Testing

Creating overly complex selectors that don't match any Pods.

Solution: Start simple, test your selectors, then add complexity if needed.

Mistake 4: Not Setting Resource Limits

Solution: Always set resource requests and limits:

Kubernetesyml
resources:
    requests:
        memory: "128Mi"
        cpu: "100m"
    limits:
        memory: "256Mi"
        cpu: "200m"

Best Practices

Use Deployments Instead of ReplicaSets

For most use cases, use Deployments:

Kubernetesyml
apiVersion: apps/v1
kind: Deployment  # Use Deployment, not ReplicaSet
metadata:
    name: nginx-deployment
spec:
    replicas: 3
    selector:
        matchLabels:
            app: nginx
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25

Use matchLabels for Simple Selectors

For simple equality-based selection, use matchLabels:

Kubernetesyml
selector:
    matchLabels:
        app: nginx
        tier: frontend

Use matchExpressions for Complex Logic

For complex selection logic, use matchExpressions:

Kubernetesyml
selector:
    matchExpressions:
        - key: environment
          operator: In
          values:
              - production
              - staging
        - key: deprecated
          operator: DoesNotExist

Add Meaningful Labels

Use descriptive labels for better organization:

Kubernetesyml
labels:
    app: web-app
    tier: frontend
    environment: production
    version: v2.0
    team: platform

Implement Health Checks

Always add Probes:

Kubernetesyml
livenessProbe:
    httpGet:
        path: /healthz
        port: 8080
readinessProbe:
    httpGet:
        path: /ready
        port: 8080

Set Resource Limits

Always define resource requests and limits:

Kubernetesyml
resources:
    requests:
        memory: "128Mi"
        cpu: "100m"
    limits:
        memory: "256Mi"
        cpu: "200m"

Monitoring ReplicaSet

Check ReplicaSet Status

Kubernetesbash
sudo kubectl get rs

Watch ReplicaSet Events

Kubernetesbash
sudo kubectl get events --sort-by='.lastTimestamp' | grep ReplicaSet

Monitor Pod Status

Kubernetesbash
sudo kubectl get pods -l app=nginx -w

Check Resource Usage

Kubernetesbash
sudo kubectl top pods -l app=nginx

Conclusion

In episode 12, we've explored ReplicaSet in Kubernetes in depth. We've learned what ReplicaSet is, how it improves upon ReplicationController, and how to use set-based selectors for flexible Pod management.

Key takeaways:

  • ReplicaSet is the modern replacement for ReplicationController
  • Supports set-based selectors with matchLabels and matchExpressions
  • Four operators: In, NotIn, Exists, DoesNotExist
  • Used as the foundation for Deployments
  • Provides same self-healing and scaling as ReplicationController
  • Best practice: Use Deployment instead of ReplicaSet directly
  • More flexible label selection than ReplicationController
  • Uses apps/v1 API group

While ReplicaSet is more powerful than ReplicationController, in practice you should use Deployment for managing stateless applications. Deployments provide all the benefits of ReplicaSets plus rolling updates, rollback capabilities, and declarative update management.

Are you getting a clearer understanding of ReplicaSet in Kubernetes? In the next episode 13, we'll discuss DaemonSet, a different type of controller that ensures a Pod runs on every node in your cluster. Keep your learning momentum going and look forward to the next episode!


Related Posts