Chiến lược triển khai / lưu trữ các trang web tĩnh dựa trên javascript trong các thùng chứa


7

Điều này thỉnh thoảng xuất hiện trong một số nhóm phát triển của chúng tôi, mà chúng tôi không tìm ra cách "đúng":

Chúng tôi sử dụng rất nhiều ứng dụng web dựa trên phản ứng "biên dịch" vào các trang web tĩnh chỉ là một vài tệp html, js và css.

Tuy nhiên, "tòa nhà" của các ứng dụng này có một số biến cho phép / vô hiệu hóa cờ tính năng, định cấu hình các url phụ trợ, v.v. Điều này có nghĩa là chúng ta không thể "xây dựng" một nhị phân theo nghĩa truyền thống và chỉ áp dụng tệp cấu hình khi triển khai- thời gian - bản thân "bản dựng" cần phải có các biến cụ thể cho môi trường này và do đó, lần duy nhất chúng ta có thể "xây dựng" là tại thời điểm triển khai.

Hiện tại, chúng tôi giải quyết điều này bằng cách đưa các biến môi trường cần thiết vào bộ chứa Docker và chạy cmd bắt đầu dọc theo dòng

npm build && nginx run

Điều này có một vài nhược điểm:

  1. Quá trình xây dựng cần rất nhiều cpu / bộ nhớ so với yêu cầu thời gian chạy của container. Điều đó có nghĩa là chúng ta cần mở rộng quy mô container cho quá trình xây dựng thay vì các yêu cầu về thời gian chạy - điều này cảm thấy sai
  2. Thất bại xây dựng là khó để "theo dõi". Chúng tôi có thể sử dụng kiểm tra sức khỏe trong Kubernetes, nhưng nếu quá trình xây dựng mất 2 phút, chúng tôi vẫn phải chờ 3 phút (thêm 1 lần cho an toàn) trước khi chúng tôi có thể bắt đầu kiểm tra điểm cuối kiểm tra sức khỏe của người chứa để xem nó còn sống hay không.
  3. Việc triển khai có thể mất nhiều thời gian: Nếu chúng tôi định cấu hình Kubernetes để thực hiện triển khai "nối tiếp", nó sẽ bắt đầu mỗi nhóm và chờ trong khoảng thời gian "initDelay" 2-3 phút trước khi bắt đầu kế tiếp. Điều này có nghĩa là chúng ta dễ dàng xem xét thời gian triển khai 10 phút nếu việc triển khai được thu nhỏ thành 3-4 nhóm.

Tất cả điều này cảm thấy rất tối ưu với tôi. Tôi rất muốn nghe cách cộng đồng giải quyết câu hỏi hóc búa "xây dựng tại thời điểm triển khai" với các ứng dụng web javascript hiện đại.

Tôi nhận ra rằng đối với Kubernetes, chúng ta có thể sử dụng "init-container" để thực hiện quá trình xây dựng, đặt các tạo phẩm vào bộ lưu trữ liên tục và sau đó các thùng chứa ứng dụng chỉ cần lấy từ bộ lưu trữ liên tục trong khi khởi động, nhưng điều này vẫn giống như "bỏ qua" vấn đề hơn giải quyết vấn đề gốc.


Xin lỗi, tôi không hiểu - tại sao bạn chạy npm buildtrong thời gian chạy thay vì trong quá trình xây dựng container?
Xiong Chiamiov

@XiongChiamiov tôi giả sử cấu hình frontend được thực hiện trong quá trình xây dựng và không thể thay đổi mà không cần xây dựng lại (tôi muốn tranh luận nó nên được tách ra trong một tập tin bao gồm trong đó, lúc xấu nhất, có thể là 'sed' lúc khởi động container)
Tensibai

chính xác. npm buildchỉ là một lệnh tùy ý. Có thể react buildhoặc sanity buildbất cứ điều gì mà khung công tác JS mong đợi. Chúng tôi buộc phải làm điều đó khi triển khai container vì đó là khi chúng tôi biết môi trường để buildlàm.
Trondh

Câu trả lời:


5

Từ quan điểm của tôi, cách tiếp cận tốt nhất sẽ là:

  1. Phân tách quá trình xây dựng bằng cách sử dụng Jenkins sẽ xây dựng dự án NodeJS thành phân phối và bọc nó thành hình ảnh Docker
  2. Quay lên đăng ký Docker sẽ tích lũy hình ảnh Docker từ Jenkins (đăng ký này có thể truy cập được từ cụm Kubernetes)
  3. Di chuyển các biến môi trường sang bí mật Jenkins hoặc sử dụng công cụ riêng biệt để thu thập và kết hợp các cấu hình từ repo Git bên ngoài (chúng tôi sử dụng Spring Cloud Config thông qua API REST để thu thập các định nghĩa json / yml cho mọi ứng dụng trong mọi môi trường)

Sử dụng Jenkins, bạn có thể định cấu hình hệ thống phân phối liên tục dựa trên các Đường ống chung. Dòng chảy có thể sẽ là:

  1. Các nhà phát triển hoàn thành công việc của họ tương ứng với GitFlow (Yêu cầu kéo mới nhất được sáp nhập vào nhánh Phát hành)
  2. Webhook kích hoạt đường ống dẫn Jenkins:
    • Giai đoạn 1: thu thập định nghĩa môi trường
    • Giai đoạn 2: xây dựng ứng dụng NodeJS bằng npm
    • Giai đoạn 3: xây dựng hình ảnh Nginx Docker với phân phối
    • Giai đoạn 4: đẩy hình ảnh Docker vào đăng ký Docker
    • Giai đoạn 5: triển khai / cập nhật dịch vụ trong Kubernetes bằng các định nghĩa chuẩn
  3. Thông báo gửi về kết quả

Quá trình này có thể được hình dung bằng Rancher. Tôi có thể trả lời câu hỏi của bạn trong trò chuyện.


Vì vậy, bạn đang đề xuất để có một hình ảnh cho mỗi môi trường? Đó là một cách giải quyết tiêu tốn một loạt không gian cho một số biến số ...
Tensibai

@Tensibai ur nói về ~ 15mb hình ảnh cho mỗi môi trường. Với vòng quay và dịch vụ người gác cổng bổ sung, 1 Gb sẽ đủ để xử lý tất cả các dự án.
Maksim

Dựa trên giải pháp này, làm thế nào bạn có thể tạo ra nhiều "cấu hình" của một ứng dụng, ví dụ một cho "dàn dựng" và một cho "prod"? (giả sử, chẳng hạn, có một cài đặt gọi là "BackendApi" khác nhau.
Trondh

@Trondh như tôi đã nói, chúng tôi sử dụng Spring Cloud Config. Những gì nó làm là cho mỗi ứng dụng, nó được cấu hình cơ bản và áp dụng các cấu hình bổ sung từ đó profiles. Ví dụ: nếu bạn yêu cầu https://config/backend.ymlbạn sẽ nhận được cấu hình từ application.ymlvà các thuộc tính bổ sung từ backend.yml. Vì https://config/backend-stage.ymlnó sẽ đáp ứng với các thuộc tính được áp dụng bởi application.yml<- backend.yml<- backend-stage.yml.
Maksim

@Maksim 15 MB cho một vài byte văn bản là một sự lãng phí, tại một số điểm với hàng trăm dịch vụ siêu nhỏ trên các môi trường khác nhau với các phiên bản khác nhau, chúng sẽ trở thành TB dữ liệu cho cùng một vài byte gốc. Theo quan điểm của tôi, đó là một con đường sai nếu tôi hiểu đúng những gì bạn đề xuất, vì bạn không thể đảm bảo hình ảnh trong QA và prod thực sự giống như chúng từ hai bản dựng (ngay cả với cùng một mã, chúng sẽ không cùng id và xác nhận trở thành một mớ hỗn độn). Nhưng có lẽ tôi đã nhận được nó và bạn chỉ có một hình ảnh và cấu hình khi quay pod, nếu vậy tôi không hiểu bài của bạn đúng.
Tensibai
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.