Alla DockerCon17 è stato rilasciato opensource LinuxKit, ulteriore Kit che si aggiunge ai vari InfraKit, DataKit e SwarmKit nell’ecosistema dei progetti Moby.
LinuxKit, a toolkit for building custom minimal, immutable Linux distributions.
Questo strumento, al momento in fase (molto) alpha, si rivolge ad utenti, hypervisor e pipeline di CI/CD che devono costruire in modo ripetibile, veloce e facile immagini Linux per container minime, immutabili e sicure da gestire poi con meccanismi IaC come Terraform o InfraKit.
Ripetibile, perché immagini uguali sono prodotte da configurazioni YAML uguali. Veloce, perché il build richiede pochi secondi. Facile, perché chiunque abbia provato a creare sistemi Linux (unikernel) minimali sa quanto può essere molesto e fuorviante il processo: la promessa di LinuKit è quella di rendere tutto fattibile con un comando.
Il risultato è un’immagine Linux (.img o .iso) pronta a girare su qemu, vmware, GCP o hyperkit (OS X) minima, perché si inizializza in pochi secondi e include solo lo stretto necessario in Containerd come configurato (binari, librerie), immutabile, perché fissa requisiti e versioni (soprattutto kernel), e sicura perché riduce al minimo la superficie di attacco.
Il progetto Moby
Contestualmente al lancio di LinuxKit, i prodotti di Docker (in Github) passano sotto il contenitore del progetto Moby. Come promesso non ci saranno cambiamenti di tool e nomi, ma la transizione è in corso. Un’altra volta ancora, innovazione a tutti i costi. Prima di tutti a morire, come al solito, la retrocompatibilità: alcuni repo façade sono in fase di completamento per non rompere i build Go…
I prodotti downstream dentro Moby sono stati separati in Community Edition (CE) e Enterprise Edition (CE).
Come modello community e enterprise, verrà seguito quello di Fedora e Red Hat.
LinuxKit
LinuxKit non è un CoreOS o una distribuzione specializzata per container, ma un toolkit per costruire immagini Linux (al volo, possibilmente) a partire da configurazioni YAML. LinuxKit al momento costruisce immagini partendo da Linux Alpine aggiungendo gli extra in Containerd (Docker stesso nella fattispecie), ma l’idea del progetto è di fare da incubatore a progetti unikernel e altri relativi alla sicurezza dei sistemi operativi.
Una configurazione YAML tipica fissa la versione del kernel e dell’equipaggiamento base (runc, containerd, certificati), e specifica i servizi da aggiungere.
Una build con sshd
Inutile dilungarsi in discussioni teoriche quando il tutto è più semplice da capire con un esempio. Si usa LinuxKit con i comandi moby e linuxkit, che vanno compilati. La toolchain Go viene containerizzata in Docker, quindi non serve installare il compilatore:
$ git clone github.com:linuxkit/linuxkit $GOPATH/src/github.com/linuxkit/linuxkit $ cd $GOPATH/src/github.com/linuxkit/linuxkit $ make
Verifichiamo:
➜ linuxkit git:(master) ./bin/moby version moby version 0.0 commit: f2d6752751318477ec86e4677514d5a4890249c1
Versione 0.0, avevamo già detto che il progetto è nuovo?
Ora, dentro examples/ e projects/ ci sono alcuni YAML di riferimento per incominciare. Creiamo una Alpine a partire dall’esempio di sshd. Occorre aggiungere una chiave valida in sshd.yml prima. Poi:
➜ examples git:(master) ../bin/moby build sshd Extract kernel image: linuxkit/kernel:4.9.x Add init containers: Process init image: linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b Process init image: linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9 Process init image: linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b Process init image: linuxkit/ca-certificates:e091a05fbf7c5e16f18b23602febd45dd690ba2f Add onboot containers: Create OCI config for linuxkit/sysctl:2cf2f9d5b4d314ba1bfc22b2fe931924af666d8c Add service containers: Create OCI config for linuxkit/rngd:c42fd499690b2cb6e4e6cb99e41dfafca1cf5b14 Create OCI config for linuxkit/dhcpcd:48e249ebef6a521eed886b3bce032db69fbb4afa Create OCI config for linuxkit/sshd:e108d208adf692c8a0954f602743e0eec445364e Add files: root/.ssh/authorizedkeys Create outputs: sshd-bzImage sshd-initrd.img sshd-cmdline sshd.iso sshd-efi.iso
Ecco l’output:
➜ examples git:(master) ls -lh sshd -rw-r--r-- 1 fsoppelsa staff 6.7M Apr 28 11:52 sshd-bzImage -rw-r--r-- 1 fsoppelsa staff 27B Apr 28 11:52 sshd-cmdline -rw-r--r-- 1 fsoppelsa staff 40M Apr 28 11:52 sshd-efi.iso -rw-r--r-- 1 fsoppelsa staff 32M Apr 28 11:52 sshd-initrd.img -rw-r--r-- 1 fsoppelsa staff 40M Apr 28 11:52 sshd.iso -rw-r--r-- 1 fsoppelsa staff 1.7K Apr 28 10:44 sshd.yml
Immagini pronte. Lanciamo la VM (nel mio caso su hyperkit):
➜ examples git:(master) ../bin/linuxkit run sshd [ 1.674388] Freeing unused kernel memory: 1548K (ffff8e7ac987d000 - ffff8e7ac9a00000) [ 1.679172] Freeing unused kernel memory: 1184K (ffff8e7ac9cd8000 - ffff8e7ac9e00000) Starting containerd Welcome to LinuxKit ## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ ______ o __/ __/ ___________/ / # INFO[0000] starting containerd boot...
In circa 3 secondi parte. Ecco cosa fa girare:
/ # runc list ID PID STATUS BUNDLE CREATED OWNER dhcpcd 414 running /containers/services/dhcpcd 2017-04-28T16:56:06.1132568Z root rngd 451 running /containers/services/rngd 2017-04-28T16:56:06.1299713Z root sshd 458 running /containers/services/sshd 2017-04-28T16:56:06.1408088Z root
Via DHCPd sulla rete interna host, l’interfaccia eth0 prende un indirizzo:
/ # ip a s eth0 4: eth0: <BROADCAST,MULTICAST,UP,LOWERUP> mtu 1500 qdisc pfifofast state UP qlen 1000 link/ether 02:50:00:00:00:07 brd ff:ff:ff:ff:ff:ff inet 192.168.65.8/24 brd 192.168.65.255 scope global eth0
Per fare ssh dentro questa VM di esempio su hyperkit, bisogna avere accesso alla rete interna host Docker, cosa fattibile tramite un container:
➜ examples git:(master) docker run -v ~/.ssh:/root/.ssh -ti jdeathe/centos-ssh ssh 192.168.65.8 The authenticity of host '192.168.65.8 (192.168.65.8)' can't be established. ECDSA key fingerprint is 19:7b:25:df:47:a4:56:2c:e8:59:6b:f4:a4:01:47:83. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.65.8' (ECDSA) to the list of known hosts. Welcome to LinuxKit moby-025000000007:# hostname moby-025000000007 moby-025000000007:# whoami root moby-025000000007:#
Scenari futuri
L’esempio di ssh è quello più banale. Sono già partiti progetti per iniziare a modellare servizi seri partendo da configurazioni LinuxKit (il mio preferito, in projects/kubernetes).
L’idea è quella di trainare tutto questo hype verso la direzione degli unikernel. I sistemi a unikernel non hanno un kernel vero e proprio, ma lo spazio di indirizzi tra kernel e userspace è fuso: le applicazioni compilano staticamente le parti di kernel e le syscall necessarie dentro il proprio binario. Se mi serve un oggetto unikernel per fare ping, non mi servono le syscall di accesso al filesystem o ai processi e la parte di crittografia del kernel. Così, l’oggetto ping unikernel compila se stesso, le raw socket e le primitive di networking e basta.
Qualcuno capace di accedere a un oggetto unikernel non ha modo di lanciare shell o usare script o librerie extra inutilizzate, perché semplicemente non ci sono. È abbastanza interessante? Per unikernel vedasi MirageOS. Però, momento, creare sistemi unikernel è un casino. Ed ecco che arriverà LinuxKit.
Certo, noi tutti amiamo i container (no?), ma unikernel è la prossima big thing.