CHIA SẺ VỀ TESTING VỚI HỆ THỐNG MICROSERVICES – PHẦN 2

Như phần 1 mình đã đề cập, thì các phần tiếp theo mình sẽ chia sẻ các vấn đề mà bản thân mình gặp phải khi làm testing trong 1 hệ thống sử dụng kiến trúc Microservices, bạn nào chưa coi qua các phần trước có thể theo dõi lại ở danh sách kế bên

Bạn sẽ làm gì khi được tham gia 1 dự án với mô hình kiến trúc Microservices?

Một ngày đẹp trời bạn nhận được một lời đề nghị tham gia dự án mới để xây dựng sản phẩm thật là hoành tráng. Khi đó mọi người đều nói rằng sẽ áp dụng kiến trúc Microservices. Vậy khi đó bạn cần sẽ làm gì để giúp cho team cũng như đồng đội testers sau này sẽ cảm thấy không phải bơi trong một mớ hỗn độn, mọi thứ trở nên rối rắm, và bản thân mình cũng không biết phải giải thích với đồng đội mới hệ thống này hoạt động ra sao.

😩 Thật ra mình chưa được trải qua kinh nghiệm đó, nhưng từ kinh nghiệm mình trải qua với hệ thống hiện tại thì, nếu bạn được tham gia dự án đó từ ban đầu thì đó là cơ hội to lớn để bạn có thể cùng đội ngũ Developer xây dựng nền móng vững chắc cho sản phẩm sau này, ở đây theo quan điểm của mình thì đối với những sản phẩm mới, đang trong quá trình phát triển để ra được một MVP (Minimum Viable Product) thì bạn có thể đặt những câu hỏi sau trong quá trình chuẩn bị phát triển nó:

  • Microservices trong thời điểm này liệu có thật sự cần thiết? Câu hỏi này nó như cách để cả team cùng ngồi lại nhìn nhận vì sao mình chọn thiết kế hệ thống theo Microservices, những ưu điểm và nhược điểm khi chọn cách này trong giai đoạn MVP, từ đó team sẽ cùng thống nhất với nhau về cách xây dựng và phát triển sản phẩm ngay từ nền móng ban đầu.
  • Nếu sử dụng Microservices thì boundary context cho những services đó là gì? Có cần phải phát triển dựa theo mô hình DDD (Domain-Driven Design) không?
  • Việc thực hiện ghi lại các documents liên quan về hệ thống sẽ được thực hiện ra sao? Có thể sẽ có bạn thắc mắc là nếu làm theo mô hình Agile thì trong mô hình đó có một ý đại khái là “Working software over comprehensive documentation”, dịch ra thì kiểu đại khái “việc phát triển sản phẩm và giúp nó hoạt động sẽ quan trọng hơn việc phát triển những tài liệu một cách đầy đủ/toàn diện”, ở đây mọi người lưu ý cụm từ “1 cách đầy đủ/toàn diện” thì nó mang hàm ý các bạn phải biết việc phát triển những tài liệu thế nào là vừa đủ, để nó cân bằng 2 thứ giữa việc phát triển phần mềm và tài liệu “vừa đủ” để các bên liên quan vẫn có thể tham khảo sau này.
  • Các services bên trong thì có thể thực hiện việc testing cho nó như thế nào? Việc hỏi câu này sẽ giúp các bạn định hướng cho team về khả năng testability của service ngay từ lúc ban đầu, tránh việc sau khi phát triển xong cũng không biết cách nào để test cho được những cái mình muốn test.
  • Có các dependencies services nào bên ngoài có thể cản trở việc testing hoặc phát triển sản phẩm không? Câu này cũng giúp các bạn định hướng khả năng testability của services

Đấy là những gì mình nghĩ có thể cần thiết để giúp cho các bạn khi được tham dự một dự án thiết kế và xây dựng sản phẩm theo mô hình Microservices ngay từ ban đầu. Những câu hỏi trên có thể giúp mọi người định hướng được việc xây dựng và kiểm tra sản phẩm có thể rõ ràng hơn.

Cách để một người mới tìm hiểu kiến thức về hệ thống Microservices trong dự án trong giai đoạn hậu MVP?

Trở lại với câu chuyện của mình 🥲 , thời điểm mình tham gia dự án thì sản phẩm đã được xây dựng cũng hơn 6 năm. Và theo độ dài vòng đời của một startup thì sản phẩm này vẫn đang ở trong giai đoạn còn non trẻ. Và vì còn non trẻ cho nên việc chạy đua để sớm ra tính năng, sớm ra MVP là điều quá hiển nhiên.

Và nó cũng kéo theo một hệ quả là khi mình tham gia dự án thì những tài liệu về hệ thống khá là rời rạc cũng như có phần bị “lạc hậu” khá nhiều. Bên cạnh đó các tài liệu về testing cũng không thật sự có đầy đủ, việc cân bằng giữa đẩy nhanh tiến độ phát triển sản phẩm và chất lượng sản phẩm vẫn luôn là một bài toán khó trong các mô hình phát triển sản phẩm, dù bạn có làm theo mô hình Waterfall hay Agile, thì nó vẫn luôn rất khó giải quyết.

Vì thế bài toán đầu tiên mình cần giải quyết là làm sao để có thể nắm được kiến thức về hệ thống một cách nhanh nhất có thể 🥲

Confluence Page hay bất kỳ nơi nào chứa các documents hoặc notes là người bạn của bạn

Ở công ty của mình thì mọi tài liệu hiện tại đang được lưu trữ trên Confluent Page, tuy có những tài liệu nó không có hoặc bị outdated nhưng ít nhất mình cũng sẽ có được những thông tin ban đầu về hệ thống, mặc dù những thông tin đó có thể vẫn sẽ còn khá rời rạc và chưa có tính kết nối với nhau.

Khi tìm kiếm trên các trang lưu trữ tài liệu thì kỹ năng xây dựng từ khóa để tìm kiếm là phần rất quan trọng, nó tượng tự kỹ năng khi bạn gặp vấn đề và cần tìm cách tìm kiếm trên Google. Một vài keywords mình thường dùng để tìm kiếm tài liệu về hệ thống như sau: “Tên_service SAD”, “Tên_service sequence diagram”, “Tên_service API document” , “Tên_service Architecture”, “Tên_serivce Error Code” hoặc chỉ cần đơn giản là tìm kiếm với tên service mà bạn đang muốn tìm hiểu.

Kỹ năng đọc Sequence Diagram và cách hiểu hình vẽ High-level Software Architect Design là thứ cần thiết

Khi bạn đa có trong thay thông tin hay tài liệu của service mình cần thì điều kế tiếp là bạn phải biết cách đọc và hiểu nó. Nó như kiểu võ công bí kíp đã đưa tới tận tay cho bạn và việc còn lại chỉ là làm sao để luyện thành võ công của mình 😄

Như ví dụ sau đây thì mình mượn tạm cái hình của TiDB khi mô tả về cách nó hoạt động bên trong nó:

Như hình sequence digram này thì các bạn sẽ thấy nó sẽ có những flows tương tác giữa 3 hệ thống bao gồm tidb, pd và tikv, trong đó thì giữa tidb và pd sẽ có khối lệnh riêng để truy vấn toàn bộ những key theo region và sau đó thì giữa tidb và tikv để truy vấn toàn bộ data theo những region key đã tìm được từ khối lệnh trên. Và cuối cùng là khối lệnh giữa client và tidb

Từ những thông tin được thể hiện trong sequence diagram thì các bạn đa có cái nhìn rõ hơn về cách các services sẽ tương tác với nhau như thế nào

Bên cạnh đó việc đọc và hiểu high-level architect sẽ giúp cho bạn có cái nhìn tổng quan hơn về toàn bộ hệ thống bên dưới, bạn có thể dễ dàng biết được những critical services sẽ là những services nào, những service nào sẽ là consumer và provider của nhau

Như ví dụ sau thì mình cũng mượn tạm hình của TiDB:

Như hình ở trên thì mình có thể nắm được là hệ thống kiến trúc của TiDB sẽ có 4 phần bao gồm TiDB, TiKV PD và TiSpark, và phần TiSPark sẽ là 1 phần riêng biệt không ảnh hưởng TiDB. Phần PD sẽ có nhiệm vụ quản lý metadata, và nó sẽ liên quan tới việc quản lý cluster của TiDB và có thể nó là phần quan trọng trong hệ thống TiDB

Hãy dùng Mindmap để tạo nên bức tranh tổng thể về toàn bộ hệ thống của sản phẩm mình đang làm

Mình nghĩ có nhiều cách để các bạn có thể xâu chuỗi những mảnh nhỏ về thông tin hệ thống thành 1 bức tranh tổng thể hơn, còn với mình thì vẫn duy trì thói quen sử dụng Mindmap cho việc này. Nó giúp mình vừa có thể dễ dàng visualize những thông tin mà mình có được thành bức tranh tổng thể hơn, bên cạnh đó khi visualize nó lên Mindmap thì mình cũng có thể nhìn ra những chỗ thông tin mà mình vẫn còn thiếu để từ đó có thể tìm cách đi tìm kiếm những thông tin đó.

Exploratory testing và những tool liên quan tới MIM là cách hiệu quả để tìm hiểu thêm về sản phẩm ở mặt business knowledge và technical knowledge

Việc kế tiếp bạn cần làm là tiến hành explore product như góc nhìn của một end user và kèm theo những tool để giúp bạn có cái nhìn ở mặt kỹ thuật. Bên mình thì sản phẩm nó sẽ được phát triển trên 2 nền tảng là Web và native mobile application, vì thế mình kết hợp cả việc dùng chrome developer tool và những tools dạng MIM (man in middle) như mitm.proxy hoặc Proxyman để intercept network.

Ở đây mình thường sẽ thực hiện 1 user journey flow và sau đó coi thử với flow đó thì hệ thống nó sẽ có những APIs nào tương tác trong flow đó, và kế tiếp là mình sẽ liên kết với những thông tin mình đã có được từ SAD và sequence diagram để có thể có một bức tranh ở mặt user journey flow.

Việc này sẽ cực kỳ có ích khi các bạn bắt đầu phát triển tính năng mới, hoặc khi sản phẩm của các bạn đã có end user sử dụng, khi đó nếu bạn gắp phải những issue (ở đây mình chỉ gọi là issue vì có thể nó chưa hẳn là bug nhé) hoặc khi khách hàng thông báo về những issue họ gặp phải thông qua hệ thống CS (customer service) thì các bạn có thể dùng khả năng suy luận để dự đoán và giới hạn khả năng issue nó từ đâu. Như hình sau từ bài viết của Oracles from the Inside Out – Michael Bolton

“Oracle is the principle or mechanism used to identify the problem. Oracle helps in making decision about the fault”


Hy vọng phần hai này sẽ có những thông tin hữu ích cho các bạn khi tham gia phát triển một sản phẩm theo mô hình Microservices ở thời điểm ban đầu hoặc là “tay ngang” như mình. Mình xin kết thúc phần hai ở đây, viết nãy giờ cũng khá dài rồi, hẹn các bạn ở phần ba, nơi mình giãi bày tiếp về những khó khăn trong quá trình phát triển tiếp tính năng và việc thực hiện testing cho nó 🥲

Chia sẻ về Testing với hệ thống Microservices – Phần 1

Năm mới chúc mọi người có thật nhiều sức khỏe, an khang thịnh vượng, và sự nghiệp ngày càng thăng tiến


Đôi dòng tản mạn trước khi bắt đầu chuỗi bài viết, năm 2021 thì mình cũng không có nhiều bài viết lắm do 1 phần mình vừa mới thay đổi chỗ làm, và công việc cũng hơi nhiều. Bên cạnh đó thì cũng mong muốn trải nghiệm nhiều hơn về testing để có thể chia sẻ thêm cho các bạn những kinh nghiệm thực tế nhưng mà mình trải qua. Còn nói đơn giản hơn thì năm ngoái mình hơi lười 🤣 chủ yếu mình chỉ toàn post bài trên fanpage Facebook để chia sẻ vài mẹo nhỏ khi thực hiện testing. Hy vọng năm nay mình sẽ bớt lười lại và có nhiều bài viết hơn ở blog này 😮‍💨 Ví dụ như chuỗi bài viết sắp tới đây về Microservices là những kinh nghiệm và thực tế mình đã trải qua trong 1 năm vừa rồi, mình thấy có những cái hay ho có thể chia sẻ để mọi người cùng có thêm những thông tin thú vị 😄 ,vì là những kinh nghiệm do mình trải qua nên có những thứ nó sẽ được nhìn nhận ở khía cạnh từ quan điểm của mình, nên có thể các bạn có cách nhìn nào hay hơn có thể comment chia sẻ nhé 😉

Microservices là gì?

Trước khi bắt đầu chuỗi series bài viết này thì mình cũng muốn chia sẻ qua 1 tí về Microservices là gì và nó khác gì so với những kiến trúc xây dựng ứng dụng trước đây?

Đầu tiên thì phải nói tới thời xa xưa, thời mình còn là con nòng nọc, lúc các chú các bác bắt đầu có Internet, và phát triển những phần mềm ứng dụng cho người dùng. Khi đó thì việc xây dựng ứng dụng nó rất là đơn giản, nó như kiểu mình xậy dựng cái nhà cấp 4, đổ nền, dựng tường, lợp mái nhà, và thế là có cái nhà. Tương tự với nền tảng ứng dụng thì chúng ta có việc xây dựng persistent layer (lớp lưu trữ dữ liệu), business logic layer (lớp chứa các yêu cầu và cách mà ứng dựng hoạt động), và cuối cùng là presentation layer (nơi hiển thị thông tin cho người dùng), ví dụ như bạn có nhu cầu xây dựng 1 ứng dụng cho phép hiển thị hình ảnh trai xinh gái đẹp, khi đó đầu tiên bạn cần persistent layer để chứa hình ảnh trai xinh gái đẹp, bạn cần có business logic để cho phép thêm, xóa hoặc chỉnh sửa hình ảnh, cũng như hiển thị hình ảnh, bạn cần presentation layer để hiên thị hình ảnh đó cho user xem trên bất kỳ nền tảng nào chẳng hạn. Với việc xây dựng ứng dụng theo cách trên thì ta gọi nó là Monolithic Architecture.

Let’s do some magic
Monolithic Architecture

Rồi thì con người cũng phải phát triển và tiến bộ hơn 🤔 từ xe bò ta lên xe ngựa, từ xe ngựa ta lên xe động cơ đốt trong và dần dần thì ta có chiếc xe hơi xịn xò như ngày hôm nay. Tương tự cho ngành công nghệ phần mềm, điều đó cũng xảy ra, từ 1 ứng dựng đơn giản chỉ click, click rồi hiển thị thông tin, ta có thêm nhiều yêu cầu hơn, ta có thêm nhiều tính năng hơn cho ứng dụng đó. Và dần dần từ Monolithic Architecture ta có Service-oriented Architecture và cuối cùng là Microservices Architecture.

Trở lại ví dụ ban đầu ở trên ứng dụng hiển thị trai xinh gái đẹp, ban đầu mình chỉ có nhu cầu hiển thị hình ảnh trai xinh gái đẹp nên ứng dụng khá đơn giản. Sau 1 thời giản ứng dụng được đưa vào hoạt động thì lại có nhu cầu mở rộng thêm như cho phép hẹn hò, cho phép đặt chỗ khách sạn hay mua vé xem phim cũng như quẹt trái quẹt phải, mua gói premium chẳng hạn, rồi bùm chúng ta có ứng dụng Tinder 😛 Khi đó thì việc tiếp tục duy trì với Monolithic Architecture hoàn toàn khả thi, chỉ là nếu tiếp tục có thêm nhiều tính năng hơn nữa thì khi đó ứng dụng sẽ trở nên khá lớn, dẫn tới việc khó bảo trì hay mở rộng thêm tính năng, ngoài ra thì khi cần thay thế hoặc nâng cấp bất cứ thứ gì nhỏ nhất bên trong ứng dụng đều tiềm ẩn những rủi ro liên quan tới mức độ phụ thuộc và độ tương thích với toàn thể ứng dụng, ví dụ như nâng cấp phiên bản thư viện nào đó trong business logic layer. Từ những vấn đề nêu trên thì dần dần phát triển ra SOA và Microservices Architecture, 2 kiến trúc trên ra đời để giải quyết những vấn khó khăn gặp phải Monolithic Architecture khi ứng dụng càng ngày càng phát triển và mở rộng hơn. Vậy SOA và Microservices Architecture khác gì so với Monolithic Architecture 🥺

Cả Service-oriented Architecture và Microservices Architecture, thì ta đều có bước chuyển đổi dần trong việc chia tách những tính năng của ứng dụng thành những module nhỏ hơn. Lúc này ứng dụng sẽ được chia nhỏ ra thành những services và mỗi services chỉ phục vụ 1 business logic cụ thể, như ví dụ ở trên lúc này khi mình muốn thêm tính năng đặt phòng khách sạn hay vé xem phim thì mình sẽ có riêng 1 service cho phần này, khi đó nếu mình có thay đổi hay làm gì đó thì những tính năng trước như thêm xóa sửa hình hoặc mua gói premeium sẽ không bị ảnh hưởng gì cả.

Vậy lợi ích của 2 kiến trúc này so với Monolithic là gì? Rõ ràng khi bạn chia tách những tính năng ra thành những module/service riêng biệt thì việc phát triển hay mở rộng ứng dụng sẽ trở nên dễ dàng hơn. Bên cạnh đó việc thay thế module/service cũng sẽ không quá phực tạp, ví dụ như mình có module/service đặt vé xem phim với CGV, giờ đùng 1 phát CGV ko muốn hợp tác nữa thì việc mình thay thế đặt vé xem phim với Lotte cũng được thực hiện 1 cách dễ dàng và không ảnh hưởng nhiều tới các services khác. Ngoài ra còn vài lợi ích khác so với Monolithic như việc mở rộng ứng dụng sẽ đơn giản hơn do lúc này mình có thể mở rộng ở mức module/service, ví dụ sau 1 năm users của ứng dụng mình tăng lên từ 100 người lên 1tr người và phần lớn toàn vô để đặt khách sạn hoặc vé xem phim, khi đó việc mở rộng module/service liên quan tính năng trên cũng sẽ dễ dàng hơn so với Monolithic, do với kiến trúc Monolithic thì khi mở rộng lên thì mình cần triển khai toàn bộ ứng dụng, dẫn tới có những phần không cần thiết phải mở rộng lên nhưng vấn được “khuyến mãi” kèm theo, và kéo theo cost sẽ không được tối ưu. Bên cạnh đó nó còn có những ưu điểm khác nữa, mọi người có thể coi thêm ở Microservices Architecture.

Vậy SOA hay Microservices Architecture nó quá hoàn hảo và không có nhược điểm gì cả? 😩 Rất tiếc là ông trời không cho cái gì hoàn hảo cả, với những ưu điểm như mình có nói sơ qua ở trên thì nhược điểm của 2 kiến trúc trên cũng có khá nhiều, ví dụ như mức độ phức tạp khi phát triển cũng như testing. Tính thống nhất giữa các services khi thực hiện communicate với nhau (data, integration, etc.) và nếu phát triển 1 hệ thống theo hướng SOA hay Microservice mà không có tính thống nhất cao (contract giữa các service, bounded context rõ ràng) thì chúc mừng team các bạn, các bạn đã quay trúng ô “1 mớ rác hỗn độn” hay còn gọi là microservice chaos, lúc này nó còn tệ hơn Monolithic Architecture 🥲

Nhìn chung 2 architectures này không quá khác biệt về mặt phylosophy, và ở mức độ bài viết của lần này thì mình cũng sẽ không đề cập quá chi tiết về sự khác biệt của 2 kiểu kiến trúc này. Nhìn chung cả 2 kiến trúc trên đều hỗ trợ nhà phát triển trong việc phát triển 1 ứng dụng khi nó bắt đầu trở nên lớn hơn, có nhiều tính năng hơn, cũng như phức tạp hơn.

Theo quan điểm của mình thì việc vận dụng hoặc lựa chọn 1 trong 3 kiến trúc này sẽ phụ thuộc khá nhiều vào nhu cầu của ứng dụng cũng như mô hình kinh doanh, không có cái nào vượt trội hơn hẳn cả, mọi cái đều có ưu điểm và nhược điểm của mình. Riêng về SOA và Microservices Architecture bạn nào quan tâm thì có thể đọc thêm bài này để rõ hơn về sự khác nhau giữa 2 kiến trúc này cũng như những ưu điểm và nhược điểm của nó SOA vs Microservices Architecture, vì nhìn qua thì 2 kiến trúc này khá tương đồng nhau 🤣

Những khó khăn trong việc testing với Microservices Architecture

Giờ thì chuẩn bị vô phần chính của chuỗi series blogs này của mình 🤠 Như mình đã giới thiệu ở trên, từ mô hình Monolithic chuyển sang SOA hay Microservices hay thì nó có những sự khác biệt cơ bản, và dẫn tới khi thực hiện testing cũng có những vấn đề cần giải quyết xung quanh đó, dưới đây là những vấn đề mà trong cả năm qua mình đã trải nghiệm cũng như giải quyết nó, và ngoài ra cũng có những vấn đề mình chưa giải quyết xong dự định năm nay sẽ ráng “xúc” nó luôn 🙄

  • Làm sao để nhận diện sự ảnh hưởng hoặc mức độ phụ thuộc lẫn nhau giữa các services khi document không đầy đủ hoặc bị outdated
  • Làm sao để có thể tìm hiểu về cả hệ thống từ view end-user đi xuống tới mức services, mình hay gọi cách này là top down approach
  • Làm sao để thực hiện việc testing hiệu quả khi có hơn gần 60+ services trong cả hệ thống, giải quyết bài toán mỗi lần service deploy new version và thực hiện regression testing thế nào
  • Làm sao để thực hiện việc automation checking cho hệ thống microservices, bao gồm cả việc rút gọn thời gian run automation cho toàn bộ test suites chỉ dưới 10-30 phút cũng như chiến lược cho việc thực hiện automation checking
  • Làm sao để thực hiện performance testing cho service khi nó có quá nhiều dependency services
  • Làm sao để thực hiện việc shift-right testing đối với 1 hệ thống lớn khi có new release quan trọng lên production
  • Làm sao để thực hiện việc testing distributed transaction trong hệ thống này

Như cái danh sách ở trên thì đó là 1 trong những vấn đề chính mà mình đã gặp phải trong cả năm vừa qua, có những cái mình đã xử xong, và cũng có những cái gọi là technical debt hy vọng năm nay xử tiếp 🤐 Trong chuỗi bài viết này thì các phần kế tiếp mình sẽ chia sẻ kinh nghiệm, trải nghiệm cũng như cách mình đã sử dụng để giải quyết dần những vấn đề trên. Đầu năm chắc mở hàng tới đây thôi, để dành cho phần tiếp theo thôi 👻

Infrastructure as Test

Previously I wrote a theory guide regarding more testing approaches for mobile applications overall. It’s easier when said rather than actual implementations. Honestly, testing is not simple like theory.

Testing is complicated, and it’s more challenging if you didn’t plan it for the beginning, more difficult when you only thoughts you can write some automation scripts to save time and then spend x3 efforts to maintain. Yet, it’s more painful when it comes to scaling tests to be agreed upon and supported by the whole team. You heard the ultimate benefits of continuous testing to it’s always good to implement that infrastructure, but you can’t maintain CI flow stability properly.

Testing infrastructure

When I sad this term, I want to point to the support and the ‘things around the testing. Followed with shift-left principle, testing activities presented in all development parts for an iteration process.

How you integrate your team and build an infrastructure to support testing is more critical than “hey, find an automated framework and let’s start writing some test scripts.” The purpose of using the in-house framework or even buy a commercial solution to help reducing testing efforts and increase collaboration is just one point of the whole testing infrastructure.

What affects the testing structure is:

  • The test strategy
  • The team
  • The automated testing framework
  • The test execution
  • The CI/CD solutions and pipelines
  • The application under testing including versioning, environments, and deployments
  • Other types of testing

Test Strategy

This is the most master thing needed for the outcome of the testing infrastructure. This is not a typical test strategy to highlight what needs to be tested but also concludes the approaches to reach the mature of testing infrastructure. Part of it is the CI/CD pipeline maturity levels.

Collaboration

Collaboration is the fundamental key here. Your testing team and even developers have to agree on what you would like to construct, not just you do it by yourself. This act won’t go anywhere. If the developers know how testing is built and how testing pinpoints the speedy results upon the pull requests, they will undoubtedly support us.

Collaboration does not incline the usage test script collaboration. Do you want the team to know to collaborate on the test script? Then the baseline of collaboration should be encouraged by testing framework extensibility.

Visibility

The testing results have to be seen from your team, including developers, managers, etc. Full visibility about the test results on the infrastructure must be public and presented in either high level or details-oriented levels.

Visibility is attainable through integration between the test management tool and the tests pipeline supplement it. In some cases, can you break that link?

Automated testing framework 

The baseline of testing infrastructure is the testing framework.

At first, the team has to think, is it worth creating the in-house framework, or do POC using some open-source frameworks out there or buy a commercial solution to help it?

Or can I use some other supporting solutions such as CypressPlaywrightKarate, or Katalon? The answer laid to how the team wants to address automated testing perspectively. The testing framework should be the whole team effort, not just you or some individuals. 

You must separate your thoughts between the testing framework and the scripts created by it. The testing framework I stated here is very distinct from the automated test scripts. How fast or firm, or maintainable the scripts all depend on the testing framework’s nature. You can produce a testing framework very quickly, but then time spent to develop test scripts and changes into AUT versioning or integrable changes from the sprint will quickly catch the testing team on fire.

Test Execution

Test execution in pair with the tests you have in the test repository. There is an interesting article to map testing efforts into automation.

The test execution from one session confines not just one test but multiple tests at the same time on given testing environments, on given browsers/devices, and on given pipelines. The testing infrastructure compromise different solutions to a specific type of breakpoints

Data

To create the proper test script, it must have 3 phases: Arrange – Act – Assert. Arrange is where you set up your test and, most importantly, is the test data. Martin Fowler has a stumble guide regards to Test Data preparation in his book. The main principle for this with testing infrastructure is to highlight the actual data testing in need of it accordingly.

Attain this depends on the testing pipeline and how the testing framework obtains data from data delivery. The immediate approach is using developer techniques such as test doublesstubsstatic data, and directly seed data from databases. This supplement can also help a complex work when the team wants to streamline the CI processes without no human interception.

How can this be accomplished in the testing infrastructure? To consider which data to be used, think every test data is a model. If it’s a person, it will likely have a name, age. If it’s a product, it will likely have a name, price, category, etc. Consider this fact apply changes in both framework and the CI pipeline:

  • For the framework, consider applying the test data factory. Either static data from JSON, data tables, or random data can be done and easy to maintain
  • For the CI pipeline, consider directly seed data from databases if possible. But you need to ensure you don’t violate data storage privacy from end customer perspectives.

The Reporting

Report for a single execution is easy when the tests are executed locally. But our testing infrastructure doesn’t do small tests like that. The infrastructure is responsible for determining which tests should be done, when and where the tests are executed against what environments and collect overall reports. As I’ve said previously, using the CI/CD tool, you can actually view the final result of an executed session, but not really enough.

The reports need to be viewed from different perspectives, not just the creators. The managers want to see the reports from his perspectives, so reporting needs to be presented in many different kinds of levels to adapt the viewing persona.

I usually use ReportPortal from the beginning, but many other solutions already integrate the reports.

Flaky Tests

The flaky test is the most common type of failure you will encounter when the automated scripts are executed. Google has some must-read articles for this that you can refer to:

One of the common ways to heal flaky tests is to retry the test as part of the testing framework feature. For me, it’s incorrect.

Retry should be handled directly from the CI/CD tool instead. When a testing pipeline is failed due to the environment is not reachable or the network connection is being very slow, rather than let the framework do the retry, let the CI/CD tool do that instead. It’s very controllable directly from the pipeline.

To supplement analyzing flaky tests is information. The notion of information is about all things you can get:

  • Logs
  • Test failure snapshot
  • Capture DOM at the point of failure
  • History execution results

Logs, snapshots, and captured DOM are done from the testing framework. For historical execution results, you can utilize CI/CD tool or use ReportPortalReportPortal is an open-source centralized report to provide you more insights into historical results along with time spent for execution.

There are still many other reasons for a flaky test, which I won’t mention more details about here. Refer to Google testing blogs that I’ve posted above

The CI/CD solutions

As part of the testing infrastructure, selecting a CI/CD tool is also very important here. 

It’s never been easier because Jenkins is the most popular one, but I’d recommend TeamCity instead. Its visualize pipeline report is much easier to detect flaky tests from your continuous testing scripts, and of course, the minimalist UI catches your eyes more refined.

Selecting the repository holder for the team’s deliverables is also part of the infrastructure. Tools like Github Action , Gitlab RunnerBitbucket add values to this properly.

The pipelines

When you consider integrating tests into the whole development pipeline, it’s another factor. 

The whole pipeline refers to both development, testing, release, and post-release pipelines. It’s a sum of pipelines that guide how testing infrastructure is being built rather than just separate components without any linkage.

Post-release monitoring

Constantly monitor what happens post-release to find out interesting things and also keep track of user journeys. There are many statistics data for a user session, and the journey they go in confine the things that infrastructure needs to be concluded for defects detection and further advances.

No matter what technology is chosen for monitoring, e.g., GrafanaELKWoopra, the stability in the record what matters for the user the most to keep us on track with our testing priority.

Application Under Test

An application under test(AUT) is another part of the testing infrastructure. If you work in a Scrum project, the iteration changes always happen, and also many different versions (release candidate, beta, official)/environments(local, staging, production) are presented there. Especially for mobile applications, the application under test confine different challenges and not easy to approach testing.

Versioning

Each release has its own version, and its internal delivery for testing also has the version. Each version might differ from UI, workflow, user scenarios. To truly adapt with the rights being a part of the infrastructure, you have to manage it directly from the automated testing framework.

The testing framework should be designed from the beginning with scale and extension in the whole testing mind. Yet this is not easy for non-technical testers, but really you need to think about it. Some beginner and advanced articles for design patterns I’ve read will be useful for you:

My advice is always to think of upcoming development infrastructure as a big picture, not a short-term solution. One day the developers think we need to release an internal version for our staff to try first, and then it’s another break in the development pipeline and affects your testing infrastructure pipeline as well.

Environment

The test environment is in pair with versioning. There will always be typical staging and production environments. In more mature projects, there will be a local one, a QA one.

Well, again, to deal with this is also a part of the design pattern you need to think of. For me, one easy way to use a pre-done supporting library such as Spring to switch to different environment properties quickly and effortlessly.

Deployments

Nowadays, microservices is a star in the sky of deployment for the web application. For mobile applications, it’s the utilization of third-party deployments such as TestFlight for iOS or App Center for Android. The deployment of this depends is not mentioned here, but rather than after deployment, how should it blend with the infrastructure?

Every deployment tied its successful deployments into a specific location. For the web application, with the help of Docker, Kubernetes then the deployment location can be a temporary URL to access at the current code changes. For mobile applications, the app distribution center will distribute the usable application file to be installed on the devices. It’s not a matter of how you select the solution for deployments, but the output of code changes can be compiled successfully and then being a snapshot for the testing infrastructure to grab and execute

With these matters, expose the output of access points of these deployments into environment variables and be used in the testing framework. The testing framework must have the ability to parameterize the environment configurations based on output environment variables so that testing will be triggered on that correct deployment.

The browsers or devices to be tested.

Another thing is the place you will use to execute the test scripts. It will be either specific browsers, devices, or both. I won’t mention the fragmentation or how to gain which places you should execute the test, but rather the supporting infrastructure to pick what kind of browsers/devices to be executed.

For this to be clearly precise, the testing framework should expose the place to configure a single or bunch of configs like e.g, JSON or YAML format so that the team just need to input their specific desired capabilities to test on.

Other types of testing

You don’t only do one specific testing in the whole infrastructure. There will be more testing, including functional and non-functional testing included. The vast of it is huge depends on the testing needs and strategy given from the final outcome of the testing meeting, but those pinpoint the needs for infrastructure to work on it.

Other types of testing, if feasible, should be included in the testing framework with multi-modules project support. The pipeline and the report will pick the results given with specific kinds of testing for visibility.

Now what

The post is quite long that has come to an end already. I always mind that testing is complicated. It’s not easy to achieve testing efficiency for the whole product and expose visibility, encourage collaboration. It’s more difficult when the product is complex, and many different tests need to be performed.

Build up a testing infrastructure is just like building your house step by step. When creating the house, you will likely meet budget issues, conflicts with your family members, decorations being changed over time due to your estimation about furniture are incorrect. Your dream house struggles quite a long time to be a place you are proud of the same for testing infrastructure construction. You can’t ignore building small things first to achieve deliverables for the teams seeing testing efforts, and it’s a step up to further wrap many components of infrastructure.

Nevertheless, the infrastructure has to be measured and maintained to let it not over-react to disrupted changes in development cycles. I hope this blog doesn’t give out too many theories to highlight the needs of testing affects majorly in the

Some (More) ways of mobile testing

Mobile application testing today required a fully sophisticated approaches to shape the desired qualities, ideally the deliverables judgment of qualities depend on test test plan and agreements of the whole team. Unlike web application, mobile application testing put up many challenges that troubleshoot us for a long term:

  • Devices diversity: A combination of lots of devices fragment in term of models, hardware and OS
  • External device factors:
    • Network
    • Interruption
    • Temperature
  • Releases: You can roll back , apply quick patches easily on web due to evolved deployments dedicated for web infrastructure, but not easy for devices. We can’t force users to update the app on the device due to mobile OS.
  • OS flavor upgrades: An application can be broken after the device’s OS is upgraded, and it’s harder to validate than web application
  • Release Approval: A new version of mobile application need to go through Google Play/ Apple review processes, while mobile application doesn’t.

Combined all of above things lead to testing variations for a specific application need to be applied for smooth release. Remember defects prevention is better than fixing them to reduce the efforts and chaos upon the releases

The better information

The most important of catching root cause issues laid in application/device/custom logs generated from the session. Check and add into the framework the capabilities to collect logs for analytics.

The better strategy

Measure and determine the release’s status on mobile testing application is not laid to functionalities anymore. Only functionalities testing can help aid in determine how the application is performed exactly what we want, not what users want and even how is it performed on different devices. Rather than, inject different kinds of testing ways to the application

Crash Testing

Crash is obviously the most annoying issue. There are many reasons crash can be occurred and quick way to check it is using chaos method applied by randomized user inputs

  • Android: Inject monkey runner command
  • iOS: Inject randomized user inputs using SwiftMonkey
  • Gather crash metrics and analytics with the help of analytics reporting tools

How much of crash rates is enough can be referred in this article. Usually this check is harnessed post-commit and track crash rates along with crash logs

Visual Testing

The more and more devices fragmentation you are going to support, the more difficulties to cover the product look and feel. A normal test script that verify every details will be very exhausting. Visual testing reduce the efforts spent for to adapt smart verification and improve the awareness which the team target on the devices.

Beta Testing

Roll out the RC version to a fixed % of end-users who will help to verify the new features. You still can’t cover all specific device settings and its root cause at the same but this hook greatly improve user experiences. Some platforms help to deploy these are TestFlight or HockeyApp

Performance Testing

This testing is not making performance validations on the server infrastructures sideloaded with the application. It’s about how well the application reacts to the device under test under specific conditions. This can be quite complex, because mobile application performance conclude many different factors:

  • Network
  • CPU Usage %
  • Memory Usage %
  • Backend:
    • Data transactions performed in the memory
    • Database queries
  • Render:
    • Time until application interaction is allowed
    • Blank/Dark screen availability
  • Storage usage

For easy analyze on these kind of factors, personally I recommend to use Apptim which I’ve had an article previously.

Post-release testing

Observations and monitoring post-release is also a critical way to benchmark the release. You probably will want to look at end-user reviews, how the application’s version is being used over time, is the latest version increase the user’s retention with your intuition fixes? Factors count toward the success of the release, and it’s also an indicator for testing to be revamped with more ways of end-users using the release

For this to be success, you need to monitor:

  • Reviews on Google Play
  • Reviews on Apple Store

Even fewer reviews are on these platforms, the internal tracking of your application will help to determine if the users drop the application or not

HƯỚNG DẪN CÁCH AUTOMATE OTP CODE TRÊN MOBILE

Hey yo! Nay cuối năm rảnh rỗi nên mình lại viết thêm 1 bài viết dành cho các bạn nào đang làm automation test với mobile.

Câu chuyện của team mình

Câu chuyện bắt đầu bằng việc team mình có nhu cầu phải làm việc với OTP code khá nhiều, bạn nào đang thực hiện việc testing cho những ứng dụng trên nền tảng mobile chắc đều biết rằng xu hướng hiện nay là bảo mật càng nhiều càng tốt, và kéo theo việc ứng dụng nào cũng tích hợp OTP code để thực hiện bảo mật 2 lớp :(((. Đây chính là nỗi khổ của những bạn nào phải làm automate với những ứng dụng có OTP code. Đối với bạn nào dùng human testing (hay hiểu là manual testing) thì việc test những ứng dụng có OTP code không phải là vấn đề gì to lớn ngoài trừ việc đợi nhận được OTP code từ SMS

Nhưng mà với những bạn làm automate thì đó là 1 bài toán cũng tương đối lằng nhằng rườm rà để giải quyết. Chẳng hạn khi làm automate thì các bạn phải làm sao để nhận biết được SMS đã được send tới điện thoại, rồi làm sao để extract được cái OTP code từ 1 cái SMS, rồi chưa kể vài thằng ứng dụng nó chơi trò send 2-3 SMS cùng 1 lúc nhưng SMS chứa OTP code nó chỉ nằm ở trong số 3 SMS mà điện thoại đã nhận. Rồi chưa kể quá trình extract OTP code thì với những bạn cần phải test ứng dụng trên những Android/iOS version cũ thì nó chưa hỗ trợ việc tự lấy OTP từ bàn phím, hiểu nôm na là bạn phải viết thêm 1 nùi automation steps để tương tác với GUI nhằm getText cái SMS string (đậu phộng automation GUI E2E đã khó, giờ còn phải tạo mớ steps cho bước này nữa thì chắc flaky test nó tăng ào ào quá)


Nhu cầu của team mình về bài toán OTP code

Trong câu chuyện trên thì nhu cầu của team mình nó cũng đơn giản như mớ thông tin dưới đây:

  • Cần tìm 1 giải pháp để lấy OTP 1 cách lẹ nhất cũng như chính xác nhất mà không thông qua việc tương tác với GUI của mobile application
  • Có thể dễ dàng tìm và filter SMS theo số điện thoại hoạc sender address gởi tới
  • Chạy càng lẹ càng tốt (chắc chạy lẹ cỡ tốc độ bàn thờ của các bạn racing boy =]])
  • Chạy phải ổn định cũng như dễ dàng debug sau này
  • Cho phép chia sẻ điện thoại nhận SMS với những bộ test khác, hiểu nôm na là những điện thoại run test sẽ không cắm sim mà sẽ share với nhau sim từ 1 device duy nhất, device này hiểu nôm na là device chỉ dành cho mục đích nhận SMS cho những devices run test
  • Tính bảo mật tốt do việc thực hiện lấy thông tin OTP code mà lộ cơ chế lấy hoặc lữu trữ nhưng thông tin này ra ngoài thì có nguy cơ bị hacker lợi dụng để làm trò bậy bạ gì đó =)))

Sau khi ngồi thao luận và list ra được mớ yêu cầu trên thì cái mặt của mình nó y chang như vậy

Mình ngồi nghĩ trong đầu “yêu cầu gì mà yêu cầu lắm yêu cầu lốn”, nhưng mà cũng phải tìm giải pháp thôi vì những cái yêu cầu đó nó hợp lý quá rồi :((((((

Sự ra đời của sms-listener-service plugin

Sau nhiều đêm trằn trọc thao thức, suy nghĩ những cách để giải quyết mớ yêu cầu trên. Tốn hết mấy chục ly cafe cũng như tiền net, mình đã quyết định sẽ implement 1 cái plugin (hiểu nôm na là 1 native application chạy trên device) nhằm mục đích có thể call Restful API từ plugin đó để lấy được SMS từ device. Hiểu nôm na thì cơ chế nó sẽ giống như 2 cái hình dưới đây:

High level sms-listener-service overview
SMS Listener Service Application Overview

Như mình mô tả ở 2 hình trên thì mình sẽ thực hiện việc viết 1 ứng dụng (plugin version hiện tại thì mình chỉ mới viết ứng dụng đó trên nền tản Android), trong đó nó sẽ chạy 1 http server (backend) bên trong chính điện thoại dưới dạng 1 background service foreground service. Server trên sẽ expose 3 APIs dạng Restful để cho users có thể thực hiện việc truy xuất SMS đang có trên devices. Chắc lúc này sẽ có vài bạn thắc mắc vì sao mình đi với lựa chọn này =)) Thì dưới đây là những lý do mình đi với lựa chọn này:

  • Mô hình dựng 1 backend bên trong device thì mình cũng dựa vào cơ chế của Appium driver, và trong tương lai với Appium 2.0 thì cơ chế này bên Appium sẽ gọi là custom driver (đọc thêm bài này nếu các bạn quan tâm về Appium 2.0)
  • Việc chạy 1 backend bên trong mobile chỉ có nhiệm vụ nhận request từ Restful APIs rồi trả về data SMS cho users sẽ giúp cho việc lấy thông tin code OTP trở nên lẹ và dễ dàng hơn, mình sẽ không cần thực hiện những bước liên quan tới GUI chỉ để lấy được SMS text
  • Mình chọn netty server vì hiện tại có tìm hiểu những thư viện serverless nhúng vô mobile thì không có nhiều sự lựa chọn lắm ngoài 2 thằng (có thể mình tìm bị sót nên nếu ai biết thư viện nào nữa thì comment share mình nhé) nanohttpdnetty.io. Lý do mình chọn netty.io cũng là do hiện tại Appium driver agent trên Android cũng đang sử dụng thư viện này, tội gì không sử dụng 1 thư viện đã được Appium kiểm tra và sử dụng chính thức =))
  • Lý do mình chọn implement plugin application này dưới dạng Android service (background service foreground service) là do việc khi sử dụng cho việc automate mobile application thì mình application được automate sẽ chạy ở main process của mobile deivce, dẫn tới việc nếu không chạy plugin application dưới dạng background service foreground service (ban đầu mình làm background service tuy nhiên hiện tại ở những Android version mới thì nó sẽ bị tình trạng điện thoại rơi vào Doze/Standby mode thì service mình sẽ bị kill vì thế mình đã chuyển sang foreground service) thì http server sẽ bị tắt, và kéo theo việc mình không thể nào truy cập được SMS của device được nữa
  • Tới đây mà bạn nào từng làm làm việc nhiều với ứng dụng Android sẽ thắc mắc là tại sao mình lại không implement plugin của mình dưới dạng “Incomming SMS Broadcast Receiver”. Khi đó mình sẽ không cần duy trì 1 http server bên trong mobile device. Thiệt ra thì cách này cũng được, chỉ khác là lúc này mình lại phải implement 1 cái http server ở ngoài mobile deivce chỉ để nó nhận và lưu trữ SMS được forward từ mobile device ra. Hiểu nôm na là cái application plugin mỗi lần có new SMS được send tới điện thoại thì nó sẽ tự động call 1 API từ cái server mình dựng từ bên ngoài để lưu trữ thông tin SMS đó ra ngoài (cơ chế nó sẽ tương tự ứng dụng này mysms). Về cơ chế thì nó tương tự nhau, nhưng cách này thì sẽ mất thời gian implement thêm và dựng tiếp 1 cái http server ở ngoài, bên cạnh đó cũng phải làm thêm cơ chế lưu trữ SMS được forwad từ điện thoại qua server đó. Dẫn tới việc phải nghĩ tới vấn đề bảo mật cho những thông tin OTP đó. Trong khi với việc chạy 1 http server bên trong điện thoại thì khi nào users có nhu cầu muốn lấy thông tin SMS thì plugin application chỉ cần đọc thông tin SMS của device và trả về luôn, việc lưu trữ những thông tin SMS sẽ không cần thiết nữa. Bên cạnh đó mình cũng muốn loại bỏ luôn yếu tố việc sync SMS từ điện thoại qua external backend bị lỗi dẫn tới có thể điện thoại nhận được SMS nhưng quá trình sync SMS từ device qua hệ thống backend external bị lỗi.

Sử dụng sms-listener-service plugin

Nãy giờ mình nói dông dài rồi, giờ thì mình vô tới phần hướng dẫn sử dụng cái application này. Nói chung việc sử dụng nó cũng dễ dàng chứ không phức tạp gì mấy.

1. Tải plugin android application từ link này

2. Kết nối điện thoại Android với máy tính của bạn và nhớ bật đầy đủ các mode hỗ trợ việc sử dụng adb command nha các anh em. Bạn nào chưa biết làm những bước gì thì có thể coi bài viết này

3. Kiểm tra thử android device máy tính đã kết nối được chưa thông qua lệnh sau

adb devices
Kiểm tra máy tính đã kết nối được với device chưa

4. Tiến hành cài đặt plugin application vô điện thoại thông qua lệnh sau

adb install -g sms-listener.apk

Ở đây các bạn nhớ phải có argument “-g” nhé. Do application sẽ đòi hỏi những permission cho việc đọc và truy cập SMS messages. Nếu các bạn không install với argument “-g” thì ứng dụng sẽ không thể chạy được

adb install options
Cài đặt plugin application vô device

5. Start application từ adb command, các bạn cũng có thể start từ việc open nó trên GUI app, nhưng ở đây mình chọn cách hướng dẫn việc start application từ adb command để các bạn có thể dễ dàng kết hợp với automation scripts của mình 1 cách dễ dàng

adb shell am start -n "com.toilatester.smslistener/com.toilatester.sms.listener.MainActivity" --ei serverPort 8185

Ở đây argument “–ei” cho phép bạn cấu hình server port sẽ chạy bên trong device. Mục đích của việc này là cho phép bạn có thể sử dụng nhiều devices cùng 1 lúc trên 1 máy tính. Do để có thể truy cập vô được APIs của plugin http server trên device thì các bạn phải truy cập qua 2 cách.

  • Dùng lệnh [adb forward tcp:8181 tcp:8185] để forward request từ máy đang kết nối device vô bên trong http server của device. Như lệnh ở trên có nghĩa là forward request được gọi tới địa chỉ localhost của máy tính ở port 8181 vô server đang được start bên trong device ở port 8185
  • Truy cập APIs thông qua IP của device đang chạy. Ví dụ: khi bạn đang connect device với wifi thì lúc này device sẽ có 1 địa chỉ IP, khi đó bạn chỉ cầng gọi trực tiếp APIs thông qua URL sau: http://địa_chỉ_ip_của_device:port_đang_start_http_server/{api_enpoints}
Start plugin application

Vậy là quá trình hướng dẫn cũng đã xong, giờ thì các bạn tận hưởng thành quả thôi

Demo plugin application khi sử dụng

Những câu hỏi liên quan tới quá trình plugin chạy

Liệu plugin có lén lấy trộm thông tin SMS của người dùng không

Trả lời: Không.

Giải thích: Đó là lý do mình không chọn cách implement với “Incomming SMS Broadcast Receiver”, vì khi đó mình cần xây dựng 1 hệ thống bên ngoài để lưu trữ những thông tin SMS để sau đó users có thể truy xuất thông tin SMS từ device thông qua Restful APIs. Do plugin của mình là 1 http server nó chỉ có nhiệm vụ nhận request từ users, truy cập thông tin SMS và trả về dưới dạng JSON data cho nên nó không hề lưu thông tin đó ở bất kỳ chỗ nào khác được. Các bạn có thể dễ dàng kiểm chứng thông qua source code =)) vì mình cũng open source cái plugin này

Việc chạy background service foreground service thì có bị tình trạng plugin application bị kill khi đang chạy

Trả lời: Có và Không

Giải thích: Hiện tại mình start background service foreground service với mode “START_STICKY”. Theo như document mình đọc thì với mode này thì khi điện thoại đang bi low memory nó sẽ có thể tự đông kill bớt 1 vài ứng dụng có mức độ ưu tiên không cao. Khi đó với mode “START_STICKY” thì ứng dụng sẽ tự động chạy lại service sms-listener 1 cách tự động. Hiện tại thì application của mình quá trình chạy sẽ không tốn quá nhiều memory của device, lý do là chỉ nhận request và trả về data liền chứ không hề lưu hay phát sinh thêm dữ liệu, từ đó khả năng dẫn tới việc gây tiêu tốn quá nhiều memory của device làm cho device tự động kill serivce là không có. Tuy nhiên có chỗ này lưu ý, nếu bạn tắt hẳn ứng dụng thì đó lại là việc khác, nó tương tự việc bạn sử dụng ứng dụng nghe nhạc, nó chạy ngầm ở hệ thống, khi nhấn vào nút recent app trên các điện thoại android và vút để tắt nó đi thì đồng nghĩa bạn đã force tắt service, khi đó thì mình cũng chịu thua do bạn đã cố ý tắt ứng dụng rồi. Nhưng dù sao thì mình cũng sẽ test thêm vấn đề này, tuy nhiên nếu phục vụ mục đích automate thì mình nghĩ nó không phải là vấn đề lớn, mỗi khi test start bạn cứ execute command start plugin service để đảm bảo plugin chạy là coi như giảm thiểu khả năng plugin không chạy rồi. Mình đã có test thử trên device android Samsung galaxy S7 Edge của mình thì service sẽ luôn chạy kể cả khi bạn nhấn button recent và close application. Lý do ở trên mình có đề cập việc nhấn recent và close ứng dụng có thể bị tắt service là do thông tin từ bài viết này (bạn nào xài thử mà có bị thì có thể báo lại mình nha)

Khi nào sẽ có plugin này trên iOS

Trả lời: Chưa biết nữa tùy theo mức độ rãnh rang của mình =))

Hướng dẫn sử dụng plugin InfluxDB và LOKI với jmeter

JMeter Real-Time Monitoring, Integration With Grafana+InfluxDB 2.0 (Flux) -  DZone Integration

Bạn nào từng làm performance test (hay còn gọi là load test, mặc dù mình ko thích cách gọi này lắm do load test chỉ là 1 phần của performance test =]]) thì thường sẽ gặp phải những vấn đề như: làm sao để có thể theo dõi kết quả chạy load test 1 cách trực tiếp? Làm sao để lưu trữ dữ liệu load test và so sánh nó với những thông số khác theo trục thời gian (HTML report thì bạn rất khó để xác định được chính xác mốc thời gian với điểm nghi ngờ bị performance và đi kiểm tra với các thông số của hệ thống). Hay thậm chí là so sánh kết quả thực hiện load test hiện tại với các mốc thời điểm 1-2-3-4-…. tháng trước? Hay thậm chí là cách nào đó để lưu trữ những dữ liệu của response data khi thực hiện load test 1 cách hiệu quả?

Từ những điều khó khăn trên mà mình gặp phải dẫn tới việc nhóm mình trong lúc rảnh rỗi đã viết 1 plugin trên JMeter để giải quyết vấn đề trên.

yay yay yay

Hướng dẫn cài đặt

Việc đầu tiên là các bạn cần vô link này nhấn like và follow (mình đùa thôi nhưng nhớ làm cũng được :D). Các bạn vô link này download plugin về (cái file để download như hình dưới đây)

Plugin download

Sau khi download xong file đó thì các bạn giải nén nó ra và copy file “jmeter-backend-listener-plugin.jar”

vô thư mục lib/ext (thư mục này nằm trong folder các bạn đã cài đặt JMeter)

Như vậy thì việc cài đặt plugin đã hoàn toàn xong =)) nói chung nó dễ đến mức không còn có thể dễ hơn được nữa

Hướng dẫn cấu hình plugins với JMeter

Sau khi đã cài đặt plugin xong thì đến bước cấu hình để sử dụng plugin, việc cấu hình plugin cũng rất là đơn giản như những bước dưới đây

Đầu tiên là các bạn cần phải mở JMeter lên rồi, =)) không mở lên thì lấy cái gì mà cấu hình hay sử dụng đúng ko nào =)). Sau đó các bạn tạo 1 thread-group bất kỳ. Sau 2 bước trên các bạn sẽ có 1 structure của JMeter như hình sau

Kế tiếp các bạn tạo tiếp 1 “backend listener” element trong JMeter theo như hình sau

add-listener-to-testplan

Sau khi add xong thì các bạn sẽ có structure của JMeter test plan như hình sau

Giờ thì đến bước cấu hình cho listener plugin, để cấu hình cho plugin thì bạn click vô “Backend listener” element và chọn 1 trong 2 options sau (mỗi option tương ứng cho việc bạn sẽ send JMeter metrics hoặc JMeter response data vô InfluxDB hoặc Loki)

select-listener

Sau khi chọn xong loại backend listener thì các bạn cấu hình thông số cho nó

config-influxdb-listener
InfluxDB Backend Listener Configuration
config-loki-listener
Loki Backend Listener Configuration

Để hiểu rõ từng options trong configuration thì các bạn có thể coi thông tin chi tiết ở link sau

Lưu ý: Nếu bạn muốn dùng cả InfluxDB và Loki thì bạn chỉ cần add 2 “backend listener” vô JMeter test plan, nhưng lưu ý là nhớ đổi tên cả 2 element, do cơ chế của JMeter là sẽ broad cast cái sampler result vô từng listener theo element name của chính nó, nên khi bạn add 2 element thì nó sẽ bị trùng tên (default name của backend listener)

Done !!!!!!!!!

Kế tiếp thì các bạn sẽ cần làm thêm 1 bước là import dashboard Grafana mà bọn mình đã xây dựng sẵn cho plugin của bọn mình. Các bạn download template ở link sau. Kế tiếp là import nó vô Grafana (bạn nào chưa biết cách import Grafana dashboard thì Google dùm mình nha =)) mình assume là ở đây mọi người đều có mạng internet và có thể truy cập được Google để tìm kiếm thông tin). Bên cạnh đó các bạn cũng cần phải cài đặt InfluxDB, LokiGrafana (các bạn có thể coi cách cài đặt những cái đó ở link mình đính kém theo cái tên của nó)

Sau khi xong hết những cái đó thì chạy thử JMeter test và tận hưởng thành quả hoy

i1
i3
l4
l3

Những câu hỏi thường gặp khi sử dụng plugin

1. Sử dụng plugin này có làm ảnh hưởng tới kết quả performance test không?

Trả lời: Plugin sẽ không ảnh hưởng tới kết quả performance test

=> Giải thích: Cơ chế của backend listener của JMeter là khi JMeter thực hiện 1 request lên SUT/AUT (system under test/application under test) thì kết quả của JMeter request đó sẽ được truyền vô plugin listener ở 1 thread riêng. Hiểu nôm na thì JMeter sẽ có 2 thread riêng khi bạn sử dụng plugin này, 1 thread sẽ chỉ chuyên làm nhiệm vụ thực hiện việc gởi những request lên hệ thống bạn test, và 1 thread làm nhiệm vụ gởi kết quả lên InfluxDB hay Loki. Với cơ chế này thì nếu bạn đang thực hiện performance test mà InfluxDB hay Loki có bị chết thì việc thực hiện load test vẫn sẽ tiếp tục diễn ra chứ không bị gián đoạn, ngoài ra nếu việc send dữ liệu lên hệ thống collect metrics bị chậm thì cũng sẽ ko ảnh hưởng tới kết quả performance test.

2. Sử dụng plugin rồi nhưng có tính trạng bị treo máy Master khi run performance test ở chế độ distributed?

Trả lời: Plugin không có lỗi, lỗi là do cơ chế nhận sampler result ở JMeter khi run ở mode distributed =))

=> Giải thích: khi các bạn run performance test với JMeter ở chế độ “Distributed” (hay còn gọi là kiểu master và slave, việt hóa là ông chủ và những nô lệ =]]). Thì cơ chế của JMeter máy master sẽ làm nhiệm vụ truyền lệnh run cũng như send *.jmx file (hay còn gọi kịch bản test) xuống những máy slave. Việc thực hiện gởi những request lên hệ thống test sẽ do những máy slave làm, sau đó thì kết quả sẽ được gởi về lại máy master. Và thường vấn đề gây treo máy nó nằm ở đây. Do khi thực hiện cơ chế này nhiều bạn mắc 1 sai lầm là physical machine (hiểu nôm na là máy dùng để chạy JMeter) đang run Master cũng là máy sẽ run Slave, khi đó physical machine đó sẽ bị quá tải ở cả Memory/CPU/Network và dẫn tới treo máy. Để hạn chế tình trạng trên thì tốt nhất mỗi máy master và slave các bạn nên run nó trên những physical machine riêng biệt. Ngoài ra thì bạn có thể vô file jmeter.properties (nằm trong folder bin) để cấu hình cơ chế mà những máy slave sẽ send kết quả về cho master như hình dưới đây:

3. Sử dụng plugin nhưng khi thực hiện query hoặc load kết quả lên Granafa rất chậm?

Trả lời: Cuộc sống thì cái này nằm ngoài phạm vi của plugin rồi

=> Giải thích: Do cơ chế lưu trữ của InfluxDB như cơ chế chia table/shard (nó tương tự cơ chế index ở bên mấy database dạng SQL) sẽ dẫn đến việc khi bạn load dữ liệu lên Grafana nó sẽ mất thời gian để query những thông số theo nhu cầu, ngoài ra thì việc sử dụng regex nhiều quá cũng ảnh hưởng tới thời gian Grafana lấy được dữ liệu từ InfluxDB

My 2020 Year

So far 2020 is a nice year for me, I’m also glad that I’m invited by my friends to join this blog for knowledge sharing.

Wish you guys Merry Christmas and a year 2021 full of joys

Mobile app performance Testing with Apptim

Recently I’ve found a tool called APPTIM. This tool is a nice addition to your performance testing on mobile devices providing a bunch of useful features to help visual performance metrics as well as collecting related logs.

This blog is a quick starter guide to help you jump in this tool. I won’t talk about fancy things regards to how important of performance testing, why performance testing is needed etc

To get started and record the session, refer to this guide

The performance bottlenecks

Upon a session is ended, you are presented into a summary screen to have a quick brief about how the application performed on the specific device. Noticable summary information are:

  • % CPU Usage
  • Avg Memory Usage
  • % Memory Usage
  • Power Usage
  • Downloaded Data
  • Errors/Exceptions if any

Visualize performance metrics

Performance testing artifacts always end with of visualized metrics. APPTIM support many common metrics which is parsed from based on dumpsys command. APPTIM actually aggregates ALL the data and round up into a friendly visualization.

  • CPU
  • Threads:
  • Memory:
  • Database:

Besides database visualize metric, APPTIM also list out the transaction performed internally in the database’s application. It also points out the WORST transaction (most spent time in ms) to perform

  • Power Usage:

All above metrics are parsed from dumpsys output command, which is nice because you will envision yourself into friendly metrics rather than a bunch of raw numbers

Logs

As said from the beginning, all logs including crash, power usage, memory dump, network…. (well so many) are also collected and presented in the local report. Those are all raw logs and bestow for you to dig in more information if you need to debug performance bottlenecks if you can’t seem to figure out from the metrics

—————————————————————————————————————————————————————–

Above are common features for a performance testing tool to record metrics and logs related. BUT APPTIM does more than that:

  • Provide activities and layout correctness (Android only): How activities and layouts are used in term of performance determinations. They help mainly developers to determine whether the application need to be adjusted to improve performance as activities and layout is important factors
  • Integrate with Jira: You can gather a piece of information from the session and send them directly to JIRA.
  • Support exploratory testing: The pros of APPTIM is logs , metrics and misc information collection. That’s why APPTIM supports the ability to take note during the session so that if any bugs found you will have all the needed pieces.
  • Support BOT testing: I think it’s coming soon.
  • Collaboration: The generated report is also pushed to your workspace. Workspace in APPTIM is your own private page which you can take part in to view the all of previously reports, not just a current one. With paid subscription, collaboration happens by inviting more of your colleagues to

Automation Testing
So does APPTIM support using it for automation testing? So far as I’ve tried, the supports of automation testing tied to local devices and AWS farm.

  • Local devices & emulators: Once your session is started, you just need to execute your tests. APPTIM collect performance information, so the automation session works along with this nicely. At the end of automation session, APPTIM also ends it session and performance testing will be collected
  • AWS farm devices: Blazemeter conducts an article regards to using APPTIM directly in their Taurus scripts, you can refer here

I will contact more with APPTIM regards to their automation support and APPTIM native scripts and write another article later about this

Summary:

Pros:

  • A all-in-one performance collection
  • Required dependencies are installed automatically
  • Support collaborations through public APPTIM cloud
  • Compare two sessions (paid)
  • Support JIRA integration
  • Provide useful correctness regards to activities and layouts on Android
  • All performance, logs, device and extensive information are delivered to you
  • Support automation testing

Cons:

  • Automation testing support still limited
  • The workflow to really start the session is cumbersome a bit

So far I’m liking this tool. It’s a nice addition to help you to start performance testing locally on the devices.

kubernetes – hướng dẫn sửa lỗi “existing bootstrap client certificate is expired”

Lâu rồi mình mới lại rảnh rỗi để viết bài, thiệt là ái ngại quá đi 😩. Trước khi bắt đầu thì mình muốn nói trước là bài viết này có những thông tin liên quan tới DevOps cũng như vài thuật ngữ liên quan tới Kubernetes 😬. Nếu bạn cảm thấy không chắc mình quan tâm tới 2 chủ đề trên thì bạn có thể …. đọc tiếp phần dưới để ủng hộ mình cũng được🤣, không sao cả, đọc nhiều thì cũng tốt mà =]] Nhưng mà đừng quá lo lắng vì ở dưới mình cũng sẽ có nói qua về Kubernetes để bạn nào chưa biết gì về nó thì cũng có thể biết Kubernetes là gì cũng như hiểu được sơ sơ những điều mình đề cập trong bài viết này.

Hướng dẫn cách sửa lỗi khi Kubernetes Certificate & Key (PKI) bị hết hạn

Ở phần này mình sẽ hướng dẫn các bạn cách sửa lỗi liên quan tới "Client Certificates Issue" khi làm việc với Kubernetes.

Để nhận biết bạn có gặp phải lỗi trên không thì bạn chỉ cần thấy Kubernetes cluster của bạn không hoạt động, và khi thực hiện kiểm tra Kubernetes cluster thông qua các lệnh như mô tả dưới đây và nếu bạn nhận về kết quả giống như những mô tả dưới đây, thì lúc này thì xin chúc mừng bạn, bạn đã quay trúng vào ô may mắn =))


kubectl cluster-info

The connection to the server <apiserver_advertise_ip>:6443 was refused - did you specify the right host or port?

Lấy thông tin về Kubernetes Cluster


systemctl status kubelet # Lệnh để lấy thông tin về status của kubelet service

● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: activating (auto-restart) (Result: exit-code) since Mon 2020-06-01 08:51:47 +0530; 3s ago
     Docs: https://kubernetes.io/docs/
  Process: 14027 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=255)
 Main PID: 14027 (code=exited, status=255)

Kiểm tra trạng thái hiện tại của Kubelet service


journalctl | grep kubelet

<date> <node_name> kubelet[3653]: E0601 08:42:54.232397    3653 bootstrap.go:264] Part of the existing bootstrap client certificate is expired: 2020-04-11 02:01:22 +0000 UTC
<date> <node_name> kubelet[3653]: F0601 08:42:54.234118    3653 server.go:265] failed to run Kubelet: unable to load bootstrap kubeconfig: stat /etc/kubernetes/bootstrap-kubelet.conf: no such file or directory
<date> <node_name> systemd[1]: kubelet.service: main process exited, code=exited, status=255/n/a
<date> <node_name> systemd[1]: Unit kubelet.service entered failed state.
<date> <node_name> systemd[1]: kubelet.service failed.
<date> <node_name> systemd[1]: kubelet.service holdoff time over, scheduling restart.
<date> <node_name> systemd[1]: Stopped kubelet: The Kubernetes Node Agent.

Lấy thông tin log hiện tại của Kubelet service


Các bước để tiến hành sửa lỗi

Lưu ý:

  1. Nếu các bạn đang sử dụng Kubernetes Cluster với chế độ HA (High-Availability) thì các bạn cần thực hiện các lệnh dưới đây trên toàn bộ các máy đang đóng vai trò là Control Plane
  2. Nếu bạn nào đang sử dụng Kubernetes 1.17 trở lên nhưng thông qua việc upgrade Kubernetes từ phiên bản 1.16 thì các bạn cần thực hiện việc upgrade toàn bộ Kubernetes configuration files để thực hiện việc gia hạn certificates cho cluster. Do bản dưới 1.17 có 1 con bug nhẹ dẫn tới việc phải thực hiện việc update /etc/kubernetes/kubelet.conf để nó trỏ tới file certificates mới nhất (thường thì file đó sẽ nằm trên /var/lib/kubelet/pki/kubelet-client-[latest date].pem, ví dụ /var/lib/kubelet/pki/kubelet-client-2020-10-11-04-30-38.pem)
  3. Nếu trước đây khi tiến hành cài đặt Kubernetes mà bạn có sử dụng những external configuration options thì khi tiến hành generate lại những files configuration thì bạn cũng phải input tương tự như lúc bạn cài đặt Kubernetes. Nếu bạn nào không nhớ thì tốt nhất nên backup lại toàn bộ những file .yaml ở những thư mục sau /etc/kubernetes và /etc/kubernetes/manifests/, khi đó bạn có thể compare file cũ và file mới để cấu hình lại cho đúng

Đối với Kubernetes version 1.17 trở xuống


Đầu tiên thực hiện việc generate lại những Certificates cần thiết để Kubernetes Cluster có thể hoạt động:

root@ubuntu:/var/lib/kubelet/pki# kubeadm init phase certs all

W1011 04:05:49.656588   17889 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Using existing ca certificate authority
[certs] Using existing apiserver certificate and key on disk
[certs] Using existing apiserver-kubelet-client certificate and key on disk
[certs] Using existing front-proxy-ca certificate authority
[certs] Using existing front-proxy-client certificate and key on disk
[certs] Using existing etcd/ca certificate authority
[certs] Using existing etcd/server certificate and key on disk
[certs] Using existing etcd/peer certificate and key on disk
[certs] Using existing etcd/healthcheck-client certificate and key on disk
[certs] Using existing apiserver-etcd-client certificate and key on disk
[certs] Using the existing "sa" key

Khởi tạo lại toàn bộ Certificates cần thiết cho Kubernetes Cluster


Kế tiếp thực hiện việc khởi tạo lại những files configuration để cấu hình cho Kubernetes Cluster

root@ubuntu:/var/lib/kubelet/pki# kubeadm init phase kubeconfig all

W1011 04:09:11.643497   18731 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"

Khởi tạo lại toàn bộ files configuration cho Kubernetes Cluster


Kế tiếp thực hiện việc cấu hình lại PKI của Kubelet service

root@ubuntu:/var/lib/kubelet/pki# kubeadm init phase kubelet-finalize all

W1011 04:19:14.156610   21834 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key

Cấu hình lại PKI của kubelet service


Và cuối cùng thực hiện việc restart Kubelet service

root@ubuntu:/var/lib/kubelet/pki# kubeadm init phase kubelet-start 

W1011 04:21:20.881312   22744 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet

Restart lại kubelet service


Đối với Kubernetes version 1.17 trở lên

Đối với những bạn sử dụng Kubernetes version 1.17 trở lên thì mọi thứ sẽ đơn giản hơn, các bạn chỉ cần thực hiện lệnh sau đây là đủ

root@ubuntu:/etc/kubernetes/pki# kubeadm alpha certs renew all

[renew] Reading configuration from the cluster...
[renew] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[renew] Error reading configuration from the Cluster. Falling back to default configuration

W1011 05:29:18.365723   19228 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healthcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed

Thực hiện việc gia hạn những certificates sử dụng trong Kubernetes Cluster


Tiến hành kiểm tra việc gia hạn certificates, lúc này bạn chú ý giá trị ở cột “EXPIRES”, nó sẽ cho bạn biết thời gian mà những certificates này sẽ hết hạn

root@ubuntu:/etc/kubernetes/manifests# kubeadm alpha certs check-expiration

[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Oct 11, 2021 05:29 UTC   364d                                    no      
apiserver                  Oct 11, 2021 05:29 UTC   364d            ca                      no      
apiserver-etcd-client      Oct 11, 2021 05:29 UTC   364d            etcd-ca                 no      
apiserver-kubelet-client   Oct 11, 2021 05:29 UTC   364d            ca                      no      
controller-manager.conf    Oct 11, 2021 05:29 UTC   364d                                    no      
etcd-healthcheck-client    Oct 11, 2021 05:29 UTC   364d            etcd-ca                 no      
etcd-peer                  Oct 11, 2021 05:29 UTC   364d            etcd-ca                 no      
etcd-server                Oct 11, 2021 05:29 UTC   364d            etcd-ca                 no      
front-proxy-client         Oct 11, 2021 05:29 UTC   364d            front-proxy-ca          no      
scheduler.conf             Oct 11, 2021 05:29 UTC   364d                                    no      

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      Oct 09, 2030 03:00 UTC   9y              no      
etcd-ca                 Oct 09, 2030 03:00 UTC   9y              no      
front-proxy-ca          Oct 09, 2030 03:00 UTC   9y              no  

Thực hiện kiểm tra thời hạn của những certificates vừa được gia hạn


Đối với việc sử dụng kubeadm không thành công

Nếu 2 cách trên mà cluster của bạn vẫn chưa chạy được thì điều đầu tiên bạn cần làm là:

  • Thực hiện reboot lại machine thông qua lệnh sau
sudo reboot
  • Tiến hành kiểm tra lại log của Kubelet service thông qua 2 lệnh sau
journalctl | grep kubelet 

service kubelet status
  • Nếu lúc này bạn vẫn nhận được thông báo có chứa thông tin lỗi như mình đã đề cập ở ban đầu thì bạn nên “hủy diệt” cả Kubernetes Cluster và tiến hành cài lại

Mình đùa thôi vẫn chưa hẳn là hết cách cứu, mà chỉ là lúc này làm sẽ hơi thủ công và cực hơn 1 tí. Khi này bạn sẽ cần phải tiến hành những bước sau (khúc này thì mình được cu em chuyên về DevOps @locmai hướng dẫn =]] mình chỉ coi thử và làm theo):

  • Cấu hình certificates tương ứng cho 4 phần (Admin, Controller-manager, Kubelet và Scheduler), có nhiều cách khác nhau để generate certificates nhưng ở đây mình sẽ dùng cfssl (hướng dẫn cài đặt cfssl). Duới đây là 1 file mẫu để generate certificate cho Kubelet service (để biết máy bạn có hostname là gì thì bạn có thể dùng lệnh sau đối với hệ điều hành ubuntu hostname -s)
{
  "CN": "system:node:thay_thế_bằng_host_name_của_bạn",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "VN",
      "L": "HCM",
      "O": "system:nodes",
      "OU": "IAMGOD",
      "ST": "BT"
    }
  ]
}
  • Dùng ca.crt và ca.key từ folder /etc/kubernetes/pki để tạo ra certificates cho Kubernetes cluster, dưới đây là lệnh để generate certificate cho Kubelet service (chỗ -hostname bạn cần truyền vô thông tin địa chỉ IP của máy hiện tại bạn đang generate certificate, như lệnh dưới đây thì máy mình đang dùng làm demo có địa chỉ IP là 192.168.10.10)
cfssl gencert -ca=pki/ca.crt -ca-key=pki/ca.key -hostname=ubuntu,127.0.0.1,192.168.10.10 -profile=kubernetes ubuntu-csr.json | cfssljson -bare ubuntu
  • Cập nhật thông tin của những certificates bạn vừa tạo ở trên vô những file configuration ở thư mục /etc/kubernetes. Lưu ý là với những file configuration dưới đây thì thông tin của certificates cũng như private key đều phải được mã hóa base64 trước khi input vô file (để có thể encode sang base64 thì các bạn có thể dùng lệnh sau ở ubuntu base64 /etc/kubernetes/ubuntu-key.pem ở đây /etc/kubernetes/ubuntu-key.pem là đường dẫn tới file bạn cần mã hóa sang base64)
    • admin.conf
    • controller-manager.conf
    • kubelet.conf
    • scheduler.conf
  • Restart lại machine và coi thử Kubernetes cluster đã chạy chưa. Đến lúc này mà nó vẫn chưa chạy thì … chắc lỗi định mệnh rồi, tiến hành sử dụng tuyệt chiêu cuối thôi (nhưng mình hy vọng các bạn không tới mức phải chơi tuyệt chiêu cuối này)
kubeadm reset
kuebadm init

Như vậy mình đã xong phần hướng dẫn cách khắc phục lỗi khi mà Kubernetes Cluster bị tình trạng "Client Certificates Issue" 😂😂😂



Nếu bạn nào nãy giờ đọc mớ ở trên và có cảm giác không hiểu gì cả thì phần bài viết dưới đây hy vọng sẽ giúp các bạn dễ hình dung hơn về những gì mình viết ở trên.

Giải đáp về Kubernetes Cluster

Những thuật ngữ cơ bản trong Kubernetes

Để giúp các bạn có thể dễ dàng hiểu được các thuật ngữ về Kubernetes mà mình dùng trong bài viết, thì ở đây mình liệt kê ra những thuật ngữ cơ bản nhất của Kubernetes kèm theo phần giải thích kế bên cho các bạn.

Thuật ngữChú thích
API serverThành phần quan trọng giúp người dùng có thể dễ dàng sử dụng Kubernetes. API server sẽ đóng vai trò trong việc giao tiếp giữa người dùng với những thành phần khác bên trong Kubernetes. Ví dụ khi bạn muốn triển khai 1 ứng dụng lên Kubernetes thì lúc này bạn chỉ cần thực hiện 1 API request đơn giản xuống API server và việc còn lại thì cứ để API server tự kết nối tới những thành phần còn lại trong Kubernetes và thực hiện việc triển khai ứng dụng cho bạn. Hình minh họa dưới đây sẽ mô tả cách mà API Server hoạt động:
ContainerLà 1 đơn vị của ứng dụng, nơi mà ứng dụng được đóng gói lại kèm theo những thành phần liên quan tới ứng dụng đó, giúp nó có thể chạy 1 cách dễ dàng ở bất cứ môi trường nào. Còn ví dụ kiểu cục súc 😂 và dễ hình dung nhất thì container giống như là việc bạn có 1 tập những videoxxx nằm trong thư mục xxx, và chỉ coi được với ứng dụng playxxx, lúc này bạn muốn chia sẻ cho những anh em đồng … khác cùng coi, thay vì bạn bắt anh em của bạn phải cài ứng dụng playxxx rồi kèm theo thiết lập đủ thứ thì bạn chỉ cần nén thư mục xxx kèm theo ứng dụng playxxx đã được bạn cài đặt sẵn bên trong thư mục đó, và sau đó bạn chỉ cần đưa file nén đó cho anh em và lúc này anh em của bạn có thể thư giãn tẹt ga với cái thư mục nén đó. Ở đây container chính là folder xxx và những thành phần bên trong folder đó bao gồm videoxxx và ứng dụng playxxx =))
ImageLà kết quả của việc đóng gói toàn bộ ứng dụng cũng như những thành phần cần cho việc chạy ứng dụng đó, Image sau khi được đóng gói thì thường sẽ có format dạng .tar.gz. Nếu hiểu theo kiểu ví dụ ở trên thì Image có thể được coi là file nén sinh ra sau khi thực hiện việc nén toàn bộ folder xxx :))
DockerDocker là nền tảng phần mềm cho phép bạn dựng, kiểm thử và triển khai ứng dụng một cách nhanh chóng. Docker đóng gói phần mềm vào các đơn vị tiêu chuẩn hóa được gọi là container. Bằng cách sử dụng Docker, bạn có thể nhanh chóng triển khai và thay đổi quy mô ứng dụng vào bất kỳ môi trường nào và biết chắc rằng mã của bạn sẽ chạy được.
Container Runtime Container runtime là 1 ứng dụng phần mềm cho phép bạn chạy các ứng dụng được đóng gói lại thành những container, nếu như hiểu theo ví dụ ở trên thì container runtime giống như ứng dụng thực hiện việc giải nén và tự động mở ứng dụng playxxx và cho phép bạn coi những videoxxx.
Container Runtime thường rất đa dạng, phổ biết nhất hiện tại là Docker, nhưng bên cạnh đó vẫn có những đối thủ khác như podman, CRI-O hay Containerd
Container runtime interface
(CRI)
Container runtime interface là một giao ước về việc các ứng dụng khi được xây dựng nhằm thực hiện việc chạy các container (hay hiểu đơn giản là việc xây dựng 1 ứng dụng container runtime) phải cam kết phải đảm bảo có đầy đủ những tiêu chí giao ước. Ví dụ như khi nói về xe máy, chúng ta có rất nhiều hãng xe máy khác nhau như Honda, Yamaha, Suzuki, nhưng các hãng đều có giao ước rằng, khi làm xe máy thì các hãng đều phải có 1 cái khung sườn, 2 cái bánh xe chẳng hạn
Control PlaneTầng điều khiển container, được dùng để đưa ra API và các interface để định nghĩa, triển khai, và quản lý vòng đời của các container
PodĐối tượng nhỏ nhất và đơn giản nhất của Kubernetes. Một Pod đại diện cho một tập các containers đang chạy trên cluster
kube-controller-managerLà 1 thành phần của Control Plane và có mục đích điều khiển toàn bộ những processes bên trong Kubernetes
kube-proxykube-proxy là một network proxy chạy trên mỗi node trong cluster, thực hiện một phần Kubernetes Service
kube-proxy duy trình network rules trên các node. Những network rules này cho phép kết nối mạng đến các pods từ trong hoặc ngoài cluster
kube-proxy sử dụng lớp packet filtering của hệ điều hành nếu có sẵn. Nếu không thì kube-proxy sẽ tự điều hướng network traffic
kubectlCông cụ chạy trực tiếp từ command line (giống kiểu các bạn muốn biết thông tin IP của máy mình thì gõ lệnh ifconfig hay ipconfig vậy) để thực thi những lệnh của người dùng xuống Kubernetes API server. Bạn có thể tạo, cập nhật, xóa hay trích xuất thông tin những đối tượng bên trong Kubernetes với kubectl
KubeletMột agent chạy trên mỗi node nằm trong cluster. Nó giúp đảm bảo rằng các containers đã chạy trong một pod. Đây là thành phần giao tiếp với Kubernetes API Server, và cũng quản lý các container
Kubernetes APITập hợp những RESTful API để cho người dùng có thể dễ dàng thực hiện việc quản lý Kubernetes thông qua những API này
MinikubeMinikube là một bộ cài đặt Kubernetes bằng cách tạo ra một máy ảo trên máy tính của bạn và triển khai một cluster đơn giản bên trong máy ảo đó chỉ bao gồm một Node
Master nodeMột master node là một máy trong Kubernetes mà nó triển khai control plane trên chính nó
Worker nodeMột worker node là một máy worker trong Kubernetes
Một worker node có thể là một máy tính ảo hay máy tính vậy lý, tùy thuộc vào cluster. Nó bao gồm một số daemons hoặc services cần thiết để chạy các Pods và được quản lý bởi control plane. Daemons trên một node bao gồm kubeletkube-proxy, và một container runtime triển khai theo CRI như Docker.
ClusterMột tập hợp các worker machine, được gọi là node, dùng để chạy các containerized application. Mỗi cụm (cluster) có ít nhất một worker node. Các worker node chứa các pod (là những thành phần của ứng dụng). Mỗi cluster sẽ có ít nhất 1 Control Plane quản lý các worker node và pod trong cluster. Trong môi trường sản phẩm (production environment), Control Plane thường chạy trên nhiều máy tính và một cluster thường chạy trên nhiều node, cung cấp khả năng chịu lỗi (fault-tolerance) và tính sẵn sàng cao (high availability). Máy nào đang chạy control plane thì có thể coi máy đó là master node
BẢNG THUẬT NGỮ KUBERNETES CƠ BẢN

Một Kubernetes Cluster sẽ bao gồm những gì?

Đầu tiên thì nếu bạn nào chưa biết Kubernetes là gì thì mình nghĩ các bạn có thể coi thêm tham khảo bài giới thiệu What is Kubernetes? ở đây. Còn mà nói theo ngôn ngữ dễ hiểu nhất thì Kubernetes là cái thứ giúp cho việc quản lý và điều khiển sự hoạt động của những containers, containers ở đây được hiểu là nơi chứa những ứng dụng mà bạn dùng để sử dụng ví dụ như WordPress, JMeter hay Jenkins chẳng hạn, nói chung thì nếu đến giờ bạn vẫn không biết container là gì thì các bạn nên cập nhật kiến thức lẹ nhé :]] chứ không là lạc hậu quá đó (các bạn có thể coi lại bài viết này Giới thiệu về Docker).

Và vì nó có khả năng quản lý và điều khiển sự hoạt động của những containers, cho nên Kubernetes Cluster sẽ bao gồm hai thứ chính là control plane components và worker/node components. Sự khác nhau của hai thành phần trên là:

  • Control Plane/Master machine : thực hiện việc quản lý những worker/node có trong cluster, ví dụ tăng hay giảm số lượng worker/node machines trong cluster, thực hiện việc yêu cầu worker/node machines khởi tạo hay “hủy diệt” containers nào đó, và nhiều thứ khác liên quan tới việc quản lý worker/node machines. Ở đây thì control plane machine có thể là 1 máy hoặc nhiều máy khác nhau, khi thực hiện việc thiết lập control plane trên nhiều máy thì lúc này bạn đã thiết lập được một Kubernetes Cluster có tính HA (High-Availability – hiểu nôm na là 1 Kubernetes Cluster có khả năng duy trì hoạt động ở mức cao nhất, giống kiểu nó có nhiều hệ thống dự phòng cho nó, chết 1 thằng thì vẫn có thằng khác hoạt động được). Ở 1 vài chỗ thì họ cũng gọi Control Plane machine là Master Node machine.
  • Worker/Node machine: thực hiện việc quản lý và điều khiển sự hoạt động của containers đang chạy trên worker/node. Ở đây thì worker/node có thể hiểu nôm na là 1 cái machine riêng biệt, nó có thể là physical machine hoặc là 1 virtual machine chẳng hạn.
  • Các thành phần chính tạo nên một Control Plane:
    • kube-apiserver: Kubernetes sẽ cung cấp cho các bạn các API để có thể tương tác với Kubernetes service bên dưới. Ví dụ khi bạn thực hiện việc deploy
    • etcd
    • kube-scheduler
    • kube-controller-manager
  • Các thành phần chính tạo nên một Worker/Node:
    • kubelet
    • kube-proxy:
    • Container runtime(Docker, containerd, CRI-O)

Vậy nếu bạn xây dựng 1 Kubernetes Cluster chỉ với 1 máy thì nó đồng nghĩa là máy đó cũng đồng thời vừa là Control Plane và cũng đồng thời là Worker/Node (đây là cách Minikube đang hoạt động), nhưng mà thường thì khi sử dụng production thì bạn nên thiết lập Kubernetes Cluster với mô hình HA sẽ tốt hơn, đặc biệt là đối với mô hình Kubernetes Cluster Bare Metal (thường chắc cái này mấy anh công ty product ở Việt Nam hay xài nhiều)

Vậy lỗi trên là do đâu gây ra?

Đừng lo lắng nếu bạn đọc không hiểu những cái trên là gì vì khi bạn cài đặt Kubernetes thì những thứ trên sẽ được gói gọn lại thông qua 1 lệnh duy nhất để khởi tạo Kubernetes.

Khi thực hiện việc cài đặt Kubernetes Cluster thì sẽ có nhiều thứ xảy ra trong đó là việc tiến hành chạy những service như API server, kubelet, etcd và vài cái services khác nữa. Những services này thường sẽ liên lạc với nhau thông qua các giao thức như HTTP hoặc gRPC. Và vì đặc thù muốn có tính bảo mật cao nhất mà những services này đều yêu cầu việc giao tiếp với nhau cần những certificate (chứng thực cho việc giao tiếp giữa các service với nhau có an toàn hay không, bạn nào muốn tìm hiểu về Certificate trong HTTPS/gRPC là gì thì có thể coi bài ở link này). Theo như mặc định thì khi các bạn cài đặt Kubernetes Cluster thì toàn bộ những certificates được tạo ra đều sẽ có thời hạn là 1 năm.

Và sau 1 năm sử dụng thì nếu các bạn không tiến hành gia hạn những certificates đó thì sẽ dẫn tới lỗi như mình gặp ở bài này.

Continuous Testing Focuses

There is no denial that Continuous Testing (CI) growth is so much faster and on-demand in software testing. A bunch of technologies, supporting tools and handicrafts are upscale to embrace faster and quick turnaround CI results to the team

This is not a typical article will go through all aspects of CI, but rather than a selection of what should be focusing so far in CI

What are CI focuses

CI aims to get fast feedback to the team for the smallest change pushed to the development repository as a commit. Once commit is made, a proper CI process will prevent bad things to deliver to respective persons by making checks on it. The checks must be:

  • Fast
  • Isolated
  • Reportable
  • Notifiable

All check attributes served to be the main focus of a CI process, of course, it depends on how the maturity established in your current project which can be less or more. These checks span across all testing activities in the project except Exploratory Testing.

Let’s talk about each check-in details

There will be no mention regards to other checks from the developers’ side such as automatic code reviews as it is part of the development pipeline.

Fast

Fast is the main core focus. Scheduling, selecting tests, and refine the CI tool for faster test preparation is the main point here.

The first thing in mind is your test script design, it must be atomic, independent of each other, and pinpoints to the absolute validations you need to check. Don’t spend time writing unnecessary steps or tests which are already done in the other tests. If your application under test has a shortcut to access the current state you want to test and this access point is already tested, then just use it without doubts.

When a test is executed, no matter what build you are using such as Gradle or Maven, etc…, they all need to download dependencies. Ensure you utilizing cache dependencies in your pipeline file/settings to avoid the same dependencies version to be re-downloaded

In a practical test pyramid, the very first thing in the gateway testing is unit test as it runs pretty fast. No need to select which unit tests to be executed as these are a very fast test which should not consume so much on the whole CI run

After unit tests are completed, the gateway will continue to execute integration tests to establish the linked component tests. This also happens in code logic so it will be fast also.

After both unit tests & integrations are completed, the next thing in line is the simple check on the build to validate it must pass smoke tests. Smoke test here is another gate for build validation against a commit or a change even small. You must not select smoke tests that spend too much time for execution and avoid actions on the interface as much as possible when they can be done from back-end services as they are cleared tested in the unit & integration-test phase.

When scheduling a test execution, always achieve parallelization in the test executions. Parallelization comes up as to server different tests can happen at the same time on different threads. Test execution time will be greatly reduced

One final thing to affect how fast of a CI process is a CI tool itself. Selecting a primary CI tool based on the fit to the whole application architecture. A CI tool is supposed to do many things at once besides the test stage. So make sure that the CI tool is maintained weekly and consider unnecessary stages elimination to avoid bottlenecks can happen. This mainly is a job of DevOps guy

CI Metrics: Average test executions time, Test environment/ data preparations, cost

Isolated

As stated previously, all of the tests should not depend on each other, otherwise, there will be a queue time waiting for a required test to be completed before actual tests happen no matter what

Isolation in CI also comes from how you wrap up your project in a container image so that it is isolated and can be portable to different CIs.

CI metrics: Number of automated tests executed

Reportable

As long as you can trigger many desired tests at the same time on the same pipeline’s stage, the gateway must report back what is tested, what is passed/failed/skipped, environment coverage, and so on. Reporting capabilities outside of test status scope are supported from the CI side, such as environment/device/browser being tested. For test details such as status, test description, etc… then CI tools will utilize the classic power of jUnit report to parse its content for general report overview. That’s not enough if you want more comprehensive reports

Roll up a centralized report dash to consolidate reports is another focus in the CI process. To achieve this, the framework must accommodate to the extension point exposed from the report dashboard to hook its execution results there. Quite many report tools have this kind of capability such as ReportPortal.io or Cube.js, etc…

Reporting comes as an important decision-maker to determine the health of the current build for immediate awareness, and decide is the release ready to roll up to production in the long term. Be sure to add this kind of consolidation reports after executions to track the build’s health and other testing metrics

CI metrics: N/A

Notifiable

The final step in the gateway is to notify the committer about the results through emails or external communication tools such as Slack. They will be notified of how their commit’s heath against the current application’s version and make immediate actions accordingly. Without notifications then who knows how our commits are

CI metrics: N/A

Above are basic checks of a gateway(s) in a CI pipeline should have. There can be more complex stages in the CI pipeline such as service virtualization or seed data for test data or clone different snapshots for a current test environment to justify more testing needs. As either more CI stages and steps are added, the CI pipeline will become more complex and more mature.

CI Mature Levels

Per my experiences a CI pipeline maturity is broken down into 3 levels:

  • Level 1: Start-up
    • A pipeline is initialized
    • Add a stage to trigger tests
    • Send emails to notify about tests results
  • Level 2: Grow up
    • Dependencies caching step is added
    • Tests are executed in parallel on different stages against a specific environment
    • Tests are executed on local browsers/devices on a host machine
    • Report executions result with JUnit reporting XML files
    • Send emails to notify about tests results
  • Level 3: Tune-up
    • Seed test data into tests
    • Different test environments (based on product compatibility) are rolled up automatically
    • Executed tests are against each deployed environments, specified cloud browsers/devices
    • Local executed tests are distributed equally
    • Test executions results are centralized and analyzed for short and long term future
    • Notify results through Slack

Of course, most of the things say here you can treat them as theories for references and can refine them accordingly if you see they are not fit in your current project.

I hope this article provides helpful information for your upcoming or existing CI process.

I’ve created a not-fancy framework with some of the above implemented here. You can refer it or not if you want