Talking to Containerd gRPC
Containerd is a fantastic tool that lets you manage containers with ease and efficiency. It is the core component of many popular platforms, such as Docker, Kubernetes, and Amazon ECS.
But how does it work? And how can you interact with it? In this article, I will show you:
1. What is Containerd and why it is so important for the IT industry
2. What is gRPC and how it enables fast and flexible communication between applications
3. How to talk to Containerd using grpcurl, a handy command-line tool for testing gRPC services
4. How to proxy Containerd unix socket over TCP, so you can access it from any network
5. How to talk to Containerd using Postman, a powerful and user-friendly tool for API development
By the end of this article, you will have a better understanding of Containerd and its capabilities, and you will be able to use different tools to explore and manipulate its features. Let’s get started!
What is Containerd:
Containerd is a powerful tool that enables developers and operators to run and manage containers efficiently and securely. It is a core component of many popular container platforms, such as Docker, Kubernetes, and Amazon ECS. It provides a low-level API for interacting with containers, images, storage, networks, and other essential features. Also it is designed to be lightweight, fast, and reliable, while also supporting advanced functionality such as live migration, checkpoint and restore, and remote execution. Containerd is so important for the IT industry because it simplifies the deployment and management of applications across different environments and platforms, and helps to improve the performance, scalability, and portability of applications, while also reducing the complexity and overhead of managing infrastructure. It is is an open source project that is widely adopted and supported by the community and the industry, and it is the future of container technology and a key enabler of cloud-native development.
What is gRPC:
gRPC is a modern, high-performance framework that evolves the age-old remote procedure call (RPC) protocol. It allows you to communicate between different applications as if they were local objects. gRPC uses “Protocol Buffers” as its interface definition language and message interchange format, which are fast, flexible, and easy to use. gRPC also supports features like: authentication, bidirectional streaming, flow control, cancellation, and timeouts. It is open source and widely adopted by many organizations for various use cases.
How to talk to Containerd:
mkdir talk2containerd
its better to create a directory for our commands on containerd installed machine.
Contained uses gRPC for communication, default path for Containerd configuration on Linux machines is: ‘/etc/containerd/config.toml’.
address of socket that listens for incoming gRPC requests is like:
```
[grpc]
address = “/run/containerd/containerd.sock”
```
In this config, Containerd uses a Linux socket to listen on gRPC requests.
to communicate with a gRPC endpoint, we can use ‘grpcurl’, it is a simple tool written in golang that mimics famous curl command. to install grpcurl in linux, try these commands to install it on a containerd node:
wget https://github.com/fullstorydev/grpcurl/releases/download/v1.8.7/grpcurl_1.8.7_linux_x86_64.tar.gz
tar xzvf grpcurl_*_linux_x86_64.tar.gz
sudo cp grpcurl /usr/bin/
sudo chmod +x /bin/grpcurl
now you can test it by running: ‘grpcurl — version’.
now we need to get .proto for containerd. .proto files define how we could talk to a gRPC endpoint, thats why we call protobuff a (Interface Definition Language).
the simplest proto file in containerd, is version api, which just responds with containerd version and revision:
https://github.com/containerd/containerd/blob/main/api/services/version/v1/version.proto
if you open it you see its a simple definition of endpoint:
syntax = “proto3”;
package containerd.services.version.v1;
import “google/protobuf/empty.proto”;
option go_package = “github.com/containerd/containerd/api/services/version/v1;version”;service Version {
rpc Version(google.protobuf.Empty) returns (VersionResponse);
}message VersionResponse {
string version = 1;
string revision = 2;
}
try this command to get it on our containerd node:
wget https://github.com/containerd/containerd/raw/main/api/services/version/v1/version.protonow you can try talking to containerd:
sudo grpcurl -plaintext -proto version.proto -unix /run/containerd/containerd.sock containerd.services.version.v1.Version/Versionon successful effort you will get a json output like:
{
"version": "1.6.18",
"revision": "2456e983eb9e37e47538f59ea18f2043c9a73640"
} Congrats! now lets get a list of containers!
wget https://github.com/containerd/containerd/raw/main/api/services/containers/v1/containers.proto
sudo grpcurl -plaintext -proto containers.proto -unix /run/containerd/containerd.sock containerd.services.containers.v1.Containers/Listyou will see:
ERROR:
Code: FailedPrecondition
Message: namespace is required: failed preconditionbecause Containerd requires a namespace to list containers, if you have ctr installed, you can run: ```sudo ctr ns ls``` to get a list of namespaces, if you have containerd installed with kubernetes, a k8s.io namespace will be present. lets try again of gRPC call:
sudo grpcurl -rpc-header "containerd-namespace: k8s.io" -plaintext -proto containers.proto -unix /run/containerd/containerd.sock containerd.services.containers.v1.Containers/Listas you see we are passing namespace name in rpc headers to our endpoint.
- also you could get list of namespaces using a gRPC call:
wget https://github.com/containerd/containerd/blob/main/api/services/namespaces/v1/namespace.proto
sudo grpcurl -plaintext -proto namespace.proto -unix /run/containerd/containerd.sock containerd.services.namespaces.v1.Namespaces/ListHow to proxy Containerd unix socket over TCP:
what if we need to call containerd gRPC endpoint from another machine?
there is a solution to share a the endpoint without even touching the containerd config.toml file:
there is project on github, named: “csi-grpc-proxy”
Actually i tried to use nginx as a proxy, its should be possible but its not as easy as it appears! so lets just this simple tool:
wget https://github.com/democratic-csi/csi-grpc-proxy/releases/download/v0.5.3/csi-grpc-proxy-v0.5.3-linux-amd64
sudo cp csi-grpc-proxy-*-linux-amd64 /bin/csi-grpc-proxy
sudo chmod +x /bin/csi-grpc-proxyas stated in csi-grpc-proxy github page, we need to pass configuration parameters as environment variables:
sudo PROXY_TO=unix:///run/containerd/containerd.sock BIND_TO=tcp://0.0.0.0:2140 csi-grpc-proxyon a successful effort, you should see:
BIND_TO [tcp://0.0.0.0:2140] is ready!now open another terminal or put a ‘&’ on the end of previous command to put it in background to try grpcurl on a tcp address:
wget https://github.com/containerd/containerd/raw/main/api/services/version/v1/version.proto
grpcurl -plaintext -proto version.proto 127.0.0.1:2140 containerd.services.version.v1.Version/Version- ** Keep in mind that exposing containerd endpoint on a network has severe security consequences.
lets make out proxy a systemd service:
sudo vim /lib/systemd/system/grpc-proxy.service :
Description=grpc proxy to containerd by aref
Wants=network-online.target
After=network-online.target
[Service]
Environment=BIND_TO=tcp://0.0.0.0:2140
Environment=PROXY_TO=unix:///run/containerd/containerd.sock
ExecStart=/bin/csi-grpc-proxy
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.targetsudo systemctl enable grpc-proxy.service
sudo systemctl start grpc-proxy.serviceHow to talk to Containerd using Postman:
Postman is a powerful tool that helps you test, document, and share APIs. With Postman, you can create requests, organize them into collections, run tests, and generate reports. You can also collaborate with your team and publish your APIs to the public. Postman is easy to use and has a friendly interface that lets you explore the possibilities of APIs.
to use gRPC requests in Postman, you need to install Postman and log into it with an email address.
then you can create a workspace, or just use default ‘My Workspace’:
then create a new collection:
new lets create a new request:
select grpc in request type:
i used ssh tunneling to tunnel our tcp proxy gRPC endpoint to my PC:
# tunnel 2140 from my containerd node to my local 2140 port
ssh devops@my-containerd-node -L2140:127.0.0.1:2140now enter 127.0.0.1:2140 ( your-node:2140 if you have direct access) in url box:
as you see in “select method” box, you see options to define .proto file.
just click on “import a .proto file”.
then you can use ‘https://github.com/containerd/containerd/raw/main/api/services/version/v1/version.proto’ address or just select it locally from your machine. and click Next
new set a name for your new api:
and Click on + Craete a new API, then “Create new API”
now in select method box you can see “Version” method:
Select it and click on “Invoke”.
on a successful effort you should see version and revision in Response box:
now to get a list of containers we need to add Containers .proto file into postman.
to save time, just click on APIs -> Containerd (that we created before) -> definition → add file
name it Containers.proto
then just open: ‘https://raw.githubusercontent.com/containerd/containerd/main/api/services/containers/v1/containers.proto’, select all and copy, then paste it to your new file. then click save
now right click on you new Containers.proto file and click “Mark as root”
now in Select method box, you can see new Methods such as List, Get, Create…
as you remember we need namespace name to list containers, so in Metadata tab, enter the headers we used before:
you can see list of your containers in “Response” tab.
Finale
now we have learned to proxy containerd unix socket and talk to it using grpcurl and postman, you can extend your exprience by trying to alter containers or create new ones.
