Showing posts with label rocket. Show all posts
Showing posts with label rocket. Show all posts

Wednesday, February 11, 2015

Rocket: First steps

Rocket is a container runtime for CoreOS. In this post we will do some basic tasks with Rocket: installing it, creating an ACI, publishing that ACI to OpenStack Swift, and pulling it down.

wget https://github.com/coreos/rocket/releases/download/v0.3.1/rocket-v0.3.1.tar.gz
tar xzvf rocket-v0.3.1.tar.gz
cd rocket-v0.3.1
./rkt help
 
I moved 'rkt' and 'stage1.aci' to ~/bin for ease of use.

We also need actool:

derp@myrkt:~$ git clone https://github.com/appc/spec.git
Cloning into 'spec'...
remote: Counting objects: 1604, done.
remote: Compressing objects: 100% (20/20), done.
Receiving objects: 100% (1604/1604), 614.19 KiB | 0 bytes/s, done.
remote: Total 1604 (delta 7), reused 1 (delta 0)
Resolving deltas: 100% (924/924), done.
Checking connectivity... done.
derp@myrkt:~$ cd spec/
derp@myrkt:~/spec$ ls
ace  aci  actool  build  CONTRIBUTING.md  DCO  discovery  examples  Godeps  LICENSE  pkg  README.md  schema  SPEC.md  test  VERSION
derp@myrkt:~/spec$ ./build 
Building actool...
go linux/amd64 not bootstrapped, not building ACE validator
derp@myrkt:~/spec$ ls bin/actool 
bin/actool
derp@myrkt:~/spec$ ./bin/actool -h
Usage of actool:
  -debug=false: Print verbose (debug) output
  -help=false: Print usage information and exit 
 
 
Now we need a simple go application:
 
package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        log.Printf("OHAIDER: request from %v\n", r.RemoteAddr)
        w.Write([]byte("hello\n"))
    })
    log.Fatal(http.ListenAndServe(":5000", nil))
} 
 
And a manifest.json file:
 
 {
    "acKind": "ImageManifest",
    "acVersion": "0.2.0",
    "name": "nializer/daemon",
    "labels": [
        {
            "name": "version",
            "value": "1.0.0"
        },
        {
            "name": "arch",
            "value": "amd64"
        },
        {
            "name": "os",
            "value": "linux"
        }
    ],
    "app": {
        "user": "root",
        "group": "root",
        "exec": [
            "/bin/daemon"
        ],
        "ports": [
        {
            "name": "www",
            "protocol": "tcp",
            "port": 5000
        }
        ]
    },
    "annotations": [
        {
        "name": "authors",
        "value": "Kelsey Hightower , Spencer Krum "
        },
        {
            "name": "created",
            "value": "2014-10-27T19:32:27.67021798Z"
        }
    ]
}
 
 
And a file structure:
 
root@myrkt:~/app# find daemon-layout/
daemon-layout/
daemon-layout/rootfs
daemon-layout/rootfs/bin
daemon-layout/rootfs/bin/daemon
daemon-layout/manifest
 
 
Then we can build(and verify) this image:
 
root@myrkt:~/app# find daemon-layout/
daemon-layout/
daemon-layout/rootfs
daemon-layout/rootfs/bin
daemon-layout/rootfs/bin/daemon
daemon-layout/manifest
root@myrkt:~/app# actool build daemon-layout/ daemon-static.aci
root@myrkt:~/app# actool --debug validate daemon-static.aci 
daemon-static.aci: valid app container image 
 
 
Then we can run the image (this doesn't work):
 
root@myrkt:~/app# rkt run daemon-static.aci
/etc/localtime is not a symlink, not updating container timezone.
Error: Unable to open "/lib64/ld-linux-x86-64.so.2": No such file or directory
Sending SIGTERM to remaining processes...
Sending SIGKILL to remaining processes...
Unmounting file systems.
Unmounting /proc/sys/kernel/random/boot_id.
All filesystems unmounted.
Halting system. 
 
 
The issue is that our go binary is not statically compiled:
 
root@myrkt:~/app# ldd daemon
        linux-vdso.so.1 =>  (0x00007fff2d2cd000)
        libgo.so.5 => /usr/lib/x86_64-linux-gnu/libgo.so.5 (0x00007ff809e45000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff809c2f000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff809868000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff80aca3000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff80964a000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff809344000) 
 
 
But this is okay because we can just add these files (plus a few more) to our ACI:
 
root@myrkt:~/app# find daemon-layout/
daemon-layout/
daemon-layout/rootfs
daemon-layout/rootfs/lib64
daemon-layout/rootfs/lib64/libc.so.6
daemon-layout/rootfs/lib64/ld-linux-x86-64.so.2
daemon-layout/rootfs/bin
daemon-layout/rootfs/bin/daemon
daemon-layout/rootfs/usr
daemon-layout/rootfs/usr/lib
daemon-layout/rootfs/usr/lib/x86_64-linux-gnu
daemon-layout/rootfs/usr/lib/x86_64-linux-gnu/libgo.so.5
daemon-layout/rootfs/lib
daemon-layout/rootfs/lib/x86_64-linux-gnu
daemon-layout/rootfs/lib/x86_64-linux-gnu/libpthread.so.0
daemon-layout/rootfs/lib/x86_64-linux-gnu/libc.so.6
daemon-layout/rootfs/lib/x86_64-linux-gnu/libgcc_s.so.1
daemon-layout/rootfs/lib/x86_64-linux-gnu/libm.so.6
daemon-layout/manifest 
 
 
Now we can re-build, verify, run:
 
 
root@myrkt:~/app# actool build --overwrite  daemon-layout/ daemon.aci                                                                                          
root@myrkt:~/app# actool --debug validate daemon.aci                                                                                                           
daemon.aci: valid app container image
root@myrkt:~/app# du -sh daemon.aci
5.6M    daemon.aci
root@myrkt:~/app# rkt run daemon.aci
/etc/localtime is not a symlink, not updating container timezone.
2015/02/11 13:32:58 OHAIDER: request from 127.0.0.1:55024

This means everything is working. You can exit by pressing ^] three times.

We can then post the daemon file to swift, using the tempurl system from a previous post. Then using a tiny url service, we can run the aci from the network:


root@myrkt:~/app# rkt fetch http://l.pdx.cat/nibz_daemon.aci
rkt: fetching image from http://l.pdx.cat/nibz_daemon.aci
Downloading aci: [============================================ ] 5.81 MB/5.84 MB
Downloading signature from http://l.pdx.cat/nibz_daemon.sig
EOF
root@myrkt:~/app# rkt run nibz_daemon
rkt only supports http or https URLs (nibz_daemon)
root@myrkt:~/app# rkt run http://l.pdx.cat/nibz_daemon.aci
rkt: fetching image from http://l.pdx.cat/nibz_daemon.aci
Downloading aci: [=====================================        ] 4.89 MB/5.84 MB
Downloading signature from http://l.pdx.cat/nibz_daemon.sig
EOF 
 
 
Okay, so that didn't work. Maybe later on I will figure that part out. I am particularly excited to use the swfit meta tags to add the security meta tags used by rocket for collecting signatures.
 
 
 

Rocket: Containers without Docker

Rocket is a container runtime from CoreOS. It is a response to Docker's feature creep. Simultaneously with Rocket, the CoreOS team released the App Container Spec, a specification of the image format consumed by a container runtime. Multiple container runtimes could then be written and could all consume the same images. In this post I will talk about my experience with it and what I like and don't like so far. Note that I don't have a ton of experience with this tool at this point.

There are a couple of things inside the app container spec/rocket ecosystem that are just fantastic(actually I'm pumped about basically the whole thing):

Security is a first class concern

Rocket uses gpg to verify the authenticity of App Container Images(aci). It does this by allowing the administrator to trust keys, then containers signed by those keys are trusted. Rocket maintains its own keyring with trust levels. This borrows from the techniques used to secure Linux packaging. Rocket/ACI also use sha512sums to uniquely identify ACIs.

Built on core unix utilities

The main operations (actually all operations) involved in creating, signing, verifying, and sharing ACI's are composed out of the standard unix utilites: tar, gpg, gzip. Any helper utilities just serialize these functions. actool is one such utility. This keeps ACI's simple, doesn't tie anyone to custom tooling, increases debugability and hackability. Particularly in the signing and verification components, this means no one has to trust CoreOS or anyone else.

Emphasis on pushing exactly what you want into the container

With ACI, you copy the files you want into the container and stop there. This encourages small images, and encourages administrators to know exactly what is going in their images.

Networking just works

No crazy -p port:port:ipaddress nonsense, you specify the listen port in the configuration file, boom done. Listens on all interfaces.

Configuration file makes sense, extendable

When you build an ACI, you bake a manifest.json into it. This is a configuration file with a combination of runtime settings and overall metadata. I am already comparing and contrasting with Puppet's metadata.json. Both of these files contain basic metadata such as authorship information. And both are young formats with tooling and use still growing up. JSON's schemalessness allows users and devs to rapidly prototype and try out new information and structures in these files.

HTTP

Http is used as the primary transport. ACI's are simple files. These ACI's can be pushed into webservers or s3 and pulled out with wget or the rocket utility itself.
This is a massive improvement over the current docker-hub situation. Rocket has some rudimentary support for inferring github http locations from names such as 'coreos.com/etcd'