cluster
The cluster: this node's identity, the other nodes, and the calls between them.
Every node runs this same server. What a node does is its roles: a
frontend signs users in and proxies their sessions, a runtime runs
sessions. Nothing is a master; what the nodes share is the object store
(store), and what each knows of the others it asks them.
- Identity. A node is its name (
node_name; by default its container's name in Docker, else the host name): its record,cluster/nodes/<name>.yml, publishes its current server key, the address of its peer listener, and the certificate that listener serves. A node started again with an empty configuration directory but the same name and storage takes its record over with a new key and is the same node. With a bucket, a node that can write it is a member as soon as it registers, since the bucket's keys admit to everything anyway; a node of a file store takes part once its record is approved, and the first node of an empty store approves itself. A node of a file store that registers under a new name while every other record carries its own address or key was renamed: it takes those records' place (register_self). - Peer calls. A node calls another on its peer listener over TLS pinned to
the certificates of the approved records, and signs each request with its
server key (
sign_request,verify_request) over the path as it goes on the wire, percent-encoded. A frontend may make a call act as a user (act), which is how a user's request reaches the node that holds the session or home directory it is about (forward). - Live state. Sessions stay with the node that runs them. Every node asks
every other for its sessions and load each
peer_poll_secondsand keeps the answers (PEERS), which placement, limits, and the dashboard read. A count taken from them is only as fresh as the last poll, so a launch of a user with limits holds the user's launch lease (lease) from the check to the session's registration, and two frontends cannot admit one user twice. - Joining. A node with a bucket registers itself and is in. A node with a
join code asks a node of the cluster (
join), proves the code without sending it, and from then on keeps the shared records on the node that holds them (store.PeerStore).
attributelogger= logging.getLogger(__name__)attributePEER_NAME= 'sealskin-peer'attributeSCHEME= 'SealSkin-Node'attributeTOKEN_SECONDS= 60attributeJOIN_CODE_SECONDS= 3600attributeMISSED_POLLS= 3attributeDEFAULT_POOL= 'default'attributeLEASE_SECONDS= 120attributeNODE_ID= ''attributeNODESdict[str, dict[str, Any]]= {}attributePOOLSdict[str, dict[str, Any]]= {}attributePEERSdict[str, dict[str, Any]]= {}attributeHOMESdict[str, dict[str, str]]= {}attributereload_proxyAny= Noneattributestore_wake= asyncio.Event()