Minor formatting updates for gvisor.dev.

* Aggregate architecture Overview in "What is gVisor?" as it makes more sense
  in one place.

* Drop "user-space kernel" and use "application kernel". The term "user-space
  kernel" is confusing when some platform implementation do not run in
  user-space (instead running in guest ring zero).

* Clear up the relationship between the Platform page in the user guide and the
  Platform page in the architecture guide, and ensure they are cross-linked.

* Restore the call-to-action quick start link in the main page, and drop the
  GitHub link (which also appears in the top-right).

* Improve image formatting by centering all doc and blog images, and move the
  image captions to the alt text.

PiperOrigin-RevId: 311845158
This commit is contained in:
Adin Scannell
2020-05-15 20:05:18 -07:00
committed by gVisor bot
parent 679fd2527b
commit 420b791a3d
40 changed files with 1064 additions and 416 deletions
+22 -55
View File
@@ -5,7 +5,7 @@
## What is gVisor?
**gVisor** is a user-space kernel, written in Go, that implements a substantial
**gVisor** is a application kernel, written in Go, that implements a substantial
portion of the Linux system surface. It includes an
[Open Container Initiative (OCI)][oci] runtime called `runsc` that provides an
isolation boundary between the application and the host kernel. The `runsc`
@@ -15,16 +15,17 @@ containers.
## Why does gVisor exist?
Containers are not a [**sandbox**][sandbox]. While containers have
revolutionized how we develop, package, and deploy applications, running
untrusted or potentially malicious code without additional isolation is not a
good idea. The efficiency and performance gains from using a single, shared
kernel also mean that container escape is possible with a single vulnerability.
revolutionized how we develop, package, and deploy applications, using them to
run untrusted or potentially malicious code without additional isolation is not
a good idea. While using a single, shared kernel allows for efficiency and
performance gains, it also means that container escape is possible with a single
vulnerability.
gVisor is a user-space kernel for containers. It limits the host kernel surface
accessible to the application while still giving the application access to all
the features it expects. Unlike most kernels, gVisor does not assume or require
a fixed set of physical resources; instead, it leverages existing host kernel
functionality and runs as a normal user-space process. In other words, gVisor
gVisor is an application kernel for containers. It limits the host kernel
surface accessible to the application while still giving the application access
to all the features it expects. Unlike most kernels, gVisor does not assume or
require a fixed set of physical resources; instead, it leverages existing host
kernel functionality and runs as a normal process. In other words, gVisor
implements Linux by way of Linux.
gVisor should not be confused with technologies and tools to harden containers
@@ -39,33 +40,24 @@ be found at [gvisor.dev][gvisor-dev].
## Installing from source
gVisor currently requires x86\_64 Linux to build, though support for other
architectures may become available in the future.
gVisor builds on x86_64 and ARM64. Other architectures may become available in
the future.
For the purposes of these instructions, [bazel][bazel] and other build
dependencies are wrapped in a build container. It is possible to use
[bazel][bazel] directly, or type `make help` for standard targets.
### Requirements
Make sure the following dependencies are installed:
* Linux 4.14.77+ ([older linux][old-linux])
* [git][git]
* [Bazel][bazel] 1.2+
* [Python][python]
* [Docker version 17.09.0 or greater][docker]
* C++ toolchain supporting C++17 (GCC 7+, Clang 5+)
* Gold linker (e.g. `binutils-gold` package on Ubuntu)
### Building
Build and install the `runsc` binary:
```
bazel build runsc
sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
```
If you don't want to install bazel on your system, you can build runsc in a
Docker container:
```
make runsc
sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
@@ -73,41 +65,19 @@ sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
### Testing
The test suite can be run with Bazel:
```
bazel test //...
```
or in a Docker container:
To run standard test suites, you can use:
```
make unit-tests
make tests
```
### Using remote execution
If you have a [Remote Build Execution][rbe] environment, you can use it to speed
up build and test cycles.
You must authenticate with the project first:
To run specific tests, you can specify the target:
```
gcloud auth application-default login --no-launch-browser
make test TARGET="//runsc:version_test"
```
Then invoke bazel with the following flags:
```
--config=remote
--project_id=$PROJECT
--remote_instance_name=projects/$PROJECT/instances/default_instance
```
You can also add those flags to your local ~/.bazelrc to avoid needing to
specify them each time on the command line.
### Using `go get`
This project uses [bazel][bazel] to build and manage dependencies. A synthetic
@@ -128,7 +98,7 @@ development on this branch is not supported. Development should occur on the
## Community & Governance
The governance model is documented in our [community][community] repository.
See [GOVERNANCE.md](GOVERANCE.md) for project governance information.
The [gvisor-users mailing list][gvisor-users-list] and
[gvisor-dev mailing list][gvisor-dev-list] are good starting points for
@@ -145,12 +115,9 @@ See [Contributing.md](CONTRIBUTING.md).
[bazel]: https://bazel.build
[community]: https://gvisor.googlesource.com/community
[docker]: https://www.docker.com
[git]: https://git-scm.com
[gvisor-users-list]: https://groups.google.com/forum/#!forum/gvisor-users
[gvisor-dev]: https://gvisor.dev
[gvisor-dev-list]: https://groups.google.com/forum/#!forum/gvisor-dev
[oci]: https://www.opencontainers.org
[old-linux]: https://gvisor.dev/docs/user_guide/networking/#gso
[python]: https://python.org
[rbe]: https://blog.bazel.build/2018/10/05/remote-build-execution.html
[sandbox]: https://en.wikipedia.org/wiki/Sandbox_(computer_security)
[gvisor-dev]: https://gvisor.dev
+4
View File
@@ -9,6 +9,10 @@ doc(
name = "index",
src = "README.md",
category = "Project",
data = glob([
"*.png",
"*.svg",
]),
permalink = "/docs/",
weight = "0",
)

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

+151 -10
View File
@@ -1,6 +1,6 @@
# What is gVisor?
gVisor is a user-space kernel, written in Go, that implements a substantial
gVisor is an application kernel, written in Go, that implements a substantial
portion of the [Linux system call interface][linux]. It provides an additional
layer of isolation between running applications and the host operating system.
@@ -9,19 +9,160 @@ that makes it easy to work with existing container tooling. The `runsc` runtime
integrates with Docker and Kubernetes, making it simple to run sandboxed
containers.
gVisor takes a distinct approach to container sandboxing and makes a different
set of technical trade-offs compared to existing sandbox technologies, thus
providing new tools and ideas for the container security landscape.
gVisor can be used with Docker, Kubernetes, or directly using `runsc`. Use the
links below to see detailed instructions for each of them:
* [Docker](./user_guide/quick_start/docker/): The quickest and easiest way to
get started.
* [Kubernetes](./user_guide/quick_start/kubernetes/): Isolate Pods in your K8s
cluster with gVisor.
* [OCI Quick Start](./user_guide/quick_start/oci/): Expert mode. Customize
* [Docker](./user_guide/quick_start/docker.md): The quickest and easiest way
to get started.
* [Kubernetes](./user_guide/quick_start/kubernetes.md): Isolate Pods in your
K8s cluster with gVisor.
* [OCI Quick Start](./user_guide/quick_start/oci.md): Expert mode. Customize
gVisor for your environment.
## What does gVisor do?
gVisor provides a virtualized environment in order to sandbox containers. The
system interfaces normally implemented by the host kernel are moved into a
distinct, per-sandbox application kernel in order to minimize the risk of an
container escape exploit. gVisor does not introduce large fixed overheads
however, and still retains a process-like model with respect to resource
utilization.
## How is this different?
Two other approaches are commonly taken to provide stronger isolation than
native containers.
**Machine-level virtualization**, such as [KVM][kvm] and [Xen][xen], exposes
virtualized hardware to a guest kernel via a Virtual Machine Monitor (VMM). This
virtualized hardware is generally enlightened (paravirtualized) and additional
mechanisms can be used to improve the visibility between the guest and host
(e.g. balloon drivers, paravirtualized spinlocks). Running containers in
distinct virtual machines can provide great isolation, compatibility and
performance (though nested virtualization may bring challenges in this area),
but for containers it often requires additional proxies and agents, and may
require a larger resource footprint and slower start-up times.
![Machine-level virtualization](Machine-Virtualization.png "Machine-level virtualization")
**Rule-based execution**, such as [seccomp][seccomp], [SELinux][selinux] and
[AppArmor][apparmor], allows the specification of a fine-grained security policy
for an application or container. These schemes typically rely on hooks
implemented inside the host kernel to enforce the rules. If the surface can be
made small enough, then this is an excellent way to sandbox applications and
maintain native performance. However, in practice it can be extremely difficult
(if not impossible) to reliably define a policy for arbitrary, previously
unknown applications, making this approach challenging to apply universally.
![Rule-based execution](Rule-Based-Execution.png "Rule-based execution")
Rule-based execution is often combined with additional layers for
defense-in-depth.
**gVisor** provides a third isolation mechanism, distinct from those above.
gVisor intercepts application system calls and acts as the guest kernel, without
the need for translation through virtualized hardware. gVisor may be thought of
as either a merged guest kernel and VMM, or as seccomp on steroids. This
architecture allows it to provide a flexible resource footprint (i.e. one based
on threads and memory mappings, not fixed guest physical resources) while also
lowering the fixed costs of virtualization. However, this comes at the price of
reduced application compatibility and higher per-system call overhead.
![gVisor](Layers.png "gVisor")
On top of this, gVisor employs rule-based execution to provide defense-in-depth
(details below).
gVisor's approach is similar to [User Mode Linux (UML)][uml], although UML
virtualizes hardware internally and thus provides a fixed resource footprint.
Each of the above approaches may excel in distinct scenarios. For example,
machine-level virtualization will face challenges achieving high density, while
gVisor may provide poor performance for system call heavy workloads.
## Why Go?
gVisor is written in [Go][golang] in order to avoid security pitfalls that can
plague kernels. With Go, there are strong types, built-in bounds checks, no
uninitialized variables, no use-after-free, no stack overflow, and a built-in
race detector. However, the use of Go has its challenges, and the runtime often
introduces performance overhead.
## What are the different components?
A gVisor sandbox consists of multiple processes. These processes collectively
comprise an environment in which one or more containers can be run.
Each sandbox has its own isolated instance of:
* The **Sentry**, which is a kernel that runs the containers and intercepts
and responds to system calls made by the application.
Each container running in the sandbox has its own isolated instance of:
* A **Gofer** which provides file system access to the containers.
![gVisor architecture diagram](Sentry-Gofer.png "gVisor architecture diagram")
## What is runsc?
The entrypoint to running a sandboxed container is the `runsc` executable.
`runsc` implements the [Open Container Initiative (OCI)][oci] runtime
specification, which is used by Docker and Kubernetes. This means that OCI
compatible _filesystem bundles_ can be run by `runsc`. Filesystem bundles are
comprised of a `config.json` file containing container configuration, and a root
filesystem for the container. Please see the [OCI runtime spec][runtime-spec]
for more information on filesystem bundles. `runsc` implements multiple commands
that perform various functions such as starting, stopping, listing, and querying
the status of containers.
### Sentry
<a name="sentry"></a> <!-- For deep linking. -->
The Sentry is the largest component of gVisor. It can be thought of as a
application kernel. The Sentry implements all the kernel functionality needed by
the application, including: system calls, signal delivery, memory management and
page faulting logic, the threading model, and more.
When the application makes a system call, the
[Platform](./architecture_guide/platforms.md) redirects the call to the Sentry,
which will do the necessary work to service it. It is important to note that the
Sentry does not pass system calls through to the host kernel. As a userspace
application, the Sentry will make some host system calls to support its
operation, but it does not allow the application to directly control the system
calls it makes. For example, the Sentry is not able to open files directly; file
system operations that extend beyond the sandbox (not internal `/proc` files,
pipes, etc) are sent to the Gofer, described below.
### Gofer
<a name="gofer"></a> <!-- For deep linking. -->
The Gofer is a standard host process which is started with each container and
communicates with the Sentry via the [9P protocol][9p] over a socket or shared
memory channel. The Sentry process is started in a restricted seccomp container
without access to file system resources. The Gofer mediates all access to the
these resources, providing an additional level of isolation.
### Application
The application is a normal Linux binary provided to gVisor in an OCI runtime
bundle. gVisor aims to provide an environment equivalent to Linux v4.4, so
applications should be able to run unmodified. However, gVisor does not
presently implement every system call, `/proc` file, or `/sys` file so some
incompatibilities may occur. See [Commpatibility](./user_guide/compatibility.md)
for more information.
[9p]: https://en.wikipedia.org/wiki/9P_(protocol)
[apparmor]: https://wiki.ubuntu.com/AppArmor
[golang]: https://golang.org
[kvm]: https://www.linux-kvm.org
[linux]: https://en.wikipedia.org/wiki/Linux_kernel_interfaces
[oci]: https://www.opencontainers.org
[runtime-spec]: https://github.com/opencontainers/runtime-spec
[seccomp]: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
[selinux]: https://selinuxproject.org
[uml]: http://user-mode-linux.sourceforge.net/
[xen]: https://www.xenproject.org

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

+8 -22
View File
@@ -5,31 +5,13 @@ package(
licenses = ["notice"],
)
doc(
name = "index",
src = "README.md",
category = "Architecture Guide",
data = [
"Layers.png",
"Layers.svg",
"Machine-Virtualization.png",
"Machine-Virtualization.svg",
"Rule-Based-Execution.png",
"Rule-Based-Execution.svg",
"Sentry-Gofer.png",
"Sentry-Gofer.svg",
],
permalink = "/docs/architecture_guide/",
weight = "0",
)
doc(
name = "platforms",
src = "platforms.md",
category = "Architecture Guide",
data = [
"Sentry-Gofer.png",
"Sentry-Gofer.svg",
"platforms.png",
"platforms.svg",
],
permalink = "/docs/architecture_guide/platforms/",
weight = "40",
@@ -39,6 +21,10 @@ doc(
name = "resources",
src = "resources.md",
category = "Architecture Guide",
data = [
"resources.png",
"resources.svg",
],
permalink = "/docs/architecture_guide/resources/",
weight = "30",
)
@@ -48,8 +34,8 @@ doc(
src = "security.md",
category = "Architecture Guide",
data = [
"Layers.png",
"Layers.svg",
"security.png",
"security.svg",
],
permalink = "/docs/architecture_guide/security/",
weight = "10",
-83
View File
@@ -1,83 +0,0 @@
# Overview
gVisor provides a virtualized environment in order to sandbox untrusted
containers. The system interfaces normally implemented by the host kernel are
moved into a distinct, per-sandbox user space kernel in order to minimize the
risk of an exploit. gVisor does not introduce large fixed overheads however, and
still retains a process-like model with respect to resource utilization.
## How is this different?
Two other approaches are commonly taken to provide stronger isolation than
native containers.
**Machine-level virtualization**, such as [KVM][kvm] and [Xen][xen], exposes
virtualized hardware to a guest kernel via a Virtual Machine Monitor (VMM). This
virtualized hardware is generally enlightened (paravirtualized) and additional
mechanisms can be used to improve the visibility between the guest and host
(e.g. balloon drivers, paravirtualized spinlocks). Running containers in
distinct virtual machines can provide great isolation, compatibility and
performance (though nested virtualization may bring challenges in this area),
but for containers it often requires additional proxies and agents, and may
require a larger resource footprint and slower start-up times.
![Machine-level virtualization](Machine-Virtualization.png "Machine-level virtualization")
**Rule-based execution**, such as [seccomp][seccomp], [SELinux][selinux] and
[AppArmor][apparmor], allows the specification of a fine-grained security policy
for an application or container. These schemes typically rely on hooks
implemented inside the host kernel to enforce the rules. If the surface can be
made small enough (i.e. a sufficiently complete policy defined), then this is an
excellent way to sandbox applications and maintain native performance. However,
in practice it can be extremely difficult (if not impossible) to reliably define
a policy for arbitrary, previously unknown applications, making this approach
challenging to apply universally.
![Rule-based execution](Rule-Based-Execution.png "Rule-based execution")
Rule-based execution is often combined with additional layers for
defense-in-depth.
**gVisor** provides a third isolation mechanism, distinct from those above.
gVisor intercepts application system calls and acts as the guest kernel, without
the need for translation through virtualized hardware. gVisor may be thought of
as either a merged guest kernel and VMM, or as seccomp on steroids. This
architecture allows it to provide a flexible resource footprint (i.e. one based
on threads and memory mappings, not fixed guest physical resources) while also
lowering the fixed costs of virtualization. However, this comes at the price of
reduced application compatibility and higher per-system call overhead.
![gVisor](Layers.png "gVisor")
On top of this, gVisor employs rule-based execution to provide defense-in-depth
(details below).
gVisor's approach is similar to [User Mode Linux (UML)][uml], although UML
virtualizes hardware internally and thus provides a fixed resource footprint.
Each of the above approaches may excel in distinct scenarios. For example,
machine-level virtualization will face challenges achieving high density, while
gVisor may provide poor performance for system call heavy workloads.
### Why Go?
gVisor is written in [Go][golang] in order to avoid security pitfalls that can
plague kernels. With Go, there are strong types, built-in bounds checks, no
uninitialized variables, no use-after-free, no stack overflow, and a built-in
race detector. (The use of Go has its challenges too, and isn't free.)
### What about Gofers?
<a name="gofer"></a> <!-- For deep linking. -->
Gofers mediate file system interactions, and are used to provide additional
isolation. For more details, see the [Platform Guide](./platforms.md).
[apparmor]: https://wiki.ubuntu.com/AppArmor
[golang]: https://golang.org
[kvm]: https://www.linux-kvm.org
[seccomp]: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
[selinux]: https://selinuxproject.org
[uml]: http://user-mode-linux.sourceforge.net/
[xen]: https://www.xenproject.org
+19 -16
View File
@@ -13,12 +13,13 @@ forms: additional cycles and memory usage, which may manifest as increased
latency, reduced throughput or density, or not at all. In general, these costs
come from two different sources.
First, the existence of the [Sentry](../) means that additional memory will be
required, and application system calls must traverse additional layers of
software. The design emphasizes [security](../security/) and therefore we chose
to use a language for the Sentry that provides benefits in this domain but may
not yet offer the raw performance of other choices. Costs imposed by these
design choices are **structural costs**.
First, the existence of the [Sentry](../README.md#sentry) means that additional
memory will be required, and application system calls must traverse additional
layers of software. The design emphasizes
[security](/docs/architecture_guide/security/) and therefore we chose to use a
language for the Sentry that provides benefits in this domain but may not yet
offer the raw performance of other choices. Costs imposed by these design
choices are **structural costs**.
Second, as gVisor is an independent implementation of the system call surface,
many of the subsystems or specific calls are not as optimized as more mature
@@ -50,7 +51,7 @@ Virtual Machines (VMs) with the following specifications:
Through this document, `runsc` is used to indicate the runtime provided by
gVisor. When relevant, we use the name `runsc-platform` to describe a specific
[platform choice](../platforms/).
[platform choice](/docs/architecture_guide/platforms/).
**Except where specified, all tests below are conducted with the `ptrace`
platform. The `ptrace` platform works everywhere and does not require hardware
@@ -131,11 +132,11 @@ full start-up and run time for the workload, which trains a model.
## System calls
Some **structural costs** of gVisor are heavily influenced by the
[platform choice](../platforms/), which implements system call interception.
Today, gVisor supports a variety of platforms. These platforms present distinct
performance, compatibility and security trade-offs. For example, the KVM
platform has low overhead system call interception but runs poorly with nested
virtualization.
[platform choice](/docs/architecture_guide/platforms/), which implements system
call interception. Today, gVisor supports a variety of platforms. These
platforms present distinct performance, compatibility and security trade-offs.
For example, the KVM platform has low overhead system call interception but runs
poorly with nested virtualization.
{% include graph.html id="syscall" url="/performance/syscall.csv" title="perf.py
syscall --runtime=runc --runtime=runsc-ptrace --runtime=runsc-kvm" y_min="100"
@@ -163,7 +164,8 @@ overhead.
Some of these costs above are **structural costs**, and `redis` is likely to
remain a challenging performance scenario. However, optimizing the
[platform](../platforms/) will also have a dramatic impact.
[platform](/docs/architecture_guide/platforms/) will also have a dramatic
impact.
## Start-up time
@@ -184,7 +186,7 @@ similarly loads a number of modules and binds an HTTP server.
> Note: most of the time overhead above is associated Docker itself. This is
> evident with the empty `runc` benchmark. To avoid these costs with `runsc`,
> you may also consider using `runsc do` mode or invoking the
> [OCI runtime](../../user_guide/quick_start/oci/) directly.
> [OCI runtime](../user_guide/quick_start/oci.md) directly.
## Network
@@ -222,8 +224,9 @@ In terms of raw disk I/O, gVisor does not introduce significant fundamental
overhead. For general file operations, gVisor introduces a small fixed overhead
for data that transitions across the sandbox boundary. This manifests as
**structural costs** in some cases, since these operations must be routed
through the [Gofer](../) as a result of our [security model](../security/), but
in most cases are dominated by **implementation costs**, due to an internal
through the [Gofer](../README.md#gofer) as a result of our
[Security Model](/docs/architecture_guide/security/), but in most cases are
dominated by **implementation costs**, due to an internal
[Virtual File System][vfs] (VFS) implementation that needs improvement.
{% include graph.html id="fio-bw" url="/performance/fio.csv" title="perf.py fio
+48 -73
View File
@@ -1,86 +1,61 @@
# Platform Guide
A gVisor sandbox consists of multiple processes when running. These processes
collectively comprise a shared environment in which one or more containers can
be run.
Each sandbox has its own isolated instance of:
* The **Sentry**, A user-space kernel that runs the container and intercepts
and responds to system calls made by the application.
Each container running in the sandbox has its own isolated instance of:
* A **Gofer** which provides file system access to the container.
![gVisor architecture diagram](Sentry-Gofer.png "gVisor architecture diagram")
## runsc
The entrypoint to running a sandboxed container is the `runsc` executable.
`runsc` implements the [Open Container Initiative (OCI)][oci] runtime
specification. This means that OCI compatible _filesystem bundles_ can be run by
`runsc`. Filesystem bundles are comprised of a `config.json` file containing
container configuration, and a root filesystem for the container. Please see the
[OCI runtime spec][runtime-spec] for more information on filesystem bundles.
`runsc` implements multiple commands that perform various functions such as
starting, stopping, listing, and querying the status of containers.
## Sentry
The Sentry is the largest component of gVisor. It can be thought of as a
userspace OS kernel. The Sentry implements all the kernel functionality needed
by the untrusted application. It implements all of the supported system calls,
signal delivery, memory management and page faulting logic, the threading model,
and more.
When the untrusted application makes a system call, the currently used platform
redirects the call to the Sentry, which will do the necessary work to service
it. It is important to note that the Sentry will not simply pass through system
calls to the host kernel. As a userspace application, the Sentry will make some
host system calls to support its operation, but it will not allow the
application to directly control the system calls it makes.
The Sentry aims to present an equivalent environment to (upstream) Linux v4.4.
File system operations that extend beyond the sandbox (not internal /proc files,
pipes, etc) are sent to the Gofer, described below.
## Platforms
[TOC]
gVisor requires a platform to implement interception of syscalls, basic context
switching, and memory mapping functionality.
switching, and memory mapping functionality. Internally, gVisor uses an
abstraction sensibly called [Platform][platform]. A simplified version of this
interface looks like:
```golang
type Platform interface {
NewAddressSpace() (AddressSpace, error)
NewContext() Context
}
type Context interface {
Switch(as AddressSpace, ac arch.Context) (..., error)
}
type AddressSpace interface {
MapFile(addr usermem.Addr, f File, fr FileRange, at usermem.AccessType, ...) error
Unmap(addr usermem.Addr, length uint64)
}
```
There are a number of different ways to implement this interface that come with
various trade-offs, generally around performance and hardware requirements.
## Implementations
The choice of platform depends on the context in which `runsc` is executing. In
general, virtualized platforms may be limited to platforms that do not require
hardware virtualized support (since the hardware is already in use):
![Platforms](platforms.png "Platform examples.")
### ptrace
The ptrace platform uses `PTRACE_SYSEMU` to execute user code without allowing
it to execute host system calls. This platform can run anywhere that ptrace
works (even VMs without nested virtualization).
The ptrace platform uses [PTRACE_SYSEMU][ptrace] to execute user code without
allowing it to execute host system calls. This platform can run anywhere that
`ptrace` works (even VMs without nested virtualization), which is ubiquitous.
### KVM (experimental)
Unfortunately, the ptrace platform has high context switch overhead, so system
call-heavy applications may pay a [performance penalty](./performance.md).
The KVM platform allows the Sentry to act as both guest OS and VMM, switching
back and forth between the two worlds seamlessly. The KVM platform can run on
bare-metal or in a VM with nested virtualization enabled. While there is no
virtualized hardware layer -- the sandbox retains a process model -- gVisor
leverages virtualization extensions available on modern processors in order to
improve isolation and performance of address space switches.
### KVM
## Gofer
The KVM platform uses the kernel's [KVM][kvm] functionality to allow the Sentry
to act as both guest OS and VMM. The KVM platform can run on bare-metal or in a
VM with nested virtualization enabled. While there is no virtualized hardware
layer -- the sandbox retains a process model -- gVisor leverages virtualization
extensions available on modern processors in order to improve isolation and
performance of address space switches.
The Gofer is a normal host Linux process. The Gofer is started with each sandbox
and connected to the Sentry. The Sentry process is started in a restricted
seccomp container without access to file system resources. The Gofer provides
the Sentry access to file system resources via the 9P protocol and provides an
additional level of isolation.
## Changing Platforms
## Application
See [Changing Platforms](../user_guide/platforms.md).
The application (aka the untrusted application) is a normal Linux binary
provided to gVisor in an OCI runtime bundle. gVisor aims to provide an
environment equivalent to Linux v4.4, so applications should be able to run
unmodified. However, gVisor does not presently implement every system call,
/proc file, or /sys file so some incompatibilities may occur.
[oci]: https://www.opencontainers.org
[runtime-spec]: https://github.com/opencontainers/runtime-spec
[kvm]: https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt
[platform]: https://cs.opensource.google/gvisor/gvisor/+/release-20190304.1:pkg/sentry/platform/platform.go;l=33
[ptrace]: http://man7.org/linux/man-pages/man2/ptrace.2.html
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+334
View File
@@ -0,0 +1,334 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="142.67763mm"
height="67.063133mm"
viewBox="0 0 142.67763 67.063134"
version="1.1"
id="svg8"
inkscape:export-filename="/home/ascannell/resources.png"
inkscape:export-xdpi="53.50127"
inkscape:export-ydpi="53.50127"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="platforms.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="86.443612"
inkscape:cy="102.88104"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-36.081387,-98.953278)">
<rect
id="rect10"
width="33.408691"
height="33.408691"
x="36.081387"
y="120.06757"
style="fill:#44aa00;stroke-width:0.26458332" />
<rect
style="fill:#b3b3b3;stroke-width:0.23881446"
id="rect16"
width="142.45465"
height="10.423517"
x="36.08139"
y="155.5929" />
<rect
id="rect10-7"
width="30.52453"
height="18.976137"
x="37.416695"
y="121.65508"
style="fill:#ff8080;stroke-width:0.19060372" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="41.03727"
y="148.58765"
id="text65"><tspan
sodipodi:role="line"
id="tspan63"
x="41.03727"
y="148.58765"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="45.473087"
y="132.50232"
id="text123"><tspan
sodipodi:role="line"
id="tspan121"
x="45.473087"
y="132.50232"
style="stroke-width:0.08327847">workload</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.43922186px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.16098055"
x="97.768547"
y="163.15665"
id="text163"><tspan
sodipodi:role="line"
id="tspan161"
x="97.768547"
y="163.15665"
style="stroke-width:0.16098055">host</tspan></text>
<rect
style="fill:#e9afdd;stroke-width:0.39185274"
id="rect16-7"
width="72.9646"
height="54.79026"
x="105.79441"
y="98.953278" />
<rect
id="rect10-5"
width="33.408691"
height="33.408691"
x="108.24348"
y="100.53072"
style="fill:#44aa00;stroke-width:0.26458332" />
<rect
id="rect10-7-6"
width="30.52453"
height="20.045216"
x="109.57877"
y="102.11823"
style="fill:#ff8080;stroke-width:0.19589928" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="112.86765"
y="129.01863"
id="text65-2"><tspan
sodipodi:role="line"
id="tspan63-9"
x="112.86765"
y="129.01863"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="117.63519"
y="114.02371"
id="text123-1"><tspan
sodipodi:role="line"
id="tspan121-2"
x="117.63519"
y="114.02371"
style="stroke-width:0.08327847">workload</tspan></text>
<rect
id="rect10-7-7"
width="11.815663"
height="8.0126781"
x="54.538059"
y="143.27702"
style="fill:#aaccff;stroke-width:0.07705856" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:4.35074377px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.10876859"
x="55.931114"
y="148.90578"
id="text144"><tspan
sodipodi:role="line"
id="tspan142"
x="55.931114"
y="148.90578"
style="stroke-width:0.10876859">KVM</tspan></text>
<rect
id="rect10-6"
width="33.408691"
height="33.408691"
x="71.044685"
y="119.73112"
style="fill:#44aa00;stroke-width:0.26458332" />
<rect
id="rect10-7-0"
width="30.52453"
height="18.976137"
x="72.37999"
y="121.31865"
style="fill:#ff8080;stroke-width:0.19060372" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="76.000565"
y="148.25128"
id="text65-6"><tspan
sodipodi:role="line"
id="tspan63-2"
x="76.000565"
y="148.25128"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="80.436386"
y="132.16595"
id="text123-6"><tspan
sodipodi:role="line"
id="tspan121-1"
x="80.436386"
y="132.16595"
style="stroke-width:0.08327847">workload</tspan></text>
<rect
id="rect10-7-7-8"
width="11.815664"
height="8.0126781"
x="89.501358"
y="142.94067"
style="fill:#ffeeaa;stroke-width:0.07705856" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.39456654px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08486416"
x="89.92292"
y="147.89806"
id="text144-7"><tspan
sodipodi:role="line"
id="tspan142-9"
x="89.92292"
y="147.89806"
style="stroke-width:0.08486416">ptrace</tspan></text>
<rect
id="rect10-7-7-8-3"
width="11.815665"
height="8.0126781"
x="127.08897"
y="123.97878"
style="fill:#ffeeaa;stroke-width:0.07705856" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.39456654px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08486416"
x="127.51052"
y="128.9362"
id="text144-7-7"><tspan
sodipodi:role="line"
id="tspan142-9-5"
x="127.51052"
y="128.9362"
style="stroke-width:0.08486416">ptrace</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:5.45061255px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.13626531"
x="138.49318"
y="152.11841"
id="text229"><tspan
sodipodi:role="line"
id="tspan227"
x="138.49318"
y="152.11841"
style="stroke-width:0.13626531">VM</tspan></text>
<rect
style="fill:#b3b3b3;stroke-width:0.16518368"
id="rect16-9"
width="68.15374"
height="10.423517"
x="108.24348"
y="134.99774" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.17854786px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15446369"
x="132.91473"
y="142.07658"
id="text248"><tspan
sodipodi:role="line"
id="tspan246"
x="132.91473"
y="142.07658"
style="stroke-width:0.15446369">guest</tspan></text>
<rect
id="rect10-5-2"
width="33.408691"
height="33.408691"
x="143.32402"
y="100.35877"
style="fill:#44aa00;stroke-width:0.26458332" />
<rect
id="rect10-7-6-2"
width="30.52453"
height="20.045216"
x="144.65933"
y="101.94627"
style="fill:#ff8080;stroke-width:0.19589929" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="147.94815"
y="128.84665"
id="text65-2-8"><tspan
sodipodi:role="line"
id="tspan63-9-9"
x="147.94815"
y="128.84665"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="152.71565"
y="113.85176"
id="text123-1-7"><tspan
sodipodi:role="line"
id="tspan121-2-3"
x="152.71565"
y="113.85176"
style="stroke-width:0.08327847">workload</tspan></text>
<rect
id="rect10-7-7-8-3-6"
width="11.815666"
height="8.0126781"
x="162.16933"
y="123.80682"
style="fill:#ffeeaa;stroke-width:0.07705856" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.39456654px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08486416"
x="162.59088"
y="128.76421"
id="text144-7-7-1"><tspan
sodipodi:role="line"
id="tspan142-9-5-2"
x="162.59088"
y="128.76421"
style="stroke-width:0.08486416">ptrace</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

+14 -13
View File
@@ -10,9 +10,10 @@ sandbox to be highly dynamic in terms of resource usage: spanning a large number
of cores and large amount of memory when busy, and yielding those resources back
to the host when not.
Some of the details here may depend on the [platform](../platforms/), but in
general this page describes the resource model used by gVisor. If you're not
familiar with the terms here, uou may want to start with the [Overview](../).
In order words, the shape of the sandbox should closely track the shape of the
sandboxed process:
![Resource model](resources.png "Workloads of different shapes.")
## Processes
@@ -23,9 +24,9 @@ the sandbox (e.g. via a [Docker exec][exec]).
## Networking
Similarly to processes, the sandbox attaches a network endpoint to the system,
but runs it's own network stack. All network resources, other than packets in
flight, exist only inside the sandbox, bound by relevant resource limits.
The sandbox attaches a network endpoint to the system, but runs it's own network
stack. All network resources, other than packets in flight on the host, exist
only inside the sandbox, bound by relevant resource limits.
You can interact with network endpoints exposed by the sandbox, just as you
would any other container, but network introspection similarly requires entering
@@ -33,15 +34,14 @@ the sandbox.
## Files
Files may be backed by different implementations. For host-native files (where a
file descriptor is available), the Gofer may return a file descriptor to the
Sentry via [SCM_RIGHTS][scmrights][^1].
Files in the sandbox may be backed by different implementations. For host-native
files (where a file descriptor is available), the Gofer may return a file
descriptor to the Sentry via [SCM_RIGHTS][scmrights][^1].
These files may be read from and written to through standard system calls, and
also mapped into the associated application's address space. This allows the
same host memory to be shared across multiple sandboxes, although this mechanism
does not preclude the use of side-channels (see the
[security model](../security/)).
does not preclude the use of side-channels (see [Security Model](./security.md).
Note that some file systems exist only within the context of the sandbox. For
example, in many cases a `tmpfs` mount will be available at `/tmp` or
@@ -64,8 +64,9 @@ scheduling decisions about all application threads.
## Time
Time in the sandbox is provided by the Sentry, through its own [vDSO][vdso] and
timekeeping implementation. This is divorced from the host time, and no state is
shared with the host, although the time will be initialized with the host clock.
time-keeping implementation. This is distinct from the host time, and no state
is shared with the host, although the time will be initialized with the host
clock.
The Sentry runs timers to note the passage of time, much like a kernel running
on hardware (though the timers are software timers, in this case). These timers
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+208
View File
@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="108.24417mm"
height="47.513165mm"
viewBox="0 0 108.24417 47.513165"
version="1.1"
id="svg8"
inkscape:export-filename="/home/ascannell/resources.png"
inkscape:export-xdpi="53.50127"
inkscape:export-ydpi="53.50127"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="resources.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="16.897058"
inkscape:cy="41.261746"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-36.081387,-118.50325)">
<rect
id="rect10"
width="33.408691"
height="33.408691"
x="36.081387"
y="120.06757"
style="fill:#44aa00;stroke-width:0.26458332" />
<circle
style="fill:#44aa00;stroke-width:0.21849461"
id="path12"
cx="87.958534"
cy="136.63828"
r="17.105247" />
<path
sodipodi:type="star"
style="fill:#44aa00;stroke-width:0.26458332"
id="path14"
sodipodi:sides="3"
sodipodi:cx="124.13387"
sodipodi:cy="141.81859"
sodipodi:r1="23.31534"
sodipodi:r2="11.65767"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 144.32555,153.47626 -20.19168,0 -20.19167,0 10.09583,-17.48651 10.09584,-17.4865 10.09584,17.4865 z"
inkscape:transform-center-x="1.8384776e-06"
inkscape:transform-center-y="-5.8288369" />
<rect
style="fill:#b3b3b3;stroke-width:0.20817307"
id="rect16"
width="108.24416"
height="10.423517"
x="36.08139"
y="155.5929" />
<path
sodipodi:type="star"
style="fill:#ff8080;stroke-width:0.20018946"
id="path14-3"
sodipodi:sides="3"
sodipodi:cx="124.13387"
sodipodi:cy="139.31911"
sodipodi:r1="17.640888"
sodipodi:r2="8.8204451"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 139.41133,148.13955 -15.27746,0 -15.27745,0 7.63872,-13.23067 7.63873,-13.23066 7.63873,13.23066 z"
inkscape:transform-center-x="3.9117172e-06"
inkscape:transform-center-y="-4.4102243" />
<circle
style="fill:#ff8080;stroke-width:0.18094084"
id="path12-6"
cx="87.93705"
cy="134.75125"
r="14.165282" />
<rect
id="rect10-7"
width="30.52453"
height="25.657875"
x="37.416695"
y="121.65508"
style="fill:#ff8080;stroke-width:0.22163473" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="47.387276"
y="151.7626"
id="text65"><tspan
sodipodi:role="line"
id="tspan63"
x="47.387276"
y="151.7626"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="82.156319"
y="151.71547"
id="text65-5"><tspan
sodipodi:role="line"
id="tspan63-3"
x="82.156319"
y="151.71547"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.40292525px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08507314"
x="118.66879"
y="151.71547"
id="text65-5-5"><tspan
sodipodi:role="line"
id="tspan63-3-6"
x="118.66879"
y="151.71547"
style="stroke-width:0.08507314">gVisor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="45.473087"
y="136.20644"
id="text123"><tspan
sodipodi:role="line"
id="tspan121"
x="45.473087"
y="136.20644"
style="stroke-width:0.08327847">workload</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="80.153076"
y="136.00925"
id="text123-1"><tspan
sodipodi:role="line"
id="tspan121-2"
x="80.153076"
y="136.00925"
style="stroke-width:0.08327847">workload</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.33113885px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.08327847"
x="116.50173"
y="138.68195"
id="text123-1-7"><tspan
sodipodi:role="line"
id="tspan121-2-0"
x="116.50173"
y="138.68195"
style="stroke-width:0.08327847">workload</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.43922186px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.16098055"
x="81.893562"
y="163.15665"
id="text163"><tspan
sodipodi:role="line"
id="tspan161"
x="81.893562"
y="163.15665"
style="stroke-width:0.16098055">host</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

Some files were not shown because too many files have changed in this diff Show More