Phát triển và triển khai IoT Edge với các container thông qua OpenShift: Phần ...


Lê Kim Xuân
10 tháng trước
Hữu ích 4 Chia sẻ Viết bình luận 0
Đã xem 9523

Trong phần đầu tiên của loạt bài này , chúng ta đã thấy một nền tảng như một dịch vụ (PaaS) hiệu quả như Red Hat OpenShift là để phát triển các ứng dụng cạnh IoT và phân phối chúng đến các trang web từ xa, nhờ vào các công nghệ containerRed Hat Ansible Automatic .

Thông thường, chúng tôi nghĩ về các ứng dụng IoT như một thứ được thiết kế đặc biệt cho các thiết bị năng lượng thấp với khả năng hạn chế. Các thiết bị IoT có thể sử dụng các kiến ​​trúc hoặc nền tảng CPU khác nhau. Vì lý do này, chúng tôi có xu hướng sử dụng các công nghệ hoàn toàn khác nhau để phát triển ứng dụng IoT so với các dịch vụ chạy trong một trung tâm dữ liệu.

Trong phần hai, chúng tôi khám phá một số kỹ thuật cho phép bạn xây dựng và kiểm tra có chứa các kiến ​​trúc thay thế như ARM64 trên máy chủ x86_64. Mục tiêu chúng tôi đang hướng tới là cho phép bạn sử dụng cùng một ngôn ngữ, khung và các công cụ phát triển cho mã chạy trong trung tâm dữ liệu của bạn hoặc tất cả các cách tiếp cận với các thiết bị cạnh IoT. Trong bài viết này, tôi sẽ trình bày việc xây dựng và chạy hình ảnh container AArch64 trên máy chủ x86_64 và sau đó xây dựng hình ảnh RPI3 để chạy nó trên phần cứng vật lý bằng Fedora và Podman .

Trong bài viết trước, tôi đã giả sử như một điều kiện tiên quyết rằng một cổng IoT có thể có khả năng chạy các container x86_64, nhưng thật không may, đây không phải là trường hợp sử dụng phổ biến do các loại cổng IoT khác nhau hiện có trên thị trường.

Tôi phát hiện ra một dự án rất thú vị có tên là "multiarch" với nhiều kho lưu trữ có sẵn trên GitHub .

Mục đích của dự án là tạo ra một cách thuận tiện để sử dụng tính năng nhân Linux tích hợp có tên binfmt_misc, được giải thích trong Wikipedia như sau: " binfmt_misc là một khả năng của hạt nhân Linux cho phép nhận dạng và thông qua các định dạng tệp thực thi tùy ý cho một số ứng dụng không gian người dùng nhất định, chẳng hạn như trình giả lập và máy ảo. Đây là một trong số các trình xử lý định dạng nhị phân trong kernel có liên quan đến việc chuẩn bị chương trình không gian người dùng để chạy. "

Các khái niệm đằng sau dự án multiarch rất đơn giản: hãy tưởng tượng khởi chạy một thùng chứa đặc quyền có thể tương tác với máy chủ của container và sử dụng binfmt_misctính năng này để thông báo cho kernel rằng một số trình xử lý nhị phân khác có sẵn ở đâu đó trong PATH.

Bạn có đoán được về những người xử lý? Chúng chỉ là các tệp thực thi QEMU x86_64 có khả năng chạy các nhị phân kiến ​​trúc cụ thể: ARM, MIPS, Power, v.v.

Hãy nhớ rằng QEMU là một trình giả lập và ảo hóa máy chung và nguồn mở, vì vậy đây là ứng cử viên phù hợp cho công việc này. Nó cũng được sử dụng để chạy các máy ảo KVM với hiệu năng gần như nguyên gốc.

Tại thời điểm này, điều duy nhất bạn phải làm là đặt các nhị phân QEMU đúng vào các thùng chứa có kiến ​​trúc khác. Tại sao chúng phải được đặt trong các thùng chứa?

Các tệp thực thi QEMU phải được đặt trong các thùng chứa vì khi công cụ chứa cố gắng thực thi một số nhị phân ARCH khác, nó sẽ kích hoạt trong nhân binfmt_misctính năng, sau đó sẽ chuyển hướng thực hiện này sang nhị phân trong đường dẫn mà chúng ta đã chỉ định. Do thực tế là chúng ta đang ở trong hệ thống tập tin gốc ảo của bộ chứa, tệp thực thi QEMU phải nằm trong cùng một môi trường của tệp nhị phân vừa chạy.

Việc kích hoạt tính năng thực sự đơn giản. Như trang dự án multiarch nêu rõ, chúng tôi chỉ cần đảm bảo rằng multiarch/qemu-user-static:registervới --resettùy chọn được sử dụng.

Trang dự án đề xuất sử dụng Docker để áp dụng hành động này và tất nhiên, tính năng này sẽ bị mất khi khởi động lại máy tiếp theo, nhưng chúng tôi có thể đặt nó làm systemddịch vụ một lần.

Đối với bài viết này, chúng tôi chỉ sử dụng cài đặt Minishift. Vì lý do này, do sự thiếu kiên trì của hệ điều hành cơ sở của Minishift, chúng tôi sẽ chỉ chạy lệnh Docker khi chúng tôi đã đăng nhập:

[alex@lenny ~]$ cdk-minishift ssh
[docker@minishift ~]$ docker run --rm --privileged multiarch/qemu-user-static:register --reset
Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
Setting /usr/bin/qemu-armeb-static as binfmt interpreter for armeb
Setting /usr/bin/qemu-sparc32plus-static as binfmt interpreter for sparc32plus
Setting /usr/bin/qemu-ppc-static as binfmt interpreter for ppc
Setting /usr/bin/qemu-ppc64-static as binfmt interpreter for ppc64
Setting /usr/bin/qemu-ppc64le-static as binfmt interpreter for ppc64le
Setting /usr/bin/qemu-m68k-static as binfmt interpreter for m68k
Setting /usr/bin/qemu-mips-static as binfmt interpreter for mips
Setting /usr/bin/qemu-mipsel-static as binfmt interpreter for mipsel
Setting /usr/bin/qemu-mipsn32-static as binfmt interpreter for mipsn32
Setting /usr/bin/qemu-mipsn32el-static as binfmt interpreter for mipsn32el
Setting /usr/bin/qemu-mips64-static as binfmt interpreter for mips64
Setting /usr/bin/qemu-mips64el-static as binfmt interpreter for mips64el
Setting /usr/bin/qemu-sh4-static as binfmt interpreter for sh4
Setting /usr/bin/qemu-sh4eb-static as binfmt interpreter for sh4eb
Setting /usr/bin/qemu-s390x-static as binfmt interpreter for s390x
Setting /usr/bin/qemu-aarch64-static as binfmt interpreter for aarch64
Setting /usr/bin/qemu-aarch64_be-static as binfmt interpreter for aarch64_be
Setting /usr/bin/qemu-hppa-static as binfmt interpreter for hppa
Setting /usr/bin/qemu-riscv32-static as binfmt interpreter for riscv32
Setting /usr/bin/qemu-riscv64-static as binfmt interpreter for riscv64
Setting /usr/bin/qemu-xtensa-static as binfmt interpreter for xtensa
Setting /usr/bin/qemu-xtensaeb-static as binfmt interpreter for xtensaeb
Setting /usr/bin/qemu-microblaze-static as binfmt interpreter for microblaze
Setting /usr/bin/qemu-microblazeel-static as binfmt interpreter for microblazeel


Như bạn đã thấy trong lệnh trước, chúng tôi vừa đăng ký cho máy chủ x86_64 hiện tại một loạt các trình xử lý sẽ nhận được các yêu cầu cụ thể cho các hướng dẫn của kiến ​​trúc khác nhau từ kernel của máy chủ.

Bây giờ chúng tôi đã sẵn sàng để thử nghiệm một dự án xây dựng container với kiến ​​trúc khác với x86_64.

Vì lý do này, tôi đã chuẩn bị một dự án thử nghiệm đơn giản để xây dựng hình ảnh container 64-bit ARM và sử dụng nó với Raspberry Pi 3: đó chỉ là một máy chủ web.

Như bạn sẽ thấy trên trang dự án , git repo chỉ chứa một Dockerfile:

FROM multiarch/debian-debootstrap:arm64-stretch-slim

RUN apt-get update
RUN apt-get install -y apache2
RUN sed -i 's/80/8080/g' /etc/apache2/ports.conf

EXPOSE 8080

CMD ["/usr/sbin/apache2ctl", "-DFOREGROUND"]


Nó bắt đầu từ một hình ảnh cơ sở Debian với kiến ​​trúc ARM64. Nó cập nhật các repos APT và cài đặt một máy chủ web. Sau đó, nó thay thế cổng nghe mặc định và sau đó nó đặt đúng initlệnh.

Tôi cá là bạn đang hỏi, "Phép thuật ở đâu?"

Vâng, điều kỳ diệu xảy ra nhờ /usr/bin/qemu-aarch64-static, có sẵn trong hình ảnh container. Nhị phân này là nhị phân x86_64, khác với tất cả các nhị phân khác là AArch64. Hạt nhân Linux sẽ chuyển tiếp các tệp nhị phân AArch64 cho trình xử lý này!

Bây giờ chúng tôi đã sẵn sàng để tạo dự án và tài nguyên OpenShift để xử lý bản dựng của hình ảnh container:

[alex@lenny ~]$ oc new-project test-arm-project
Now using project "test-arm-project" on server "https://192.168.42.213:8443".

[alex@lenny ~]$ oc new-app https://github.com/alezzandro/test-arm-container
--> Found Docker image 4734ae4 (3 days old) from Docker Hub for "multiarch/debian-debootstrap:arm64-stretch-slim"

    * An image stream tag will be created as "debian-debootstrap:arm64-stretch-slim" that will track the source image
    * A Docker build using source code from https://github.com/alezzandro/test-arm-container will be created
      * The resulting image will be pushed to image stream tag "test-arm-container:latest"
      * Every time "debian-debootstrap:arm64-stretch-slim" changes a new build will be triggered
    * This image will be deployed in deployment config "test-arm-container"
    * Port 8080/tcp will be load balanced by service "test-arm-container"
      * Other containers can access this service through the hostname "test-arm-container"
    * WARNING: Image "multiarch/debian-debootstrap:arm64-stretch-slim" runs as the 'root' user which may not be permitted by your cluster administrator

--> Creating resources ...
    imagestream.image.openshift.io "debian-debootstrap" created
    imagestream.image.openshift.io "test-arm-container" created
    buildconfig.build.openshift.io "test-arm-container" created
    deploymentconfig.apps.openshift.io "test-arm-container" created
    service "test-arm-container" created
--> Success
    Build scheduled, use 'oc logs -f bc/test-arm-container' to track its progress.
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose svc/test-arm-container' 
    Run 'oc status' to view your app.


Nhìn qua giao diện web OpenShift, chúng ta có thể thấy rằng hình ảnh container đã được xây dựng thành công và nó cũng đang chạy:

Chúng tôi thậm chí có thể truy cập vào container đang chạy và cố gắng thực hiện một số lệnh:

Như bạn có thể thấy từ lệnh trước, chúng tôi đã đính kèm vào thùng chứa đang chạy và xác minh rằng mọi lệnh đều được ủy quyền thông qua /usr/bin/qemu-aarch64-static.

Chúng tôi cũng đã kiểm tra rằng các nhị phân thực sự là kiến ​​trúc AArch64.

Bây giờ chúng ta có thể thử hình ảnh container vừa được xây dựng trên Raspberry Pi 3. Tôi đã chọn làm hệ điều hành cơ bản Fedora ARM Linux.

Đầu tiên, tôi thiết lập một thẻ SD với một công cụ dễ sử dụng sau khi tôi tải xuống hình ảnh từ trang web của Fedora :

[alex@lenny Downloads]$ sudo arm-image-installer --addkey=/home/alex/.ssh/id_rsa.pub --image=/home/alex/Downloads/Fedora-Minimal-29-1.2.aarch64.raw.xz --relabel --resizefs --norootpass --target=rpi3 --media=/dev/sda
[sudo] password for alex: 
 ***********************************************************
 ** WARNING: You have requested the image be written to sda.
 ** /dev/sda is usually the root filesystem of the host. 
 ***********************************************************
 ** Do you wish to continue? (type 'yes' to continue)
 ***********************************************************
 = Continue? yes

=====================================================
= Selected Image:                                 
= /home/alex/Downloads/Fedora-Minimal-29-1.2.aarch64.raw.xz
= Selected Media : /dev/sda
= U-Boot Target : rpi3
= SELinux relabel will be completed on first boot.
= Root Password will be removed.
= Root partition will be resized
= SSH Public Key /home/alex/.ssh/id_rsa.pub will be added.
=====================================================
...
= Raspberry Pi 3 Uboot is already in place, no changes needed.
= Removing the root password.
= Adding SSH key to authorized keys.
= Touch /.autorelabel on rootfs.

= Installation Complete! Insert into the rpi3 and boot.


Trong khi hệ điều hành Raspberry Pi 3 hoàn toàn mới của chúng tôi khởi động, chúng tôi có thể xuất hình ảnh Docker từ máy ảo Minishift đang chạy.

Chúng tôi sẽ kết nối trực tiếp với VM và chạy docker savelệnh. Chúng tôi có thể sử dụng thủ thuật này vì chúng tôi đang ở trong môi trường demo; trong trường hợp sử dụng thực tế, chúng tôi có thể xuất sổ đăng ký OpenShift nội bộ để cho phép các thiết bị bên ngoài kết nối.

[alex@lenny ~]$ cdk-minishift ssh
Last login: Thu Jan 24 19:15:36 2019 from 192.168.42.1

[docker@minishift ~]$ docker save -o test-arm-container.tar 172.30.1.1:5000/test-arm-project/test-arm-container:latest

[alex@lenny Downloads]$ scp -i ~/.minishift/machines/minishift/id_rsa docker@`cdk-minishift ip`/home/docker/test-arm-container.tar


Sau đó chúng ta có thể đẩy hình ảnh lên Raspberry Pi và cài đặt Podman để chạy nó!

Không biết Podman là gì? Đọc thêm về Podman, có trong Red Hat Enterprise Linux .

[alex@lenny Downloads]$ scp test-arm-container.tar root@192.168.1.52:/root/test-arm-container.tar                              100% 214MB 450.1KB/s 08:07 

[alex@lenny Downloads]$ ssh root@192.168.1.52

[root@localhost ~]# cat /etc/fedora-release 
Fedora release 29 (Twenty Nine)

[root@localhost ~]# uname -a
Linux localhost.localdomain 4.19.15-300.fc29.aarch64 #1 SMP Mon Jan 14 16:22:13 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux

[root@localhost ~]# dnf install -y podman


Sau đó, chúng tôi tải hình ảnh container và cuối cùng chạy nó:

[root@localhost ~]# podman load -i test-arm-container.tar 
Getting image source signatures
Copying blob 36a049148cc6: 104.31 MiB / 104.31 MiB [=====================] 1m34s
Copying blob d56ce20a3f9c: 15.20 MiB / 15.20 MiB [=======================] 1m34s
Copying blob cf01d69beeaf: 94.53 MiB / 94.53 MiB [=======================] 1m34s
Copying blob 115c696bd46d: 3.00 KiB / 3.00 KiB [=========================] 1m34s
Copying config 478a2361357e: 5.46 KiB / 5.46 KiB [==========================] 0s
Writing manifest to image destination
Storing signatures
Loaded image(s): 172.30.1.1:5000/arm-project/test-arm-container:latest

[root@localhost ~]# podman images
REPOSITORY                                       TAG IMAGE ID CREATED SIZE
172.30.1.1:5000/arm-project/test-arm-container   latest 478a2361357e 4 hours ago 224 MB

[root@localhost ~]# podman run -d 172.30.1.1:5000/arm-project/test-arm-container:latest
cdbf0ac43a2dd01afd73220d5756060665df0b72a43bd66bf865d1c6149f325f

[root@localhost ~]# podman ps
CONTAINER ID  IMAGE                                         COMMAND CREATED STATUS PORTS  NAMES
cdbf0ac43a2d  172.30.1.1:5000/arm-project/test-arm-container:latest  /usr/sbin/apache2... 6 seconds ago Up 5 seconds ago       pedantic_agnesi


Sau đó chúng tôi có thể kiểm tra máy chủ web:

[root@localhost ~]# podman inspect cdbf0ac43a2d | grep -i address
            "LinkLocalIPv6Address": "",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "GlobalIPv6Address": "",
            "IPAddress": "10.88.0.7",
            "MacAddress": "1a:c8:30:a4:be:2f"

[root@localhost ~]# curl 10.88.0.7:8080 2>/dev/null | head
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Apache2 Debian Default Page: It works</title>
    <style type="text/css" media="screen">
  * {
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;


Cuối cùng, chúng ta cũng kiểm tra nội dung và so sánh các nhị phân trong thùng chứa với các tệp trong Raspberry Pi:

[root@localhost ~]# podman run -ti 172.30.1.1:5000/arm-project/test-arm-container:latest /bin/bash

root@8e39d1c28259:/# 
root@8e39d1c28259:/# id
uid=0(root) gid=0(root) groups=0(root)

root@8e39d1c28259:/# uname -a
Linux 8e39d1c28259 4.19.15-300.fc29.aarch64 #1 SMP Mon Jan 14 16:22:13 UTC 2019 aarch64 GNU/Linux

root@8e39d1c28259:/# cat /etc/debian_version 
9.6

root@8e39d1c28259:/# file /bin/bash

/bin/bash: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=29b2624b1e147904a979d91daebc60c27ac08dc6, stripped

root@8e39d1c28259:/# exit

[root@localhost ~]# file /bin/bash

/bin/bash: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=25dee020ab8f6525bd244fb3f9082a47e940b1e6, stripped, too many notes (256)


Chúng tôi chỉ thấy rằng chúng tôi có thể chạy container này với Podman. Vì vậy, tại sao không áp dụng một số kỹ thuật mà chúng ta đã thấy trong các bài viết trước đây về Podman và sự tích hợp của nó với systemd?

Đọc thêm về Podman và quản lý các dịch vụ hệ thống container .

Nếu bạn đang tìm cách phát triển sự nghiệp của mình, tư cách thành viên chương trình Red Hat Developer miễn phí có thể mở khóa thư viện của chúng tôi về các mánh gian lận và sách điện tử về phát triển ứng dụng thế hệ tiếp theo. Nhấn vào đây để biết thêm thông tin .

Tài nguyên bổ sung

Đó là tất cả. Tôi hy vọng bạn thích giải pháp IoT này!

Hữu ích 4 Chia sẻ Viết bình luận 0
Đã xem 9523