Commit 07b4a871 authored by Amy Qualls's avatar Amy Qualls

Merge branch 'ash2k/tunnel-docs' into 'master'

Document reverse gRPC tunnel for Kubernetes Agent

See merge request gitlab-org/gitlab!51859
parents e7c2bdbb dcca1da7
...@@ -134,90 +134,97 @@ of the `kas` receiving the request from the _external_ endpoint to retry and re- ...@@ -134,90 +134,97 @@ of the `kas` receiving the request from the _external_ endpoint to retry and re-
requests. This method ensures a single central component for each request can determine requests. This method ensures a single central component for each request can determine
how a request is routed, rather than distributing the decision across several `kas` instances. how a request is routed, rather than distributing the decision across several `kas` instances.
### API definitions ### Reverse gRPC tunnel
This section explains how the `agentk` -> `kas` reverse gRPC tunnel is implemented.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a video overview of how some of the blocks map to code, see
[GitLab Kubernetes Agent reverse gRPC tunnel architecture and code overview
](https://www.youtube.com/watch?v=9pnQF76hyZc).
#### High level schema
```proto In this example, `Server side of module A` exposes its API to get the `Pod` list
syntax = "proto3"; on the `Public API gRPC server`. When it receives a request, it must determine
the agent ID from it, then call the proxying code which forwards the request to
import "google/protobuf/timestamp.proto"; a suitable `agentk` that can handle it.
message KasAddress { The `Agent side of module A` exposes the same API on the `Internal gRPC server`.
string ip = 1; When it receives the request, it needs to handle it (such as retrieving and returning
uint32 port = 2; the `Pod` list).
}
This schema describes how reverse tunneling is handled fully transparently
message ConnectedAgentInfo { for modules, so you can add new features:
// Agent id.
int64 id = 1; ```mermaid
// Identifies a particular agentk->kas connection. Randomly generated when agent connects. graph TB
int64 connection_id = 2; subgraph kas
string version = 3; server-internal-grpc-server[Internal gRPC server]
string commit = 4; server-api-grpc-server[Public API gRPC server]
// Pod namespace. server-module-a[Server side of module A]
string pod_namespace = 5; server-module-b[Server side of module B]
// Pod name. end
string pod_name = 6; subgraph agentk
// When the connection was established. agent-internal-grpc-server[Internal gRPC server]
google.protobuf.Timestamp connected_at = 7; agent-module-a[Agent side of module A]
KasAddress kas_address = 8; agent-module-b[Agent side of module B]
// What else do we need? end
}
agent-internal-grpc-server -- request --> agent-module-a
message KasInstanceInfo { agent-internal-grpc-server -- request --> agent-module-b
string version = 1;
string commit = 2; server-module-a-. expose API on .-> server-internal-grpc-server
KasAddress address = 3; server-module-b-. expose API on .-> server-api-grpc-server
// What else do we need?
} server-internal-grpc-server -- proxy request --> agent-internal-grpc-server
server-api-grpc-server -- proxy request --> agent-internal-grpc-server
message ConnectedAgentsForProjectRequest {
int64 project_id = 1;
}
message ConnectedAgentsForProjectResponse {
// There may 0 or more agents with the same id, depending on the number of running Pods.
repeated ConnectedAgentInfo agents = 1;
}
message ConnectedAgentsByIdRequest {
int64 agent_id = 1;
}
message ConnectedAgentsByIdResponse {
repeated ConnectedAgentInfo agents = 1;
}
// API for use by GitLab.
service KasApi {
// Connected agents for a particular configuration project.
rpc ConnectedAgentsForProject (ConnectedAgentsForProjectRequest) returns (ConnectedAgentsForProjectResponse) {
}
// Connected agents for a particular agent id.
rpc ConnectedAgentsById (ConnectedAgentsByIdRequest) returns (ConnectedAgentsByIdResponse) {
}
// Depends on the need, but here is the call from the example above.
rpc GetPods (GetPodsRequest) returns (GetPodsResponse) {
}
}
message Pod {
string namespace = 1;
string name = 2;
}
message GetPodsRequest {
int64 agent_id = 1;
int64 connection_id = 2;
}
message GetPodsResponse {
repeated Pod pods = 1;
}
// Internal API for use by kas for kas -> kas calls.
service KasInternal {
// Depends on the need, but here is the call from the example above.
rpc GetPods (GetPodsRequest) returns (GetPodsResponse) {
}
}
``` ```
#### Implementation schema
`HandleTunnelConnection()` is called with the server-side interface of the reverse
tunnel. It registers the connection and blocks, waiting for a request to proxy
through the connection.
`HandleIncomingConnection()` is called with the server-side interface of the incoming
connection. It registers the connection and blocks, waiting for a matching tunnel
to proxy the connection through.
After it has two connections that match, `Connection registry` starts bi-directional
data streaming:
```mermaid
graph TB
subgraph kas
server-tunnel-module[Server tunnel module]
connection-registry[Connection registry]
server-internal-grpc-server[Internal gRPC server]
server-api-grpc-server[Public API gRPC server]
server-module-a[Server side of module A]
server-module-b[Server side of module B]
end
subgraph agentk
agent-internal-grpc-server[Internal gRPC server]
agent-tunnel-module[Agent tunnel module]
agent-module-a[Agent side of module A]
agent-module-b[Agent side of module B]
end
server-tunnel-module -- "HandleTunnelConnection()" --> connection-registry
server-internal-grpc-server -- "HandleIncomingConnection()" --> connection-registry
server-api-grpc-server -- "HandleIncomingConnection()" --> connection-registry
server-module-a-. expose API on .-> server-internal-grpc-server
server-module-b-. expose API on .-> server-api-grpc-server
agent-tunnel-module -- "establish tunnel, receive request" --> server-tunnel-module
agent-tunnel-module -- make request --> agent-internal-grpc-server
agent-internal-grpc-server -- request --> agent-module-a
agent-internal-grpc-server -- request --> agent-module-b
```
### API definitions
- [`agent_tracker/agent_tracker.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/agent_tracker/agent_tracker.proto)
- [`agent_tracker/rpc/rpc.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/agent_tracker/rpc/rpc.proto)
- [`reverse_tunnel/rpc/rpc.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/reverse_tunnel/rpc/rpc.proto)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment