Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add crate for stress testing the shims #734

Merged
merged 10 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
585 changes: 470 additions & 115 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"crates/containerd-shim-wasmtime",
"crates/containerd-shim-wasmer",
"crates/containerd-shim-wamr",
"crates/stress-test",
"benches/containerd-shim-benchmarks",
]
resolver = "2"
Expand Down
27 changes: 27 additions & 0 deletions crates/stress-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "stress-test"
edition.workspace = true
version.workspace = true
license.workspace = true
readme.workspace = true
repository.workspace = true
homepage.workspace = true

[dependencies]
anyhow = { workspace = true }
trapeze = "0.7"
prost = "0.13"
prost-types = "0.13"
tokio = { workspace = true, features = ["macros", "fs", "process", "signal"] }
humantime = "2.1.0"
tempfile = { workspace = true }
oci-spec = { workspace = true }
containerd-shim-wasm-test-modules.workspace = true
clap = { version = "4", features = [ "derive"] }
log = { workspace = true }
env_logger = { workspace = true }
nix = { workspace = true, features = ["process", "signal"] }

[package.metadata.cargo-machete]
# used by the bindings generated by trapeze
ignored = ["prost", "prost-types"]
19 changes: 19 additions & 0 deletions crates/stress-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Shim stress test

This crate provides a way to stress test the shim.

## Getting started

```bash
cargo run -p stress-test -- --help
```

Build some shim
```bash
make build-wasmtime
```

then stress test it
```bash
cargo run -p stress-test -- $PWD/target/x86_64-unknown-linux-gnu/debug/containerd-shim-wasmtime-v1
jprendes marked this conversation as resolved.
Show resolved Hide resolved
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
Copyright The containerd Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

syntax = "proto3";

package containerd.task.v2;

import "google/protobuf/any.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "github.com/containerd/containerd/api/types/mount.proto";
import "github.com/containerd/containerd/api/types/task/task.proto";

option go_package = "github.com/containerd/containerd/api/runtime/task/v2;task";

// Shim service is launched for each container and is responsible for owning the IO
// for the container and its additional processes. The shim is also the parent of
// each container and allows reattaching to the IO and receiving the exit status
// for the container processes.
service Task {
rpc State(StateRequest) returns (StateResponse);
rpc Create(CreateTaskRequest) returns (CreateTaskResponse);
rpc Start(StartRequest) returns (StartResponse);
rpc Delete(DeleteRequest) returns (DeleteResponse);
rpc Pids(PidsRequest) returns (PidsResponse);
rpc Pause(PauseRequest) returns (google.protobuf.Empty);
rpc Resume(ResumeRequest) returns (google.protobuf.Empty);
rpc Checkpoint(CheckpointTaskRequest) returns (google.protobuf.Empty);
rpc Kill(KillRequest) returns (google.protobuf.Empty);
rpc Exec(ExecProcessRequest) returns (google.protobuf.Empty);
rpc ResizePty(ResizePtyRequest) returns (google.protobuf.Empty);
rpc CloseIO(CloseIORequest) returns (google.protobuf.Empty);
rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty);
rpc Wait(WaitRequest) returns (WaitResponse);
rpc Stats(StatsRequest) returns (StatsResponse);
rpc Connect(ConnectRequest) returns (ConnectResponse);
rpc Shutdown(ShutdownRequest) returns (google.protobuf.Empty);
}

message CreateTaskRequest {
string id = 1;
string bundle = 2;
repeated containerd.types.Mount rootfs = 3;
bool terminal = 4;
string stdin = 5;
string stdout = 6;
string stderr = 7;
string checkpoint = 8;
string parent_checkpoint = 9;
google.protobuf.Any options = 10;
}

message CreateTaskResponse {
uint32 pid = 1;
}

message DeleteRequest {
string id = 1;
string exec_id = 2;
}

message DeleteResponse {
uint32 pid = 1;
uint32 exit_status = 2;
google.protobuf.Timestamp exited_at = 3;
}

message ExecProcessRequest {
string id = 1;
string exec_id = 2;
bool terminal = 3;
string stdin = 4;
string stdout = 5;
string stderr = 6;
google.protobuf.Any spec = 7;
}

message ExecProcessResponse {
}

message ResizePtyRequest {
string id = 1;
string exec_id = 2;
uint32 width = 3;
uint32 height = 4;
}

message StateRequest {
string id = 1;
string exec_id = 2;
}

message StateResponse {
string id = 1;
string bundle = 2;
uint32 pid = 3;
containerd.v1.types.Status status = 4;
string stdin = 5;
string stdout = 6;
string stderr = 7;
bool terminal = 8;
uint32 exit_status = 9;
google.protobuf.Timestamp exited_at = 10;
string exec_id = 11;
}

message KillRequest {
string id = 1;
string exec_id = 2;
uint32 signal = 3;
bool all = 4;
}

message CloseIORequest {
string id = 1;
string exec_id = 2;
bool stdin = 3;
}

message PidsRequest {
string id = 1;
}

message PidsResponse {
repeated containerd.v1.types.ProcessInfo processes = 1;
}

message CheckpointTaskRequest {
string id = 1;
string path = 2;
google.protobuf.Any options = 3;
}

message UpdateTaskRequest {
string id = 1;
google.protobuf.Any resources = 2;
map<string, string> annotations = 3;
}

message StartRequest {
string id = 1;
string exec_id = 2;
}

message StartResponse {
uint32 pid = 1;
}

message WaitRequest {
string id = 1;
string exec_id = 2;
}

message WaitResponse {
uint32 exit_status = 1;
google.protobuf.Timestamp exited_at = 2;
}

message StatsRequest {
string id = 1;
}

message StatsResponse {
google.protobuf.Any stats = 1;
}

message ConnectRequest {
string id = 1;
}

message ConnectResponse {
uint32 shim_pid = 1;
uint32 task_pid = 2;
string version = 3;
}

message ShutdownRequest {
string id = 1;
bool now = 2;
}

message PauseRequest {
string id = 1;
}

message ResumeRequest {
string id = 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the last review, was head down on a few different this this week and had some power outages.

Is there a reason we are coping in the protos and generating them when we already have a dep on rust-extensions which has these protos build for us?

https://github.com/containerd/rust-extensions/blob/main/crates/shim-protos/src/events.rs

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Copyright The containerd Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

syntax = "proto3";

package containerd.services.events.ttrpc.v1;

import "github.com/containerd/containerd/protobuf/plugin/fieldpath.proto";
import "google/protobuf/any.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/containerd/containerd/api/services/ttrpc/events/v1;events";

service Events {
// Forward sends an event that has already been packaged into an envelope
// with a timestamp and namespace.
//
// This is useful if earlier timestamping is required or when forwarding on
// behalf of another component, namespace or publisher.
rpc Forward(ForwardRequest) returns (google.protobuf.Empty);
}

message ForwardRequest {
Envelope envelope = 1;
}

message Envelope {
option (containerd.plugin.fieldpath) = true;
google.protobuf.Timestamp timestamp = 1;
string namespace = 2;
string topic = 3;
google.protobuf.Any event = 4;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Copyright The containerd Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

syntax = "proto3";

package containerd.types;

option go_package = "github.com/containerd/containerd/api/types;types";

// Mount describes mounts for a container.
//
// This type is the lingua franca of ContainerD. All services provide mounts
// to be used with the container at creation time.
//
// The Mount type follows the structure of the mount syscall, including a type,
// source, target and options.
message Mount {
// Type defines the nature of the mount.
string type = 1;

// Source specifies the name of the mount. Depending on mount type, this
// may be a volume name or a host path, or even ignored.
string source = 2;

// Target path in container
string target = 3;

// Options specifies zero or more fstab style mount options.
repeated string options = 4;
}
Loading
Loading