Cách ưa thích để lưu trữ cấu hình ứng dụng là gì?


38

Hầu hết thời gian, tôi lưu trữ cấu hình ứng dụng phát triển trong thư mục gốc của dự án, như thế này:

app
|-- config.json

Nhưng đó dường như không phải là cách tiếp cận tốt nhất, vì cấu hình này cuối cùng được lưu trữ trong hệ thống kiểm soát phiên bản - có thể dẫn đến tên người dùng, mật khẩu bị rò rỉ và các nội dung nhạy cảm khác.

12 Hướng dẫn ứng dụng Factor khuyên bạn nên bỏ hoàn toàn các tệp cấu hình và sử dụng các biến môi trường để thiết lập cấu hình:

... lưu trữ cấu hình trong các biến môi trường. Env vars dễ dàng thay đổi giữa các triển khai mà không thay đổi bất kỳ mã nào; Không giống như các tập tin cấu hình, rất ít khả năng chúng được kiểm tra vào mã repo một cách tình cờ; và không giống như các tệp cấu hình tùy chỉnh hoặc các cơ chế cấu hình khác như Thuộc tính hệ thống Java, chúng là một tiêu chuẩn không biết ngôn ngữ và hệ điều hành.

Điều đó nghe có vẻ thực sự tốt với tôi, nhưng một cửa hàng nói các biến môi trường ở đâu, mà không kiểm tra chúng trong kiểm soát nguồn? Và công cụ nào tôi có thể sử dụng để chuyển các biến đó vào ứng dụng? Có thể có hàng tá tùy chọn cấu hình và nhập chúng bằng tay mỗi khi bạn khởi chạy ứng dụng không đẹp - vì vậy chúng phải được lưu trữ trong một số loại tệp ở đâu đó. Do đó, tập tin đã nói sẽ kết thúc trong kiểm soát nguồn và chúng tôi quay trở lại nơi chúng tôi đã bắt đầu.

Có một số cách xử lý tùy chọn cấu hình được chấp nhận phổ biến, điều đó không có nguy cơ lưu trữ cấu hình cục bộ trong kiểm soát nguồn?


1
Chà, ít nhất git có một cái gì đó giống như .gitignorenơi tôi có thể xác định các tệp hoặc thư mục không nên được kiểm tra trong kiểm soát phiên bản. Như bạn nói tôi không thấy nơi Env vars thực sự có ích, vì bạn có một tập lệnh để đặt chúng và nên được lưu trữ cùng với dự án hoặc bạn có chúng 'ở đâu đó' trên hệ thống của bạn (thư mục chính hoặc ngay cả khi máy khởi động các tập lệnh) dường như tự tạo ra rất nhiều vấn đề, đặc biệt là nếu cần nhiều cấu hình. Trong mọi trường hợp, tôi sẽ phân chia các tệp cấu hình để thông tin bí mật đi vào các tệp khác nhau.
thorsten müller

@ thorstenmüller - chỉ có vấn đề với .gitignore mà cấu hình cơ sở / mẫu vẫn phải được lưu trữ, điều đó có nghĩa là ứng dụng đó phải đọc hai cấu hình - cơ sở một, với các tùy chọn mặc định (được lưu trữ trong scm) và cục bộ, ghi đè lên cơ sở (và không được lưu trữ trong scm). Với env vars, tôi tưởng tượng rằng việc triển khai hàng loạt trở nên dễ dàng hơn - việc chỉ định các biến môi trường cho thiết lập máy ảo mới đơn giản hơn là viết một cái gì đó vào một tệp không chuẩn.
Rogach

Câu hỏi hay, Sau khi tôi bắt đầu sử dụng kho dữ liệu ứng dụng dành riêng cho người dùng thông thường cho việc này, cuộc sống trở nên dễ dàng hơn ;-)
Wolf

1
Bạn đã thử "Redis" redis.io . Nó chỉ có ý nghĩa đặc biệt cho việc lưu trữ cấu trúc khóa-giá trị.
Karan

2
@jporcenaluk - Tôi thích lưu trữ khóa-giá trị, nhưng việc thêm một bản đỏ hoàn chỉnh vào ứng dụng chỉ để xử lý việc quản lý cấu hình có cảm giác hơi quá mức. Mặt khác, có lẽ tôi chưa bao giờ làm việc trong các dự án đủ lớn.
Rogach

Câu trả lời:


16

Có thể không có câu trả lời tốt cho điều này. Có vẻ như bạn cần lưu trữ dữ liệu này ở một nơi an toàn, vì nó sẽ cần thiết cho mục đích khắc phục thảm họa vào một ngày nào đó. Điều này áp dụng như nhau cho các tệp thuộc tính và tập lệnh đặt các biến môi trường.

  • Với mã nguồn (trong SVN / GIT, v.v.) là một ý tưởng thực sự tồi tệ, vì dữ liệu này sẽ chứa mật khẩu cơ sở dữ liệu sản xuất và những thứ tương tự.
  • Sao lưu hàng đêm của công ty bạn có thể là đủ, nhưng không có khả năng giữ một lịch sử thay đổi dễ tiếp cận.
  • Dữ liệu cần được phiên bản riêng cho phần mềm tiêu thụ. Trong hệ thống hiện tại của chúng tôi, việc thay đổi cấu hình dẫn đến việc xây dựng ứng dụng mới và điều này hoàn toàn sai.

Chúng tôi hiện đang xem xét các giải pháp cho vấn đề này và đang nghiêng về một kho lưu trữ mã với quyền truy cập hạn chế. Kho lưu trữ này sẽ chỉ chứa dữ liệu đồng bộ. Những người khác có kinh nghiệm để chia sẻ?


2
Có hai kho lưu trữ riêng biệt cho một dự án có vẻ như không phải là ý tưởng hay - bạn không thể thực hiện khôi phục sạch hoặc làm việc với các chi nhánh, vì sau đó bạn sẽ cần phải thao tác hai kho lưu trữ đồng thời (ví dụ: chi nhánh khác yêu cầu một số tùy chọn cấu hình mới và khi bạn chuyển sang chi nhánh mới mà không chuyển đổi trong kho cấu hình, mọi thứ sẽ phá vỡ theo những cách lạ).
Rogach

2
@Rogach Tôi lấy quan điểm của bạn. Có những lý do hợp lệ để giữ một số cấu hình với mã, nhưng như bạn nói trong câu hỏi của mình, những thứ nhạy cảm cần phải đi nơi khác. Vì vậy, hai kho lưu trữ dường như không thể tránh khỏi. Ngoài ra, tôi đã không đề cập rằng các máy chủ ứng dụng thường giúp đỡ ở đây. Nguồn dữ liệu và biến JNDI có thể được quản trị viên thiết lập và sẽ không được công khai.
kiwiron

Một cửa hàng thứ hai có ý nghĩa. Có thể có các loại dữ liệu khác, cũng được bảo mật, có thể được lưu trữ cùng với cấu hình (ví dụ: dữ liệu sản xuất đang được phân tích để khắc phục sự cố của khách hàng).
Sói

1
@Rogach Họ dường như thu hút rất nhiều sự ghét bỏ, nhưng các mô đun con git sẽ xử lý việc này tốt, tôi nghĩ - nếu cái chính được thiết lập đúng, và repo truy cập bị hạn chế chỉ có thể sống bên trong nó.
SeldomNeedy

9

Khi xem xét các vấn đề và giải pháp khả thi, nó giúp tôi sử dụng một phương pháp phổ biến bởi Jeff Atwood : Nếu Chúa tạo ra một cách lưu trữ thông tin cấu hình nhạy cảm, anh ấy sẽ làm thế nào?

Chà, anh ta sẽ biết ai cần thông tin cấu hình và chỉ cung cấp cho những người đó, và thông tin sẽ không bao giờ có thể được truy cập bởi bất kỳ ai khác.

Phần đầu tiên cần được quan tâm: hệ thống kiểm soát nguồn của bạn sẽ xác thực người dùng. Và cách tiếp cận này cũng được đưa ra có hiệu lực theo # 10 trong 10 Điều răn về kiểm soát nguồn của Troy Hunt , "sự phụ thuộc cần phải được kiểm soát nguồn".

Nhưng làm thế nào để giữ an toàn nếu nó bị rò rỉ? Vâng, nó không cần phải được lưu trữ ở đó trong văn bản đơn giản! Sử dụng mã hóa. Trong .NET, có các bước bạn có thể thực hiện để mã hóa dữ liệu chuỗi kết nối trong tệp cấu hình của mình . Bạn sẽ phải tìm các phương pháp tương đương để làm như vậy với công nghệ lựa chọn cụ thể của bạn.


3
Chỉ muốn làm rõ - cấu hình mã hóa sẽ giúp như thế nào? Theo tôi hiểu, bạn sẽ được yêu cầu chia sẻ cùng một mật khẩu giải mã giữa tất cả các nhà phát triển và điều đó nghe có vẻ như đang kêu gọi sự cố.
Rogach

Nếu ai đó bên ngoài công ty của bạn có quyền truy cập vào kho lưu trữ của bạn, mật khẩu của bạn sẽ bị xáo trộn. Nếu ai đó sao chép các tệp từ một dự án vào ổ USB và để nó ở đâu đó, điều tương tự. Nó sẽ là công việc nhiều hơn để duy trì, tất nhiên. An ninh hơn thường đi kèm với giá của sự thuận tiện. Giải pháp này hơi khó sử dụng, tôi sẽ cung cấp cho bạn điều đó. Tôi đang mở một cách tốt hơn để giải quyết câu hỏi của OP!
jporcenaluk

5

Nhiều người chỉ trích việc lưu trữ cấu hình trong các tệp thông thường cùng với mã nguồn của bạn nhưng theo kinh nghiệm của tôi, đây thực sự là một giải pháp khá tốt:

  • Đơn giản để thực hiện trong bất kỳ ngôn ngữ. Trong nhiều trường hợp, bạn nhận được hỗ trợ cho các tệp cấu hình phức tạp. Ví dụ, trong trường hợp Java với Spring Boot, bạn nhận được hỗ trợ YAML có thể biểu thị bất kỳ cấu trúc giống như cây nào và thật dễ dàng để có các tệp cấu hình riêng biệt cho các môi trường khác nhau cũng như cấu hình cơ sở mà các tệp cụ thể theo môi trường có thể kế thừa.
  • Cấu hình là cần thiết để chạy phần mềm của bạn và các thay đổi về mã thường yêu cầu cài đặt / sửa đổi cấu hình để thêm / sửa đổi, do đó, việc giữ cấu hình và mã cùng nhau là điều tự nhiên.
  • Lưu cấu hình với nguồn cung cấp cho bạn tất cả các lợi ích của kiểm soát nguồn, như biết ai đã sửa đổi cài đặt nào và khi nào hoặc có thể kiểm tra cấu hình trong quá trình xem xét mã thông thường.
  • Trừ khi bạn làm việc cho CIA, đối số bảo mật dường như quá mức đối với tôi. Vì vậy, mật khẩu cơ sở dữ liệu của bạn được lưu trữ trong một tệp trên máy nơi ứng dụng của bạn chạy. Chà, nếu ai đó có quyền truy cập vào máy bằng ứng dụng của bạn, có lẽ bạn đã gặp rất nhiều rắc rối - ví dụ như họ có thể gỡ ứng dụng của bạn xuống và khởi động ứng dụng của chính họ ở cùng một cổng. Trong trường hợp như vậy, việc truy cập vào mật khẩu DB có thể không phải là vấn đề lớn. Trừ khi tất cả các kết nối của bạn được mã hóa hoàn toàn, có quyền truy cập vào máy của bạn, họ vẫn có thể đánh hơi được nhiều dữ liệu thú vị từ các giao diện mạng.
  • Bạn có thể sử dụng một công cụ như Hiera để có tệp cấu hình văn bản nhưng không lưu trữ mật khẩu hoặc dữ liệu nhạy cảm khác bên trong nó.

Vì vậy, trong nhiều trường hợp, cấu hình văn bản được lưu trữ trong kiểm soát nguồn cùng với mã là một khởi đầu tốt.

Nếu bạn đang ở trong các hệ thống phân tán hoặc muốn có thể trao đổi nóng cấu hình của mình mà không cần triển khai lại các ứng dụng của mình, bạn có thể tìm thấy giải pháp dựa trên máy chủ cấu hình tốt hơn. Spring Cloud có hỗ trợ cho các cơ chế như vậy và các cấu hình phục vụ phụ trợ có thể là kho lưu trữ git hoặc Eureka . Bạn cũng có thể tự cuộn bằng cách sử dụng Zookeeper . Bất kỳ cách tiếp cận nào trong số này sẽ giúp quản lý cấu hình nhất quán trên nhiều máy chủ dễ dàng hơn để cập nhật cấu hình mà không phải xây dựng lại và triển khai lại phần mềm của bạn. Điều này có chi phí tất nhiên, đó là tìm hiểu máy chủ cấu hình và cách sử dụng nó từ các ứng dụng của bạn cũng như một hệ thống khác để triển khai và bảo trì.


Nhưng mã thay đổi thành một người không sở hữu bí mật trong các tệp cấu hình, sẽ có một mớ hỗn độn thực sự.
Tim Ludwinski

@TimLudwinski Khóa / bí mật thuộc về công ty, không phải nhà phát triển riêng lẻ, vì vậy chúng nên được duy trì theo cách mà chúng không bị mất nếu có bất kỳ cá nhân nào rời khỏi. Chúng có thể là các vấn đề và được duy trì bởi quản trị viên / nhóm bảo mật chẳng hạn, do đó có một sổ đăng ký trung tâm.
Michał Kosmulski

5

Chúng tôi đang chiến đấu với cùng một vấn đề nơi tôi làm việc. Ngay bây giờ tất cả các cấu hình của chúng tôi đều dựa trên tệp và nguồn được kiểm soát với các ứng dụng riêng lẻ sử dụng chúng. Điều này dẫn đến sự trùng lặp và các nhà phát triển có quyền truy cập vào mật khẩu sản xuất / qa thay vì chỉ phát triển.

Điều đó nói rằng tôi nghĩ rằng chúng tôi đã đưa ra một giải pháp tốt trong tương lai. Chúng tôi đang chuyển các tập tin cấu hình của chúng tôi sang một repo git riêng (được dán nhãn repo cấu hình). Sau đó, chúng tôi đã thiết lập một máy chủ spring-cloud-config (java) để phục vụ các tệp từ repo cấu hình dựa trên các cấu hình được truyền cho nó. Điều này rất tốt cho các ứng dụng Java có thể sử dụng máy khách và tải xuống chúng khi khởi động. Đối với các ứng dụng PHP / không phải java của chúng tôi, chúng tôi sẽ kéo tệp xuống trực tiếp. (Không lý tưởng). Trong tương lai, chúng tôi có thể viết một cái gì đó cho phép ứng dụng PHP tự tải xuống các cấu hình và lưu trữ chúng ở đâu đó, nhưng đó không phải là ưu tiên cao cho lần chạy đầu tiên. Tôi nghĩ giải pháp này là cấu hình như một dịch vụ không vi phạm rõ ràng các đề xuất ứng dụng 12 yếu tố.

Tôi tin rằng người quản lý vườn thú có thể được sử dụng cho cùng một điều (tôi đã thấy một thiết lập với kubernetes + người quản lý vườn thú) vì vậy tôi không chắc tại sao câu trả lời đó lại có -1 ở trên.

Liên kết:

https://spring.io/guides/gs/centralized-configuration/

https://cloud.spring.io/spring-cloud-config/


3

Thay vì lưu trữ toàn bộ cấu hình trong một tệp, hãy lưu trữ nó trong một số tệp.

  • Có một thư mục cấu hình . Tất cả các tệp ở đó được hiểu là các tệp cấu hình, ngoại trừ có thể README*.
  • Tất cả các tên tệp được sắp xếp theo thứ tự abc và các tệp được tải theo thứ tự đó. Đây là lý do tại sao các tệp trong các trường hợp như vậy thường bắt đầu bằng một hoặc hai chữ số : 01-logging.json. 02-database.jsonv.v.
  • Dữ liệu từ tất cả các tệp được tải vào cùng một cấu trúc cấu hình có sẵn cho ứng dụng. Đây là cách một số tệp có thể bổ sung cho các cài đặt của nhau và thậm chí ghi đè lên chúng theo cách có thể dự đoán được.
  • Chỉ lưu trữ trong VCS các tệp cấu hình có giá trị an toàn để xem hoặc giá trị mặc định. Thêm các tệp cấu hình với các bí mật trong quá trình triển khai hoặc tốt hơn là sử dụng dịch vụ lưu trữ bí mật đã được xác thực.

Trên hộp Linux gần nhất của bạn, hãy xem /etc/sudoers.dhoặc /etc/nginx/conf.d. Nó cho thấy mô hình tương tự.

Quản lý bí mật là một con thú khác nhau. Bạn có thể quản lý chúng như một bước thủ công trong khi bạn còn nhỏ. Bạn có thể sử dụng những thứ như Zookeeper. Bạn thậm chí có thể kiểm tra các bí mật vào một VCS ở dạng được mã hóa và giải mã chúng như một bước triển khai. Một số tùy chọn khác tồn tại.

(Ngoài ra, một ý kiến: JSON không phải là một định dạng tệp cấu hình tốt, bởi vì nó không cho phép các bình luận; các bình luận rất quan trọng. Các định dạng TOML, YAML và thậm chí INI tốt hơn trong sử dụng thực tế.)


2

Tôi nghĩ rằng các tùy chọn của bạn được xác định phần nào bởi HĐH mà bạn đang triển khai

Tôi sẽ đề nghị, có đặt các giá trị trong kiểm soát nguồn. NHƯNG chỉ các phiên bản 'dev'. Bạn muốn mã nguồn của bạn biên dịch VÀ làm việc! không bao gồm các bước bí mật thêm

Quá trình xây dựng và triển khai của bạn sau đó sẽ trao đổi các giá trị này trên mỗi môi trường trong quá trình triển khai. (bạch tuộc có loại mô hình này)


0

Người quản lý vườn thú Apache cung cấp các tùy chọn tuyệt vời để lưu trữ các cấu hình ứng dụng cho các hệ thống phân tán. Những thay đổi được thực hiện tại người quản lý vườn thú có thể được nắm bắt và xử lý bằng cách có người quản lý hoặc người lắng nghe vườn thú ở cuối ứng dụng.


6
Các tùy chọn là gì? làm thế nào nó hoạt động? Nơi nào nó lưu trữ chúng? Là một ưu tiên hơn một? Những lợi thế và bất lợi khác nhau của mỗi lựa chọn là gì? Làm thế nào để điều này tương tác trên các hệ điều hành khác nhau?

3
@Gangz - Tôi sẽ quan tâm đến một câu trả lời chi tiết hơn, xin vui lòng đừng nản lòng với các downvote, và cải thiện câu trả lời của bạn để nó có thể giúp ích.
Jay Elston
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.