The `Usage.Reduce` RPC's promise is to reclaim as much Sentry memory as
possible and to give it back to the host.
Seems like running Go GC should be part of that.
PiperOrigin-RevId: 547312564
Currently there's no implementation to enable the container to be
initialized to it's cgroups and hence the `EnterInitialCgroups` would
inherit all the root's cgroups when the container would start.
With this implementation we make sure that when the container starts
it enter's into the cgroups that is passed down it to from the sandbox.
PiperOrigin-RevId: 540650868
This commit adds support for program execution via a host file
descriptor. To make use of this feature, the host file descriptor must
be provided to the --exec-fd argument. For example,
exec 3</usr/bin/echo
runsc exec --exec-fd=3 mycontainer hello world
will run the host's echo binary inside gVisor. In this case, "hello" is
supplied to echo as argv[0]. As a result, the output of the above
command is "world".
This feature is useful for bootstrapping unknown guest environments and
allows static executables to perform setup actions inside the container
while they need not be part of the guest file system.
This adds an optional `GET` parameter `runsc-sandbox-metrics-filter` which can
be used to filter the set of sandbox metrics requested from each sandbox. In
cases where the metric client isn't interested in learning everything about
the sandboxes, this saves on RPC cost and latency.
This also has the benefit of reducing memory usage of the `metric-server`
further, as it does not need to hold onto data that it will not export.
As the sandbox process is untrusted, the metrics returned are double-checked
on the `metric-server` side to ensure that the filter was respected.
PiperOrigin-RevId: 521055953
This commit implements file descriptor passing from the host to the
guest. It implements a --pass-fd flag that can be specified multiple
times with FD numbers from the host that will be inserted into the file
descriptor table of the guest.
Addresses gotsan-found data race when reading metric registration data over
urpc vs during initialization.
In practice, this can never happen, because the urpc call for metric
registration only happens after the boot sync file descriptor has been
written to, but there's no way for gotsan to know that. So this change just
switches it to an atomic boolean for good measure.
Also verified in `metric.GetSnapshot`, because why not.
PiperOrigin-RevId: 500210642
This metric registration information contains the metadata of all the metrics
that the Sentry is expected to produce during its lifetime, including all
possible field combinations, the types, distribution bucket boundaries, etc.
This will be called during sandbox startup, before starting any container, in
order to save this information in the metrics server so that it can verify the
validity of instrumentation data from the Sentry once the container is
started.
This change has no tests, but coverage is provided in a later change that
provides an end-to-end container tests that the metric server works and
exports data faithfully.
This change is part of a series of changes to support Prometheus-style metrics
in `runsc`. Doing so requires making several seemingly-odd design decisions,
due to the following architectural constraints:
- Prometheus requires an HTTP server serving the `/metrics` endpoint.
- For performance reasons, the `runsc boot` process cannot run the `netpoller`
goroutine.
- Since we don't want to write our own HTTP server implementation, this
means the HTTP endpoint has to be served by a separate process that
remains running during the lifetime of the container.
- The `runsc boot` process is untrusted.
- This means we cannot trust metrics data that comes out of the Sentry.
Therefore, there needs to be an elaborate dance where we pre-register
metric metadata before starting any untrusted workload. Then, the server
relaying the metric data must verify the validity of metric values against
this metric metadata. This avoids leaking metrics, cardinality blow-ups,
and other such DoS vectors.
- This feature needs to be easy-to-use in a typical Docker setting.
- This means having the ability to just say
`--metrics-server=localhost:1337` in the `runsc` runtime entry in
`/etc/docker/daemon.json` and have that Just Work(TM), even when multiple
containers are running.
- Since only one process may listen on a port at a given time, this means
the metric server needs to be able to multiplex requests out to multiple
running sandboxes, and remain alive for the entire duration of either of
these sandboxes. However, it should also die when there are no sandboxes,
so that we don't end up with leftover metric servers lying around.
- For this reason, the metrics server runs *outside* of the usual
per-container cgroups.
- This also saves system resources by not running one server per sandbox.
- The metrics server must be exposed to the outside world, and cannot assume
that its clients are trustworthy.
- For this reason, a metrics server is bound to a runtime root directory,
and double-checks all that the sandboxes it is asked to follow actually
exist in this root directory.
PiperOrigin-RevId: 498076197
This subcommand prints a sandbox's instrumentation data in Prometheus format
to stdout.
This change is part of a series of changes to support Prometheus-style metrics
in `runsc`. Doing so requires making several seemingly-odd design decisions,
due to the following architectural constraints:
- Prometheus requires an HTTP server serving the `/metrics` endpoint.
- For performance reasons, the `runsc boot` process cannot run the `netpoller`
goroutine.
- Since we don't want to write our own HTTP server implementation, this
means the HTTP endpoint has to be served by a separate process that
remains running during the lifetime of the container.
- The `runsc boot` process is untrusted.
- This means we cannot trust metrics data that comes out of the Sentry.
Therefore, there needs to be an elaborate dance where we pre-register
metric metadata before starting any untrusted workload. Then, the server
relaying the metric data must verify the validity of metric values against
this metric metadata. This avoids leaking metrics, cardinality blow-ups,
and other such DoS vectors.
- This feature needs to be easy-to-use in a typical Docker setting.
- This means having the ability to just say
`--metrics-server=localhost:1337` in the `runsc` runtime entry in
`/etc/docker/daemon.json` and have that Just Work(TM), even when multiple
containers are running.
- Since only one process may listen on a port at a given time, this means
the metric server needs to be able to multiplex requests out to multiple
running sandboxes, and remain alive for the entire duration of either of
these sandboxes. However, it should also die when there are no sandboxes,
so that we don't end up with leftover metric servers lying around.
- For this reason, the metrics server runs *outside* of the usual
per-container cgroups.
- This also saves system resources by not running one server per sandbox.
- The metrics server must be exposed to the outside world, and cannot assume
that its clients are trustworthy.
- For this reason, a metrics server is bound to a runtime root directory,
and double-checks all that the sandboxes it is asked to follow actually
exist in this root directory.
PiperOrigin-RevId: 498067941
Including the time when a container start request is
received and the time it is completed in the
ContainerStartedEvent proto message.
PiperOrigin-RevId: 495390114
- Adds IsRunning() control message which returns true if the container is
running.
- Adds a test to verify the result of IsRunning().
PiperOrigin-RevId: 461759652
- Adds a new control message GetExitStatus() which blocks until the container
has finished execution and returns the exit status.
- Tests to verify that the GetExitStatus() works correctly.
PiperOrigin-RevId: 459333916
- Adds SandboxShutdown() control message to destroy sandbox manually.
- Adds a new gVisor API for destroying the sandbox in multi container mode.
- Test to verify the API and the control message works correctly.
PiperOrigin-RevId: 459290099
This change will allow the gVisor sandbox to run multiple containers.
- Added new functions to validate the SentryMultiContainerSpec and the
container mounts.
- Changes to set the target path in container mounts for eg: root target will
be "/container0" and the submounts target will be "/container0/dev".. etc in
multi-container mode.
- Added new fields in the protos: container name in ContainerSpec and
MultiContainerConfig in SentryConfig.
- Updated the sentry to create the mount namespaces for all the containers
during the sentry start as we have all the container mount configs. These
mount namespaces are passed to the control server in a map with the container
name as the key.
- Updated changes in StartContainer():
- Use ContainerSpec instead of SandboxRunSpec.
- No longer create the mount namespaces here and use the ones created by
the sentry.
- Added test to run two containers in multi-container mode using the
SentryMultiContainerSpec.
PiperOrigin-RevId: 454649646
This is the first set of changes to allow multiple containers in a sandbox.
- Changes to allow kernel.Start() without any tasks.
- New control message to StartContainer() in root namespaces.
- Added new function StartSandbox() to keep the existing behavior separate from
when the multi-containers is enabled.
- Test to verify the new control message with one container.
PiperOrigin-RevId: 446792577
All atomic 64 bit ints are changed to atomicbitops.(Ui|I)nt64. A nogo checker
enforces that sync/atomic 64 bit functions are not called.
For reviewers: the interesting changes are in the atomicbitops and checkaligned
packages.
Why do this?
- It is very easy to accidentally use atomic values without sync/atomic funcs.
- We have checkatomics, but this is optional and is forgotten in several places.
- Using a type+checker to enforce this seems less error prone and simpler.
- We get NoCopy protection.
- Use of 64 bit atomics can break 32 bit builds. We have types to handle this
without any runtime cost, so we might as well use them.
PiperOrigin-RevId: 440473398
Add global flags -profile-{block,cpu,heap,mutex} and -trace which
enable collection of the specified profile for the entire duration of a
container execution. This provides a way to definitively start profiling
before that application starts, rather than attempting to race with an
out-of-band `runsc debug`.
Note that only the main boot process is profiled.
This exposed a bug in Task.traceExecEvent: a crash when tracing and
-race are enabled. traceExecEvent is called off of the task goroutine,
but uses the Task as a context, which is a violation of the Task
contract. Switching to the AsyncContext fixes the issue.
Fixes#220
Set stdio ownership based on the container's user to ensure the
user can open/read/write to/from stdios.
1. stdios in the host are changed to have the owner be the same
uid/gid of the process running the sandbox. This ensures that the
sandbox has full control over it.
2. stdios owner owner inside the sandbox is changed to match the
container's user to give access inside the container and make it
behave the same as runc.
Fixes#6180
PiperOrigin-RevId: 384347009