Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Creating Containers with Golang

Creating Containers with Golang

@Geeks Who Drink in Fukuoka -Go Go Golang Edition!-
2017/06/28
https://nulab.connpass.com/event/57238/

KONDO Uchio

June 28, 2017
Tweet

More Decks by KONDO Uchio

Other Decks in Technology

Transcript

  1. Introduction to Handmade Containers!!
    Uchio Kondo / GMO Pepabo, Inc.
    2017.06.27 Geeks Who Drink
    Creating Containers

    Using Golang

    View full-size slide

  2. Engineer
    Uchio Kondo @udzura
    GMO Pepabo / Dev Productivity Team
    System Programming Newbie
    Favorite syscall: ptrace(2)
    Favorite ramen: ΒʔΊΜ޻๪ཾ (in Kitakyu)

    View full-size slide

  3. Our company
    GMO Pepabo, Inc.

    View full-size slide

  4. runs the web service
    minne

    View full-size slide

  5. GMO Pepabo
    promotes
    a handmade market

    View full-size slide

  6. So I’m talking
    about
    handmade containers !!

    View full-size slide

  7. Containers in Golang

    View full-size slide

  8. libcontainer
    •RunC: Internal container engine of Docker, written in Golang
    •libcontainer: Internal library of RunC
    •Using libcontainer, you can create containers for your own purpose.
    • You can get GitHub 2,000 stars⭐ with your own container!!

    View full-size slide

  9. Casual handcraft

    View full-size slide

  10. Go-native container features
    •Golang itself supports container features, such as:
    •syscall package:
    • func syscall.Chroot
    • func syscall.Exec
    •exec.Cmd’s SysProcAttr member
    IUUQTHPMBOHPSHQLHPTFYFD$NE
    IUUQTHPMBOHPSHQLHTZTDBMM

    View full-size slide

  11. Chroot’ing and Exec

    View full-size slide

  12. Setting up root filesystems
    •Using docker export
    $ sudo su -
    # mkdir -p /tmp/gwd && docker export $(docker run -d \
    debian:stretch /bin/sleep 9999) | tar xvf - -C /tmp/gwd
    ## Provision: name resolution in container
    # cp /etc/resolv.conf /tmp/gwd/etc/resolv.conf
    # cp `which ps` /tmp/gwd/bin/ ## installs just ps...
    # cp /lib/x86_64-linux-gnu/libprocps.so.4 \
    /tmp/gwd/lib/x86_64-linux-gnu/

    View full-size slide

  13. Smallest implementation of chroot(1)
    package main
    import (
    "os"
    "syscall"
    )
    func must(e error) {
    if e != nil {
    panic(e)
    }
    }
    func main() {
    must(syscall.Chroot(os.Args[1]))
    must(syscall.Chdir("/"))
    must(syscall.Exec("/bin/sh", []string{}, os.Environ()))
    }

    View full-size slide

  14. It works!!
    Compiling source with GOOS=linux
    Move it to vagrant box, then kick
    And now I’m in the Debian!!

    View full-size slide

  15. More isolation required...
    I can accidentally see

    the host’s processes

    View full-size slide

  16. Linux namespace

    View full-size slide

  17. A namespace wraps a global system resource in an
    abstraction that makes it appear to the processes within
    the namespace that they have their own isolated instance
    of the global resource...
    “man 7 namespaces”

    View full-size slide

  18. In a picture
    Global UTS namespace
    hostname: foo.example.com
    unshared namespace
    hostname: bar.example.com
    hostname: xxx.example.com
    hostname: zzz.example.com
    A Process

    View full-size slide

  19. In a picture
    Global UTS namespace
    hostname: foo.example.com
    unshared namespace
    hostname: bar.example.com
    hostname: xxx.example.com
    hostname: zzz.example.com
    A Process
    If some of processes unshared
    its UTS namespace, these processes
    can have their own hostname
    even in the same machine

    View full-size slide

  20. For other resources, it’s same as UTS

    View full-size slide

  21. Then we’re going to try
    Let’s unshare
    PID namespaces!

    View full-size slide

  22. exec.Cmd ’s member
    unshare on fork() (= clone(2))

    View full-size slide

  23. Write some code
    package main
    import (
    "os"
    "os/exec"
    "syscall"
    )
    func must(e error) {
    if e != nil { panic(e) }
    }
    func main() {
    must(syscall.Chroot(os.Args[1]))
    must(syscall.Chdir("/"))
    cmd := exec.Command("/bin/sh")
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.SysProcAttr = &syscall.SysProcAttr{Cloneflags: syscall.CLONE_NEWPID}
    must(cmd.Run())
    }

    View full-size slide

  24. Then build and run...

    View full-size slide

  25. Check the PID starts with one!!!!!!

    View full-size slide

  26. Newborn
    handmade container!!

    View full-size slide

  27. Summary:
    creating your own container is
    easier than you think!!

    View full-size slide

  28. Summary:
    creating your own container is
    easier than you think!!
    ......Maybe ;)

    View full-size slide

  29. You can get 2,000 stars⭐
    with your container

    View full-size slide

  30. As pt did!!!

    View full-size slide

  31. More container talk on YAPC::Fukuoka

    View full-size slide

  32. See also (many in Japanese...)
    •Full golang source code by @hayajo
    •ʮGoͰͭ͘ΔLinuxίϯςφʯPresentation
    •...And his movie
    •Thanks @hayajo for the basic idea and implementation!!!
    IUUQTHJTUHJUIVCDPNIBZBKPDBCBCGECFGF
    IUUQTTQFBLFSEFDLDPNIBZBKPDUTUVEZ
    IUUQTZPVUVCFHJ2DKD:QMX

    View full-size slide