diff --git a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/deployment/installation.rb b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/deployment/installation.rb
index b59ceafd65b907eb72ae783944c4f7f7dbe3d654..2adaf9d671a3269d8accb8e5101544d647f53142 100644
--- a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/deployment/installation.rb
+++ b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/deployment/installation.rb
@@ -161,7 +161,7 @@ def env_values
         # @return [String] chart reference
         def run_pre_deploy_setup
           Helpers::Spinner.spin("running pre-deployment setup") do
-            chart_reference = helm.add_helm_chart(chart_sha)
+            chart_reference = helm.add_gitlab_helm_chart(chart_sha)
             create_namespace
             create_license
 
diff --git a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/helm/client.rb b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/helm/client.rb
index e740f6921f87b07980858f87f849a45400b82d72..89d1e167f4e47b34c7e0901f9d03d86098379e86 100644
--- a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/helm/client.rb
+++ b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/helm/client.rb
@@ -9,33 +9,41 @@ class Client
         include Helpers::Shell
         include Helpers::Output
 
-        HELM_CHART_PREFIX = "gitlab"
-        HELM_CHART = "https://charts.gitlab.io"
-        HELM_CHART_REPO = "https://gitlab.com/gitlab-org/charts/gitlab"
+        GITLAB_CHART_PREFIX = "gitlab"
+        GITLAB_CHART_URL = "https://charts.gitlab.io"
+        GITLAB_CHART_PROJECT_URL = "https://gitlab.com/gitlab-org/charts/gitlab"
 
         # Error raised by helm client class
         Error = Class.new(StandardError)
 
-        # Add helm chart and return reference
+        # Add helm chart repository
         #
-        # @param [String] sha fetch and package helm chart using specific repo sha
-        # @return [String] chart reference or path to packaged chart tgz
-        def add_helm_chart(sha = nil)
-          return package_chart(sha) if sha
-
-          log("Adding gitlab helm chart '#{HELM_CHART}'", :info)
-          puts run_helm(%W[repo add #{HELM_CHART_PREFIX} #{HELM_CHART}])
-          "#{HELM_CHART_PREFIX}/gitlab"
+        # @param [String] name
+        # @param [String] url
+        # @return [void]
+        def add_helm_chart(name, url)
+          log("Adding helm chart '#{url}'", :info)
+          puts run_helm(%W[repo add #{name} #{url}])
         rescue Error => e
           if e.message.include?("already exists")
             log("helm chart repo already exists, updating", :warn)
-            puts(run_helm(%w[repo update gitlab]))
-            return "#{HELM_CHART_PREFIX}/gitlab"
+            return puts(run_helm(%W[repo update #{name}]))
           end
 
           raise(Error, e.message)
         end
 
+        # Add helm chart and return reference
+        #
+        # @param [String] sha fetch and package helm chart using specific repo sha
+        # @return [String] chart reference or path to packaged chart tgz
+        def add_gitlab_helm_chart(sha = nil)
+          return package_chart(sha) if sha
+
+          add_helm_chart(GITLAB_CHART_PREFIX, GITLAB_CHART_URL)
+          "#{GITLAB_CHART_PREFIX}/gitlab"
+        end
+
         # Run helm upgrade command with --install argument
         #
         # @param [String] name deployment name
@@ -108,7 +116,7 @@ def package_chart(sha)
         # @param [String] sha
         # @return [String] path to extracted repo
         def fetch_chart_repo(sha)
-          uri = URI("#{HELM_CHART_REPO}/-/archive/#{sha}/gitlab-#{sha}.tar")
+          uri = URI("#{GITLAB_CHART_PROJECT_URL}/-/archive/#{sha}/gitlab-#{sha}.tar")
           res = Net::HTTP.get_response(uri)
           raise "Failed to download chart, got response code: #{res.code}" unless res.code == "200"
 
diff --git a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/kind/cluster.rb b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/kind/cluster.rb
index eb6fe6257b553a9490f13160696b23928ccc4f45..ea8062f8d9cfd2b9a7691ee1e35a790f00d2d2f4 100644
--- a/qa/gems/gitlab-cng/lib/gitlab/cng/lib/kind/cluster.rb
+++ b/qa/gems/gitlab-cng/lib/gitlab/cng/lib/kind/cluster.rb
@@ -17,6 +17,10 @@ class Cluster
         HTTP_PORT = 32080
         SSH_PORT = 32022
 
+        METRICS_CHART_NAME = "metrics-server"
+        METRICS_CHART_URL = "https://kubernetes-sigs.github.io/metrics-server/"
+        METRICS_CHART_VERSION = "^3.12"
+
         # Destroy kind cluster
         #
         # @param [String] name
@@ -44,6 +48,7 @@ def create
 
           create_cluster
           update_server_url
+          install_metrics_server
           log("Cluster '#{name}' created", :success)
         rescue Helpers::Shell::CommandFailure
           # Exit cleanly without stacktrace if shell command fails
@@ -54,6 +59,13 @@ def create
 
         attr_reader :ci, :name, :docker_hostname, :host_http_port, :host_ssh_port
 
+        # Helm client instance
+        #
+        # @return [Helm::Client]
+        def helm_client
+          @helm_client ||= Helm::Client.new
+        end
+
         # Create kind cluster
         #
         # @return [void]
@@ -70,6 +82,26 @@ def create_cluster
           end
         end
 
+        # Install metrics-server on cluster
+        #
+        # Avoids "FailedGetResourceMetric" cluster errors and adds support for resource monitoring
+        #
+        # @return [void]
+        def install_metrics_server
+          Helpers::Spinner.spin("installing metrics server", raise_on_error: false) do
+            helm_client.add_helm_chart(METRICS_CHART_NAME, METRICS_CHART_URL)
+            helm_client.upgrade(
+              METRICS_CHART_NAME,
+              "#{METRICS_CHART_NAME}/#{METRICS_CHART_NAME}",
+              namespace: "kube-system",
+              timeout: "1m",
+              values: { "args" => ["--kubelet-insecure-tls"] }.to_yaml,
+              # use atomic to avoid leaving broken state if install fails
+              args: ["--atomic", "--version", METRICS_CHART_VERSION]
+            )
+          end
+        end
+
         # Update server url in kubeconfig for kubectl to work correctly with remote docker
         #
         # @return [void]
diff --git a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/deployment/installation_spec.rb b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/deployment/installation_spec.rb
index d56c0eb5164bbc07a827ef38f1b52a56e34de2cb..85cdde63c20dc169383f5c27c9734823deb400e4 100644
--- a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/deployment/installation_spec.rb
+++ b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/deployment/installation_spec.rb
@@ -28,7 +28,7 @@
     end
 
     let(:helmclient) do
-      instance_double(Gitlab::Cng::Helm::Client, add_helm_chart: chart_reference, upgrade: nil)
+      instance_double(Gitlab::Cng::Helm::Client, add_gitlab_helm_chart: chart_reference, upgrade: nil)
     end
 
     let(:configuration) do
@@ -126,7 +126,7 @@
       it "runs setup and helm deployment" do
         expect { installation.create }.to output(/Creating CNG deployment 'gitlab'/).to_stdout
 
-        expect(helmclient).to have_received(:add_helm_chart).with(nil)
+        expect(helmclient).to have_received(:add_gitlab_helm_chart).with(nil)
         expect(helmclient).to have_received(:upgrade).with(
           "gitlab",
           chart_reference,
@@ -157,7 +157,7 @@
       it "runs helm install with correctly merged values and component versions" do
         expect { installation.create }.to output(/Creating CNG deployment 'gitlab'/).to_stdout
 
-        expect(helmclient).to have_received(:add_helm_chart).with(chart_sha)
+        expect(helmclient).to have_received(:add_gitlab_helm_chart).with(chart_sha)
         expect(helmclient).to have_received(:upgrade).with(
           "gitlab",
           chart_reference,
diff --git a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/helm/client_spec.rb b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/helm/client_spec.rb
index 958dfe08b8465f6f342558a4bd9601d23135806f..9745c6119647371661e7c6e2f38b9fa02613af80 100644
--- a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/helm/client_spec.rb
+++ b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/helm/client_spec.rb
@@ -7,7 +7,7 @@
     allow(client).to receive(:execute_shell)
   end
 
-  describe "#add_helm_chart" do
+  describe "#add_gitlab_helm_chart" do
     let(:tmpdir) { Dir.mktmpdir("cng") }
 
     before do
@@ -17,8 +17,8 @@
     context "with default chart" do
       it "adds default chart repo" do
         expect do
-          expect(client.add_helm_chart).to eq("gitlab/gitlab")
-        end.to output(%r{Adding gitlab helm chart 'https://charts.gitlab.io'}).to_stdout
+          expect(client.add_gitlab_helm_chart).to eq("gitlab/gitlab")
+        end.to output(%r{Adding helm chart 'https://charts.gitlab.io'}).to_stdout
 
         expect(client).to have_received(:execute_shell).with(
           %w[helm repo add gitlab https://charts.gitlab.io],
@@ -34,7 +34,7 @@
           ))
 
         expect do
-          expect(client.add_helm_chart).to eq("gitlab/gitlab")
+          expect(client.add_gitlab_helm_chart).to eq("gitlab/gitlab")
         end.to output(/helm chart repo already exists, updating/).to_stdout
       end
 
@@ -43,7 +43,7 @@
           .with(%w[helm repo add gitlab https://charts.gitlab.io], stdin_data: nil)
           .and_raise(Gitlab::Cng::Helpers::Shell::CommandFailure.new("something went wrong"))
 
-        expect { expect { client.add_helm_chart }.to raise_error("something went wrong") }.to output.to_stdout
+        expect { expect { client.add_gitlab_helm_chart }.to raise_error("something went wrong") }.to output.to_stdout
       end
     end
 
@@ -62,7 +62,7 @@
 
       it "packages chart from specific sha" do
         expect do
-          expect(client.add_helm_chart(sha)).to eq(File.join(chart_dir, "gitlab-#{sha}.tgz"))
+          expect(client.add_gitlab_helm_chart(sha)).to eq(File.join(chart_dir, "gitlab-#{sha}.tgz"))
         end.to output(/Packaging chart for git sha '#{sha}'/).to_stdout
 
         expect(client).to have_received(:execute_shell).with(
diff --git a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/kind/cluster_spec.rb b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/kind/cluster_spec.rb
index d31342f55a20ff98c8e8318bbdc095f9af6b73a1..d365febd9138b19a35d3bcc0869888f8fb986d3f 100644
--- a/qa/gems/gitlab-cng/spec/unit/gitlab/cng/kind/cluster_spec.rb
+++ b/qa/gems/gitlab-cng/spec/unit/gitlab/cng/kind/cluster_spec.rb
@@ -18,10 +18,12 @@
     let(:tmp_config_path) { File.join("/tmp", "kind-config.yml") }
     let(:command_status) { instance_double(Process::Status, success?: true) }
     let(:clusters) { "kind" }
+    let(:helm) { instance_double(Gitlab::Cng::Helm::Client, add_helm_chart: nil, upgrade: nil) }
 
     before do
       allow(Gitlab::Cng::Helpers::Utils).to receive(:tmp_dir).and_return("/tmp")
       allow(Gitlab::Cng::Helpers::Spinner).to receive(:spin).and_yield
+      allow(Gitlab::Cng::Helm::Client).to receive(:new).and_return(helm)
       allow(File).to receive(:write).with(tmp_config_path, kind_config_content)
 
       allow(Open3).to receive(:popen2e).with({}, *%w[
@@ -80,8 +82,20 @@
           ]).and_return(["", command_status])
         end
 
-        it "creates cluster with ci specific configuration" do
+        it "creates cluster with ci specific configuration", :aggregate_failures do
           expect { cluster.create }.to output(/Cluster '#{name}' created/).to_stdout
+          expect(helm).to have_received(:add_helm_chart).with(
+            "metrics-server",
+            "https://kubernetes-sigs.github.io/metrics-server/"
+          )
+          expect(helm).to have_received(:upgrade).with(
+            "metrics-server",
+            "metrics-server/metrics-server",
+            namespace: "kube-system",
+            timeout: "1m",
+            values: { "args" => ["--kubelet-insecure-tls"] }.to_yaml,
+            args: ["--atomic", "--version", "^3.12"]
+          )
         end
       end
     end