kata #
The Kata Containers guest protocols in pure OCaml.
Kata Containers runs each container in its own lightweight VM. The host
runtime creates the VM and then tells the agent inside it what to run, using
ttrpc on a single vsock
port. ttrpc is protobuf RPC over a raw stream socket, with no HTTP/2 in
between. vsock (AF_VSOCK) is a socket family that carries traffic between a
virtual machine and its host without a network; its addresses are a context
id, which names the VM, and a port.
kata.agent is the guest side of that exchange written as OCaml values, and
does no I/O itself. It has hand-written
nox-protobuf codecs for
the grpc.AgentService messages a host needs, plus the typed method table
that names them. kata.oci encodes an OCI runtime configuration from the
runc library as the agent's grpc.Spec message. That configuration is the
config.json of the Open Container Initiative runtime specification, which
gives the process to run, its root filesystem and mounts, its namespaces and
its resource limits.
Installation #
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam install kata
Usage #
Each RPC is a Ttrpc.Method.t that pairs the service-qualified name with the
request and response codecs. A host, a test and the pure Ttrpc.Client state
machine all drive a method in the same way:
# Ttrpc.Method.service Kata_agent.Agent.process_wait
- : string = "grpc.AgentService"
# Ttrpc.Method.name Kata_agent.Agent.read_stdout
- : string = "ReadStdout"
# Protobuf.to_string
(Ttrpc.Method.request Kata_agent.Agent.process_wait)
{ Kata_agent.Process.Wait.container_id = "c1"; exec_id = "" }
- : string = "\n\002c1"
Over a connected vsock, Ttrpc_eio.Client.call issues the same method
against a running agent:
let exit_status ~sw ~clock flow ~container_id =
let client = Ttrpc_eio.Client.connect ~sw ~clock flow in
match
Ttrpc_eio.Client.call client Kata_agent.Agent.process_wait
{ Kata_agent.Process.Wait.container_id; exec_id = "" }
with
| Ok { status } -> Ok status
| Error e -> Error (Fmt.str "%a" Ttrpc_eio.Client.pp_error e)
What is covered #
The service declares many more methods than kata.agent carries. The library
has the ones a host needs to start a sandbox, run a container in it and watch
that container:
CreateSandbox, DestroySandbox, CreateContainer, StartContainer,
ExecProcess, SignalProcess, WaitProcess, ReadStdout, ReadStderr,
CopyFile and GetGuestDetails. agent.proto makes the first of those the
precondition for the rest: "We allow only one sandbox per agent and implicitly
require that CreateSandbox is called before other sandbox/network calls."
health.proto declares a second service on the same connection, grpc.Health,
and Kata_agent.Health carries its Check, the liveness poll a host sends
before anything else and which an agent with no sandbox still answers.
CreateContainerRequest.OCI and ExecProcessRequest.process are the two
fields whose types come from oci.proto. kata.agent carries them as encoded
message bodies without decoding them, so a request round-trips byte for byte
(see Kata_agent.Oci). kata.oci builds those bodies from a
Runc.Config.t or a Runc.Process.t, and refuses a configuration that
grpc.Spec cannot express, such as a process umask, an idmapped mount or a
seccomp default errno.
Spec #
protos/ vendors agent.proto and its import closure
(oci.proto, csi.proto, types.proto and google/protobuf/empty.proto)
verbatim from
kata-containers/kata-containers,
src/libs/protocols/protos/. They keep their upstream Apache-2.0 terms, and were
taken at kata-containers commit
84a479111f1a08437ac2bfe232ab2590433da7ca.
Each module cites the messages and field numbers it implements.
test/interop/kata-go/ replays wire bytes produced by
google.golang.org/protobuf from those same vendored schemas, and asserts
that this library's encoders produce identical bytes
(REGEN=1 dune build @traces refreshes them).
Related work #
- kata-containers/kata-containers is the agent (Rust) and the host runtime (Go and Rust) this protocol connects.
- ttrpc is the transport
underneath, implementing containerd's
PROTOCOL.md. - vaccel is another ttrpc agent protocol in OCaml, with the same shape and a different service.
- nox-protobuf is the codec library the messages are written with.
License #
ISC. See LICENSE.md. The files under protos/ are third-party
and keep their own terms; see protos/README.md.