Chúng tôi yêu Python tại Nylas. Cú pháp đơn giản và rõ ràng, có rất nhiều mô-đun và khung mã nguồn mở có sẵn, cộng đồng rất thân thiện và đa dạng. Chương trình phụ trợ của chúng tôi được viết riêng bằng Python và nhóm của chúng tôi thường xuyên nói chuyện tại PyCon và các buổi gặp mặt. Bạn có thể nói chúng tôi là những người hâm mộ cuồng nhiệt
Tuy nhiên, một trong những nhược điểm lớn của Python là thiếu các công cụ rõ ràng để triển khai các ứng dụng máy chủ Python. Trạng thái của nghệ thuật dường như là "chạy git pull và cầu nguyện", đây không phải là một tùy chọn khi người dùng phụ thuộc vào ứng dụng của bạn. Việc triển khai Python thậm chí còn trở nên phức tạp hơn khi ứng dụng của bạn có nhiều phụ thuộc cũng đang di chuyển. Bình luận HN này tóm tắt tình trạng tồi tệ của việc triển khai Python
Tại sao sau nhiều năm, tôi không có cách nào gửi phần mềm được viết bằng python, ở định dạng deb?
Tại Nylas, chúng tôi đã phát triển một cách tốt hơn để triển khai mã Python cùng với các phần phụ thuộc của nó, dẫn đến các gói nhẹ có thể dễ dàng cài đặt, nâng cấp hoặc gỡ bỏ. Và chúng tôi đã hoàn thành việc đó mà không cần chuyển đổi toàn bộ ngăn xếp của mình sang một hệ thống như Docker, CoreOS hoặc AMI hoàn chỉnh
Triển khai trăn đầu tiên của em bé. git & pip
Python cung cấp một hệ sinh thái mô-đun phong phú. Cho dù bạn đang xây dựng một máy chủ web hay một bộ phân loại học máy, có thể có một mô-đun để giúp bạn bắt đầu. Cách tiêu chuẩn hóa ngày nay để nhận các mô-đun này là thông qua pip, tải xuống và cài đặt từ Chỉ mục gói Python [còn gọi là PyPI]. Điều này giống như apt, yum, rubygem, v.v.
Hầu hết mọi người thiết lập môi trường phát triển của họ bằng cách sao chép mã đầu tiên bằng git, sau đó cài đặt các phụ thuộc qua pip. Vì vậy, có lý do tại sao đây cũng là cách mà hầu hết mọi người lần đầu tiên thử triển khai mã của họ. Một tập lệnh triển khai có thể trông giống như thế này
git-pull-pip-install-deploy.sh git clone //github.com/company/somerepo.git cd /opt/myproject pip install -r requirements.txt python start_server.py
Nhưng khi triển khai dịch vụ sản xuất lớn, chiến lược này bị phá vỡ vì nhiều lý do
pip không cung cấp chiến lược “hoàn nguyên triển khai”
Việc chạy
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine1 không phải lúc nào cũng hoạt động bình thường và không có cách nào để “khôi phục” về trạng thái trước đó. Virtualenv có thể trợ giúp việc này, nhưng nó thực sự không được xây dựng để quản lý lịch sử môi trường.
Việc cài đặt các phần phụ thuộc với pip có thể khiến quá trình triển khai trở nên chậm chạp
Gọi
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine2 cho một mô-đun có phần mở rộng C thường sẽ xây dựng mô-đun đó từ nguồn, có thể mất vài phút để hoàn thành một . Triển khai phải là một quy trình nhẹ, nhanh, diễn ra trong vài giây.
Việc xây dựng mã của bạn một cách riêng biệt trên mỗi máy chủ sẽ gây ra các vấn đề về tính nhất quán
Khi bạn triển khai bằng pip, phiên bản ứng dụng của bạn đang chạy không được đảm bảo giống nhau giữa các máy chủ. Lỗi trong quá trình xây dựng hoặc các phụ thuộc hiện có dẫn đến sự không nhất quán khó gỡ lỗi.
**Triển khai sẽ không thành công nếu PyPI hoặc máy chủ git của bạn ngừng hoạt động
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine2 và
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine4 đôi khi phụ thuộc vào máy chủ bên ngoài. Bạn có thể chọn sử dụng các hệ thống của bên thứ ba [e. g. Github, PyPI] hoặc thiết lập máy chủ của riêng bạn. Bất kể, điều quan trọng là phải đảm bảo rằng quy trình triển khai của bạn đáp ứng cùng kỳ vọng về thời gian hoạt động và quy mô. Các dịch vụ bên ngoài thường gặp lỗi đầu tiên khi bạn mở rộng quy mô cơ sở hạ tầng của riêng mình, đặc biệt là với các triển khai lớn.
Nếu bạn đang chạy một ứng dụng mà mọi người phụ thuộc vào và chạy nó trên nhiều máy chủ, thì chiến lược git+pip sẽ chỉ khiến bạn đau đầu. Điều chúng tôi cần là một chiến lược triển khai nhanh, nhất quán và đáng tin cậy. Cụ thể hơn
- Khả năng xây dựng mã thành một tạo phẩm duy nhất, được phiên bản
- Kiểm tra đơn vị và hệ thống có thể kiểm tra tạo tác được phiên bản
- Một cơ chế đơn giản để cài đặt/gỡ cài đặt sạch các tạo phẩm từ các máy chủ từ xa
Có ba điều này sẽ cho phép chúng tôi dành nhiều thời gian hơn để xây dựng các tính năng và ít thời gian hơn để vận chuyển mã của chúng tôi theo cách nhất quán
“Chỉ cần sử dụng Docker”
Thoạt nhìn, đây có vẻ là một công việc hoàn hảo cho Docker, công cụ quản lý vùng chứa phổ biến. Trong Dockerfile, người ta chỉ cần thêm một tham chiếu đến kho lưu trữ mã và cài đặt các thư viện và phụ thuộc cần thiết. Sau đó, chúng tôi tạo một hình ảnh Docker và gửi nó dưới dạng tạo tác được phiên bản tới các máy chủ từ xa
Tuy nhiên, chúng tôi đã gặp phải một số vấn đề khi cố gắng thực hiện điều này
- Phân phối hình ảnh Docker trong một mạng riêng cũng yêu cầu một dịch vụ riêng mà chúng tôi sẽ cần định cấu hình, kiểm tra và bảo trì
- Việc chuyển đổi tự động hóa thiết lập ansible của chúng tôi sang Dockerfile sẽ rất khó khăn và yêu cầu rất nhiều thủ thuật xấu xí với cấu hình ghi nhật ký, quyền của người dùng, quản lý bí mật, v.v.
Ngay cả khi chúng tôi thành công trong việc khắc phục các sự cố này, nhóm kỹ thuật của chúng tôi sẽ phải học cách giao tiếp với Docker để gỡ lỗi các sự cố sản xuất. Chúng tôi không nghĩ rằng mã vận chuyển nhanh hơn nên liên quan đến việc triển khai lại toàn bộ lớp điều phối và tự động hóa cơ sở hạ tầng của chúng tôi. Vì vậy, chúng tôi đã tìm kiếm trên
PEX
PEX là một công cụ thông minh đang được phát triển tại Twitter cho phép gửi mã Python dưới dạng tệp zip có thể thực thi được. Đó là một ý tưởng khá hay và chúng tôi khuyên bạn nên nói chuyện với Đại học Twitter của Brian Wickman về chủ đề này
Thiết lập PEX đơn giản hơn Docker vì nó chỉ liên quan đến việc chạy tệp zip thực thi kết quả, nhưng việc xây dựng tệp PEX hóa ra lại là một cuộc đấu tranh lớn. Chúng tôi gặp phải một số vấn đề khi xây dựng yêu cầu thư viện của bên thứ ba, đặc biệt là khi bao gồm các tệp tĩnh. Chúng tôi cũng phải đối mặt với các dấu vết ngăn xếp khó hiểu được tạo ra từ bên trong mã nguồn của PEX, khiến việc gỡ lỗi các bản dựng trở nên khó khăn hơn. Đây là một công cụ giải quyết vấn đề vì mục tiêu chính của chúng tôi là cải thiện năng suất kỹ thuật và làm cho mọi thứ dễ hiểu hơn
Sử dụng Docker sẽ tăng thêm độ phức tạp cho thời gian chạy của chúng tôi. Sử dụng PEX sẽ tăng thêm độ phức tạp cho các bản dựng của chúng tôi. Chúng tôi cần một giải pháp có thể giảm thiểu độ phức tạp tổng thể, đồng thời cung cấp cho chúng tôi các triển khai đáng tin cậy, vì vậy việc tìm kiếm của chúng tôi vẫn tiếp tục
gói. các "container" ban đầu
Vài năm trước, Spotify lặng lẽ phát hành một công cụ gọi là dh-virtualenv, mà bạn có thể sử dụng để xây dựng gói debian có chứa virtualenv. Chúng tôi nghĩ điều này thú vị và đã có nhiều kinh nghiệm sử dụng Debian cũng như chạy nó trong sản xuất. [Một trong những người đồng sáng lập của chúng tôi, Christine, là nhà phát triển Debian. ]
Xây dựng với
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine5 chỉ cần tạo một gói debian bao gồm một virtualenv, cùng với bất kỳ phần phụ thuộc nào được liệt kê trong các yêu cầu. tập tin txt. Khi gói debian này được cài đặt trên máy chủ, nó sẽ đặt virtualenv tại
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine6. Đó là nó
Đây là cốt lõi của cách chúng tôi triển khai mã tại Nylas. Máy chủ tích hợp liên tục của chúng tôi [Jenkins] chạy dh-virtualenv để xây dựng gói và sử dụng bộ đệm bánh xe của Python để tránh xây dựng lại các phụ thuộc. Điều này tạo ra một tạo phẩm được đóng gói duy nhất [gói debian], sau đó được chạy qua các bài kiểm tra hệ thống và đơn vị mở rộng. Nếu hiện vật vượt qua, nó được chứng nhận là an toàn cho prod và được tải lên s3
Một phần quan trọng của quy trình này là chúng ta có thể giảm thiểu độ phức tạp của tập lệnh triển khai bằng cách tận dụng trình quản lý gói dựng sẵn của Debian, dpkg. Một tập lệnh triển khai có thể trông giống như thế này
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine
Để khôi phục, chúng tôi chỉ cần triển khai tạo phẩm được tạo phiên bản trước đó. Tiện ích dpkg xử lý dọn dẹp code cũ miễn phí
Một trong những khía cạnh quan trọng nhất của chiến lược này là nó đạt được tính nhất quán và độ tin cậy, nhưng vẫn phù hợp với môi trường phát triển của chúng tôi. Các kỹ sư của chúng tôi đã sử dụng virtualenv và dh-virtualenv thực sự chỉ là một cách để gửi chúng đến các máy chủ từ xa. Nếu chúng tôi đã chọn Docker hoặc PEX, chúng tôi sẽ phải thay đổi đáng kể cách chúng tôi phát triển tại địa phương và tạo ra rất nhiều sự phức tạp. Chúng tôi cũng không muốn tạo gánh nặng phức tạp đó cho các nhà phát triển sử dụng mã nguồn mở của chúng tôi
Hôm nay, chúng tôi gửi tất cả mã Python của mình với các gói Debian. Toàn bộ cơ sở mã của chúng tôi [với hàng tá phần phụ thuộc] mất chưa đầy 2 phút để xây dựng và vài giây để triển khai
Bắt đầu với dh-virtualenv
Nếu bạn đang gặp khó khăn khi triển khai Python, hãy hỏi bác sĩ của bạn về dh-virtualenv. Nó có thể phù hợp với bạn
Việc cấu hình các gói Debian có thể phức tạp đối với người mới, vì vậy chúng tôi đã xây dựng một tiện ích để giúp bạn bắt đầu có tên là make-deb. Nó tạo ra một cấu hình Debian dựa trên thiết lập. py trong dự án Python của bạn
Trước tiên hãy cài đặt công cụ
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine0, sau đó chạy nó từ thư mục gốc của dự án của bạn
cd /my/project pip install make-deb make-deb
Nếu thông tin bị thiếu trong thiết lập của bạn. py,
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine0 sẽ yêu cầu bạn thêm nó. Sau khi có tất cả các chi tiết cần thiết,
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine0 sẽ tạo một thư mục debian ở thư mục gốc của dự án chứa tất cả cấu hình bạn cần cho dh-virtualenv
Xây dựng một gói Debian yêu cầu bạn phải chạy Debian đã cài đặt dh-virtualenv. Nếu bạn không chạy Debian, chúng tôi khuyên dùng Vagrant+Virtualbox để thiết lập một máy ảo Debian trên Mac hoặc Windows. Bạn có thể xem ví dụ về cấu hình này bằng cách xem Vagrantfile trong kho lưu trữ Git của công cụ đồng bộ hóa của chúng tôi
Cuối cùng, chạy
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine3 sẽ tạo gói Debian. Bạn không cần gọi trực tiếp dh-virtualenv, vì nó đã được chỉ định trong quy tắc cấu hình mà
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine0 đã tạo cho bạn. Khi lệnh này kết thúc, bạn sẽ có một tạo phẩm sáng bóng sẵn sàng để triển khai
Một tập lệnh triển khai đơn giản có thể trông như thế này
________số 8Để triển khai, bạn cần tải cấu phần phần mềm này lên máy sản xuất của mình. Để cài đặt nó, chỉ cần chạy
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine5. Virtualenv của bạn sẽ được đặt tại
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine6 và mọi tệp tập lệnh được xác định trong thiết lập của bạn. py sẽ có sẵn trong thư mục
temp=$[mktemp /tmp/deploy.deb.XXXXX] curl “//artifacts.nylas.net/sync-engine-3k48dls.deb” -o $temp dpkg -i $temp sv reload sync-engine7 đi kèm. Và đó là nó. Bạn đang trên đường triển khai đơn giản hơn
kết thúc
Khi xây dựng các hệ thống lớn, tình thế tiến thoái lưỡng nan về kỹ thuật thường là tìm sự cân bằng giữa việc tạo ra công cụ phù hợp, nhưng không liên tục cấu trúc lại một hệ thống mới từ đầu. Chúng tôi nghĩ rằng việc sử dụng triển khai dựa trên gói Debian là một giải pháp tuyệt vời để triển khai các ứng dụng Python và quan trọng nhất là nó cho phép chúng tôi gửi mã nhanh hơn với ít sự cố hơn