Saturday 5 September 2020

Bucket list của tôi

Trong tiếng anh có một thuật ngữ "bucket list", được định nghĩa như này:

-  a number of experiences or achievements that a person hopes to have or accomplish during their lifetime

- những thứ bạn muốn làm và đạt được trong cuộc đời mình (thứ hữu hạn)

Có hẳn một bộ phim tên là The Bucket List bạn đã xem chưa? Bạn nên xem nếu bạn thấy cuộc đời mình đang vô lý và nghĩa (bế tắc mạnh).

Tôi viết bài blog này để lưu lại các khoá học hay, mà tôi cho là hữu ích. Chắc là tôi sẽ bắt đầu học chúng khi tôi về nghỉ hưu xD


1. Online Crytography Course

2. Probability and Statistics

3. https://www.edx.org/micromasters/mitx-statistics-and-data-science



Lưu mật khẩu xuống database an toàn

Một ngày hệ thống của bạn bị hacked, dù bạn có mong chờ hay không.

Làm thế nào để, dù hacker có lấy được thông tin mật khẩu người dùng trong database ứng dụng của bạn, thì anh ta cũng không biết được (hoặc sẽ mất rất nhiều công sức và thời gian để biết được) mật khẩu của người dùng trong database ứng dụng của bạn là gì?

Hãy tham khảo bài viết chi tiết này của Taylor Hornby (defuse.ca), trong đó Taylor chia sẻ về cách lưu mật khẩu người dùng đúng cách xuống database:

https://crackstation.net/hashing-security.htm

tl;dr

- khi lưu mật khẩu người dùng vô db cần hash trước khi lưu

- dùng các thư viện và hàm hash chuẩn như Argon2, bcrypt, scrypt, or PBKDF2 

- thêm muối (salt) khi hash, tạo salt bằng hàm random mạnh

- dùng slow hash function để làm chậm khả năng bị brute force và dictionary 


và cuối cùng là bạn không nên tự thiết kế một hàm băm mật khẩu rồi đem xài nó cho production (trừ khi bạn là một chuyên gia trong việc này). Hãy dùng các hàm băm chuẩn đã được sử dụng và đánh gía bởi các chuyên gia.

Saturday 27 June 2020

Nghề SRE

Vị trí SRE (Site Reliability Engineer) đảm bảo cho hệ thống được vận hành trơn tru, ổn định cao bằng cách sử dụng các kỹ năng, phương pháp, lập trình phần mềm vào việc vận hành hệ thống. Vị trí này ngoài việc hiểu về Hardware, Networking, OS, System bạn cũng cần có kỹ năng về lập trình phần mềm. 

Đối với team nhỏ thì bạn cần có càng nhiều kỹ năng trên càng tốt, còn trong team lớn thì thường mỗi người sẽ đảm nhiệm chuyển sâu về một mảng.

Thông thường các công việc vận hành hệ thống thường có nhiều việc xử lý manually cần được tự động hoá nhiều nhất có thể để tránh các lỗi do con người.

Các công ty lớn có đội ngũ SRE riêng thì họ thường tự viết các tools để xài, trong khi các công ty nhỏ có thể dùng các công cụ nguồn mở hoặc sử dụng các dịch vụ DevOps của bên thứ 3. 

Tôi thấy có các nguồn tài liệu hay cho các bạn muốn theo hướng làm SRE hay DevOps ở dưới

Chạy ứng dụng machine learning trên production


Đi cùng với sự phổ cập AI/ML trong đời sống từng người dân,  khái niệm DevOps cho các ứng dụng Machine Learning, thường gọi MLOps, đang dần hình thành ở giai bước đầu với nhiều công cụ open-source với nhiều đóng góp khá sôi động.

Theo tôi MLOps dựa trên các khái niệm, công cụ sử dụng trong DevOps tuy nhiên có một vài đặc thù  phát triển và vận hành các ứng dụng ML cần có các công cụ được tuỳ biến để phù hợp với việc xây dựng một life cycle cho các ứng dụng ML từ khâu design, development tới chạy production.

Các điểm khác biệt của một ứng dụng ML 

- Data Versioning
- Model Versioning
- GPU, hardware requirements
- Release, Production ML application


Các bài viết, công cụ trên internet liên quan tới MLOps về các công cụ này mà tôi sưu tầm được

- Continuous Delivery for Machine Learning (CD4ML) https://martinfowler.com/articles/cd4ml.html
- What I learned from looking at 200 machine learning tools https://huyenchip.com/2020/06/22/mlops.html




<tiếp tục cập nhật>

Monday 7 October 2019

Bắt đầu với kỹ thuật sharding trong database

Một trong các bottleneck của hệ thống thường xảy ra ở lớp database. Bạn phát hiện ra hệ thống của mình cũng rơi vào trường hợp tương tụ như vậy, việc đọc và ghi dữ liêu vô database bị chậm với lượng dữ liệu ngày càng lớn. Khi đó bạn phải nghĩ tới việc mở rộng database của mình. 

Một bài viết hay về sharding.
https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6




Khi nói tới việc mở rộng databases có hai xu hướng chính:
 
- mở rộng theo chiều dọc (vertical scaling)
- mở rộng theo chiều ngang (horizontal scaling) 

Mở rộng theo chiều dọc: 
- thực hiện việc tạo thêm nhiều tables và lưu ở các databases riêng biệt. Công việc này thường sẽ thực hiện ở lớp ứng dụng, bạn sẽ cần phải phân chia các ứng dụng của mình, mỗi ứng dụng sẽ sử dụng một database tách biệt. Việc sử dụng micro services cùng với việc mỗi service sử dụng một ngôn ngữ lập trình và một hệ cơ sở dữ liệu khác nhau được xem là một phương thức áp dụng việc mở rộng database theo chiều dọc.

Mở rộng theo chiều ngang: 
- thực hiện lưu trữ các rows của một table ở trên các máy chủ database khác nhau (được gọi là kỹ thuật sharding). Sharding đã được áp dụng ở nhiều hệ cơ sở dữ liệu khác nhau, gần như các hệ cơ sở dữ liệu hiện đại đều đang dùng sharding như là một tính năng hiển nhiên phải có,  ví dụ Cassandra, MongoDB, HBase ... 


Sharding (mở rộng database theo chiều ngang) được sử dụng khi dữ liệu lưu trữ trong một table quá lớn dẫn tới việc lưu trữ các rows của table đó ở nhiều máy chủ khác nhau là cần thiết, nhằm đảm bảo hiệu năng và khả năng mở rộng cho hệ thống. 

Có nhiều phương pháp thực hiện sharding, các phương pháp được phân biệt và so sánh dựa trên: 

- cách dữ liệu được đọc lên từ database (reading data) 
- cách dữ liệu được ghi xuống database (writing data)

Một khái niệm quan trọng trong sharding là Partition Key, nó sẽ xác định việc dữ liệu sẽ được lưu trữ phân tán như thế nào, dựa trên Partition Key để truy cập và chỉnh sửa dữ liệu một cách hiệu quả thông qua việc điều hướng các thao tác với database vô đúng nơi mà dữ liệu đang được lưu. Các dữ liệu có cùng Partition Key sẽ được lưu trên cùng một nơi (máy chủ).


Sharding được phân theo 2 loại chính là Algorithmic và Dynamic. Với Algorithmic sharding thì client sẽ tự xác định được dữ liệu đang được lưu ở đâu, còn đối với Dynamic sharding cần có một locator service để giúp xác định dữ liệu đang được lưu ở đâu.

Algorithmic sharding

Kiểu sharding này sẽ sử dụng một hàm sharding nhận vô tham số partition_key và trả về database_id để xác định vị trí dữ liệu ở đâu. 
Một hàm sharding đơn giản có thể dùng đó là: hash(key) % number_of_db. 

Dữ liệu được lưu trữ phân tán chỉ dựa trên hàm sharding, không phụ thuộc vào độ lớn dữ liệu hay không gian lưu trữ. Do đó kiểu sharding này chỉ nên sử dụng cho loại dữ liệu key-value trong đó loại dữ liệu phải giống nhau (không quá khác biệt).

Dynamic sharding

Trong kiểu sharding này, cần có một locator service chạy riêng biệt giúp xác định việc lưu trữ dữ liệu ở đâu. Để đọc và ghi dữ liệu, client cần kết nối và truy vấn vô locator service trước tiên. Locator sẽ thực hiện việc điều phối các hoạt động lưu trữ dữ liệu trong cluster một cách linh động. HDFS, Apache HBase, MôngDB đều sử dụng kiểu sharding này.

---
Vitess là công cụ nguồn mở giúp việc mở rộng Mysql theo chiều ngang (horizontal scaling or sharding) được thực hiện dễ dàng, đây là một trong những core infrastructure của Youtube

Vitess: https://github.com/vitessio/vitess
Sharding thực hiện ở instagram: https://instagram-engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c

Friday 4 October 2019

Học Data Structures & Algorithms phỏng vấn xin việc

Hầu như các công ty công nghệ lớn làm sản phẩm khi tuyển nhân viên họ đều muốn tìm các ứng viên có kiến thức tốt về cấu trúc dữ liệu và thuật toán. Với những người mất gốc và tưởng lầm thời gian học đại học là để chơi game, tán gái như tôi thì việc tự học cấu trúc dữ liệu và thuật toán là một việc không dễ dàng.

Một trong những khoá tôi cảm thấy học dễ vô nhất về cấu trúc dữ liệu và thuật toán là khoá học Intro to Data Structures and Algorithms trên Udacity, ngoài việc cấu trúc khoá học được thiết kế chi tiết dễ theo dõi không yêu cầu các kiến thức chuyên sâu khác để theo được hết khoá học, còn có lẽ là do cô giảng viên xinh đẹp tóc vàng Brynn



Ngoài việc học được các kiến thức cơ bản nhất về cấu trúc dữ liệu và thuật toán, khoá học này còn giúp bạn một số kỹ năng để đi phỏng vấn ở các công ty công nghệ lớn như Google, Facebook ... nghe thế này cũng đáng để học rồi đấy.

Cấu trúc chính của khoá học sẽ nói về các hiệu quả của các chương trình và các đo hiệu quả các chương trình đó bằng Big O(). Tiếp sẽ giới thiệu về các cấu trúc dữ liệu, cách triển khai các cấu trúc này trong python như list, maps, trees, graphs ... các thuật toán chính trong searching và sorting như binary search, bubble sort, merge sort, quick sort ...

Phần cuối của khoá sẽ có một vài cách để trả lời các câu hỏi phỏng vấn về cấu trúc dữ liệu và thuật toán, có phần giả lập đi kèm xem rất giống thật.

  1. Introduction and Efficiency
  2. List-Based Collections
  3. Searching and Sorting
  4. Maps and Hashing
  5. Trees
  6. Graphs
  7. Case Studies in Algorithms
  8. Technical Interview Tip
Một điều hấp dẫn khác là  khoá học này miễn phí trên Udacity, bạn nào muốn tự mình khám phá thì nhào vô link ở đây để học ngay thôi, bạn nào muốn tìm bạn để trao đổi thảo luận về nội dung khoá học thì để lại còm men ở dưới bài này nhé.


Sunday 25 November 2018

Làm thế nào chạy nhiều ứng dụng trên kubernetes


Introduction

Một trong các vấn đề khi chạy sản phẩm trên internet public phục vụ số lượng người dùng lớn mà chúng ta thường gặp phải là khả năng mở rộng (Scalability) của hệ thống. Khi số lượng người dùng tăng lên với số lượng lớn, một hệ thống muốn đáp ứng được thì cần phải có tính mở rộng, tăng lượng tài nguyên để đảm bảo khả năng đáp ứng số lượng truy cập của người dùng tăng.




Kubernetes (thường gọi tắt là k8s) đang trở nên thông dụng với việc số lượng các công ty (cả enterprises lẫn startups) sử dụng k8s đang tăng lên nhanh chóng. K8s được ưa chuộng không chỉ bởi số star trên github của project đang là 42,941 với 1860 contributors (thời điểm viết bài), mà còn do các tính năng vượt trội mà nó mang lại trong việc thực hiện deployment, maintenance, và scaling các ứng dụng chạy trên đó.

Tìm hiểu thêm về Kubernetes trên Github

Trong bài viết này tôi sẽ chia sẻ về cách chúng tôi dùng Kubernetes, cụ thể là GKE (Google Kubernetes Engine), để chạy sản phẩm của dự án và Gitlab CI để hỗ trợ thực hiện tích hợn liên tục CI (Continuous Integration) giúp tăng tốc độ quá trình phát triển sản phẩm.

Tech Stack

Một trong các ưu điểm của k8s, phù hợp để chạy các ứng dụng microservice, trong đó mỗi service có thể được phát triển dùng các ngôn ngữ, công nghệ khác nhau và được đóng gói vào trong các docker image riêng biệt. Dưới đây là một số công nghệ và framework mà chúng tôi sử dụng trong dự án.

  • nodejs – phát triển frontend
  • vuejs – phát triển cms client
  • akka-http – phát triển backend (rest api)
  • docker – đóng gói ứng dụng
  • kubernetes – chạy, quản lý, điều phối docker container
  • google kubernetes engine (gke) – chạy kubernetes cluster
  • google cloud sql – chạy mysql database
  • gitlab ci – lưu trữ source code và thực hiện tích hợp liên tục


Dockerize Application

Đầu tiên chúng tôi cần viết các Dockerfile cho từng service frontend/cms/backend, Dockerfile là nơi viết các hướng dẫn, câu lệnh để build các docker images.

Dockerfile cho frontend, thực hiện cài đặt thư viện phụ thuộc, build nodejs app, sau đó copy kết quả vào image. Mở port 3000 cho kết nối từ bên ngoài, chạy lệnh npm start khi bật container.

Tương tự cho các service cms và backend, chúng tôi cũng cần viết Dockerfile để đóng gói source code của ứng dụng vào trong docker image. Phần backend chúng tôi dùng sbt plugin là sbt-native-package để build docker image.

Kubernetes

Sau khi application đã được đóng gói vào trong các docker images bằng Dockerfile, bước tiếp theo cần tìm cách để chạy các containers từ các images này một cách hiệu quả? Đây là thời điểm k8s trở nên hữu ích với các tính năng scale không giới hạn của mình (thực ra giới hạn hiện tại của k8s thời điểm viết bài này là 5000 nodes, 100 pods trên một node, tổng số pods là 150000, tổng số containers là 300000).

Để chạy một ứng dụng trên k8s, chúng tôi viết các manifest file cho ứng dụng đó. Đây là các file (ở định dạng YAML) đặc tả chứa những thông tin liên quan tới việc chạy container trên k8s chẳng hạn như : tên image, container port, biến môi trường, đánh label … Trong k8s manifest file sẽ cần có 2 thành phần chính là DeploymentService.

  • Deployment : sẽ đảm bảo các containers chạy đúng về số lượng, cấu hình với cài đặt như trong manifest file
  • Service : giống như một endpoint được exposed để cho phép truy cập từ bên ngoài

Dưới đây là k8s manifest file cho frontend service : frontend.yaml

Để áp dụng các manifest file này lên k8s cluster, chúng tôi dùng kubectl (kubernetes client). Đây là một ứng dụng dòng lệnh giúp tương tác với k8s cluster. Trước khi dùng kubectl chúng tôi cần thực hiện việc cấu hình xác thực để kubectl làm việc với k8s cluster. Lệnh phía dưới sẽ đọc nội dung của file frontend.yaml, gọi vào API của k8s cluster để thực hiện lệnh theo yêu cầu.

kubectl create -f frontend.yaml


Một cách khác chuyên nghiệp hơn (maybe ;)) là viết manifest này thành một helm chart để deploy lên cluster, nếu các bạn muốn có thể tìm hiểu thêm về helm ở đây

Ngoài Deployment và Service, còn có các thành phần khác mà chúng tôi cần phải cài đặt để giúp hoàn thiện việc triển khai app chạy trên k8s.

  • ingress : quản lý, điều khiển các request vào các service phía trong k8s, chúng tôi chọn nginx-ingress được cộng đồng hỗ trợ tốt với nhiều tính năng, dễ dàng cài đặt và sử dụng cho những người đã có kinh nghiệm với nginx.
  • service account : giúp phân quyền truy cập thao tác vào k8s cluster
  • configmap, secret : lưu trữ các cấu hình, tham số
  • persistent volume : dùng cho các dữ liệu cần lưu trữ lâu dài


Google Kubernetes Engine

Để triển khai và chạy k8s cluster, chúng tôi cân nhắc các lựa chọn :

  • Amazon Cloud AWS thì có thể dùng EKS (service cung cấp bởi AWS) hoặc sử dụng Kops xây dựng bởi cộng đồng
  • Microsoft Cloud Azure có AKS
  • Google Cloud GCP có GKE

Sau khi cân nhắc về khía cạnh maturity (mức độ ổn định của một sản phẩm), tính đơn giản dễ sử dụng chúng tôi đã quyết định lựa chọn GKE, một điểm cộng cho GKE là các maintainer chính của Kubernetes open source cũng là những người xây dựng nên GKE

Trên GKE chúng tôi tạo 2 Kubernetes cluster :

  • development cluster sử dụng cho môi trường test/staging
  • production cluster sử dụng cho môi trường live/production


Gitlab CI

Cuối cùng chúng tôi dùng Gitlab CI để tự động hoá các bước test, build, package và deploy. Việc thực hiện CI trên Gitlab được thiết lập qua .gitlab-ci.yml file. Các bước trong .gitlab-ci.yml :

  • test : chạy unit test code
  • build : chạy các job build
  • package : đóng gói docker image và đẩy lên image registry (gitlab có tích hợp sẵn)
  • deploy : chạy deploy lên k8s clusterfile .gitlab-ci.yml của frontend mô tả các jobs (test, build, package, deploy) sẽ tự động chạy khi có code được merge vào nhánh develop trên Gitlab.
Tạo .gitlab-ci.yml file của frontend mô tả các jobs (test, build, package, deploy) sẽ tự động chạy khi có code được merge vào nhánh develop trên Gitlab :

Conclusion

Đến đây chúng tôi đã xây dựng cơ bản một ứng dụng có thể chạy trên k8s cluster. Trong thời gian tiếp theo, chúng tôi sẽ tập trung vào các best practice để áp dụng vào hệ thống, giúp cải thiện hiệu năng, tiết kiệm tài nguyên và tăng tính bảo mật của hệ thống.

Cám ơn bạn đã đọc bài, welcome các ý kiến đóng góp của các bạn. Hãy để lại comments ở dưới bài viết.

Bucket list của tôi

Trong tiếng anh có một thuật ngữ "bucket list", được định nghĩa như này: -  a number of experiences or achievements that a person ...