👋 Hello anh em, cũng khá lâu rồi mình mới quay trở lại viết bài. Khoảng thời gian vừa rồi mình tập trung khá nhiều vào công việc, lần trở lại này hy vọng có thể chia sẻ được nhiều kiến thức và kinh nghiệm mình đã gặp phải 😍
📌 ĐẶT VẤN ĐỀ
Việc triển khai kubernetes trên production cho website ngày càng được nhiều developer lựa chọn vì sự phổ biến và hiệu quả mà nó mang lại.
Kubernetes là một nền tảng nguồn mở, khả chuyển, có thể mở rộng để quản lý các ứng dụng được đóng gói và các service, giúp thuận lợi trong việc cấu hình và tự động hoá việc triển khai ứng dụng.
Ở bài viết này mình xin mạn phép chia sẻ việc estimate resources cho website triển khai Kubernetes trên production. Rồi rồi chắc cũng cần lấy ví dụ về một website cụ thể các bạn nhỉ 😬, ở đây chắc mình lấy ví dụ về 1 trang blog như viblo.asia. Đầu tiên chắc chúng ta cùng tìm hiểu xem trang viblo.asia có gì nào.
Một website như viblo.asia thông thường cũng sẽ có một số các thành phần như sau:
-
Backend: PHP, NodeJS, Rust, Golang,... (ở đây chắc mình chọn
PHP
cho phổ biến ha) bao gồm các serviceApi
,Worker
,Scheduler
,Elasticseach
- Api: cho phép bạn kết nối, lấy dữ liệu hoặc cập nhật cơ sở dữ liệu có thể theo tiêu chuẩn REST, RESTful và HTTP. Ví dụ trên viblo cung cấp api lấy danh sách bài viết: https://viblo.asia/api/posts
- Worker (queue): Xử lý các công việc (job) theo thứ tự giúp tránh thưc các công việc tiêu tốn tài nguyên phải thực hiện ngay lập tức. Ví dụ tính năng gửi mail báo bài viết spam, mail maketing của Viblo,...
- Scheduler: Đặt lịch các công việc để chạy theo thời gian bạn mong muốn ví dụ tính năng đặt lịch share bài viết lên fanpage của Viblo,...
-
Frontend: F12 lên thì có thể thấy import nhiều file build của Nuxt nên mạn phép chọn
Nuxtjs
cho phần web -
Database: Mysql, Postgresql, MongoDB, Redis... (Giả sử là
Mysql
,Redis
nha)
- Storage: viblo.asia có tính năng lưu trữ ảnh bài viết nên chắc cần 1 storage khoảng 500GB, chắc nhiều bạn cũng thắc mắc là tại sao không dùng ổ cứng luôn mà lại thuê storage cho mất tiền mất công đúng không 😆.
Đương nhiên rồi việc sử dụng cloud storage chúng ta sẽ tận dụng được triệt để được hiệu quả của điện toán đám mây
- Cũng bởi khi chúng ta sử dụng cloud storage thì ở mọi nơi, server, node,... đều có thể truy xuất dữ liệu ảnh, video,...
- Không cần phải share tài nguyên này trên các server, node, thường phải tự cấu hình Network File System (NFS)
- Khi dung lượng bị đầy sẽ không làm ảnh hướng đến server, node đang dùng
- Và việc thuê cloud storage cũng khá là rẻ nha, mình sẽ viết ở phía bên dưới .....
📌 THUÊ DỊCH VỤ
Việc thuê các dịch vụ có cấu hình ra sao phụ thuộc khá nhiều vào nhu cầu sử dụng của trang web. Ví dụ trang web của bạn có 4 triệu pageview/tháng cũng sẽ đòi hỏi cấu hình và số lượng node (server) hơn 2 triệu pageview/tháng. Chính vì vậy bạn cần đo lường các thông số trước
- Đo lường realtime users, pageview hàng ngày, hàng tuần, hàng tháng,... có thể sử dụng Google Analytics
- Đo lường khả năng chịu tải: tham khảo tại đây
Hiện này ở Việt Nam và nước ngoài có khá nhiều nhà cung cấp các dịch vụ server, cloud như Viettel Cloud, FPT Cloud, AWS, Linode,... Tuy nhiên sau khi xem xét về chi phí và khả năng scaling thì mình sẽ chọn nhà cung cấp Linode nhé. Bạn có thể thuê các server cloud của Linode sau đó tự cài K8s cluster tuy nhiên các bạn cũng có thể thuê luôn Linode Kubernetes. Để tiện hơn thì mình sẽ chọn option thuê luôn Linode Kubernetes . Theo kinh nghiệm của mình thì chúng ra nên tách các thành phần và sử dụng riêng các node tùy theo công năng để tránh việc service này ảnh hưởng đến các service còn lại. Tuy nhiên để tránh lãng phí resources ta nên estimate một cách kỹ lưỡng tránh việc, resources quá lớn mà lại không sử dụng lại phí $ 🤪. Cụ thể với các thành phần trang web như trên với 1-2 triệu pageview/tháng và giờ cao điểm khoảng 300 users realtime thì sẽ cần:
- Web service: x4 node 4 CPU, 8GB (16 CPU, 32GB): 160$/month https://www.linode.com/pricing/#kubernetes
- Mysql Database service: x3 2CPU, 4GB (6CPU, 12GB): 140$/month https://www.linode.com/pricing/#databases-mysql
- (Optional) Redis Instance: x1 CPU, 24GB: 60$/month (Trường hợp bạn cần sử dụng nhiều bộ nhớ RAM), hoặc bạn có thể cài đặt redis trong các node của web service cũng được nhưng nhớ rằng phải thêm Resources Limits nha. Mình thấy hình như trên trang Viblo có tính năng pagecache nên sẽ cần lưu lại nhiều file hình nên chắc họ cũng cần bộ nhớ RAM lớn. https://www.linode.com/pricing/#compute-high-memory
- Monitoring: x1 node 2 CPU, 6GB: 30$/month
- Redis + Search: x2 Volume: 2$/month (hiểu đơn giảm volume dùng để mount point từ server, node vào trong container)
- x1 Nodebalencers 10$/month
Việc thuê thêm Nodebalencers sẽ mang lại cho ta nhiều tác dụng
NodeBalancers của Linode giúp cân bằng tải trên nhiều server được khởi tạo trên cùng Datacenter, đặc biệt hữu ích khi lưu lượng truy cập quá lớn. Khi đó, NodeBalancers giúp phân bố đồng đều lưu lượng truy cập, cải thiện năng suất hoạt động tổng thể cũng như giảm thiểu tình trạng quá tải, ngưng hoạt động. Tính năng này được kích hoạt với mức giá 10$/tháng hay 0.015$/giờ.
Đọc thêm tại: https://www.linode.com/products/nodebalancers
Về storage có thể dùng Viettel Cloud Storage, FPT CLoud Storage hoặc Linode Object Storage. Không phải sính ngoại nhưng dịch vụ storage của các doanh nghiệp Việt chi phí đang khá là cao nên chắc mình lựa chọn Linode Object Storage dung lượng 500GB với chi phí chỉ có 10$ 1 tháng
Vậy là với tổng chi phí thuê dịch vụ khoảng 400$/month, ta đã có một hạ tầng ngon, bổ rẻ rồi 😍. Cấu hình trên không hoàn toàn đúng với các trang web vì performance code của chúng ta là khác nhau, hãy cố gắng review lại code của mình đi có thể sẽ giảm được tương đối $ đó 🤑
📌 RESOURCES REQUESTS VÀ LIMITS
- Request – Yêu cầu
Pods yêu cầu về lượng tài nguyên CPU, memory trong workload nó sẽ được cấp. Tài nguyên request tối đa phải nhỏ hơn lượng tài nguyên mà một node mạnh nhất trong cluster có thể tải được Nếu lượng tài nguyên yêu cầu không sẵn có trên node thì pod sẽ ở trạng thái "pending" và không thể khởi tạo trên node đó được, đồng nghĩa với việc pod này không hoạt động 🤧
Cần thêm resouces requests trong trường hợp bạn dùng rất nhiều các services để kube-scheduler đánh dấu xem tài nguyên của node nào đã bị chiếm dụng để không assign pod vào node đó. Điều này tránh việc tất cả các pods bị assign vào một node mà lại không assign vào node còn lại rồi khi tài nguyên sử dụng thực tế không đồng đều giữa các node.
- Limits – Giới hạn
Hiểu đơn giản là mình chỉ định giới hạn CPU và memory cho một pod, ví dụ limits CPU: 1, memory: 1Gi thì trong quá trình running nếu tài nguyên sử dụng vượt quá giới hạn đó thì pod sẽ bị crash (không hoạt động) nha 😣
Ở phần thuê dịch vụ chúng ta đã tính toán rất kỹ cấu hình bao gồm CPU và Memory rồi đúng không. Với cấu hình đã thuê ở trên bây giờ chúng ta phải estimate từng services với resources tương ứng, cụ thể là mỗi service sẽ được dùng tối đa bao nhiêu CPU và Memory.
Với việc thuê riêng database Mysql ta sẽ không cần cài đặt gì cho nó nữa vì ta sẽ chỉ cần connect đến DB HOST là được. Do Redis Instance trên 1 node riêng nên ta có thể bỏ qua set limit resources cho service này.
Vậy chúng ta cần estimate resources cho web service: Api
, Worker
, Scheduler
, Elasticseach
, với resources chúng ta thuê là 16 CPU với 32GB RAM thì
- API: scale 4 pod, mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 1 memory: 2Gi requests: cpu: 500m memory: 512Mi
Giới hạn đến 4 CPU và 8GB RAM
- Web: scale 4 pod, mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 1 memory: 2Gi requests: cpu: 500m memory: 1Gi
Giới hạn đến 4 CPU và 8GB RAM đó
- Workers: scale 3 pod, mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 500m memory: 1Gi requests: cpu: 250m memory: 256Mi
Giới hạn đến 1.5 CPU và 3GB RAM
- Scheduler: scale 1 pod, mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 1 memory: 1Gi requests: cpu: 500m memory: 512Mi
Giới hạn đến 1 CPU và 1GB RAM
- Redis: scale 1 pod, nếu sử dụng resources của web service thì mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 1 memory: 4Gi requests: cpu: 500m memory: 1Gi
Giới hạn đến 1 CPU và 4GB RAM
- Elasticsearch: scale 1 pod, mỗi pod sẽ estimate resources như sau
resources: limits: cpu: 2 memory: 2Gi requests: cpu: 1 memory: 1Gi
Giới hạn đến 2 CPU và 2GB RAM
- Ngoài ra phía service monitoring việc estimate và nâng cấp resources tùy thuộc bạn muốn cài đặt những gì trên đó như grafana, prometheus,...
=> Chúng ta đã estimate sử dụng tối đa 13.5 CPU (84%) và 26 GB RAM(81%), mình nghĩ nên chỉ cho phép các service dùng tối đa 80~85% resources hiện có để đảm bảo tính ổn định và tốc độ trang web trong trường hợp có nhiều người sử dụng, tránh việc dùng hết 100% resources đến khi quá tải lại sập hết các dịch vụ 😭
Ở bài viết này tạm dừng lại ở việc thuê dịch vụ và estimate resources cho các service, ở các bài viết sau sẽ thêm chi tiết việc triển khai nha các bạn yêu quý 💞