diff --git a/core/authorize.php b/core/authorize.php
index a965e60b0e9f932c604e9c8943af89f8e69c85e9..aa66be5fd3d2e1310fab151c5e740e87307b23d9 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -27,6 +27,8 @@
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Drupal\Core\Site\Settings;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\Routing\Route;
 
 // Change the directory to the Drupal root.
 chdir('..');
@@ -65,7 +67,15 @@ function authorize_access_allowed(Request $request) {
 try {
   $request = Request::createFromGlobals();
   $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
-  $kernel->prepareLegacyRequest($request);
+  $kernel->boot();
+  // A route is required for route matching.
+  $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
+  $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
+  $kernel->preHandle($request);
+  // Ensure our request includes the session if appropriate.
+  if (PHP_SAPI !== 'cli') {
+    $request->setSession($kernel->getContainer()->get('session'));
+  }
 }
 catch (HttpExceptionInterface $e) {
   $response = new Response('', $e->getStatusCode());
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 360290430b1933647bfba34eb4b9b9951e6a6765..9922166cb65d688c2e164e41d6cf8bc9230933cb 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -627,6 +627,7 @@ function drupal_install_system($install_state) {
   // Add the normal installer service provider.
   $GLOBALS['conf']['container_service_providers']['InstallerServiceProvider'] = 'Drupal\Core\Installer\NormalInstallerServiceProvider';
 
+  // Get the existing request.
   $request = \Drupal::request();
   // Reboot into a full production environment to continue the installation.
   /** @var \Drupal\Core\Installer\InstallerKernel $kernel */
@@ -634,7 +635,13 @@ function drupal_install_system($install_state) {
   $kernel->shutdown();
   // Have installer rebuild from the disk, rather then building from scratch.
   $kernel->rebuildContainer(FALSE);
-  $kernel->prepareLegacyRequest($request);
+  // Reboot the kernel with new container.
+  $kernel->boot();
+  $kernel->preHandle($request);
+  // Ensure our request includes the session if appropriate.
+  if (PHP_SAPI !== 'cli') {
+    $request->setSession($kernel->getContainer()->get('session'));
+  }
 
   // Before having installed the system module and being able to do a module
   // rebuild, prime the \Drupal\Core\Extension\ModuleExtensionList static cache
diff --git a/core/includes/utility.inc b/core/includes/utility.inc
index 70d74a1ef5ee6fc3d7659586060573e0a72b3e34..c3fc86fee10bbca724a3789aae30e53133739d12 100644
--- a/core/includes/utility.inc
+++ b/core/includes/utility.inc
@@ -35,13 +35,16 @@ function drupal_rebuild($class_loader, Request $request) {
   // Bootstrap up to where caches exist and clear them.
   $kernel = new DrupalKernel('prod', $class_loader);
   $kernel->setSitePath(DrupalKernel::findSitePath($request));
+  $kernel->boot();
+  $kernel->preHandle($request);
+  // Ensure our request includes the session if appropriate.
+  if (PHP_SAPI !== 'cli') {
+    $request->setSession($kernel->getContainer()->get('session'));
+  }
 
   // Invalidate the container.
   $kernel->invalidateContainer();
 
-  // Prepare a NULL request.
-  $kernel->prepareLegacyRequest($request);
-
   foreach (Cache::getBins() as $bin) {
     $bin->deleteAll();
   }
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index e3607d237b8aebec9182c00b78092078b17fa4ea..25a0f4e96049b5d58c17ba271b8296bdc4ccdfbd 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -753,6 +753,7 @@ public function prepareLegacyRequest(Request $request) {
     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
     $this->container->get('request_stack')->push($request);
     $this->container->get('router.request_context')->fromRequest($request);
+    @trigger_error(__NAMESPACE__ . '\DrupalKernel::prepareLegacyRequest is deprecated drupal:8.0.0 and is removed from drupal:9.0.0. Use DrupalKernel::boot() and DrupalKernel::preHandle() instead. See https://www.drupal.org/node/3070678', E_USER_DEPRECATED);
     return $this;
   }
 
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index ff065a8f8240c2409479704b00b31391ab5a95ab..cdea12c29c1c3d4200d74ca08ecc03c13457eabe 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -132,8 +132,10 @@ public function invalidateContainer();
    *
    * @return $this
    *
-   * @deprecated in Drupal 8.0.x and will be removed before 9.0.0. Only used by
-   *   legacy front-controller scripts.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use
+   *   DrupalKernel::boot() and DrupalKernel::preHandle() instead.
+   *
+   * @see https://www.drupal.org/node/3070678
    */
   public function prepareLegacyRequest(Request $request);
 
diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
index 9c200679bc7e68ed3538cfbc2922c8d8d58ebfac..3f8a74326abb39e9609dd372bf961fc7aabb0d77 100644
--- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
+++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
@@ -18,6 +18,8 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Yaml\Yaml as SymfonyYaml;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\Routing\Route;
 
 /**
  * Defines a trait for shared functional test setup functionality.
@@ -390,13 +392,15 @@ protected function initUserSession() {
    */
   protected function initKernel(Request $request) {
     $this->kernel = DrupalKernel::createFromRequest($request, $this->classLoader, 'prod', TRUE);
-
     // Force the container to be built from scratch instead of loaded from the
     // disk. This forces us to not accidentally load the parent site.
     $this->kernel->invalidateContainer();
-
-    $this->kernel->prepareLegacyRequest($request);
-    return \Drupal::getContainer();
+    $this->kernel->boot();
+    // Add our request to the stack and route context.
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
+    $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
+    $this->kernel->preHandle($request);
+    return $this->kernel->getContainer();
   }
 
   /**
@@ -446,7 +450,6 @@ protected function rebuildAll() {
     // @todo Test-specific setUp() methods may set up further fixtures; find a
     //   way to execute this after setUp() is done, or to eliminate it entirely.
     $this->resetAll();
-    $this->kernel->prepareLegacyRequest(\Drupal::request());
 
     // Explicitly call register() again on the container registered in \Drupal.
     // @todo This should already be called through
@@ -580,7 +583,8 @@ protected function prepareEnvironment() {
     $kernel = TestRunnerKernel::createFromRequest($request, $this->classLoader);
     // TestRunnerKernel expects the working directory to be DRUPAL_ROOT.
     chdir(DRUPAL_ROOT);
-    $kernel->prepareLegacyRequest($request);
+    $kernel->boot();
+    $kernel->preHandle($request);
     $this->prepareDatabasePrefix();
 
     $this->originalSite = $kernel->findSitePath($request);
diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php
index e173f8f35e420f9d83eda8528aa2a93c8b42a4f9..703097696dbedb29e25b36d2d3ec29050b0df396 100644
--- a/core/modules/simpletest/src/InstallerTestBase.php
+++ b/core/modules/simpletest/src/InstallerTestBase.php
@@ -158,8 +158,13 @@ protected function setUp() {
       // Not using File API; a potential error must trigger a PHP warning.
       chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
       $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
-      $this->kernel->prepareLegacyRequest($request);
+      $this->kernel->boot();
+      $this->kernel->preHandle($request);
       $this->container = $this->kernel->getContainer();
+      // Ensure our request includes the session if appropriate.
+      if (PHP_SAPI !== 'cli') {
+        $request->setSession($this->container->get('session'));
+      }
 
       // Manually configure the test mail collector implementation to prevent
       // tests from sending out emails and collect them in state instead.
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index fcc3f2e602f0a46953b5c1ee4aeb75dcabcaa77f..9b39ae46948471495332dddc15f0ba93702e183c 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -539,7 +539,8 @@ function simpletest_script_init() {
   try {
     $request = Request::createFromGlobals();
     $kernel = TestRunnerKernel::createFromRequest($request, $autoloader);
-    $kernel->prepareLegacyRequest($request);
+    $kernel->boot();
+    $kernel->preHandle($request);
   }
   catch (Exception $e) {
     echo (string) $e;
diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
index 5b93b5b7c2bdec552b418a7b2d552d29ecfe16cf..eaccc1bdf22b72475dba9c774c63e7dbaf8eb7f8 100644
--- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
+++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
@@ -181,7 +181,8 @@ protected function setUp() {
       // Not using File API; a potential error must trigger a PHP warning.
       chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
       $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
-      $this->kernel->prepareLegacyRequest($request);
+      $this->kernel->boot();
+      $this->kernel->preHandle($request);
       $this->container = $this->kernel->getContainer();
 
       // Manually configure the test mail collector implementation to prevent
diff --git a/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php b/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php
index b5cb96b8cc4754a577cdbed51a8c909abc16cb14..aede46b3555db7820840e3f2cb4e2f3a7ac89312 100644
--- a/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php
+++ b/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php
@@ -191,4 +191,24 @@ public function testPreventChangeOfSitePath() {
     $kernel->setSitePath($path);
   }
 
+  /**
+   * @group legacy
+   * @expectedDeprecation Drupal\Core\DrupalKernel::prepareLegacyRequest is deprecated drupal:8.0.0 and is removed from drupal:9.0.0. Use DrupalKernel::boot() and DrupalKernel::preHandle() instead. See https://www.drupal.org/node/3070678
+   */
+  public function testPrepareLegacyRequest() {
+    $request = Request::createFromGlobals();
+    // Manually create kernel to avoid replacing settings.
+    $class_loader = require $this->root . '/autoload.php';
+    $kernel = DrupalKernel::createFromRequest($request, $class_loader, 'testing');
+    $this->setSetting('container_yamls', []);
+    $this->setSetting('hash_salt', $this->databasePrefix);
+
+    $this->assertNull($kernel->getContainer());
+    // Restore the usual PHPUnit error handler for deprecation testing.
+    restore_error_handler();
+    $kernel->prepareLegacyRequest($request);
+
+    $this->assertSame($request, $kernel->getContainer()->get('request_stack')->getMasterRequest());
+  }
+
 }
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index 02afacda64e66ad8d1dfe632db5f474fab3ad77d..f89aa4d9b00ec5bc57db56806809c6101f84eeb2 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -27,6 +27,8 @@
 use Symfony\Component\HttpFoundation\Request;
 use org\bovigo\vfs\vfsStream;
 use org\bovigo\vfs\visitor\vfsStreamPrintVisitor;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\Routing\Route;
 
 /**
  * Base class for functional integration tests.
@@ -341,9 +343,11 @@ private function bootKernel() {
     // DrupalKernel::boot() is not sufficient as it does not invoke preHandle(),
     // which is required to initialize legacy global variables.
     $request = Request::create('/');
-    $kernel->prepareLegacyRequest($request);
+    $kernel->boot();
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
+    $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
+    $kernel->preHandle($request);
 
-    // register() is only called if a new container was built/compiled.
     $this->container = $kernel->getContainer();
 
     // Ensure database tasks have been run.
@@ -358,8 +362,6 @@ private function bootKernel() {
       $this->container->get('module_handler')->loadAll();
     }
 
-    $this->container->get('request_stack')->push($request);
-
     // Setup the destion to the be frontpage by default.
     \Drupal::destination()->set('/');
 
diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
index f2b61fa68a9206d2a1ee922aac4a2f7230ed4375..05037bb208ad3643b31b1f4e07d4e11376d772de 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
@@ -214,7 +214,8 @@ public function testRenderWithTheme() {
   /**
    * @covers ::bootKernel
    */
-  public function testFileDefaultScheme() {
+  public function testBootKernel() {
+    $this->assertNull($this->container->get('request_stack')->getParentRequest(), 'There should only be one request on the stack');
     $this->assertEquals('public', \Drupal::config('system.file')->get('default_scheme'));
   }
 
diff --git a/core/tests/Drupal/TestSite/Commands/TestSiteUserLoginCommand.php b/core/tests/Drupal/TestSite/Commands/TestSiteUserLoginCommand.php
index 55c92032cdce7198e30b94a54e2d77d1b8a3aa23..bff190e4922a85aa8f13b211d61fda70d067bf89 100644
--- a/core/tests/Drupal/TestSite/Commands/TestSiteUserLoginCommand.php
+++ b/core/tests/Drupal/TestSite/Commands/TestSiteUserLoginCommand.php
@@ -52,9 +52,9 @@ protected function execute(InputInterface $input, OutputInterface $output) {
     Settings::initialize($kernel->getAppRoot(), $kernel->getSitePath(), $this->classLoader);
 
     $request = Request::createFromGlobals();
-    $kernel->prepareLegacyRequest($request);
 
     $kernel->boot();
+    $kernel->preHandle($request);
 
     $container = $kernel->getContainer();
     $uid = $input->getArgument('uid');