You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2021/04/21 12:30:07 UTC

[ignite-3] branch main updated: IGNITE-14411 Defined minimal set of cluster components and their lifecycle. Fixes #96

This is an automated email from the ASF dual-hosted git repository.

sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 3565c9d  IGNITE-14411 Defined minimal set of cluster components and their lifecycle. Fixes #96
3565c9d is described below

commit 3565c9d0ab61af1dcc44ad3060e1facae4d7461c
Author: Alexander Lapin <la...@gmail.com>
AuthorDate: Wed Apr 21 15:29:21 2021 +0300

    IGNITE-14411 Defined minimal set of cluster components and their lifecycle. Fixes #96
    
    Signed-off-by: Slava Koptilin <sl...@gmail.com>
---
 modules/{table => affinity}/pom.xml                |  43 ++-
 .../ignite/internal/affinity/AffinityManager.java  |  60 ++++
 modules/api/pom.xml                                |   6 +
 .../main/java/org/apache/ignite/app/Ignite.java}   |  15 +-
 .../main/java/org/apache/ignite/app/Ignition.java} |  17 +-
 .../org/apache/ignite/app/IgnitionManager.java     |  62 ++++
 .../network/NetworkConfigurationSchema.java}       |  15 +-
 .../schemas/rest}/RestConfigurationSchema.java     |   6 +-
 .../runner/ClusterConfigurationSchema.java}        |  25 +-
 .../apache/ignite/table/manager/TableManager.java} |   7 +-
 modules/baseline/pom.xml                           |  54 ++++
 .../ignite/internal/baseline/BaselineManager.java  |  58 ++++
 .../notifications/ConfigurationListenerTest.java   |  16 +-
 .../ignite/configuration/sample/UsageTest.java     |  21 +-
 modules/configuration/pom.xml                      |   5 +
 .../ignite/configuration/ConfigurationChanger.java |   7 +
 .../configuration/ConfigurationRegistry.java       |  34 +-
 .../internal/ConfigurationManager.java             |  92 ++++++
 .../internal/rest/FormatConverter.java}            |  25 +-
 .../configuration/internal/rest/JsonConverter.java | 356 +++++++++++++++++++++
 .../ignite/configuration/validation/Validator.java |   2 -
 modules/metastorage/pom.xml                        |  60 ++++
 .../internal/metastorage/MetaStorageManager.java   | 112 +++++++
 .../network/MetaStorageMessageTypes.java}          |  30 +-
 .../org/apache/ignite/internal/raft/Loza.java}     |  21 +-
 modules/rest/pom.xml                               |   6 +
 .../java/org/apache/ignite/rest/RestModule.java    |   5 +-
 .../rest/presentation/json/JsonConverterTest.java  |  12 +-
 modules/runner/pom.xml                             |  61 +++-
 .../ignite/internal/runner/app/IgnitionTest.java   |  81 +++++
 .../java/org/apache/ignite/app/IgniteRunner.java   | 113 +------
 .../ignite/configuration/ConfigurationModule.java  |  67 ----
 .../apache/ignite/internal/app/IgniteImpl.java}    |  29 +-
 .../apache/ignite/internal/app/IgnitionImpl.java   | 181 +++++++++++
 .../storage/DistributedConfigurationStorage.java   | 104 ++++++
 .../storage/LocalConfigurationStorage.java         | 104 ++++++
 .../services/org.apache.ignite.app.Ignition        |   1 +
 .../ignite/internal/schema/SchemaManager.java}     |  21 +-
 modules/table/pom.xml                              |  31 ++
 .../table/distributed/TableManagerImpl.java        |  69 ++++
 modules/{api => vault}/pom.xml                     |  15 +-
 .../ignite/internal/vault/VaultManager.java}       |  17 +-
 parent/pom.xml                                     |   1 +
 pom.xml                                            |   4 +
 44 files changed, 1766 insertions(+), 305 deletions(-)

diff --git a/modules/table/pom.xml b/modules/affinity/pom.xml
similarity index 55%
copy from modules/table/pom.xml
copy to modules/affinity/pom.xml
index 1f58901..42c02af 100644
--- a/modules/table/pom.xml
+++ b/modules/affinity/pom.xml
@@ -1,25 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
 
-       http://www.apache.org/licenses/LICENSE-2.0
+      http://www.apache.org/licenses/LICENSE-2.0
 
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+  -->
 
-<!--
-    POM file.
--->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -32,38 +29,38 @@
         <relativePath>../../parent/pom.xml</relativePath>
     </parent>
 
-    <artifactId>ignite-table</artifactId>
+    <artifactId>ignite-affinity</artifactId>
     <version>3.0.0-SNAPSHOT</version>
 
     <dependencies>
         <dependency>
             <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-api</artifactId>
+            <artifactId>ignite-configuration</artifactId>
             <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-schema</artifactId>
+            <artifactId>ignite-metastorage</artifactId>
             <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-core</artifactId>
+            <artifactId>ignite-baseline</artifactId>
             <version>${project.version}</version>
         </dependency>
 
-        <!-- Test dependencies -->
+        <!-- Test dependencies. -->
         <dependency>
             <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-engine</artifactId>
+            <artifactId>junit-jupiter-api</artifactId>
             <scope>test</scope>
         </dependency>
 
         <dependency>
             <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-params</artifactId>
+            <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/modules/affinity/src/main/java/org/apache/ignite/internal/affinity/AffinityManager.java b/modules/affinity/src/main/java/org/apache/ignite/internal/affinity/AffinityManager.java
new file mode 100644
index 0000000..7e28308
--- /dev/null
+++ b/modules/affinity/src/main/java/org/apache/ignite/internal/affinity/AffinityManager.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.affinity;
+
+import org.apache.ignite.internal.baseline.BaselineManager;
+import org.apache.ignite.configuration.internal.ConfigurationManager;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+
+/**
+ * Affinity manager is responsible for affinity function related logic including calculating affinity assignments.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class AffinityManager {
+    /**
+     * MetaStorage manager in order to watch private distributed affinity specific configuration,
+     * cause ConfigurationManger handles only public configuration.
+     */
+    private final MetaStorageManager metaStorageMgr;
+
+    /** Configuration manager in order to handle and listen affinity specific configuration.*/
+    private final ConfigurationManager configurationMgr;
+
+    /** Baseline manager. */
+    private final BaselineManager baselineMgr;
+
+    /**
+     * The constructor.
+     *
+     * @param configurationMgr Configuration manager.
+     * @param metaStorageMgr Meta storage manager.
+     */
+    public AffinityManager(
+        ConfigurationManager configurationMgr,
+        MetaStorageManager metaStorageMgr,
+        BaselineManager baselineMgr
+    ) {
+        this.configurationMgr = configurationMgr;
+        this.metaStorageMgr = metaStorageMgr;
+        this.baselineMgr = baselineMgr;
+    }
+
+    // TODO: IGNITE-14237 Affinity function.
+    // TODO: IGNITE-14238 Creating and destroying caches.
+    // TODO: IGNITE-14235 Provide a minimal cache/table configuration.
+}
diff --git a/modules/api/pom.xml b/modules/api/pom.xml
index 2ca3c60..c0e395b 100644
--- a/modules/api/pom.xml
+++ b/modules/api/pom.xml
@@ -37,5 +37,11 @@
             <groupId>org.jetbrains</groupId>
             <artifactId>annotations</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-configuration-annotation-processor</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/testframework/package-info.java b/modules/api/src/main/java/org/apache/ignite/app/Ignite.java
similarity index 71%
rename from modules/core/src/test/java/org/apache/ignite/internal/testframework/package-info.java
rename to modules/api/src/main/java/org/apache/ignite/app/Ignite.java
index 23ab2d4..c9613dd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/testframework/package-info.java
+++ b/modules/api/src/main/java/org/apache/ignite/app/Ignite.java
@@ -15,7 +15,18 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.app;
+
+import org.apache.ignite.table.manager.TableManager;
+
 /**
- * Contains internal tests or test related classes and interfaces.
+ * Ignite node interface. Main entry-point for all Ignite APIs.
  */
-package org.apache.ignite.internal.testframework;
+public interface Ignite extends AutoCloseable {
+    /**
+     * Gets a manager for tables.
+     *
+     * @return Table manager.
+     */
+    TableManager tableManager();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/api/src/main/java/org/apache/ignite/app/Ignition.java
similarity index 60%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/api/src/main/java/org/apache/ignite/app/Ignition.java
index 9cc76fb..9904f4c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/api/src/main/java/org/apache/ignite/app/Ignition.java
@@ -15,7 +15,20 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.app;
+
+import org.jetbrains.annotations.Nullable;
+
 /**
- * Common utility classes for strings.
+ * Entry point for handling grid lifecycle.
  */
-package org.apache.ignite.internal.tostring;
+@SuppressWarnings("UnnecessaryInterfaceModifier")
+public interface Ignition {
+    /**
+     * Starts Ignite node with optional bootstrap configuration in json format.
+     * @param jsonStrBootstrapCfg Node configuration in json format.
+     * @return Started Ignite node.
+     */
+    // TODO: IGNITE-14599 Add generic way to bootstrap configuration.
+    public Ignite start(@Nullable String jsonStrBootstrapCfg);
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java b/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java
new file mode 100644
index 0000000..1d66c30
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.app;
+
+import java.util.ServiceLoader;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Service loader based implementation of an entry point for handling grid lifecycle.
+ */
+public class IgnitionManager {
+    /** Loaded Ignition instance. */
+    private static Ignition ignition;
+
+    /**
+     * Starts Ignite node with optional bootstrap configuration in json format.
+     * @param jsonStrBootstrapCfg Node configuration in json format.
+     * @return Started Ignite node.
+     */
+    // TODO IGNITE-14580 Add exception handling logic to IgnitionProcessor.
+    public static synchronized Ignite start(@Nullable String jsonStrBootstrapCfg) {
+        if (ignition == null) {
+            ServiceLoader<Ignition> ldr = ServiceLoader.load(Ignition.class);
+            ignition = ldr.iterator().next();
+        }
+
+        return ignition.start(jsonStrBootstrapCfg);
+    }
+
+    /**
+     * Starts Ignite node with optional bootstrap configuration in json format.
+     * @param jsonStrBootstrapCfg Node configuration in json format.
+     * @param clsLdr The class loader to be used to load provider-configuration files
+     * and provider classes, or {@code null} if the system class
+     * loader (or, failing that, the bootstrap class loader) is to be used
+     * @return Started Ignite node.
+     */
+    // TODO IGNITE-14580 Add exception handling logic to IgnitionProcessor.
+    public static synchronized Ignite start(@Nullable String jsonStrBootstrapCfg, @Nullable ClassLoader clsLdr) {
+        if (ignition == null) {
+            ServiceLoader<Ignition> ldr = ServiceLoader.load(Ignition.class, clsLdr);
+            ignition = ldr.iterator().next();
+        }
+
+        return ignition.start(jsonStrBootstrapCfg);
+    }
+}
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
similarity index 77%
copy from modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
copy to modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
index 66eaa51..1a1b51f 100644
--- a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.rest.configuration;
+package org.apache.ignite.configuration.schemas.network;
 
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
@@ -23,21 +23,18 @@ import org.apache.ignite.configuration.annotation.ConfigurationRoot;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-import static org.apache.ignite.rest.RestModule.DFLT_PORT;
-
 /**
- * Configuration schema for REST endpoint subtree.
+ * Configuration schema for network endpoint subtree.
  */
-@ConfigurationRoot(rootName = "rest", type = ConfigurationType.LOCAL)
-public class RestConfigurationSchema {
+@ConfigurationRoot(rootName = "network", type = ConfigurationType.LOCAL)
+public class NetworkConfigurationSchema {
     /** */
     @Min(1024)
     @Max(0xFFFF)
     @Value(hasDefault = true)
-    public final int port = DFLT_PORT;
+    public final int port = 3040;
 
     /** */
-    @Min(0)
     @Value(hasDefault = true)
-    public final int portRange = 0;
+    public String[] netClusterNodes = {"localhost:" + port};
 }
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/rest/RestConfigurationSchema.java
similarity index 90%
copy from modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
copy to modules/api/src/main/java/org/apache/ignite/configuration/schemas/rest/RestConfigurationSchema.java
index 66eaa51..d65360f 100644
--- a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/rest/RestConfigurationSchema.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.rest.configuration;
+package org.apache.ignite.configuration.schemas.rest;
 
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
@@ -23,8 +23,6 @@ import org.apache.ignite.configuration.annotation.ConfigurationRoot;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-import static org.apache.ignite.rest.RestModule.DFLT_PORT;
-
 /**
  * Configuration schema for REST endpoint subtree.
  */
@@ -34,7 +32,7 @@ public class RestConfigurationSchema {
     @Min(1024)
     @Max(0xFFFF)
     @Value(hasDefault = true)
-    public final int port = DFLT_PORT;
+    public final int port = 10300;
 
     /** */
     @Min(0)
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/ClusterConfigurationSchema.java
similarity index 64%
rename from modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
rename to modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/ClusterConfigurationSchema.java
index 66eaa51..63278e3 100644
--- a/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/ClusterConfigurationSchema.java
@@ -15,29 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.rest.configuration;
+package org.apache.ignite.configuration.schemas.runner;
 
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
 import org.apache.ignite.configuration.annotation.ConfigurationRoot;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-import static org.apache.ignite.rest.RestModule.DFLT_PORT;
-
 /**
- * Configuration schema for REST endpoint subtree.
+ * Configuration schema for cluster endpoint subtree.
  */
-@ConfigurationRoot(rootName = "rest", type = ConfigurationType.LOCAL)
-public class RestConfigurationSchema {
-    /** */
-    @Min(1024)
-    @Max(0xFFFF)
-    @Value(hasDefault = true)
-    public final int port = DFLT_PORT;
-
-    /** */
-    @Min(0)
-    @Value(hasDefault = true)
-    public final int portRange = 0;
+@ConfigurationRoot(rootName = "cluster", type = ConfigurationType.DISTRIBUTED)
+public class ClusterConfigurationSchema {
+    /** List of unique names of those cluster nodes that will host distributed metastorage instances. */
+    @Value
+    String[] metastorageClusterNodeNames;
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/api/src/main/java/org/apache/ignite/table/manager/TableManager.java
similarity index 86%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/api/src/main/java/org/apache/ignite/table/manager/TableManager.java
index 9cc76fb..f7fcf50 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/manager/TableManager.java
@@ -15,7 +15,10 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.table.manager;
+
 /**
- * Common utility classes for strings.
+ * Interface that provides methods for managing tables.
  */
-package org.apache.ignite.internal.tostring;
+public interface TableManager {
+}
diff --git a/modules/baseline/pom.xml b/modules/baseline/pom.xml
new file mode 100644
index 0000000..ef01290
--- /dev/null
+++ b/modules/baseline/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>ignite-baseline</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-network</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-configuration</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-metastorage</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/modules/baseline/src/main/java/org/apache/ignite/internal/baseline/BaselineManager.java b/modules/baseline/src/main/java/org/apache/ignite/internal/baseline/BaselineManager.java
new file mode 100644
index 0000000..e2b78d8
--- /dev/null
+++ b/modules/baseline/src/main/java/org/apache/ignite/internal/baseline/BaselineManager.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.baseline;
+
+import org.apache.ignite.configuration.internal.ConfigurationManager;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+import org.apache.ignite.network.ClusterService;
+
+/**
+ * Baseline manager is responsible for handling baseline related logic.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class BaselineManager {
+    /** Configuration manager in order to handle and listen baseline specific configuration.*/
+    private final ConfigurationManager configurationMgr;
+
+    /**
+     * MetaStorage manager in order to watch private distributed baseline specific configuration,
+     * cause ConfigurationManger handles only public configuration.
+     */
+    private final MetaStorageManager metastorageMgr;
+
+    /** Cluster network service in order to retrieve information about current cluster nodes. */
+    private final ClusterService clusterSvc;
+
+    /**
+     * The constructor.
+     *
+     * @param configurationMgr Configuration manager.
+     * @param metastorageMgr MetaStorage manager.
+     * @param clusterSvc Cluster network service.
+     */
+    public BaselineManager(
+        ConfigurationManager configurationMgr,
+        MetaStorageManager metastorageMgr,
+        ClusterService clusterSvc
+    ) {
+        this.configurationMgr = configurationMgr;
+        this.metastorageMgr = metastorageMgr;
+        this.clusterSvc = clusterSvc;
+    }
+}
+
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/notifications/ConfigurationListenerTest.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/notifications/ConfigurationListenerTest.java
index c3dd2b2..3d1c308 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/notifications/ConfigurationListenerTest.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/notifications/ConfigurationListenerTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.configuration.notifications;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.configuration.ConfigurationRegistry;
@@ -26,6 +27,7 @@ import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.ConfigurationRoot;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
 import org.apache.ignite.configuration.annotation.Value;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 import org.apache.ignite.configuration.storage.TestConfigurationStorage;
 import org.junit.jupiter.api.AfterEach;
@@ -61,7 +63,7 @@ public class ConfigurationListenerTest {
     }
 
     /** */
-    private final ConfigurationRegistry registry = new ConfigurationRegistry();
+    private ConfigurationRegistry registry;
 
     /** */
     private ParentConfiguration configuration;
@@ -69,13 +71,15 @@ public class ConfigurationListenerTest {
     /** */
     @BeforeEach
     public void before() {
-        registry.registerRootKey(ParentConfiguration.KEY);
+        ConfigurationStorage testConfigurationStorage = new TestConfigurationStorage();
 
-        TestConfigurationStorage storage = new TestConfigurationStorage();
+        registry = new ConfigurationRegistry(
+            Collections.singletonList(ParentConfiguration.KEY),
+            Collections.emptyMap(),
+            Collections.singletonList(testConfigurationStorage)
+        );
 
-        registry.registerStorage(storage);
-
-        registry.startStorageConfigurations(storage.type());
+        registry.startStorageConfigurations(testConfigurationStorage.type());
 
         configuration = registry.getConfiguration(ParentConfiguration.KEY);
     }
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
index 41f14d9..21416ab 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.configuration.sample;
 
+import java.util.Arrays;
+import java.util.Collections;
 import org.apache.ignite.configuration.ConfigurationRegistry;
 import org.apache.ignite.configuration.storage.TestConfigurationStorage;
 import org.junit.jupiter.api.AfterEach;
@@ -33,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
  */
 public class UsageTest {
     /** */
-    private final ConfigurationRegistry registry = new ConfigurationRegistry();
+    private ConfigurationRegistry registry;
 
     /** */
     @AfterEach
@@ -46,9 +48,11 @@ public class UsageTest {
      */
     @Test
     public void test() throws Exception {
-        registry.registerRootKey(LocalConfiguration.KEY);
-
-        registry.registerStorage(new TestConfigurationStorage());
+        registry = new ConfigurationRegistry(
+            Collections.singletonList(LocalConfiguration.KEY),
+            Collections.emptyMap(),
+            Collections.singletonList(new TestConfigurationStorage())
+        );
 
         LocalConfiguration root = registry.getConfiguration(LocalConfiguration.KEY);
 
@@ -100,10 +104,11 @@ public class UsageTest {
 
         long autoAdjustTimeout = 30_000L;
 
-        registry.registerRootKey(NetworkConfiguration.KEY);
-        registry.registerRootKey(LocalConfiguration.KEY);
-
-        registry.registerStorage(new TestConfigurationStorage());
+        registry = new ConfigurationRegistry(
+            Arrays.asList(NetworkConfiguration.KEY, LocalConfiguration.KEY),
+            Collections.emptyMap(),
+            Collections.singletonList(new TestConfigurationStorage())
+        );
 
         registry.getConfiguration(LocalConfiguration.KEY).change(local ->
             local.changeBaseline(baseline ->
diff --git a/modules/configuration/pom.xml b/modules/configuration/pom.xml
index 02e54de..e2c86ca 100644
--- a/modules/configuration/pom.xml
+++ b/modules/configuration/pom.xml
@@ -51,5 +51,10 @@
             <groupId>org.jetbrains</groupId>
             <artifactId>annotations</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationChanger.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationChanger.java
index 8e628f3..0eb3465 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationChanger.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationChanger.java
@@ -127,6 +127,13 @@ public final class ConfigurationChanger {
     }
 
     /** */
+    public <A extends Annotation> void addValidators(Class<A> annotationType, Set<Validator<A, ?>> validators) {
+        this.validators
+            .computeIfAbsent(annotationType, a -> new HashSet<>())
+            .addAll(validators);
+    }
+
+    /** */
     public void addRootKey(RootKey<?, ?> rootKey) {
         assert !storageInstances.containsKey(rootKey.type());
 
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
index e30f396..766714e 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
@@ -20,9 +20,11 @@ package org.apache.ignite.configuration;
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.BiFunction;
 import java.util.function.Function;
@@ -67,21 +69,27 @@ public class ConfigurationRegistry {
         changer.addValidator(Max.class, new MaxValidator());
     }
 
-    /** */
-    public void registerRootKey(RootKey<?, ?> rootKey) {
-        changer.addRootKey(rootKey);
-
-        configs.put(rootKey.key(), (DynamicConfiguration<?, ?, ?>)rootKey.createPublicRoot(changer));
-    }
+    /**
+     * Constructor.
+     *
+     * @param rootKeys Configuration root keys.
+     * @param validators Validators.
+     * @param configurationStorages Configuration Storages.
+     */
+    public <A extends Annotation> ConfigurationRegistry(
+        Collection<RootKey<?, ?>> rootKeys,
+        Map<Class<A>, Set<Validator<A, ?>>> validators,
+        Collection<ConfigurationStorage> configurationStorages
+    ) {
+        rootKeys.forEach(rootKey ->
+        {
+            changer.addRootKey(rootKey);
+            configs.put(rootKey.key(), (DynamicConfiguration<?, ?, ?>)rootKey.createPublicRoot(changer));
+        });
 
-    /** */
-    public <A extends Annotation> void registerValidator(Class<A> annotationType, Validator<A, ?> validator) {
-        changer.addValidator(annotationType, validator);
-    }
+        validators.forEach(changer::addValidators);
 
-    /** */
-    public void registerStorage(ConfigurationStorage configurationStorage) {
-        changer.register(configurationStorage);
+        configurationStorages.forEach(changer::register);
     }
 
     /** */
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/ConfigurationManager.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/ConfigurationManager.java
new file mode 100644
index 0000000..46e3b17
--- /dev/null
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/ConfigurationManager.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.configuration.internal;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.apache.ignite.configuration.ConfigurationRegistry;
+import org.apache.ignite.configuration.RootKey;
+import org.apache.ignite.configuration.internal.rest.JsonConverter;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.configuration.validation.Validator;
+
+/**
+ * Configuration manager is responsible for handling configuration lifecycle and provides configuration API.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings("WeakerAccess") public class ConfigurationManager {
+    /** Configuration registry. */
+    private final ConfigurationRegistry confRegistry;
+
+    /** Set of configuration storages. */
+    private final Set<ConfigurationStorage> configurationStorages;
+
+    /**
+     * The constructor.
+     *
+     * @param rootKeys Configuration root keys.
+     * @param validators Validators.
+     * @param configurationStorages Configuration storages.
+     */
+    public <A extends Annotation> ConfigurationManager(
+        Collection<RootKey<?, ?>> rootKeys,
+        Map<Class<A>, Set<Validator<A, ?>>> validators,
+        Collection<ConfigurationStorage> configurationStorages
+    ) {
+        this.configurationStorages = Set.copyOf(configurationStorages);
+
+        confRegistry = new ConfigurationRegistry(rootKeys, validators, configurationStorages);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param rootKeys Configuration root keys.
+     * @param configurationStorages Configuration storages.
+     */
+    public ConfigurationManager(
+        Collection<RootKey<?, ?>> rootKeys,
+        Collection<ConfigurationStorage> configurationStorages
+    ) {
+        this(rootKeys, Collections.emptyMap(), configurationStorages);
+    }
+
+    /**
+     * Bootstrap configuration manager with customer user cfg.
+     * @param jsonStr Customer configuration in json format.
+     */
+    public void bootstrap(String jsonStr) throws InterruptedException, ExecutionException {
+        JsonObject jsonCfg = JsonParser.parseString(jsonStr).getAsJsonObject();
+
+        for (ConfigurationStorage configurationStorage : configurationStorages)
+            confRegistry.change(JsonConverter.jsonSource(jsonCfg), configurationStorage).get();
+    }
+
+    /**
+     * @return Configuration registry.
+     */
+    public ConfigurationRegistry configurationRegistry() {
+        return confRegistry;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/FormatConverter.java
similarity index 64%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/FormatConverter.java
index 9cc76fb..d39d01b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/FormatConverter.java
@@ -15,7 +15,24 @@
  * limitations under the License.
  */
 
-/**
- * Common utility classes for strings.
- */
-package org.apache.ignite.internal.tostring;
+package org.apache.ignite.configuration.internal.rest;
+
+import java.io.Reader;
+
+/** */
+public interface FormatConverter {
+    /** */
+    String convertTo(Object obj);
+
+    /** */
+    String convertTo(String rootName, Object obj);
+
+    /** */
+    String rootName(String source);
+
+    /** */
+    Object convertFrom(String source, String rootName, Class<?> clazz);
+
+    /** */
+    <T> T convertFrom(Reader source, String rootName, Class<T> clazz);
+}
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/JsonConverter.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/JsonConverter.java
new file mode 100644
index 0000000..83d6571
--- /dev/null
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/internal/rest/JsonConverter.java
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.configuration.internal.rest;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.ignite.configuration.tree.ConfigurationSource;
+import org.apache.ignite.configuration.tree.ConfigurationVisitor;
+import org.apache.ignite.configuration.tree.ConstructableTreeNode;
+import org.apache.ignite.configuration.tree.InnerNode;
+import org.apache.ignite.configuration.tree.NamedListNode;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.configuration.internal.util.ConfigurationUtil.join;
+
+public class JsonConverter {
+    /** */
+    public static ConfigurationVisitor<JsonElement> jsonVisitor() {
+        return new ConfigurationVisitor<JsonElement>() {
+            /** */
+            private final Deque<JsonObject> jsonObjectsStack = new ArrayDeque<>();
+
+            /** {@inheritDoc} */
+            @Override public JsonElement visitLeafNode(String key, Serializable val) {
+                JsonElement jsonLeaf = toJsonLeaf(val);
+
+                addToParent(key, jsonLeaf);
+
+                return jsonLeaf;
+            }
+
+            /** {@inheritDoc} */
+            @Override public JsonElement visitInnerNode(String key, InnerNode node) {
+                JsonObject innerJsonNode = new JsonObject();
+
+                jsonObjectsStack.push(innerJsonNode);
+
+                node.traverseChildren(this);
+
+                jsonObjectsStack.pop();
+
+                addToParent(key, innerJsonNode);
+
+                return innerJsonNode;
+            }
+
+            /** {@inheritDoc} */
+            @Override public <N extends InnerNode> JsonElement visitNamedListNode(String key, NamedListNode<N> node) {
+                JsonObject namedListJsonNode = new JsonObject();
+
+                jsonObjectsStack.push(namedListJsonNode);
+
+                for (String subkey : node.namedListKeys())
+                    node.get(subkey).accept(subkey, this);
+
+                jsonObjectsStack.pop();
+
+                addToParent(key, namedListJsonNode);
+
+                return namedListJsonNode;
+            }
+
+            /** */
+            @NotNull private JsonElement toJsonLeaf(Serializable val) {
+                if (val == null)
+                    return JsonNull.INSTANCE;
+
+                Class<? extends Serializable> valClass = val.getClass();
+
+                if (!valClass.isArray())
+                    return toJsonPrimitive(val);
+
+                int size = Array.getLength(val);
+
+                JsonArray jsonArray = new JsonArray(size);
+
+                for (int idx = 0; idx < size; idx++)
+                    jsonArray.add(toJsonPrimitive(Array.get(val, idx)));
+
+                return jsonArray;
+            }
+
+            /** */
+            @NotNull private JsonElement toJsonPrimitive(Object val) {
+                if (val == null)
+                    return JsonNull.INSTANCE;
+
+                if (val instanceof Boolean)
+                    return new JsonPrimitive((Boolean)val);
+
+                if (val instanceof String)
+                    return new JsonPrimitive((String)val);
+
+                assert val instanceof Number : val.getClass();
+
+                return new JsonPrimitive((Number)val);
+            }
+
+            /**
+             * Add subelement to the paretn JSON object if it exists.
+             *
+             * @param key Key for the passed JSON element.
+             * @param jsonElement JSON element to add to the parent.
+             */
+            private void addToParent(String key, JsonElement jsonElement) {
+                if (!jsonObjectsStack.isEmpty())
+                    jsonObjectsStack.peek().add(key, jsonElement);
+            }
+        };
+    }
+
+    /**
+     * @param jsonElement JSON that has to be converted to the configuration source.
+     * @return JSON-based configuration source.
+     */
+    public static ConfigurationSource jsonSource(JsonElement jsonElement) {
+        if (!jsonElement.isJsonObject())
+            throw new IllegalArgumentException("JSON object is expected as a configuration source");
+
+        return new JsonObjectConfigurationSource(new ArrayList<>(), jsonElement.getAsJsonObject());
+    }
+
+    private static class JsonObjectConfigurationSource implements ConfigurationSource {
+        /** */
+        private final List<String> path;
+
+        /** */
+        private final JsonObject jsonObject;
+
+        private JsonObjectConfigurationSource(List<String> path, JsonObject jsonObject) {
+            this.path = path;
+            this.jsonObject = jsonObject;
+        }
+
+        /** {@inheritDoc} */
+        @Override public <T> T unwrap(Class<T> clazz) {
+            throw new IllegalArgumentException(
+                "'" + clazz.getSimpleName() + "' is expected as a type for '"
+                    + join(path) + "' configuration value"
+            );
+        }
+
+        /** {@inheritDoc} */
+        @Override public void descend(ConstructableTreeNode node) {
+            for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+                String key = entry.getKey();
+
+                JsonElement jsonElement = entry.getValue();
+
+                try {
+                    if (jsonElement.isJsonArray() || jsonElement.isJsonPrimitive()) {
+                        List<String> path = new ArrayList<>(this.path.size() + 1);
+                        path.addAll(this.path);
+                        path.add(key);
+
+                        node.construct(key, new JsonPrimitiveConfigurationSource(path, jsonElement));
+                    }
+                    else if (jsonElement.isJsonNull()) {
+                        node.construct(key, null);
+                    }
+                    else {
+                        assert jsonElement.isJsonObject();
+
+                        List<String> path = new ArrayList<>(this.path.size() + 1);
+                        path.addAll(this.path);
+                        path.add(key);
+
+                        node.construct(key, new JsonObjectConfigurationSource(path, jsonElement.getAsJsonObject()));
+                    }
+                }
+                catch (NoSuchElementException e) {
+                    if (path.isEmpty()) {
+                        throw new IllegalArgumentException(
+                            "'" + key + "' configuration root doesn't exist"
+                        );
+                    }
+                    else {
+                        throw new IllegalArgumentException(
+                            "'" + join(path) + "' configuration doesn't have '" + key + "' subconfiguration"
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    private static class JsonPrimitiveConfigurationSource implements ConfigurationSource {
+        private final List<String> path;
+
+        private final JsonElement jsonLeaf;
+
+        private JsonPrimitiveConfigurationSource(List<String> path, JsonElement jsonLeaf) {
+            assert !path.isEmpty();
+
+            this.path = path;
+            this.jsonLeaf = jsonLeaf;
+        }
+
+        /** {@inheritDoc} */
+        @Override public <T> T unwrap(Class<T> clazz) {
+            if (clazz.isArray()) {
+                if (!jsonLeaf.isJsonArray())
+                    throw wrongTypeException(clazz, -1);
+
+                JsonArray jsonArray = jsonLeaf.getAsJsonArray();
+                int size = jsonArray.size();
+
+                Class<?> componentType = clazz.getComponentType();
+                Class<?> boxedComponentType = box(componentType);
+
+                Object resArray = Array.newInstance(componentType, size);
+
+                for (int idx = 0; idx < size; idx++) {
+                    JsonElement element = jsonArray.get(idx);
+
+                    if (!element.isJsonPrimitive())
+                        throw wrongTypeException(boxedComponentType, idx);
+
+                    Array.set(resArray, idx, unwrap(element.getAsJsonPrimitive(), boxedComponentType, idx));
+                }
+
+                return (T)resArray;
+            }
+            else {
+                if (jsonLeaf.isJsonArray())
+                    throw wrongTypeException(clazz, -1);
+
+                return unwrap(jsonLeaf.getAsJsonPrimitive(), clazz, -1);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void descend(ConstructableTreeNode node) {
+            throw new IllegalArgumentException(
+                "'" + join(path) + "' is expected to be a composite configuration node, not a single value"
+            );
+        }
+
+        @NotNull private <T> IllegalArgumentException wrongTypeException(Class<T> clazz, int idx) {
+            return new IllegalArgumentException(
+                "'" + unbox(clazz).getSimpleName() + "' is expected as a type for '"
+                    + join(path) + (idx == -1 ? "" : ("[" + idx + "]")) + "' configuration value"
+            );
+        }
+
+        /**
+         * @param clazz Class object.
+         * @return Same object of it doesn't represent primitive class, boxed version otherwise.
+         */
+        private static Class<?> box(Class<?> clazz) {
+            if (!clazz.isPrimitive())
+                return clazz;
+
+            switch (clazz.getName()) {
+                case "boolean":
+                    return Boolean.class;
+
+                case "int":
+                    return Integer.class;
+
+                case "long":
+                    return Long.class;
+
+                default:
+                    assert clazz == double.class;
+
+                    return Double.class;
+            }
+        }
+
+        private static Class<?> unbox(Class<?> clazz) {
+            assert !clazz.isPrimitive();
+
+            if (clazz == Boolean.class)
+                return boolean.class;
+            else if (clazz == Integer.class)
+                return int.class;
+            else if (clazz == Long.class)
+                return long.class;
+            else if (clazz == Double.class)
+                return double.class;
+            else
+                return clazz;
+        }
+
+        private <T> T unwrap(JsonPrimitive jsonPrimitive, Class<T> clazz, int idx) {
+            assert !clazz.isArray();
+            assert !clazz.isPrimitive();
+
+            if (clazz == String.class) {
+                if (!jsonPrimitive.isString())
+                    throw wrongTypeException(clazz, idx);
+
+                return clazz.cast(jsonPrimitive.getAsString());
+            }
+
+            if (Number.class.isAssignableFrom(clazz)) {
+                if (!jsonPrimitive.isNumber())
+                    throw wrongTypeException(clazz, idx);
+
+                if (clazz == Double.class)
+                    return clazz.cast(jsonPrimitive.getAsDouble());
+
+                if (clazz == Long.class)
+                    return clazz.cast(jsonPrimitive.getAsLong());
+
+                assert clazz == Integer.class;
+
+                long longValue = jsonPrimitive.getAsLong();
+
+                if (longValue < Integer.MIN_VALUE || longValue > Integer.MAX_VALUE) {
+                    throw new IllegalArgumentException(
+                        "'" + join(path) + "' has integer type"
+                            + " and the value " + longValue + " is out of bounds"
+                    );
+                }
+
+                return clazz.cast((int)longValue);
+            }
+
+            assert clazz == Boolean.class;
+
+            if (!jsonPrimitive.isBoolean())
+                throw wrongTypeException(clazz, idx);
+
+            return clazz.cast(jsonPrimitive.getAsBoolean());
+        }
+    }
+}
+
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/validation/Validator.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/validation/Validator.java
index 47b57ab..d9e422a 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/configuration/validation/Validator.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/validation/Validator.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.configuration.validation;
 
 import java.lang.annotation.Annotation;
-import org.apache.ignite.configuration.ConfigurationRegistry;
 
 /**
  * Interface for all configuration validators. Recommended to be a stateless class.
@@ -27,7 +26,6 @@ import org.apache.ignite.configuration.ConfigurationRegistry;
  *
  * @param <A> Type of the annotation that puts current validator to the field.
  * @param <VIEW> Upper bound for field types that can be validated with this validator.
- * @see ConfigurationRegistry#registerValidator(Class, Validator)
  */
 public interface Validator<A extends Annotation, VIEW> {
     /**
diff --git a/modules/metastorage/pom.xml b/modules/metastorage/pom.xml
new file mode 100644
index 0000000..d85d192
--- /dev/null
+++ b/modules/metastorage/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>ignite-metastorage</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-network</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-raft</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-vault</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>metastorage-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
new file mode 100644
index 0000000..d613b3e
--- /dev/null
+++ b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metastorage;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.ignite.internal.vault.VaultManager;
+import org.apache.ignite.metastorage.client.MetaStorageService;
+import org.apache.ignite.metastorage.common.Key;
+import org.apache.ignite.metastorage.common.WatchListener;
+import org.apache.ignite.network.ClusterService;
+import org.apache.ignite.internal.raft.Loza;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * MetaStorage manager is responsible for:
+ * <ul>
+ *     <li>Handling cluster init message.</li>
+ *     <li>Managing meta storage lifecycle including instantiation meta storage raft group.</li>
+ *     <li>Providing corresponding meta storage service proxy interface</li>
+ * </ul>
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused", "WeakerAccess"}) public class MetaStorageManager {
+    /** Vault manager in order to commit processed watches with corresponding applied revision. */
+    private final VaultManager vaultMgr;
+
+    /** Cluster network service that is used in order to handle cluster init message. */
+    private final ClusterService clusterNetSvc;
+
+    /** Raft manager that is used for metastorage raft group handling. */
+    private final Loza raftMgr;
+
+    /** Meta storage service. */
+    private MetaStorageService metaStorageSvc;
+
+    /**
+     * The constructor.
+     *
+     * @param vaultMgr Vault manager.
+     * @param clusterNetSvc Cluster network service.
+     * @param raftMgr Raft manager.
+     */
+    public MetaStorageManager(
+        VaultManager vaultMgr,
+        ClusterService clusterNetSvc,
+        Loza raftMgr
+    ) {
+        this.vaultMgr = vaultMgr;
+        this.clusterNetSvc = clusterNetSvc;
+        this.raftMgr = raftMgr;
+
+        // TODO: IGNITE-14088: Uncomment and use real serializer factory
+//        Arrays.stream(MetaStorageMessageTypes.values()).forEach(
+//            msgTypeInstance -> net.registerMessageMapper(
+//                msgTypeInstance.msgType(),
+//                new DefaultMessageMapperProvider()
+//            )
+//        );
+
+        clusterNetSvc.messagingService().addMessageHandler((message, sender, correlationId) -> {
+            // TODO: IGNITE-14414 Cluster initialization flow.
+        });
+    }
+
+    /**
+     * Register subscription on meta storage updates for further deployment when DMS is ready.
+     *
+     * @param key The target key. Couldn't be {@code null}.
+     * @param lsnr Listener which will be notified for each update.
+     * @return Subscription identifier. Could be used in {@link #unregisterWatch} method in order to cancel
+     * subscription.
+     */
+    public synchronized CompletableFuture<Long> registerWatch(@Nullable Key key, @NotNull WatchListener lsnr) {
+        // TODO: IGNITE-14446 Implement DMS manager with watch registry.
+        return null;
+    }
+
+    /**
+     * Unregister subscription for the given identifier.
+     *
+     * @param id Subscription identifier.
+     * @return Completed future in case of operation success. Couldn't be {@code null}.
+     */
+    public synchronized CompletableFuture<Void> unregisterWatch(long id) {
+        // TODO: IGNITE-14446 Implement DMS manager with watch registry.
+        return null;
+    }
+
+    /**
+     * Deploy all registered watches through{@code MetaStorageService.watch()}.
+     */
+    public synchronized void deployWatches() {
+        // TODO: IGNITE-14446 Implement DMS manager with watch registry.
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/network/MetaStorageMessageTypes.java
similarity index 57%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/network/MetaStorageMessageTypes.java
index 9cc76fb..6113fa0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/network/MetaStorageMessageTypes.java
@@ -15,7 +15,33 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.internal.metastorage.network;
+
 /**
- * Common utility classes for strings.
+ * Metastorage message types
  */
-package org.apache.ignite.internal.tostring;
+// TODO: IGNITE-14088: Uncomment and use real serializer factory
+//@DirectlyMarshallableTypes(moduleType = 11)
+public enum MetaStorageMessageTypes {
+    /** */
+    CLUSTER_INIT_REQUEST((short)1100);
+
+    /** */
+    private short msgType;
+
+    /**
+     * Constructor.
+     *
+     * @param msgType Message type.
+     */
+    MetaStorageMessageTypes(short msgType) {
+        this.msgType = msgType;
+    }
+
+    /**
+     * @return Message type.
+     */
+    public short msgType() {
+        return msgType;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
similarity index 59%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
index 9cc76fb..e91ff2d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
@@ -15,7 +15,24 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.internal.raft;
+
+import org.apache.ignite.network.ClusterService;
+
 /**
- * Common utility classes for strings.
+ * Best raft manager ever since 1982.
  */
-package org.apache.ignite.internal.tostring;
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class Loza {
+    /** Cluster network service. */
+    private final ClusterService clusterNetSvc;
+
+    /**
+     * Constructor.
+     *
+     * @param clusterNetSvc Cluster network service.
+     */
+    public Loza(ClusterService clusterNetSvc) {
+        this.clusterNetSvc = clusterNetSvc;
+    }
+}
diff --git a/modules/rest/pom.xml b/modules/rest/pom.xml
index 45c6b5d..ad4a082 100644
--- a/modules/rest/pom.xml
+++ b/modules/rest/pom.xml
@@ -42,6 +42,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
         </dependency>
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java b/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
index 867bbac..91cce7f 100644
--- a/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
@@ -33,9 +33,9 @@ import java.net.BindException;
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 import org.apache.ignite.configuration.ConfigurationRegistry;
+import org.apache.ignite.configuration.schemas.rest.RestConfiguration;
+import org.apache.ignite.configuration.schemas.rest.RestView;
 import org.apache.ignite.configuration.validation.ConfigurationValidationException;
-import org.apache.ignite.rest.configuration.RestConfiguration;
-import org.apache.ignite.rest.configuration.RestView;
 import org.apache.ignite.rest.netty.RestApiInitializer;
 import org.apache.ignite.rest.presentation.ConfigurationPresentation;
 import org.apache.ignite.rest.presentation.json.JsonPresentation;
@@ -81,7 +81,6 @@ public class RestModule {
      */
     public void prepareStart(ConfigurationRegistry sysCfg) {
         sysConf = sysCfg;
-        sysCfg.registerRootKey(RestConfiguration.KEY);
 
         presentation = new JsonPresentation(sysCfg);
     }
diff --git a/modules/rest/src/test/java/org/apache/ignite/rest/presentation/json/JsonConverterTest.java b/modules/rest/src/test/java/org/apache/ignite/rest/presentation/json/JsonConverterTest.java
index 7a60a5a..23f6bbf 100644
--- a/modules/rest/src/test/java/org/apache/ignite/rest/presentation/json/JsonConverterTest.java
+++ b/modules/rest/src/test/java/org/apache/ignite/rest/presentation/json/JsonConverterTest.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.rest.presentation.json;
 
 import com.google.gson.JsonNull;
+
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import org.apache.ignite.configuration.ConfigurationRegistry;
@@ -105,7 +107,7 @@ public class JsonConverterTest {
     }
 
     /** */
-    private final ConfigurationRegistry registry = new ConfigurationRegistry();
+    private ConfigurationRegistry registry;
 
     /** */
     private JsonRootConfiguration configuration;
@@ -113,9 +115,11 @@ public class JsonConverterTest {
     /** */
     @BeforeEach
     public void before() {
-        registry.registerRootKey(JsonRootConfiguration.KEY);
-
-        registry.registerStorage(new TestConfigurationStorage());
+        registry = new ConfigurationRegistry(
+            Collections.singletonList(JsonRootConfiguration.KEY),
+            Collections.emptyMap(),
+            Collections.singletonList(new TestConfigurationStorage())
+        );
 
         configuration = registry.getConfiguration(JsonRootConfiguration.KEY);
     }
diff --git a/modules/runner/pom.xml b/modules/runner/pom.xml
index d8c680a..cfb8626 100644
--- a/modules/runner/pom.xml
+++ b/modules/runner/pom.xml
@@ -43,28 +43,77 @@
 
         <dependency>
             <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-configuration-annotation-processor</artifactId>
+            <artifactId>ignite-rest</artifactId>
             <version>${project.version}</version>
             <scope>compile</scope>
         </dependency>
 
         <dependency>
             <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-rest</artifactId>
+            <artifactId>ignite-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-vault</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-network</artifactId>
             <version>${project.version}</version>
-            <scope>compile</scope>
         </dependency>
 
-        <!-- 3rd party dependencies. -->
         <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-raft</artifactId>
+            <version>${project.version}</version>
         </dependency>
 
         <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-metastorage</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-baseline</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-affinity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-table</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- 3rd party dependencies. -->
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-simple</artifactId>
         </dependency>
+
+        <!-- Test dependencies. -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java
new file mode 100644
index 0000000..12f4f4a
--- /dev/null
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.runner.app;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.app.Ignite;
+import org.apache.ignite.app.IgnitionManager;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Ignition interface tests.
+ */
+class IgnitionTest {
+
+    /** Nodes bootstrap configuration. */
+    private final String[] nodesBootstrapCfg =
+        {
+            "{\n" +
+                "  \"network\": {\n" +
+                "    \"port\":3344,\n" +
+                "    \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
+                "  }\n" +
+                "}",
+
+            "{\n" +
+                "  \"network\": {\n" +
+                "    \"port\":3345,\n" +
+                "    \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
+                "  }\n" +
+                "}",
+
+            "{\n" +
+                "  \"network\": {\n" +
+                "    \"port\":3346,\n" +
+                "    \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
+                "  }\n" +
+                "}",
+        };
+
+    /**
+     * Check that Ignition.start() with bootstrap configuration returns Ignite instance.
+     */
+    @Test
+    void testNodesStartWithBootstrapConfiguration() {
+        List<Ignite> startedNodes = new ArrayList<>();
+
+        for (String nodeBootstrapCfg : nodesBootstrapCfg)
+            startedNodes.add(IgnitionManager.start(nodeBootstrapCfg));
+
+        Assertions.assertEquals(3, startedNodes.size());
+
+        startedNodes.forEach(Assertions::assertNotNull);
+    }
+
+    /**
+     * Check that Ignition.start() with bootstrap configuration returns Ignite instance.
+     */
+    @Test
+    void testNodeStartWithoutBootstrapConfiguartion() {
+        Ignite ignite = IgnitionManager.start(null);
+
+        Assertions.assertNotNull(ignite);
+    }
+}
diff --git a/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java b/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
index d741fb7..61c5f9c 100644
--- a/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
+++ b/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
@@ -17,120 +17,9 @@
 
 package org.apache.ignite.app;
 
-import io.netty.channel.ChannelFuture;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-import org.apache.ignite.configuration.ConfigurationModule;
-import org.apache.ignite.rest.RestModule;
-import org.apache.ignite.utils.IgniteProperties;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * Sample application integrating new configuration module and providing standard REST API to access and modify it.
  */
 public class IgniteRunner {
-    /** */
-    private static final String[] BANNER = new String[] {
-        "",
-        "           #              ___                         __",
-        "         ###             /   |   ____   ____ _ _____ / /_   ___",
-        "     #  #####           / /| |  / __ \\ / __ `// ___// __ \\ / _ \\",
-        "   ###  ######         / ___ | / /_/ // /_/ // /__ / / / // ___/",
-        "  #####  #######      /_/  |_|/ .___/ \\__,_/ \\___//_/ /_/ \\___/",
-        "  #######  ######            /_/",
-        "    ########  ####        ____               _  __           _____",
-        "   #  ########  ##       /  _/____ _ ____   (_)/ /_ ___     |__  /",
-        "  ####  #######  #       / / / __ `// __ \\ / // __// _ \\     /_ <",
-        "   #####  #####        _/ / / /_/ // / / // // /_ / ___/   ___/ /",
-        "     ####  ##         /___/ \\__, //_/ /_//_/ \\__/ \\___/   /____/",
-        "       ##                  /____/\n"
-    };
-
-    /** */
-    private static final String CONF_PARAM_NAME = "--config";
-
-    /** */
-    private static final String DFLT_CONF_FILE_NAME = "bootstrap-config.json";
-
-    /** */
-    private static final String VER_KEY = "version";
-
-    /** */
-    private static final Logger log = LoggerFactory.getLogger(IgniteRunner.class);
-
-    /**
-     * It is possible to start application with a custom configuration in form of json file other than that in resources.
-     *
-     * To make application pick up custom configuration file its full path should be passed to arguments after key "--config".
-     *
-     * @param args Empty or providing path to custom configuration file after marker parameter "--config".
-     */
-    public static void main(String[] args) throws IOException, InterruptedException {
-        ackBanner();
-
-        ConfigurationModule confModule = new ConfigurationModule();
-
-        RestModule restModule = new RestModule(log);
-
-        BufferedReader confReader = null;
-
-        try {
-            if (args != null) {
-                for (int i = 0; i < args.length; i++) {
-                    if (CONF_PARAM_NAME.equals(args[i]) && i + 1 < args.length) {
-                        confReader = new BufferedReader(new FileReader(args[i + 1]));
-
-                        break;
-                    }
-                }
-            }
-
-            if (confReader == null) {
-                confReader = new BufferedReader(new InputStreamReader(
-                    IgniteRunner.class.getClassLoader().getResourceAsStream(DFLT_CONF_FILE_NAME)));
-            }
-
-            StringBuilder bldr = new StringBuilder();
-
-            String str;
-
-            while ((str = confReader.readLine()) != null)
-                bldr.append(str);
-
-            restModule.prepareStart(confModule.configurationRegistry());
-
-            confModule.bootstrap(bldr.toString());
-        }
-        finally {
-            if (confReader != null)
-                confReader.close();
-        }
-
-        ChannelFuture restChFut = restModule.start();
-
-        ackSuccessStart();
-
-        restChFut.sync();
-    }
-
-    /** */
-    private static void ackSuccessStart() {
-        log.info("Apache Ignite started successfully!");
-    }
-
-    /** */
-    private static void ackBanner() {
-        String ver = IgniteProperties.get(VER_KEY);
-
-        String banner = Arrays
-            .stream(BANNER)
-            .collect(Collectors.joining("\n"));
-
-        log.info(banner + '\n' + " ".repeat(22) + "Apache Ignite ver. " + ver + '\n');
-    }
+    // TODO: IGNITE-14413 Start of Ignite node should be supported by ignite-ctl tool
 }
diff --git a/modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java b/modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
deleted file mode 100644
index e738974..0000000
--- a/modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.configuration;
-
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import java.util.concurrent.ExecutionException;
-import org.apache.ignite.configuration.extended.LocalConfiguration;
-import org.apache.ignite.rest.configuration.InMemoryConfigurationStorage;
-import org.apache.ignite.rest.presentation.json.JsonConverter;
-
-/**
- * Module is responsible for preparing configuration when module is started.
- *
- * Preparing configuration includes reading it from configuration file, parsing it and initializing
- * {@link ConfigurationRegistry} object.
- */
-@SuppressWarnings("PMD.UnusedPrivateField")
-public class ConfigurationModule {
-    /** */
-    private LocalConfiguration localConfigurator;
-
-    /** */
-    private final ConfigurationRegistry confRegistry = new ConfigurationRegistry();
-
-    /**
-     * @param jsonStr
-     */
-    public void bootstrap(String jsonStr) throws InterruptedException {
-        confRegistry.registerRootKey(LocalConfiguration.KEY);
-
-        InMemoryConfigurationStorage storage = new InMemoryConfigurationStorage();
-
-        confRegistry.registerStorage(storage);
-
-        JsonObject jsonCfg = JsonParser.parseString(jsonStr).getAsJsonObject();
-
-        try {
-            confRegistry.change(JsonConverter.jsonSource(jsonCfg), storage).get();
-        }
-        catch (ExecutionException e) {
-            throw new RuntimeException(e.getCause());
-        }
-
-        localConfigurator = confRegistry.getConfiguration(LocalConfiguration.KEY);
-    }
-
-    /** */
-    public ConfigurationRegistry configurationRegistry() {
-        return confRegistry;
-    }
-}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
similarity index 54%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 9cc76fb..c60026c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -15,7 +15,32 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.internal.app;
+
+import org.apache.ignite.app.Ignite;
+import org.apache.ignite.table.manager.TableManager;
+
 /**
- * Common utility classes for strings.
+ * Ignite internal implementation.
  */
-package org.apache.ignite.internal.tostring;
+public class IgniteImpl implements Ignite {
+    /** Distributed table manager. */
+    private final TableManager distributedTblMgr;
+
+    /**
+     * @param TblMgr Table manager.
+     */
+    IgniteImpl(TableManager TblMgr) {
+        this.distributedTblMgr = TblMgr;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableManager tableManager() {
+        return distributedTblMgr;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() {
+        // TODO IGNITE-14581 Implement IgniteImpl close method.
+    }
+}
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java
new file mode 100644
index 0000000..b6b2622
--- /dev/null
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.app;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.ignite.app.Ignite;
+import org.apache.ignite.app.Ignition;
+import org.apache.ignite.internal.baseline.BaselineManager;
+import org.apache.ignite.configuration.RootKey;
+import org.apache.ignite.configuration.internal.ConfigurationManager;
+import org.apache.ignite.configuration.storage.ConfigurationType;
+import org.apache.ignite.configuration.schemas.network.NetworkConfiguration;
+import org.apache.ignite.configuration.schemas.network.NetworkView;
+import org.apache.ignite.internal.affinity.AffinityManager;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.internal.table.distributed.TableManagerImpl;
+import org.apache.ignite.internal.vault.VaultManager;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.network.ClusterLocalConfiguration;
+import org.apache.ignite.network.ClusterService;
+import org.apache.ignite.network.message.MessageSerializationRegistry;
+import org.apache.ignite.network.scalecube.ScaleCubeClusterServiceFactory;
+import org.apache.ignite.internal.raft.Loza;
+import org.apache.ignite.internal.storage.DistributedConfigurationStorage;
+import org.apache.ignite.internal.storage.LocalConfigurationStorage;
+import org.apache.ignite.internal.schema.SchemaManager;
+import org.apache.ignite.table.manager.TableManager;
+import org.apache.ignite.utils.IgniteProperties;
+
+/**
+ * Implementation of an entry point for handling grid lifecycle.
+ */
+public class IgnitionImpl implements Ignition {
+    /** */
+    private static final String[] BANNER = new String[] {
+        "",
+        "           #              ___                         __",
+        "         ###             /   |   ____   ____ _ _____ / /_   ___",
+        "     #  #####           / /| |  / __ \\ / __ `// ___// __ \\ / _ \\",
+        "   ###  ######         / ___ | / /_/ // /_/ // /__ / / / // ___/",
+        "  #####  #######      /_/  |_|/ .___/ \\__,_/ \\___//_/ /_/ \\___/",
+        "  #######  ######            /_/",
+        "    ########  ####        ____               _  __           _____",
+        "   #  ########  ##       /  _/____ _ ____   (_)/ /_ ___     |__  /",
+        "  ####  #######  #       / / / __ `// __ \\ / // __// _ \\     /_ <",
+        "   #####  #####        _/ / / /_/ // / / // // /_ / ___/   ___/ /",
+        "     ####  ##         /___/ \\__, //_/ /_//_/ \\__/ \\___/   /____/",
+        "       ##                  /____/\n"
+    };
+
+    /** */
+    private static final String VER_KEY = "version";
+
+    /** */
+    private static final IgniteLogger LOG = IgniteLogger.forClass(IgnitionImpl.class);
+
+    /** {@inheritDoc} */
+    @Override public synchronized Ignite start(String jsonStrBootstrapCfg) {
+        ackBanner();
+
+        // Vault Component startup.
+        VaultManager vaultMgr = new VaultManager();
+
+        boolean cfgBootstrappedFromPds = vaultMgr.bootstrapped();
+
+        List<RootKey<?, ?>> rootKeys = new ArrayList<>(Collections.singletonList(NetworkConfiguration.KEY));
+
+        List<ConfigurationStorage> configurationStorages =
+            new ArrayList<>(Collections.singletonList(new LocalConfigurationStorage(vaultMgr)));
+
+        // Bootstrap local configuration manager.
+        ConfigurationManager locConfigurationMgr = new ConfigurationManager(rootKeys, configurationStorages);
+
+        if (!cfgBootstrappedFromPds && jsonStrBootstrapCfg != null)
+            try {
+                locConfigurationMgr.bootstrap(jsonStrBootstrapCfg);
+            }
+            catch (Exception e) {
+                LOG.warn("Unable to parse user specific configuration, default configuration will be used", e);
+            }
+        else if (jsonStrBootstrapCfg != null)
+            LOG.warn("User specific configuration will be ignored, cause vault was bootstrapped with pds configuration");
+        else
+            locConfigurationMgr.configurationRegistry().startStorageConfigurations(ConfigurationType.LOCAL);
+
+        NetworkView netConfigurationView =
+            locConfigurationMgr.configurationRegistry().getConfiguration(NetworkConfiguration.KEY).value();
+
+        var serializationRegistry = new MessageSerializationRegistry();
+
+        // Network startup.
+        ClusterService clusterNetSvc = new ScaleCubeClusterServiceFactory().createClusterService(
+            new ClusterLocalConfiguration(
+                "Node" + netConfigurationView.port(),
+                netConfigurationView.port(),
+                Arrays.asList(netConfigurationView.netClusterNodes()),
+                serializationRegistry
+            )
+        );
+
+        // Raft Component startup.
+        Loza raftMgr = new Loza(clusterNetSvc);
+
+        // MetaStorage Component startup.
+        MetaStorageManager metaStorageMgr = new MetaStorageManager(
+            vaultMgr,
+            clusterNetSvc,
+            raftMgr
+        );
+
+        // TODO IGNITE-14578 Bootstrap configuration manager with distributed configuration.
+        configurationStorages.add(new DistributedConfigurationStorage(metaStorageMgr));
+
+        // Start configuration manager.
+        ConfigurationManager configurationMgr = new ConfigurationManager(rootKeys, configurationStorages);
+
+        // Baseline manager startup.
+        BaselineManager baselineMgr = new BaselineManager(configurationMgr, metaStorageMgr, clusterNetSvc);
+
+        // Affinity manager startup.
+        new AffinityManager(configurationMgr, metaStorageMgr, baselineMgr);
+
+        SchemaManager schemaMgr = new SchemaManager(configurationMgr);
+
+        // Distributed table manager startup.
+        TableManager distributedTblMgr = new TableManagerImpl(
+            configurationMgr,
+            clusterNetSvc,
+            metaStorageMgr,
+            schemaMgr,
+            raftMgr
+        );
+
+        // TODO IGNITE-14579 Start rest manager.
+
+        // Deploy all resisted watches cause all components are ready and have registered their listeners.
+        metaStorageMgr.deployWatches();
+
+        clusterNetSvc.start();
+
+        ackSuccessStart();
+
+        return new IgniteImpl(distributedTblMgr);
+    }
+
+    /** */
+    private static void ackSuccessStart() {
+        LOG.info("Apache Ignite started successfully!");
+    }
+
+    /** */
+    private static void ackBanner() {
+        String ver = IgniteProperties.get(VER_KEY);
+
+        String banner = Arrays
+            .stream(BANNER)
+            .collect(Collectors.joining("\n"));
+
+        LOG.info(banner + '\n' + " ".repeat(22) + "Apache Ignite ver. " + ver + '\n');
+    }
+}
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/storage/DistributedConfigurationStorage.java b/modules/runner/src/main/java/org/apache/ignite/internal/storage/DistributedConfigurationStorage.java
new file mode 100644
index 0000000..9d53731
--- /dev/null
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/storage/DistributedConfigurationStorage.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.configuration.storage.ConfigurationStorageListener;
+import org.apache.ignite.configuration.storage.ConfigurationType;
+import org.apache.ignite.configuration.storage.Data;
+import org.apache.ignite.configuration.storage.StorageException;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+
+/**
+ * Distributed configuration storage.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class DistributedConfigurationStorage implements ConfigurationStorage {
+    /** MetaStorage manager */
+    private final MetaStorageManager metaStorageMgr;
+
+    /**
+     * Constructor.
+     *
+     * @param metaStorageMgr MetaStorage Manager.
+     */
+    public DistributedConfigurationStorage(MetaStorageManager metaStorageMgr) {
+        this.metaStorageMgr = metaStorageMgr;
+    }
+
+    /** Map to store values. */
+    private Map<String, Serializable> map = new ConcurrentHashMap<>();
+
+    /** Change listeners. */
+    private List<ConfigurationStorageListener> listeners = new CopyOnWriteArrayList<>();
+
+    /** Storage version. */
+    private AtomicLong version = new AtomicLong(0);
+
+    /** {@inheritDoc} */
+    @Override public synchronized Data readAll() throws StorageException {
+        return new Data(new HashMap<>(map), version.get(), 0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized CompletableFuture<Boolean> write(Map<String, Serializable> newValues, long version) {
+        if (version != this.version.get())
+            return CompletableFuture.completedFuture(false);
+
+        for (Map.Entry<String, Serializable> entry : newValues.entrySet()) {
+            if (entry.getValue() != null)
+                map.put(entry.getKey(), entry.getValue());
+            else
+                map.remove(entry.getKey());
+        }
+
+        this.version.incrementAndGet();
+
+        listeners.forEach(listener -> listener.onEntriesChanged(new Data(newValues, this.version.get(), 0)));
+
+        return CompletableFuture.completedFuture(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addListener(ConfigurationStorageListener listener) {
+        listeners.add(listener);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeListener(ConfigurationStorageListener listener) {
+        listeners.remove(listener);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void notifyApplied(long storageRevision) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public ConfigurationType type() {
+        return ConfigurationType.DISTRIBUTED;
+    }
+}
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/storage/LocalConfigurationStorage.java b/modules/runner/src/main/java/org/apache/ignite/internal/storage/LocalConfigurationStorage.java
new file mode 100644
index 0000000..eb99781
--- /dev/null
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/storage/LocalConfigurationStorage.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.configuration.storage.ConfigurationStorageListener;
+import org.apache.ignite.configuration.storage.ConfigurationType;
+import org.apache.ignite.configuration.storage.Data;
+import org.apache.ignite.configuration.storage.StorageException;
+import org.apache.ignite.internal.vault.VaultManager;
+
+/**
+ * Local configuration storage.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class LocalConfigurationStorage implements ConfigurationStorage {
+    /** Vault manager. */
+    private final VaultManager vaultMgr;
+
+    /**
+     * Constructor.
+     *
+     * @param vaultMgr Vault manager.
+     */
+    public LocalConfigurationStorage(VaultManager vaultMgr) {
+        this.vaultMgr = vaultMgr;
+    }
+
+    /** Map to store values. */
+    private Map<String, Serializable> map = new ConcurrentHashMap<>();
+
+    /** Change listeners. */
+    private List<ConfigurationStorageListener> listeners = new CopyOnWriteArrayList<>();
+
+    /** Storage version. */
+    private AtomicLong version = new AtomicLong(0);
+
+    /** {@inheritDoc} */
+    @Override public synchronized Data readAll() throws StorageException {
+        return new Data(new HashMap<>(map), version.get(), 0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized CompletableFuture<Boolean> write(Map<String, Serializable> newValues, long version) {
+        if (version != this.version.get())
+            return CompletableFuture.completedFuture(false);
+
+        for (Map.Entry<String, Serializable> entry : newValues.entrySet()) {
+            if (entry.getValue() != null)
+                map.put(entry.getKey(), entry.getValue());
+            else
+                map.remove(entry.getKey());
+        }
+
+        this.version.incrementAndGet();
+
+        listeners.forEach(listener -> listener.onEntriesChanged(new Data(newValues, this.version.get(), 0)));
+
+        return CompletableFuture.completedFuture(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addListener(ConfigurationStorageListener listener) {
+        listeners.add(listener);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeListener(ConfigurationStorageListener listener) {
+        listeners.remove(listener);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void notifyApplied(long storageRevision) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public ConfigurationType type() {
+        return ConfigurationType.LOCAL;
+    }
+}
diff --git a/modules/runner/src/main/resources/META-INF/services/org.apache.ignite.app.Ignition b/modules/runner/src/main/resources/META-INF/services/org.apache.ignite.app.Ignition
new file mode 100644
index 0000000..d54df30
--- /dev/null
+++ b/modules/runner/src/main/resources/META-INF/services/org.apache.ignite.app.Ignition
@@ -0,0 +1 @@
+org.apache.ignite.internal.app.IgnitionImpl
\ No newline at end of file
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
similarity index 54%
copy from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
copy to modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
index 9cc76fb..f5831c4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
@@ -15,7 +15,24 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.internal.schema;
+
+import org.apache.ignite.configuration.internal.ConfigurationManager;
+
 /**
- * Common utility classes for strings.
+ * Schema Manager.
  */
-package org.apache.ignite.internal.tostring;
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class SchemaManager {
+    /** Configuration manager in order to handle and listen schema specific configuration.*/
+    private final ConfigurationManager configurationMgr;
+
+    /**
+     * The constructor.
+     *
+     * @param configurationMgr Configuration manager.
+     */
+    public SchemaManager(ConfigurationManager configurationMgr) {
+        this.configurationMgr = configurationMgr;
+    }
+}
diff --git a/modules/table/pom.xml b/modules/table/pom.xml
index 1f58901..553d2b1 100644
--- a/modules/table/pom.xml
+++ b/modules/table/pom.xml
@@ -54,6 +54,37 @@
             <version>${project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-metastorage</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-baseline</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-network</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-schema</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-raft</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.junit.jupiter</groupId>
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManagerImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManagerImpl.java
new file mode 100644
index 0000000..5932ea1
--- /dev/null
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManagerImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table.distributed;
+
+import org.apache.ignite.configuration.internal.ConfigurationManager;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+import org.apache.ignite.network.ClusterService;
+import org.apache.ignite.internal.schema.SchemaManager;
+import org.apache.ignite.internal.raft.Loza;
+import org.apache.ignite.table.manager.TableManager;
+
+/**
+ * Table Manager that handles inner table lifecycle and provide corresponding API methods.
+ */
+// TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
+@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class TableManagerImpl implements TableManager {
+    /** Meta storage service. */
+    private final MetaStorageManager metaStorageMgr;
+
+    /** Network cluster. */
+    private final ClusterService clusterNetSvc;
+
+    /** Schema manager. */
+    private final SchemaManager schemaMgr;
+
+    /** Configuration manager. */
+    private final ConfigurationManager configurationMgr;
+
+    /** Raft manager. */
+    private final Loza raftMgr;
+
+    /**
+     * The constructor.
+     *
+     * @param configurationMgr Configuration table.
+     * @param clusterNetSvc Cluster network service.
+     * @param metaStorageMgr MetaStorage manager.
+     * @param schemaMgr Schema manager.
+     * @param raftMgr Raft manager.
+     */
+    public TableManagerImpl(
+        ConfigurationManager configurationMgr,
+        ClusterService clusterNetSvc,
+        MetaStorageManager metaStorageMgr,
+        SchemaManager schemaMgr,
+        Loza raftMgr
+    ) {
+        this.configurationMgr = configurationMgr;
+        this.clusterNetSvc = clusterNetSvc;
+        this.metaStorageMgr = metaStorageMgr;
+        this.schemaMgr = schemaMgr;
+        this.raftMgr = raftMgr;
+    }
+}
diff --git a/modules/api/pom.xml b/modules/vault/pom.xml
similarity index 78%
copy from modules/api/pom.xml
copy to modules/vault/pom.xml
index 2ca3c60..48ab776 100644
--- a/modules/api/pom.xml
+++ b/modules/vault/pom.xml
@@ -17,8 +17,10 @@
   limitations under the License.
 -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
@@ -29,13 +31,6 @@
         <relativePath>../../parent/pom.xml</relativePath>
     </parent>
 
-    <artifactId>ignite-api</artifactId>
+    <artifactId>ignite-vault</artifactId>
     <version>3.0.0-SNAPSHOT</version>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jetbrains</groupId>
-            <artifactId>annotations</artifactId>
-        </dependency>
-    </dependencies>
 </project>
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java b/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
similarity index 61%
rename from modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
rename to modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
index 9cc76fb..f3d7f48 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/tostring/package-info.java
+++ b/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
@@ -15,7 +15,20 @@
  * limitations under the License.
  */
 
+package org.apache.ignite.internal.vault;
+
 /**
- * Common utility classes for strings.
+ * VaultManager is responsible for handling VaultService lifecycle and providing interface for managing local keys.
  */
-package org.apache.ignite.internal.tostring;
+public class VaultManager {
+
+    /**
+     * @return {@code true} if VaultService beneath given VaultManager was bootstrapped with data
+     * either from PDS or from user initial bootstrap configuration.
+     */
+    public boolean bootstrapped() {
+        return false;
+    }
+
+    // TODO: IGNITE-14405 Local persistent key-value storage (Vault).
+}
diff --git a/parent/pom.xml b/parent/pom.xml
index d0cd6ea..aa2f3d5 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -634,6 +634,7 @@
                         <exclude>**/*.iml</exclude> <!-- IntelliJ IDEA project files -->
                         <exclude>modules/bytecode/src/main/java/com/facebook/presto/bytecode/ClassInfo.java</exclude> <!-- MIT license. -->
                         <exclude>modules/bytecode/src/main/java/com/facebook/presto/bytecode/ClassInfoLoader.java</exclude> <!-- MIT license. -->
+                        <exclude>**/META-INF/services/**</exclude> <!-- Interface mappings: cannot be changed -->
                     </excludes>
                 </configuration>
             </plugin>
diff --git a/pom.xml b/pom.xml
index 9612a10..4aee2ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,7 @@
         <module>modules/configuration</module>
         <module>modules/configuration-annotation-processor</module>
         <module>modules/core</module>
+        <module>modules/metastorage</module>
         <module>modules/metastorage-client</module>
         <module>modules/metastorage-common</module>
         <module>modules/network</module>
@@ -50,6 +51,9 @@
         <module>modules/runner</module>
         <module>modules/schema</module>
         <module>modules/table</module>
+        <module>modules/vault</module>
+        <module>modules/baseline</module>
+        <module>modules/affinity</module>
     </modules>
 
     <build>