Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
drmorr0 committed Feb 1, 2024
1 parent 182520d commit 25884ac
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 241 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@ A collection of tools for simulating Kubernetes scheduling and autoscaling behav

This package provides the following components:

- `sk-cloudprov`: an [external gRPC-based cloud provider](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler/cloudprovider/externalgrpc)
for Cluster Autoscaler that can communicate with and scale the `sk-vnode` "node group".
- `skctl`: a CLI utility for interacting with various other SimKube components
- `sk-ctrl`: a Kubernetes Controller that watches for Simulation custom resources and runs a simulation based on the
provided trace file.
- `sk-driver`: the actual runner for a specific simulation, created as a Kubernetes Job by `sk-ctrl`
- `sk-tracer`: a watcher for Kubernetes pod creation and deletion events, saves these events in a replayable trace
format.
- `sk-vnode`: a [Virtual Kubelet](https://virtual-kubelet.io)-based "hollow node" that allows customization based off a
"skeleton" node file (see the example in `simkube/k8s/sk_vnode.py`).

### Architecture Diagram

Expand All @@ -38,11 +34,11 @@ This package provides the following components:

### Prerequisites

- Go >= 1.20
- Rust >= 1.71 (needed if you want to build outside of Docker)
- Docker
- kubectl >= 1.27
- Kubernetes >= 1.27
- [KWOK](https://kwok.sigs.k8s.io) >= 0.4.0
- [CertManager](https://cert-manager.io) for setting up mutating webhook certificates

### Optional Prerequisites
Expand All @@ -57,14 +53,20 @@ following additional dependencies:
Additionally, if you want to run SimKube on a local development cluster, [kind](https://kind.sigs.k8s.io) >= 0.19 is the
supported tooling for doing so.

If you want to test autoscaling, SimKube currently supports either the [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler)
or [Karpenter](https://karpenter.sh). You will need to install and configure these applications to use the
corresponding KWOK provider. For the Kubernetes Cluster Autoscaler, a KWOK [cloud provider](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler/cloudprovider/kwok)
is available, and for Karpenter, a basic [KWOK provider](https://github.com/kubernetes-sigs/karpenter/tree/main/kwok) is
used. Configuring these applications in your environment is beyond the scope of this documentation.

### Building

To build all SimKube artifacts for the first time run:

- `git submodule init && git submodule update`
- `make build` and `make skctl` from the root of this repository.
- `make build` from the root of this repository.

For all subsequent builds of SimKube artifacts, run only `make build` and `make skctl` from the root of this repository.
For all subsequent builds of SimKube artifacts, run only `make build` from the root of this repository.

### Docker images

Expand All @@ -75,7 +77,6 @@ To build and push Docker images for all the artifacts, run `DOCKER_REGISTRY=path
You will need a KUBECONFIG file with cluster admin permissions; `make run` will use 🔥Config to generate the Kubernetes
manifests and deploy all SimKube artifacts to the specified cluster.


### Cleaning up

All build artifacts are placed in the `.build/` directory. You can remove this directory or run `make clean` to clean
Expand Down
62 changes: 7 additions & 55 deletions docs/api_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ template: docs.html

## SimKube Custom Resource Definition changes

The Simulation CRD is auto-generated from the Golang struct in `./lib/go/api/v1/simulation_types.go` using the
[controller-gen](https://book.kubebuilder.io/reference/controller-gen.html) utility. The resulting CRDs are stored in
`./k8s/raw/`, and then Rust structs are generated from the resulting CRD using
[kopium](https://github.com/kube-rs/kopium). This _should_ all be done automagically by running `make crd`, but kopium
is listed as unstable, so check the diff output carefully.
The Simulation CRD is auto-generated from the Rust structs in `./src/api/v1/(simulations|simulation_roots).rs`
If these structs change, you will need to regenerate the CRD yaml by running `make crd`; the resulting CRDs are stored
in `./k8s/raw/`. A pre-commit check as well as a GitHub action will complain if you have not updated the CRD yaml
before committing.

## SimKube API changes

Expand All @@ -21,59 +20,12 @@ specification in `./api/v1/simkube.yml`. I haven't _yet_ figured out how to wir
from this file. This process is currently quite manual. The steps look something like the following:

1. `make api`
2. In `lib/go/api/v1/*.go`, replace all the k8s-generated types with the correct imports from the Kubernetes API (make
sure to do this not just in the model files but also in `utils.go`.
3. In `lib/go/api/v1/*.go`, make sure to update the package name from `openapi` to `v1`.
4. In `lib/go/api/v1/*.go`, annotate the generated objects with `//+kubebuilder:object:generate=false` to keep
`controller-gen` from trying to interpret these files as custom resource types.
5. In `lib/rust/api/v1/*.rs`, add `use super::*` to the top of each generated file
6. In `lib/rust/api/v1/*.rs`, replace all the k8s-generated types with the correct imports from `k8s-openapi`.
2. In `src/api/v1/*.rs`, add `use super::*` to the top of each generated file
3. In `src/api/v1/*.rs`, replace all the k8s-generated types with the correct imports from `k8s-openapi`.

Once you've made all of these changes, you will need to check the diff quite carefully to ensure that nothing is broken.

### Example modifications for generated Golang code

This generated output:

```go
package openapi

import (
"encoding/json"
)

// ExportFilters struct for ExportFilters
type ExportFilters struct {
ExcludedNamespaces []string `json:"excludedNamespaces"`
ExcludedLabels []ExportFiltersExcludedLabelsInner `json:"excludedLabels"`
ExcludeDaemonsets bool `json:"excludeDaemonsets"`
}

...
```

should be transformed into:

```go
package v1

import (
"encoding/json"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

//+kubebuilder:object:generate=false

// ExportFilters struct for ExportFilters
type ExportFilters struct {
ExcludedNamespaces []string `json:"excludedNamespaces"`
ExcludedLabels []metav1.LabelSelector `json:"excludedLabels"`
ExcludeDaemonsets bool `json:"excludeDaemonsets"`
}
```

### Example modifications for generated Rust code
### Example modifications for generated code

This generated output:

Expand Down
54 changes: 20 additions & 34 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ template: docs.html
In addition to the project prerequisites, you will need to have the following installed:

- [pre-commit](https://pre-commit.com)
- [golangci-lint](https://golangci-lint.run/)
- Nightly version of rustfmt

### Optional prerequisites

- [grcov](https://github.com/mozilla/grcov) (if you want to generate coverage reports locally)
- [controller-gen](https://book.kubebuilder.io/reference/controller-gen.html) (if you need to make changes to the
Simulation CRD)
- [kopium](https://github.com/kube-rs/kopium) (if you need to make changes to the Simulation CRD)
- [openapi-generator](https://openapi-generator.tech) (if you need to make changes to the SimKube API)
- [delve](https://github.com/go-delve/delve) (for debugging Golang code)
- [msgpack-tools](https://github.com/ludocode/msgpack-tools) (for inspecting the contents of exported trace files)
Expand All @@ -37,22 +33,18 @@ The SimKube repo is organized as follows:
/<root>
/api - OpenAPI v3 definitions for the SimKube API
/build - build scripts and helper functions (git submodule)
/cli - Golang code for the `skctl` CLI utility
/cloudprov - Golang code for the `sk-cloudprov` Cluster Autoscaler cloud provider
/cli - Rust code for the `skctl` CLI utility
/ctrl - Rust code for the `sk-ctrl` Kubernetes controller
/docs - Documentation
/driver - Rust code for the `sk-driver` Simulation runner
/images - Dockerfiles for all components
/k8s - 🔥Config Python scripts for Kubernetes manifest generation
/lib
/go - shared Golang code
/rust - shared Rust code
/src - shared library code
/tracer - Rust code for the `sk-tracer` Kubernetes object
/vnode - Golang code for the Virtual-Kubelet-based virtual node
```

In general, code that is specific to a single artifact should go in the subdirectory for that artifact, but code that
needs to be shared between multiple artifacts should go in either `lib/go` or `lib/rust`.
needs to be shared between multiple artifacts should go in either `src/`.

> [!NOTE]
> If you are planning to make changes to the API (either the Custom Resource Definition or the SimKube API), please read
Expand All @@ -64,23 +56,20 @@ needs to be shared between multiple artifacts should go in either `lib/go` or `l

To build all SimKube artifacts for the first time run:
- `git submodule init && git submodule update`
- `make build` and `make skctl` from the root of this repository.
- `make build` from the root of this repository.

For all subsequent builds of SimKube artifacts, run only `make build` and `make skctl` from the root of this repository.
For all subsequent builds of SimKube artifacts, run only `make build` from the root of this repository.

For all the components that run inside a Kubernetes cluster, you can simply run `make build`. For minor technical
reasons, the CLI utility (`skctl`) is built separately: `make skctl`. All build artifacts are placed in the `.build`
directory at the root of the repository. If you just want to build a subset of the SimKube artifacts, you can set the
`ARTIFACTS` environment variable. This will help limit compilation time if you are just working on a single or a few
components:
All build artifacts are placed in the `.build` directory at the root of the repository. If you just want to build a
subset of the SimKube artifacts, you can set the `ARTIFACTS` environment variable. This will help limit compilation
time if you are just working on a single or a few components:

```
ARTIFACTS="sk-ctrl sk-driver" make build
```

By default, the Rust artifacts (`sk-ctrl`, `sk-driver`, and `sk-tracer`) are built inside Docker containers. All the
intermediate compilation steps and the executables are saved in `.build/cargo`. The Go artifacts (`skctl`,
`sk-cloudprov`, and `sk-vnode`) are built locally on your machine.
By default, all the artifacts are built inside Docker containers. All the intermediate compilation steps and the
executables are saved in `.build/cargo`.

### Building docker images

Expand Down Expand Up @@ -125,15 +114,14 @@ environment variables will be respected for the steps where they make sense.
### Testing your changes

Tests are divided into "unit tests" and "integration tests". The distinction between these is fuzzy. To run all the
tests, do `make test`. If you'd just like to run the Golang tests, you can do `make test-go`, and if you just want to
run the Rust unit tests, you can do `make test-rust`. To run the Rust integration tests, do `make itest-rust`.
tests, do `make test`.

### Linting your changes

Code linting rules are defined in `./golangci.yml` and `.rustfmt.toml` for Go and Rust code, respectively. We also use
[clippy](https://doc.rust-lang.org/stable/clippy/usage.html) for additional Rust linting and checks. We use a _nightly_
version of rustfmt to take advantage of unstable formatting rules, so you will need to install a nightly toolchain here.
(Note that all actual Rust code does not use any nightly features). You can run all lints with `make lint`.
Code linting rules are defined in `.rustfmt.toml`. We also use [clippy](https://doc.rust-lang.org/stable/clippy/usage.html)
for additional Rust linting and checks. We use a _nightly_ version of rustfmt to take advantage of unstable formatting
rules, so you will need to install a nightly toolchain here. (Note that all actual Rust code does not use any nightly
features). You can run all lints with `make lint`.

### Code coverage

Expand All @@ -145,8 +133,7 @@ Code coverage is checked whenever you open a PR using [CodeCov](https://about.co
comment showing you coverage changes and provide a link to a dashboard with more detailed information about what is and
is not covered.

If you'd like to generate coverage reports locally, for Golang it is as simple as running `make cover-go`. For Rust, it
is a little more complicated:
If you'd like to generate coverage reports locally, it is a little more complicated:

```
WITH_COVERAGE=1 RUST_COVER_TYPE=markdown make test-rust cover-rust
Expand All @@ -157,11 +144,10 @@ builds.

### Writing new tests

There is a suite of utility functions for tests in `lib/(go|rust)/testutils` that provide additional fixtures and helper
There is a suite of utility functions for tests in `src/testutils` that provide additional fixtures and helper
functions for writing tests. Feel free to add more utilities in here if it would be helpful.

Go tests live in `_test.go` files next to the source file they are testing. Rust tests should in most cases be put into
a separate submodule called `tests` and included with a
Tests should in most cases be put into a separate submodule called `tests` and included with a

```rust
#[cfg(test)]
Expand All @@ -170,8 +156,8 @@ mod tests;

block at the bottom of the main module.

In order to make `lib/rust/testutils` accessible outside the `lib/rust` crate, they are not included with
`#[cfg(test)]`, but instead with an optional `testutils` feature.
In order to make `src/testutils` accessible outside the `src/` crate, they are not included with `#[cfg(test)]`, but
instead with an optional `testutils` feature.

## Making a PR

Expand Down
Binary file modified docs/images/sk-overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ nav:
- Home: README.md
- Usage:
- Components:
- sk-cloudprov: docs/sk-cloudprov.md
- sk-ctrl: docs/sk-ctrl.md
- sk-driver: docs/sk-driver.md
- sk-tracer: docs/sk-tracer.md
- sk-vnode: docs/sk-vnode.md
- skctl: docs/skctl.md
- Contributing:
- Developer's Guide: docs/contributing.md
Expand Down
39 changes: 0 additions & 39 deletions docs/sk-cloudprov.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/sk-ctrl.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ spec:
The `SimulationSpec` contains two fields, the location of the trace file which we want to use for the simulation, and
the namespace to launch the driver into. Currently the only trace location supported is `file:///`, i.e., the trace
file already has to be present on the driver node at the specified location. In the future we will support downloading
from an S3 bucket or other persistant storage.
from an S3 bucket or other persistent storage.

The Simulation CR is cluster-namespaced, because it must create SimulationRoots.

Expand Down
5 changes: 3 additions & 2 deletions docs/sk-driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ annotations:
simkube.io/lifetime-seconds: <pod-lifetime> (if present in the trace)
spec:
tolerations:
- key: simkube.io/virtual-node
value: true
- key: kwok-provider
operator: Exists
effect: NoSchedule
nodeSelector:
type: virtual
```
Expand Down
4 changes: 2 additions & 2 deletions docs/sk-tracer.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ trackedObjects:
trackLifecycle: true/false (optional)
```
Here is an example config file that watchs both Deployments and VolcanoJobs from the [Volcano](https://volcano.sh/en/)
Here is an example config file that watches both Deployments and VolcanoJobs from the [Volcano](https://volcano.sh/en/)
Kubernetes scheduler:
```yaml
Expand Down Expand Up @@ -106,7 +106,7 @@ the object contents. The pod lifecycle data has the following format:

Because pods in the simulation will not have the same names as in the production trace, we can't use the pod name as a
stable identifier to track lifecycles. So instead, we index by the pod owner, and the hash of the pod object. Because
an owner can have pods with different characteristics (e.g., if a Deployment changes and creates a new replicaset, or if
an owner can have pods with different characteristics (e.g., if a Deployment changes and creates a new ReplicaSet, or if
there are multiple pod types specified in a VolcanoJob), we must track the lifecycles for these pods separately. This
is done by way of the hash of the PodSpec.

Expand Down
Loading

0 comments on commit 25884ac

Please sign in to comment.