call to arms - usenix · arm64 debian stretch dockerfile from debian:stretch-slim as builder run...

98
Call to ARMs: adopting an arm64 server into x86 infrastructure Ignat Korchagin @secumod

Upload: others

Post on 23-May-2020

14 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Call to ARMs:adopting an arm64 server into x86 infrastructureIgnat Korchagin @secumod

Page 2: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

$ whoami

● Platform engineer at Cloudflare

● Passionate about security and crypto

● Enjoy low level programming

Page 3: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why?

Page 4: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Vendor lock-in

Page 5: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Save the power

Page 6: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cut equipment costs

Page 7: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Security

Page 8: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

Page 9: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space

Page 10: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient

Page 11: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient● huge developer community

Page 12: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient● huge developer community● first class support in Linux

Page 13: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient● huge developer community● first class support in Linux● established tools

Page 14: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient● huge developer community● first class support in Linux● established tools● > 32 bits

Page 15: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Why ARM64?

● performs well in the mobile/IoT space● potentially more power-efficient● huge developer community● first class support in Linux● established tools● > 32 bits● mitigates the RISC ;)

Page 16: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Initial benchmarks

Page 17: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

So you have an ARM64 server

● Falkor core● 46 cores● 2.5 GHz● Thermal design power

120W○ compared to 170W Skylake

Page 18: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Public key cryptography (single core)

Page 19: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Public key cryptography (all cores)

Page 20: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Symmetric cryptography (single core)

Page 21: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Symmetric cryptography (all cores)

Page 22: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Gzip (single core)

Page 23: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Gzip (all cores)

Page 24: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Brotli (single core)

Page 25: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Brotli (all cores)

Page 26: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

nginx (with power!)

Page 27: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Putting an ARM64 server in a DC

Page 28: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Initial integration in the DC

Page 29: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Edge server software stack

Linux kernel

RAM-based basic root filesystem

nginxnginxnginxnginxnginxOther apps and services

nginxnginxOther apps and services

Page 30: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Consider your developers

Page 31: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64

production arch != developer arch

Page 32: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64

production arch != developer arch

● need to (cross-)compile packages for a different architecture

Page 33: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64

production arch != developer arch

● need to (cross-)compile packages for a different architecture

● cannot run even basic unit tests locally

Page 34: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64 options

● cross-compiling○ relatively easy, but requires many changes○ potential side-effects (ex. library paths)

Page 35: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64 options

● cross-compiling○ relatively easy, but requires many changes○ potential side-effects (ex. library paths)

● native builds on arm64 servers○ no spare hardware○ chicken-and-egg problem: requires setting up an

arm64 server and we need packages for it

Page 36: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Building packages for ARM64 options

● cross-compiling○ relatively easy, but requires many changes○ potential side-effects (ex. library paths)

● native builds on arm64 servers○ no spare hardware○ chicken-and-egg problem: requires setting up an

arm64 server and we need packages for it● ???

Page 37: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Edge server software stack

Linux kernel

RAM-based basic root filesystem

nginxnginxnginxnginxnginxOther apps and services

nginxnginxOther apps and services

Page 38: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cross-compiling Linux kernel● need a cross-compiler

○ sudo apt-get install crossbuild-essential-arm64

Page 39: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cross-compiling Linux kernel● need a cross-compiler

○ sudo apt-get install crossbuild-essential-arm64

● need to adjust kernel build system to call the cross-compiler○ make (xxxconfig) => make ARCH=arm64

CROSS_COMPILE=aarch64-linux-gnu- O=arm64build (xxxconfig)

Page 40: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cross-compiling Linux kernel● need a cross-compiler

○ sudo apt-get install crossbuild-essential-arm64

● need to adjust kernel build system to call the cross-compiler○ make (xxxconfig) => make ARCH=arm64

CROSS_COMPILE=aarch64-linux-gnu- O=arm64build (xxxconfig)

● need a working kernel configuration file○ cp config-amd64 .config

○ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- oldconfig

Page 41: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 Linux kernel caveats● need to trace down and install many arm64 build

dependencies for perf○ otherwise perf is very limited

Page 42: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 Linux kernel caveats● need to trace down and install many arm64 build

dependencies for perf○ otherwise perf is very limited

● need to trace down and enable required hardware modules○ our OOB console access did not work until we enabled some

non-standard serial driver

Page 43: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 Linux kernel caveats● need to trace down and install many arm64 build

dependencies for perf○ otherwise perf is very limited

● need to trace down and enable required hardware modules○ our OOB console access did not work until we enabled some

non-standard serial driver● by default your kernel will be configured with 39-bit

virtual address space○ allows to address up to 512GB○ https://www.kernel.org/doc/Documentation/arm64/memory.txt

Page 44: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Edge server software stack

Linux kernel

RAM-based basic root filesystem

nginxnginxnginxnginxnginxOther apps and services

nginxnginxOther apps and services

Page 45: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

Page 46: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

● no easy way to do cross-arch debootstrap○ https://wiki.debian.org/EmDebian/CrossDebootstrap

Page 47: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

● no easy way to do cross-arch debootstrap○ https://wiki.debian.org/EmDebian/CrossDebootstrap

● requires many changes and complex logic in both the build system and build environment

Page 48: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Docker

Cloudflare build system

yaml file(build environment)

Makefile(build recipe)

Page 49: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Docker

Cloudflare build system

yaml file(build environment)

Makefile(build recipe)

build deps, tools,

configs

Page 50: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Docker

Cloudflare build system

yaml file(build environment)

Makefile(build recipe)

build deps, tools,

configsbuild steps

Page 51: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cloudflare build system● Docker-based

○ a Makefile - how to build○ a yaml file - build dependencies and environment

Page 52: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cloudflare build system● Docker-based

○ a Makefile - how to build○ a yaml file - build dependencies and environment

● reproducible in CI

Page 53: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Cloudflare build system● Docker-based

○ a Makefile - how to build○ a yaml file - build dependencies and environment

● reproducible in CI

● can we emulate ARM64 environment with Docker?○ without virtual machines○ change only the build environment, not the recipe

Page 54: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

● dynamically translates foreign architecture code upon execution

● allows to execute arm64 binary directly on x86

Page 55: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

qemu-user in actionignat@dev:~$ gcc -static -o helloarch helloarch.c

ignat@dev:~$ readelf -h helloarch | grep -i machine

Machine: Advanced Micro Devices X86-64

ignat@dev:~$ ./helloarch

Hello, x86_64!

ignat@dev:~$ aarch64-linux-gnu-gcc -static -o helloarch helloarch.c

ignat@dev:~$ readelf -h helloarch | grep -i machine

Machine: AArch64

ignat@dev:~$ ./helloarch

bash: ./helloarch: cannot execute binary file: Exec format error

ignat@dev:~$ sudo apt-get install qemu-user-static

ignat@dev:~$ qemu-aarch64-static ./helloarch

Hello, aarch64!

Page 56: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

binfmt_misc Linux kernel module

● allows to register custom “interpreters” for specific executables and scripts

● can specify executables by file header or extension

https://www.kernel.org/doc/html/v4.14/admin-guide/binfmt-misc.html

Page 57: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

binfmt_misc in actionignat@dev:~$ ./helloarch

-bash: ./helloarch: cannot execute binary file: Exec format error

ignat@dev:~$ echo ":qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-static:OC" | sudo tee -a /proc/sys/fs/binfmt_misc/register

:qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-static:OC

ignat@dev:~$ ./helloarch

Hello, aarch64!

Page 58: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

binfmt_misc in action

User process

binfmt_misc

exec /bin/foo

read header/extension

find registered format

execute via interpreter

/qemu-aarch64 /bin/foo

Page 59: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Combining QEMU, binfmt_misc and Dockerignat@dev:~$ cat Dockerfile

FROM arm64v8/debian:stretch

COPY qemu-aarch64-static /usr/bin/qemu-aarch64-static

ignat@dev:~$ docker build -t arm64/stretch .

...

Successfully tagged arm64/stretch:latest

ignat@dev:~$ docker run --rm -it arm64/stretch

root@4e466498353f:/# uname -m

aarch64

Page 60: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Foreign arch containers with just qemu● QEMU translates every system call before

passing it on to the kernel

Page 61: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

QEMU user emulation

ARM64 user process

Linux kernel

Page 62: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

QEMU user emulation

ARM64 user process

exec /bin/foo

Linux kernel

Page 63: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

QEMU user emulation

ARM64 user process

exec /bin/foo

translate ARM64 exec -> x86 exec

Linux kernel

Page 64: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

QEMU user emulation

ARM64 user process

exec /bin/foo

translate ARM64 exec -> x86 exec

x86 exec /bin/foo

Linux kernel

Page 65: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Foreign arch containers with just qemu● QEMU translates every system call before

passing it on to the kernel● Why not replicate binfmt_misc functionality in

QEMU itself?

Page 66: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

Modified QEMU user emulation

ARM64 user process

exec /bin/foo

translate ARM64 exec -> x86 exec

Linux kernel

Page 67: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

Modified QEMU user emulation

ARM64 user process

exec /bin/foo

translate ARM64 exec -> x86 exec

Linux kernel

rewriteexec /bin/foo -> exec /qemu-user /bin/foo

Page 68: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

QEMU user emulation

Modified QEMU user emulation

ARM64 user process

exec /bin/foo

translate ARM64 exec -> x86 exec

x86 exec /qemu-user /bin/foo

Linux kernel

rewriteexec /bin/foo -> exec /qemu-user /bin/foo

Page 69: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Foreign arch containers with just qemu● QEMU translates every system call before

passing it on to the kernel● Why not replicate binfmt_misc functionality in

QEMU itself?● Don’t need to rely on external binfmt_misc

functionality and can create truly self-contained foreign architecture Docker images

Page 70: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Foreign arch containers with just qemu

Page 71: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Foreign arch containers with just qemu

https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/

Page 72: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 Debian Stretch DockerfileFROM debian:stretch-slim as builder

RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev wget

RUN wget https://download.qemu.org/qemu-2.12.0.tar.xz && tar xf qemu-2.12.0.tar.xz

COPY qemu-execve.patch /qemu-execve.patch

RUN patch -d qemu-2.12.0 -p1 < qemu-execve.patch && \

mkdir qemu-build && cd qemu-build && \

/qemu-2.12.0/configure --static --target-list=aarch64-linux-user --disable-system && \

make

Page 73: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 Debian Stretch Dockerfile (cont)FROM arm64v8/debian:stretch-slim

COPY --from=builder /qemu-build/aarch64-linux-user/qemu-aarch64 /qemu-aarch64

SHELL ["/qemu-aarch64", "/bin/sh", "-c"]

RUN apt-get update && apt-get install -y --no-install-recommends libcap2-bin && \

setcap cap_setuid,cap_setgid+ep /qemu-aarch64 && \

apt-get remove --purge -y libcap2-bin && apt-get autoremove -y && \

rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["/qemu-aarch64"]

CMD ["/bin/bash"]

Page 74: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Edge server software stack

Linux kernel

RAM-based basic root filesystem

nginxnginxnginxnginxnginxOther apps and services

nginxnginxOther apps and services

Page 75: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

Page 76: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

● no changes to the build system

Page 77: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

● no changes to the build system● only a single toggle to use ARM64 Debian

Stretch as a base instead of x86 one

Page 78: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 baseimg● just a minimal Debian image

○ debootstrap --variant=minbase stretch baseimg○ install config-management agent (salt-minion)○ package baseimg folder as initramfs

● no changes to the build system● only a single toggle to use ARM64 Debian

Stretch as a base instead of x86 one● works on x86-based CI out of the box

Page 79: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Edge server software stack

Linux kernel

RAM-based basic root filesystem

nginxnginxnginxnginxnginxOther apps and services

nginxnginxOther apps and services

Page 80: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting user-space applications● reused arm64 Docker based approach

○ reduced avg package porting time from days to minutes○ no cross-compiling problems, no foreign arch dependency tracing○ allows devs and CI to run basic tests

Page 81: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting user-space applications● reused arm64 Docker based approach

○ reduced avg package porting time from days to minutes○ no cross-compiling problems, no foreign arch dependency tracing○ allows devs and CI to run basic tests

● most of the stack was done in ~1 month

Page 82: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting user-space applications● reused arm64 Docker based approach

○ reduced avg package porting time from days to minutes○ no cross-compiling problems, no foreign arch dependency tracing○ allows devs and CI to run basic tests

● most of the stack was done in ~1 month● although slower build times due to

emulation layer○ ex. nginx takes 2m instead of usual 10s (~10x slower)

Page 83: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Slower build times - it’s a feature!

Page 84: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting timeline

● started porting applications beginning of March

Page 85: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting timeline

● started porting applications beginning of March

● March 23rd - served first production DNS request

Page 86: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Porting timeline

● started porting applications beginning of March

● March 23rd - served first production DNS request

● April 18th - served first production HTTPS request with cached content

Page 87: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

ARM64 in production

Page 88: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

How is it doing now?

Page 89: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

nginx-cache CPU time

Page 90: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

nginx-cache user CPU time

Page 91: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

nginx-cache system CPU time

Page 92: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

RRDNS CPU time

Page 93: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

RRDNS memory usage

Page 94: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Quicksilver CPU time

Page 95: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Quicksilver memory cache

Page 96: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Conclusions● ARM64 is a competitive server architecture

○ most software works OK out of the box● Migrating to ARM64 is not that hard

○ popular OSes support ARM64 already● QEMU user emulation + Docker provides a low-cost

quick-start solution to port in-house software to ARM64○ in both hw costs and effort cost○ minimal disruption to the dev process

Page 97: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Some links● https://blog.cloudflare.com/arm-takes-wing/● https://blog.cloudflare.com/neon-is-the-new-black/● https://blog.cloudflare.com/using-go-as-a-scripting-la

nguage-in-linux/● https://www.kernel.org/doc/html/latest/admin-guide/

binfmt-misc.html● https://resin.io/blog/building-arm-containers-on-any-

x86-machine-even-dockerhub/

Page 98: Call to ARMs - USENIX · ARM64 Debian Stretch Dockerfile FROM debian:stretch-slim as builder RUN apt-get update && apt-get install -y build-essential python patch libglib2.0-dev libfdt-dev

Thank you!