1 điểm bởi GN⁺ 21 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Yocto không phải là một bản phân phối mà là công cụ để tự lắp ráp bản phân phối Linux riêng, và nếu không cần mức độ kiểm soát đó thì khó coi đây là lựa chọn mặc định
  • Bản phân phối riêng đồng nghĩa với tự bảo trì, kéo theo cả trách nhiệm cập nhật bảo mật trong suốt vòng đời sản phẩm và đáp ứng các quy định như CRA
  • Việc áp dụng Yocto đi kèm thời gian build hàng giờ, thư mục build vượt 100GiB, đường cong học tập kéo dài nhiều tuần và các lớp BSP có chất lượng rất không đồng đều
  • Nếu chỉ cần một nền Linux vững chắc để chạy ứng dụng thì Debian cùng các công cụ tạo image như mkosi, ELBE, debos có thể đã đủ với khối lượng công việc theo từng dự án ít hơn nhiều
  • Yocto chỉ thực sự vượt trội khi cần tùy biến sâu, bị ràng buộc về kích thước hay thời gian khởi động, cần loại trừ giấy phép, hoặc có hỗ trợ Yocto từ nhà cung cấp thật sự vững; nếu còn phân vân thì bản phân phối có sẵn thường tốt hơn

Bản chất thực sự của Yocto và vì sao nó thường thành lựa chọn mặc định

  • Yocto không phải là “bản phân phối Yocto Linux” mà là bộ công cụ để tạo ra bản phân phối Linux riêng
  • Yocto Project đồng thời cung cấp bản phân phối tham chiếu Poky được tạo từ bitbake, openembedded-core, meta-yocto
  • Yocto cho phép lắp ráp rất chi tiết hệ thống Linux cần cho các dự án nhúng
    • Có thể biên dịch toàn bộ user space cho CPU đích
    • Có thể áp dụng patch cho bất kỳ thành phần nào
    • Có thể bật hoặc tắt tính năng của từng recipe
    • Có thể cố định hoặc thay đổi mọi phiên bản
  • Nhiều nhà cung cấp SoC và đối tác phần cứng cung cấp các lớp BSP (Board Support Package) dùng được ngay, tạo điểm khởi đầu chạy được trên phần cứng thực tế
  • Chính sự kết hợp giữa tính linh hoạt và hỗ trợ từ vendor khiến Yocto thường trở thành lựa chọn mặc định, nhưng nếu không cần mức kiểm soát đó thì gánh nặng có thể còn lớn hơn lợi ích

Bản phân phối riêng đồng nghĩa với tự bảo trì

  • Các quy định như Cyber Resilience Act (CRA) yêu cầu nhà cung cấp sản phẩm phải giữ cho phần mềm họ phát hành luôn an toàn và cung cấp cập nhật bảo mật trong suốt vòng đời sản phẩm
  • Một bản phát hành Yocto thông thường chỉ được duy trì khoảng 7 tháng cho tới khi bản phát hành tiếp theo ra mắt
  • Từ Yocto 5.0 Scarthgap, theo chính sách hiện tại các bản phát hành LTS sẽ nhận cập nhật tối đa 4 năm
  • Một bản phát hành Yocto gồm tập recipe bitbake với các phiên bản và metadata xác định, cùng bản phân phối tham chiếu Poky
  • Trong thời gian bảo trì, các maintainer của Yocto áp dụng sửa lỗi và vá bảo mật cho các thành phần và cho Poky, còn các chỉnh sửa phần mềm thường được backport từ phiên bản upstream mới nhất
  • Trong sản phẩm thực tế, rất dễ có các thay đổi so với Yocto nguyên bản như sau
    • Áp dụng các patch không đơn giản hoặc thay đổi cục bộ cho một số thành phần
    • Bổ sung các thành phần mà Yocto không cung cấp
    • Nâng cấp hoặc cố định phiên bản để nhận sửa lỗi hoặc giữ trạng thái đã biết là tốt
  • Mỗi khi có bản bảo trì Yocto mới, cần kiểm tra xem các thay đổi cục bộ còn áp dụng sạch lên trạng thái mới hay không
  • Với các thành phần được thêm vào hoặc bị cố định phiên bản, maintainer Yocto không thể biết đến chúng, nên bạn cũng phải tự xác nhận rằng chúng vẫn tiếp tục nhận được các bản sửa lỗi
  • Nếu bạn dùng Poky gần như không thay đổi, thì nên xem lại lý do vì sao cần Yocto ngay từ đầu

Linux kernel và sự phụ thuộc vào vendor

  • Yocto có cung cấp và bảo trì Linux kernel như một phần của mỗi bản phát hành, nhưng trong sản phẩm thực tế hiếm khi dùng nguyên vẹn không sửa đổi
  • Thông thường ít nhất cũng phải áp dụng patch từ vendor, và cần dùng kernel đủ mới để có các driver và bản sửa cần thiết
  • Nếu tính cả việc theo dõi CVE thì riêng kernel đã là gánh nặng bảo trì lớn, bất kể có dùng Yocto hay không
  • Để kiểm soát gánh nặng bảo trì, nên xây dựng trên kernel LTS từ kernel.org và giữ mọi thay đổi trong một hàng đợi patch được tổ chức gọn gàng
  • Để bám theo các bản vá bảo mật, hãy chuyển sang bản stable mới rồi áp lại hàng đợi patch
  • kernel.org duy trì kernel LTS trong nhiều năm, vì vậy thông thường hàng đợi patch sẽ áp dụng sạch, và chỉ khi chuyển sang bản LTS mới mới cần công sức đáng kể
  • Tùy cấu hình và yêu cầu bảo mật, nguyên tắc tương tự cũng áp dụng cho bootloader, vốn cũng thường mang tính đặc thù vendor rất cao
  • Giữ nguyên kernel do vendor cung cấp thường là một lựa chọn không tốt
    • kernel của vendor thường chậm hơn kernel.org nhiều năm
    • Hầu như không nhận cập nhật
    • Bỏ lỡ phần lớn các bản vá bảo mật

Chi phí áp dụng Yocto

  • Quyết định tạo bản phân phối riêng đòi hỏi thời gian kỹ thuật thật sự
  • Thời gian build

    • Yocto biên dịch gần như mọi thứ từ mã nguồn
    • Ngay cả build sạch cho một image không quá đơn giản cũng mất hàng giờ trên workstation nhanh
    • sstate-cacheDL_DIR dùng chung giúp tăng tốc các lần build lặp lại, nhưng chỉ một thay đổi nhỏ trong recipe cũng có thể làm mất hiệu lực phần lớn cache
  • Chi phí đĩa và CI

    • Thư mục build Yocto rất dễ phình lên hơn 100GiB
    • CI runner cần đủ dung lượng lưu trữ và cơ chế chia sẻ sstate giữa các job
    • Có thể bớt đau đầu bằng cách mirror sstateDL_DIR, nhưng hạ tầng đó bạn phải tự vận hành
  • Đường cong học tập

    • Có rất nhiều thứ phải nắm: recipe bitbake, layer, dynamic layer, class, override, file bbappend, PACKAGECONFIG, sự khác biệt giữa DEPENDSRDEPENDS, v.v.
    • Để một kỹ sư onboard vào codebase Yocto không mất vài ngày mà là vài tuần
  • Chất lượng BSP layer chênh lệch lớn

    • Một số vendor SoC cung cấp BSP layer sạch sẽ và được bảo trì tốt
    • Các vendor khác lại cố định kernel hoặc bootloader đã 5 năm tuổi, hardcode recipe theo từng máy vào sai layer, và cung cấp layer meta-vendor cứ nâng Poky là hỏng
    • Một BSP trông như điểm khởi đầu tốt có thể lại là phần tệ nhất của toàn bộ hệ build
    • Đây không phải lý do để mặc định tránh Yocto, mà là lý do để xác nhận trước xem bạn có thật sự cần nó hay không

Phương án thay thế: tái sử dụng bản phân phối đã được kiểm chứng

  • Nếu chỉ cần một nền Linux vững chắc để chạy ứng dụng, một bản phân phối có sẵn như Debian GNU/Linux có thể giải quyết phần lớn cùng bài toán với khối lượng công việc riêng theo dự án ít hơn rất nhiều
  • Debian hiện cung cấp khoảng 70.000 gói nhị phân
  • Các kiến trúc được hỗ trợ gồm amd64, i386, arm64, armhf, riscv64, ppc64el và nhiều kiến trúc khác
  • Nhiều SoC rất có thể chạy trực tiếp binary Debian mà không cần biên dịch lại
  • Debian không chỉ là bản phân phối cung cấp một user space hiện đại có systemd, udev, dbus
  • Kho phần mềm của Debian cũng có các thành phần để tạo hệ Linux nhỏ dùng init kiểu SysV hoặc dựa trên BusyBox
  • Bạn có thể chọn nền mỏng và chỉ cài các gói cần cho sản phẩm, đồng thời tận dụng công sức của các maintainer gói Debian

Mô hình bảo trì của Debian

  • Debian stable nhận cập nhật bảo mật từ Debian Security Team trong khoảng 3 năm
  • Sau đó, dự án cộng đồng Debian LTS kéo dài hỗ trợ thêm khoảng 2 năm trên các kiến trúc phổ biến
  • Thực tế là mỗi bản phát hành có thể được hỗ trợ khoảng 5 năm, tương đương Yocto LTS nhưng với khối lượng công việc riêng theo dự án ít hơn rất nhiều
  • Để nhận các bản sửa mới nhất, chỉ cần lấy các gói Debian mới nhất và tạo lại image
  • Bản chất công việc này rất khác so với Yocto, nơi bạn phải tự backport patch upstream hoặc kiểm tra lại xem các thay đổi cục bộ còn áp dụng được trên bản bảo trì mới hay không

Cách xây dựng image nhúng

  • Một image nhúng dựa trên Debian không phải là kiểu khởi động SoC từ USB rồi chạy trình cài đặt Debian
  • Thay vào đó, image có thể flash được sẽ được tạo trên máy build host rồi ghi vào thiết bị
  • Các thành phần cần thiết là
    • Bootloader thường đặc thù SoC, ví dụ u-boot
    • Linux kernel cũng thường đặc thù SoC
    • Root filesystem dựa trên user space Linux lấy trực tiếp từ Debian
    • Công cụ lắp ráp image để kết hợp ba phần trên thành image có thể flash
  • Các lựa chọn phổ biến cho công cụ lắp ráp image là mkosi, ELBE, debos
  • Cả ba công cụ đều là phần mềm tự do và tạo ra các image có tính quyết định, có thể flash lên phần cứng
  • Công việc bảo trì giảm đi đáng kể, và phần lớn cập nhật sẽ là làm mới các gói trong image theo kiểu apt thay vì viết lại recipe

Ví dụ build Debian dựa trên debos

  • debos đọc các recipe YAML
  • Recipe là danh sách action như chạy lệnh, tạo root filesystem, cài các gói Debian từ nguồn đã cấu hình
  • Luồng cơ bản như sau
    • Vận hành một mirror Debian cục bộ bằng aptly chứa bản sao của mọi gói Debian cần thiết
    • Build Linux kernel và nếu cần thì cả bootloader thành gói Debian rồi thêm vào mirror
    • Tạo snapshot của mirror và gắn thẻ cho nó
    • Thẻ đó chính là bản phát hành
    • Cấu hình debos dùng mirror đó và viết các action trong recipe để tạo image đích
    • Nếu cần, lưu cùng image cả gói nguồn Debian và SBOM (Software Bill of Materials) của image
  • Việc lưu gói nguồn và SBOM giúp tuân thủ nghĩa vụ cung cấp mã nguồn theo GPL và yêu cầu danh mục vật liệu của CRA
  • Các công cụ như debsbom có thể tạo SBOM trực tiếp từ hệ Debian

Khi nào nên chọn Yocto

  • Yocto phù hợp khi cần bản phân phối được tùy biến sâu
    • User space tùy chỉnh
    • Cờ biên dịch tùy chỉnh
    • Thay đổi sâu với các thành phần nền tảng
  • Phù hợp khi có ràng buộc nghiêm ngặt về kích thước hoặc thời gian khởi động mà bản phân phối sẵn có không đáp ứng được
  • Phù hợp khi có ràng buộc giấy phép đòi hỏi phải loại trừ những nhóm giấy phép phổ biến
    • Một số ngành như thiết bị y tế, ô tô, một số công việc quốc phòng không phân phối thành phần GPLv3
    • Cơ chế INCOMPATIBLE_LICENSE của Yocto giúp dễ loại trừ cả một họ giấy phép khỏi toàn bộ image
    • Với Debian thông thường, bạn phải tự kiểm toán và cắt giảm gói
  • Phù hợp khi con đường hỗ trợ chính thức từ vendor SoC là Yocto và chất lượng BSP thực sự vững vàng

Khi nào nên tránh Yocto

  • Nếu chỉ cần Linux hiện đại để triển khai và chạy ứng dụng thì có thể bạn không cần Yocto
  • Nếu ngân sách lưu trữ và bộ nhớ đủ cho image Debian thông thường thì lợi thế của Yocto giảm đi
    • Mốc ví dụ là flash cỡ vài trăm MB và RAM từ 256MB trở lên
  • Nếu vòng đời sản phẩm dài và việc dựa vào Debian Security Team hợp lý hơn so với tự bảo trì thì nên tránh Yocto

Khi nào nên tránh Debian

  • Nếu bạn phải sửa đổi hoặc build lại nhiều gói Debian thì Debian trở nên bất lợi
    • Build lại vài gói vẫn có thể quản lý được
    • Mỗi gói build lại là một phần việc bảo trì do bạn tự gánh
    • Nếu phải patch hàng chục gói upstream thì tức là bạn đang tái tạo lại công việc mà maintainer Debian vốn làm giúp
    • Ở quy mô này, mô hình recipe của Yocto xử lý gọn gàng hơn
  • Nếu cần libc không phải glibc như musl hoặc uClibc thì Debian không phù hợp
    • Kho phần mềm chính của Debian nhìn chung dùng glibc
    • Muốn thay thế nó thì bạn sẽ phải tự build lại phần lớn kho phần mềm
  • Nếu cần phần mềm mới hơn rất nhiều so với những gì Debian stable cung cấp thì Debian cũng bất lợi
    • backports có thể hữu ích với một số gói
    • Nếu sản phẩm cần compiler mới hoặc runtime mới thì điều đó xung đột với Debian stable
    • Debian testing không phải đích đến cho môi trường production

Nguyên tắc ra quyết định và kết luận

  • Quyết định có dùng Yocto hay không cần được đưa ra một cách có chủ đích, từ sớm trong vòng đời sản phẩm
  • Đây là lựa chọn nền tảng rất khó đảo ngược sau khi sản phẩm đã được triển khai ngoài thực địa
  • Nếu còn nghi ngờ, tốt hơn là bắt đầu với một bản phân phối có sẵn
  • Chi phí chuyển sang Yocto về sau, khi đã có lý do thực sự, thấp hơn nhiều so với việc phát hiện giữa dự án rằng mình đã gánh nhiều năm bảo trì mà không thu được lợi ích tương xứng
  • Yocto là một thành quả kỹ thuật xuất sắc, cho phép tạo ra đúng hệ Linux bạn cần, nhưng chính mức kiểm soát chính xác đó lại trở thành vấn đề khi bạn không thật sự cần nó
  • Lập luận này cũng gần như áp dụng nguyên vẹn cho các công cụ build từ mã nguồn khác như Buildroot
  • Khoảnh khắc bạn bắt đầu lắp ráp bản phân phối riêng cũng là lúc bạn trực tiếp sở hữu trách nhiệm bảo trì của nó
  • Kết luận cốt lõi là rất rõ ràng
    • “Bản phân phối riêng” thực chất có nghĩa là tự bảo trì
    • CRA và các quy định tương tự biến chi phí đó thành gánh nặng có thật
    • Một bản build Yocto đã bị sửa đổi nhiều sẽ không tự động kế thừa các bản sửa từ upstream
    • Mỗi bản phát hành bảo trì đều trở thành một đợt rà soát và làm lại
    • Các bản phân phối có sẵn như Debian, được đóng image bằng mkosi, ELBE, debos, xử lý phần lớn trường hợp thông thường với ít công sức riêng theo dự án hơn nhiều
    • Khi cần kiểm soát hệ thống ở mức “phẫu thuật”, Yocto là bên thắng
    • Còn nếu không, chọn Yocto sẽ trở thành cách giải một bài toán không tồn tại theo hướng dài hơi và tốn kém

1 bình luận

 
Ý kiến trên Lobste.rs
  • Nếu con đường hỗ trợ chính thức của nhà cung cấp SoC là Yocto thì dù BSP không thật sự vững chắc, tôi vẫn thấy nó thường tốt hơn các bản port Ubuntu chất lượng thấp
    Các bản port Ubuntu khiến những việc như tích hợp RAUC hay làm root filesystem bất biến trở nên phiền phức. Tôi thật sự ghét Yocto và thứ phương ngữ bash/python biến tướng của nó, nhưng rốt cuộc vẫn bị trói vào đó

  • Tôi làm khá nhiều tư vấn về Yocto, nhưng gần như chưa từng gặp những vấn đề mà bài viết than phiền. Thường thì ngược lại, ngay cả khi Yocto là lựa chọn tốt nhất thì khách hàng vẫn cố tránh, nên phải thuyết phục ban quản lý
    Tuy vậy, việc Yocto bị ghét là điều dễ hiểu. Nó khó, dễ gây rối, chậm, và công cụ chắc chắn vẫn có thể tốt hơn. Dù vậy tôi cũng không biết có lựa chọn thay thế thực tế nào không, và cũng tò mò liệu phía BSD có thứ gì tương tự không

    • Tôi không rõ nó giống Yocto đến mức nào, nhưng cách thông thường để tạo image cho hệ thống nhúng trên FreeBSD là NanoBSD
      https://docs.freebsd.org/en/articles/nanobsd/
    • Tôi chưa dùng sâu trong thực tế và có thể nó chưa hoàn thiện bằng Yocto, nhưng buildroot có khá nhiều thứ hay
      Tôi chủ yếu dùng nó trong bối cảnh Nerves, mà về cơ bản là tổ hợp buildroot + fwup + Erlang VM và phần mềm hỗ trợ. Nó khá tiện để phát triển rồi đóng gói/phân phối các hệ thống Linux nhúng
    • Tôi không trực tiếp làm việc với các hệ thống Linux/BSD nhúng, nhưng từ góc nhìn của người từng dùng NetBSD thì chỉ riêng hệ thống build build.sh cũng đã có vẻ đủ dùng
      Bạn có thể cross-compile kernel và user space một cách dễ dàng. Nếu ở bước cuối cần thêm ứng dụng pkgsrc hoặc đưa bootloader như u-boot vào image tạo ra thì có thể phải viết thêm chút script. Có lẽ đây không phải một quy trình hoàn thiện có thể tùy biến ngay cho từng ứng dụng, nhưng làm nền tảng thì ổn
    • NetBSD được tổ chức khá tốt cho việc cross-compile hướng tới các môi trường hạn chế, và khi đã quen tay thì dùng khá dễ chịu
  • Theo chút trải nghiệm hạn chế của tôi sau khi nếm mùi sự kinh khủng của mảng nhúng, thì NixOS khá hợp cho kiểu nhu cầu này và công cụ build cũng tốt hơn Yocto rất nhiều

    • Tôi tò mò không biết trên các thiết bị ARM có vậy không. Tôi cứ nghĩ hệ sinh thái NixOS vẫn còn hơi sớm đối với những thiết bị như thế
  • Đúng lúc công ty tôi đang lên kế hoạch và bắt đầu xây dựng kernel Linux và bản phân phối tùy chỉnh cho thiết bị dùng Rockchip, nên đây là một bài rất đúng thời điểm
    BSP có vẻ sẽ cần bảo trì khá nhiều, và việc “cứ dùng” Debian có vẻ dễ quản lý hơn nhiều so với các tác vụ bitbake do tôi viết cẩu thả. Dù vậy, bản thân hệ sinh thái Yocto cũng khá ổn, và có các công cụ như kas hay isar giúp việc bắt đầu dễ dàng hơn

    • Xem README của isar thì nó có vẻ dựa trên Debian chứ không phải Yocto. Tôi tò mò không biết việc trộn cả hai có phổ biến không
      Trong bài thì nghe như là Yocto hoặc Debian, chứ không phải cách kết hợp cả hai