(Document status: mostly complete)
Much of the architecture of Apocryph revolves around two key pieces, the "Publisher Client" and the "Provider Client". A publisher is a buyer in the Apocryph network seeking to provision their pod/container on the network. A provider is a seller seeking to offer their hardware for rent.
The planned version of Apocryph takes care of matching the two and provisioning the pod on a specific target provider. While it offers a way to manually pick a provider, it defaults to automatically picking one for the user. However, it does not take care of operational issues that might subsequently arise; specifically, it does not take care of rescheduling pods when a provider becomes unavailable nor does it make any guarantees about uptime or availability of data—those will be handled in later versions. Such concerns are kept track of in the backlog.
flowchart
classDef Go stroke:#0ff
classDef Chain stroke:#f0f
classDef Lib stroke:#000
classDef User stroke:#ff0
subgraph Publisher machine
RegistryPub[K8s Registry]:::Lib
PubCl[Publisher Client]:::Go
end
External[External Clients]:::User
Network[libp2p/IPFS]:::Lib
subgraph TEE
ProCl[Provider Client]:::Go
KubeCtl[K8s Control Plane]:::Lib
RegistryPro[K8s Registry]:::Lib
Http[HTTP Facade]:::Lib
App[Application Pod]:::User
end
subgraph On-chain
RegistryC[Registry Contract]:::Chain
PaymentC[Payment Contract]:::Chain
end
%% KubeCtl -- Execute --> ProCl
RegistryC -- List Providers --> PubCl -- Create --> PaymentC -- Monitor --> ProCl
RegistryPub -- App Container --> PubCl
PubCl -- Encrypted App Container --> Network -- Execution request --> ProCl
ProCl -- App Container --> RegistryPro --> App
ProCl -- Configuration --> KubeCtl
KubeCtl -- Execute --> Http -- Metrics --> KubeCtl -- Execute --> App
External -- Requests --> Http -- Requests --> App
As a sequence of steps:
- The user starts the Publisher Client to deploy a container
- The Publisher Client collects the Pod Manifest
- The Publisher Client gets the list of providers from the Registry Contract
- The Publisher Client selects a provider, using the configured strategy (automatic or by asking the user to manually make a choice)
- The Publisher Client creates a Payment Contract and transfers the initial payment amount (possibly in parallel with steps 5-6)
- The Publisher Client bundles up the Pod Manifest, any related resources, and the Payment Contract's address and sends them to the Provider Client over the Deployment sub-protocol, encrypted
- The Provider Client creates the relevant configurations for the Pod using the Kubernetes API, including an HTTP Scaler, an Application Pod, and Monitoring
- The Provider Client confirms receiving the manifest and resources
- When HTTP requests come in, the HTTP Scaler contacts the Kubernetes API in order to scale the Application Pod up
- The Application Pod is started using the configuration from earlier
- The Application Pod handles the incoming requests
- After a period of no requests the Scaler uses the Kubernetes API to scale the Application Pod down
- The Monitoring component keeps track of how many e.g. CPU-seconds the Application Pod has run for, and forwards these metrics to the Provider Client
- The Provider Client submits the metrics to the Payment Contract and is then able to claim the payment due
- Whenever the Payment Contract runs out of funds, the Provider Client removes the related configurations from Kubernetes
Sequence Diagram
sequenceDiagram
box
actor User as User
participant PubCl as Publisher Client
end
box
participant RegistryC as Registry Contract
participant PaymentC as Payment Contract
participant IPFS as IPFS Network
end
box
participant ProCl as Provider Client
participant RegistryD as Docker Registry
participant K8s as Kubernetes API
participant Monitoring as Monitoring
participant HTTP as HTTP Scaler
participant App as Application Pod
end
%% 0.
%% 1.
User ->>+ PubCl: Pod Manifest
User ->> PubCl: Pod Container
%% 2.
PubCl -->>+ RegistryC: List Providers
RegistryC ->>- PubCl:
%% 3.
PubCl ->> PubCl: Select Provider
%% 4.
%%PubCl ->>+ ProCl: Initial execution request
%%ProCl -->>- PubCl: Confirmation
PubCl ->> PaymentC: Create & Configure
%% 5.
PubCl ->>+ IPFS: Upload Encrypted Container
PubCl ->>+ ProCl: Execution request
%% 6.
ProCl -->> IPFS: Download Container
IPFS ->>- ProCl:
ProCl ->>+ PaymentC: Monitor
ProCl ->> K8s: Configure Application & Scaler
K8s ->>+ HTTP: Start Intercepting
%% 7.
ProCl -->>- PubCl: Confirmation
PubCl -->>- User:
%% 8.
User ->>+ HTTP: HTTP Request
HTTP ->>+ K8s: Scale up
%% 9.
K8s ->>- App: Start w/ Secrets
K8s ->>+ Monitoring: App up
App ->>+ RegistryD: Fetch Image
RegistryD ->>+ IPFS:
IPFS ->>- RegistryD: OCI Image
RegistryD ->>- App:
App ->> App: Decrypt Image
%% 10.
HTTP ->>+ App: Request
App ->>- HTTP: Response
HTTP ->>- User:
%% 11.
note over HTTP: Time passes
HTTP ->>+ K8s: Scale down
K8s -x- App: Stop
Monitoring ->>- K8s: App down
%% 12.
ProCl ->>+ Monitoring: Get Metrics
Monitoring ->>- ProCl:
%% 13.
ProCl ->>+ PaymentC: Submit Metrics
PaymentC -->>- ProCl:
%% 14.
User ->>+ PaymentC: Unlock Funds
PaymentC -->> User:
PaymentC -->>+ ProCl:
deactivate PaymentC
opt insufficient funds left
ProCl ->>- K8s: Remove Configurations
K8s ->> HTTP: Stop intercepting
deactivate HTTP
end
deactivate PaymentC