diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
index 767dc8433d2e509148e84c869f08ea599fec60e4..3c7b47dbd5fabc882fb52f7b3b34114de0931c3a 100644
--- a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
+++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
@@ -20,7 +20,6 @@ variables:
   tags:
     - e2e
   variables:
-    DOCKER_DRIVER: overlay2
     DOCKER_HOST: tcp://docker:2375
     QA_GENERATE_ALLURE_REPORT: "true"
     QA_CAN_TEST_PRAEFECT: "false"
@@ -29,6 +28,7 @@ variables:
     RSPEC_REPORT_OPTS: "--order random --force-color --format documentation --format RspecJunitFormatter --out tmp/rspec-${CI_JOB_ID}.xml --format QA::Support::JsonFormatter --out tmp/rspec-${CI_JOB_ID}.json  --format html --out tmp/rspec-${CI_JOB_ID}.htm"
     FF_NETWORK_PER_BUILD: 1
     GDK_URL: http://gdk.test:3000
+    KNAPSACK_TEST_FILE_PATTERN: "qa/specs/features/**/*_spec.rb"
   before_script:
     - echo "SUITE_RAN=true" > suite_status.env
     - echo -e "\e[0Ksection_start:`date +%s`:pull_image\r\e[0KPull GDK QA image"
@@ -52,11 +52,11 @@ variables:
     - source scripts/utils.sh
     - cd qa && bundle install
   script:
-    - retry_exponential test_url ${GDK_URL}/users/sign_in
+    - retry_exponential test_url $GDK_URL/users/sign_in
     - echo -e "\e[0Ksection_end:`date +%s`:launch_gdk\r\e[0K"
     - echo -e "\e[0Ksection_start:`date +%s`:run_tests\r\e[0KRun E2E tests"
-    - QA_COMMAND="bundle exec bin/qa Test::Instance::All ${GDK_URL} -- ${RSPEC_TAGS} ${RSPEC_REPORT_OPTS}"
-    - echo "Running - '${QA_COMMAND}'"
+    - export QA_COMMAND="bundle exec bin/qa ${QA_SCENARIO:=Test::Instance::All} $GDK_URL $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"
+    - echo "Running - '$QA_COMMAND'"
     - eval "$QA_COMMAND"
     - echo -e "\e[0Ksection_end:`date +%s`:run_tests\r\e[0K"
   after_script:
@@ -76,6 +76,11 @@ variables:
     when: always
   allow_failure: true
 
+download-knapsack-report:
+  extends:
+    - .download-knapsack-report
+    - .rules:download-knapsack
+
 cache-gems:
   extends:
     - .ruby-image
@@ -105,9 +110,8 @@ gdk-qa-smoke:
   extends:
     - .gdk-qa-base
   variables:
-    TEST_GDK_TAGS: "--tag smoke"
+    QA_SCENARIO: Test::Instance::Smoke
     QA_RUN_TYPE: gdk-qa-smoke
-    RSPEC_TAGS: --tag smoke
   rules:
     - when: always
 
@@ -116,9 +120,8 @@ gdk-qa-smoke-with-load-balancer:
     - .gdk-qa-base
     - .gdk-with-load-balancer-setup
   variables:
-    TEST_GDK_TAGS: "--tag smoke"
+    QA_SCENARIO: Test::Instance::Smoke
     QA_RUN_TYPE: gdk-qa-smoke
-    RSPEC_TAGS: --tag smoke
   rules:
     - changes:
         - ".gitlab/ci/test-on-gdk/**"
@@ -128,11 +131,10 @@ gdk-qa-smoke-with-load-balancer:
 gdk-qa-reliable:
   extends:
     - .gdk-qa-base
-  parallel: 5
+    - .parallel
   variables:
+    QA_SCENARIO: Test::Instance::Blocking
     QA_RUN_TYPE: gdk-qa-blocking
-    QA_KNAPSACK_REPORT_NAME: ee-instance-parallel
-    RSPEC_TAGS: --tag smoke --tag reliable
   allow_failure: true
   rules:
     - when: manual
@@ -141,11 +143,10 @@ gdk-qa-reliable-with-load-balancer:
   extends:
     - .gdk-qa-base
     - .gdk-with-load-balancer-setup
-  parallel: 5
+    - .parallel
   variables:
+    QA_SCENARIO: Test::Instance::Blocking
     QA_RUN_TYPE: gdk-qa-blocking
-    QA_KNAPSACK_REPORT_NAME: ee-instance-parallel
-    RSPEC_TAGS: --tag smoke --tag reliable
   allow_failure: true
   rules:
     - changes:
@@ -155,11 +156,10 @@ gdk-qa-reliable-with-load-balancer:
 gdk-qa-non-blocking:
   extends:
     - .gdk-qa-base
-  parallel: 5
+    - .parallel
   variables:
+    QA_SCENARIO: Test::Instance::NonBlocking
     QA_RUN_TYPE: gdk-qa-non-blocking
-    QA_KNAPSACK_REPORT_NAME: ee-instance-parallel
-    QA_SKIP_SMOKE_RELIABLE: "true"
   allow_failure: true
   rules:
     - when: manual
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 54f9db65afb227a9089d50ff4a3964e0a5ef18fa..173027d784bbb0301e919b86f654d69d6889cafe 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -622,6 +622,10 @@ def one_p_github_uuid
         ENV['QA_1P_GITHUB_UUID']
       end
 
+      def gdk_url
+        ENV['GDK_URL']
+      end
+
       private
 
       def remote_grid_credentials
diff --git a/qa/qa/scenario/test/instance/airgapped.rb b/qa/qa/scenario/test/instance/airgapped.rb
index 556741ec040e49dfc945152cd2fe40afa2a5bfdf..1d4d57b342e9e42466014802ade268de3f698225 100644
--- a/qa/qa/scenario/test/instance/airgapped.rb
+++ b/qa/qa/scenario/test/instance/airgapped.rb
@@ -8,7 +8,7 @@ class Airgapped < Template
           include Bootable
           include SharedAttributes
           def perform(address, *rspec_options)
-            Runtime::Scenario.define(:runner_network, 'airgapped')
+            Runtime::Scenario.define(:network, 'airgapped')
 
             super
           end
diff --git a/qa/qa/scenario/test/instance/blocking.rb b/qa/qa/scenario/test/instance/blocking.rb
new file mode 100644
index 0000000000000000000000000000000000000000..26bd71e04e8a42b9df044cfa17ba3bc55ae735ee
--- /dev/null
+++ b/qa/qa/scenario/test/instance/blocking.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+  module Scenario
+    module Test
+      module Instance
+        class Blocking < All
+          tags :reliable,
+            *Specs::Runner::DEFAULT_SKIPPED_TAGS.map { |tag| :"~#{tag}" }
+        end
+      end
+    end
+  end
+end
diff --git a/qa/qa/scenario/test/instance/non_blocking.rb b/qa/qa/scenario/test/instance/non_blocking.rb
new file mode 100644
index 0000000000000000000000000000000000000000..602fa60b646c64df2dafd544bc94a21efedf6a53
--- /dev/null
+++ b/qa/qa/scenario/test/instance/non_blocking.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module QA
+  module Scenario
+    module Test
+      module Instance
+        class NonBlocking < All
+          tags :"~reliable",
+            :"~smoke",
+            *Specs::Runner::DEFAULT_SKIPPED_TAGS.map { |tag| :"~#{tag}" }
+        end
+      end
+    end
+  end
+end
diff --git a/qa/qa/service/docker_run/base.rb b/qa/qa/service/docker_run/base.rb
index 1a25aeb4c199c32dd25f40efdfb5a6c0d64f61d6..b33c421ec7f92bb0251ebe29e501ad1d5d5230b2 100644
--- a/qa/qa/service/docker_run/base.rb
+++ b/qa/qa/service/docker_run/base.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require 'socket'
+
 module QA
   module Service
     module DockerRun
@@ -11,8 +13,7 @@ def self.authenticated_registries
         end
 
         def initialize
-          @network = Runtime::Scenario.attributes[:network] || 'test'
-          @runner_network = Runtime::Scenario.attributes[:runner_network] || @network
+          @network = gdk_network || Runtime::Scenario.attributes[:network] || 'test'
         end
 
         # Authenticate against a container registry
@@ -42,10 +43,6 @@ def network
           network_exists?(@network) ? @network : 'bridge'
         end
 
-        def runner_network
-          network_exists?(@runner_network) ? @runner_network : network
-        end
-
         def inspect_network(name)
           shell("docker network inspect #{name}", fail_on_exception: false, return_exit_status: true)
         end
@@ -90,6 +87,24 @@ def restart
         def health
           shell("docker inspect --format='{{json .State.Health.Status}}' #{@name}").delete('"')
         end
+
+        # The network to use when testing against GDK in docker
+        #
+        # @return [String]
+        def gdk_network
+          return unless Runtime::Env.gdk_url
+
+          'host'
+        end
+
+        # The IP address of the docker host when testing against GDK in docker
+        #
+        # @return [String]
+        def gdk_host_ip
+          return unless Runtime::Env.gdk_url
+
+          Addrinfo.tcp(URI(Runtime::Env.gdk_url).host, nil).ip_address
+        end
       end
     end
   end
diff --git a/qa/qa/service/docker_run/gitlab_runner.rb b/qa/qa/service/docker_run/gitlab_runner.rb
index 078a3048cad83a46e14b093d5603709e694c337e..c340a09e38c20eb859fd2d957c78bc20a47fe02e 100644
--- a/qa/qa/service/docker_run/gitlab_runner.rb
+++ b/qa/qa/service/docker_run/gitlab_runner.rb
@@ -40,9 +40,10 @@ def register!
           raise("Missing runner token value!") unless token
 
           cmd = <<~CMD.tr("\n", ' ')
-            docker run -d --rm --network #{runner_network} --name #{@name}
+            docker run -d --rm --network #{network} --name #{@name}
             #{'-v /var/run/docker.sock:/var/run/docker.sock' if @executor == :docker}
             --privileged
+            #{"--add-host gdk.test:#{gdk_host_ip}" if gdk_network}
             #{@image}  #{add_gitlab_tls_cert if @address.include? 'https'}
             && docker exec --detach #{@name} sh -c "#{register_command}"
           CMD
@@ -51,7 +52,7 @@ def register!
           wait_until_running_and_configured
 
           # Prove airgappedness
-          shell("docker exec #{@name} sh -c '#{prove_airgap}'") if runner_network == 'airgapped'
+          shell("docker exec #{@name} sh -c '#{prove_airgap}'") if network == 'airgapped'
         end
 
         def tags=(tags)