Trường Hợp Sử Dụng – Hạ Tầng Bất Biến với Docker và Artifactory

Trường Hợp Sử Dụng – Hạ Tầng Bất Biến với Docker và Artifactory

Talk Transcription:

(Keith) Xin chào mọi người, các bạn cảm thấy thế nào hôm nay? Mọi người có đang tận hưởng không khí ngoài Napa không?

(Khán giả) Có chứ.

(Keith) Tuyệt vời. Tôi là Keith Kreissl, Principal Developer tại cars.com. Hôm nay đi cùng tôi là Zlatko Sisic, Mac Heller-Ogden, và Deep Mistry – toàn bộ đều là Senior Developer. Trước khi bắt đầu, chúng tôi muốn làm rõ một vài điều: Thứ nhất, cars.com không bán xe hơi, cũng không lấy phần trăm hoa hồng từ giao dịch xe hơi, và quan trọng nhất, chúng tôi cũng không nhận được ưu đãi khi mua xe. Nếu ai đó ở đây mong điều đó thì rất tiếc. Tuy nhiên, hy vọng mọi người sẽ ở lại và thưởng thức buổi chia sẻ này.

Vậy cars.com làm gì? Cars.com là điểm đến trực tuyến dẫn đầu cho người mua và chủ xe. Chúng tôi cung cấp thông tin đáng tin cậy và dễ hiểu giúp người dùng nghiên cứu, định giá, tìm kiếm xe mới – cũ, cũng như các dịch vụ bảo trì, sửa chữa chất lượng. Giờ hãy cùng khám phá vai trò của team công nghệ tại cars.com.

Hãy cùng xem một vài chỉ số về hệ thống. Cars.com được thành lập năm 1998 và với nhu cầu xử lý khối lượng dữ liệu lớn, lựa chọn giải pháp ban đầu là stack JDE truyền thống: máy chủ HTTP, app server, Java (Oracle hoặc IBM), chạy trên bất kỳ máy chủ Linux nào rồi kết nối với cơ sở dữ liệu. Qua thời gian, hệ thống phát triển vượt tầm và yêu cầu chúng tôi nâng cấp kiến trúc. Bạn có thể thấy trong sơ đồ: gồm các tier render, composite, service và data store. Qua nhiều năm, nhiều lãnh đạo kỹ thuật đã để lại di sản là đa dạng loại server: 2 loại HTTP (IBM, Oracle), 2 loại app server (WebLogic, WebSphere), runtime Java với nhiều phiên bản (vẫn còn chạy bản 1.5 trên IBM Portal, Java 7 và đang xem xét Java 8). OS cũng có Oracle Linux, Red Hat Linux, thậm chí một số máy IBM AIX.

Không chỉ vậy, cars.com sở hữu 5 môi trường: dev, future testing, integration, performance testing, và production – nhân tất cả lên 5. Hiện đang vận hành khoảng 10 web app và 100 services cùng lúc. Quản lý toàn bộ tài nguyên, môi trường, VM trở thành thách thức lớn.

Để giải quyết, nhiều người khuyên nên dùng Chef – và chúng tôi đã sử dụng Chef để tự động hoá triển khai VM, rất hiệu quả. Tuy nhiên, trọng tâm vẫn là các developer, những người xây dựng giải pháp mỗi ngày bằng laptop cá nhân – có thể là NGINX hoặc Apache, app server có thể là Jetty, Tomcat, hoặc Spring Boot, với nhiều phiên bản Java (Oracle/OpenJDK), OS có thể là OSX hoặc Windows. Vấn đề tiếp tục phức tạp dần theo thời gian.

Khi tôi lãnh đạo DevOps team, câu hỏi phổ biến nhất là “sao chạy được ở máy tôi mà không chạy trên môi trường khác?” – cực kỳ đau đầu khi phải xác định nguyên nhân trong một hệ sinh thái quá đa dạng.

Giải pháp là kiến trúc immutable infrastructure: cars.com hướng đến việc “đóng gói” hoàn toàn ứng dụng, môi trường runtime, và cả OS, từ develop đến production, để đảm bảo tính nhất quán qua mọi môi trường – chỉ cần xây một artifact, artifact đó sẽ được deploy xuyên suốt mọi khâu.

Mục tiêu của chúng tôi là: hạ tầng dự đoán được, dễ scale, tự động hồi phục, rollback nhanh nếu có sự cố. Lúc này Docker trở thành chìa khoá: cho phép cô lập, đóng gói trọn vẹn toàn bộ ứng dụng, runtime và OS vào một image; dễ dàng xây dựng, tự động triển khai và rollback nhanh. Ví dụ khi cần blue/green hoặc canary release, chỉ cần vài container với load balancer là kiểm thử tính năng mới dễ dàng. Nếu muốn thử nghiệm công nghệ (Java sang Node), chỉ việc dựng container song song và so sánh hiệu năng – cực kỳ thuận tiện và linh hoạt.

Để áp dụng Docker hoá, chúng tôi bắt đầu với engine rendering – vốn là JDE app – chuyển sang Node và đóng gói cùng Docker. Tuy nhiên, điều này tạo ra một số thách thức mới – Zlatko sẽ tiếp tục chia sẻ về cách giải quyết.

(Zlatko) Cảm ơn Keith. Thực tế không chỉ chúng tôi đối mặt với sự phức tạp này. Với engine render mới viết bằng Node, chúng tôi muốn Docker hóa và deploy nhanh nhất có thể ra production. Đội ngũ phát triển liên tục refactor, tạo mới module, và phải tích hợp toàn bộ vào Docker image.

Khởi đầu, chúng tôi sử dụng image Node chính thức, kéo về và deploy – dễ dàng nhưng khi scale sang môi trường VM, việc di chuyển image giữa các máy trở nên chậm vì kích thước lớn. Do đó, chúng tôi tiến hành tối ưu, lựa chọn một base image đủ nhẹ, đáp ứng các nhóm phát triển khác nhau (JavaScript, Java, Data…), tất cả đều cần môi trường nhất quán.
Sau quá trình đánh giá, Alpine Linux là lựa chọn tối ưu: nhỏ (~5 MB), nhiều tiện ích out-of-box, dễ mở rộng qua APK. Image nền chỉ 12 MB, sau thêm các runtime (Java, Node nhiều bản, Tomcat…) vẫn duy trì kích thước nhỏ gọn (Tomcat từ 357MB xuống 181MB, Node “slim” còn 55MB, full app với dependencies khoảng 80MB).

Chúng tôi áp dụng các best practices: gộp lệnh khi build, cài và xoá binary ngay trong quá trình, tối ưu permission để không chạy container dưới quyền root, giảm rủi ro bảo mật, và tinh chỉnh thứ tự các lệnh để giảm tối thiểu kích thước image đầu ra.

Sau khi đã có image tối ưu, câu hỏi là lưu trữ ra sao? Chúng tôi duy trì nhiều loại artifact (Docker image, npm, Maven, JAR, static file…) từ nhiều môi trường với package manager khác nhau, gây phức tạp quản trị. Khi đó Artifactory là giải pháp “one-stop shop”: lưu trữ tất cả artifact, hỗ trợ tích hợp tốt với Jenkins, cho phép tổ chức repo theo nhiều dạng (local, remote, virtual), quản lý snapshot và release, cache artifact từ public internet. Chỉ cần trỏ về Artifactory, để hệ thống tự động xác định nguồn lấy artifact.

Ngoài ra, chúng tôi tận dụng khả năng tagging, dùng metadata cho CI/CD, tích hợp REST API để truy xuất artifact theo yêu cầu. Mac sẽ tiếp tục nói về phần scripting custom để hoàn thiện quy trình build/deploy này.

(Mac) Cảm ơn Zlatko. Một bài toán tiếp theo là: build/deploy thực sự như thế nào? Có rất nhiều công cụ ngoài kia nhưng đa số vẫn còn non trẻ, chỉ giải quyết một phần tổng thể. Điều chúng tôi cần là giải pháp đáp ứng nhu cầu ngay lập tức nhưng không “lock-in” vào một tool cố định – đơn giản, không cầu kỳ, có thể dùng để containerize ứng dụng Node đầu tiên này. Immutable infrastructure cũng cần áp dụng vào quy trình build và deploy, không chỉ vào bản thân container.

Một ý tưởng hiển nhiên là xài Makefile – công cụ build kinh điển, syntax khai báo, lưu cùng source, chia sẻ logic build giữa phòng phát triển và production. Tuy nhiên, Makefile lớn, hơi khó phân phối. Để đơn giản hoá, chúng tôi tạo điểm entry-point nhỏ cho Makefile, custom lại để khai báo hết các cấu hình port, biến môi trường, volume… tất cả nằm trong file “powertrain.mk” ở project root.

Các lệnh CLI như “powertrain build”, “powertrain publish”, “powertrain deploy” – tất cả đều không cần flag vì được khai báo sẵn trong file cấu hình. Triển khai nhanh, rollback nhanh, chỉ định được số instance tại runtime, v.v. Như vậy từ build system đến runtime đều tham chiếu cùng file config, dễ kiểm soát, đẩy image cũng tiện lợi hơn. Tiếp theo, Deep sẽ nói về CI/CD và vai trò Jenkins.

(Deep) Cảm ơn Mac đã giới thiệu về giải pháp build/deploy. Để đẩy production, cars.com tiêu chuẩn hoá CI/CD với Jenkins làm server, Bitbucket cho source control, Artifactory giúp quản lý tất cả artifact: Docker registry, Alpine APK, Maven, Gradle… Docker không chỉ chạy ứng dụng mà còn phục vụ test automation tại nhiều khâu khác trong pipeline. Máy Jenkins/slave cũng được cấu hình tự động chuẩn với Chef.

Quy trình điển hình: Developer commit code lên Bitbucket, hook kích hoạt Jenkins build job, kéo source về, build Docker image bằng powertrain, gán version (kết hợp số build và git hash), spin up container, chạy test automation để đảm bảo chất lượng, rồi push image lên Artifactory. Mỗi lần build tự động triển khai vào môi trường dev – deploy job sẽ SSH vào Docker host, chạy các lệnh powertrain (giống các script local) để pull, deploy image tương ứng. Thậm chí có thể extract config từ image đã build, phù hợp từng môi trường.

Một điểm mạnh là mọi commit đều có thể build thành image riêng biệt, truy vết dễ dàng, nhanh rollback nếu có vấn đề. Artifactory cho phép giám sát mỗi layer trong image để tối ưu kích thước. Nhờ đó, image ứng dụng chỉ còn 88MB thay vì 500MB như nền tảng Ubuntu trước đây.

Quy trình deploy cũng tự động lên các môi trường kế tiếp (future testing, integration, perf test, production) nếu cần. Tính linh hoạt và tính nhất quán được ưu tiên tối đa với từng environment.

Với khối lượng developer commit liên tục, scale Jenkins cũng là việc thiết yếu – đang dự định triển khai Jenkins multi-master để tăng hiệu quả.

Kết thúc, mời Keith chia sẻ thêm về tương lai Docker tại cars.com.

(Keith) Đúng như vậy – sắp tới chúng tôi tiếp tục đưa các app/service còn lại lên Docker, mở rộng hệ sinh thái, đồng thời không giới hạn ngôn ngữ (Node, Scala, v.v.), miễn là đáp ứng kiến trúc container, tăng tính linh hoạt thử nghiệm công nghệ mới, giúp team công nghệ bứt phá trong sáng tạo và tối ưu vận hành.

Chúng tôi cảm ơn các bạn đã lắng nghe, sẵn sàng tiếp nhận feedback hoặc chia sẻ thêm kinh nghiệm. Để được tư vấn chuyên sâu hoặc mua giải pháp, hãy liên hệ Softribution ngay hôm nay!

Share this post