9.0. Giới thiệu khóa học

Khóa học này được thiết kế để dạy bạn cách quản lý các container ứng dụng, sử dụng Kubernetes. Khóa học được xây dựng bởi các chuyên gia như Kelsey Hightower và Carter Morgan đến từ Google và cựu kiến ​​trúc sư của Cloud của Netflix, Adrian Cockcroft, người đã cung cấp những bài học quan trọng trong suốt khóa học.

Làm chủ tốt việc quản lý cơ sở hạ tầng mở rộng là rất quan trọng do ngày nay, kì vọng của khách hàng ngày càng tăng lên. Ví dụ như khách hàng muốn website ưa thích của họ phục vụ 24/7 và website cũng cần tung ra các tính năng mới thường xuyên mà không có bất kì sự gián đoạn dịch vụ nào. Để đạt được điều này yêu cầu các công cụ cho phép bạn đảm bảo tốc độ phát triển của ứng dụng, ổn định cơ sở hạ tầng và có khả năng mở rộng.

Trong khóa học này, chúng ta sẽ đi sâu tìm hiểu:

  • Containerize một ứng dụng nhờ việc tạo các file câu hình Docker và xây dựng các quy trình để tạo ra tất cả các Docker images cần thiết
  • Cấu hình và chạy một Kubernetes cluster tự động mở rộng và tự dộng điều chỉnh
  • Sử dụng Kubernetes để quản lý việc triển khai, mở rộng và cập nhật ứng dụng
  • Áp dụng các best practices cho việc sử dụng các containers nói chung và Kubernetes nói riêng, khi kiến trúc và phát triển các microservices mới.

9.1. Giới thiệu Microservices

Phần này sẽ giới thiệu các ứng dụng hiện đại sử dụng mô hình thiết kế microservices như thế nào.

9.1.1. Sự tiến hóa của các ứng dụng

Những năm vừa qua có vô số các ứng dụng được tạo ra. Chúng ta mất rất nhiều thời gian trong việc build ứng dụng và sau đó phải tìm nơi nào đó để chạy ứng dụng. Vì vậy, chúng ta release phần mềm không thường xuyên.

Gần đây, xu hướng chia nhỏ phần mềm thành những khối càng ngày càng nhỏ hơn và nhiệm vụ của microservices là làm cho các khối đó nhỏ hơn. Vì vậy, nếu thời gian build bây giờ giảm từ vài giờ xuống vài giây và ứng dụng được đóng trong một container, sau đó chỉ cần deploy container thì chỉ mất vài giây để thực hiện deploy ứng dụng. Hiển nhiên, khi việc deploy trở nên dễ dàng thì phần mềm sẽ được release thường xuyên hơn vì không phải đợi hàng tháng để release code mới.

Lý do chính cho sử dụng microservice là giúp cho việc deploy ứng dụng. Ví dụ, có 100 người cùng xây dựng một ứng dụng một khối (monolithic app), một người gây ra lỗi trong code, kiểm thử tìm ra lỗi đó và việc release bị trì hoãn trong 1 tuần. Dẫn đến công việc của 99 người còn lại là lãng phí và chưa hoàn thành hoặc khi ứng dụng đã được triển khai thì ứng dụng phải bị rollback và mất lại mất thêm một tuần nữa thực hiện lại. Điều xảy ra khi có nhiều người cùng xây dựng một khối code lớn, duy nhất là ở chỗ bất kì một lỗi nhỏ trong code nào cũng gây ra block toàn bộ khối code. Vì vậy, việc chia nhỏ thành các microservices thực sự giải phỏng mọi người để release ứng dụng với tốc độ của chính họ. Ví dụ, một vài người nào đó có một ý tưởng hoàn toàn mới, họ bặt đầu xây dựng và có thể thực hiện mười release trong một ngày.

Làm sao có thể kết hợp các microservices với nhau? Thực sự không phải kết hợp chúng vì nếu làm thế thì chúng ta lại quay về kiến trúc một khối và làm mọi thứ chậm lại. Điểm quan trọng là để mọi người release trong chu kì của chính họ nghĩa là cần đảm bảo rằng các giao diện phải tương đối ổn định và có thể deploy bất kì phần nào độc lập với các phần còn lại mà không cần có sự cho phép nhưng thông thường nên cho mọi người biết.

Cơ sở hạ tầng cần thiết để quản lý microservices? Cần có nhiều sự tự động hóa để thực hiện điều này một cách hiệu quả. Ví dụ như có một đội điều hành thực hiện xây dựng ra các APIs và scripts,.. Một cách chính xác để cấu hình những thứ phức tạo là sử dụngscripts hoặc thực hiện thiết lập thủ công hoặc đóng gói tất cả trong một container. Vì tất cả được gắn chặt với nhau nên nếu muốn kết hợp tất cả chúng và release chúng trong một lần thì cần có sự lập lịch là một cách để kết hợp chúng và liên kết mọi thứ với nhau giống như Dockerfile hoặc file cấu hình Kubernetes

9.1.2. Microservices

a. Kiến trúc một khối (monolithic applications)

Tưởng tượng bạn phải xây dựng một dịch vụ gọi taxi qua di động cạnh tranh với Uber và Hailo. Sau một số buổi họp thu thập yêu cầu và phân tích thiết kế, bạn sẽ chọn công nghệ (technology stack) rồi tạo dự án đại loại như Rails, Spring Boot, Play, hay Maven. Dự án này sẽ có kiến trúc chia khối lục giác (hexagol architecture) hoặc ít hơn. Kiến trúc đa diện giúp ứng dụng chuyên biệt mô hình dữ liệu và đầu vào, đầu ra.

Trong lõi của ứng dụng là business logic được thể hiện bởi các khối dịch vụ, đối tượng cho từng vùng nghiệp vụ (domain objects) và các sự kiện (events: khách đặt xe, khách hủy xe, xe nhận khách...) Xung quanh lõi là bộ chuyển đổi (adapter) ví dụ như kết nối vào cơ sở dữ liệu, gửi nhận thông điệp (messaging), web service hoặc giao diện web front end.

Mặc dù có cấu trúc module hóa hợp lý, nhưng ứng dụng kiểu này sẽ đóng gói và cài đặt thành một khối (monolithic). Mã chạy cụ thể tùy thuộc vào ngôn ngữ lập trình hay thư viện framework. Ví dụ ứng dụng Java đóng trong file WAR, triển khai trên application server như Tomcat hay Jetty. Dùng framework khác, thì ứng dụng Java là một file tự đóng gói để chạy là JAR. Ứng Rails hay Node.js đóng gói theo cấu trúc thư mục phân cấp.

Ứng dụng được viết kiểu trên đây rất phổ biến. Chúng dễ viết, dễ thử nghiệm, dễ copy & paste bởi các công cụ lập trình IDE và dự án mẫu được tối ưu để tạo ra ứng dụng khối đơn nhất (Do cần thuyết phục lập trình viên đi theo công nghệ/framework nên nhà sản xuất phải làm sao lập trình chỉ cần New Project, ấn nút Build & Run là ứng dụng chạy được ngay và luôn). Có thể kiểm thử tự động giao diện web với Selenium. Ứng dụng khối đơn nhất khá dễ triển khai. PHP, Python thì chỉ cần cập nhật mã. Một số khác có chức năng khởi động nóng (hot reload: dịch lại nạp lên chạy tiếp) như Node.js, Play Framework, Revel. Để tăng khả năng chịu tải thì bổ xung thêm web application server giống nhau sau bộ cân bằng tải (load balancer) (Tất nhiên mở rộng cơ sở dữ liệu liên tục ghi thành nhiều bản không dễ dàng)

Cách tiếp cận kiến trúc đơn nhất tuy dễ dàng nhưng bắt đầu bộc lộ nhiều khiếm khuyết. Ứng dụng thành công - số lượng người dùng tăng - yêu cầu tính năng mới tăng - dữ liệu tăng - logic phức tạp hơn - giao tiếp với hệ thống khác tăng kết quả một ứng dụng khủng. Sau mỗi kỳ phát triển (sprint), đội phát triển bổ xung vài tính năng mới, thêm code, thêm bảng, thêm logic... Chỉ sau vài năm, ứng dụng đơn giản sẽ kềnh càng như quái vật. Tôi có trao đổi với một lập trình viên, người từng viết công cụ phân tích sự phụ thuộc giữa hàng nghìn gói thư viện JAR trong ứng dụng hàng triệu dòng code. Chắc chắn một số lượng lớn man month và tiền tấn để tạo ra quái vật khủng đến vậy.

Ứng dụng một khối mà phình to sẽ rắc rối như một gia đình nhiều thế hệ đông con cái ở trong cùng một nhà. Nhà to đến mấy rồi cũng sẽ gặp vấn đề. Mọi nỗ lực tối ưu, phương pháp làm việc agile (mềm dẻo) đều không còn hiệu quả. Một thư viện được tham chiếu nhiều chỗ khi nâng cấp sẽ phải kiểm tra ở tất cả những điểm, nghiệp vụ mà nó được gọi. Ứng dụng đơn nhất dùng một ngôn ngữ lập trình duy nhất. Đội lập trình sẽ quen với sự thuận tiện, dễ dàng khi chỉ cần nắm sâu một ngôn ngữ, một công cụ có thể giải quyết hầu hết vấn đề. Họ dần lệ thuộc vào ngôn ngữ đó và trở nên thiên vị, ngại cởi mở, tích hợp với những công nghệ khác của ngôn ngữ khác. Thậm chí khi framework hay ngôn ngữ có nhược điểm cố hữu, tính đơn nhất một khối của ứng dụng sẽ bó buộc lập trình viên thử nghiệm đưa vào thay đổi đột phá ngoại lai.

Ứng dụng một khối có hơn 2 triệu dòng mã trên framework XYZ, liệu đội bạn có đủ dũng cảm, nguồn lực để viết lại toàn bộ trên framework ABC mới hơn, tốt hơn. Lập trình giỏi, sáng tạo cũng không muốn làm trong kiểu dự án mặc kẹt này. Tình trạng giữ thì khổ, xây thì khó, khiến dịch vụ - sản phẩm của bạn ì ạch kém cạnh tranh so với các dịch vụ mới nổi uyển chuyển, linh hoạt.

Trong ứng dụng một khối, sự chặt chẽ là ưu điểm tự nhiên xuất phát từ kiến trúc, nhưng nó tiềm ẩn nguy cơ ràng buộc cứng nhắc đóng bê tông (tight coupling). Chi phí, thời gian, nỗ lực phát triển - sửa lỗi - kiểm thử một chức năng sẽ tăng tỷ lệ bậc 2 theo độ lớn của ứng dụng. Nói cách khác đi, mã nguồn khó đọc, khó bảo trì tỷ lệ bậc 2 theo số ràng buộc, tham chiếu được tạo ra hết sức dễ dãi khi phát triển.

Gần đây, Các ứng dụng triển khai đều đặn (continous deployment) nổi lên. Những ứng dụng SaaS (Software application as Service) tiên tiến, cần phải cập nhật vài lần trong một ngày. Quá khó để triển khai lại cả một ứng dụng cực lớn chỉ vì một số nâng cấp nhỏ. Hoạt động bị ngưng trệ, kiểm thử lại sau triển khai sẽ lâu công hơn. Kết quả là triển khai đều đặn khó áp dụng với ứng dụng một khối.

b. Kiến trúc Microservices

Microservices chỉ là một cách tiếp cận có kiến trúc để thiết kế các ứng dụng theo cách module hóa, dễ dàng triển khai và mở rộng một cách độc lập. Có rất nhiều lợi ích của mô hình thiết kế microservice :

  • Áp dụng cho bất kì ứng dụng nào thậm chí cả ứng dụng web truyền thống.
  • Triển khai ứng dụng nhanh.
  • Cung cấp tính năng ứng dụng liên tục thông qua cập nhật phiên bản.
  • Đẩy các giới hạn của hầu hết các công cụ tự động hóa và cơ sở hạ tầng hiện này đến giới hạn của nó.

Nhiều tập đoàn như Amazon, eBay, Netflix đã giải quyết vấn đề ứng dụng một khối bằng kiến trúc microservices (nhiều dịch vụ nhỏ). Ý tưởng là chia nhỏ ứng dụng lớn ra thành các dịch vụ nhỏ kết nối với nhau.

Mỗi dịch vụ nhỏ thực hiện một tập các chức năng chuyên biệt như quản lý đơn hàng, quản lý khách hàng. Mỗi dịch vụ là một ứng dụng nhỏ có kiến trúc đa diện lõi là business logic kết nối ra các adapter khác nhau. Một số dịch vụ nhỏ lộ ra giao tiếp lập trình API cho dịch vụ nhỏ khác hay ứng dụng client gọi tới. Khi vận hành, mỗi dịch vụ nhỏ được chạy trong một máy ảo (virtual machine) hoặc Docker container (ảo hóa tầng ứng dụng)

Mỗi vùng chức năng giờ được thực thị bởi một dịch vụ nhỏ. Ứng dụng web cũng có thể chia nhỏ hơn chuyên cho từng đối tượng người dùng (một cho hành khách taxi, một cho tài xế). Thiết kế giao diện cho từng đối tượng người dùng giúp tối ưu trải nghiệm tốt hơn, tốc độ nhanh hơn, dễ tương thích hơn trong khi chức năng tối giản hơn.

Mỗi dịch vụ đằng sau (back end service) lộ ra REST API (hiện nay còn nhiều lựa chọn khác như Google Protobuf, Apache Thrift, Apache Avro tốn ít băng thông hơn REST JSON)

Các dịch vụ sẽ gọi / sử dụng API cung cấp bởi dịch vụ khác. Ví dụ dịch vụ quản lý tài xe sử dụng Notification Server để chủ động báo tài xế đang rảnh đón khách hàng tiềm năng. Phần giao diện (UI services) sẽ gọi đến các dịch vụ khác để lấy dữ liệu hiển thị. Hiện nay, pattern reactive cho phép dịch vụ có thể thông báo hoặc chủ động gửi dữ liệu mới để giao diện cập nhật. Đặc điểm của kết nối giữa các dịch vụ có thể là:

  • Synchronous (đồng bộ - gọi xong chờ)
  • Asynchronous (bất đồng bộ - gọi xong chạy tiếp. Khi có kết quả thì xử lý)

Cách gọi:

  • REST (tập lệnh gửi qua HTTP để truy vấn, thao tác dữ liệu. Kiểu dữ liệu XML, JSON, JSONb)
  • RPC (remote procedure call -lệnh gọi từ xa. Kiểu dữ liệu binary, Thrift, Protobuf, Avro)
  • SOAP (Simple Object Access Protocol)

Một số dịch API REST có thể lộ ra cho thiết bị di động của hành khách và tài xế kết nối. Ứng dụng của người dùng cuối sẽ không được kết nối trực tiếp vào dịch vụ đằng sau. Thay vào đó có một cổng API (API gateway) đứng giữa. Cổng API có một số nhiệm vụ như phân tải, lưu tạm (cache), kiểm tra quyền truy cập, đo và theo dõi (API metering and monitoring).

Ưu điểm của Microservices

  • Giảm thiểu sự gia tăng phức tạp rối rắm hệ thống lớn.
  • Chia nhỏ ứng dụng một khối cồng kềnh thành các dịch vụ nhỏ dễ quản lý, bảo trì nâng cấp, tự do chọn, nâng cấp công nghệ mới.
  • Mỗi dịch vụ nhỏ sẽ định ra ranh giới rõ ràng dưới dạng RPC hay API hướng thông điệp.
  • Microservice thúc đẩy tách rạch ròi các khối chức năng (loose coupling - high cohesion), điều rất khó thực hiện với ứng dụng một khối. Nếu muốn loose coupling - high cohesion trong ứng dụng một khối, sẽ phải thiết kế theo Design Pattern (Gang Of Four) và liên tục tái cấu trúc (refactor)

Mỗi dịch vụ nhỏ sẽ phát triển dễ hơn, nhanh hơn, dễ viết mã kiểm thử tự động.

Một số dịch vụ có thuê ngoài phát triển mà vẫn bảo mật hệ thống - mã nguồn phần dịch vụ còn lại. Đội phát triển có nhiều lựa chọn công nghệ mới, framework, CSDL mới, đa dạng để nâng cấp từng dịch vụ nhỏ, chọn môi trường tối ưu nhất để chạy. Các dịch vụ có thể bật tắt để kiểm nghiệm so sánh A|B, tăng tốc quá trình cải tiến giao diện. Triển khai đều đặn khả thi với microservice. Dịch vụ nhỏ đóng gói trong Docker container có thể chuyển từ môi trường phát triển sang môi trường chạy thật không phải cấu hình thủ công lại, không phải copy file quá lớn.

Nhược điểm của microservices

Nhược điểm đầu tiên của microservices cũng chính từ tên gọi của nó. Microservice nhấn mạnh kích thước nhỏ gọn của dịch vụ. Một số lập trình đề xuất dịch vụ siêu nhỏ cỡ dưới 100 dòng code. Chia quá nhiều sẽ dẫn đến manh mún, vụn vặt, khó kiểm soát. Việc lưu dữ liệu cục bộ bên trong những dịch vụ quá nhỏ sẽ khiến dữ liệu phân tán quá mức cần thiết.

Nhược điểm tiếp của microservice đến từ đặc điểm hệ thống phân tán (distributed system):

  • Phải xử lý sự cố khi kết nối chậm, lỗi khi thông điệp không gửi được hoặc thông điệp gửi đến nhiều đích đến vào các thời điểm khác nhau
  • Đảm bảo giao dịch phân tán (distributed transaction) cập nhật dữ liệu đúng đắn (all or none) vào nhiều dịch vụ nhỏ khác nhau khó hơn rất nhiều, đôi khi là không thể so với đảm bảo giao dịch cập nhật vào nhiều bảng trong một cơ sở dữ liệu trung tâm.
  • Theo nguyên tắc CAP (CAP theorem) thì giao dịch phân tán sẽ không thể thỏa mãn cả 3 điều kiện: consistency (dữ liệu ở điểm khác nhau trong mạng phải giống nhau), availablity (yêu cầu gửi đi phải có phúc đáp), partition tolerance (hệ thống vẫn hoạt động được ngay cả khi mạng bị lỗi). Những công nghệ cơ sở dữ liệu phi quan hệ (NoSQL) hay môi giới thông điệp (message broker) tốt nhất hiện nay cũng chưa vượt qua nguyên tắc CAP.
  • Kiểm thử tự động một dịch vụ trong kiến trúc microservices đôi khi yêu cầu phải chạy cả các dịch vụ nhỏ khác mà nó phụ thuộc. Do đó khi phân rã ứng dụng một khối thành microservices cần luôn kiểm tra mức độ ràng buộc giữa các dịch vụ mềm dẻo hơn hay cứng nhắc - lệ thuộc hơn. Nếu ràng buộc ít đi, lỏng leo hơn, bạn đi đúng hướng và ngược lại.
  • Nếu các dịch vụ nhỏ thiết kế phục thuộc vào nhau theo chuỗi. A gọi B, B gọi C, C gọi D. Nếu một mắt xích có giao tiếp API thay đổi, liệu các mắt xích khác có phải thay đổi theo không? Nếu có thì việc bảo trì, kiểm thử sẽ phức tạp tương tự ứng dụng một khối. Thiết kế dịch vụ tốt sẽ giảm tối đa ảnh hưởng lan truyền đến các dịch vụ khác.
  • Cuộc họp có 2 người sẽ có 1 bắt tay, 3 người có 3 bắt tay. 4 người có 6 bắt tay, 5 có 10 bắt tay. Tổ hợp chập 2 của 5 = 10, công thức tổng quát = n! /((n-2)! * 2!). Thực thế không phải dịch vụ nào trong microservice cũng sẽ giao tiếp với tất cả những dịch vụ còn lại. Nhưng nếu không có quy tắc phân luồng - quản lý - đo đếm - theo dõi (manage - meter - monitor) , thì số lượng kết nối giữa các dịch vụ nhỏ gia tăng tùy tiện, chất lượng kết nối không kiểm soát. Hệ thống chậm nhưng không thể biết đoạn nghẽn cổ chai ở đâu?

  • Triển khai dịch vụ microservices nếu làm thủ công theo cách đã làm với ứng dụng một khối phức tạp hơn rất nhiều. Ứng dụng một khối bổ xung các server mới giống hệt nhau đằng sau bộ cần bằng tại. Trong khi ở kiến trúc microservice, các dịch vụ nhỏ nằm trên nhiều máy ảo hay Docker container khác nhau, hoặc một dịch vụ có nhiều thực thể phân tán ra nhiều. Theo Adrian Crockcroft, Hailo có 160 dịch vụ, NetFlix có hơn 600 dịch vụ. Trong dịch vụ đám mây, các máy ảo, docker container, thực thể có thể linh động bật tắt, dịch chuyển. Vậy cần thiết phải có một cơ chế phát hiện dịch vụ (service discovery mechanism) để cập nhật tự động địa chỉ IP và cổng, mô tả, phiên bản của mỗi dịch vụ.

9.1.3. Mười hai yếu tố xây dựng các ứng dụng hiện đại

Trong kỷ nguyên hiện đại, phần mềm thường được cung cấp như một dịch vụ được gọi là "web apps" hay "software-as-a-service". 12 yếu tố (twelve-factor) là một phương pháp luận cho việc xây dựng các ứng dụng SaaS :

  • Sử dụng các định dạng khai báo để tự động thiết lập, để tối thiểu thời gian và chi phí cho các dev mới tham gia vào dự án
  • Có rằng buộc rõ ràng với hệ điều hành bên dưới, cung cấp khả năng di chuyển tối đa giữa các môi trường thực thi.
  • Thích hợp cho triển khai trên các nền tảng điện toán đám mây, không cần quản lý các máy chủ và hệ thống.
  • Tối thiểu sự khác nhau giữa môi trường phát triển và môi trường sản phẩm, hỗ trợ việc triển khai liên tục.
  • Có thể mở rộng mà không có sự thay đổi đáng kể về công cụ, kiến trúc hoặc thực tiễn phát triển.

    Phương pháp luận 12 yếu tố có thể được áp dụng để các ứng dụn được viết bởi bất kì ngôn ngữ lập trình nào và sử dụng bất kì sự kết hợp nào của backing services như database, queue, memory cache, ...

a. Codebase

Một codebase được theo rõi dưới sự kiểm soát sửa đổi, version và nhiều lần triển khai

Một ứng dụng twelve-factor luôn được theo dõi bởi hệ thống kiểm soát phiên bản như Git hay Subversion.

b. Dependencies

Khai báo và cô lập các dependency một cách rõ ràng, tường minh.

c. Config

Lưu trữ cấu hình trong môi trường.

Cấu hình của ứng dụng là mọi thứ có thể thay đổi trong quá trình triển khai ,giữa môi trường của nhà phát triển và sản phẩm.

Ứng dụng đôi khi lưu trữ cấu hình dưới dạng hằng số trong code. Việc này vi phạm mười hai yếu tố do nó yêu cầu bắt buộc phải tách biệt cấu hình ra khỏi code. Cấu hình thay đổi liên tục trong các lần triển khai nhưng code thì không thay đổi.

d. Backing services

Đối xử với các backing service như các tài nguyên được đính kèm.

Backing service là bất kì dịch vụ nào mà ứng dụng sử dụng qua mạng như là một phần hoạt động. Ví dụ như lưu trữ dữ liệu (MySQL hay Oracle), các hệ thống messaging/queueing ( RabbitMQ), các dịch vụ SMTP cho email...

Twelve-factor app không phân biệt giữa các dịch vụ local hay bên thứ ba. Đối với ứng dụng tất cả đều là các tài nguyên đính kèm, được truy nhật qua một URL được lưu trữ trong config. Mỗi backing service là một tài nguyên. Ví dụ, một cơ sở dữ liệu MySQL là 1 tài nguyên, 2 cơ sở dữ liệu MySQL (được sử dụng cho việc chia sẻ tại lớp ứng dụng) là 2 tài nguyên riêng biệt. Twelve-factor app đối xử với các cơ sở dữ liệu này như là các tài nguyên đính kém, chỉ ra sự liên kết lỏng lẻo của chúng với việc triển khai mà chúng được gắn vào

e. Build, release, run

Tách biệt một cách nghiêm ngặt các pha build và run

Một codebase được chuyển thành 1 deploy thông qua 2 pha :

  • Pha build là sự chuyển đổi từ một code repo thành một bundle thực thi được biết như là một build.
  • Pha release lấy build được tạo ra từ pha build và kết hợp với cấu hình deploy hiện tại. Release kết quả chứa cả build và cấu hình và sẵn sàng để thực thi ngay lập tức trong môi trường thực thi.
  • Pha run (được biết như là "runtime" - thời gian chạy) chạy ứng dụng trong môi trường thực thi nhờ khởi động một vài các tiến trình của ứng dụng đối với một release đã được chọn.

Twelve-factor app yêu cầu nghiêm ngặt việc tách biệt giữa các pha build, release và run. Ví dụ như, không thể thay đổi code tại pha runtime do không có cách nào truyền các thay đổi đó trở về pha build

f. Proccesses

Thực thi ứng dụng như là một hoặc nhiều tiến trình không trạng thái.

Ứng dụng được thực thi trong môi trường thực thi như một hoặc nhiều tiến trình. Trong trường hợp đơn giản nhất, code là một script độc lập, môi trường thực thi là máy tính của lập trình viên được cài đặt môi trường để chạy ngôn ngữ của code, và tiến trình được chạy thông qua comand line ( ví dụ như python my_script.py).

Các tiến trình của twelve-factor không có trạng thái và không chia sẻ. Bất kì dữ liệu cần tồn tại phải được lưu trữ trong một backing service có trạng thái ví dụ như database.

g. Port binding

Export các service thông qua port binding.

Các ứng dụng web thỉnh thỏng được thực hiện trong webserver container. Ví dụ, ứng dụng PHP có thể được chạy như một module trong apache HTTPD hoặc ứng dụng Java có thể được chạy trong Tomcat.

Ứng dụng twelve-factor hoàn toàn tự khép kín. Ứng dụng web export HTTP như một service nhờ binding đến một port và lắng nghe các request đến port đó

h. Concurrency

Mở rộng thông qua process model.

Bất kì chương trình máy tính nào khi chạy được biểu diễn bởi một hoặc nhiều tiến trình. Ví dụ, các tiến trình PHP chạy như là các tiến trình con Apache còn các tiến trình Java có cách tiếp cận ngược lại, sử dụng máy ảo Java (JVM) cung cấp một tiến trình khổng lồ dành sẵn một khối lớn nguồn tài nguyên hệ thống (CPU và bộ nhớ) khi khởi động. Trong cả hai trường hợp, các tiến trình chạy chỉ hiển thị tối thiểu cho nhà phát triển ứng dụng.

Trong ứng dụng twelve-factor, các tiến trình là lớp thứ nhất. Các tiến trình trong ứng dụng twelve-factor lấy mô hình tiến trình của unix để chạy service daemons. Sử dụng mô hình này, nhà phát triển có thể kiến trúc ứng dụng của họ để xử lý khối lượng công việc đa dạng nhờ việc gán mỗi loại công việc cho một loại tiến trình. Ví dụ, các HTTP request có thể được xử lý bởi một tiến trình web và các nhiệm vụ background chạy thời gian dài được xử lý bởi một tiến trình worker.

i. Disposability

Tối đa hóa sức mạnh với khởi động và tắt nhanh.

Các tiến trình của ứng dụng twelve-factor luôn sẵn sàng sử dụng nghĩa là chúng có thể được bắt đầu và dừng lại tại bất kì thời điểm được thông báo nào. Điều này tạo điều kiện thuận lợi cho việc mở rộng, triển khai code nhanh hoặc thay đổi cấu hình.

k. Dev/prod parity

Giữ cho sự phát triển, dàn dựng và sản phẩm giống nhau nhất có thể.

Về mặt lịch sử, có những khoảng trống đáng kể giữa development (một dev thực hiện chỉnh sửa local deploy của ứng dụng) và production (một triển khai đang chạy của ứng dụng được truy cập bởi người sử dụng). Những khoảng trống này thể hiện trong ba lĩnh phần :

  • Time gap : một dev có thể làm việc trên code mất nhiều ngày, tuần hoặc thậm chí cả tháng để đưa ra sản phẩm.
  • Personel gap: Dev viết code, kĩ sữ vận hành triển khai nó
  • Tools gap: Dev có thể sử dụng một stack như Nginx, SQlite và OS X, trong khi triển khai sản phẩm sử dụng Apache, MySQL và Linux

Ứng dụng twelve-factor được thiết kế cho việc phát triển liên tục nhờ việc tối thiểu "gap" giữa môi trường phát triển và sản phẩm :

  • Make the time gap small: một dev có thể viết code và triển khai nó trong vài giờ hoặc thậm chí vài phút.
  • Make the personel gap small: dev viết code được tham gia chặt chẽ trong việc triển khai nó và theo dõi hành vi của nó trên sản phẩm
  • Make the tools gap small: giữ cho development và production giống nhau nhất có thể.

l. Logs

Đối xử với logs như các dòng sự kiện

Logs cung cấp khả năng hiển thị hành vi của ứng dụng đang chạy. Trong môi trường máy chủ, chúng thường được viết vào một file trên đĩa (một logfile), nhưng đây chỉ là một định dạng đầu ra.

Logs là dòng các sự kiện được sắp xếp theo thứ thự thời gian, được thu thập từ các nguồn đầu ra của tất cả các tiến trình và backing service đang chạy. Logs dạng thô thường có định dạng text với một sự kiện trên một dòng. Logs không có bắt đầu vào kết thúc cố định nhưng luồng liên thục miễn là ứng dụng đang hoạt động

Ứng dụng twelve-factor không bao giờ quan tâm việc định tuyến hoặc lưu trữ các stream đầu ra của chính nó. Không nên cố gắng viết hoặc quản lý các logfile. Thay vào đó, mỗi tiến trình chạy viết stream sự kiện của mình để hiển thị. Trong quá trình phát triển local, dev sẽ xem các stream này trên foreground của terminal để quan sát hành vi của ứng dụng

m. Admin processes

Chạy các nhiệm vụ quản trị/quản lý như các tiến trình một lần (one-off)

Các tiến trình quản trị một lần nên chạy trong một môi trường đồng nhất như là các tiến trình định kì của ứng dụng. Chúng chạy lại với một release, sử dụng cùng codebase và cấu hình giống như bất kì tiến trình nào chạy với release đó. Code quản trì nhất thiết phải gửi kèm với code ứng dụng để tránh các vấn đề đồng bộ.

9.1.4. Kết luận

Kiến trúc một khối sẽ hữu hiệu đối với ứng dụng đơn giản, ít chức năng. Nó bộc lộ nhiều nhược điểm khi ứng dụng phát triển lớn nhiều chức năng. Kiến trúc microservices chia nhỏ kiến trúc một khối ra các dịch vụ nhỏ. Microservices sẽ hiệu quả, phù hợp cho những ứng dụng phức tạp, liên tục phát triển nếu được thiết kế đúng và tận dụng các công nghệ quản lý, vận hành tự động.

Các ứng dụng hiện đại đang đẩy các hạn chế của mình cho các công cụ tự động hóa như Docker hay Kubernetes. Thay vì có một khối mã nhị phân lớn, bây giờ các ứng dụng này được chia thành nhiều khối nhị phân nhỏ hơn, dễ dàng viết và triển khai hơn. Các khối nhị phân độc lập này có khả năng cập nhật bất kì điểm nào theo nhu cầu. Trong các bài học tới, chúng ta sẽ tìm hiểu các công cụ và cơ sở hạ tầng bên dưới được sử dụng để hỗ trợ các ứng dụng hiện đại này

9.2. Docker

Phần này sẽ giới thiệu việc sử dụng Docker để xây dựng các container images mà đóng gói một ứng dụng và các dependencies cho việc triển khai trên một máy (single machine)

9.2.1. Lịch sử phát triển

Ngày xưa, mô hình máy chủ thường là 1 máy chủ vật lý + 1 hệ điều hành (OS) + 1 ứng dụng

Khi ứng dụng phát triển lên, mô hình này nảy sinh ra nhiều vấn đề, ví dụ:

  • Lãng phí tài nguyên: mặc dù cấu hình máy tính cao nhưng hệ thống lại không tận dụng được hết lợi thế này.
  • Khó khăn trong việc mở rộng hệ thống: muốn mở rộng bạn phải thuê thêm server, rồi thì cấu hình, rồi thì cân bằng tải

Lúc này, công nghệ ảo hóa (virtualization) ra đời :

Với công nghệ ảo hóa, trên cùng 1 máy chủ vật lý, có thể tạo ra nhiều OS, tức là sẽ chạy được nhiều ứng dụng. Vì vậy, tài nguyên của máy được tận dụng tốt hơn. Tuy nhiên, việc ảo hóa này lại nảy sinh vấn đề mới:

  • Ngốn tài nguyên: khi chạy 1 máy ảo, nó sẽ luôn chiếm 1 phần tài nguyên cố định. Vd: máy chủ có 512GB SSD, 16GB RAM. Bạn tạo ra 4 máy ảo Linux, mỗi máy bạn cấp 64GB SSD và 2GB RAM. Như vậy, bạn sẽ mất 256 GB SSD để chứa 4 máy ảo, và khi chạy cùng 4 máy ảo lên cùng lúc, chúng sẽ chiếm 8GB RAM. Mặc dù chỉ chạy lên để không đó thôi, chưa dùng gì cả nhưng nó vẫn chiếm từng đó.
  • Tốn thời gian thực thi: thời gian khởi động, shutdown của các máy ảo sẽ lâu
  • Cồng kềnh: rõ ràng việc phải gánh cho cả 1 team như vậy thì cái server của bạn không thế chạy hết hiệu suất được.

Bước tiến hóa tiếp theo, người ta phát minh ra containerlization:

Với công nghệ này, trên một máy chủ, ta sẽ sinh ra được nhiều máy con (giống với ảo hóa), nhưng điều đặc biệt là các máy con (guess OS)này đều dùng chung phần nhân của máy mẹ (host OS) và chia sẻ với nhau tài nguyên của máy mẹ (RAM chẳng hạn). Như vậy việc tận dụng tài nguyên sẽ được tối ưu hơn.

9.2.2. Giới thiệu Docker

  • Docker là một nền tảng mở cho việc phát triển, di chuyển và chạy các ứng dụng.Docker giúp bạn tách rời các ứng dụng xây dựng khỏi các kiến trúc phía dưới nên bạn có thể thay đỗi phần mềm một cách nhanh chóng. Với Docker, bạn có thể quản lý các kiến trúc phía dưới theo cái cách mà bạn quản lý các ứng dụng của mình.

  • Docker là một công cụ tạo môi trường được " đóng gói" (Container) trên máy tính mà không làm tác động tới môi trường hiện tại của máy, môi trường trong Docker sẽ chạy độc lập.Một số developer thường tạo sẵn các môi trường này và upload lên mạng để mọi người sử dụng

9.2.2 Các thành phần Docker

  • Docker Engine: cung cấp đầy đủ các func,tion để cho người sử dụng có thể làm việc với Docker image và Docker Container. Để gọi đến các function này , người dùng gọi đến REST API của Docker hoặc thực hiện qua Command.

  • Docker Toolbox: là tool của Docker, được sử dụng trên MacOS và Window (vì docker chỉ hỗ trợ native trên linux )

  • Docker Hub: là một dịch vụ registry cloud based, nghĩa là nơi lưu trữ chung cho tất cả các repository của người dụng. Mỗi user tạo một tài khoản trên DockerHub, user được lưu trữ một số lượng public và private repository nào đó, nếu lớn hơn thì phải trả phí. DockerHub cho phép lưu trữ, chia sẻ, build và test các image của user. Ngoài ra, DockerHub còn chứa các official image của các nhà cung cấp chính thức như Linux, Window. Người dùng có thể pull về sử dụng. Khi người dùng build 1 image, người dùng cóthể lưu trữ image trong public reposiotry (cho phép tất cả user có thể sử dụng image của mình), private repository (chỉ cho phép những người mà user chia sẻ image mới có thể sử dụng image)

  • Docker Trusted Registry (DTR): Nếu bạn cần bảo mật và chỉ muốn chia sẻ image ở nội bộ, hoặc chỉ cho những ai bạn muốn chia sẻ. Thì DTR như một Docker Hub phiên bản private. (đây là phiên bản mất phí, bạn sẽ trả tiền, và sẽ có người của công ti support cho bạn trong việc cài đặt và bảo trì hệ thống. Một phiên bản open-source là Docker Registry (không mất phí). Docker Registry là registry local của bạn, nghĩa là bạn down Registry image về, cài đặt nó lên 1 server nào đó, và nó trở thành 1 Registry của riêng bạn. Để tránh việc quá tải trên Docker Hub, bạn sử dụng Docker Registry để lưu trữ và distribute Docker image. Registry gắn chặt với Docker engine nên image lưu trữ trên Docker Registry sẽ trở thành private registry nghĩa là chỉ mình bạn được sử dụng image lưu trữ trên registry của mình.

  • Docker Machine :Là công cụ giúp cài đặt Docker Engine lên môi trường máy ảo một cách tự động, đồng thời cũng quản lý các host này với các câu lệnh của docker-machine

  • Ngoài ra còn có nhiều thành phần khác như Docker Swarm, Docker Compose, Docker Registry, Docker Cloud...

9.2.3 Kiến trúc của Docker

Docker sử dụng kiến trúc client-server. Docker client sẽ nói liên lạc với các Docker daemon, các Docker daemon sẽ thực hiện các task buid,run và distribuing các Docker container. Cả Docker client và Docker daemon có thể chạy trên cùng một máy hoặc có thể kết nối theo kiểu Docker client điều khiển các Docker daemon như hình dưới. Docker client và docker daemon giao tiếp với nhau thông qua socker hoặc RESTful API.

Docker daemon

Như trên biểu đồ , docker daemon chạy trên các máy host. Người dùng sẽ không tương tác trực tiếp với daemon , mà thông qua Docker client.

Docker Client

Là giao diện người dùng của Docker, nó cung cấp cho người dùng giao diện dòng lệnh và thực hiện phản hồi với các Docker daemon

Docker Images

Là một template chỉ cho phép đọc, là các file và các settings sử dụng trong container được lưu lại và sử dụng lại.

Docker cho phép chúng ta build và cập nhật các image có sắn một cách cơ bản và đầy đủ nhất hoặc bạn có thể download imageDocker images của người khác

Docker Container

Docker Container có nét giống với các directory .Một Docker Container giữ mọi thứ chúng ta cần để chạy một app.Mỗi container được tạo từ Docker image.Docker Container có thể có các trạng thái run,started,stopped,moved và deleted.

9.2.4. Docker hoạt động thế nào

a,Build

Build là chúng ta sẽ tạo ra một dockerfile,dockerfile là một text documents mà trong nó bao gồm tất cả command mà user có thể gọi trên command line nhằm biên dịch một image. Dockerfile sẽ được build tại một máy tính đã cài đặt Docker Engine. Sau khi build ta sẽ thu được Container, trong Container này chứa toàn bộ thư viện và ứng dụng của chúng ta.

docker build [OPTIONS] PATH | URL |

b,Push

Sau khi tạo ra Container ta có thể thực hiện push Container lên Docker Hub hoặc Docker Container Image Registry và lưu trữ ở đó. Việc push này có thể thực hiện qua Internet.

docker push [OPTIONS] NAME[:TAG]

c,Pull,Run

Máy tính muốn sử dụng Container mà chúng ta push lên Docker Registry ( Máy đã cài Docker Engine) thì bắt buộc phải thực hiện việc Pull Container này về máy sau đó Run Container.

docker pull [OPTIONS] NAME[:TAG|@DIGEST]
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

9.2.5. Kết luận

Chúng ta đã tìm hiểu đóng gói các ứng dụng trong các container image nghĩa là các công cụ như Docker để không những distribute ứng dụng mà còn chạy ứng dụng trên một loại các server khác nhau. Điều này mở ra cánh cửa cho sự tự động hóa : đóng gói và chạy ứng dụng trên những hệ điều hành riêng. Bây giờ, chúng ta có thể tập trung vào việc đưa ra các ý tưởng mới thỏa mãn khách hàng.

9.3. Kubernetes

Phần này giới thiệu về Kubernetes - một cơ sở hạ tầng hỗ trợ mở rộng ứng dụng quan trọng như chính ứng dụng.

9.3.1. Kubernetes là gì

Docker giúp chúng ta dễ dàng deploy và run containers trên single machine nhưng trong môi trường cluster, Docker bộc lộ nhiều hạn chế như lỗi tại một điểm. Kubernetes ra đời để quản lý các container trong cluster.

Kubernetes là một project opensource được phát triển bởi Google. Kubernetes phục vụ cho việc deploy, scale, operator các application container trên các cụm máy chủ dùng container app làm trung tâm.Kubernetes như một người quản lý các Container và thay vì làm việc trực tiếp với Container thì mình làm việc với Kubernetes. Việc này làm đơn giản việc triển khai và quản lý các app Container rất nhiều.

Với Kubernetes bạn có thể nhanh chóng đáp ứng được nhu cầu khách hàng;

  • Deploy app một cách nhanh nhất
  • Hỗ trợ tự động scale app
  • Liên tục tích hợp các tính năng mới
  • Tối ưu hóa phần cứng ( cho phép người dùng lựa chọn nguồn tài nguyên mà người đó cần)

9.3.2. Các thành phần chính

Kubernetes gồm có các thành phần chính sau đây;

  • Kube-apiserver: Kubernetes API server xác thực và cấu hình dữ liệu cho các đối tượng api (api objects) bao gồm pods,services, replication controllers và nhiều thứ khác. API Servers services REST hoạt động và cung cấp tương tác với mặt trước của cluster's shared state thông qua đó tương tác với mọi thành phần khác.

  • Kube-proxy: Kubernetes network proxy chạy trên mỗi node.Điều này ảnh hưởng lại các services đã được đinh nghĩa trong Kubernetes API trên mỗi node và có thể dễ dàng thực hiện TCP,UDP stream fordwarding hoặc round robin TCP,UDP fordwarding qua một tập các backends. Services cluster ips và các port thường được tìm thấy thông qua các port đặc tả biến môi trường Docker-links-compatible đã được mở bởi service proxy. Đó là một addon tùy chọn mà cung cấp cluster DNS cho các cluster IPs. Người sử dụng nhất thiết phải tạo một service với apiserver API để cấu hình proxy.

  • Kube-scheduler: là a policy-rich, topology-aware, workload-specific function mà ảnh hưởng đáng kể đến tính sẵn có, hiệu quả và năng lực. Trình lên lịch cần phải tính đến các yêu cầu tài nguyên cá nhân và tập thể, chất lượng các yêu cầu dịch vụ, các rằng buộc về phần cứng / phần mềm / chính sách, deadlines,.... Các yêu cầu cụ thể về khối lượng công việc sẽ tải sẽ được thể hiện thông qua API khi cần thiết.

  • Kubelet: là một“node agent” chính chạy trên mỗi node. Kubelet làm việc dưới dạng một PodSpec. A PodSpec là một đối tượng YAML hoặc JSON dùng để mô tả 1 pod. Kubelet lấy một tập các PodSpecs được cung cập thông qua các cơ chế (chủ yếu là apiserver) và đảm bảo rằng các containers được mô tả trong các PodSpecs đang chạy đúng.

  • Kube-controller-manager: là một tiến trình ẩn giám sát trạng thái của cluster thông qua apiserver và khiến các thay đổi được thực hiện để hệ thống từ trạng thái hiện tại sang trạng thái mong muốn. Ví dụ cho các bộ điều khiển replication controller, endpoints controller, namespace controller, and service accounts controller.

  • Pods: là thành phần lõi của Kubernetes. Một pod chứa 1 hoặc nhiều container. Thông thường , nếu nhiều containers phụ thuộc lẫn nhau thì chúng nên được đóng gói cùng với nhau trong cùng một pod . Pod cũng có nhiều volumes . Volume là dữ liệu/lib tồn tại cùng với pod và có thể được sử dụng bởi bất kì containers nào trong pod . Pod cung cấp một shared namespace cho contents của nó nghĩa là các container trong 1 pod có thể trao đổi với nhau, và cùng chia sẻ các volumes được attached lên . Pod cũng chia sẻ 1 network namespace nghĩa là 1 pod có 1 Ip duy nhất.

9.3.3. Giám sát và kiểm tra

Kubernetes đảm bảo rằng các ứng dụng đang chạy một cách chính xác nhờ các tiến trình "Monitoring and Health Checks". Thỉnh thoảng, một container trong pod có thể đang chạy nhưng ứng dụng trong conatinter có thể đang gặp sự cố, ví dụ như code bị deadlocked. Kuber hỗ trợ việc đảm bảo rằng ứng dụng của bạn đang chạy đúng như cài đặt của user nhờ có việc kiểm tra tính sẵn sàng (Readiness) và sự sống (Aliveness).

Readiness chỉ ra rằng 1 container đã sẵn sàng phục vụ traffic. Nếu kiểm tra tính sẵn sàng bị fail thì container sẽ được đánh dấu không sẵn sàng và được loại khỏi cân bằng tải.

Aliveness chỉ ra rằng 1 container còn sống. Nếu kiểm tra aliveness bị fail nhiều lần thì container sẽ được restart.

Ví dụ : chúng ta có 1 pod có 1 container app1 và 1 Kuber daemon được gọi là Kubelet. Kebelet chịu trách nhiệm cho việc đảm bảo pod healthy. Kubelet hỏi app : Bạn còn sống không. Vì 1 số lý do nào đó, container của chúng ta dead và app1 trả lời không. Sau đó, Kubelet restart conatiner và kiểm tra lại từ đầu, đến khi nào app1 trả lời có.

9.3.4. Bảo mật

Nhiều ứng dụng yêu cầu thiết lập cấu hình bí mật như TLS cert để chạy trong môi trường production. Nhưng mà khi sử dụng Docker, nhiều lập trình viên thường thiết lập các cấu hình và đẩy chúng lên public DockerHub, dẫn đến vi phạm yêu cầu bảo mật của ứng dụng.

Trong Kuber, Configmaps và Secrets chịu trách nhiệm cho vấn đề bảo mật. Configmaps tương tự như Secrets nhưng Configmaps không chứa dữ liệu nhạy cảm (user/password). Configmaps và Secrets có thể sử dụng các biến môi trường và nói cho pod biết cấu hình đã được thay đổi hoặc pod tự restart nếu cầu thiết.

Create Secrects từ file sử dụng lệnh tạo secret.

Kuber Master đã biết về secret. Sau đó, chúng ta có thể upload secret đó cho 1 pod.

Khi chúng ta start 1 pod sử dụng secret? Sau khi chạy lệnh tạo Pod, 1 pod được tạo và secret được upload vào pod như 1 volume. Cách này đảm bảo tất cả các cấu hình ở trong pod trước khi container start.

9.3.4. Services

Phần trước, chúng ta đã nói rằng pods có thể được restart nếu kiểm tra aliveness bị fail, điều này dẫn đến 1 vấn đề : nếu chúng ta muốn trao đổi với 1 tập các pod, khi 1 pod được restart, nó có 1 địa chỉ IP khác, làm sao các pod khác biết được địa chỉ IP mới của nó. Chính vì vậy, service được sinh ra. Thay vì sử dụng địa chỉ IP của pod, Kubernetes cung cấp các service như 1 endpoint cố định cho pod. Service sử nhãn để tìm ra pod.

Các mức độ truy cập vào service phụ thuộc vào loại service. Hiện tại có 3 loại service :

  • Type Cluster IP : chỉ các Pod trong cùng một cluster mới truy cập được vào service.
  • Type Node Port : cung cấp cho mỗi nốt 1 external IP có thể truy cập ra bên ngoài.
  • Type Load balancing : thêm một bộ cân bằng tải từ clould provider.

9.3.5. Kết luận

Giống như Docker, Kubernetes khiến ứng dụng trở nên dễ dàng chạy và distribute. Điều này, được gọi là tự động hóa. Kubernetes giúp chúng ta quản lý container một cách tự động trong môi trường cluster. Từ đó, chúng ta chỉ cần tập trung vào ứng dụng hơn là quản lý ứng dụng.

9.4. Triển khai Microservices sử dụng Kubernetes

Phần này giới thiệu việc sử dụng Kubernetes để quản lý các ứng dụng thực tế.

9.4.1. Giới thiệu Deployment

Từ đầu tới giờ, chúng ta đều sử dụng Docker và Kubernetes theo cách đơn giản nhất. Ví dụ như ta chạy lệnh Kuctl để triển khai các container và chạy lệnh expose để kiến chúng có có giá trị bên ngoài cluster. Trong trường hợp sử dụng cao hơn, bạn muốn khai báo trạng thái cơ sở hạ tầng mong muốn của mình nghĩa là viết cấu hình Kubernetes. Cấu hình Kubernetes cho phép quản lý mọi thứ như secrets và chúng ta muốn cập nhật ứng dụng đã phát hành như thế nào. Trạng thái mong muốn là những yêu cầu bạn đặt ra cho hệ thống và Kubernetes sẽ thực hiện như thiết lập security, load balancing,..

Deployment là một cách khai báo từ trạng thái hiện tại đến trạng thái mong muốn (Cái gì được triển khai ở đâu). Deployment sử dụng khái niệm bộ lặp (replica set) để đảm bảo số lượng Pods hiện tại luôn bằng số lượng Pods mong muốn.Khi quản lý Pods, deployment xác định chi tiết Node nào cài đặt Pod, Pod nào ở trạng thái active. Pod được gắn chặt với thời gian sống của Node nghĩa là Node mà down thì Pod cũng down.

Ví dụ trạng thái mong muốn của một ứng dụng là được lặp 3 lần. Nếu một Node down (Node 3) thì deployment sẽ start một pod mới và tìm một node nào đó để cài đặt pod đó cho chúng ta.

9.4.2. Mở rộng Deployments

Mở rộng được thực hiện nhờ việc cập nhật trường replicas trong file deployment manifest mà không sử dụng lệnh. Deployment tạo ra một tập replica để xử lý việc tạo, xóa và cập nhật Pod. Chúng ta không cần lo lằng về việc quản lý chúng, sử dụng deployment theo cách này khiến cho việc mở rộng hoặc thu hẹp ứng dụng trở nên dễ dàng như là thêm một, hai, ba.

9.4.3. Cập nhật Deployments

Khi chúng ta muốn cập nhật container để bảo vệ dữ liệu hoặc để cung cấp code mới cho người dùng thì có thể xảy rủi ro nếu tất cả các thay đổi được thực hiện một lần. Thay vì đó chúng ta sử dụng lệnh rollout hàng đợi trong quá trình cập nhật. Ví dụ, chúng ta có một service với 2 pod lặp và muốn cập nhật Pods lên một phiên bản mới. Sử dụng lệnh rollout cho Pod version 2 của ứng dụng thì một Pod version 2 được kích hoạt trên một Node nào đó (ví dụ Node 3). Sau đó, server bắt đầu định tuyến lưu lượng đến Pod có version 2 của ứng dụng. Như vậy, cả Pod version 1 và Pod version 2 đều phục vụ lưu lượng đồng thời. Tiếp theo, server ngưng định tuyến lưu lượng đến Pod version 1 và ngắt Pod version 1 ra khỏi hệ thống. Lặp lại tương tự với các Node còn lại, như vậy ta có tất cả các Pods đều được cập nhật lên version 2.

9.5. Kết luận chung

Trong khóa học, chúng ta tìm hiểu về :

  • Thiết kế ứng dụng hiện đại.
  • Các best practices cho việc sử dụng các container từ đóng gói cho đến deploy trong môi trường sản phẩm.
  • Quản lý và mở rộng container sử dụng Kubernetes

9.6. Tài liệu tham khảo

  1. https://classroom.udacity.com/courses/ud615
  2. https://12factor.net/
  3. https://martinfowler.com/articles/microservices.html
  4. https://www.docker.com/
  5. https://kubernetes.io/
  6. https://kipalog.com/posts/Toi-da-dung-Docker-nhu-the-nao
  7. http://blog.appconus.com/2016/04/15/docker-cho-nguoi-moi-bat-dau-p1
  8. https://techmaster.vn/posts/33594/gioi-thieu-ve-microservices
  9. http://blog.ows.vn/docker-ao-hoa-server-1/
  10. https://luanbn.wordpress.com/2016/05/10/kubernetes-phan-1-kubernetes-la-gi/

results matching ""

    No results matching ""