Sanallaştırmanın Üvey Evladı LXD

Standard

Merhabalar;

Günümüzde her geçen gün yaygınlaşan teknolojilerden birisi de sanallaştırma teknolojileri. Uygulama geliştirirken önceleri tek bir işletim sistemi üzerinde hem veritabanı, hem web arayüzü hem de sistem yönetimi yapılırken, artık mimariler bu parçaların her birini farklı yerlerde tutarak güvenliği artırmaya beraberinde de sistemlerin birbirinden bağımsız çalışmasına imkan sağlayarak daha güvenilir bir yapı kurmaya odaklandı. 2013’te ortaya çıkan ve o günden beri kullanımı gittikçe popülerleşen docker teknolojisinin öncesinde de, LXC mevcuttu…

LXC’nin kendini docker gibi sevdirememesinin temelinde hem kurulum zorlukları hem de sonrasında konfigurasyon sıkıntıları olsa da birden fazla teknolojinin kullanılıp aynı zamanda sistem seviyesinde kontrol edebileceğiniz bir mimari inşa ettiğinizde, karşınıza LXC çıkmakta.

Peki LXD nedir?

Aslında docker LXC’nin bir sonraki jenerasyonu olarak, konfigurasyon karmaşasını ve birçok kullanım kolaylığını hayatımıza kazandırırken, Canonical LXD adında bir ürünle, servis deployment sürecinden ziyade sanal bir GNU/Linux ortamına ihtiyaç duyulan durumlarda kullanılması üzerine bu teknolojiyi geliştirdi.

Şemadan da anlaşılabileceği üzere, aslında LXD size daha ziyade bir VM sunarken, docker ise belirli bir servisi konteyner olarak sunmakta.

Gelelim LXD’yi nasıl kurup kullanabileceğimize…

apt install lxd

Güvenlik sebepleri ve otomatik güncelleme özelliği olması nedeniyle snap uzerinden kurulumu tavsiye edilmekte:

service lxc stop
apt remove --purge lxc lxd
snap install lxd

Kurulum tamamlandıktan sonra lxc konfigurasyonları otomatik yapması için;

lxd init --auto

Kurulum sonrası servisin doğru bir şekilde çalıştığını kontrol edelim;

systemctl status snap.lxd.daemon.service

Artık ilk contaıner’ımız oluşturmaya hazırız.

Konteynerınızı oluşturduktan sonra herhangi bir kısıtlama belirtmezseniz, sistemin kaynaklarının tamamı konterner için de kullanılabilir olacaktır:

lxc launch ubuntu:18.04 first

Artık elimizde fiziksel işletim sisteminin altında oluşturulmuş durumda, ancak kendisine dair yapılandırma ayarlarını her seferinde manuel olarak tanımlamak gerekli:

Ram ve CPU kısıtlaması yapalım:

lxc config set first limits.cpu 4
lxc config set first limits.memory 4GB

Şimdi tekrar bağlanıp, tekrar htop üzerinden kontrol ettiğimizde:

Bu işlem gibi genel ihtiyaçları kapsayan şöyle bir “lxc-create” adında bashscript yazıp /usr/local/bin altına taşırsanız, terminalden direkt kullanabilirsiniz:

 #!/bin/bash

container_name="$1"
cpu_limit="$2"
memory_limit="$3"
[ -z "${memory}" ] && echo "Usage: create-lxc <container_name> <cpu_limit> <cpu_core_limit> <memory_size_in_gb>" && exit 1

lxc launch ubuntu:18.04 ${container_name}
lxc config set ${container_name} limits.cpu ${cpu_limit}
lxc config set ${container_namre} limits.memory ${limits_memory} ${memory_limit}GB

Çalıştırabilmek için “chmod +x dosya_adi” şeklinde yetkilendirme yapmayı unutmayın.

LXC üzerinde daha detaylı yapabilecekleriniz hakkında bilgiye buradan bakabilirsiniz.

LXC Konteynerları İçin Standart Oluşturma

Eğer ihtiyacınız olan tamamen boş bir işletim sistemiyse işler kısayken, belirli bir proje ya da bir geliştirme ortamını sürekli ayağa kaldırmak isterseniz, yapabileceğiniz birkaç yöntem bulunmakta. Ya bununla alakalı bir bashscript yazarak bunu her seferinde çalıştırabilirsiniz ya da LXC üzerinde profiller oluşturarakta benzer şekilde istediğiniz ortamların kurulu olduğu ve ayarların yapıldığı bir konteyner oluşturabilirsiniz.

Profiller

Docker bilenler için karşılığı (tam karşılamasa da) Dockerfile yazma işleminin LXD’de çözümü profiller oluşturmaktır. Kabaca, YAML üzerinden bir sistem ayağa kalkarken, yapılmasını istediğiniz işlemleri LXD’ye bildirip, konteyner’a bu profili atarsak, LXD otomatik olarak bu YAML’da belirtilen konfigürasyonlar ile konteyner’ı oluşturacaktır. Profil oluşturmakla başlıyoruz,

lxc profile create standart_ortamim
lxc profile edit standart_ortamim

Profili editleyerek içerisine, sistem başladığında docker,motd ekleyip, konsoluda fish olarak yükleyen, bu esnada sisteme istediğimiz birkaç özel paketi kurup güncelleme yapan, bir sistemle örneklendirelim:

config:
  security.nesting: "true"
  security.privileged: "true"
  user.user-data: |
    #cloud-config
    users:
      - name: root
        ssh_pwauth: true
          - ssh-rsa [buraya_otomatik_giris_yapmak_isterseniz_ssh_keyini_koyabilirsiniz.]

    chpasswd:
        ssh_authorized_keys:
      list: |
        root:cokgizliparola
      expire: false

    apt:
      conf: |
        APT {
          Get {
            AllowUnauthenticated "true";
          };
        };
        Acquire {
          https {
            Verify-Peer "false";
            Verify-Host "false";
          };
        };

    write_files:
      - path: /usr/bin/initCloud
        permissions: 0777
        content: |
          #!/bin/bash

          function installGitWithSSL() {
            sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list
            apt update
            rm -rf "/tmp/source-git/"
            apt-get build-dep git -y
            apt install -y libcurl4-openssl-dev
            mkdir -p "/tmp/source-git/"
            cd "/tmp/source-git/"
            apt-get source git
            cd $(find -mindepth 1 -maxdepth 1 -type d -name "git-*")
            pwd
            sed -i -- 's/libcurl4-gnutls-dev/libcurl4-openssl-dev/' ./debian/control
            sed -i -- '/TEST\s*=\s*test/d' ./debian/rules
            dpkg-buildpackage -rfakeroot -b -uc -us
            find .. -type f -name "git_*ubuntu*.deb" -exec dpkg -i \{\} \;
            apt-mark hold git
          }

          function installDotfiles() {
            git clone https://github.com/yasinuslu/dotfiles /opt/dotfiles
            cd /opt/dotfiles/
            ./install.sh

            echo 'function fish_greeting; end' > /root/.config/fish/functions/fish_greeting.fish

            fish -c 'npm config set strict-ssl false'

            fish -c 'npm i -g yarn'
            fish -c 'yarn config set strict-ssl false'

            mkdir -p /root/.config/fnm/bin
            mkdir -p /root/.yarn/bin
            mkdir -p /snap/bin
          }

          function installDocker() {
            su - root -c 'curl https://get.docker.com/ | sh'
          }

          function installMotd() {
            rm -rf /etc/update-motd.d/*
            ln -s /usr/bin/motd-spec /etc/update-motd.d/
          }

          function initServices() {
            systemctl daemon-reload

            systemctl restart docker
            systemctl enable docker
          }

          function initLocale() {
            cp /usr/share/zoneinfo/Europe/Istanbul /etc/localtime
          }
          function init() {
            chsh -s /usr/bin/fish
            initLocale
            installDotfiles
            installGitWithSSL
            installDocker
            installMotd
            initServices
          }

          init

      - path: /usr/bin/motd-spec
        permissions: 0777
        content: |
          #!/bin/bash

          echo
          echo
          screenfetch
          echo
          echo
          echo '  Use `docker --help` command for managing containers'
          echo '  Use `docker-compose --help` command for defining and running multi-container Docker applications'
          echo
          echo

      - path: /etc/ssh/sshrc
        content: |
          #!/bin/bash
          grep -q "Cloud-init .* finished" /var/log/cloud-init.log

          if [ $? -ne 0 ]; then
            echo "##################################################"
            echo "Waiting for cloud-init to finish, check back later"
            echo "##################################################"
            kill -9 $(ps aux | grep [email protected] | head  -n 1 | tr -s ' ' | cut -f 2 -d ' ')
          else
            rm -rf /etc/ssh/sshrc
          fi

      - path: /etc/ssh/sshd_config
        content: |
          PermitRootLogin yes
          PrintLastLog no
          UsePAM yes
          PasswordAuthentication yes
          ChallengeResponseAuthentication no
          X11Forwarding yes
          AcceptEnv LANG LC_*
          Subsystem sftp  /usr/lib/openssh/sftp-server

      - path: /etc/environment
        permissions: 0644
        content: |
          export LC_ALL=en_US.UTF-8
          export NODE_TLS_REJECT_UNAUTHORIZED=0
          export TZ='Europe/Istanbul'

    package_update: true
    package_upgrade: true
    packages:
      - build-essential
      - fakeroot
      - dpkg-dev
      - fish
      - tmux
      - vim
      - zip
      - unzip
      - curl
      - wget
      - python3
      - python3-pip
      - screenfetch
    runcmd:
      - su - root -c '/usr/bin/initCloud'

description: "Ornek bir otomatik LXC container icin profil olusturma ornegi"
name: "standart_ortamim"
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: lxdbr0
    type: nic
  root:
    path: /
    pool: default
    type: disk
  used_by:[]

Aslında bu kadar uzun konfigurasyonlara genellikle ihtiyaç duymasakta birçok detay kodun içeriğinden öğrenilebileceği için eklemek istedim. Şimdi yeni oluşturduğumuz profili kullanarak bir konteyner oluşturalım:

lxc launch ubuntu:18.04 otomatize_ortam -p standart_ortamim

Böyle güzel bir teknolojiyi öğrenmeme vesile olan Osman Alperen ELHAN‘a katkıları için teşekkür ederim…

kaynaklar:
https://discuss.linuxcontainers.org/t/is-the-snap-the-recommended-way-to-install-lxd-in-ubuntu-18-04/2248
https://unix.stackexchange.com/questions/254956/what-is-the-difference-between-docker-lxd-and-lxc
https://www.cyberciti.biz/faq/install-lxd-pure-container-hypervisor-on-ubuntu-18-04-lts/

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir