No menu items!
No menu items!
More

    Build image KVM với Packer

    Packer là một công cụ để tự động hóa việc tạo ra nhiều image của Hashicorp. Nó hỗ trợ nhiều cloud như AWS EC2, DigitalOcean, LXD, VMWare, QEMU, v.v. Trong bài viết này, mình sẽ chia sẻ cách đóng gói một image có chứa bộ kubernetes cho QEMU/KVM dựa trên Cloud Image rút gọn của Ubuntu 18.04.

    Yêu cầu:

    • Packer
    • Cloud-localds (from cloud-image-utils in ubuntu)
    • QEMU/KVM được cài đặt sẵn trong máy chủ

    1. Đảm bảo bạn đã cài đặt QEMU/KVM cũng như Packer trong máy chủ. Nếu bạn sử dụng Linux, bạn có thể sử dụng các lệnh sau:

    sudo apt install packer -y
    sudo apt-get install cloud-image-utils qemu-system-x86 -y

    2. Tạo file cấu hình chứa các thông tin để build image có tên kubernetes.json. Đầu tiên hãy tạo 1 thư mục chứa các file config.

    sudo mkdir -p /root/packer

    Sau đó chạy đoạn code dưới để tạo file kubernetes.json.

    cat > /root/packer/kubernetes.json << 'OEF'
    {
        "builders":[
            {
                "type": "qemu",
                "iso_url": "{{ user `image_url` }}",
                "iso_checksum": "{{ user `image_checksum` }}",
                "iso_checksum_type": "{{ user `image_checksum_type` }}",
                "format": "qcow2",
                "disk_image": true,
                "disk_size": "{{ user `disk_size` }}",
                "output_directory": "build",
                "disk_compression": true,
                "headless": true,
                "boot_command": [
                    "<enter>"
                ],
                "accelerator": "kvm",
                "ssh_username": "{{ user `ssh_username` }}",
                "ssh_password": "{{ user `ssh_password` }}",
                "ssh_port": 22,
                "ssh_wait_timeout": "300s",
                "vm_name": "{{ user `vm_name` }}",
                "use_default_display": false,
                "qemuargs": [
                    ["-m", "{{ user `memory` }}"],
                    ["-smp", "cpus={{ user `cpus` }}"],
                    ["-cdrom", "{{ user `cloud_init_image` }}"],
                    ["-serial", "mon:stdio"]
                ]
          }
        ],
        "provisioners": [
          {
            "execute_command": "echo '{{ user `ssh_password` }}' | {{.Vars}} sudo -E -S bash -x '{{.Path}}'",
            "scripts": [
              "setup.sh"
            ],
            "type": "shell"
          },
          {
            "type": "shell",
            "inline": ["sudo sync"]
          }
        ],
        "variables": {
          "cpus": "2",
          "image_checksum": "2f8c35d32e9c0e09efe75759e1c1b9c3dbd8f41392051e6c4220d2b689dc85b4",
          "image_checksum_type": "sha256",
          "image_url" : "https://cloud-images.ubuntu.com/minimal/releases/bionic/release/ubuntu-18.04-minimal-cloudimg-amd64.img",
          "cloud_init_image": "/root/packer/cloud-init.img",
          "disk_size": "8192",
          "memory": "2048M",
          "ssh_username": "ubuntu",
          "ssh_password": "Hoanghd164",
          "vm_name": "kubernetes-{{timestamp}}.qcow2"
        }
    }
    OEF

    Ghi chú:

    • image_checksum có thể được tìm thấy từ SHA256SUMS hoặc sử dụng sha256sum <image_file>
    • image_url, có thể là đường dẫn file local hoặc đường dẫn http(s), trong trường hợp này, chúng ta sử dụng đường dẫn https từ cloud image của Ubuntu.
    • cloud_init_image là cloud image ubuntu rút gọn có hỗ trợ cấu hình cloudinit
    • ssh_username, theo mặc định, sử dụng image rút gọn thường sử dụng ubuntu làm username mặc định.
    • ssh_password là giá trị cần được xác định trong cấu hình cloudinit lúc khởi tạo máy ảo.

    3. Tạo file userdata.cfg

    cat > /root/packer/userdata.cfg << 'OEF'
    #cloud-config
    password: Hoanghd164
    ssh_pwauth: true
    chpasswd:
      expire: false
    
    locale: en_US.UTF-8
    locale_configfile: /etc/default/locale'''
    OEF

    Sau đó tạo 1 image mới gắn file userdata.cfg để cài đặt cấu hình cloudinit:

    cloud-localds /root/packer/cloud-init.img /root/packer/userdata.cfg

    4. Tạo file script cài đặt Keepalived, Haproxy, Containerd và Kubernetes.

    cat > /root/packer/setup.sh << 'OEF'
    #!/bin/bash -x
    
    apt update && apt-get install ca-certificates curl gnupg lsb-release -y 
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list 
    
    curl -s https://packages.cloud.google.com/apt/dists/kubernetes-xenial/main/binary-amd64/Packages | grep Version | tail -5 
    curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -  && \
    echo 'deb http://apt.kubernetes.io/ kubernetes-xenial main' | tee /etc/apt/sources.list.d/kubernetes.list  && \
    
    apt update && apt-get upgrade -y
    
    apt-get install containerd.io -y 
    apt-get install -y kubelet=1.23.8-00 kubectl=1.23.8-00 kubeadm=1.23.8-00
    apt-get install keepalived -y
    apt-get install haproxy -y
    
    tee /etc/sysctl.d/kubernetes.conf<<EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
    EOF
    
    echo "net.netfilter.nf_conntrack_max=1000000" >> /etc/sysctl.conf
    sysctl --system 
    
    tee /etc/modules-load.d/containerd.conf <<EOF
    overlay
    br_netfilter
    EOF
    
    modprobe overlay 
    modprobe br_netfilter 
    sysctl --system 
    
    sed -i "/ swap / s/^\(.*\)$/#\1/g" /etc/fstab || sed -i '/swap/d' /etc/fstab 
    swapoff -a
    
    mkdir -p /etc/containerd
    containerd config default > /etc/containerd/config.toml
    systemctl enable containerd
    systemctl restart containerd
    kubeadm config images pull
    OEF

    Ghi chú:

    • kubeadm config images pull, lệnh này sẽ kéo các image docker cần thiết để chạy Kubernetes. Điều này sẽ tiết kiệm thời gian của bạn khi bạn khởi động một Cluster, vì image docker được đưa vào image của VM.
    • sudo apt-mark hold kubelet kubeadm kubectl lệnh này sẽ đảm bảo các gói được đề cập không được nâng cấp để tránh bị hỏng khi tự động nâng cấp được kích hoạt.

    5. Tất cả mọi thứ được thiết lập! Bước tiếp theo là xác thực cấu hình và sau đó build image.

    Sau khi chuẩn bị xong các file, bạn sẽ có cây thư mục như dưới.

    packer/
    ├── cloud-init.img
    ├── kubernetes.json
    ├── setup.sh
    └── userdata.cfg
    
    0 directories, 4 files

    Xác thực cấu hình bằng lệnh dưới.

    $ cd /root/packer/ && packer validate kubernetes.json
    Template validated successfully.

    Nếu xác thực không có lỗi, tiến hành build image.

    packer build kubernetes.json

    Đây là đoạn logs quá trình build image, mình đã lược bỏ 1 số phần để cho gọn.

    $ packer build kubernetes.json
    qemu output will be in this color.
    
    ==> qemu: Retrieving ISO
    1 items:  199.94 MiB / 199.94 MiB [=====================================================================================================================================================================================================================================] 23s
        qemu: Transferred: https://cloud-images.ubuntu.com/minimal/releases/bionic/release/ubuntu-18.04-minimal-cloudimg-amd64.img
    ==> qemu: Copying hard drive...
    ==> qemu: Resizing hard drive...
    ==> qemu: Found port for communicator (SSH, WinRM, etc): 2423.
    ==> qemu: Looking for available port between 5900 and 6000 on 127.0.0.1
    ==> qemu: Starting VM, booting disk image
        qemu: The VM will be run headless, without a GUI. If you want to
        qemu: view the screen of the VM, connect via VNC without a password to
        qemu: vnc://127.0.0.1:5965
    ==> qemu: Overriding defaults Qemu arguments with QemuArgs...
    ==> qemu: Waiting 10s for boot...
    ==> qemu: Connecting to VM via VNC (127.0.0.1:5965)
    ==> qemu: Typing the boot command over VNC...
    ==> qemu: Using ssh communicator to connect: 127.0.0.1
    ==> qemu: Waiting for SSH to become available...
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
        qemu: I1207 17:29:19.761412    2583 version.go:255] remote version is much newer: v1.25.4; falling back to: stable-1.23
        qemu: [config/images] Pulled k8s.gcr.io/kube-apiserver:v1.23.14
        qemu: [config/images] Pulled k8s.gcr.io/kube-controller-manager:v1.23.14
        qemu: [config/images] Pulled k8s.gcr.io/kube-scheduler:v1.23.14
        qemu: [config/images] Pulled k8s.gcr.io/kube-proxy:v1.23.14
        qemu: [config/images] Pulled k8s.gcr.io/pause:3.6
        qemu: [config/images] Pulled k8s.gcr.io/etcd:3.5.1-0
        qemu: [config/images] Pulled k8s.gcr.io/coredns/coredns:v1.8.6
    ==> qemu: Provisioning with shell script: /tmp/packer-shell368451394
    ==> qemu: Halting the virtual machine...
    ==> qemu: Converting hard drive...
    ==> qemu: Error getting file lock for conversion; retrying...
    Build 'qemu' finished.
    
    ==> Builds finished. The artifacts of successful builds are:
    --> qemu: VM files in directory: build

    Bây giờ bạn đã thấy có 1 image mới có tên kubernetes-1670434068.qcow2 trong thư mục /root/packer/build

    /root/packer/
    ├── build
    │   └── kubernetes-1670434068.qcow2
    ├── cloud-init.img
    ├── kubernetes.json
    ├── packer_cache
    │   └── 9bd9c054d3a88540f4806699924621fa27d683a6f38750b5011f58b944920d3a.iso
    ├── setup.sh
    └── userdata.cfg
    
    2 directories, 6 files

    6. Image đã sẵn sàng để sử dụng, nếu kích thước đĩa os được tạo ra qua nhỏ, bạn có thể thay đổi kích thước image bằng lệnh sau qemu-img resize <IMAGE_FILE> +DESIRED_SIZE. Giả sử mình muốn kubernetes-1584350145.qcow2 cái hiện có kích thước 8GB, được thay đổi kích thước thành 100GB, thì lệnh sẽ là:

    qemu-img resize kubernetes-1670434068.qcow2 +92G

    Và khi bạn tạo máy ảo mới bằng file image kubernetes-1670434068.qcow2, tất cả các ứng dụng bạn đã chạy đã có sẵn trong máy ảo.

    ubuntu@ubuntu:~$ sudo -s
    
    root@ubuntu:~# which kubeadm                                                                                                          │root@kvm-node03:~#
    /usr/bin/kubeadm     
                                                                                                                     │root@kvm-node03:~#
    root@ubuntu:~# which kubectl                                                                                                          │root@kvm-node03:~#
    /usr/bin/kubectl     
                                                                                                                     │root@kvm-node03:~#
    root@ubuntu:~# which haproxy                                                                                                          │root@kvm-node03:~#
    /usr/sbin/haproxy   
                                                                                                                      │root@kvm-node03:~#
    root@ubuntu:~# which keepalived                                                                                                       │root@kvm-node03:~#
    /usr/sbin/keepalived

    Chúc các bạn thành công.

    Bài viết gần đây

    spot_img

    Related Stories

    Leave A Reply

    Please enter your comment!
    Please enter your name here

    Đăng ký nhận thông tin bài viết qua email