Bây giờ tôi đã có một dự án cỡ vừa sắp kết thúc giai đoạn "nguyên mẫu được cung cấp bởi caffeine cho trình diễn của khách hàng" và chuyển sang giai đoạn "nghĩ về tương lai". Dự án bao gồm các thiết bị dựa trên Linux với phần mềm và chương trình cơ sở và máy chủ web quản trị trung tâm. 10 nguyên mẫu hiện đang tồn tại, sản xuất dự kiến sẽ ở mức thấp 1000.
Không thành thạo trong nghệ thuật cập nhật tự động và không có nhiều thời gian, tôi đã nhanh chóng thực hiện chiến lược triển khai / tự động cập nhật phần mềm của riêng mình và thật lòng mà nói, nó rất tệ. Nó hiện bao gồm những điều sau đây:
- Một git repo được lưu trữ (GitLab) với nhánh phát hành sản xuất (lưu ý nguồn máy chủ web cũng nằm trong cùng repo này, cũng như một vài thứ khác).
- Nút "triển khai cập nhật" trên giao diện web:
- Kéo phiên bản mới nhất từ nhánh phát hành sản xuất vào khu vực repo cục bộ và cũng sao chép nó vào khu vực dàn dựng gói chuẩn bị tạm thời.
- Chạy một kịch bản khử trùng (được lưu trữ trong repo) trong khu vực tổ chức để loại bỏ các tệp nguồn không liên quan (ví dụ: nguồn máy chủ, nguồn phần sụn, v.v.) và các tệp .git.
- Viết hàm git hiện tại vào một tệp trong gói cập nhật (mục đích sẽ trở nên rõ ràng bên dưới).
- Nếu mọi việc suôn sẻ, nó sẽ điều chỉnh nó và làm cho nó sẵn sàng phục vụ bằng cách ghi đè gói đã được nén trước đó bằng một tệp có cùng tên, sau đó xóa khu vực tổ chức.
- Lưu ý rằng hiện tại có hai bản sao của phần mềm thiết bị hiện tại trên máy chủ, dự kiến sẽ được đồng bộ hóa: Một bản git đầy đủ cục bộ trên nhánh sản xuất mới nhất và gói gzipped sẵn sàng hiện được coi là đại diện cho điều đó cùng phiên bản.
- Phần mềm trên thiết bị được chứa trong một thư mục có tên
/opt/example/current
, đây là một liên kết tượng trưng cho phiên bản hiện tại của phần mềm. - Chức năng tự động cập nhật trên thiết bị, khi khởi động:
- Kiểm tra sự hiện diện của một
do_not_update
tập tin và không có hành động nào thêm nếu nó tồn tại (đối với các thiết bị dev, xem bên dưới). - Đọc hàm băm cam kết hiện tại từ tệp văn bản đã đề cập ở trên.
- Tạo một yêu cầu HTTP đến máy chủ với hàm băm đó làm tham số truy vấn. Máy chủ sẽ phản hồi với 304 (băm là phiên bản hiện tại) hoặc sẽ phục vụ gói cập nhật được nén.
- Cài đặt gói cập nhật, nếu nhận được, vào
/opt/example
:- Trích xuất thông tin phần mềm cập nhật một thư mục có tên
stage
. - Chạy một kịch bản sau khi cài đặt từ gói cập nhật, thực hiện những việc như thực hiện các thay đổi cục bộ cần thiết cho bản cập nhật đó, v.v.
- Sao chép thư mục gốc phần mềm hiện tại vào
previous
(xóaprevious
trước, nếu có). - Sao chép
stage
thư mục vàolatest
(xóalatest
trước, nếu có). - Đảm bảo các
current
liên kết tượng trưng để trỏ đếnlatest
. - Khởi động lại thiết bị (cập nhật firmware, nếu có, được áp dụng khi khởi động lại).
- Trích xuất thông tin phần mềm cập nhật một thư mục có tên
- Kiểm tra sự hiện diện của một
Ngoài ra còn có vấn đề triển khai ban đầu trên các thiết bị mới được xây dựng. Các thiết bị hiện đang dựa trên thẻ SD (có vấn đề riêng, nằm ngoài phạm vi ở đây) vì vậy quy trình này bao gồm:
- Một hình ảnh SD tồn tại có một số phiên bản phần mềm ổn định trước đó trên đó.
- Một thẻ SD được tạo ra từ hình ảnh này.
- Trong lần khởi động đầu tiên, việc khởi tạo khác nhau (dựa trên số sê-ri) dành riêng cho thiết bị lần đầu tiên diễn ra và sau đó trình cập nhật tự động lấy và cài đặt phiên bản sản xuất mới nhất của phần mềm như bình thường.
Ngoài ra, tôi cần hỗ trợ cho các thiết bị phát triển. Đối với các thiết bị phát triển:
- Một repo git địa phương đầy đủ được duy trì trên thiết bị.
- Các
current
symlink trỏ đến thư mục phát triển. - Một
do_not_update
tệp cục bộ tồn tại để ngăn trình cập nhật tự động thổi bay mã phát triển với bản cập nhật sản xuất.
Bây giờ, quá trình triển khai đã được dự định trên lý thuyết là:
- Khi mã đã sẵn sàng để triển khai, đẩy nó đến nhánh phát hành.
- Nhấn nút "triển khai cập nhật" trên máy chủ.
- Bản cập nhật hiện đang hoạt động và các thiết bị sẽ tự động cập nhật vào lần kiểm tra tiếp theo.
Tuy nhiên, có một tấn của các vấn đề trong thực tế:
- Mã máy chủ web nằm trong cùng một repo với mã thiết bị và máy chủ có một repo git cục bộ mà tôi thực hiện. Mã máy chủ web mới nhất không nằm trên cùng nhánh với mã thiết bị mới nhất. Cấu trúc thư mục có vấn đề. Khi nút "triển khai cập nhật" kéo phiên bản mới nhất từ nhánh sản xuất, nó sẽ kéo nó vào thư mục con của mã máy chủ. Điều này có nghĩa là khi tôi triển khai đến một máy chủ từ đầu, tôi phải tự "gieo" thư mục con này bằng cách lấy nhánh sản xuất thiết bị vào nó, bởi vì, có lẽ là do lỗi người dùng git, nếu tôi không cố gắng triển khai kéo mã thiết bị từ nhánh máy chủ web của thư mục mẹ . Tôi nghĩ điều này có thể giải quyết được bằng cách làm cho khu vực tổ chức không phải là thư mục con của repo git cục bộ của máy chủ.
- Máy chủ web hiện không duy trì băm git của phần mềm thiết bị. Khi khởi động máy chủ, nó thực hiện
git rev-parse HEAD
repo phần mềm thiết bị cục bộ để lấy lại hàm băm hiện tại. Vì những lý do tôi không thể che giấu điều này cũng gây ra vô số lỗi logic mà tôi sẽ không mô tả ở đây, đủ để nói rằng đôi khi khởi động lại máy chủ làm hỏng mọi thứ, đặc biệt là nếu máy chủ hoàn toàn mới và không sản xuất repo chi nhánh đã được kéo. Tôi vui vẻ chia sẻ nguồn cho logic đó nếu được yêu cầu, nhưng bài đăng này đang trở nên dài. - Nếu vì lý do nào đó, kịch bản khử trùng (phía máy chủ) không thành công, thì máy chủ sẽ bị bỏ lại một gói cập nhật nhưng gói cập nhật không đồng bộ / bị thiếu, do đó
git rev-parse HEAD
sẽ trả về hàm băm không khớp với thực tế được phục vụ cho các thiết bị và các sự cố ở đây phải được sửa chữa thủ công trên dòng lệnh máy chủ. Tức là máy chủ không biết gói cập nhật không chính xác, nó chỉ luôn luôn giả định như vậy với đức tin thuần túy. Điều này kết hợp với các điểm trước đó làm cho máy chủ cực kỳ mong manh trong thực tế. - Một trong những vấn đề lớn nhất là : Hiện tại không có trình nền cập nhật riêng biệt nào đang chạy trên thiết bị. Do các biến chứng đang chờ truy cập internet wifi và một số tin tặc vào phút cuối, đây là phần mềm điều khiển thiết bị chính tự kiểm tra và cập nhật thiết bị. Điều này có nghĩa là nếu bằng cách nào đó, một phiên bản được thử nghiệm kém khiến nó được sản xuất và phần mềm điều khiển không thể khởi động, thì tất cả các thiết bị tồn tại về cơ bản đều bị brick, vì nó không thể tự cập nhật nữa. Đây sẽ là một cơn ác mộng tuyệt đối trong sản xuất. Thỏa thuận tương tự cho một thiết bị duy nhất nếu nó mất điện vào thời điểm không may mắn.
- Vấn đề lớn khác là : Không có hỗ trợ cho các cập nhật gia tăng. Nếu một thiết bị, giả sử, không được bật trong một thời gian, thì lần sau khi cập nhật thiết bị, nó bỏ qua một loạt các phiên bản phát hành, nó phải có thể thực hiện cập nhật bỏ qua phiên bản trực tiếp. Hậu quả của việc triển khai được cập nhật này là một cơn ác mộng về việc đảm bảo rằng mọi cập nhật đã cho đều có thể được áp dụng trên bất kỳ phiên bản nào trước đây. Hơn nữa, vì băm git được sử dụng để xác định các phiên bản thay vì số phiên bản, nên việc so sánh từ điển của các phiên bản để tạo điều kiện cập nhật gia tăng hiện không thể thực hiện được.
- Một yêu cầu mới mà hiện tại tôi không hỗ trợ là sẽ tồn tại một số tùy chọn cấu hình trên mỗi thiết bị (cặp khóa / giá trị) phải được cấu hình ở phía máy chủ quản trị. Tôi không bận tâm bằng cách nào đó phục vụ các tùy chọn trên mỗi thiết bị này trở lại thiết bị trong cùng một yêu cầu HTTP như bản cập nhật phần mềm (có lẽ tôi có thể gói nó trong tiêu đề / cookie HTTP) mặc dù tôi không quá lo lắng về điều này, vì tôi có thể luôn luôn làm cho nó một yêu cầu HTTP riêng.
- Có một sự phức tạp nhỏ do thực tế là có hai phiên bản (và nhiều hơn nữa trong tương lai) của phần cứng tồn tại. Phiên bản hiện tại của phần cứng thực sự được lưu trữ dưới dạng biến môi trường trên hình ảnh SD ban đầu (chúng không thể tự nhận dạng) và tất cả phần mềm được thiết kế để tương thích với tất cả các phiên bản của thiết bị. Các bản cập nhật phần sụn được chọn dựa trên biến môi trường này và gói cập nhật chứa phần sụn cho tất cả các phiên bản phần cứng. Tôi có thể sống với điều này mặc dù nó có một chút lộn xộn.
- Hiện tại không có cách nào để tải lên bản cập nhật cho thiết bị theo cách thủ công (câu chuyện ngắn là các thiết bị này có hai bộ điều hợp wifi, một để kết nối với internet và một ở chế độ AP mà người dùng sử dụng để định cấu hình thiết bị; trong tương lai Tôi dự định thêm chức năng "cập nhật phần mềm" vào giao diện web cục bộ của thiết bị). Đây không phải là một vấn đề lớn nhưng có một số tác động đến phương pháp cài đặt cập nhật.
- Một loạt các thất vọng khác và sự không an toàn nói chung.
Vì vậy, ... đó là dài. Nhưng câu hỏi của tôi sôi nổi về vấn đề này:
Làm thế nào để tôi làm điều này đúng cách và an toàn? Có những điều chỉnh nhỏ nào tôi có thể thực hiện cho quy trình hiện tại của mình không? Có chiến lược / hệ thống hiện có nào được thử nghiệm mà tôi có thể tận dụng để tôi không phải tung ra hệ thống cập nhật nhảm nhí của riêng mình không? Hoặc nếu tôi phải tự lăn lộn, đâu là những điều phải đúng để quá trình triển khai / cập nhật được an toàn và thành công? Tôi cũng phải có thể bao gồm các thiết bị phát triển trong hỗn hợp.
Tôi hy vọng câu hỏi là rõ ràng. Tôi nhận ra nó hơi mờ nhạt, nhưng tôi chắc chắn 100% rằng đây là vấn đề đã được giải quyết trước đó và được giải quyết thành công, tôi chỉ không biết các chiến lược hiện đang được chấp nhận là gì.