0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Nguyên Tắc Copy-on-Write (CoW) của Docker: Khám Phá Tối Ưu Hóa Container

Đăng vào 1 tháng trước

• 11 phút đọc

Nguyên Tắc Copy-on-Write (CoW) của Docker: Khám Phá Tối Ưu Hóa Container

Bởi Bhavya Singh

Trong thế giới phát triển phần mềm và vận hành, tốc độ và hiệu suất là rất quan trọng. Chúng ta cố gắng tạo ra, kiểm tra và triển khai ứng dụng nhanh hơn bao giờ hết. Tuy nhiên, ảo hóa truyền thống thường cảm thấy nặng nề và chậm chạp. Việc khởi động một máy ảo hoàn toàn chỉ để chạy một ứng dụng đơn lẻ có thể mất vài phút và tốn hàng gigabyte dung lượng ổ đĩa.

Docker đã cách mạng hóa quy trình này, giúp việc khởi động container gần như tức thì và tiêu thụ tài nguyên tối thiểu. Một trong những công nghệ cốt lõi, nhưng thường bị bỏ qua, giúp điều này là nguyên tắc Copy-on-Write (CoW). Đây là một chiến lược lưu trữ tinh tế và rất quan trọng đối với cách mà các hình ảnh và container của Docker hoạt động.

Hiểu biết về CoW là điều cần thiết cho bất kỳ nhà phát triển hoặc kỹ sư DevOps nào muốn thực sự nắm vững Docker, tối ưu hóa quy trình làm việc với container, và đánh giá thiết kế tinh tế của nó.

Bài viết này sẽ:

  • Khám phá những thách thức của môi trường ứng dụng truyền thống.
  • Giải thích nguyên tắc Copy-on-Write với một phép ẩn dụ rõ ràng.
  • Chi tiết cách CoW được triển khai trong Docker thông qua các hệ thống tệp union.
  • Thảo luận về những lợi ích và trường hợp sử dụng thực tiễn của nó.
  • Phác thảo những giới hạn và các thực hành tốt nhất để vượt qua chúng.

🔹 Vấn Đề: Chi Phí Cao của Việc Sao Chép

Trước khi đi sâu vào Copy-on-Write, hãy cùng nhận thức về vấn đề mà nó giải quyết. Hãy tưởng tượng bạn đang phát triển ba dịch vụ vi mô khác nhau, tất cả đều dựa trên một hệ điều hành Ubuntu 22.04 chung với một bộ thư viện tiêu chuẩn đã được cài đặt.

Trong cách tiếp cận dựa trên máy ảo truyền thống, bạn sẽ có:

  • VM 1: Một bản sao hoàn chỉnh của hệ điều hành Ubuntu + thư viện của bạn + Dịch vụ vi mô A. (ví dụ: 10 GB)
  • VM 2: Một bản sao hoàn chỉnh của hệ điều hành Ubuntu + thư viện của bạn + Dịch vụ vi mô B. (ví dụ: 10 GB)
  • VM 3: Một bản sao hoàn chỉnh của hệ điều hành Ubuntu + thư viện của bạn + Dịch vụ vi mô C. (ví dụ: 10 GB)

Bạn vừa sử dụng 30 GB dung lượng ổ đĩa, mặc dù hơn 95% dữ liệu đó (hệ điều hành Ubuntu và thư viện) là giống nhau trên cả ba máy ảo. Hơn nữa, việc khởi động mỗi máy ảo yêu cầu khởi động một hệ điều hành hoàn chỉnh, điều này có thể mất vài phút. Cách tiếp cận này chậm, không hiệu quả, và tốn kém về mặt lưu trữ.

Đây chính là sự không hiệu quả mà chiến lược Copy-on-Write của Docker được thiết kế để loại bỏ.


🔹 Copy-on-Write (CoW): Nghệ Thuật Chia Sẻ và Sao Chép

Copy-on-Write (CoW) là một chiến lược quản lý tài nguyên quy định rằng nếu nhiều caller yêu cầu tài nguyên mà ban đầu không thể phân biệt, thì tất cả có thể được cấp các con trỏ đến cùng một tài nguyên chia sẻ. Việc chia sẻ này có thể tiếp tục cho đến khi một caller cố gắng sửa đổi "bản sao" của tài nguyên đó. Vào thời điểm đó, một bản sao riêng thực sự được tạo ra và các thay đổi được áp dụng cho nó, để lại bản gốc và các bản sao chia sẻ khác không bị ảnh hưởng.

Trong ngữ cảnh của Docker:

Thay vì tạo một bản sao hoàn chỉnh của hệ thống tệp của một hình ảnh cho mỗi container, CoW cho phép tất cả các container chia sẻ hệ thống tệp của hình ảnh. Một bản sao chỉ được tạo ra cho tệp cụ thể mà một container cần phải ghi hoặc sửa đổi.

Cách tiếp cận "sao chép lười" này có nghĩa là các container rất nhẹ và có thể được tạo ra gần như ngay lập tức.

🎨 Phép Ẩn Dụ: Bản Thiết Kế Chính và Đội Ngũ Kiến Trúc Sư

Hãy mở rộng phép ẩn dụ trước đó. Hãy tưởng tượng một kiến trúc sư trưởng thiết kế một bản thiết kế chính cho một tòa nhà chọc trời. Bản thiết kế này được hoàn thiện, lamination và lưu trữ trong một kho công cộng—nó chỉ có thể đọc.

  • Bản Thiết Kế Chính: Đây là hình ảnh Docker của bạn, bao gồm một số lớp chỉ đọc (ví dụ: lớp hệ điều hành cơ sở, lớp phụ thuộc, lớp mã ứng dụng). Nó không thể thay đổi.

Bây giờ, một đội ngũ kiến trúc sư chuyên gia (nhà thiết kế nội thất, kỹ sư điện, v.v.) được thuê để tùy chỉnh các tầng khác nhau của tòa nhà.

  • Các Kiến Trúc Sư: Đây là các container Docker của bạn. Mỗi cái bắt đầu từ cùng một bản thiết kế chính.
  • Giấy Tracing Trong Suốt: Khi một kiến trúc sư bắt đầu công việc của họ, họ không nhận được một bản sao đầy đủ của bản thiết kế khổng lồ. Thay vào đó, họ nhận được một tấm giấy tracing trong suốt để đặt lên bản thiết kế chính. Tấm giấy tracing này là nơi làm việc có thể ghi của họ—lớp ghi của container.

Dưới đây là cách quy trình CoW diễn ra:

  1. Đọc: Khi nhà thiết kế nội thất cần xem vị trí của một cột hỗ trợ, họ nhìn thẳng qua tấm giấy tracing của họ đến bản thiết kế chính bên dưới. Điều này nhanh chóng và không yêu cầu sao chép.
  2. Ghi (Sửa đổi): Nhà thiết kế quyết định di chuyển một bức tường không tải. Họ không thể xóa bức tường trên bản thiết kế chính đã được laminated. Thay vào đó, họ vẽ lại bức tường gốc lên tấm giấy tracing của họ và sau đó xóa nó và vẽ lại ở vị trí mới trên tấm giấy của họ. Đây là thao tác "sao chép lên". Từ quan điểm của họ, bức tường đã di chuyển, nhưng bản thiết kế chính và mọi góc nhìn của các kiến trúc sư khác vẫn không thay đổi.
  3. Ghi (Tạo Mới): Nếu nhà thiết kế muốn thêm một đài phun nước mới, họ chỉ cần vẽ nó lên tấm giấy tracing. Nó không tồn tại trên bản thiết kế chính.
  4. Xóa: Nếu kỹ sư điện quyết định loại bỏ một thiết bị chiếu sáng được hiển thị trên bản thiết kế chính, họ không thể xóa nó khỏi bản gốc. Thay vào đó, họ đặt một nhãn "whiteout" đặc biệt trên tấm giấy tracing của họ để che khu vực của thiết bị chiếu sáng. Đối với họ, thiết bị chiếu sáng đã biến mất, nhưng nó vẫn còn xuất hiện trên bản thiết kế chính và có thể nhìn thấy với những người khác.

Hệ thống này rất hiệu quả. Tất cả các kiến trúc sư chia sẻ một bản thiết kế chính lớn duy nhất, và chỉ những thay đổi cá nhân của họ mới chiếm không gian mới trên các tấm giấy tracing cá nhân.


🔹 Cách CoW được Triển Khai: Hệ Thống Tệp Union

Docker sử dụng hệ thống tệp union (như OverlayFS, đây là mặc định hiện đại) để triển khai CoW. Một hệ thống tệp union cho phép nhiều thư mục (gọi là lớp trong Docker) được xếp chồng lên nhau và được trình bày như một hệ thống tệp duy nhất và thống nhất.

Khi bạn chạy docker run -it ubuntu bash:

  1. Lớp Hình Ảnh: Docker lấy tất cả các lớp chỉ đọc tạo thành hình ảnh ubuntu.
  2. Xếp Chồng: Trình điều khiển lưu trữ union "xếp chồng" những lớp này. Lớp trên cùng là lớp gần đây nhất, và lớp dưới cùng là lớp cơ sở.
  3. Lớp Có Thể Ghi: Docker sau đó tạo một lớp mỏng, có thể ghi mới trên đỉnh của chồng này. Lớp này là duy nhất cho container mới.
  4. Góc Nhìn Thống Nhất: Trình điều khiển lưu trữ trình bày một góc nhìn thống nhất của tất cả những lớp này. Khi bạn thực hiện ls -l / bên trong container, bạn đang thấy một góc nhìn hợp nhất của lớp có thể ghi của container và tất cả các lớp hình ảnh chỉ đọc bên dưới nó.

Quá trình đọc/ghi hoạt động như sau:

  • Đọc: Khi bạn đọc một tệp, Docker tìm kiếm nó trong lớp có thể ghi trên cùng. Nếu không có ở đó, nó tìm kiếm trong lớp tiếp theo xuống, và cứ như vậy, cho đến khi nó tìm thấy tệp trong một trong các lớp hình ảnh chỉ đọc.
  • Ghi/Xóa: Khi bạn sửa đổi một tệp tồn tại trong một lớp thấp hơn, trình điều khiển lưu trữ thực hiện thao tác sao chép lên. Nó sao chép tệp từ lớp chỉ đọc lên lớp có thể ghi, và sau đó container ghi các thay đổi vào bản sao mới này. Việc xóa một tệp cũng tương tự, liên quan đến việc tạo một tệp "whiteout" trong lớp có thể ghi để che khuất tệp gốc trong lớp bên dưới.

🔹 Đặc Điểm Chính và Lợi Ích Giải Thích

1. Hiệu Quả Lưu Trữ Cực Cao

Bởi vì hàng ngàn container có thể chia sẻ cùng một lớp hình ảnh cơ sở (như ubuntu, alpine, hoặc node), diện tích chiếm trên đĩa được giảm đáng kể. Một hình ảnh Node.js 500 MB không trở thành 50 GB khi bạn chạy 100 container. Thay vào đó, nó chỉ là 500 MB cộng với một vài megabyte cho mỗi lớp có thể ghi độc đáo của container.

2. Tạo và Xóa Container Nhanh Chóng

Chiến lược CoW là lý do chính khiến các container khởi động trong mili giây thay vì phút. Không có hệ điều hành nào để khởi động và không có hệ thống tệp lớn nào để sao chép. Docker chỉ cần tạo lớp có thể ghi nhỏ và khởi động quá trình. Việc xóa một container cũng nhanh—Docker đơn giản chỉ cần loại bỏ lớp có thể ghi.

3. Tính Bất Biến và Tính Đồng Nhất Của Hình Ảnh

Các lớp hình ảnh là chỉ đọc. Tính bất biến này là một tính năng mạnh mẽ đảm bảo rằng một container luôn bắt đầu từ một trạng thái đã biết, đồng nhất. Điều này loại bỏ các vấn đề "chạy trên máy của tôi" và đảm bảo rằng môi trường có thể tái tạo từ phát triển đến sản xuất.

4. Cập Nhật và Vá Lỗi Đơn Giản

Khi một lỗ hổng bảo mật được tìm thấy trong một hình ảnh cơ sở (ví dụ: Ubuntu), bạn chỉ cần cập nhật hình ảnh cơ sở. Khi bạn khởi động lại các container ứng dụng của mình bằng hình ảnh mới đã được vá, chúng sẽ tự động chia sẻ các lớp mới, ngay lập tức nhận được bản vá bảo mật mà không cần bạn phải xây dựng lại mã ứng dụng.


🔹 Giới Hạn và Thực Hành Tốt Nhất của CoW

Mặc dù Copy-on-Write là một tối ưu hóa tuyệt vời, nhưng nó không phải là một giải pháp hoàn hảo. Thiết kế của nó đi kèm với một sự đánh đổi về hiệu suất, đặc biệt là đối với các công việc tải ghi.

Độ Trễ Trong Thao Tác "Copy-Up"

Lần đầu tiên container của bạn ghi vào một tệp chia sẻ, thao tác copy-up sẽ gây ra độ trễ. Điều này có thể không đáng kể đối với các tệp cấu hình nhỏ nhưng có thể đáng chú ý khi sửa đổi các tệp lớn như cơ sở dữ liệu, tệp video hoặc tệp nhật ký lớn. Mỗi lần ghi tiếp theo vào cùng một tệp đó sẽ nhanh chóng vì nó bây giờ tồn tại trong lớp có thể ghi, nhưng cú sốc ban đầu có thể là một nút thắt cổ chai.

Thực Hành Tốt Nhất: Sử Dụng Volumes cho Dữ Liệu Ghi Nặng

Đối với bất kỳ ứng dụng nào cần thực hiện ghi có thông lượng cao hoặc lưu trữ dữ liệu vượt qua vòng đời của container, Docker Volumes là câu trả lời.

  • Chúng là gì? Volumes là các thư mục trên máy chủ mà được gắn trực tiếp vào một container.
  • Tại sao sử dụng chúng? Chúng hoàn toàn bỏ qua hệ thống tệp union và cơ chế CoW. Khi ứng dụng của bạn ghi vào một volume, nó đang ghi trực tiếp vào hệ thống tệp gốc của máy chủ, điều này cung cấp hiệu suất tối đa và thông lượng I/O.

Nguyên Tắc Chung: Sử dụng hệ thống tệp CoW cho mã và phụ thuộc của ứng dụng của bạn (những gì có trong hình ảnh). Sử dụng volumes cho dữ liệu mà ứng dụng của bạn tạo ra và quản lý (tệp cơ sở dữ liệu, nhật ký, tải lên của người dùng).

Thực Hành Tốt Nhất: Giữ Hình Ảnh Nhỏ Với Các Xây Dựng Đa Giai Đoạn

Càng ít lớp mà Docker phải tìm kiếm để tìm một tệp, càng tốt. Bằng cách sử dụng các xây dựng đa giai đoạn, bạn có thể tạo ra các hình ảnh sản xuất gọn nhẹ chỉ chứa các sản phẩm cuối cùng của ứng dụng, không phải các công cụ xây dựng và tệp trung gian. Điều này dẫn đến các hình ảnh nhỏ hơn và một hệ thống tệp CoW hiệu quả hơn.


🔹 Kết Luận: Nền Tảng của Hiện Đại Hóa Container

Nguyên tắc Copy-on-Write là một viên gạch nền tảng của điều làm cho Docker nhanh, hiệu quả và biến đổi. Bằng cách chia sẻ một cách thông minh các lớp hệ thống tệp và chỉ sao chép dữ liệu khi thực sự cần thiết, CoW cho phép triển khai nhanh chóng, mở rộng mật độ cao và tính đồng nhất môi trường mà chúng ta hiện nay mong đợi từ các ứng dụng đám mây hiện đại.

Mặc dù điều quan trọng là hiểu những giới hạn của nó và sử dụng các công cụ như volumes cho các khối lượng công việc phù hợp, CoW vẫn là một giải pháp thanh tao cho một vấn đề phức tạp. Lần tới khi bạn thấy một container khởi động trong nháy mắt, bạn sẽ biết rằng ý tưởng đơn giản, mạnh mẽ của "sao chép khi ghi" đang hoạt động một cách hiệu quả phía sau.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào