Uncloud L4
Natively Uncloud doesn’t do L4 forwarding. This is an open issue as we are figuring out how to actually do this. But it turns out you can already do this with the current code - well almost.
Buckle up, because there is quite some stuff you may need:
- A patched Uncloud, see this PR for that.
- A custom Caddy build, with the L4 plugin.
- A DNS server, I use atomdns of course.
Caddy⌗
With the following Dockerfile you create a custom caddy image that we will use.
FROM caddy:2.11.2-builder AS builder
RUN xcaddy build \
--with github.com/mholt/caddy-l4
FROM caddy:2.11.2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
The compose.yaml is remarkably short, but we also need a Caddyfile, both are listed here, the Caddyfile first, this tells caddy to forward the DNS traffic to the internal address of the DNS server.
{
layer4 {
udp/:53 {
route {
proxy udp/atomdns.internal:53
}
}
tcp/:53 {
route {
proxy tcp/atomdns.internal:53
}
}
}
}
And the compose.yaml:
services:
caddy:
image: registry.science.ru.nl/cncz/sys/image/caddy:latest
command: caddy run -c /config/Caddyfile
environment:
CADDY_ADMIN: unix//run/caddy/admin.sock
volumes:
- /var/lib/uncloud/caddy:/data
- /var/lib/uncloud/caddy:/config
- /run/uncloud/caddy:/run/caddy
x-ports:
- 80:80@host
- 443:443@host
- 443:443/udp@host
- enp1s0:53:53@host
- enp1s0:53:53/udp@host
x-caddy: Caddyfile
deploy:
mode: global
Where I want to highlight enp1s0:53:53@host and enp1s0:53:53/udp@host which is what the pull requests
adds. As the interface name is shared on all machines, the caddy service can still be globally deployed. If I
were to bind on all interfaces (the default for Uncloud) I trample on uncloudd own use of the port 53.
If you are in the directory where you saved the above files you can just run uc deploy -y and have caddy
running.
atomdns⌗
We use this Dockerfile to build atomdns ourselves.
ARG BUILD_IMAGE=golang:latest
ARG BASE=alpine:latest
FROM --platform=$BUILDPLATFORM ${BUILD_IMAGE} AS build
WORKDIR /tmp
RUN git clone --depth 1 https://codeberg.org/miekg/dns
WORKDIR /tmp/dns/cmd/atomdns
RUN go mod download
RUN CGO_ENABLED=0 go build
FROM ${BASE}
COPY --from=build /tmp/dns/cmd/atomdns/atomdns /atomdns
WORKDIR /
EXPOSE 53 53/udp 443
ENTRYPOINT ["/atomdns"]
The compose file a longer, and includes the Conffile for atomdns to use:
# This compose file configures a atomdns that can be used as the cluster-dns' server.
services:
atomdns:
image: registry.science.ru.nl/cncz/sys/image/atomdns:latest
pull_policy: always
configs:
- source: atomdns_config
target: /etc/Conffile
mode: 0444
command:
- /etc/Conffile
x-ports:
- ctrl.u.science.ru.nl:443/https
deploy:
replicas: 1
volumes:
- atomdns_data:/var/lib/atomdns
volumes:
atomdns_data:
labels:
nl.ru.science.backup: "kopia"
configs:
atomdns_config:
content: |
{
log
root /var/lib/atomdns
dns {
addr [::]:53
}
}
u.science.ru.nl {
uncloud u.science.ru.nl.db {
addr [::]:443
}
dbsqlite u.science.ru.nl.db
}
# add example.org for debugging purposes
example.org {
whoami
log
}
Also deploy that. Note because the database (sqlite) isn’t shared, this can only run on a single machine. Also the example.org zone is there to help in debugging.
When running the above you can send DNS queries to your cluster and they will get answers
% uc ls
NAME MODE REPLICAS IMAGE ENDPOINTS
atomdns replicated 1 registry.science.ru.nl/cncz/sys/image/atomdns:latest https://ctrl.u.science.ru.nl → :443
caddy global 2 registry.science.ru.nl/cncz/sys/image/caddy:latest (custom Caddy config)
debug replicated 1 registry.science.ru.nl/cncz/sys/image/debug:latest
And dig @uncloud1.vm.science.ru.nl a whoami.example.org returns an answer.