18

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

Thông thường, chúng ta 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ị công suất 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 để phát triển ứng dụng IoT so với các dịch vụ chạy trong 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ác cấu trúc thay thế như ARM64 trên máy chủ x86_64. Mục tiêu mà 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ữ, khuôn khổ và 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 thiết bị tiên tiến IoT. Trong bài viết này, tôi sẽ trình bày cách xây dựng và chạy hình ảnh vùng chứa AArch64 trên máy chủ x86_64 và sau đó xây dựng hình ảnh RPI3 để chạy trên phần cứng vật lý bằng Fedora và Podman .

Trong bài viết trước, tôi đã giả định điều kiện tiên quyết là cổng IoT có thể chạy các vùng chứa x86_64, nhưng rất tiếc, đây không phải là trường hợp sử dụng phổ biến do có nhiều loại cổng IoT khác nhau hiện nay 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 tiện dụng để 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 nhân Linux cho phép các định dạng tệp thực thi tùy ý được nhận dạng và chuyển. tới 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. Nó là một trong số các trình xử lý định dạng nhị phân trong nhân có liên quan đến việc chuẩn bị chạy chương trình không gian người dùng. "

Các khái niệm đằng sau dự án multiarch thực sự rất đơn giản: hãy tưởng tượng khởi chạy một vùng chứa đặc quyền có thể tương tác với máy chủ của vùng chứa và sử dụng binfmt_misctính năng để thông báo cho hạt nhân 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 về những người xử lý không? Chúng chỉ là các tệp thực thi QEMU x86_64 có khả năng chạy các tệp 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 mã nguồn mở, chung chung, vì vậy nó 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 suất gần như nguyên bản.

Tại thời điểm này, điều duy nhất bạn phải làm là đặt các tệp nhị phân QEMU phù hợp vào các vù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ố tệp nhị phân ARCH khác, nó sẽ kích hoạt binfmt_misctính năng trong nhân , sau đó sẽ chuyển hướng thực thi này đến tệp nhị phân trong đường dẫn mà chúng tôi đã chỉ định. Do thực tế là chúng ta đang ở trong hệ thống tệp gốc ảo của vùng 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 này thực sự đơn giản. Như trang dự án nhiều tìm kiếm 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 ta 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ỉ đang sử dụng cài đặt Minishift. Vì lý do này, do hệ điều hành cơ bản của Minishift thiếu tính ổn định, 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ừ hạt nhân của máy chủ.

Bây giờ chúng tôi đã sẵn sàng để kiểm tra một dự án xây dựng vùng chứa có 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 vùng chứa ARM 64-bit và sử dụng nó với Raspberry Pi 3: nó 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ừ hình ảnh cơ sở Debian với kiến ​​trúc ARM64. Nó cập nhật các repo APT và cài đặt một máy chủ web. Sau đó, nó thay thế cổng lắng nghe mặc định và sau đó nó đặt initlệnh phù hợp .

Tôi cá là bạn đang hỏi, "Điều kỳ diệu nằm ở đâu?"

Chà, điều kỳ diệu xảy ra nhờ /usr/bin/qemu-aarch64-staticcó sẵn trong chính hình ảnh vùng chứa. Nhị phân này là một nhị phân x86_64, khác với tất cả các nhị phân khác là AArch64. Nhân Linux sẽ chuyển tiếp các thực thi mã nhị phân AArch64 tới trình xử lý này!

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

[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 vùng chứa đã được tạo thành công và nó cũng đang chạy:

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

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

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

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

Chúng tôi cũng đã kiểm tra xem các tệp nhị phân có thực sự là kiến ​​trúc AArch64 hay không.

Bây giờ chúng ta có thể thử hình ảnh vùng chứa vừa xây dựng trên Raspberry Pi 3. Tôi đã chọn làm hệ điều hành cơ sở 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 máy ảo và chạy một docker savelệnh. Chúng ta có thể sử dụng thủ thuật này vì chúng ta đang ở trong môi trường demo; trong trường hợp sử dụng thực, 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 tôi có thể đẩy hình ảnh sang Raspberry Pi và cài đặt Podman để chạy nó!

Bạn không biết Podman là gì? Đọc thêm về Podman, 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 vùng chứa 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, hãy cũng kiểm tra nội dung và so sánh các tệp nhị phân trong vù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 vừa thấy rằng chúng tôi có thể chạy vùng chứa 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 được đóng gói .

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

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

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!

|