From 958712d9a9ef25aae53ea8d3de2c80d43a08e045 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Mon, 29 Aug 2022 13:16:17 -0400 Subject: [PATCH] expand v0.10.0 notes --- notes/v0.10.0.md | 91 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/notes/v0.10.0.md b/notes/v0.10.0.md index dbab8279..b871292c 100644 --- a/notes/v0.10.0.md +++ b/notes/v0.10.0.md @@ -1,37 +1,92 @@ This is a big release that overhauls the networking stack and adds a new kind of value: a *thunk addr*. -Thunks can now provide ports: -```clojure -(-> ($ python -m http.server 80) - (with-image (linux/python)) - (with-port :http 80)) -``` - -Ports can be referenced using a [thunk addr]. A thunk addr is a lot like a -[thunk path] except it represents to a TCP address instead of a filesystem -path. +## thunk ports & addrs +Thunks can now provide TCP ports using [`with-port`] which can be referenced +with [`addr`] to construct a [thunk addr]: ```clojure (def srv - (-> ($ python -m http.server 80) + (-> ($ python -m http.server "80") (with-image (linux/python)) (with-port :http 80))) (-> ($ wget (addr srv :http "http://$host:$port")) - (with-image (linux/ubuntu)) + (with-image (linux/alpine)) run) ``` -The server thunk runs lazily. The client thunk doesn't run until the server's -ports are listening. +A thunk addr is a lot like a [thunk path] except it represents to a TCP address +instead of a filesystem path. + +When using a thunk addr you don't need to worry about managing the lifecycle of +the service that the thunk represents. The service will be run lazily, +de-duplicated across multiple Bass runs, and stopped when all clients go away. + +The advantage of this approach over traditional service lifecycle management +parallels the advantages of using thunk paths instead of managing state in a +local filesystem. It allows thunks that depend on services provided by other +thunks to remain reproducible, just like thunks that depend on files created by +other thunks. -Thunks no longer run in the host network. Instead they run in a [bridge -network] to prevent port collisions. +[`with-port`]: https://bass-lang.org/stdlib.html#binding-with-port +[`addr`]: https://bass-lang.org/stdlib.html#binding-addr +[thunk path]: https://bass-lang.org/bassics.html#term-thunk%20path +[thunk addr]: https://bass-lang.org/bassics.html#term-thunk%20addr -Thunks use DNS to address each other in order to maximize caching. (Using IPs -would introduce a source of randomness!) + +## bridge networking & DNS + +To prevent port collisions, thunks no longer run in the host network. Instead +they run in a [bridge network] where each thunk has its own IP and reaches +other thunks using DNS. + +Using DNS is important because IPs are not reproducible. If thunks reached each +other using direct container IPs then caches would be busted every time a +service runs. + +Now that thunks run in their own network, you can't use Bass to run and expose +services to the host machine. This may be added in a future release via port +forwarding. Alternatively you could take the `path-name` (a bit of a misnomer) +of the thunk and reverse-proxy to its container port using the same DNS server +that thunks use. [bridge network]: https://www.cni.dev/plugins/current/main/bridge/ +[`path-name`]: https://bass-lang.org/stdlib.html#binding-path-name + + +## automatic TLS + +Thunks may also use TLS. A unique "bass" certificate authority is generated by +the runtime and automaticaly trusted by all thunks that it runs. + +To generate a certificate for a thunk, use [`with-tls`]: + +```clojure +(def registry-mirror + (let [config {:version "0.1" + :http {:addr "0.0.0.0:5000" + :tls {:certificate "/registry.crt" + :key "/registry.key"}} + :storage {:filesystem {:rootdirectory "/var/lib/registry"}} + :proxy {:remoteurl "https://registry-1.docker.io"}}] + (-> ($ registry serve (mkfile ./config.yml (json config))) + (with-image (linux/registry)) + (with-tls /registry.crt /registry.key) + (with-port :http 5000)))) + +(defn main [] + (-> (from (linux/alpine) + ($ apk add curl) + ($ curl (addr registry-mirror :http "https://$host:$port/v2/"))) + run)) +``` + +Generating TLS certs is a necessary part of the puzzle because thunks use their +own hash as their hostname and DNS entry. It would be impossible to generate a +cert ahead of time and pass it to the thunk because doing so would change the +hash! + +[`with-tls`]: https://bass-lang.org/stdlib.html#binding-with-tls