diff --git a/docs/design/assetgeneration.md b/docs/design/assetgeneration.md deleted file mode 100644 index aad6ce5934b..00000000000 --- a/docs/design/assetgeneration.md +++ /dev/null @@ -1,150 +0,0 @@ -# Asset Generation - -The installer internally uses a directed acyclic graph to represent all of the assets it creates as well as their dependencies. This process looks very similar to many build systems (e.g. Bazel, Make). - -## Overview - -The installer generates assets based on the [dependency graph](#dependency-graph). Each asset seperately defines how it can be generated as well as its dependencies. Targets represent a set of assets that should be generated and written to disk for the user's consumption. When a user invokes the installer for a particular target, each of the assets in the set is generated as well as any dependencies. This eventually results in the user being prompted for any missing information (e.g. administrator password, target platform). - -The installer is also able to read assets from disk if they have been provided by the user. In the event that an asset exists on disk, the install won't generate the asset, but will instead consume the asset from disk (removing the file). This allows the installer to be run multiple times, using the assets generated by the previous invocation. It also allows a user to make modifications to the generated assets before continuing to the next target. - -Each asset is individually responsible for declaring its dependencies. Each asset is also responsible resolving conflicts when combining its input from disk and its state from a previous run. The installer ensures all the dependencies for an asset is generated and provides the asset with latest state to generate its own output. - -## Asset - -An asset is the generic representation of work-item for installer that needs to be generated. Each asset defines all the other assets that are required for it to generate itself as dependencies. - -The asset would usually follow these steps to generate its output: - -1. Fetch its parent assets. - -2. Generate the assets either by: - * Using the parent assets - * Loading from on-disk assets - * Loading from state file - -3. If any of the parent assets are **dirty** (currently we think all on-disk assets are **dirty**), then use the parent assets to generate and return **dirty**. - -4. If none of the parent assets are **dirty**, but the asset itself is on disk, then use the on-disk asset and return **dirty**. - -5. If none of the parent assets or this asset is **dirty**, but the asset is found in the state file, then use the asset from state file and return **NOT dirty**. - -6. If none of the parent assets are **dirty**, this asset is not **dirty**, and this asset is not found in the state file, then generate the asset using its parent assets and return **NOT dirty**. - -An example of the Asset: - -```go -type Asset interface { - Dependencies() []Assets - Generate(Parents) error - Name() string -} -``` - -## Writable Asset - -A writable asset is an asset that generates files to write to disk. These files could be for the user to consume as output from installer targets, such as install-config.yml from the InstallConfig asset. Or these files could be used internally by the installer, such as the cert/key files generated by TLS assets. -A writable asset can also be loaded from disk to construct. - -```go -type WritableAsset interface{ - Asset - Files() []File - Load(FileFetcher) (found bool, err error) -} - -type File struct { - Filename string - Data []byte -} - -// FileFetcher is passed to every Loadable asset when implementing -// the Load() function. The FileFetcher enables the Loadable asset -// to read specific file(s) from disk. -type FileFetcher interface { - // FetchByName returns the file with the given name. - FetchByName(string) (*File, error) - // FetchByPattern returns the files whose name match the given glob. - FetchByPattern(*regexp.Regexp) ([]*File, error) -} -``` -After being loaded and consumed by a children asset, the existing on-disk asset will be purged. -E.g. - -```shell -$ openshift-install create install-config -# Generate install-config.yml - -$ openshift-install create manifests -# Generate manifests/ and tectonic/ dir, also remove install-config.yml -``` - -## Target generation - -The installer uses depth-first traversal on the dependency graph, starting at the target nodes, generating all the dependencies of the asset before generating the asset itself. After all the target assets have been generated, the installer outputs the contents of the components of the targets to disk. - -### Dirty detection - -An asset generation reports **DIRTY** when it detects that the components have been modified from previous run. For now the asset is considered dirty when it's on-disk. - -### Example - -```dot -digraph G { - size ="4,4"; - A1; - A2; - A3; - A4; - A5; - A6; - A5 -> {A3, A4}; - A3 -> {A1, A2}; - A6 -> {A1, A2}; -} -``` - -When generating targets **A5 and A6** - -``` -load state; - -A5: (A3, A4) - A3: (A1, A2) - A1: - A1.generate(state) - update state - A2: - A2.generate(state) - update state - set dirty if one of A1/A2 is dirty - A3.generate(state): pass dirty if set - update state - A4: - A4.generate(state) - update state - set dirty if one of A3/A4 is dirty - A5.generate(state): pass dirty if set - update state -A6: (A1, A2) - A1: - reuse - A2: - reuse - set dirty if one of A1/A2 is dirty - A6.generate(state): pass dirty if set - update state -Flush A5 and A6 to disk -``` - -## Dependency graph - -The following graph shows the relationship between the various assets that the installer generates: - -![Image depicting the resource dependency graph](resource_dep.svg) - -This graph is generated from the using the following command: - -```sh -bin/openshift-install graph | dot -Tsvg >docs/design/resource_dep.svg -``` diff --git a/docs/design/resource_dep.svg b/docs/user/assets.svg similarity index 100% rename from docs/design/resource_dep.svg rename to docs/user/assets.svg diff --git a/docs/user/overview.md b/docs/user/overview.md index da51eb05bc5..adde4e459ba 100644 --- a/docs/user/overview.md +++ b/docs/user/overview.md @@ -4,7 +4,57 @@ The OpenShift Installer is designed to help users, ranging from novices to exper In [supported environments](#supported-environments), the installer is also capable of provisioning the underlying infrastructure for the cluster. It is recommended that most users make use of this functionality in order to avoid having to provision their own infrastructure. In unsupported environments or scenarios in which installer-created infrastructure would be incompatible, the installer can stop short of creating the infrastructure, and allow the user to provision their own infrastructure using the cluster assets generated by the installer. -## Cluster Installation Process +## Lifecycle + +### Asset Generation + +The first installation phase is completely local, as the installer generates the assets that will be used to create the cluster resources. +The installer maintains an asset graph tracking dependency relations between assets. + +![Asset dependencies](assets.svg) + +This graph is generated with: + +```sh +openshift-install graph | dot -Tsvg >docs/user/assets.svg +``` + +This is similar to other tools which operate on a dependency graph (e.g. `make` and `systemd`). +The root target is `cluster`, and once that target is built, there is enough information to move on to [installation](#installation). + +Running: + +```sh +openshift-install --dir example create assets +``` + +will render the asset graph into the `example` directory. +The installer will pick reasonable defaults where possible, and prompt the user for assets where we cannot find a reasonable default for all users. +To avoid being prompted, you can pass your choices into the installer using [environment variables](environment-variables.md). + +Each asset is represented by two files, one in the asset directory itself, and another in its `.state` subdirectory. +The entry in the `.state` subdirectory holds the rendered JSON `Asset` structure, containing the asset's raw data along with associated metadata (parent references, etc.). +The entry in the asset directory holds the asset's raw data without the associated metadata. + +The installer uses the JSON state files to preserve asset information between invocations, but editing the JSON payload is an awkward way to make manual adjustments. +The raw data files are provided as a more convenient avenue for user adjustments. + +To adjust a particular asset, you can edit the raw data file and rerun `openshift-install ... create assets`. +For example: + +```sh +openshift-install --dir example create assets +sed -i 's|^\(OPENSHIFT_HYPERSHIFT_IMAGE\)=.*|\1=quay.io/your/hypershift:123|' example/bootkube.sh +openshift-install --dir example create assets +``` + +will rebuild the asset graph using your custom HyperShift image in `bootkube.sh`. + +You can continue to edit and run `openshift-install ... create assets` as many times as you like. +To return to the installer's built-in logic for an asset, remove its `.state/{slugged-asset-name}` file (it doesn't matter if you also remove the associated raw data file or not). +When you are satisfied with the asset store, move on to installation. + +### Installation OpenShift is unique in that its management extends all the way down to the operating system itself. Every machine boots with a configuration which references resources hosted in the cluster its joining. This allows the cluster to manage itself as updates are applied. A downside to this approach, however, is that new clusters have no way of starting without external help - every machine in the to-be-created cluster is waiting on the to-be-created cluster. @@ -25,31 +75,19 @@ The result of this bootstrapping process is a fully running OpenShift cluster. T [ignition]: https://github.com/coreos/ignition/blob/master/doc/getting-started.md -## Key Concepts - -While striving to remain simple and easy to use, the installer allows many aspects of the clusters it creates to be customized. It is helpful to understand certain key concepts before attempting to customize the installation. - -### Targets - -The OpenShift Installer operates on the notion of creating and destroying targets. Similar to other tools which operate on a graph of dependencies (e.g. make, systemd), each target represents a subset of the dependencies in the graph. The main target in the installer creates a cluster, but the other targets allow the user to interrupt this process and consume or modify the intermediate artifacts (e.g. the Kubernetes manifests that will be installed into the cluster). Only the immediate dependencies of a target are written to disk by the installer, but the installer can be invoked [multiple times](#multiple-invocations). - -The following targets can be created by the installer: - -- `install-config` - The install config contains the main parameters for the installation process. This configuration provides the user with more options than the interactive prompts and comes pre-populated with default values. -- `manifests` - This target outputs all of the Kubernetes manifests that will be installed on the cluster. -- `ignition-configs` - These are the three Ignition Configs for the bootstrap, master, and worker machines. -- `cluster` - This target provisions the cluster by invoking a locally-installed Terraform. - -The following targets can be destroyed by the installer: +### Teardown -- `cluster` - This destroys the created cluster and its associated infrastructure. -- `bootstrap` - This destroys the bootstrap infrastructure. +You can manually remove the bootstrap infrastructure with: -### Multiple Invocations +```sh +openshift-install ... destroy bootstrap +``` -In order to allow users to customize their installation, the installer can be invoked multiple times. The state is stored in a hidden file in the target directory and contains all of the intermediate artifacts. This allows the installer to pause during the installation and wait for the user to modify intermediate artifacts. +And you can remove the entire cluster with: -For example, if changes to the install config were desired (e.g. the number of worker machines to create), the user would first invoke the installer with the `install-config` target: `openshift-install create install-config`. After prompting the user for the base parameters, the installer writes the install config into the target directory. The user can then make the desired modifications to the install config and invoke the installer with the `cluster` target: `openshift-install create cluster`. The installer will consume the install config from disk, removing it from the target directory, and proceed to create a cluster using the provided configuration. +```sh +openshift-install ... destroy cluster +``` ## Supported Environments