diff --git a/app/assets/javascripts/environments/helpers/k8s_integration_helper.js b/app/assets/javascripts/environments/helpers/k8s_integration_helper.js
index 04a42bed41612f158035b48fdef6c93724c528bc..5813ce488ffbbfe352034888616a10ffcd48db4c 100644
--- a/app/assets/javascripts/environments/helpers/k8s_integration_helper.js
+++ b/app/assets/javascripts/environments/helpers/k8s_integration_helper.js
@@ -80,10 +80,10 @@ export function getStatefulSetStatuses(items) {
 
 export function getReplicaSetStatuses(items) {
   const failed = items.filter((item) => {
-    return item.status?.readyReplicas < item.spec?.replicas;
+    return calculateStatefulSetStatus(item) === STATUS_FAILED;
   });
   const ready = items.filter((item) => {
-    return item.status?.readyReplicas === item.spec?.replicas;
+    return calculateStatefulSetStatus(item) === STATUS_READY;
   });
 
   return {
diff --git a/app/assets/javascripts/kubernetes_dashboard/graphql/client.js b/app/assets/javascripts/kubernetes_dashboard/graphql/client.js
index a3ad75eacf527a5cf59c4b4cdcbf8c4004240b99..e4f0c7ee344e8944997414a2c12eadaca3f1d447 100644
--- a/app/assets/javascripts/kubernetes_dashboard/graphql/client.js
+++ b/app/assets/javascripts/kubernetes_dashboard/graphql/client.js
@@ -4,6 +4,7 @@ import typeDefs from '~/environments/graphql/typedefs.graphql';
 import k8sPodsQuery from './queries/k8s_dashboard_pods.query.graphql';
 import k8sDeploymentsQuery from './queries/k8s_dashboard_deployments.query.graphql';
 import k8sStatefulSetsQuery from './queries/k8s_dashboard_stateful_sets.query.graphql';
+import k8sReplicaSetsQuery from './queries/k8s_dashboard_replica_sets.query.graphql';
 import { resolvers } from './resolvers';
 
 export const apolloProvider = () => {
@@ -63,6 +64,25 @@ export const apolloProvider = () => {
     },
   });
 
+  cache.writeQuery({
+    query: k8sReplicaSetsQuery,
+    data: {
+      metadata: {
+        name: null,
+        namespace: null,
+        creationTimestamp: null,
+        labels: null,
+        annotations: null,
+      },
+      status: {
+        readyReplicas: null,
+      },
+      spec: {
+        replicas: null,
+      },
+    },
+  });
+
   return new VueApollo({
     defaultClient,
   });
diff --git a/app/assets/javascripts/kubernetes_dashboard/graphql/queries/k8s_dashboard_replica_sets.query.graphql b/app/assets/javascripts/kubernetes_dashboard/graphql/queries/k8s_dashboard_replica_sets.query.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..38aaa79853c5844afa757e40f5e998ef31182381
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/graphql/queries/k8s_dashboard_replica_sets.query.graphql
@@ -0,0 +1,17 @@
+query getK8sDashboardReplicaSets($configuration: LocalConfiguration) {
+  k8sReplicaSets(configuration: $configuration) @client {
+    metadata {
+      name
+      namespace
+      creationTimestamp
+      labels
+      annotations
+    }
+    status {
+      readyReplicas
+    }
+    spec {
+      replicas
+    }
+  }
+}
diff --git a/app/assets/javascripts/kubernetes_dashboard/graphql/resolvers/kubernetes.js b/app/assets/javascripts/kubernetes_dashboard/graphql/resolvers/kubernetes.js
index e61545c9b45a17aed7d8f2bfc566eeebce40b93b..818295dab07f2fcb3de38e73cacae9e1f5842370 100644
--- a/app/assets/javascripts/kubernetes_dashboard/graphql/resolvers/kubernetes.js
+++ b/app/assets/javascripts/kubernetes_dashboard/graphql/resolvers/kubernetes.js
@@ -11,6 +11,7 @@ import {
 import k8sDashboardPodsQuery from '../queries/k8s_dashboard_pods.query.graphql';
 import k8sDashboardDeploymentsQuery from '../queries/k8s_dashboard_deployments.query.graphql';
 import k8sDashboardStatefulSetsQuery from '../queries/k8s_dashboard_stateful_sets.query.graphql';
+import k8sDashboardReplicaSetsQuery from '../queries/k8s_dashboard_replica_sets.query.graphql';
 
 export default {
   k8sPods(_, { configuration }, { client }) {
@@ -91,4 +92,41 @@ export default {
         }
       });
   },
+
+  k8sReplicaSets(_, { configuration, namespace = '' }, { client }) {
+    const config = new Configuration(configuration);
+
+    const appsV1api = new AppsV1Api(config);
+    const deploymentsApi = namespace
+      ? appsV1api.listAppsV1NamespacedReplicaSet({ namespace })
+      : appsV1api.listAppsV1ReplicaSetForAllNamespaces();
+    return deploymentsApi
+      .then((res) => {
+        const watchPath = buildWatchPath({
+          resource: 'replicasets',
+          api: 'apis/apps/v1',
+          namespace,
+        });
+        watchWorkloadItems({
+          client,
+          query: k8sDashboardReplicaSetsQuery,
+          configuration,
+          namespace,
+          watchPath,
+          queryField: 'k8sReplicaSets',
+          mapFn: mapSetItem,
+        });
+
+        const data = res?.items || [];
+
+        return data.map(mapSetItem);
+      })
+      .catch(async (err) => {
+        try {
+          await handleClusterError(err);
+        } catch (error) {
+          throw new Error(error.message);
+        }
+      });
+  },
 };
diff --git a/app/assets/javascripts/kubernetes_dashboard/pages/replica_sets_page.vue b/app/assets/javascripts/kubernetes_dashboard/pages/replica_sets_page.vue
new file mode 100644
index 0000000000000000000000000000000000000000..212cc0dbaf73ef0eb7633c4e51ef5d68f92f37ed
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/pages/replica_sets_page.vue
@@ -0,0 +1,80 @@
+<script>
+import { s__ } from '~/locale';
+import { getAge, calculateStatefulSetStatus } from '../helpers/k8s_integration_helper';
+import WorkloadLayout from '../components/workload_layout.vue';
+import k8sReplicaSetsQuery from '../graphql/queries/k8s_dashboard_replica_sets.query.graphql';
+import { STATUS_FAILED, STATUS_READY, STATUS_LABELS } from '../constants';
+
+export default {
+  components: {
+    WorkloadLayout,
+  },
+  inject: ['configuration'],
+  apollo: {
+    k8sReplicaSets: {
+      query: k8sReplicaSetsQuery,
+      variables() {
+        return {
+          configuration: this.configuration,
+        };
+      },
+      update(data) {
+        return (
+          data?.k8sReplicaSets?.map((replicaSet) => {
+            return {
+              name: replicaSet.metadata?.name,
+              namespace: replicaSet.metadata?.namespace,
+              status: calculateStatefulSetStatus(replicaSet),
+              age: getAge(replicaSet.metadata?.creationTimestamp),
+              labels: replicaSet.metadata?.labels,
+              annotations: replicaSet.metadata?.annotations,
+              kind: s__('KubernetesDashboard|ReplicaSet'),
+            };
+          }) || []
+        );
+      },
+      error(err) {
+        this.errorMessage = err?.message;
+      },
+    },
+  },
+  data() {
+    return {
+      k8sReplicaSets: [],
+      errorMessage: '',
+    };
+  },
+  computed: {
+    replicaSetsStats() {
+      return [
+        {
+          value: this.countReplicaSetsByStatus(STATUS_READY),
+          title: STATUS_LABELS[STATUS_READY],
+        },
+        {
+          value: this.countReplicaSetsByStatus(STATUS_FAILED),
+          title: STATUS_LABELS[STATUS_FAILED],
+        },
+      ];
+    },
+    loading() {
+      return this.$apollo.queries.k8sReplicaSets.loading;
+    },
+  },
+  methods: {
+    countReplicaSetsByStatus(phase) {
+      const filteredReplicaSets = this.k8sReplicaSets.filter((item) => item.status === phase) || [];
+
+      return filteredReplicaSets.length;
+    },
+  },
+};
+</script>
+<template>
+  <workload-layout
+    :loading="loading"
+    :error-message="errorMessage"
+    :stats="replicaSetsStats"
+    :items="k8sReplicaSets"
+  />
+</template>
diff --git a/app/assets/javascripts/kubernetes_dashboard/router/constants.js b/app/assets/javascripts/kubernetes_dashboard/router/constants.js
index 34bb4e8f42f5de8157283bf70d52c41963b497a7..daa2bd6075be867b35f5e05b7abc29a256ad9bc9 100644
--- a/app/assets/javascripts/kubernetes_dashboard/router/constants.js
+++ b/app/assets/javascripts/kubernetes_dashboard/router/constants.js
@@ -1,7 +1,9 @@
 export const PODS_ROUTE_NAME = 'pods';
 export const DEPLOYMENTS_ROUTE_NAME = 'deployments';
 export const STATEFUL_SETS_ROUTE_NAME = 'statefulSets';
+export const REPLICA_SETS_ROUTE_NAME = 'replicaSets';
 
 export const PODS_ROUTE_PATH = '/pods';
 export const DEPLOYMENTS_ROUTE_PATH = '/deployments';
 export const STATEFUL_SETS_ROUTE_PATH = '/statefulsets';
+export const REPLICA_SETS_ROUTE_PATH = '/replicasets';
diff --git a/app/assets/javascripts/kubernetes_dashboard/router/routes.js b/app/assets/javascripts/kubernetes_dashboard/router/routes.js
index 96e7a35bfe2afe0a53ebab844b4830e498b0decb..ee5afcef14f0679a08c189bd2df13cacb3123550 100644
--- a/app/assets/javascripts/kubernetes_dashboard/router/routes.js
+++ b/app/assets/javascripts/kubernetes_dashboard/router/routes.js
@@ -2,6 +2,7 @@ import { s__ } from '~/locale';
 import PodsPage from '../pages/pods_page.vue';
 import DeploymentsPage from '../pages/deployments_page.vue';
 import StatefulSetsPage from '../pages/stateful_sets_page.vue';
+import ReplicaSetsPage from '../pages/replica_sets_page.vue';
 import {
   PODS_ROUTE_NAME,
   PODS_ROUTE_PATH,
@@ -9,6 +10,8 @@ import {
   DEPLOYMENTS_ROUTE_PATH,
   STATEFUL_SETS_ROUTE_NAME,
   STATEFUL_SETS_ROUTE_PATH,
+  REPLICA_SETS_ROUTE_NAME,
+  REPLICA_SETS_ROUTE_PATH,
 } from './constants';
 
 export default [
@@ -36,4 +39,12 @@ export default [
       title: s__('KubernetesDashboard|StatefulSets'),
     },
   },
+  {
+    name: REPLICA_SETS_ROUTE_NAME,
+    path: REPLICA_SETS_ROUTE_PATH,
+    component: ReplicaSetsPage,
+    meta: {
+      title: s__('KubernetesDashboard|ReplicaSets'),
+    },
+  },
 ];
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d4a4fd6fd7a60764631d1c659af46d2429841d9a..fdc2ce3cbd0746c1d680ec0da1ffa43b75e4b002 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -27899,6 +27899,12 @@ msgstr ""
 msgid "KubernetesDashboard|Ready"
 msgstr ""
 
+msgid "KubernetesDashboard|ReplicaSet"
+msgstr ""
+
+msgid "KubernetesDashboard|ReplicaSets"
+msgstr ""
+
 msgid "KubernetesDashboard|Running"
 msgstr ""
 
diff --git a/spec/frontend/kubernetes_dashboard/graphql/mock_data.js b/spec/frontend/kubernetes_dashboard/graphql/mock_data.js
index 030e801c06dec8c9fc778bea348a8ef44e98c563..fe26bf5c60083aecab72a928cf1c1cfc13adeeed 100644
--- a/spec/frontend/kubernetes_dashboard/graphql/mock_data.js
+++ b/spec/frontend/kubernetes_dashboard/graphql/mock_data.js
@@ -289,3 +289,9 @@ export const mockStatefulSetsTableItems = [
     kind: 'StatefulSet',
   },
 ];
+
+export const k8sReplicaSetsMock = [readyStatefulSet, readyStatefulSet, failedStatefulSet];
+
+export const mockReplicaSetsTableItems = mockStatefulSetsTableItems.map((item) => {
+  return { ...item, kind: 'ReplicaSet' };
+});
diff --git a/spec/frontend/kubernetes_dashboard/graphql/resolvers/kubernetes_spec.js b/spec/frontend/kubernetes_dashboard/graphql/resolvers/kubernetes_spec.js
index 5841c73ea7163b7d32efa3caa6470c756491e51c..feee63546dd9e76460398d9e93b1ce7a0be56150 100644
--- a/spec/frontend/kubernetes_dashboard/graphql/resolvers/kubernetes_spec.js
+++ b/spec/frontend/kubernetes_dashboard/graphql/resolvers/kubernetes_spec.js
@@ -3,7 +3,13 @@ import { resolvers } from '~/kubernetes_dashboard/graphql/resolvers';
 import k8sDashboardPodsQuery from '~/kubernetes_dashboard/graphql/queries/k8s_dashboard_pods.query.graphql';
 import k8sDashboardDeploymentsQuery from '~/kubernetes_dashboard/graphql/queries/k8s_dashboard_deployments.query.graphql';
 import k8sDashboardStatefulSetsQuery from '~/kubernetes_dashboard/graphql/queries/k8s_dashboard_stateful_sets.query.graphql';
-import { k8sPodsMock, k8sDeploymentsMock, k8sStatefulSetsMock } from '../mock_data';
+import k8sDashboardReplicaSetsQuery from '~/kubernetes_dashboard/graphql/queries/k8s_dashboard_replica_sets.query.graphql';
+import {
+  k8sPodsMock,
+  k8sDeploymentsMock,
+  k8sStatefulSetsMock,
+  k8sReplicaSetsMock,
+} from '../mock_data';
 
 describe('~/frontend/environments/graphql/resolvers', () => {
   let mockResolvers;
@@ -276,4 +282,92 @@ describe('~/frontend/environments/graphql/resolvers', () => {
       ).rejects.toThrow('API error');
     });
   });
+
+  describe('k8sReplicaSets', () => {
+    const client = { writeQuery: jest.fn() };
+
+    const mockWatcher = WatchApi.prototype;
+    const mockReplicaSetsListWatcherFn = jest.fn().mockImplementation(() => {
+      return Promise.resolve(mockWatcher);
+    });
+
+    const mockOnDataFn = jest.fn().mockImplementation((eventName, callback) => {
+      if (eventName === 'data') {
+        callback([]);
+      }
+    });
+
+    const mockReplicaSetsListFn = jest.fn().mockImplementation(() => {
+      return Promise.resolve({
+        items: k8sReplicaSetsMock,
+      });
+    });
+
+    const mockAllReplicaSetsListFn = jest.fn().mockImplementation(mockReplicaSetsListFn);
+
+    describe('when the ReplicaSets data is present', () => {
+      beforeEach(() => {
+        jest
+          .spyOn(AppsV1Api.prototype, 'listAppsV1ReplicaSetForAllNamespaces')
+          .mockImplementation(mockAllReplicaSetsListFn);
+        jest
+          .spyOn(mockWatcher, 'subscribeToStream')
+          .mockImplementation(mockReplicaSetsListWatcherFn);
+        jest.spyOn(mockWatcher, 'on').mockImplementation(mockOnDataFn);
+      });
+
+      it('should request all ReplicaSets from the cluster_client library and watch the events', async () => {
+        const ReplicaSets = await mockResolvers.Query.k8sReplicaSets(
+          null,
+          {
+            configuration,
+          },
+          { client },
+        );
+
+        expect(mockAllReplicaSetsListFn).toHaveBeenCalled();
+        expect(mockReplicaSetsListWatcherFn).toHaveBeenCalled();
+
+        expect(ReplicaSets).toEqual(k8sReplicaSetsMock);
+      });
+
+      it('should update cache with the new data when received from the library', async () => {
+        await mockResolvers.Query.k8sReplicaSets(
+          null,
+          { configuration, namespace: '' },
+          { client },
+        );
+
+        expect(client.writeQuery).toHaveBeenCalledWith({
+          query: k8sDashboardReplicaSetsQuery,
+          variables: { configuration, namespace: '' },
+          data: { k8sReplicaSets: [] },
+        });
+      });
+    });
+
+    it('should not watch ReplicaSets from the cluster_client library when the ReplicaSets data is not present', async () => {
+      jest.spyOn(AppsV1Api.prototype, 'listAppsV1ReplicaSetForAllNamespaces').mockImplementation(
+        jest.fn().mockImplementation(() => {
+          return Promise.resolve({
+            items: [],
+          });
+        }),
+      );
+
+      await mockResolvers.Query.k8sReplicaSets(null, { configuration }, { client });
+
+      expect(mockReplicaSetsListWatcherFn).not.toHaveBeenCalled();
+    });
+
+    it('should throw an error if the API call fails', async () => {
+      jest
+        .spyOn(AppsV1Api.prototype, 'listAppsV1ReplicaSetForAllNamespaces')
+        .mockRejectedValue(new Error('API error'));
+
+      await expect(
+        mockResolvers.Query.k8sReplicaSets(null, { configuration }, { client }),
+      ).rejects.toThrow('API error');
+    });
+  });
 });
diff --git a/spec/frontend/kubernetes_dashboard/pages/replica_sets_page_spec.js b/spec/frontend/kubernetes_dashboard/pages/replica_sets_page_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..0e442ec8328afedf21e9f6e121643933c05ec548
--- /dev/null
+++ b/spec/frontend/kubernetes_dashboard/pages/replica_sets_page_spec.js
@@ -0,0 +1,106 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import ReplicaSetsPage from '~/kubernetes_dashboard/pages/replica_sets_page.vue';
+import WorkloadLayout from '~/kubernetes_dashboard/components/workload_layout.vue';
+import { useFakeDate } from 'helpers/fake_date';
+import {
+  k8sReplicaSetsMock,
+  mockStatefulSetsStats,
+  mockReplicaSetsTableItems,
+} from '../graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('Kubernetes dashboard replicaSets page', () => {
+  let wrapper;
+
+  const configuration = {
+    basePath: 'kas/tunnel/url',
+    baseOptions: {
+      headers: { 'GitLab-Agent-Id': '1' },
+    },
+  };
+
+  const findWorkloadLayout = () => wrapper.findComponent(WorkloadLayout);
+
+  const createApolloProvider = () => {
+    const mockResolvers = {
+      Query: {
+        k8sReplicaSets: jest.fn().mockReturnValue(k8sReplicaSetsMock),
+      },
+    };
+
+    return createMockApollo([], mockResolvers);
+  };
+
+  const createWrapper = (apolloProvider = createApolloProvider()) => {
+    wrapper = shallowMount(ReplicaSetsPage, {
+      provide: { configuration },
+      apolloProvider,
+    });
+  };
+
+  describe('mounted', () => {
+    it('renders WorkloadLayout component', () => {
+      createWrapper();
+
+      expect(findWorkloadLayout().exists()).toBe(true);
+    });
+
+    it('sets loading prop for the WorkloadLayout', () => {
+      createWrapper();
+
+      expect(findWorkloadLayout().props('loading')).toBe(true);
+    });
+
+    it('removes loading prop from the WorkloadLayout when the list of pods loaded', async () => {
+      createWrapper();
+      await waitForPromises();
+
+      expect(findWorkloadLayout().props('loading')).toBe(false);
+    });
+  });
+
+  describe('when gets pods data', () => {
+    useFakeDate(2023, 10, 23, 10, 10);
+
+    it('sets correct stats object for the WorkloadLayout', async () => {
+      createWrapper();
+      await waitForPromises();
+
+      expect(findWorkloadLayout().props('stats')).toEqual(mockStatefulSetsStats);
+    });
+
+    it('sets correct table items object for the WorkloadLayout', async () => {
+      createWrapper();
+      await waitForPromises();
+
+      expect(findWorkloadLayout().props('items')).toMatchObject(mockReplicaSetsTableItems);
+    });
+  });
+
+  describe('when gets an error from the cluster_client API', () => {
+    const error = new Error('Error from the cluster_client API');
+    const createErroredApolloProvider = () => {
+      const mockResolvers = {
+        Query: {
+          k8sReplicaSets: jest.fn().mockRejectedValueOnce(error),
+        },
+      };
+
+      return createMockApollo([], mockResolvers);
+    };
+
+    beforeEach(async () => {
+      createWrapper(createErroredApolloProvider());
+      await waitForPromises();
+    });
+
+    it('sets errorMessage prop for the WorkloadLayout', () => {
+      expect(findWorkloadLayout().props('errorMessage')).toBe(error.message);
+    });
+  });
+});