16/09/2018, 13:12

Xây dựng container tối ưu hóa cho Kubernetes

Giới thiệu Hình ảnh vùng chứa là định dạng đóng gói chính để xác định các ứng dụng trong Kubernetes. Được sử dụng làm cơ sở cho các nhóm và các đối tượng khác, hình ảnh đóng một vai trò quan trọng trong việc tận dụng các tính năng của Kubernetes để chạy các ứng dụng một cách hiệu quả trên nền ...

Giới thiệu

Hình ảnh vùng chứa là định dạng đóng gói chính để xác định các ứng dụng trong Kubernetes. Được sử dụng làm cơ sở cho các nhóm và các đối tượng khác, hình ảnh đóng một vai trò quan trọng trong việc tận dụng các tính năng của Kubernetes để chạy các ứng dụng một cách hiệu quả trên nền tảng này. Các hình ảnh được thiết kế tốt là an toàn, có hiệu suất cao và tập trung. Họ có thể phản ứng với dữ liệu cấu hình hoặc hướng dẫn do Kubernetes cung cấp và cũng thực hiện các điểm cuối mà hệ thống dàn nhạc sử dụng để hiểu trạng thái ứng dụng nội bộ.

Trong bài viết này, chúng tôi sẽ giới thiệu một số chiến lược để tạo hình ảnh chất lượng cao và thảo luận một vài mục tiêu chung để giúp hướng dẫn các quyết định của bạn khi đưa vào ứng dụng. Chúng tôi sẽ tập trung vào xây dựng hình ảnh dự định chạy trên Kubernetes, nhưng nhiều đề xuất áp dụng như nhau để chạy các thùng chứa trên các nền tảng dàn nhạc khác hoặc trong các ngữ cảnh khác.

Đặc điểm của hình ảnh container hiệu quả

Trước khi chúng tôi đi qua các hành động cụ thể để thực hiện khi tạo hình ảnh vùng chứa, chúng tôi sẽ nói về điều gì tạo nên hình ảnh vùng chứa tốt. Mục tiêu của bạn nên là gì khi thiết kế hình ảnh mới? Những đặc điểm nào và hành vi nào là quan trọng nhất?

Một số phẩm chất nhằm mục đích là:

Một mục đích duy nhất, được xác định rõ ràng

Hình ảnh vùng chứa phải có trọng tâm riêng biệt. Tránh suy nghĩ về hình ảnh vùng chứa dưới dạng máy ảo, nơi có thể có ý nghĩa với chức năng liên quan đến gói. Thay vào đó, hãy xử lý hình ảnh vùng chứa của bạn như tiện ích Unix, duy trì sự tập trung chặt chẽ vào việc thực hiện một điều nhỏ. Các ứng dụng có thể được phối hợp bên ngoài phạm vi vùng chứa để soạn chức năng phức tạp.

Thiết kế chung với khả năng chèn cấu hình khi chạy

Hình ảnh vùng chứa nên được thiết kế với mục đích sử dụng lại khi có thể. Ví dụ: khả năng điều chỉnh cấu hình trong thời gian chạy thường được yêu cầu để đáp ứng các yêu cầu cơ bản như thử nghiệm hình ảnh của bạn trước khi triển khai sang sản xuất. Các hình ảnh nhỏ, chung có thể được kết hợp trong các cấu hình khác nhau để sửa đổi hành vi mà không cần tạo hình ảnh mới.

Kích thước hình ảnh nhỏ

Hình ảnh nhỏ hơn có một số lợi ích trong môi trường nhóm như Kubernetes. Chúng tải xuống nhanh chóng các nút mới và thường có một gói nhỏ hơn các gói đã cài đặt, có thể cải thiện bảo mật. Hình ảnh vùng chứa xuống giúp việc gỡ lỗi dễ dàng hơn bằng cách giảm thiểu số lượng phần mềm có liên quan.

Trạng thái được quản lý bên ngoài

Các thùng chứa trong môi trường phân cụm trải qua một vòng đời rất dễ bay hơi bao gồm tắt máy theo kế hoạch và không có kế hoạch do sự khan hiếm tài nguyên, mở rộng quy mô hoặc lỗi nút. Để duy trì tính nhất quán, hỗ trợ phục hồi và tính khả dụng của các dịch vụ của bạn và để tránh mất dữ liệu, điều quan trọng là bạn lưu trữ trạng thái ứng dụng ở một vị trí ổn định bên ngoài vùng chứa.

Dễ hiểu

Điều quan trọng là cố gắng giữ hình ảnh vùng chứa đơn giản và dễ hiểu nhất có thể. Khi khắc phục sự cố, việc có thể dễ dàng giải thích vấn đề bằng cách xem cấu hình hình ảnh vùng chứa hoặc kiểm tra hành vi vùng chứa có thể giúp bạn đạt được độ phân giải nhanh hơn. Việc suy nghĩ về hình ảnh vùng chứa dưới dạng định dạng đóng gói cho ứng dụng của bạn thay vì cấu hình máy có thể giúp bạn đạt được số dư phù hợp.

Thực hiện theo các phương pháp hay nhất về phần mềm được gói gọn

Hình ảnh nên hướng đến hoạt động trong mô hình vùng chứa thay vì hành động chống lại nó. Tránh thực hiện các thực hành quản trị hệ thống thông thường, như bao gồm các hệ thống init đầy đủ và các ứng dụng daemonizing. Đăng nhập vào chuẩn để Kubernetes có thể trưng ra dữ liệu cho các quản trị viên thay vì sử dụng một trình tiện ích đăng nhập nội bộ. Mỗi trong số này khác với các phương pháp hay nhất cho các hệ điều hành đầy đủ.

Tận dụng đầy đủ các tính năng của Kubernetes

Ngoài việc tuân theo mô hình container, điều quan trọng là phải hiểu và hòa giải với môi trường và công cụ mà Kubernetes cung cấp. Ví dụ, cung cấp các điểm cuối để kiểm tra tính linh hoạt và sẵn sàng hoặc điều chỉnh hoạt động dựa trên những thay đổi trong cấu hình hoặc môi trường có thể giúp các ứng dụng của bạn sử dụng môi trường triển khai động của Kubernetes để lợi thế của chúng.

Bây giờ chúng tôi đã thiết lập một số phẩm chất xác định hình ảnh vùng chứa có chức năng cao, chúng tôi có thể đi sâu hơn vào các chiến lược giúp bạn đạt được các mục tiêu này.

Tái sử dụng các lớp cơ sở tối thiểu, được chia sẻ

Chúng tôi có thể bắt đầu bằng cách kiểm tra các nguồn tài nguyên mà hình ảnh vùng chứa được tạo từ: hình ảnh cơ sở. Mỗi hình ảnh vùng chứa được tạo từ một hình ảnh gốc, hình ảnh được sử dụng làm điểm xuất phát hoặc từ tóm tắt scratch lớp, một lớp hình ảnh trống không có hệ thống tập tin. A hình ảnh cơ bản là hình ảnh vùng chứa làm nền tảng cho hình ảnh trong tương lai bằng cách xác định hệ điều hành cơ bản và cung cấp chức năng chính. Hình ảnh bao gồm một hoặc nhiều lớp hình ảnh được xây dựng trên đầu trang của nhau để tạo thành một hình ảnh cuối cùng.

Không có tiện ích hoặc hệ thống tệp chuẩn nào khả dụng khi làm việc trực tiếp từ scratch, có nghĩa là bạn chỉ có quyền truy cập vào chức năng cực kỳ hạn chế. Trong khi hình ảnh được tạo trực tiếp từ scratch có thể rất hợp lý và tối thiểu, mục đích chính của chúng là xác định hình ảnh cơ sở. Thông thường, bạn muốn xây dựng hình ảnh vùng chứa của mình ở trên cùng của hình ảnh gốc, thiết lập môi trường cơ bản mà các ứng dụng của bạn chạy để bạn không phải xây dựng một hệ thống hoàn chỉnh cho mọi hình ảnh.

Mặc dù có những hình ảnh cơ sở cho nhiều bản phân phối Linux, tốt nhất là nên cân nhắc về những hệ thống bạn chọn. Mỗi máy mới sẽ phải tải xuống hình ảnh gốc và mọi lớp bổ sung mà bạn đã thêm. Đối với hình ảnh lớn, điều này có thể tiêu tốn một lượng đáng kể băng thông và kéo dài đáng kể thời gian khởi động của các thùng chứa của bạn trong lần chạy đầu tiên. Không có cách nào để giảm bớt một hình ảnh được sử dụng như là một phụ huynh ở hạ lưu trong quá trình xây dựng container, do đó, bắt đầu với một phụ huynh tối thiểu là một ý tưởng tốt.

Tính năng môi trường phong phú như Ubuntu cho phép ứng dụng của bạn chạy trong một môi trường mà bạn quen thuộc, nhưng có một số sự cân bằng để xem xét. Hình ảnh Ubuntu (và các hình ảnh phân phối thông thường tương tự) có xu hướng tương đối lớn (trên 100MB), có nghĩa là bất kỳ hình ảnh vùng chứa nào được xây dựng từ chúng sẽ thừa hưởng trọng lượng đó.

Alpine Linux là một lựa chọn phổ biến cho hình ảnh cơ sở vì nó đóng gói thành công rất nhiều chức năng vào một hình ảnh cơ bản rất nhỏ (~ 5MB). Nó bao gồm một trình quản lý gói với các kho lưu trữ khá lớn và có hầu hết các tiện ích chuẩn mà bạn mong đợi từ môi trường Linux tối thiểu.

Khi thiết kế các ứng dụng của bạn, bạn nên cố gắng sử dụng lại cùng một phụ huynh cho mỗi hình ảnh. Khi ảnh của bạn chia sẻ một phụ huynh, các máy chạy các vùng chứa của bạn sẽ chỉ tải xuống lớp cha một lần. Sau đó, họ sẽ chỉ cần tải xuống các lớp khác nhau giữa các hình ảnh của bạn. Điều này có nghĩa là nếu bạn có các tính năng hoặc chức năng phổ biến mà bạn muốn nhúng vào mỗi hình ảnh, việc tạo một hình ảnh gốc chung để kế thừa từ có thể là một ý tưởng hay. Hình ảnh chia sẻ một dòng dõi giúp giảm thiểu lượng dữ liệu bổ sung bạn cần tải xuống trên các máy chủ mới.

Quản lý Lớp chứa

Khi bạn đã chọn hình ảnh gốc, bạn có thể xác định hình ảnh vùng chứa của mình bằng cách thêm phần mềm bổ sung, sao chép tệp, hiển thị cổng và chọn quy trình để chạy. Một số hướng dẫn trong tệp cấu hình hình ảnh (a Dockerfile nếu bạn đang sử dụng Docker) sẽ thêm các lớp bổ sung vào hình ảnh của bạn.

Đối với nhiều lý do tương tự được đề cập trong phần trước, điều quan trọng là phải lưu ý cách bạn thêm lớp vào hình ảnh của bạn do kích thước kết quả, thừa kế và độ phức tạp của thời gian chạy. Để tránh việc xây dựng hình ảnh lớn, khó sử dụng, điều quan trọng là phải hiểu rõ cách thức các lớp container tương tác, cách công cụ xây dựng lưu trữ lớp và cách sự khác biệt tinh tế trong hướng dẫn tương tự có thể có tác động lớn đến hình ảnh bạn tạo.

Hiểu các lớp hình ảnh và xây dựng bộ nhớ cache

Docker tạo một lớp hình ảnh mới mỗi khi nó thực thi RUN, COPY, hoặc là ADD chỉ dẫn. Nếu bạn xây dựng lại hình ảnh, công cụ xây dựng sẽ kiểm tra từng hướng dẫn để xem liệu nó có một lớp hình ảnh được lưu trong bộ nhớ cache cho hoạt động hay không. Nếu nó tìm thấy một kết quả phù hợp trong bộ nhớ đệm, nó sẽ sử dụng lớp hình ảnh hiện có thay vì thực hiện lại lệnh và xây dựng lại lớp đó.

Quá trình này có thể rút ngắn đáng kể thời gian xây dựng, nhưng điều quan trọng là phải hiểu cơ chế được sử dụng để tránh các vấn đề tiềm ẩn. Để biết hướng dẫn sao chép tệp như COPY và ADD, Docker so sánh tổng kiểm tra của các tệp để xem liệu thao tác có cần thực hiện lại hay không. Dành cho RUN hướng dẫn, Docker kiểm tra xem nó có một lớp hình ảnh hiện có được lưu trữ cho chuỗi lệnh cụ thể đó hay không.

Mặc dù có thể không rõ ràng ngay lập tức nhưng hành vi này có thể gây ra các kết quả không mong muốn nếu bạn không cẩn thận. Một ví dụ phổ biến của việc này là cập nhật chỉ mục gói địa phương và cài đặt các gói theo hai bước riêng biệt. Chúng tôi sẽ sử dụng Ubuntu cho ví dụ này, nhưng tiền đề cơ bản áp dụng tốt cho các hình ảnh cơ sở cho các bản phân phối khác:

Package installation example Dockerfile

FROM ubuntu:18.04
RUN apt -y update
RUN apt -y install nginx
. . .

Ở đây, chỉ mục gói cục bộ được cập nhật trong một RUN chỉ dẫn (apt -y update) và Nginx được cài đặt trong một hoạt động khác. Điều này làm việc mà không có vấn đề khi nó được sử dụng lần đầu tiên. Tuy nhiên, nếu Dockerfile được cập nhật sau để cài đặt một gói bổ sung, có thể có vấn đề:

Package installation example Dockerfile

FROM ubuntu:18.04
RUN apt -y update
RUN apt -y install nginx php-fpm
. . .

Chúng tôi đã thêm gói thứ hai vào lệnh cài đặt được chạy theo lệnh thứ hai. Nếu một khoảng thời gian đáng kể đã trôi qua kể từ khi xây dựng hình ảnh trước đó, bản dựng mới có thể không thành công. Đó là vì hướng dẫn cập nhật chỉ mục gói (RUN apt -y update) có không phải đã thay đổi, vì vậy Docker sử dụng lại lớp hình ảnh được liên kết với lệnh đó. Vì chúng tôi đang sử dụng chỉ mục gói cũ, phiên bản của php-fpm gói chúng tôi có trong hồ sơ địa phương của chúng tôi có thể không còn trong kho, dẫn đến lỗi khi lệnh thứ hai được chạy.

Để tránh trường hợp này, hãy chắc chắn hợp nhất bất kỳ bước nào phụ thuộc lẫn nhau vào một RUN hướng dẫn để Docker sẽ thực thi lại tất cả các lệnh cần thiết khi thay đổi xảy ra:

Package installation example Dockerfile

FROM ubuntu:18.04
RUN apt -y update && apt -y install nginx php-fpm
. . .

Lệnh bây giờ cập nhật bộ nhớ cache gói cục bộ bất cứ khi nào danh sách gói thay đổi.

Giảm kích thước lớp hình ảnh bằng cách tinh chỉnh lệnh RUN

Ví dụ trước cho thấy cách hoạt động của bộ nhớ đệm của Docker có thể phá vỡ các kỳ vọng, nhưng có một số điều khác cần lưu ý RUN hướng dẫn tương tác với hệ thống phân tầng của Docker. Như đã đề cập trước đó, vào cuối mỗi RUN hướng dẫn, Docker cam kết các thay đổi như là một lớp hình ảnh bổ sung. Để kiểm soát phạm vi của các lớp hình ảnh được tạo ra, bạn có thể dọn dẹp các tệp không cần thiết trong môi trường cuối cùng sẽ được cam kết bằng cách chú ý đến các tạo tác được giới thiệu bởi các lệnh bạn chạy.

Nói chung, chuỗi lệnh cùng nhau thành một RUN hướng dẫn cung cấp rất nhiều quyền kiểm soát đối với lớp sẽ được viết. Đối với mỗi lệnh, bạn có thể thiết lập trạng thái của lớp (apt -y update), thực hiện lệnh lõi (apt install -y nginx php-fpm), và loại bỏ bất kỳ hiện vật không cần thiết để làm sạch môi trường trước khi nó được cam kết. Ví dụ, nhiều chuỗi Dockerfiles rm -rf /var/lib/apt/lists/* đến cuối apt lệnh, loại bỏ các chỉ mục gói đã tải xuống, để giảm kích thước lớp cuối cùng:

Package installation example Dockerfile

FROM ubuntu:18.04
RUN apt -y update && apt -y install nginx php-fpm && rm -rf /var/lib/apt/lists/*
. . .

Để tiếp tục giảm kích thước của các lớp hình ảnh bạn đang tạo, cố gắng hạn chế các tác dụng phụ không mong muốn khác của các lệnh bạn đang chạy có thể hữu ích. Ví dụ, ngoài các gói được khai báo rõ ràng, apt cũng cài đặt các gói "được khuyến nghị" theo mặc định. Bạn có thể bao gồm --no-install-recommends cho bạn apt lệnh xóa hành vi này. Bạn có thể phải thử nghiệm để tìm hiểu xem bạn có dựa vào bất kỳ chức năng nào được cung cấp bởi các gói được đề xuất hay không.

Chúng tôi đã sử dụng các lệnh quản lý gói trong phần này làm ví dụ, nhưng các nguyên tắc tương tự này áp dụng cho các trường hợp khác. Ý tưởng chung là xây dựng các điều kiện tiên quyết, thực thi lệnh tối thiểu khả thi, và sau đó dọn dẹp mọi tạo phẩm không cần thiết trong một RUN lệnh để giảm chi phí của lớp mà bạn sẽ tạo ra.

Sử dụng Bản dựng nhiều giai đoạn

Bản dựng nhiều giai đoạn được giới thiệu trong Docker 17.05, cho phép các nhà phát triển kiểm soát chặt chẽ hơn các hình ảnh thời gian chạy cuối cùng mà họ tạo ra. Bản dựng nhiều giai đoạn cho phép bạn chia Dockerfile thành nhiều phần đại diện cho các giai đoạn riêng biệt, mỗi phần có FROM tuyên bố để xác định hình ảnh cha mẹ riêng biệt.

Các phần trước đó xác định các hình ảnh có thể được sử dụng để xây dựng ứng dụng của bạn và chuẩn bị các tài sản. Chúng thường chứa các công cụ xây dựng và các tệp phát triển cần thiết để tạo ra ứng dụng, nhưng không cần thiết để chạy nó. Mỗi giai đoạn tiếp theo được xác định trong tệp sẽ có quyền truy cập vào các tạo phẩm được tạo bởi các giai đoạn trước đó.

Cuối cùng FROM tuyên bố xác định hình ảnh sẽ được sử dụng để chạy ứng dụng. Thông thường, đây là hình ảnh được ghép đôi chỉ cài đặt các yêu cầu thời gian chạy cần thiết và sau đó sao chép các tạo tác ứng dụng được tạo ra bởi các giai đoạn trước đó.

Hệ thống này cho phép bạn ít lo lắng về việc tối ưu hóa RUN hướng dẫn trong các giai đoạn xây dựng vì các lớp chứa này sẽ không có mặt trong hình ảnh thời gian chạy cuối cùng. Bạn vẫn nên chú ý đến cách hướng dẫn tương tác với bộ nhớ đệm lớp trong giai đoạn xây dựng, nhưng những nỗ lực của bạn có thể được hướng tới giảm thiểu thời gian xây dựng thay vì kích thước hình ảnh cuối cùng. Việc chú ý đến các hướng dẫn trong giai đoạn cuối vẫn quan trọng trong việc giảm kích thước hình ảnh, nhưng bằng cách tách các giai đoạn khác nhau của công việc xây dựng container, bạn sẽ dễ dàng có được hình ảnh được sắp xếp hợp lý hơn mà không có nhiều phức tạp Dockerfile.

Chức năng phạm vi ở cấp độ container và cấp độ Pod

Mặc dù các lựa chọn bạn thực hiện liên quan đến hướng dẫn xây dựng vùng chứa là quan trọng, nhưng các quyết định rộng hơn về cách thức chứa dịch vụ của bạn thường có tác động trực tiếp hơn đến thành công của bạn. Trong phần này, chúng ta sẽ nói thêm một chút về cách chuyển đổi tốt nhất các ứng dụng của bạn từ một môi trường thông thường hơn để chạy trên một nền tảng container.

Container theo chức năng

Nói chung, thực hành tốt là đóng gói từng phần của chức năng độc lập vào một hình ảnh vùng chứa riêng biệt.

Điều này khác với các chiến lược chung được sử dụng trong các môi trường máy ảo nơi các ứng dụng thường được nhóm lại với nhau trong cùng một hình ảnh để giảm kích thước và giảm thiểu các tài nguyên cần thiết để chạy VM. Vì các thùng chứa là trừu tượng nhẹ mà không ảo hóa toàn bộ chồng hệ điều hành, sự cân bằng này ít hấp dẫn hơn đối với Kubernetes. Vì vậy, trong khi một máy ảo web stack có thể gói một máy chủ web Nginx với một máy chủ ứng dụng Gunicorn trên một máy duy nhất để phục vụ một ứng dụng Django, trong Kubernetes chúng có thể được chia thành các thùng chứa riêng biệt.

Việc thiết kế các thùng chứa thực hiện một phần chức năng rời rạc cho các dịch vụ của bạn cung cấp một số lợi thế. Mỗi thùng chứa có thể được phát triển độc lập nếu các giao diện chuẩn giữa các dịch vụ được thiết lập. Ví dụ, thùng chứa Nginx có thể được sử dụng để ủy quyền cho một số phần phụ trợ khác nhau hoặc có thể được sử dụng như một bộ cân bằng tải nếu được đưa ra một cấu hình khác.

Khi được triển khai, mỗi hình ảnh vùng chứa có thể được thu nhỏ một cách độc lập để giải quyết các hạn chế về tải và tài nguyên khác nhau. Bằng cách chia ứng dụng của bạn thành nhiều hình ảnh vùng chứa, bạn sẽ linh hoạt trong việc phát triển, tổ chức và triển khai.

Kết hợp hình ảnh vùng chứa trong nhóm

Ở Kubernetes, vỏ trái cây là đơn vị nhỏ nhất có thể được quản lý trực tiếp bởi mặt phẳng điều khiển. Các nhóm bao gồm một hoặc nhiều vùng chứa cùng với dữ liệu cấu hình bổ sung để cho nền tảng biết cách chạy các thành phần đó. Các thùng chứa trong một nhóm luôn được lên lịch trên cùng một nút công nhân trong cụm và hệ thống tự động khởi động lại các vùng chứa không thành công. Sự trừu tượng của pod là rất hữu ích, nhưng nó giới thiệu một lớp quyết định khác về cách kết hợp các thành phần của các ứng dụng của bạn.

Giống như hình ảnh vùng chứa, các nhóm cũng trở nên kém linh hoạt khi có quá nhiều chức năng được nhóm vào một thực thể duy nhất. Bản thân các Pod có thể được thu nhỏ bằng cách sử dụng các phép trừu tượng khác, nhưng các thùng chứa bên trong không thể được quản lý hoặc thu nhỏ một cách độc lập. Vì vậy, để tiếp tục sử dụng ví dụ trước của chúng tôi, các thùng chứa Nginx và Gunicorn riêng biệt có lẽ không nên được nhóm lại với nhau thành một nhóm để chúng có thể được kiểm soát và triển khai riêng biệt.

Tuy nhiên, có những tình huống mà nó làm cho tinh thần để kết hợp các container khác nhau chức năng như một đơn vị. Nói chung, chúng có thể được phân loại là các tình huống trong đó một vùng chứa bổ sung hỗ trợ hoặc tăng cường chức năng cốt lõi của thùng chứa chính hoặc giúp nó thích nghi với môi trường triển khai của nó. Một số mẫu phổ biến là:

  • Sidecar: Vùng chứa thứ cấp mở rộng chức năng cốt lõi của vùng chứa chính bằng cách đóng vai trò hỗ trợ tiện ích. Ví dụ, thùng chứa sidecar có thể chuyển tiếp các bản ghi hoặc cập nhật hệ thống tập tin khi một kho lưu trữ từ xa thay đổi. Các container chính vẫn tập trung vào trách nhiệm cốt lõi của nó, nhưng được tăng cường bởi các tính năng được cung cấp bởi sidecar.
  • Đại sứ: Một đại sứ container có trách nhiệm phát hiện và kết nối (thường phức tạp) tài nguyên bên ngoài. Vùng chứa chính có thể kết nối với vùng chứa đại sứ trên các giao diện nổi tiếng bằng môi trường nhóm nội bộ. Đại sứ tóm tắt các tài nguyên phụ trợ và lưu lượng truy cập proxy giữa vùng chứa chính và nhóm tài nguyên.
  • Bộ đổi nguồn: Một thùng chứa bộ điều hợp có trách nhiệm bình thường hóa các giao diện, dữ liệu và các giao thức thùng chứa chính để căn chỉnh với các thuộc tính mà các thành phần khác mong đợi. Vùng chứa chính có thể hoạt động bằng cách sử dụng định dạng gốc và vùng chứa bộ chuyển đổi dịch và chuẩn hóa dữ liệu để giao tiếp với thế giới bên ngoài.

Như bạn có thể đã nhận thấy, mỗi mẫu trong số này hỗ trợ chiến lược xây dựng các hình ảnh vùng chứa chuẩn, chung chung có thể được triển khai trong một ngữ cảnh và cấu hình đa dạng. Các thùng chứa thứ cấp giúp thu hẹp khoảng cách giữa vùng chứa chính và môi trường triển khai cụ thể đang được sử dụng. Một số thùng chứa bên ngoài cũng có thể được tái sử dụng để thích ứng với nhiều thùng chứa chính với cùng điều kiện môi trường. Các mẫu này được hưởng lợi từ hệ thống tệp được chia sẻ và không gian tên mạng được cung cấp bởi trừu tượng nhóm trong khi vẫn cho phép phát triển độc lập và triển khai linh hoạt các vùng chứa được chuẩn hóa.

Thiết kế cho cấu hình thời gian chạy

Có một số căng thẳng giữa mong muốn xây dựng các thành phần tiêu chuẩn hóa, tái sử dụng và các yêu cầu liên quan đến việc thích nghi với các ứng dụng trong môi trường thời gian chạy của chúng. Cấu hình thời gian chạy là một trong những phương pháp tốt nhất để thu hẹp khoảng cách giữa các mối quan tâm này. Các thành phần được xây dựng để vừa tổng quát vừa linh hoạt và hành vi được yêu cầu được nêu trong thời gian chạy bằng cách cung cấp phần mềm với thông tin cấu hình bổ sung. Cách tiếp cận tiêu chuẩn này làm việc cho các thùng chứa cũng như cho các ứng dụng.

Xây dựng với cấu hình thời gian chạy trong tâm trí đòi hỏi bạn phải suy nghĩ trước trong cả hai bước phát triển ứng dụng và các bước container. Ứng dụng nên được thiết kế để đọc các giá trị từ tham số dòng lệnh, tệp cấu hình hoặc biến môi trường khi chúng được khởi chạy hoặc khởi động lại. Phân tích cú pháp cấu hình và logic tiêm phải được triển khai trong mã trước khi đưa vào container.

Khi viết một Dockerfile, container cũng phải được thiết kế với cấu hình thời gian chạy. Các thùng chứa có một số cơ chế để cung cấp dữ liệu khi chạy. Người dùng có thể gắn kết các tệp hoặc thư mục từ máy chủ dưới dạng ổ đĩa trong vùng chứa để bật cấu hình dựa trên tệp. Tương tự như vậy, các biến môi trường có thể được chuyển vào thời gian chạy container nội bộ khi vùng chứa được bắt đầu. Các CMD và ENTRYPOINT Các lệnh Dockerfile cũng có thể được định nghĩa theo cách cho phép thông tin cấu hình thời gian chạy được truyền vào như các tham số lệnh.

Vì Kubernetes xử lý các đối tượng mức cao hơn như các pod thay vì quản lý các thùng chứa trực tiếp, có các cơ chế có sẵn để định nghĩa cấu hình và đưa nó vào môi trường vùng chứa khi chạy. Kubernetes ConfigMapsBí mật cho phép bạn xác định dữ liệu cấu hình một cách riêng biệt và sau đó chiếu các giá trị vào môi trường vùng chứa dưới dạng các biến môi trường hoặc các tệp khi chạy. ConfigMaps là các đối tượng có mục đích chung nhằm lưu trữ dữ liệu cấu hình có thể thay đổi dựa trên môi trường, giai đoạn thử nghiệm, v.v.

Bằng cách hiểu và sử dụng chính xác các tùy chọn cấu hình thời gian chạy có sẵn trong mỗi lớp trừu tượng, bạn có thể xây dựng các thành phần linh hoạt lấy tín hiệu của chúng từ các giá trị do môi trường cung cấp. Điều này làm cho nó có thể tái sử dụng các hình ảnh container giống nhau trong các kịch bản rất khác nhau, giảm chi phí phát triển bằng cách cải thiện tính linh hoạt của ứng dụng.

Thực hiện quản lý quy trình với vùng chứa

Khi chuyển sang môi trường dựa trên vùng chứa, người dùng thường bắt đầu bằng cách thay đổi khối lượng công việc hiện tại, với ít hoặc không có thay đổi, đối với hệ thống mới. Chúng đóng gói các ứng dụng trong các thùng chứa bằng cách gói các công cụ mà chúng đã sử dụng trong sự trừu tượng mới. Mặc dù việc sử dụng các mẫu thông thường của bạn để có được các ứng dụng được di chuyển và chạy, việc thả các triển khai trước đó trong các vùng chứa có thể đôi khi dẫn đến thiết kế không hiệu quả.

Xử lý vùng chứa như ứng dụng, không phải dịch vụ

Các sự cố thường xuyên phát sinh khi các nhà phát triển triển khai chức năng quản lý dịch vụ quan trọng trong vùng chứa. Ví dụ, chạy các dịch vụ systemd trong container hoặc daemonizing các máy chủ web có thể được coi là thực hành tốt nhất trong một môi trường tính toán bình thường, nhưng chúng thường xung đột với các giả định vốn có trong mô hình container.

Các máy chủ quản lý các sự kiện vòng đời của thùng chứa bằng cách gửi tín hiệu đến quy trình hoạt động như PID (ID tiến trình) 1 bên trong vùng chứa. PID 1 là quá trình đầu tiên bắt đầu, đó sẽ là hệ thống init trong môi trường điện toán truyền thống. Tuy nhiên, vì máy chủ chỉ có thể quản lý PID 1, sử dụng hệ thống init thông thường để quản lý các quy trình trong vùng chứa đôi khi có nghĩa là không có cách nào để kiểm soát ứng dụng chính. Máy chủ có thể khởi động, dừng hoặc tiêu diệt hệ thống init nội bộ, nhưng không thể quản lý trực tiếp ứng dụng chính. Các tín hiệu đôi khi truyền bá hành vi dự định đến ứng dụng đang chạy, nhưng điều này làm tăng thêm độ phức tạp và không phải lúc nào cũng cần thiết.

Hầu hết thời gian, tốt hơn là đơn giản hóa môi trường đang chạy trong vùng chứa để PID 1 đang chạy ứng dụng chính ở nền trước. Trong trường hợp phải chạy nhiều tiến trình, PID 1 chịu trách nhiệm quản lý vòng đời của các quá trình tiếp theo. Một số ứng dụng nhất định, như Apache, xử lý điều này bằng cách sinh sản và quản lý nhân viên xử lý các kết nối. Đối với các ứng dụng khác, một kịch bản trình bao bọc hoặc một hệ thống init rất đơn giản như dumb-init hoặc bao gồm tini hệ thống init có thể được sử dụng trong một số trường hợp. Bất kể việc triển khai bạn chọn, quá trình chạy như PID 1 trong vùng chứa sẽ phản hồi phù hợp với TERM tín hiệu được gửi bởi Kubernetes để hành xử như mong đợi.

Quản lý sức khỏe vùng chứa trong Kubernetes

Các triển khai và dịch vụ của Kubernetes cung cấp quản lý vòng đời cho các quy trình chạy dài và truy cập đáng tin cậy, liên tục vào các ứng dụng, ngay cả khi các thùng chứa cơ bản cần được khởi động lại hoặc bản thân việc triển khai thay đổi. Bằng cách trích xuất trách nhiệm theo dõi và duy trì sức khỏe dịch vụ ngoài vùng chứa, bạn có thể tận dụng các công cụ của nền tảng để quản lý tải công việc lành mạnh.

Để Kubernetes quản lý các thùng chứa đúng cách, nó phải hiểu liệu các ứng dụng chạy trong các thùng chứa có lành mạnh và có khả năng thực hiện công việc hay không. Để cho phép điều này, các thùng chứa có thể thực hiện các đầu dò liveness: các điểm cuối mạng hoặc các lệnh có thể được sử dụng để báo cáo tình trạng sức khỏe của ứng dụng. Kubernetes sẽ định kỳ kiểm tra các đầu dò liveness được xác định để xác định xem container có hoạt động như mong đợi hay không. Nếu vùng chứa không đáp ứng một cách thích hợp, Kubernetes khởi động lại vùng chứa trong một nỗ lực để thiết lập lại chức năng.

Kubernetes cũng cung cấp đầu dò sẵn sàng, một cấu trúc tương tự. Thay vì cho biết ứng dụng trong một thùng chứa có lành mạnh hay không, các đầu dò sẵn sàng xác định xem ứng dụng có sẵn sàng nhận lưu lượng hay không. Điều này có thể hữu ích khi một ứng dụng được chứa có một thường trình khởi tạo phải hoàn thành trước khi nó sẵn sàng nhận các kết nối. Kubernetes sử dụng đầu dò sẵn sàng để xác định có thêm nhóm vào hoặc xóa nhóm từ dịch vụ hay không.

Việc xác định điểm cuối cho hai loại đầu dò này có thể giúp Kubernetes quản lý các thùng chứa của bạn một cách hiệu quả và có thể ngăn chặn các vấn đề về vòng đời của thùng chứa ảnh hưởng đến tính khả dụng của dịch vụ. Các cơ chế để đáp ứng các kiểu yêu cầu y tế này phải được xây dựng trong ứng dụng và phải được hiển thị trong cấu hình hình ảnh Docker.

Phần kết luận

Trong hướng dẫn này, chúng tôi đã đề cập đến một số cân nhắc quan trọng cần lưu ý khi
chạy các ứng dụng được chứa trong Kubernetes. Để nhắc lại, một số
đề xuất chúng tôi đã đi qua là:

  • Sử dụng hình ảnh gốc tối thiểu, có thể chia sẻ để tạo hình ảnh với màu tối thiểu và giảm thời gian khởi động
  • Sử dụng các bản dựng nhiều giai đoạn để tách các môi trường xây dựng và môi trường chạy bộ chứa
  • Kết hợp các hướng dẫn Dockerfile để tạo các lớp hình ảnh sạch và tránh các lỗi trong bộ nhớ đệm hình ảnh
  • Container bằng cách cô lập chức năng rời rạc để cho phép mở rộng quy mô và quản lý linh hoạt
  • Thiết kế vỏ để có một trách nhiệm tập trung duy nhất
  • Đóng gói các thùng chứa trợ giúp để tăng cường chức năng của vùng chứa chính hoặc để thích ứng với môi trường triển khai
  • Xây dựng ứng dụng và vùng chứa để phản hồi cấu hình thời gian chạy để cho phép linh hoạt hơn khi triển khai
  • Chạy các ứng dụng như các quá trình chính trong các thùng chứa để Kubernetes có thể quản lý các sự kiện vòng đời
  • Phát triển các điểm cuối về sức khỏe và sức sống trong ứng dụng hoặc vùng chứa để Kubernetes có thể theo dõi sức khỏe của vùng chứa

Trong suốt quá trình phát triển và thực hiện, bạn sẽ cần đưa ra các quyết định có thể ảnh hưởng đến sự mạnh mẽ và hiệu quả của dịch vụ của bạn. Hiểu các cách mà các ứng dụng được đóng gói khác với các ứng dụng thông thường và học cách chúng hoạt động trong một môi trường cụm được quản lý có thể giúp bạn tránh một số cạm bẫy phổ biến và cho phép bạn tận dụng tất cả các khả năng mà Kubernetes cung cấp.

0