Contents

Penerapan Linux OverlayFS pada Container Image

Adalah tidak mungkin untuk menggunakan container tanpa container image. Artikel ini akan mengulas bagaimana kombinasi mounting filesystem dan penerapannya pada teknologi container dalam membangun container image.

Overlay Filesystem

Overlay filesystem juga sering disebut sebagai union filesystem memungkinkan pembuatan kombinasi dua atau lebih direktori, yang akan menjadi list dari yang biasa dijuluki sebagai direktori lower dan direktori upper. Direktori lower biasanya memiliki permission read only, sedangkan direktori upper dapat diberikan permission read-write. Saya teringat, salah satu use case Overlay filesystem yang pernah saya lakukan adalah memakainya untuk membuat extroot atau external root pada OpenWrt guna memperluas filesystem sebuah wireless router dengan cara menaruh penyimpanannya ke media eksternal seperti USB storage.

Untuk memahami Overlay filesystem kita dapat mempraktekannya dengan bantuan perintah mount pada sistem operasi GNU/Linux. Mari melihat apa yang dimaksud dengan pernyataan sebelumnya dengan mencobanya.

Membuat Overlay Filesystem

Saya akan membuat beberapa folder dan mengkombinasikannya. Pertama saya ingin membuat sebuah folder bernama mount dimana nantinya akan berisikan gabungan dari keseluruhan folder lainnya. Kemudian saya membuat sebuah sekelompok folder bernama 1-lower-layer, 2-lower-layer, dan 3-upper-layer. Dan akhirnya saya membuat sebuah folder bernama workdir yang diperlukan oleh overay filesystem untuk dapat bekerja dengan benar.

1
2
3
cd /tmp && mkdir overlay-example && cd overlay-example
mkdir -v mount 1-lower-layer 2-lower-layer 3-upper-layer workdir
ls -l

/penerapan-linux-overlayfs-pada-container-image/membuat-folder.png
Membuat Folder

Sekarang mari membuat beberapa file dalam folder 1-lower-layer 2-lower-layer memakai perintah echo. Untuk folder 3-upper-layer akan kita biarkan kosong sebagai contoh dari direktori upper saja. Kita akan melihat bagaimana nantinya mereka akan bekerja.

1
2
3
echo "ini layer 1" > ./1-lower-layer/file1
echo "ini layer 2" > ./2-lower-layer/file2
tree

/penerapan-linux-overlayfs-pada-container-image/membuat-file-lower.png
Membuat file pada direktori _lower_

Pada akhirnya, mari kita jalankan perintah mount pada mereka.

1
2
3
4
5
sudo mount -vt overlay overay-example -o \
lowerdir=/tmp/overlay-example/1-lower-layer:/tmp/overlay-example/2-lower-layer,upperdir=/tmp/overlay-example/3-upper-layer,workdir=/tmp/overlay-example/workdir \
/tmp/overlay-example/mount
df -h | grep overlay
tree

Jika berhasil kita dapat melihatnya seperti output berikut ini.

/penerapan-linux-overlayfs-pada-container-image/mounting-overlay.png
Mounting Overlay

Sebagaimana kita mengharapkannya, seluruh konten dari folder 1-lower-layer dan 2-lower-layer dapat dikombinasikan dan dimuat ke dalam folder mount. Mari kita periksa konten dari file tersebut yang sebelumnya telah kita tuliskan sebuah string menggunakan perintah echo.

1
cat mount/file2

Sudah dipastikan bahwa memang file tersebut identik dengan apa yang sudah kita ciptakan sebelumnya.

/penerapan-linux-overlayfs-pada-container-image/memeriksa-isi-konten.png
Memeriksa isi konten

Lalu bagaimana jika kita membuat sebuah file baru pada folder mount? mari kita coba.

1
2
echo "Ini adalah file baru" > ./mount/file-baru
tree

/penerapan-linux-overlayfs-pada-container-image/membuat-file-upper.png
Membuat file baru

Terlihat bahwa file baru yang kita ciptakan di folder mount akan tersimpan pada upper layer atau di sini kita menamai foldernya dengan nama 3-upper-layer. Lalu bagaimana jika kita menghapus salah satu file milik lower layer, misalnya adalah file2.

1
2
rm mount/file2
tree

/penerapan-linux-overlayfs-pada-container-image/menghapus-lower-file.png
Menghapus file

File tersebut berhasil dihapus dari folder mount, tapi ternyata file2 masih utuh dan baik-baik saja di dalam folder 2-lower-layer. Kemudian jika diperhatikan, akan muncul sebuah file baru pada folder 3-upper-layer bernama file2 sesuai dengan yang baru saja kita hapus. Mari kita periksa file tersebut.

1
ls -lhtra 3-upper-layer

/penerapan-linux-overlayfs-pada-container-image/memeriksa-upper-layer.png
Memeriksa upper layer

File baru di dalam folder 3-upper-layer ternyata adalah sebuah character file. File semacam ini seringkali disebut sebagai file whiteout dan begitulah overlay filesystem menampilkan berkas yang akan dihapus.

Menarik Kesimpulan

Sebagaimana yang saya bicarakan pada awal tadi, overlay filesystem memungkinkan kita untuk membuat sebauh union atau kesatuan beberapa direktori. Dalam kasus kita saat ini union dibuat pada folder mount dan di dalamnya akan berisi konten kolaborasi dari direktori layer yaitu folder 1-lower-layer dan 2-lower-layer sebagai lapisan direktori lower, serta folder 3-upper-layer sebagai lapisan direktori upper.

Setiap perubahan yang kita lakukan pada union (membuat, menghapus, atau mengedit konten) akan dicatat pada upper layer. Ini adalah alasan kenapa lapisan upper juga sering disebut sebagai lapisan diff. Fakta lainnya adalah, berkas-berkas dari union merupakan bayangan dari lower layer namun upper layer memiliki tingkatan lebih tinggi untuk ditampilkan ke panggung, contohnya ketika kita membuat file atau folder pada 3-upper-layer dengan nama yang sama seperti dalam 1-lower-layer dan 2-lower-layer maka justru konten dari 3-upper-layer yang akan ditampilkan pada union atau dalam kasus ini yaitu folder mount.

/penerapan-linux-overlayfs-pada-container-image/upper-layer-override.png
Upper Layer override


Container Image

Container Image sebenarnya adalah sebuah tarfile dengan root filesystem dan beberapa metadata. Kita mungkin pernah mendengar tentang karakteristik image layer dan setiap baris dari Dockerfile (sebuah textfile yang berisi baris perintah untuk membangun container image) akan membuat layer baru. Contohnya seperti berikut, dimana dia akan membuat tiga layer untuk setiap baris perintahnya.

1
2
3
4
FROM scratch
ADD my-files /doc
ADD hello /
CMD ["/hello"]

Jadi apa yang sebenarnya terjadi saat kita menjalankan perintah docker run. Banyak hal yang sebenarnya terjadi, tapi untuk kepentingan artikel kali ini kita akan meluruskan ketertarikan kita pada container image.

/penerapan-linux-overlayfs-pada-container-image/container-image-construct.jpg
Container Image Construct

Secara pandangan high level, docker akan mengunduh tarball untuk image, kemudian melakukan unpack pada setiap layer menjadi beberapa direktori terpisah dan kemudian menggunakan overlay filesystem untuk mengkombinasinya menjadi sebuah kesatuan direktori upper kosong yang akan digunakan oleh container untuk menuliskan segala perubahan ketika tengah berjalan.

Ketika kita melakukan suatu perubahan, seperti membuat atau menghapus file di dalam container, perubahan tersebut akan disimpan pada direktori kosong di upper layer. Ketika container dihentikan, docker akan membersihkan folder tersebut. Itulah alasannya kenapa setiap perubahan yang kita lakukan di dalam container by default tidak disimpan permanen.

Layer Cache

/penerapan-linux-overlayfs-pada-container-image/layer-cache.png
Layer Cache
Ini adalah metode yang digunakan oleh overlay filesystem untuk memungkinkan host melakukan caching container image secara efektif. Sebagai contoh, jika kita mendefinisikan dua container image, mereka berdua dapat menggunakan beberapa layer yang sama. Sehingga host tidak perlu mengunduh kembali atau menyimpan salinannya berkali-kali pada disk.

OCI format

Menjalankan sebuah container dapat dianalogikan menjadi dua langkah proses: membangun image dan menjalankan container dari image tersebut. Popularitas container telah meyakinkan orang-orang untuk melakukan standarisasi kedua langkah proses tersebut. Karena open source, kedua langkah proses tersebut dapat dikembangkan secara terpisah. Open Container Initiative (OCI) merupakan sebuah project dari Linux Foundation yang mengelola standarisasi container supaya dapat disesuaikan dengan lingkungan industri.

Saat artikel ini dibuat, OCI memiki dua macam spesifikasi: Runtime Specification (runtime-spec) dan Image Specification (image-spec). Runtime Specification menguraikan cara untuk menjalankan “filesystem bundle” yang dapat dibongkar pada disk. Penerapan OCI seperti mengunduh OCI Image kemudian melakukan unpack image tersebut ke dalam OCI Runtime filesystem bundle. Pada titik ini OCI Runtime Bundle akan dijalankan oleh sebuah OCI Runtime.

Standarisasi tersebut memperbolehkan setiap orang untuk mengembangkan custom container builder dan custom runtime. Sebagai contoh, ada jessfraz/img, buildah, hingga Skopeo yang mampu kita pakai untuk membangun container image tanpa perlu bergantung pada Docker. Banyak tool lain yang juga bisa kita gunakan untuk menjalankan container (disebut container runtime) seperti runC (yang dipakai oleh Docker) dan rkt.


Overlay Filesystem Lainnya

/penerapan-linux-overlayfs-pada-container-image/other-overlayfs.png
OverlayFS lain
Docker tidak cuma mampu menggunakan Overlay untuk melakukan kombinasi filesystem. Ada beberapa lainnya yang memiliki potensi untuk dapat digunakan seperti AuFS, Btrfs, ZFS, hingga Device mapper.


Build Container Image

/penerapan-linux-overlayfs-pada-container-image/container-image-layer.jpg
Container Image Layer
Misalkan kita memiliki sebuah Dockerfile seperti berikut untuk membangun image. Apa yang sebenarnya terjadi?

1
2
3
FROM centos:7
RUN yum install -y wget
...

Pada pandangan high level, inilah yang akan terjadi dari Dockerfile tersebut.

  1. Docker mengunduh tarball untuk image karena perintah FROM dan membongkarnya. Ini akan menjadi layer paling bawah dari container image.
  2. Memuat union filesystem. Berkas yang sebelumnya telah terunduh pada langkah pertama akan dipakai sebagai lower layer.
  3. Menjalankan shell command di dalam environment chroot karena perintah RUN. Perintah tersebut adalah /bin/sh -c "yum install -y wget.
  4. Ketika baris perintah terakhir telah dijalankan, container runtime akan membuat upper layer. Ini adalah lapisan baru dari image yang kita bangun.
  5. Jika Dockerfile mengandung perintah lainnya, maka proses pada langkah kedua akan diulangi sebagai lower layer dan berikutnya hingga selesai.

Tentu anggapan ini cenderung terlalu menyederhanakan workflow dimana saya tidak menyinggung perintah lain seperti ENV hingga ENTRYPOINT. Perintah tersebut akan disimpan di dalam metadata dan kemudian dikemas bersama ke dalam layer.


Kesimpulan

Gagasan untuk merangkum keseluruhan root filesystem menjadi sebuah tarfile dan memisahkan setiap layer menjadi begitu powerful. Ini tidak hanya dipakai pada teknologi container, tapi konsep ini juga dapat digunakan pada konteks lainnya. Saya kira, di masa mendatang akan semakin banyak tools yang memanfaatkan hal serupa.


Referensi