From a453f4b7068611c510f75c5a75db0386d5d13211 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Thu, 24 Mar 2022 10:11:06 +0800 Subject: [PATCH 01/42] updated releasenotes docs of master --- ...mon-vulnerabilities-and-exposures-(cve).md | 2 +- .../en/docs/Releasenotes/installing-the-os.md | 30 +++++++-------- docs/en/docs/Releasenotes/key-features.md | 37 +++++++++++-------- docs/en/docs/Releasenotes/release_notes.md | 2 +- docs/en/docs/Releasenotes/user-notice.md | 5 ++- docs/en/menu/index.md | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md b/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md index 4286b2459..1485fd759 100644 --- a/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md +++ b/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md @@ -1,4 +1,4 @@ # Common Vulnerabilities and Exposures (CVEs) -For CVEs involved in the version, see the [CVE list](https://www.openeuler.org/en/security/cve/). +For details about the CVEs involved in the version, see the [CVE list](https://www.openeuler.org/en/security/cve/). diff --git a/docs/en/docs/Releasenotes/installing-the-os.md b/docs/en/docs/Releasenotes/installing-the-os.md index 46cb1a80c..80f737499 100644 --- a/docs/en/docs/Releasenotes/installing-the-os.md +++ b/docs/en/docs/Releasenotes/installing-the-os.md @@ -1,20 +1,20 @@ -# Installing the OS +# OS Installation ## Release Files -The openEuler release files include [ISO release pacakges](http://repo.openeuler.org/openEuler-21.09/ISO/), [VM images](http://repo.openeuler.org/openEuler-21.09/virtual_machine_img/), [containier images](http://repo.openeuler.org/openEuler-21.09/docker_img/), [edge images](http://repo.openeuler.org/openEuler-21.09/edge_img/), [embedded images](https://repo.openeuler.org/openEuler-21.09/edge_img/), and [repo sources](http://repo.openeuler.org/openEuler-21.09/). The following tables describe those files respectively. +The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. Table 1 ISO release packages | Name | Description | | ------------------------------------------ | ------------------------------------------------------------ | -| openEuler-21.03-aarch64-dvd.iso | Basic installation ISO file of the AArch64 architecture, including the core components for running the minimum system. | -| openEuler-21.03-everything-aarch64-dvd.iso | Full installation ISO file of the AArch64 architecture, including all components for running the entire system. | -| openEuler-21.03-debuginfo-aarch64-dvd.iso | ISO file for openEuler debugging in the AArch64 architecture, including the symbol table information required for debugging. | -| openEuler-21.03-x86_64-dvd.iso | Basic installation ISO file of the x86_64 architecture, including the core components for running the minimum system. | -| openEuler-21.03-everything-x86_64-dvd.iso | Full installation ISO file of the x86_64 architecture, including all components for running the entire system. | -| openEuler-21.03-debuginfo-x86_64-dvd.iso | ISO file for openEuler debugging in the x86_64 architecture, including the symbol table information required for debugging. | -| openEuler-21.03-source-dvd.iso | ISO file of the openEuler source code. | +| openEuler-22.03-LTS-aarch64-dvd.iso | Base installation ISO file of the AArch64 architecture, including the core components for running the minimum system. | +| openEuler-22.03-LTS-everything-aarch64-dvd.iso | Full installation ISO file of the AArch64 architecture, including all components for running the entire system. | +| openEuler-22.03-LTS-everything-debug-aarch64-dvd.iso | ISO file for openEuler debugging in the AArch64 architecture, including the symbol table information required for debugging. | +| openEuler-22.03-LTS-x86_64-dvd.iso | Base installation ISO file of the x86_64 architecture, including the core components for running the minimum system. | +| openEuler-22.03-LTS-everything-x86_64-dvd.iso | Full installation ISO file of the x86_64 architecture, including all components for running the entire system. | +| openEuler-22.03-LTS-everything-debuginfo-x86_64-dvd.iso | ISO file for openEuler debugging in the x86_64 architecture, including the symbol table information required for debugging. | +| openEuler-22.03-LTS-source-dvd.iso | ISO file of the openEuler source code. | | openEuler-21.09-edge-aarch64-dvd.iso | Edge ISO file in the AArch64 architecture, including the core components for running the minimum system. | | openEuler-21.09-edge-x86_64-dvd.iso | Edge ISO file in the x86_64 architecture, including the core components for running the minimum system. | @@ -22,8 +22,8 @@ Table 2 VM images | Name | Description | | -------------------------------- | -------------------------------------------------- | -| openEuler-21.03.aarch64.qcow2.xz | VM image of openEuler in the AArch64 architecture. | -| openEuler-21.03.x86_64.qcow2.xz | VM image of openEuler in the x86_64 architecture. | +| openEuler-22.03-LTS-aarch64.qcow2.xz | VM image of openEuler in the AArch64 architecture. | +| openEuler-22.03-LTS-x86_64.qcow2.xz | VM image of openEuler in the x86_64 architecture. | Note: The default password of **root** user of the VM image is **openEuler12#$**. Change the password upon the first login. @@ -51,7 +51,7 @@ Table 4 Repo sources ## Minimum Hardware Specifications -The following table lists the minimum hardware specifications for openEuler 21.03. +The following table lists the minimum hardware specifications for openEuler 22.03 LTS. Table 1 Minimum hardware requirements @@ -63,7 +63,7 @@ Table 1 Minimum hardware requirements ## Hardware Compatibility -The following table lists the supported servers and configurations of openEuler. +The following table describes the servers and configurations supported by openEuler. openEuler will support more servers in the future. Partners and developers are welcome to participate in the contribution and verification. For details about the servers supported by openEuler, see the [Compatibility List](https://www.openeuler.org/en/compatibility/). Table 1 Supported servers and configurations @@ -92,7 +92,7 @@ Table 1 Supported servers and configurations

Memory

-

32G\*4 2933MHz

+

4 x 32 GB 2933 MHz

RAID card

@@ -118,7 +118,7 @@ Table 1 Supported servers and configurations

Memory

-

32*4 2400MHz

+

4 x 32 GB 2400 MHz

RAID card

diff --git a/docs/en/docs/Releasenotes/key-features.md b/docs/en/docs/Releasenotes/key-features.md index b33be6a0a..648020be1 100644 --- a/docs/en/docs/Releasenotes/key-features.md +++ b/docs/en/docs/Releasenotes/key-features.md @@ -16,7 +16,7 @@ In-depth optimizations of scheduling, I/O, and memory management have been perfo - **Huge page vmalloc performance optimization**: When calling vmalloc() to allocate spaces that exceed the minimum size of huge pages, the huge page instead of the base page is used to map the memory, improving the TLB usage and reducing TLB misses. -- **Uncorrectable error (UCE) fault tolerance**: When a UCE occurs in the copy-on-write (COW) or pagecache scenario in kernel mode, the system kills the user-mode process instead of panicking. This feature is disabled by default, you can enable it by adding **CONFIG_UCE_KERNEL_RECOVERY** to the kernel configuration, and configure it in the kernel boot parameter interface **/proc/cmdline** (add **uce_kernel_recovery=[0,3]**) and proc interface **/proc/sys/kernel/uce_kernel_recovery**. +- **Uncorrectable error (UCE) fault tolerance**: When a UCE occurs in the copy_from_user scenario, the system kills the associated user-mode process instead of kernel panicking. This feature is disabled by default. You can enable it by adding **CONFIG_UCE_KERNEL_RECOVERY** to the kernel configuration, and configure it in the kernel boot parameter interface **/proc/cmdline** (add **uce_kernel_recovery=[0,4]**) and proc interface **/proc/sys/kernel/uce_kernel_recovery**. ## File System for New Media @@ -29,6 +29,10 @@ Various memory and storage media can be used to expand the system memory capacit - **User-mode swap**: The evicted cold memory can be swapped to the user-mode storage based on a preset etMem policy. The user-mode swap delivers a higher performance than the kernel-mode swap and the whole swap process is transparent to users. +## User-Mode Protocol Stack +The Gazelle user-mode protocol stack is added. It can be used without application program modification or recompilation, supporting high-performance and low-latency network transmission for upper-layer services. + +- **Gazelle user-mode protocol stack**: Powered by dpdk and lwip, Gazelle is a lock-free and multi-thread high-performance user-mode protocol stack to improve the network performance of applications. It can be used without modification, adaptation, or recompilation. ## Enhanced Cloud Native Scheduling @@ -36,21 +40,26 @@ In cloud service scenarios, online interactive services are sensitive to latenci - **Quality Aware Scheduler (QAS)**: It ensures that online tasks quickly preempt CPU resources, schedules tasks in a deterministic manner, and suppresses interference from offline tasks. - **Memory reclamation for OOM**: When OOM occurs, memory reclamation is preferentially performed for process groups with low priorities to ensure the normal running of online services. +- **Hybrid container deployment framework**: In a hybrid Kubernetes cluster, openEuler users only need to add online or offline labels to services. The system can automatically detect service creation and configure resources based on service priorities to implement resource isolation and preemption. + +## QEMU Hot Patch +- **LibcarePlus**: It is a hot patch framework that can fix QEMU process bugs without affecting VM services. ## KubeOS KubeOS is a container operating system, which centrally manages cloud native cluster OSs in containers. It has the following features: -- Supports OS containerization and Kubernetes interconnection for unified OS management and atomized lifecycle management -- Supports lightweight OS tailoring, which reduces unnecessary packages for quicker upgrades and replacements. +- **OS containerization**: Interconnection with Kubernetes facilitates unified OS management and atomized lifecycle management. +- **Lightweight OS tailoring**: This reduces unnecessary packages for quicker upgrades and replacements. ## Enhanced Lightweight Secure Container Based on Stratovirt, a lightweight virtualization technology, containers have low load and VMs are more secure. -- Supports UEFI boot, ACPI table construction, and addition of PCIe/PCI devices (including vrtio-pci) to VMs. -- Supports VFIO, allowing physical devices on the host to be accessed from VMs and enabling VMs to obtain high performance close to raw devices. +- **UEFI boot**: Supports UEFI boot, ACPI table construction, and addition of PCIe/PCI devices (including vrtio-pci) to VMs. +- **VFIO**: It allows physical devices on the host to be accessed from VMs and enables VMs to obtain high performance close to raw devices. +- **Hot swap of passthrough devices**: Devices such as virtio-blk-pci, virtio-net-pci, and VFIO can be hot swapped. This prevents system shutdown and service interruption caused by peripheral replacement. ## Enhanced iSulad @@ -80,14 +89,10 @@ Basic capabilities, such as lightweight, security hardening, and lightweight con - **Security hardening**: Security hardening is performed on resources such as account passwords and file permissions. OS security is enabled by default. - **Lightweight containers**: Standard container images can be deployed and run in lightweight containers in embedded scenarios. - **Multi-architecture support**: The ARM32 and ARM64 chip architectures are supported. - -## Intelligent O&M A-Ops - -The basic intelligent O&M framework provides basic capabilities such as configuration tracing, architecture awareness, and fault locating to support quick troubleshooting and reduce O&M costs. - -- **Application topology awareness**: The eBPF-based low-load probe framework provides automatic network topology awareness and detection capabilities at the application level. -- **Configuration tracing**: implements the configuration baseline and comparison functions and quickly rectify configuration problems. -- **Intelligent fault locating**: A-Ops supports exception detection and user-defined fault tree, and provides an expert-mode engine to detect system faults in real time and rectify system faults in a timely manner, reducing system downtime and O&M costs. +- **Hybrid deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. +- **Small-scale tailoring**: Small-scale tailoring based on the Yocto build package is supported. ARM Cross Compilation +- **ARM cross compilation tool**: The ARM cross compilation tool chain is provided based on GCC 10.3 of the community. +- **Distributed soft bus (DSoftBus)**: The DSoftBus of HarmonyOS is integrated to implement interconnection and interworking between embedded devices running on openEuler. ## secPaver @@ -106,5 +111,7 @@ secPaver is an SELinux policy development tool used to assist developers in deve More desktop environments are provided to ensure better development experience. -- DDE is upgraded and supports drawing board, music, and cinema applications. -- UKUI is upgraded and supports the Chinese input method and multimedia. \ No newline at end of file +- **DDE** is upgraded and supports drawing board, music, and cinema applications. +- **UKUI** is upgraded and supports the Chinese input method and multimedia. +- **kiran-desktop** is supported. +- **GNOME** is supported. \ No newline at end of file diff --git a/docs/en/docs/Releasenotes/release_notes.md b/docs/en/docs/Releasenotes/release_notes.md index 146d127b1..ce3d0b760 100644 --- a/docs/en/docs/Releasenotes/release_notes.md +++ b/docs/en/docs/Releasenotes/release_notes.md @@ -1,3 +1,3 @@ # Release Notes -This document is the release notes for the openEuler 21.03 release version. \ No newline at end of file +This document is the release notes of openEuler 22.03 LTS. \ No newline at end of file diff --git a/docs/en/docs/Releasenotes/user-notice.md b/docs/en/docs/Releasenotes/user-notice.md index 65e12ded9..60f0e9f9f 100644 --- a/docs/en/docs/Releasenotes/user-notice.md +++ b/docs/en/docs/Releasenotes/user-notice.md @@ -1,5 +1,6 @@ # User Notice -- The version number counting rule of openEuler is changed from openEuler _x.x_ to openEuler _year_._month_. For example, openEuler 21.03 indicates that the version is released in March 2020. -- The [Python core team](https://www.python.org/dev/peps/pep-0373/#update) has stopped maintaining Python 2 in January 2020. In 2020, openEuler 21.03 fixes only the critical CVE of Python 2 and will reach the end of maintenance \(EOM\) on December 31, 2020. Please switch to Python 3 as soon as possible. +- The version number counting rule of openEuler is changed from openEuler _x.x_ to openEuler _year_._month_. For example, openEuler 21.03 indicates that the version is released in March 2021. +- The [Python core team](https://www.python.org/dev/peps/pep-0373/#update) has stopped maintaining Python 2 in January 2020. Python 2 reached end of maintenance (EOM) on December 31, 2020. In 2021, openEuler 21.03 fixed only the critical CVEs related to Python 2. Please switch to Python 3 as soon as possible. +- From openEuler 22.03 LTS, only Python 3 is supported. Please switch to Python 3 to use the OS. diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 16cd18d03..d4921b293 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -5,7 +5,7 @@ headless: true - [Release Notes]({{< relref "./docs/Releasenotes/release_notes.md" >}}) - [User Notice]({{< relref "./docs/Releasenotes/user-notice.md" >}}) - [Introduction]({{< relref "./docs/Releasenotes/introduction.md" >}}) - - [Installing the OS]({{< relref "./docs/Releasenotes/installing-the-os.md" >}}) + - [OS Installation]({{< relref "./docs/Releasenotes/installing-the-os.md" >}}) - [Key Features]({{< relref "./docs/Releasenotes/key-features.md" >}}) - [Known Issues]({{< relref "./docs/Releasenotes/known-issues.md" >}}) - [Resolved Issues]({{< relref "./docs/Releasenotes/resolved-issues.md" >}}) -- Gitee From aaf41aa2079f6dd80a220cd3d62727b3fe70ed44 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Thu, 24 Mar 2022 10:45:27 +0800 Subject: [PATCH 02/42] updated installation-modes.md --- docs/en/docs/Installation/installation-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/Installation/installation-modes.md b/docs/en/docs/Installation/installation-modes.md index d291e2077..e06583f90 100644 --- a/docs/en/docs/Installation/installation-modes.md +++ b/docs/en/docs/Installation/installation-modes.md @@ -103,12 +103,14 @@ Pay attention to the capacity of the USB flash drive. The USB flash drive must h ``` # dd if=/home/testuser/Downloads/openEuler-21.09-aarch64-dvd.iso of=/dev/sdb bs=512k ``` +>![](./public_sys-resources/icon-note.gif) **NOTE** +>As described in ISOLINUX, the ISO 9660 file system created by the **mkisofs** command will boot through BIOS firmware, but only from the CD-ROM, DVD-ROM, or BD. In this case, you need to run the **isohybrid -u your.iso** command to process the ISO file and then run the **dd** command to write the ISO file to the USB flash drive. (This problem affects only the x86 architecture.) 5. After the image is written, remove the USB flash drive. No progress is displayed during the image write process. When the number sign (#) appears again, run the following command to write the data to the drive. Then exit the **root** account and remove the USB flash drive. In this case, you can use the USB drive as the installation source of the system. - ``` + ```bash # sync ``` -- Gitee From 0368f76a05b49ec6a8016c0b6cb3cbba07b3326b Mon Sep 17 00:00:00 2001 From: gomico Date: Thu, 24 Mar 2022 16:55:32 +0800 Subject: [PATCH 03/42] =?UTF-8?q?update=20translation=20for=20the=20follow?= =?UTF-8?q?ing=20zh=20docs=20LibcarePlus.md=20at=20f8953c3=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E4=BD=BF=E7=94=A8=E6=8C=87=E5=8D=97.md=20at=201d2e0d4?= =?UTF-8?q?=20vmtop.md=20at=201d2e0d4=20FAQ-54.md=20at=203aa66c7=20?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5iSula=E5=AE=89=E5=85=A8=E5=AE=B9=E5=99=A8.md?= =?UTF-8?q?=20at=2064692d9=20=E8=B4=A6=E6=88=B7=E5=8F=A3=E4=BB=A4.md=20at?= =?UTF-8?q?=2072fd461=20KubeEdge=E9=83=A8=E7=BD=B2=E6=8C=87=E5=8D=97.md=20?= =?UTF-8?q?at=209b782f7=20=E6=8E=A5=E5=8F=A3=E5=8F=82=E8=80=83.md=20at=20b?= =?UTF-8?q?6e7836=20=E8=99=9A=E6=8B=9F=E6=9C=BA=E7=AE=A1=E7=90=86.md=20at?= =?UTF-8?q?=20759a34f?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/Administration/faqs.md | 42 +- .../KubeEdge/kubeedge-deployment-guide.md | 1378 ++--------------- docs/en/docs/SecHarden/account-passwords.md | 34 +- docs/en/docs/StratoVirt/VM_management.md | 206 ++- docs/en/docs/StratoVirt/interconnect_isula.md | 90 +- docs/en/docs/Virtualization/LibcarePlus.md | 410 +++++ docs/en/docs/Virtualization/tool-guide.md | 197 +-- docs/en/docs/Virtualization/vmtop.md | 196 +++ docs/en/docs/secGear/api-description.md | 3 + docs/en/menu/index.md | 2 + 10 files changed, 1049 insertions(+), 1509 deletions(-) create mode 100644 docs/en/docs/Virtualization/LibcarePlus.md create mode 100644 docs/en/docs/Virtualization/vmtop.md diff --git a/docs/en/docs/Administration/faqs.md b/docs/en/docs/Administration/faqs.md index bf8aeebad..c18ba5615 100644 --- a/docs/en/docs/Administration/faqs.md +++ b/docs/en/docs/Administration/faqs.md @@ -2,17 +2,18 @@ - [FAQs](#faqs) - - [Why Is the Memory Usage of the libvirtd Service Queried by Running the systemctl and top Commands Different?](#why-is-the-memory-usage-of-the-libvirtd-service-queried-by-running-the-systemctl-and-top-commands-different) - - [An Error Occurs When stripsize Is Set to 4 During RAID 0 Volume Configuration](#an-error-occurs-when-stripsize-is-set-to-4-during-raid-0-volume-configuration) - - [Failed to Compile MariaDB Using rpmbuild](#failed-to-compile-mariadb-using-rpmbuild) - - [Failed to Start the SNTP Service Using the Default Configuration](#failed-to-start-the-sntp-service-using-the-default-configuration) - - [Installation Failure Caused by Software Package Conflict, File Conflict, or Missing Software Package](#installation-failure-caused-by-software-package-conflict-file-conflict-or-missing-software-package) - - [Failed to Downgrade libiscsi](#failed-to-downgrade-libiscsi) - - [Failed to Downgrade xfsprogs](#failed-to-downgrade-xfsprogs) - - [CPython/Lib Detects CVE-2019-9674: Zip Bomb](#cpython/lib-detects-cve-2019-9674:-zip-bomb) - - [ReDoS Attack Occurs Due to Improper Use of glibc Regular Expressions](#redos-attack-occurs-due-to-improper-use-of-glibc-regular-expressions) - - [An Error Is Reported When gdbm-devel Is Installed or Uninstalled During the Installation and Uninstallation of httpd-devel and apr-util-devel](#an-error-is-reported-when-gdbm-devel-is-installed-or-uninstalled-during-the-installation-and-uninstallation-of-httpd-devel-and-apr-util-devel) - - [An rpmdb Error Is Reported When Running the yum or dnf Command After the System Is Rebooted](#an-rpmdb-error-is-reported-when-running-the-yum-or-dnf-command-after-the-system-is-rebooted) + - [Why Is the Memory Usage of the libvirtd Service Queried by Running the systemctl and top Commands Different?](#why-is-the-memory-usage-of-the-libvirtd-service-queried-by-running-the-systemctl-and-top-commands-different) + - [An Error Occurs When stripsize Is Set to 4 During RAID 0 Volume Configuration](#an-error-occurs-when-stripsize-is-set-to-4-during-raid-0-volume-configuration) + - [Failed to Compile MariaDB Using rpmbuild](#failed-to-compile-mariadb-using-rpmbuild) + - [Failed to Start the SNTP Service Using the Default Configuration](#failed-to-start-the-sntp-service-using-the-default-configuration) + - [Installation Failure Caused by Software Package Conflict, File Conflict, or Missing Software Package](#installation-failure-caused-by-software-package-conflict-file-conflict-or-missing-software-package) + - [Failed to Downgrade libiscsi](#failed-to-downgrade-libiscsi) + - [Failed to Downgrade xfsprogs](#failed-to-downgrade-xfsprogs) + - [CPython/Lib Detects CVE-2019-9674: Zip Bomb](#cpythonlib-detects-cve-2019-9674-zip-bomb) + - [ReDoS Attack Occurs Due to Improper Use of glibc Regular Expressions](#redos-attack-occurs-due-to-improper-use-of-glibc-regular-expressions) + - [An Error Is Reported When gdbm-devel Is Installed or Uninstalled During the Installation and Uninstallation of httpd-devel and apr-util-devel](#an-error-is-reported-when-gdbm-devel-is-installed-or-uninstalled-during-the-installation-and-uninstallation-of-httpd-devel-and-apr-util-devel) + - [An rpmdb Error Is Reported When Running the yum or dnf Command After the System Is Rebooted](#an-rpmdb-error-is-reported-when-running-the-yum-or-dnf-command-after-the-system-is-rebooted) + - [Failed to Run `rpmrebuild -d /home/test filesystem` to Rebuild the **filesystem** Package](#failed-to-run-rpmrebuild--d-hometest-filesystem-to-rebuild-the-filesystem-package) @@ -331,3 +332,22 @@ A core dump occurs on the process that uses the regular expression. The glibc re Step 1 Run the `kill -9` command to terminate all running RPM-related commands. Step 2 Delete all **/var/lib/rpm/__db.00*** files. Step 3 Run the `rpmdb --rebuilddb` command to rebuild the RPM database. + +## Failed to Run `rpmrebuild -d /home/test filesystem` to Rebuild the **filesystem** Package + +### Symptom + +Failed to run the `rpmrebuild --comment-missing=y --keep-perm -b -d /home/test filesystem-3.16-3.oe1.aarch64` command to rebuild the **filesystem** package. The following information is displayed: +```shell +/usr/lib/rpmrebuild/rpmrebuild.sh:Error:(RpmBuild) Package 'filesystem-3.16-3.oe1.aarch64' build failed. +/usr/lib/rpmrebuild/rpmrebuild.sh:Error: RpmBuild +``` + +### Possible Cause +The software package creates the directory in the **%pretrans -p** phase, and modify the diretory in the **%ghost** phase. If you create a file or diretory in the diretory and use `rpmrebuild` to build the package, the created file or directory will be included in the package. + +The root cause of the symptom is that **filesystem** creates the **/proc** diretory in the **%pretrans** phase and modifies the directory in the **%ghost** phase, but some small processes are dynamically created during system running. As a result, `rpmrebuild` cannot include the processes in the package because they are not files or diretories and fails to rebuild the package. + +### Solution + +Do not use `rpmrebuild` to rebuild the **filesystem** package. \ No newline at end of file diff --git a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md index ac273dca0..e35d2bd77 100644 --- a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md +++ b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md @@ -6,19 +6,19 @@ KubeEdge is an open source system dedicated to solving problems in edge scenarios. It extends the capabilities of containerized application orchestration and device management to edge devices. Based on Kubernetes, KubeEdge provides core infrastructure support for networks, application deployment, and metadata synchronization between the cloud and the edge. KubeEdge supports MQTT and allows for custom logic to enable communication for the resource-constrained devices at the edge. KubeEdge consists of components deployed on the cloud and edge nodes. The components are now open source. -> https://kubeedge.io/ +> https://kubeedge.io/ ### iSulad iSulad is a lightweight container runtime daemon designed for IoT and cloud infrastructure. It is lightweight, fast, and is not restricted by hardware specifications or architectures. It is suitable for wide application in various scenarios, such as cloud, IoT, and edge computing. -> https://gitee.com/openeuler/iSulad +> https://gitee.com/openeuler/iSulad -## Preparations +## Cluster Overview ### Component Versions -| Component| Version| +| Component | Version | | ---------- | --------------------------------- | | OS | openEuler 21.09 | | Kubernetes | 1.20.2-4 | @@ -27,487 +27,197 @@ iSulad is a lightweight container runtime daemon designed for IoT and cloud infr ### Node Planning Example -| Node| Location| Components| -| ------------ | ------------- | -------------------------------- | -| 9.63.252.224 | Cloud| Kubernetes (Master), iSulad, CloudCore| -| 9.63.252.227 | Edge| iSulad, EdgeCore| - -### Environment Configurations +| Node | Location | Components | +| -------------- | -------- | -------------------------------- | +| cloud.kubeedge | Cloud | Kubernetes (Master), iSulad, CloudCore | +| edge.kubeedge | Edge | iSulad, EdgeCore | -Configure the following settings on the cloud and edge nodes: +> Note: You can run the `hostnamectl set-hostname [cloud,edge].kubeedge` command to set the cloud and edge node names in advance. -```bash -# Disable the firewall. -$ systemctl stop firewalld -$ systemctl disable firewalld - -# Disable SELinux. -$ setenforce 0 - -# Configure the network, and enable the required forwarding mechanism. -$ cat >> /etc/sysctl.d/k8s.conf <> /etc/hosts << EOF -9.63.252.224 cloud.kubeedge -9.63.252.227 edge.kubeedge -EOF - -# Choose an accessible NTP server to synchronize the clock. -$ ntpdate cn.pool.ntp.org - -# Install the cri-tools network tool. -$ wget --no-check-certificate https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.20.0/crictl-v1.20.0-linux-amd64.tar.gz -$ tar zxvf crictl-v1.20.0-linux-amd64.tar.gz -C /usr/local/bin - -# Install the CNI network plugins. -$ wget --no-check-certificate https://github.com/containernetworking/plugins/releases/download/v0.9.0/cni-plugins-linux-amd64-v0.9.0.tgz -$ mkdir -p /opt/cni/bin -$ tar -zxvf cni-plugins-linux-amd64-v0.9.0.tgz -C /opt/cni/bin -``` +## Preparations -### Configuring iSulad +### Tool Package Download -Configure the following settings on the cloud and edge nodes: +[kubeedge-tools](https://gitee.com/Poorunga/kubeedge-tools) provides complete offline installation packages and deployment scripts for easy and quick KubeEdge cluster deployment even if the node cannot access the Internet. ```bash -# Configure iSulad (only the items to be modified are listed). -$ cat /etc/isulad/daemon.json -{ - "registry-mirrors": [ - "docker.io" - ], - "insecure-registries": [ - "k8s.gcr.io", - "quay.io", - "hub.oepkgs.net" - ], - "pod-sandbox-image": "k8s.gcr.io/pause:3.2", - "network-plugin": "cni", - "cni-bin-dir": "/opt/cni/bin", - "cni-conf-dir": "/etc/cni/net.d", -} - -# Configure the proxy if the node cannot directly access the Internet. Otherwise, skip this section. -$ cat /usr/lib/systemd/system/isulad.service -[Service] -Type=notify -Environment="HTTP_PROXY=http://..." -Environment="HTTPS_PROXY=http://..." - -# Restart the iSulad and set it to start upon system startup. -$ systemctl daemon-reload && systemctl restart isulad -``` +# Download and decompress the kubeedge-tools package on both the cloud and edge nodes. +$ wget -O kubeedge-tools.zip https://gitee.com/Poorunga/kubeedge-tools/repository/archive/master.zip +$ unzip kubeedge-tools.zip -### Deploying the Kubernetes Components +# Go to the kubeedge-tools directory for all the subsequent operations. +$ cd kubeedge-tools-master +``` -Install and deploy the Kubernetes components on the cloud node only. +### Kubernetes Deployment -```bash -# Install the Kubernetes tools. -$ yum install kubernetes-master kubernetes-kubeadm kubernetes-client kubernetes-kubelet -# Set kubelet to start upon system startup. -$ systemctl enable kubelet --now +Perform the following operations on the cloud node only. -# Note that the system proxy must be canceled before using the kubeadm init command. -$ unset `env | grep -iE "tps?_proxy" | cut -d= -f1` -$ env | grep proxy +#### Initializing the Cloud Environment -# Run the kubeadm init command. -$ kubeadm init --kubernetes-version v1.20.2 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock -# The default Kubernetes component image is gcr.k8s.io. You can add the --image-repository=xxx option to configure a custom image repository address (to test your own Kubernetes image). - -# Note that the network segment specified by pod-network-cidr cannot overlap the network segment of the host machine. Otherwise, the network is inaccessible. -# You are advised to run the init command before configuring the network. -Your Kubernetes control-plane has initialized successfully! +```bash +$ ./setup-cloud.sh +``` -To start using your cluster, you need to run the following as a regular user: +#### Deploying Kubernetes - mkdir -p $HOME/.kube - sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config - sudo chown $(id -u):$(id -g) $HOME/.kube/config +Deploy Kubernetes by referring to the [Kubernetes Cluster Deployment Guide](https://docs.openeuler.org/en/docs/21.09/docs/Kubernetes/Kubernetes.html). -You should now deploy a pod network to the cluster. -Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: - https://kubernetes.io/docs/concepts/cluster-administration/addons/ +> Note: Preferentially, use `kubeadm` to deploy Kubernetes if the cloud node has access to the Internet. The procedure is as follows: -Then you can join any number of worker nodes by running the following on each as root: +```bash +$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +... +Your Kubernetes control-plane has initialized successfully! ... -# Run the commands as prompted. -mkdir -p $HOME/.kube -cp -i /etc/kubernetes/admin.conf $HOME/.kube/config -chown $(id -u):$(id -g) $HOME/.kube/config -# The commands make a copy of admin.conf, which is a kubectl configuration file initialized by the kubeadm command. -# The file contains important configurations, such as the authentication information. - -# You can reset the configurations if an error occurs when running the init command. -$ kubeadm reset - -# If "Unable to read config path "/etc/kubernetes/manifests"" is displayed, run the following command: -$ mkdir -p /etc/kubernetes/manifests +# After Kubernetes is installed, copy the specified file to the directory as prompted. +# mkdir -p $HOME/.kube +# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +# sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` -### Configuring the Network +#### Configuring Network for the Cloud Container -Because **the Calico network plugin cannot run on edge nodes**, `flannel` is used instead. The [issue](https://github.com/kubeedge/kubeedge/issues/2788#issuecomment-907627687) has been submitted to the KubeEdge community. - -The cloud and edge nodes are in different network environments and require different **affinity**. Therefore, two flannel configuration files are required. +Container Network Interface (CNI) software that provides network for Kubernetes nodes include [flannel](https://github.com/flannel-io/flannel), [Calico](https://github.com/projectcalico/calico), [Cilium](https://github.com/cilium/cilium), and more. If you have not decided which CNI software to use, run the following command to configure network for the cloud container: ```bash -# Download the flannel network plugin. -$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml - -# Prepare for network configuration for the cloud node. -$ cp kube-flannel.yml kube-flannel-cloud.yml - -# Modify the network configuration for the cloud node. -$ patch kube-flannel-cloud.yml - < -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959661 424578 signcerts.go:100] Succeed to creating token -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959716 424578 server.go:44] start unix domain socket server -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959973 424578 uds.go:71] listening on: //var/lib/kubeedge/kubeedge.sock -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.966693 424578 server.go:64] Starting cloudhub websocket server -Aug 29 10:50:17 cloud.kubeedge cloudcore[424578]: I0829 10:50:17.847150 424578 upstream.go:63] Start upstream devicecontroller +# active (running) indicates a normal status +$ systemctl status cloudcore | grep running + Active: active (running) since Fri 2022-03-04 10:54:30 CST; 5min ago ``` CloudCore has been deployed on the cloud node. Then, deploy EdgeCore on the edge node. -### Managing the Edge Node - -Run the `keadm join` command on the edge node to manage it. +### EdgeCore Deployment -#### Modifying iSulad Configurations +Perform the following operations only on the edge node unless otherwise specified. -File path: `/etc/isulad/daemon.json` +#### Initializing the Edge Environment ```bash -{ - # Set pod-sandbox-image. - "pod-sandbox-image": "kubeedge/pause:3.1", - # The listening port `10350` of EdgeCore conflicts with the WebSocket port of iSulad. As a result, EdgeCore cannot be started. To resolve the conflict, change the value of `websocket-server-listening-port` in the iSulad configuration file (`/etc/isulad/daemon.json`) to `10351`. - "websocket-server-listening-port": 10351, -} +$ ./setup-edge.sh ``` -After the configuration file is modified, run the `systemctl restart isulad` command to restart iSulad. +#### Managing the Edge Node +```bash +# Run the keadm gettoken command on the cloud node. +$ keadm gettoken +96058ab80ffbeb87fe58a79bfb19ea13f9a5a6c3076a17c00f80f01b406b4f7c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDY0NDg4NzF9.1mJegWB7SUVjgf-OvAqILgbZXeMHR9eOzMxpNFc42SI +# Save this token for subsequent steps. -#### Connecting EdgeCore to CloudCore + +# Run the keadm join command on the edge node. +# Set --cloudcore-ipport to the IP address and port number (10000) of the cloud node. Set --token to the token saved in the previous step. +$ keadm join --cloudcore-ipport=clou_node_IP_address:10000 --kubeedge-version=1.8.0 --token=96058ab80ffbeb87fe58a79bfb19ea13f9a5a6c3076a17c00f80f01b406b4f7c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDY0NDg4NzF9.1mJegWB7SUVjgf-OvAqILgbZXeMHR9eOzMxpNFc42SI +... +KubeEdge edgecore is running... +``` + +#### Configuring EdgeCore ```bash -# Obtain a token on the cloud node. -$ keadm gettoken -28c25d3b137593f5bbfb776cf5b19866ab9727cab9e97964dd503f87cd52cbde.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzAyOTE4MTV9.aGUyCi9gdysVtMu0DQzrD5TcV_DcXob647YeqcOxKDA - -# Run the keadm join command to connect EdgeCore to CloudCore. -# --cloudcore-ipport is a mandatory parameter. 10000 is the default port of CloudCore. -$ keadm join --cloudcore-ipport=9.63.252.224:10000 --kubeedge-version=1.8.0 --token=28c25d3b137593f5bbfb776cf5b19866ab9727cab9e97964dd503f87cd52cbde.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzAyOTE4MTV9.aGUyCi9gdysVtMu0DQzrD5TcV_DcXob647YeqcOxKDA -Host has mosquit+ already installed and running. Hence skipping the installation steps !!! -kubeedge-v1.8.0-linux-amd64.tar.gz checksum: -checksum_kubeedge-v1.8.0-linux-amd64.tar.gz.txt content: -[Run as service] start to download service file for edgecore -[Run as service] success to download service file for edgecore -kubeedge-v1.8.0-linux-amd64/ -kubeedge-v1.8.0-linux-amd64/edge/ -kubeedge-v1.8.0-linux-amd64/edge/edgecore -kubeedge-v1.8.0-linux-amd64/cloud/ -kubeedge-v1.8.0-linux-amd64/cloud/csidriver/ -kubeedge-v1.8.0-linux-amd64/cloud/csidriver/csidriver -kubeedge-v1.8.0-linux-amd64/cloud/admission/ -kubeedge-v1.8.0-linux-amd64/cloud/admission/admission -kubeedge-v1.8.0-linux-amd64/cloud/cloudcore/ -kubeedge-v1.8.0-linux-amd64/cloud/cloudcore/cloudcore -kubeedge-v1.8.0-linux-amd64/version - -KubeEdge edgecore is running, For logs visit: journalctl -u edgecore.service -b +$ ./patch-edge.sh ``` -At this time, the deployment of EdgeCore is not complete because Docker is used in the default settings. You need to modify the configuration file to connect EdgeCore to iSulad. +#### Configuring Network for the Edge Container -#### Modifying EdgeCore Configurations +If you have not decided which CNI software to use, run the following command to configure network for the edge container: ```bash -# Enable systemd to manage EdgeCore. -# Copy edgecore.service to /usr/lib/systemd/system. -$ cp /etc/kubeedge/edgecore.service /usr/lib/systemd/system - -# Modify the EdgeCore configurations. -$ cd /etc/kubeedge/config -$ patch edgecore.yaml - < - -# You can see that Nginx has been successfully deployed on the edge node. +# Check whether Nginx is deployed on the edge node and running. +$ kubectl get pod -owide | grep nginx +nginx-deployment-84b99f4bf-jb6sz 1/1 Running 0 30s 10.244.1.2 edge.kubeedge ``` #### Testing the Function ```bash -# Test whether the function is running properly. -# Run the curl command on the edge node to access the IP address of Nginx, which is 10.244.2.4. -$ curl 10.244.2.4:80 +# Access the IP address of Nginx on the edge node. +$ curl 10.244.1.2:80 Welcome to nginx! @@ -525,868 +235,4 @@ Commercial support is available at ``` -The deployment of KubeEdge and iSulad is complete. - -## Deploying the KubeEdge Cluster Using Binary Files - -You can also deploy the KubeEdge cluster using binary files. Only two RPM packages are required: `cloudcore` (on the cloud node) and `edgecore` (on the edge node). -> The KubeEdge deployment using binary files is for testing only. Do not use this method in the production environment. - -### Deploying CloudCore on the Cloud Node - -> Log in to the cloud host. - -#### Installing the `cloudcore` RPM Package - -```bash -$ yum install kubeedge-cloudcore -``` - -#### Creating CRDs - -```bash -$ kubectl apply -f /etc/kubeedge/crds/devices/ -$ kubectl apply -f /etc/kubeedge/crds/reliablesyncs/ -$ kubectl apply -f /etc/kubeedge/crds/router/ -``` - -#### Preparing the Configuration File - -```bash -$ cloudcore --defaultconfig > /etc/kubeedge/config/cloudcore.yaml -``` - -Modify CloudCore configurations by referring to **Deploying CloudCore Using Keadm**. - -#### Running CloudCore - -```bash -$ pkill cloudcore -$ systemctl start cloudcore -``` - -### Deploying EdgeCore on the Edge Node - -> Log in to the edge host. - -#### Installing the `edgecore` RPM Package - -```bash -$ yum install kubeedge-edgecore -``` - -#### Preparing the Configuration File - -```bash -$ edgecore --defaultconfig > /etc/kubeedge/config/edgecore.yaml -``` - -Modify EdgeCore configurations by referring to **Deploying EdgeCore Using Keadm**. - - - -```bash -$ kubectl get secret -nkubeedge tokensecret -o=jsonpath='{.data.tokendata}' | base64 -d -1c4ff11289a14c59f2cbdbab726d1857262d5bda778ddf0de34dd59d125d3f69.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzE0ODM3MzN9.JY77nMVDHIKD9ipo03Y0mSbxief9qOvJ4yMNx1yZpp0 - -# Add the obtained token to the configuration file. -sed -i -e "s|token: .*|token: ${token}|g" /etc/kubeedge/config/edgecore.yaml - -# The value of the token variable is obtained in the previous step. -``` - -#### Running EdgeCore - -```bash -$ pkill edgecore -$ systemctl start edgecore -``` - -## Appendix - -### kube-flannel-cloud.yml - -```bash -# Application scenario: cloud node ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: psp.flannel.unprivileged - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default - seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default - apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default - apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default -spec: - privileged: false - volumes: - - configMap - - secret - - emptyDir - - hostPath - allowedHostPaths: - - pathPrefix: "/etc/cni/net.d" - - pathPrefix: "/etc/kube-flannel" - - pathPrefix: "/run/flannel" - readOnlyRootFilesystem: false - # Users and groups - runAsUser: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - fsGroup: - rule: RunAsAny - # Privilege Escalation - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - # Capabilities - allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] - defaultAddCapabilities: [] - requiredDropCapabilities: [] - # Host namespaces - hostPID: false - hostIPC: false - hostNetwork: true - hostPorts: - - min: 0 - max: 65535 - # SELinux - seLinux: - # SELinux is unused in CaaSP - rule: 'RunAsAny' ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -rules: -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: ['psp.flannel.unprivileged'] -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch -- apiGroups: - - "" - resources: - - nodes/status - verbs: - - patch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flannel -subjects: -- kind: ServiceAccount - name: flannel - namespace: kube-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: flannel - namespace: kube-system ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: kube-flannel-cfg - namespace: kube-system - labels: - tier: node - app: flannel -data: - cni-conf.json: | - { - "name": "cbr0", - "cniVersion": "0.3.1", - "plugins": [ - { - "type": "flannel", - "delegate": { - "hairpinMode": true, - "isDefaultGateway": true - } - }, - { - "type": "portmap", - "capabilities": { - "portMappings": true - } - } - ] - } - net-conf.json: | - { - "Network": "10.244.0.0/16", - "Backend": { - "Type": "vxlan" - } - } ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: kube-flannel-cloud-ds - namespace: kube-system - labels: - tier: node - app: flannel -spec: - selector: - matchLabels: - app: flannel - template: - metadata: - labels: - tier: node - app: flannel - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: node-role.kubernetes.io/agent - operator: DoesNotExist - hostNetwork: true - priorityClassName: system-node-critical - tolerations: - - operator: Exists - effect: NoSchedule - serviceAccountName: flannel - initContainers: - - name: install-cni - image: quay.io/coreos/flannel:v0.14.0 - command: - - cp - args: - - -f - - /etc/kube-flannel/cni-conf.json - - /etc/cni/net.d/10-flannel.conflist - volumeMounts: - - name: cni - mountPath: /etc/cni/net.d - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - containers: - - name: kube-flannel - image: quay.io/coreos/flannel:v0.14.0 - command: - - /opt/bin/flanneld - args: - - --ip-masq - - --kube-subnet-mgr - resources: - requests: - cpu: "100m" - memory: "50Mi" - limits: - cpu: "100m" - memory: "50Mi" - securityContext: - privileged: false - capabilities: - add: ["NET_ADMIN", "NET_RAW"] - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: run - mountPath: /run/flannel - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - volumes: - - name: run - hostPath: - path: /run/flannel - - name: cni - hostPath: - path: /etc/cni/net.d - - name: flannel-cfg - configMap: - name: kube-flannel-cfg - -``` - -### kube-flannel-edge.yml - -```bash -# Application scenario: edge node ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: psp.flannel.unprivileged - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default - seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default - apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default - apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default -spec: - privileged: false - volumes: - - configMap - - secret - - emptyDir - - hostPath - allowedHostPaths: - - pathPrefix: "/etc/cni/net.d" - - pathPrefix: "/etc/kube-flannel" - - pathPrefix: "/run/flannel" - readOnlyRootFilesystem: false - # Users and groups - runAsUser: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - fsGroup: - rule: RunAsAny - # Privilege Escalation - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - # Capabilities - allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] - defaultAddCapabilities: [] - requiredDropCapabilities: [] - # Host namespaces - hostPID: false - hostIPC: false - hostNetwork: true - hostPorts: - - min: 0 - max: 65535 - # SELinux - seLinux: - # SELinux is unused in CaaSP - rule: 'RunAsAny' ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -rules: -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: ['psp.flannel.unprivileged'] -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch -- apiGroups: - - "" - resources: - - nodes/status - verbs: - - patch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flannel -subjects: -- kind: ServiceAccount - name: flannel - namespace: kube-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: flannel - namespace: kube-system ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: kube-flannel-cfg - namespace: kube-system - labels: - tier: node - app: flannel -data: - cni-conf.json: | - { - "name": "cbr0", - "cniVersion": "0.3.1", - "plugins": [ - { - "type": "flannel", - "delegate": { - "hairpinMode": true, - "isDefaultGateway": true - } - }, - { - "type": "portmap", - "capabilities": { - "portMappings": true - } - } - ] - } - net-conf.json: | - { - "Network": "10.244.0.0/16", - "Backend": { - "Type": "vxlan" - } - } ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: kube-flannel-edge-ds - namespace: kube-system - labels: - tier: node - app: flannel -spec: - selector: - matchLabels: - app: flannel - template: - metadata: - labels: - tier: node - app: flannel - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: node-role.kubernetes.io/agent - operator: Exists - hostNetwork: true - priorityClassName: system-node-critical - tolerations: - - operator: Exists - effect: NoSchedule - serviceAccountName: flannel - initContainers: - - name: install-cni - image: quay.io/coreos/flannel:v0.14.0 - command: - - cp - args: - - -f - - /etc/kube-flannel/cni-conf.json - - /etc/cni/net.d/10-flannel.conflist - volumeMounts: - - name: cni - mountPath: /etc/cni/net.d - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - containers: - - name: kube-flannel - image: quay.io/coreos/flannel:v0.14.0 - command: - - /opt/bin/flanneld - args: - - --ip-masq - - --kube-subnet-mgr - - --kube-api-url=http://127.0.0.1:10550 - resources: - requests: - cpu: "100m" - memory: "50Mi" - limits: - cpu: "100m" - memory: "50Mi" - securityContext: - privileged: false - capabilities: - add: ["NET_ADMIN", "NET_RAW"] - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: run - mountPath: /run/flannel - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - volumes: - - name: run - hostPath: - path: /run/flannel - - name: cni - hostPath: - path: /etc/cni/net.d - - name: flannel-cfg - configMap: - name: kube-flannel-cfg - -``` - -### cloudcore.service - -```bash -# Application scenario: cloud node -# File path: /usr/lib/systemd/system/cloudcore.service -[Unit] -Description=cloudcore.service - -[Service] -Type=simple -ExecStart=/usr/local/bin/cloudcore -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -### cloudcore.yaml - -```bash -# Application scenario: cloud node -# File path: /etc/kubeedge/config/cloudcore.yaml -apiVersion: cloudcore.config.kubeedge.io/v1alpha1 -commonConfig: - tunnelPort: 10351 -kind: CloudCore -kubeAPIConfig: - burst: 200 - contentType: application/vnd.kubernetes.protobuf - kubeConfig: /root/.kube/config - master: "" - qps: 100 -modules: - cloudHub: - advertiseAddress: - - 9.63.252.224 - dnsNames: - - "" - edgeCertSigningDuration: 365 - enable: true - https: - address: 0.0.0.0 - enable: true - port: 10002 - keepaliveInterval: 30 - nodeLimit: 1000 - quic: - address: 0.0.0.0 - enable: false - maxIncomingStreams: 10000 - port: 10001 - tlsCAFile: /etc/kubeedge/ca/rootCA.crt - tlsCAKeyFile: /etc/kubeedge/ca/rootCA.key - tlsCertFile: /etc/kubeedge/certs/server.crt - tlsPrivateKeyFile: /etc/kubeedge/certs/server.key - tokenRefreshDuration: 12 - unixsocket: - address: unix:///var/lib/kubeedge/kubeedge.sock - enable: true - websocket: - address: 0.0.0.0 - enable: true - port: 10000 - writeTimeout: 30 - cloudStream: - enable: false - streamPort: 10003 - tlsStreamCAFile: /etc/kubeedge/ca/streamCA.crt - tlsStreamCertFile: /etc/kubeedge/certs/stream.crt - tlsStreamPrivateKeyFile: /etc/kubeedge/certs/stream.key - tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt - tlsTunnelCertFile: /etc/kubeedge/certs/server.crt - tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key - tunnelPort: 10004 - deviceController: - buffer: - deviceEvent: 1 - deviceModelEvent: 1 - updateDeviceStatus: 1024 - context: - receiveModule: devicecontroller - responseModule: cloudhub - sendModule: cloudhub - enable: true - load: - updateDeviceStatusWorkers: 1 - dynamicController: - enable: true - edgeController: - buffer: - configMapEvent: 1 - deletePod: 1024 - endpointsEvent: 1 - podEvent: 1 - queryConfigMap: 1024 - queryEndpoints: 1024 - queryNode: 1024 - queryPersistentVolume: 1024 - queryPersistentVolumeClaim: 1024 - querySecret: 1024 - queryService: 1024 - queryVolumeAttachment: 1024 - ruleEndpointsEvent: 1 - rulesEvent: 1 - secretEvent: 1 - serviceAccountToken: 1024 - serviceEvent: 1 - updateNode: 1024 - updateNodeStatus: 1024 - updatePodStatus: 1024 - context: - receiveModule: edgecontroller - responseModule: cloudhub - sendModule: cloudhub - sendRouterModule: router - enable: true - load: - ServiceAccountTokenWorkers: 4 - UpdateRuleStatusWorkers: 4 - deletePodWorkers: 4 - queryConfigMapWorkers: 4 - queryEndpointsWorkers: 4 - queryNodeWorkers: 4 - queryPersistentVolumeClaimWorkers: 4 - queryPersistentVolumeWorkers: 4 - querySecretWorkers: 4 - queryServiceWorkers: 4 - queryVolumeAttachmentWorkers: 4 - updateNodeStatusWorkers: 1 - updateNodeWorkers: 4 - updatePodStatusWorkers: 1 - nodeUpdateFrequency: 10 - router: - address: 0.0.0.0 - enable: false - port: 9443 - restTimeout: 60 - syncController: - enable: true - -``` - -### edgecore.service - -```bash -# Application scenario: edge node -# File path: /etc/systemd/system/edgecore.service -[Unit] -Description=edgecore.service - -[Service] -Type=simple -ExecStart=/usr/local/bin/edgecore -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -### edgecore.yaml - -```bash -# Application scenario: edge node -# File path: /etc/kubeedge/config/edgecore.yaml -apiVersion: edgecore.config.kubeedge.io/v1alpha1 -database: - aliasName: default - dataSource: /var/lib/kubeedge/edgecore.db - driverName: sqlite3 -kind: EdgeCore -modules: - dbTest: - enable: false - deviceTwin: - enable: true - edgeHub: - enable: true - heartbeat: 15 - httpServer: https://9.63.252.224:10002 - projectID: e632aba927ea4ac2b575ec1603d56f10 - quic: - enable: false - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.227:10001 - writeDeadline: 15 - rotateCertificates: true - tlsCaFile: /etc/kubeedge/ca/rootCA.crt - tlsCertFile: /etc/kubeedge/certs/server.crt - tlsPrivateKeyFile: /etc/kubeedge/certs/server.key - token: ""# Enter the token obtained from the cloud side. - websocket: - enable: true - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.224:10000 - writeDeadline: 15 - edgeMesh: - enable: false - lbStrategy: RoundRobin - listenInterface: docker0 - listenPort: 40001 - subNet: 9.251.0.0/16 - edgeStream: - enable: false - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.224:10004 - tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt - tlsTunnelCertFile: /etc/kubeedge/certs/server.crt - tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key - writeDeadline: 15 - edged: - cgroupDriver: cgroupfs - cgroupRoot: "" - cgroupsPerQOS: true - clusterDNS: "" - clusterDomain: "" - cniBinDir: /opt/cni/bin - cniCacheDirs: /var/lib/cni/cache - cniConfDir: /etc/cni/net.d - concurrentConsumers: 5 - devicePluginEnabled: false - dockerAddress: unix:///var/run/docker.sock - edgedMemoryCapacity: 7852396000 - enable: true - enableMetrics: true - gpuPluginEnabled: false - hostnameOverride: edge.kubeedge - imageGCHighThreshold: 80 - imageGCLowThreshold: 40 - imagePullProgressDeadline: 60 - maximumDeadContainersPerPod: 1 - networkPluginMTU: 1500 - nodeIP: 9.63.252.227 - nodeStatusUpdateFrequency: 10 - podSandboxImage: kubeedge/pause:3.1 - registerNode: true - registerNodeNamespace: default - remoteImageEndpoint: unix:///var/run/isulad.sock - remoteRuntimeEndpoint: unix:///var/run/isulad.sock - runtimeRequestTimeout: 2 - runtimeType: remote - volumeStatsAggPeriod: 60000000000 - eventBus: - enable: true - eventBusTLS: - enable: false - tlsMqttCAFile: /etc/kubeedge/ca/rootCA.crt - tlsMqttCertFile: /etc/kubeedge/certs/server.crt - tlsMqttPrivateKeyFile: /etc/kubeedge/certs/server.key - mqttMode: 2 - mqttQOS: 0 - mqttRetain: false - mqttServerExternal: tcp://127.0.0.1:1883 - mqttServerInternal: tcp://127.0.0.1:1884 - mqttSessionQueueSize: 100 - metaManager: - contextSendGroup: hub - contextSendModule: websocket - enable: true - metaServer: - debug: false - enable: true - podStatusSyncInterval: 60 - remoteQueryTimeout: 60 - serviceBus: - enable: false - -``` - -### daemon.json - -```bash -# Application scenarios: cloud and edge nodes -# File path: /etc/isulad/daemon.json -{ - "group": "isula", - "default-runtime": "lcr", - "graph": "/var/lib/isulad", - "state": "/var/run/isulad", - "engine": "lcr", - "log-level": "ERROR", - "pidfile": "/var/run/isulad.pid", - "log-opts": { - "log-file-mode": "0600", - "log-path": "/var/lib/isulad", - "max-file": "1", - "max-size": "30KB" - }, - "log-driver": "stdout", - "container-log": { - "driver": "json-file" - }, - "hook-spec": "/etc/default/isulad/hooks/default.json", - "start-timeout": "2m", - "storage-driver": "overlay2", - "storage-opts": [ - "overlay2.override_kernel_check=true" - ], - "registry-mirrors": [ - "docker.io" - ], - "insecure-registries": [ - "k8s.gcr.io", - "quay.io", - "hub.oepkgs.net" - ], - "pod-sandbox-image": "k8s.gcr.io/pause:3.2", # Set this parameter to kubeedge/pause:3.1 for edge nodes. - "websocket-server-listening-port": 10351, - "native.umask": "secure", - "network-plugin": "cni", - "cni-bin-dir": "/opt/cni/bin", - "cni-conf-dir": "/etc/cni/net.d", - "image-layer-check": false, - "use-decrypted-key": true, - "insecure-skip-verify-enforce": false -} -``` +The deployment of KubeEdge is complete. diff --git a/docs/en/docs/SecHarden/account-passwords.md b/docs/en/docs/SecHarden/account-passwords.md index 66c373ad5..4ccfd0c14 100644 --- a/docs/en/docs/SecHarden/account-passwords.md +++ b/docs/en/docs/SecHarden/account-passwords.md @@ -1,13 +1,13 @@ # Account Passwords - [Account Passwords](#account-passwords) - - [Shielding System Accounts](#shielding-system-accounts) - - [Restricting Permissions on the su Command](#restricting-permissions-on-the-su-command) - - [Setting Password Complexity](#setting-password-complexity) - - [Setting the Password Validity Period](#setting-the-password-validity-period) - - [Setting Password Encryption Algorithms](#setting-password-encryption-algorithms) - - [Locking an Account After Three Login Failures](#locking-an-account-after-three-login-failures) - - [Hardening the su Command](#hardening-the-su-command) + - [Shielding System Accounts](#shielding-system-accounts) + - [Restricting Account Permissions on the su Command](#restricting-account-permissions-on-the-su-command) + - [Setting Password Complexity](#setting-password-complexity) + - [Setting the Password Validity Period](#setting-the-password-validity-period) + - [Setting Password Encryption Algorithms](#setting-password-encryption-algorithms) + - [Locking an Account After Three Login Failures](#locking-an-account-after-three-login-failures) + - [Hardening the su Command](#hardening-the-su-command) ## Shielding System Accounts @@ -26,11 +26,11 @@ usermod -L -s /sbin/nologin $systemaccount >![](./public_sys-resources/icon-note.gif) **NOTE:** >_$systemaccount_ indicates the system account. -## Restricting Permissions on the su Command +## Restricting Account Permissions on the su Command ### Description -The **su** command is used to switch user accounts. To improve system security, only the user **root** and users in the wheel group can use the **su** command. +The **su** command is used to switch user accounts. To improve system security, only the user **root** and users in the **wheel** group can use the **su** command. ### Implementation @@ -86,12 +86,12 @@ This section provides an example for configuring password complexity. - At least one space or one of the following special characters: \` \~ ! @ \# $ % ^ & \* \( \) - \_ = + \\ | \[ \{ \} \] ; : ' " , < . \> / ? -3. Cannot be the same as an account or the account in reverse order. +3. Cannot be the same as an account name or the account name in reverse order. 4. Cannot be the last five passwords used. **Implementation** -Add the following content to the first two lines of password in the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files: +Add the following content to the first two lines of the **password** configuration item in the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files: ``` password requisite pam_pwquality.so minlen=8 minclass=3 enforce_for_root try_first_pass local_users_only retry=3 dcredit=0 ucredit=0 lcredit=0 ocredit=0 @@ -271,16 +271,16 @@ password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_au ### Description -To ensure user system security, you are advised to set the maximum number of incorrect password attempts \(three attempts are recommended\) and the automatic unlocking time \(300 seconds are recommended\) for a locked account. +To ensure user system security, you are advised to set the maximum number of failed login attempts \(three attempts are recommended\) and the automatic unlocking time \(300 seconds are recommended\) for a locked account. -If an account is locked, any input is invalid but does not cause the locking timer to recount. Records of the user's invalid inputs are cleared once unlocked. The preceding settings protect passwords from being forcibly cracked and improve system security. +If an account is locked, any input is invalid but does not reset the locking countdown timer. Records of the user's invalid inputs are cleared once unlocked. The preceding settings protect passwords from being forcibly cracked and improve system security. >![](./public_sys-resources/icon-note.gif) **NOTE:** ->By default, the maximum number of incorrect password attempts is 3 in openEuler. After the system is locked, the automatic unlock time is 60 seconds. +>By default, the maximum number of failed login attempts is 3 in openEuler. After an account is locked, the automatic unlock time is 60 seconds. ### Implementation -The password complexity is set by modifying the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files. The maximum number of incorrect password attempts is set to **3**, and the unlocking time after the system is locked is set to **300** seconds. The configuration is as follows: +The password complexity is set by modifying the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files. The maximum number of failed login attempts is set to **3**, and the unlocking time after an account is locked is set to **300** seconds. The configuration is as follows: ``` auth required pam_faillock.so preauth audit deny=3 even_deny_root unlock_time=300 @@ -304,12 +304,12 @@ auth sufficient pam_faillock.so authsucc audit deny=3 even_deny_root u

deny=3

-

A user account will be locked after three login attempts.

+

A user account will be locked after three failed login attempts.

unlock_time=300

-

A locked common user account is automatically unlocked in 300 seconds.

+

A locked common user account is automatically unlocked after 300 seconds.

even_deny_root

diff --git a/docs/en/docs/StratoVirt/VM_management.md b/docs/en/docs/StratoVirt/VM_management.md index c58a74382..7796925b1 100644 --- a/docs/en/docs/StratoVirt/VM_management.md +++ b/docs/en/docs/StratoVirt/VM_management.md @@ -165,25 +165,51 @@ QMP provides the quit command to exit a VM, that is, to exit the StratoVirt proc StratoVirt allows you to adjust the number of disks when a VM is running. That is, you can add or delete VM disks without interrupting services. -#### Hot Plugged-in Disks +**Note** + +* For a standard VM, the **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* For a standard VM, devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding Disks **Usage:** +Lightweight VM: + ``` {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} {"execute": "device_add", "arguments": {"id": "drive-0", "driver": "virtio-blk-mmio", "addr": "0x1"}} ``` +Standard VM: + +``` +{"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} +{"execute":"device_add", "arguments":{"id":"drive-0", "driver":"virtio-blk-pci", "drive": "drive-0", "addr":"0x0", "bus": "pcie.1"}} +``` + **Parameters:** -- The value of **node-name** in **blockdev-add** must be the same as the value of **id** in **device_add**. For example, both values are **drive-0** in the preceding example. -- **/path/to/block** is the image path of the hot plugged-in disks. It cannot be the path of the disk image that boots the rootfs. -- For **addr**, **0x0** is mapped to **vda** of the VM, **0x1** is mapped to **vdb**, and so on. To be compatible with the QMP protocol, **addr** can be replaced by **lun**, but **lun=0** is mapped to the **vdb** of the client. -- StratoVirt supports a maximum of six virtio-blk disks. Note this when hot plugging in disks. +- For a lightweight VM, the value of **node-name** in **blockdev-add** must be the same as that of **id** in **device_add**. For example, the values of **node-name** and **id** are both **drive-0** as shown above. + +- For a standard VM, the value of **drive** must be the same as that of **node-name** in **blockdev-add**. + +- **/path/to/block** is the image path of the hot added disks. It cannot be the path of the disk image that boots the rootfs. + +- For a lightweight VM, the value of **addr**, starting from **0x0**, is mapped to a virtio device on the VM. **0x0** is mapped to **vda**, **0x1** is mapped to **vdb**, and so on. To be compatible with the QMP protocol, **addr** can be replaced by **lun**, but **lun=0** is mapped to the **vdb** of the guest machine. For a standard VM, the value of **addr** must be **0x0**. + +- For a standard VM, **bus** indicates the name of the bus to mount the device. Currently, the device can be hot added only to the root port device. The value of **bus** must be the ID of the root port device. + +- For a lightweight VM, StratoVirt supports a maximum of six virtio-blk disks. Note this when hot adding disks. For a standard VM, the maximum number of hot added disks depends on the number of root port devices. **Example:** +Lightweight VM: + ``` <- {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} -> {"return": {}} @@ -191,29 +217,70 @@ StratoVirt allows you to adjust the number of disks when a VM is running. That i -> {"return": {}} ``` -#### Hot Plugged-out Disks +Standard VM: + +``` +<- {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} +-> {"return": {}} +<- {"execute":"device_add", "arguments":{"id":"drive-0", "driver":"virtio-blk-pci", "drive": "drive-0", "addr":"0x0", "bus": "pcie.1"}} +-> {"return": {}} +``` +#### Hot Removing Disks **Usage:** -**{"execute": "device_del", "arguments": {"id":"drive-0"}}** +Lightweight VM: + +``` +{"execute": "device_del", "arguments": {"id":"drive-0"}} +``` + +Standard VM: + +``` +{"execute": "device_del", "arguments": {"id":"drive-0"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drive-0"}} +``` **Parameters:** -**id** indicates the ID of the hot plugged-out disk. +**id** indicates the ID of the disk to be hot removed. +- **node-name** indicates the backend name of the disk. **Example:** +Lightweight VM: + ``` <- {"execute": "device_del", "arguments": {"id": "drive-0"}} -> {"event":"DEVICE_DELETED","data":{"device":"drive-0","path":"drive-0"},"timestamp":{"seconds":1598513162,"microseconds":367129}} -> {"return": {}} ``` +Standard VM: + +``` +<- {"execute": "device_del", "arguments": {"id":"drive-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"drive-0","path":"drive-0"},"timestamp":{"seconds":1598513162,"microseconds":367129}} +<- {"execute": "blockdev-del", "arguments": {"node-name": "drive-0"}} +-> {"return": {}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. ### Hot-Pluggable NICs StratoVirt allows you to adjust the number of NICs when a VM is running. That is, you can add or delete VM NICs without interrupting services. -#### Hot Plugged-in NICs +**Note** + +* For a standard VM, the **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* For a standard VM, devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding NICs **Preparations (Requiring the root Permission)** @@ -239,21 +306,36 @@ StratoVirt allows you to adjust the number of NICs when a VM is running. That is **Usage:** +Lightweight VM: + ``` {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} {"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-mmio", "addr":"0x0"}} ``` +Standard VM: + +``` +{"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} +{"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-pci", "addr":"0x0", "netdev": "net-0", "bus": "pcie.1"}} +``` + **Parameters:** -- **id** in **netdev_add** must be the same as that in **device_add**. **ifname** is the name of the backend tap device. +- For a lightweight VM, **id** in **netdev_add** must be the same as that in **device_add**. **ifname** is the name of the backend tap device. + +- For a standard VM, the value of **netdev** must be the value of **id** in **netdev_add**. -- For **addr**, **0x0** is mapped to **eth0** of the VM, **0x1** is mapped to **eth1**, and so on. +- For a lightweight VM, the value of **addr**, starting from **0x0**, is mapped to an NIC on the VM. **0x0** is mapped to **eth0 **, **0x1** is mapped to **eth1**. For a standard VM, the value of **addr** must be **0x0**. -- StratoVirt supports a maximum of two virtio-net NICs. Therefore, pay attention to the specification restrictions when hot plugging in NICs. +- For a standard VM, **bus** indicates the name of the bus to mount the device. Currently, the device can be hot added only to the root port device. The value of **bus** must be the ID of the root port device. + +- For a lightweight VM, StratoVirt supports a maximum of two virtio-net NICs. Therefore, pay attention to the specification restrictions when hot adding in NICs. For a standard VM, the maximum number of hot added disks depends on the number of root port devices. **Example:** +Lightweight VM: + ``` <- {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} -> {"return": {}} @@ -263,24 +345,120 @@ StratoVirt allows you to adjust the number of NICs when a VM is running. That is **addr:0x0** corresponds to **eth0** in the VM. -#### Hot Plugged-out NICs +Standard VM: + +``` +<- {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} +-> {"return": {}} +<- {"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-pci", "addr":"0x0", "netdev": "net-0", "bus": "pcie.1"}} +-> {"return": {}} +``` + +#### Hot Removing NICs **Usage:** -**{"execute": "device_del", "arguments": {"id": "net-0"}}** +Lightweight VM: + +``` +{"execute": "device_del", "arguments": {"id": "net-0"}} +``` + +Standard VM: + +``` +{"execute": "device_del", "arguments": {"id":"net-0"}} +{"execute": "netdev_del", "arguments": {"id": "net-0"}} +``` + **Parameters:** **id**: NIC ID, for example, **net-0**. +- **id** in **netdev_del** indicates the backend name of the NIC. + **Example:** +Lightweight VM: + ``` <- {"execute": "device_del", "arguments": {"id": "net-0"}} -> {"event":"DEVICE_DELETED","data":{"device":"net-0","path":"net-0"},"timestamp":{"seconds":1598513339,"microseconds":97310}} -> {"return": {}} ``` +Standard VM: + +``` +<- {"execute": "device_del", "arguments": {"id":"net-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"net-0","path":"net-0"},"timestamp":{"seconds":1598513339,"microseconds":97310}} +<- {"execute": "netdev_del", "arguments": {"id": "net-0"}} +-> {"return": {}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. + +### Hot-swappable Pass-through Devices + +You can add or delete the passthrough devices of a StratoVirt standard VM when it is running. + +**Note** + +* The **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* Devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding Pass-through Devices + +**Usage:** + +``` +{"execute":"device_add", "arguments":{"id":"vfio-0", "driver":"vfio-pci", "bus": "pcie.1", "addr":"0x0", "host": "0000:1a:00.3"}} +``` + +**Parameters:** + +- **id** indicates the ID of the hot added device. + +- **bus** indicates the name of the bus to mount the device. + +- **addr** indicates the slot and function numbers to mount the device. Currently, **addr** must be set to **0x0**. + +- **host** indicates the domain number, bus number, slot number, and function number of the passthrough device on the host machine. + +**Example:** + +``` +<- {"execute":"device_add", "arguments":{"id":"vfio-0", "driver":"vfio-pci", "bus": "pcie.1", "addr":"0x0", "host": "0000:1a:00.3"}} +-> {"return": {}} +``` + +#### Hot Removing Pass-through Devices + +**Usage:** + +``` +{"execute": "device_del", "arguments": {"id": "vfio-0"}} +``` + +**Parameters:** + +- **id** indicates the ID of the device to be hot removed, which is specified when the device is hot added. + +**Example:** + +``` +<- {"execute": "device_del", "arguments": {"id": "vfio-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"vfio-0","path":"vfio-0"},"timestamp":{"seconds":1614310541,"microseconds":554250}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. + ## Using Ballon Devices The balloon device is used to reclaim idle memory from a VM. It called by running the QMP command. diff --git a/docs/en/docs/StratoVirt/interconnect_isula.md b/docs/en/docs/StratoVirt/interconnect_isula.md index 02ee4d5cb..baa77be73 100644 --- a/docs/en/docs/StratoVirt/interconnect_isula.md +++ b/docs/en/docs/StratoVirt/interconnect_isula.md @@ -51,7 +51,7 @@ The following describes how to install and configure iSulad and kata-containers. ], ``` -3. Restart isulad. +3. Restart **isulad**. ```shell # systemctl daemon-reload @@ -76,15 +76,18 @@ The following describes how to install and configure iSulad and kata-containers. This section describes how to interconnect StratoVirt with kata-containers to access the iSula container ecosystem. -1. Modify the kata configuration file. Its default path is **/usr/share/defaults/kata-containers/configuration.toml**. You can also configure the file by referring to **configuration-stratovirt.toml** in the same directory. Set the Hypervisor type of the secure container to **stratovirt**, kernel to the absolute path of the kernel image of kata-containers, and initrd to the **initrd** image file of kata-containers. (If you use Yum to install kata-containers, the two image files are downloaded and stored in the **/var/lib/kata/** directory by default. You can also use other images during the configuration.) +#### Connecting to a Lightweight VM - The configurations are as follows: +1. Modify the kata configuration file. Its default path is **/usr/share/defaults/kata-containers/configuration.toml**. You can also configure the file by referring to **configuration-stratovirt.toml** in the same directory. Modify the **hypervisor** type of the secure container to **stratovirt**, **kernel** to the absolute path of the kernel image of kata-containers, and **initrd** to the **initrd** image file of kata-containers. (If you use Yum to install kata-containers, the two image files are downloaded and stored in the **/var/lib/kata/** directory by default. You can also use other images during the configuration.) + + The modified configurations are as follows: ```shell [hypervisor.stratovirt] path = "/usr/bin/stratovirt" kernel = "/var/lib/kata/kernel" initrd = "/var/lib/kata/kata-containers-initrd.img" + machine_type = "microvm" block_device_driver = "virtio-mmio" use_vsock = true enable_netmon = true @@ -95,7 +98,7 @@ This section describes how to interconnect StratoVirt with kata-containers to ac disable_vhost_net = true ``` -2. Run the `isula` command **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. +2. Run the `isula` command with **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. ```shell # isula run -tid --runtime "io.containerd.kata.v2" --net=none --name test busybox:latest sh @@ -103,7 +106,7 @@ This section describes how to interconnect StratoVirt with kata-containers to ac 3. Run the `isula ps` command to check whether the secure container **test** is running properly. Then run the following command to access the container: - ``` + ```shell # isula exec –ti test sh ``` @@ -141,3 +144,80 @@ This section describes how to interconnect StratoVirt with kata-containers to ac ``` You can now run container commands in the **test** container. + +#### Connecting to a Standard VM + +To use a StratoVirt standard VM as the sandbox of a secure container, you need to modify some other configurations. + +1. The configurations are as follows: + + ```shell + [hypervisor.stratovirt] + path = "/usr/bin/stratovirt" + kernel = "/var/lib/kata/kernel" + initrd = "/var/lib/kata/kata-containers-initrd.img" + # x86_64 architecture + machine_type = "q35" + # AArch64 architecture + machine_type = "virt" + block_device_driver = "virtio-blk" + pcie_root_port = 2 + use_vsock = true + enable_netmon = true + internetworking_model = "tcfilter" + sandbox_cgroup_with_emulator = false + disable_new_netns = false + disable_block_device_use = false + disable_vhost_net = true + ``` + + In the configurations above, modify the VM type according to the architecture of the host machine. Change the value of **block_device_driver** to **virtio-blk**. StratoVirt supports only devices hot-plugged to the root port. Set a proper value of **pcie_root_port** based on the number of devices to be hot-plugged. + +2. Install the firmware required for starting a standard VM. + + x86_64 architecture: + + ```shell + # yum install -y edk2-ovmf + ``` + + AArch64 architecture: + + ```shell + # yum install -y edk2-aarch64 + ``` + +3. Build and replace the binary file of kata-containers 2.x. + + Currently, a StratoVirt standard VMs can only be used as the sandbox of a kata-containers 2.x container (corresponding to the openEuler-21.09 branch in the kata-containers repository). You need to download and compile the kata-containers source code and replace the **containerd-shim-kata-v2** binary file in the **/usr/bin** directory. + + ```shell + # mkdir -p /root/go/src/github.com/ + # cd /root/go/src/github.com/ + # git clone https://gitee.com/src-openeuler/kata-containers.git + # cd kata-containers + # git checkout openEuler-21.09 + # ./apply-patches + # cd src/runtime + # make + ``` + + Back up the kata binary file in the **/usr/bin/** directory and replace it with the compiled binary file **containerd-shim-kata-v2**. + + ```shell + # cp /usr/bin/containerd-shim-kata-v2 /usr/bin/containerd-shim-kata-v2.bk + # cp containerd-shim-kata-v2 /usr/bin/containerd-shim-kata-v2 + ``` + +4. Run the `isula` command with **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. + + ```shell + # isula run -tid --runtime "io.containerd.kata.v2" --net=none --name test busybox:latest sh + ``` + +5. Run the `isula ps` command to check whether the secure container **test** is running properly. Then run the following command to access the container: + + ```shell + # isula exec -ti test sh + ``` + diff --git a/docs/en/docs/Virtualization/LibcarePlus.md b/docs/en/docs/Virtualization/LibcarePlus.md new file mode 100644 index 000000000..d554c3fc5 --- /dev/null +++ b/docs/en/docs/Virtualization/LibcarePlus.md @@ -0,0 +1,410 @@ +# LibcarePlus + + + +- [LibcarePlus](#libcareplus) + - [Overview](#overview) + - [Hardware and Software Requirements](#hardware-and-software-requirements) + - [Precautions and Constraints](#precautions-and-constraints) + - [Installing LibcarePlus](#installing-libcareplus) + - [Software Installation Dependencies](#software-installation-dependencies) + - [Installing LibcarePlus](#installing-libcareplus-1) + - [Creating LibcarePlus Hot Patches](#creating-libcareplus-hot-patches) + - [Introduction](#introduction) + - [Manual Creation](#manual-creation) + - [Creation Through a Script](#creation-through-a-script) + - [Applying the LibcarePlus Hot Patch](#applying-the-libcareplus-hot-patch) + - [Preparation](#preparation) + - [Loading the Hot Patch](#loading-the-hot-patch) + - [Querying a Hot Patch](#querying-a-hot-patch) + - [Uninstalling the Hot Patch](#uninstalling-the-hot-patch) + + + +## Overview + +LibcarePlus is a hot patch framework for user-mode processes. It can perform hot patch operations on target processes running on the Linux system without restarting the processes. Hot patches can be used to fix CVEs and urgent bugs that do not interrupt application services. + +## Hardware and Software Requirements + +The following software and hardware requirements must be met to use LibcarePlus on openEuler: + +- Currently, the x86 and ARM64 architectures are supported. + +- LibcarePlus can run on any Linux distribution that supports **libunwind**, **elfutils**, and **binutils**. +- LibcarePlus uses the **ptrace()** system call, which requires the kernel configuration option enabled for the corresponding Linux distribution. +- LibcarePlus needs the symbol table of the original executable file when creating a hot patch. Do not strip the symbol table too early. +- On the Linux OS where SELinux is enabled, manually adapt the SELinux policies. + +## Precautions and Constraints + +When using LibcarePlus, comply with the following hot patch specifications and constraints: + +- Only the code written in the C language is supported. The assembly language is not supported. +- Only user-mode programs are supported. Dynamic library patches are not supported. +- The code file name must comply with the C language identifier naming specifications. That is, the code file name consists of letters (A-Z and a-z), digits (0-9), and underscores (_) but the first character cannot be a digit. Special characters such as hyphens (-) and dollar signs ($) are not allowed. +- Incremental patches are supported. Multiple patches can be installed on a process. However, you need to design the patch installation and uninstallation management. Generally, the installation and uninstallation comply with the first-in, last-out (FILO) rule. +- Automatic patch loading is not natively supported. You can design an automatic patch loading method for a specific process. +- Patch query is supported. +- The static function patch is restricted by the symbol table that can find the function in the system. +- Hot patches are process-specific. That is, a hot patch of a dynamic library can be applied only to process that invoke the dynamic library. +- The number of patches that can be applied to a process is limited by the range of the jump instruction and the size of the hole in the virtual memory address space. Generally, up to 512 patches can be applied to a process. +- Thread local storage (TLS) variables of the initial executable (IE) model can be modified. +- Symbols defined in a patch cannot be used in subsequent patches. +- Hot patches are not supported in the following scenarios: + - Infinite loop function, non-exit function, inline function, initialization function, and non-maskable interrupt (NMI) function + - Replacing global variables + - Functions less than 5 bytes + - Modifying the header file + - Adding or deleting the input and output parameters of the target function + - Changing (adding, deleting, or modifying) data structure members + - Modifying the C files that contain GCC macros such as __LINE__ and __FILE__ + - Modifying the Intel vector assembly instruction + +## Installing LibcarePlus + +### Software Installation Dependencies + +The LibcarePlus running depends on **libunwind**, **elfutils**, and **binutils**. On the openEuler system configured with the Yum repo, you can run the following commands to install the software on which LibcarePlus depends: + +``` shell +# yum install -y binutils elfutils elfutils-libelf-devel libunwind-devel +``` + +#### Installing LibcarePlus + +```shell +# yum install libcareplus -y +``` + +Check whether LibcarePlus is installed. + +``` shell +# libcare-ctl -h +usage: libcare-ctl [options] [args] + +Options: + -v - verbose mode + -h - this message + +Commands: + patch - apply patch to a user-space process + unpatch- unapply patch from a user-space process + info - show info on applied patches +``` + +## Creating LibcarePlus Hot Patches + +### Introduction + +LibcarePlus hot patch creation methods: + +- Manual creation +- Creation through a script + +The process of manually creating a hot patch is complex. For a project with a large amount of code, for example, QEMU, it is extremely difficult to manually create a hot patch. You are advised to use the script provided by LibcarePlus to generate a hot patch file with one click. + +#### Manual Creation + +The following takes the original file **foo.c** and the patch file **bar.c** as examples to describe how to manually create a hot patch. + +1. Prepare the original file and patch file written in the C language. For example, **foo.c** and **bar.c**. + +
+ Expand foo.c +

+ + ``` c + // foo.c + #include + #include + + void print_hello(void) + { + printf("Hello world!\n"); + } + + int main(void) + { + while (1) { + print_hello(); + sleep(1); + } + } + ``` + +

+
+ +
+ Expand bar.c +

+ + ``` c + // bar.c + #include + #include + + void print_hello(void) + { + printf("Hello world %s!\n", "being patched"); + } + + int main(void) + { + while (1) { + print_hello(); + sleep(1); + } + } + ``` + +

+
+ +2. Build the original file and patch file to obtain the assembly files **foo.s** and **bar.s**. + + ``` shell + # gcc -S foo.c + # gcc -S bar.c + # ls + bar.c bar.s foo.c foo.s + ``` + +3. Run `kpatch_gensrc` to compare **foo.s** and **bar.s** and generate the **foobar.s** file that contains the assembly content of the original file and the differences. + + ``` shell + # sed -i 's/bar.c/foo.c/' bar.s + # kpatch_gensrc --os=rhel6 -i foo.s -i bar.s -o foobar.s --force-global + ``` + + By default, `kpatch_gensrc` compares the original files in the same C language. Therefore, before the comparison, you need to run the `sed` command to change the file name **bar.c** in the patch assembly file **bar.s** to the original file name **foo.c**. Call `kpatch_gensrc` to specify the input files as **foo.s** and **bar.s** and the output file as **foobar.s**. + +4. Build the assembly file **foo.s** in the original file and the generated assembly file **foobar.s** to obtain the executable files **foo** and **foobar**. + + ``` shell + # gcc -o foo foo.s + # gcc -o foobar foobar.s -Wl,-q + ``` + + The **-Wl, -q** linker options reserve the relocation sections in **foobar**. + +5. Use `kpatch_strip` to remove the duplicate content from the executables **foo** and **foobar** and reserve the content required for creating hot patches. + + ``` shell + # kpatch_strip --strip foobar foobar.stripped + # kpatch_strip --rel-fixup foo foobar.stripped + # strip --strip-unneeded foobar.stripped + # kpatch_strip --undo-link foo foobar.stripped + ``` + + The options in the preceding command are described as follows: + + - **--strip** removes useless sections for patch creation from **foobar**. + - **--rel-fixup** repairs the address of the variables and functions accessed in the patch. + - **strip --strip-unneeded** removes the useless symbol information for hot patch relocation. + - **--undo-link** changes the symbol address in a patch from absolute to relative. + +6. Create a hot patch file. + + After the preceding operations, the contents required for creating the hot patch are obtained. Run the `kpatch_make` command to input parameters Build ID of the original executable file and **foobar.stripped** (output file of `kpatch_strip`) to `kpatch_make` to generate a hot patch file. + + ``` shell + # str=$(readelf -n foo | grep 'Build ID') + # substr=${str##* } + # kpatch_make -b $substr -i 0001 foobar.stripped -o foo.kpatch + # ls + bar.c bar.s foo foobar foobar.s foobar.stripped foo.c foo.kpatch foo.s + ``` + + The final hot patch file **foo.kpatch** whose patch ID is **0001** is obtained. + +#### Creation Through a Script + +This section describes how to use LibcarePlus built-in **libcare-patch-make** script to create a hot patch file. The original file **foo.c** and patch file **bar.c** are used as an example. + +1. Run the `diff` command to generate the comparison file of **foo.c** and **bar.c**. + + ``` shell + # diff -up foo.c bar.c > foo.patch + ``` + + The content of the **foo.patch** file is as follows: + +
+ Expand foo.patch +

+ + + ``` diff + --- foo.c 2020-12-09 15:39:51.159632075 +0800 + +++ bar.c 2020-12-09 15:40:03.818632220 +0800 + @@ -1,10 +1,10 @@ + -// foo.c + +// bar.c + #include + #include + + void print_hello(void) + { + - printf("Hello world!\n"); + + printf("Hello world %s!\n", "being patched"); + } + + int main(void) + ``` + +

+
+ + +2. Write the **makefile** for building **foo.c** as follows: + +
+ Expand makefile +

+ + ``` makefile + all: foo + + foo: foo.c + $(CC) -o $@ $< + + clean: + rm -f foo + + install: foo + mkdir $$DESTDIR || : + cp foo $$DESTDIR + ``` + +

+
+ + +3. After the **makefile** is done, directly call `libcare-patch-make`. If `libcare-patch-make` asks you which file to install the patch, enter the original file name, as shown in the following: + + ``` shell + # libcare-patch-make --clean -i 0001 foo.patch + rm -f foo + BUILDING ORIGINAL CODE + /usr/local/bin/libcare-cc -o foo foo.c + INSTALLING ORIGINAL OBJECTS INTO /libcareplus/test/lpmake + mkdir $DESTDIR || : + cp foo $DESTDIR + applying foo.patch... + can't find file to patch at input line 3 + Perhaps you used the wrong -p or --strip option? + The text leading up to this was: + -------------------------- + |--- foo.c 2020-12-10 09:43:04.445375845 +0800 + |+++ bar.c 2020-12-10 09:48:36.778379648 +0800 + -------------------------- + File to patch: foo.c + patching file foo.c + BUILDING PATCHED CODE + /usr/local/bin/libcare-cc -o foo foo.c + INSTALLING PATCHED OBJECTS INTO /libcareplus/test/.lpmaketmp/patched + mkdir $DESTDIR || : + cp foo $DESTDIR + MAKING PATCHES + Fixing up relocation printf@@GLIBC_2.2.5+fffffffffffffffc + Fixing up relocation print_hello+0 + patch for /libcareplus/test/lpmake/foo is in /libcareplus/test/patchroot/700297b7bc56a11e1d5a6fb564c2a5bc5b282082.kpatch + ``` + + After the command is executed, the output indicates that the hot patch file is in the **patchroot** directory of the current directory, and the executable file is in the **lpmake** directory. By default, the Build ID is used to name a hot patch file generated by a script. + + + +## Applying the LibcarePlus Hot Patch + +This following uses the original file **foo.c** and patch file **bar.c** as an example to describe how to use the LibcarePlus hot patch. + +### Preparation + +Before using the LibcarePlus hot patch, prepare the original executable file **foo** and hot patch file **foo.kpatch**. + +### Loading the Hot Patch + +The procedure for applying the LibcarePlus hot patch is as follows: + +1. In the first shell window, run the executable file to be patched: + + ``` shell + # ./lpmake/foo + Hello world! + Hello world! + Hello world! + ``` + +2. In the second shell window, run the `libcare-ctl` command to apply the hot patch: + + ``` shell + # libcare-ctl -v patch -p $(pidof foo) ./foo.kpatch + ``` + + If the hot patch is applied successfully, the following information is displayed in the second shell window: + + ``` shell + 1 patch hunk(s) have been successfully applied to PID '10999' + ``` + + The following information is displayed for the target process running in the first shell window: + + ``` shell + Hello world! + Hello world! + Hello world being patched! + Hello world being patched! + ``` + + +### Querying a Hot Patch + +The procedure for querying a LibcarePlus hot patch is as follows: + +1. Run the following command in the second shell window: + + ```shell + # libcare-ctl info -p $(pidof foo) + + ``` + + If a hot patch is installed, the following information is displayed in the second shell window: + + ```shell + Pid: 551763 + Target: foo + Build id: df05a25bdadd282812d3ee5f0a460e69038575de + Applied patch number: 1 + Patch id: 0001 + ``` + + + + +### Uninstalling the Hot Patch + +The procedure for uninstalling the LibcarePlus hot patch is as follows: + +1. Run the following command in the second shell window: + + ``` shell + # libcare-ctl unpatch -p $(pidof foo) + ``` + + If the hot patch is uninstalled successfully, the following information is displayed in the second shell window: + + ``` shell + 1 patch hunk(s) were successfully cancelled from PID '10999' + ``` + +2. The following information is displayed for the target process running in the first shell window: + + ``` shell + Hello world being patched! + Hello world being patched! + Hello world! + Hello world! + ``` diff --git a/docs/en/docs/Virtualization/tool-guide.md b/docs/en/docs/Virtualization/tool-guide.md index 06bbb1650..565ebecf3 100644 --- a/docs/en/docs/Virtualization/tool-guide.md +++ b/docs/en/docs/Virtualization/tool-guide.md @@ -1,196 +1 @@ -# Tool Guide - -- [vmtop](#vmtop) - -## vmtop - -### Overview - -vmtop is a user-mode tool running on the host machine. You can use the vmtop tool to dynamically view the usage of VM resources in real time, such as CPU usage, memory usage, and the number of vCPU traps. Therefore, the vmtop tool can be used to locate virtualization problems and optimize performance. - -#### Multi-Architecture Support - -Currently, the vmtop supports the AArch64 and x86_64 processor architectures. - -#### Display Item Description - -The vmtop display items vary according to the processor architecture. This document describes the meaning of each display item and whether it is displayed in the corresponding architecture. -Note: The following sampling difference refers to the difference between two times of data obtained in a specified interval. - -##### **Display Items of the AArch64 and x86_64 Architectures** - -- VM/task-name: VM/Process name -- DID: VM ID -- PID: PID of the qemu process of the VM -- %CPU: CPU usage of a process -- EXTsum: Total number of KVM exits (sampling difference) -- S: Process status -- P: ID of the physical CPU occupied by a process -- %ST: Ratio of the preemption time to the CPU running time -- %GUE: Ratio of the VM internal occupation time to the CPU running time -- %HYP: Virtualization overhead ratio - -##### Display Items Only for the Aarch64 Architecture - -- EXThvc: Number of hvc-exits (sampling difference) -- EXTwfe: Number of wfe-exits (sampling difference) -- EXTwfi: Number of wfi-exits (sampling difference) -- EXTmmioU: Number of mmioU-exits (sampling difference) -- EXTmmioK: Number of mmioK-exits (sampling difference) -- EXTfp: Number of fp-exits (sampling difference) -- EXTirq: Number of irq-exits (sampling difference) -- EXTsys64: Number of sys64 exits (sampling difference) -- EXTmabt: Number of mem abort exits (sampling difference) - -##### Display Items Only for the x86_64 Architecture - -- PFfix: Number of page faults (sampling difference) -- PFgu: Number of times that page faults are injected to the guest OS (sampling difference) -- INvlpg: Number of times that a TLB item is flushed (one of the TLB items, which is not fixed) -- EXTio: Number of io VM-exit times (sampling difference) -- EXTmmio: Number of mmio VM-exit times (sampling difference) -- EXThalt: Number of halt VM-exit times (sampling difference) -- EXTsig: Number of VM-exits caused by signal processing (sampling difference) -- EXTirq: Number of VM-exits caused by interrupts (sampling difference) -- EXTnmiW: Number of VM-exit times caused by non-maskable interrupts (sampling difference) -- EXTirqW: Interruptwindow mechanism. When the interrupt function is enabled, exit is used to inject interrupts (sampling difference) -- IrqIn: Number of times that IRQ interrupts are injected (sampling difference) -- NmiIn: Number of times that NMI interrupts are injected (sampling difference) -- TLBfl: Number of times that the entire TLB is flushed (sampling difference) -- HostReL: Number of times that the host status is overloaded (sampling difference) -- Hyperv: Number of times that the guest OS is simulated to call hypercal in virtualization-assistant mode (sampling difference) -- EXTcr: Number of times that the access to the CR register exits (sampling difference) -- EXTrmsr: Number of times that the read MSR exits (sampling difference) -- EXTwmsr: Number of times that the write MSR exits (sampling difference) -- EXTapic: Number of APIC write times (sampling difference) -- EXTeptv: Ept page fault exit times (sampling difference) -- EXTeptm: Number of Ept error exits (sampling difference) -- EXTpau: Number of times that the VCPU pauses and exits (sampling difference) - -### Usage - -vmtop is a command line tool. You can directly run the vmtop in command line mode. -In addition, the vmtop tool provides different options for querying different information. - -#### Syntax - -```sh -vmtop [option] -``` - -#### Option Description - -- -d: sets the refresh interval, in seconds. -- -H: displays the VM thread information. -- -n: sets the number of refresh times and exits after the refresh is complete. -- -b: displays Batch mode, which can be used to redirect to a file. -- -h: displays help information. -- -v: displays versions. -- -p: monitors the VM with a specified ID. - -#### Keyboard Shortcut - -Shortcut key used when the vmtop is running. - -- H: displays or stops the VM thread information. The information is displayed by default. -- up/down: moves the VM list upwards or downwards. -- left/right: moves the cursor leftwards or rightwards to display the columns that are hidden due to the screen width. -- f: enters the editing mode of a monitoring item and selects the monitoring item to be enabled. -- q: exits the vmtop process. - -### Example - -Run the vmtop command on the host. - -```sh -vmtop -``` - -The command output is as follows: - -```sh -vmtop - 2020-09-14 09:54:48 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP - 2 example 4054916 13.0 0 0 1206 10 0 144 62 174 0 1452 S 106 0.0 99.7 16.0 -``` - -As shown in the output, there is only one VM named "example" on the host. The ID is 2. The CPU usage is 13.0%. The total number of traps within one second is 1452. The physical CPU occupied by the VM process is CPU 106. The ratio of the VM internal occupation time to the CPU running time is 99.7%. - -1. Display VM thread information. -Press H to display the thread information. - -```sh -vmtop - 2020-09-14 10:11:27 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP - 2 example 4054916 13.0 0 0 1191 17 4 120 76 147 0 1435 S 119 0.0 123.7 4.0 - |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 - |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 - |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 - |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 0.0 0.0 0.0 - |_ CPU 0/KVM 4054933 3.0 0 0 280 6 4 28 19 41 0 350 S 105 0.0 27.9 0.0 - |_ CPU 1/KVM 4054934 3.0 0 0 260 0 0 16 12 36 0 308 S 31 0.0 20.0 0.0 - |_ CPU 2/KVM 4054935 3.0 0 0 341 0 0 44 20 26 0 387 R 108 0.0 27.9 4.0 - |_ CPU 3/KVM 4054936 5.0 0 0 310 11 0 32 25 44 0 390 S 103 0.0 47.9 0.0 - |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 0.0 0.0 0.0 - |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 0.0 0.0 0.0 - |_ worker 4143738 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 -``` - -The example VM has 11 threads, including the vCPU thread, vnc_worker, and IO mon_iotreads. Each thread also displays detailed CPU usage and trap information. - -2. Select the monitoring item. -Enter f to edit the monitoring item. - -```sh -field filter - select which field to be showed -Use up/down to navigate, use space to set whether chosen filed to be showed -'q' to quit to normal display - - * DID - * VM/task-name - * PID - * %CPU - * EXThvc - * EXTwfe - * EXTwfi - * EXTmmioU - * EXTmmioK - * EXTfp - * EXTirq - * EXTsys64 - * EXTmabt - * EXTsum - * S - * P - * %ST - * %GUE - * %HYP -``` - -All monitoring items are displayed by default. You can press the up or down key to select a monitoring item, press the space key to set whether to display or hide the monitoring item, and press the q key to exit. -After %ST, %GUE, and %HYP are hidden, the following information is displayed: - -```sh -vmtop - 2020-09-14 10:23:25 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P - 2 example 4054916 12.0 0 0 1213 14 1 144 68 168 0 1464 S 125 - |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 125 - |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 - |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 - |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 - |_ CPU 0/KVM 4054933 2.0 0 0 303 6 0 29 10 35 0 354 S 98 - |_ CPU 1/KVM 4054934 4.0 0 0 279 0 0 39 17 49 0 345 S 1 - |_ CPU 2/KVM 4054935 3.0 0 0 283 0 0 33 20 40 0 343 S 122 - |_ CPU 3/KVM 4054936 3.0 0 0 348 8 1 43 21 44 0 422 S 110 - |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 - |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 - |_ worker 1794 0.0 0 0 0 0 0 0 0 0 0 0 S 126 -``` - -%ST, %GUE, and %HYP will not be displayed on the screen. +To help users better use virtualization, openEuler provides a set of tools, including vmtop and LibcarePlus. This section describes how to install and use these tools. \ No newline at end of file diff --git a/docs/en/docs/Virtualization/vmtop.md b/docs/en/docs/Virtualization/vmtop.md new file mode 100644 index 000000000..346cc01c2 --- /dev/null +++ b/docs/en/docs/Virtualization/vmtop.md @@ -0,0 +1,196 @@ +# Tool Guide + +- [vmtop](#vmtop) + +## vmtop + +### Overview + +vmtop is a user-mode tool running on the host machine. You can use the vmtop tool to dynamically view the usage of VM resources in real time, such as CPU usage, memory usage, and the number of vCPU traps. Therefore, the vmtop tool can be used to locate virtualization problems and optimize performance. + +#### Multi-Architecture Support + +Currently, the vmtop supports the AArch64 and x86_64 processor architectures. + +#### Display Item Description + +The vmtop display items vary according to the processor architecture. This document describes the meaning of each display item and whether it is displayed in the corresponding architecture. +Note: The following sampling difference refers to the difference between two times of data obtained in a specified interval. + +##### **Display Items of the AArch64 and x86_64 Architectures** + +- VM/task-name: VM/Process name +- DID: VM ID +- PID: PID of the qemu process of the VM +- %CPU: CPU usage of a process +- EXTsum: Total number of KVM exits (sampling difference) +- S: Process status +- P: ID of the physical CPU occupied by a process +- %ST: Ratio of the preemption time to the CPU running time +- %GUE: Ratio of the VM internal occupation time to the CPU running time +- %HYP: Virtualization overhead ratio + +##### Display Items Only for the Aarch64 Architecture + +- EXThvc: Number of hvc-exits (sampling difference) +- EXTwfe: Number of wfe-exits (sampling difference) +- EXTwfi: Number of wfi-exits (sampling difference) +- EXTmmioU: Number of mmioU-exits (sampling difference) +- EXTmmioK: Number of mmioK-exits (sampling difference) +- EXTfp: Number of fp-exits (sampling difference) +- EXTirq: Number of irq-exits (sampling difference) +- EXTsys64: Number of sys64 exits (sampling difference) +- EXTmabt: Number of mem abort exits (sampling difference) + +##### Display Items Only for the x86_64 Architecture + +- PFfix: Number of page faults (sampling difference) +- PFgu: Number of times that page faults are injected to the guest OS (sampling difference) +- INvlpg: Number of times that a TLB item is flushed (one of the TLB items, which is not fixed) +- EXTio: Number of io VM-exit times (sampling difference) +- EXTmmio: Number of mmio VM-exit times (sampling difference) +- EXThalt: Number of halt VM-exit times (sampling difference) +- EXTsig: Number of VM-exits caused by signal processing (sampling difference) +- EXTirq: Number of VM-exits caused by interrupts (sampling difference) +- EXTnmiW: Number of VM-exit times caused by non-maskable interrupts (sampling difference) +- EXTirqW: Interruptwindow mechanism. When the interrupt function is enabled, exit is used to inject interrupts (sampling difference) +- IrqIn: Number of times that IRQ interrupts are injected (sampling difference) +- NmiIn: Number of times that NMI interrupts are injected (sampling difference) +- TLBfl: Number of times that the entire TLB is flushed (sampling difference) +- HostReL: Number of times that the host status is overloaded (sampling difference) +- Hyperv: Number of times that the guest OS is simulated to call hypercall in virtualization-assistant mode (sampling difference) +- EXTcr: Number of times that the access to the CR register exits (sampling difference) +- EXTrmsr: Number of times that the read MSR exits (sampling difference) +- EXTwmsr: Number of times that the write MSR exits (sampling difference) +- EXTapic: Number of APIC write times (sampling difference) +- EXTeptv: Ept page fault exit times (sampling difference) +- EXTeptm: Number of Ept error exits (sampling difference) +- EXTpau: Number of times that the VCPU pauses and exits (sampling difference) + +### Usage + +vmtop is a command line tool. You can directly run the vmtop in command line mode. +In addition, the vmtop tool provides different options for querying different information. + +#### Syntax + +```sh +vmtop [option] +``` + +#### Option Description + +- -d: sets the refresh interval, in seconds. +- -H: displays the VM thread information. +- -n: sets the number of refresh times and exits after the refresh is complete. +- -b: displays Batch mode, which can be used to redirect to a file. +- -h: displays help information. +- -v: displays versions. +- -p: monitors the VM with a specified ID. + +#### Keyboard Shortcut + +Shortcut key used when the vmtop is running. + +- H: displays or stops the VM thread information. The information is displayed by default. +- up/down: moves the VM list upwards or downwards. +- left/right: moves the cursor leftwards or rightwards to display the columns that are hidden due to the screen width. +- f: enters the editing mode of a monitoring item and selects the monitoring item to be enabled. +- q: exits the vmtop process. + +### Example + +Run the vmtop command on the host. + +```sh +vmtop +``` + +The command output is as follows: + +```sh +vmtop - 2020-09-14 09:54:48 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP + 2 example 4054916 13.0 0 0 1206 10 0 144 62 174 0 1452 S 106 0.0 99.7 16.0 +``` + +As shown in the output, there is only one VM named "example" on the host. The ID is 2. The CPU usage is 13.0%. The total number of traps within one second is 1452. The physical CPU occupied by the VM process is CPU 106. The ratio of the VM internal occupation time to the CPU running time is 99.7%. + +1. Display VM thread information. +Press H to display the thread information. + +```sh +vmtop - 2020-09-14 10:11:27 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP + 2 example 4054916 13.0 0 0 1191 17 4 120 76 147 0 1435 S 119 0.0 123.7 4.0 + |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 + |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 + |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 + |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 0.0 0.0 0.0 + |_ CPU 0/KVM 4054933 3.0 0 0 280 6 4 28 19 41 0 350 S 105 0.0 27.9 0.0 + |_ CPU 1/KVM 4054934 3.0 0 0 260 0 0 16 12 36 0 308 S 31 0.0 20.0 0.0 + |_ CPU 2/KVM 4054935 3.0 0 0 341 0 0 44 20 26 0 387 R 108 0.0 27.9 4.0 + |_ CPU 3/KVM 4054936 5.0 0 0 310 11 0 32 25 44 0 390 S 103 0.0 47.9 0.0 + |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 0.0 0.0 0.0 + |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 0.0 0.0 0.0 + |_ worker 4143738 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 +``` + +The example VM has 11 threads, including the vCPU thread, vnc_worker, and IO mon_iotreads. Each thread also displays detailed CPU usage and trap information. + +2. Select the monitoring item. +Enter f to edit the monitoring item. + +```sh +field filter - select which field to be showed +Use up/down to navigate, use space to set whether chosen filed to be showed +'q' to quit to normal display + + * DID + * VM/task-name + * PID + * %CPU + * EXThvc + * EXTwfe + * EXTwfi + * EXTmmioU + * EXTmmioK + * EXTfp + * EXTirq + * EXTsys64 + * EXTmabt + * EXTsum + * S + * P + * %ST + * %GUE + * %HYP +``` + +All monitoring items are displayed by default. You can press the up or down key to select a monitoring item, press the space key to set whether to display or hide the monitoring item, and press the q key to exit. +After %ST, %GUE, and %HYP are hidden, the following information is displayed: + +```sh +vmtop - 2020-09-14 10:23:25 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P + 2 example 4054916 12.0 0 0 1213 14 1 144 68 168 0 1464 S 125 + |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 125 + |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 + |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 + |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 + |_ CPU 0/KVM 4054933 2.0 0 0 303 6 0 29 10 35 0 354 S 98 + |_ CPU 1/KVM 4054934 4.0 0 0 279 0 0 39 17 49 0 345 S 1 + |_ CPU 2/KVM 4054935 3.0 0 0 283 0 0 33 20 40 0 343 S 122 + |_ CPU 3/KVM 4054936 3.0 0 0 348 8 1 43 21 44 0 422 S 110 + |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 + |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 + |_ worker 1794 0.0 0 0 0 0 0 0 0 0 0 0 S 126 +``` + +%ST, %GUE, and %HYP will not be displayed on the screen. diff --git a/docs/en/docs/secGear/api-description.md b/docs/en/docs/secGear/api-description.md index 6e48a8c83..ec94310aa 100644 --- a/docs/en/docs/secGear/api-description.md +++ b/docs/en/docs/secGear/api-description.md @@ -10,6 +10,9 @@ Creates an enclave API. Initialization API. The function calls different TEE creation functions based on the type to initialize the enclave context in different TEE solutions. This API is called by the REE. +>![](./public_sys-resources/icon-note.gif) **说明:** +> Due to Intel SGX restrictions, memory mapping contention exists when multiple thread invoke cc_enclave_create concurrently. As a result, the creation of the enclave API may fail. Avoid concurrent invocations of cc_enclave_create in your code. + **Function Declarations:** cc_enclave_result_t cc_enclave_create(const char* path, enclave_type_t type, uint32_t version,uint32_t flags,const enclave_features_t* features,uint32_t features_count, diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 16cd18d03..0aaaacf6d 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -67,6 +67,8 @@ headless: true - [VM Maintainability Management]({{< relref "./docs/Virtualization/vm-maintainability-management.md" >}}) - [Best Practices]({{< relref "./docs/Virtualization/best-practices.md" >}}) - [Tool Guide]({{< relref "./docs/Virtualization/tool-guide.md" >}}) + - [vmtop]({{< relref "./docs/Virtualization/vmtop.md" >}}) + - [LibcarePlus]({{< relref "./docs/Virtualization/LibcarePlus.md" >}}) - [Appendix]({{< relref "./docs/Virtualization/appendix.md" >}}) - [StratoVirt Virtualization User Guide]({{< relref "./docs/StratoVirt/StratoVrit_guidence.md" >}}) - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_intoduction.md" >}}) -- Gitee From 91b84794931e2cd36d097bf6f7070e69bfff93dc Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 24 Mar 2022 17:51:12 +0800 Subject: [PATCH 04/42] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E6=8C=87=E5=AF=BC=E6=96=87=E6=A1=A3=EF=BC=8C=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=BC=80=E5=8F=91=E6=96=87=E6=A1=A3=EF=BC=8C?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 100 ++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 152 ++++++++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 143 ++++++++++++++++ .../public_sys-resources/hosttools.png | Bin 0 -> 175700 bytes ...77\347\224\250\346\226\271\346\263\225.md" | 45 ------ ...05\344\270\216\350\277\220\350\241\214.md" | 49 ++++-- ...\273\272\346\214\207\345\257\274.markdown" | 4 + docs/zh/menu/index.md | 5 +- 8 files changed, 436 insertions(+), 62 deletions(-) create mode 100644 "docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" create mode 100644 docs/zh/docs/Embedded/public_sys-resources/hosttools.png delete mode 100644 "docs/zh/docs/Embedded/\344\275\277\347\224\250\346\226\271\346\263\225.md" create mode 100644 "docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" new file mode 100644 index 000000000..283757eed --- /dev/null +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -0,0 +1,100 @@ +# 基于openEuler Embedded的SDK应用开发 + +当前发布的镜像除了体验openEuler Embedded的基本功能外,还可以进行基本的应用开发,也即在openEuler Embedded上运行用户自己的程序。本章主要介绍如何基于openEuler Embedded的SDK进行应用开发。 + + + +- [安装SDK](#安装SDK) +- [使用SDK编译](#使用SDK编译) + + +### 安装SDK + +1. **执行SDK自解压安装脚本** + +运行如下命令: + +``` {.sourceCode .console} +sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh +``` + +根据提示输入工具链的安装路径,默认路径是/opt/openeuler/\/;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 + +举例如下: + +``` +sh ./openeuler-glibc-x86_64-openeuler-image-armv7a-qemu-arm-toolchain-22.03.sh`` +openEuler embedded(openEuler Embedded Reference Distro) SDK installer version 22.03 +================================================================ +Enter target directory for SDK (default: /opt/openeuler/22.03): sdk +You are about to install the SDK to "/usr1/openeuler/sdk". Proceed [Y/n]? y +Extracting SDK...............................................done +Setting it up...SDK has been successfully set up and is ready to be used. +Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. +$ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +2. **设置SDK环境变量** + +运行source命令。上例中前一步执行结束最后已打印source命令,运行即可。 + +``` {.sourceCode .console} +. /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +3. **查看是否安装成功** + +运行如下命令,查看是否安装成功、环境设置成功。 + +``` {.sourceCode .console} +arm-openeuler-linux-gnueabi-gcc -v +``` + +### 使用SDK编译 + +下面以使用SDK编译hello world为样例。 + +1. **准备代码** + +以构建一个hello world程序为例,运行在openEuler Embedded根文件系统镜像中。 + +创建一个hello.c文件,源码如下: + +``` c +#include + +int main(void) +{ + printf("hello world\n"); +} +``` + +编写CMakelist.txt,和hello.c文件放在同一个目录。 + +``` +project(hello C) + +add_executable(hello hello.c) +``` + +2. **编译生成二进制** + +进入hello.c文件所在目录,使用工具链编译,命令如下: + +``` {.sourceCode .console} +cmake .. +make +``` + +把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述使能共享文件系统场景。 + +3. **运行用户态程序** + +在openEuler Embedded系统中运行hello程序。 + +``` {.sourceCode .console} +cd /tmp/myfiles/ +./hello +``` + +如运行成功,则会输出\"hello world\"。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..2074cf578 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,152 @@ +openEuler Embedded容器构建指导 +============================== + +由于openEuler Embedded构建过程需要基于openEuler操作系统,且需要安装较多系统工具和构建工具。为方便开发人员快速搭建构建环境,我们将构建过程所依赖的操作系统和工具封装到一个容器中,这就使得开发人员可以快速搭建一个构建环境,进而投入到代码开发中去,避免在准备环境阶段消耗大量时间。 + + + +- [环境准备](#环境准备) + - [安装docker](#安装docker) + - [获取容器镜像](#获取容器镜像) + - [准备容器构建环境](#准备容器构建环境) +- [openEuler Embedded版本构建](#openEuler Embedded版本构建) + - [下载源码](#下载源码) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +## 环境准备 + +需要使用docker创建容器环境,为了确保docker成功安装,需满足以下软件硬件要求: + +- 操作系统: 推荐使用Ubuntu、Debian和RHEL(Centos、Fedora等) +- 内核: 推荐3.8及以上的内核 +- 驱动: 内核必须支持一种合适的存储驱动,例如: Device Mapper、AUFS、vfs、btrfs、ZFS +- 架构: 运行64位架构的计算机(x86\_64和amd64) + +### 安装docker + +------------- + +1. 检查当前环境是否已安装docker工具 + +运行如下命令,可以看到当前docker版本信息,则说明当前环境已安装docker,无需再次安装。 + +``` {.sourceCode .console} +docker version +``` + +2. 如果没有安装,可参考官方链接安装 + +官网地址: ,openEuler环境可参考Centos安装Docker。 + +例如openEuler环境docker安装命令如下: + +``` +sudo yum install docker +``` + +### 获取容器镜像 + +--------------- + +通过docker pull命令拉取华为云中的镜像到宿主机。命令如下: + +``` +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +``` + +### 准备容器构建环境 + +------------------- + +#### 1.启动容器 + +可通过docker run命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: + +``` +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +``` + +参数说明: + +- -i 让容器的标准输入保持打开 +- -d 让 Docker 容器在后台以守护态(Daemonized)形式运行 +- -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上 +- \--network 将容器连接到(host)网络 +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest + (镜像名称:镜像版本) +- bash 进入容器的方式 + +#### 2.查看已启动的容器id + +``` +docker ps +``` + +#### 3.进入容器 + +``` +docker exec -it 容器id bash +``` + +构建环境已准备完成,下面就可以在容器中进行构建了。 + +## openEuler Embedded版本构建 + +### 下载源码 + +1. 获取源码下载脚本 + +``` +git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v /usr1/openeuler/src/yocto-meta-openeuler +``` + +2. 通过脚本下载源码 + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +sh download_code.sh /usr1/openeuler/src +``` + +### 编译构建 + +- 编译架构: aarch64-std、aarch64-pro、arm-std、raspberrypi4-64 +- 构建目录: /usr1/build +- 源码目录: /usr1/openeuler/src +- 编译器所在路径: /usr1/openeuler/gcc/openeuler\_gcc\_arm64le + +>![](./public_sys-resources/icon-note.gif) **说明:** +>- 不同的编译架构使用不同的编译器,aarch64-std、aarch64-pro、raspberrypi4-64使用openeuler\_gcc\_arm64le编译器,arm-std使用openeuler\_gcc\_arm32le编译器。 +>- 下面以以aarch64-std目标架构编译为例。 + +1. 将/usr1目录所属群组改为openeuler,否则切换至openeuler用户构建会存在权限问题。 + +``` +chown -R openeuler:users /usr1 +``` + +2. 切换至openeuler用户。 + +``` +su openeuler +``` + +3. 进入构建脚本所在路径,运行编译脚本。 + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +source compile.sh aarch64-std /usr1/build /usr1/openeuler/gcc/openeuler_gcc_arm64le +bitbake openeuler-image +``` + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面aarch64-std的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..fc4974d26 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,143 @@ +openEuler Embedded构建指导 +===================== + +本章主要介绍如何构建openEuler Embedded。 + + + +- [环境准备](#环境准备) + - [Yocto中主机端命令使用](#Yocto中主机端命令使用) + - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) + - [已安装好工具的构建容器](#已安装好工具的构建容器) +- [openEuler Embedded版本构建](#openEuler Embedded版本构建) + - [构建代码下载](#构建代码下载) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +环境准备 +-------------- + +### Yocto中主机端命令使用 + +Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 + +为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 + +Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: + +![](./public_sys-resources/hosttools.png) + +当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: + +| 工具名 | 用途 | +| ------ | ------------- | +| cmake | cmake构建工具 | +| ninjia | ninja构建系统 | + +### openEuler Embedded所需构建工具 + +- 构建OS + + [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- 安装系统额外工具 + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- 预编译的交叉工具链和库 + + Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 + + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + + - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [ARM64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + +### 已安装好工具的构建容器 + +openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 + +使用者可以通过如下链接获得容器镜像直接用于编译: + +​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +具体构建指导请参考[openEuler Embedded容器构建指导](https://docs.openeuler.org/zh/22.03_LTS/docs/Embedded/openEuler Embedded容器构建指导.html)。 + +## openEuler Embedded版本构建 + +### 构建代码下载 + +openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: + +><顶层目录openeuler_embedded> +>├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 +>├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 + +1. 获取源码下载脚本 + + 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: + + - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 + - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 + - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 + +2. 通过脚本下载源码 + + - 下载最新代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - 下载指定版本代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 + +### 编译构建 + +一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 + +编译脚本的主要流程说明: + +1. 设置PATH增加额外工具路径 +2. TEMPLATECONF指定local.conf.sample等配置文件路径 +3. 调用poky仓的oe-init-build-env进行初始化配置 +4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 +5. 在编译目录执行bitbake openeuler-image编译openEuler + Embedded的image和sdk +6. 执行完发布件在编译目录的output目录下 + +运行编译脚本,以编译标准arm架构为例,编译方法如下: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git a/docs/zh/docs/Embedded/public_sys-resources/hosttools.png b/docs/zh/docs/Embedded/public_sys-resources/hosttools.png new file mode 100644 index 0000000000000000000000000000000000000000..83bb076a7763d522dde36168b1f713e524141531 GIT binary patch literal 175700 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≀xz@bFQS4ry9XjQoA0sw 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�(R?AoPm92`mzaRGj^aKz8aO;Uq9oyUI4 z{@kH7CHy9a^HSEN{KzH@bngXreGlvzt!;Ql`V>AOj}3nV7ADqkX`-Q(!Ru`s zKVrBu`iK@};g|EdNVuB##*;X=s~yJmd&)N|w>G*R-))-}dvQ=&Ekzz-s_bF=p#MQZ zh`=QK^s4d>@DJJ8Fz%RN$ECb?=kdK5<)rD3ayzYQ=ol9=vJrXOw%WCRos3vZXQK&* zf31AhiO4qeeZ(%*+IoR%r;gsD+IIZ`vhqb?1Pj(|Yn08CJCV-ot}10t0wK3bj3O@D zk5V&`VdD0p&aLgNuyI-tx!OCEYvGx(lGyw$*Fu3(_yX?@zDpB)oh*ZcMjHX3#h~C$ z0NFssYz{^YZB<8g3QqBGn!^-mL4b({TDVn{Wh>u8b9x8=f;TX9D|EpuX$U1A2*$`l zct@w!BJ&tSomT4EU0g?~VfNOm@IKcy8?qez-4n_jxNE2E^IZIF4jVU%z11e}?oTuF zBpZj7K<+KP*wC#-@!%zza_Kr~x&i7oV{4?|gI0bbK!!;U8`ql_PmY1Vc}wZ)=a-vX zrU2E${gWVU@qsmCQh>7^`YTr;C&aNW{VVhN1)6TwH7P5iI&L`9~`Wal(Z8lx`p66il z0%!Y$>mPilaU;$)^U4A9@o$aJRkMy*K_mE}`S`ienQfXGR;_pB=0TF+-LKD1k2!p@-3%+ zOOW_ExOIQw#^~0ly9?Guv40&HI0H3U_8vc(hMIKpOnLWiU#i$zXVcuQ-Uhk@c>U8F zgF*Z*dy91i;Cx>$-u8t3&dEO;`z619CC?bSl!rCY-o2iK25FoA9$f|;ne)3cAT>L? zN_~fNHf(k?XbPB31{lxxE0p41jWaRZ=)*10&%XMV#ApnQk^3z97SGEBbJo20<4EXU z#od4T22}Fe_}nFn+VwVx)`$9urV8xp(}HemV=5(&=s(~? zf-7nHZpT(gU(^a>KQAYok)g_DXtX$cKB*bp)9wKtR?1BiraloqbrZ)|5xKW14l z^%grYoZojw@6eKl)-nFt5?7OP{6SF5Do{hPsf?VtYo(zZpPA>`FyeHe_|9}fVal*n zvCFNOx35VBvcLw9%~Cu+IrW-8NE*RH6t6|dH@kk+;BWWxzw50TUBs~}r^F2P^e97S zlV})}UpWvVYvrn=b$kXY+~0^Erfy(XN`$O;`7jn4rG~Z>$#1Lw=kM2?s0S<9Ec-1o zYAr!KZ$C4Ac7NwZlblCpD=V+IXW2bY+V{E2>vrAf>V;w;WHZ{IsAC%79%uZx(ja#aK;%T8bJ$fd`5%o`fc&P*G zRH;}SCU#Zq18gt~v}QZc(cIfeGc!yE2U6Fgs#_>@Qq4H!|D-N><_t%s6wVS*dFYz`OQi0s)qzMIiJQ_f$Yt zLg+?x?3modnV^p%Q4V!8r8o4bpwz<-e%rQHIBQ*WRK=W`q;6AA7(oj}$tz5?%qw_) zyt1g?t~Eg?p_=)`M+T;&!7>U`ps+h#TycjDhO;v13Gi}-?)N@q-JmRI&I;EHd*A_E ztjDvV8MYIc3awT|ub%h*xI>UWgj~MP{gY< z81%L}dar%+84$Ho%$+(Ic&y&Z^F%IFPPfamfB-4ckLGtA zvW6P>v;gRcMI3=L0kBEKudNW@M?Hni2?oN#>P>e6@8;#p)-;`X{5_cju7+LblFO;a znS=K@7x^~DnJVV2%bJMM;jN2IVT?7!K*6eHXe;N<^##C(gxv;o1m+bqdOOJPuD<(6 zt2Y=b57JyUenI>udI(2oz&{KBPy%TgZn57!pfLfoK%Ea=NOH--Z=z1Te8YIry z#J^T6uWoW9%u3L$`IPOHh0}h@M$pQz`4RkY*Mu#}BUv4uAacd_ zJ>TvkFb(0wwoE?X%7a;Si%7G-9qRlSUFcq(?pUNZodm9-f4Bdvb+@t?vz&+@o$JeF z5o!LV<25wNb|Gsju~dVi`7W;rreByNUH5ja$Q)PIQ$Qn)YbP7_iT%0~s9D$+RZ~RD zcv(b+h*fq>zi`hHC4NAeeg55m5x65vQ1@6m^&LessjxJl(8)u``J)-0~n20Y)X!nf8bk_dq}k*HKMh&Y+mn_HQNGqL=p?9vGfvKDVp}PW@9^k zplCJQSwZT-Km{?c?5|6Hgi{4%4 zWi~n^*2e;QlkqfG$@T$OJ;QT|@ii7;1>~D?&aS($<-;?nFn0mbCy^yinHz)3C-t~g z*B7{u`!jSy?uu+Ik*3G<<^f{YZGM01koBaKJPxF2*65$V&WXMz4-d2A_*3fo zU8?VuMxa;^QQ`S`05T<`ovZ|=uJ*%E*(1IIS8vNc;zX>hauI9Y&OAb?7eHB%E6^54 zOVrVH;`)1*ab>-BMpaWmc2_2h=noO*J`~ECxPr%qwa{1(=I_EQ`CZu4L22Vb=wB4& zw?Y1ME2Qkh**FEAf;gA$(17SdC#4+p{f*ygP!kR zixcq7A}fs=gOx-AfKRr5+i0Two$|o~;#g%X{w}9KOpO_4EzB*&!CMoCu~vQ~^Gn9G znzP+?jb6^_#Mxk^Eb0%8eO*Ac-^elEwIsMP#Zkg6STASa%-k&K){|Oax%rTzt{M(=JK9@zgT|8+$O!uZu}Z; z2O6R_y_CED;L}XwWD4kkqG?(|`N~z6;6Yc+;OLqZ%op=(!sLWqv+_Af+I*QV!G_XJ zRiam?8wL*d6zCFQ5$)>_+X3o09bV{cQ*&`;$3>t}dgIp{;JL-@$-{0D)|KfVj4*fT zZB4T8NbL5ZQ6fAw{R`aR=s^tf&xf=?5J{}DSNA8D0~2$)VNFT1-Lx~h@@9vSe=?&5n%>>2n`;jSyismCMdll9*ww3OAAe^3S66O_EiUw#JG7us zets0{=wEZLS?Nj#FQbTB;%#Dz&6dc!l}SD~I^WT27wnUS>_F&#cc^OZibV;(5eBG~p78&EE84 zzK)YG+oiZ#{5ZW%ibz4d(ZG7kdP+kPPkqc8M|;=Q!RK$J zK0tHOUs+35x%rvuZDu9tYoe{Lu9Hjoyy43h@Ud6^d)JF^X)*(n3W`{#KOIMdROtZ> zIaWCtD3W?*FCGf5p-xoauNub{A{I@2*v_N|j7P(LludqNi%R~QtCfI+p4Jz(-G>u1WG^wJd+k?m# z7OSU&m<3Z=+*KDi^gHKDGJz?sl8sX)fFY#URZaHQB)mrG6KZdi`uU6(BJ_%{@l7RaqdA{qte{hD;}`FRh0!0{K)E=XUe-y zJv%X${q&z}(rFXBp!u5i2b&cWf~J4dnM#2mQ*t9G6$?YoKX@nYXO+7ADk8>k*NEpm zgIm_eE!n@rLXT_32hQ0GqJ#9T;?6K7Z^G0jlw=ew-=C}}`puIxrS_s5WexUwH740~ zD|$i4gYt$a5_uMx8bgiZaB*jg)Pyyw#GtU*zBt5TB)g8cd8=ko^y_Uu2j2i%Q6WYw z<-U{~_lcZgN+nfFLFI-$$R~X~A>*#UkpJQd4#%^yDkUnn|QXw9e?v^~|G5-Hz{v=N-Ht z#`!dv8_|MzNEUUch}^!MoX*xTEoaqGH@F?)qW0uW1b0e{*B6z@99IHSzzL1Wjf@g#a><7! zetPb~Q3cR$mO<_L>rtk444GGn`(9Quq_=!=Gg6!HD7cY?)qcC<@zub$nlaJK?c02F zfxJ_b1;NRj$ZRNQNZ3}>9D4a~`x(gYkPWeQxz*+JXhM6_xZ|5RL*g~sy9MwIQ2&Z` zA@=6S^n-UqOYnsMusDht-xfOs_Ut4ZCE$MK`nw?>^Kc?_&Eg;p%9T1{&CZpkFBvDgWrf4EM&E#TF-IJ=2A=$?LI<&Y$KW%dJIY4oJuZ--oVw5@6V!LX zQq|_rWjp4Cdp}3fM$ur2$?qbC_InElx5Ai-x%QNc8a+fM1h_O22)kD_tjlIQlfC%+ zq5R1xHr-O`7WUILARZpNG!=;Q^O$tXbSKnVtA@-ioV{0=3hBx)MiC+Y$|Ugm3sFPm zdi+0IGCMN#!ZMu0C0ltVQRNWVrH960-syG7j>kt#cV5{6lyNh9{9ZohBsj@pak1cr zeLM91uBp3<F?Phl^nR&&R!ay0>@HH>yMo;|(qv-q!riC^xuM3M+K>N}xtw(aW&F)IUYRr5dWOsXCTqvg$CsHe~od zN<kK9Re31@CdIKGrzdCGXY& zppIwA`N4Hi)_LZ%*h;aFQjR*y9F4ki8j8|VZ&<#>YvoG@oOv}IBnzn8$x z_Ifw;@*R?TYcQ+-XogR({fU}9Jj(Ym1xXf;10?25S1x?1@jb5l{XIIpc2E@(mIZmR z?_rA{uRETn1gIsQg&=C`I|K2U?9x~zRn;J3g97!h@e(PbmR}_6&s=5T=JC+VZ+Sp; z{&9;yJ|sHVUh9m6=dm#p&s#kQB~Z- z^M{f4<@3D(xSjo4rBL1VIl`ws{?X|^%g0&RW81#Ta#%(8l^fO;ACpYLcb87M`Q!;$n4f;k?ZKpYOR+rN+(rRYS^XISOUNZTkY!L$3`TgAbkZl7yQ1% zMvd#8Lv}I2TUL1v`tN=~HmdMC3r=SYt#y^hOUC$?M_+c$eb*!?LnQ#eOM$s|c>_u* z204LnqhK!R{juI)ZJy?mC(I$N&nsF{pPWU~^QY4>Nwnk`ozsob1kmwE=(w+e6Wuvo za={nE#&({%brHwo?feVh6XMO99WAN2yPHGCoyY2bIlvxkL+~*dGZu0|P5a0u@vXI? zOnGcNgl)jrv{xMM_wsFq{cP(nw1FS7$3+4y>0J(sFHMM~Rej7lk1G4M?kn{iliO*Su{2v3EKQQ%w$<$nchBn|RW8m0= zomeiAICr#G<+-l08MU8p>{dPT*0At5^ehHURmvYllZOIEEY0Fuin9~8Qv85riJLLS z-&(V-)FY1d2yln+{$R2Tv^5qM zRW00(WLPn!A~?1DJkM_p2l9jOoGKw{jA63qA@hkZw&jfe$sl+cyiYV|rVQ~Hzg7~+ zM!hT{8;h&EaP@ckyx*!d%}23I1vE}R-K`u4^p#vNl`a(>1FyvG=fW@rP>0r-ck(Cs zzz>Br7CD{i567XQz+y$@0!8Z2o+M%gK+ho|>5Q>kcS86NZCnOi3ORj6V7=qev6_a; zA<@-f-qG_$;_cB>3ORuf5+AhzeHQR@S$4U2*~AaV0~2!V6M)w!dGMJD9V971*LBXxX(xsT5BoMzS5( z%>CM(U{8`EHp1!r6aq1)`Dd?>NlSyyg^7B&b@6G(j{#mXHN3I>^bc%!=*wTuYz)EL zBNY8F=fBeinr;BlkAE1}fFK365oUJW;=3-qO|td;!S>}y3QFVjLM++A*!Y9qKf|~E zr{%`tp^@04B<#$}1|z1i``ORzyV#Wyq5t1ODmP?0CA~G|MNk^$biQFQxyGPS{x9SF z#(Phhl_r}ccLaw2?|076r~1>mB{?ZW8BwdG2Dr>>dfYCF#Zr(CuAh>9Qb`-lYHRIt z7)5JsrT><7G~5pb5rlC1S~WiM6{7Y#VzO5EFB7u7~4n?0{CmkZi2QDM6&Z-3mi zvb?UbRB_RYx}K@XH16JQ`pC#Z8s_wt>7aq%rq0q6nC8991!v0BO?_AP6IP$A-F}7S zdk*LL@kWzVpqvzTwyMffpg=Ur?-eVpQt>DFY-QbsKRXyfO@a9=>N&iUS-*L+0lKA< z6vPlt>`)#NG&WgEd_p>k%~SnAy(!P&LK4thZp*c$$wb#w_@RG>Sa4cb_)b_UrAgjy z)B$`p;`n+biK_USHfA62i4|=7Rl|ZRQEk6f^r9A6zu-*6PrQz?< z5y|Yn<_6rfj6wC+!}*`dDcTPd6lg_>5am1v@5q-)%;va-?{#>VVd!5Qgobj^!2O-& z42$@XYXzLXHo+h1HbDiz^!t`;F#_tgGwvs)>uHLV5QY)nNw7kqlM;f=&zDiA{i5EB z#u@P6a!GwC+!D(+DH4+0F3gwxiVa3F1$)I41(Lu1jiX$?ofS#$NiFzOfbCeCtdo1x zS~9(7@lfR}ptA7uk%zwG6Np#;a@TtBA-KCrB=W#8q)wGoV_kq@^=GjF&Gw`qyYzk` z``Ki((te3XJxM56q@r^e7>MGDmr>fxZQiFt_GNSGkO__eI>Iz3v?t|JS3Sog2dP+; zZt99Q-1cFA`3T3G$;aueX^WR?cd$lM6l2d0d8R}aq=2YR9I&NmR+!f zzi8fXn=Gt&a>5le4FbGz-IBt|3vqHupteE4W~8OO^UR2fA(7sc(p>z;|NLKQ4i~BA zTu9aPY{`&rIUPf}L14 z8VP=(r(uiG>vc;XQO44nfpI|*sqqK7>`T1+OC0yaBIDa+8(zrYZWrd^(XuCs537m` zMV#Z@gzxbF1f?GoS!6@85Eo-pTL=f+g|)27W>}1Tl6YvPFTa4M0L=G2)I<~)Wnu11 zv_jdTp6=vCh5fwR;d-IRxV0o`Jj^IfaUw)>JH5G-Dx$&?wj$uu#+Y-{_%>p+^`KVgJfY#U`2H* zFesK0xc_EwCRb3ejU&vb#T_RW)5dD|hNW6=Wc`JqOS+17N;<%<(^b8QIdc6NsM#TQ z-&Pa50$weOIgtu>YMQEDkmSEEuBl)x3AOUtzkD_9&rTV7KVMbMSTz+qSAHS{KH9i9 z%*yk|$2I?{csdUOI-)K(@2Hq|@OYz{P;C<@F|~vCv#9e^!no7jKqZ5GiGI*iT-(vz zXs5I2q*|2p`9Zy4<=1+^IN^SFeK-2Q14fI*`&)~FWlhKl&s6sNvJ@SEgd&wr85aJP zA-b_^x$;CV z!~ZEVaiwJX^?Y0$2>sc#k6U=F;_QLgPp4Qr3`1Y{HX^PFH72DqEtC3_bAk#K{}uMn zHX?#YhAzFn*{-u&wtt#_PFOb4n*_n;>d`4jx!T3pfO~UqPhS1AG0Dk>P6{DK+9yS} zW@^~&$GhjOzb{^!swAFb2H8xmCMVoKHtiiv%)qaMv$+0MBOw{AxO8T@VLH2ab#+Mr zKWJ%nsv0PU8Qz%`%iXpgS6nppD8ZwD{DEKs-^WY|faY6VkWJjwogmqkEfh_AGJVzK zsc+Xaje89|Mykc+F0G#4!%P1@o)L-R1!U#!zOh-HUu-Hbf~CdM*YxjvcB(1^>~`UU zN6Sz454jY0|9iV7HGn5r?~F^69lN0SCmoW^2yI!rk8-NV<5wSi^y7#wCwSubj-p$B?YvhSPX4bt42tmw zrK2t-E|a47`QD27?(dI7UM~^|y>D$fo8TY4nsgRTg#Ue(ed8vV>iOLdrKyvE=GNKe zkYwwn7)?7qM9g5_J-q-Hl%hOa6xGtTGxn=v`@h%cN9tkT=0D(W>Rw2_n+iy_ZFm@8 z|4OEG94-GD)!1!6|98jme~N|M}SZA&0LFi*DWi^rDXaNKAiYBh|xyyD|_^2@_M$wK58? z+YRII-AS|St8?N86#xHuD=vZ#X<={l_BvKyqvCYNHp_eKyL;Td|AcU4IDAuv$1RLB z5y^CAEdt@2Mk$~FQ@RPf0yJ^7Jsh_P^Cr@gf`q-Sw*RUL9PekT>hV%5Y02Tc?bWSk z#&#a2y6S5Gj>VxxfXj6g@1b?Qu;^1Rlp>Y)6Z~&!)bxO6ncUi?tQFP*f^>zRSQtlYG<2 zj}2%?BsFj+X%|@e8OP(=App#L<(bZ>_!=y1u+Uk^x|d z*8Q;sf2K9+v)(iSHg?&W5}f_Pf9=4jYviu&A}o9m_+hL-9qT+tAap*2s>4n>8P<(A zmIZIl-3z@q2mTSJ@Bb(ag>nEuRU?380=xL78j+nz8d6SSX6w1|ZE5b-VwGE)_t>BQ z#we8R$O$MHSeZok@2pX_t|ezP);r@D_gd9R)64olkMY>8|x3Ae-yki zfc_CXxSh|izT!z_44aHCz}%~|8O?LsOQj{(=r{vzJW}{X(m%H#IXYp0^gnH-G-Ux2X_IoD|Rbk@qJeA(YMHpL+W9Jh?kC255N zy>cgsW!Zi!HSWXreH5&JlzXoF{!g;(o3XczOgX=9CS(gn2y8_t-zHB4T^FcHBK)ux;HmOo)lrxiQol^hF&ZKHkV_C(_fPvRI{``m-r*b?5ISGko>>19s zP#?2t47Gs zGMn69j3$?s=_b@*zY5WRd zsLm(zxiC$}K95ebGe01ekF^Wawu0IXc;OvjN z`3ozjFL}?W<8)}SO1!Nu!N{ucf<`YbP;@(m(=T7!41wI58t$nQF%j!+Ns9y3#oK~j;09V(Ip-kMzD_Z&~&kve8*1sH{71AWx z98#ek{Oo616*3fi4!%LW-^n3!%pT3omQu=SB<$~NKpWE{KJwJRE(D4BdU4n*WxeIY zWG!`ETo7OqZZ6T8KB|P38DEz@*68y*oa{3RteVQFfBxvUQUJ4K;sC@!TDiAQrd;&kXsEI06VLEp{0UfRGjS-K1 zYSe&-U(!>`ZU@y5Lo=p^MTrxNy{1K}SWh$eUoS$lFh65lYg)moK*QkaBsdjVlBoMP zokI(tVb>4H1^RwWr++b&thwDIoPa(pNVoqI?QT0a?RO=qdD3`jQ2-N&ZCpWnCz_x! z(plGtd9wyK8Y?gAQ7`#xrZx2Op??n|nnFGZN16XzcIu#Nz4f5s*TKRR%heHfJ=O1z z_tN^@+v@YD$L?RJ|79Tv-5SW>334Po><3MGRua3eWX7&Yi2BXzF%80g{1x9WrQJBJ z&bRSENrUCl=$)}3*V?kwgK;+q#RlniMk^0hB6)eqopR+A+psJaF|-9+%iFN0Zh$!? zSsEUCwo2+C=4)mgX;ubRK&k7#IVTxYCEmhI-Cw9NdL;PTSKq=-Wt-T75MCz$Fii8!8$h5TL(TY6#C4N!3AKgE#Mo@%XC9cWC z4paiyFqP2`0v`%uoL}AW#GhM1lc_=55c%tsKzmDN7<||h|7+vzfMDmg#E3vkLVL|Z zV#3<`^J&&UepUK%$vkh5Z3)!om&L|}h~wqvuU%jDouTJ1SH^VH9vd}|y-AbSPsQ?2 zeGuqw^xDb`?x#GQI@k6;82Dd@d-XH$unH|kxXs+Y`DZyvikiJ_31{honFRv8q_`*M z^;?d)?k09Al|*k;h{ibS4W0y3=N$bTRb)k>QGE)4swMEq{@ zH@NHu_Tij|KBkz@*uuT2&Ce|@GA*fLw6g>Qg?@)cgUIn;)bFyK?6$#2=()NtUf-%fT zOXELk%W1A`77M=K?5`3}&NFNJ5b37a9(f5S4Xuuu9u&?g)OZqgaY40cUFc%^T{tSJ zu#LYut->3-g)>lYPa<_Dbik5 z{mCM{c$t>o&C&dA8w?|~d96K0|8heKR^_tNJ^csfln*1=%<~UMFz{}{Gg-|1Fk-!# zvQiL+Ll!S5>wJ@4@|BW_bW>xy`A24AT7{Bpg!y&tcD;?MlQZTVcT`}ziY5jPQ`P*R zTsY=y){TU}8jO7pRLAL+m?=h2pydgJ;^A@(orSJ(stU|2kJ7B^en!5&NGNJ;Eh&LU zzw8Bv)oF<1t4^YbS9*I-LTk8L;N<4UCNTp^JTZI~(rZCBJ_pI$jGbI>W_895%m7^g zQKyCG<&t&)x8*QhWzjX=Aj`eHCue14b$f&;@aUgYT*K0n(Y^Vm&(-95LoPo=$dESe z*VHb5L{ET2V%PMAArQL83ira#=B)rS=;MLpAP-dh?(C1*LBFfx<$tajn; zaZ=u4lQ%4S5ui7*E^%9lIQb6W3sh4WROOW?PAdFB6`rNeYUf+rp}S9+jc6`P?3C!u zPZ#eI>Y?Yxg#EgY>ADMDkPBz-Sz!{wRBlnxW0_6Id$S+ADI z^RqKSy}g!*YbtXiApEd5Ro$%Ro1{&a0s(qdg#QTP^zb*vYVVy@c-K0|luKDQX*T zWwQd4!ErH$Gl2;Ecy*6&i7p2(@wf6UaJ~yuCfr>25x4j8Z&t>^`S484BYA@{mCC*= zl~p+~0lS9Mr!~GE)?D)xgT7K?J*rAA(qWL!QwxPMDr&^g(an*aehf?@Y~t{X*9e!f zjOpyVk6fbGKcWkcxVr(nA|2M;iw;Jl8lWEq+~nIvwa!P_W!Z@isVcLVZ!2k+(VKnFD(_40nsK2C!9A&w-BL1|J?Uh7Wm>9mDuUWVBm@ZB3Q z!zs$a#8=W$@5RweVIR&jYqZ$f8ii>u4l=>s&1%AN&E=>OJWJHbz5$yYb4KV1sM ztWh9K5ANCY?k$aiuFZH8qMjyo`^84JK^DcXyc82CYLuB}+0K{n0f$f-6Jl6f&mqYr zQQ|{v$$fkc)y}$>L`yCMY)CY+x-JI!8t#`XHH8md74Hx zFW%UUQ(SKzunXorQD2Y0Hf1>$S};+iLUSRc1;ntDrb)u*gVK_WH*sx)*QN(*kf?Y{ ze>vq1p(@YZgM&faXF1Qf)i2wecgPH@K{4$DFFkk29G}o$6;1_XQa^qdG2TAnq`7(u zn%P5-;o!#1N7m4OQgi6}Z-x6Su7sR5vTWw9l6T2$%SqU3rzFMEks3s2_2UM_uZwMz z*8udni8G&G9WF?4v?0UgQLEbo6`459Fz*P46Z;=IzG zgP9W+gi(&#H2AZycC_e`;tD^u>U+oPh`ox>hnMcYZ{b$j9ujW6$R;$nj7q;ieK=8H zAtw7m;&+*t*WGp&x38LJmqLU-MG{>xkh$zIp1K#M2bBNN)LI43WxaSjTEy>f!O)Xep%oJni7EM8yel7|=LoJB*~>F$w|Z4B z$`C>zoa$_!7#Up9FYr_?o#WAMS=5by4S#UJ)arLJeo8aCH<4i+DqE@t#(lUC1)3{v zer1zVb)MSko@_J9%glhwL*T`>4NPzY^Uz zkHGKNIV~bNAAq2~p`a8aIClKy@TPvPtu}$w`Df6iWeh~NZ&}`A($Fnx-WB~gcM>TLoF1Cmp|+pkb(mj)h!1L}kKc)j7w^a5V|Vjnm_ZP?4o2&y z8dbpL%o#u}x-s0Hd02R83BEi<4nrvESgQ@kf_y2n)kXysq;BV5nO(6{TU5U3UK#%p z#ZDXAoN8W@avNLlm)aQF$e8Z=t3Hg&MZ}_S%tGqJIECggs z(`|iRN)Q!>D)Li0-MN=X0yK;NJ4dwpc8Vvod>WPZzIQzH>Vlb?b}KvmFJfCd8sqT7 zifpr|+Bbvb{5fdf^?qADmfaADijhZz8%A(2@6U|XQ1koVeskC*%%?fp&fcL0C4+W~ z4Qx_$sF9-sIMR9q7?7R{#yOa5wuRQz+{@QYy?IW)@@;M^DD$XeWN{`U2kZ1+z=UpZ zU3tI+G9Wn|w&4_yk_bntU!O$X?Z@xTCRel5>}_mKW?^WtEoTdFQ?W7){kJe+JFr-V zmce{REbXQUbqcE}FIB=^cRAM6EI`_ro}(q}kgq3Sy}9k+W4FPy9^4?|mu}|@IDuCe zANfoJpF+svyn8N)k-()83Y=s&DBz?94=&Z(Hx#6Yy&omi(%3&lX{n*ax~o}DkXbIs z7K10-%f)#L*PAS?3`PxNFCMj%sX+%M2E*$h0>HokZs2I{2eDwx4*!R+>6c`aT~Mh1}+%Dd2+W<%bDkyeI$-Ze`7BF=;Q* z=NxHQF8OLKlFMm861Q);rjU!VP~M8r;ct{37wBX0?|;e=gR6MS1%3Fu*P$x>Oj0cy%Kd%1 z#v=W&t}M0bmmnAOaTUtLxr~Z9Gt!Q=H8Ds8b>8ay|KdOU`mb(vhc=nM_%`!G{qAye ztSorg{8@XL_mpVqmmVnpNL*DNPk30n5`zxk>^k-x{dp9ddv&>1Bq;+(@=aTMJ}#VI{Jt6o*M^B5&kw{b1!WhN>yTMlIgvaXyZ&ol2;p-xNdGL%cZ1J4@)>P`a_p7Gf z&Bu@8@-|oku85Xj;B)(acwiRwat@w33uF?=wp9h71|Q#0Q*ea=<_%^cQCiUunB$!X z$`zI7Ju_S5>u03MMpqd@d;n_h%mk~@`?mPjiKsZsyF;#!dh_D zRQ@4L0YAjzylFL3-m8S=H`F;N1v(_TnO!INkS|t|EWjx}<{^*3#x0y2JU? z@5UeNUzf>0d|LCW2;R~aBd@J-L8l0L#OhUctQez72=IhKu&m~Tb^#ZMfZQl5WNwUa;zlrr{XkXb86Sl zDXzdpLtjZr$wgFrNwKe=A|-Xv`a|`gOn2NYr8}zclXAk~(+^xHS0Y^Z>$oL*d(Q-D z$l{zJ!Oyl(;Rb2AtgN7S?5o9VVX=>nL4;4bIP!pyDs5j`!===Y6fajuPUksS8Zr}c z9w0#F%u3qH@tq&!-cbYJ;yU&L=Q}92azvVko3Hg0N4%01R7fXGk>WxShvsc=3}vru zrH8Bzf(T!>-?m-)j@t!7x8`S`PJx0g@^JTl2lI~=4F0%816I6!I|$$jkrxTh-oy!hbZF#+*O6mv@3oolG3yl41ZRNnsS zT$|PlGqw>L2JUSU(Ate8axvhc-_xvXCR zE(^nV>+mGR2JQs_{)^hO{rsUkbdFm>YI0xi=py+_!_0pPINU*LY!bs?Uc8#3Sa51{ ztyN{}zIb_<#0&{`gYt5#j&8F^v1ZeL=bEw1AiOZkgL)^Xm(%?^`Mmq478Y_UV%ma? zF_qu|C8k~3HAq`7{#YnE8WhpsCd(Tq4MIAVMs-KoIGdvO3`b>D!91SfFCY@??sR}E}+V@hY`Da`GEV@ zZmv_|sX%%6q4-y}A*EfVnC?UHYGJFv0~EK;G%PvH#viAs$JR|2ia4@v#XqfKoA}ze zvW?e7XF6M@5KOddXd*y>OB+J9_Pc=08h9-^0qxPQ^#SKHCVe80S6R6^v$^PhXrSp= zTc#z^zQm#U5Xh|jn^JLWH>a_H$xG`UvSb0C-zhbY8g!Hrm|~Xyy>JNjPXVLPQXcu5 zv33Se2-cEb4YQ7+4E!G>kIzeU-W+)0p1zH)eW;`;k1WQ8; zAw=sIet~C0VvoNdg_O6KD)Urt-iLJqR5U%bRl|&x!8fGbs2FYM|WK%?X{<+#h0P-w;$6=cFHwix4GdJdF&zRfvK9-2GB ziha3_wR14VSKo}QL!v9eafFUC{5UX< zh2zL4E)OuAxiokXL$Hjf62AAG{OH}W=3${J>N#^_E2{74wvq1UZSaSxkgxT*d zasXCVTwbDjypCfQU@hNq3V)KCZ5WTL3|0>oP%Tn!liZZ*4d95hSOOQ6dq?5~6nUto z&k&IeQ7FMJd7~1D0QCVwfhP&_o`EQ8>RJ*JX}-u|yk1==B=T|N&QZ1@mRO)QfizYT zo^y?${F3ZPYH|Fd&> z{gXuO9nMzT%}a5Vw7YeekNe#}o78*2ndnc>>yP2lpNCARR$yTHBIxJd%gc<{QZ}nz zdIVD%3`L>orCKtgo+=00mIJXLS+~TfZZ*702=in`ov?s=dyfZKt9%nkvz@L`ufkV~ znR{0$qI=UMEWNMIwOJgHIUKl(tLKQ&yX{o)xn5QcM7Hf@+XfwMw8 zQQlhg1qY9L2mL5t0Qp7|O*Gb~1`&n+WU_m!=KHRdF^slkb`lMez-pb>X$t7xM#2g0 z#X4*IvNuis{!^rNu1fpR>SY{&xCFnK9W%`ibSAxIz8^u~yexf&)twqj>|Ttz!OiH> zD3{F_EXVC4-zi}dCt7=xi#1gEgz>`V&0(;)Nhp;TF42~80Lx(00%;7uOLel3tCoDR zsB|L6L(Uu35MPfHArooOHcYdgR?#W_;E2EA?$PrYss1Nl2x8i3KGbtHc9 zJRG0M50^gI8X79xvssm1+-D%b?{=sB2C_Zz4f>r=5Jo=IlJ15)xnt^_+RLpbJ%;(` zm2rov3y7fK4GA$Pk?Z7ob+>IZi8BJ%jWH$KI z?2=excvguQLf(7FzvSAXI1T6~ehiZBREy0WLXh#rl!xbo3I&OHrcM$!MIdPGRSqtE zLtK;6R?4f-TTf??hGYd3l<=jOqNenbZ#t=iP$uXKr;JTXpKY)k2&%#Tq(ZAhy!xJM zxR2=WiXm?gRh^SR0Yg8;cmgAWos30Pl-p5bs;wf)wfa3PAFy!=q`3thr&vCb*HwoB6hjqbGlv=`Bzs&`Ya+?ri3)L`?6od}J`Y)Oq=G{qUDQN?QM%cAA|Tz8V7 zle&>-SiA3qSEq;r!(*=xsnaohcXlmOn7XSpKKj@UXu~aG0S6`2aMk-}q6q7gaQ$Iwu(#4!+&(ZU-WGRwqmO=SXT4YBnmjnrF z#GlNAU6hB!cwRA_N7oqC4Z!M>kT~zSyVy)t2QFEkSaP>d7vkmI{`%1q2fd!#UcjA*<^ItV&gr3R?iM*cngQYo!`#^dh?BB0d zTHdBui1mycV=Mso4^O6VKuR|B+Pvl8&G-Tb{g1nN^g$2>g$oAgi^3cEGLcKRa^liE=kO|hjKr3wfEqZ@PqJ>YisAd;Kq z^kK%$xi@YEhhF>ty_UUk!Wo8(#vWW$TD3!e&8 z2S&Y9AuI{{DtSjJ@Go;$#Ia!kFM0Gdg=a2!9Qt#d#(AJIk=%OTo7$5$V53KVMPu!I%8eaC%n0N&Z)MO>KLt2Rk^z)_(QlAJ4p!Er=h9SVNds9o=UzxTa}Oy=qLU6ValivD zfxy5Ze?)he?k$}M&xwD;{iP6!Ov;gyt0#{~@lQV`=!W7py1sQZ1-y_aE*iuaL8SBQ z^TIVSy+{5|q+1#MTVL4lR#BQ6j&m<_Jtv!rkba)Dt*#$^85qJ2c)u#5X1scIe|23r zr}&giT+@G;<)5=j~@ad!j4 z5JBIROpdrX@&}ntYK&r*xF|*U)<8i)q-4Z$gfiyaBaH$rd2~v6qHMHNizkjf{ ztS3sdQLk3wEgW+SWUy^n&Y6Ln%xzsWU=O6FEJzjDRAv7#<{dJa$guWs)3#uzo?n_~|DP|1T6XXzbps1>rCYVak8q%5KYjG|*LmE# zZ%FJtEOM&RA*DZA=3$a$!L+KM$G4X4`Tf!#ybKVX`78YB_2>!n#lRWTM0Jw!m|}7R z2>Yi-9*eS;S=BHQk|MG(1}Y(Eod%mG245v^-z7)QG5^BvyqILtLnoJ7$%yP6q7Ai1-5{Z41@;UY`CCIs*MMo}##^FFk_@=eL(Aehdqc{COz=@s2YZ?^0GB~(z>i{Gz{7w>*7YgBN@{VYta$J4oQX8uhi zS?`mSL2YWW4xguWCFvKax2w##F$9^xUg~37qf@Yt0C3#{iZM1JH!K3_)`xYVSs`o2e^x`VSB^6`Bi!ft#v#7J> zrkIE(fOlD$qv*pS2I7ud%gbQG{6@Z`^;<1n`; zVr3gahOI7T*$Z0DVumZt1LJgx=_yh7BcVU+q7=R-DskU&a1b@|e#dIA$Ac_Uk#XQZ zzHlD+2#65GsiMp%mD0}-Qq3H5F1rxRXF2hi`-1!iOr$3+PCb$EwX+_c3CK*K`B+hH zl^;q#F&SbW_bNa1)H*FKae(Qu>NY^S?w|Y?DyV7%l34K``{Fglf?}0x(LNnd)0<}g z@-)vWcYlbyFMub{N0lcnRCwnb&!qZ*lc8?m5umhHpN=XjNf9VB(;itrr380FuwuLv zn?o_sd&hW*)D%(~uX1(ElUo+c43nlj^QIMlR)m@I4?l0#ErfS@Fkhmcy>-{bhKBsL zyTsx&7mI#8^5`{IMfGv*L3R4u+r$#`CT2nEeu4;l81C7quHbLGGgg1U{wv&Pn(Fa> zjoHc33ytxqNrBMJat#(iF+Yg0J8e<@I?LB~ zccz7i9k*BP$ zKD}@N5R^N$Df?JhZyD-39BOGtbtbw;w!@NocG{xYTc9e?(|dArIk_c&kN?k%jK$NM z*t3=LrRmwn=Ko0HeJ*&{lP^b4e6~TqTG}W_b8{?~cK20R?Yp^1Q=UtvJ+bE}R?{io zPS%XQ&!%^TnzQWVM^g};mLvA4N3-GMuDcH7YH!L^QelPlMLHHJMFPD{9;1?{Td+HG*UBSIi^57Zm&E{ex?3!9JJ88 z28x82z)|LXZoj((af}$-1Ew`pEE_P;jpW+}@=jns(kd3wBh=*CF{OZd9k^HV9{3|o z54ODlGx_>=``pjc?8HUw2|WiEAiM!pX`(UT?_uq+=Iy{x;B$5)byj?B@59FhSEJnY z#$|M(CTl_YgHw!Z6r-!u@Sqb<%`i8khebfJQV{_VjcF~i?8ia`U*>K`Wh%#~&$=0W zClx;be44v#y)!r$MZw%_v%1FHQ?oU9G%+fAHepc8NT7J#m5U>S&$BqRKQ(Lc*6g+; zpRkvCZ(yifFDia**6%yWG<(DD|8)8`Kg#!KsRX5yh2g~lKf`2%3xI{5^YNY+tsWCm zw^TN9AIOQcaBfwT7hh`vg&j(^*%cXzM5gS~XcH7ojwQ{(!`T8=~`MC1~1z@`GV;vW4HhG(HN)|L+a~Pn~v}JvlCi7p1+f`t~+U0)aVf@IG`E02uw!N@ z$Z+WG?w!a_XEI_}FTx~?=F~Q#MC_b+71Ocg%rl{gkxIL9wFi$M(od;cQ*=M96+|&c zP(mo=FH*nQ778%KmAf{Z73aa%JS)FM^Ou`NUZW5DTQ&!3C9E1QUdcD_`|MKC=%VV^ zmKz={P5oeW@$5=m>t^su^b==V`wJHsim+tGeZgpV>y82z1TFI7JrAtvPsNQZw3w6Y z$R^%iCo>&YQHLJR*sS7SBqan0j(TmKHR(j|b_=3|T=pkxs7JA1c8}rTg>r)Saci11 zm_}sfLX}`9h*fGVz?X8xAPQ<*=UDX}%DP%R(yfDkPID!%*;X_lU-s4-(nA^gv?4lh z=6kYGU%nmxY}sV0SY*;fao!{e&F-`Ma+n1-sd-{VHb)xv>qTL=2lk|K=NH(VHF>_? z(Xw;`4Sm&R12I(=2<FMa5lUJ$*Sr-diddxX=ESSTr>ZW1<`~ zGOveBD8sG`K;?;U6(0So9tL!gA413OAn9M}8EPCplJ~Z^Ev(lm=_Q#dQqMR_b=R_i z%;b2Pd5#kC&azrhvG>lP$dF0=Q|xiH3Et+vX`n(5La^I0H5SVaMmn`E+BCcJUeZ0} zNp=)HSz>``maXGs(r$?aAI(mvYX9e|t4vSjuF5x*)DB#}d_HcWN3r}2>!tcLmMfp@ z=W1iCELRV4CvK@1uA$N!57T4Zg5jwE&$ezMHtZrSyHeG3L%vKz?@mf7M{0IOm3yQQ zUEd(1(JeQ(o6iz$F7>{yI)wQx2;>i0A!xaj%SY38njRfP&7#dCi{fWT8;Vz=kv)b7 zcC@~MPTG$2g_$u$3x-EXE(ngnF5^^$+6I#!DkRf^DISzJH=cMYFC!VsU2YGuOs{#m z#(f8S(9hPp*Pq%xRoSnNW6E=*c1NY__{z4P{_f}5dNCd(aIRH%X71~{qGrk0H0_>N zofhfhv>jZzP(rkmP?p*5^WXT;-Tc^mXlTJ=o}c8seHIT z^u=v`lXaUg`PK-M3Qc7xYHZ9$;ZxS(ja$EuzdH{Sw%#zHx!am?&E+`8D&I#3w%dP_7|y~_`nBls2VTYWYx zO!O$Wt8mX4mDUdVIRSAmH@TH4HV}ggi_3^YcRzY^?qr4ac0#CmyQ{oMjbv%7Jr{mw z#{Zp!GNZ0Z=Bq7!?VXU%ZX%AfRp}*C^tzGa6n)WmyGcL$#QrwP%Y6K}?>(bScT>b$ zCsEPN`ubYb)52H>eYWEZ49ERk73Rf)Q-w!`&9O4RQjDB4Jw~$#zv<}umRPFVPdpyR zs){a7IY!DhXW`FAW~Veo^J+3f7<^hPFEhQYUApS{U)ldK(#@LL9jtxV_4E>%G(XpX z_8JgvutR@uqUQfFaD=nAqA=n6hX4MSVzus@`%%m61Ei|ZgkytE*&srS`}7X*9n3+HG7mC+KDY7)ilOK3@j|1<9w+hC zz0sTz^bnbl{H#8fnzuZoxij6-%csRBcOipE zl!O0t{mrm)AG))Zx&F?@A%|?ft_S8R$9lcXAz#E;CycMxf_AOMO~Rg#?{)8WzlD7f z_39oCwRu9WllQjuSFHqpD59Ca>BT{9t0lgf1_4&n-XmV(J!$ zN$2F$l%yQ0yYUvm)nD=OzmF-9_GsgO@7RU?h7TX#k66`o1fw&kzE6J9cWixjh_t8G zuvwGkZeh7A^6>B9-)wjk@PBs_?%O(p;_f}8n#{Vt;qi7xR0LEy1Q11f@0}4)q}QQCgiwqm zK!`MHI!X};D7^$2I*hbH2pv>NA|(Nd5(ohX5Eu-hN+&BGs)?10Y~H;P<@*~ zVWTk&rrFYI=bfZNzA&+fcf3OVWv&>S%yQgw9}=bx8$bBpikd{)G*orBYK z(J~;}nQP7V3RKViCBw*G*{gWu(^Q$yKcT(?yFx`65i`vBHM6VPvAl24;jE3Dta)X> z-3~@|bCxC!9cQhc6S=)nOAyK6TDvC=72jQ}dDE#RqY^x zfcMQ;5;uIJHw^YDchD2j`JWbE8AFRQRA;N&Grd4{>hQO#YW{mu9PD!st6#4i%-W?g z?B(&Rzq%JLE379Cf32)I9@q9>IQf=CNWj5Db`MnE;5pjj@6mz1n=NxZbUunOy=aw! zTM`InV7ePh;$x8~VPMCpwHnw;?E!D3nozFRr+6)*Qub-81u)&U-wUqImeu5l9TDT6 z8Vy1Qh4dd7)vW@2m`f00skV@!qrXx?*x2$;3AYmSAT^6I{7GU4OyxA)(ZOwM-p(^? zZU%2W&gUH9S!9e2YZx=e9tp{k@;%HbD&c!CmMU{J#SUC*R*Eub_be2q%#Rk4QstUv ziH=vea#zw$mt!rv&pf=qxDRt$r0GniEU8tbJSt6%+1VOofF&nxB%0HdEfOj3q1m4W zbID64w1thKcqYu;;!pAbS(DifzHFa`FkWHq6-Gm;l_TbIs|Rb^gRW(Wgb%BHhTh~e ziAyS^!cUyQVC1G`mPByt=Dkr4;@mgf%>)zSvuT&WvCJ(7@{2I8j-HtfFHt9NY z@Q=_lx%W(S*VERg2kbnBcq#o=N7q}ER~D%$BWq%hDu-HG3r5kRT$A_aW-Yb00kJXe zIwGu82)&HT?D5Xt2qE*Hg%3jGju!hNqAewxi{!6dgh2;%vmIikMp|MZgc?FUYb&kO z80)mtgM`SSn;Y`Uz4-f1aRpMTAv-8_{UNO`I^Q{9L4EHXFFy6i z7-s$h`cWYLJYAC|?as9bpgp`ucIv`dw$l%h`$g1bA)hsAn<=OW_}$S^mX+T z)=b9QkeuNp11WTFkaH?S+@*xd*3-v4KAg05Uv`TGADDTIb(U@*SMhE0#*`vw&8db3 zNZGvz1GynS$v0{_`LuM{32pY>?nj&8D0l4Vpb7;2co1#RIiYS*q!eJOHMZN5X@B%E zzpAZDX*N5G@ObU@%n-+Nsf}=GI{VB4&eC}7v1IjNzA)C6Yf=8W@T-Aqd~YU_oExSk zJLJ8`j^^hI8V$A5k2)9K0SmLZ&5(W&R7&e%#<|gel0H$0TCfdaIOLjY!489tlZ$_iv;wZa!kWVq?RM(|jrUr@!giCeiWI?jCW zwjbB%a?+7+G??N85=u>TpbFf6Nx!_Z;?wjhTJ@UhEYBk`y)g$*woUO8GB@$A);u97 zjJDbx4jtTu#Mz%&KTRanl%HaF=$3M`@G(IPnD=hcTZRfUygPb{r-NhBZnNMm~m^LW`pB&SIoIUoJIfjR=UFIr?MA^Lo_Q7pSbpidvS4f4l%AN8=pJ zJAEM!_9Xtak;_i~Q>(Fa!PV{TNDiT`r7)1tx9tyqX`xpWTxu7ab9orwj(g0#{>_JJ z3<`uBLbb8mc5c`|3&Qgynk_yg%>lbc1}lY%c&Uvz#v z6c$$sjo2Bf=a$fQ#80vDzFL^+9|~8* z1%r7aeI5ubpX_||UpIzfWubGMSUKXoRb}%SyL8>F1!|QOX%hHscp~k_Cn?7Bm3sv4 zw&dozZyQpyWgsx1xwCuvo?cEXbPTU=uBC%b(G2IhQKN4Av0%*5eh+(0PjV}rplHHu z5*g=#0cCccIS~Dm&|;F4XJ2|-+ytY%Dk7uf`25!Qy}qsS_ScuOQhf`ZV9TZuH2y9> zkkybS_Fk}vN<(+RqRC|PJRAUie}F7`p6hoVEsuBqY4lZ6F_PKpamru4zNS$3-iIrYeF9t|V6yam35 zxK6r1Q*aF%x<bPxI^4dct4 zQy%5klFHiD5FlcbAcL3}xZn4?*F9DGX7m*2qRdkYiB+M8lwaiNNy1q@^^W>E8P)pP zI@CG`?{6}}PtFLz_j~W}yf1!C`fx_^L9UyCU6XWr3osLD1G)4M!4u}o1 zao*f(&0mi@x0SrWU?4?w7U;Ua?u1Y7-?q@KU1oU9o2a*lLW=3B#-#yUIGbx5`xEbPAh{0%;J(NiKA==jf z!alkvC`&lO7$BpK;lw8Xen@H9hVhPl7}R=Z+L7fk7%2rhR^E~tg8eEStOE_Wqy^3WGZ@=UW-5D(DJJ~Nw@Fwc@0{`}S};m-H&{U^XLF|6w! zucFQCzBRX!oBz4^_fVEPRAR`=j1%~uTmBgZQ|_k}W&ryCbIU)sPoiI6RVy*4ZLjeE zfj@0w!?Jh@{-;va*;T_5M0%al-(qQ#XAhrBm^)gYpyXtE@U*h2(@*^Pe53xXRlGw% zuzr)c!}@Ow;K&=QYTAqcL7bkjBt(-nVKJC zc=3m>r`kCZ=GnIYR)*wwFIDTHCWRC&p9hGb0_qtPTEf{G0JC^*QWmQjqkQoJFAkPik`(9JqWew_=Aci^I^7FjAgiq9uzhG7?rEC^{Jj~PR-`@f~?l2Z2aK!vz+0z;YZI(~q$t?|ml zrZClKb?swruKhL{1=|W7s0X2dE%PX3{xYs)Pl_jG?JpEj(8XEu;ElT2NMS*Q{Hao6 z6yb~K>+_yP^(^_Rtpoad>vrEdefTApA2nh9fLcDunUI*e!W;Im_58rgPo_I}fTRHtGRp)A0aF}Szrthwr7*sfQ4|_C- zPE1+Zlf1zb=&MgEoTNsnh%xE;xe{;W8XFs|$AnWe9VoE?ql~`lOm1c|qlKu0-4~I? zyL>|W&zh{WU!y}f-=n1eTv+xu;wINOHcP;`?sq$PuAA(De@op_aMmm>*BDa99Yw5q z2kyP32NYlKim2|=K^t_wqV2o-hwnCv;k&qb^PSOxYd|3nRH-`oo5T$DGWN(<7t`!o z3>R(5tbWxa+BwdzIv_14#l!DVzMk2xZKEGE9pfDc4Tf!+5*$6Y$~8XdgPX`aquU3+ zOhF^Q@rDPtsAPD!P?Jw|h8b-G<$KZYZo-@ORw5nD~gfDC03r-g=eZPe+8nY2w-)yE%#s|WP!J9Q?5Qu%-N{v-O@m&DIT zfbAQmHqbM*TkhtCrJNGp0zY1MiYq4 zyXN4Ta2b{|!9eEAtMQ0QO>Gg+<-OBE2G|r*pFkCvTB;F_uOmt&UP2>gOPuZLY1c`| zniiE+u>paWf#5F8+>tMBF8GSo+5DH(6<6I=P<(>oM@|5!!>R^O8X9f{$%7v4{cfQr z`6-H$xeFaU@f>XunYl1O(S>P2Zx)5F)Uab~Kboe8AWz!I!k_~!`*)eD>8UaA)7P_C zGYu9;;`5Co=x9y;o2wuXs%CMCm)UjvbDxIs_m{7Y`We`heNHNB0CLfF5wiK2PYJIu(vh(Q9Ocbni zVjiHD>H~sh6;XGVsnv9<&hQbBMn5tV1b$8^s|tV6YCs&YnV#

7SmeGEkt$2AqN! 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

tP&tSUE2a(A~VxEqz%h;(C}?~`GE)-O-J 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 - -int main(void) -{ - printf("hello openEuler\r\n"); -} -``` - -然后在宿主机上使用对应的工具链编译, 相应命令如下: -```shell -export PATH=$PATH:/opt/openEuler_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin -aarch64-linux-gnu-gcc --sysroot= hello.c -o hello -mv hello /temp -``` -把交叉编译好的hello程序拷贝到/tmp目录下,然后参照使能共享文件系统中的描述,使得openEuler embedded可以访问宿主机的目录。 - -3. **运行用户态程序** - -在openEuler embedded中运行hello程序。 -```shell -cd /tmp/host -./hello -``` -如运行成功,openEuler Embedded的shell中就会输出hello openEuler。 diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index f20caf191..8111524af 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -27,11 +27,17 @@ - 内核镜像**zImage**: 基于openEuler社区Linux 5.10代码构建得到。相应的内核配置可通过如下链接获取: - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel), 针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) + - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) - 根文件系统镜像(依据具体需求,以下二选一) + - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器等软件包。该镜像适合进行更加丰富的功能探索。 + + - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 + +- SDK(Software Development Kit)工具 + + - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -40,7 +46,7 @@ --- **注意事项** -- 建议使用QEMU5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在QEMU中使能,则运行时可能会产生错误,此时可能需要从源码重新编译QEMU。 +- 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 >![](./public_sys-resources/icon-note.gif) **说明:** @@ -48,6 +54,11 @@ --- +qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: + +``` {.sourceCode .console} +qemu-system-aarch64 --version +``` ### 极简运行场景 @@ -56,11 +67,11 @@ 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```shell +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```shell +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd ``` @@ -82,18 +93,18 @@ qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```sh +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```sh +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` 2. **映射文件系统** 在openEuler Embedded启动并登录之后,需要运行如下命令,映射(mount)共享文件系统 -```shell +``` cd /tmp mkdir host mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host @@ -104,7 +115,7 @@ mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host 在openEuler Embedded中,运行如下命令: -```shell +``` cd /tmp/host ls ``` @@ -116,34 +127,40 @@ ls 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```shell +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```shell +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` 2. **宿主上建立虚拟网卡** -在宿主机上需要建立名为tap0的虚拟网卡,可以借助/etc/qemu-ifup脚本实现,其执行需要root权限,具体内容如下: +在宿主机上需要建立名为tap0的虚拟网卡,可以借助脚本实现,创建qemu-ifup脚本,放在/etc/下,具体内容如下: -```sh +``` #!/bin/bash ifconfig $1 192.168.10.1 up ``` +其执行需要root权限: + +``` +chmod a+x qemu-ifup +``` + 通过qemu-ifup脚本,宿主机上将创建名为tap0的虚拟网卡,地址为192.168.10.1。 3. **配置openEuler embedded网卡** openEuler Embedded登陆后,执行如下命令: -```shell +``` ifconfig eth0 192.168.10.2 ``` 4. **确认网络连通** 在openEuler Embedded中,执行如下命令: -```shell +``` ping 192.168.10.1 ``` @@ -151,4 +168,4 @@ ping 192.168.10.1 --- >![](./public_sys-resources/icon-note.gif) **说明:** - >如需openEuler embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 + >如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 diff --git "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..f9776a511 --- /dev/null +++ "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,4 @@ +openEuler Embedded构建指导 +===================== + +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index c949493c2..10868e4af 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -140,7 +140,10 @@ headless: true - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - - [使用方法]({{< relref "./docs/Embedded/使用方法.md" >}}) + - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/构建指导.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [openEuler Embedded容器构建指导]({{< relref "./docs/Embedded/openEuler Embedded容器构建指导.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From 8a2088afeab17b83c366553609bb8db394b30868 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 24 Mar 2022 17:58:59 +0800 Subject: [PATCH 05/42] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=91=E8=A1=8C?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E4=B8=AD=E5=85=B3=E9=94=AE=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E9=87=8C=E7=9A=84=E5=B5=8C=E5=85=A5=E5=BC=8F=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...05\263\351\224\256\347\211\271\346\200\247.md" | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index f9dbd8291..5ea9dcfe0 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -68,15 +68,12 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 - **边缘轻量化**,内存占用少,可在资源受限情况下工作。 ## 嵌入式镜像 -提供轻量化、安全和容器等基础能力,支持ARM32、ARM64芯片架构。 -- **轻量化**,提供OS镜像 < 5M, 运行底噪<15 M, 以及<5S快速启动等能力。 -- **安全加固**,对账户口令、文件权限等资源安全加固,OS默认安全使能 -- **轻量容器**,面向嵌入式场景的轻量容器运行时,支持标准容器镜像的部署运行。 -- **多架构支持**,支持ARM32和ARM64芯片架构。 -- **混合部署**,:支持soc内实时和非实时多平面混合部署。 -- **开放小型化裁剪**,开放基于Yocto构建包的小型化定制裁剪能力。ARM交叉编译工具 -- **支持ARM交叉编译工具**,基于社区10.3版本gcc提供ARM版本交叉编译工具链 -- **A支持分布式软总线**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通 +- **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 +- **多硬件支持**,新增支持树莓派作为嵌入式场景通用硬件。 +- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 +- **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 +- **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 +- **嵌入式软件包支持**,新增80+嵌入式领域常用软件包的构建。 ## secPaver secPaver是一款SELinux安全策略开发工具,用于辅助开发人员为应用程序开发安全策略。 -- Gitee From eda887d2ddb2de720939d4b6fbf94733edd31272 Mon Sep 17 00:00:00 2001 From: reus Date: Thu, 24 Mar 2022 20:00:33 +0800 Subject: [PATCH 06/42] add score_admin.yaml for documentation debugging --- score_admins.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 score_admins.yaml diff --git a/score_admins.yaml b/score_admins.yaml new file mode 100644 index 000000000..fd5ef5469 --- /dev/null +++ b/score_admins.yaml @@ -0,0 +1,5 @@ +score_admins: + amy_mayun + zhangcuihong + lanlanbenming + rachel_123456 \ No newline at end of file -- Gitee From 28880315c17a53e99ba9a6e6f756abd2428a713a Mon Sep 17 00:00:00 2001 From: fushanqing Date: Sun, 27 Mar 2022 06:31:37 +0800 Subject: [PATCH 07/42] =?UTF-8?q?=E5=A2=9E=E5=8A=A0NestOS=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/NestOS/overview.md | 3 + ...77\347\224\250\346\226\271\346\263\225.md" | 493 ++++++++++++++++++ ...71\346\200\247\346\217\217\350\277\260.md" | 103 ++++ ...05\344\270\216\351\203\250\347\275\262.md" | 129 +++++ ...63\351\224\256\347\211\271\346\200\247.md" | 8 + docs/zh/menu/index.md | 4 + 6 files changed, 740 insertions(+) create mode 100644 docs/zh/docs/NestOS/overview.md create mode 100644 "docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" create mode 100644 "docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" create mode 100644 "docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" diff --git a/docs/zh/docs/NestOS/overview.md b/docs/zh/docs/NestOS/overview.md new file mode 100644 index 000000000..808961df7 --- /dev/null +++ b/docs/zh/docs/NestOS/overview.md @@ -0,0 +1,3 @@ +# NestOS用户指南 + +本文介绍云底座操作系统NestOS的安装部署与各个特性说明和使用方法,使用户能够快速了解并使用NestOS。NestOS搭载iSulad、docker、podman等主流容器基础平台,克服了由于用户修改系统内容、用户服务对系统组件依赖,以及系统软件包升级时不稳定中间态等种种导致升级过程不可靠的因素,最终以一种轻量级、定制化的操作系统呈现出来,并且具备十分便捷的集群组建能力。镜像下载地址详见[NestOS仓库](https://gitee.com/openeuler/NestOS)。 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" "b/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" new file mode 100644 index 000000000..24148750a --- /dev/null +++ "b/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" @@ -0,0 +1,493 @@ +# K8S+iSulad 搭建 + +**以下步骤在master节点和node节点均需执行**,本教程以master为例 + +## 开始之前 + +需准备如下内容 +1.NestOS-22.03-date.x86_64.iso +2.一台主机用作master,一台主机用作node + +## 组件下载 + +编辑源文件,添加k8s的阿里云源 + +``` +vi /etc/yum.repos.d/openEuler.repo +``` + +添加如下内容 + +``` +[kubernetes] +name=Kubernetes +baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +enabled=1 +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +``` + +下载k8s组件以及同步系统时间所用组件 + +``` +rpm-ostree install kubelet kubeadm kubectl ntp ntpdate wget +``` + +重启生效 + +``` +systemctl reboot +``` + +选择最新的版本分支进入系统 + +## 配置环境 + +### 修改主机名,以master为例 + +``` +hostnamectl set-hostname k8s-master +sudo -i +``` + +编辑/etc/hosts + +``` +vi /etc/hosts +``` + +添加如下内容,ip为主机ip + +``` +192.168.237.133 k8s-master +192.168.237.135 k8s-node01 +``` + +### 同步系统时间 + +``` +ntpdate time.windows.com +systemctl enable ntpd +``` + +``` +关闭swap分区,防火墙,selinux +``` + +NestOS默认无swap分区,默认关闭防火墙 +关闭selinux如下 + +``` +vi /etc/sysconfig/selinux +修改为SELINUX=disabled +``` + +### 网络配置,开启相应的转发机制 + +创建配置文件 + +``` +vi /etc/sysctl.d/k8s.conf +``` + +添加如下内容 + +``` +net.bridge.bridge-nf-call-iptables=1 +net.bridge.bridge-nf-call-ip6tables=1 +net.ipv4.ip_forward=1 +``` + +使配置生效 + +``` +modprobe br_netfilter +sysctl -p /etc/sysctl.d/k8s.conf +``` + +## 配置iSula + +查看k8s需要的系统镜像,需注意pause的版本号 + +``` +kubeadm config images list +``` + +修改daemon配置文件 + +``` +vi /etc/isulad/daemon.json +``` + +``` +##关于添加项的解释说明## +registry-mirrors 设置为"docker.io" +insecure-registries 设置为"rnd-dockerhub.huawei.com" +pod-sandbox-image 设置为"registry.aliyuncs.com/google_containers/pause:3.5"(使用阿 +里云,pause版本可在上一步查看) +network-plugin 设置为"cni"。 +cni-bin-dir 设置为"/opt/cni/bin"; +cni-conf-dir 设置为"/etc/cni/net.d" +``` + +修改后的完整文件如下 + +``` +{"group": "isula", +"default-runtime": "lcr", +"graph": "/var/lib/isulad", +"state": "/var/run/isulad", +"engine": "lcr", +"log-level": "ERROR", +"pidfile": "/var/run/isulad.pid", +"log-opts": { +"log-file-mode": "0600", +"log-path": "/var/lib/isulad", +"max-file": "1", +"max-size": "30KB" +}, +"log-driver": "stdout", +"container-log": { +"driver": "json-file" +}, +"hook-spec": "/etc/default/isulad/hooks/default.json", +"start-timeout": "2m", +"storage-driver": "overlay2", +"storage-opts": [ +"overlay2.override_kernel_check=true" +], +"registry-mirrors": [ +"docker.io" +], +"insecure-registries": [ +"rnd-dockerhub.huawei.com" +], +"pod-sandbox-image": "registry.aliyuncs.com/google_containers/pause:3.5", +"native.umask": "secure", +"network-plugin": "cni", +"cni-bin-dir": "/opt/cni/bin", +"cni-conf-dir": "/etc/cni/net.d", +"image-layer-check": false, +"use-decrypted-key": true, +"insecure-skip-verify-enforce": false +} +``` + +启动相关服务 + +``` +systemctl restart isulad +systemctl enable isulad +systemctl enable kubelet +``` + +**以上为master,node节点均需执行的操作。** + +## master节点初始化 + +**该部分仅master节点执行。** +初始化,在这一步会拉取镜像,需等待一小段时间。也可在该步骤之前手动拉取镜像。 + +``` +kubeadm init --kubernetes-version=1.22.2 --apiserver-advertise- +address=192.168.237.133 --cri-socket=/var/run/isulad.sock --image-repository +registry.aliyuncs.com/google_containers --service-cidr=10.10.0.0/16 --pod- +network-cidr=10.122.0.0/16 +``` + +``` +##关于初始化参数的解释说明## +kubernetes-version 为当前安装的版本 +apiserver-advertise-address 为master节点ip +cri-socket 指定引擎为isulad +image-repository 指定镜像源为阿里云,可省去修改tag的步骤 +service-cidr 指定service分配的ip段 +pod-network-cidr 指定pod分配的ip段 +``` + +初始化成功后,复制最后两行内容方便后续node节点加入使用 + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +**注意**:添加--cri-socket=/var/run/isulad.sock以使用isulad为容器引擎 +查看下载好的镜像 + +``` +isula images +``` + +按照初始化成功所提示,配置集群 + +``` +mkdir -p $HOME/.kube +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +chown $(id -u):$(id -g) $HOME/.kube/config +export KUBECONFIG=/etc/kubernetes/admin.conf +source /etc/profile +``` + +查看健康状态 + +``` +kubectl get cs +``` + +可能存在controller-manager,scheduler状态为unhealthy的情况,解决方法如下: +编辑相关配置文件 + +``` +vi /etc/kubernetes/manifests/kube-controller-manager.yaml +``` + +``` +注释如下内容: +--port=0 +修改hostpath: +将所有/usr/libexec/kubernetes/kubelet-plugins/volume/exec 修改为/opt/libexec/... +``` + +``` +vi /etc/kubernetes/manifests/kube-scheduler.yaml +``` + +``` +注释如下内容: +--port=0 +``` + +修改完成后,再次查看健康状态 + +## 配置网络插件 + +仅需要在master节点配置网络插件,但是要在**所有节点**提前拉取镜像,拉取镜像指令如下。 + +``` +isula pull calico/node:v3.19.3 +isula pull calico/cni:v3.19.3 +isula pull calico/kube-controllers:v3.19.3 +isula pull calico/pod2daemon-flexvol:v3.19.3 +``` + +**以下步骤仅在master节点执行** +获取配置文件 + +``` +wget https://docs.projectcalico.org/v3.19/manifests/calico.yaml +``` + +编辑calico.yaml 修改所有/usr/libexec/... 为 /opt/libexec/... +然后执行如下命令完成calico的安装: + +``` +kubectl apply -f calico.yaml +``` + +通过kubectl get pod -n kube-system查看calico是否安装成功 +通过kubectl get pod -n kube-system查看是否所有pod状态都为running + +## node节点加入集群 + +在node节点执行如下指令,将node节点加入集群 + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +通过kubectl get node 查看master,node节点状态是否为ready + +至此,k8s部署成功。 + +# rpm-ostree使用 + +## rpm-ostree安装软件包 + +安装wget + +``` +rpm-ostree install wget +``` + +重启系统,可在启动时通过键盘上下按键选择rpm包安装完成后或安装前的系统状态,其中【ostree:0】为安装之后的版本。 + +``` +systemctl reboot +``` + +查看wget是否安装成功 + +``` +rpm -qa | grep wget +``` + +## rpm-ostree 手动更新升级 NestOS + +在NestOS中执行命令可查看当前rpm-ostree状态,可看到当前版本号 + +``` +rpm-ostree status +``` + +执行检查命令查看是否有升级可用,发现存在新版本 + +``` +rpm-ostree upgrade --check +``` + +预览版本的差异 + +``` +rpm-ostree upgrade --preview +``` + +在最新版本中,我们将nano包做了引入。 +执行如下指令会下载最新的ostree和RPM数据,不需要进行部署 + +``` +rpm-ostree upgrade --download-only +``` + +重启NestOS,重启后可看到系统的新旧版本两个状态,选择最新版本的分支进入 + +``` +rpm-ostree upgrade --reboot +``` + +## 比较NestOS版本差别 + +检查状态,确认此时ostree有两个版本,分别为LTS.20210927.dev.0和LTS.20210928.dev.0 + +``` +rpm-ostree status +``` + +根据commit号比较2个ostree的差别 + +``` +rpm-ostree db diff 55eed9bfc5ec fe2408e34148 +``` + +## 系统回滚 + +当一个系统更新完成,之前的NestOS部署仍然在磁盘上,如果更新导致了系统出现问题,可以使用之前的部署回滚系统。 + +### 临时回滚 + +要临时回滚到之前的OS部署,在系统启动过程中按住shift键,当引导加载菜单出现时,在菜单中选择相关的分支。 + +### 永久回滚 + +要永久回滚到之前的操作系统部署,登录到目标节点,运行rpm-ostree rollback,此操作将使用之前的系统部署作为默认部署,并重新启动到其中。 +执行命令,回滚到前面更新前的系统。 + +``` +rpm-ostree rollback +``` + +重启后失效。 + +## 切换版本 + +在上一步将NestOS回滚到了旧版本,可以通过命令切换当前 NestOS 使用的rpm-ostree版本,将旧版本切换为新版本。 + +``` +rpm-ostree deploy -r 22.03.20220325.dev.0 +``` + +重启后确认目前NestOS已经使用的是新版本的ostree了。 + + +# zincati自动更新使用 + +zincati负责NestOS的自动更新,zincati通过cincinnati提供的后端来检查当前是否有可更新版本,若检测到有可能新版本,会通过rpm-ostree进行下载。 + +目前系统默认关闭zincati自动更新服务,可通过修改配置文件设置为开机自动启动自动更新服务。 + +``` +vi /etc/zincati/config.d/95-disable-on-dev.toml +``` + +将updates.enabled设置为true +同时增加配置文件,修改cincinnati后端地址 + +``` +vi /etc/zincati/config.d/update-cincinnati.toml +``` + +添加如下内容 + +``` +[cincinnati] +base_url="http://nestos.org.cn:8080" +``` + +重新启动zincati服务 + +``` +systemctl restart zincati.service +``` + +当有新版本时,zincati会自动检测到可更新版本,此时查看rpm-ostree状态,可以看到状态是“busy”,说明系统正在升级中。 + +一段时间后NestOS将自动重启,此时再次登录NestOS,可以再次确认rpm-ostree的状态,其中状态转为"idle",而且当前版本已经是“20220325”,这说明rpm-ostree版本已经升级了。 + +查看zincati服务的日志,确认升级的过程和重启系统的日志。另外日志显示的"auto-updates logic enabled"也说明更新是自动的。 + +# 定制NestOS + +我们可以使用nestos-installer 工具对原始的NestOS ISO文件进行加工,将Ignition文件打包进去从而生成定制的 NestOS ISO文件。使用定制的NestOS ISO文件可以在系统启动完成后自动执行NestOS的安装,因此NestOS的安装会更加简单。 + +在开始定制NestOS之前,需要做如下准备工作: + +- 下载 NestOS ISO +- 准备 config.ign文件 + +## 生成定制NestOS ISO文件 + +### 设置参数变量 + +``` +$ export COREOS_ISO_ORIGIN_FILE=nestos-22.03.20220324.x86_64.iso +$ export COREOS_ISO_CUSTOMIZED_FILE=my-nestos.iso +$ export IGN_FILE=config.ign +``` + +### ISO文件检查 + +确认原始的NestOS ISO文件中是没有包含Ignition配置。 + +``` +$ nestos-installer iso ignition show $COREOS_ISO_ORIGIN_FILE + +Error: No embedded Ignition config. +``` + +### 生成定制NestOS ISO文件 + +将Ignition文件和原始NestOS ISO文件打包生成定制的NestOS ISO文件。 + +``` +$ nestos-installer iso ignition embed $COREOS_ISO_ORIGIN_FILE --ignition-file $IGN_FILE $COREOS_ISO_ORIGIN_FILE --output $COREOS_ISO_CUSTOMIZED_FILE +``` + +### ISO文件检查 + +确认定制NestOS ISO 文件中已经包含Ignition配置了 + +``` +$ nestos-installer iso ignition show $COREOS_ISO_CUSTOMIZED_FILE +``` + +执行命令,将会显示Ignition配置内容 + +## 安装定制NestOS ISO文件 + +使用定制的 NestOS ISO 文件可以直接引导安装,并根据Ignition自动完成NestOS的安装。在完成安装后,我们可以直接在虚拟机的控制台上用nest/password登录NestOS。 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" "b/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" new file mode 100644 index 000000000..3bcae9e30 --- /dev/null +++ "b/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" @@ -0,0 +1,103 @@ +# 功能特性描述 + +## 容器技术 + +NestOS通过容器化 (containerized) 的运算环境向应用程序提供运算资源,应用程序之间共享系统内核和资源,但是彼此之间又互不可见。这意味着应用程序将不会再被直接安装到操作系统中,而是通过 Docker 运行在容器中。大大降低了操作系统、应用程序及运行环境之间的耦合度。相对于传统的应用程序部署部署方式而言,在NestOS 集群中部署应用程序更加灵活便捷,应用程序运行环境之间的干扰更少,而且操作系统自身的维护也更加容易。 + +## rpm-ostree + +### 系统更新 + +rpm-ostree是一种镜像/包混合系统,可以看成是rpm和ostree的合体。一方面它提供了基于rpm的软件包安装管理方式,另一方面它提供了基于ostree的操作系统更新升级。rpm-ostree将这两种操作都视为对操作系统的更新,每次对系统的更新都像rpm-ostree在提交“Transaction-事务”,从而确保更新全部成功或全部失败,允许在更新系统后回滚到更新前的状态。 + +rpm-ostree在更新操作系统的时候会有2个bootable区域,分别为更新前和更新后的,对系统的更新升级只有在重启操作系统后才生效。如果软件安装或升级出现问题,通过rpm-ostree回滚会使nestos系统返回到先前的状态。我们可以查看nestos的“/ostree/”和“/boot/”目录,它们是ostree Repository环境并且可以观察到boot使用哪个ostree。 + +### 文件系统 + +在rpm-ostree的文件系统布局中,只有/etc和/var是唯一可写的目录,/var中的任何数据不会被触及,而是在升级过程中共享。在系统升级的过程中采用新的默认值/etc,并将更改添加到顶部。这意味着升级将会接收/etc中新的默认文件,这是一个非常关键的特性。 + +Ostree旨在可以并行安装多个独立操作系统的版本,ostree依赖于一个新的ostree 目录,该目录实际上可以并行安装在现有的操作系统或者是占据物理/root目录的发行版本中。每台客户机和每组部署上都存储在 /ostree/deploy/STATEROOT/CHECKSUM 上,而且还有一个ostree存储库存储在 /ostree/repo 中。每个部署主要由一组指向存储库的硬链接组成,这意味着每个版本都进行了重复数据的删除并且升级过程中只消耗了与新文件成比例的磁盘空间加上一些恒定的开销。 + +Ostree模型强调的是OS只读内容保存在 /usr 中,它附带了用于创建Linux只读安装以防止无意损坏的代码,对于给定的操作系统,每个部署之间都有一个 /var 共享的可供读写的目录。Ostree核心代码不触及该目录的内容,如何管理和升级状态取决于每个操作系统中的代码。 + +### 系统扩展 + +出于安全性和可维护性的考虑,nestos让基础镜像尽可能保持小巧和精简。但是在某些情况下,需要向基本操作系统本身添加软件,例如驱动软件,VPN等等,因为它们比较难容器化。这些包拓展了操作系统的功能,为此,rpm-ostree将这些包视为拓展,而不是仅仅在用户运行时提供。也就是说,目前nestos对于实际安装哪些包没有限制,默认情况下,软件包是从openEuler仓库下载的。 + +要对软件包进行分层,需要重新编写一个systemd单元来执行rpm-ostree命令安装所需要的包,所做的更改应⽤于新部署,重新启动才能生效。 + +## nestos-installer + +nestos-installer是一个帮助安装Nestos的程序,它可以执行以下操作: + +(1)安装操作系统到一个目标磁盘,可使用Ignition和首次引导内核参数对其进行自定义(nestos-installer install) + +(2)下载并验证各种云平台、虚拟化或者裸机平台的操作系统映像(nestos-installer download) + +(3)列出可供下载的nestos镜像(nestos-installer list-stream) + +(4)在ISO中嵌入一个Ignition配置,以自定义地从中启动操作系统(nestos-installer iso ignition) + +(5)将Ignition配置包装在initd映像中,该映像可以被加入到PXE initramfs中以自定义从中启动的操作系统(nestos-installer pxe ignition) + +## zincati + +Zincati是nestos自动更新的代理,它作为Cincinnati和rpm-ostree的客户端,负责自动更新/重启机器。Zincati有如下特点: + +(1)支持自动更新代理,支持分阶段推出 + +(2)通过toml配置文件支持运行时自定义,用户自定义配置文件可覆盖默认配置 + +(3)多种更新策略 + +(4)通过维护窗口每周在特定时间范围内进行更新的策略 + +(5)收集和导出本地运行的zincati内部指标,可提供给Prometheus以减轻跨大量节点的监控任务 + +(6)具有可配置优先级的日志记录 + +(7)通过Cincinnati协议支持复杂的更新图 + +(8)通过外部锁管理器支持集群范围的重启编排 + +## 系统初始化(Ignition) + +Ignition 是一个与分发无关的配置实用程序,不仅用于安装,还读取配置文件(JSON 格式)并根据该配置nestos系统。可配置的组件包括存储和文件系统、systemd单元和用户。 + +Ignition仅在系统第一次引导期间运行一次(在initramfs中)。因为 Ignition 在启动过程的早期运行,所以它可以在用户空间开始启动之前重新分区磁盘、格式化文件系统、创建用户和写入文件。 因此,systemd 服务在 systemd 启动时已经写入磁盘,从而加快了启动速度。 + +(1)Ignition 仅在第一次启动时运行 + +Ignition 旨在用作配置工具,而不是配置管理工具。 Ignition 鼓励不可变的基础设施,其中机器修改要求用户丢弃旧节点并重新配置机器。 + +(2)Ignition不是在任何情况下都可以完成配置 + +Ignition 执行它需要的操作,使系统与 Ignition 配置中描述的状态相匹配。 如果由于任何原因 Ignition 无法提供配置要求的确切机器,Ignition 会阻止机器成功启动。例如,如果用户想要获取托管在 https://example.com/foo.conf 的文档并将其写入磁盘,如果无法解析给定的 URL,Ignition 将阻止机器启动。 + +(3)Ignition只是声明性配置 + +Ignition配置只描述了系统的状态,没有列出 Ignition 应该采取的一系列步骤。 + +Ignition 配置不允许用户提供任意逻辑(包括 Ignition 运行的脚本)。用户只需描述哪些文件系统必须存在、哪些文件必须创建、哪些用户必须存在等等。任何进一步的定制都必须使用由 Ignition 创建的 systemd 服务。 + +(4)Ignition配置不应手写 + +Ignition 配置被设计为人类可读但难以编写,是为了阻止用户尝试手动编写配置。可以使用Butane或类似工具生成或转化生成Ignition 配置。 + +## Afterburn + +Afterburn是类似于云平台一样的一次性代理,可以用于与特定的提供者的元数据端点进行交互,通常和Ignition结合使用。 + +Afterburn包含了很多可以在实例生命周期中不同时间段运行的模块。下面的服务是根据特定的平台可能在第一次启动时在initramfs中运行的: + +(1)设置本地主机名 + +(2)加入网络命令行参数 + +以下的功能是在一定条件下,作为systemd服务单元在一些平台上才能使用的: + +(1)为本地系统用户安装公共SSH密钥 + +(2)从实例元数据中检索属性 + +(3)给提供者登记以便报道成功的启动或实例供应 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" new file mode 100644 index 000000000..6eb2dca54 --- /dev/null +++ "b/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -0,0 +1,129 @@ +# 安装与部署 + +## 在 VMware 上部署 NestOS + +本指南展示了如何在VMware虚拟机管理程序上配置最新的 NestOS。 + +目前NestOS仅支持x86_64架构。 + +### 开始之前 + +​ 在开始部署 NestOS 之前,需要做如下准备工作: + +- 下载 NestOS ISO +- 准备 config.bu 文件 +- 配置 butane 工具(Linux环境/win10环境) +- 安装有VMware的宿主机 + +### 初步安装与启动 + +#### 启动 NestOS + +初次启动 NestOS ,ignition 尚未安装,可根据系统提示使用 nestos-installer 组件进行ignition的安装。 + +### 配置 ignition 文件 + +#### 获取 Butane + +可以通过 Butane 将 bu 文件转化为 igniton 文件。ignition 配置文件被设计为可读但难以编写,是为了 +阻止用户尝试手动编写配置。 +Butane 提供了多种环境的支持,可以在 linux/windows 宿主机中或容器环境中进行配置。 + +``` +docker pull quay.io/coreos/butane:release +``` + +#### 生成登录密码 + +在宿主机执行如下命令,并输入你的密码。 + +``` +# openssl passwd -1 -salt yoursalt +Password: +$1$yoursalt$1QskegeyhtMG2tdh0ldQN0 +``` + +#### 生成ssh-key + +在宿主机执行如下命令,获取公钥和私钥以供后续 ssh 登录。 + +``` +# ssh-keygen -N '' -f ./id_rsa +Generating public/private rsa key pair. +Your identification has been saved in ./id_rsa +Your public key has been saved in ./id_rsa.pub +The key fingerprint is: +SHA256:4fFpDDyGHOYEd2fPaprKvvqst3T1xBQuk3mbdon+0Xs root@host-12-0-0-141 +``` + +``` +The key's randomart image is: ++---[RSA 3072]----+ +| ..= . o . | +| * = o * . | +| + B = * | +| o B O + . | +| S O B o | +| * = . . | +| . +o . . | +| +.o . .E | +| o*Oo ... | ++----[SHA256]-----+ +``` + +可以在当前目录查看id_rsa.pub公钥 + +``` +# cat id_rsa.pub +ssh-rsa +AAAAB3NzaC1yc2... +``` + +#### 编写bu文件 + +进行最简单的初始配置,如需更多详细的配置,参考后面的 ignition 详解。 +如下为最简单的 config.bu 文件 + +``` +variant: fcos +version: 1.1.0 +passwd: + users: + - name: nest + password_hash: "$1$yoursalt$1QskegeyhtMG2tdh0ldQN0" + ssh_authorized_keys: + - "ssh-rsa + AAAAB3NzaC1yc2EAAA..." +``` + +#### 生成ignition文件 + +将 config.bu 通过 Butane 工具转换为 config.ign 文件,如下为在容器环境下进行转换。 + +``` +# docker run --interactive --rm quay.io/coreos/butane:release \ +--pretty --strict < your_config.bu > transpiled_config.ign +``` + +### 安装 NestOS + +将宿主机生成的的config.ign文件通过scp拷贝到前面初步启动的 NestOS 中,该OS目前运行在内存中, +并没有安装到硬盘。 + +``` +sudo -i +scp root@your_ipAddress:/root/config.ign /root +``` + +根据系统所给提示,执行如下指令完成安装。 + +``` +nestos-installer install /dev/sda --ignition-file config.ign +``` + +安装完成后重启 NestOS 。 + +``` +systemctl reboot +``` +完成 diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 5ea9dcfe0..382d97667 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -79,6 +79,14 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 secPaver是一款SELinux安全策略开发工具,用于辅助开发人员为应用程序开发安全策略。 - **策略管理**,提供高阶配置语言,根据策略配置文件内容生成SELinux策略文件,降低SElinux使用门槛。 +## NestOS +NestOS是一款在openEuler社区CloudNative sig组孵化的云底座操作系统,专注于提供最佳的容器主机,大规模下安全的运行容器化工作负载。 +- **开箱即用的容器平台**,搭载了iSulad、docker、podman 、cri-o等主流容器基础平台。 +- **简单易用的安装配置过程**,采用了Ignition技术,提供个性化配置。 +- **安全可靠的包管理方式**,使用rpm-ostree进行包管理。 +- **友好可控的自动更新代理**,采用zincati实现无感升级。 +- **紧密配合的双系统分区**,双系统分区设计确保系统安全。 + ## 更多的第三方应用支持 - **KubeSphere**,KubeSphere 是在 Kubernetes 之上构建的以应用为中心的容器平台,完全开源,由青云科技发起,并由 openEuler 社区 SIG-KubeSphere 提供支持和维护。 - **OpenStack Wallaby**,OpenStack版本更新到Wallaby。Wallaby是2021年4月份发布的最新稳定版本,包含nova、kolla、cyborg、tacker等核心项目的重要更新。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cb3b360db..2f8d63396 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -216,3 +216,7 @@ headless: true - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) - [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) +- [NestOS用户指南]({{< relref "./docs/NestOS/overview.md" >}}) + - [安装与部署]({{< relref "./docs/NestOS/安装与部署.md" >}}) + - [使用方法]({{< relref "./docs/NestOS/使用方法.md" >}}) + - [功能特性描述]({{< relref "./docs/NestOS/功能特性描述.md" >}}) -- Gitee From ad8f2c0ea4c8ab7314bcc315062b815c3fc09c5e Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Mon, 28 Mar 2022 07:27:25 +0000 Subject: [PATCH 08/42] =?UTF-8?q?update=20docs/zh/docs/gazelle/gazelle.md.?= =?UTF-8?q?=20=E5=8E=BB=E6=8E=89=E8=AF=A5=E6=96=87=E4=BB=B6=E6=9C=80?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E7=9A=84=E6=97=A0=E6=95=88=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/gazelle/gazelle.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/zh/docs/gazelle/gazelle.md b/docs/zh/docs/gazelle/gazelle.md index f2a933c70..8ea1f3e52 100644 --- a/docs/zh/docs/gazelle/gazelle.md +++ b/docs/zh/docs/gazelle/gazelle.md @@ -1,5 +1,3 @@ -gazelle - # gazelle ## Introduction -- Gitee From 2742bdab2bb1c192eb93d2ef6fa26c6acaaf9283 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Mon, 28 Mar 2022 07:56:11 +0000 Subject: [PATCH 09/42] =?UTF-8?q?update=20docs/zh/menu/index.md.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E6=96=87=E6=A1=A3=20gazelle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/menu/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 10868e4af..cb3b360db 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -215,3 +215,4 @@ headless: true - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) +- [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) -- Gitee From 906acf9fb79996c2989ce9ef0988ea0a7ff18d3a Mon Sep 17 00:00:00 2001 From: x30004928 Date: Wed, 30 Mar 2022 09:53:23 +0800 Subject: [PATCH 10/42] update imagetailor menu --- .../docs/TailorCustom/figures/flowchart.png | Bin 0 -> 21270 bytes ...77\347\224\250\346\214\207\345\215\227.md" | 935 ++++++++++++++++++ ...77\347\224\250\346\214\207\345\215\227.md" | 884 ----------------- .../public_sys-resources/delete.PNG | Bin 17428 -> 0 bytes .../public_sys-resources/drivers.png | Bin 7060 -> 0 bytes .../public_sys-resources/flowchart.png | Bin 29937 -> 0 bytes .../public_sys-resources/libs.png | Bin 4180 -> 0 bytes .../public_sys-resources/tools.png | Bin 2992 -> 0 bytes docs/zh/menu/index.md | 2 +- 9 files changed, 936 insertions(+), 885 deletions(-) create mode 100644 docs/zh/docs/TailorCustom/figures/flowchart.png create mode 100644 "docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" delete mode 100644 "docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/drivers.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/flowchart.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/libs.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/tools.png diff --git a/docs/zh/docs/TailorCustom/figures/flowchart.png b/docs/zh/docs/TailorCustom/figures/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..e4fecb8b310f204d6cfd07449ccc3c93d1badd51 GIT binary patch literal 21270 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 X@4L`5c?#MHM8+U%jJ;)U5F_Tf22 literal 0 HcmV?d00001 diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" new file mode 100644 index 000000000..f7b29e358 --- /dev/null +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -0,0 +1,935 @@ +# imageTailor 使用指南 + +- [简介](#简介) +- [安装工具](# 安装工具) + - [软硬件要求](#软硬件要求) + - [获取安装包](#获取安装包) + - [安装 imageTailor](#安装 imageTailor) + - [目录介绍](#目录介绍) +- [定制系统](#定制系统) + - [总体流程](#总体流程) + - [定制业务包](#定制业务包) + - [配置本地 repo 源](#配置本地 repo 源) + - [添加文件](#添加文件) + - [添加 RPM 包](#添加 RPM 包) + - [添加 hook 脚本](#添加 hook 脚本) + - [配置系统参数](#配置系统参数) + - [配置主机参数](#配置主机参数) + - [配置初始密码](#配置初始密码) + - [配置分区](#配置分区) + - [配置网络](#配置网络) + - [配置内核参数](#配置内核参数) + - [制作系统](#制作系统) + - [命令介绍](#命令介绍) + - [制作指导](#制作指导) + - [裁剪时区](#裁剪时区) + - [定制示例](#定制示例) + + + +## 简介 + +操作系统除内核外,还包含各种功能的外围包。通用操作系统包含较多外围包,提供了丰富的功能,但是这也带来了一些影响: + +- 占用资源(内存、磁盘、CPU 等)多,导致系统运行效率低 +- 很多功能用户不需要,增加了开发和维护成本 + +因此,openEuler 提供了 imageTailor 镜像裁剪定制工具。用户可以根据需求裁剪操作系统镜像中不需要的外围包,或者添加所需的业务包或文件。该工具主要提供了以下功能: + +- 系统包裁剪:根据需要选择安装的 RPM 包列表,裁剪系统命令、库、驱动。 +- 系统配置修改:配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、内核版本号。 +- 软件包增加:将用户的 RPM 包安装到系统中或者将用户文件添加到系统中。 + + + +## 安装工具 + +本节以 openEuler 22.03 LTS 版本 AArch64 架构为例,说明安装方法。 + +### 软硬件要求 + +安装和运行 imageTailor 需要满足以下软硬件要求: + +- 机器架构为 x86_64 或者 AArch64 + +- 操作系统为 openEuler 22.03 LTS(该版本内核版本为 5.10,python 版本为 3.9,满足工具要求) + +- 运行工具的机器根目录 '/' 需要 40 GB 以上空间 + +- python 版本 3.9 及以上 + +- kernel 内核版本 5.10 及以上 + +- 关闭 SElinux 服务 + + ```shell + $ sudo setenforce 0 + $ getenforce + Permissive + ``` + + + +### 获取安装包 + +安装和使用 imageTailor 工具,首先需要下载 openEuler 发布件。 + +1. 获取 ISO 镜像文件和对应的校验文件。 + + 镜像必须为 everything 版本,此处假设存放在 root 目录,参考命令如下: + + ```shell + $ cd /root/temp + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +3. 获取 sha256sum 校验文件中的校验值。 + + ```shell + $ cat openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +4. 计算 ISO 镜像文件的校验值。 + + ```shell + $ sha256sum openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +5. 对比上述 sha256sum 文件的检验值和 ISO 镜像的校验值,如果两者相同,说明文件完整性检验成功。否则说明文件完整性被破坏,需要重新获取文件。 + +### 安装 imageTailor + +此处以 openEuler 22.03 LTS 版本的 AArch64 架构为例,介绍如何安装 imageTailor 工具。 + +1. 确认机器已经安装操作系统 openEuler 22.03 LTS( imageTailor 工具的运行环境)。 + + ```shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. 创建文件 /etc/yum.repos.d/local.repo,配置对应 yum 源。配置内容参考如下,其中 baseurl 是用于挂载 ISO 镜像的目录: + + ```shell + [local] + name=local + baseurl=file:///root/imageTailor_mount + gpgcheck=0 + enabled=1 + ``` + +3. 使用 root 权限,挂载光盘镜像到 /root/imageTailor_mount 目录(请与上述 repo 文件中配置的 baseurl 保持一致,且建议该目录的磁盘空间大于 20 GB)作为 yum 源,参考命令如下: + + ```shell + $ mkdir /root/imageTailor_mount + $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-aarch64-dvd.iso /root/imageTailor_mount/ + ``` + +4. 使 yum 源生效: + + ```shell + $ yum clean all + $ yum makecache + ``` + +5. 使用 root 权限,安装 imageTailor 裁剪工具: + + ```shell + $ sudo yum install -y imageTailor + ``` + +6. 使用 root 权限,确认工具已安装成功。 + + ```shell + $ cd /opt/imageTailor/ + $ sudo ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] + Options: + -p,--product Specify the product to make, check custom/cfg_yourProduct. + -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx + --minios Make minios: yes|no|force + --sec Perform security hardening + -h,--help Display help information + + Example: + command: + ./mkdliso -p openEuler -c custom/cfg_openEuler --sec + + help: + ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + ``` + +### 目录介绍 + +imageTailor 工具安装完成后,工具包的目录结构如下: + +```shell +[imageTailor] + |-[custom] + |-[cfg_openEuler] + |-[usr_file] // 存放用户添加的文件 + |-[usr_install] // 存放用户的 hook 脚本 + |-[all] + |-[conf] + |-[hook] + |-[cmd.conf] // 配置 ISO 镜像默认使用的命令和库 + |-[rpm.conf] // 配置 ISO 镜像默认安装的 RPM 包和驱动列表 + |-[security_s.conf] // 配置安全加固策略 + |-[sys.conf] // 配置 ISO 镜像系统参数 + |-[kiwi] // imageTailor 基础配置 + |-[repos] // RPM 源,制作 ISO 镜像需要的 RPM 包 + |-[security-tool] // 安全加固工具 + |-mkdliso // 制作 ISO 镜像的可执行脚本 +``` + +## 定制系统 + +本章介绍使用 imageTailor 工具将业务 RPM 包、自定义文件、驱动、命令和文件打包至目标 ISO 镜像。 + +### 总体流程 + +使用 imageTailor 工具定制系统的流程请参见下图: + +![](./figures/flowchart.png) + +各流程含义如下: + +- 检查软硬件环境:确认制作 ISO 镜像的机器满足软硬件要求。 + +- 定制业务包:包括添加 RPM 包(包括业务 RPM 包、命令、驱动、库文件)和添加文件(包括自定义文件、命令、驱动、库文件) + + - 添加业务 RPM 包:用户可以根据需要,添加 RPM 包到 ISO 镜像。具体要求请参见 [安装工具](# 安装工具) 章节。 + - 添加自定义文件:若用户希望在目标 ISO 系统安装或启动时,能够进行自定义的硬件检查、系统配置检查、驱动安装等操作,可编写自定义文件,并打包到 ISO 镜像。 + - 添加驱动、命令、库文件:当 openEuler 的 RPM 包源未包含用户需要的驱动、命令或库文件时,可以使用 imageTailor 工具将对应驱动、命令或库文件打包至 ISO 镜像。 + +- 配置系统参数 + + - 配置主机参数:为了确保 ISO 镜像安装和启动成功,需要配置主机参数。 + - 配置分区:用户可以根据业务规划配置业务分区,同时可以调整系统分区。 + - 配置网络:用户可以根据需要配置系统网络参数,例如:网卡名称、IP 地址、子网掩码。 + - 配置初始密码:为了确保 ISO 镜像安装和启动成功,需要配置 root 初始密码和 grub 初始密码。 + - 配置内核参数:用户可以根据需求配置内核的命令行参数。 + +- 配置安全加固策略 + + imageTailor 提供了默认地安全加固策略。用户可以根据业务需要,通过编辑 security_s.conf 对系统进行二次加固(仅在系统 ISO 镜像定制阶段),具体的操作方法请参见 《 [安全加固指南](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/SecHarden/secHarden.html) 》。 + +- 制作操作系统 ISO 镜像 + + 使用 imageTailor 工具制作操作系统 ISO 镜像。 + +### 定制业务包 + +用户可以根据业务需要,将业务 RPM 包、自定义文件、驱动、命令和库文件打包至目标 ISO 镜像。 + +#### 配置本地 repo 源 + +定制 ISO 操作系统镜像,必须在 /opt/imageTailor/repos/euler_base/ 目录配置 repo 源。本节主要介绍配置本地 repo 源的方法。 + +以 openEuler 发布 ISO 的 RPM 包为例。 + +1. 下载 openEuler 发布的 ISO 。 + ```shell + $ cd /opt + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + ``` + +2. 创建挂载目录 /opt/openEuler_repo ,并挂载 ISO 到该目录 。 + ```shell + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + ``` + +3. 拷贝 ISO 中的 RPM 包到 /opt/imageTailor/repos/euler_base/ 目录下。 + ```shell + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +#### 添加文件 + +用户可以根据需要添加文件到 ISO 镜像,此处的文件类型可以是用户自定义文件、驱动、命令、库文件。用户只需要将文件放至 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下即可。 + +##### 注意事项 + +- 命令必须具有可执行权限,否则 imageTailor 工具无法将该命令打包至 ISO 中。 + +- 存放在 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下的文件,会生成在 ISO 根目录下,所以文件的目录结构必须是从根目录开始的完整路径,以便 imageTailor 工具能够将该文件放至正确的目录下。 + + 例如:假设希望文件 file1 在 ISO 的 /opt 目录下,则需要在 usr_file 目录下新建 opt 目录,再将 file1 文件拷贝至 opt 目录。如下: + + ```shell + $ pwd + /opt/imageTailor/custom/cfg_openEuler/usr_file + + $ tree + . + ├── etc + │   ├── default + │   │   └── grub + │   └── profile.d + │   └── csh.precmd + └── opt + └── file1 + + 4 directories, 3 files + ``` + +- 存放在 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下的目录必须是真实路径(例如路径中不包含软连接。可在系统中使用 `realpath` 或 `readlink -f` 命令查询真实路径)。 + +- 如果需要在系统启动或者安装阶段调用用户提供的脚本,即 hook 脚本,则需要将该文件放在 hook 目录下。 + +#### 添加 RPM 包 + +##### 操作流程 + +用户可以添加 RPM 包(驱动、命令或库文件)到 ISO 镜像,操作步骤如下: + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 下述 rpm.conf 和 cmd.conf 均在 /opt/imageTailor/custom/cfg_openEuler/ 目录下。 +>- 下述 RPM 包裁剪粒度是指 sys_cut='no' 。裁剪粒度详情请参见 [配置主机参数](#配置主机参数) 。 +>- 若没有配置本地 repo 源,请参见 [配置本地 repo 源 ](#配置本地 repo 源)进行配置。 +> + +1. 确认 /opt/imageTailor/repos/euler_base/ 目录中是否包含需要添加的 RPM 包。 + + - 是,请执行步骤 2 。 + - 否,请执行步骤 3 。 +2. 在 rpm.conf 的 \ 字段配置该 RPM 包信息。 + - 若为 RPM 包裁剪粒度,则操作完成。 + - 若为其他裁剪粒度,请执行步骤 4 。 +3. 用户自己提供 RPM 包,放至 /opt/imageTailor/custom/cfg_openEuler/usr_rpm 目录下。如果 RPM 包依赖于其他 RPM 包,也必须将依赖包放至该目录,因为新增 RPM 包需要和依赖 RPM 包同时打包至 ISO 镜像。 + - 若为用户 RPM 包文件裁剪,则执行 4 。 + - 其他裁剪粒度,则操作完成。 +4. 请在 rpm.conf 和 cmd.conf 中配置该 RPM 包中要保留的驱动、命令和库文件。如果有要裁剪的普通文件,需要在 cmd.conf 文件中的 \\ 区域配置。 + + +##### 配置文件说明 + +| 对象 | 对应配置文件 | 填写区域 | +| :----------- | :----------- | :----------------------------------------------------------- | +| 添加驱动 | rpm.conf | \
\
\

说明:其中驱动名称所在路径为 " /lib/modules/{内核版本号}/kernel/ " 的相对路径 | +| 添加命令 | cmd.conf | \
\
\
| +| 添加库文件 | cmd.conf | \
\
\
| +| 删除其他文件 | cmd.conf | \
\
\

说明:普通文件名称必须包含绝对路径 | + +**示例** + +- 添加驱动 + + ```shell + + + + + ...... + + ``` + +- 添加命令 + + ```shell + + + + + ...... + + ``` + +- 添加库文件 + + ```shell + + + + + + ``` + +- 删除其他文件 + + ```shell + + + + + + ``` + +#### 添加 hook 脚本 + +hook 脚本由 OS 在启动和安装过程中调用,执行脚本中定义的动作。imageTailor 工具存放 hook 脚本的目录为 custom/cfg_openEuler/usr_install/hook,且其下有不同子目录,每个子目录代表 OS 启动或安装的不同阶段,用户根据脚本需要被调用的阶段存放,OS 会在对应阶段调用该脚本。用户可以根据需要存放自定义脚本到指定目录。 + +##### **脚本命名规则** + +用户可自定义脚本名称,必须 "S+数字(至少两位,个位数以0开头)" 开头,数字代表 hook 脚本的执行顺序。脚本名称示例:S01xxx.sh + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>hook 目录下的脚本是通过 source 方式调用,所以脚本中需要谨慎使用 exit 命令,因为调用 exit 命令之后,整个安装的脚本程序也同步退出了。 + + + +##### hook 子目录说明 + +| hook 子目录 | hook 脚本举例 | hook 执行点 | 说明 | +| :-------------------- | :---------------------| :------------------------------- | :----------------------------------------------------------- | +| insmod_drv_hook | 无 | 加载 OS 驱动之后 | 无 | +| custom_install_hook | S01custom_install.sh | 驱动加载完成后(即 insmod_drv_hook 执行后) | 用户可以自定义安装过程,不需要使用 OS 默认安装流程。 | +| env_check_hook | S01check_hw.sh | 安装初始化之前 | 初始化之前检查硬件配置规格、获取硬件类型。 | +| set_install_ip_hook | S01set_install_ip.sh | 安装初始化过程中,配置网络时 | 用户根据自身组网,自定义网络配置。 | +| before_partition_hook | S01checkpart.sh | 在分区前调用 | 用户可以在分区之前检查分区配置文件是否正确。 | +| before_setup_os_hook | 无 | 解压repo之前 | 用户可以进行自定义分区挂载操作。
如果安装包解压的路径不是分区配置中指定的根分区。则需要用户自定义分区挂载,并将解压路径赋值给传入的全局变量。 | +| before_mkinitrd_hook | S01install_drv.sh | 执行 mkinitrd 操作之前 | initrd 放在硬盘的场景下,执行 mkinitrd 操作之前的 hook。用户可以进行添加、更新驱动文件等自定义操作。 | +| after_setup_os_hook | 无 | 安装完系统之后 | 用户可以在安装完成之后进行系统文件的自定义操作,包括修改 grub.cfg 等 | +| install_succ_hook | 无 | 系统安装流程成功结束 | 用户执行解析安装信息,回传安装是否成功等操作。install_succ_hook 不可以设置为 install_break。 | +| install_fail_hook | 无 | 系统安装失败 | 用户执行解析安装信息,回传安装是否成功等操作。install_fail_hook 不可以设置为 install_break。 | + +### 配置系统参数 + +开始制作操作系统 ISO 镜像之前,需要配置系统参数,包括主机参数、初始密码、分区、网络、编译参数和系统命令行参数。 + +#### 配置主机参数 + + /opt/imageTailor/custom/cfg_openEuler/sys.conf 文件的 \ \ 区域用于配置系统的常用参数,例如主机名、内核启动参数等。 + +openEuler 提供的默认配置如下,用户可以需要进行修改: + +```shell + + sys_service_enable='ipcc' + sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' + sys_utc='yes' + sys_timezone='' + sys_cut='no' + sys_usrrpm_cut='no' + sys_hostname='Euler' + sys_usermodules_autoload='' + sys_gconv='GBK' + +``` + +配置中的各参数含义如下: + +- sys_service_enable + + 可选配置。OS 默认启用的服务,多个服务请以空格分开。如果用户不需要新增系统服务,请保持默认值,默认值为 ipcc 。配置时请注意: + + - 只能在默认配置的基础上增加系统服务,不能删减系统服务。 + - 可以配置业务相关的服务,但是需要 repo 源中包含业务 RPM 包。 + - 默认只开启该参数中配置的服务,如果服务依赖其他服务,需要将被依赖的服务也配置在该参数中。 + +- sys_service_disable + + 可选配置。禁止服务开机自启动的服务,多个服务请以空格分开。如果用户没有需要禁用的系统服务,请修改该参数为空。 + +- sys_utc + + 必选配置。是否采用 UTC 时间。yes 表示采用,no 表示不采用,默认值为 yes 。 + +- sys_timezone + + 可选配置。设置时区,即该单板所处的时区。可配置的范围为 openEuler 支持的时区,可通过 /usr/share/zoneinfo/zone.tab 文件查询。 + +- sys_cut + + 必选配置。是否裁剪 RPM 包。可配置为 yes、no 或者 debug 。yes 表示裁剪,no 表示不裁剪(仅安装 rpm.conf 中的 RPM 包),debug 表示裁剪但会保留 `rpm` 命令方便安装后定制。默认值为 no 。 + + > ![](.\public_sys-resources\icon-note.gif)说明: + > + > - imageTailor 工具会先安装用户添加的 RPM 包,再删除 cmd.conf + > 中 \ 区域的文件,最后删除 + > cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。 + > - sys_cut='yes' 时,imageTailor 工具不支持 `rpm` 命令的安装,即使在 rpm.conf 中配置了也不生效。 + +- sys_usrrpm_cut + + 必选配置。是否裁剪用户添加到 /opt/imageTailor/custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。yes 表示裁剪,no 表示不裁剪。默认值为 no 。 + + - sys_usrrpm_cut='yes' :imageTailor 工具会先安装用户添加的 RPM 包,然后删除 cmd.conf 中 \ 区域配置的文件,最后删除 cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。 + + - sys_usrrpm_cut='no' :imageTailor 工具会安装用户添加的 RPM 包,不删除用户 RPM 包中的文件。 + +- sys_hostname + + 必选配置。主机名。大批量部署 OS 时,部署成功后,建议修改每个节点的主机名,确保各个节点的主机名不重复。 + + 主机名要求:字母、数字、"-" 的组合,首字母必须是字母或数字。字母支持大小写。字符个数不超过 63 。默认值为 Euler 。 + +- sys_usermodules_autoload + + 可选配置。系统启动阶段加载的驱动,配置该参数时,不需要填写后缀 .ko 。如果有多个驱动,请以空格分开。默认为空,不加载额外驱动。 + +- sys_gconv + + 可选配置。该参数用于定制 /usr/lib/gconv, /usr/lib64/gconv ,配置取值为: + + - null/NULL:表示不配置。如果裁剪系统(sys_cut=“yes”),则/usr/lib/gconv 和 /usr/lib64/gconv 会被删除。 + - all/ALL:不裁剪 /usr/lib/gconv 和 /usr/lib64/gconv 。 + - xxx,xxx: 保留 /usr/lib/gconv 和 /usr/lib64/gconv 目录下对应的文件。若需要保留多个文件,可用 "," 分隔。 + +- sys_man_cut + + 可选配置。配置是否裁剪 man 文档。yes 表示裁剪,no 表示不裁剪。默认值为 yes 。 + + + +> ![](.\public_sys-resources\icon-note.gif)说明: +> +> sys_cut 和 sys_usrrpm_cut 同时配置时,sys_cut 优先级更高,即遵循如下原则: +> +> - sys_cut='no' +> +> 无论 sys_usrrpm_cut='no' 还是 sys_usrrpm_cut='yes' ,都为系统 RPM 包裁剪粒度,即imageTailor 会安装 repo 源中的 RPM 包和 usr_rpm 目录下的 RPM 包,但不会裁剪 RPM 包中的文件。即使用户不需要这些 RPM 包中的部分文件,imageTailor 也不会进行裁剪。 +> +> - sys_cut='yes' +> +> - sys_usrrpm_cut='no' +> +> 系统 RPM 包文件裁剪粒度:imageTailor 会根据用户配置,裁剪 repo 源中 RPM 包的文件。 +> +> - sys_usrrpm_cut='yes' +> +> 系统和用户 RPM 包文件裁剪粒度:imageTailor 会根据用户的配置,裁剪 repo 源和 usr_rpm 目录中 RPM 包的文件。 +> + + + +#### 配置初始密码 + +操作系统安装时,必须具有 root 初始密码和 grub 初始密码,否则裁剪得到的 ISO 在安装后无法使用 root 账号进行登录。本节介绍配置初始密码的方法。 + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> root 初始密码和 grub2 初始密码,必须由用户自行配置。 + +##### 配置 root 初始密码 + +###### 简介 + +root 初始密码保存在 "/opt/imageTailor/custom/cfg_openEuler/rpm.conf" 中,用户通过修改该文件配置 root 初始密码。 + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 若使用 `mkdliso` 命令制作 ISO 镜像时需要使用 --minios yes/force 参数(制作在系统安装时进行系统引导的 initrd),则还需要在 /opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf 中填写相应信息。 + +/opt/imageTailor/custom/cfg_openEuler/rpm.conf 中 root 初始密码的默认配置如下,需要用户自行添加: + +``` + + + +``` + +各参数含义如下: + +- group:用户所属组。 +- pwd:用户初始密码的加密密文,加密算法为 SHA-512。${pwd} 需要替换成用户实际的加密密文。 +- home:用户的家目录。 +- name:需要配置用户的用户名。 + +###### 修改方法 + +用户在制作 ISO 镜像前需要修改 root 用户的初始密码,这里给出设置 root 初始密码的方法(需使用 root 权限): + +1. 添加用于生成密码的用户,此处假设 testUser。 + + ```shell + $ sudo useradd testUser + ``` + +2. 设置 testUser 用户的密码。参考命令如下,根据提示设置密码: + + ```shell + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. 查看 /etc/shadow 文件,testUser 后的内容(两个 : 间的字符串)即为加密后的密码。 + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: + ``` + +4. 拷贝上述加密密码替换 /opt/imageTailor/custom/cfg_openEuler/rpm.conf 中的 pwd 字段,如下所示: + ``` shell script + + + + ``` + +5. 若使用 `mkdliso` 命令制作 ISO 镜像时需要使用 --minios yes/force 参数,请修改 /opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf 中对应用户的 pwd 字段。 + + ``` shell script + + + + ``` + +##### 配置 grub2 初始密码 + +grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub2 初始密码。如果未配置 grub2 初始密码,制作 ISO 镜像会失败。 + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> - 配置 gurb2 初始密码需要使用 root 权限。 +> - grub2 密码对应的默认用户为 root 。 +> +> - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 + +1. 执行如下命令,根据提示设置 grub2 密码: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 + ``` + +3. 复制上述密文,并在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 文件中增加如下配置: + + ```shell + GRUB_PASSWORD="grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615" + ``` + + +#### 配置分区 + +若用户想调整系统分区或业务分区,可以通过修改 /opt/imageTailor/custom/cfg_openEuler/sys.conf 文件中的 \ 实现。 + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 系统分区:存放操作系统的分区 +>- 业务分区:存放业务数据的分区 +>- 差别:在于存放的内容,而每个分区的大小、挂载路径和文件系统类型都不是区分业务分区和系统分区的依据。 +>- 配置分区为可选项,用户也可以在安装 OS 之后,手动配置分区 + + \ 的配置格式为: + +hd 磁盘号 挂载路径 分区大小 分区类型 文件系统类型 [二次格式化标志位] + +其默认配置如下: + +``` shell script + +hd0 /boot 512M primary ext4 yes +hd0 /boot/efi 200M primary vfat yes +hd0 / 30G primary ext4 +hd0 - - extended - +hd0 /var 1536M logical ext4 +hd0 /home max logical ext4 + +``` + +各参数含义如下: + +- hd 磁盘号 + 磁盘的编号。请按照 hdx 的格式填写,x 指第 x 块盘。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >分区配置只在被安装机器的磁盘能被识别时才有效。 + +- 挂载路径 + 指定分区挂载的路径。用户既可以配置业务分区,也可以对默认配置中的系统分区进行调整。如果不挂载,则设置为 '-'。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >- 分区配置中必须有 '/' 挂载路径。其他的请用户自行调整。 + >- 采用 UEFI 引导时,在 x86_64 的分区配置中必须有 '/boot' 挂载路径,在 AArch64 的分区配置中必须有 '/boot/efi' 挂载路径。 + +- 分区大小 + 分区大小的取值有以下四种: + + - G/g:指定以 GB 为单位的分区大小,例如:2G。 + - M/m:指定以 MB 为单位的分区大小,例如:300M。 + - T/t:指定以 TB 为单位的分区大小,例如:1T。 + - MAX/max:指定将硬盘上剩余的空间全部用来创建一个分区。只能在最后一个分区配置该值。 + + >![](./public_sys-resources/icon-note.gif) **说明:** +> + >- 分区大小不支持小数,如果是小数,请换算成其他单位,调整为整数的数值。例如:不能填写 1.5G,应填写为 1536M。 + >- 分区大小取 MAX/max 值时,剩余分区大小不能超过支持文件系统类型的限制(默认文件系统类型 ext4,限制大小 16T)。 + +- 分区类型 + 分区有以下三种: + + - 主分区: primary + - 扩展分区:extended(该分区只需配置 hd 磁盘号即可) + - 逻辑分区:logical + +- 文件系统类型 + 目前支持的文件系统类型有:ext4、vfat + +- 二次格式化标志位 + 可选配置,表示二次安装时是否格式化: + + - 是:yes + - 否:no 。不配置默认为 no 。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >二次格式化是指本次安装之前,磁盘已安装过 openEuler 系统。当前一次安装跟本次安装的使用相同的分区表配置(分区大小,挂载点,文件类型)时,该标志位可以配置是否格式化之前的分区,'/boot' 和 '/' 分区除外,每次都会重新格式化。如果目标机器第一次安装,则该标志位不生效,所有指定了文件系统的分区都会进行格式化。 + +#### 配置网络 + +系统网络参数保存在 /opt/imageTailor/custom/cfg_openEuler/sys.conf 中,用户可以通过该文件的\\ 配置修改目标 ISO 镜像的网络参数,例如:网卡名称、IP地址、子网掩码。 + +sys.conf 中默认的网络配置如下,其中 netconfig-0 代表网卡 eth0。如果需要配置多块网卡,例如eth1,请在配置文件中增加 \\,并在其中填写网卡 eth1 的各项参数。 + +```shell + +BOOTPROTO="dhcp" +DEVICE="eth0" +IPADDR="" +NETMASK="" +STARTMODE="auto" + +``` + +各参数含义请参见下表: + +- | 参数名称 | 是否必配 | 参数值 | 说明 | + | :-------- | -------- | :------------------------------------------------ | :----------------------------------------------------------- | + | BOOTPROTO | 是 | none / static / dhcp | none:引导时不使用协议,不配地址
static:静态分配地址
dhcp:使用 DHCP 协议动态获取地址 | + | DEVICE | 是 | 如:eth1 | 网卡名称 | + | IPADDR | 是 | 如:192.168.11.100 | IP 地址
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | + | NETMASK | 是 | - | 子网掩码
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | + | STARTMODE | 是 | manual / auto / hotplug / ifplugd / nfsroot / off | 启用网卡的方法:
manual:用户在终端执行 ifup 命令启用网卡。
auto \ hotplug \ ifplug \ nfsroot:当 OS 识别到该网卡时,便启用该网卡。
off:任何情况下,网卡都无法被启用。
各参数更具体的说明请在制作 ISO 镜像的机器上执行 `man ifcfg` 命令查看。 | + + +#### 配置内核参数 + +为了系统能够更稳定高效地运行,用户可以根据需要修改内核命令行参数。imageTailor 工具制作的 OS 镜像,可以通过修改 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中的 GRUB_CMDLINE_LINUX 配置实现内核命令行参数修改。 GRUB_CMDLINE_LINUX 中内核命令行参数的默认配置如下: + +```shell +GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" +``` + +此处各配置含义如下(其余常见的内核命令行参数请查阅内核相关文档): + +- net.ifnames=0 biosdevname=0 + + 以传统方式命名网卡。 + +- crashkernel=512M + + 为 kdump 预留的内存空间大小为 512 MB。 + +- oops=panic panic=3 + + 内核 oops 时直接 panic,并且 3 秒后重启系统。 + +- softlockup_panic=1 + + 在检测到软死锁(soft-lockup)时让内核 panic。 + +- reserve_kbox_mem=16M + + 为 kbox 预留的内存空间大小为 16 MB。 + +- console=tty0 + + 指定第一个虚拟控制台的输出设备为 tty0。 + +- crash_kexec_post_notifiers + + 系统 crash 后,先调用注册到 panic 通知链上的函数,再执行 kdump。 + +### 制作系统 + +操作系统定制完成后,可以通过 mkdliso 脚本制作系统镜像文件。 imageTailor 制作的 OS 为 ISO 格式的镜像文件。 + +#### 命令介绍 + +##### 命令格式 + +**mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h]** + +##### 参数说明 + +| 参数名称 | 是否必选 | 参数含义 | 取值范围 | +| -------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| -p | 是 | 设置产品名称 | openEuler | +| c | 是 | 指定配置文件的相对路径 | custom/cfg_openEuler | +| --minios | 否 | 制作在系统安装时进行系统引导的 initrd | 默认为 yes
yes:第一次执行命令时会制作 initrd,之后执行命令会判断 'usr_install/boot'
目录下是否存在 initrd(sha256 校验)。如果存在,就不重新制作 initrd,否则制作 initrd 。
no:不制作 initrd,采用原有方式,系统引导和运行使用的 initrd 相同。
force:强制制作 initrd,不管 'usr_install/boot' 目录下是否存在 initrd。 | +| --sec | 否 | 是否对生成的 ISO 进行安全加固
如果用户不输入该参数,则由此造成的安全风险由用户承担 | 无 | +| -h | 否 | 获取帮助信息 | 无 | + +#### 制作指导 + +使用 mkdliso 制作 ISO 镜像的操作步骤如下: + +> ![](.\public_sys-resources\icon-note.gif)说明: +> +> - mkdliso 所在的绝对路径中不能有空格,否则会导致制作 ISO 失败。 +> - 制作 ISO 的环境中,umask 的值必须设置为 0022。 + +1. 使用 root 权限,执行 mkdliso 命令,生成 IOS 镜像文件。参考命令如下: + + ```shell + # sudo /opt/imageTailor/mkdliso -p openEuler -c custom/cfg_openEuler --sec + ``` + + 命令执行完成后,制作出的新文件在 /opt/imageTailor/result/{日期} 目录下,包括 openEuler-aarch64.iso 和 openEuler-aarch64.iso.sha256 。 + +2. 验证 ISO 镜像文件的完整性。此处假设日期为 2022-03-21-14-48 。 + + ```shell + $ cd /opt/imageTailor/result/2022-03-21-14-48/ + $ sha256sum -c openEuler-aarch64.iso.sha256 + ``` + + 回显如下,表示 ISO 镜像文件完整,ISO 制作完成。 + + ``` + openEuler-aarch64.iso: OK + ``` + + 若回显如下,表示镜像不完整,说明 ISO 镜像文件完整性被破坏,需要重新制作。 + + ```shell + openEuler-aarch64.iso: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + +3. 查看日志 + + 镜像制作完成后,可以根据需要(例如制作出错时)查看日志。第一次制作镜像时,对应的日志和安全加固日志被压缩为一个 tar 包(日志的命名格式为:sys_custom_log_{*日期* }.tar.gz),存放在 result/log 目录下。该目录只保留最近时间的 50 个日志压缩包,超过 50 个时会对旧文件进行覆盖。 + + + +### 裁剪时区 + +定制完成的 ISO 镜像安装后,用户可以根据需求裁剪 openEuler 系统支持的时区。本节介绍裁剪时区的方法。 + +openEuler 操作系统支持的时区信息存放在时区文件夹 /usr/shre/zoninfo 下,可通过如下命令查看: + +```shell +$ ls /usr/share/zoneinfo/ +Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ +Pacific/ zone.tab +``` + +其中每个子文件夹代表一个 Area ,当前 Area 包括:大陆、海洋以及 Etc 。每个 Area 文件夹内部则包含了隶属于其的 Location 。一个 Location 一般为一座城市或者一个岛屿。 + +所有时区均以 Area/Location 的形式来表示,比如中国大陆南部使用北京时间,其时区为 Asia/Shanghai(Location 并不一定会使用首都)。对应的,其时区文件为: + +``` +/usr/share/zoneinfo/Asia/Shanghai +``` + +若用户希望裁剪某些时区,则只需将对应的时区文件删除即可。 + +### 定制示例 + +本节给出使用 imageTailor 工具定制一个 ISO 操作系统镜像的简易方案,方便用户了解制作的整体流程。 + +1. 检查制作 ISO 所在环境是否满足要求。 + + ``` shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. 确保根目录有 40 GB 以上空间。 + + ```shell + $ df -h + Filesystem Size Used Avail Use% Mounted on + ...... + /dev/vdb 196G 28K 186G 1% / + ``` + +3. 安装 imageTailor 裁剪工具。具体安装方法请参见 [安装工具](#安装工具) 章节。 + + ```shell +$ sudo yum install -y imageTailor + $ ll /opt/imageTailor/ + total 88K + drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom + drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi + -r-x------. 1 root root 69K Mar 3 08:00 mkdliso + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool + ``` + +4. 配置本地 repo 源。 + + ```shell +$ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +5. 修改 grub/root 密码 + + 以下 ${pwd} 的实际内容请参见 [配置初始密码](#配置初始密码) 章节生成并替换。 + + ```shell + $ cd /opt/imageTailor/ + $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub + GRUB_PASSWORD="${pwd1}" + $ + $ sudo vi kiwi/minios/cfg_minios/rpm.conf + + + + $ + $ sudo vi custom/cfg_openEuler/rpm.conf + + + + ``` + +6. 执行裁剪命令。 + + ```shell + $ sudo rm -rf /opt/imageTailor/result + $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force + ...... + Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso + move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz + $ ll result/2022-03-09-15-31/ + total 889M + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 + ``` + + diff --git "a/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" deleted file mode 100644 index c918c59d2..000000000 --- "a/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ /dev/null @@ -1,884 +0,0 @@ -# imageTailor 使用指南 - -- [1. 概述](#1、概述) - - [1.1 背景介绍](#1.1、背景介绍) - - [1.2 功能介绍](#1.2、功能介绍) -- [2. 发布包介绍](#2、发布包介绍) - - [2.1 获取发布包](#2.1、获取发布包) - - [2.2 安装 imageTailor 工具](#2.2、安装imageTailor工具) - - [2.3 imageTailor 包目录介绍](#2.3、imageTailor包目录介绍) -- [3. 定制 OS](#3、定制OS) - - [3.1 使用流程](#3.1、使用流程) - - [3.2 检查软硬件环境](#3.2、检查软硬件环境) - - [3.3 定制业务包](#3.3、定制业务包) - - [3.4 配置系统参数](#3.4、配置系统参数) - - [3.5 制作 OS](#3.5、制作OS) - - [3.6 时区裁剪](#3.6、时区裁剪) - - [3.7 裁剪流程使用实例](#3.7、裁剪流程使用实例) - -## 1、概述 -介绍 imageTailor 是操作系统镜像文件级裁剪定制工具,该工具是基于开源软件 kiwi 进行功能增强开发,实现了多种裁剪定制功能, -包括系统包裁剪定制、系统配置裁剪定制、用户文件定制等,最后通过 cdrkit 生成 iso 格式的镜像文件。 - -### 1.1、背景介绍 -操作系统除内核外,还包含大量提供各种功能的外围包。因此,通用的操作系统功能较多,占用资源多,这带来了两方面的影响: - -- 大量占用有限的内存、磁盘、CPU 等资源,导致系统运行低效。 -- 很多功能客户不会使用,增加开发和维护成本。 - -OS 定制特性正是基于这样的现状提出。openEuler 提供 imageTailor 定制工具,根据客户的需求量身打造操作系统。用户可裁剪不需要的外围包,还可以添加自己的业务包。 - -### 1.2、功能介绍 - -#### 1.2.1、基本功能 -imageTailor 裁剪定制工具为用户提供以下功能: - -- 系统包裁剪定制:用户可选择默认安装的 RPM,定制裁剪系统命令、库、驱动。 -- 系统配置定制:可以配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、版本号。 -- 用户软件包定制:将用户的 RPM 包安装到系统中,将用户文件定制到系统中。 - -#### 1.2.2、基本概念 - -- 驱动:硬件驱动,为内核模块(后缀名为 ko)。一般是硬件部门将自己开发的驱动添加进 OS 中。驱动存放于 /lib/modules/{内核版本号}/kernel/ 目录下。 -- 命令:可执行文件,用户定制的命令可以是标准 openEuler 自带的,也可以是用户自己开发的。只有当可执行文件位于 /bin、/sbin、/usr/bin 或 /usr/sbin 时,才会被 imageTailor 工具识别为命令,如果是放在其他目录下,则被视为普通的文件。 -- 库:库是一种可执行程序的二进制形式,可以被操作系统载入内存执行。它是别人已写好的、可复用的代码。库文件一般存放在 /lib、/lib64、/usr/lib/、/usr/lib64、/usr/X11R6/lib 或 /usr/X11R6/lib64 目录下,统一以 lib 开头,格式为 libxxx。 -- 自定义文件:这里可以是安装脚本、配置脚本或其他文件。imageTailor 工具对自定义文件不做任何限制,只要是用户自己提供的文件,imageTailor 都默认打包至 OS 中。 -- RPM:RPM 包可以简单的理解为 linux 环境中的软件包。具体说来,一个 RPM 包就是能够让应用软件运行的全部文件的集合,它记录了二进制软件的内容、安装的位置、软件包的描述信息、软件包之间的依赖关系等信息。linux 中安装和卸载 RPM 包都有对应的命令。 - - -## 2、发布包介绍 - -### 2.1、获取发布包 -用户需下载 openEuler 发布包。 - -1. 获取 openEuler 发布包 - - AArch64 架构的镜像下载链接为: - ``` - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso - - eg: - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso - ``` - - > **说明:** - > x86_64 架构的镜像下载链接为: - > - > http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - -2. 校验发布包完整性 - - 1. 以 openEuler-22.03-LTS-aarch64-dvd.iso 为例。 - - 2. 下载 iso 到制作 OS 的机器上,并下载与 iso 同名的 sha256sum 文件(此处为 openEuler-22.03-LTS-x86_64-dvd.iso.sha256sum) - ``` - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso.sha256sum - ``` - - 3. 获取 sha256 文件中的校验值;计算 openEuler-22.03-LTS-aarch64-dvd.iso 的 sha256 值。 - ``` - $ cat openEuler-22.03-LTS-aarch64-dvd.iso.sha256sum - d22787ac209e544bb43c08f7c44f54373cafb79430e7fcae3d488d197f73793a openEuler-22.03-LTS-aarch64-dvd.iso - $ sha256sum openEuler-22.03-LTS-aarch64-dvd.iso - d22787ac209e544bb43c08f7c44f54373cafb79430e7fcae3d488d197f73793a openEuler-22.03-LTS-aarch64-dvd.iso - ``` - - 4. 对比以上两个计算的校验值是否一致。不一致说明文件完整性已被破坏,需要重新获取。 - - -### 2.2、安装imageTailor工具 - -此处以 openEuler 22.03 LTS 版本的 x86_64 架构为例,介绍 imageTailor 裁剪工具的安装操作 - -1. 确认机器已经安装操作系统 openEuler 22.03 LTS(imageTailor 裁剪工具的运行环境) - - ``` - $ cat /etc/openEuler-release - openEuler release 22.03 LTS - ``` - -2. 下载对应架构的 ISO 镜像(必须是 everything 版本),并存放在任一目录(建议该目录磁盘空间大于 20 GB),此处假设存放在 /root/imageTailor_mount 目录。 - - x86_64 架构的镜像下载链接为: - ``` - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/x86_64/openEuler-22.03-LTS-everything-x86_64-dvd.iso - ``` - 其他详细下载链接参考 2.1、获取发布包 - -3. 创建文件 /etc/yum.repos.d/local.repo,配置对应 yum 源。配置内容参考如下,其中 baseurl 是用于挂载 ISO 镜像的目录: - - ``` - [local] - name=local - baseurl=file:///root/imageTailor_mount - gpgcheck=0 - enabled=1 - ``` - -4. 使用 root 权限,挂载光盘镜像到 /root/imageTailor_mount 目录(请与上述 repo 文件中配置的 baseurl 保持一致)作为 yum 源,参考命令如下: - - ``` - $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-x86_64-dvd.iso /root/imageTailor_mount/ - mount: /root/imageTailor_mount: WARNING: source write-protected, mounted read-only. - ``` - -5. 使 yum 源生效: - - ``` - yum clean all - yum makecache - ``` - -6. 使用 root 权限,安装 imageTailor 裁剪工具: - - ```shell - sudo yum install -y imageTailor - ``` - -7. 使用 root 权限,确认工具已安装成功。 - - ``` - $ cd /opt/imageTailor/ - $ sudo ./mkdliso -h - ------------------------------------------------------------------------------------------------------------- - Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] - Options: - -p,--product Specify the product to make, check custom/cfg_yourProduct. - -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx - --minios Make minios: yes|no|force - --sec Perform security hardening - -h,--help Display help information - - Example: - command: - ./mkdliso -p openEuler -c custom/cfg_openEuler --sec - - help: - ./mkdliso -h - ------------------------------------------------------------------------------------------------------------- - $ - ``` - -### 2.3、imageTailor包目录介绍 -imageTailor 工具包含用户需要的 RPM 包源、imageTailor 定制工具和用户的配置文件。工具包部分目录结构如下: - - ``` - [imageTailor] - |-[custom] - |-[cfg_openEuler] - |-[usr_file] // 存放用户添加的文件 - |-[usr_install] // 存放用户的 hook 脚本 - |-[all] - |-[conf] - |-[hook] - |-[cmd.conf] // 配置 OS 默认使用的命令和库 - |-[rpm.conf] // 配置 OS 默认安装的 RPM 包和驱动列表 - |-[security_s.conf] // 配置安全加固策略 - |-[sys.conf] // 配置 OS 系统参数 - |-[kiwi] // imageTailor 基础配置 - |-[repos] // RPM 源,制作 OS 需要的 RPM 包 - |-[security-tool] // 安全加固工具 - |-mkdliso // 制作 OS 的可执行脚本 - ``` - -## 3、定制OS -使用 imageTailor 工具将业务 RPM 包、自定义文件、驱动、命令和文件打包至 OS 中,制作出 OS。 - -### 3.1、使用流程 - -定制工具的使用流程为:获取发布包、检查软硬件环境、定制业务包、配置系统参数和制作 OS。 - -使用定制工具进行 OS 定制的流程请参见 图1 -- 图1 定制工具使用流程图 - - ![](./public_sys-resources/flowchart.png) - -步骤说明如 表1 -- 表1 定制步骤说明 - - | 步骤 | | 说明 | - | :--- | :--- | :--- | - | 检查软硬件环境 | |了解制作 OS 的机器需要满足的软硬件要求。 | - | 定制业务包 | 添加业务 RPM 包 | 当用户希望同时部署业务和 OS,可以将业务 RPM 包打包至 OS 中。如果是用户自己提供的 RPM 包,请放在 custom/cfg_openEuler/usr_rpm 目录下。 | - | | 添加自定义文件 | 当用户希望 OS 在安装或启动时,能够进行硬件检查、系统配置检查、安装驱动或其他操作,可编写自定义文件,并将该文件打包至 OS 中。 | - | | 添加驱动 | 当 openEuler 的 RPM 包源未包含用户需要的驱动时,可以使用 imageTailor 工具将该驱动打包至 OS 中。 | - | | 添加命令 | 当 openEuler 的 RPM 包源未包含用户需要的命令时,可以使用 imageTailor 工具将该命令打包至 OS 中。 | - | 定制业务包 | 添加库文件 | 当 openEuler 的 RPM 包源未包含用户需要的库文件时,可以使用 imageTailor 工具将该库文件打包至 OS 中。 | - | 配置系统参数 | 配置主机参数 | 为了确保 OS 安装和启动成功,需要配置主机参数。 | - | | 配置分区 | 用户可以根据业务规划配置业务分区,同时可以调整系统分区。 | - | | 配置网络 | 根据产品的组网情况,配置网络参数,例如:网卡名称、IP 地址、子网掩码。 | - | 配置系统参数 | 配置编译参数 | 当用户希望 imageTailor 工具先编译代码,再将其添加至 OS 中,则需要配置编译参数。 | - | 配置安全加固策略 | | openEuler 发布给产品时已进行安全加固,满足公司安全规定。产品如果需要根据业务情况进行二次加固,只能在定制阶段进行,编辑 security_s.conf 进行安全加固。具体操作请参见安全加固操作指南。 | - | 制作OS | | 使用 imageTailor 工具提供的脚本制作 OS。 | - -### 3.2、检查软硬件环境 - -为了确保 OS 定制成功,用于制作 OS 的机器需要满足一定的软硬件要求 -- 机器架构为 x86_64 或者 AArch64 -- 操作系统为 openEuler 22.03 LTS - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- openEuler 22.03 满足 python 3.9 与 kernel 5.10 要求 - -- python 版本 3.9 以上 -- kernel 内核版本 5.10 以上 -- 用户裁剪机器根目录 '/' 需要 40 GB 以上空间 -- 关闭 SElinux 服务 - ``` - $ sudo setenforce 0 - $ getenforce - Permissive - ``` - -### 3.3、定制业务包 - -用户可以根据业务需要,将业务 RPM 包、自定义文件、驱动、命令和库文件打包至 OS 中。 - -#### 3.3.1、操作指导 - -用户要添加驱动、命令、库文件和脚本,可能是文件的形式,也可能是 RPM 包的形式。不同的形式有不同的定制方法。 - -1. 添加文件 - - 这里的文件可以是驱动、命令、库文件,也可以是脚本。用户只需将文件放至 custom/cfg_openEuler/usr_file 目录下即可。 - - **注意事项**: - - - 命令必须具有可执行权限,否则 imageTailor 工具无法将该命令打包至 OS 中。 - - - 在 custom/cfg_openEuler/usr_file 目录下放置文件时,文件的目录结构必须是从根目录开始的完整目录,以便 imageTailor 工具能够将该文件放至正确的目录下。 - - 例如:用户希望文件 file1 最终能放至 /opt 目录下,则需要在 usr_file 目录下新建 opt 目录,再将 file1 文件拷贝至 opt 目录。如下: - - ``` - $ tree - . - ├── etc - │   ├── default - │   │   └── grub - │   └── profile.d - │   └── csh.precmd - └── opt - └── file1 - - 4 directories, 3 files - & pwd - /opt/imageTailor/custom/cfg_openEuler/usr_file - ``` - - - 上述说的目录需要是系统中的真实路径(路径中不含软链接,可在系统中使用 realpath 或 readlink -f 命令查询真实路径)。 - - - 在 usr_file 新建目录时,若是系统中已有的目录,新建的目录权限需要和系统中目录权限保持一致,不然会导致 usr_file 下目录权限覆盖系统中目录的权限,可能导致系统问题。在添加目录之前请确定系统中目录的权限。 - - - 如果用户自己提供的脚本希望由 OS 在启动和安装阶段调用,即为 hook 脚本,需要将其放在 hook 目录下。 - -2. 添加 RPM 包 - - 1. 确认 repos 源中是否包含该 RPM 包。 - - 有,请执行 3 - - 无,请执行 2 - 2. 用户自己提供 RPM 包,放至 custom/cfg_openEuler/usr_rpm 目录下。如果 RPM 包依赖于其他 RPM 包,也必须将依赖包打包至 OS 中。 - 请用户根据采用哪种裁剪粒度,来执行后续的操作。 - - 用户 RPM 包文件裁剪,则执行 4 - - 其他裁剪粒度,则操作完成。 - 3. 在 rpm.conf 的 \ 字段配置该 RPM 包信息。请用户根据采用哪种裁剪粒度,来执行后续的操作。 - - RPM 包裁剪粒度,则操作完成 - - 其他裁剪粒度,则执行 4 - 4. 在 cmd.conf 和 rpm.conf 中配置该 RPM 包中要保留的驱动、命令和库文件。如果有要裁剪的普通文件,也需要在 cmd.conf 文件中配置。 - -3. 表 配置文件填写说明 - -- 表 配置文件填写说明 - - | 对象 | 操作 | 需要填写的配置文件 | 填写的区域 | 填写方法 | 注意事项 | 填写示例 | - | :--- | :--- | :--- |:--- | :--- | :--- | :--- | - | 驱动 | 保留 | custom/cfg_openEuler/rpm.conf | \\ | 新增一行 \ | 填写驱动名称时请填写相对于 "/lib/modules/{内核版本号}/kernel/" 的相对路径。 | 如下 图1 | - | 命令 | 保留 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写命令名称。 | 如下 图2 | - | 库文件 | 保留 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写库文件名称。 | 如下 图3 | - | 其他文件 | 删除 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写普通文件名称,请填写绝对路径。 | 如下 图4 | - -- 图1 drivers 填写示例 - - ![](./public_sys-resources/drivers.png) - -- 图2 tools 填写示例 - - ![](./public_sys-resources/tools.png) - -- 图3 libs 填写示例 - - ![](./public_sys-resources/libs.png) - -- 图4 delete 填写示例 - - ![](./public_sys-resources/delete.PNG) - - -#### 3.3.2、定制示例:添加驱动 - -1. 用户场景 - - 当 imageTailor 默认配置中会裁剪部分驱动,而用户又希望添加 repos 源中的某款硬件驱动至 OS 中。 - -2. 操作步骤 - - 由于该硬件驱动已经在 repos 源中,因此用户只需将其填写配置在 rpm.conf 中即可,避免被 imageTailor 裁剪掉。 - - 1. 在 custom/cfg_openEuler/rpm.conf 中的 \\ 区域添加该驱动信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - - 2. (可选)当用户希望 OS 在启动时自动加载驱动,则需要配置 sys.conf 文件。 - - 具体操作请参见 表 《sysconfig 系统参数说明》 中的 sys_usermodules_autoload 参数。 - -#### 3.3.3、定制实例:添加命令 - -1. 用户场景 - - 用户由于业务需要,希望添加某个命令至 OS 中。但用户不知道该命令是否已包含在 repos 中。 - -2. 操作步骤 - - 1. 确认该命令属于的 RPM 包名称。如果命令中没有,则代表 repos 源中没有该命令,请用户自行获取该命令所属的 RPM 包。 - - 是,请执行 3 - - 否,请用户到标准 openEuler 的 ISO 文件中获取 RPM 包。获取后,执行 2。 - 2. 将包含命令的 RPM 包放至 usr_rpm 目录下。 - 3. 在 custom/cfg_openEuler/cmd.conf 文件的 \\ 区域添加命令信息区域添加该命令信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - -#### 3.3.4、定制实例:添加库文件 - -1. 用户场景 - - 用户在添加命令或驱动时,出现了缺少库文件的问题( imageTailor 会自动报错),则需要先添加库文件。 - -2. 操作步骤 - - 1. 确认该库文件属于的 RPM 包名称。如果库文件中没有,则代表 repos 源中没有该库文件,请用户自行获取该库文件。 - - 是,请执行 3 - - 否,请用户到标准 openEuler 的 ISO 文件中获取 RPM 包。获取后,执行 2。 - 2. 将包含库文件的 RPM 包放至 usr_rpm 目录下。 - 3. 在 custom/cfg_openEuler/cmd.conf 文件的 \\ 区域添加命令信息区域添加该库文件信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - -#### 3.3.5、参考:hook 目录说明 - -hook 在 linux 中指钩子函数,由 OS 在启动和安装过程中调用,执行钩子函数中定义的动作。 - -hook 目录为 custom/cfg_openEuler/usr_install/hook/,openEuler 在该目录下规划了子目录, -每个子目录代表 OS 启动和安装的不同阶段,用户将脚本放在子目录下,OS 则会在相应的阶段调用该脚本。 - -- 表 hook 目录说明 - - | hook 目录 | 脚本命名规则 | hook 脚本形式 | hook 执行点 | 说明 | - | :--- | :--- | :--- |:--- | :--- | - | insmod_drv_hook | 如下
脚本命名规则 | 无 | 加载OS驱动之后 | 无 | - | custom_install_hook | | eg:
S01custom_install.sh | 驱动加载完成后 | 用户可以自定义安装过程,不需要使用 OS 默认安装流程。如果用户不添加脚本,openEuler 采用自己默认的安装流程。 | - | env_check_hook | | eg:
S01check_hw.sh
S02get_hwtype.sh | 安装初始化之前 | 初始化之前检查硬件配置规格、获取硬件类型。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | set_install_ip_hook | | eg:
S01set_install_ip.sh | 安装初始化过程中,配置网络时 | 用户根据自身组网,自定义网络配置。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | before_partition_hook | | eg:
S01checkpart.sh $part_conf_file(分区配置文件路径) | 在分区前调用 | 用户可以在分区之前检查分区配置文件是否正确。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | before_setup_os_hook | | 无 | 解压repo之前 | 用户可以进行自定义分区挂载操作。
如果安装包解压的路径不是分区配置中指定的根分区。则需要用户自定义分区挂载,并将解压路径赋值给传入的全局变量。
使用方法:eval $1=待解压的路径 | - | before_mkinitrd_hook | | eg:
S01install_drv.sh | 执行 mkinitrd 操作之前 | initrd 放在硬盘的场景下,执行 mkinitrd 操作之前的 hook。用户可以进行添加、更新驱动文件等自定义操作。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | after_setup_os_hook | | 无 | 安装完系统之后 | OS 包解压到硬盘之后的 hook,用户可以进行系统文件的自定义操作,包括修改 grub.cfg 等 | - | install_succ_hook | | 无 | 系统安装流程成功结束 | 用户执行解析安装信息,回传安装是否成功等操作。install_succ_hook 不可以设置为 install_break。 | - | install_fail_hook | | 无 | 系统安装失败 | 用户执行解析安装信息,回传安装是否成功等操作。install_fail_hook 不可以设置为 install_break。 | - -- 脚本命名规则:用户可自定义脚本名称(支持多个),必须以 S+ 数字开头,一位数前面补 0,代表 hook 脚本执行顺序。脚本名称格式示例:S01xxx.sh - ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->- hook 目录下的钩子脚本是通过 source 方式调用,所以脚本中需要谨慎使用 exit 命令,因为调用 exit 命令之后,整个安装的脚本程序也同步退出了。 - -### 3.4、配置系统参数 - -配置系统参数包含:主机参数、分区、网络和编译参数。 - -系统参数都在 custom/cfg_openEuler/sys.conf 文件中。 - -#### 3.4.1、配置主机参数 - -为了确保 OS 安装成功,需要配置主机参数,例如:主机名、内核启动参数。 - -在 sys.conf 文件的 \\ 区域配置系统常用参数。 - -- openEuler 提供的默认配置如下: - - ``` - - sys_service_enable='ipcc' - sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' - sys_utc='yes' - sys_timezone='' - sys_cut='no' - sys_usrrpm_cut='no' - sys_hostname='Euler' - sys_usermodules_autoload='' - sys_gconv='GBK' - - ``` - 参数说明请参见下表1 - -- 表1 sysconfig 系统参数说明 - - | 参数 | 说明 | 取值范围 | 默认值 | 是否必配 | - | :--- | :--- | :--- |:--- | :--- | - | sys_service_enable | OS 默认启用的服务,如果有多个服务请以空格分开。请注意
以下几点:

- 只能在默认配置的基础上增加系统服务,不能删减系统
服务。

- 可以配置业务相关的服务。需要先按照 3.3-定制业务包 中描述的方法将业务 RPM 包打包至 OS 中 sys_usrrpm_cut,然后才能在此处配置。

- 默认只开启该配置文件中的服务,如果服务需要依赖
其他服务,需要将依赖的服务也配置在该参数中。

| 无 | "ipcc" | 选配。如果用户没有新增的系
统服务,请保持默认值。 | - | sys_service_disable | 禁止服务开机自启动,用法参考 sys_service_enable。 | 无 | 无 | 选配。如果用户没有禁用的系
统服务,请保持默认值 | - | sys_utc | 是否采用 UTC 时间。 | yes: 是
no: 否 | yes | 必配 | - | sys_timezone | 设置时区,即该单板所处的时区。 | 查询 openEuler 支持的时区,请在制作 OS 的机器上查看 /usr/share/zoneinfo/zone.tab 文件。 | RPC: 中国 | 选配 | - | sys_cut | 是否裁剪。

- 裁剪版的 OS 会先安装 rpm.conf 中的 RPM 包,然后卸载掉 cmd.conf 中不包含的命令和库文件,
最后卸载掉 rpm.conf中
\\ 区域的 RPM 包。

**说明:** imageTailor 工具不支持 RPM 管理包本身的安装,
即使用户在 rpm.conf 中配置了 RPM 包本身,imageTailor 工具也不会安装。

- 不裁剪版的 OS 仅安装 rpm.conf 中的 RPM 包,不再做其他操作。
用户根据业务需要决定是否裁剪。

| - yes:裁剪
- no: 不裁剪
- debug: 裁剪但是会保留 RPM 命令本身
该参数和 sys_usrrpm_cut 参数的具体含义请参见表后的
sys_cut 和 sys_usrrpm_cut 参数说明。
| 'no' | 必配 | - | sys_usrrpm_cut | 是否裁剪用户添加的 RPM 包中的指定文件。

- 裁剪:imageTailor 工具会先安装用户添加的 RPM 包,再删除掉 cmd.conf
中 \ 区域的文件。最后会删除掉
cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。

- 不裁剪:imageTailor 工具会安装用户添加的 RPM 包,不删除用户 RPM 包中的文件。

**须知:** 在不裁剪的情况下,当用户自己制作的 RPM 包中有安装过程中生成的文件,需要在 cmd.conf 或 rpm.conf 中配置,避免 imageTailor 将其删除。

用户根据业务需要决定是否裁剪 | - yes:裁剪
- no: 不裁剪
该参数和 sys_usrrpm_cut 参数的具体含义请参见表后的
sys_cut 和 sys_usrrpm_cut 参数说明。
| 'no' | 必配 | - | sys_hostname | 主机名。当用户大批量部署 OS 时,建议部署成功
后,修改每个节点的主机名,确保不重复。 | 主机名请按照以下要求输入:可以是字母、数字、
"-" 的组合。字符支持大小写。字符个数小于等于 63。
首字符必须是字母或数字。 | 'Euler' | 必配 | - | sys_usermodules_autoload | 系统启动阶段加载的驱动,输入该参数的值时,请去
掉后缀名 .ko。如果有多个驱动,请以空格分开。 | 无 | 无 | 选配 | - | sys_gconv | 该参数用于定制 /usr/lib/gconv, /usr/lib64/gconv。 | - null/NULL:表示不配置,为空,如果系统裁
剪,/usr/lib/gconv, /usr/lib64/gconv 就会被删除。

- all/ALL:/usr/lib/gconv, /usr/lib64/gconv 不裁剪。

- xxx,xxx: 保留 /usr/lib/gconv, /usr/lib64/gconv 目录下对应的文件,如果多个,可用逗号 "," 分隔。
| 默认不配置,会被裁剪。 | 选配 | - | sys_man_cut | 该参数用来指定是否裁剪 man 文档。 | yes:裁剪 man 文档
no:不裁剪man文档 | yes | 选配 | - -- sys_cut 和 sys_usrrpm_cut 参数说明 - - 1. sys_cut="no": - - sys_usrrpm_cut="no" 或 sys_usrrpm_cut="yes" - - 系统 RPM 包裁剪粒度:imageTailor 会安装 repo 源中的 RPM 包和 usr_rpm 目录下的 RPM 包,但不会裁剪 RPM 包中的文件。 - 即使这些 RPM 包中的部分文件,用户不想要,imageTailor 也不会进行裁剪。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 默认值为 no,请不要修改此参数,可能会导致裁剪出来的 ISO 安装失败。若需要配置成 yes/debug ,请与 openEuler 联系。 - - 2. sys_cut="yes": - - 1. sys_usrrpm_cut="no" - - 系统 RPM 包文件裁剪粒度:imageTailor 会根据用户配置,裁剪 repo 源中 RPM 包的文件。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 区域内容,裁剪掉未配置的驱动。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的命令。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的库文件。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉配置的文件。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 即使用户 RPM 包中的驱动、命令和库文件没有配置在配置文件中,imageTailor 也不会裁剪,会保留 usr_rpm 目录中所有 RPM 包的完整性。 - - 2. sys_usrrpm_cut="yes" - - 系统和用户 RPM 包文件裁剪粒度:imageTailor 会根据用户的配置,裁剪 repo 源和 usr_rpm 目录中 RPM 包的文件。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 区域内容,裁剪掉未配置的驱动。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的命令。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的库文件。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉配置的文件。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 内容,卸载掉配置的 RPM 包。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 如果用户 RPM 包中的驱动、命令和库文件没有配置在配置文件中,则 imageTailor 会进行裁剪。 - - -#### 3.4.2、配置初始密码 - -##### 3.4.2.1、配置 root 初始密码 - -配置 root 初始密码需要在 "custom/cfg_openEuler/rpm.conf" 中填写相应信息: - -用户需要在该文件中配置 root 初始密码,否则,裁剪得到的 ISO 在安装后无法使用 root 账号进行登录。 - -1. 默认配置 - - 在 rpm.conf 中有以下配置项: - ``` - - - - ``` - 参数说明: - - group 为用户所属组。 - - pwd 为用户初始密码的加密密文,加密算法为 SHA-512。${pwd} 需要替换成用户实际的加密密文,生成方式参见下文 修改初始密码 部分。 - - home 为用户的家目录。 - - name 为要配置用户的用户名。 - -2. 修改初始密码 - - 如果用户在做包时想修改 root 用户的初始密码,请按照如下步骤操作(需使用 root 权限): - 1. 选择一台安装有 openEuler 的环境上。 - 2. 添加用户 user。 - 3. 通过 passwd 命令设置 user 密码。 - 4. 查看 /etc/shadow 文件,拷贝其中的内容,替换 rpm.conf 中的 pwd 字段。 - 5. 脚本如下: - ``` shell script - $ sudo useradd testx - $ - $ sudo passwd testx - Changing password for user testx. - New password: - Retype new password: - passwd: all authentication tokens updated successfully. - $ - $ sudo cat /etc/shadow | grep testx - testx:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: - ``` - -##### 3.4.2.2、配置 grub2 初始密码 - -配置grub2初始密码需要在 custom/cfg_openEuler/usr_file/etc/default/grub 中填写相应信息: - -1. 配置初始密码 - - 在 usr_file/etc/default/grub 文件中增加以下配置项 - ``` - GRUB_PASSWORD=${pwd} - ``` - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 密码默认用户为 root。 - >- ${pwd} 需要替换成用户实际的加密密文,密文的首尾请勿使用引号,否则会造成系统安装后无法修改 grub2 密码。 - >- 若用户未配置 grub2 初始密码,会导致:裁剪后的 ISO 安装失败。 - -2. 修改初始密码 - - 如果用户在做包时想设置 grub2 的初始密码,请按照如下步骤操作(需使用 root 权限): - 1. 选择一台安装有 grub2-set-password 命令的环境上。 - 2. 执行 "grub2-set-password -o ./" 命令,设置密码。 - 3. 查看当前目录下的 user.cfg 文件中,复制文件内以 grub.pbkdf2.sha512 开头的密文,替换 grub 文件中的 ${pwd} 字段。 - 4. 脚本如下: - ``` shell script - $ sudo grub2-set-password -o ./ - Enter password: - Confirm password: - grep: .//grub.cfg: No such file or directory - WARNING: The current configuration lacks password support! - Update your configuration with grub2-mkconfig to support this feature. - $ - $ ll - total 4.0K - -rw-------. 1 root root 298 Mar 1 20:54 user.cfg - $ - $ sudo cat user.cfg - GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 - B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 - 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 - ``` - -#### 3.4.3、配置分区 - -用户可以根据业务规划配置业务分区,同时可以调整系统分区。 - ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->- 系统分区:存放操作系统的分区 ->- 业务分区:存放业务数据的分区 ->- 差别:在于存放的内容,而每个分区的大小、挂载路径和文件系统类型都不是区分业务分区和系统分区的依据。 ->- 配置分区为可选项,用户也可以在安装 OS 之后,手动配置分区 - -1. 用户可以在 "custom/cfg_openEuler/sys.conf" 文件中的 \ 中配置分区 - -2. 分区配置 - - 配置格式: - hd磁盘号 挂载路径 分区大小 分区类型 文件系统类型 - - eg: - ``` shell script - - hd0 /boot 512M primary ext4 yes - hd0 /boot/efi 200M primary vfat yes - hd0 / 30G primary ext4 - hd0 - - extended - - hd0 /var 1536M logical ext4 - hd0 /home max logical ext4 - - ``` - -3. 参数说明 - - 磁盘号: - 磁盘的编号。请按照 hdx 的格式填写,x 指第 x 块盘 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区配置只在被安装机器的磁盘能被识别时才有效。 - - - 挂载路径: - 指定分区挂载的路径。用户既可以配置业务分区,也可以对默认配置中的系统分区进行调整。如果不挂载,则设置为 '-'。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区配置中必须有 '/' 挂载路径。其他的请用户自行调整。 - >- 采用 UEFI 引导时,在 X86_64 的分区配置中必须有 '/boot' 挂载路径,在 AArch64 的分区配置中必须有 '/boot/efi' 挂载路径。 - - - 分区大小: - 分区大小的取值有以下四种: - - G/g:指定以 G 为单位的分区大小,例如:2G。 - - M/m:指定以 M 为单位的分区大小,例如:300M。 - - T/t:指定以 T 为单位的分区大小,例如:1T。 - - MAX/max:指定将硬盘上剩余的空间全部用来创建一个分区。只能在最后一个分区配置该值。 - - extended 分区无需配置,其他分区类型必选。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区大小不支持小数,如果是小数,请换算成其他单位,调整为整数的数值。例如:不能填写 1.5G,应填写为 1536M。 - >- 分区大小取 MAX/max 值时,剩余分区大小不能超过支持文件系统类型的限制(默认文件系统类型 ext3、ext4,限制大小 16T)。 - - - 分区类型: - 分区有以下三种: - - 主分区: primary - - 扩展分区:extended - - 逻辑分区:logical - - - 文件系统类型: - 目前支持的文件系统类型有: - - ext4、vfat - - - 二次格式化标志位: - 二次安装时是否格式化。 - - 是:yes - - 否:no - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 二次格式化是指本次安装之前,磁盘已安装过 openEuler 系统。当先前一次安装跟本次安装的使用相同的分区表配置(分区大小,挂载点,文件类型)时,该标志位可以配置是否格式化之前的分区,'/boot' 和 '/' 分区除外,每次都会重新格式化。如果目标板第一次安装,则该标志位不生效,所有指定了文件系统的分区都会进行格式化。 - -#### 3.4.4、配置网络 -根据产品的组网情况,配置网络参数,例如:网卡名称、IP地址、子网掩码。 - -1. 网络参数简介: - - 在 sys.conf 文件的 \\ 中配置网络参数,netconfig-0 代表网卡 eth0。 - 如果您需要配置多块网卡,例如eth1,请在配置文件中增加 \\,并在其中填写网卡 eth1 的各项参数。 - - 参数如下: - - ``` - - BOOTPROTO="dhcp" - DEVICE="eth0" //网卡名称 - IPADDR="" //IP地址 - NETMASK="" //子网掩码 - STARTMODE="auto" //启用网卡的方法 - - ``` - -2. 网络参数说明: - - | 参数名称 | 参数值 | 说明 | 是否匹配 | - | :----- | :---- | :---- | :----| - | BOOTPROTO | none / static / dhcp | none:引导时不使用协议,不配地址
static:静态分配地址
dhcp:使用 DHCP 协议动态获取地址 | 必配 | - | DEVICE | 如 eth1 | 网卡名称 | 必配 | - | IPADDR | 如:192.168.11.100 | IP 地址
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | 必配 | - | NETMASK | 如:255.255.255.0 | 子网掩码
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | 必配 | - | STARTMODE | manual / auto / hotplug / ifplugd / nfsroot / off | 启用网卡的方法:
- manual:用户在终端执行 ifup 命令启用网卡。
- auto \ hotplug \ ifplug \ nfsroot:当 OS 识别到该网卡时,便启用该网卡。
- off:任何情况下,网卡都无法被启用。
各参数更具体的说明请在制作 OS 的机器上执行 man ifcfg 命令查看。 | 必配 | - -#### 3.4.5、配置系统命令行参数 - -根据服务器规格( CPU 个数,内存大小等),用户需要修改系统命令行参数,使主机能够更加稳定、高效的运行。 - -1. 配置说明 - - 在 custom/cfg_openEuler/usr_file/etc/default/grub 中的 "GRUB_CMDLINE_LINUX" 中配置内核命令行参数。 - - ``` - GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" - ``` - -2. 参数介绍 - - - net.ifnames=0 biosdevname=0,以传统方式命名网卡,比如 eth0、eth1。 - - crashkernel=512M,为 kdump 预留的内存空间大小。 - - oops=panic panic=3,内核 oops 时直接 panic,并且 3 秒后重启系统。 - - softlockup_panic=1,在检测到软死锁(soft-lockup)的时候让内核 panic。 - - reserve_kbox_mem=16M,为 kbox 预留的内存空间大小。 - - console=tty0,指定第一个虚拟控制台 tty0 为输出设备。 - - crash_kexec_post_notifiers,系统 crash 后,先调用注册到 panic 通知链上的函数,再执行 kdump。 - - 其余常见的系统命令行参数请查阅内核相关文档。 - - -### 3.5、制作OS - -当确认已完成定制后,执行 mkdliso 脚本制作 OS。imageTailor 制作出的 OS 为 ISO 镜像文件(iso 格式)。 - -请在 mkdliso 所在的目录下执行该脚本(需使用 root 权限): - -``` -$ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h] -``` - -> **须知:** -> ->- mkdliso 所在的绝对路径中不能有空格,否则会导致制作 OS 失败。 ->- 制作 OS 的环境上,umask 的值必须设置为 0022。 - -1. 参数说明 - - | 参数名称 | 是否必选 | 参数含义 | 取值范围 | - | :----- | :---- | :---- | :---- | - | -p | Y | 设置产品名称 | openEuler | - | -c | Y | 指定配置文件的相对路径 | custom/cfg_openEuler | - | --minios | N | 制作在系统安装时进行系统引导的 initrd | 默认为 yes
- yes:第一次执行命令时会制作 initrd,之后执行命令会判断 'usr_install/boot'
目录下是否存在 initrd(sha256 校验)。如果存在,就不重新制作 initrd。
- no:不制作 initrd,采用原有方式,系统引导和运行使用的 initrd 相同。
- force:强制制作 initrd,不管 'usr_install/boot' 目录下是否存在 initrd。 | - | --sec | N | 表示是否进行安全加固
如果用户不输入该参数,则由此造成的安全风险由用户去承担 | 无 | - | -h | N | 获取帮助信息 | 无 | - -2. 示例 - - ``` - sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --sec - ``` - -3. 获取和验证 OS - - 制作出的 ISO 文件在 result/{日期} 目录下获取, - 目录下有两个新生成的文件:openEuler-aarch64.iso 和 openEuler-aarch64.iso.sha256。 - - sha256 文件用于验证 iso 文件是否完整。操作如下 - ``` - $ sha256sum -c openEuler-aarch64.iso.sha256 - openEuler-aarch64.iso: OK # 表示OS完整 - ``` - 当有如下显示时,表示 ISO 不完整: - ``` - $ sha256sum -c openEuler-aarch64.iso.sha256 - openEuler-aarch64.iso: FAILED - sha256sum: WARNING: 1 computed checksum did NOT match - ``` - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- sha256 文件只能验证 ISO 文件的完整性,如果校验成功说明文件完整性没有破坏,可以使用;如果校验失败则可以确认文件完整性已被破坏,需要重新获取。 - -4. 查看日志 - -每一次制作 OS 时,制作 OS 的日志和安全加固日志被压缩为一个 tar 包,存放在 result/log 目录下。 - -日志命名格式为:sys_custom_log_{日期}.tar.gz。 -log 目录下的日志只保留 50 个,若超过 50 个则覆盖最旧的压缩包。 - -### 3.6、时区裁剪 - -openEuler 的用户可以根据自己的需求来对系统支持的时区进行裁剪。本节内容主要包括时区裁剪的方法以及当前 openEuler 支持的时区列表。 - -#### 3.6.1、裁剪方法 - -1. 系统中所有的时区信息均存放于时区文件夹: - - ``` - $ ls /usr/share/zoneinfo/ - Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ - Pacific/ zone.tab - ``` - 其中每一个子文件夹代表了一个 "Area"。当前 "Area" 包括了三类:大陆、海洋以及 "Etc"。 - 每个 "Area" 文件夹内部则包含了隶属于其的 "Location"。一个 "Location" 一般为一座城市或者一个岛屿。 - 所有时区均以 "Area/Location" 的形式来表示,比如中国大陆南部使用北京时间,其时区为 "Asia/Shanghai"(Location 并不一定会使用首都),对应的,其时区文件为: - ``` - /usr/share/zoneinfo/Asia/Shanghai - ``` - 若用户希望裁剪某些时区,则只需将这些时区对应的时区文件删除即可。 - - -### 3.7、裁剪流程使用实例 - -以 openEuler 22.03 LTS, x86_64 机器为例。sudo 部分即为需要 root 权限 - -1. 检查当前环境 - - ``` - $ cat /etc/openEuler-release - openEuler release 22.03 LTS - ``` - -2. 配置 yum 源,使 yum 源生效 - - yum 源要求使用 everything 的源 - ``` - $ yum clean all && yum makecache - ``` - -3. 添加磁盘,保证 '/opt' 或 '/' 有 40 GB 以上空间 - - 此处以 /dev/vdb 挂载 /opt 为例 - ``` - $ sudo mkfs.ext4 /dev/vdb - $ mkdir -p /opt - $ sudo mount /dev/vdb /opt - $ - $ df -h - Filesystem Size Used Avail Use% Mounted on - ...... - /dev/vdb 196G 28K 186G 1% /opt - ``` - -4. 安装 imageTailor 裁剪工具(imageTailor) - - ``` - $ sudo yum install -y imageTailor - $ ll /opt/imageTailor/ - total 88K - drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom - drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi - -r-x------. 1 root root 69K Mar 3 08:00 mkdliso - drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos - drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool - $ - ``` - -5. 配置 RPM 包 - - 以 openEuler 发布 iso 的 RPM 包为例。如果用户需要添加或删除 RPM 包,请参考 3.3、定制业务包 。 - ``` - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-x86_64-dvd.iso /opt/openEuler_repo - mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. - $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base - $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base - $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base - $ sudo ls /opt/imageTailor/repos/euler_base|wc -l - 2577 - $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo && sudo rm -rf openEuler-22.03-LTS-x86_64-dvd.iso - $ cd /opt/imageTailor - ``` - -6. 修改 grub/root 密码 - - grub/root 密码配置与 3.4.2、配置初始密码 - ``` - $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub # 添加以下字符串在文末 - GRUB_PASSWORD="grub.pbkdf2.sha512.10000.D4D775602C4E9F76EF4A9A6E726486941C8AAFB4762227E6973690ED5A760D59247E7E6ECA72472FBEEBFD9DB60F8EE56A4078094542C790BF0967879BE2D60C.B2742F38995B4B716EA7B0E639D02BE6C4E649E30576E5F5505B85844172B831841DA80D264FD14B025F3C8804158E7FC082998664BD03A92663FB4CE293807B" - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' custom/cfg_openEuler/rpm.conf - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' kiwi/minios/cfg_minios/rpm.conf - # 以下命令仅 x86_64 需要修改 - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' kiwi/minios/cfg_minios_efi/rpm.conf - ``` - -7. 执行裁剪命令 - - ``` - $ sudo rm -rf /opt/imageTailor/result - $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force - ...... - Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso - move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz - $ ll result/2022-03-09-15-31/ - total 889M - -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso - -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 - ``` diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG b/docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG deleted file mode 100644 index 2309b8f37bdbe58916f235f29422f7cb703789d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17428 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 O(#z+H(#24tfd3EsF-oKW diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/drivers.png b/docs/zh/docs/TailorCustom/public_sys-resources/drivers.png deleted file mode 100644 index 1bb43150cde548a5d6cf227aed5c354cbb31ec89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7060 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 diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/tools.png b/docs/zh/docs/TailorCustom/public_sys-resources/tools.png deleted file mode 100644 index b7bf100e26359588985a8703275832254cdb33e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2992 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 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cb3b360db..ebf263c19 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -214,5 +214,5 @@ headless: true - [http接口文档]({{< relref "./docs/rubik/http接口文档.md" >}}) - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) + - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) - [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) -- Gitee From 2c8ef7e9f6044724dec660f69fe2d1a0b3aec807 Mon Sep 17 00:00:00 2001 From: Poorunga <2744323@qq.com> Date: Thu, 31 Mar 2022 11:03:31 +0800 Subject: [PATCH 11/42] modify app version in kubeedge docs --- ...Edge\351\203\250\347\275\262\346\214\207\345\215\227.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" "b/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" index ec91c0ddd..12babcdc6 100644 --- "a/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" @@ -20,9 +20,9 @@ iSulad 是一个轻量级容器 runtime 守护程序,专为 IOT 和 Cloud 基 | 组件 | 版本 | | ---------- | --------------------------------- | -| OS | openEuler 21.09 | +| OS | openEuler 22.03 | | Kubernetes | 1.20.2-4 | -| iSulad | 2.0.9-20210625.165022.git5a088d9c | +| iSulad | 2.0.11 | | KubeEdge | v1.8.0 | ### 节点规划(示例) @@ -64,7 +64,7 @@ $ ./setup-cloud.sh > 提示:在云侧节点可以访问外网的条件下建议优先选用 `kubeadm` 工具部署 k8s,示例: ```bash -$ kubeadm init --apiserver-advertise-address=云侧IP --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +$ kubeadm init --apiserver-advertise-address=云侧IP --kubernetes-version v1.20.15 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock ... Your Kubernetes control-plane has initialized successfully! ... -- Gitee From aa6d2b445e5ef2defdb684ca408437575d3c40f0 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Thu, 31 Mar 2022 14:24:15 +0800 Subject: [PATCH 12/42] update imagetailor menu --- ...77\347\224\250\346\214\207\345\215\227.md" | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" index f7b29e358..3902c6e0b 100644 --- "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -1,18 +1,18 @@ # imageTailor 使用指南 - [简介](#简介) -- [安装工具](# 安装工具) +- [安装工具](#安装工具) - [软硬件要求](#软硬件要求) - [获取安装包](#获取安装包) - - [安装 imageTailor](#安装 imageTailor) + - [安装 imageTailor](#安装-imageTailor) - [目录介绍](#目录介绍) - [定制系统](#定制系统) - [总体流程](#总体流程) - [定制业务包](#定制业务包) - - [配置本地 repo 源](#配置本地 repo 源) + - [配置本地 repo 源](#配置本地-repo-源) - [添加文件](#添加文件) - - [添加 RPM 包](#添加 RPM 包) - - [添加 hook 脚本](#添加 hook 脚本) + - [添加 RPM 包](#添加-RPM-包) + - [添加 hook 脚本](#添加-hook-脚本) - [配置系统参数](#配置系统参数) - [配置主机参数](#配置主机参数) - [配置初始密码](#配置初始密码) @@ -229,18 +229,16 @@ imageTailor 工具安装完成后,工具包的目录结构如下: 定制 ISO 操作系统镜像,必须在 /opt/imageTailor/repos/euler_base/ 目录配置 repo 源。本节主要介绍配置本地 repo 源的方法。 -以 openEuler 发布 ISO 的 RPM 包为例。 - -1. 下载 openEuler 发布的 ISO 。 +1. 下载 openEuler 发布的 ISO (必须使用 openEuler 发布 everything 版本镜像 的 RPM 包)。 ```shell $ cd /opt - $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso ``` 2. 创建挂载目录 /opt/openEuler_repo ,并挂载 ISO 到该目录 。 ```shell $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. ``` @@ -446,7 +444,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: 必选配置。是否裁剪 RPM 包。可配置为 yes、no 或者 debug 。yes 表示裁剪,no 表示不裁剪(仅安装 rpm.conf 中的 RPM 包),debug 表示裁剪但会保留 `rpm` 命令方便安装后定制。默认值为 no 。 - > ![](.\public_sys-resources\icon-note.gif)说明: + >![](./public_sys-resources/icon-note.gif) 说明: > > - imageTailor 工具会先安装用户添加的 RPM 包,再删除 cmd.conf > 中 \ 区域的文件,最后删除 @@ -485,7 +483,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: -> ![](.\public_sys-resources\icon-note.gif)说明: +>![](./public_sys-resources/icon-note.gif) 说明: > > sys_cut 和 sys_usrrpm_cut 同时配置时,sys_cut 优先级更高,即遵循如下原则: > @@ -512,7 +510,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: > ![](./public_sys-resources/icon-note.gif)说明: > -> root 初始密码和 grub2 初始密码,必须由用户自行配置。 +> root 初始密码和 grub 初始密码,必须由用户自行配置。 ##### 配置 root 初始密码 @@ -581,18 +579,18 @@ root 初始密码保存在 "/opt/imageTailor/custom/cfg_openEuler/rpm.conf" 中 ``` -##### 配置 grub2 初始密码 +##### 配置 grub 初始密码 -grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub2 初始密码。如果未配置 grub2 初始密码,制作 ISO 镜像会失败。 +grub 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub 初始密码。如果未配置 grub 初始密码,制作 ISO 镜像会失败。 > ![](./public_sys-resources/icon-note.gif)说明: > -> - 配置 gurb2 初始密码需要使用 root 权限。 -> - grub2 密码对应的默认用户为 root 。 +> - 配置 grub 初始密码需要使用 root 权限。 +> - grub 密码对应的默认用户为 root 。 > > - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 -1. 执行如下命令,根据提示设置 grub2 密码: +1. 执行如下命令,根据提示设置 grub 密码: ```shell $ sudo grub2-set-password -o ./ @@ -603,7 +601,7 @@ grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/d Update your configuration with grub2-mkconfig to support this feature. ``` -2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub 加密密码。 ```shell $ sudo cat user.cfg @@ -788,7 +786,7 @@ GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic soft 使用 mkdliso 制作 ISO 镜像的操作步骤如下: -> ![](.\public_sys-resources\icon-note.gif)说明: +>![](./public_sys-resources/icon-note.gif) 说明: > > - mkdliso 所在的绝对路径中不能有空格,否则会导致制作 ISO 失败。 > - 制作 ISO 的环境中,umask 的值必须设置为 0022。 @@ -871,8 +869,8 @@ Pacific/ zone.tab 3. 安装 imageTailor 裁剪工具。具体安装方法请参见 [安装工具](#安装工具) 章节。 - ```shell -$ sudo yum install -y imageTailor + ```shell + $ sudo yum install -y imageTailor $ ll /opt/imageTailor/ total 88K drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom @@ -885,9 +883,9 @@ $ sudo yum install -y imageTailor 4. 配置本地 repo 源。 ```shell -$ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base @@ -924,12 +922,12 @@ $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.0 $ sudo rm -rf /opt/imageTailor/result $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force ...... - Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso + Complete release iso file at: result/2022-03-09-15-31/openEuler-aarch64.iso move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz $ ll result/2022-03-09-15-31/ total 889M - -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso - -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-aarch64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-aarch64.iso.sha256 ``` -- Gitee From 6d6610074c44fce83c7d62f9224689b9c1138518 Mon Sep 17 00:00:00 2001 From: wuchangsheng Date: Wed, 30 Mar 2022 16:55:23 +0800 Subject: [PATCH 13/42] modify Gazelle doc standard --- .../gazelle.md => Gazelle/Gazelle.md} | 260 ++++++++---------- docs/zh/menu/index.md | 2 +- 2 files changed, 123 insertions(+), 139 deletions(-) rename docs/zh/docs/{gazelle/gazelle.md => Gazelle/Gazelle.md} (42%) diff --git a/docs/zh/docs/gazelle/gazelle.md b/docs/zh/docs/Gazelle/Gazelle.md similarity index 42% rename from docs/zh/docs/gazelle/gazelle.md rename to docs/zh/docs/Gazelle/Gazelle.md index 8ea1f3e52..61f298c06 100644 --- a/docs/zh/docs/gazelle/gazelle.md +++ b/docs/zh/docs/Gazelle/Gazelle.md @@ -1,88 +1,75 @@ -# gazelle +# 用户态协议栈Gazelle用户指南 -## Introduction -gazelle是高性能的用户态协议栈,通过dpdk在用户态直接读写网卡报文,共享大页内存传递报文,并使用轻量级lwip协议栈。能够大幅提高应用的网络IO吞吐能力. +## 简介 -## Compile -- 编译依赖软件包 -cmake gcc-c++ lwip dpdk-devel(>=21.11-2) -numactl-devel libpcap-devel libconfig-devel libboundscheck rpm-build -- 编译 -``` sh -#创建目录 -mkdir -p ~/rpmbuild/SPECS -mkdir -p ~/rpmbuild/SOURCES - -#创建压缩包 -mkdir gazelle-1.0.0 -mv build gazelle-1.0.0 -mv src gazelle-1.0.0 -tar zcvf gazelle-1.0.0.tar.gz gazelle-1.0.0/ - -#编包 -mv gazelle-1.0.0.tar.gz ~/rpmbuild/SPECS -cp gazelle.spec ~/rpmbuild/SPECS -cd ~/rpmbuild/SPECS -rpmbuild -bb gazelle.spec - -#编出的包 -ls ~/rpmbuild/RPMS -``` +Gazelle是一款高性能用户态协议栈。它基于DPDK在用户态直接读写网卡报文,共享大页内存传递报文,使用轻量级LwIP协议栈。能够大幅提高应用的网络I/O吞吐能力。专注于数据库网络性能加速,如MySQL、redis等。 +- 高性能 +报文零拷贝,无锁,灵活scale-out,自适应调度。 +- 通用性 +完全兼容POSIX,零修改,适用不同类型的应用。 -## Install -``` sh +单进程且网卡支持多队列时,只需使用liblstack.so有更短的报文路径。其余场景使用ltran进程分发报文到各个线程。 + +## 安装 +配置openEuler的yum源,直接使用yum命令安装 +```sh #dpdk >= 21.11-2 yum install dpdk yum install libconfig -yum install numacttl +yum install numactl yum install libboundscheck yum install libpcap yum install gazelle - ``` -## Use -### 1. 安装ko模块 +## 使用方法 +配置运行环境,使用Gazelle加速应用程序步骤如下: +### 1. 使用root权限安装ko +根据实际情况选择使用ko,提供虚拟网口、绑定网卡到用户态功能。 +若使用虚拟网口功能,则使用rte_kni.ko ``` sh -modprobe uio -insmod /usr/lib/modules/5.10.0-54.0.0.27.oe1.x86_64/extra/dpdk/igb_uio.ko -insmod /usr/lib/modules/5.10.0-54.0.0.27.oe1.x86_64/extra/dpdk/rte_kni.ko carrier="on" +modprobe rte_kni carrier="on" +``` +网卡从内核驱动绑为用户态驱动的ko,根据实际情况选择一种 +``` sh +#若IOMMU能使用 +modprobe vfio-pci + +#若IOMMU不能使用,且VFIO支持noiommu +modprobe vfio enable_unsafe_noiommu_mode=1 +modprobe vfio-pci + +#其它情况 +modprobe igb_uio ``` + ### 2. dpdk绑定网卡 -- 对于虚拟网卡或一般物理网卡,绑定到驱动igb_uio +将网卡绑定到步骤1选择的驱动。为用户态网卡驱动提供网卡资源访问接口。 ``` sh +#使用vfio-pci +dpdk-devbind -b vfio-pci enp3s0 + +#使用igb_uio dpdk-devbind -b igb_uio enp3s0 ``` -- 1822网卡绑定到驱动vfio-pci(由kernel提供) + +### 3. 大页内存配置 +Gazelle使用大页内存提高效率。使用root权限配置系统预留大页内存,可选用任意页大小。因每页内存都需要一个fd,使用内存较大时,建议使用1G的大页,避免占用过多fd。 +根据实际情况,选择一种页大小,配置足够的大页内存即可。配置大页操作如下: ``` sh -modprobe vfio-pci -dpdk-devbind -b vfio-pci enp3s0 -``` +#配置2M大页内存:在node0上配置 2M * 1024 = 2G +echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages -### 3. 大页内存配置 -dpdk提供了高效的大页内存管理和共享机制,gazelle的报文数据、无锁队列等都使用了大页内存。大页内存需要root用户配置。2M或1G大页按实际需要配置,推荐使用2M大页内存,该内存是本机上ltran和所有lstack可以使用的总内存,具体方法如下: -- 2M大页配置 - - 配置系统大页数量 - ``` sh - #示例:在node0上配置2M * 2000 = 4000M - echo 2000 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node2/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node3/hugepages/hugepages-2048kB/nr_hugepages - # 查看配置结果 - grep Huge /proc/meminfo - ``` -- 1G大页配置 -1G大页配置方法与2M类似 - - 配置系统大页数量 - ``` sh - #示例:在node0上配置1G * 5 = 5G - echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages - ``` +#配置1G大页内存:在node0上配置1G * 5 = 5G +echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages + +#查看配置结果 +grep Huge /proc/meminfo +``` ### 4. 挂载大页内存 -创建两个目录,分别给lstack的进程、ltran进程使用。操作步骤如下: +创建两个目录,分别给lstack的进程、ltran进程访问大页内存使用。操作步骤如下: ``` sh mkdir -p /mnt/hugepages mkdir -p /mnt/hugepages-2M @@ -92,34 +79,35 @@ mount -t hugetlbfs nodev /mnt/hugepages mount -t hugetlbfs nodev /mnt/hugepages-2M ``` -### 5. 应用程序从内核协议栈切换至用户态协议栈 -+ 一种方式:重新编译程序 -修改应用的makefile文件,使其链接liblstack.so。示例如下: -``` makefile -#在makefile中添加 -ifdef USE_GAZELLE - -include /etc/gazelle/lstack.Makefile -endif -gcc test.c -o test $(LSTACK_LIBS) +### 5. 应用程序使用Gazelle +有两种使能Gazelle方法,根据需要选择其一 +- 重新编译应用程序,链接Gazelle的库 +修改应用makefile文件链接liblstack.so,示例如下: +``` +#makefile中添加Gazelle的Makefile +-include /etc/gazelle/lstack.Makefile + +#编译添加LSTACK_LIBS变量 +gcc test.c -o test ${LSTACK_LIBS} ``` -+ 另一个方式:使用LD_PRELOAD +- 使用LD_PRELOAD加载Gazelle的库 +GAZELLE_BIND_PROCNAME环境变量指定进程名,LD_PRELOAD指定Gazelle库路径 ``` -GAZELLE_BIND_PROCNAME=test(具体进程名) LD_PRELOAD=/usr/lib64/liblstack.so ./test +GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test ``` ### 6. 配置文件 -- lstack.conf用于指定lstack的启动参数,Gazelle发布件会包括ltran.conf供用户参考,路径为/etc/gazelle/lstack.conf, 配置文件参数如下 +- lstack.conf用于指定lstack的启动参数,默认路径为/etc/gazelle/lstack.conf, 配置文件参数如下 |选项|参数格式|说明| |:---|:---|:---| |dpdk_args|--socket-mem(必需)
--huge-dir(必需)
--proc-type(必需)
--legacy-mem
--map-perfect
等|dpdk初始化参数,参考dpdk说明| |use_ltran| 0/1 | 是否使用ltran | -|num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量),仅在use_ltran=0时生效,如果机器不支持网卡多队列,lstack线程数量应该为1| -|num_weakup|"1,3,5 ..."|weakup线程绑定的cpu编号,编号的数量为weakup线程个数,与lstack线程的数量保持一致| -|numa_bind|0/1|是否支持将用户线程绑定到与某lstack线程相同numa内| +|num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量)。可按NUMA选择cpu| +|num_wakeup|"1,3,5 ..."|wakeup线程绑定的cpu编号,编号的数量为wakeup线程个数,与lstack线程的数量保持一致。与numcpus选择对应NUMA的cpu。不配置则为不使用唤醒线程| |low_power_mode|0/1|是否开启低功耗模式,暂不支持| -|kni_swith|0/1|rte_kni开关,默认为0| +|kni_swith|0/1|rte_kni开关,默认为0。只有不使用ltran时才能开启| |host_addr|"192.168.xx.xx"|协议栈的IP地址,必须和redis-server配置
文件里的“bind”字段保存一致。| |mask_addr|"255.255.xx.xx"|掩码地址| |gateway_addr|"192.168.xx.1"|网关地址| @@ -135,10 +123,8 @@ kni_switch=0 low_power_mode=0 -num_cpus="2" -num_weakup="3" - -numa_bind=1 +num_cpus="2,22" +num_wakeup="3,23" host_addr="192.168.1.10" mask_addr="255.255.255.0" @@ -146,7 +132,7 @@ gateway_addr="192.168.1.1" devices="aa:bb:cc:dd:ee:ff" ``` -- ltran.conf用于指定ltran启动的参数,Gazelle发布件会包括ltran.conf供用户参考,路径为/etc/gazelle/ltran.conf,仅在lstack.conf内配置use_ltran=1时生效,配置文件格式如下 +- ltran.conf用于指定ltran启动的参数,默认路径为/etc/gazelle/ltran.conf。使用ltran时,lstack.conf内配置use_ltran=1,配置参数如下: |功能分类|选项|参数格式|说明| |:---|:---|:---|:---| @@ -180,24 +166,26 @@ bond_macs="aa:bb:cc:dd:ee:ff" bond_ports="0x1" tcp_conn_scan_interval=10 -``` -### 7. 启动 -- 不使用ltran模式(use_ltran=0)时,不需要启动ltran -- 启动ltran,如果不指定--config-file,则使用默认路径/etc/gazelle/ltran.conf +``` +### 7. 启动应用程序 +- 启动ltran进程 +单进程且网卡支持多队列,则直接使用网卡多队列分发报文到各线程,不启动ltran进程,lstack.conf的use_ltran配置为0. +启动ltran时不使用-config-file指定配置文件,则使用默认路径/etc/gazelle/ltran.conf ``` sh ltran --config-file ./ltran.conf ``` -- 启动redis,如果不指定环境变量LSTACK_CONF_PATH,则使用默认路径/etc/gazelle/lstack.conf +- 启动应用程序 +启动应用程序前不使用环境变量LSTACK_CONF_PATH指定配置文件,则使用默认路径/etc/gazelle/lstack.conf ``` sh export LSTACK_CONF_PATH=./lstack.conf -redis-server redis.conf +LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf ``` ### 8. API -liblstack.so编译进应用程序后wrap网络编程标准接口,应用程序无需修改代码。 +Gazelle wrap应用程序POSIX接口,应用程序无需修改代码。 -### 9. gazellectl -- 不使用ltran模式时不支持gazellectl ltran xxx 命令 +### 9. 调测命令 +- 不使用ltran模式时不支持gazellectl ltran xxx命令,以及lstack -r命令 ``` Usage: gazellectl [-h | help] or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] @@ -226,54 +214,50 @@ Usage: gazellectl [-h | help] #### 1. dpdk配置文件的位置 如果是root用户,dpdk启动后的配置文件将会放到/var/run/dpdk目录下; 如果是非root用户,dpdk配置文件的路径将由环境变量XDG_RUNTIME_DIR决定; -+ 如果XDG_RUNTIME_DIR为空,dpdk配置文件放到/tmp/dpdk目录下; -+ 如果XDG_RUNTIME_DIR不为空,dpdk配置文件放到变量XDG_RUNTIME_DIR下; -+ 注意有些机器会默认设置XDG_RUNTIME_DIR +- 如果XDG_RUNTIME_DIR为空,dpdk配置文件放到/tmp/dpdk目录下; +- 如果XDG_RUNTIME_DIR不为空,dpdk配置文件放到变量XDG_RUNTIME_DIR下; +- 注意有些机器会默认设置XDG_RUNTIME_DIR -## Constraints -- 提供的命令行、配置文件以及配置大页内存需要root权限执行或修改。非root用户使用,需先提权以及修改文件权限。 -- 若要把用户态网卡绑回内核驱动,必须先将Gazelle退出。 +## 约束限制 + +使用 Gazelle 存在一些约束限制: +#### 功能约束 - 不支持accept阻塞模式或者connect阻塞模式。 -- 最多只支持20000个链接(需要保证进程内,非网络连接的fd个数小于2000个)。 -- 协议栈当前只支持tcp、icmp、arp、ipv4。 -- 大页内存不支持在挂载点里创建子目录重新挂载。 -- 在对端ping时,要求指定报文长度小于等于14000。 +- 最多支持1500个TCP连接。 +- 当前仅支持TCP、ICMP、ARP、IPv4 协议。 +- 在对端ping Gazelle时,要求指定报文长度小于等于14000B。 - 不支持使用透明大页。 -- 需要保证ltran的可用大页内存 >=1G -- 需要保证应用实例协议栈线程的可用大页内存 >=800M -- 不支持32位系统使用。 - ltran不支持使用多种类型的网卡混合组bond。 - ltran的bond1主备模式,只支持链路层故障主备切换(例如网线断开),不支持物理层故障主备切换(例如网卡下电、拔网卡)。 -- 构建X86版本使用-march=native选项,基于构建环境的CPU(Intel® Xeon® Gold 5118 CPU @ 2.30GHz)指令集进行优化。要求运行环境CPU支持SSE4.2、AVX、AVX2、AVX-512指令集。 -- 最大IP分片数为10(ping最大包长14790),TCP协议不使用IP分片。 -- sysctl配置网卡rp_filter参数为1,否则可能使用内核协议栈 -- 虚拟机网卡不支持多队列。 -- 不使用ltran模式,kni网口只支持本地通讯使用,且需要启动前配置NetworkManager不管理kni网卡 -- 虚拟kni网口的ip及mac地址,需要与lstack配置文件保持一致 - -## Security risk note -gazelle有如下安全风险,用户需要评估使用场景风险 -1. 共享内存 +- 虚拟机网卡不支持多队列。 +#### 操作约束 +- 提供的命令行、配置文件默认root权限。非root用户使用,需先提权以及修改文件所有者。 +- 将用户态网卡绑回到内核驱动,必须先退出Gazelle。 +- 大页内存不支持在挂载点里创建子目录重新挂载。 +- ltran需要最低大页内存为1GB。 +- 每个应用实例协议栈线程最低大页内存为800MB 。 +- 仅支持64位系统。 +- 构建x86版本的Gazelle使用了-march=native选项,基于构建环境的CPU(Intel® Xeon® Gold 5118 CPU @ 2.30GHz指令集进行优化。要求运行环境CPU支持 SSE4.2、AVX、AVX2、AVX-512 指令集。 +- 最大IP分片数为10(ping 最大包长14790B),TCP协议不使用IP分片。 +- sysctl配置网卡rp_filter参数为1,否则可能不按预期使用Gazelle协议栈,而是依然使用内核协议栈。 +- 不使用ltran模式,KNI网口不可配置只支持本地通讯使用,且需要启动前配置NetworkManager不管理KNI网卡。 +- 虚拟KNI网口的IP及mac地址,需要与lstack.conf配置文件保持一致 。 + +## 风险提示 +Gazelle可能存在如下安全风险,用户需要根据使用场景评估风险。 + +**共享内存** - 现状 -大页内存mount至/mnt/hugepages-2M目录,链接liblstack.so的进程初始化时在/mnt/hugepages-2M目录下创建文件,每个文件对应2M大页内存,并mmap这些文件。ltran在收到lstask的注册信息后,根据大页内存配置信息也mmap目录下文件,实现大页内存共享。 -ltran在/mnt/hugepages目录的大页内存同理。 -- 当前消减措施 -大页文件权限600,只有OWNER用户才能访问文件,默认root用户,支持配置成其它用户; -大页文件有dpdk文件锁,不能直接写或者mmap。 -- 风险点 -属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致gazelle程序crash。建议用户下的进程属于同一信任域。 -2. 流量限制 -- 风险点 -gazelle没有做流量限制,用户有能力发送最大网卡线速流量的报文到网络。 -3. 进程仿冒 -- 风险点 -合法注册到ltran的两个lstack进程,进程A可仿冒进程B发送仿冒消息给ltran,修改ltran的转发控制信息,造成进程B通讯异常,进程B报文转发给进程A等问题。建议lstack进程都为可信任进程。 - -## How to Contribute -We are happy to provide guidance for the new contributors. -Please sign the CLA before contributing. - -## Licensing -gazelle is licensed under the Mulan PSL v2. - - + 大页内存 mount 至 /mnt/hugepages-2M 目录,链接 liblstack.so 的进程初始化时在 /mnt/hugepages-2M 目录下创建文件,每个文件对应 2M 大页内存,并 mmap 这些文件。ltran 在收到 lstask 的注册信息后,根据大页内存配置信息也 mmap 目录下文件,实现大页内存共享。 + ltran 在 /mnt/hugepages 目录的大页内存同理。 +- 当前消减措施 + 大页文件权限 600,只有 OWNER 用户才能访问文件,默认 root 用户,支持配置成其它用户; + 大页文件有 DPDK 文件锁,不能直接写或者映射。 +- 风险点 + 属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致Gazelle程序crash。建议用户下的进程属于同一信任域。 + +**流量限制** +Gazelle没有做流量限制,用户有能力发送最大网卡线速流量的报文到网络,可能导致网络流量拥塞。 + +**进程仿冒** +合法注册到ltran的两个lstack进程,进程A可仿冒进程B发送仿冒消息给ltran,修改ltran的转发控制信息,造成进程B通讯异常,进程B报文转发给进程A信息泄露等问题。建议lstack进程都为可信任进程。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 344d0fdd7..efd2f5678 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -215,7 +215,7 @@ headless: true - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) -- [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) +- [Gazelle用户指南]({{< relref "./docs/Gazelle/Gazelle.md" >}}) - [NestOS用户指南]({{< relref "./docs/NestOS/overview.md" >}}) - [安装与部署]({{< relref "./docs/NestOS/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/NestOS/使用方法.md" >}}) -- Gitee From d4a93eb205654167dbcba28ee5fcfa2da88b7876 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 15:34:05 +0800 Subject: [PATCH 14/42] =?UTF-8?q?22.03-LTS=E5=88=86=E6=94=AF=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=88=B0master=E5=88=86=E6=94=AF=20=E5=88=86=E6=94=AF?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 89 +++++++++-- docs/zh/docs/Embedded/embedded.md | 4 +- ...21\350\241\214\350\257\264\346\230\216.md" | 32 ++++ ...\273\272\346\214\207\345\257\274.markdown" | 141 +---------------- ...05\344\270\216\350\277\220\350\241\214.md" | 43 ++++-- ...\273\272\346\214\207\345\257\274.markdown" | 31 ++-- ...\273\272\346\214\207\345\257\274.markdown" | 142 ++++++++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 4 - ...63\351\224\256\347\211\271\346\200\247.md" | 2 +- ...73\347\273\237\345\256\211\350\243\205.md" | 32 +++- docs/zh/menu/index.md | 7 +- 11 files changed, 333 insertions(+), 194 deletions(-) create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" rename "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" => "docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" (77%) create mode 100644 "docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" delete mode 100644 "docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 283757eed..96bc29e1e 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -5,8 +5,9 @@ - [安装SDK](#安装SDK) -- [使用SDK编译](#使用SDK编译) - +- [使用SDK编译hello world样例](#使用SDK编译hello world样例) +- [使用SDK编译内核模块样例](#使用SDK编译内核模块样例) +- ### 安装SDK @@ -14,11 +15,11 @@ 运行如下命令: -``` {.sourceCode .console} +``` sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh ``` -根据提示输入工具链的安装路径,默认路径是/opt/openeuler/\/;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 +根据提示输入工具链的安装路径,默认路径是`/opt/openeuler/\/`;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 举例如下: @@ -38,7 +39,7 @@ $ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi 运行source命令。上例中前一步执行结束最后已打印source命令,运行即可。 -``` {.sourceCode .console} +``` . /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi ``` @@ -46,13 +47,11 @@ $ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi 运行如下命令,查看是否安装成功、环境设置成功。 -``` {.sourceCode .console} +``` arm-openeuler-linux-gnueabi-gcc -v ``` -### 使用SDK编译 - -下面以使用SDK编译hello world为样例。 +### 使用SDK编译hello world样例 1. **准备代码** @@ -81,7 +80,7 @@ add_executable(hello hello.c) 进入hello.c文件所在目录,使用工具链编译,命令如下: -``` {.sourceCode .console} +``` cmake .. make ``` @@ -92,9 +91,75 @@ make 在openEuler Embedded系统中运行hello程序。 -``` {.sourceCode .console} +``` cd /tmp/myfiles/ ./hello ``` -如运行成功,则会输出\"hello world\"。 \ No newline at end of file +如运行成功,则会输出\"hello world\"。 + +### 使用SDK编译内核模块样例 + +1. **准备代码** + +以编译一个内核模块为例,运行在openEuler Embedded内核中。 + +创建一个hello.c文件,源码如下: + +```c +#include +#include + +static int hello_init(void) +{ + printk("Hello, openEuler Embedded!\r\n"); + return 0; +} + +static void hello_exit(void) +{ + printk("Byebye!"); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_LICENSE(GPL); +``` + +编写Makefile,和hello.c文件放在同一个目录: + +``` + KERNELDIR := ${KERNEL_SRC_DIR} + CURRENT_PATH := $(shell pwd) + + target := hello + obj-m := $(target).o + + build := kernel_modules + + kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean +``` + +`KERNEL_SRC_DIR` 为SDK中内核源码树的目录,该变量在安装SDK后会被自动设置。 + +2. **编译生成内核模块** + +进入hello.c文件所在目录,使用工具链编译,命令如下: + + make + +将编译好的hello.ko拷贝到openEuler Embedded系统的目录下。 + +如何拷贝可以参考前文所述使能共享文件系统场景。 + +3. **插入内核模块** + +在openEuler Embedded系统中插入内核模块: + + insmod hello.ko + +如运行成功,则会在内核日志中出现"Hello, openEuler Embedded!"。 \ No newline at end of file diff --git a/docs/zh/docs/Embedded/embedded.md b/docs/zh/docs/Embedded/embedded.md index e63829588..44412fc68 100755 --- a/docs/zh/docs/Embedded/embedded.md +++ b/docs/zh/docs/Embedded/embedded.md @@ -1,5 +1,5 @@ # openEuler Embedded 用户指南 -openEuler Embedded是基于openEuler社区面向嵌入式场景的Linux版本。由于嵌入式系统应用受到多个因素的约束,如资源、功耗、多样性等,使得面向服务器领域的Linux及相应的构建系统很难满足嵌入式场景的要求,因此业界广泛采用[Yocto](https://www.yoctoproject.org/)来定制化构建嵌入式Linux。openEuler Embedded当前也采用的Yocto构建,但实现了与openEuler其他版本代码同源,具体的构建方法请参考[SIG-Yocto](https://gitee.com/openeuler/community/tree/master/sig/sig-Yocto)下相关代码仓中的内容。 +openEuler Embedded是基于openEuler社区面向嵌入式场景的Linux版本,旨在成为一个高质量的以Linux为中心的嵌入式系统软件平台。openEuler Embedded在内核版本、软件包版本等代码层面会与openEuler其他场景的Linux保持一致,共同演进,不同之处在于针对嵌入场景的内核配置、软件包的组合与配置、代码特性补丁的不同。 -本文档主要用于介绍如何获取预先构建好的镜像,如何运行镜像,以及如何基于镜像完成基本的嵌入式Linux应用开发。使用人员需要具备基本的Linux操作系统知识。 +本文档主要用于介绍如何获取预先构建好的镜像,如何运行镜像,如何基于镜像完成基本的嵌入式Linux应用开发以及如何构建openEuler Embedded。使用人员需要具备基本的Linux操作系统知识。 diff --git "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" new file mode 100644 index 000000000..3fd5a5328 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" @@ -0,0 +1,32 @@ +# openEuler Embedded 22.03发行说明 + +openEuler Embedded 22.03是openEuler Embedded第一次正式发布,包含的内容大概如下: + +## 内核 + +- 内核升级到 5.10.0-60.17.0 + +- 内核支持Preempt-RT补丁 + +- 内核支持树莓派4B相关补丁 + +## 软件包 + +- 支持80+软件包,详见[openEuler Embedded所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) + +## 亮点特性 + +- 多OS混合部署框架的初步实现,支持openEuler Embedded和Zephyr的混合部署,详见[多OS混合部署框架](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html) +- 分布式软总线的初步集成,详见[分布式软总线](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html) + +- 安全加固指导,详见[openEuler Embedded的安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) +- 基于Preempt-RT的软实时,详见[openEuler Embedded软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) + +## 南向生态 + +- 新增树莓派4B支持,详见[openEuler Embedded树莓派系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) + +## 构建系统 + +- 初步的openEuler Embedded构建体系, 详见[快速构建指导](./快速构建指导.html) +- 容器化构建,详见[容器构建指导](./容器构建指导.html) \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index fc4974d26..f9776a511 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,143 +1,4 @@ openEuler Embedded构建指导 ===================== -本章主要介绍如何构建openEuler Embedded。 - - - -- [环境准备](#环境准备) - - [Yocto中主机端命令使用](#Yocto中主机端命令使用) - - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) - - [已安装好工具的构建容器](#已安装好工具的构建容器) -- [openEuler Embedded版本构建](#openEuler Embedded版本构建) - - [构建代码下载](#构建代码下载) - - [编译构建](#编译构建) - - [构建结果说明](#构建结果说明) - - -环境准备 --------------- - -### Yocto中主机端命令使用 - -Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: - -- Python3 \> 3.6.0 -- Git \> 1.8.3.1 -- Tar \> 1.28 - -在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 - -为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 - -Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: - -![](./public_sys-resources/hosttools.png) - -当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: - -| 工具名 | 用途 | -| ------ | ------------- | -| cmake | cmake构建工具 | -| ninjia | ninja构建系统 | - -### openEuler Embedded所需构建工具 - -- 构建OS - - [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) - -- 安装系统额外工具 - -``` -yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel -``` - -- 预编译的交叉工具链和库 - - Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: - - - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) - - [ARM64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) - -### 已安装好工具的构建容器 - -openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 - -使用者可以通过如下链接获得容器镜像直接用于编译: - -​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) - -具体构建指导请参考[openEuler Embedded容器构建指导](https://docs.openeuler.org/zh/22.03_LTS/docs/Embedded/openEuler Embedded容器构建指导.html)。 - -## openEuler Embedded版本构建 - -### 构建代码下载 - -openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: - -><顶层目录openeuler_embedded> ->├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 ->├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 - -1. 获取源码下载脚本 - - 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: - - ``` - git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler - ``` - - 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: - - - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 - - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 - - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 - -2. 通过脚本下载源码 - - - 下载最新代码: - - ``` - sh src/yocto-meta-openeuler/scripts/download_code.sh - ``` - - - 下载指定版本代码: - - ``` - sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" - ``` - - 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 - -### 编译构建 - -一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 - -编译脚本的主要流程说明: - -1. 设置PATH增加额外工具路径 -2. TEMPLATECONF指定local.conf.sample等配置文件路径 -3. 调用poky仓的oe-init-build-env进行初始化配置 -4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 -5. 在编译目录执行bitbake openeuler-image编译openEuler - Embedded的image和sdk -6. 执行完发布件在编译目录的output目录下 - -运行编译脚本,以编译标准arm架构为例,编译方法如下: - - source src/yocto-meta-openeuler/scripts/compile.sh arm-std - bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 - -### 构建结果说明 - -结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: - -| filename | description | -| --------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | -| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | -| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | -| zImage | openEuler Embedded compressed image | \ No newline at end of file +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index 8111524af..c8d5dfe0a 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -11,9 +11,10 @@ - [极简运行场景](#极简运行场景) - [使能共享文件系统场景](#使能共享文件系统场景) - [使能网络场景](#使能网络场景) - + ## 获取镜像 + 当前发布的已构建好的镜像,只支持arm和aarch64两种架构,且只支持qemu中ARM virt-4.0平台,您可以通过如下链接获得相应的镜像: - [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm):32位arm架构,ARM Cortex A15处理器 @@ -30,13 +31,13 @@ - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) - 根文件系统镜像(依据具体需求,以下二选一) - + - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - + - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 - + - SDK(Software Development Kit)工具 - + - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -44,19 +45,21 @@ 通过运行镜像,一方面您可以体验openEuler Embedded的功能,一方面也可以完成基本的嵌入式Linux开发。 --- + **注意事项** - 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 >![](./public_sys-resources/icon-note.gif) **说明:** - >后续说明以标准根文件系统为例(initrd)。 +> +>后续说明以标准根文件系统为例(initrd)。 --- qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: -``` {.sourceCode .console} +``` qemu-system-aarch64 --version ``` @@ -67,17 +70,21 @@ qemu-system-aarch64 --version 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd ``` >![](./public_sys-resources/icon-note.gif) **说明:** - >- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 - >- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 +> +>- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 +>- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 2. **检查运行是否成功** @@ -93,10 +100,13 @@ qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` @@ -104,11 +114,13 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr 2. **映射文件系统** 在openEuler Embedded启动并登录之后,需要运行如下命令,映射(mount)共享文件系统 + ``` cd /tmp mkdir host mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host ``` + 即把共享文件系统映射到openEuler Embedded的/tmp/host目录下。 3. **检查共享是否成功** @@ -119,21 +131,27 @@ mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host cd /tmp/host ls ``` + 如能发现hello_openeuler.txt,则共享成功。 ### 使能网络场景 通过qemu的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler embedded之间的网络通信。 + 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` + 2. **宿主上建立虚拟网卡** 在宿主机上需要建立名为tap0的虚拟网卡,可以借助脚本实现,创建qemu-ifup脚本,放在/etc/下,具体内容如下: @@ -142,6 +160,7 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr #!/bin/bash ifconfig $1 192.168.10.1 up ``` + 其执行需要root权限: ``` @@ -153,6 +172,7 @@ chmod a+x qemu-ifup 3. **配置openEuler embedded网卡** openEuler Embedded登陆后,执行如下命令: + ``` ifconfig eth0 192.168.10.2 ``` @@ -160,6 +180,7 @@ ifconfig eth0 192.168.10.2 4. **确认网络连通** 在openEuler Embedded中,执行如下命令: + ``` ping 192.168.10.1 ``` @@ -167,5 +188,7 @@ ping 192.168.10.1 如能ping通,则宿主机和openEuler Embedded之间的网络是连通的。 --- + >![](./public_sys-resources/icon-note.gif) **说明:** - >如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 +> +>如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" similarity index 77% rename from "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" rename to "docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 2074cf578..a0803aa14 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -9,7 +9,7 @@ openEuler Embedded容器构建指导 - [安装docker](#安装docker) - [获取容器镜像](#获取容器镜像) - [准备容器构建环境](#准备容器构建环境) -- [openEuler Embedded版本构建](#openEuler Embedded版本构建) +- [版本构建](#版本构建) - [下载源码](#下载源码) - [编译构建](#编译构建) - [构建结果说明](#构建结果说明) @@ -32,7 +32,7 @@ openEuler Embedded容器构建指导 运行如下命令,可以看到当前docker版本信息,则说明当前环境已安装docker,无需再次安装。 -``` {.sourceCode .console} +``` docker version ``` @@ -50,10 +50,10 @@ sudo yum install docker --------------- -通过docker pull命令拉取华为云中的镜像到宿主机。命令如下: +通过`docker pull`命令拉取华为云中的镜像到宿主机。命令如下: ``` -docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container ``` ### 准备容器构建环境 @@ -62,10 +62,10 @@ docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-contai #### 1.启动容器 -可通过docker run命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: +可通过`docker run`命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: ``` -docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container bash ``` 参数说明: @@ -73,9 +73,8 @@ docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedd - -i 让容器的标准输入保持打开 - -d 让 Docker 容器在后台以守护态(Daemonized)形式运行 - -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上 -- \--network 将容器连接到(host)网络 -- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest - (镜像名称:镜像版本) +- --network 将容器连接到(host)网络 +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container 指定镜像名称 - bash 进入容器的方式 #### 2.查看已启动的容器id @@ -92,7 +91,7 @@ docker exec -it 容器id bash 构建环境已准备完成,下面就可以在容器中进行构建了。 -## openEuler Embedded版本构建 +## 版本构建 ### 下载源码 @@ -144,9 +143,9 @@ bitbake openeuler-image 结果件默认生成在构建目录下的output目录下,例如上面aarch64-std的构建结果件生成在/usr1/build/output目录下,如下表: -| filename | description | -| --------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | -| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | -| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | -| zImage | openEuler Embedded compressed image | \ No newline at end of file +| filename | description | +| ---------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..1080d7193 --- /dev/null +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,142 @@ +快速构建指导 +===================== + +本章主要介绍如何构建openEuler Embedded。 + + + +- [环境准备](#环境准备) + - [Yocto中主机端命令使用](#Yocto中主机端命令使用) + - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) + - [已安装好工具的构建容器](#已安装好工具的构建容器) +- [版本构建](#版本构建) + - [构建代码下载](#构建代码下载) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +环境准备 +-------------- + +### Yocto中主机端命令使用 + +Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 + +为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 + +Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: + +![](./public_sys-resources/hosttools.png) + +当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: + +| 工具名 | 用途 | +| ------ | ------------- | +| cmake | cmake构建工具 | +| ninjia | ninja构建系统 | + +### openEuler Embedded所需构建工具 + +- 构建OS + + [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- 安装系统额外工具 + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- 预编译的交叉工具链和库 + + Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 + + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + + - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [ARM 64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + +### 已安装好工具的构建容器 + +openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 + +使用者可以通过如下链接获得容器镜像直接用于编译: + +​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +具体构建指导请参考[容器构建指导](./容器构建指导.html)。 + +## 版本构建 + +### 构建代码下载 + +openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: + +><顶层目录openeuler_embedded> +>├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 +>├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 + +1. 获取源码下载脚本 + + 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: + + - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 + - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 + - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 + +2. 通过脚本下载源码 + + - 下载最新代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - 下载指定版本代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 + +### 编译构建 + +一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 + +编译脚本的主要流程说明: + +1. 设置PATH增加额外工具路径 +2. TEMPLATECONF指定local.conf.sample等配置文件路径 +3. 调用poky仓的oe-init-build-env进行初始化配置 +4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 +5. 在编译目录执行bitbake openeuler-image编译openEuler Embedded的image和sdk +6. 执行完发布件在编译目录的output目录下 + +运行编译脚本,以编译标准arm架构为例,编译方法如下: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| ---------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" deleted file mode 100644 index f9776a511..000000000 --- "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ /dev/null @@ -1,4 +0,0 @@ -openEuler Embedded构建指导 -===================== - -本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 5ea9dcfe0..9eb473df3 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -69,7 +69,7 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 ## 嵌入式镜像 - **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 -- **多硬件支持**,新增支持树莓派作为嵌入式场景通用硬件。 +- **多硬件支持**,新增支持树莓派4B作为嵌入式场景通用硬件。 - **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 - **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 - **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index 3cf60381b..ac05dbab2 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -2,11 +2,12 @@ ## 发布件
-openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表4](#table953512211576)。 +openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)、[嵌入式镜像](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表5](#table953512211576)。 **表 1** 发布ISO列表 +

名称

描述

@@ -64,6 +65,7 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 **表 2** 虚拟机镜像 +

名称

描述

@@ -107,10 +109,22 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+**表 4** 嵌入式镜像列表 -**表 4** repo源列表 +| 名称 | 描述 | +| -------------------------------------- | ------------------------------- | +| arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | +| arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | +| arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | +| arm64/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | +| arm64/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm64/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| source-list/manifest.xml | 构建使用的源码清单 | + +**表 5** repo源列表 + + + +

目录

描述

@@ -142,6 +156,11 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03

存放虚拟机镜像

embedded_img

+

存放嵌入式镜像

+

everything

存放全量软件包源

@@ -170,11 +189,12 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+ ## 最小硬件要求 -安装 openEuler 22.03-LTS 所需的最小硬件要求如[表5](#zh-cn_topic_0182825778_tff48b99c9bf24b84bb602c53229e2541)所示。 +安装 openEuler 22.03-LTS 所需的最小硬件要求如[表6](#zh-cn_topic_0182825778_tff48b99c9bf24b84bb602c53229e2541)所示。 -**表 5** 最小硬件要求 +**表 6** 最小硬件要求

部件名称

@@ -204,9 +224,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 ## 硬件兼容性 -openEuler已验证支持的服务器和各部件典型配置请参见[表6](#zh-cn_topic_0227922427_table39822012)。openEuler后续将逐步增加对其他服务器的支持,也欢迎广大合作伙伴/开发者参与贡献和验证。openEuler当前支持的服务器可见[兼容列表](https://www.openeuler.org/zh/compatibility/)。 +openEuler已验证支持的服务器和各部件典型配置请参见[表7](#zh-cn_topic_0227922427_table39822012)。openEuler后续将逐步增加对其他服务器的支持,也欢迎广大合作伙伴/开发者参与贡献和验证。openEuler当前支持的服务器可见[兼容列表](https://www.openeuler.org/zh/compatibility/)。 -**表 6** 支持的服务器及典型配置 +**表 7** 支持的服务器及典型配置

厂商

diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 10868e4af..96a9cc64d 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -139,11 +139,12 @@ headless: true - [常见问题与解决方法]({{< relref "./docs/A-Tune/常见问题与解决方法.md" >}}) - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) + - [openEuler Embedded 22.03发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/构建指导.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) - - [openEuler Embedded容器构建指导]({{< relref "./docs/Embedded/openEuler Embedded容器构建指导.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [快速构建指导]({{< relref "./docs/Embedded/快速构建指导.md" >}}) + - [容器构建指导]({{< relref "./docs/Embedded/容器构建指导.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From b7aa50b1ed9a2a4c6a45814a1d3dd1640201defe Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 16:03:27 +0800 Subject: [PATCH 15/42] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=88=97=E8=A1=A8=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E9=94=99=E8=AF=AF=20=E4=BF=AE=E6=94=B9=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=88=97=E8=A1=A8=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- .../\347\263\273\347\273\237\345\256\211\350\243\205.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index ac05dbab2..7424d86a5 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -116,9 +116,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 | arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | | arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | | arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | -| arm64/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | -| arm64/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | -| arm64/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| arm32/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | +| arm32/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm32/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | | source-list/manifest.xml | 构建使用的源码清单 | **表 5** repo源列表 -- Gitee From 096cc7e442c142a66a7df993029dcf37861046c3 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 16:08:35 +0800 Subject: [PATCH 16/42] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=90=8D=E7=A7=B0=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=B5=8C=E5=85=A5=E5=BC=8F=E9=95=9C=E5=83=8F=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- .../\347\263\273\347\273\237\345\256\211\350\243\205.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index 7424d86a5..d013e5af0 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -116,9 +116,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 | arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | | arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | | arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | -| arm32/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | -| arm32/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | -| arm32/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| arm32/arm-std/zImage | arm架构下支持qemu的内核镜像 | +| arm32/arm-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm32/arm-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | | source-list/manifest.xml | 构建使用的源码清单 | **表 5** repo源列表 -- Gitee From 625c93d6676aaae682755679a87c4e53151cccdb Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 19:44:04 +0800 Subject: [PATCH 17/42] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A3=80=E8=A7=86?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E4=BF=AE=E6=94=B9=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84=E5=92=8C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E6=A0=87=E9=A2=98=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=8C=E8=A1=A5=E5=85=85=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E6=8C=87=E5=AF=BC=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...DK\345\272\224\347\224\250\345\274\200\345\217\221.md" | 3 ++- ...\236\204\345\273\272\346\214\207\345\257\274.markdown" | 5 ++++- ...\236\204\345\273\272\346\214\207\345\257\274.markdown" | 2 +- docs/zh/menu/index.md | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 96bc29e1e..97be7a4c3 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -7,7 +7,8 @@ - [安装SDK](#安装SDK) - [使用SDK编译hello world样例](#使用SDK编译hello world样例) - [使用SDK编译内核模块样例](#使用SDK编译内核模块样例) -- + + ### 安装SDK diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index f9776a511..eb0f6a530 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,4 +1,7 @@ openEuler Embedded构建指导 ===================== -本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 + +- 初步的openEuler Embedded构建体系, 详见[快速构建指导](./快速构建指导.html) +- 容器化构建,详见[容器构建指导](./容器构建指导.html) \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index a0803aa14..7b7fe2d22 100644 --- "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,4 +1,4 @@ -openEuler Embedded容器构建指导 +容器构建指导 ============================== 由于openEuler Embedded构建过程需要基于openEuler操作系统,且需要安装较多系统工具和构建工具。为方便开发人员快速搭建构建环境,我们将构建过程所依赖的操作系统和工具封装到一个容器中,这就使得开发人员可以快速搭建一个构建环境,进而投入到代码开发中去,避免在准备环境阶段消耗大量时间。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index ff6949735..7b9fe8426 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -139,12 +139,12 @@ headless: true - [常见问题与解决方法]({{< relref "./docs/A-Tune/常见问题与解决方法.md" >}}) - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) - - [openEuler Embedded 22.03发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) - - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) + - [构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) - [快速构建指导]({{< relref "./docs/Embedded/快速构建指导.md" >}}) - [容器构建指导]({{< relref "./docs/Embedded/容器构建指导.md" >}}) + - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) + - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From 26db81b7a797387feb93e1f85cac6c4eaf9b5b72 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:09:06 +0000 Subject: [PATCH 18/42] =?UTF-8?q?update=20README.md.=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8D=89=E8=99=AB=E6=B4=BB=E5=8A=A8=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a9fd16651..95450c2de 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ [English](./README-en.md) | 简体中文 +文档捉虫活动火热进行中,欢迎参加: +[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +[点我查看活动详情](#https://docs-bug.openeuler.sh/) + ### 介绍 Docs包含了openEuler社区的所有文档,包括发行说明、操作系统安装、管理员指南、虚拟化和容器的使用指导、A-Tune使用指导和应用开发指导等内容。 -- Gitee From e846c2741179e93ceda1d535aaaaac491a86cc35 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:11:18 +0000 Subject: [PATCH 19/42] update README.md. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95450c2de..4b0d8ce61 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [English](./README-en.md) | 简体中文 文档捉虫活动火热进行中,欢迎参加: -[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +
[点我查看活动详情](#https://docs-bug.openeuler.sh/) ### 介绍 -- Gitee From cec993bd0a0f6d93d000d05db75438dda7b3ccf1 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:12:45 +0000 Subject: [PATCH 20/42] update README.md. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4b0d8ce61..7f0c1d1b1 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ [English](./README-en.md) | 简体中文 文档捉虫活动火热进行中,欢迎参加: -[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) -
-[点我查看活动详情](#https://docs-bug.openeuler.sh/) +[点我马上开启文档捉虫](https://docs.openeuler.org/zh/) +
+[点我查看活动详情](https://docs-bug.openeuler.sh/) ### 介绍 -- Gitee From 914f956cd51f5e28db690fa8e11717c040d50cd4 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:13:06 +0000 Subject: [PATCH 21/42] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f0c1d1b1..22a5c33d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [English](./README-en.md) | 简体中文 -文档捉虫活动火热进行中,欢迎参加: +文档捉虫活动火热进行中,欢迎参加:
[点我马上开启文档捉虫](https://docs.openeuler.org/zh/)
[点我查看活动详情](https://docs-bug.openeuler.sh/) -- Gitee From f676f4b30675ff71fdc590ed3b71b1d8d14e980f Mon Sep 17 00:00:00 2001 From: hwyytw Date: Mon, 11 Apr 2022 10:04:30 +0800 Subject: [PATCH 22/42] =?UTF-8?q?=E5=90=8C=E6=AD=A522.03=E5=88=86=E6=94=AF?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=88=B0master=E5=88=86=E6=94=AF=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A522.03=E5=88=86=E6=94=AF=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 19 +++++--- ...21\350\241\214\350\257\264\346\230\216.md" | 8 ++-- ...05\344\270\216\350\277\220\350\241\214.md" | 45 ++++++++----------- ...\273\272\346\214\207\345\257\274.markdown" | 2 +- ...\273\272\346\214\207\345\257\274.markdown" | 11 +++-- ...63\351\224\256\347\211\271\346\200\247.md" | 2 +- ...73\347\273\237\345\256\211\350\243\205.md" | 1 + 7 files changed, 47 insertions(+), 41 deletions(-) diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 97be7a4c3..4fb31398f 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -86,7 +86,7 @@ cmake .. make ``` -把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述使能共享文件系统场景。 +把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述[使能共享文件系统场景](./安装与运行.html#使能共享文件系统场景)。 3. **运行用户态程序** @@ -101,7 +101,16 @@ cd /tmp/myfiles/ ### 使用SDK编译内核模块样例 -1. **准备代码** +1. **准备环境** + +在设置好SDK环境的基础之上,编译内核模块还需准备相应环境,但只需要准备一次即可。运行如下命令会创建相应的内核模块编译环境: + +``` +cd /sysroots/-openeuler-linux/usr/src/kernel +make module_prepare +``` + +2. **准备代码** 以编译一个内核模块为例,运行在openEuler Embedded内核中。 @@ -147,7 +156,7 @@ MODULE_LICENSE(GPL); `KERNEL_SRC_DIR` 为SDK中内核源码树的目录,该变量在安装SDK后会被自动设置。 -2. **编译生成内核模块** +3. **编译生成内核模块** 进入hello.c文件所在目录,使用工具链编译,命令如下: @@ -155,9 +164,9 @@ MODULE_LICENSE(GPL); 将编译好的hello.ko拷贝到openEuler Embedded系统的目录下。 -如何拷贝可以参考前文所述使能共享文件系统场景。 +如何拷贝可以参考前文所述[使能共享文件系统场景](./安装与运行.html#使能共享文件系统场景)。 -3. **插入内核模块** +4. **插入内核模块** 在openEuler Embedded系统中插入内核模块: diff --git "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" index 3fd5a5328..915644291 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" +++ "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" @@ -12,19 +12,19 @@ openEuler Embedded 22.03是openEuler Embedded第一次正式发布,包含的 ## 软件包 -- 支持80+软件包,详见[openEuler Embedded所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) +- 支持80+软件包,详见[当前所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) ## 亮点特性 - 多OS混合部署框架的初步实现,支持openEuler Embedded和Zephyr的混合部署,详见[多OS混合部署框架](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html) - 分布式软总线的初步集成,详见[分布式软总线](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html) -- 安全加固指导,详见[openEuler Embedded的安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) -- 基于Preempt-RT的软实时,详见[openEuler Embedded软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) +- 安全加固指导,详见[安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) +- 基于Preempt-RT的软实时,详见[软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) ## 南向生态 -- 新增树莓派4B支持,详见[openEuler Embedded树莓派系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) +- 新增树莓派4B支持,详见[树莓派4B的支持](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) ## 构建系统 diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index c8d5dfe0a..e7cd05ef7 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -17,8 +17,8 @@ 当前发布的已构建好的镜像,只支持arm和aarch64两种架构,且只支持qemu中ARM virt-4.0平台,您可以通过如下链接获得相应的镜像: -- [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm):32位arm架构,ARM Cortex A15处理器 -- [qemu_aarch64](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-aarch64):64位aarch64架构,ARM Cortex A57处理器 +- [qemu_arm](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm32/arm-std/):32位arm架构,ARM Cortex A15处理器 +- [qemu_aarch64](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm64/aarch64-std/):64位aarch64架构,ARM Cortex A57处理器 只要相应环境支持qemu仿真器(版本5.0以上),您可以将提供的openEuler Embedded镜像部署在物理裸机、云环境、容器或虚拟机上。 @@ -27,18 +27,16 @@ 所下载的镜像,由以下几部分组成: - 内核镜像**zImage**: 基于openEuler社区Linux 5.10代码构建得到。相应的内核配置可通过如下链接获取: - - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) + - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm/defconfig-kernel) + - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) -- 根文件系统镜像(依据具体需求,以下二选一) +- 根文件系统镜像 - - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - - - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 + - **openeuler-image-qemu-xxx.cpio.gz**:标准根文件系统镜像,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器所支持的软件包。 - SDK(Software Development Kit)工具 - - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 + - **openeuler-glibc-x86_64-xxxxx.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -48,16 +46,12 @@ **注意事项** -- 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 +- 建议使用QEMU 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在QEMU中使能,则运行时可能会产生错误,此时可能需要从源码重新编译QEMU。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->后续说明以标准根文件系统为例(initrd)。 - --- -qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: +QEMU的下载与安装可以参考[QEMU官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: ``` qemu-system-aarch64 --version @@ -65,9 +59,9 @@ qemu-system-aarch64 --version ### 极简运行场景 -该场景下,qemu未使能网络和共享文件系统,适合快速的功能体验。 +该场景下,QEMU未使能网络和共享文件系统,适合快速的功能体验。 -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -83,21 +77,20 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr >![](./public_sys-resources/icon-note.gif) **说明:** > ->- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 ->- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 +>由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 2. **检查运行是否成功** -qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 +QEMU运行成功并登录后,将会呈现openEuler Embedded的Shell。 ### 使能共享文件系统场景 -通过共享文件系统,可以使得运行qemu仿真器的宿主机和openEuler Embedded共享文件,这样在宿主机上交叉编译的程序,拷贝到共享目录中,即可在openEuler Embedded上运行。 +通过共享文件系统,可以使得运行QEMU仿真器的宿主机和openEuler Embedded共享文件,这样在宿主机上交叉编译的程序,拷贝到共享目录中,即可在openEuler Embedded上运行。 假设将宿主机的/tmp目录作为共享目录,并事先在其中创建了名为hello_openeuler.txt的文件,使能共享文件系统功能的操作指导如下: -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -136,9 +129,9 @@ ls ### 使能网络场景 -通过qemu的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler embedded之间的网络通信。 +通过QEMU的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler Embedded之间的网络通信。除了通过virtio-fs实现文件共享外,还可以通过网络的方式,例如 **scp** 命令,实现宿主机和 openEuler Embedded传输文件。 -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -169,9 +162,9 @@ chmod a+x qemu-ifup 通过qemu-ifup脚本,宿主机上将创建名为tap0的虚拟网卡,地址为192.168.10.1。 -3. **配置openEuler embedded网卡** +3. **配置openEuler Embedded网卡** -openEuler Embedded登陆后,执行如下命令: +openEuler Embedded登录后,执行如下命令: ``` ifconfig eth0 192.168.10.2 diff --git "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 7b7fe2d22..7d08267df 100644 --- "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -145,7 +145,7 @@ bitbake openeuler-image | filename | description | | ---------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | +| Image-\* | openEuler Embedded image | | openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | | openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | | zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 1080d7193..2d29dcbed 100644 --- "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -57,10 +57,13 @@ yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持, 通过如下方式可以获得: - - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) - - [ARM 64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + - 下载rpm包: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` + - 解压rpm包: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` + - 解压后可以看到当前路径下会有tmp目录,编译链存放于该目录下 + - ARM 32位工具链: openeuler_gcc_arm32le.tar.xz + - ARM 64位工具链: openeuler_gcc_arm64le.tar.xz ### 已安装好工具的构建容器 @@ -136,7 +139,7 @@ openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_emb | filename | description | | ---------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | +| Image-\* | openEuler Embedded image | | openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | | openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | | zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 4582e5abb..a2869c4bb 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -70,7 +70,7 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 ## 嵌入式镜像 - **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 - **多硬件支持**,新增支持树莓派4B作为嵌入式场景通用硬件。 -- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 +- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延微秒级。 - **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 - **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 - **嵌入式软件包支持**,新增80+嵌入式领域常用软件包的构建。 diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index d013e5af0..8436fea53 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -109,6 +109,7 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+ **表 4** 嵌入式镜像列表 | 名称 | 描述 | -- Gitee From 8c359e75b4a61f67d1ef36d1fa30678478cda72e Mon Sep 17 00:00:00 2001 From: hwyytw Date: Mon, 11 Apr 2022 10:09:45 +0800 Subject: [PATCH 23/42] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC=20=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...37\346\236\204\345\273\272\346\214\207\345\257\274.markdown" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 2d29dcbed..d5d41a8bc 100644 --- "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -57,7 +57,7 @@ yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持, 通过如下方式可以获得: + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过如下方式可以获得: - 下载rpm包: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` - 解压rpm包: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` -- Gitee From 17c9ae4dbff0d2dea8cfcbd3d30dca325cfba580 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Mon, 11 Apr 2022 14:20:10 +0800 Subject: [PATCH 24/42] =?UTF-8?q?imageTailor=20=E4=BD=BF=E7=94=A8=E6=8C=87?= =?UTF-8?q?=E5=8D=97=20=E7=AE=80=E4=BB=8B=E9=83=A8=E5=88=86=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=8F=8F=E8=BF=B0=E9=9C=80=E8=A6=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lor \344\275\277\347\224\250\346\214\207\345\215\227.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" index 3902c6e0b..10cfe8d67 100644 --- "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -36,9 +36,9 @@ 因此,openEuler 提供了 imageTailor 镜像裁剪定制工具。用户可以根据需求裁剪操作系统镜像中不需要的外围包,或者添加所需的业务包或文件。该工具主要提供了以下功能: -- 系统包裁剪:根据需要选择安装的 RPM 包列表,裁剪系统命令、库、驱动。 -- 系统配置修改:配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、内核版本号。 -- 软件包增加:将用户的 RPM 包安装到系统中或者将用户文件添加到系统中。 +- 系统包裁剪定制:用户可以选择默认安装以及裁剪的rpm,也支持用户裁剪定制系统命令、库、驱动。 +- 系统配置定制:用户可以配置主机名、启动服务、时区、网络、分区、加载驱动、版本号等。 +- 用户文件定制:支持用户添加定制文件到系统镜像中。 -- Gitee From ea7ca9de179f93fcd366e1b46482bbdc6b005493 Mon Sep 17 00:00:00 2001 From: zhangsong Date: Tue, 12 Apr 2022 11:43:14 +0800 Subject: [PATCH 25/42] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0rubik=E6=B7=B7?= =?UTF-8?q?=E9=83=A8=E9=9A=94=E7=A6=BB=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangsong --- ...24\347\246\273\347\244\272\344\276\213.md" | 233 ++++++++++++++++++ docs/zh/menu/index.md | 1 + 2 files changed, 234 insertions(+) create mode 100644 "docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" diff --git "a/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" new file mode 100644 index 000000000..48895ccce --- /dev/null +++ "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" @@ -0,0 +1,233 @@ +## 混部隔离示例 + +### 环境准备 + +查看内核是否支持混部隔离功能 + +```bash +# 查看/boot/config-系统配置是否开启混部隔离功能 +# 若CONFIG_QOS_SCHED=y则说明使能了混部隔离功能,例如: +cat /boot/config-5.10.0-60.18.0.50.oe2203.x86_64 | grep CONFIG_QOS +CONFIG_QOS_SCHED=y +``` + +安装docker容器引擎 + +```bash +yum install -y docker-engine +docker version +# 如下为docker version显示结果 +Client: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Wed Mar 30 05:07:38 2022 + OS/Arch: linux/amd64 + Experimental: false + +Server: + Engine: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 (minimum version 1.12) + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Tue Mar 22 00:00:00 2022 + OS/Arch: linux/amd64 + Experimental: false +``` + +### 混部业务 + +**在线业务(clickhouse)** + +使用clickhouse-benmark测试工具进行性能测试,统计出QPS/P50/P90/P99等相关性能指标,用法参考:https://clickhouse.com/docs/zh/operations/utilities/clickhouse-benchmark/ + +**离线业务(stress)** + +stress是一个CPU密集型测试工具,可以通过指定--cpu参数启动多个并发CPU密集型任务给系统环境加压 + +### 使用说明 + +1)启动一个clickhouse容器(在线业务)。 + +2)进入容器内执行clickhouse-benchmark命令,设置并发线程数为10个、查询10000次、查询总时间30s。 + +3)同时启动一个stress容器(离线业务),并发执行10个CPU密集型任务对环境进行加压。 + +4)clickhouse-benchmark执行完后输出一个性能测试报告。 + +混部隔离测试脚本(**test_demo.sh**)如下: + +```bash +#!/bin/bash + +with_offline=${1:-no_offline} +enable_isolation=${2:-no_isolation} +stress_num=${3:-10} +concurrency=10 +timeout=30 +output=/tmp/result.json +online_container= +offline_container= + +exec_sql="echo \"SELECT * FROM system.numbers LIMIT 10000000 OFFSET 10000000\" | clickhouse-benchmark -i 10000 -c $concurrency -t $timeout" + +function prepare() +{ + echo "Launch clickhouse container." + online_container=$(docker run -itd \ + -v /tmp:/tmp:rw \ + --ulimit nofile=262144:262144 \ + -p 34424:34424 \ + yandex/clickhouse-server) + + sleep 3 + echo "Clickhouse container lauched." +} + +function clickhouse() +{ + echo "Start clickhouse benchmark test." + docker exec $online_container bash -c "$exec_sql --json $output" + echo "Clickhouse benchmark test done." +} + +function stress() +{ + echo "Launch stress container." + offline_container=$(docker run -itd joedval/stress --cpu $stress_num) + echo "Stress container launched." + + if [ $enable_isolation == "enable_isolation" ]; then + echo "Set stress container qos level to -1." + echo -1 > /sys/fs/cgroup/cpu/docker/$offline_container/cpu.qos_level + fi +} + +function benchmark() +{ + if [ $with_offline == "with_offline" ]; then + stress + sleep 3 + fi + clickhouse + echo "Remove test containers." + docker rm -f $online_container + docker rm -f $offline_container + echo "Finish benchmark test for clickhouse(online) and stress(offline) colocation." + echo "===============================clickhouse benchmark==================================================" + cat $output + echo "===============================clickhouse benchmark==================================================" +} + +prepare +benchmark +``` + +### 测试结果 + +单独执行clickhouse在线业务 + +```bash +sh test_demo.sh no_offline no_isolation +``` + +得到在线业务的QoS(QPS/P50/P90/P99等指标)**基线数据**如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8853412284364512, +...... +}, +"query_time_percentiles": { +...... +"50": 0.484905256, +"60": 0.519641313, +"70": 0.570876148, +"80": 0.632544937, +"90": 0.728295525, +"95": 0.808700418, +"99": 0.873945121, +...... +} +} +} +``` + +启用stress离线业务,未开启混部隔离功能下,执行test_demo.sh测试脚本 + +```bash +# with_offline参数表示启用stress离线业务 +# no_isolation参数表示未开启混部隔离功能 +sh test_demo.sh with_offline no_isolation +``` + +**未开启混部隔离的情况下**,clickhouse业务QoS数据(QPS/P80/P90/P99等指标)如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 0.9424028693636205, +...... +}, +"query_time_percentiles": { +...... +"50": 0.840476774, +"60": 1.304607373, +"70": 1.393591017, +"80": 1.41277543, +"90": 1.430316688, +"95": 1.457534764, +"99": 1.555646855, +...... +} +} +``` + +启用stress离线业务,开启混部隔离功能下,执行test_demo.sh测试脚本 + +```bash +# with_offline参数表示启用stress离线业务 +# enable_isolation参数表示开启混部隔离功能 +sh test_demo.sh with_offline enable_isolation +``` + +**开启混部隔离功能的情况下**,clickhouse业务QoS数据(QPS/P80/P90/P99等指标)如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8825798759270718, +...... +}, +"query_time_percentiles": { +...... +"50": 0.485725185, +"60": 0.512629901, +"70": 0.55656488, +"80": 0.636395956, +"90": 0.734695906, +"95": 0.804118275, +"99": 0.887807409, +...... +} +} +} +``` + +从上面的测试结果整理出一个表格如下: + +| 业务部署方式 | QPS | P50 | P90 | P99 | +| -------------------------------------- | ------------- | ------------- | ------------- | ------------- | +| 单独运行clickhouse在线业务(基线) | 1.885 | 0.485 | 0.728 | 0.874 | +| clickhouse+stress(未开启混部隔离功能) | 0.942(-50%) | 0.840(-42%) | 1.430(-49%) | 1.556(-44%) | +| clickhouse+stress(开启混部隔离功能) | 1.883(-0.11%) | 0.486(-0.21%) | 0.735(-0.96%) | 0.888(-1.58%) | + +在未开启混部隔离功能的情况下,在线业务clickhouse的QPS从1.9下降到0.9,同时业务的响应时延(P90)也从0.7s增大到1.4s,在线业务QoS下降了50%左右;而在开启混部隔离功能的情况下,不管是在线业务的QPS还是响应时延(P50/P90/P99)相比于基线值下降不到2%,在线业务QoS基本没有变化。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cee7bf5e0..0ba65f344 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -213,6 +213,7 @@ headless: true - [云原生混合部署rubik用户指南]({{< relref "./docs/rubik/overview.md" >}}) - [安装与部署]({{< relref "./docs/rubik/安装与部署.md" >}}) - [http接口文档]({{< relref "./docs/rubik/http接口文档.md" >}}) + - [混部隔离示例]({{< relref "./docs/rubik/混部隔离示例.md" >}}) - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) -- Gitee From b1f834c97157f4b0e3574b57077fc267289edecb Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Sat, 16 Apr 2022 17:49:41 +0800 Subject: [PATCH 26/42] added rubik docs and modified index.md --- .../public_sys-resources/hosttools.png | Bin 0 -> 210345 bytes ...-isolation-for-hybrid-deployed-services.md | 233 ++++++++++++++++++ docs/en/docs/rubik/http-apis.md | 67 +++++ .../docs/rubik/installation-and-deployment.md | 199 +++++++++++++++ docs/en/docs/rubik/overview.md | 17 ++ docs/en/menu/index.md | 4 + 6 files changed, 520 insertions(+) create mode 100644 docs/en/docs/Embedded/public_sys-resources/hosttools.png create mode 100644 docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md create mode 100644 docs/en/docs/rubik/http-apis.md create mode 100644 docs/en/docs/rubik/installation-and-deployment.md create mode 100644 docs/en/docs/rubik/overview.md diff --git a/docs/en/docs/Embedded/public_sys-resources/hosttools.png b/docs/en/docs/Embedded/public_sys-resources/hosttools.png new file mode 100644 index 0000000000000000000000000000000000000000..1b154b40fc76ead162cdd7c7d32303f581d9cfa8 GIT binary patch literal 210345 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%0DZr)O$%pOkgk_wGDUlaEp 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%0DJ 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®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 system configuration. +# If **CONFIG_QOS_SCHED=y**, the function is enabled. Example: +cat /boot/config-5.10.0-60.18.0.50.oe2203.x86_64 | grep CONFIG_QOS +CONFIG_QOS_SCHED=y +``` + +Install the Docker engine. + +```bash +yum install -y docker-engine +docker version +# The following shows the output of docker version. +Client: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Wed Mar 30 05:07:38 2022 + OS/Arch: linux/amd64 + Experimental: false + +Server: + Engine: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 (minimum version 1.12) + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Tue Mar 22 00:00:00 2022 + OS/Arch: linux/amd64 + Experimental: false +``` + +### Hybrid Deployed Services + +**Online Service ClickHouse** + +Use the clickhouse-benchmark tool to test the performance and collect statistics on performance metrics such as QPS, P50, P90, and P99. For details, see https://clickhouse.com/docs/en/operations/utilities/clickhouse-benchmark/. + +**Offline Service Stress** + +Stress is a CPU-intensive test tool. You can specify the **--cpu** parameter to start multiple concurrent CPU-intensive tasks to increase the stress on the system. + +### Usage + +1) Start a ClickHouse container (online service). + +2) Access the container and run the **clickhouse-benchmark** command. Set the number of concurrent threads to 10, the number of query times to 10000, and the total query time to 30s. + +3) Start a Stress container (offline service) at the same time and concurrently execute 10 CPU-intensive tasks to increase the stress on the environment. + +4) After the **clickhouse-benchmark** command is executed, a performance test report is generated. + +The **test_demo.sh** script for the isolation test for hybrid deployed services is as follows: + +```bash +#!/bin/bash + +with_offline=${1:-no_offline} +enable_isolation=${2:-no_isolation} +stress_num=${3:-10} +concurrency=10 +timeout=30 +output=/tmp/result.json +online_container= +offline_container= + +exec_sql="echo \"SELECT * FROM system.numbers LIMIT 10000000 OFFSET 10000000\" | clickhouse-benchmark -i 10000 -c $concurrency -t $timeout" + +function prepare() +{ + echo "Launch clickhouse container." + online_container=$(docker run -itd \ + -v /tmp:/tmp:rw \ + --ulimit nofile=262144:262144 \ + -p 34424:34424 \ + yandex/clickhouse-server) + + sleep 3 + echo "Clickhouse container lauched." +} + +function clickhouse() +{ + echo "Start clickhouse benchmark test." + docker exec $online_container bash -c "$exec_sql --json $output" + echo "Clickhouse benchmark test done." +} + +function stress() +{ + echo "Launch stress container." + offline_container=$(docker run -itd joedval/stress --cpu $stress_num) + echo "Stress container launched." + + if [ $enable_isolation == "enable_isolation" ]; then + echo "Set stress container qos level to -1." + echo -1 > /sys/fs/cgroup/cpu/docker/$offline_container/cpu.qos_level + fi +} + +function benchmark() +{ + if [ $with_offline == "with_offline" ]; then + stress + sleep 3 + fi + clickhouse + echo "Remove test containers." + docker rm -f $online_container + docker rm -f $offline_container + echo "Finish benchmark test for clickhouse(online) and stress(offline) colocation." + echo "===============================clickhouse benchmark==================================================" + cat $output + echo "===============================clickhouse benchmark==================================================" +} + +prepare +benchmark +``` + +### Test Results + +Independently execute the online service ClickHouse. + +```bash +sh test_demo.sh no_offline no_isolation +``` + +The QoS **baseline data** (QPS/P50/P90/P99) of the online service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8853412284364512, +...... +}, +"query_time_percentiles": { +...... +"50": 0.484905256, +"60": 0.519641313, +"70": 0.570876148, +"80": 0.632544937, +"90": 0.728295525, +"95": 0.808700418, +"99": 0.873945121, +...... +} +} +} +``` + +Start the offline service Stress, disable isolation of hybrid deployed services, and execute the **test_demo.sh** script. + +```bash +# **with_offline** indicates that the offline service Stress is enabled. +# **no_isolation** indicates that isolation of hybrid deployed services is disabled. +sh test_demo.sh with_offline no_isolation +``` + +**When isolation of hybrid deployed services is disabled**, the QoS data (QPS/P80/P90/P99) of the ClickHouse service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 0.9424028693636205, +...... +}, +"query_time_percentiles": { +...... +"50": 0.840476774, +"60": 1.304607373, +"70": 1.393591017, +"80": 1.41277543, +"90": 1.430316688, +"95": 1.457534764, +"99": 1.555646855, +...... +} +} +``` + +Start the offline service Stress, enable isolation of hybrid deployed services, and execute the **test_demo.sh** script. + +```bash +# **with_offline** indicates that the offline service Stress is enabled. +# **enable_isolation** indicates that isolation of hybrid deployed services is enabled. +sh test_demo.sh with_offline enable_isolation +``` + +**When isolation of hybrid deployed services is enabled**, the QoS data (QPS/P80/P90/P99) of the ClickHouse service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8825798759270718, +...... +}, +"query_time_percentiles": { +...... +"50": 0.485725185, +"60": 0.512629901, +"70": 0.55656488, +"80": 0.636395956, +"90": 0.734695906, +"95": 0.804118275, +"99": 0.887807409, +...... +} +} +} +``` + +The following table lists the test results. + +| Service Deployment Mode | QPS | P50 | P90 | P99 | +| -------------------------------------- | ------------- | ------------- | ------------- | ------------- | +| ClickHouse (baseline) | 1.885 | 0.485 | 0.728 | 0.874 | +| ClickHouse + Stress (isolation disabled)| 0.942 (-50%) | 0.840 (-42%) | 1.430 (-49%) | 1.556 (-44%) | +| ClickHouse + Stress (isolation enabled) | 1.883 (-0.11%) | 0.486 (-0.21%) | 0.735 (-0.96%) | 0.888 (-1.58%) | + +When isolation of hybrid deployed services is disabled, the QPS of ClickHouse decreases from approximately 1.9 to 0.9, the service response delay (P90) increases from approximately 0.7s to 1.4s, and the QoS decreases by about 50%. When isolation of hybrid deployed services is enabled, the QPS and response delay (P50/P90/P99) of ClickHouse decrease by less than 2% compared with the baseline, and the QoS remains unchanged. diff --git a/docs/en/docs/rubik/http-apis.md b/docs/en/docs/rubik/http-apis.md new file mode 100644 index 000000000..e5d315a0a --- /dev/null +++ b/docs/en/docs/rubik/http-apis.md @@ -0,0 +1,67 @@ +# HTTP APIs + +## Overview + +The open APIs of Rubik are all HTTP APIs, including the API for setting or updating the pod priority, API for detecting the Rubik availability, and API for querying the Rubik version. + +## APIs + +### API for Setting or Updating the Pod Priority + +Rubik provides the function of setting or updating the pod priority. External systems can call this API to send pod information. Rubik sets the priority based on the received pod information to isolate resources. The API calling format is as follows: + +```bash +HTTP POST /run/rubik/rubik.sock +{ + "Pods": { + "podaaa": { + "CgroupPath": "kubepods/burstable/podaaa", + "QosLevel": 0 + }, + "podbbb": { + "CgroupPath": "kubepods/burstable/podbbb", + "QosLevel": -1 + } + } +} +``` + +In the **Pods** settings, specify information about the pods whose priorities need to be set or updated. At least one pod must be specified for each HTTP request, and **CgroupPath** and **QosLevel** must be specified for each pod. The meanings of **CgroupPath** and **QosLevel** are as follows: + +| Item | Value Type| Value Range| Description | +| ---------- | ---------- | ------------ | ------------------------------------------------------- | +| QosLevel | Integer | 0, -1 | pod priority. The value **0** indicates that the service is an online service, and the value **-1** indicates that the service is an offline service. | +| CgroupPath | String | Relative path | cgroup subpath of the pod (relative path in the cgroup subsystem)| + +The following is an example of calling the API: + +```sh +curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST --data '{"Pods": {"podaaa": {"CgroupPath": "kubepods/burstable/podaaa","QosLevel": 0},"podbbb": {"CgroupPath": "kubepods/burstable/podbbb","QosLevel": -1}}}' --unix-socket /run/rubik/rubik.sock http://localhost/ +``` + +### API for Detecting Availability + +As an HTTP service, Rubik provides an API for detecting whether Rubik is running. + +API format: HTTP/GET /ping + +The following is an example of calling the API: + +```sh +curl -XGET --unix-socket /run/rubik/rubik.sock http://localhost/ping +``` + +If **ok** is returned, the Rubik service is running. + +### API for Querying Version Information + +Rubik allows you to query the current Rubik version number through an HTTP request. + +API format: HTTP/GET /version + +The following is an example of calling the API: + +```sh +curl -XGET --unix-socket /run/rubik/rubik.sock http://localhost/version +{"Version":"0.0.1","Release":"1","Commit":"29910e6","BuildTime":"2021-05-12"} +``` diff --git a/docs/en/docs/rubik/installation-and-deployment.md b/docs/en/docs/rubik/installation-and-deployment.md new file mode 100644 index 000000000..6a713ec22 --- /dev/null +++ b/docs/en/docs/rubik/installation-and-deployment.md @@ -0,0 +1,199 @@ +# Installation and Deployment + +## Overview + +This document describes how to install and deploy the Rubik component. + +## Software and Hardware Requirements + +### Hardware + +* Architectures: x86 and AArch64 +* Drive: 1 GB or more +* Memory: 100 MB or more + +### Software + +* OS: openEuler 22.03-LTS +* Kernel: openEuler 22.03-LTS kernel + +### Environment Preparation + +* Install the openEuler OS. For details, see the _openEuler 22.03-LTS Installation Guide_. +* Install and deploy Kubernetes. For details, see the _Kubernetes Cluster Deployment Guide_. +* Install the Docker or iSulad container engine. If the iSulad container engine is used, you need to install the isula-build container image building tool. + +## Installing Rubik + +Rubik is deployed on each Kubernetes node as a DaemonSet. Therefore, you need to perform the following steps to install the Rubik RPM package on each node. + +1. Configure the Yum repositories openEuler 22.03-LTS and openEuler 22.03-LTS:EPOL (Rubik component is available only in the EPOL repository). + + ``` + # openEuler 22.03-LTS officially released repository + name=openEuler22.03 + baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/everything/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=https://repo.openeuler.org/openEuler-22.03-LTS/everything/RPM-GPG-KEY-openEuler + ``` + + ``` + # openEuler 22.03-LTS:EPOL officially released repository + name=Epol + baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/$basearch/ + enabled=1 + gpgcheck=0 + ``` + +2. Install Rubik as the **root** user. + + ```shell + sudo yum install -y rubik + ``` + + +> ![](D:\Typora-image\icon-note.gif)**Note**: +> +> Files related to the Rubik tool are installed in the **/var/lib/rubik** directory. + +## Deploying Rubik + +Rubik runs as a container in a Kubernetes cluster in hybrid deployment scenarios. It is used to isolate and restrict resources for services with different priorities to prevent offline services from interfering with online services, improving the overall resource utilization and ensuring the service quality of online services. Currently, Rubik supports isolation and restriction of CPU and memory resources, which must be used together with the openEuler 22.03-LTS kernel. To enable the memory priority feature (that is, to implement memory resource tiering for services with different priorities), you need to set **/proc/sys/vm/memcg_qos_enable**. The value can be **0** or **1**. The default value **0** indicates that the feature is disabled, and the value **1** indicates that the feature is enabled. + +```bash +sudo echo 1 > /proc/sys/vm/memcg_qos_enable +``` + +### Deploying Rubik DaemonSet + +1. Use the Docker or isula-build engine to build Rubik images. Because Rubik is deployed as a DaemonSet, each node requires a Rubik image. After building an image on a node, use the `docker save/load` command to load the Rubik image to each node of Kubernetes. Alternatively, build a Rubik image on each node. The following uses isula-build as an example. The command is as follows: + +```sh +isula-build ctr-img build -f /var/lib/rubik/Dockerfile --tag rubik:0.1.0 . +``` + +2. On the Kubernetes master node, change the Rubik image name in the `/var/lib/rubik/rubik-daemonset.yaml` file to the name of the image built in the previous step. + +```yaml +... +containers: +- name: rubik-agent + image: rubik:0.1.0 # The image name must be the same as the Rubik image name built in the previous step. + imagePullPolicy: IfNotPresent +... +``` + +3. On the Kubernetes master node, run the `kubectl` command to deploy the Rubik DaemonSet. Rubik is automatically deployed on all Kubernetes nodes. + +```sh +kubectl apply -f /var/lib/rubik/rubik-daemonset.yaml +``` + +4. Run the `kubectl get pods -A` command to check whether Rubik has been deployed on each node in the cluster. (The number of rubik-agents is the same as the number of nodes and all rubik-agents are in the Running state.) + +```sh +[root@localhost rubik]# kubectl get pods -A +NAMESPACE NAME READY STATUS RESTARTS AGE +... +kube-system rubik-agent-76ft6 1/1 Running 0 4s +... +``` + +## Common Configuration Description + +The Rubik deployed using the preceding method is started with the default configuration. You can modify the Rubik configuration as required by modifying the **config.json** section in the **rubik-daemonset.yaml** file and then redeploy the Rubik DaemonSet. + +This section describes common configurations of **config.json**. + +### Configuration Item Description + +```yaml +# The configuration items are in the **config.json** section of the **rubik-daemonset.yaml** file. +{ + "autoConfig": true, + "autoCheck": false, + "logDriver": "stdio", + "logDir": "/var/log/rubik", + "logSize": 1024, + "logLevel": "info", + "cgroupRoot": "/sys/fs/cgroup" +} +``` + +| Item | Value Type| Value Range | Description | +| ---------- | ---------- | ------------------ | ------------------------------------------------------------ | +| autoConfig | Boolean | **true** or **false** | **true**: enables automatic pod awareness.
**false**: disables automatic pod awareness.| +| autoCheck | Boolean | **true** or **false** | **true**: enables pod priority check.
**false**: disables pod priority check.| +| logDriver | String | **stdio** or **file** | **stdio**: prints logs to the standard output. The scheduling platform collects and dumps logs.
**file**: prints files to the log directory specified by **logDir**.| +| logDir | String | Absolute path | Directory for storing logs. | +| logSize | Integer | [10,1048576] | Total size of logs, in MB. If the total size of logs reaches the upper limit, the earliest logs will be discarded.| +| logLevel | String | **error**, **info**, or **debug**| Log level. | +| cgroupRoot | String | Absolute path | cgroup mount point. | + +### Automatic Configuration of Pod Priorities + +If **autoConfig** is set to **true** in the Rubik configuration to enable automatic pod awareness, you only need to specify the priority in **annotation** in the YAML file when deploying the service pod. After the deployment, Rubik automatically detects the creation and update of the pods on the current node, and sets the pod priorities based on the configured priorities. + +### Pod Priority Configuration Depending on kubelet + +The automatic configuration of the pod priority depends on the event notification created by **api-server pod**, which has a certain delay. The pod priority cannot be configured before the process is started. As a result, the service performance may fluctuate. You can disable the automatic priority configuration option by modifying the kubelet source code. After the container cgroup is created and before the container process is started, call the Rubik HTTP API to configure the pod priorities. For details about how to use the HTTP API, see [HTTP APIs](./http-apis.md). + +### Automatic Verification of Pod Priorities + +Rubik supports consistency check on the pod QoS priority configurations of the current node during startup. It checks whether the configuration in the Kubernetes cluster is consistent with the pod priority configuration of Rubik. This function is disabled by default. You can enable or disable it using the **autoCheck** option. If this function is enabled, Rubik automatically verifies and corrects the pod priority configuration of the current node when it is started or restarted. + +## Example of Configuring Rubik for Offline Services + +After Rubik is successfully deployed, you can modify the YAML file of a service based on the following configuration example to specify the offline service. Then Rubik can configure the priority of the service after the service is deployed to isolate resources. + +The following is an example of deploying the online service Nginx: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx + namespace: qosexample + annotations: + volcano.sh/preemptable: "false" # If **volcano.sh/preemptable** is set to **true**, the service is an offline service. If it is set to **false**, the service is an online service. The default value is **false**. +spec: + containers: + - name: nginx + image: nginx + resources: + limits: + memory: "200Mi" + cpu: "1" + requests: + memory: "200Mi" + cpu: "1" +``` + +## Restrictions + +- The maximum number of concurrent HTTP requests that Rubik can receive is 1,000 QPS. If the number of concurrent HTTP requests exceeds the upper limit, an error is reported. + +- The maximum number of pods in a single request received by Rubik is 100. If the number of pods exceeds the threshold, an error is reported. + +- Only one Rubik can be deployed on each Kubernetes node. Multiple Rubiks may conflict with each other. + +- Rubik does not provide port access and can communicate only through sockets. + +- Rubik accepts only valid HTTP request paths and network protocols: http://localhost/ (POST), http://localhost/ping (GET), and http://localhost/version (GET). For details about the functions of HTTP requests, see HTTP APIs(./http-apis.md). + +- Rubik drive requirement: 1 GB or more. + +- Rubik memory requirement: 100 MB or more. + +- Services cannot be switched from a low priority (offline services) to a high priority (online services). For example, if service A is set to an offline service and then to an online service, Rubik reports an error. + +- When a container is mounted to a directory, the service side must ensure that the minimum permission on the Rubik local socket directory **/run/Rubik** is 700. + +- When the Rubik server is available, the timeout interval of a single request is 120s. If the Rubik process enters the T (suspended or tracing) or D (uninterruptible sleep) state, the server becomes unavailable. In this case, the Rubik service does not respond to any request. To avoid this problem, set the timeout interval on the client to avoid infinite waiting. + +- If hybrid deployment is used, the original **cgroup cpu share** function has the following restrictions: + + If both online and offline tasks are running on the CPU, the CPU share configuration of offline tasks cannot take effect. + + If the current CPU has only online or offline tasks, the CPU share configuration takes effect. diff --git a/docs/en/docs/rubik/overview.md b/docs/en/docs/rubik/overview.md new file mode 100644 index 000000000..bcf79fc62 --- /dev/null +++ b/docs/en/docs/rubik/overview.md @@ -0,0 +1,17 @@ +# Rubik User Guide + +## Overview + +Low server resource utilization has always been a recognized challenge in the industry. With the development of cloud native technologies, hybrid deployment of online (high-priority) and offline (low-priority) services becomes an effective means to improve resource utilization. + +In hybrid service deployment scenarios, Rubik container scheduling properly schedules resources based on QoS levels to greatly improve resource utilization while ensuring the quality of online services. + +Rubik supports the following features: + +- Pod CPU priority configuration +- Pod memory priority configuration + +This document is intended for community developers, open source enthusiasts, and partners who use the openEuler system and want to learn and use Rubik. Users must: + +* Know basic Linux operations. +* Be familiar with basic operations of Kubernetes and Docker/iSulad. diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 74ce94a24..ecdfd3f66 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -198,5 +198,9 @@ headless: true - [About KubeOS]({{< relref "./docs/KubeOS/about-kubeos.md" >}}) - [Installation and Deployment]({{< relref "./docs/KubeOS/installation-and-deployment.md" >}}) - [Usage Instructions]({{< relref "./docs/KubeOS/usage-instructions.md" >}}) +- [Rubik User Guide]({{< relref "./docs/rubik/overview.md" >}}) + - [Installation and Deployment]({{< relref "./docs/rubik/installation-and-deployment.md" >}}) + - [HTTP APIs]({{< relref "./docs/rubik/http-apis.md" >}}) + - [Example of Isolation for Hybrid Deployed Services]({{< relref "./docs/rubik/example-of-isolation-for-hybrid-deployed-services.md" >}}) - [Image Tailoring and Customization Tool]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) \ No newline at end of file -- Gitee From 2a39fcda4c31e883bbf279d2751d39c7225739f4 Mon Sep 17 00:00:00 2001 From: gomico Date: Mon, 18 Apr 2022 15:05:19 +0800 Subject: [PATCH 27/42] =?UTF-8?q?update=20translation=20for=20some=20zh=20?= =?UTF-8?q?docs=20desktop/kubesphere.md=20at=20ab6f97b=20Embedded/SDK?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=BC=80=E5=8F=91.md=20at=20f676f4b=20Embedd?= =?UTF-8?q?ed/=E5=AE=B9=E5=99=A8=E6=9E=84=E5=BB=BA=E6=8C=87=E5=AF=BC.markd?= =?UTF-8?q?own=20at=20f676f4b=20Embedded/embedded.md=20at=20d4a93eb=20Embe?= =?UTF-8?q?dded/=E5=AE=89=E8=A3=85=E4=B8=8E=E8=BF=90=E8=A1=8C.md=20at=20f6?= =?UTF-8?q?76f4b=20Embedded/openEuler=20Embedded=2022.03=E5=8F=91=E8=A1=8C?= =?UTF-8?q?=E8=AF=B4=E6=98=8E.md=20at=20f676f4b=20Embedded/openEuler=20Emb?= =?UTF-8?q?edded=E6=9E=84=E5=BB=BA=E6=8C=87=E5=AF=BC.markdown=20at=20625c9?= =?UTF-8?q?3d=20Embedded/=E5=BF=AB=E9=80=9F=E6=9E=84=E5=BB=BA=E6=8C=87?= =?UTF-8?q?=E5=AF=BC.markdown=20at=208c359e7=20Gazelle/Gazelle.md=20at=206?= =?UTF-8?q?d66100=20KubeEdge/KubeEdge=E9=83=A8=E7=BD=B2=E6=8C=87=E5=8D=97.?= =?UTF-8?q?md=20at=202c8ef7e=20NestOS/=E5=8A=9F=E8=83=BD=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0.md=20at=202888031=20NestOS/=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=B8=8E=E9=83=A8=E7=BD=B2.md=20at=202888031=20NestOS?= =?UTF-8?q?/overview.md=20at=202888031=20NestOS/=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=B9=E6=B3=95.md=20at=202888031=20Releasenotes/=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=AE=89=E8=A3=85.md=20at=20f676f4b=20Releasenotes/?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E7=89=B9=E6=80=A7.md=20at=20f676f4b=20Tailor?= =?UTF-8?q?Custom/imageTailor=20=E4=BD=BF=E7=94=A8=E6=8C=87=E5=8D=97.md=20?= =?UTF-8?q?at=2017c9ae4=20thirdparty=5Fmigration/OpenStack-train.md=20at?= =?UTF-8?q?=205fe3a40=20thirdparty=5Fmigration/OpenStack-wallaby.md=20at?= =?UTF-8?q?=205fe3a40?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application-development-using-sdk.md | 172 + .../en/docs/Embedded/container-build-guide.md | 151 + docs/en/docs/Embedded/embedded.md | 186 +- .../docs/Embedded/installation-and-running.md | 166 + .../openEuler-Embedded-22.03-release-notes.md | 32 + .../openEuler-Embedded-build-guide.md | 7 + .../public_sys-resources/icon-caution.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-danger.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-note.gif | Bin 0 -> 394 bytes .../public_sys-resources/icon-notice.gif | Bin 0 -> 406 bytes .../public_sys-resources/icon-tip.gif | Bin 0 -> 253 bytes .../public_sys-resources/icon-warning.gif | Bin 0 -> 580 bytes docs/en/docs/Embedded/quick-build-guide.md | 146 + docs/en/docs/Gazelle/Gazelle.md | 263 ++ .../KubeEdge/kubeedge-deployment-guide.md | 6 +- docs/en/docs/NestOS/feature-description.md | 98 + .../NestOS/installation-and-deployment.md | 128 + docs/en/docs/NestOS/overview.md | 3 + docs/en/docs/NestOS/usage.md | 489 +++ .../en/docs/Releasenotes/installing-the-os.md | 21 +- docs/en/docs/Releasenotes/key-features.md | 26 +- .../docs/TailorCustom/figures/flowchart.png | Bin 0 -> 19918 bytes .../TailorCustom/imageTailor-user-guide.md | 928 ++++++ ...tion.md => virtualization-installation.md} | 0 docs/en/docs/desktop/kubesphere.md | 2 +- .../thirdparty_migration/OpenStack-train.md | 2961 +++++++++++++++++ .../OpenStack-victoria.md | 1832 ---------- .../thirdparty_migration/OpenStack-wallaby.md | 566 +++- docs/en/docs/userguide/patch-tracking.md | 2 +- docs/en/menu/index.md | 49 +- 30 files changed, 6160 insertions(+), 2074 deletions(-) create mode 100644 docs/en/docs/Embedded/application-development-using-sdk.md create mode 100644 docs/en/docs/Embedded/container-build-guide.md create mode 100644 docs/en/docs/Embedded/installation-and-running.md create mode 100644 docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md create mode 100644 docs/en/docs/Embedded/openEuler-Embedded-build-guide.md create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-caution.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-danger.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-note.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-notice.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-tip.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-warning.gif create mode 100644 docs/en/docs/Embedded/quick-build-guide.md create mode 100644 docs/en/docs/Gazelle/Gazelle.md create mode 100644 docs/en/docs/NestOS/feature-description.md create mode 100644 docs/en/docs/NestOS/installation-and-deployment.md create mode 100644 docs/en/docs/NestOS/overview.md create mode 100644 docs/en/docs/NestOS/usage.md create mode 100644 docs/en/docs/TailorCustom/figures/flowchart.png create mode 100644 docs/en/docs/TailorCustom/imageTailor-user-guide.md rename docs/en/docs/Virtualization/{installation-to-virtualization.md => virtualization-installation.md} (100%) create mode 100644 docs/en/docs/thirdparty_migration/OpenStack-train.md delete mode 100644 docs/en/docs/thirdparty_migration/OpenStack-victoria.md diff --git a/docs/en/docs/Embedded/application-development-using-sdk.md b/docs/en/docs/Embedded/application-development-using-sdk.md new file mode 100644 index 000000000..c2ae831dc --- /dev/null +++ b/docs/en/docs/Embedded/application-development-using-sdk.md @@ -0,0 +1,172 @@ +# Application Development Using openEuler Embedded SDK + +In addition to the basic functions of openEuler Embedded, you can also develop applications, that is, running your own programs on openEuler Embedded. This chapter describes how to develop applications using openEuler Embedded SDK. + + +- [Application Development Using openEuler Embedded SDK](#application-development-using-openeuler-embedded-sdk) + - [Installing the SDK](#installing-the-sdk) + - [Using the SDK to Build a Hello World Example](#using-the-sdk-to-build-a-hello-world-example) + - [Using the SDK to Build a Kernel Module Example](#using-the-sdk-to-build-a-kernel-module-example) + + +### Installing the SDK + +1. **Run the self-extracting installation script of the SDK.** + +Run the following command: + +``` +sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh +``` + +Enter the installation path of the toolchain as prompted. The default path is **/opt/openeuler/\/**. You can also set the path to a relative or absolute path. + +The following is an example: + +``` +sh ./openeuler-glibc-x86_64-openeuler-image-armv7a-qemu-arm-toolchain-22.03.sh`` +openEuler embedded(openEuler Embedded Reference Distro) SDK installer version 22.03 +================================================================ +Enter target directory for SDK (default: /opt/openeuler/22.03): sdk +You are about to install the SDK to "/usr1/openeuler/sdk". Proceed [Y/n]? y +Extracting SDK...............................................done +Setting it up...SDK has been successfully set up and is ready to be used. +Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. +$ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +2. **Set the environment variable of the SDK.** + +Run the `source` command. The `source` command is displayed in the output of the previous step. Run the command. + +``` +. /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +3. **Check whether the installation is successful.** + +Run the following command to check whether the installation and environment configuration are successful: + +``` +arm-openeuler-linux-gnueabi-gcc -v +``` + +### Using the SDK to Build a Hello World Example + +1. **Prepare the code.** + +The following describes how to build a hello world program that runs in the image of the openEuler Embedded root file system. + +Create a **hello.c** file. The source code is as follows: + +``` c +#include + +int main(void) +{ + printf("hello world\n"); +} +``` + +Compose a **CMakelist.txt** file as follows and place it in the same directory as the **hello.c** file. + +``` +project(hello C) + +add_executable(hello hello.c) +``` + +2. **Compile and generate a binary file.** + +Go to the directory where the **hello.c** file is stored and run the following commands to compile the file using the toolchain: + +``` +cmake .. +make +``` + +Copy the compiled **hello** program to a sub-directory of **/tmp/** (for example, **/tmp/myfiles/**) on openEuler Embedded. For details about how to copy the file, see [Shared File System Enabled Scenario](./installation-and-running.md#shared-file-system-enabled-scenario). + +3. **Run the user-mode program.** + +Run the **hello** program on openEuler Embedded. + +``` +cd /tmp/myfiles/ +./hello +``` + +If the running is successful, the message **hello world** is displayed. + +### Using the SDK to Build a Kernel Module Example + +1. **Prepare the environment.** + +After setting up the SDK, you need to prepare the environment for compiling the kernel module. Run the following commands to create the corresponding kernel module compilation environment: + +``` +cd /sysroots/-openeuler-linux/usr/src/kernel +make module_prepare +``` + +2. **Prepare the code.** + +The following describes how to build a kernel module that runs in the kernel of openEuler Embedded. + +Create a **hello.c** file. The source code is as follows: + +```c +#include +#include + +static int hello_init(void) +{ + printk("Hello, openEuler Embedded!\r\n"); + return 0; +} + +static void hello_exit(void) +{ + printk("Byebye!"); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_LICENSE(GPL); +``` + +Compose a Makefile as follows and place it in the same directory as the **hello.c** file. + +``` + KERNELDIR := ${KERNEL_SRC_DIR} + CURRENT_PATH := $(shell pwd) + + target := hello + obj-m := $(target).o + + build := kernel_modules + + kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean +``` + +`KERNEL_SRC_DIR` indicates the directory of the kernel source tree. This variable is automatically configured after the SDK is installed. + +3. **Compile and generate a kernel module.** + +Go to the directory where the **hello.c** file is stored and run the following command to compile the file using the toolchain: + + make + +Copy the compiled **hello.ko** file to a directory on openEuler Embedded. For details about how to copy the file, see the [Shared File System Enabled Scenario](./installation-and-running.md#shared-file-system-enabled-scenario). + +4. **Insert the kernel module.** + +Insert the kernel module to openEuler Embedded: + + insmod hello.ko + +If the running is successful, the message **Hello, openEuler Embedded!** is output to the kernel logs. \ No newline at end of file diff --git a/docs/en/docs/Embedded/container-build-guide.md b/docs/en/docs/Embedded/container-build-guide.md new file mode 100644 index 000000000..ee6e8e6af --- /dev/null +++ b/docs/en/docs/Embedded/container-build-guide.md @@ -0,0 +1,151 @@ +Container Build Guide +============================== + +The openEuler Embedded build process is based on the openEuler OS, and requires many system tools and build tools to be installed. To help developers quickly set up a build environment, the operating system and tools on which the build process depends are encapsulated into a container. In this way, developers can avoid the time-consuming environment preparation process and focus on development. + + + + - [Environment Preparation](#environment-preparation) + - [Installing Docker](#installing-docker) + - [Obtaining the Container Image](#obtaining-the-container-image) + - [Preparing the Container Build Environment](#preparing-the-container-build-environment) + - [Version Build](#version-build) + - [Downloading Source Code](#downloading-source-code) + - [Compiling the build](#compiling-the-build) + - [Build Result](#build-result) + + +## Environment Preparation + +Use Docker to create a container environment. The software and hardware requirements of Docker are as follows: + +- OS: Ubuntu, Debian, and RHEL (CentOS and Fedora) are recommended. +- Kernel: Linux 3.8 or later is recommended. +- Driver: The kernel must include a proper storage driver, for example, Device Mapper, AUFS, vfs, btrfs, or ZFS. +- Architecture: 64-bit architecture (x86-64 or AMD64). + +### Installing Docker + +------------- + +1. Check whether Docker has been installed in the current environment. + +Run the following command. If the Docker version is displayed, Docker has been installed in the current environment. You can use it directly. + +``` {.sourceCode .console} +docker version +``` + +1. If Docker is not installed, install it by referring to the [official document](http://docs.docker.com/engine/install/). + +Install Docker on openEuler by referring to the installation guide for CentOS. + +For example, run the following command to install Docker on openEuler: + +``` +sudo yum install docker +``` + +### Obtaining the Container Image + +--------------- + +Run the `docker pull` command to pull the image from Huawei Cloud to the host machine: + +``` +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +``` + +### Preparing the Container Build Environment + +------------------- + +#### 1. Start a container. + +Run the docker run command to start the container. To ensure that the container can run in the background and access the Internet after being started, you are advised to run the following command to start the container: + +``` +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +``` + +Parameter description: + +- -i: keeps the standard input open. +- -d: starts a container in daemon mode in the background. +- -t: allocates a pseudo-tty and binds it to the standard input of the container. +- \--network: connects the container to the network of the host machine. +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest (image_name:image_version) +- bash: method for accessing a container. + +#### 2. Check the ID of the started container. + +``` +docker ps +``` + +#### 3. Enter the container. + +``` +docker exec -it bash +``` + +After the build environment is ready, you can build in the container. + +## Version Build + +### Downloading Source Code + +1. Obtain the source code download script. + +``` +git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v /usr1/openeuler/src/yocto-meta-openeuler +``` + +2. Download the source code using the script. + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +sh download_code.sh /usr1/openeuler/src +``` + +### Compiling the build + +- Compilation architecture: aarch64-std, aarch64-pro, arm-std or raspberrypi4-64 +- Build directory: **/usr1/build** +- Source code directory: **/usr1/openeuler/src** +- Path of the compiler: **/usr1/openeuler/gcc/openeuler\_gcc\_arm64le** + +>![](./public_sys-resources/icon-note.gif) **NOTE** +>- Use different compilers for different compilation architectures. aarch64-std, aarch64-pro, and raspberrypi4-64 use the openeuler\_gcc\_arm64le compiler, and arm-std uses the openeuler\_gcc\_arm32le compiler. +>- The following uses the aarch64-std architecture as an example. + +1. Change the owner group of the **/usr1** directory to openeuler. Otherwise, permission issues may occur when switching to the **openeuler** user. + +``` +chown -R openeuler:users /usr1 +``` + +2. Switch to the **openeuler** user. + +``` +su openeuler +``` + +3. Go to the path where the compilation script is stored and run the script. + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +source compile.sh aarch64-std /usr1/build /usr1/openeuler/gcc/openeuler_gcc_arm64le +bitbake openeuler-image +``` + +### Build Result + +By default, the files are generated in the **output** directory of the build directory. For example, the built files of the aarch64-std example are generated in the **/usr1/build/output** directory, as shown in the following table: + +| Filename | Description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-\* | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded SDK toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | diff --git a/docs/en/docs/Embedded/embedded.md b/docs/en/docs/Embedded/embedded.md index b4aa274ed..5c0af0196 100644 --- a/docs/en/docs/Embedded/embedded.md +++ b/docs/en/docs/Embedded/embedded.md @@ -1,185 +1,5 @@ -# openEuler Embedded Usage Guide +# openEuler Embedded User Guide -openEuler Embedded is a Linux version for embedded scenarios based on the openEuler community version. The embedded system applications are restricted by multiple factors, such as resources, power consumption, and diversity. Therefore, the server-oriented Linux versions and the corresponding build systems can hardly satisfy the requirements of embedded scenarios. The [Yocto](https://www.yoctoproject.org/) is widely used to customize and build embedded Linux. Currently, openEuler Embedded is also built using Yocto, but has the same source code as other openEuler versions. For details about the build method, see the related code repository in [SIG-Yocto](https://gitee.com/openeuler/community/tree/master/sig/sig-Yocto). +openEuler Embedded is a Linux distribution for embedded scenarios based on the openEuler community version aiming to build a high-quality Linux-centric embedded software platform. openEuler Embedded will keep consistent with other openEuler versions in terms of kernel and software versions, with kernel configurations, software package combinations and configurations, and feature patches optimized for embedded scenarios. -This document describes how to obtain pre-built images, run the images, and develop basic embedded Linux applications based on the images. - -## Obtaining the Image -The released pre-built images support only the ARM and AArch64 architectures, and are compatible only with the ARM virt-4.0 platform of QEMU. You can obtain the images through the following links: - -- [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm) for ARM Cortex A15 processor of 32-bit ARM architecture. -- [qemu_aarch64](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-aarch64) for ARM Cortex A57 processor of 64-bit AArch64 architecture. - -You can deploy an openEuler Embedded image on a physical bare-metal server, cloud server, container, or VM as long as the environment supports QEMU emulator version 5.0 or later. - -## Image Content - -The downloaded image consists of the following parts: - -- Kernel image **zImage**, which is built based on Linux 5.10 of the openEuler community. You can obtain the kernel configurations through the following links: - - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel) for the AArch64 architecture. The image provides the image self-decompression function in addition. For details, see the corresponding [patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch). - -- Root file system image (select one of the following as required): - - **initrd_tiny**, which is the image of the simplified root file system with only basic functions. It contains the BusyBox and basic glibc library. The image is simple and consumes little memory. It is suitable for exploring Linux kernel functions. - - **initrd**, which is the image of the standard root file system. In addition to the content of the simplified root file system image, the standard image has received necessary security hardening and includes various software packages, such as audit, cracklib, OpenSSH, Linux PAM, shadow and iSula containers. This image is suitable for exploring more functions. - -## Executing the Image - -You can run the image to experience the functions of openEuler Embedded, and develop basic embedded Linux applications. - ---- -**_Note_** - -- You are advised to use QEMU 5.0 or later to run the image. Some additional functions (the network and shared file system) depend on the virtio-net and virtio-fs features of QEMU. If these features are not enabled in QEMU, errors may occur during image running. In this case, you may need to recompile QEMU from the source code. - -- When running the image, you are advised to place the kernel image and root file system image in the same directory. The following uses the standard root file system image (initrd) as an example. - ---- - - -### Simplified Running Scenario - -In this scenario, the network and shared file system are not enabled in QEMU. You can use this scenario to experience the functions. - -For ARM architecture (ARM Cortex A15), run the following command: -```shell -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```shell -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -``` - -The standard root file system image is securely hardened and requires you to set a password for the root user during the first startup. The password must contain at least eight characters, including digits, letters, and special characters, for example, openEuler@2021. For systems running the simplified root file system image, you can log in without the user name and password. - -After you successfully run QEMU and log in to the system, the Shell of openEuler Embedded is displayed. - -### Shared File System Enabled Scenario - -Shared file system allows the host machine of QEMU emulator to share files with openEuler Embedded. In this way, programs that are cross-compiled on the host machine can run on openEuler Embedded after being copied to the shared directory. - -Assume that the `/tmp` directory of the host machine is used as the shared directory, and a `hello_openeuler.txt` file is created in the directory in advance. To enable the shared file system function, perform the following steps: - -1. **Start QEMU.** - -For ARM architecture (ARM Cortex A15), run the following command: -```sh -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```sh -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp -``` - -2. **Mount the file system.** - -After you start and log in to openEuler Embedded, run the following commands to mount the shared file system: -```shell -cd /tmp -mkdir host -mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host -``` -The shared file system is mounted to the `/tmp/host` directory of openEuler Embedded. - -3. **Check whether the file system is shared successfully.** - -In openEuler Embedded, run the following commands: - -```shell -cd /tmp/host -ls -``` -If `hello_openeuler.txt` is discovered, the file system is shared successfully. - -### Network Enabled Scenario - -The virtio-net of QEMU and the virtual NIC of the host machine allow for the network communication between the host machine and openEuler Embedded. -1. **Start QEMU.** - -For ARM architecture (ARM Cortex A15), run the following command: -```shell -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```shell -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup -``` -2. **Create the vNIC on the host machine.** - -You can use the `/etc/qemu-ifup` script to create a **tap0** vNIC on the host machine. **root** permission is required for running the script. The script details are as follows: - -```sh -#!/bin/bash -ifconfig $1 192.168.10.1 up -``` -Use the `qemu-ifup` script to create a **tap0** vNIC on the host machine. The IP address of the vNIC is 192.168.10.1. - -3. **Configure the NIC of openEuler Embedded.** - -Log in to openEuler Embedded and run the following command: -```shell -ifconfig eth0 192.168.10.2 -``` - -4. **Check whether the network connection is normal.** - -In openEuler Embedded, run the following command: -```shell -ping 192.168.10.1 -``` - -If the IP address can be pinged, the network connection between the host machine and openEuler Embedded is normal. - ---- -**_Note_** - -If you need openEuler Embedded to access the Internet through the host machine, create a bridge on the host machine. For details, see the related documents. - ---- - -## User-Mode Application Development Based on openEuler Embedded - -In addition to the basic functions of openEuler Embedded, you can also use the released images for the basic development of user-mode applications, that is, running your own programs on openEuler Embedded. - - -1. **Prepare the environment.** - -The current images are built using the Linaro ARM/AArch64 GCC 7.3.1 toolchains. It is recommended that the same toolchains are used for application development. You can obtain the toolchains from the following links: -- [linaro arm](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabi/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabi.tar.xz) -- [linrao arm sysroot](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabi/sysroot-glibc-linaro-2.25-2018.05-arm-linux-gnueabi.tar.xz) -- [linaro aarch64](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz) -- [linrao aarch64 sysroot](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu.tar.xz) - -Download and decompress the required packages to a specified directory, for example, `/opt/openEuler_toolchain`. - -2. **Create and compile a user-mode program.** - -The following uses a `hello openEuler` program as an example to describe how to build a program that runs on the AArch64 standard root file system image. - -Create a `hello.c` file on the host machine. The source code is as follows: -```c -#include - -int main(void) -{ - printf("hello openEuler\r\n"); -} -``` - -On the host machine, run the following commands to compile using the corresponding toolchain: -```shell -export PATH=$PATH:/opt/openEuler_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin -aarch64-linux-gnu-gcc --sysroot= hello.c -o hello -mv hello /temp -``` -Copy the cross-compiled hello program to the `/tmp` directory, and enable openEuler Embedded to access the directory on the host machine by referring to the description in **Shared File System Enabled Scenario**. - -3. **Run the user-mode program.** - -In openEuler Embedded, run the following commands to run the hello program: -```shell -cd /tmp/host -./hello -``` -If the program runs successfully, **hello openEuler** is displayed in the Shell of openEuler Embedded. +This document describes how to obtain pre-built images, run the images, develop basic embedded Linux applications based on the images, and build openEuler Embedded. diff --git a/docs/en/docs/Embedded/installation-and-running.md b/docs/en/docs/Embedded/installation-and-running.md new file mode 100644 index 000000000..7eeb26cd6 --- /dev/null +++ b/docs/en/docs/Embedded/installation-and-running.md @@ -0,0 +1,166 @@ +# Installation and Running + +This chapter describes how to obtain a pre-built image and how to run an image. + + + +- [Installation and Running](#installation-and-running) + - [Obtaining the Image](#obtaining-the-image) + - [Image Content](#image-content) + - [Running the Image](#running-the-image) + - [Simplified Running Scenario](#simplified-running-scenario) + - [Shared File System Enabled Scenario](#shared-file-system-enabled-scenario) + - [Network Enabled Scenario](#network-enabled-scenario) + + +## Obtaining the Image +The released pre-built images support only the ARM and AArch64 architectures, and are compatible only with the ARM virt-4.0 platform of QEMU. You can obtain the images through the following links: + +- [qemu_arm](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm32/arm-std/) for ARM Cortex A15 processor of 32-bit ARM architecture. +- [qemu_aarch64](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm64/aarch64-std/) for ARM Cortex A57 processor of 64-bit AArch64 architecture. + +You can deploy an openEuler Embedded image on a physical bare-metal server, cloud server, container, or VM as long as the environment supports QEMU emulator version 5.0 or later. + +## Image Content + +The downloaded image consists of the following parts: + +- Kernel image **zImage**, which is built based on Linux 5.10 of the openEuler community. You can obtain the kernel configurations through the following links: + - [ARM(Cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm/defconfig-kernel) + - [ARM(Cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm64/defconfig-kernel) for the AArch64 architecture. The image provides the image self-decompression function in addition. For details, see the corresponding [patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch). + +- Root file system image: + - **openeuler-image-qemu-xxx.cpio.gz**, which is the image of the standard root file system. It has received necessary security hardening and includes various software packages, such as audit, cracklib, OpenSSH, Linux PAM, shadow and software packages supported by iSula. + +- Software Development Kit (SDK) + + - **openeuler-glibc-x86_64-xxxxx.sh**: The self-extracting installation package of openEuler Embedded SDK. The SDK contains tools, libraries, and header files for developing user mode applications and kernel modules. + +## Running the Image + +You can run the image to experience the functions of openEuler Embedded, and develop basic embedded Linux applications. + +--- +**Precautions** + +- You are advised to use QEMU 5.0 or later to run the image. Some additional functions (the network and shared file system) depend on the virtio-net and virtio-fs features of QEMU. If these features are not enabled in QEMU, errors may occur during image running. In this case, you may need to recompile QEMU from the source code. + +- When running the image, you are advised to place the kernel image and root file system image in the same directory. + +--- + +Download and install QEMU by referring to the [QEMU official website](https://www.qemu.org/download/#linux), or download and build from [source](https://www.qemu.org/download/#source). Use the following command to verify the installation: + +``` +qemu-system-aarch64 --version +``` + +### Simplified Running Scenario + +In this scenario, the network and shared file system are not enabled in QEMU. You can use this scenario to experience the functions. + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd +``` + +>![](./public_sys-resources/icon-note.gif) **Note:** +>The standard root file system image is securely hardened and requires you to set a password for the **root** user during the first startup. The password must contain at least eight characters, including digits, letters, and special characters, for example, **openEuler@2021**. + + +2. **Check whether QEMU is started successfully.** + +The shell of openEuler Embedded will be displayed after QEMU is successfully started and logged in. + +### Shared File System Enabled Scenario + +Shared file system allows the host machine of QEMU emulator to share files with openEuler Embedded. In this way, programs that are cross-compiled on the host machine can run on openEuler Embedded after being copied to the shared directory. + +Assume that the **/tmp** directory of the host machine is used as the shared directory, and a **hello_openeuler.txt** file is created in the directory in advance. To enable the shared file system function, perform the following steps: + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp +``` + +2. **Mount the file system.** + +After you start and log in to openEuler Embedded, run the following commands to mount the shared file system: +``` +cd /tmp +mkdir host +mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host +``` +The shared file system is mounted to the **/tmp/host** directory of openEuler Embedded. + +3. **Check whether the file system is shared successfully.** + +In openEuler Embedded, run the following commands: + +``` +cd /tmp/host +ls +``` +If **hello_openeuler.txt** is discovered, the file system is shared successfully. + +### Network Enabled Scenario + +The virtio-net of QEMU and the virtual NIC of the host machine allow for the network communication between the host machine and openEuler Embedded. In addition to sharing files using virtio-fs, you can transfer files between the host machine and openEuler Embedded using the network, for example, the **scp** command. + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup +``` +2. **Create a vNIC on the host machine.** + +You can create a **/qemu-ifup** script in the **/etc** directory and run the script to create a **tap0** vNIC on the host machine. The script details are as follows: + +``` +#!/bin/bash +ifconfig $1 192.168.10.1 up +``` +**root** permissions are required for running the script. + +``` +chmod a+x qemu-ifup +``` + +Use the **qemu-ifup** script to create a **tap0** vNIC on the host machine. The IP address of the vNIC is **192.168.10.1**. + +3. **Configure the NIC of openEuler Embedded.** + +Log in to openEuler Embedded and run the following command: +``` +ifconfig eth0 192.168.10.2 +``` + +4. **Check whether the network connection is normal.** + +In openEuler Embedded, run the following command: +``` +ping 192.168.10.1 +``` + +If the IP address can be pinged, the network connection between the host machine and openEuler Embedded is normal. + +--- +>![](./public_sys-resources/icon-note.gif) **Note:** + >If you need openEuler Embedded to access the Internet through the host machine, create a bridge on the host machine. For details, see the related documents. diff --git a/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md b/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md new file mode 100644 index 000000000..3c4d340c1 --- /dev/null +++ b/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md @@ -0,0 +1,32 @@ +# openEuler Embedded 22.03 Release Notes + +openEuler Embedded 22.03 is the first official release of openEuler Embedded. This section describes the main features of this version. + +## Kernel + +- The kernel is upgraded to 5.10.0-60.17.0. + +- The kernel supports Preempt-RT patches. + +- The kernel supports Raspberry Pi 4B patches. + +## Software Packages + +- More than 80 software packages are supported. For details, see [Supported Software Packages](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html). + +## Feature Highlights + +- The multi-OS hybrid deployment framework supports hybrid deployment of openEuler Embedded and Zephyr. For details, see [Multi-OS Hybrid Deployment Framework](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html). +- The distributed soft bus is preliminarily integrated. For details, see [Distributed Soft Bus](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html). + +- For details about security hardening, see [Security Hardening Description](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html). +- Preempt-RT-based soft real-time. For details, see [Soft Real-Time System Introduction](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html). + +## Southbound Ecosystem + +- Added support for Raspberry Pi 4B. For details, see [Support for Raspberry Pi 4B](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html). + +## Build System + +- openEuler Embedded build system is preliminarily implemented. For details, see [Quick Build Guide](./quick-build-guide.md). +- Containerized build. For details, see [Container Build Guide](./container-build-guide.md). diff --git a/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md b/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md new file mode 100644 index 000000000..5c8f74c6d --- /dev/null +++ b/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md @@ -0,0 +1,7 @@ +openEuler Embedded Build Guide +===================== + +This document provides two methods for preparing a building environment and describes the building process in details. Choose one of the methods as required. + +- To build openEuler Embedded, see [Quick Build Guide](./quick-build-guide.md) +- For containerized build, see [Container Build Guide](./container-build-guide.md) \ No newline at end of file diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-caution.gif b/docs/en/docs/Embedded/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-danger.gif b/docs/en/docs/Embedded/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-note.gif b/docs/en/docs/Embedded/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-notice.gif b/docs/en/docs/Embedded/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 GIT binary patch literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/quick-build-guide.md b/docs/en/docs/Embedded/quick-build-guide.md new file mode 100644 index 000000000..0f9625d64 --- /dev/null +++ b/docs/en/docs/Embedded/quick-build-guide.md @@ -0,0 +1,146 @@ +Quick Build Guide +===================== + +This chapter describes how to build openEuler Embedded. + + + - [Environment Preparation](#environment-preparation) + - [Using Host Machine Commands in Yocto](#using-host-machine-commands-in-yocto) + - [Tools Required for Building openEuler Embedded](#tools-required-for-building-openeuler-embedded) + - [Build Container with Tools Installed](#build-container-with-tools-installed) + - [Version Build](#version-build) + - [Downloading Build Code](#downloading-build-code) + - [Compiling the Build](#compiling-the-build) + - [Build Result](#build-result) + + +Environment Preparation +-------------- + +### Using Host Machine Commands in Yocto + +Yocto, or BitBake, is a group of Python programs. The minimum environment requirements are as follows: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +Yocto can build other tools required in the build process based on the corresponding software package recipes so that Yocto is self-contained. During this process, Yocto installs dedicated Yocto patches for corresponding tools (such as DNF and RPM) as required. These host tools are built from the source code in the first build. Therefore, the first build of Yocto can be time-consuming. + +To accelerate the building process, especially for the first build, openEuler Embedded preferentially uses the pre-built native tools on the host. This requires that the software package management tools (such as APT, DNF, Yum, and Zypper) be installed in advance. + +Yocto uses the **HOSTTOOLS** variable to introduce host tools and creates a soft link for each tool listed in **HOSTTOOLS**. To prevent host contamination, Yocto prepares an environment that is independent from the host, for example, the **PATH** variable. Therefore, if a command that depends on the host is added, the command must be added to **HOSTTOOLS**. Otherwise, even if the command exists on the host, an error message will be displayed during Yocto building, indicating that the corresponding tool cannot be found. The following figure shows the process. + +![](./public_sys-resources/hosttools.png) + +The host tools required by openEuler Embedded are defined in **HOSTTOOLS** in the **local.conf.sample** file by default. The tools include: + +| Tool| Description | +| ------ | ------------- | +| cmake | CMake build tool| +| ninjia | Ninja build system| + +### Tools Required for Building openEuler Embedded + +- Operating system. + + [openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- Additional tools. + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- Pre-built cross-compilation toolchain and library. + + Yocto can build the cross-compilation toolchains and C libraries required for cross-compilation. However, the process is complex and time-consuming and is performed only in the first build. At the same time, most developers do not build toolchains and C libraries themselves. To simplify the process, openEuler Embedded uses pre-built cross-compilation toolchains and libraries maintained by the openEuler community. + + Currently, the toolchains for the ARM32 and AArch64 architectures are provided. You can download the toolchains by performing the following methods: + + - [ARM32 Toolchain] (https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [AArch64 Toolchain] (https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + - Download the RPM package: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` + - Decompress the RPM package: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` + - After the decompression, a **/tmp** directory containing the toolchain is generated in the current directory. + - Toolchain for the ARM 32-bit architecture: openeuler_gcc_arm32le.tar.xz + - Toolchain for the ARM 64-bit architecture: openeuler_gcc_arm64le.tar.xz + +### Build Container with Tools Installed + +A large number of host tools are used during the build of openEuler Embedded. To accelerate the build process, openEuler Embedded uses the tools installed on the host in advance. However, the tool versions vary depending on the host environment. For example, CMake 1.9 or later is required for the build, but the version on the host is CMake 1.8. To solve this problem, openEuler Embedded provides a dedicated build container to provide a unified build environment. + +You can obtain the container images for the build from the following link: + +​ [Basic Build Container Image for openEuler Embedded](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +For details, see the [Container Build Guide](./container-build-guide.html). + +## Version Build + +### Downloading Build Code + +The file layout of the openEuler Embedded build project is as follows. Assume that **openeuler\_embedded** is the top-level directory. + +> +>├── src Source code directory, including all software package code, kernel code, and Yocto build code +>├── build openEuler Embedded build directory. The generated images are stored in this directory. + +1. Obtain the source code download script. + + Download the script to a specified directory, for example, **src/yocto-meta-openeuler**. + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + The script **src/yocto-meta-openeuler/scripts/download\_code.sh** has the following parameters: + + - 1. Path to download the source code. By default, the source code is downloaded relative to the script location. For example, in the preceding example, the code repository is downloaded to the **src/** directory. + - 2. Branch to be downloaded. See the script for the default value. Determine the branch based on the version. + - 3. XML file for downloading the code, which is in the standard manifest format. The code is downloaded based on the XML configurations. + +2. Download the source code using the script. + + - To download the latest code: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - To download the code of a specified version: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + Obtain the **manifest.xml** file for specifying the version of the openEuler Embedded code from the openEuler Embedded release directory **embedded\_img/source-list/**. + +### Compiling the Build + +Run the one-click compilation script **src/yocto-meta-openeuler/scripts/compile.sh**. For details, see the script content. + +The process of the compilation script is as follows: + +1. Adds the paths of the additional tools to **PATH**. +2. Sets the **TEMPLATECONF** variable to include the paths of configuration files such as **local.conf.sample**. +3. Invokes `oe-init-build-env` of the Poky repository to perform initial configuration. +4. Sets the **MACHINE** variable in the **conf/local.conf** file in the compilation directory to add layers as required. +5. Runs the `bitbake openeuler-image` command in the compilation directory to build the image and SDK of openEuler Embedded. +6. The files are generated in the **output** directory of the compilation directory. + +Run the compilation script. The following uses the standard ARM architecture as an example to describe the compilation method: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image # You will be prompted to run the bitbake command after the source command is executed + +### Build Result + +By default, the files are generated in the **output** directory of the build directory. For example, the built files of the ARM example are generated in the **/usr1/build/output** directory, as shown in the following table: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-\* | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | diff --git a/docs/en/docs/Gazelle/Gazelle.md b/docs/en/docs/Gazelle/Gazelle.md new file mode 100644 index 000000000..380a8876b --- /dev/null +++ b/docs/en/docs/Gazelle/Gazelle.md @@ -0,0 +1,263 @@ +# Gazelle User Guide + +## Introduction + +Gazelle is a high-performance user-mode protocol stack. It directly reads and writes NIC packets in user mode based on DPDK and transmit the packets through shared hugepage memory, and uses the LwIP protocol stack. Gazelle greatly improves the network I/O throughput of applications and accelerates the network for the databases, such as MySQL and Redis. +- High Performance +Zero-copy and lock-free packets that can be flexibly scaled out and scheduled adaptively. +- Universality +Compatible with POSIX without modification, and applicable to different types of applications. + +In the single-process scenario where the NIC supports multiple queues, **liblstack.so** is used to shorten the packet path. In other scenarios, the ltran process is used to distribute packets to each thread. + +## Installation +Configure the Yum source of openEuler and run the`yum` command to install Gazelle. +```sh +#dpdk >= 21.11-2 +yum install dpdk +yum install libconfig +yum install numactl +yum install libboundscheck +yum install libpcap +yum install gazelle +``` + +## Usage +To configure the running environment and use Gazelle to accelerate applications, perform the following steps: +### 1. Installing the .ko File as the **root** User +Install the .ko files based on the site requirements to enable the virtual network ports and bind NICs to the user-mode driver. +To enable the virtual network port function, use **rte_kni.ko**. +``` sh +modprobe rte_kni carrier="on" +``` +Bind the NIC from the kernel driver to the user-mode driver. Choose one of the following .ko files based on the site requirements. +``` sh +#If the IOMMU is available +modprobe vfio-pci + +#If the IOMMU is not available and the VFIO supports the no-IOMMU mode +modprobe vfio enable_unsafe_noiommu_mode=1 +modprobe vfio-pci + +#Other cases +modprobe igb_uio +``` + + +### 2. Binding the NIC Using DPDK +Bind the NIC to the driver selected in Step 1 to provide an interface for the user-mode NIC driver to access the NIC resources. +``` sh +# Using vfio-pci +dpdk-devbind -b vfio-pci enp3s0 + +# Using igb_uio +dpdk-devbind -b igb_uio enp3s0 +``` + +### 3. Configuring Memory Huge Pages +Gazelle uses hugepage memory to improve efficiency. You can configure any size for the memory huge pages reserved by the system using the **root** permissions. Each memory huge page requires a file descriptor. If the memory is large, you are advised to use 1 GB huge pages to avoid occupying too many file descriptors. +Select a page size based on the site requirements and configure sufficient memory huge pages. Run the following commands to configure huge pages: +``` sh +# Configuring 1024 2 MB huge pages on node0. Total memory is 2 GB. +echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages + +# Configuring 5 1 GB huge pages on node0. Total memory is 5 GB. +echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages + +# Viewing configuration results. +grep Huge /proc/meminfo +``` + +### 4. Mounting Memory Huge Pages +Create two directories for the lstack and ltran processes to access the memory huge pages. Run the following commands: +``` sh +mkdir -p /mnt/hugepages +mkdir -p /mnt/hugepages-2M +chmod -R 700 /mnt/hugepages +chmod -R 700 /mnt/hugepages-2M +mount -t hugetlbfs nodev /mnt/hugepages +mount -t hugetlbfs nodev /mnt/hugepages-2M +``` + +### 5. Enabling Gazelle for an Application +Enable Gazelle for an application using either of the following methods as required. +- Recompiling the application to link the Gazelle library. +Modify the makefile of the application to link to **liblstack.so**. The following is an example: +``` +# Add the Makefile of Gazelle to the application makefile. +-include /etc/gazelle/lstack.Makefile + +# Add the LSTACK_LIBS variable when compiling the source code. +gcc test.c -o test ${LSTACK_LIBS} +``` + +- Using the **LD_PRELOAD** environment variable to load the Gazelle library. +Use the **GAZELLE_BIND_PROCNAME** environment variable to specify the process name, and **LD_PRELOAD** to specify the Gazelle library path. +``` +GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test +``` + +### 6. Configuring Gazelle +- The **lstack.conf** file is used to specify the startup parameters of lstack. The default path is **/etc/gazelle/lstack.conf**. The parameters in the configuration file are as follows: + +|Parameter|Value|Description| +|:---|:---|:---| +|dpdk_args|--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-type (mandatory)
--legacy-mem
--map-perfect
|DPDK initialization parameter. For details, see the DPDK description.| +|use_ltran| 0/1 | Whether to use ltran.| +|num_cpus|"0,2,4 ..."|IDs of the CPUs bound to the lstack threads. The number of IDs is the number of lstack threads (less than or equal to the number of NIC queues). You can select CPUs by NUMA nodes.| +|num_wakeup|"1,3,5 ..."|IDs of the CPUs bound to the wakeup threads. The number of IDs is the number of wakeup threads, which is the same as the number of lstack threads. Select CPUs of the same NUMA nodes of the num_cpus parameter respectively. If this parameter is not set, the wakeup thread is not used.| +|low_power_mode|0/1|Whether to enable the low-power mode. This parameter is not supported currently.| +|kni_swith|0/1|Whether to enable the rte_kni module. The default value is 0. This module can be enabled only when ltran is not used.| +|host_addr|"192.168.xx.xx"|IP address of the protocol stack, which must be consistent with the **bind** field in the redis-server configuration file.| +|mask_addr|"255.255.xx.xx"|Subnet mask.| +|gateway_addr|"192.168.xx.1"|Gateway IP address.| +|devices|"aa:bb:cc:dd:ee:ff"|MAC address for NIC communication. The value must be the same as that of **bond_macs** in the **ltran.conf** file.| + + +**lstack.conf** example: +``` conf +dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-2M", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] + +use_ltran=1 +kni_switch=0 + +low_power_mode=0 + +num_cpus="2,22" +num_wakeup="3,23" + +host_addr="192.168.1.10" +mask_addr="255.255.255.0" +gateway_addr="192.168.1.1" +devices="aa:bb:cc:dd:ee:ff" +``` + +- The **ltran.conf** file is used to specify ltran startup parameters. The default path is **/etc/gazelle/ltran.conf**. To enable ltran, set **use_ltran=1** in the **lstack.conf** file. The configuration parameters are as follows: + +|**Function**|Parameter|Value|Description| +|:---|:---|:---|:---| +|kit|forward_kit|"dpdk"|Specifies the transceiver module of an NIC.
This field is reserved and is not used currently.| +||forward_kit_args|-l
--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-TYPE (mandatory)
--legacy-mem (mandatory)
--map-perfect (mandatory)
|DPDK initialization parameter. For details, see the DPDK description.
Note: **--map-perfect** is an extended feature. It is used to prevent the DPDK from occupying excessive address space and ensure that extra address space is available for lstack.| +|kni|kni_switch|0/1|Whether to enable the rte_kni module. The default value is 0.| +|dispatcher|dispatch_max_clients|n|Maximum number of clients supported by ltran.
1. In the multi-process single-thread scenario, the number of lstack instances cannot exceed 32. Each lstack instance has one network thread.
2. In the single-process multi-thread scenario, one lstack instance is supported. The number of network threads of the lstack instance cannot exceed 32.| +||dispatch_subnet|192.168.xx.xx|Subnet mask, which is the subnet segment of the IP addresses that can be identified by ltran. The value is an example. Set the subnet based on the site requirements.| +||dispatch_subnet_length|n|Length of the Subnet that can be identified by ltran. For example, if the value of length is 4, the value ranges from 192.168.1.1 to 192.168.1.16.| +|bond|bond_mode|n|Bond mode. Currently, only Active Backup (Mode1) is supported. The value is 1.| +||bond_miimon|n|Bond link monitoring time. The unit is millisecond. The value ranges from 1 to 2^64 - 1 - (1000 x 1000).| +||bond_ports|"0xaa"|DPDK NIC to be used. The value 0x1 indicates the first NIC.| +||bond_macs|"aa:bb:cc:dd:ee:ff"|MAC address of the bound NIC, which must be the same as the MAC address of the KNI.| +||bond_mtu|n|Maximum transmission unit. The default and maximum value is 1500. The minimum value is 68.| + +**ltran.conf** example: +``` conf +forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages --proc-type primary --legacy-mem --map-perfect --syslog daemon" +forward_kit="dpdk" + +kni_switch=0 + +dispatch_max_clients=30 +dispatch_subnet="192.168.1.0" +dispatch_subnet_length=8 + +bond_mode=1 +bond_mtu=1500 +bond_miimon=100 +bond_macs="aa:bb:cc:dd:ee:ff" +bond_ports="0x1" + +tcp_conn_scan_interval=10 +``` +### 7. Starting an Application +- Start the ltran process. +If there is only one process and the NIC supports multiple queues, the NIC multi-queue is used to distribute packets to each thread. You do not need to start the ltran process. Set the value of **use_ltran** in the **lstack.conf** file to **0**. +If you do not use `-config-file` to specify a configuration file when starting ltran, the default configuration file path **/etc/gazelle/ltran.conf** is used. +``` sh +ltran --config-file ./ltran.conf +``` +- Start the application. +If the environment variable **LSTACK_CONF_PATH** is not used to specify the configuration file before the application is started, the default configuration file path **/etc/gazelle/lstack.conf** is used. +``` sh +export LSTACK_CONF_PATH=./lstack.conf +LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf +``` + +### 8. APIs +Gazelle wraps the POSIX interfaces of the application. The code of the application does not need to be modified. + +### 9. Commissioning Commands +- If ltran is not used, the `gazellectl ltran xxx` and `lstack -r` commands are not supported. +``` +Usage: gazellectl [-h | help] + or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] + or: gazellectl lstack show {ip} [LSTACK_OPTIONS] [time] + + quit ltran process exit + + where LTRAN_OPTIONS := + show ltran all statistics + -r, rate show ltran statistics per second + -i, instance show ltran instance register info + -b, burst show ltran NIC packet len per second + -l, latency show ltran latency + + where LSTACK_OPTIONS := + show lstack all statistics + -r, rate show lstack statistics per second + -s, snmp show lstack snmp + -c, connetct show lstack connect + -l, latency show lstack latency + + [time] measure latency time default 1S +``` + +### 10. Precautions +#### 1. Location of the DPDK Configuration File +For the **root** user, the configuration file is stored in the **/var/run/dpdk** directory after the DPDK is started. +For a non-root user, the path of the DPDK configuration file is determined by the environment variable **XDG_RUNTIME_DIR**. +- If **XDG_RUNTIME_DIR** is not set, the DPDK configuration file is stored in **/tmp/dpdk**. +- If **XDG_RUNTIME_DIR** is set, the DPDK configuration file is stored in in the path specified by **XDG_RUNTIME_DIR**. +- Note that **XDG_RUNTIME_DIR** is set by default on some servers. + +## Restrictions + +Restrictions of Gazelle are as follows: +#### Function Restrictions +- Blocking **accept()** or **connect()** is not supported. +- A maximum of 1500 TCP connections are supported. +- Currently, only TCP, ICMP, ARP, and IPv4 are supported. +- When a peer end pings Gazelle, the specified packet length must be less than or equal to 14,000 bytes. +- Transparent huge pages are not supported. +- ltran does not support the hybrid bonding of multiple types of NICs. +- The active/standby mode (bond1 mode) of ltran supports active/standby switchover only when a fault occurs at the link layer (for example, the network cable is disconnected), but does not support active/standby switchover when a fault occurs at the physical layer (for example, the NIC is powered off or removed). +- VM NICs do not support multiple queues. +#### Operation Constraints +- By default, the command lines and configuration files provided by Gazelle requires **root** permissions. Privilege escalation and changing of file owner are required for non-root users. +- To bind the NIC from user-mode driver back to the kernel driver, you must exit Gazelle first. +- Memory huge pages cannot be remounted to subdirectories created in the mount point. +- The minimum huge page memory required by ltran is 1 GB. +- The minimum hugepage memory of each application instance protocol stack thread is 800 MB. +- Gazelle supports only 64-bit OSs. +- The `-march=native` option is used when building the x86 version of Gazelle to optimize Gazelle based on the CPU instruction set of the build environment (Intel® Xeon® Gold 5118 CPU @ 2.30GHz). Therefore, the CPU of the running environment must support the SSE4.2, AVX, AVX2, and AVX-512 instruction set extensions. +- The maximum number of IP fragments is 10 (the maximum ping packet length is 14,790 bytes). TCP does not use IP fragments. +- You are advised to set the **rp_filter** parameter of the NIC to 1 using the `sysctl` command. Otherwise, the Gazelle protocol stack may not be used as expected. Instead, the kernel protocol stack is used. +- If ltran is not used, the KNI cannot be configured to be used only for local communication. In addition, you need to configure the NetworkManager not to manage the KNI network adapter before starting Gazelle. +- The IP address and MAC address of the virtual KNI must be the same as those in the **lstack.conf** file. + +## Risk Warning +Gazelle may have the following security risks. You need to evaluate the risks based on the application scenario. + +Shared memory +- Current situation: + The memory huge pages are mounted to the **/mnt/hugepages-2M** directory. During the initialization of a process that links to **liblstack.so**, files are created in the **/mnt/hugepages-2M** directory. Each file corresponds to a 2 MB memory huge page, and the mmap function is performed on the files. After receiving the registration information of lstask, ltran also perform the mmap function on the file in the directory based on the huge page memory configuration information to implement shared huge page memory. + The procedure also applies to the files in the **/mnt/hugepages** directory. +- Current Mitigation Measures + The huge page file permission is **600**. Only the owner can access the files. The default owner is the **root** user. Other users can be configured. + Huge page files are locked by DPDK and cannot be directly written or mapped. +- Risks: + Malicious processes belonging to the same user imitate the DPDK implementation logic to share huge page memory using huge page files and perform write operations to damage the huge page memory. As a result, the Gazelle program crashes. It is recommended that the processes of a user belong to the same trust domain. + +**Traffic Limit**: +Gazelle does not limit the traffic. Users can send packets at the maximum NIC line rate to the network, which may congest the network. + +**Process spoofing**: +If two lstack processes A and B are legitimately registered with ltran, A can impersonate B to send spoofing messages to ltran and modify the ltran forwarding control information. As a result, the communication of B becomes abnormal, and information leakage occurs when packets for B are sent to A. Ensure that all lstack processes are trusted. diff --git a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md index e35d2bd77..dac3ec162 100644 --- a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md +++ b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md @@ -20,9 +20,9 @@ iSulad is a lightweight container runtime daemon designed for IoT and cloud infr | Component | Version | | ---------- | --------------------------------- | -| OS | openEuler 21.09 | +| OS | openEuler 22.03 | | Kubernetes | 1.20.2-4 | -| iSulad | 2.0.9-20210625.165022.git5a088d9c | +| iSulad | 2.0.11 | | KubeEdge | v1.8.0 | ### Node Planning Example @@ -66,7 +66,7 @@ Deploy Kubernetes by referring to the [Kubernetes Cluster Deployment Guide](http > Note: Preferentially, use `kubeadm` to deploy Kubernetes if the cloud node has access to the Internet. The procedure is as follows: ```bash -$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.15 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock ... Your Kubernetes control-plane has initialized successfully! ... diff --git a/docs/en/docs/NestOS/feature-description.md b/docs/en/docs/NestOS/feature-description.md new file mode 100644 index 000000000..10bc35f33 --- /dev/null +++ b/docs/en/docs/NestOS/feature-description.md @@ -0,0 +1,98 @@ +# Feature Description + +## Container Technology + +NestOS provides computing resources for applications using a containerized computing environment. Applications share a system kernel and resources, but are invisible to each other. This means that applications are no longer directly installed in the OS. Instead, they run in containers through Docker. This greatly reduces the coupling among the OS, applications, and running environment. Compared with the traditional application deployment mode, the NestOS cluster provides more flexible and convenient application deployment, less interference between application running environments , and the easier maintenance of OSs. + +## rpm-ostree + +### System Upgrade + +rpm-ostree is a hybrid image/package system that combines RPM and OSTree. It provides RPM-based software package installation and management, and OSTree-based OS update and upgrade. rpm-ostree sees the two operations as updates to the OS. Each update to the system is similar to a transaction submitted by rpm-ostree. This ensures that the update completely succeeds or fails completely and allows the system to be rolled back to the status before the update. + +When updating the OS, rpm-ostree keeps two bootable deployments: one before the update and one after the update. The update takes effect only after the OS is restarted. If an error occurs during software installation or upgrade, the rpm-ostree rollback allows NestOS to revert to the previous deployment. The **/ostree/** and **/boot/** directories of NestOS are the OSTree repository environment and show which OSTree deployment is booted into. + +### File System + +In the rpm-ostree file system layout, only the **/etc** and **/var** directories are writable. Any data in the **/var** directory is not touched and is shared across upgrades. During the system upgrade, rpm-ostree takes the new default **/etc** and adds the changes on the top. This means that the upgrades will receive new default files in **/etc**, which is a critical feature. + +OSTree is designed to parallel-install multiple versions of multiple independent operating systems. OSTree relies on a new top-level **ostree** directory; it can in fact parallel install inside an existing OS or distribution occupying the physical **/root**. On each client machine, there is an OSTree repository stored in **/ostree/repo**, and a set of deployments stored in **/ostree/deploy/$STATEROOT/$CHECKSUM**. Each deployment is primarily composed of a set of hard links into the repository. This means each version is deduplicated; an upgrade process only costs disk space proportional to the new files, plus some constant overhead. + +The model OSTree emphasizes is that the OS read-only content is kept in **/usr**; it comes with code to create a Linux read-only bind mount to prevent inadvertent corruption. There is exactly one **/var** writable directory shared between each deployment for a given OS. The OSTree core code does not touch content in this directory; it is up to the code in each operating system for how to manage and upgrade state. + +### OS Extensions + +NestOS keeps the base image as simple and small as possible for security and maintainability reasons. However, in some cases it is necessary to add software to the base OS itself. For example, drivers or VPN software are potential candidates because they are harder to containerize. These software packages extend the functionality of the base OS rather than providing runtimes for user applications. For this reason, rpm-ostree treats these packages as extensions. That said, there are no restrictions on which packages you can actually install. By default, packages are downloaded from the openEuler repositories. + +To layer a software package, you need to write a systemd unit that executes the `rpm-ostree` command to install the wanted package. The changes are added to a new deployment, which takes effect after restart. + +## nestos-installer + +nestos-installer helps with NestOS installation. It provides the following functions: + +(1) Installing the OS to a target disk, optionally customizing it with an Ignition configuration or first-boot kernel parameters (`nestos-installer install`) + +(2) Downloading and verify an OS image for various cloud, virtualization, or bare metal platforms (`nestos-installer download`) + +(3) Listing NestOS images available for download (`nestos-installer list-stream`) + +(4) Embed an Ignition configuration in a live ISO image to customize the running system that boots from it (`nestos-installer iso ignition`) + +(5) Wrap an Ignition configuration in an initrd image that can be appended to the live PXE initramfs to customize the running system that boots from it (`nestos-installer pxe ignition`) + +## zincati + +Zincati is an auto-update agent for NestOS hosts. It works as a client for Cincinnati and rpm-ostree, taking care of automatically updating/rebooting machines. Zincati has the following features: + +(1) Agent for continuous automatic updates, with support for phased rollouts + +(2) Runtime customization via TOML dropins, allowing users to overwrite the default configuration. + +(3) Multiple update strategies + +(4) Local maintenance windows on a weekly schedule for planned upgrades + +(5) Tracks and exposes Zincati internal metrics to Prometheus to ease monitoring tasks across a large fleet of nodes + +(6) Logging with configurable priority levels + +(7) Support for complex update-graphs via Cincinnati protocol + +(8) Support for cluster-wide reboot orchestration, via an external lock-manager + +## System Initialization (Ignition) + +Ignition is a distribution-agnostic provisioning utility that not only installs, but also reads configuration files (in JSON format) to provision NestOS. Configurable components include storage and file systems, systemd units, and users. + +Ignition runs only once during the first boot of the system (while in the initramfs). Because Ignition runs so early in the boot process, it can re-partition disks, format file systems, create users, and write files before the userspace begins to boot. As a result, systemd services are already written to disk when systemd starts, speeding the time to boot. + +(1) Ignition runs only on the first boot +Ignition is designed to be used as a provisioning tool, not as a configuration management tool. Ignition encourages immutable infrastructure, in which machine modification requires that users discard the old node and re-provision the machine. + +(2) Ignition produces the machine specified or no machine at all +Ignition does what it needs to make the system match the state described in the Ignition configuration. If for any reason Ignition cannot deliver the exact machine that the configuration asked for, Ignition prevents the machine from booting successfully. For example, if the user wanted to fetch the document hosted at **https://example.com/foo.conf** and write it to disk, Ignition would prevent the machine from booting if it were unable to resolve the given URL. + +(3) Ignition configurations are declarative +Ignition configurations describe the state of a system. Ignition configurations do not list a series of steps that Ignition should take. +Ignition configurations do not allow users to provide arbitrary logic (including scripts for Ignition to run). Users describe which file systems must exist, which files must be created, which users must exist, and more. Any further customization must use systemd services, created by Ignition. + +(4) Ignition configurations should not be written by hand +Ignition configurations were designed to be human readable, but difficult to write, to discourage users from attempting to write configs by hand. Use Butane, or a similar tool, to generate Ignition configurations. + +## Afterburn + +Afterburn is a one-shot agent for cloud-like platforms which interacts with provider-specific metadata endpoints. It is typically used in conjunction with Ignition. + +Afterburn comprises several modules which may run at different times during the lifecycle of an instance. Depending on the specific platform, the following services may run in the initramfs on first boot: + + - setting local hostname + + - injecting network command-line arguments + +The following features are conditionally available on some platforms as systemd service units: + + - installing public SSH keys for local system users + + - retrieving attributes from instance metadata + + - checking in to the provider in order to report a successful boot or instance provisioning diff --git a/docs/en/docs/NestOS/installation-and-deployment.md b/docs/en/docs/NestOS/installation-and-deployment.md new file mode 100644 index 000000000..0bce37b22 --- /dev/null +++ b/docs/en/docs/NestOS/installation-and-deployment.md @@ -0,0 +1,128 @@ +# Installation and Deployment + +## Deploying NestOS on VMware + +This guide describes how to configure latest NestOS in VMware. + +Currently, NestOS supports only the x86_64 architecture. + +### Before You Start + +​ Before deploying NestOS, make the following preparations: + +- Downloading the NestOS ISO +- Preparing the **config.bu** File +- Configuring the Butane Tool (on Linux or Windows 10) +- A host machine with VMware installed + +### Initial Installation and Startup + +#### Starting NestOS + +When NestOS is started for the first time, Ignition is not installed. You can use the nestos-installer component to install Ignition as prompted. + +### Producing an Ignition File + +#### Obtaining Butane + +You can use Butane to convert a .bu file into an Ignition file. Ignition configurations were designed to be human readable, but difficult to write, to +discourage users from attempting to write configs by hand. +Butane supports multiple environments. You can use Butane in a Linux or Windows host machines or in container environments. + +``` +docker pull quay.io/coreos/butane:release +``` + +#### Generating a Login Password + +Run the following command on the host machine and enter the password: + +``` +# openssl passwd -1 -salt yoursalt +Password: +$1$yoursalt$1QskegeyhtMG2tdh0ldQN0 +``` + +#### Generating an SSH Key Pair + +Run the following command on the host machine to obtain the public key and private key for SSH login: + +``` +# ssh-keygen -N '' -f ./id_rsa +Generating public/private rsa key pair. +Your identification has been saved in ./id_rsa +Your public key has been saved in ./id_rsa.pub +The key fingerprint is: +SHA256:4fFpDDyGHOYEd2fPaprKvvqst3T1xBQuk3mbdon+0Xs root@host-12-0-0-141 +``` + +``` +The key's randomart image is: ++---[RSA 3072]----+ +| ..= . o . | +| * = o * . | +| + B = * | +| o B O + . | +| S O B o | +| * = . . | +| . +o . . | +| +.o . .E | +| o*Oo ... | ++----[SHA256]-----+ +``` + +You can view the **id_rsa.pub** public key in the current directory. + +``` +# cat id_rsa.pub +ssh-rsa +AAAAB3NzaC1yc2... +``` + +#### Compiling a .bu File + +Perform a simple initial configuration. For more details, see the description of Ignition. +A simple **config.bu** file is as follows: + +``` +variant: fcos +version: 1.1.0 +passwd: + users: + - name: nest + password_hash: "$1$yoursalt$1QskegeyhtMG2tdh0ldQN0" + ssh_authorized_keys: + - "ssh-rsa + AAAAB3NzaC1yc2EAAA..." +``` + +#### Generating an Ignition File + +Use the Butane tool to convert the **config.bu** file to a **config.ign** file in the container environment. + +``` +# docker run --interactive --rm quay.io/coreos/butane:release \ +--pretty --strict < your_config.bu > transpiled_config.ign +``` + +### Installing NestOS + +Use SCP to copy the **config.ign** file generated by the host machine to NestOS that is initially started, which is not installed to the disk and runs in the memory. + +``` +sudo -i +scp root@your_ipAddress:/root/config.ign /root +``` + +Run the following command and complete the installation as prompted: + +``` +nestos-installer install /dev/sda --ignition-file config.ign +``` + +After the installation is complete, restart NestOS. + +``` +systemctl reboot +``` +Complete. diff --git a/docs/en/docs/NestOS/overview.md b/docs/en/docs/NestOS/overview.md new file mode 100644 index 000000000..e6072c28f --- /dev/null +++ b/docs/en/docs/NestOS/overview.md @@ -0,0 +1,3 @@ +# NestOS User Guide + +This document describes the installation, deployment, features, and usage of the NestOS cloud-based operating system. NestOS integrates mainstream container platforms, such as iSulad, Docker, and PodMan. It eliminates unreliable issues during upgrades caused by modification to the system, dependency of user services on system components, and unstable intermediate states of software packages. NestOS is provided as a lightweight and customizable OS for easy cluster deployment. To download NestOS images, visit the [NestOS Repository](https://gitee.com/openeuler/NestOS). diff --git a/docs/en/docs/NestOS/usage.md b/docs/en/docs/NestOS/usage.md new file mode 100644 index 000000000..76f64e3ca --- /dev/null +++ b/docs/en/docs/NestOS/usage.md @@ -0,0 +1,489 @@ +# Setting Up Kubernetes and iSulad + +**Perform the following steps on both the master and node.** This tutorial uses the master as an example. + +## Before You Start + +Prepare **NestOS-22.03-date.x86_64.iso** and two hosts as the master and node. + +## Downloading the Components + +Open the repo source file to add the Alibaba Cloud source of Kubernetes. + +``` +vi /etc/yum.repos.d/openEuler.repo +``` + +Add the following content: + +``` +[kubernetes] +name=Kubernetes +baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +enabled=1 +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +``` + +Downloads the Kubernetes components and the components for synchronizing the system time. + +``` +rpm-ostree install kubelet kubeadm kubectl ntp ntpdate wget +``` + +Restart the system to use the components. + +``` +systemctl reboot +``` + +Select the latest version branch and enter the system. + +## Configuring the Environment + +### Change the Host Name of the Master + +``` +hostnamectl set-hostname k8s-master +sudo -i +``` + +Open the **/etc/hosts** file. + +``` +vi /etc/hosts +``` + +Add the IP addresses of the hosts. + +``` +192.168.237.133 k8s-master +192.168.237.135 k8s-node01 +``` + +### Synchronizing the System Time + +``` +ntpdate time.windows.com +systemctl enable ntpd +``` + +``` +Disable the swap partition, firewall, and SELinux. +``` + +By default, the NestOS does not have the swap partition and the firewall is disabled. +Run the following command to disable SELinux: + +``` +vi /etc/sysconfig/selinux +Change the value of SELINUX to disabled. +``` + +### Enabling Forwarding Mechanisms + +Create a configuration file. + +``` +vi /etc/sysctl.d/k8s.conf +``` + +Add the following content: + +``` +net.bridge.bridge-nf-call-iptables=1 +net.bridge.bridge-nf-call-ip6tables=1 +net.ipv4.ip_forward=1 +``` + +Make the configuration take effect. + +``` +modprobe br_netfilter +sysctl -p /etc/sysctl.d/k8s.conf +``` + +## Configuring iSula + +Check the OS image required by Kubernetes. Pay attention to the version number of the pause container. + +``` +kubeadm config images list +``` + +Modify the **daemon.json** configuration file. + +``` +vi /etc/isulad/daemon.json +``` + +``` +## Description of the added items ## +Set registry-mirrors to "docker.io". +Set insecure-registries to "rnd-dockerhub.huawei.com". +Set pod-sandbox-image to "registry.aliyuncs.com/google_containers/pause:3.5". (The Alibaba Cloud source is used. The pause version is obtained in the previous step.) +Set network-plugin to "cni". +Set cni-bin-dir to "/opt/cni/bin". +Set cni-conf-dir to "/etc/cni/net.d". +``` + +The modified file is as follows: + +``` +{"group": "isula", +"default-runtime": "lcr", +"graph": "/var/lib/isulad", +"state": "/var/run/isulad", +"engine": "lcr", +"log-level": "ERROR", +"pidfile": "/var/run/isulad.pid", +"log-opts": { +"log-file-mode": "0600", +"log-path": "/var/lib/isulad", +"max-file": "1", +"max-size": "30KB" +}, +"log-driver": "stdout", +"container-log": { +"driver": "json-file" +}, +"hook-spec": "/etc/default/isulad/hooks/default.json", +"start-timeout": "2m", +"storage-driver": "overlay2", +"storage-opts": [ +"overlay2.override_kernel_check=true" +], +"registry-mirrors": [ +"docker.io" +], +"insecure-registries": [ +"rnd-dockerhub.huawei.com" +], +"pod-sandbox-image": "registry.aliyuncs.com/google_containers/pause:3.5", +"native.umask": "secure", +"network-plugin": "cni", +"cni-bin-dir": "/opt/cni/bin", +"cni-conf-dir": "/etc/cni/net.d", +"image-layer-check": false, +"use-decrypted-key": true, +"insecure-skip-verify-enforce": false +} +``` + +Start the services. + +``` +systemctl restart isulad +systemctl enable isulad +systemctl enable kubelet +``` + +**Perform the preceding steps on both the master and node.** + +## Initializing the Master + +**Perform this step only on the master.** +Run the following command and wait for the host to pull the image. You can also manually pull the image before performing this step. + +``` +kubeadm init --kubernetes-version=1.22.2 --apiserver-advertise- +address=192.168.237.133 --cri-socket=/var/run/isulad.sock --image-repository +registry.aliyuncs.com/google_containers --service-cidr=10.10.0.0/16 --pod- +network-cidr=10.122.0.0/16 +``` + +``` +## Description of initialization parameters ## +kubernetes-version indicates the version to be installed. +apiserver-advertise-address indicates the IP address of the master. +cri-socket specifies the iSulad engine. +image-repository specifies that the image source is Alibaba Cloud. You do not need to modify the tag. +service-cidr specifies the IP address range allocated to the service. +pod-network-cidr specifies the IP address range allocated to the Pod network. +``` + +After the initialization is successful, copy the `kubeadm join` command that is output by `kubeadm init` for subsequent node joining. + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +**Note**: `--cri-socket=/var/run/isulad.sock` specifies that iSulad is used as the container engine. +View the downloaded image. + +``` +isula images +``` + +Configure the cluster based on the output of the initialization command. + +``` +mkdir -p $HOME/.kube +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +chown $(id -u):$(id -g) $HOME/.kube/config +export KUBECONFIG=/etc/kubernetes/admin.conf +source /etc/profile +``` + +Check the health status. + +``` +kubectl get cs +``` + +The status of **controller-manager** and **scheduler** may be **unhealthy**. To rectify the fault, perform the following steps: +Edit the configuration file. + +``` +vi /etc/kubernetes/manifests/kube-controller-manager.yaml +``` + +``` +Comment out the following content: +--port=0 +Modify hostpath: +Change all /usr/libexec/kubernetes/kubelet-plugins/volume/exec to /opt/libexec/... +``` + +``` +vi /etc/kubernetes/manifests/kube-scheduler.yaml +``` + +``` +Comment out the following content: +--port=0 +``` + +After the modification is complete, check the health status again. + +## Configuring the Network Plugin + +Configure the network plugin only on the master. However, you need to pull images on all hosts in advance. The commands for pulling images are as follows: + +``` +isula pull calico/node:v3.19.3 +isula pull calico/cni:v3.19.3 +isula pull calico/kube-controllers:v3.19.3 +isula pull calico/pod2daemon-flexvol:v3.19.3 +``` + +**Perform the following steps only on the master.** +Obtain the configuration file. + +``` +wget https://docs.projectcalico.org/v3.19/manifests/calico.yaml +``` + +Edit **calico.yaml** and change all **/usr/libexec/...** to **/opt/libexec/...**. +Run the following command to install Calico: + +``` +kubectl apply -f calico.yaml +``` + +Run the `kubectl get pod -n kube-system` command to check whether Calico is successfully installed. +Run the `kubectl get pod -n kube-system` command to check whether all Pods are in the** running** status. + +## Joining the Node to the Cluster + +Run the following command on the node to join the node to the cluster: + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +Run the `kubectl get node` command to check whether the master and node statuses are **ready**. + +If yes, Kubernetes is successfully deployed. + +# Using rpm-ostree + +## Installing Software Packages Using rpm-ostree + +Install wget. + +``` +rpm-ostree install wget +``` + +Restart the system. During the startup, use the up and down arrow keys on the keyboard to enter system before or after the RPM package installation. **ostree:0** indicates the version after the installation. + +``` +systemctl reboot +``` + +Check whether wget is successfully installed. + +``` +rpm -qa | grep wget +``` + +## Manually Upgrading NestOS Using rpm-ostree + +Run the following command in NestOS to view the current rpm-ostree status and version: + +``` +rpm-ostree status +``` + +Run the check command to check whether a new version is available. + +``` +rpm-ostree upgrade --check +``` + +Preview the differences between the versions. + +``` +rpm-ostree upgrade --preview +``` + +In the latest version, the nano package is imported. +Run the following command to download the latest ostree and RPM data without performing the deployment. + +``` +rpm-ostree upgrade --download-only +``` + +Restart NestOS. After the restart, the old and new versions of the system are available. Enter the latest version. + +``` +rpm-ostree upgrade --reboot +``` + +## Comparing NestOS Versions + +Check the status. Ensure that two versions of ostree exist: **LTS.20210927.dev.0** and **LTS.20210928.dev.0**. + +``` +rpm-ostree status +``` + +Compare the ostree versions based on commit IDs. + +``` +rpm-ostree db diff 55eed9bfc5ec fe2408e34148 +``` + +## Rolling Back the System + +When a system upgrade is complete, the previous NestOS deployment is still stored on the disk. If the upgrade causes system problems, you can roll back to the previous deployment. + +### Temporary Rollback + +To temporarily roll back to the previous OS deployment, hold down **Shift** during system startup. When the boot load menu is displayed, select the corresponding branch from the menu. + +### Permanent Rollback + +To permanently roll back to the previous OS deployment, log in to the target node and run the `rpm-ostree rollback` command. This operation sets the previous OS deployment as the default deployment to boot into. +Run the following command to roll back to the system before the upgrade: + +``` +rpm-ostree rollback +``` + + +## Switching Versions + +NestOS is rolled back to an older version. You can run the following command to switch the rpm-ostree version used by NestOS to a newer version. + +``` +rpm-ostree deploy -r 22.03.20220325.dev.0 +``` + +After the restart, check whether NestOS uses the latest ostree version. + + +# Using Zincati for Automatic Update + +Zincati automatically updates NestOS. Zincati uses the Cincinnati backend to check whether a new version is available. If a new version is available, Zincati downloads it using rpm-ostree. + +Currently, the Zincati automatic update service is disabled by default. You can modify the configuration file to set the automatic startup upon system startup for Zincati. + +``` +vi /etc/zincati/config.d/95-disable-on-dev.toml +``` + +Set **updates.enabled** to true. +Create a configuration file to specify the address of the Cincinnati backend. + +``` +vi /etc/zincati/config.d/update-cincinnati.toml +``` + +Add the following content: + +``` +[cincinnati] +base_url="http://nestos.org.cn:8080" +``` + +Restart the Zincati service. + +``` +systemctl restart zincati.service +``` + +When a new version is available, Zincati automatically detects the new version. Check the rpm-ostree status. If the status is **busy**, the system is being upgraded. + +After a period of time, NestOS automatically restarts. Log in to NestOS again and check the rpm-ostree status. If the status changes to **idle** and the current version is **20220325**, rpm-ostree has been upgraded. + +View the zincati service logs to check the upgrade process and system restart logs. In addition, the information "auto-updates logic enabled" in the logs indicates that the update is automatic. + +# Customizing NestOS + +You can use the nestos-installer tool to customize the original NestOS ISO file and package the Ignition file to generate a customized NestOS ISO file. The customized NestOS ISO file can be used to automatically install NestOS after the system is started for easy installation. + +Before customizing NestOS, make the following preparations: + +- Downloading the NestOS ISO. +- Preparing a **config.ign** File. + +## Generating a Customized NestOS ISO File + +### Setting Parameter Variables + +``` +$ export COREOS_ISO_ORIGIN_FILE=nestos-22.03.20220324.x86_64.iso +$ export COREOS_ISO_CUSTOMIZED_FILE=my-nestos.iso +$ export IGN_FILE=config.ign +``` + +### Checking the ISO File + +Ensure that the original NestOS ISO file does not contain the Ignition configuration. + +``` +$ nestos-installer iso ignition show $COREOS_ISO_ORIGIN_FILE + +Error: No embedded Ignition config. +``` + +### Generating a Customized NestOS ISO File + +Package the Ignition file into the original NestOS ISO file to generate a customized NestOS ISO file. + +``` +$ nestos-installer iso ignition embed $COREOS_ISO_ORIGIN_FILE --ignition-file $IGN_FILE $COREOS_ISO_ORIGIN_FILE --output $COREOS_ISO_CUSTOMIZED_FILE +``` + +### Checking the ISO File + +Ensure that the customized NestOS ISO file contains the Ignition configuration. + +``` +$ nestos-installer iso ignition show $COREOS_ISO_CUSTOMIZED_FILE +``` + +The previous command displays the Ignition configuration. + +## Installing the Customized NestOS ISO File + +The customized NestOS ISO file can be used to directly boot the installation. NestOS is automatically installed based on the Ignition configuration. After the installation is complete, you can use **nest/password** to log in to NestOS on the VM console. diff --git a/docs/en/docs/Releasenotes/installing-the-os.md b/docs/en/docs/Releasenotes/installing-the-os.md index 80f737499..5b608c0d8 100644 --- a/docs/en/docs/Releasenotes/installing-the-os.md +++ b/docs/en/docs/Releasenotes/installing-the-os.md @@ -2,7 +2,7 @@ ## Release Files -The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. +The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), [embedded images](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. Table 1 ISO release packages @@ -34,7 +34,19 @@ Table 3 Container images | openEuler-docker.aarch64.tar.xz | Container image of openEuler in the AArch64 architecture. | | openEuler-docker.x86_64.tar.xz | Container image of openEuler in the x86_64 architecture. | -Table 4 Repo sources +Table 4 Embedded images + +| Name | Description | +| -------------------------------------- | ------------------------------- | +| arm64/aarch64-std/zImage | Kernel image that supports QEMU in the AArch64 architecture. | +| arm64/aarch64-std/\*toolchain-22.03.sh | Development and compilation toolchain in the AArch64 architecture. | +| arm64/aarch64-std/\*rootfs.cpio.gz | File system that supports QEMU in the AArch64 architecture. | +| arm32/arm-std/zImage | Kernel image that supports QEMU in the ARM architecture. | +| arm32/arm-std/\*toolchain-22.03.sh | Development and compilation toolchain in the ARM architecture. | +| arm32/arm-std/\*rootfs.cpio.gz | File system that supports QEMU in the ARM architecture. | +| source-list/manifest.xml | Manifest of source code used for building. | + +Table 5 Repo sources | Name | Description | | ------------------- | ------------------------------------------ | @@ -43,6 +55,7 @@ Table 4 Repo sources | debuginfo | Stores debugging package sources. | | docker_img | Stores container images. | | virtual_machine_img | Stores VM images. | +| embedded_img | Stores embedded images. | | everything | Stores full software package sources. | | extras | Stores extended software package sources. | | source | Stores source code software package. | @@ -53,7 +66,7 @@ Table 4 Repo sources The following table lists the minimum hardware specifications for openEuler 22.03 LTS. -Table 1 Minimum hardware requirements +Table 6 Minimum hardware requirements | Component | Minimum Hardware Specification | | ---------- | --------------------------------------------------- | @@ -65,7 +78,7 @@ Table 1 Minimum hardware requirements The following table describes the servers and configurations supported by openEuler. openEuler will support more servers in the future. Partners and developers are welcome to participate in the contribution and verification. For details about the servers supported by openEuler, see the [Compatibility List](https://www.openeuler.org/en/compatibility/). -Table 1 Supported servers and configurations +Table 7 Supported servers and configurations diff --git a/docs/en/docs/Releasenotes/key-features.md b/docs/en/docs/Releasenotes/key-features.md index 648020be1..f49f40a02 100644 --- a/docs/en/docs/Releasenotes/key-features.md +++ b/docs/en/docs/Releasenotes/key-features.md @@ -83,24 +83,26 @@ Unified edge-cloud synergy framework KubeEdge+ is provided, implementing basic c ## Embedded Image -Basic capabilities, such as lightweight, security hardening, and lightweight containers, are provided, and the ARM32 and ARM64 chip architectures are supported. - -- **Lightweight capability**: The OS image size can be less than 5 MB, the background noise can be less than 15 MB, and the startup time can be less than 5s. -- **Security hardening**: Security hardening is performed on resources such as account passwords and file permissions. OS security is enabled by default. -- **Lightweight containers**: Standard container images can be deployed and run in lightweight containers in embedded scenarios. -- **Multi-architecture support**: The ARM32 and ARM64 chip architectures are supported. -- **Hybrid deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. -- **Small-scale tailoring**: Small-scale tailoring based on the Yocto build package is supported. ARM Cross Compilation -- **ARM cross compilation tool**: The ARM cross compilation tool chain is provided based on GCC 10.3 of the community. +- ** Lightweight models**: The Yocto small-scale build tailoring framework allows you to customize system items into compressed, lightweight models. For example, OS images can be reduced to less than 5 MB, memory overhead to under 15 MB, and startup to under 5s. +- **Support for multiple types of hardware**: Raspberry Pi 4B is supported as the universal hardware for embedded scenarios. +- **Soft real-time kernel**: The soft real-time capabilities based on the Linux 5.10 kernel allow for microsecond-level soft real-time interrupt response latency. +- **Hybrid critical deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. Zephyr real-time kernel is also supported. - **Distributed soft bus (DSoftBus)**: The DSoftBus of HarmonyOS is integrated to implement interconnection and interworking between embedded devices running on openEuler. +- **Embedded software package support**: More than 80 common embedded software packages can be built using openEuler. ## secPaver - secPaver is an SELinux policy development tool used to assist developers in developing security policies for applications. - - **Policy management**: provides a high-level configuration language and generates SELinux policy files based on the policy configuration file to reduce the threshold for using SELinux. +## NestOS +NestOS is a cloud-based OS provided by the CloudNative SIG of the openEuler community. It is dedicated to providing optimal container hosts for securely running containerized workloads on a large scale. +- **Out-of-the-box container platforms**: Mainstream basic container platforms such as iSulad, Docker, PodMan, and CRI-O are included. +- **Easy-to-use installation and configuration**: Ignition is used to provide personalized configuration. +- **Secure and reliable package management**: rpm-ostree is used for package management. +- **User-friendly and controllable automatic update agent**: Zincati provides insensible upgrade. +- **Dual-partition system**: The dual-partition design ensures system security. + ## Third-party Application Support - **KubeSphere**: It is an application-centric and open-source container platform built based on Kubernetes. It is initiated by Beijing Qingyun Technology Co., Ltd. and supported and maintained by SIG-KubeSphere of the openEuler community. @@ -114,4 +116,4 @@ More desktop environments are provided to ensure better development experience. - **DDE** is upgraded and supports drawing board, music, and cinema applications. - **UKUI** is upgraded and supports the Chinese input method and multimedia. - **kiran-desktop** is supported. -- **GNOME** is supported. \ No newline at end of file +- **GNOME** is supported. diff --git a/docs/en/docs/TailorCustom/figures/flowchart.png b/docs/en/docs/TailorCustom/figures/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a71e8bfdb886222151cea3b2a3c0e8d8eae64a GIT binary patch literal 19918 zcmeFZgWTZlpJ#}8t0IT>lr`j~0?~lvrC)1$rNLo=U-7L|m@b_N>y3Csc+N`-wuC*{ zDhx51Je@m#PfoHI^YFRW(32QBkrVHVhalli6)YwYzR=)d_Y9#B)FxKjlJulN6S-W6 zlE5{8qJ))Ez8m`RK75zc^{GN__P&L8OW7X5e>V{@5K{Fl&Z=>Eqm8+8|4-Ogorx#!tZZFOeQ+L-@9?SFlEly71% z{~&N75qN9JCM*ZDJM6!Q1l}DUEd}~0FAa}UmEF%LOtl=`Z#jvdCBgS~Alw;+MA1yX zBqo{|JxM}61XGbNT2$tdwptEKdW=_Pr`FWB!Av)yfj3Dvf&Qo4_cf~J+r2!hye$*! zN)lJdm#0y^mjZ!x*N4}EewWL=Cd*43brNT;keeyaXr^McwSKa-sGasp*6!qNAMUbK z5)I9ATeD*O?+^CZRS%mJa)K9f!FHLKJv?@-i*TmOHD3wu&ubF*t5F5hr^ipZkx0?-3?zuMiC-b*$2l!;f$j(Js`DL5Prgx!W}@#Qu8Gn>oHl&Ds~*@Xks|IX9FVHS*n>!p z>REZ|WwGMTFP^6q^-Z4yj3*`de5AYV${0_pCl>DT9BUys*vBRkQ+4Ot_bsLHeL4EM zFHG5}Zf1WE&nS(|1lSWMrXJwzq4F_B0ies%l{ID6a(MaScgrSUx{u0ZpWzn9ExYB| z+e=~3*HBX$;Pf3JS!1CmMY)8XlR=g9eTmpwDNN-~;Pnwmg+!=BA~x1L3n%0@LW+6* zAiVad%LlqxdqK42g~iqTBRa9lgQFI)!fGj3&?EZ+~N@|A)bpK%!9$-Ov|@dNb;VShe$T_N90WmXiHa8AT`e za{ZMUPe zdg76t>gmc4rt634dp6E zQ+^qz1SNXrzNPk;r^GC>!3y7_qrB{#vQN*-?!sm3R;^BTw<-4&jQvRQ>pwv}r^Ew- z+-4({J9Q54sF~@pj&1xN^pDb>w%46)nX?uOSr^l&P|THG)up@X4NSKT++nE({!EKH z-m*XKMN{9hW|Sw)FE_dCFMp z6n1!~Qz74A&IxPyq`Y)WD2I;@j7Zt_C$`UZp7&oFHRp%3AzD#>)+o6-Jb9y z{JRMeUbZRnb=B3beD{S??M{@NIH(@iGty&}sHqjPBG|s46#a*NzTmly& zNp4sP!6sb#C@_rzntas#}7ps`&=)TR~(*wG98Lk&6^7mK8AZ&qIW zXAbTw>dCYoyEycc7kna_gW%Dty`M(=ihpfB_J~oX*+{gkyfspJEcg|#+TL1})0+LM z_K_bZb@!ac>%9d7o2B!SJQd2DaWb*WPxvHl@te&rTy}`C7ZwY>o!-LNBXOZojQ9n% zsUzb;>ygh!)+X0>9+yT}0e(0Cn#Ko1CwQ0EgvO~SARPL!ViI;KCcDny4|;LfUI0#N z<^R3k@-`NFKK4}GIG_;#2=C)%yW-*xS##c;N_?h1omaL-&akzP(2Nk)J zp8Sw>ZfZ?nDfca!3eQ2Ak~aG(6wlf-@N+82*j9F48s4ExN4F!WHQdjXZDr5{VR|-8 zpsZOhLaXxzooxCCbGj;%lR)-uLD@Xb^Cl9tP_2x4gR}|VpFeir`;|JHgmJPuu*|dE zOp7t@O>j&X?XKndH~L4T^IxmGw7k1Aubt0;wmv^2F&2tAVLTzI=~WNl%xU3zKC0ty zKS|=TrliJAm3XwzX1V(MWYI*JH|SgQ6OfLx{X9rEzQ$po#R<~|PsxzInyZTVVPkPH z9sLOYog3^vy5xIw_RG>qKt3ZTbax0k*?&%YJ+vlIR?G1m=iA&@15JW zDZ}a1W@R~48%|WDz2SdzP?ZdgiJyVa@llr}s8bGa>TE-->4P3@lL&j6#v|qa>kEm^ zVkpD|S7V2}sg+u!7VV?m!AfV7RqCxgg9-}1M(CMD_07xEjUAWePQ{churR-Evh8Zg zwAYKK3%S_BJcW%K<1&SfFjB=QT(akkA1u{^Jw29nOSKd+4=l5sm0}{mW3Ck+qi``Q z)JC_y#)wbfkV>DKve(>;6pwoh`OWn&$3jm zM07*%duQJN8YeykV3Gg;4h*iZJpZPL#Khl|jO%50==-QaK;Ty+_Kyd@SUyi5h}g~Z zPZn+_MEe5vk3YawP8+`uGKih|LY<(fu?ZI2w1rMkp#%}*EVmsJ`aPg^Q)iFkEOsh0 z=W#3c-E{1qbmu+>8QvU0qxh&&QEK?hqW8M=D35+>innj$6xT=j;r0JX_C zi8Q~cz7gzf2q*AzalWqQOcA~x<-kd8Or{+=H`gp;xQQ07KmtWyCK4a9qw))o+KxS2 zDc_;O=eMt^Fh4{4Y1LQY8uo^gQTNhm{`JCSV$fuzFt8{dieP<~wat*~@y(awP0o)~ zv(W}d1+>ojDq!nqnjF2GuPCW?V#32v;pJ967p^&L#Y*;loplMbh1+h0k>dP&Jbm86 ztSuypl|HRGtp0VAZlbkX;of08gy-vG{6$5WOo%mP9eZ3Kxp_A}9 zrT;lsjg+p4d&|Oj7NuYq&8PNpY71yqBJ^RP{M6to8EjYn=JFam`vH+Ge%}6uMkciw zFX8m*->folM6l(A_UL)qS{U|MWG&dRN5nuS!bqsk?0o#V6NNWLiW5rA7aO3*{xX{M zj91cASHn}ic4hZRa^+sB6HTJk)fRuuB9_|RI@^Xt0<{|CX95@)EU|M^a#I{3NV`bv zTMB`{ta!ObNtNCy=yBJ-Cp~D%7O$lm700=wka@1h*_YX6(9<0~FqA&|p!;=8d@pNq;T^4Rep@&k_LPpni zzQJ)n(T#LOr9)c~Iq*XH+1}G$Lw8?Uu9oO049?hcc%{5etqa}@{!}`#yoFpNlU?;M zD~YX3qtRX&3*A0KeUZ04(ZwP(9lKo%#(f|nqtpSd&(5-`LWGXY_{#YnD9rqL4dYg$ zDkcXG3Kf<(&L~uij*p(SiEjGJ1+U7N)&Fe1 zurqXPxHfp@&S3hbco~a|um&{<)9-M5XQLde8p6e=2jmWxz9+Bk*w{HwDkr3(dB z%J&iihob>^eGjwy0lM3}VZ`7|SmkKxIY(Jpng1D1t=|RGZ`hGE%xPYZP1pNsyG7#u z58;7%+x-5$ZV_XdW;3Y??67$P%fBQOe+^t`RxGesP&!ucHV1A+$@{EB+Mlhulk_)N zZzxLfC;ELvqV!Q~PhKC~vZGgdlk!a>>6|uM#P+GEQNv&cCaq_8<4?H{ab z++blX$eK{!%Rp{SZKhU>TBf*9{awyXj5BAC&`931z| z@~9N0SEN1`Yd!b!ntH#kOwnNmt74LajO0Y@O5|`{d@nkC?@i(ueRd8T;iN1_)Q{hp zsl-dNl5QU*6&|_l>Awx61%ZB1I=$IKGDY*Cg8s%QzG@6mX;Dz{;(IQ4PD&J{wmFt6 zT0YXMt3LmGq`SUa)ns7(t^SN_Lj!q!Ea9f+)L7=N{G*yXm%b)EG%un%Fd~NO+{;5m zB-d%gh;`IEqJBD#?Ehurj@Z;PKT!^<3lkTG-Zzsxch9ySYi&GDZM{5z!eaCPOzZ9t zMPEJB@-r#2M8hW>HSrhv=-ooQrF_hbRAZmRXSHy1rEfVMrBFez(u9gP>C_;~Y8s!@Rcep*xI$tdAQt(oA9a>JOY^1<{Wz>+#^Zj-uC!A>0j9JH~?5*q~6O6=}-*6lx}ZD>T0{jv7HK|;0K}!GuxvR!XU9-938`k_Uotq#HmkH(!PqG$>u( z()O0{T)6e5-EIkJ-u?vQz&mEzXOm7ZZngZ$5u23`wm+u!*jbfnI$HH;Slr!5&nCC3 zIFTe%cb51$i5t_nvkk24Am337nhg-s`T^0`rN`V<7x2qFj;#Q}!`Bdq}x(f#?OgTV870VoWQ4(*eeYpvjkdYvkM5asl@CQdVSqlNk&gXoLQeMDrTIe;~NzCS!zU*HGB)szbeXYNjwhws@ z{|NXr_`(^V9Pa~Pxl@cdb)K$EUF#&*ho*< zk`R1=>33vu`}$Aa!xS<65AnAj0k8b*E6ALg-WjUZnfc-IsT|y4$IBsQMp1RD|E_=9 zgyrG-NqdvLW*_W${NmC)WW8bBn@=yRb&NF~2O?yZ-jI0`=LZUDAm#*J#f8h3|2!sF z_0M^9v_BK&Mw^HYXQq6)0`O=EvB2u)eo}(OAD^bf;Zi{lGosW`6PY%xz(7D}nI(mV z*M;)xd;l~`KWmg{MxvwkS0`KCXEhf&@cpm^eCp+<3U@1nk?Py1H>Fr7krs`}h>c&A*Np6hc71cMhzDJ(Rf4&(A zI{VV+e>Mp9*&p<}NT6{xtk(5ja#VT8we*|mTMe+#b^fXP@Vd`>qSm51OwZc(PeLpj zy^Kwna|#xW5DeHoI^);qj^FGs_wL|bTIPD|CI5)5lWBo)rs*Z~NXApMf*4wS#3>`A zBt!Xw%m>Wz3)TfjxnYS4lGMuYRww5}usa6~Fv&c07a1>YzADFfXp(J}{_yQ3IjY zj%TZXKyGV2*!8Vmy9nITe~ zc?{8m9CXcq$yXy=QHrj}F0N|fIfP;Hzv*pbs_Zhn%qCUnB&BP)%feH_j$|eUqnT`} zEcxyt;4uwB{S29Xp?v=S*7uur{DF2$0354^`P<|pWNq&ahFl;Kh9EUy+cfCs>h?g& z-)9h?CltB)s8MO>-CqpIPe4l)!`2->MOfazO`rwd0igCSnJd1Y7P8p9T>tc5CiooRaD$1>U9m6|UTtcx=aZ8&{vU&dJuMu4|@yJ1^}L zwR@7ze8JNf!V2PBa@cu;o^8i>b%vLYzjmx?J-}Yd4dN*Q#0m2{-J=mNd#&hIPJ6Ro zKB#a)#9Bq%(=PpG;PlU%t`FWCb{WiLuWlZyJtE^({{pZQtQ&#Mo4_3Zv0gxHRs_V( z^gwiJKwM1#G}B`>d*NoOi!~_)3Y0Hwql$IT?*u;D_o|+Nz|b~8u7o?sfDgUePDlC_`*d^@GJ}Fy8>w92P*tG?-WwsYK9ZiGP9OT z(e6)rl~Pz+A$BD{u{-JfF2AMjL*`6P^UTI~jqA}Xd_mpLttJ@>j%O|+FX(fsx`?EvEu#FMSjq+7Yu5vgLx?V? z2vK%>^HRUAJn_|7tJPoSbef;@!W_tZ zSC1dM%ciw9isNZnUxJ^TOm_U11=St8P?5Oz$8u1TwN2W)|wAyP0 zQ$8K~lXJyD!}z?@wR{g5^%x*+HZdo)iq?9*;slT9MG>im6$ym0Lo3c2w*=x_Mt&#$ zGG+T&R_MT_ZD^TMcwW=9=E8kXk+pC${B!5RhhAdK==?^nV~5Y<=6(M7)}x_$t_yFo zfql76GnY+UcK=``!l6^ePm92 zycbu8|H$6iLXyrC%35}zTuj$J-Jz`22QaLKXw)OemdihYR1lgK!g$x0Dg73vbI-8I zs@L?MEyEXE+PzR9v}E#Hn2p~|M(Sa$wQ*+W#l4R-$H5$Gz=%K$OgyFNRLJz+sFBC# zF@8ZLu?p+i#JOkX)cNf`!w##Muwfu6^-@_Ap_(e0cqBf#6*t`;vuG}P?ZxW6AbE30 z`i@`oN{*l}Yj}FfN)jNdO=bC$jE!v1BRFFGT&A7Gvx0!n-!rC>$ISLPnO!%wvB}1)!gC(i$h3U z-;-<5yX9b29j-u!pD_Qd{J5>2tj^6cKqP(4#w7up0ZMiX0=*M|N$38ww>u&;#|WO^ zUWJywg({~3wbpbh6BwnGW&}V3C(Mg)H19cAw?1b~tRhNSKt4%Wq%2dF#?C3DX=?Vw z_oJh;i)L$Afr-m86Ah) zGLH`ICk=l?|1zVs+AyKJyRFl;oRQ70i%k63BCSiKNfH%b9AUUu;SHwvTwonF=>B?T zt@R;}3kstI0qK?LS+ZcBQIoltu}A4m)p4zHt1;D-A?!e1wR`TfZQP2p$Q9!)uX!ZGYCf7(0nikeHhU9XlYp zDj+ZYbQ{mQzmC$nU61N*{aef3>e4uqjV<{w92+-ApMv2uuAn;Fse>qH3X8QgvV;~2 ztHhM6#1^UO40_^8Fh!=3AWGFteEHMJZ4-9ajsZYZL#=hj`;$NZmQ)kUFxG6D-2-H2 zmItqZ;O?-sf5A~&ES7p|o&rkrkS+M)-WeU+WJ)l7X*IBFgh30Kx#u{3^Ce zrH_ODc2ESK%oSVTaea`L7c+nIO&{GPkPy%~zcp1;JBcRsT$DR>EB1<*d--sXxu^(_ zjW3mo-=2=G$rAYNlcW==PKul77XYGGB(y)`Z}nW=yqFrKt$owt3zrbT#)0n> z7?S^@YI7|^!suX;S{XHJV#b+TqAY3&D3A%vUElzbAKBM9XoJ6P<)ZkXdd5=uEiPRc zLvF_2P~xjjy8Z8C+@A39?tCE6uGo6?Ck+D?c$WV5atk~Yu<5&Fi|7nU2gX(W-#PL7$!&xS((pVb09b#P6F6TIOn1c-0EJ@Xt^SdJ#<` z`bEU6K-)m+<|(3W08DCLta`Iv6?i`kHqeI*UA5xWBayyr~}zbh;_O z)dN<+4j|YBDWi0i>qQ;VMCH2FeNS(w3X}PEx53n58 zzbztS4X6*3{nUG)wTP7Rq*a6s4Nu!4s@2+m@(>eYOYYV*X^6?ZI~i>`+LlVY%W1DM zLG)PY&nUW9AKb0ueR;TCA#Sa#bt;&Un5_YNRWO_XX|)J7{(|ULQ7lLFE2MO@<_|Dl zvCedlieHAQF4wi558AbgUbFez1)fES-$L;dxoBB0ce%8W1aNdJPCdam64wy9hm~Fl zlji-&1|5$V8HH5QOm@*+K#LBTz&vuNyMEkUNv*j!qA2p9#H9Xk?f?^L$GARCxeq+u z?(9v?@Xmg4ItaYKZ0PY!O|wAs6-ivJ9+itX6A4K8e`d?PxM<$0p3<;u_bT37fyn(j zuaSc9%gULG&UIcEM;~cL9$9|jmZ>o_Oz2I{*5}R-FPwK-B~v?jfvEISl(il+O8;|B zVkNKR6T{8OZ*_#`j>&nLf0z36B9=aa7J0O0xO!ft2y zS2?$j_W!>0|F}IhbAX7v0!~`_WK`|iNTT%WK?3ctwWdr2xHoC<58nsjeQRgEoRgkp zj-~01Cp10;OvDxU{wrg)N+&~RVa3q*TP1Ds;&+wP8%yov=qced=Gk&WdE1|P`{b>6hB%*YVBkZH z!+foODeMkt+}koom@LQH<y? z?0Fnf2-EFNMVNQtYrtgHAa|p`M{xokEeF1|2j-0Uk3Lkuz$YE;+JqPXnmJZG^{DjZ zlmB=O=@KO+T=?;>*Iy@^is(EmvaZnfv^JwW80ozJ`v@#pUi^%GdS_p$WDVx6yM!38 z(AT;Ce{-gFCH1GY<;2Ekt-ATN!&YVrzDwetoqWyTD}njGs-xGqJs@`c8^XoDomiM1 zq8=v`$b@I3t0~c?Me)*%jlScC%L=kc-cHb8YPgVPgnp=(65Q_i822Rv82Bl|p9{eZ zaq>-v9T;9KA;e#m7zgdYy=MO&>ZF|-gmFlX-I<;tr%-IZH7>UP; z@UTNRQ*P2bG=xbd>J@~BL-o$e3Kh6B;}owaO(q^q>QsRdFcjf-2!7J&C>U6ne9Pt; zq*3(Nv@nqQd4DY0Y9C!p_)OI73ahOT7pPgqT>#OS;k=9 zEEE2HX=}5PfE`rUWXjAHzV5A;;e=nfEL^#zC0Pk1Sqa%Buq0>7HXB@fZE86ft`_pD zw|LA2TcIc%o-IRPy4M%9_cG_M0K?c3{kvkjg?g9HX>(`Di}!Qi(;i_DvvyuthvDM9 z$KT;4a@O@83A4Y&eEEsmt^dWsp{X_jck^6RbFLlIQOR)dK>kO0ylg=%9EMy;yjKoP zX;KXFpS%Np$Xd9R{2u)vow=SU(Sm9AElqUemA@n7<0n)~#9vh1xO1yJ!+SsKseNW1 z=}7w0NBsIJJ#&|2;7>}SERm6?^T=To7hfk9;TO^EVHEp>m4X62atZ97zaM+%oxhBF1L>U2t7f`nTB(AO z3K;GXKCyX%F=y8L=z+m+?lJoht0c$IQ|Y!hdPkR)eM>r-siA^fa(q0vks7q3vxFY> zsjWC|!8U4L)sC5ry?QPNZ30E-Hn^O1n@b(cJurm_u#gF1-PAcw;ROX?2{nUI56>XL zHOe>)YL|xvmbyd^novMqcV{ydmV=4oSXJH&XhU(8H{KTRo;PSK>iE5{L0Th_r2P$0 zJ#TDZgw5hKIOaxyepT7-9xgk3Zbzuy%jETfV`QLnI>Fk%D&;dop`(%Z-3k?h7Y#u^ zZ~QJKt2}XDJ16DDvZk~)Fh)!caDmb;goic`WQh6xvL2;6!4fq;r2W)A#4FmE%O0Gp zLscdw_UDscS=cUqjU=O$+e$vBS^m79 z*o^crvy^3tiDNCU_MAgBM(z&|m3+=$Qv=WR)mMH!gLIq;#4O;JX1fh zx%3n78nswHs6EO6jN6QdjI%i>F~S?~NyAt6A%70H84mnl0bJzoZigtK1!u@ao~Hv3 zU{5gT89#x9#vjX>!S$S|PHj>3*FT+z%v_!c=Es?SM&5C@7wG735Z)grgPvS1qr{7B z9m|Bh>Wbn8c?x1?ZodjZx)*}KIMTndbnyemt@0jj7!wzWbn&D(3L^H7TG?*N5=A!7 z+i-s7Mg^J;`6cp}1p5Gcly2|K`}|k$A=VWRTEzP7BRc&Rnl6r|BY@SZh3(pTqJ={@ zxb9cEv|Eo8$|rBHEnY@6GzfuSF%wAA;4-&n#Y-}O?X?&Wxq3wvm)I$`K?^RkXhD5 zykrB${YU~k?4#GKhUI7dv}x;f4u}-wlNP6{i85c)h%lJmZ<+_2-aX4v($0))Nnwqw zH8pY2#^EFHVLRmvHa3H_(VZWmg;vB04u9mOL=?Zbz9=xt5MY1zVIk(y40VDE2iV1T zw=W*ClYS|fWrF$ngYV*-Q*GESpO3-`-N}<2H3A$D|;-aZa4t268YZHq) zdCoI^gZ+NTpO~4ihb;qTs+mCYh@zu03wk~uKWZd>FV}ryd+b?|h=1#bdk5c_sd{oK zVEqjn@Df{GAhq-T(g7P7JLBllEXV9-s^f2eheA_y3`BK`)s?M%YqCPdT+EarofY#%?Xa9xhAH&$&vQLz?9&rxco6n3yysOKFw?6x%~`BVZ&ma`O2$IL zTa%2co#&m_6%YY-Q5o1YX&=N9YF231xuVrF$S0_yKi>QX-T2s=TkD}_1A{A+*b2{= zU~yb>3lVgvqw2N^Vq;u803u7z_2Q1g^tZQgjD#nM$U-?>khQokRkO zmvX78Mujh%2A1?V46Go^<}vQzlL7s|5Ja;}=t^4IOt{tX(0n|pyW_isk-_|q5Is0$ zL~9y$9*spy6@jvrlb29}=|2vyTfAP(uo=3pbRS~5csG>9cL0ef-t{*~N0AE5uW?%k zzt=D^hpjeMCf4zFB1afc5IzIP0b-#44Q>mp<1wQ_zS*4@8Wj%!?1B$f#MLw`ekFU* zr|~vi2yaR;xT2CiRF@^z7)toQh7GI=p$z_O676X3O7`F%%;65+UiD2jcW2FF6IF-a z^yppFuS-_6o2-Y>a@|O%Ya|GM?)WTyni6{9@t(Nj1nJ5vADEGjIjk64(9Sz`pldm% zFN$?wON#SuGiF$_#7;bzY#y66#+qHH$iS}ip8)x$WJW;@EMV&%*Pv2%0n_7~CO2Aw zEY2!2#wDkwqJTb2(mp~)>LeoVTE{ebsN+!jQMlGb7H7=#OPG;~$|;ps_zU2WLkJY7 z2C3+2bol>)MWHXFf?SF9T68qYuQ6{PSQ|v@u5h%e1X)uqz@c4860yq-gCS!SR@GwRz7~#d_xsN6G``dg@TS2 z?9N&l-n(J*BwG-}L^zvag0zdy=JILp7RvZZw?*Tx(Felbr@a;wD>SO~EDwe;TW|f1 z7{Z*@Pa0EZRuSK^p&tQSIH{)e&RTqPdVKEqofhqPDOZR4%513#SJv>suEh!6@||W4qM{5c;fQCrW$U*S{m{HB4}3M^SyQe zvu~HDu9Z&v7z~*Fg=^dI z^V6TUJrc`0dF-L z%r&l+^eXekg_Rc2L%qIjH5R~3_l`lh)28S)?8Q#Me27I(quY~W)|5;gAl?M~-Q?%b zIXK#QABbhS_oq(>WhrvErmpr#(;}=_$WQt_=lFW#B4obSzDMa>$=J4z>UXQjkXnY=IVJke8eOzr41(XBE4JLmfgXQkOL5A~xL59$AJ5Qm1fr~3W zyoq4`Oz;`S(}1DjO}@ZXpHVRYKiE_lvz?V}&g^Ix_PYWIAyU3d%m0*UM#V|%yHhRo z^wvH}Oxb~v)1G^nb{81%wxC;vtt!u8*@PpNJKwT$F=Zo z#+Yl?oMoFwooBMmeXBLDQO|@N*2~8@u8BXDdOtYX%Q+Y3!dy*U5nrp~)$>-MX((t- z!M*p4sk6yL(9Tf9guir9dmID;zZuFpJz2Cab;;%izQQTc{gKIV3p8s zQL{fr9kt6F4gL2N_$of0B0KA9l+TOg+=`Hf8W`jlSn7Ei4i^6%0}c09kOFlTX~Rqd zaKi67ZxKM^3}BB_Z62ljLv-W&E`@p7F;Q+sH8q|#c4nPDZk87s3q$~Fs|{;ldtMG| zFg{Cb^_%0)V?0kTW2_B$&AF6&t>56MyYiPFq}*vL7Ey}lixC41r191LrT8G=$ZS)Fe$+QDXB<6gkCite!chF~?%)94ijJNDRYwKs zP5mj;E!XFvXdMF{HU0Z&f3zw0KxLG~G!4E6^yZw_4r+*7jy|a^9COerhw4(#PyA_Io%&Ts zIg&E3sltfr^eCB7W}}%VDfOhsigubWNh$_Tlu&7pnpnU9C?>qqc6k|7kop`BrC03{C(kJsTc5`wY+_(2NXF=|z_!n1LBj-IgGo8~d)3v&(_j>oYS ze#1)0ig|{U$M9U}3w_i-nTdBoHX6uG-L$*v4RGEGWl8QXNn0cWbHTXZt14nHzQJC}4R0t*UjihpNh5@oqBb+zY1n3|;9UR*{X*^>&^Yf^OHLn(Hd@+SN)T0tZ_vP@h^0l6f zNXH++g$CcRAPXWll1z#)LvoFdaY-Vn-A4vn;N0;Z0GfU?^ei_)j2ZH;F)J-G7X40? z{jLU0dXidiEt{@3Q~$|B3Jr1^7bkr?`{y_v8zTb^93V|SA<4!h9?_TRI^Aq2RyW@Z zQ2IJo={L3bSkEV{L^^~qEs1|I$k!*4cLC@s*aA{h$(Eer4I^DHBGHr$J#aALVk_Bf4gzJ^xw!_csH-vUVXwQHJ(Z+Ol zAiG7q(eb`8ZXM*ltaK?9D9xMnI~r;D?^Jmv68=66I%p~8hJn#`$@~Zu%=ylg7OgI& zd&aLtG&zG((yzzX2nhlF85aAQY=xf`UGe&fQ?FXTJgkG{#{<4FyU2;lm-^p0FYW#M z<3Ex}TumU*Kb$v%{9l|G_HUe*`q)Y=EYMNgn6R}hK(CrU+H8SRPIOtun1e^~4|1gq zrt*Lu> zTu5`>la{Sd*+5eG_-_I zX(U+8p!B0gi3SrxyL`3JRXTHE<*uHi9_ku}B4r;8n!&oqX|+aqnQNx&s{Fi0pp=}RrH#=lqo(eA#6_SEuPR*O#H zZr%QJKNbUX6OFrF}CFJd^B61^j14v=@ zerQeKL{tiE#dr9AJe(HT;mD5vanMrQgxsceAW{c;B z{F5_HTYkgMWd6#=_@4p#5z2}DOY7CX>mG$TAs{m=o9HV5KSba?;^zYVTb3@Kt6k5N z3YS|Axt`UU+D=qQpVAM83A(=qq(Hmmc^8S;5-aK-x?PJx)xsBNX_;211v770J~s_e zc$X6|>P}5<4i0q1pSSp;z;9q(>cLkl z@@}LV2tB$R9=7tT?z|B&egr_X`x^}w3#VXK>Q5{3)RgMP$amfvxdxE^k2KZw$s3Xx zi5H0t;1F*4eg2yB*7;Zn>+vLsPB7Q{zj0N*nCkd2yXq?ZS&!ALqQ$e_8EznA06PA1 zdoWt^k00&8oilPknVim-J$+BI$GJBs) z(IK_Xx=)L~5?5d&Ea%QXWhUnUoTY7O;r9phRHcnAv;7;eu%xs-f ziC}a4IRV;}qPOTpnkBcpCD2JRYZ5w>bD<(HW4^7X!viHu#umX$%>&Xp*U69;oHNT@aIMt;ns>C`o{cNN|CtTHeNu$`z}Wto*ix>7#5yVt*x0q z+PJk*MB(}{2+JFxA(HRZ5o8jl5p!~L^dUN`7ZsBvuwGG=i;u$8cCf;YTE|tfy+`HQ zsYnqk;JS;r@ot05suYz2I&!<1_|vTMB^}R^Gk>K<*Jj9<$3RsJ`JW0(s(@4NnXU{_ zU8(lG5d%c)FyD~R(=jgY@!dZ$_7&j3_Ird?DB7qVs&-gIcv1%N6tuo@JBR@AdQPDl zyyx~L@7d@5wArmxtuTN%vF*w72QJB`D%dE24wapR3IK zAZ7HV=jHy^w<#E$`txA=6uZ5y5g*#NF?NvRNgs`&BaPGURF8ii1_tNA0{YCP3f5DN zXT`9(3?R$t)}uY4LeF>jOM$QAiI?KJ&~-(bN;=~R`+IUc@>2!ybI&)Hie*3RZzaQ7_OSbv1SEWE8 zTF<7jNU0iPn_w%~&;61edXYUtLY~MBJqc`!S%uwf`~-7ipdtR(2gA7mmTS7)%EA77vexRnw} z2gIxC0K5NFuRlqtxtm(}9+jA4gYV9I^Wo-HF`MqUoa&=yQ}(qq}H0aWB(QKJ$(_;s9z%4q^pj@0`YQf z;8WqWt~4|dJM{FDTOf7jHioyCRaX?PPtTt}CQJSbMM+oSvps*Stx+E>uG99E$#>6to-2v8&VDkC6 zQl^d3&;Q~t`dJHK=ex~}tc=9$z}Lf2vWZZK2ltZd{F?Zu3DXT_n!5(Q*~WER{&v~M z<`l-p2Zw<`;?5@H2GCvHhmnw6bqyb8D&~=~y22$x^*a43cwikHrl*fuT=?KduAh0R zfn8!vOHIj+yTMc)JCvEK{&bPK=#5T2Bn@}Qc0-YTP)#(&V5@Rl)2p2VKE`Q9{8Jpm$iM&oWJ!Dnb z`{Z6I{NCdtoAS}6h}{?-Fw2Y{peT-lx%1SPJoHk3x^&u+?f)f))A-eoh(uVOHJ0ue z08jupeF)HXu>-m|(aSrX5WB*#4vB*iwRU+&476B+>HOJ^q;i=+d!A?fzX2Z zStjEX)st0Gq&Bqw6gN87pqaPu5@{#`%ChWk{}J$cox=ZTiN03^fxXG6Vr$m~t1a8| z{jKwlvcuUo!kwM8p13yit!}#;t$WK8*sFYd2)Iu>H))Ng?OR5#uyv~!=4}N|L3pU} z-Cxu3>)qq%E3emu9G^(@qB`00%-OSy3{DFLm>L@ryLpm|+SbRbFEaSMw2x)) z;zz5`etl{ED(1>U*W(voSOEQKbok*f7d~ZOU4_@uuiwevbx~UvzrPRI%eATaz`!qO za{xF~4HQ{-Ut@EJNsU2Re+#gxUE%qm^zcv9%l=amU#tvSVQ|HM$|RHSgk^#ss|0r^ zNUU3zt3OSPZ>c$7wz*#|C%8V-&6zyW{X)go{+kmzMSo{q?JJz0c04*~N83LSk5(s- zrAbehd#9N6XV2Fzw>z^fbh-ADEzfO}e^_T!N58WG&RqXnc1zR4?0l@}e~VsVuDI0? zT*4l#VV}eNQSnUC%<7^QkUnwV^qW0mt#j`1B8}5B%_ei4c45d#pLv%K0~`IoDH{>P z=i&`sZ(n@NEZXDnv}_GO53o8*g;i(lkP+PH_t=*_?>@P4UB2ix)(LS8eA(X~&JFxG zm*;Tojcac#Y-Z^F@x99JaCOdZo}^Qi`g{7*-prE+CbVb3shs0|MjZ(Z2jVX*nD-JTqUH!lW#pGv#WUhd+&|;Q@63!Os-4)JJE5+ zomrqJc6s_!Q=e6qeXGvT-NX;66R+=-;{s-(+8rN&3s6dX@lIT?g^m3N2_JG~n6*l* z3_AAvq{SFo<#p!*tGwtvR(l!Fv^AcX$@6DdpiS6YiSL=Ed#-*x-UF`zTUYX%{Yu-J zYr4vkZ};hT3X&A<0dCHuP;N~aq{y>@wO}6uMJvE#IAb& znCZG?^`7eW_n$&%sQZC4)OH(CyWKh07ky8NvXA{NW=<9EX$m6(x{1C~ncU##nXo81EQ_!R`A*$Zz4S6lbK;%B%Y zAji1=(xB7F{*;6+ehlg`@c`EY2nt?3ZIQG4-b2vh92e6^ z1+}jt|Ni}J4xB`uER~fn_;uR9fB%eHUwFEIcwA7y$jEnF4VZDv9&a!N4o9rKC$Y|d z$#Gy&=5j>~*z^Dy0bC|c-qJhp?rfJU(Z7EG&ae4&QhoOAyZnp7UcG<6|KdA40l~oh cAO9KG)g6ft`+waDct9J2r>mdKI;Vst0NYe>82|tP literal 0 HcmV?d00001 diff --git a/docs/en/docs/TailorCustom/imageTailor-user-guide.md b/docs/en/docs/TailorCustom/imageTailor-user-guide.md new file mode 100644 index 000000000..2ad4ae701 --- /dev/null +++ b/docs/en/docs/TailorCustom/imageTailor-user-guide.md @@ -0,0 +1,928 @@ +# ImageTailor User Guide + + - [Introduction](#introduction) + - [Installation](#installation) + - [Software and Hardware Requirements](#software-and-hardware-requirements) + - [Obtaining the Installation Package](#obtaining-the-installation-package) + - [Installing imageTailor](#installing-imagetailor) + - [Directory Description](#directory-description) + - [Image Customization](#image-customization) + - [Overall Process](#overall-process) + - [Customizing Service Packages](#customizing-service-packages) + - [Setting a Local Repo Source](#setting-a-local-repo-source) + - [Adding Files](#adding-files) + - [Adding RPM Packages](#adding-rpm-packages) + - [Adding Hook Scripts](#adding-hook-scripts) + - [Configuring System Parameters](#configuring-system-parameters) + - [Configuring Host Parameters](#configuring-host-parameters) + - [Configuring Initial Passwords](#configuring-initial-passwords) + - [Configuring Partitions](#configuring-partitions) + - [Configuring the Network](#configuring-the-network) + - [Configuring Kernel Parameters](#configuring-kernel-parameters) + - [Creating an Image](#creating-an-image) + - [Command Description](#command-description) + - [Image Creation Guide](#image-creation-guide) + - [Tailoring Time Zones](#tailoring-time-zones) + - [Customization Example](#customization-example) + + + +## Introduction + +In addition to the kernel, an operating system contains various peripheral packages. These peripheral packages provide functions of a general-purpose operating system but also cause the following problems: + +- A large number of resources (such as memory, disks, and CPUs) are occupied, resulting in low system performance. +- Unnecessary functions increase the development and maintenance costs. + +To address these problems, openEuler provides the imageTailor tool for tailoring and customization images. You can tailor unnecessary peripheral packages in the OS image or add service packages or files as required. This tool includes the following functions: + +- System package tailoring: Tailors system commands, libraries, and drivers based on the list of RPM packages to be installed. +- System configuration modification: Configures the host name, startup services, time zone, network, partitions, drivers to be loaded, and kernel version. +- Software package addition: Adds custom RPM packages or files to the system. + + + +## Installation + +This section uses openEuler 22.03 LTS in the AArch64 architecture as an example to describe the installation method. + +### Software and Hardware Requirements + +The software and hardware requirements of imageTailor are as follows: + +- The architecture is x86_64 or AArch64. + +- The OS is openEuler 22.03 LTS (the kernel version is 5.10 and the Python version is 3.9, which meet the tool requirements). + +- The root directory **/** of the host to run the tool have at least 40 GB space. + +- The Python version is 3.9 or later. + +- The kernel version is 5.10 or later. + +- The SElinux service is disabled. + + ```shell + $ sudo setenforce 0 + $ getenforce + Permissive + ``` + + + +### Obtaining the Installation Package + +Download the openEuler release package to install and use imageTailor. + +1. Obtain the ISO image file and the corresponding verification file. + + The image must be an everything image. Assume that the image is to be stored in the **root** directory. Run the following commands: + + ```shell + $ cd /root/temp + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +3. Obtain the verification value in the sha256sum verification file. + + ```shell + $ cat openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +4. Calculate the verification value of the ISO image file. + + ```shell + $ sha256sum openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +5. Compare the verification value in the sha256sum file with that of the ISO image. If they are the same, the file integrity is verified. Otherwise, the file integrity is damaged. You need to obtain the file again. + +### Installing imageTailor + +The following uses openEuler 22.03 LTS in AArch64 architecture as an example to describe how to install imageTailor. + +1. Ensure that openEuler 22.03 LTS (or a running environment that meets the requirements of imageTailor) has been installed on the host. + + ```shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. Create a **/etc/yum.repos.d/local.repo** file to configure the Yum source. The following is an example of the configuration file. **baseurl** indicates the directory for mounting the ISO image. + + ```shell + [local] + name=local + baseurl=file:///root/imageTailor_mount + gpgcheck=0 + enabled=1 + ``` + +3. Run the following commands as the **root** user to mount the image to the **/root/imageTailor_mount** directory as the Yum source (ensure that the value of **baseurl** is the same as that configured in the repo file and the disk space of the directory is greater than 20 GB): + + ```shell + $ mkdir /root/imageTailor_mount + $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-aarch64-dvd.iso /root/imageTailor_mount/ + ``` + +4. Make the Yum source take effect. + + ```shell + $ yum clean all + $ yum makecache + ``` + +5. Install the imageTailor tool as the **root** user. + + ```shell + $ sudo yum install -y imageTailor + ``` + +6. Run the following command as the **root** user to verify that the tool has been installed successfully: + + ```shell + $ cd /opt/imageTailor/ + $ sudo ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] + Options: + -p,--product Specify the product to make, check custom/cfg_yourProduct. + -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx + --minios Make minios: yes|no|force + --sec Perform security hardening + -h,--help Display help information + + Example: + command: + ./mkdliso -p openEuler -c custom/cfg_openEuler --sec + + help: + ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + ``` + +### Directory Description + +After imageTailor is installed, the directory structure of the tool package is as follows: + +```shell +[imageTailor] + |-[custom] + |-[cfg_openEuler] + |-[usr_file] // Stores files to be added. + |-[usr_install] //Stores hook scripts to be added. + |-[all] + |-[conf] + |-[hook] + |-[cmd.conf] // Configures the default commands and libraries used by an ISO image. + |-[rpm.conf] // Configures the list of RPM packages and drivers installed by default for an ISO image. + |-[security_s.conf] // Configures security hardening policies. + |-[sys.conf] // Configures ISO image system parameters. + |-[kiwi] // Basic configurations of imageTailor. + |-[repos] //RPM sources for obtaining the RPM packages required for creating an ISO image. + |-[security-tool] // Security hardening tool. + |-mkdliso // Executable script for creating an ISO image. +``` + +## Image Customization + +This section describes how to use the imageTailor tool to package the service RPM packages, custom files, drivers, commands, and libraries to the target ISO image. + +### Overall Process + +The following figure shows the process of using imageTailor to customize an image. + +![](./figures/flowchart.png) + +The steps are described as follows: + +- Check software and hardware environment: Ensure that the host for creating the ISO image meets the software and hardware requirements. + +- Customize service packages: Add RPM packages (including service RPM packages, commands, drivers, and library files) and files (including custom files, commands, drivers, and library files). + + - Adding service RPM packages: Add RPM packages to the ISO image as required. For details, see [Installation](#installation). + - Adding custom files: If you want to perform custom operations such as hardware check, system configuration check, and driver installation when the target ISO system is installed or started, you can compile custom files and package them to the ISO image. + - Adding drivers, commands, and library files: If the RPM package source of openEuler does not contain the required drivers, commands, or library files, you can use imageTailor to package the corresponding drivers, commands, or library files into the ISO image. + +- Configure system parameters: + + - Configuring host parameters: To ensure that the ISO image is successfully installed and started, you need to configure host parameters. + - Configuring partitions: You can configure service partitions based on the service plan and adjust system partitions. + - Configuring the network: You can set system network parameters as required, such as the NIC name, IP address, and subnet mask. + - Configuring the initial password: To ensure that the ISO image is successfully installed and started, you need to configure the initial passwords of the **root** user and GRUB. + - Configuring kernel parameters: You can configure the command line parameters of the kernel as required. + +- Configure security hardening policies. + + ImageTailor provides default security hardening policies. You can modify **security_s.conf** (in the ISO image customization phase) to perform secondary security hardening on the system based on service requirements. For details, see the [Security Hardening Guide](https://docs.openeuler.org/en/docs/22.03_LTS/docs/SecHarden/secHarden.html). + +- Create an ISO image: + + Use the imageTailor tool to create an ISO image. + +### Customizing Service Packages + +You can pack service RPM packages, custom files, drivers, commands, and library files into the target ISO image as required. + +#### Setting a Local Repo Source + +To customize an ISO image, you must set a repo source in the **/opt/imageTailor/repos/euler_base/** directory. This section describes how to set a local repo source. + +1. Download the ISO file released by openEuler. (The RPM package of the everything image released by the openEuler must be used.) + ```shell + $ cd /opt + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +2. Create a mount directory **/opt/openEuler_repo** and mount the ISO file to the directory. + ```shell + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + ``` + +3. Copy the RPM packages in the ISO file to the **/opt/imageTailor/repos/euler_base/** directory. + ```shell + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +#### Adding Files + +You can add files to an ISO image as required. The file types include custom files, drivers, commands, or library file. Store the files to the **/opt/imageTailor/custom/cfg_openEuler/usr_file** directory. + +##### Precautions + +- The commands to be packed must be executable. Otherwise, imageTailor will fail to pack the commands into the ISO. + +- The file stored in the **/opt/imageTailor/custom/cfg_openEuler/usr_file** directory will be generated in the root directory of the ISO. Therefore, the directory structure of the file must be a complete path starting from the root directory so that imageTailor can place the file in the correct directory. + + For example, if you want **file1** to be in the **/opt** directory of the ISO, create an **opt** directory in the **usr_file** directory and copy **file1** to the **opt** directory. For example: + + ```shell + $ pwd + /opt/imageTailor/custom/cfg_openEuler/usr_file + + $ tree + . + ├── etc + │   ├── default + │   │   └── grub + │   └── profile.d + │   └── csh.precmd + └── opt + └── file1 + + 4 directories, 3 files + ``` + +- The paths in **/opt/imageTailor/custom/cfg_openEuler/usr_file** must be real paths. For example, the paths do not contain soft links. You can run the `realpath` or `readlink -f` command to query the real path. + +- If you need to invoke a custom script in the system startup or installation phase, that is, a hook script, store the file in the **hook** directory. + +#### Adding RPM Packages + +##### Procedure + +To add RPM packages (drivers, commands, or library files) to an ISO image, perform the following steps: + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- The **rpm.conf** and **cmd.conf** files are stored in the **/opt/imageTailor/custom/cfg_openEuler/** directory. +>- The RPM package tailoring granularity below indicates **sys_cut='no'**. For details about the cutout granularity, see [Configuring Host Parameters](#configuring-host-parameters). +>- If no local repo source is configured, configure a local repo source by referring to [Setting a Local Repo Source](#setting-a-local-repo-source). +> + +1. Check whether the **/opt/imageTailor/repos/euler_base/** directory contains the RPM package to be added. + + - If yes, go to step 2. + - If no, go to step 3. +2. Configure the RPM package information in the **\** section in the **rpm.conf** file. + - For the RPM package tailoring granularity, no further action is required. + - For other tailoring granularities, go to step 4. +3. Obtain the RPM package and store it in the **/opt/imageTailor/custom/cfg_openEuler/usr_rpm** directory. If the RPM package depends on other RPM packages, store the dependency packages to this directory because the added RPM package and its dependent RPM packages must be packed into the ISO image at the same time. + - For the RPM package tailoring granularity, go to step 4. + - For other tailoring granularities, no further action is required. +4. Configure the drivers, commands, and library files to be retained in the RPM package in the **rpm.conf** and **cmd.conf** files. If there are common files to be tailored, configure them in the **\\** section in the **cmd.conf** file. + + +##### Configuration File Description + +| Operation | Configuration File| Section | +| :----------- | :----------- | :----------------------------------------------------------- | +| Adding drivers | rpm.conf | \
\
\

Note: The **driver_name** is the relative path of **/lib/modules/{kernel_version_number}/kernel/**.| +| Adding commands | cmd.conf | \
\
\
| +| Adding library files | cmd.conf | \
\
\
| +| Deleting other files| cmd.conf | \
\
\

Note: The file name must be an absolute path.| + +**Example** + +- Adding drivers + + ```shell + + + + + ...... + + ``` + +- Adding commands + + ```shell + + + + + ...... + + ``` + +- Adding library files + + ```shell + + + + + + ``` + +- Deleting other files + + ```shell + + + + + + ``` + +#### Adding Hook Scripts + +A hook script is invoked by the OS during startup and installation to execute the actions defined in the script. The directory for storing hook scripts of imageTailor is **custom/cfg_openEuler/usr_install/hook directory**, which has different subdirectories. Each subdirectory represents an OS startup or installation phase. Store the scripts based on the phases in which the scripts are invoked. + +##### Script Naming Rule + +The script name must start with **S+number** (the number must be at least two digits). The number indicates the execution sequence of the hook script. Example: **S01xxx.sh** + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>The scripts in the **hook** directory are executed using the `source` command. Therefore, exercise caution when using the `exit` command in the scripts because the entire installation script exits after the `exit` command is executed. + + + +##### Description of hook Subdirectories + +| Subdirectory | Script Example | Time for Execution | Description | +| :-------------------- | :---------------------| :------------------------------- | :----------------------------------------------------------- | +| insmod_drv_hook | N/A | After OS drivers are loaded | N/A | +| custom_install_hook | S01custom_install.sh | After the drivers are loaded, that is, after **insmod_drv_hook** is executed| You can customize the OS installation process by using a custom script.| +| env_check_hook | S01check_hw.sh | Before the OS installation initialization | The script is used to check hardware specifications and types before initialization.| +| set_install_ip_hook | S01set_install_ip.sh | When network configuration is being performed during OS installation initialization. | You can customize the network configuration by using a custom script.| +| before_partition_hook | S01checkpart.sh | Before partitioning | You can check correctness of the partition configuration file by using a custom script.| +| before_setup_os_hook | N/A | Before the repo file is decompressed | You can customize partition mounting.
If the decompression path of the installation package is not the root partition specified in the partition configuration, customize partition mounting and assign the decompression path to the input global variable.| +| before_mkinitrd_hook | S01install_drv.sh | Before the `mkinitrd` command is run | The hook script executed before running the `mkinitrd` command when **initrd** is saved to the disk. You can add and update driver files in **initrd**.| +| after_setup_os_hook | N/A | After OS installation | After the installation is complete, you can perform custom operations on the system files, such as modifying **grub.cfg**.| +| install_succ_hook | N/A | When the OS is successfully installed | The scripts in this subdirectory are used to parse the installation information and send information of whether the installation succeeds.**install_succ_hook** cannot be set to **install_break**.| +| install_fail_hook | N/A | When the OS installation fails | The scripts in this subdirectory are used to parse the installation information and send information of whether the installation succeeds.**install_fail_hook** cannot be set to **install_break**.| + +### Configuring System Parameters + +Before creating an ISO image, you need to configure system parameters, including host parameters, initial passwords, partitions, network, compilation parameters, and system command line parameters. + +#### Configuring Host Parameters + + The **\ \** section in the **/opt/imageTailor/custom/cfg_openEuler/sys.conf** file is used to configure common system parameters, such as the host name and kernel boot parameters. + +The default configuration provided by openEuler is as follows. You can modify the configuration as required. + +```shell + + sys_service_enable='ipcc' + sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' + sys_utc='yes' + sys_timezone='' + sys_cut='no' + sys_usrrpm_cut='no' + sys_hostname='Euler' + sys_usermodules_autoload='' + sys_gconv='GBK' + +``` + +The parameters are described as follows: + +- sys_service_enable + + This parameter is optional. Services enabled by the OS by default. Separate multiple services with spaces. If you do not need to add a system service, use the default value **ipcc**. Pay attention to the following during the configuration: + + - Default system services cannot be deleted. + - You can configure service-related services, but the repo source must contain the service RPM package. + - By default, only the services configured in this parameter are enabled. If a service depends on other services, you need to configure the depended services in this parameter. + +- sys_service_disable + + This parameter is optional. Services that are not allowed to automatically start upon system startup. Separate multiple services with spaces. If no system service needs to be disabled, leave this parameter blank. + +- sys_utc + + (Mandatory) Indicates whether to use coordinated universal time (UTC) time. The value can be **yes** or **no**. The default value is **yes**. + +- sys_timezone + + This parameter is optional. Sets the time zone. The value can be a time zone supported by openEuler, which can be queried in the **/usr/share/zoneinfo/zone.tab** file. + +- sys_cut + + (Mandatory) Indicates whether to tailor the RPM packages. The value can be **yes**, **no**, or **debug**.**yes** indicates that the RPM packages are tailored. **no** indicates that the RPM packages are not tailored (only the RPM packages in the **rpm.conf** file is installed). **debug** indicates that the RPM packages are tailored but the `rpm` command is retained for customization after installation. The default value is **no**. + + >![](./public_sys-resources/icon-note.gif) NOTE: + > + > - imageTailor installs the RPM package added by the user, deletes the files configured in the **\** section of the **cmd.conf** file, and then deletes the commands, libraries, and drivers that are not configured in **cmd.conf** or **rpm.conf**. + > - When **sys_cut='yes'** is configured, imageTailor does not support the installation of the `rpm` command. Even if the `rpm` command is configured in the **rpm.conf** file, the configuration does not take effect. + +- sys_usrrpm_cut + + (Mandatory) Indicates whether to tailor the RPM packages added by users to the **/opt/imageTailor/custom/cfg_openEuler/usr_rpm** directory. The value can be **yes** or **no**. The default value is **no**. + + - **sys_usrrpm_cut='yes'**: imageTailor installs the RPM packages added by the user, deletes the file configured in the **\** section in the **cmd.conf** file, and then deletes the commands, libraries, and drivers that are not configured in **cmd.conf** or **rpm.conf**. + + - **sys_usrrpm_cut='no'**: imageTailor installs the RPM packages added by the user but does not delete the files in the RPM packages. + +- sys_hostname + + (Mandatory) Host name. After the OS is deployed in batches, you are advised to change the host name of each node to ensure that the host name of each node is unique. + + The host name must be a combination of letters, digits, and hyphens (-) and must start with a letter or digit. Letters are case sensitive. The value contains a maximum of 63 characters. The default value is **Euler**. + +- sys_usermodules_autoload + + (Optional) Driver loaded during system startup. When configuring this parameter, you do not need to enter the file extension **.ko**. If there are multiple drivers, separate them by space. By default, this parameter is left blank, indicating that no additional driver is loaded. + +- sys_gconv + + (Optional) This parameter is used to tailor **/usr/lib/gconv** and **/usr/lib64/gconv**. The options are as follows: + + - **null**/**NULL**: indicates that this parameter is not configured. If **sys_cut='yes'** is configured, **/usr/lib/gconv** and **/usr/lib64/gconv** will be deleted. + - **all**/**ALL**: keeps **/usr/lib/gconv** and **/usr/lib64/gconv**. + - **xxx,xxx**: keeps the corresponding files in the **/usr/lib/gconv** and **/usr/lib64/gconv** directories. If multiple files need to be kept, use commas (,) to separate them. + +- sys_man_cut + + (Optional) Indicates whether to tailor the man pages. The value can be **yes** or **no**. The default value is **yes**. + + + +>![](./public_sys-resources/icon-note.gif) NOTE: +> +> If both **sys_cut** and **sys_usrrpm_cut** are configured, **sys_cut** is used. The following rules apply: +> +> - sys_cut='no' +> +> No matter whether **sys_usrrpm_cut** is set to **yes** or **no**, the system RPM package tailoring granularity is used. That is, imageTailor installs the RPM packages in the repo source and the RPM packages in the **usr_rpm** directory, however, the files in the RPM package are not deleted. Even if some files in the RPM packages are not required, imageTailor will delete them. +> +> - sys_cut='yes' +> +> - sys_usrrpm_cut='no' +> +> System RPM package tailoring granularity: imageTailor deletes files in the RPM packages in the repo sources as configured. +> +> - sys_usrrpm_cut='yes' +> +> System and user RPM package tailoring granularity: imageTailor deletes files in the RPM packages in the repo sources and the **usr_rpm** directory as configured. +> + + + +#### Configuring Initial Passwords + +The **root** and GRUB passwords must be configured during OS installation. Otherwise, you cannot log in to the OS as the **root** user after the OS is installed using the tailored ISO image. This section describes how to configure the initial passwords. + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> You must configure the initial **root** and GRUB passwords manually. + +##### Configuring the Initial Password of the root User + +###### Introduction + +The initial password of the **root** user is stored in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file. You can modify this file to set the initial password of the **root** user. + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- If the `--minios yes/force` parameter is required when you run the `mkdliso` command to create an ISO image, you need to enter the corresponding information in the **/opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf** file. + +The default configuration of the initial password of the **root** user in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file is as follows. Add a password of your choice. + +``` + + + +``` + +The parameters are described as follows: + +- **group**: group to which the user belongs. +- **pwd**: ciphertext of the initial password. The encryption algorithm is SHA-512. Replace **${pwd}** with the actual ciphertext. +- **home**: home directory of the user. +- **name**: name of the user to be configured. + +###### Modification Method + +Before creating an ISO image, you need to change the initial password of the **root** user. The following describes how to set the initial password of the **root** user (**root** permissions are required): + +1. Add a user for generating a password, for example, **testUser**. + + ```shell + $ sudo useradd testUser + ``` + +2. Set the password of **testUser**. Run the following command and set the password as prompted: + + ```shell + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. View the **/etc/shadow** file. The content following **testUser** (string between two colons) is the ciphertext of the password. + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: + ``` + +4. Copy and paste the ciphertext to the **pwd** field in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file. + ``` shell script + + + + ``` + +5. If the `--minios yes/force` parameter is required when you run the `mkdliso` command to create an ISO image, configure the **pwd** field of the corresponding user in **/opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf**. + + ``` shell script + + + + ``` + +##### Configuring the Initial GRUB Password + +The initial GRUB password is stored in the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file. Modify this file to configure the initial GRUB password. If the initial GRUB password is not configured, the ISO image will fail to be created. + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The **root** permissions are required for configuring the initial GRUB password. +> - The default user corresponding to the GRUB password is **root**. +> +> - The `grub2-set-password` command must exist in the system. If the command does not exist, install it in advance. + +1. Run the following command and set the GRUB password as prompted: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. After the command is executed, the **user.cfg** file is generated in the current directory. The content starting with **grub.pbkdf2.sha512** is the encrypted GRUB password. + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 + ``` + +3. Copy the preceding ciphertext and add the following configuration to the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file: + + ```shell + GRUB_PASSWORD="grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615" + ``` + + +#### Configuring Partitions + +If you want to adjust system partitions or service partitions, modify the **\** section in the **/opt/imageTailor/custom/cfg_openEuler/sys.conf** file. + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- System partition: partition for storing the OS. +>- Service partition: partition for service data. +>- The type of a partition is determined by the content it stores, not the size, mount path, or file system. +>- Partition configuration is optional. You can manually configure partitions after OS installation. + + The format of **\** is as follows: + +disk_ID mount _path partition _size partition_type file_system [Secondary formatting flag] + +The default configuration is as follows: + +``` shell script + +hd0 /boot 512M primary ext4 yes +hd0 /boot/efi 200M primary vfat yes +hd0 / 30G primary ext4 +hd0 - - extended - +hd0 /var 1536M logical ext4 +hd0 /home max logical ext4 + +``` + +The parameters are described as follows: + +- disk_ID: + ID of a disk. Set this parameter in the format of **hd***x*, where *x* indicates the *x*th disk. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >Partition configuration takes effect only when the disk can be recognized. + +- mount_path: + Mount path to a specified partition. You can configure service partitions and adjust the default system partition. If you do not mount partitions, set this parameter to **-**. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >- You must configure the mount path to **/**. You can adjust mount paths to other partitions according to your needs. + >- When the UEFI boot mode is used, the partition configuration in the x86_64 architecture must contain the mount path **/boot**, and the partition configuration in the AArch64 architecture must contain the mount path **/boot/efi**. + +- partition_size: + The value types are as follows: + + - G/g: The unit of a partition size is GB, for example, 2G. + - M/m: The unit of a partition size is MB, for example, 300M. + - T/t: The unit of a partition size is TB, for example, 1T. + - MAX/max: The rest space of a hard disk is used to create a partition. This value can only be assigned to the last partition. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** +> + >- A partition size value cannot contain decimal numbers. If there are decimal numbers, change the unit of the value to make the value an integer. For example, 1.5 GB should be changed to 1536 MB. + >- When the partition size is set to **MAX**/**max**, the size of the remaining partition cannot exceed the limit of the supported file system type (the default file system type is **ext4**, and the maximum size is **16T**). + +- partition_type: + The values of partition types are as follows: + + - primary: primary partitions + - extended: extended partition (configure only *disk_ID* for this partition) + - logical: logical partitions + +- file_system: + Currently, **ext4** and **vfat** file systems are supported. + +- [Secondary formatting flag]: + Indicates whether to format the disk during secondary installation. This parameter is optional. + + - The value can be **yes** or **no**. The default value is **no**. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >Secondary formatting indicates that openEuler has been installed on the disk before this installation. If the partition table configuration (partition size, mount point, and file type) used in the previous installation is the same as that used in the current installation, this flag can be used to configure whether to format the previous partitions, except the **/boot** and **/** partitions. If the target host is installed for the first time, this flag does not take effect, and all partitions with specified file systems are formatted. + +#### Configuring the Network + +The system network parameters are stored in **/opt/imageTailor/custom/cfg_openEuler/sys.conf**. You can modify the network parameters of the target ISO image, such as the NIC name, IP address, and subnet mask, by configuring **\\** in this file. + +The default network configuration in the **sys.conf** file is as follows. **netconfig-0** indicates the **eth0** NIC. If you need to configure an additional NIC, for example, **eth1**, add **\\** to the configuration file and set the parameters of **eth1**. + +```shell + +BOOTPROTO="dhcp" +DEVICE="eth0" +IPADDR="" +NETMASK="" +STARTMODE="auto" + +``` + +The following table describes the parameters. + +- | Parameter | Mandatory or Not| Value | Description | + | :-------- | -------- | :------------------------------------------------ | :----------------------------------------------------------- | + | BOOTPROTO | Yes | none / static / dhcp | **none**: No protocol is used for boot, and no IP address is assigned.
**static**: An IP address is statically assigned.
**dhcp**: An IP address is dynamically obtained using the dynamic host configuration protocol (DHCP).| + | DEVICE | Yes | Example: **eth1** | NIC name. | + | IPADDR | Yes | Example: **192.168.11.100** | IP address.
This parameter must be configured only when the value of **BOOTPROTO** is **static**.| + | NETMASK | Yes | - | Subnet mask.
This parameter must be configured only when the value of **BOOTPROTO** is **static**.| + | STARTMODE | Yes | manual / auto / hotplug / ifplugd / nfsroot / off | NIC start mode.
**manual**: A user runs the `ifup` command on a terminal to start an NIC.
**auto**/**hotplug**/**ifplug**/**nfsroot**: An NIC is started when the OS identifies it.
**off**: An NIC cannot be started in any situations.
For details about the parameters, run the `man ifcfg` command on the host that is used to create the ISO image.| + + +#### Configuring Kernel Parameters + +To ensure stable and efficient running of the system, you can modify kernel command line parameters as required. For an OS image created by imageTailor, you can modify the **GRUB_CMDLINE_LINUX** configuration in the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file to modify the kernel command line parameters. The default settings of the kernel command line parameters in **GRUB_CMDLINE_LINUX** are as follows: + +```shell +GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" +``` + +The meanings of the configurations are as follows (for details about other common kernel command line parameters, see related kernel documents): + +- net.ifnames=0 biosdevname=0 + + Name the NIC in traditional mode. + +- crashkernel=512M + + The memory space reserved for kdump is 512 MB. + +- oops=panic panic=3 + + The kernel panics when an oops error occurs, and the system restarts 3 seconds later. + +- softlockup_panic=1 + + The kernel panics when a soft-lockup is detected. + +- reserve_kbox_mem=16M + + The memory space reserved for Kbox is 16 MB. + +- console=tty0 + + Specifies **tty0** as the output device of the first virtual console. + +- crash_kexec_post_notifiers + + After the system crashes, the function registered with the panic notification chain is called first, and then kdump is executed. + +### Creating an Image + +After customizing the operating system, you can use the `mkdliso` script to create the OS image file. The OSimage created using imageTailor is an ISO image file. + +#### Command Description + +##### Syntax + +**mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h]** + +##### Parameter Description + +| Parameter| Mandatory| Description | Value Range | +| -------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| -p | Yes | Specifies the product name. | **openEuler** | +| c | Yes | Specifies the relative path of the configuration file. | **custom/cfg_openEuler** | +| --minios | No | Specifies whether to create the **initrd** file that is used to boot the system during system installation. | The default value is **yes**.
**yes**: The **initrd** file will be created when the command is executed for the first time. When a subsequent `mkdliso` is executed, the system checks whether the **initrd** file exists in the **usr_install/boot** directory using sha256 verification. If the **initrd** file exists, it is not created again. Otherwise, it is created.
**no**: The **initrd** file is not created. The **initrd** file used for system boot and running is the same.
**force**: The **initrd** file will be created forcibly, regardless of whether it exists in the **usr_install/boot** directory or not.| +| --sec | No | Specifies whether to perform security hardening on the generated ISO file.
If this parameter is not specified, the user should undertake the resultant security risks| N/A | +| -h | No | Obtains help information. | N/A | + +#### Image Creation Guide + +To create an ISO image using`mkdliso`, perform the following steps: + +>![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The absolute path to `mkdliso` must not contain spaces. Otherwise, the ISO image creation will fail. +> - In the environment for creating the ISO image, the value of **umask** must be set to **0022**. + +1. Run the `mkdliso` command as the **root** user to generate the ISO image file. The following command is used for reference: + + ```shell + # sudo /opt/imageTailor/mkdliso -p openEuler -c custom/cfg_openEuler --sec + ``` + + After the command is executed, the created files are stored in the **/opt/imageTailor/result/{date}** directory, including **openEuler-aarch64.iso** and **openEuler-aarch64.iso.sha256**. + +2. Verify the integrity of the ISO image file. Assume that the date and time is **2022-03-21-14-48**. + + ```shell + $ cd /opt/imageTailor/result/2022-03-21-14-48/ + $ sha256sum -c openEuler-aarch64.iso.sha256 + ``` + + If the following information is displayed, the ISO image creation is complete. + + ``` + openEuler-aarch64.iso: OK + ``` + + If the following information is displayed, the image is incomplete. The ISO image file is damaged and needs to be created again. + + ```shell + openEuler-aarch64.iso: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + +3. View the logs. + + After an image is created, you can view logs as required (for example, when an error occurs during image creation). When an image is created for the first time, the corresponding log file and security hardening log file are compressed into a TAR package (the log file is named in the format of **sys_custom_log_{Date}.tar.gz**) and stored in the **result/log directory**. Only the latest 50 compressed log packages are stored in this directory. If the number of compressed log packages exceeds 50, the earliest files will be overwritten. + + + +### Tailoring Time Zones + +After the customized ISO image is installed, you can tailor the time zones supported by the openEuler system as required. This section describes how to tailor the time zones. + +The information about time zones supported by openEuler is stored in the time zone folder **/usr/shre/zoninfo**. You can run the following command to view the time zone information: + +```shell +$ ls /usr/share/zoneinfo/ +Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ +Pacific/ zone.tab +``` + +Each subfolder represents an area. The current areas include continents, oceans, and **Etc**. Each area folder contains the locations that belong to it. Generally, a location is a city or an island. + +All time zones are in the format of *area/location*. For example, if China Standard Time is used in southern China, the time zone is Asia/Shanghai (location may not be the capital). The corresponding time zone file is: + +``` +/usr/share/zoneinfo/Asia/Shanghai +``` + +If you want to tailor some time zones, delete the corresponding time zone files. + +### Customization Example + +This section describes how to use imageTailor to create an ISO image. + +1. Check whether the environment used to create the ISO meets the requirements. + + ``` shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. Ensure that the root directory has at least 40 GB free space. + + ```shell + $ df -h + Filesystem Size Used Avail Use% Mounted on + ...... + /dev/vdb 196G 28K 186G 1% / + ``` + +3. Install the imageTailor tailoring tool. For details, see [Installation](#installation). + + ```shell + $ sudo yum install -y imageTailor + $ ll /opt/imageTailor/ + total 88K + drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom + drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi + -r-x------. 1 root root 69K Mar 3 08:00 mkdliso + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool + ``` + +4. Configure a local repo source. + + ```shell + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +5. Change the **root** and GRUB passwords. + + Replace **\${pwd}** with the encrypted password by referring to [Configuring Initial Passwords](#configuring-initial-passwords). + + ```shell + $ cd /opt/imageTailor/ + $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub + GRUB_PASSWORD="${pwd1}" + $ + $ sudo vi kiwi/minios/cfg_minios/rpm.conf + + + + $ + $ sudo vi custom/cfg_openEuler/rpm.conf + + + + ``` + +6. Run the tailoring command. + + ```shell + $ sudo rm -rf /opt/imageTailor/result + $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force + ...... + Complete release iso file at: result/2022-03-09-15-31/openEuler-aarch64.iso + move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz + $ ll result/2022-03-09-15-31/ + total 889M + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-aarch64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-aarch64.iso.sha256 + ``` diff --git a/docs/en/docs/Virtualization/installation-to-virtualization.md b/docs/en/docs/Virtualization/virtualization-installation.md similarity index 100% rename from docs/en/docs/Virtualization/installation-to-virtualization.md rename to docs/en/docs/Virtualization/virtualization-installation.md diff --git a/docs/en/docs/desktop/kubesphere.md b/docs/en/docs/desktop/kubesphere.md index 32baa2eb1..40a47a96f 100644 --- a/docs/en/docs/desktop/kubesphere.md +++ b/docs/en/docs/desktop/kubesphere.md @@ -1,4 +1,4 @@ -# KubeSphere Installation Guide +# KubeSphere Deployment Guide This document describes how to install and deploy Kubernetes and KubeSphere clusters on openEuler 21.09. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-train.md b/docs/en/docs/thirdparty_migration/OpenStack-train.md new file mode 100644 index 000000000..0816483f0 --- /dev/null +++ b/docs/en/docs/thirdparty_migration/OpenStack-train.md @@ -0,0 +1,2961 @@ +# OpenStack-Wallaby Deployment Guide + + + +- [OpenStack-Wallaby Deployment Guide](#openstack-wallaby-deployment-guide) + - [OpenStack](#openstack) + - [Conventions](#conventions) + - [Preparing the Environment](#preparing-the-environment) + - [Environment Configuration](#environment-configuration) + - [Installing the SQL Database](#installing-the-sql-database) + - [Installing RabbitMQ](#installing-rabbitmq) + - [Installing Memcached](#installing-memcached) + - [OpenStack Installation](#openstack-installation) + - [Installing Keystone](#installing-keystone) + - [Installing Glance](#installing-glance) + - [Installing Placement](#installing-placement) + - [Installing Nova](#installing-nova) + - [Installing Neutron](#installing-neutron) + - [Installing Cinder](#installing-cinder) + - [Installing Horizon](#installing-horizon) + - [Installing Tempest](#installing-tempest) + - [Installing Ironic](#installing-ironic) + - [Installing Kolla](#installing-kolla) + - [Installing Trove](#installing-trove) + - [Installing Swift](#installing-swift) + - [Installing Cyborg](#installing-cyborg) + - [Installing Aodh](#installing-aodh) + - [Installing Gnocchi](#installing-gnocchi) + - [Installing Ceilometer](#installing-ceilometer) + - [Installing Heat](#installing-heat) + - [OpenStack Quick Installation](#openstack-quick-installation) + + +## OpenStack + +OpenStack is an open source cloud computing infrastructure software project developed by the community. It provides an operating platform or tool set for deploying the cloud, offering scalable and flexible cloud computing for organizations. + +As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. + +The official source of openEuler 20.03-LTS-SP3 now supports OpenStack Train. You can configure the Yum source then deploy OpenStack by following the instructions of this document. + +## Conventions + +OpenStack supports multiple deployment modes. This document includes two deployment modes: **All in One** and **Distributed**. The conventions are as follows: + +**All in One** mode: + +```text +Ignores all possible suffixes. +``` + +**Distributed** mode: + +```text +A suffix of (CTL) indicates that the configuration or command applies only to the control node. +A suffix of (CPT) indicates that the configuration or command applies only to the compute node. +A suffix of (STG) indicates that the configuration or command applies only to the storage node. +In other cases, the configuration or command applies to both the control node and compute node. +``` + +***Note*** + +The services involved in the preceding conventions are as follows: + +- Cinder +- Nova +- Neutron + +## Preparing the Environment + +### Environment Configuration + +1. Start the OpenStack Train Yum source. + + ```shell + yum update + yum install openstack-release-train + yum clean all && yum makecache + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + ``` + +2. Change the host name and mapping. + + Set the host name of each node: + + ```shell + hostnamectl set-hostname controller (CTL) + hostnamectl set-hostname compute (CPT) + ``` + + Assuming the IP address of the controller node is **10.0.0.11** and the IP address of the compute node (if any) is **10.0.0.12**, add the following information to the **/etc/hosts** file: + + ```shell + 10.0.0.11 controller + 10.0.0.12 compute + ``` + +### Installing the SQL Database + +1. Run the following command to install the software package: + + ```shell + yum install mariadb mariadb-server python3-PyMySQL + ``` + +2. Run the following command to create and edit the **/etc/my.cnf.d/openstack.cnf** file: + + ```shell + vim /etc/my.cnf.d/openstack.cnf + + [mysqld] + bind-address = 10.0.0.11 + default-storage-engine = innodb + innodb_file_per_table = on + max_connections = 4096 + collation-server = utf8_general_ci + character-set-server = utf8 + ``` + + ***Note*** + + **`bind-address` is set to the management IP address of the controller node.** + +3. Run the following commands to start the database service and configure it to automatically start upon system boot: + + ```shell + systemctl enable mariadb.service + systemctl start mariadb.service + ``` + +4. (Optional) Configure the default database password: + + ```shell + mysql_secure_installation + ``` + + ***Note*** + + **Perform operations as prompted.** + +### Installing RabbitMQ + +1. Run the following command to install the software package: + + ```shell + yum install rabbitmq-server + ``` + +2. Start the RabbitMQ service and configure it to automatically start upon system boot: + + ```shell + systemctl enable rabbitmq-server.service + systemctl start rabbitmq-server.service + ``` + +3. Add the OpenStack user: + + ```shell + rabbitmqctl add_user openstack RABBIT_PASS + ``` + + ***Note*** + + **Replace *RABBIT_PASS* to set the password for the openstack user.** + +4. Run the following command to set the permission of the **openstack** user to allow the user to perform configuration, write, and read operations: + + ```shell + rabbitmqctl set_permissions openstack ".*" ".*" ".*" + ``` + +### Installing Memcached + +1. Run the following command to install the dependency package: + + ```shell + yum install memcached python3-memcached + ``` + +2. Open the **/etc/sysconfig/memcached** file in insert mode. + + ```shell + vim /etc/sysconfig/memcached + + OPTIONS="-l 127.0.0.1,::1,controller" + ``` + +3. Run the following command to start the Memcached service and configure it to automatically start upon system boot: + + ```shell + systemctl enable memcached.service + systemctl start memcached.service + ``` + + ***Note*** + + **After the service is started, you can run `memcached-tool controller stats` to ensure that the service is started properly and available. You can replace `controller` with the management IP address of the controller node.** + +## OpenStack Installation + +### Installing Keystone + +1. Create the **keystone** database and grant permissions: + + ``` sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE keystone; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ + IDENTIFIED BY 'KEYSTONE_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ + IDENTIFIED BY 'KEYSTONE_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *KEYSTONE_DBPASS* to set the password for the keystone database.** + +2. Install the software package: + + ```shell + yum install openstack-keystone httpd mod_wsgi + ``` + +3. Configure Keystone: + + ```shell + vim /etc/keystone/keystone.conf + + [database] + connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone + + [token] + provider = fernet + ``` + + ***Description*** + + In the **[database]** section, configure the database entry . + + In the **[token]** section, configure the token provider . + + ***Note:*** + + **Replace *KEYSTONE_DBPASS* with the password of the keystone database.** + +4. Synchronize the database: + + ```shell + su -s /bin/sh -c "keystone-manage db_sync" keystone + ``` + +5. Initialize the Fernet keystore: + + ```shell + keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone + keystone-manage credential_setup --keystone-user keystone --keystone-group keystone + ``` + +6. Start the service: + + ```shell + keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ + --bootstrap-admin-url http://controller:5000/v3/ \ + --bootstrap-internal-url http://controller:5000/v3/ \ + --bootstrap-public-url http://controller:5000/v3/ \ + --bootstrap-region-id RegionOne + ``` + + ***Note*** + + **Replace *ADMIN_PASS* to set the password for the admin user.** + +7. Configure the Apache HTTP server: + + ```shell + vim /etc/httpd/conf/httpd.conf + + ServerName controller + ``` + + ```shell + ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ + ``` + + ***Description*** + + Configure **ServerName** to use the control node. + + ***Note*** + **If the ServerName item does not exist, create it. + +8. Start the Apache HTTP service: + + ```shell + systemctl enable httpd.service + systemctl start httpd.service + ``` + +9. Create environment variables: + + ```shell + cat << EOF >> ~/.admin-openrc + export OS_PROJECT_DOMAIN_NAME=Default + export OS_USER_DOMAIN_NAME=Default + export OS_PROJECT_NAME=admin + export OS_USERNAME=admin + export OS_PASSWORD=ADMIN_PASS + export OS_AUTH_URL=http://controller:5000/v3 + export OS_IDENTITY_API_VERSION=3 + export OS_IMAGE_API_VERSION=2 + EOF + ``` + + ***Note*** + + **Replace *ADMIN_PASS* with the password of the admin user.** + +10. Create domains, projects, users, and roles in sequence. python3-openstackclient must be installed first: + + ```shell + yum install python3-openstackclient + ``` + + Import the environment variables: + + ```shell + source ~/.admin-openrc + ``` + + Create the project **service**. The domain **default** has been created during keystone-manage bootstrap. + + ```shell + openstack domain create --description "An Example Domain" example + ``` + + ```shell + openstack project create --domain default --description "Service Project" service + ``` + + Create the (non-admin) project **myproject**, user **myuser**, and role **myrole**, and add the role **myrole** to **myproject** and **myuser**. + + ```shell + openstack project create --domain default --description "Demo Project" myproject + openstack user create --domain default --password-prompt myuser + openstack role create myrole + openstack role add --project myproject --user myuser myrole + ``` + +11. Perform the verification. + + Cancel the temporary environment variables **OS_AUTH_URL** and **OS_PASSWORD**. + + ```shell + source ~/.admin-openrc + unset OS_AUTH_URL OS_PASSWORD + ``` + + Request a token for the **admin** user: + + ```shell + openstack --os-auth-url http://controller:5000/v3 \ + --os-project-domain-name Default --os-user-domain-name Default \ + --os-project-name admin --os-username admin token issue + ``` + + Request a token for user **myuser**: + + ```shell + openstack --os-auth-url http://controller:5000/v3 \ + --os-project-domain-name Default --os-user-domain-name Default \ + --os-project-name myproject --os-username myuser token issue + ``` + +### Installing Glance + +1. Create the database, service credentials, and the API endpoints. + + Create the database: + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE glance; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ + IDENTIFIED BY 'GLANCE_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ + IDENTIFIED BY 'GLANCE_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note:*** + + **Replace *GLANCE_DBPASS* to set the password for the glance database.** + + Create the service credential: + + ```shell + source ~/.admin-openrc + + openstack user create --domain default --password-prompt glance + openstack role add --project service --user glance admin + openstack service create --name glance --description "OpenStack Image" image + ``` + + Create the API endpoints for the image service: + + ```shell + openstack endpoint create --region RegionOne image public http://controller:9292 + openstack endpoint create --region RegionOne image internal http://controller:9292 + openstack endpoint create --region RegionOne image admin http://controller:9292 + ``` + +2. Install the software package: + + ```shell + yum install openstack-glance + ``` + +3. Configure Glance: + + ```shell + vim /etc/glance/glance-api.conf + + [database] + connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = glance + password = GLANCE_PASS + + [paste_deploy] + flavor = keystone + + [glance_store] + stores = file,http + default_store = file + filesystem_store_datadir = /var/lib/glance/images/ + ``` + + ***Description:*** + + In the **[database]** section, configure the database entry. + + In the **[keystone_authtoken]** and **[paste_deploy]** sections, configure the identity authentication service entry. + + In the **[glance_store]** section, configure the local file system storage and the location of image files. + + ***Note*** + + **Replace *GLANCE_DBPASS* with the password of the glance database.** + + **Replace *GLANCE_PASS* with the password of user glance.** + +4. Synchronize the database: + + ```shell + su -s /bin/sh -c "glance-manage db_sync" glance + ``` + +5. Start the service: + + ```shell + systemctl enable openstack-glance-api.service + systemctl start openstack-glance-api.service + ``` + +6. Perform the verification. + + Download the image: + + ```shell + source ~/.admin-openrc + + wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img + ``` + + ***Note*** + + **If the Kunpeng architecture is used in your environment, download the image of the AArch64 version. the cirros-0.5.2-aarch64-disk.img image file has been tested.** + + Upload the image to the image service: + + ```shell + openstack image create --disk-format qcow2 --container-format bare \ + --file cirros-0.4.0-x86_64-disk.img --public cirros + ``` + + Confirm the image upload and verify the attributes: + + ```shell + openstack image list + ``` + +### Installing Placement + +1. Create a database, service credentials, and API endpoints. + + Create a database. + + Access the database as the **root** user. Create the **placement** database, and grant permissions. + + ```shell + mysql -u root -p + MariaDB [(none)]> CREATE DATABASE placement; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ + IDENTIFIED BY 'PLACEMENT_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ + IDENTIFIED BY 'PLACEMENT_DBPASS'; + MariaDB [(none)]> exit + ``` + + **Note**: + + **Replace *PLACEMENT_DBPASS* to set the password for the placement database.** + + ```shell + source admin-openrc + ``` + + Run the following commands to create the Placement service credentials, create the **placement** user, and add the **admin** role to the **placement** user: + + Create the Placement API Service. + + ```shell + openstack user create --domain default --password-prompt placement + openstack role add --project service --user placement admin + openstack service create --name placement --description "Placement API" placement + ``` + + Create API endpoints of the **placement** service. + + ```shell + openstack endpoint create --region RegionOne placement public http://controller:8778 + openstack endpoint create --region RegionOne placement internal http://controller:8778 + openstack endpoint create --region RegionOne placement admin http://controller:8778 + ``` + +2. Perform the installation and configuration. + + Install the software package: + + ```shell + yum install openstack-placement-api + ``` + + Configure Placement: + + Edit the **/etc/placement/placement.conf** file: + + In the **[placement_database]** section, configure the database entry. + + In **[api]** and **[keystone_authtoken]** sections, configure the identity authentication service entry. + + ```shell + # vim /etc/placement/placement.conf + [placement_database] + # ... + connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement + [api] + # ... + auth_strategy = keystone + [keystone_authtoken] + # ... + auth_url = http://controller:5000/v3 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = placement + password = PLACEMENT_PASS + ``` + + Replace **PLACEMENT_DBPASS** with the password of the **placement** database, and replace **PLACEMENT_PASS** with the password of the **placement** user. + + Synchronize the database: + + ```shell + su -s /bin/sh -c "placement-manage db sync" placement + ``` + + Start the httpd service. + + ```shell + systemctl restart httpd + ``` + +3. Perform the verification. + + Run the following command to check the status: + + ```shell + . admin-openrc + placement-status upgrade check + ``` + + Run the following command to install osc-placement and list the available resource types and features: + + ```shell + yum install python3-osc-placement + openstack --os-placement-api-version 1.2 resource class list --sort-column name + openstack --os-placement-api-version 1.6 trait list --sort-column name + ``` + +### Installing Nova + +1. Create a database, service credentials, and API endpoints. + + Create a database. + + ```sql + mysql -u root -p (CTL) + + MariaDB [(none)]> CREATE DATABASE nova_api; + MariaDB [(none)]> CREATE DATABASE nova; + MariaDB [(none)]> CREATE DATABASE nova_cell0; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> exit + ``` + + **Note**: + + **Replace *NOVA_DBPASS* to set the password for the nova database.** + + ```shell + source ~/.admin-openrc (CTL) + ``` + + Run the following command to create the Nova service certificate: + + ```shell + openstack user create --domain default --password-prompt nova (CTL) + openstack role add --project service --user nova admin (CTL) + openstack service create --name nova --description "OpenStack Compute" compute (CTL) + ``` + + Create a Nova API endpoint. + + ```shell + openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 (CTL) + openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 (CTL) + openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 (CTL) + ``` + +2. Install the software packages: + + ```shell + yum install openstack-nova-api openstack-nova-conductor \ (CTL) + openstack-nova-novncproxy openstack-nova-scheduler + + yum install openstack-nova-compute (CPT) + ``` + + **Note**: + + **If the ARM64 architecture is used, you also need to run the following command:** + + ```shell + yum install edk2-aarch64 (CPT) + ``` + +3. Configure Nova: + + ```shell + vim /etc/nova/nova.conf + + [DEFAULT] + enabled_apis = osapi_compute,metadata + transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ + my_ip = 10.0.0.1 + use_neutron = true + firewall_driver = nova.virt.firewall.NoopFirewallDriver + compute_driver=libvirt.LibvirtDriver (CPT) + instances_path = /var/lib/nova/instances/ (CPT) + lock_path = /var/lib/nova/tmp (CPT) + + [api_database] + connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api (CTL) + + [database] + connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova (CTL) + + [api] + auth_strategy = keystone + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000/ + auth_url = http://controller:5000/ + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = nova + password = NOVA_PASS + + [vnc] + enabled = true + server_listen = $my_ip + server_proxyclient_address = $my_ip + novncproxy_base_url = http://controller:6080/vnc_auto.html (CPT) + + [glance] + api_servers = http://controller:9292 + + [oslo_concurrency] + lock_path = /var/lib/nova/tmp (CTL) + + [placement] + region_name = RegionOne + project_domain_name = Default + project_name = service + auth_type = password + user_domain_name = Default + auth_url = http://controller:5000/v3 + username = placement + password = PLACEMENT_PASS + + [neutron] + auth_url = http://controller:5000 + auth_type = password + project_domain_name = default + user_domain_name = default + region_name = RegionOne + project_name = service + username = neutron + password = NEUTRON_PASS + service_metadata_proxy = true (CTL) + metadata_proxy_shared_secret = METADATA_SECRET (CTL) + ``` + + Description + + In the **[default]** section, enable the compute and metadata APIs, configure the RabbitMQ message queue entry, configure **my_ip**, and enable the network service **neutron**. + + In the **[api_database]** and **[database]** sections, configure the database entry. + + In the **[api]** and **[keystone_authtoken]** sections, configure the identity service entry. + + In the **[vnc]** section, enable and configure the entry for the remote console. + + In the **[glance]** section, configure the API address for the image service. + + In the **[oslo_concurrency]** section, configure the lock path. + + In the **[placement]** section, configure the entry of the Placement service. + + **Note**: + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Set *my_ip* to the management IP address of the controller node.** + + **Replace *NOVA_DBPASS* with the password of the nova database.** + + **Replace *NOVA_PASS* with the password of the nova user.** + + **Replace *PLACEMENT_PASS* with the password of the placement user.** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + + Others + + Check whether VM hardware acceleration (x86 architecture) is supported: + + ```shell + egrep -c '(vmx|svm)' /proc/cpuinfo (CPT) + ``` + + If the returned value is **0**, hardware acceleration is not supported. You need to configure libvirt to use QEMU instead of KVM. + + ```shell + vim /etc/nova/nova.conf (CPT) + + [libvirt] + virt_type = qemu + ``` + + If the returned value is **1** or a larger value, hardware acceleration is supported. You can set the value of **virt_type** to **kvm**. + + **Note**: + + **If the ARM64 architecture is used, you also need to run the following command on the compute node:** + + ```shell + + mkdir -p /usr/share/AAVMF + chown nova:nova /usr/share/AAVMF + + ln -s /usr/share/edk2/aarch64/QEMU_EFI-pflash.raw \ + /usr/share/AAVMF/AAVMF_CODE.fd + ln -s /usr/share/edk2/aarch64/vars-template-pflash.raw \ + /usr/share/AAVMF/AAVMF_VARS.fd + + vim /etc/libvirt/qemu.conf + + nvram = ["/usr/share/AAVMF/AAVMF_CODE.fd: \ + /usr/share/AAVMF/AAVMF_VARS.fd", \ + "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw: \ + /usr/share/edk2/aarch64/vars-template-pflash.raw"] + ``` + In addition, when the deployment environment in the ARM architecture is nested virtualization, configure the **[libvirt]** section as follows: + + ```shell + [libvirt] + virt_type = qemu + cpu_mode = custom + cpu_model = cortex-a72 + ``` + +4. Synchronize the database. + + Run the following command to synchronize the **nova-api** database: + + ```shell + su -s /bin/sh -c "nova-manage api_db sync" nova (CTL) + ``` + + Run the following command to register the **cell0** database: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova (CTL) + ``` + + Create the **cell1** cell: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova (CTL) + ``` + + Synchronize the **nova** database: + + ```shell + su -s /bin/sh -c "nova-manage db sync" nova (CTL) + ``` + + Verify whether **cell0** and **cell1** are correctly registered: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova (CTL) + ``` + + Add compute node to the OpenStack cluster: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova (CPT) + ``` + +5. Start the services: + + ```shell + systemctl enable \ (CTL) + openstack-nova-api.service \ + openstack-nova-scheduler.service \ + openstack-nova-conductor.service \ + openstack-nova-novncproxy.service + + systemctl start \ (CTL) + openstack-nova-api.service \ + openstack-nova-scheduler.service \ + openstack-nova-conductor.service \ + openstack-nova-novncproxy.service + ``` + + ```shell + systemctl enable libvirtd.service openstack-nova-compute.service (CPT) + systemctl start libvirtd.service openstack-nova-compute.service (CPT) + ``` + +6. Perform the verification. + + ```shell + source ~/.admin-openrc (CTL) + ``` + + List the service components to verify that each process is successfully started and registered: + + ```shell + openstack compute service list (CTL) + ``` + + List the API endpoints in the identity service to verify the connection to the identity service: + + ```shell + openstack catalog list (CTL) + ``` + + List the images in the image service to verify the connections: + + ```shell + openstack image list (CTL) + ``` + + Check whether the cells are running properly and whether other prerequisites are met. + + ```shell + nova-status upgrade check (CTL) + ``` + +### Installing Neutron + +1. Create the database, service credentials, and API endpoints. + + Create the database: + + ```sql + mysql -u root -p (CTL) + + MariaDB [(none)]> CREATE DATABASE neutron; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ + IDENTIFIED BY 'NEUTRON_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ + IDENTIFIED BY 'NEUTRON_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *NEUTRON_DBPASS* to set the password for the neutron database.** + + ```shell + source ~/.admin-openrc (CTL) + ``` + + Create the **neutron** service credential: + + ```shell + openstack user create --domain default --password-prompt neutron (CTL) + openstack role add --project service --user neutron admin (CTL) + openstack service create --name neutron --description "OpenStack Networking" network (CTL) + ``` + + Create the API endpoints of the Neutron service: + + ```shell + openstack endpoint create --region RegionOne network public http://controller:9696 (CTL) + openstack endpoint create --region RegionOne network internal http://controller:9696 (CTL) + openstack endpoint create --region RegionOne network admin http://controller:9696 (CTL) + ``` + +2. Install the software packages: + + ```shell + yum install openstack-neutron openstack-neutron-linuxbridge ebtables ipset \ (CTL) + openstack-neutron-ml2 + ``` + + ```shell + yum install openstack-neutron-linuxbridge ebtables ipset (CPT) + ``` + +3. Configure Neutron. + + Set the main configuration items: + + ```shell + vim /etc/neutron/neutron.conf + + [database] + connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron (CTL) + + [DEFAULT] + core_plugin = ml2 (CTL) + service_plugins = router (CTL) + allow_overlapping_ips = true (CTL) + transport_url = rabbit://openstack:RABBIT_PASS@controller + auth_strategy = keystone + notify_nova_on_port_status_changes = true (CTL) + notify_nova_on_port_data_changes = true (CTL) + api_workers = 3 (CTL) + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = neutron + password = NEUTRON_PASS + + [nova] + auth_url = http://controller:5000 (CTL) + auth_type = password (CTL) + project_domain_name = Default (CTL) + user_domain_name = Default (CTL) + region_name = RegionOne (CTL) + project_name = service (CTL) + username = nova (CTL) + password = NOVA_PASS (CTL) + + [oslo_concurrency] + lock_path = /var/lib/neutron/tmp + ``` + + ***Description*** + + Configure the database entry in the **[database]** section. + + Enable the ML2 and router plugins, allow IP address overlapping, and configure the RabbitMQ message queue entry in the **[default]** section. + + Configure the identity authentication service entry in the **[default]** and **[keystone]** sections. + + Enable the network to notify the change of the compute network topology in the **[default]** and **[nova]** sections. + + Configure the lock path in the **[oslo_concurrency]** section. + + ***Note*** + + **Replace *NEUTRON_DBPASS* with the password of the neutron database.** + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *NOVA_PASS* with the password of the nova user.** + + Configure the ML2 plugin: + + ```shell + vim /etc/neutron/plugins/ml2/ml2_conf.ini + + [ml2] + type_drivers = flat,vlan,vxlan + tenant_network_types = vxlan + mechanism_drivers = linuxbridge,l2population + extension_drivers = port_security + + [ml2_type_flat] + flat_networks = provider + + [ml2_type_vxlan] + vni_ranges = 1:1000 + + [securitygroup] + enable_ipset = true + ``` + + Create the symbolic link for /etc/neutron/plugin.ini. + + ```shell + ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini + ``` + + **Note** + + **Enable flat, vlan, and vxlan networks, enable the linuxbridge and l2population mechanisms, and enable the port security extension driver in the [ml2] section.** + + **Configure the flat network as the provider virtual network in the [ml2_type_flat] section.** + + **Configure the range of the VXLAN network identifier in the [ml2_type_vxlan] section.** + + **Set ipset enabled in the [securitygroup] section.** + + **Remarks** + + **The actual configurations of l2 can be modified based as required. In this example, the provider network + linuxbridge is used.** + + Configure the Linux bridge agent: + + ```shell + vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini + + [linux_bridge] + physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME + + [vxlan] + enable_vxlan = true + local_ip = OVERLAY_INTERFACE_IP_ADDRESS + l2_population = true + + [securitygroup] + enable_security_group = true + firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver + ``` + + ***Description*** + + Map the provider virtual network to the physical network interface in the **[linux_bridge]** section. + + Enable the VXLAN overlay network, configure the IP address of the physical network interface that processes the overlay network, and enable layer-2 population in the **[vxlan]** section. + + Enable the security group and configure the linux bridge iptables firewall driver in the **[securitygroup]** section. + + ***Note*** + + **Replace *PROVIDER_INTERFACE_NAME* with the physical network interface.** + + **Replace *OVERLAY_INTERFACE_IP_ADDRESS* with the management IP address of the controller node.** + + Configure the Layer-3 agent: + + ```shell + vim /etc/neutron/l3_agent.ini (CTL) + + [DEFAULT] + interface_driver = linuxbridge + ``` + + ***Description*** + + Set the interface driver to linuxbridge in the **[default]** section. + + Configure the DHCP agent: + + ```shell + vim /etc/neutron/dhcp_agent.ini (CTL) + + [DEFAULT] + interface_driver = linuxbridge + dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq + enable_isolated_metadata = true + ``` + + ***Description*** + + In the **[default]** section, configure the linuxbridge interface driver and Dnsmasq DHCP driver, and enable the isolated metadata. + + Configure the metadata agent: + + ```shell + vim /etc/neutron/metadata_agent.ini (CTL) + + [DEFAULT] + nova_metadata_host = controller + metadata_proxy_shared_secret = METADATA_SECRET + ``` + + ***Description*** + + In the **[default]**, configure the metadata host and the shared secret. + + ***Note*** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + +4. Configure Nova: + + ```shell + vim /etc/nova/nova.conf + + [neutron] + auth_url = http://controller:5000 + auth_type = password + project_domain_name = Default + user_domain_name = Default + region_name = RegionOne + project_name = service + username = neutron + password = NEUTRON_PASS + service_metadata_proxy = true (CTL) + metadata_proxy_shared_secret = METADATA_SECRET (CTL) + ``` + + ***Description*** + + In the **[neutron]** section, configure the access parameters, enable the metadata agent, and configure the secret. + + ***Note*** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + +5. Synchronize the database: + + ```shell + su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ + --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron + ``` + +6. Run the following command to restart the compute API service: + + ```shell + systemctl restart openstack-nova-api.service + ``` + +7. Start the network service: + + ```shell + systemctl enable neutron-server.service neutron-linuxbridge-agent.service \ (CTL) + neutron-dhcp-agent.service neutron-metadata-agent.service \ + neutron-l3-agent.service + + systemctl restart neutron-server.service neutron-linuxbridge-agent.service \ (CTL) + neutron-dhcp-agent.service neutron-metadata-agent.service \ + neutron-l3-agent.service + + systemctl enable neutron-linuxbridge-agent.service (CPT) + systemctl restart neutron-linuxbridge-agent.service openstack-nova-compute.service (CPT) + ``` + +8. Perform the verification. + + Run the following command to verify whether the Neutron agent is started successfully: + + ```shell + openstack network agent list + ``` + +### Installing Cinder + +1. Create the database, service credentials, and API endpoints. + + Create the database: + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE cinder; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ + IDENTIFIED BY 'CINDER_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ + IDENTIFIED BY 'CINDER_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *CINDER_DBPASS* to set the password for the cinder database.** + + ```shell + source ~/.admin-openrc + ``` + + Create the Cinder service credentials: + + ```shell + openstack user create --domain default --password-prompt cinder + openstack role add --project service --user cinder admin + openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 + openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 + ``` + + Create the API endpoints for the block storage service: + + ```shell + openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%\(project_id\)s + ``` + +2. Install the software packages: + + ```shell + yum install openstack-cinder-api openstack-cinder-scheduler (CTL) + ``` + + ```shell + yum install lvm2 device-mapper-persistent-data scsi-target-utils rpcbind nfs-utils \ (STG) + openstack-cinder-volume openstack-cinder-backup + ``` + +3. Prepare the storage devices. The following is an example: + + ```shell + pvcreate /dev/vdb + vgcreate cinder-volumes /dev/vdb + + vim /etc/lvm/lvm.conf + + + devices { + ... + filter = [ "a/vdb/", "r/.*/"] + ``` + + ***Description*** + + In the **devices** section, add filters to allow the **/dev/vdb** devices and reject other devices. + +4. Prepare the NFS: + + ```shell + mkdir -p /root/cinder/backup + + cat << EOF >> /etc/export + /root/cinder/backup 192.168.1.0/24(rw,sync,no_root_squash,no_all_squash) + EOF + + ``` + +5. Configure Cinder: + + ```shell + vim /etc/cinder/cinder.conf + + [DEFAULT] + transport_url = rabbit://openstack:RABBIT_PASS@controller + auth_strategy = keystone + my_ip = 10.0.0.11 + enabled_backends = lvm (STG) + backup_driver=cinder.backup.drivers.nfs.NFSBackupDriver (STG) + backup_share=HOST:PATH (STG) + + [database] + connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = cinder + password = CINDER_PASS + + [oslo_concurrency] + lock_path = /var/lib/cinder/tmp + + [lvm] + volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver (STG) + volume_group = cinder-volumes (STG) + iscsi_protocol = iscsi (STG) + iscsi_helper = tgtadm (STG) + ``` + + ***Description*** + + In the **[database]** section, configure the database entry. + + In the **[DEFAULT]** section, configure the RabbitMQ message queue entry and **my_ip**. + + In the **[DEFAULT]** and **[keystone_authtoken]** sections, configure the identity authentication service entry. + + In the **[oslo_concurrency]** section, configure the lock path. + + ***Note*** + + **Replace *CINDER_DBPASS* with the password of the cinder database.** + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Set *my_ip* to the management IP address of the controller node.** + + **Replace *CINDER_PASS* with the password of the cinder user.** + + **Replace *HOST:PATH* with the host IP address and the shared path of the NFS.** + +6. Synchronize the database: + + ```shell + su -s /bin/sh -c "cinder-manage db sync" cinder (CTL) + ``` + +7. Configure Nova: + + ```shell + vim /etc/nova/nova.conf (CTL) + + [cinder] + os_region_name = RegionOne + ``` + +8. Restart the compute API service: + + ```shell + systemctl restart openstack-nova-api.service + ``` + +9. Start the Cinder service: + + ```shell + systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) + systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) + ``` + + ```shell + systemctl enable rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) + openstack-cinder-volume.service \ + openstack-cinder-backup.service + systemctl start rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) + openstack-cinder-volume.service \ + openstack-cinder-backup.service + ``` + + ***Note*** + + If the Cinder volumes are mounted using tgtadm, modify the **/etc/tgt/tgtd.conf** file as follows to ensure that tgtd can discover the iscsi target of cinder-volume. + + ```shell + include /var/lib/cinder/volumes/* + ``` + +10. Perform the verification: + + ```shell + source ~/.admin-openrc + openstack volume service list + ``` + +### Installing Horizon + +1. Install the software package: + + ```shell + yum install openstack-dashboard + ``` + +2. Modify the file. + + Modify the variables: + + ```text + vim /etc/openstack-dashboard/local_settings + + OPENSTACK_HOST = "controller" + ALLOWED_HOSTS = ['*', ] + + SESSION_ENGINE = 'django.contrib.sessions.backends.cache' + + CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': 'controller:11211', + } + } + + OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST + OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True + OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default" + OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user" + + OPENSTACK_API_VERSIONS = { + "identity": 3, + "image": 2, + "volume": 3, + } + ``` + +3. Restart the httpd service: + + ```shell + systemctl restart httpd.service memcached.service + ``` + +4. Perform the verification. + Open the browser, enter in the address bar, and log in to Horizon. + + ***Note*** + + **Replace *HOSTIP* with the management plane IP address of the controller node.** + +### Installing Tempest + +Tempest is the integrated test service of OpenStack. If you need to run a fully automatic test of the functions of the installed OpenStack environment, you are advised to use Tempest. Otherwise, you can choose not to install it. + +1. Install Tempest: + + ```shell + yum install openstack-tempest + ``` + +2. Initialize the directory: + + ```shell + tempest init mytest + ``` + +3. Modify the configuration file: + + ```shell + cd mytest + vi etc/tempest.conf + ``` + + Configure the current OpenStack environment information in **tempest.conf**. For details, see the [official example](https://docs.openstack.org/tempest/latest/sampleconf.html). + +4. Perform the test: + + ```shell + tempest run + ``` + +5. (Optional) Install the tempest extensions. + The OpenStack services have provided some tempest test packages. You can install these packages to enrich the tempest test content. In Train, extension tests for Cinder, Glance, Keystone, Ironic and Trove are provided. You can run the following command to install and use them: + ``` + yum install python3-cinder-tempest-plugin python3-glance-tempest-plugin python3-ironic-tempest-plugin python3-keystone-tempest-plugin python3-trove-tempest-plugin + ``` + +### Installing Ironic + +Ironic is the bare metal service of OpenStack. If you need to deploy bare metal machines, Ironic is recommended. Otherwise, you can choose not to install it. + +1. Set the database. + + The bare metal service stores information in the database. Create a **ironic** database that can be accessed by the **ironic** user and replace **IRONIC_DBPASSWORD** with a proper password. + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ + IDENTIFIED BY 'IRONIC_DBPASSWORD'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ + IDENTIFIED BY 'IRONIC_DBPASSWORD'; + ``` + +2. Install the software packages. + + ```shell + yum install openstack-ironic-api openstack-ironic-conductor python3-ironicclient + ``` + + Start the services. + + ```shell + systemctl enable openstack-ironic-api openstack-ironic-conductor + systemctl start openstack-ironic-api openstack-ironic-conductor + ``` + +3. Create service user authentication. + + 1. Create the bare metal service user: + + ```shell + openstack user create --password IRONIC_PASSWORD \ + --email ironic@example.com ironic + openstack role add --project service --user ironic admin + openstack service create --name ironic \ + --description "Ironic baremetal provisioning service" baremetal + ``` + + 1. Create the bare metal service access entries: + + ```shell + openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 + openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 + openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 + ``` + +4. Configure the ironic-api service. + + Configuration file path: **/etc/ironic/ironic.conf** + + 1. Use **connection** to configure the location of the database as follows. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. + + ```shell + [database] + + # The SQLAlchemy connection string used to connect to the + # database (string value) + + connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic + ``` + + 1. Configure the ironic-api service to use the RabbitMQ message broker. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. + + ```shell + [DEFAULT] + + # A URL representing the messaging driver to use and its full + # configuration. (string value) + + transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ + ``` + + You can also use json-rpc instead of RabbitMQ. + + 1. Configure the ironic-api service to use the credential of the identity authentication service. Replace **PUBLIC_IDENTITY_IP** with the public IP address of the identity authentication server and **PRIVATE_IDENTITY_IP** with the private IP address of the identity authentication server, replace **IRONIC_PASSWORD** with the password of the **ironic** user in the identity authentication service. + + ```shell + [DEFAULT] + + # Authentication strategy used by ironic-api: one of + # "keystone" or "noauth". "noauth" should not be used in a + # production environment because all authentication will be + # disabled. (string value) + + auth_strategy=keystone + + [keystone_authtoken] + # Authentication type to load (string value) + auth_type=password + # Complete public Identity API endpoint (string value) + www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 + # Complete admin Identity API endpoint. (string value) + auth_url=http://PRIVATE_IDENTITY_IP:5000 + # Service username. (string value) + username=ironic + # Service account password. (string value) + password=IRONIC_PASSWORD + # Service tenant name. (string value) + project_name=service + # Domain name containing project (string value) + project_domain_name=Default + # User's domain name (string value) + user_domain_name=Default + + ``` + + 1. Create the bare metal service database table: + + ```shell + ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema + ``` + + 1. Restart the ironic-api service: + + ```shell + sudo systemctl restart openstack-ironic-api + ``` + +5. Configure the ironic-conductor service. + + 1. Replace **HOST_IP** with the IP address of the conductor host. + + ```shell + [DEFAULT] + + # IP address of this host. If unset, will determine the IP + # programmatically. If unable to do so, will use "127.0.0.1". + # (string value) + + my_ip=HOST_IP + ``` + + 1. Specifies the location of the database. ironic-conductor must use the same configuration as ironic-api. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. + + ```shell + [database] + + # The SQLAlchemy connection string to use to connect to the + # database. (string value) + + connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic + ``` + + 1. Configure the ironic-api service to use the RabbitMQ message broker. ironic-conductor must use the same configuration as ironic-api. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. + + ```shell + [DEFAULT] + + # A URL representing the messaging driver to use and its full + # configuration. (string value) + + transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ + ``` + + You can also use json-rpc instead of RabbitMQ. + + 1. Configure the credentials to access other OpenStack services. + + To communicate with other OpenStack services, the bare metal service needs to use the service users to get authenticated by the OpenStack Identity service when requesting other services. The credentials of these users must be configured in each configuration file associated to the corresponding service. + + ```shell + [neutron] - Accessing the OpenStack network services. + [glance] - Accessing the OpenStack image service. + [swift] - Accessing the OpenStack object storage service. + [cinder] - Accessing the OpenStack block storage service. + [inspector] Accessing the OpenStack bare metal introspection service. + [service_catalog] - A special item to store the credential used by the bare metal service. The credential is used to discover the API URL endpoint registered in the OpenStack identity authentication service catalog by the bare metal service. + ``` + + For simplicity, you can use one service user for all services. For backward compatibility, the user name must be the same as that configured in [keystone_authtoken] of the ironic-api service. However, this is not mandatory. You can also create and configure a different service user for each service. + + In the following example, the authentication information for the user to access the OpenStack network service is configured as follows: + + ```shell + The network service is deployed in the identity authentication service domain named RegionOne. Only the public endpoint interface is registered in the service catalog. + + A specific CA SSL certificate is used for HTTPS connection when sending a request. + + The same service user as that configured for ironic-api. + + The dynamic password authentication plugin discovers a proper identity authentication service API version based on other options. + ``` + + ```shell + [neutron] + + # Authentication type to load (string value) + auth_type = password + # Authentication URL (string value) + auth_url=https://IDENTITY_IP:5000/ + # Username (string value) + username=ironic + # User's password (string value) + password=IRONIC_PASSWORD + # Project name to scope to (string value) + project_name=service + # Domain ID containing project (string value) + project_domain_id=default + # User's domain id (string value) + user_domain_id=default + # PEM encoded Certificate Authority to use when verifying + # HTTPs connections. (string value) + cafile=/opt/stack/data/ca-bundle.pem + # The default region_name for endpoint URL discovery. (string + # value) + region_name = RegionOne + # List of interfaces, in order of preference, for endpoint + # URL. (list value) + valid_interfaces=public + ``` + + By default, to communicate with other services, the bare metal service attempts to discover a proper endpoint of the service through the service catalog of the identity authentication service. If you want to use a different endpoint for a specific service, specify the endpoint_override option in the bare metal service configuration file. + + ```shell + [neutron] ... endpoint_override = + ``` + + 1. Configure the allowed drivers and hardware types. + + Set enabled_hardware_types to specify the hardware types that can be used by ironic-conductor: + + ```shell + [DEFAULT] enabled_hardware_types = ipmi + ``` + + Configure hardware interfaces: + + ```shell + enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool + ``` + + Configure the default value of the interface: + + ```shell + [DEFAULT] default_deploy_interface = direct default_network_interface = neutron + ``` + + If any driver that uses Direct Deploy is enabled, you must install and configure the Swift backend of the image service. The Ceph object gateway (RADOS gateway) can also be used as the backend of the image service. + + 1. Restart the ironic-conductor service: + + ```shell + sudo systemctl restart openstack-ironic-conductor + ``` + +6. Configure the httpd service. + + 1. Create the root directory of the httpd used by Ironic, and set the owner and owner group. The directory path must be the same as the path specified by the **http_root** configuration item in the **[deploy]** group in **/etc/ironic/ironic.conf**. + + ``` + mkdir -p /var/lib/ironic/httproot ``chown ironic.ironic /var/lib/ironic/httproot + ``` + + 2. Install and configure the httpd Service. + + 1. Install the httpd service. If the httpd service is already installed, skip this step. + + ``` + yum install httpd -y + ``` + 2. Create the **/etc/httpd/conf.d/openstack-ironic-httpd.conf** file. The file content is as follows: + + ``` + Listen 8080 + + + ServerName ironic.openeuler.com + + ErrorLog "/var/log/httpd/openstack-ironic-httpd-error_log" + CustomLog "/var/log/httpd/openstack-ironic-httpd-access_log" "%h %l %u %t \"%r\" %>s %b" + + DocumentRoot "/var/lib/ironic/httproot" + + Options Indexes FollowSymLinks + Require all granted + + LogLevel warn + AddDefaultCharset UTF-8 + EnableSendfile on + + + ``` + + The listening port must be the same as the port specified by **http_url** in the **[deploy]** section of **/etc/ironic/ironic.conf**. + + 3. Restart the httpd service: + + ``` + systemctl restart httpd + ``` + + + +8. Create the deploy ramdisk image. + + The ramdisk image of Train can be created using the ironic-python-agent service or disk-image-builder tool. You can also use the latest ironic-python-agent-builder provided by the community. You can also use other tools. + To use the Train native tool, you need to install the corresponding software package. + + ```shell + yum install openstack-ironic-python-agent + or + yum install diskimage-builder + ``` + + For details, see the [official document](https://docs.openstack.org/ironic/queens/install/deploy-ramdisk.html). + + The following describes how to use the ironic-python-agent-builder to build the deploy image used by ironic. + + 1. Install ironic-python-agent-builder. + + 1. Install the tool: + + ```shell + pip install ironic-python-agent-builder + ``` + + 2. Modify the python interpreter in the following files: + + ```shell + /usr/bin/yum /usr/libexec/urlgrabber-ext-down + ``` + + 3. Install the other necessary tools: + + ```shell + yum install git + ``` + + **DIB** depends on the `semanage` command. Therefore, check whether the `semanage --help` command is available before creating an image. If the system displays a message indicating that the command is unavailable, install the command: + + ```shell + # Check which package needs to be installed. + [root@localhost ~]# yum provides /usr/sbin/semanage + Loaded plug-in: fastestmirror + Loading mirror speeds from cached hostfile + * base: mirror.vcu.edu + * extras: mirror.vcu.edu + * updates: mirror.math.princeton.edu + policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities + Source: base + Matching source: + File name: /usr/sbin/semanage + # Install. + [root@localhost ~]# yum install policycoreutils-python + ``` + + 2. Create the image. + + For Arm architecture, add the following information: + ```shell + export ARCH=aarch64 + ``` + + Basic usage: + + ```shell + usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] + [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] + distribution + + positional arguments: + distribution Distribution to use + + optional arguments: + -h, --help show this help message and exit + -r RELEASE, --release RELEASE + Distribution release to use + -o OUTPUT, --output OUTPUT + Output base file name + -e ELEMENT, --element ELEMENT + Additional DIB element to use + -b BRANCH, --branch BRANCH + If set, override the branch that is used for ironic- + python-agent and requirements + -v, --verbose Enable verbose logging in diskimage-builder + --extra-args EXTRA_ARGS + Extra arguments to pass to diskimage-builder + ``` + + Example: + + ```shell + ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky + ``` + + 3. Allow SSH login. + + Initialize the environment variables and create the image: + + ```shell + export DIB_DEV_USER_USERNAME=ipa \ + export DIB_DEV_USER_PWDLESS_SUDO=yes \ + export DIB_DEV_USER_PASSWORD='123' + ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser + ``` + + 4. Specify the code repository. + + Initialize the corresponding environment variables and create the image: + + ```shell + # Specify the address and version of the repository. + DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git + DIB_REPOREF_ironic_python_agent=origin/develop + + # Clone code from Gerrit. + DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent + DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 + ``` + + Reference: [source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html). + + The specified repository address and version are verified successfully. + + 5. Note + +The template of the PXE configuration file of the native OpenStack does not support the ARM64 architecture. You need to modify the native OpenStack code. + +In Train, Ironic provided by the community does not support the boot from ARM 64-bit UEFI PXE. As a result, the format of the generated grub.cfg file (generally in /tftpboot/) is incorrect, causing the PXE boot failure. + +You need to modify the code logic for generating the grub.cfg file. + +The following TLS error is reported when Ironic sends a request to IPA to query the command execution status: + +By default, both IPA and Ironic of Train have TLS authentication enabled to send requests to each other. Disable TLS authentication according to the description on the official website. + +1. Add **ipa-insecure=1** to the following configuration in the Ironic configuration file (**/etc/ironic/ironic.conf**): + +``` +[agent] +verify_ca = False + +[pxe] +pxe_append_params = nofb nomodeset vga=normal coreos.autologin ipa-insecure=1 +``` + +2. Add the IPA configuration file **/etc/ironic_python_agent/ironic_python_agent.conf** to the ramdisk image and configure the TLS as follows: + +**/etc/ironic_python_agent/ironic_python_agent.conf** (The **/etc/ironic_python_agent** directory must be created in advance.) + +``` +[DEFAULT] +enable_auto_tls = False +``` + +Set the permission: + +``` +chown -R ipa.ipa /etc/ironic_python_agent/ +``` + +3. Modify the startup file of the IPA service and add the configuration file option. + + vim usr/lib/systemd/system/ironic-python-agent.service + + ``` + [Unit] + Description=Ironic Python Agent + After=network-online.target + + [Service] + ExecStartPre=/sbin/modprobe vfat + ExecStart=/usr/local/bin/ironic-python-agent --config-file /etc/ironic_python_agent/ironic_python_agent.conf + Restart=always + RestartSec=30s + + [Install] + WantedBy=multi-user.target + ``` + + +Other services such as ironic-inspector are also provided for OpenStack Train. Install the services based on site requirements. + +### Installing Kolla + +Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. + +The installation of Kolla is simple. You only need to install the corresponding RPM packages: + +``` +yum install openstack-kolla openstack-kolla-ansible +``` + +After the installation is complete, you can run commands such as `kolla-ansible`, `kolla-build`, `kolla-genpwd`, `kolla-mergepwd` to create an image or deploy a container environment. + +### Installing Trove +Trove is the database service of OpenStack. If you need to use the database service provided by OpenStack, Trove is recommended. Otherwise, you can choose not to install it. + +1. Set the database. + + The database service stores information in the database. Create a **trove** database that can be accessed by the **trove** user and replace **TROVE_DBPASSWORD** with a proper password. + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE trove CHARACTER SET utf8; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'localhost' \ + IDENTIFIED BY 'TROVE_DBPASSWORD'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'%' \ + IDENTIFIED BY 'TROVE_DBPASSWORD'; + ``` + +2. Create service user authentication. + + 1. Create the **Trove** service user. + + ```shell + openstack user create --domain default --password-prompt trove + openstack role add --project service --user trove admin + openstack service create --name trove --description "Database" database + ``` + **Description:** Replace *TROVE_PASSWORD* with the password of the **trove** user. + + 1. Create the **Database** service access entry + + ```shell + openstack endpoint create --region RegionOne database public http://controller:8779/v1.0/%\(tenant_id\)s + openstack endpoint create --region RegionOne database internal http://controller:8779/v1.0/%\(tenant_id\)s + openstack endpoint create --region RegionOne database admin http://controller:8779/v1.0/%\(tenant_id\)s + ``` + +3. Install and configure the **Trove** components. + + 1. Install the **Trove** package: + ```shell script + yum install openstack-trove python3-troveclient + ``` + + 2. Configure **trove.conf**: + ```shell script + vim /etc/trove/trove.conf + + [DEFAULT] + log_dir = /var/log/trove + trove_auth_url = http://controller:5000/ + nova_compute_url = http://controller:8774/v2 + cinder_url = http://controller:8776/v1 + swift_url = http://controller:8080/v1/AUTH_ + rpc_backend = rabbit + transport_url = rabbit://openstack:RABBIT_PASS@controller:5672 + auth_strategy = keystone + add_addresses = True + api_paste_config = /etc/trove/api-paste.ini + nova_proxy_admin_user = admin + nova_proxy_admin_pass = ADMIN_PASSWORD + nova_proxy_admin_tenant_name = service + taskmanager_manager = trove.taskmanager.manager.Manager + use_nova_server_config_drive = True + # Set these if using Neutron Networking + network_driver = trove.network.neutron.NeutronDriver + network_label_regex = .* + + [database] + connection = mysql+pymysql://trove:TROVE_DBPASSWORD@controller/trove + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000/ + auth_url = http://controller:5000/ + auth_type = password + project_domain_name = default + user_domain_name = default + project_name = service + username = trove + password = TROVE_PASSWORD + ``` + **Description:** + - In the **[Default]** section, **nova_compute_url** and **cinder_url** are endpoints created by Nova and Cinder in Keystone. + - **nova_proxy_XXX** is a user who can access the Nova service. In the preceding example, the **admin** user is used. + - **transport_url** is the **RabbitMQ** connection information, and **RABBIT_PASS** is the RabbitMQ password. + - In the **[database]** section, **connection** is the information of the database created for Trove in MySQL. + - Replace **TROVE_PASSWORD** in the Trove user information with the password of the **trove** user. + + 3. Configure **trove-guestagent.conf**: + ```shell script + vim /etc/trove/trove-guestagent.conf + + rabbit_host = controller + rabbit_password = RABBIT_PASS + trove_auth_url = http://controller:5000/ + ``` + **Description:** **guestagent** is an independent component in Trove and needs to be pre-built into the virtual machine image created by Trove using Nova. + After the database instance is created, the guestagent process is started to report heartbeat messages to the Trove through the message queue (RabbitMQ). + Therefore, you need to configure the user name and password of the RabbitMQ. + **Since Victoria, Trove uses a unified image to run different types of databases. The database service runs in the Docker container of the Guest VM.** + - Replace **RABBIT_PASS** with the RabbitMQ password. + + 4. Generate the **Trove** database table. + ```shell script + su -s /bin/sh -c "trove-manage db_sync" trove + ``` + +4. Complete the installation and configuration. + 1. Configure the **Trove** service to automatically start: + ```shell script + systemctl enable openstack-trove-api.service \ + openstack-trove-taskmanager.service \ + openstack-trove-conductor.service + ``` + 2. Start the services: + ```shell script + systemctl start openstack-trove-api.service \ + openstack-trove-taskmanager.service \ + openstack-trove-conductor.service + ``` +### Installing Swift + +Swift provides a scalable and highly available distributed object storage service, which is suitable for storing unstructured data in large scale. + +1. Create the service credentials and API endpoints. + + Create the service credential: + + ``` shell + # Create the swift user. + openstack user create --domain default --password-prompt swift + # Add the admin role for the swift user. + openstack role add --project service --user swift admin + # Create the swift service entity. + openstack service create --name swift --description "OpenStack Object Storage" object-store + ``` + + Create the Swift API endpoints. + + ```shell + openstack endpoint create --region RegionOne object-store public http://controller:8080/v1/AUTH_%\(project_id\)s + openstack endpoint create --region RegionOne object-store internal http://controller:8080/v1/AUTH_%\(project_id\)s + openstack endpoint create --region RegionOne object-store admin http://controller:8080/v1 + ``` + + +2. Install the software packages: + + ```shell + yum install openstack-swift-proxy python3-swiftclient python3-keystoneclient python3-keystonemiddleware memcached (CTL) + ``` + +3. Configure the proxy-server. + + The Swift RPM package contains a **proxy-server.conf** file which is basically ready to use. You only need to change the values of **ip** and swift **password** in the file. + + ***Note*** + + **Replace password with the password you set for the swift user in the identity service.** + +4. Install and configure the storage node. (STG) + + Install the supported program packages: + ```shell + yum install xfsprogs rsync + ``` + + Format the /dev/vdb and /dev/vdc devices into XFS: + + ```shell + mkfs.xfs /dev/vdb + mkfs.xfs /dev/vdc + ``` + + Create the mount point directory structure: + + ```shell + mkdir -p /srv/node/vdb + mkdir -p /srv/node/vdc + ``` + + Find the UUID of the new partition: + + ```shell + blkid + ``` + + Add the following to the **/etc/fstab** file: + + ```shell + UUID="" /srv/node/vdb xfs noatime 0 2 + UUID="" /srv/node/vdc xfs noatime 0 2 + ``` + + Mount the devices: + + ```shell + mount /srv/node/vdb + mount /srv/node/vdc + ``` + ***Note*** + + **If the disaster recovery function is not required, you only need to create one device and skip the following rsync configuration.** + + (Optional) Create or edit the **/etc/rsyncd.conf** file to include the following content: + + ```shell + [DEFAULT] + uid = swift + gid = swift + log file = /var/log/rsyncd.log + pid file = /var/run/rsyncd.pid + address = MANAGEMENT_INTERFACE_IP_ADDRESS + + [account] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/account.lock + + [container] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/container.lock + + [object] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/object.lock + ``` + **Replace *MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node.** + + Start the rsyncd service and configure it to start upon system startup. + + ```shell + systemctl enable rsyncd.service + systemctl start rsyncd.service + ``` + +5. Install and configure the components on storage nodes. (STG) + + Install the software packages: + + ```shell + yum install openstack-swift-account openstack-swift-container openstack-swift-object + ``` + + Edit **account-server.conf**, **container-server.conf**, and **object-server.conf** in the **/etc/swift directory** and replace **bind_ip** with the management network IP address of the storage node. + + Ensure the proper ownership of the mount point directory structure. + + ```shell + chown -R swift:swift /srv/node + ``` + + Create the recon directory and ensure that it has the correct ownership. + + ```shell + mkdir -p /var/cache/swift + chown -R root:swift /var/cache/swift + chmod -R 775 /var/cache/swift + ``` + +6. Create the account ring. (CTL) + + Switch to the **/etc/swift** directory: + + ```shell + cd /etc/swift + ``` + + Create the basic **account.builder** file: + + ```shell + swift-ring-builder account.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder account.builder add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6202 --device DEVICE_NAME --weight DEVICE_WEIGHT + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to each storage device on each storage node.** + + Verify the ring contents: + + ```shell + swift-ring-builder account.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder account.builder rebalance + ``` + +7. Create the container ring. (CTL) + + Switch to the **/etc/swift** directory: + + Create the basic **container.builder** file: + + ```shell + swift-ring-builder container.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder container.builder \ + add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6201 \ + --device DEVICE_NAME --weight 100 + + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to every storage devices on every storage nodes.** + + Verify the ring contents: + + ```shell + swift-ring-builder container.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder container.builder rebalance + ``` + +8. Create the object ring. (CTL) + + Switch to the **/etc/swift** directory: + + Create the basic **object.builder** file: + + ```shell + swift-ring-builder object.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder object.builder \ + add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6200 \ + --device DEVICE_NAME --weight 100 + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to every storage devices on every storage nodes.** + + Verify the ring contents: + + ```shell + swift-ring-builder object.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder object.builder rebalance + ``` + + Distribute ring configuration files: + + Copy **account.ring.gz**, **container.ring.gz**, and **object.ring.gz** to the **/etc/swift** directory on each storage node and any additional nodes running the proxy service. + + + +9. Complete the installation. + + Edit the **/etc/swift/swift.conf** file: + + ``` shell + [swift-hash] + swift_hash_path_suffix = test-hash + swift_hash_path_prefix = test-hash + + [storage-policy:0] + name = Policy-0 + default = yes + ``` + + **Replace test-hash with a unique value.** + + Copy the **swift.conf** file to the **/etc/swift** directory on each storage node and any additional nodes running the proxy service. + + Ensure correct ownership of the configuration directory on all nodes: + + ```shell + chown -R root:swift /etc/swift + ``` + + On the controller node and any additional nodes running the proxy service, start the object storage proxy service and its dependencies, and configure them to start upon system startup. + + ```shell + systemctl enable openstack-swift-proxy.service memcached.service + systemctl start openstack-swift-proxy.service memcached.service + ``` + + On the storage node, start the object storage services and configure them to start upon system startup. + + ```shell + systemctl enable openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service + + systemctl start openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service + + systemctl enable openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service + + systemctl start openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service + + systemctl enable openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service + + systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service + ``` +### Installing Cyborg + +Cyborg provides acceleration device support for OpenStack, for example, GPUs, FPGAs, ASICs, NPs, SoCs, NVMe/NOF SSDs, ODPs, DPDKs, and SPDKs. + +1. Initialize the databases. + +``` +CREATE DATABASE cyborg; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +$ openstack user create --domain default --password-prompt cyborg +$ openstack role add --project service --user cyborg admin +$ openstack service create --name cyborg --description "Acceleration Service" accelerator + +$ openstack endpoint create --region RegionOne \ + accelerator public http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator internal http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator admin http://:6666/v1 +``` + +3. Install Cyborg + +``` +yum install openstack-cyborg +``` + +4. Configure Cyborg + +Modify **/etc/cyborg/cyborg.conf**. + +``` +[DEFAULT] +transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ +use_syslog = False +state_path = /var/lib/cyborg +debug = True + +[database] +connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg + +[service_catalog] +project_domain_id = default +user_domain_id = default +project_name = service +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[placement] +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = placement +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[keystone_authtoken] +memcached_servers = localhost:11211 +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password +``` + +Set the user names, passwords, and IP addresses as required. + +1. Synchronize the database table. + +``` +cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade +``` + +6. Start the Cyborg services. + +``` +systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +``` + +### Installing Aodh + +1. Create the database. + +``` +CREATE DATABASE aodh; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt aodh + +openstack role add --project service --user aodh admin + +openstack service create --name aodh --description "Telemetry" alarming + +openstack endpoint create --region RegionOne alarming public http://controller:8042 + +openstack endpoint create --region RegionOne alarming internal http://controller:8042 + +openstack endpoint create --region RegionOne alarming admin http://controller:8042 +``` + +3. Install Aodh. + +``` +yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient +``` + +4. Modify the configuration file. + +``` +[database] +connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh + +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +auth_strategy = keystone + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +aodh-dbsync +``` + +6. Start the Aodh services. + +``` +systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service + +systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service +``` + +### Installing Gnocchi + +1. Create the database. + +``` +CREATE DATABASE gnocchi; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt gnocchi + +openstack role add --project service --user gnocchi admin + +openstack service create --name gnocchi --description "Metric Service" metric + +openstack endpoint create --region RegionOne metric public http://controller:8041 + +openstack endpoint create --region RegionOne metric internal http://controller:8041 + +openstack endpoint create --region RegionOne metric admin http://controller:8041 +``` + +3. Install Gnocchi. + +``` +yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient +``` + +1. Modify the **/etc/gnocchi/gnocchi.conf** configuration file. + +``` +[api] +auth_mode = keystone +port = 8041 +uwsgi_mode = http-socket + +[keystone_authtoken] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_name = Default +user_domain_name = Default +project_name = service +username = gnocchi +password = GNOCCHI_PASS +interface = internalURL +region_name = RegionOne + +[indexer] +url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi + +[storage] +# coordination_url is not required but specifying one will improve +# performance with better workload division across workers. +coordination_url = redis://controller:6379 +file_basepath = /var/lib/gnocchi +driver = file +``` + +5. Initialize the database. + +``` +gnocchi-upgrade +``` + +6. Start the Gnocchi services. + +``` +systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service + +systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service +``` + +### Installing Ceilometer + +1. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt ceilometer + +openstack role add --project service --user ceilometer admin + +openstack service create --name ceilometer --description "Telemetry" metering +``` + +2. Install Ceilometer. + +``` +yum install openstack-ceilometer-notification openstack-ceilometer-central +``` + +1. Modify the **/etc/ceilometer/pipeline.yaml** configuration file. + +``` +publishers: + # set address of Gnocchi + # + filter out Gnocchi-related activity meters (Swift driver) + # + set default archive policy + - gnocchi://?filter_project=service&archive_policy=low +``` + +4. Modify the **/etc/ceilometer/ceilometer.conf** configuration file. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = ceilometer +password = CEILOMETER_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +ceilometer-upgrade +``` + +6. Start the Ceilometer services. + +``` +systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service + +systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service +``` + +### Installing Heat + +1. Creat the **heat** database and grant proper privileges to it. Replace **HEAT_DBPASS** with a proper password. + +``` +CREATE DATABASE heat; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; +``` + +2. Create a service credential. Create the **heat** user and add the **admin** role to it. + +``` +openstack user create --domain default --password-prompt heat +openstack role add --project service --user heat admin +``` + +3. Create the **heat** and **heat-cfn** services and their API enpoints. + +``` +openstack service create --name heat --description "Orchestration" orchestration +openstack service create --name heat-cfn --description "Orchestration" cloudformation +openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 +``` + +4. Create additional OpenStack management information, including the **heat** domain and its administrator **heat_domain_admin**, the **heat_stack_owner** role, and the **heat_stack_user** role. + +``` +openstack user create --domain heat --password-prompt heat_domain_admin +openstack role add --domain heat --user-domain heat --user heat_domain_admin admin +openstack role create heat_stack_owner +openstack role create heat_stack_user +``` + +5. Install the software packages. + +``` +yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine +``` + +6. Modify the configuration file **/etc/heat/heat.conf**. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +heat_metadata_server_url = http://controller:8000 +heat_waitcondition_server_url = http://controller:8000/v1/waitcondition +stack_domain_admin = heat_domain_admin +stack_domain_admin_password = HEAT_DOMAIN_PASS +stack_user_domain_name = heat + +[database] +connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_name = default +user_domain_name = default +project_name = service +username = heat +password = HEAT_PASS + +[trustee] +auth_type = password +auth_url = http://controller:5000 +username = heat +password = HEAT_PASS +user_domain_name = default + +[clients_keystone] +auth_uri = http://controller:5000 +``` + +7. Initialize the **heat** database table. + +``` +su -s /bin/sh -c "heat-manage db_sync" heat +``` + +8. Start the services. + +``` +systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +``` + +## OpenStack Quick Installation + +The OpenStack SIG provides the Ansible script for one-click deployment of OpenStack in All in One or Distributed modes. Users can use the script to quickly deploy an OpenStack environment based on openEuler RPM packages. The following uses the All in One mode installation as an example. + +1. Install the OpenStack SIG Tool. + + ```shell + pip install openstack-sig-tool + ``` + +2. Configure the OpenStack Yum source. + + ```shell + yum install openstack-release-train + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + +3. Update the Ansible configurations. + + Open the **/usr/local/etc/inventory/all_in_one.yaml** file and modify the configuration based on the environment and requirements. Modify the file as follows: + + ```shell + all: + hosts: + controller: + ansible_host: + ansible_ssh_private_key_file: + ansible_ssh_user: root + vars: + mysql_root_password: root + mysql_project_password: root + rabbitmq_password: root + project_identity_password: root + enabled_service: + - keystone + - neutron + - cinder + - placement + - nova + - glance + - horizon + - aodh + - ceilometer + - cyborg + - gnocchi + - kolla + - heat + - swift + - trove + - tempest + neutron_provider_interface_name: br-ex + default_ext_subnet_range: 10.100.100.0/24 + default_ext_subnet_gateway: 10.100.100.1 + neutron_dataplane_interface_name: eth1 + cinder_block_device: vdb + swift_storage_devices: + - vdc + swift_hash_path_suffix: ash + swift_hash_path_prefix: has + children: + compute: + hosts: controller + storage: + hosts: controller + network: + hosts: controller + vars: + test-key: test-value + dashboard: + hosts: controller + vars: + allowed_host: '*' + kolla: + hosts: controller + vars: + # We add openEuler OS support for kolla in OpenStack Queens/Rocky release + # Set this var to true if you want to use it in Q/R + openeuler_plugin: false + ``` + + Key Configurations + + | Item | Description| + |---|---| + | ansible_host | IP address of the all-in-one node.| + | ansible_ssh_private_key_file | Key used by the Ansible script for logging in to the all-in-one node.| + | ansible_ssh_user | User used by the Ansible script for logging in to the all-in-one node.| + | enabled_service | List of services to be installed. You can delete services as required.| + | neutron_provider_interface_name | Neutron L3 bridge name. | + | default_ext_subnet_range | Neutron private network IP address range. | + | default_ext_subnet_gateway | Neutron private network gateway. | + | neutron_dataplane_interface_name | NIC used by Neutron. You are advised to use a new NIC to avoid conflicts with existing NICs causing disconnection of the all-in-one node. | + | cinder_block_device | Name of the block device used by Cinder.| + | swift_storage_devices | Name of the block device used by Swift. | + +4. Run the installation command. + + ```shell + oos env setup all_in_one + ``` + + After the command is executed, the OpenStack environment of the All in One mode is successfully deployed. + + The environment variable file **.admin-openrc** is stored in the home directory of the current user. + +5. Initialize the Tempest environment. + + If you want to perform the Tempest test in the environment, run the `oos env init all_in_one` command to create the OpenStack resources required by Tempest. + + After the command is executed successfully, a **mytest** directory is generated in the home directory of the user. You can run the `tempest run` command in the directory. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-victoria.md b/docs/en/docs/thirdparty_migration/OpenStack-victoria.md deleted file mode 100644 index 28e921a4c..000000000 --- a/docs/en/docs/thirdparty_migration/OpenStack-victoria.md +++ /dev/null @@ -1,1832 +0,0 @@ -# OpenStack Victoria Deployment Guide - -## OpenStack - -OpenStack is an open source cloud computing infrastructure software project developed by the community. It provides an operating platform or tool set for deploying the cloud, offering scalable and flexible cloud computing for organizations. - -As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. - -The official Yum source of openEuler 21.09 supports the Openstack Victoria version. You can configure the official Yum source and then deploy OpenStack by following the instructions of this document. - -## Preparing the Environment -### Environment Configuration - -Add controller in the `/etc/hosts` file, for example, for node IP `10.0.0.11`, add the following information: - -```shell -10.0.0.11 controller -``` - -### Installing the SQL Database - -1. Run the following command to install the software package: - - ```plain - # yum install mariadb mariadb-server python-PyMySQL - ``` - -2. Run the following command to create and edit the `/etc/my.cnf.d/openstack.cnf` file: - - ``` - vim /etc/my.cnf.d/openstack.cnf - ``` - - Copy the following content to the file (set **bind-address** to the management IP address of the controller node): - - ``` - [mysqld] - bind-address = 10.0.0.11 - default-storage-engine = innodb - innodb_file_per_table = on - max_connections = 4096 - collation-server = utf8_general_ci - character-set-server = utf8 - ``` - -3. Run the following command to start the database service and enable it to automatically start upon system boot: - - ``` - # systemctl enable mariadb.service - # systemctl start mariadb.service - ``` - -### Installing RabbitMQ - -1. Run the following command to install the software package: - - ``` - #yum install rabbitmq-server - ``` - -2. Start the RabbitMQ service and enable it to automatically start upon system boot. - - ``` - #systemctl enable rabbitmq-server.service - #systemctl start rabbitmq-server.service - ``` - -3. Add an OpenStack user. - - ``` - #rabbitmqctl add_user openstack RABBIT_PASS - ``` - -4. Replace **RABBIT\_PASS** with the password of the OpenStack user. - -5. Run the following command to set the permission of the **openstack** user so that the user can perform configuration, write, and read operations: - - ``` - #rabbitmqctl set_permissions openstack ".*" ".*" ".*" - ``` - -### Installing Memcached - -1. Run the following command to install the target software package: - - ``` - #yum install memcached python3-memcached - ``` - -2. Run the following command to edit the `/etc/sysconfig/memcached` file: - - ``` - #vim /etc/sysconfig/memcached - OPTIONS="-l 127.0.0.1,::1,controller" - ``` - - Change the value of **OPTIONS** to the actual management IP address of the controller node. - -3. Run the following command to start the Memcached service and enable it to automatically start upon system boot: - - ``` - # systemctl enable memcached.service - # systemctl start memcached.service - ``` - -## Installing OpenStack - -### Installing Keystone - -1. Log in to the database as the **root** user. Create the **keystone** database, and grant permissions to the user. - - ``` - # mysql -u root -p - MariaDB [(none)]> CREATE DATABASE keystone; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **KEYSTONE\_DBPASS** with the password of the **keystone** database. - -2. Run the following command to install the software package: - - ``` - #yum install openstack-keystone httpd mod_wsgi - ``` - -3. Edit the `/etc/keystone/keystone.conf` file to configure the **keystone** database. In the **\[database]** section, configure the database entry. In the **\[token]** section, configure the token provider. - - ``` - # vim /etc/keystone/keystone.conf - [database] - connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone - [token] - provider = fernet - ``` - - Replace **KEYSTONE\_DBPASS** with the password of the **keystone** database. - -4. Run the following command to synchronize the database. - - ``` - su -s /bin/sh -c "keystone-manage db_sync" keystone - ``` - -5. Run the following command to initialize the Fernet keystore: - - ``` - # keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone - # keystone-manage credential_setup --keystone-user keystone --keystone-group keystone - ``` - -6. Run the following commands to enable the identity service: - - ``` - # keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ - --bootstrap-admin-url http://controller:5000/v3/ \ - --bootstrap-internal-url http://controller:5000/v3/ \ - --bootstrap-public-url http://controller:5000/v3/ \ - --bootstrap-region-id RegionOne - ``` - - Replace **ADMIN\_PASS** with the password of the **admin** user. - -7. Edit the `/etc/httpd/conf/httpd.conf` file and configure the Apache HTTP server. - - ``` - #vim /etc/httpd/conf/httpd.conf - ``` - - Enable **ServerName** to reference the controller node: - - ``` - ServerName controller - ``` - - If **ServerName** does not exist, create it. - -8. Run the following command to create a link for the `/usr/share/keystone/wsgi-keystone.conf` file: - - ``` - #ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ - - #vim /etc/httpd/conf.d/wsgi-keystone.conf - ``` - -9. After the installation is complete, run the following command to start the Apache HTTP service: - - ``` - # systemctl enable httpd.service - # systemctl start httpd.service - ``` - -10. Run the following command to set environment variables: - - ``` - $ export OS_USERNAME=admin - $ export OS_PASSWORD=ADMIN_PASS - $ export OS_PROJECT_NAME=admin - $ export OS_USER_DOMAIN_NAME=Default - $ export OS_PROJECT_DOMAIN_NAME=Default - $ export OS_AUTH_URL=http://controller:5000/v3 - $ export OS_IDENTITY_API_VERSION=3 - ``` - - Replace **ADMIN\_PASS** with the password set in the **keystone-manage bootstrap** command. - -11. Run the following commands to create the domain, project, user, and role: - - Create a domain named **example**. - - ``` - $ openstack domain create --description "An Example Domain" example - ``` - - Note: The domain **default** has been created in **keystone-manage bootstrap**. - - Create a project named **service**. - - ``` - $ openstack project create --domain default --description "Service Project" service - ``` - - Create a non-admin project named **myproject**, a user named **myuser**, and a role named **myrole**. Add the **myrole** role to **myproject** and **myuser**. - - ``` - $ openstack project create --domain default --description "Demo Project" myproject - $ openstack user create --domain default --password-prompt myuser - $ openstack role create myrole - $ openstack role add --project myproject --user myuser myrole - ``` - -12. Perform the verification. - - Cancel the temporary environment variables **OS\_AUTH\_URL** and **OS\_PASSWORD**. - - ``` - $ unset OS_AUTH_URL OS_PASSWORD - ``` - - Request a token for the **admin** user: - - ``` - $ openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name admin --os-username admin token issue - ``` - - Request a token for the **myuser** user: - - ``` - $ openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name myproject --os-username myuser token issue - ``` - -13. Create the environment script for the OpenStack client. - - Create environment variable scripts for the **admin** and **demo** users. - - ``` - # vim admin-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=admin - export OS_USERNAME=admin - export OS_PASSWORD=ADMIN_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - # - ``` - - ``` - # vim demo-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=myproject - export OS_USERNAME=myuser - export OS_PASSWORD=DEMO_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - ``` - - Replace **ADMIN\_PASS** with the password of the **admin** user. - - Replace **DEMO\_PASS** with the password of the **myuser** user. - - Run the following script to load environment variables: - - ``` - $ source admin-openrc - ``` - -### Installing Glance - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Log in to the database as the **root** user. Create the **glance** database, and grant permissions to the database. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE glance; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **GLANCE\_DBPASS** with the password of the **glance** database. - - ``` - $ source admin-openrc - ``` - - Run the following commands to create the **glance** service credential, create the **glance** user, and add the **admin** role to the **glance** user: - - ``` - $ openstack user create --domain default --password-prompt glance - $ openstack role add --project service --user glance admin - $ openstack service create --name glance --description "OpenStack Image" image - ``` - - Create API endpoints for the image service. - - ``` - $ openstack endpoint create --region RegionOne image public http://controller:9292 - $ openstack endpoint create --region RegionOne image internal http://controller:9292 - $ openstack endpoint create --region RegionOne image admin http://controller:9292 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - #yum install openstack-glance openstack-glance-api - ``` - - Configure Glance: - - Edit the **/etc/glance/glance-api.conf** file: - - In the **\[database]** section, configure the database entry. - - In the **\[keystone\_authtoken]** and **\[paste\_deploy]** sections, configure the identity authentication service entry. - - In the **\[glance\_store]** section, configure the local file system storage and the location where image files are stored. - - ``` - # vim /etc/glance/glance-api.conf - [database] - # ... - connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = glance - password = GLANCE_PASS - [paste_deploy] - # ... - flavor = keystone - [glance_store] - # ... - stores = file,http - default_store = file - filesystem_store_datadir = /var/lib/glance/images/ - ``` - - In the preceding command, replace **GLANCE\_DBPASS** with the password of the **glance** database, and replace **GLANCE\_PASS** with the password of the **glance** user. - - Synchronize the database: - - ``` - su -s /bin/sh -c "glance-manage db_sync" glance - ``` - - Run the following command to start the image service: - - ``` - # systemctl enable openstack-glance-api.service - # systemctl start openstack-glance-api.service - ``` - -3. Perform the verification. - - Download the image. - - ``` - $ source admin-openrc - # Note: If the Kunpeng architecture is used in your environment, download the ARM64 image. - $ wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img - ``` - - Upload the image to the image service. - - ``` - $ glance image-create --name "cirros" --file cirros-0.4.0-x86_64-disk.img --disk-format qcow2 --container-format bare --visibility=public - ``` - - Confirm the image upload and verify the attributes. - - ``` - $ glance image-list - ``` - -### Installing Placement - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **placement** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE placement; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **PLACEMENT\_DBPASS** with the password of the **placement** database. - - ``` - $ source admin-openrc - ``` - - Run the following commands to create the placement service credentials, create the **placement** user, and add the **admin** role to the **placement** user: - - Create the Placement API Service. - - ``` - $ openstack user create --domain default --password-prompt placement - $ openstack role add --project service --user placement admin - $ openstack service create --name placement --description "Placement API" placement - ``` - - Create API endpoints of the Placement service. - - ``` - $ openstack endpoint create --region RegionOne placement public http://controller:8778 - $ openstack endpoint create --region RegionOne placement internal http://controller:8778 - $ openstack endpoint create --region RegionOne placement admin http://controller:8778 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - yum install openstack-placement-api - ``` - - Configure Placement: - - Edit the **/etc/placement/placement.conf** file: - - In the **\[placement\_database]** section, configure the database entry. - - In **\[api]** and **\[keystone\_authtoken]** sections, configure the identity authentication service entry. - - ``` - # vim /etc/placement/placement.conf - [placement_database] - # ... - connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - auth_url = http://controller:5000/v3 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = placement - password = PLACEMENT_PASS - ``` - - Replace **PLACEMENT\_DBPASS** with the password of the **placement** database, and replace **PLACEMENT\_PASS** with the password of the **placement** user. - - Synchronize the database: - - ``` - #su -s /bin/sh -c "placement-manage db sync" placement - ``` - - Start the httpd service. - - ``` - #systemctl restart httpd - ``` - -3. Perform the verification. - - Run the following command to check the status: - - ``` - $ . admin-openrc - $ placement-status upgrade check - ``` - - Run the following command to install **osc-placement** and list the available resource types and features: - - ``` - $ yum install python3-osc-placement - $ openstack --os-placement-api-version 1.2 resource class list --sort-column name - $ openstack --os-placement-api-version 1.6 trait list --sort-column name - ``` - -### Installing Nova - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **nova**, **nova\_api**, and **nova\_cell0** databases and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE nova_api; - MariaDB [(none)]> CREATE DATABASE nova; - MariaDB [(none)]> CREATE DATABASE nova_cell0; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **NOVA\_DBPASS** with the password of the **nova** database. - - Run the following commands to create Nova service credentials, create a **nova** user, and add the **admin** role to the **nova** user: - - ``` - $ . admin-openrc - $ openstack user create --domain default --password-prompt nova - $ openstack role add --project service --user nova admin - $ openstack service create --name nova --description "OpenStack Compute" compute - ``` - - Create API endpoints for the computing service. - - ``` - $ openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 - $ openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 - $ openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - # yum install openstack-nova-api openstack-nova-conductor \ - openstack-nova-novncproxy openstack-nova-scheduler openstack-nova-compute - ``` - - Configure Nova: - - Edit the **/etc/nova/nova.conf** file. - - In the **\[default]** section, enable the computing and metadata APIs, configure the RabbitMQ message queue entry, and set **my\_ip**. - - In the **\[api\_database]** and **\[database]** sections, configure the database entry. - - In the **\[api]** and **\[keystone\_authtoken]** sections, configure the identity service entry. - - In the **\[vnc]** section, enable and configure the entry for the remote console. - - In the **\[glance]** section, configure the API address for the image service. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - In the **\[placement]** section, configure the entry of the Placement service. - - ``` - # vim /etc/nova/nova.conf - [DEFAULT] - # ... - enabled_apis = osapi_compute,metadata - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - my_ip = 10.0.0.11 - [api_database] - # ... - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api - [database] - # ... - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000/ - auth_url = http://controller:5000/ - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = nova - password = NOVA_PASS - [vnc] - enabled = true - # ... - server_listen = $my_ip - server_proxyclient_address = $my_ip - novncproxy_base_url = http://controller:6080/vnc_auto.html - [glance] - # ... - api_servers = http://controller:9292 - [oslo_concurrency] - # ... - lock_path = /var/lib/nova/tmp - [placement] - # ... - region_name = RegionOne - project_domain_name = Default - project_name = service - auth_type = password - user_domain_name = Default - auth_url = http://controller:5000/v3 - username = placement - password = PLACEMENT_PASS - [neutron] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - ``` - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Set **my\_ip** to the management IP address of the controller node. - - Replace **NOVA\_DBPASS** with the password of the **nova** database. - - Replace **NOVA\_PASS** with the password of the **nova** user. - - Replace **PLACEMENT\_PASS** with the password of the **placement** user. - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Run the following command to synchronize the **nova-api** database: - - ``` - su -s /bin/sh -c "nova-manage api_db sync" nova - ``` - - Run the following command to register the **cell0** database: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova - ``` - - Create the **cell1** cell: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova - ``` - - Synchronize the **nova** database: - - ``` - su -s /bin/sh -c "nova-manage db sync" nova - ``` - - Verify whether **cell0** and **cell1** are correctly registered: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova - ``` - - Check whether VM hardware acceleration (x86 architecture) is supported: - - ``` - $ egrep -c '(vmx|svm)' /proc/cpuinfo - ``` - - If the returned value is **0**, hardware acceleration is not supported. You need to configure libvirt to use QEMU instead of KVM. - - ``` - # vim /etc/nova/nova.conf - [libvirt] - # ... - virt_type = qemu - ``` - - If the returned value is **1** or a larger value, hardware acceleration is supported, and no extra configuration is required. - - Start the computing service and its dependencies, and enable the service to start automatically upon system boot. - - ``` - # systemctl enable \ - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - # systemctl start \ - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - ``` - - ``` - # systemctl enable libvirtd.service openstack-nova-compute.service - # systemctl start libvirtd.service openstack-nova-compute.service - ``` - - Add the compute nodes to the **cell** database: - - Check whether the compute node exists: - - ``` - $ . admin-openrc - $ openstack compute service list --service nova-compute - ``` - - Register a compute node: - - ``` - #su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova - ``` - -3. Perform the verification. - - ``` - $ . admin-openrc - ``` - - List service components to verify that each process is successfully started and registered. - - ``` - $ openstack compute service list - ``` - - List the API endpoints in the identity service and verify the connection to the identity service. - - ``` - $ openstack catalog list - ``` - - List the images in the image service and verify the connections: - - ``` - $ openstack image list - ``` - - Check whether the cells and placement APIs are running properly and whether other prerequisites are met. - - ``` - #nova-status upgrade check - ``` - -### Installing Neutron - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user, create the **neutron** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE neutron; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **NEUTRON\_DBPASS** with the password of the **neutron** database. - - ``` - $ . admin-openrc - ``` - - Run the following commands to create the **neutron** service credential, create the **neutron** user, and add the **admin** role to the **neutron** user: - - Create the **neutron** service credential. - - ``` - $ openstack user create --domain default --password-prompt neutron - $ openstack role add --project service --user neutron admin - $ openstack service create --name neutron --description "OpenStack Networking" network - ``` - - Create API endpoints of the network services. - - ``` - $ openstack endpoint create --region RegionOne network public http://controller:9696 - $ openstack endpoint create --region RegionOne network internal http://controller:9696 - $ openstack endpoint create --region RegionOne network admin http://controller:9696 - ``` - -2. Install and configure the self-service network. - - Install the software package: - - ``` - # yum install openstack-neutron openstack-neutron-ml2 \ - openstack-neutron-linuxbridge ebtables ipset - ``` - - Configure Neutron: - - Edit the **/etc/neutron/neutron.conf** file: - - In the **\[database]** section, configure the database entry. - - In the **\[default]** section, enable the ML2 and router plug-ins. Allow IP address overlapping, and configure the RabbitMQ message queue entry. - - In the **\[default]** and **\[keystone]** sections, configure the identity authentication service entry. - - In the **\[default]** and **\[nova]** sections, enable the network to notify the change of the computing network topology. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - ``` - # vim /etc/neutron/neutron.conf - [database] - # ... - connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron - [DEFAULT] - # ... - core_plugin = ml2 - service_plugins = router - allow_overlapping_ips = true - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - notify_nova_on_port_status_changes = true - notify_nova_on_port_data_changes = true - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = default - user_domain_name = default - project_name = service - username = neutron - password = NEUTRON_PASS - [nova] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = nova - password = NOVA_PASS - [oslo_concurrency] - # ... - lock_path = /var/lib/neutron/tmp - ``` - - Replace **NEUTRON\_DBPASS** with the password of the **neutron** database. - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Replace **NOVA\_PASS** with the password of the **nova** user. - - Configure the ML2 plug-in. - - Edit the **/etc/neutron/plugins/ml2/ml2\_conf.ini** file. - - In the **\[ml2]** section, enable the flat, VLAN, and VXLAN networks, enable the bridge and layer-2 population mechanism, and enable the port security extension driver. - - In the **\[ml2\_type\_flat]** section, configure the flat network as the provider virtual network. - - In the **\[ml2\_type\_vxlan]** section, configure the VXLAN network identifier range. - - In the **\[securitygroup]** section, set **ipset**. - - ``` - # vim /etc/neutron/plugins/ml2/ml2_conf.ini - [ml2] - # ... - type_drivers = flat,vlan,vxlan - tenant_network_types = vxlan - mechanism_drivers = linuxbridge,l2population - extension_drivers = port_security - [ml2_type_flat] - # ... - flat_networks = provider - [ml2_type_vxlan] - # ... - vni_ranges = 1:1000 - [securitygroup] - # ... - enable_ipset = true - ``` - - Configure the Linux bridge agent: - - Edit the **/etc/neutron/plugins/ml2/linuxbridge\_agent.ini** file: - - In the **\[linux\_bridge]** section, map the provider virtual network to the physical network API. - - In the **\[vxlan]** section, enable the VXLAN network. Configure the IP address of the physical network API that processes the coverage network, and enable layer-2 population. - - In the **\[securitygroup]** section, enable the security group and configure the **linux bridge iptables** firewall driver. - - ``` - # vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini - [linux_bridge] - physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME - [vxlan] - enable_vxlan = true - local_ip = OVERLAY_INTERFACE_IP_ADDRESS - l2_population = true - [securitygroup] - # ... - enable_security_group = true - firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver - ``` - - Replace **PROVIDER\_INTERFACE\_NAME** with the physical network API. - - Replace **OVERLAY\_INTERFACE\_IP\_ADDRESS** with the management IP address of the controller node. - - Configure the Layer 3 proxy. - - Edit the **/etc/neutron/l3\_agent.ini** file: - - In the **\[default]** section, set the API driver to **linuxbridge**. - - ``` - # vim /etc/neutron/l3_agent.ini - [DEFAULT] - # ... - interface_driver = linuxbridge - ``` - - Configures the DHCP agent: - - Edit the **/etc/neutron/dhcp\_agent.ini** file. - - In the **\[default]** section, configure the linuxbridge interface driver and Dnsmasq DHCP driver. Enable the isolated metadata. - - ``` - # vim /etc/neutron/dhcp_agent.ini - [DEFAULT] - # ... - interface_driver = linuxbridge - dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq - enable_isolated_metadata = true - ``` - - Configure the metadata proxy. - - Edit the **/etc/neutron/metadata\_agent.ini** file. - - In the **\[default]**, configure the metadata host and shared secret. - - ``` - # vim /etc/neutron/metadata_agent.ini - [DEFAULT] - # ... - nova_metadata_host = controller - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - Replace **METADATA\_SECRET** with a proper metadata agent secret. - -3. Configure the computing service. - - Edit the **/etc/nova/nova.conf** file. - - In the **\[neutron]** section, configure access parameters, enable the metadata proxy, and configure secret. - - ``` - # vim /etc/nova/nova.conf - [neutron] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Replace **METADATA\_SECRET** with a proper metadata agent secret. - -4. Complete the installation. - - Add a link: - - ``` - #ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini - ``` - - Synchronize the database: - - ``` - # su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ - --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron - ``` - - Run the following command to restart the computing API service: - - ``` - #systemctl restart openstack-nova-api.service - ``` - - Start the network service and enable the service to start automatically upon system boot. - - ``` - # systemctl enable neutron-server.service \ - neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ - neutron-metadata-agent.service - # systemctl start neutron-server.service \ - neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ - neutron-metadata-agent.service - # systemctl enable neutron-l3-agent.service - # systemctl start neutron-l3-agent.service - ``` - -5. Perform the verification. - - Run the following command to list the neutron agents: - - ``` - $ openstack network agent list - ``` - -### Installing Cinder - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **cinder** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE cinder; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **CINDER\_DBPASS** with the password for the **cinder** database. - - ``` - $ source admin-openrc - ``` - - Create Cinder service credentials: - - Create the **cinder** user. - - Add the **admin** role to the **cinder** user. - - Create the **cinderv2** and **cinderv3** services. - - ``` - $ openstack user create --domain default --password-prompt cinder - $ openstack role add --project service --user cinder admin - $ openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 - $ openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 - ``` - - Create API endpoints for the block storage service. - - ``` - $ openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%s - $ openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%s - $ openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%s - ``` - -2. Install and configure the controller node. - - Install the software package: - - ``` - #yum install openstack-cinder - ``` - - Configure Cinder: - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[database]** section, configure the database entry. - - In the **\[DEFAULT]** section, configure the RabbitMQ message queue entry and **my\_ip**. - - In the **\[DEFAULT]** and **\[keystone\_authtoken]** sections, configure the identity authentication service entry. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - ``` - # vim /etc/cinder/cinder.conf - [database] - # ... - connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder - [DEFAULT] - # ... - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - my_ip = 10.0.0.11 - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = default - user_domain_name = default - project_name = service - username = cinder - password = CINDER_PASS - [oslo_concurrency] - # ... - lock_path = /var/lib/cinder/tmp - ``` - - Replace **CINDER\_DBPASS** with the password of the **cinder** database. - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Set **my\_ip** to the management IP address of the controller node. - - Replace **CINDER\_PASS** with the password of the **cinder** user. - - Synchronize the database: - - ``` - su -s /bin/sh -c "cinder-manage db sync" cinder - ``` - - Configure the block storage for the compute nodes. - - Edit the **/etc/nova/nova.conf** file. - - ``` - # vim /etc/nova/nova.conf - [cinder] - os_region_name = RegionOne - ``` - - Complete the installation. - - Restart the computing API service. - - ``` - systemctl restart openstack-nova-api.service - ``` - - Start the block storage service. - - ``` - # systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service - # systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service - ``` - -3. Install and configure the storage node. - - Install the software package: - - ``` - yum install lvm2 device-mapper-persistent-data targetcli python3-keystone - ``` - - Start the service: - - ``` - # systemctl enable lvm2-lvmetad.service - # systemctl start lvm2-lvmetad.service - ``` - - Create the LVM physical volume **/dev/sdb**. - - ``` - pvcreate /dev/sdb - ``` - - Create the LVM volume group **cinder-volumes**. - - ``` - vgcreate cinder-volumes /dev/sdb - ``` - - Edit the **/etc/lvm/lvm.conf** file. - - In the **devices** section, add filtering to allow the **/dev/sdb** device to reject other devices. - - devices { - - ... - - filter = \[ "a/sdb/", "r/.\*/"] - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[lvm]** section, configure the LVM backend using the LVM driver, cinder-volumes volume group, iSCSI protocol, and appropriate iSCSI services. - - In the **\[DEFAULT]** section, enable the LVM backend and configure the location of the API of the image service. - - ``` - [lvm] - volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver - volume_group = cinder-volumes - target_protocol = iscsi - target_helper = lioadm - [DEFAULT] - # ... - enabled_backends = lvm - glance_api_servers = http://controller:9292 - ``` - - Complete the installation. - - ``` - # systemctl enable openstack-cinder-volume.service target.service - # systemctl start openstack-cinder-volume.service target.service - ``` - -4. Install and configure the backup service. - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[DEFAULT]** section, configure the backup options. - - ``` - [DEFAULT] - # ... - # Note: openEuler 21.09 does not provide the OpenStack Swift software package. You need to install it manually. Alternatively, you can use another backup backend, for example, NFS. The NFS has been tested and verified and can be used properly. - backup_driver = cinder.backup.drivers.swift.SwiftBackupDriver - backup_swift_url = SWIFT_URL - ``` - - Replace **SWIFT\_URL** with the URL of the object storage service. The URL can be found through the object storage API endpoint. - - ``` - $ openstack catalog show object-store - ``` - - Complete the installation. - - ``` - # systemctl enable openstack-cinder-backup.service - # systemctl start openstack-cinder-backup.service - ``` - -5. Perform the verification. - - List service components and verify that each step is successful. - - ``` - $ source admin-openrc - $ openstack volume service list - ``` - - Note: Currently, the Swift component is not supported. If possible, you can configure the interconnection with Ceph. - -### Installing Horizon - -1. Install the software package: - - ```plain - yum install openstack-horizon - ``` - -2. Modify the `/usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py` file. - - Modify the variables. - - ```plain - ALLOWED_HOSTS = ['*', ] - OPENSTACK_HOST = "controller" - OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST - ``` - - Add variables. - - ```plain - OPENSTACK_API_VERSIONS = { - "identity": 3, - "image": 2, - "volume": 3, - } - WEBROOT = "/dashboard/" - COMPRESS_OFFLINE = True - OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "default" - OPENSTACK_KEYSTONE_DEFAULT_ROLE = "admin" - LOGIN_URL = '/dashboard/auth/login/' - LOGOUT_URL = '/dashboard/auth/logout/' - ``` - -3. Run the following command in the **/usr/share/openstack-dashboard** directory: - - ```plain - ./manage.py compress - ``` - -4. Restart the httpd service. - - ```plain - systemctl restart httpd - ``` - -5. Perform the verification - Open a browser and enter **http://***\* in the address box to log in to Horizon. - -### Installing Tempest - -Tempest is the integrated test service of OpenStack. If you need to run a fully automatic test of the functions of the installed OpenStack environment, you are advised to use Tempest. Otherwise, you can choose not to install it. - -1. Install Tempest: - ``` - yum install openstack-tempest - ``` -2. Initialize the directory: - - ``` - tempest init mytest - ``` -3. Modify the configuration file: - - ``` - cd mytest - vi etc/tempest.conf - ``` - Configure the current OpenStack environment information in **tempest.conf**. For details, see the [official example](https://docs.openstack.org/tempest/latest/sampleconf.html). - -4. Perform the test: - - ``` - tempest run - ``` - -### Installing Ironic - -Ironic is the bare metal service of OpenStack. If you need to deploy bare metal machines, you are advised to use Ironic. Otherwise, you can choose not to install it. - -1. Set the database. - - The bare metal service stores information in the database. Create a **ironic** database that can be accessed by the **ironic** user and replace **IRONIC_DBPASSWORD** with a proper password. - - ``` - # mysql -u root -p MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - ``` - -2. Install and configure the components. - - ##### Creating Service User Authentication - - 1. Create the bare metal service user: - - ``` - $ openstack user create --password IRONIC_PASSWORD \ - --email ironic@example.com ironic - $ openstack role add --project service --user ironic admin - $ openstack service create --name ironic --description \ - "Ironic baremetal provisioning service" baremetal - - $ openstack service create --name ironic-inspector --description "Ironic inspector baremetal provisioning service" baremetal-introspection - $ openstack user create --password IRONIC_INSPECTOR_PASSWORD --email ironic_inspector@example.com ironic_inspector - $ openstack role add --project service --user ironic-inspector admin - ``` - - 2. Create the bare metal service access entries: - - ``` - $ openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal-introspection internal http://172.20.19.13:5050/v1 - $ openstack endpoint create --region RegionOne baremetal-introspection public http://172.20.19.13:5050/v1 - $ openstack endpoint create --region RegionOne baremetal-introspection admin http://172.20.19.13:5050/v1 - ``` - - ##### Configuring the ironic-api Service - - Configuration file path: **/etc/ironic/ironic.conf**. - - 1. Use **connection** to configure the location of the database as follows. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. - - ``` - [database] - - # The SQLAlchemy connection string used to connect to the - # database (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 2. Configure the ironic-api service to use the RabbitMQ message broker. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. - - ``` - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - You can also use json-rpc instead of RabbitMQ. - - 3. Configure the ironic-api service to use the credential of the identity authentication service. Replace **PUBLIC_IDENTITY_IP** with the public IP address of the identity authentication server and **PRIVATE_IDENTITY_IP** with the private IP address of the identity authentication server, replace **IRONIC_PASSWORD** with the password of the **ironic** user in the identity authentication service. - - ``` - [DEFAULT] - - # Authentication strategy used by ironic-api: one of - # "keystone" or "noauth". "noauth" should not be used in a - # production environment because all authentication will be - # disabled. (string value) - - auth_strategy=keystone - - [keystone_authtoken] - # Authentication type to load (string value) - auth_type=password - # Complete public Identity API endpoint (string value) - www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 - # Complete admin Identity API endpoint. (string value) - auth_url=http://PRIVATE_IDENTITY_IP:5000 - # Service username. (string value) - username=ironic - # Service account password. (string value) - password=IRONIC_PASSWORD - # Service tenant name. (string value) - project_name=service - # Domain name containing project (string value) - project_domain_name=Default - # User's domain name (string value) - user_domain_name=Default - ``` - - 4. Create the bare metal service database table: - - ``` - $ ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema - ``` - - 5. Restart the ironic-api service: - - ``` - sudo systemctl restart openstack-ironic-api - ``` - - ##### Configuring the ironic-conductor Service. - - 1. Replace **HOST_IP** with the IP address of the conductor host. - - ``` - [DEFAULT] - - # IP address of this host. If unset, will determine the IP - # programmatically. If unable to do so, will use "127.0.0.1". - # (string value) - - my_ip=HOST_IP - ``` - - 2. Specifies the location of the database. ironic-conductor must use the same configuration as ironic-api. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace DB_IP with the IP address of the database server. - - ``` - [database] - - # The SQLAlchemy connection string to use to connect to the - # database. (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 3. Configure the ironic-api service to use the RabbitMQ message broker. ironic-conductor must use the same configuration as ironic-api. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. - - ``` - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - You can also use json-rpc instead of RabbitMQ. - - 4. Configure the credentials to access other OpenStack services. - - To communicate with other OpenStack services, the bare metal service needs to use the service users to get authenticated by the OpenStack Identity service when requesting other services. The credentials of these users must be configured in each configuration file associated to the corresponding service. - - ``` - [neutron] - Accessing the OpenStack network services. - [glance] - Accessing the OpenStack image service. - [swift] - Accessing the OpenStack object storage service. - [cinder] - Accessing the OpenStack block storage service. - [inspector] Accessing the OpenStack bare metal introspection service. - [service_catalog] - A special item to store the credential used by the bare metal service. The credential is used to discover the API URL endpoint registered in the OpenStack identity authentication service catalog by the bare metal service. - ``` - - For simplicity, you can use one service user for all services. For backward compatibility, the user name must be the same as that configured in **[keystone_authtoken]** of the ironic-api service. However, this is not mandatory. You can also create and configure a different service user for each service. - - In the following example, the authentication information for the user to access the OpenStack network service is configured as follows: - - ``` - The network service is deployed in the identity authentication service domain named RegionOne. Only the public endpoint interface is registered in the service catalog. - - A specific CA SSL certificate is used for HTTPS connection when sending a request. - - The same service user as that configured for ironic-api. - - The dynamic password authentication plugin discovers a proper identity authentication service API version based on other options. - ``` - - ``` - [neutron] - - # Authentication type to load (string value) - auth_type = password - # Authentication URL (string value) - auth_url=https://IDENTITY_IP:5000/ - # Username (string value) - username=ironic - # User's password (string value) - password=IRONIC_PASSWORD - # Project name to scope to (string value) - project_name=service - # Domain ID containing project (string value) - project_domain_id=default - # User's domain id (string value) - user_domain_id=default - # PEM encoded Certificate Authority to use when verifying - # HTTPs connections. (string value) - cafile=/opt/stack/data/ca-bundle.pem - # The default region_name for endpoint URL discovery. (string - # value) - region_name = RegionOne - # List of interfaces, in order of preference, for endpoint - # URL. (list value) - valid_interfaces=public - ``` - - By default, to communicate with other services, the bare metal service attempts to discover a proper endpoint of the service through the service catalog of the identity authentication service. If you want to use a different endpoint for a specific service, specify the endpoint_override option in the bare metal service configuration file. - - ``` - [neutron] ... endpoint_override = - ``` - - 5. Configure the allowed drivers and hardware types. - - Set enabled_hardware_types to specify the hardware types that can be used by ironic-conductor: - - ``` - [DEFAULT] enabled_hardware_types = ipmi - ``` - - Configure hardware interfaces: - - ``` - enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool - ``` - - Configure the default value of the interface: - - ``` - [DEFAULT] default_deploy_interface = direct default_network_interface = neutron - ``` - - If any driver that uses Direct Deploy is enabled, you must install and configure the Swift backend of the image service. The Ceph object gateway (RADOS gateway) can also be used as the backend of the image service. - - 6. Restart the ironic-conductor service. - - ``` - sudo systemctl restart openstack-ironic-conductor - ``` - - ##### Configuring the ironic-inspector Service - - Configuration file path: **/etc/ironic-inspector/inspector.conf** - - 1. Create the database: - - ``` - # mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE ironic_inspector CHARACTER SET utf8; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'localhost' \ IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'%' \ - IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - ``` - - 2. Use **connection** to configure the location of the database as follows. Replace **IRONIC_INSPECTOR_DBPASSWORD** with the password of user **ironic_inspector** and replace **DB_IP** with the IP address of the database server. - - ``` - [database] - backend = sqlalchemy - connection = mysql+pymysql://ironic_inspector:IRONIC_INSPECTOR_DBPASSWORD@DB_IP/ironic_inspector - ``` - - 3. Configure the communication address of the message queue: - - ``` - [DEFAULT] transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 4. Configure the Keystone authentication: - - ``` - [DEFAULT] - - auth_strategy = keystone - - [ironic] - - api_endpoint = http://IRONIC_API_HOST_ADDRRESS:6385 - auth_type = password - auth_url = http://PUBLIC_IDENTITY_IP:5000 - auth_strategy = keystone - ironic_url = http://IRONIC_API_HOST_ADDRRESS:6385 - os_region = RegionOne - project_name = service - project_domain_name = default - user_domain_name = default - username = IRONIC_SERVICE_USER_NAME - password = IRONIC_SERVICE_USER_PASSWORD - ``` - - 5. Configure the ironic inspector dnsmasq service: - - ``` - # Configuration file path: /etc/ironic-inspector/dnsmasq.conf - port=0 - interface=enp3s0 #Replace with the actual listening network interface. - dhcp-range=172.20.19.100,172.20.19.110 #Replace with the actual DHCP IP address range. - bind-interfaces - enable-tftp - - dhcp-match=set:efi,option:client-arch,7 - dhcp-match=set:efi,option:client-arch,9 - dhcp-match=aarch64, option:client-arch,11 - dhcp-boot=tag:aarch64,grubaa64.efi - dhcp-boot=tag:!aarch64,tag:efi,grubx64.efi - dhcp-boot=tag:!aarch64,tag:!efi,pxelinux.0 - - tftp-root=/tftpboot #Replace with the actual tftpboot directory. - log-facility=/var/log/dnsmasq.log - ``` - - 6. Start the services: - - ``` - $ systemctl enable --now openstack-ironic-inspector.service - $ systemctl enable --now openstack-ironic-inspector-dnsmasq.service - ``` - -3. Creatie the deploy ramdisk Image. - - Currently, you can use the ironic python agent builder to build the ramdisk image. The following describes how to use this tool to build the deploy image used by ironic. - - ##### Installing ironic-python-agent-builder - - 1. Install Python 3 on the local host, switch the local Python to Python 3, and resolve the problems after the switching (for example, the Yum source cannot be used). - - ``` - yum install python36 - ``` - - 2. Install the tool: - - ``` - pip install ironic-python-agent-builder - ``` - - 3. Modify the python interpreter in the following file: - - ``` - /usr/bin/yum /usr/libexec/urlgrabber-ext-down - ``` - - 4. Install the other necessary tools: - - ``` - yum install git - ``` - - `DIB` depends on the `semanage` command. Therefore, check whether the `semanage --help` command is available before creating an image. If the system displays a message indicating that the command is unavailable, install the command: - - ``` - # Check which package needs to be installed. - [root@localhost ~]# yum provides /usr/sbin/semanage - Loaded plug-in: fastestmirror - Loading mirror speeds from cached hostfile - * base: mirror.vcu.edu - * extras: mirror.vcu.edu - * updates: mirror.math.princeton.edu - policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities - Source: base - Matching source: - File name: /usr/sbin/semanage - # Install. - [root@localhost ~]# yum install policycoreutils-python - ``` - - ##### Creating the Image - - According to the test result, only version 8 is supported for CentOS. In addition, centos8-minimal lacks some NIC drivers. As a result, all NICs are in the down state after the Dell physical machine is started. Therefore, CentOS 8 is used in the example. Add the following environment variables: - - ``` - export DIB_PYTHON_VERSION=3 \ - export DIB_RELEASE=8 \ - export DIB_YUM_MINIMAL_CREATE_INTERFACES - ``` - - For `arm` architecture, add the following information in addition: - - ``` - export ARCH=aarch64 - ``` - - ###### Common Image - - Basic usage: - - ``` - usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] - [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] - distribution - - positional arguments: - distribution Distribution to use - - optional arguments: - -h, --help show this help message and exit - -r RELEASE, --release RELEASE - Distribution release to use - -o OUTPUT, --output OUTPUT - Output base file name - -e ELEMENT, --element ELEMENT - Additional DIB element to use - -b BRANCH, --branch BRANCH - If set, override the branch that is used for ironic- - python-agent and requirements - -v, --verbose Enable verbose logging in diskimage-builder - --extra-args EXTRA_ARGS - Extra arguments to pass to diskimage-builder - ``` - - Example: - - ``` - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky - ``` - - ###### Allowing SSH login - - Initialize the environment variables and create the image: - - ``` - export DIB_DEV_USER_USERNAME=ipa \ - export DIB_DEV_USER_PWDLESS_SUDO=yes \ - export DIB_DEV_USER_PASSWORD='123' - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser - ``` - - ###### Specifying the Code Repository - - Initialize the corresponding environment variables and create the image: - - ``` - # Specify the address and version of the repository. - DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git - DIB_REPOREF_ironic_python_agent=origin/develop - - # Clone code from Gerrit. - DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent - DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 - ``` - - Reference: [source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html). - - The specified repository address and version are verified successfully. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md b/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md index ea6141653..486d1856d 100644 --- a/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md +++ b/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md @@ -31,7 +31,7 @@ OpenStack is an open source cloud computing infrastructure software project deve As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. -The official source of openEuler 21.09 now supports OpenStack Wallaby. You can configure the Yum source then deploy OpenStack by following the instructions of this document. +The official source of openEuler 22.03 LTS now supports OpenStack Wallaby. You can configure the Yum source then deploy OpenStack by following the instructions of this document. ## Conventions @@ -64,33 +64,26 @@ The services involved in the preceding conventions are as follows: ### Environment Configuration -1. Configure the openEuler 21.09 official Yum source. Enable the EPOL software repository to support OpenStack. +1. Configure the openEuler 22.03 LTS official Yum source. Enable the EPOL software repository to support OpenStack. ```shell - cat << EOF >> /etc/yum.repos.d/21.09-OpenStack_Wallaby.repo - [OS] - name=OS - baseurl=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/RPM-GPG-KEY-openEuler + yum update + yum install openstack-release-wallaby + yum clean all && yum makecache + ``` - [everything] - name=everything - baseurl=http://repo.openeuler.org/openEuler-21.09/everything/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/everything/$basearch/RPM-GPG-KEY-openEuler + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo [EPOL] name=EPOL - baseurl=http://repo.openeuler.org/openEuler-21.09/EPOL/main/$basearch/ + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ enabled=1 gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/RPM-GPG-KEY-openEuler + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler EOF - - yum clean all && yum makecache ``` 2. Change the host name and mapping. @@ -102,7 +95,7 @@ The services involved in the preceding conventions are as follows: hostnamectl set-hostname compute (CPT) ``` - Assuming the IP address of the controller node is `10.0.0.11` and the IP address of the compute node (if any) is `10.0.0.12`, add the following information to the `/etc/hosts` file: + Assuming the IP address of the controller node is **10.0.0.11** and the IP address of the compute node (if any) is **10.0.0.12**, add the following information to the **/etc/hosts** file: ```shell 10.0.0.11 controller @@ -2211,7 +2204,7 @@ chown -R ipa.ipa /etc/ironic_python_agent/ ### Installing Kolla -Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. The Kolla and Kolla-ansible services are introduced in openEuler in version 21.09. +Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. The Kolla and Kolla-ansible services are introduced in openEuler in version 22.03 LTS. The installation of Kolla is simple. You only need to install the corresponding RPM packages: @@ -2596,7 +2589,7 @@ Swift provides a scalable and highly available distributed object storage servic Rebalance the ring: ```shell - swift-ring-builder account.builder rebalance + swift-ring-builder container.builder rebalance ``` 8. Create the object ring. (CTL) @@ -2631,7 +2624,7 @@ Swift provides a scalable and highly available distributed object storage servic Rebalance the ring: ```shell - swift-ring-builder account.builder rebalance + swift-ring-builder object.builder rebalance ``` Distribute ring configuration files: @@ -2686,3 +2679,530 @@ Swift provides a scalable and highly available distributed object storage servic systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service ``` + +### Installing Cyborg + +Cyborg provides acceleration device support for OpenStack, for example, GPUs, FPGAs, ASICs, NPs, SoCs, NVMe/NOF SSDs, ODPs, DPDKs, and SPDKs. + +1. Initialize the databases. + +``` +CREATE DATABASE cyborg; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +$ openstack user create --domain default --password-prompt cyborg +$ openstack role add --project service --user cyborg admin +$ openstack service create --name cyborg --description "Acceleration Service" accelerator + +$ openstack endpoint create --region RegionOne \ + accelerator public http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator internal http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator admin http://:6666/v1 +``` + +3. Install Cyborg + +``` +yum install openstack-cyborg +``` + +4. Configure Cyborg + +Modify **/etc/cyborg/cyborg.conf**. + +``` +[DEFAULT] +transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ +use_syslog = False +state_path = /var/lib/cyborg +debug = True + +[database] +connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg + +[service_catalog] +project_domain_id = default +user_domain_id = default +project_name = service +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[placement] +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = placement +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[keystone_authtoken] +memcached_servers = localhost:11211 +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password +``` + +Set the user names, passwords, and IP addresses as required. + +1. Synchronize the database table. + +``` +cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade +``` + +6. Start the Cyborg services. + +``` +systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +``` + +### Installing Aodh + +1. Create the database. + +``` +CREATE DATABASE aodh; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt aodh + +openstack role add --project service --user aodh admin + +openstack service create --name aodh --description "Telemetry" alarming + +openstack endpoint create --region RegionOne alarming public http://controller:8042 + +openstack endpoint create --region RegionOne alarming internal http://controller:8042 + +openstack endpoint create --region RegionOne alarming admin http://controller:8042 +``` + +3. Install Aodh. + +``` +yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient +``` + +4. Modify the configuration file. + +``` +[database] +connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh + +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +auth_strategy = keystone + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +aodh-dbsync +``` + +6. Start the Aodh services. + +``` +systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service + +systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service +``` + +### Installing Gnocchi + +1. Create the database. + +``` +CREATE DATABASE gnocchi; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt gnocchi + +openstack role add --project service --user gnocchi admin + +openstack service create --name gnocchi --description "Metric Service" metric + +openstack endpoint create --region RegionOne metric public http://controller:8041 + +openstack endpoint create --region RegionOne metric internal http://controller:8041 + +openstack endpoint create --region RegionOne metric admin http://controller:8041 +``` + +3. Install Gnocchi. + +``` +yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient +``` + +1. Modify the **/etc/gnocchi/gnocchi.conf** configuration file. + +``` +[api] +auth_mode = keystone +port = 8041 +uwsgi_mode = http-socket + +[keystone_authtoken] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_name = Default +user_domain_name = Default +project_name = service +username = gnocchi +password = GNOCCHI_PASS +interface = internalURL +region_name = RegionOne + +[indexer] +url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi + +[storage] +# coordination_url is not required but specifying one will improve +# performance with better workload division across workers. +coordination_url = redis://controller:6379 +file_basepath = /var/lib/gnocchi +driver = file +``` + +5. Initialize the database. + +``` +gnocchi-upgrade +``` + +6. Start the Gnocchi services. + +``` +systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service + +systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service +``` + +### Installing Ceilometer + +1. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt ceilometer + +openstack role add --project service --user ceilometer admin + +openstack service create --name ceilometer --description "Telemetry" metering +``` + +2. Install Ceilometer. + +``` +yum install openstack-ceilometer-notification openstack-ceilometer-central +``` + +1. Modify the **/etc/ceilometer/pipeline.yaml** configuration file. + +``` +publishers: + # set address of Gnocchi + # + filter out Gnocchi-related activity meters (Swift driver) + # + set default archive policy + - gnocchi://?filter_project=service&archive_policy=low +``` + +4. Modify the **/etc/ceilometer/ceilometer.conf** configuration file. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = ceilometer +password = CEILOMETER_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +ceilometer-upgrade +``` + +6. Start the Ceilometer services. + +``` +systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service + +systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service +``` + +### Installing Heat + +1. Creat the **heat** database and grant proper privileges to it. Replace **HEAT_DBPASS** with a proper password. + +``` +CREATE DATABASE heat; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; +``` + +2. Create a service credential. Create the **heat** user and add the **admin** role to it. + +``` +openstack user create --domain default --password-prompt heat +openstack role add --project service --user heat admin +``` + +3. Create the **heat** and **heat-cfn** services and their API enpoints. + +``` +openstack service create --name heat --description "Orchestration" orchestration +openstack service create --name heat-cfn --description "Orchestration" cloudformation +openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 +``` + +4. Create additional OpenStack management information, including the **heat** domain and its administrator **heat_domain_admin**, the **heat_stack_owner** role, and the **heat_stack_user** role. + +``` +openstack user create --domain heat --password-prompt heat_domain_admin +openstack role add --domain heat --user-domain heat --user heat_domain_admin admin +openstack role create heat_stack_owner +openstack role create heat_stack_user +``` + +5. Install the software packages. + +``` +yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine +``` + +6. Modify the configuration file **/etc/heat/heat.conf**. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +heat_metadata_server_url = http://controller:8000 +heat_waitcondition_server_url = http://controller:8000/v1/waitcondition +stack_domain_admin = heat_domain_admin +stack_domain_admin_password = HEAT_DOMAIN_PASS +stack_user_domain_name = heat + +[database] +connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_name = default +user_domain_name = default +project_name = service +username = heat +password = HEAT_PASS + +[trustee] +auth_type = password +auth_url = http://controller:5000 +username = heat +password = HEAT_PASS +user_domain_name = default + +[clients_keystone] +auth_uri = http://controller:5000 +``` + +7. Initialize the **heat** database table. + +``` +su -s /bin/sh -c "heat-manage db_sync" heat +``` + +8. Start the services. + +``` +systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +``` + +## OpenStack Quick Installation + +The OpenStack SIG provides the Ansible script for one-click deployment of OpenStack in All in One or Distributed modes. Users can use the script to quickly deploy an OpenStack environment based on openEuler RPM packages. The following uses the All in One mode installation as an example. + +1. Install the OpenStack SIG Tool. + + ```shell + pip install openstack-sig-tool + ``` + +2. Configure the OpenStack Yum source. + + ```shell + yum install openstack-release-wallaby + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + +3. Update the Ansible configurations. + + Open the **/usr/local/etc/inventory/all_in_one.yaml** file and modify the configuration based on the environment and requirements. Modify the file as follows: + + ```shell + all: + hosts: + controller: + ansible_host: + ansible_ssh_private_key_file: + ansible_ssh_user: root + vars: + mysql_root_password: root + mysql_project_password: root + rabbitmq_password: root + project_identity_password: root + enabled_service: + - keystone + - neutron + - cinder + - placement + - nova + - glance + - horizon + - aodh + - ceilometer + - cyborg + - gnocchi + - kolla + - heat + - swift + - trove + - tempest + neutron_provider_interface_name: br-ex + default_ext_subnet_range: 10.100.100.0/24 + default_ext_subnet_gateway: 10.100.100.1 + neutron_dataplane_interface_name: eth1 + cinder_block_device: vdb + swift_storage_devices: + - vdc + swift_hash_path_suffix: ash + swift_hash_path_prefix: has + children: + compute: + hosts: controller + storage: + hosts: controller + network: + hosts: controller + vars: + test-key: test-value + dashboard: + hosts: controller + vars: + allowed_host: '*' + kolla: + hosts: controller + vars: + # We add openEuler OS support for kolla in OpenStack Queens/Rocky release + # Set this var to true if you want to use it in Q/R + openeuler_plugin: false + ``` + + Key Configurations + + | Item | Description| + |---|---| + | ansible_host | IP address of the all-in-one node.| + | ansible_ssh_private_key_file | Key used by the Ansible script for logging in to the all-in-one node.| + | ansible_ssh_user | User used by the Ansible script for logging in to the all-in-one node.| + | enabled_service | List of services to be installed. You can delete services as required.| + | neutron_provider_interface_name | Neutron L3 bridge name. | + | default_ext_subnet_range | Neutron private network IP address range. | + | default_ext_subnet_gateway | Neutron private network gateway. | + | neutron_dataplane_interface_name | NIC used by Neutron. You are advised to use a new NIC to avoid conflicts with existing NICs causing disconnection of the all-in-one node. | + | cinder_block_device | Name of the block device used by Cinder.| + | swift_storage_devices | Name of the block device used by Swift. | + +4. Run the installation command. + + ```shell + oos env setup all_in_one + ``` + + After the command is executed, the OpenStack environment of the All in One mode is successfully deployed. + + The environment variable file **.admin-openrc** is stored in the home directory of the current user. + +5. Initialize the Tempest environment. + + If you want to perform the Tempest test in the environment, run the `oos env init all_in_one` command to create the OpenStack resources required by Tempest. + + After the command is executed successfully, a **mytest** directory is generated in the home directory of the user. You can run the `tempest run` command in the directory. \ No newline at end of file diff --git a/docs/en/docs/userguide/patch-tracking.md b/docs/en/docs/userguide/patch-tracking.md index 1f427a5d9..67586ab4d 100644 --- a/docs/en/docs/userguide/patch-tracking.md +++ b/docs/en/docs/userguide/patch-tracking.md @@ -335,4 +335,4 @@ During the operation of the patch-tracking, the following error message may occu #### Cause Analysis -The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, HUAWEI CLOUD Hong Kong). \ No newline at end of file +The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, Huawei Cloud Hong Kong). \ No newline at end of file diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 74ce94a24..d3376362e 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -17,7 +17,7 @@ headless: true - [Installation Guide]({{< relref "./docs/Installation/Installation.md" >}}) - [Installation on Servers]({{< relref "./docs/Installation/install-server.md" >}}) - [Installation Preparations]({{< relref "./docs/Installation/installation-preparations.md" >}}) - - [Installation Mode]({{< relref "./docs/Installation/installation-mode.md" >}}) + - [Installation Modes]({{< relref "./docs/Installation/Installation-Modes1.md" >}}) - [Installation Guideline]({{< relref "./docs/Installation/installation-guideline.md" >}}) - [Using Kickstart for Automatic Installation]({{< relref "./docs/Installation/using-kickstart-for-automatic-installation.md" >}}) - [FAQs]({{< relref "./docs/Installation/faqs.md" >}}) @@ -57,7 +57,7 @@ headless: true - [Appendix]({{< relref "./docs/SecHarden/appendix.md" >}}) - [Virtualization User Guide]({{< relref "./docs/Virtualization/virtualization.md" >}}) - [Introduction to Virtualization]({{< relref "./docs/Virtualization/introduction-to-virtualization.md" >}}) - - [Installation to Virtualization]({{< relref "./docs/Virtualization/installation-to-virtualization.md" >}}) + - [Installing Virtualization]({{< relref "./docs/Virtualization/virtualization-installation.md" >}}) - [Environment Preparation]({{< relref "./docs/Virtualization/environment-preparation.md" >}}) - [VM Configuration]({{< relref "./docs/Virtualization/vm-configuration.md" >}}) - [Managing VMs]({{< relref "./docs/Virtualization/managing-vms.md" >}}) @@ -71,12 +71,15 @@ headless: true - [LibcarePlus]({{< relref "./docs/Virtualization/LibcarePlus.md" >}}) - [Appendix]({{< relref "./docs/Virtualization/appendix.md" >}}) - [StratoVirt Virtualization User Guide]({{< relref "./docs/StratoVirt/StratoVrit_guidence.md" >}}) - - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_intoduction.md" >}}) + - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_introduction.md" >}}) - [Installing StratoVirt]({{< relref "./docs/StratoVirt/Install_StratoVirt.md" >}}) - [Preparing the Environment]({{< relref "./docs/StratoVirt/Prepare_env.md" >}}) - [Configuring a VM]({{< relref "./docs/StratoVirt/VM_configuration.md" >}}) - [VM Management]({{< relref "./docs/StratoVirt/VM_management.md" >}}) - - [Connecting to the iSula Secure Container]({{< relref "./docs/StratoVirt/connecting-to-the-isula-secure-container.md" >}}) + - [Connecting to the iSula Secure Container]({{< relref "./docs/StratoVirt/interconnect_isula.md" >}}) + - [Interconnecting with libvirt]({{< relref "./docs/StratoVirt/Interconnect_libvirt.md" >}}) + - [StratoVirt VFIO Instructions]({{< relref "./docs/StratoVirt/StratoVirt_VFIO_instructions.md" >}}) +- [Container User Guide]({{< relref "./docs/Container/container.md" >}}) - [iSulad Container Engine]({{< relref "./docs/Container/isulad-container-engine.md" >}}) - [Installation, Upgrade and Uninstallation]({{< relref "./docs/Container/installation-upgrade-Uninstallation.md" >}}) - [Installation and Configuration]({{< relref "./docs/Container/installation-configuration.md" >}}) @@ -85,8 +88,6 @@ headless: true - [Application Scenarios]({{< relref "./docs/Container/application-scenarios.md" >}}) - [Container Management]({{< relref "./docs/Container/container-management.md" >}}) - [Interconnection with the CNI Network]({{< relref "./docs/Container/interconnection-with-the-cni-network.md" >}}) -}) - - [Container Resource Management]({{< relref "./docs/Container/container-resource-management.md" >}}) - [Privileged Container]({{< relref "./docs/Container/privileged-container.md" >}}) - [CRI]({{< relref "./docs/Container/cri.md" >}}) - [Image Management]({{< relref "./docs/Container/image-management.md" >}}) @@ -136,17 +137,24 @@ headless: true - [Application Scenarios]({{< relref "./docs/A-Tune/application-scenarios.md" >}}) - [FAQs]({{< relref "./docs/A-Tune/faqs.md" >}}) - [Appendixes]({{< relref "./docs/A-Tune/appendixes.md" >}}) +- [openEuler Embedded User Guide]({{< relref "./docs/Embedded/embedded.md" >}}) + - [Installation and Running]({{< relref "./docs/Embedded/installation-and-running.md" >}}) + - [Build Guide]({{< relref "./docs/Embedded/building-guide.md" >}}) + - [Quick Build Guide]({{< relref "./docs/Embedded/quick-build-guide.md" >}}) + - [Container Build Guide]({{< relref "./docs/Embedded/container-build-guide.md" >}}) + - [Installation and Running]({{< relref "./docs/Embedded/installation-and-running.md" >}}) + - [Application Development Using openEuler Embedded SDK]({{< relref "./docs/Embedded/application-development-using-sdk.md" >}}) +- [Kernel Live Upgrade Guide]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) + - [Installation and Deployment]({{< relref "./docs/KernelLiveUpgrade/installation-and-deployment.md" >}}) + - [How to Run]({{< relref "./docs/KernelLiveUpgrade/how-to-run.md" >}}) + - [Common Problems and Solutions]({{< relref "./docs/KernelLiveUpgrade/common-problems-and-solutions.md" >}}) - [Application Development Guide]({{< relref "./docs/ApplicationDev/application-development.md" >}}) - - [Preparation]({{< relref "./docs/ApplicationDev/preparation.md" >}}) + - [Preparation]({{< relref "./docs/ApplicationDev/preparations-for-development-environment.md" >}}) - [Using GCC for Compilation]({{< relref "./docs/ApplicationDev/using-gcc-for-compilation.md" >}}) - [Using Make for Compilation]({{< relref "./docs/ApplicationDev/using-make-for-compilation.md" >}}) - [Using JDK for Compilation]({{< relref "./docs/ApplicationDev/using-jdk-for-compilation.md" >}}) - [Building an RPM Package]({{< relref "./docs/ApplicationDev/building-an-rpm-package.md" >}}) - [FAQ]({{< relref "./docs/ApplicationDev/FAQ.md" >}}) -- [Kernel Hot Upgrade Guide]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - - [Installation and Deployment]({{< relref "./docs/KernelLiveUpgrade/installation-and-deployment.md" >}}) - - [How to Run]({{< relref "./docs/KernelLiveUpgrade/how-to-run.md" >}}) - - [Common Problems and Solutions]({{< relref "./docs/KernelLiveUpgrade/common-problems-and-solutions.md" >}}) - [secGear Development Guide]({{< relref "./docs/secGear/secGear.md" >}}) - [Introduction to secGear]({{< relref "./docs/secGear/introduction-to-secGear.md" >}}) - [Installing secGear]({{< relref "./docs/secGear/installing-secGear.md" >}}) @@ -166,10 +174,15 @@ headless: true - [Deploying a Cluster]({{< relref "./docs/Kubernetes/eggo-deploying-a-cluster.md" >}}) - [Dismantling a Cluster]({{< relref "./docs/Kubernetes/eggo-dismantling-a-cluster.md" >}}) - [Running the Test Pod]({{< relref "./docs/Kubernetes/running-the-test-pod.md" >}}) +- [KubeEdge User Guide]({{< relref "./docs/KubeEdge/overview.md" >}}) + - [KubeEdge Usage Guide]({{< relref "./docs/KubeEdge/kubeedge-usage-guide.md" >}}) + - [KubeEdge Deployment Guide]({{< relref "./docs/KubeEdge/kubeedge-deployment-guide.md" >}}) - [Third-Party Software Deployment Guide]({{< relref "./docs/thirdparty_migration/thidrparty.md" >}}) - - [OpenStack Victoria Deployment Guide]({{< relref "./docs/thirdparty_migration/OpenStack-victoria.md" >}}) - - [Installing and Deploying an HA Cluster]({{< relref "./docs/thirdparty_migration/installha.md" >}}) - - [KubeSphere Installation Guide]({{< relref "./docs/thirdparty_migration/kubesphere.md" >}}) + - [OpenStack-Wallaby Deployment Guide]({{< relref "./docs/thirdparty_migration/OpenStack-wallaby.md" >}}) + - [HA User Guide]({{< relref "./docs/desktop/ha.md" >}}) + - [Deploying an HA Cluster]({{< relref "./docs/thirdparty_migration/installha.md" >}}) + - [HA Usage Example]({{< relref "./docs/desktop/HA_usage_example.md" >}}) + - [KubeSphere Deployment Guide]({{< relref "./docs/desktop/kubesphere.md" >}}) - [Desktop Environment User Guide]({{< relref "./docs/desktop/desktop.md" >}}) - [UKUI]({{< relref "./docs/desktop/ukui.md" >}}) - [UKUI Installation]({{< relref "./docs/desktop/installing-UKUI.md" >}}) @@ -199,4 +212,10 @@ headless: true - [Installation and Deployment]({{< relref "./docs/KubeOS/installation-and-deployment.md" >}}) - [Usage Instructions]({{< relref "./docs/KubeOS/usage-instructions.md" >}}) - [Image Tailoring and Customization Tool]({{< relref "./docs/TailorCustom/overview.md" >}}) - - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) \ No newline at end of file + - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) + - [ImageTailor User Guide]({{< relref "./docs/TailorCustom/imageTailor-user-guide.md" >}}) +- [Gazelle User Guide]({{< relref "./docs/Gazelle/Gazelle.md" >}}) +- [NestOS User Guide]({{< relref "./docs/NestOS/overview.md" >}}) + - [Installation and Deployment]({{< relref "./docs/NestOS/installation-and-deployment.md" >}}) + - [Setting Up Kubernetes and iSulad]({{< relref "./docs/NestOS/usage.md" >}}) + - [Feature Description]({{< relref "./docs/NestOS/feature-description.md" >}}) \ No newline at end of file -- Gitee From 455800b6feec520f887d90db6a0901878bb0ed45 Mon Sep 17 00:00:00 2001 From: Judith Date: Thu, 12 May 2022 10:36:07 +0000 Subject: [PATCH 28/42] =?UTF-8?q?update=20docs/zh/docs/ApplicationDev/?= =?UTF-8?q?=E4=BD=BF=E7=94=A8GCC=E7=BC=96=E8=AF=91.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...344\275\277\347\224\250GCC\347\274\226\350\257\221.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" "b/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" index 57c425e98..8d4e70ee9 100644 --- "a/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" +++ "b/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" @@ -126,7 +126,7 @@ _options_ :编译选项。 _filenames_ :文件名称。 -GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有些大部分并不常用,常用的 _options_ 取值如[表2](#table1342946175212)所示。 +GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但大部分并不常用,常用的 _options_ 取值如[表2](#table1342946175212)所示。 **表 2** GCC常用的编译选项 @@ -214,7 +214,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有
@@ -243,7 +243,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有 - 分别编译各个源文件,之后对编译后输出的目标文件链接。编译时只重新编译修改的文件,未修改的文件不用重新编译。 - 示例:分别编译test1.c,test2.c,在将二者的目标文件test1.o,test2.o链接成test可执行文件。 + 示例:分别编译test1.c,test2.c,再将二者的目标文件test1.o,test2.o链接成test可执行文件。 ``` $ gcc -c test1.c @@ -262,7 +262,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有 - 资源利用不一样。 - 静态库为生成的可执行文件的一部分,而动态库为单独的文件。所以使用静态库和和动态库的可执行文件大小和占用的磁盘空间大小不一样,导致资源利用不一样。 + 静态库为生成的可执行文件的一部分,而动态库为单独的文件。所以使用静态库和动态库的可执行文件大小和占用的磁盘空间大小不一样,导致资源利用不一样。 - 扩展性与兼容性不一样 -- Gitee From 69cba63a9533905040b733c29fe7c03dc7e83283 Mon Sep 17 00:00:00 2001 From: Judith Date: Thu, 12 May 2022 10:37:20 +0000 Subject: [PATCH 29/42] =?UTF-8?q?update=20docs/zh/docs/ApplicationDev/?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E7=8E=AF=E5=A2=83=E5=87=86=E5=A4=87.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...17\221\347\216\257\345\242\203\345\207\206\345\244\207.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" index 52cc0e383..5e5266e4c 100644 --- "a/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ "b/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" @@ -426,7 +426,7 @@ $ export PATH=$JAVA_HOME/bin:$PATH $ dnf list installed | grep gtk ``` -如果显示gtk2或者gtk3,则表示您已安装该库,可以直接跳过进入下一步,否则在root权限西下运行如下命令自动下载安装gtk库。 +如果显示gtk2或者gtk3,则表示您已安装该库,可以直接跳过进入下一步,否则在root权限下运行如下命令自动下载安装gtk库。 ``` # dnf -y install gtk2 libXtst libXrender xauth @@ -448,7 +448,7 @@ $ mkdir ~/.ssh 然后在.ssh目录下编辑config文件并保存: -1. 使用vim打卡config文件 +1. 使用vim打开config文件 ``` $ vim config -- Gitee From 9d5f232a3a1cd14d97743f6cb8457656c67c5ddb Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 16 May 2022 07:37:49 +0000 Subject: [PATCH 30/42] =?UTF-8?q?update=20score=5Fadmins.yaml.=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- score_admins.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/score_admins.yaml b/score_admins.yaml index fd5ef5469..b1a8b426a 100644 --- a/score_admins.yaml +++ b/score_admins.yaml @@ -2,4 +2,5 @@ score_admins: amy_mayun zhangcuihong lanlanbenming - rachel_123456 \ No newline at end of file + rachel_123456 + hebin03 \ No newline at end of file -- Gitee From 0d030f27b26df95f3cd8bfa3933d502975f2c43c Mon Sep 17 00:00:00 2001 From: x30004928 Date: Sat, 14 May 2022 15:23:19 +0800 Subject: [PATCH 31/42] =?UTF-8?q?isocut=20=E5=B7=A5=E5=85=B7=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20kickstart=20=E5=8A=9F=E8=83=BD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\346\214\207\345\215\227.md" | 158 ++++++++++++++++-- 1 file changed, 145 insertions(+), 13 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" index 27ad1109d..dd3eb734a 100644 --- "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -80,9 +80,9 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 ```shell $ sudo isocut -h Checking input ... - usage: isocut [-h] [-t temporary_path] [-r rpm_path] source_iso dest_iso + usage: isocut [-h] [-t temporary_path] [-r rpm_path] [-k file_path] source_iso dest_iso - Cut EulerOS iso to small one + Cut openEuler iso to small one positional arguments: source_iso source iso image @@ -92,6 +92,7 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 -h, --help show this help message and exit -t temporary_path temporary path -r rpm_path extern rpm packages path + -k file_path kickstart file ``` @@ -106,17 +107,18 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 镜像裁剪定制工具通过 isocut 命令执行功能。命令的使用格式为: -**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] < *source_iso* > < *dest_iso* > +**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] [ -k <*file_path*> ] < *source_iso* > < *dest_iso* > #### 参数说明 -| 参数 | 是否必选 | 参数含义 | -| ------------ | -------- | -------------------------------------------------------- | -| --help \| -h | 否 | 查询命令的帮助信息。 | -| -t <*temp_path*> | 否 | 指定工具运行的临时目录 *temp_path*,其中 *temp_path* 为绝对路径。默认为 /tmp 。 | -| -r <*rpm_path*> | 否 | 用户需要额外添加到 ISO 镜像中的 RPM 包路径。 | -| *source_iso* | 是 | 用于裁剪的 ISO 源镜像所在路径和名称。不指定路径时,默认当前路径。 | -| *dest_iso* | 是 | 裁剪定制生成的 ISO 新镜像存放路径和名称。不指定路径时,默认当前路径。 | +| 参数 | 是否必选 | 参数含义 | +| ---------------- | -------- | ------------------------------------------------------------ | +| --help \| -h | 否 | 查询命令的帮助信息。 | +| -t <*temp_path*> | 否 | 指定工具运行的临时目录 *temp_path*,其中 *temp_path* 为绝对路径。默认为 /tmp 。 | +| -r <*rpm_path*> | 否 | 用户需要额外添加到 ISO 镜像中的 RPM 包路径。 | +| -k <*file_path*> | 否 | 用户需要使用 kickstart 自动安装,指定 kickstart 模板路径。 | +| *source_iso* | 是 | 用于裁剪的 ISO 源镜像所在路径和名称。不指定路径时,默认当前路径。 | +| *dest_iso* | 是 | 裁剪定制生成的 ISO 新镜像存放路径和名称。不指定路径时,默认当前路径。 | @@ -126,7 +128,7 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 - 原有 ISO 镜像。该情况通过配置文件 /etc/isocut/rpmlist 指定需要安装的 RPM 软件包,配置格式为 "软件包名.对应架构",例如:kernel.aarch64 。 -- 额外指定。执行 **isocut** 时使用 -r 参数指定软件包所在路径。 +- 额外指定。执行 **isocut** 时使用 -r 参数指定软件包所在路径,并将添加的 RPM 包按上述格式添加到配置文件 /etc/isocut/rpmlist 中。 @@ -135,11 +137,136 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 >- 裁剪定制镜像时,若无法找到配置文件中指定的 RPM 包,则镜像中不会添加该 RPM 包。 >- 若 RPM 包的依赖有问题,则裁剪定制镜像时可能会报错。 - -### 操作指导 +### kickstart 功能介绍 + +用户需要实现镜像自动化安装,可以通过 kickstart 的方式。在执行 **isocut** 时使用 -k 参数指定 kickstart 文件。 + +isocut 为用户提供了 kickstart 模板,路径是 /etc/isocut/anaconda-ks.cfg,用户可以基于该模板修改。 + +#### 修改 kickstart 模板 + +若用户需要使用 isocut 工具提供的 kickstart 模板,需要修改以下内容: + +- 必须在文件 /etc/isocut/anaconda-ks.cfg 中配置 root 和 grub2 的密码。否则镜像自动化安装会卡在设置密码的环节,等待用户手动输入密码。 +- 如果要添加额外 RPM 包,并使用 kickstart 自动安装,则在 /etc/isocut/rpmlist 和 kickstart 文件的 %packages 字段都要指定该 RPM 包。 + +接下来介绍 kickstart 文件详细修改方法。 + +##### 配置初始密码 + +###### 配置 root 初始密码 + +/etc/isocut/anaconda-ks.cfg 中 root 初始密码的默认配置如下,其中 ${pwd} 需要替换成用户实际的加密密文: + +```shell +rootpw --iscrypted ${pwd} +``` + +这里给出设置 root 初始密码的方法(需使用 root 权限): + +1. 添加用于生成密码的用户,此处假设 testUser。 + + ``` shell script + $ sudo useradd testUser + ``` + +2. 设置 testUser 用户的密码。参考命令如下,根据提示设置密码: + + ``` shell script + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. 查看 /etc/shadow 文件,获取加密密码(用户 testUser 后,两个 : 间的字符串,此处使用 *** 代替)。 + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:***:19052:0:90:7:35:: + ``` + +4. 拷贝上述加密密码替换 /etc/isocut/anaconda-ks.cfg 中的 pwd 字段,如下所示(请用实际内容替换 *** ): + ``` shell script + rootpw --iscrypted *** + ``` + +###### 配置 grub2 初始密码 +/etc/isocut/anaconda-ks.cfg 文件中添加以下配置,配置 grub2 初始密码。其中 ${pwd} 需要替换成用户实际的加密密文: +```shell +%addon com_huawei_grub_safe --iscrypted --password='${pwd}' +%end +``` + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> - 配置 grub 初始密码需要使用 root 权限。 +> - grub 密码对应的默认用户为 root 。 +> +> - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 + +1. 执行如下命令,根据提示设置 grub2 密码: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.*** + ``` + +3. 复制上述密文,并在 /etc/isocut/anaconda-ks.cfg 文件中增加如下配置: + + ```shell + %addon com_huawei_grub_safe --iscrypted --password='grub.pbkdf2.sha512.***' + %end + ``` + +##### 配置 %packages 字段 + +如果需要添加额外 RPM 包,并使用 kickstart 自动安装,需要在 /etc/isocut/rpmlist 和 kickstart 文件的 %packages 字段都指定该 RPM 包。 + +此处介绍在 /etc/isocut/anaconda-ks.cfg 文件中添加 RPM 包。 + +/etc/isocut/anaconda-ks.cfg 文件的 %packages 默认配置如下: + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +%end +``` + +将额外指定的 RPM 软件包添加到 %packages 配置中,需要遵循如下配置格式: + +"软件包名.对应架构",例如:kernel.aarch64 + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +kernel.aarch64 +%end +``` + + +### 操作指导 >![](./public_sys-resources/icon-note.gif) **说明:** > @@ -200,3 +327,8 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 ```shell sudo isocut -t /home/temp -r /home/rpms /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso ``` + + **场景三**:使用 kickstart 文件实现自动化安装,需要修改 /etc/isocut/anaconda-ks.cfg 文件 + ```shell + sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso + ``` -- Gitee From 4d732671f83c15da7d945c33cfbf5b8f82cc97d5 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Mon, 23 May 2022 21:29:55 +0800 Subject: [PATCH 32/42] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=BB=98=E8=AE=A4rpm?= =?UTF-8?q?=E5=8C=85=E5=88=97=E8=A1=A8=E5=AE=89=E8=A3=85=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\346\214\207\345\215\227.md" | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" index dd3eb734a..14204524b 100644 --- "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -7,6 +7,8 @@ - [命令介绍](#命令介绍) - [软件包来源](#软件包来源) - [操作指导](#操作指导) +- [FAQ](#FAQ) + - [默认 rpm 包列表安装系统失败](#默认-rpm-包列表安装系统失败) ## 简介 @@ -332,3 +334,51 @@ kernel.aarch64 ```shell sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso ``` + + +## FAQ + +### 默认 rpm 包列表安装系统失败 + +#### 背景描述 + +用户使用 isocut 裁剪镜像时通过配置文件 /etc/isocut/rpmlist 指定需要安装的软件包。 + +由于不同版本会有软件包减少,可能导致裁剪镜像时出现缺包等问题。 +因此 /etc/isocut/rpmlist 中默认只包含 kernel 软件包。 +保证默认配置裁剪镜像必定成功。 + +#### 问题描述 + +使用默认配置裁剪出来的 iso 镜像,能够裁剪成功,但是安装可能失败。 + +安装报错缺包,报错截图如下: + +![](./figures/lack_pack.png) + +#### 原因分析 + +使用默认配置的 RPM 软件包列表,裁剪的 iso 镜像在安装时缺少必要的 RPM 包。 +缺少的包如报错的图示,并且在不同版本中,缺少的 RPM 包也可能是不同的,以安装时实际报错为准。 + +# 解决方案 + +1. 增加缺少的包 + + 1. 根据报错的提示整理缺少的 RPM 包列表 + 2. 将上述 RPM 包列表添加到配置文件 /etc/isocut/rpmlist 中。 + 3. 再次裁剪安装 iso 镜像 + + 以问题描述中的缺包情况为例,修改 rpmlist 配置文件如下: + ```shell + $ cat /etc/isocut/rpmlist + kernel.aarch64 + lvm2.aarch64 + chrony.aarch64 + authselect.aarch64 + shim.aarch64 + efibootmgr.aarch64 + grub2-efi-aa64.aarch64 + dosfstools.aarch64 + ``` + -- Gitee From f7b731c7cf0f2a8dd72da59c2eb07239468e34eb Mon Sep 17 00:00:00 2001 From: gomico Date: Wed, 25 May 2022 18:20:08 +0800 Subject: [PATCH 33/42] revise some KubeOS docs --- docs/en/docs/KubeOS/about-kubeos.md | 12 +++--- .../file-system-layout-of-a-container-os.png | Bin 42326 -> 28281 bytes .../KubeOS/figures/kubeos-architecture.png | Bin 190442 -> 90848 bytes .../KubeOS/installation-and-deployment.md | 39 +++++++++--------- docs/en/docs/KubeOS/usage-instructions.md | 18 ++++---- 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/docs/en/docs/KubeOS/about-kubeos.md b/docs/en/docs/KubeOS/about-kubeos.md index 0793503e8..54feebcea 100644 --- a/docs/en/docs/KubeOS/about-kubeos.md +++ b/docs/en/docs/KubeOS/about-kubeos.md @@ -4,9 +4,9 @@ Containers and Kubernetes are widely used in cloud scenarios. However, a current manner of managing the containers and the OSs separately usually faces problems of function redundancy and difficult collaboration between scheduling systems. In addition, it is difficult to manage OS versions. Software packages are installed, updated, and deleted separately in OSs of the same version. After a period of time, the OS versions become inconsistent, causing version fragmentation. Besides, the OSs may be tightly coupled with services, making it difficult to upgrade major versions. To solve the preceding problems, openEuler provides KubeOS, a container OS upgrade tool based on openEuler. -Container OSs are lightweight OSs designed for scenarios where services run in containers. KubeOS connects container OSs as components to Kubernetes, so that the container OSs are in the same position as services. The Kubernetes cluster manages containers and container OSs in a unified system. +Container OSs are lightweight OSs designed for scenarios where services run in containers. KubeOS connects container OSs as components to Kubernetes, so that the container OSs are in the same position as services. With KubeOS, a Kubernetes cluster manages containers and container OSs in a unified system. -KubeOS is a Kubernetes operator for controlling the container OS upgrade process and upgrading the container OSs as a whole to implement collaboration between the OS manager and services. Before the container OSs are upgraded, services are migrated to other nodes to reduce the impact on services during OS upgrade and configuration. In this upgrade pattern, the container OSs are upgraded atomically so that the OSs remain synchronized with the expected status. This ensures that the OS versions in the cluster are consistent, preventing version fragmentation. +KubeOS is a Kubernetes operator for controlling the container OS upgrade process and upgrading the container OSs as a whole to implement collaboration between the OS managers and services. Before the container OSs are upgraded, services are migrated to other nodes to reduce the impact on services during OS upgrade and configuration. In this upgrade pattern, the container OSs are upgraded atomically so that the OSs remain synchronized with the expected status. This ensures that the OS versions in the cluster are consistent, preventing version fragmentation. ## Architecture @@ -16,13 +16,13 @@ KubeOS is a Kubernetes operator for controlling the container OS upgrade process ![](./figures/kubeos-architecture.png) -As shown in the preceding figure, KubeOS consists of three components: os-operator, os-proxy, and os-agent. The os-operator and os-proxy components run in containers and are deployed in the Kubernetes cluster. The os-agent component does not belong to the cluster and runs on worker nodes as processes. +As shown in the preceding figure, KubeOS consists of three components: os-operator, os-proxy, and os-agent. The os-operator and os-proxy components run in containers and are deployed in the Kubernetes cluster. os-agent is not considered a cluster component. Its instances run on worker nodes as processes. - os-operator: global container OS manager, which continuously checks the container OS versions of all nodes, controls the number of nodes to be upgraded concurrently based on the configured information, and marks the nodes to be upgraded. - os-proxy: OS manager of a single node, which continuously checks the container OS version of the node. If a node is marked as the node to be upgraded by os-operator, the node is locked, the pod is evicted, and the upgrade information is forwarded to os-agent. -- os-agent: receives information from the proxy, downloads the container OS image used for upgrade from the OS image server, upgrades the container OS, and restarts the node. +- os-agent: receives information from os-proxy, downloads the container OS image used for upgrade from the OS image server, upgrades the container OS, and restarts the node. ### File System of a Container OS @@ -37,6 +37,6 @@ As shown in the figure, a container OS comprises four partitions: - boot partition: GRUB2 file partition. - Persist partition: stores persistent user data. When the container OS is upgraded, the data in this partition is retained. -- Two root partitions: A container OS uses the dual-partition mode with two root partitions, rootA and rootB. Assume that the system runs on the rootA partition after initialization. When the system is upgraded, the new system is downloaded to the rootB partition. GRUB has two boot options: A and B. The default boot option of GRUB is set to B and the node is restarted. After the node is started, the container OS runs on the updated rootB partition. +- Two root partitions: Container OSs use the dual-partition mode with two root partitions, rootA and rootB. Assume that the container runs the OS stored in the rootA partition after initialization. When the system is upgraded, the new system is downloaded to the rootB partition. GRUB has two boot options: A and B. The default boot option of GRUB is set to B and the node is restarted. After the node is started, the container runs the upgraded OS in the rootB partition. -The root file system of the container OS is read-only. Users' persistent data is stored in the Persist partition. +The root file system of a container OS is read-only. Users' persistent data is stored in the Persist partition. diff --git a/docs/en/docs/KubeOS/figures/file-system-layout-of-a-container-os.png b/docs/en/docs/KubeOS/figures/file-system-layout-of-a-container-os.png index b4a3af27b6dd7f23dc6f45ec4601bfceabbf5e9a..add62e72f85b103b7dd5780d2e360049f5f712df 100644 GIT binary patch literal 28281 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 literal 42326 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 VkBC(9HtN9N>43Wf>APbW{tps!E2;nh diff --git a/docs/en/docs/KubeOS/figures/kubeos-architecture.png b/docs/en/docs/KubeOS/figures/kubeos-architecture.png index 7d32855d3167706975c2323109005af3ffb1b4f5..7834a3793b73c49ddd046502c65335a08f576c30 100644 GIT binary patch literal 90848 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

DQ+9|mxdL?!c(ddGMkt$C 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%0A=%#;K2@`kTsf}57)owUC+k- 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 CKD-YA diff --git a/docs/en/docs/KubeOS/installation-and-deployment.md b/docs/en/docs/KubeOS/installation-and-deployment.md index 1ce8f8070..0c0d8cf5c 100644 --- a/docs/en/docs/KubeOS/installation-and-deployment.md +++ b/docs/en/docs/KubeOS/installation-and-deployment.md @@ -45,7 +45,7 @@ This chapter describes how to install and deploy the KubeOS tool. To install KubeOS, perform the following steps: -1. Configure the Yum sources: openEuler 21.09 and openEuler 21.09:EPOL: +1. Configure the Yum sources openEuler 21.09 and openEuler 21.09:EPOL: ``` [openEuler21.09] # openEuler 21.09 official source @@ -108,9 +108,9 @@ Before using Docker to create a container image, ensure that Docker has been ins 4. Compile a Dockerfile to build an image. Pay attention to the following points when compiling a Dockerfile: - * The os-operator and os-proxy images must be built based on the base image. Ensure the security of the base image. + * The os-operator and os-proxy images must be built based on the base image. Ensure that the base image is safe. * Copy the os-operator and os-proxy binary files to the corresponding images. - * Ensure that the **root** owner and owner group are assigned for the os-proxy binary file in the os-proxy image, and the file permission is **500**. + * Ensure that the owner and owner group of the os-proxy binary file in the os-proxy image are the **root** user, and the file permission is **500**. * Ensure that the owner and owner group of the os-operator binary file in the os-operator image are the user who runs the os-operator process in the container, and the file permission is **500**. * The locations of the os-operator and os-proxy binary files in the image and the commands run during container startup must correspond to the parameters specified in the YAML file used for deployment. @@ -128,9 +128,9 @@ Before using Docker to create a container image, ensure that Docker has been ins ENTRYPOINT ["/operator"] ``` - You can build the Dockerfile in multiple phases. + Alternatively, you can use multi-stage builds in the Dockerfile. -5. Build the images to be deployed in containers (os-operator and os-proxy images). +5. Build the images (the os-operator and os-proxy images) to be included in the containers OS image. ```shell # Specify the Dockerfile path of os-proxy. @@ -142,7 +142,7 @@ Before using Docker to create a container image, ensure that Docker has been ins docker build -t ${IMG_PROXY} -f ${DOCKERFILE_PROXY} . ``` -6. Push the container images to the image repository. +6. Push the images to the image repository. ```shell docker push ${IMG_OPERATOR} @@ -155,29 +155,29 @@ Before using Docker to create a container image, ensure that Docker has been ins #### Precautions * The **root** permissions are required for creating a container OS image. -* The RPM package source of the container OS image build tool is the full ISO file of openEuler, for example, **openEuler-21.09-everything-x86_64-dvd.iso**. -* By default, the container OS image built using the default RPM list is stored in the same path as the build tool. This partition must have at least 25 GiB free disk space. +* The RPM package source of the container OS image is the Everything and EPOL repositories of a specific version of openEuler. You are advised to configure both the Everything and EPOL repositories as Yum sources in the repo file provided for creating the image. +* By default, the container OS image built using the default RPM list is stored in the same path as the build tool. This partition must have at least 25 GiB free space. * When creating a container OS image, you cannot customize the file system to be mounted. #### Procedure The command for creating a container OS is as follows: -`generate.sh` *ISO_PATH VERSION AGENT_PATH ENCRYPTED_PASSWD* +`generate.sh` *REPO_PATH VERSION AGENT_PATH ENCRYPTED_PASSWD* The parameters are described as follows: -- `ISO_PATH`: full ISO file path +- `REPO_PATH`: repo file path - `AGENT_PATH`: os-agent binary file path * `VERSION`: version of the created container OS image -* `ENCRYPTED_PASSWD`: password of the **root** user of the container OS image. The password is encrypted with a salt value and can be generated using OpenSSL or KIWI commands. +* `ENCRYPTED_PASSWD`: password of the **root** user of the container OS image. The password must be encrypted and salted. You can generate a password using OpenSSL or KIWI commands. To create a container OS, perform the following steps: -1. Go to the execution directory. +1. Go to the working directory. ```shell cd /opt/kubeOS/scripts @@ -186,31 +186,32 @@ To create a container OS, perform the following steps: 2. Run `generate.sh` to create the container OS. The following is a command example: ```shell - bash generate.sh openEuler-21.09-everything-x86_64-dvd.iso v1 ../bin/os-agent '''$1$xyz$RdLyKTL32WEvK3lg8CXID0''' + bash generate.sh xx.repo v1 ../bin/os-agent '''$1$xyz$RdLyKTL32WEvK3lg8CXID0''' ``` + In the command, **xx.repo** indicates the actual Yum source file used for creating the image. You are advised to configure both the Everything and EPOL repositories as Yum sources. After the container OS image is created, the following files are generated in the **/opt/kubeOS/scripts** directory: - **system.qcow2**: system image. The default size of **system.qcow2** is 20 GiB. The size of the root file system partition is less than 2020 MiB, and the size of the Persist partition is less than 16 GiB. - **update.img**: partition image of the root file system that is used for upgrade. - The created container OS image can be used only in the VM of the x86 or AArch64 architecture. + The created container OS image can be used only in a VM of the x86 or AArch64 architecture. ### Deploying CRD, os-operator, and os-proxy #### Precautions -* Deploy the Kubernetes cluster first. For details, see the _openEuler 21.09 Kubernetes Cluster Deployment Guide_. +* The Kubernetes cluster must be deployed first. For details, see the _openEuler 21.09 Kubernetes Cluster Deployment Guide_. -- The OS of the worker nodes to be upgraded in the cluster must be the container OS built using the method described in the previous section. If it is not, use **system.qcow2** to deploy the VM again. For details about how to deploy a VM, see the _openEuler 21.09 Virtualization User Guide_. Currently, the master nodes do not support container OS upgrade. Use openEuler 21.09 to deploy the upgrade on the master nodes. -- Compile the YAML files for deploying CustomResourceDefinition (CRD), os-operator, os-proxy, and role-based access control (RBAC) of the OS. +- The OS of the worker nodes to be upgraded in the cluster must be the container OS built using the method described in the previous section. If it is not, use **system.qcow2** to deploy the VM again. For details about how to deploy a VM, see the _openEuler 21.09 Virtualization User Guide_. Currently, KubeOS does not support the master nodes. Use openEuler 21.09 to deploy the upgrade on the master nodes. +- The YAML files for deploying CustomResourceDefinition (CRD), os-operator, os-proxy, and role-based access control (RBAC) of the OS need to be compiled. - The os-operator and os-proxy components are deployed in the Kubernetes cluster. os-operator must be deployed as a Deployment, and os-proxy as a DaemonSet. -- Deploy Kubernetes security mechanisms, such as the RBAC, pod service account, and security policy. +- Kubernetes security mechanisms, such as the RBAC, pod service account, and security policies, must be deployed. #### Procedure -1. Prepare YAML files, including those used for deploying CRD, RBAC, os-operator, and os-proxy of the OS. For details, see [YAML examples](https://gitee.com/openeuler/KubeOS/tree/master/docs/example/config). The following uses **crd.yaml**, **rbac.yaml**, and **manager.yaml** as examples. +1. Prepare YAML files used for deploying CRD, RBAC, os-operator, and os-proxy of the OS. For details, see [YAML examples](https://gitee.com/openeuler/KubeOS/tree/master/docs/example/config). The following uses **crd.yaml**, **rbac.yaml**, and **manager.yaml** as examples. 2. Deploy CRD, RBAC, os-operator, and os-proxy. Assume that the **crd.yaml**, **rbac.yaml**, and **manager.yaml** files are stored in the **config/crd**, **config/rbac**, and **config/manager** directories, respectively. Run the following commands: diff --git a/docs/en/docs/KubeOS/usage-instructions.md b/docs/en/docs/KubeOS/usage-instructions.md index 9e54dda2e..1c9c6738f 100644 --- a/docs/en/docs/KubeOS/usage-instructions.md +++ b/docs/en/docs/KubeOS/usage-instructions.md @@ -24,14 +24,14 @@ ## Precautions -1. KubeOS provides atomic upgrade for all software packages. By default, single-package upgrade is not supported. +1. KubeOS upgrades the container OS in an atomic manner, where all software packages are upgraded at the same time. By default, single-package upgrade is not supported. 2. KubeOS supports container OSs with two partitions. Partitions more than two are not supported. 3. You can view the upgrade logs of a single node in the **/var/log/messages** file on the node. -4. Strictly follow the upgrade and rollback processes described in this document. If the processes are invoked in an abnormal sequence, the system may fail to be upgraded or rolled back. +4. Strictly follow the upgrade and rollback procedures described in this document. If the steps are performed in a wrong sequence, the system may fail to be upgraded or rolled back. ## Upgrade -Compile the YAML file to deploy the instance of the OS custom resource (CR) in the cluster. The following is an example YAML file for deploying the CR instance: +Compile the YAML file for deploying the OS as a custom resource (CR) instance in the cluster. The following is an example YAML file for deploying the CR instance: ``` apiVersion: upgrade.openeuler.org/v1alpha1 @@ -50,15 +50,15 @@ Parameter description: | Parameter | Description | Mandatory (Yes/No)| | -------------- | ----------------------------------- | -------- | -| osversion | Address of the image used for the upgrade | Yes | -| imageurl | Version of the OS image used for the upgrade | Yes | +| osversion | Version of the OS image used for the upgrade | Yes | +| imageurl | Address of the OS image used for the upgrade | Yes | | maxunavailable | Number of nodes that are upgraded concurrently | Yes | | checksum | Checksum (SHA-256) value of the image used for the upgrade| Yes | | flagsafe | Whether `imageurl` specifies a secure address| Yes | -The address specified by `imageurl` contains the protocol. Only the HTTP or HTTPS protocol is supported. If `imageurl` is set to an HTTPS address, secure transmission is used. If `imageurl` is set to an HTTP address, set `flagsafe` to `true`, because the image can be downloaded only when the address is secure. If `imageurl` is set to an HTTP address but `flagsafe` is not set to `true`, the address is insecure by default. The image will not be downloaded, and a message is written to the log of the node to be upgraded indicating that the address is insecure. +The address specified by `imageurl` contains the protocol. Only the HTTP or HTTPS protocol is supported. If `imageurl` is set to an HTTPS address, secure transmission is used. If `imageurl` is set to an HTTP address, set `flagsafe` to `true`, because the image can be downloaded only when the address is secure. If `imageurl` is set to an HTTP address but `flagsafe` is not set to `true`, the address is considered insecure by default. The image will not be downloaded, and a message is written to the log of the node to be upgraded indicating that the address is insecure. -You are advised to set `imageurl` to an HTTPS address. In this case, ensure that the required certificate has been installed on the node to be upgraded. If the image server is maintained by yourself, you need to sign the certificate and ensure that the certificate has been installed on the node to be upgraded. Place the certificate in the **/etc/pki/ca-trust/source/anchors** directory of the container OS and run the `update-ca-trust extract` command to install the certificate. The administrator specifies the address and must ensure the security of the address. The intranet address is recommended. +You are advised to set `imageurl` to an HTTPS address. In this case, ensure that the required certificate has been installed on the node to be upgraded. If the image server is maintained by yourself, you need to sign the certificate and ensure that the certificate has been installed on the node to be upgraded. Place the certificate in the **/etc/pki/ca-trust/source/anchors** directory of the container OS and run the `update-ca-trust extract` command to install the certificate. The administrator specifies the address and must ensure the security of the address. An intranet address is recommended. Assume that the YAML file is **upgrade_v1alpha1_os.yaml**. @@ -82,7 +82,7 @@ kubectl get nodes -o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.osI > ![](./public_sys-resources/icon-note.gif)**NOTE**: > -> If the upgrade needs to be performed again, modify the `imageurl`, `osversion`, `checksum`, `maxunavailable`, or `flagsafe` parameter in the **upgrade_v1alpha1_os.yaml** file. +> If the upgrade needs to be performed again, modify the `imageurl`, `osversion`, `checksum`, `maxunavailable`, and `flagsafe` parameters in the **upgrade_v1alpha1_os.yaml** file. ## Rollback @@ -107,7 +107,7 @@ Manually restart the node and select the second boot option to roll back the con After the update is complete, the node rolls back the container OS based on the configuration information. -3. Check the OS version of the container on the node to determine whether the rollback is successful. +3. Check the container OS version on the node to determine whether the rollback is successful. ``` kubectl get nodes -o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.osImage' -- Gitee From 64ca75a6354070ea75862ce7b23722c793ca9f7c Mon Sep 17 00:00:00 2001 From: x30004928 Date: Sat, 28 May 2022 16:26:34 +0800 Subject: [PATCH 34/42] =?UTF-8?q?isocut=E4=BD=BF=E7=94=A8=E6=8C=87?= =?UTF-8?q?=E5=8D=97=E6=B7=BB=E5=8A=A0lack=5Fpack.png=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/TailorCustom/figures/lack_pack.png | Bin 0 -> 33182 bytes ...\277\347\224\250\346\214\207\345\215\227.md" | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/zh/docs/TailorCustom/figures/lack_pack.png diff --git a/docs/zh/docs/TailorCustom/figures/lack_pack.png b/docs/zh/docs/TailorCustom/figures/lack_pack.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b7f1da15da70f63a86aae360e89017c2b98f2d GIT binary patch literal 33182 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 Date: Tue, 28 Jun 2022 17:32:19 +0800 Subject: [PATCH 35/42] =?UTF-8?q?update=20=E5=AF=B9=E6=8E=A5libvirt.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\257\271\346\216\245libvirt.md" | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" "b/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" index d655ecb9f..3b22a8384 100644 --- "a/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" +++ "b/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" @@ -460,7 +460,7 @@ XML 中还有一些体系架构相关的配置,如 pflash、主板等。 /path/to/standard_vm_kernel console=hvc0 root=/dev/vda reboot=k panic=1 rw /path/to/pflash - /path/to/OVMF_VARS + /path/to/OVMF_VARS @@ -626,7 +626,7 @@ libvirt 使用 virsh 命令来管理虚拟机,当 StratoVirt 平台和 libvirt ### 管理虚拟机生命周期 -假设用户已经按照需要完成一个名为 stratovirt 的虚拟机配置文件 st.xml ,则对应生命周期管理的命令如下: +假设用户已经按照需要完成一个名为 StratoVirt 的虚拟机配置文件 st.xml ,则对应生命周期管理的命令如下: - 创建虚拟机 @@ -634,40 +634,40 @@ libvirt 使用 virsh 命令来管理虚拟机,当 StratoVirt 平台和 libvirt virsh create st.xml ``` - 虚拟机创建完成后,可以通过 **virsh list** 命令查看,会存在一个名为 stratovirt 的虚拟机。 + 虚拟机创建完成后,可以通过 **virsh list** 命令查看,会存在一个名为 StratoVirt 的虚拟机。 - 挂起虚拟机 ```shell - virsh suspend stratovirt + virsh suspend StratoVirt ``` - 虚拟机挂起后,虚拟机暂停运行。可以通过 **virsh list** 命令查看,虚拟机 stratovirt 的状态为 paused 。 + 虚拟机挂起后,虚拟机暂停运行。可以通过 **virsh list** 命令查看,虚拟机 StratoVirt 的状态为 paused 。 - 恢复虚拟机 ``` - virsh resume stratovirt + virsh resume StratoVirt ``` - 虚拟机恢复后,可以通过 **virsh list** 命令查看,虚拟机 stratovirt 的状态为 running 。 + 虚拟机恢复后,可以通过 **virsh list** 命令查看,虚拟机 StratoVirt 的状态为 running 。 - 销毁虚拟机 ``` - virsh destroy stratovirt + virsh destroy StratoVirt ``` - 虚拟机销毁后,使用 **virsh list** 查看虚拟机,发现虚拟机 stratovirt 不存在。 + 虚拟机销毁后,使用 **virsh list** 查看虚拟机,发现虚拟机 StratoVirt 不存在。 ### 登录虚拟机 -虚拟机创建完成后,可以通过 **virsh console** 登录虚拟机内部操作虚拟机。假设虚拟机名称为 stratovirt,参考命令如下: +虚拟机创建完成后,可以通过 **virsh console** 登录虚拟机内部操作虚拟机。假设虚拟机名称为 StratoVirt,参考命令如下: ``` -virsh console stratovirt +virsh console StratoVirt ``` -- Gitee From 2c6114b7a406d00abfd06a278b88ae26593aa272 Mon Sep 17 00:00:00 2001 From: "Xinle.Guo" Date: Fri, 24 Jun 2022 14:21:40 +0800 Subject: [PATCH 36/42] stratovirt: remove strating vm with json file StratoVirt does not support json file to start virtual machine. Delete related content from docs. Signed-off-by: Xinle.Guo --- ...37\346\234\272\347\256\241\347\220\206.md" | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" index ce0609811..17944d23d 100644 --- "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" +++ "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" @@ -72,7 +72,7 @@ StratoVirt可以对虚拟机进行启动、暂停、恢复、退出等生命周 ### 创建并启动虚拟机 -根据虚拟机配置可知,可以通过命令行参数或json文件指定虚拟机配置,并在主机通过stratovirt命令创建并启动虚拟机。 +通过命令行参数指定虚拟机配置,创建并启动虚拟机。 - 使用命令行参数给出虚拟机配置,创建并启动虚拟机的命令如下: @@ -80,23 +80,9 @@ StratoVirt可以对虚拟机进行启动、暂停、恢复、退出等生命周 $ /path/to/stratovirt -[参数1] [参数选项] -[参数2] [参数选项] ... ``` - - -- 使用json文件给出虚拟机配置,创建并启动虚拟机的命令如下: - -``` -$ /path/to/stratovirt \ - -config /path/to/json \ - -qmp unix:/path/to/socket -``` - -其中,/path/to/json为json配置文件的路径。/path/to/socket为用户指定的socket文件(如/tmp/stratovirt.socket),使用上述命令会自动创建socket文件。为确保虚拟机能够正常启动,在创建socket文件前确保该文件不存在。 - - - -> ![](./figures/zh-cn_image_0218587436.png) +> ![](./public_sys-resources/icon-note.gif)说明: > -> 虚拟机启动后,内部会有eth0和eth1两张网卡。这两张网卡预留用于网卡热插拔。热插的第一张网卡是eth0,热插的第二张网卡是eth1,目前只支持热插2张virtio-net网卡。 +> 轻量虚拟启动后,内部会有eth0和eth1两张网卡。这两张网卡预留用于网卡热插拔。热插的第一张网卡是eth0,热插的第二张网卡是eth1,目前只支持热插两张virtio-net网卡。 @@ -120,7 +106,7 @@ StratoVirt当前采用QMP管理虚拟机,暂停、恢复、退出虚拟机等 -> ![](./figures/zh-cn_image_0218587436.png) +> ![](./public_sys-resources/icon-note.gif)说明: > > QMP提供了stop、cont、quit和query-status等来管理和查询虚拟机状态。 > -- Gitee From 73a5b3347a3c9a74dbebd46ffbd0e2a121d208e5 Mon Sep 17 00:00:00 2001 From: YeXiao Date: Mon, 27 Jun 2022 16:05:32 +0800 Subject: [PATCH 37/42] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0:Stra?= =?UTF-8?q?toVirt=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97-=E5=87=86=E5=A4=87?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=8E=AF=E5=A2=83=201.=20alpine-mini=20rootf?= =?UTF-8?q?s=E4=B8=8B=E8=BD=BD=E8=B7=AF=E5=BE=84=E6=9B=B4=E6=96=B0=202.=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8E=A8=E8=8D=90=E5=86=85=E6=A0=B8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=9E=E6=8E=A5=E6=9B=B4=E6=96=B0=203.=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\347\216\257\345\242\203.md" | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" index f9890b5e5..43e7d2e59 100644 --- "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" +++ "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" @@ -4,7 +4,7 @@ ## 使用说明 - StratoVirt仅支持运行于x86_64和AArch64处理器架构下并启动相同架构的Linux虚拟机。 -- 建议在 openEuler 21.09 版本编译、调测和部署该版本 StratoVirt。 +- 建议在 openEuler 22.03 版本编译、调测和部署该版本 StratoVirt。 - StratoVirt支持以非root权限运行。 ## 环境要求 @@ -50,17 +50,17 @@ 1. 获取openEuler的kernel源代码,参考命令如下: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. 查看并切换kernel的版本到5.10,参考命令如下: +2. 查看并切换kernel的版本到openEuler-22.03-LTS,参考命令如下: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. 配置并编译Linux kernel。可使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将其复制到kernel路径下并重命名为`.config`。也可通过以下命令进行交互,根据提示完成kernel配置。 +3. 配置并编译Linux kernel。目前有两种方式可以生成配置文件:1. 使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将指定版本的推荐文件复制到kernel路径下并重命名为`.config`, 并执行命令`make olddefconfig`更新到最新的默认配置(否则后续编译可能有选项需要手动选择)。2. 通过以下命令进行交互,根据提示完成kernel配置,可能会提示缺少指定依赖,按照提示使用`yum install`命令进行安装。 ``` $ make menuconfig @@ -109,21 +109,21 @@ rootfs镜像是一种文件系统镜像,在StratoVirt启动时可以装载带 4. 获取对应处理器架构的最新alpine-mini rootfs。 - - 如果是AArch64处理器架构,参考命令如下: + - 对于AArch64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-aarch64.tar.gz ,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - 如果是x86_64处理器架构,参考命令如下: + - 对于x86_64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取指定架构最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-x86_64.tar.gz,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` -- Gitee From af410494cc9d4d03f31ca50d7e9148a9e27a22aa Mon Sep 17 00:00:00 2001 From: zhouli57 Date: Tue, 7 Jun 2022 19:55:48 +0800 Subject: [PATCH 38/42] StratoVirt: update StratoVirt version Signed-off-by: zhouli57 --- docs/en/docs/StratoVirt/Install_StratoVirt.md | 2 +- "docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/StratoVirt/Install_StratoVirt.md b/docs/en/docs/StratoVirt/Install_StratoVirt.md index b9a9fd8a1..4751e1131 100644 --- a/docs/en/docs/StratoVirt/Install_StratoVirt.md +++ b/docs/en/docs/StratoVirt/Install_StratoVirt.md @@ -31,7 +31,7 @@ To use StratoVirt virtualization, it is necessary to install StratoVirt. Before ``` $ stratovirt -version - StratoVirt 2.0.0 + StratoVirt 2.1.0 ``` diff --git "a/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" "b/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" index 81a8d9d21..fdfc80929 100644 --- "a/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" +++ "b/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" @@ -33,7 +33,7 @@ ``` $ stratovirt -version - StratoVirt 2.0.0 + StratoVirt 2.1.0 ``` -- Gitee From ec847e9d74e8a81b762b8ca6cf5fc94cc0ba883e Mon Sep 17 00:00:00 2001 From: YeXiao Date: Mon, 27 Jun 2022 16:05:32 +0800 Subject: [PATCH 39/42] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0:Stra?= =?UTF-8?q?toVirt=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97-=E5=87=86=E5=A4=87?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=8E=AF=E5=A2=83=201.=20alpine-mini=20rootf?= =?UTF-8?q?s=E4=B8=8B=E8=BD=BD=E8=B7=AF=E5=BE=84=E6=9B=B4=E6=96=B0=202.=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8E=A8=E8=8D=90=E5=86=85=E6=A0=B8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=9E=E6=8E=A5=E6=9B=B4=E6=96=B0=203.=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/StratoVirt/Prepare_env.md | 26 +++++++++---------- ...77\347\224\250\347\216\257\345\242\203.md" | 26 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/en/docs/StratoVirt/Prepare_env.md b/docs/en/docs/StratoVirt/Prepare_env.md index 55689ef71..54f80ed27 100644 --- a/docs/en/docs/StratoVirt/Prepare_env.md +++ b/docs/en/docs/StratoVirt/Prepare_env.md @@ -4,7 +4,7 @@ ## Usage - StratoVirt can run on VMs with the x86_64 or AArch64 processor architecture. -- You are advised to compile, debug, and deploy StratoVirt on openEuler 21.09. +- You are advised to compile, debug, and deploy StratoVirt on openEuler 22.03 LTS. - StratoVirt can run with non-root permissions. ## Environment Requirements @@ -50,17 +50,17 @@ StratoVirt of the current version supports only the PE kernel image of the x86_6 1. Run the following commands to obtain the kernel source code of openEuler: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. Run the following command to check and switch to the kernel version 5.10: +2. Run the following command to check and switch to the kernel version openEuler-22.03-LTS: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. Configure and compile the Linux kernel. It is better to use the recommended configuration file ([Obtain configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy it to the kernel directory, and rename it as **.config**. You can also run the following command to configure the kernel as prompted: +3. Configure and compile the Linux kernel. It is better to use the recommended configuration file ([Obtain configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy it to the kernel directory, and rename it as **.config**. And run the command 'make olddefconfig' to update to the latest default configuration (otherwise, there may be options for subsequent compilation that need to be manually selected). You can also run the following command to configure the kernel as prompted: ``` $ make menuconfig @@ -107,21 +107,21 @@ The rootfs image is a file system image. When StratoVirt is started, the ext4 im 4. Obtain the latest alpine-mini rootfs of the corresponding processor architecture. - - If the AArch64 processor architecture is used, run the following command: + - If the AArch64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-aarch64.tar.gz, the reference command is as follows: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - If the x86_64 processor architecture is used, run the following command: + - If the x86_64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-x86_64.tar.gz, the reference command is as follows: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` diff --git "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" index f9890b5e5..5c17d7213 100644 --- "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" +++ "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" @@ -4,7 +4,7 @@ ## 使用说明 - StratoVirt仅支持运行于x86_64和AArch64处理器架构下并启动相同架构的Linux虚拟机。 -- 建议在 openEuler 21.09 版本编译、调测和部署该版本 StratoVirt。 +- 建议在 openEuler 22.03 LTS 版本编译、调测和部署该版本 StratoVirt。 - StratoVirt支持以非root权限运行。 ## 环境要求 @@ -50,17 +50,17 @@ 1. 获取openEuler的kernel源代码,参考命令如下: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. 查看并切换kernel的版本到5.10,参考命令如下: +2. 查看并切换kernel的版本到openEuler-22.03-LTS,参考命令如下: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. 配置并编译Linux kernel。可使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将其复制到kernel路径下并重命名为`.config`。也可通过以下命令进行交互,根据提示完成kernel配置。 +3. 配置并编译Linux kernel。目前有两种方式可以生成配置文件:1. 使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将指定版本的推荐文件复制到kernel路径下并重命名为`.config`, 并执行命令`make olddefconfig`更新到最新的默认配置(否则后续编译可能有选项需要手动选择)。2. 通过以下命令进行交互,根据提示完成kernel配置,可能会提示缺少指定依赖,按照提示使用`yum install`命令进行安装。 ``` $ make menuconfig @@ -109,21 +109,21 @@ rootfs镜像是一种文件系统镜像,在StratoVirt启动时可以装载带 4. 获取对应处理器架构的最新alpine-mini rootfs。 - - 如果是AArch64处理器架构,参考命令如下: + - 对于AArch64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-aarch64.tar.gz ,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - 如果是x86_64处理器架构,参考命令如下: + - 对于x86_64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取指定架构最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-x86_64.tar.gz,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` -- Gitee From f09324f4a0127f52004a8fc640bd930d3241f921 Mon Sep 17 00:00:00 2001 From: z30023234 Date: Tue, 12 Jul 2022 17:25:14 +0800 Subject: [PATCH 40/42] add secGear desc --- .../\345\256\211\350\243\205secGear.md" | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git "a/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" "b/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" index 79b42ebe9..222b2a0ab 100644 --- "a/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" +++ "b/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" @@ -1,14 +1,41 @@ # 安装 secGear -## 环境要求 +## 操作系统 -当前 secGear 仅支持以下软硬件,后续会逐步支持更多的软硬件。 +openEuler 21.03、openEuler 20.03 LTS SP2 或更高版本 -- 处理器:当前 secGear 仅支持 x86_64 处理器架构,且该处理器需要支持 Intel SGX (Intel Software Guard Extensions)功能 +## CPU 架构 -- 操作系统:openEuler 21.03 或更高版本 +#### x86_64 +需要有 Intel SGX ( Intel Software Guard Extensions ) 功能 + +#### AArch64 + + - 硬件要求 + + | 项目 | 版本 | + | ------ | --------------------------------------------- | + | 服务器 | TaiShan 200 服务器(型号 2280),仅限双路服务器 | + | 主板 | 鲲鹏主板 | + | BMC | 1711 单板(型号 BC82SMMAB) | + | CPU | 鲲鹏 920 处理器(型号 7260、5250、5220) | + | 机箱 | 不限,建议 8 盘或 12 盘 | + + 要求运行的泰山服务器已经预置了 TrustZone 特性,即预装 iTrustee 安全 OS 以及配套的 BMC、BIOS 固件。 + + - 运行环境要求 + + CA(Client Application)应用需要 REE(Rich Execution Environment)侧 patch 才能实现与 TEE(Trusted Execution Environment)侧的 TA(Trusted Application)应用通信,在安装 secGear 前,请先搭建运行环境,操作如下: + + 1. [搭建 TA/CA 应用运行环境](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0007.html#:~:text=%E6%90%AD%E5%BB%BA%3E%20%E6%90%AD%E5%BB%BA%E6%AD%A5%E9%AA%A4-,%E6%90%AD%E5%BB%BA%E6%AD%A5%E9%AA%A4,-%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%EF%BC%9A2022) + + 2. 申请调测环境TA应用开发者证书 + + a. [生成 configs.xml 文件](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#:~:text=%E5%88%86%E4%BA%AB-,%E7%94%9F%E6%88%90configs.xml%E6%96%87%E4%BB%B6,-%E6%A0%B9%E6%8D%AEmanifest.txt) + + b. [申请 TA 开发者证书](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#:~:text=%E5%86%85%E5%AE%B9%E4%BA%88%E4%BB%A5%E6%9B%BF%E6%8D%A2%E3%80%82-,TA%E5%BC%80%E5%8F%91%E8%80%85%E8%AF%81%E4%B9%A6%E7%94%B3%E8%AF%B7,-%E7%94%9F%E6%88%90%E6%9C%AC%E5%9C%B0%E5%AF%86) ## 安装指导 @@ -21,15 +48,9 @@ #yum install secGear-devel ``` - - -2. 查看安装是否成功。参考命令和回显如下表示安装成功。 +2. 查看安装是否成功。参考命令如下,若回显有对应软件包,表示安装成功: ```shell #rpm -q secGear - secGear-1.0-1.oe1.x86_64 #rpm -q secGear-devel - secGear-devel-1.0-1.oe1.x86_64 - ``` - - + ``` \ No newline at end of file -- Gitee From a6bbd96679e2a110353cd605ac5bc47f0c09c4fd Mon Sep 17 00:00:00 2001 From: z30023234 Date: Wed, 13 Jul 2022 09:29:44 +0800 Subject: [PATCH 41/42] fix invalid links --- ...1secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" index 2b3773d61..f74da9fee 100644 --- "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" +++ "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" @@ -419,7 +419,7 @@ 将设备公钥文件 rsa_public_key_cloud.pem 复制到 enclave 目录。此处的设备公钥用于使用临时生成的 aes 密钥对安全区动态库进行加密。 - 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/secGear/blob/master/examples/helloworld/enclave/rsa_public_key_cloud.pem + 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/itrustee_sdk/blob/master/build/signtools/cloud/rsa_public_key_cloud.pem -- Gitee From 13385e15667ba0c0d89d6717e518f82633f73e8c Mon Sep 17 00:00:00 2001 From: "Xinle.Guo" Date: Wed, 13 Jul 2022 17:22:07 +0800 Subject: [PATCH 42/42] stratovirt: update doc Update the doc that stratovirt support guest kernel version 4.19 and 5.10. Signed-off-by: Xinle.Guo --- .../zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" "b/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" index 26f48c670..9842e25a6 100644 --- "a/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" +++ "b/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" @@ -46,6 +46,6 @@ StratoVirt核心架构自顶向下分为三层: #### 约束 -- 仅支持Linux操作系统,推荐内核版本为4.19; -- 虚拟机操作系统仅支持Linux,内核版本建议为4.19; +- 仅支持Linux操作系统,推荐内核版本为4.19, 5.10; +- 虚拟机操作系统仅支持Linux,内核版本建议为4.19, 5.10; - 最大支持254个CPU; -- Gitee

Vendor

-shared

默认选项,可省略。

-
  • 可以生成动态库文件。
  • 进行动态编译,优先链接动态库,只有没有动态库是才会链接同名的静态库。
+
  • 可以生成动态库文件。
  • 进行动态编译,优先链接动态库,只有没有动态库时才会链接同名的静态库。

-