Xây dựng container được tối ưu hóa cho Kubernetes
Containers images 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 group và các đối tượng khác, hình ảnh đóng một role 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 trên nền tảng một cách hiệu quả. Hình ảnh được thiết kế tốt sẽ an toàn, hiệu suất cao và tập trung. Chúng 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 triển khai các điểm cuối mà hệ thống điều phối sử dụng để hiểu trạng thái ứng dụng nội bộ.Trong bài viết này, ta 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 số mục tiêu chung để giúp định hướng các quyết định của bạn khi chứa các ứng dụng. Ta sẽ tập trung vào việc xây dựng hình ảnh dự định chạy trên Kubernetes, nhưng nhiều đề xuất áp dụng tương tự cho việc chạy containers trên các nền tảng điều phối khác hoặc trong các ngữ cảnh khác.
Đặc điểm của containers images hiệu quả
Trước khi xem xét các hành động cụ thể cần thực hiện khi xây dựng containers images , ta sẽ nói về những gì tạo nên một containers images tốt. Mục tiêu của bạn khi thiết kế hình ảnh mới là gì? Đặc điểm nào và hành vi nào là quan trọng nhất?
Một số phẩm chất cần hướng tới là:
Một mục đích duy nhất, được xác định rõ ràng
Containers images phải có một tiêu điểm rời rạc. Tránh nghĩ containers images là máy ảo, nơi nó có thể có ý nghĩa khi đóng gói các chức năng liên quan lại với nhau. Thay vào đó, hãy coi các containers images của bạn giống như các tiện ích Unix, duy trì sự tập trung chặt chẽ vào việc làm tốt một việc nhỏ. Các ứng dụng có thể được điều phối bên ngoài phạm vi containers để tạo ra các chức năng phức tạp.
Thiết kế chung với khả năng đưa cấu hình vào thời gian chạy
Containers images nên được thiết kế với lưu ý tái sử dụng 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ư kiểm tra hình ảnh của bạn trước khi triển khai production . Hình ảnh nhỏ, chung chung có thể được kết hợp theo 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 group như Kubernetes. Chúng tải nhanh xuống các node mới và thường có một tập hợp các gói cài đặt nhỏ hơn, có thể cải thiện tính bảo mật. Containers images được giảm bớt giúp việc gỡ lỗi trở nên đơn giản hơn bằng cách giảm thiểu lượng phần mềm liên quan.
Trạng thái được quản lý bên ngoài
Các containers trong môi trường phân cụm trải qua một vòng đời rất biến động bao gồm các lần ngừng hoạt động theo kế hoạch và không có kế hoạch do 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ợ khôi phục và tính khả dụng của các dịch vụ của bạn cũng như tránh mất dữ liệu, điều quan trọng là bạn phải lưu trữ trạng thái ứng dụng ở một vị trí ổn định bên ngoài containers .
Dễ hiểu
Điều quan trọng là cố gắng giữ cho containers images càng đơn giản và dễ hiểu càng tốt. Khi khắc phục sự cố, có thể dễ dàng lý giải sự cố bằng cách xem cấu hình containers images hoặc kiểm tra hành vi containers có thể giúp bạn đạt được độ phân giải nhanh hơn. Việc coi containers images như một đị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ự cân bằng phù hợp.
Thực hiện theo các phương pháp hay nhất về phần mềm được chứa đựng
Hình ảnh nên hướng tới hoạt động trong mô hình containers thay vì hoạt động chống lại nó.Tránh thực hiện các phương pháp 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 theo tiêu chuẩn để Kubernetes có thể hiển thị dữ liệu cho administrator thay vì sử dụng daemon ghi log nội bộ. Mỗi điều này khác với các phương pháp hay nhất dành cho 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 containers , điều quan trọng là phải hiểu và hòa hợp với môi trường và công cụ mà Kubernetes cung cấp. Ví dụ: việc cung cấp điểm cuối để kiểm tra tính sẵn sàng và hoạt độ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 một cách thuận lợi.
Bây giờ ta đã cài đặt một số phẩm chất xác định containers images có chức năng cao, ta có thể đi sâu hơn vào các chiến lược giúp bạn đạt được những mục tiêu này.
Sử dụng lại các lớp cơ sở được chia sẻ, tối thiểu
Ta có thể bắt đầu bằng cách kiểm tra các tài nguyên mà containers images được xây dựng từ: hình ảnh cơ sở. Mỗi containers images được xây dựng từ một hình ảnh mẹ , một hình ảnh được sử dụng làm điểm bắt đầu hoặc từ lớp scratch
trừu tượng, một lớp hình ảnh trống không có hệ thống file . Hình ảnh cơ sở là hình ảnh containers 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 cốt lõi. Hình ảnh bao gồm một hoặc nhiều lớp hình ảnh được xây dựng chồng lên nhau để tạo thành hình ảnh cuối cùng.
Không có tiện ích hoặc hệ thống file tiêu chuẩn nào khả dụng khi làm việc trực tiếp từ scratch
, nghĩa là bạn chỉ có quyền truy cập vào chức năng cực kỳ hạn chế. Mặc dù 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 các containers images của bạn trên một hình ảnh root để cài đặt một môi trường cơ bản mà các ứng dụng của bạn chạy trong đó để 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ó các hình ảnh cơ sở cho nhiều bản phân phối Linux, nhưng tốt nhất bạn nên cân nhắc về hệ thống mà bạn chọn. Mỗi máy mới sẽ phải download hình ảnh root và bất kỳ lớp bổ sung nào 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 băng thông đáng kể và kéo dài đáng kể thời gian khởi động containers của bạn trong lần chạy đầu tiên. Không có cách nào để loại bỏ một hình ảnh được sử dụng làm ảnh root trong quá trình xây dựng containers , vì vậy bắt đầu với một ảnh root tối thiểu là một ý kiến hay.
Các môi trường giàu tính năng như Ubuntu cho phép ứng dụng của bạn chạy trong môi trường mà bạn quen thuộc, nhưng có một số sự cân bằng cần 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 (hơn 100MB), nghĩa là bất kỳ containers images nào được xây dựng từ chúng sẽ kế thừa trọng lượng đó.
Alpine Linux là một giải pháp thay thế phổ biến cho hình ảnh cơ sở vì nó gói thành công nhiều chức năng vào một hình ảnh cơ sở rất nhỏ (~ 5MB). Nó bao gồm một trình quản lý gói với các repository lớn và có hầu hết các tiện ích tiêu chuẩn mà bạn mong đợi từ mộ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 root cho mỗi hình ảnh. Khi hình ảnh của bạn dùng chung một lớp cha, các máy chạy containers của bạn sẽ chỉ download lớp cha một lần. Sau đó, họ sẽ chỉ cần tải các lớp khác nhau giữa các hình ảnh của bạn. Điều này 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, thì việc tạo một hình ảnh mẹ chung để kế thừa có thể là một ý tưởng hay. Hình ảnh có chung dòng dõi giúp giảm thiểu lượng dữ liệu bổ sung bạn cần download trên các server mới.
Quản lý các lớp containers
Khi bạn đã chọn hình ảnh root , bạn có thể xác định containers images của bạn bằng cách thêm phần mềm bổ sung, sao chép file , hiển thị các cổng và chọn các quy trình để chạy. Một số hướng dẫn nhất định trong file cấu hình hình ảnh (tệp 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.
Vì 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 ý đến cách bạn thêm các lớp vào hình ảnh của bạn do kích thước kết quả, tính kế thừa và độ phức tạp thời gian chạy. Để tránh xây dựng các hình ảnh lớn và khó sử dụng, điều quan trọng là phải hiểu rõ về cách các lớp containers tương tác, cách bộ máy xây dựng lưu vào các lớp và sự khác biệt nhỏ trong các hướng dẫn tương tự có thể có tác động lớn như thế nào đến hình ảnh bạn tạo.
Hiểu các lớp hình ảnh và tạo bộ nhớ đệm
Docker tạo một lớp hình ảnh mới mỗi khi nó thực hiện lệnh RUN
, COPY
hoặc ADD
. 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 lệnh để xem liệu nó có lớp hình ảnh được lưu vào bộ nhớ cache cho hoạt động hay không. Nếu nó tìm thấy một kết quả trùng khớp trong bộ nhớ cache, 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. Đối với các hướng dẫn sao chép file như COPY
và ADD
, Docker so sánh tổng kiểm tra của các file để xem liệu có cần thực hiện lại thao tác hay không. Đối với các hướng dẫn RUN
, Docker kiểm tra xem liệu nó có lớp hình ảnh hiện có được lưu trong bộ nhớ cache 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 những 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 về điều này là cập nhật index gói local và cài đặt gói theo hai bước riêng biệt. Ta sẽ sử dụng Ubuntu cho ví dụ này, nhưng tiền đề cơ bản cũng áp dụng tốt cho các hình ảnh cơ sở cho các bản phân phối khác:
FROM ubuntu:18.04 RUN apt -y update RUN apt -y install nginx . . .
Tại đây, index gói local được cập nhật trong một lệnh RUN
( apt -y update
) và Nginx được cài đặt trong một thao tác khác. Điều này hoạt động 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ể xảy ra sự cố:
FROM ubuntu:18.04 RUN apt -y update RUN apt -y install nginx php-fpm . . .
Ta đã thêm gói thứ hai vào lệnh cài đặt chạy bằng lệnh thứ hai. Nếu một khoảng thời gian đáng kể đã trôi qua kể từ lần tạo hình ảnh trước đó, bản dựng mới có thể không thành công. Đó là bởi vì lệnh cập nhật index gói ( RUN apt -y update
) không 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ì ta đang sử dụng index gói cũ, version của gói php-fpm
mà ta có trong bản ghi local của bạn có thể không còn trong repository lưu trữ, dẫn đến lỗi khi chạy lệnh thứ hai.
Để tránh trường hợp này, hãy đảm bảo hợp nhất bất kỳ bước nào phụ thuộc lẫn nhau thành một lệnh RUN
duy nhất để Docker sẽ thực thi lại tất cả các lệnh cần thiết khi xảy ra thay đổi:
FROM ubuntu:18.04 RUN apt -y update && apt -y install nginx php-fpm . . .
Hướng dẫn hiện cập nhật cache ẩn gói local khi nào danh sách gói thay đổi.
Giảm kích thước lớp ảnh bằng cách tinh chỉnh hướng dẫn RUN
Ví dụ trước chứng minh cách hành vi lưu trong 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 ý về cách các lệnh RUN
tương tác với hệ thống phân lớp của Docker. Như đã đề cập trước đó, ở cuối mỗi lệnh RUN
, Docker commit các thay đổi như 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ể xóa các file không cần thiết trong môi trường cuối cùng sẽ được commit bằng cách chú ý đến các thành phần được giới thiệu bởi các lệnh bạn chạy.
Nói chung, việc xâu chuỗi các lệnh lại với nhau thành một lệnh RUN
duy nhất 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ể cài đặt trạng thái của lớp ( apt -y update
), thực hiện lệnh cốt 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 nào để dọn dẹp môi trường trước khi nó được commit . Ví dụ: nhiều chuỗi Dockerfiles rm -rf /var/lib/apt/lists/*
ists rm -rf /var/lib/apt/lists/*
đến cuối các apt
, xóa các index gói đã download , để giảm kích thước lớp cuối cùng:
FROM ubuntu:18.04 RUN apt -y update && apt -y install nginx php-fpm && rm -rf /var/lib/apt/lists/* . . .
Để giảm thê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 “khuyến nghị” theo mặc định. Bạn có thể bao gồm --no-install-recommends
vào các apt
của bạn để loại bỏ 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.
Ta đã 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 yêu cầu , thực hiện lệnh khả thi tối thiểu và sau đó dọn dẹp mọi hiện vật không cần thiết trong một lệnh RUN
duy nhất để giảm chi phí của lớp mà bạn sẽ tạo ra.
Sử dụng Công trình nhiều giai đoạn
Các 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. Các bản dựng nhiều giai đoạn cho phép bạn chia Dockerfile của bạn thành nhiều phần đại diện cho các giai đoạn riêng biệt, mỗi phần có một câu lệnh FROM
để chỉ định các hình ảnh root riêng biệt.
Các phần trước đó xác định hình ảnh được dùng để xây dựng ứng dụng của bạn và chuẩn bị nội dung. Chúng thường chứa các công cụ xây dựng và file 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 file sẽ có quyền truy cập vào các tạo tác được tạo ra bởi các giai đoạn trước.
Câu lệnh FROM
cuối cùng xác định hình ảnh sẽ được sử dụng để chạy ứng dụng. Thông thường, đây là một hình ảnh giảm bớt 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 bớt lo lắng về việc tối ưu hóa các lệnh RUN
trong các giai đoạn xây dựng vì các lớp containers đó sẽ không xuất hiện trong hình ảnh thời gian chạy cuối cùng. Bạn vẫn nên chú ý đến cách các hướng dẫn tương tác với bộ nhớ đệm lớp trong các giai đoạn xây dựng, nhưng nỗ lực của bạn có thể hướng đến việc giảm thiểu thời gian xây dựng hơn là kích thước hình ảnh cuối cùng. Chú ý đến các hướng dẫn trong giai đoạn cuối cùng 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 quá trình xây dựng containers của bạn, sẽ dễ dàng hơn để có được hình ảnh được sắp xếp hợp lý mà không quá phức tạp Dockerfile.
Chức năng xác định phạm vi ở cấp containers và group
Mặc dù các lựa chọn bạn đưa ra liên quan đến hướng dẫn xây dựng containers là quan trọng, nhưng các quyết định rộng hơn về cách chứa các 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, 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 sang chạy trên nền tảng containers .
Chứa đựng theo chức năng
Nói chung, bạn nên đóng gói từng phần chức năng độc lập vào một containers images riêng biệt.
Điều này khác với các chiến lược phổ biến được sử dụng trong môi trường máy ảo nơi các ứng dụng thường được group lại với nhau trong cùng một hình ảnh để giảm kích thước và giảm thiểu tài nguyên cần thiết để chạy VM. Vì các containers là các bản tóm tắt nhẹ không ảo hóa toàn bộ ngăn xếp hệ điều hành, nên sự cân bằng này kém hấp dẫn hơn trên Kubernetes.Vì vậy, mặc dù máy ảo ngăn xếp web có thể kết hợp web server Nginx với server ứng dụng Gunicorn trên một máy duy nhất để phục vụ ứng dụng Django, trong Kubernetes, chúng có thể được chia thành các containers riêng biệt.
Thiết kế containers triển khai một phần chức năng riêng biệt cho các dịch vụ của bạn mang lại một số lợi thế. Mỗi containers 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 cài đặt . Ví dụ: containers Nginx có khả năng được sử dụng để ủy quyền cho một số phần mềm backend khác nhau hoặc được dùng làm bộ cân bằng tải nếu được cung cấp một cấu hình khác.
Sau khi được triển khai, mỗi containers images có thể được thay đổi tỷ lệ độ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 các ứng dụng của bạn thành nhiều containers images , bạn có được sự linh hoạt trong phát triển, tổ chức và triển khai.
Kết hợp containers images trong group
Trong Kubernetes, pod 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. Group bao gồm một hoặc nhiều containers cùng với dữ liệu cấu hình bổ sung để cho nền tảng biết cách các thành phần đó sẽ được chạy. Các containers trong một group 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 sẽ tự động khởi động lại các containers bị lỗi. Tóm tắt group 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 ứng dụng với nhau.
Giống như containers images , các group cũng trở nên kém linh hoạt hơn khi có quá nhiều chức năng được đóng gói vào một thực thể duy nhất. Bản thân các group có thể được chia tỷ lệ bằng cách sử dụng các phần tóm tắt khác, nhưng các containers bên trong không thể được quản lý hoặc mở rộng một cách độc lập. Vì vậy, để tiếp tục sử dụng ví dụ trước của ta , các containers Nginx và Gunicorn riêng biệt có lẽ không nên được group lại với nhau thành một group duy nhất để 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à việc kết hợp các containers khác nhau về mặt chức năng thành một đơn vị sẽ có ý nghĩa. Nói chung, chúng có thể được gọi là các tình huống trong đó một containers bổ sung hỗ trợ hoặc nâng cao chức năng cốt lõi của containers chính hoặc giúp nó thích ứng với môi trường triển khai của bạn . Một số mẫu phổ biến là:
- Sidecar : Vùng chứa phụ mở rộng chức năng cốt lõi của containers chính bằng cách đóng role tiện ích hỗ trợ. Ví dụ: containers sidecar có thể chuyển tiếp log hoặc cập nhật hệ thống file khi repository từ xa thay đổi. Vùng chứa 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 do sidecar cung cấp.
- Đại sứ : Một container đại sứ có nhiệm vụ phát hiện và kết nối với các nguồn lực bên ngoài (thường phức tạp). Vùng chứa chính có thể kết nối với containers đại sứ trên các giao diện nổi tiếng bằng cách sử dụng môi trường group bên trong. Đại sứ tóm tắt các tài nguyên backend và lưu lượng truy cập proxy giữa containers chính và group tài nguyên.
- Bộ điều hợp : Hộp chứa bộ điều hợp chịu trách nhiệm chuẩn hóa các giao diện, dữ liệu và giao thức của containers chính để phù hợp 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 các định dạng root và containers bộ điều hợp 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 này hỗ trợ chiến lược xây dựng containers images chính chung, chuẩn, sau đó có thể được triển khai trong nhiều bối cảnh và cấu hình khác nhau. Các containers thứ cấp giúp thu hẹp khoảng cách giữa containers chính và môi trường triển khai cụ thể đang được sử dụng. Một số container sidecar cũng có thể được tái sử dụng để điều chỉnh nhiều container chính với cùng điều kiện môi trường. Những mẫu này được hưởng lợi từ hệ thống file được chia sẻ và không gian tên mạng được cung cấp bởi tính trừu tượng group trong khi vẫn cho phép phát triển độc lập và triển khai linh hoạt các containers được tiêu 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, có thể tái sử dụng và các yêu cầu liên quan đến việc thích ứng các ứng dụng với 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 những mối quan tâm này. Các thành phần được xây dựng để vừa chung chung vừa linh hoạt và hành vi được yêu cầu được phác thảo trong thời gian chạy bằng cách cung cấp cho phần mềm thông tin cấu hình bổ sung. Cách tiếp cận tiêu chuẩn này hoạt động đối với các container cũng như đối với các ứng dụng.
Xây dựng với cấu hình thời gian chạy yêu cầu bạn phải suy nghĩ trước trong cả các bước phát triển ứng dụng và chứa. Các ứng dụng phải được thiết kế để đọc các giá trị từ tham số dòng lệnh, file cấu hình hoặc biến môi trường khi chúng được chạy hoặc khởi động lại. Logic phân tích cú pháp và chèn cấu hình này phải được thực hiện trong mã trước khi chứa.
Khi viết Dockerfile, containers cũng phải được thiết kế với cấu hình thời gian chạy. Vùng chứa có một số cơ chế để cung cấp dữ liệu trong thời gian chạy. User có thể mount các file hoặc folder từ server lưu trữ dưới dạng ổ đĩa trong containers để kích hoạt cấu hình dựa trên file . Tương tự như vậy, các biến môi trường có thể được truyền vào thời gian chạy containers bên trong khi containers được khởi động. Các lệnh CMD
và ENTRYPOINT
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 chuyển vào dưới dạng các tham số lệnh.
Vì Kubernetes thao tác các đối tượng cấp cao hơn như group thay vì quản lý trực tiếp containers , nên có sẵn các cơ chế để xác cấu hình và đưa nó vào môi trường containers trong thời gian chạy. Kubernetes ConfigMaps and Secrets cho phép bạn xác định dữ liệu cấu hình riêng biệt và sau đó chiếu các giá trị vào môi trường containers dưới dạng các biến môi trường hoặc file trong thời gian chạy. Bản đồ cấu hình 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 tùy theo môi trường, giai đoạn thử nghiệm, v.v. Bí mật cung cấp giao diện tương tự nhưng được thiết kế đặc biệt cho dữ liệu nhạy cảm, như password account hoặc thông tin đăng nhập API.
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 dấu hiệu của chúng từ các giá trị do môi trường cung cấp. Điều này giúp bạn có thể sử dụng lại các containers images giống nhau trong các tình huống 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 container
Khi chuyển đổi sang môi trường dựa trên containers , user thường bắt đầu bằng cách chuyển dung lượng công việc hiện có, với ít hoặc không có thay đổi, sang hệ thống mới. Họ đóng gói các ứng dụng trong các container bằng cách gói các công cụ họ đang sử dụng trong phần trừu tượng mới.Mặc dù sẽ hữu ích khi sử dụng các mẫu thông thường của bạn để cài đặt và chạy các ứng dụng đã di chuyển, nhưng việc giảm các triển khai trước đó trong containers đôi khi có thể 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 vấn đề 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 containers . Ví dụ: chạy các dịch vụ systemd trong containers hoặc daemonizing web server có thể được coi là các phương pháp hay nhất trong môi trường máy tính 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 containers .
Server quản lý các sự kiện trong vòng đời của containers bằng cách gửi tín hiệu đến quá trình hoạt động dưới dạng PID (ID tiến trình) 1 bên trong containers . PID 1 là quá trình đầu tiên được bắt đầu, sẽ là hệ thống init trong môi trường máy tính truyền thống. Tuy nhiên, vì server chỉ có thể quản lý PID 1 nên việc sử dụng hệ thống init thông thường để quản lý các quy trình trong containers đôi khi nghĩa là không có cách nào để kiểm soát ứng dụng chính. Server có thể khởi động, dừng hoặc hủy 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 hành vi dự định cho ứng dụng đang chạy, nhưng điều này làm tăng thêm sự 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 bên trong containers để 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 quy trình, PID 1 chịu trách nhiệm quản lý vòng đời của các quy trình tiếp theo. Một số ứng dụng nhất định, như Apache, xử lý điều này một cách nguyên bản bằng cách tạo và quản lý các nhân viên xử lý kết nối. Đối với các ứng dụng khác, một tập lệnh shell bọc hoặc một hệ thống init rất đơn giản như câm-init hoặc hệ thống tini init đi kèm được dùng trong một số trường hợp. Dù cách triển khai bạn chọn là gì, quá trình chạy dưới dạng PID 1 bên trong containers sẽ phản hồi thích hợp với các tín hiệu TERM
do Kubernetes gửi để hoạt động như mong đợi.
Quản lý tình trạng containers trong Kubernetes
Các dịch vụ và triển khai Kubernetes cung cấp khả năng quản lý vòng đời cho các quy trình chạy lâu dài và khả năng truy cập liên tục, tin cậy vào các ứng dụng, ngay cả khi các containers bên dưới 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 extract trách nhiệm theo dõi và duy trì tình trạng dịch vụ ra khỏi containers , bạn có thể tận dụng các công cụ của nền tảng để quản lý dung lượng công việc lành mạnh.
Để Kubernetes quản lý containers đúng cách, nó phải hiểu liệu các ứng dụng chạy trong containers có khỏe mạnh và có khả năng thực hiện công việc hay không. Để kích hoạt điều này, containers có thể triển khai các đầu dò độ sống: điểm cuối mạng hoặc lệnh được dùng để báo cáo tình trạng ứng dụng. Kubernetes sẽ kiểm tra định kỳ các đầu dò độ sống đã xác định để xác định xem container có hoạt động như mong đợi hay không. Nếu containers không phản hồi thích hợp, Kubernetes sẽ khởi động lại containers để cố gắng cài đặt lại chức năng.
Kubernetes cũng cung cấp các đầu dò sẵn sàng, một cấu trúc tương tự. Thay vì chỉ ra liệu ứng dụng bên trong containers có hoạt động tốt hay không, các thăm dò mức độ sẵn sàng xác định xem ứng dụng đã sẵn sàng để nhận lưu lượng truy cập hay chưa. Điều này có thể hữu ích khi ứng dụng được chứa trong containers có quy trình khởi tạo phải hoàn thành trước khi sẵn sàng nhận kết nối.Kubernetes sử dụng các đầu dò về mức độ sẵn sàng để xác định xem nên thêm một group vào hay xóa một group khỏi một dịch vụ.
Việc xác định điểm cuối cho hai loại thăm dò này có thể giúp Kubernetes quản lý containers 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 containers ảnh hưởng đến tính khả dụng của dịch vụ. Các cơ chế để phản hồi các loại yêu cầu tình trạng này phải được tích hợp sẵn trong chính ứng dụng và phải được hiển thị trong cấu hình Docker image .
Kết luận
Trong hướng dẫn này, ta đã đề cập đến một số cân nhắc quan trọng cần ghi nhớ khi
đang chạy các ứng dụng chứa trong Kubernetes. Để nhắc lại, một số
đề xuất ta đã xem qua là:
- Sử dụng hình ảnh mẹ tối thiểu, có thể chia sẻ để tạo hình ảnh với độ phồng 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 biệt môi trường xây dựng containers và thời gian chạy
- Kết hợp các hướng dẫn của Dockerfile để tạo các lớp hình ảnh sạch và tránh các lỗi lưu vào bộ nhớ đệm hình ảnh
- Ngăn chứa bằng cách cô lập chức năng rời rạc để cho phép mở rộng và quản lý linh hoạt
- Thiết kế các group để có một trách nhiệm tập trung duy nhất
- Group các containers trợ giúp để nâng cao chức năng của containers chính hoặc để điều chỉnh nó với môi trường triển khai
- Xây dựng các ứng dụng và containers để đáp ứng vớ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 làm quy trình chính trong containers để 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ống trong ứng dụng hoặc containers để Kubernetes có thể theo dõi tình trạng của containers
Trong suốt quá trình phát triển và triển khai, bạn cần đưa ra các quyết định có thể ảnh hưởng đến tính mạnh mẽ và hiệu quả của dịch vụ. Việc hiểu các ứng dụng được chứa trong containers khác với các ứng dụng thông thường và tìm hiểu cách chúng hoạt động trong 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.
Các tin liên quan