Thứ năm, 01/12/2016 | 00:00 GMT+7

Cách quản lý môi trường nhiều tầng với Ansible

Ansible là một hệ thống quản lý cấu hình mạnh mẽ được sử dụng để cài đặt và quản lý cơ sở hạ tầng và ứng dụng trong các môi trường khác nhau. Mặc dù Ansible cung cấp cú pháp dễ đọc, quy trình làm việc linh hoạt và công cụ mạnh mẽ, nhưng việc quản lý số lượng lớn server lưu trữ có thể khó khăn khi chúng thay đổi theo môi trường triển khai và chức năng.

Trong hướng dẫn này, ta sẽ thảo luận về một số chiến lược sử dụng Ansible để làm việc với các môi trường triển khai nhiều tầng. Thông thường, các yêu cầu cho các giai đoạn khác nhau sẽ dẫn đến số lượng và cấu hình của các thành phần khác nhau. Ví dụ: các yêu cầu bộ nhớ cho server phát triển có thể khác với các yêu cầu cho dàn dựng và production và điều quan trọng là phải kiểm soát rõ ràng cách các biến đại diện cho các yêu cầu đó được ưu tiên. Trong bài viết này, ta sẽ thảo luận một số cách mà những khác biệt này có thể được trừu tượng hóa và một số cấu trúc mà Ansible cung cấp để khuyến khích tái sử dụng cấu hình.

Các chiến lược chưa hoàn chỉnh để quản lý môi trường đa tầng với Ansible

Mặc dù có một số cách mà bạn có thể quản lý môi trường bên trong Ansible, nhưng bản thân Ansible không đưa ra một giải pháp phù hợp. Thay vào đó, nó cung cấp nhiều cấu trúc được dùng để quản lý môi trường và cho phép user lựa chọn.

Cách tiếp cận mà ta sẽ trình bày trong hướng dẫn này dựa trên các biến group Ansible và nhiều khoảng không quảng cáo . Tuy nhiên, có một số chiến lược khác đáng được xem xét. Ta sẽ khám phá một số ý tưởng dưới đây và tại sao chúng có thể gây ra các vấn đề khi thực hiện trong môi trường phức tạp.

Nếu bạn muốn bắt đầu với chiến lược được đề xuất của Ansible, hãy chuyển sang phần sử dụng group Ansible và nhiều khoảng không quảng cáo .

Chỉ dựa vào các biến group

Thoạt nhìn, có vẻ như các biến group cung cấp tất cả sự tách biệt giữa các môi trường mà Ansible yêu cầu. Bạn có thể chỉ định một số server nhất định thuộc về môi trường phát triển của bạn và những server khác có thể được chỉ định cho các khu vực production và dàn dựng. Ansible giúp bạn dễ dàng tạo group và gán biến cho chúng.

Tuy nhiên, sự giao nhau giữa các group lại gây ra nhiều vấn đề nghiêm trọng cho hệ thống này. Group thường được sử dụng để phân loại nhiều thứ nguyên. Ví dụ:

  • môi trường triển khai (local, dev, stage, prod, v.v.)
  • chức năng server ( web server , server database , v.v.)
  • khu vực trung tâm dữ liệu (NYC, SFO, v.v.)

Trong những trường hợp này, server thường sẽ nằm trong một group cho mỗi danh mục. Ví dụ: server lưu trữ có thể là web server (chức năng) trên sân khấu (môi trường triển khai) ở NYC (vùng trung tâm dữ liệu).

Nếu cùng một biến được đặt bởi nhiều group cho một server lưu trữ, Ansible không có cách nào chỉ định rõ ràng mức độ ưu tiên. Bạn có thể thích các biến được liên kết với môi trường triển khai overrides các giá trị khác, nhưng Ansible không cung cấp cách xác định điều này.

Thay vào đó, Ansible sử dụng giá trị được tải cuối cùng . Vì Ansible đánh giá các group theo thứ tự bảng chữ cái, nên biến được liên kết với bất kỳ tên group nào đứng cuối cùng trong thứ tự từ điển sẽ thắng. Đây là hành vi có thể dự đoán được, nhưng việc quản lý rõ ràng bảng chữ cái tên group thì ít lý tưởng hơn từ góc độ quản trị.

Sử dụng Group Con để Cài đặt Hệ thống Phân cấp

Ansible cho phép bạn chỉ định group cho các group khác bằng cú pháp [ groupname :children] trong repository .Điều này cung cấp cho bạn khả năng đặt tên cho một số group thành viên của các group khác. Các group con có khả năng overrides các biến do group mẹ đặt.

Thông thường, điều này được sử dụng để phân loại tự nhiên. Ví dụ, ta có thể có một group được gọi là environments bao gồm các group dev , stage , prod . Điều này có nghĩa ta có thể cài đặt các biến trong environment group và overrides lên chúng trong dev group . Bạn tương tự có thể có một group phụ huynh gọi là functions có chứa các group web , database , và loadbalancer .

Cách sử dụng này không giải quyết được vấn đề giao group vì các group con chỉ overrides cha mẹ của chúng. Các group con có thể overrides các biến bên trong tổ chức mẹ, nhưng tổ chức trên đã không cài đặt bất kỳ mối quan hệ nào giữa các danh mục group , như environmentsfunctions . Mức độ ưu tiên thay đổi giữa hai danh mục vẫn chưa được xác định.

thể khai thác hệ thống này bằng cách cài đặt thành viên group phi tự nhiên. Ví dụ: nếu bạn muốn cài đặt mức độ ưu tiên sau, từ mức độ ưu tiên cao nhất đến mức độ ưu tiên thấp nhất:

  • môi trương phat triển
  • khu vực
  • chức năng

Bạn có thể chỉ định tư cách thành viên group giống như sau:

Hàng tồn kho mẫu
. . . [function:children] web database loadbalancer region  [region:children] nyc sfo environments  [environments:children] dev stage prod 

Ta đã cài đặt một hệ thống phân cấp ở đây cho phép các biến vùng overrides các biến chức năng vì group region là con của group function . Tương tự như vậy, các biến được đặt trong các group environments có thể overrides lên bất kỳ biến nào khác. Điều này nghĩa là nếu ta đặt cùng một biến thành một giá trị khác trong group dev , nycweb , thì một server thuộc mỗi group này sẽ sử dụng biến từ dev .

Điều này đạt được kết quả mong muốn và cũng có thể dự đoán được. Tuy nhiên, nó không trực quan và nó làm xáo trộn sự phân biệt giữa những đứa trẻ thực sự và những đứa trẻ cần thiết để cài đặt hệ thống phân cấp. Ansible được thiết kế để cấu hình của nó rõ ràng và dễ theo dõi ngay cả đối với user mới. Loại công việc xung quanh thỏa hiệp mục tiêu đó.

Sử dụng cấu trúc an toàn cho phép thứ tự tải rõ ràng

Có một số cấu trúc bên trong Ansible cho phép sắp xếp tải thay đổi rõ ràng, cụ thể là vars_filesinclude_vars . Chúng được dùng trong các lượt chơi Ansible để tải rõ ràng các biến bổ sung theo thứ tự được xác định trong file . Chỉ thị vars_files hợp lệ trong ngữ cảnh của một trò chơi, trong khi module include_vars được dùng trong các việc .

Ý tưởng chung là chỉ đặt các biến nhận dạng cơ bản trong group_vars và sau đó tận dụng các biến này để tải các file biến chính xác với phần còn lại của các biến mong muốn.

Ví dụ: một số file group_vars có thể trông giống như sau:

group_vars / dev
--- env: dev 
group_vars / stage
--- env: stage 
group_vars / web
--- function: web 
group_vars / database
--- function: database 

Sau đó, ta sẽ có một file vars riêng biệt xác định các biến quan trọng cho mỗi group . Chúng thường được giữ trong một folder vars riêng biệt để rõ ràng. Không giống như các file group_vars , khi xử lý include_vars , các file phải bao gồm phần mở rộng file .yml .

Hãy giả sử rằng ta cần đặt biến server_memory_size thành một giá trị khác trong mỗi file vars . Server phát triển của bạn có thể sẽ nhỏ hơn server production của bạn. Hơn nữa, web server và server database của bạn có thể có các yêu cầu bộ nhớ khác nhau:

vars / dev.yml
--- server_memory_size: 512mb 
vars / prod.yml
--- server_memory_size: 4gb 
vars / web.yml
--- server_memory_size: 1gb 
vars / database.yml
--- server_memory_size: 2gb 

Sau đó, ta có thể tạo một playbook tải file vars chính xác một cách rõ ràng dựa trên các giá trị được gán cho server từ các file group_vars . Thứ tự của các file được tải sẽ xác định mức độ ưu tiên, với giá trị cuối cùng sẽ chiến thắng.

Với vars_files , một lần chơi mẫu sẽ giống như sau:

example_play.yml
--- - name: variable precedence test   hosts: all   vars_files:     - "vars/{{ env }}.yml"     - "vars/{{ function }}.yml"   tasks:     - debug: var=server_memory_size 

Vì các group chức năng được tải sau cùng, giá trị server_memory_size sẽ được lấy từ các var/web.ymlvar/database.yml :

  • ansible-playbook -i inventory example_play.yml
Output
. . . TASK [debug] ******************************************************************* ok: [host1] => { "server_memory_size": "1gb" # value from vars/web.yml } ok: [host2] => { "server_memory_size": "1gb" # value from vars/web.yml } ok: [host3] => { "server_memory_size": "2gb" # value from vars/database.yml } ok: [host4] => { "server_memory_size": "2gb" # value from vars/database.yml } . . .

Nếu ta chuyển đổi thứ tự của các file sẽ được tải, ta có thể làm cho các biến môi trường triển khai có mức độ ưu tiên cao hơn:

example_play.yml
--- - name: variable precedence test   hosts: all   vars_files:     - "vars/{{ function }}.yml"     - "vars/{{ env }}.yml"   tasks:     - debug: var=server_memory_size 

Chạy lại playbook sẽ hiển thị các giá trị đang được áp dụng từ các file môi trường triển khai:

  • ansible-playbook -i inventory example_play.yml
Output
. . . TASK [debug] ******************************************************************* ok: [host1] => { "server_memory_size": "512mb" # value from vars/dev.yml } ok: [host2] => { "server_memory_size": "4gb" # value from vars/prod.yml } ok: [host3] => { "server_memory_size": "512mb" # value from vars/dev.yml } ok: [host4] => { "server_memory_size": "4gb" # value from vars/prod.yml } . . .

Playbook tương đương sử dụng include_vars , hoạt động như một tác vụ, sẽ giống như sau:

--- - name: variable precedence test   hosts: localhost   tasks:     - include_vars:         file: "{{ item }}"       with_items:         - "vars/{{ function }}.yml"         - "vars/{{ env }}.yml"     - debug: var=server_memory_size 

Đây là một lĩnh vực mà Ansible cho phép đặt hàng rõ ràng, điều này có thể rất hữu ích. Tuy nhiên, cũng như các ví dụ trước, có một số nhược điểm đáng kể.

Trước hết, việc sử dụng vars_filesinclude_vars yêu cầu bạn đặt các biến được liên kết chặt chẽ với các group ở một vị trí khác. Vị trí group_vars trở thành sơ khai cho các biến thực tế nằm trong folder vars . Điều này làm tăng thêm sự phức tạp và giảm độ rõ ràng. User phải khớp đúng các file biến với server , đây là điều mà Ansible thực hiện tự động khi sử dụng group_vars .

Quan trọng hơn, việc dựa vào những kỹ thuật này khiến chúng trở nên bắt buộc. Mỗi playbook sẽ yêu cầu một phần tải rõ ràng các file biến chính xác theo đúng thứ tự. Playbook không có điều này sẽ không thể sử dụng các biến được liên kết. Hơn nữa, việc chạy lệnh ansible cho các việc đặc biệt sẽ gần như hoàn toàn không thể đối với bất kỳ thứ gì dựa vào các biến.

Lúc này, ta đã xem xét một số chiến lược để quản lý môi trường nhiều tầng và thảo luận về lý do tại sao chúng có thể không phải là một giải pháp hoàn chỉnh. Tuy nhiên, dự án Ansible đưa ra một số gợi ý về cách tốt nhất để tóm tắt cơ sở hạ tầng của bạn trên các môi trường.

Cách tiếp cận được khuyến khích là làm việc với môi trường nhiều tầng bằng cách tách biệt hoàn toàn từng môi trường hoạt động. Thay vì duy trì tất cả các server của bạn trong một file khoảng không quảng cáo, một khoảng không quảng cáo được duy trì cho từng môi trường riêng lẻ của bạn. Các folder group_vars riêng biệt cũng được duy trì.

Cấu trúc folder cơ bản sẽ giống như sau:

. ├── ansible.cfg ├── environments/         # Parent directory for our environment-specific directories │   │ │   ├── dev/              # Contains all files specific to the dev environment │   │   ├── group_vars/   # dev specific group_vars files │   │   │   ├── all │   │   │   ├── db │   │   │   └── web │   │   └── hosts         # Contains only the hosts in the dev environment │   │ │   ├── prod/             # Contains all files specific to the prod environment │   │   ├── group_vars/   # prod specific group_vars files │   │   │   ├── all │   │   │   ├── db │   │   │   └── web │   │   └── hosts         # Contains only the hosts in the prod environment │   │ │   └── stage/            # Contains all files specific to the stage environment │       ├── group_vars/   # stage specific group_vars files │       │   ├── all │       │   ├── db │       │   └── web │       └── hosts         # Contains only the hosts in the stage environment │ ├── playbook.yml │ └── . . . 

Như bạn thấy , mỗi môi trường đều khác biệt và được ngăn cách. Các folder môi trường chứa một file kiểm kê ( hosts được đặt tên tùy ý) và một folder group_vars riêng biệt.

Có một số sự trùng lặp rõ ràng trong cây folder . Có các file webdb cho từng môi trường riêng lẻ. Trong trường hợp này, sự trùng lặp là mong muốn. Thay đổi biến có thể được triển khai trên các môi trường bằng cách sửa đổi đầu tiên các biến trong một môi trường và chuyển chúng sang môi trường tiếp theo sau khi thử nghiệm, giống như bạn làm với các thay đổi về mã hoặc cấu hình. Các biến group_vars theo dõi các giá trị mặc định hiện tại cho mỗi môi trường.

Một hạn chế là không thể chọn tất cả các server theo chức năng trên các môi trường. May mắn là điều này rơi vào cùng một loại với vấn đề trùng lặp biến ở trên. Mặc dù việc chọn tất cả các web server của bạn cho một nhiệm vụ đôi khi rất hữu ích, nhưng bạn hầu như luôn muốn áp dụng các thay đổi trên các môi trường của bạn cùng một lúc. Điều này giúp ngăn ngừa những sai sót ảnh hưởng đến môi trường production của bạn.

Đặt các biến môi trường chéo

Một điều không thể thực hiện được trong cài đặt được đề xuất là chia sẻ biến trên các môi trường. Có một số cách ta có thể triển khai chia sẻ biến môi trường chéo. Một trong những cách đơn giản nhất là tận dụng khả năng của Ansible để sử dụng folder thay cho file . Ta có thể thay thế all file trong mỗi folder group_vars bằng một folder all .

Bên trong folder , ta có thể đặt lại tất cả các biến theo môi trường cụ thể trong một file . Sau đó, ta có thể tạo một softlink đến một vị trí file có chứa các biến môi trường chéo. Cả hai điều này sẽ được áp dụng cho tất cả các server trong môi trường.

Bắt đầu bằng cách tạo file biến môi trường chéo ở đâu đó trong hệ thống phân cấp. Trong ví dụ này, ta sẽ đặt nó trong folder environments . Đặt tất cả các biến môi trường chéo trong file đó:

  • cd environments
  • touch 000_cross_env_vars

Tiếp theo, di chuyển vào một trong folder group_vars , đổi tên all file và tạo folder all . Di chuyển file đã đổi tên vào folder mới:

  • cd dev/group_vars
  • mv all env_specific
  • mkdir all
  • mv env_specific all/

Tiếp theo, bạn có thể tạo một softlink đến file biến môi trường chéo:

  • cd all/
  • ln -s ../../../000_cross_env_vars .

Khi bạn đã hoàn thành các bước trên cho từng môi trường của bạn , cấu trúc folder của bạn sẽ trông giống như sau:

. ├── ansible.cfg ├── environments/ │   │ │   ├── 000_cross_env_vars │   │ │   ├── dev/ │   │   ├── group_vars/ │   │   │   ├── all/ │       │   │   ├── 000_cross_env_vars -> ../../../000_cross_env_vars │   │   │   │   └── env_specific │   │   │   ├── db │   │   │   └── web │   │   └── hosts │   │ │   ├── prod/ │   │   ├── group_vars/ │   │   │   ├── all/ │   │   │   │   ├── 000_cross_env_vars -> ../../../000_cross_env_vars │   │   │   │   └── env_specific │   │   │   ├── db │   │   │   └── web │   │   └── hosts │   │ │   └── stage/ │       ├── group_vars/ │       │   ├── all/ │       │   │   ├── 000_cross_env_vars -> ../../../000_cross_env_vars │       │   │   └── env_specific │       │   ├── db │       │   └── web │       └── hosts │ ├── playbook.yml │ └── . . . 

Các biến được đặt trong file 000_cross_env_vars sẽ có sẵn cho mỗi môi trường có mức độ ưu tiên thấp.

Đặt khoảng không quảng cáo môi trường mặc định

Có thể đặt file kiểm kê mặc định trong file ansible.cfg . Đây là một ý tưởng hay vì một vài lý do.

Đầu tiên, nó cho phép bạn loại bỏ các cờ kiểm kê rõ ràng thành sách có thể ansible và có thể ansible-playbook . Vì vậy, thay vì gõ:

  • ansible -i environments/dev -m ping

Bạn có thể truy cập khoảng không quảng cáo mặc định bằng lệnh :

  • ansible -m ping

Thứ hai, đặt khoảng không quảng cáo mặc định giúp ngăn chặn những thay đổi không mong muốn vô tình ảnh hưởng đến môi trường production hoặc dàn dựng. Bằng cách mặc định môi trường phát triển của bạn, cơ sở hạ tầng ít quan trọng nhất bị ảnh hưởng bởi các thay đổi. Khi đó, thúc đẩy các thay đổi đối với môi trường mới là một hành động rõ ràng yêu cầu cờ -i .

Để đặt khoảng không quảng cáo mặc định, hãy mở file ansible.cfg của bạn. Điều này có thể nằm trong folder root của dự án của bạn hoặc tại /etc/ansible/ansible.cfg tùy thuộc vào cấu hình của bạn.

Lưu ý: Ví dụ dưới đây minh họa việc chỉnh sửa file ansible.cfg trong folder dự án. Nếu bạn đang sử dụng file /etc/ansibile/ansible.cfg cho các thay đổi của bạn , hãy sửa đổi đường dẫn chỉnh sửa bên dưới. Khi sử dụng /etc/ansible/ansible.cfg , nếu khoảng không quảng cáo của bạn được duy trì bên ngoài folder /etc/ansible , hãy đảm bảo sử dụng đường dẫn tuyệt đối thay vì đường dẫn tương đối khi đặt giá trị inventory .

  • nano ansible.cfg

Như đã đề cập ở trên, bạn nên đặt môi trường phát triển của bạn làm khoảng không quảng cáo mặc định. Lưu ý cách ta có thể chọn toàn bộ folder môi trường thay vì file server mà nó chứa:

[defaults] inventory = ./environments/dev 

Đến đây bạn có thể sử dụng khoảng không quảng cáo mặc định của bạn mà không có tùy chọn -i . Khoảng không quảng cáo không mặc định sẽ vẫn yêu cầu sử dụng -i , giúp bảo vệ chúng khỏi những thay đổi ngẫu nhiên.

Kết luận

Trong bài viết này, ta đã khám phá tính linh hoạt mà Ansible cung cấp để quản lý server của bạn trên nhiều môi trường. Điều này cho phép user áp dụng nhiều chiến lược khác nhau để xử lý mức độ ưu tiên thay đổi khi server lưu trữ là thành viên của nhiều group , nhưng sự mơ hồ và thiếu định hướng chính thức có thể là một thách thức. Như với bất kỳ công nghệ nào, sự phù hợp nhất cho tổ chức của bạn sẽ phụ thuộc vào các trường hợp sử dụng và mức độ phức tạp của các yêu cầu của bạn. Cách tốt nhất để tìm một chiến lược phù hợp với nhu cầu của bạn là thử nghiệm. Chia sẻ trường hợp sử dụng và cách tiếp cận của bạn trong các comment bên dưới.


Tags:

Các tin liên quan