Thứ sáu, 17/05/2019 | 00:00 GMT+7

Quản lý cấu hình 101: Viết các thao tác rối

Tóm lại, quản lý cấu hình server (còn được gọi phổ biến là Tự động hóa CNTT) là một giải pháp để biến quản trị cơ sở hạ tầng của bạn thành một cơ sở mã, mô tả tất cả các quy trình cần thiết để triển khai server trong một tập hợp các tập lệnh cấp phép có thể được tạo version và dễ dàng sử dụng lại. Nó có thể cải thiện đáng kể tính toàn vẹn của bất kỳ cơ sở hạ tầng server nào theo thời gian.

Trong hướng dẫn trước , ta đã nói về những lợi ích chính của việc triển khai chiến lược quản lý cấu hình cho cơ sở hạ tầng server của bạn, cách hoạt động của các công cụ quản lý cấu hình và những điểm chung của những công cụ này.

Phần này của loạt bài sẽ hướng dẫn bạn quá trình tự động hóa việc cung cấp server bằng Puppet, một công cụ quản lý cấu hình phổ biến có khả năng quản lý cơ sở hạ tầng phức tạp một cách minh bạch, sử dụng server chính để sắp xếp cấu hình của các node . Ta sẽ tập trung vào thuật ngữ ngôn ngữ, cú pháp và các tính năng cần thiết để tạo một ví dụ đơn giản nhằm tự động hóa hoàn toàn việc triển khai web server Ubuntu 18.04 bằng Apache.

Đây là danh sách các bước ta cần tự động hóa để đạt được mục tiêu của bạn :

  1. Cập nhật bộ nhớ cache apt
  2. Cài đặt Apache
  3. Tạo một folder root tài liệu tùy chỉnh
  4. Đặt index.html vào root tài liệu tùy chỉnh
  5. Áp dụng một mẫu để cài đặt server ảo tùy chỉnh của ta
  6. Khởi động lại Apache

Ta sẽ bắt đầu bằng cách xem xét thuật ngữ được Puppet sử dụng, sau đó là tổng quan về các tính năng ngôn ngữ chính được dùng để viết các bản kê khai. Ở cuối hướng dẫn này, ta sẽ chia sẻ ví dụ hoàn chỉnh để bạn có thể tự mình thử.

Lưu ý: hướng dẫn này nhằm giới thiệu cho bạn ngôn ngữ Puppet và cách viết file kê khai để tự động hóa việc cấp phép server của bạn. Để có cái nhìn giới thiệu hơn về Puppet, bao gồm các bước cần thiết để cài đặt và bắt đầu với công cụ này, vui lòng tham khảo tài liệu chính thức của Puppet .

Bắt đầu

Trước khi ta có thể chuyển sang một cái nhìn thực tế hơn về Puppet, điều quan trọng là ta phải làm quen với các thuật ngữ và khái niệm quan trọng được giới thiệu bởi công cụ này.

Điều khoản puppet

  • Puppet Master : server chính điều khiển cấu hình trên các node
  • Nút tác nhân puppet : một nút được điều khiển bởi Bậc thầy puppet
  • Tệp kê khai : một file chứa một tập hợp các hướng dẫn được thực thi
  • Resource : một phần mã khai báo một phần tử của hệ thống và trạng thái của nó sẽ được thay đổi như thế nào. Ví dụ, để cài đặt một gói, ta cần xác định tài nguyên gói và đảm bảo trạng thái của nó được đặt thành “đã cài đặt”
  • Mô-đun : tập hợp các file kê khai và các file liên quan khác được tổ chức theo cách xác định trước để tạo điều kiện chia sẻ và sử dụng lại các phần của cấp phép
  • Lớp : giống như với các ngôn ngữ lập trình thông thường, các lớp được sử dụng trong Puppet để tổ chức việc cấp phép tốt hơn và giúp sử dụng lại các phần của mã dễ dàng hơn
  • Sự kiện : các biến toàn cục chứa thông tin về hệ thống, như network interface và hệ điều hành
  • Dịch vụ : được sử dụng để kích hoạt các thay đổi trạng thái dịch vụ, như khởi động lại hoặc dừng một dịch vụ

Cấp phép cho puppet được viết bằng DSL tùy chỉnh (ngôn ngữ dành riêng cho domain ) dựa trên Ruby.

Tài nguyên

Với Puppet, các nhiệm vụ hoặc các bước được xác định bằng cách khai báo tài nguyên . Tài nguyên có thể đại diện cho các gói, file , dịch vụ, user và lệnh. Chúng có thể có một trạng thái, điều này sẽ kích hoạt sự thay đổi hệ thống trong trường hợp trạng thái của tài nguyên đã khai báo khác với trạng thái hiện có trên hệ thống. Ví dụ: tài nguyên gói được đặt thành installed trong file kê khai của bạn sẽ kích hoạt cài đặt gói trên hệ thống nếu gói chưa được cài đặt trước đó.

Đây là tài nguyên gói trông như thế nào:

package { 'nginx':     ensure  => 'installed' } 

Bạn có thể thực hiện bất kỳ lệnh tùy ý bằng cách tuyên bố một exec tài nguyên, như sau:

exec { 'apt-get update':     command => '/usr/bin/apt-get update' } 

Lưu ý phần apt-get update trên dòng đầu tiên không phải là khai báo lệnh thực tế, mà là một định danh cho tài nguyên duy nhất này. Thông thường, ta cần tham chiếu các tài nguyên khác từ bên trong một tài nguyên và ta sử dụng định danh của chúng cho điều đó. Trong trường hợp này, số nhận dạng là apt-get update , nhưng nó có thể là bất kỳ chuỗi nào khác.

Sự phụ thuộc tài nguyên

Khi viết các file kê khai, điều quan trọng cần lưu ý là Puppet không đánh giá các tài nguyên theo thứ tự mà chúng được xác định. Đây là một nguồn nhầm lẫn phổ biến cho những người bắt đầu với Puppet. Các tài nguyên phải xác định rõ ràng dependencies giữa nhau, nếu không, không có gì đảm bảo tài nguyên nào sẽ được đánh giá và do đó được thực thi trước.

Ví dụ đơn giản, giả sử bạn muốn thực thi một lệnh, nhưng trước tiên bạn cần đảm bảo một phần phụ thuộc đã được cài đặt:

package { 'python-software-properties':     ensure => 'installed' }  exec { 'add-repository':     command => '/usr/bin/add-apt-repository ppa:ondrej/php5 -y'     require => Package['python-software-properties'] } 

Các require lựa chọn nhận như tham số một tham chiếu đến tài nguyên khác. Trong trường hợp này, ta đang đề cập đến tài nguyên Gói được xác định là python-software-properties .
Điều quan trọng cần lưu ý là trong khi ta sử dụng exec , package , v.v. để khai báo tài nguyên (với chữ thường), khi đề cập đến các tài nguyên đã xác định trước đó, ta sử dụng Exec , Package , v.v. (viết hoa).

Bây giờ, giả sử bạn cần đảm bảo một tác vụ được thực thi trước một tác vụ khác. Đối với trường hợp như thế này, ta có thể sử dụng tùy chọn before để thay thế:

package { 'curl':     ensure => 'installed'     before => Exec['install script'] }  exec { 'install script':     command => '/usr/bin/curl http://example.com/some-script.sh' 

Định dạng file kê khai

Manifests về cơ bản là một tập hợp các khai báo tài nguyên, sử dụng phần mở rộng .pp . Dưới đây, bạn có thể tìm thấy một ví dụ về một playbook đơn giản thực hiện hai tác vụ: cập nhật cache apt và cài đặt vim sau đó:

exec { 'apt-get update':     command => '/usr/bin/apt-get update' }  package { 'vim':     ensure => 'installed'     require => Exec['apt-get update'] } 

Trước khi kết thúc hướng dẫn này, ta sẽ xem một ví dụ thực tế hơn về file kê khai, được giải thích chi tiết. Phần tiếp theo sẽ cung cấp cho bạn tổng quan về các yếu tố và tính năng quan trọng nhất được dùng để viết các bản kê khai Puppet .

Viết Manifests

Làm việc với các biến

Các biến có thể được xác định tại bất kỳ điểm nào trong file kê khai. Các loại biến phổ biến nhất là chuỗi và mảng chuỗi, nhưng các loại khác cũng được hỗ trợ, chẳng hạn như boolean và băm.

Ví dụ dưới đây xác định một biến chuỗi sau này được sử dụng bên trong tài nguyên:

$package = "vim"  package { $package:    ensure => "installed" } 

Sử dụng vòng lặp

Vòng lặp thường được sử dụng để lặp lại một tác vụ sử dụng các giá trị đầu vào khác nhau. Ví dụ: thay vì tạo 10 tác vụ để cài đặt 10 gói khác nhau, bạn có thể tạo một tác vụ duy nhất và sử dụng vòng lặp để lặp lại tác vụ với tất cả các gói khác nhau mà bạn muốn cài đặt.

Cách đơn giản nhất để lặp lại một tác vụ với các giá trị khác nhau trong Puppet là sử dụng các mảng, như trong ví dụ dưới đây:

$packages = ['vim', 'git', 'curl']  package { $packages:    ensure => "installed" } 

Kể từ version 4, Puppet hỗ trợ các cách bổ sung để lặp qua các việc . Ví dụ dưới đây thực hiện tương tự như ví dụ trước, nhưng lần này sử dụng each trình lặp. Tùy chọn này mang lại cho bạn sự linh hoạt hơn trong việc lặp lại các định nghĩa tài nguyên:

$packages.each |String $package| {   package { $package:     ensure => "installed"   } } 

Sử dụng Điều kiện

Các điều kiện được dùng để tự động quyết định xem có nên thực thi một khối mã hay không, dựa trên một biến hoặc kết quả từ một lệnh, chẳng hạn.

Puppet hỗ trợ hầu hết các cấu trúc có điều kiện mà bạn có thể tìm thấy với các ngôn ngữ lập trình truyền thống, như if/else và các câu lệnh case . Ngoài ra, một số tài nguyên như exec sẽ hỗ trợ các thuộc tính hoạt động giống như điều kiện, nhưng chỉ chấp nhận kết quả lệnh như điều kiện.

Giả sử bạn muốn thực hiện một lệnh dựa trên một thực tế . Trong trường hợp này, khi bạn muốn kiểm tra giá trị của một biến, bạn cần sử dụng một trong các cấu trúc điều kiện được hỗ trợ, như if/else :

if $osfamily != 'Debian' {  warning('This manifest is not supported on this OS.') } else {  notify { 'Good to go!': } } 

Một tình huống phổ biến khác là khi bạn muốn điều kiện thực hiện một lệnh dựa trên kết quả từ một lệnh khác. Đối với những trường hợp như thế này, bạn có thể sử dụng onlyif hoặc unless , như trong ví dụ bên dưới. Lệnh này sẽ chỉ được thực thi khi kết quả từ /bin/which php thành công, tức là lệnh thoát với trạng thái 0 :

exec { "Test":  command => "/bin/echo PHP is installed here > /tmp/test.txt",  onlyif => "/bin/which php" } 

Tương tự, unless sẽ thực hiện lệnh mọi lúc, ngoại trừ khi lệnh dưới unless thoát thành công:

exec { "Test":  command => "/bin/echo PHP is NOT installed here > /tmp/test.txt",  unless => "/bin/which php" } 

Làm việc với các mẫu

Các mẫu thường được sử dụng để cài đặt các file cấu hình, cho phép sử dụng các biến và các tính năng khác nhằm mục đích làm cho các file này linh hoạt hơn và có thể tái sử dụng. Puppet hỗ trợ hai định dạng khác nhau cho các mẫu: Embedded Puppet (EPP) và Embedded Ruby (ERB). Tuy nhiên, định dạng EPP chỉ hoạt động với các version Puppet gần đây (bắt đầu từ version 4.0).

Dưới đây là một ví dụ về mẫu ERB để cài đặt server ảo Apache, sử dụng một biến để cài đặt root tài liệu cho server này:

<VirtualHost *:80>     ServerAdmin webmaster@localhost     DocumentRoot <%= @doc_root %>      <Directory <%= @doc_root %>>         AllowOverride All         Require all granted     </Directory> </VirtualHost> 

Để áp dụng mẫu, ta cần tạo một tài nguyên file hiển thị nội dung mẫu bằng phương thức template . Đây là cách bạn áp dụng mẫu này để thay thế server ảo Apache mặc định:

file { "/etc/apache2/sites-available/000-default.conf":     ensure => "present",     content => template("apache/vhost.erb")  }     

Puppet đưa ra một số giả định khi xử lý các file local , để thực thi tổ chức và mô đun. Trong trường hợp này, Puppet sẽ tìm kiếm file mẫu vhost.erb bên trong folder apache/templates , bên trong folder module của bạn.

Dịch vụ xác định và kích hoạt

Tài nguyên dịch vụ được sử dụng đảm bảo các dịch vụ được khởi tạo và kích hoạt. Chúng cũng được sử dụng để kích hoạt khởi động lại dịch vụ.

Hãy xem xét ví dụ sử dụng mẫu trước đây của ta , nơi ta cài đặt server ảo Apache. Nếu bạn cần đảm bảo Apache được khởi động lại sau khi thay đổi server ảo, trước tiên bạn cần tạo tài nguyên dịch vụ cho dịch vụ Apache. Đây là cách tài nguyên đó được định nghĩa trong Puppet:

service { 'apache2':     ensure => running,     enable => true } 

Bây giờ, khi xác định tài nguyên, bạn cần bao gồm tùy chọn notify để kích hoạt khởi động lại:

file { "/etc/apache2/sites-available/000-default.conf":     ensure => "present",     content => template("vhost.erb"),     notify => Service['apache2']  }  

Tệp kê khai mẫu

Bây giờ ta hãy xem một file kê khai sẽ tự động cài đặt web server Apache trong hệ thống Ubuntu 14.04, như được thảo luận trong phần giới thiệu của hướng dẫn này.

Bạn có thể tìm thấy ví dụ đầy đủ, bao gồm file mẫu để cài đặt Apache và file HTML được web server cung cấp trên Github . Thư mục này cũng chứa Vagrantfile cho phép bạn kiểm tra file kê khai trong một cài đặt đơn giản, sử dụng máy ảo do Vagrant quản lý.

Dưới đây, bạn có thể tìm thấy toàn bộ file kê khai:

default.pp
  • $doc_root = "/var/www/example"
  • exec { 'apt-get update':
  • command => '/usr/bin/apt-get update'
  • }
  • package { 'apache2':
  • ensure => "installed",
  • require => Exec['apt-get update']
  • }
  • file { $doc_root:
  • ensure => "directory",
  • owner => "www-data",
  • group => "www-data",
  • mode => 644
  • }
  • file { "$doc_root/index.html":
  • ensure => "present",
  • source => "puppet:///modules/main/index.html",
  • require => File[$doc_root]
  • }
  • file { "/etc/apache2/sites-available/000-default.conf":
  • ensure => "present",
  • content => template("main/vhost.erb"),
  • notify => Service['apache2'],
  • require => Package['apache2']
  • }
  • service { 'apache2':
  • ensure => running,
  • enable => true
  • }

Giải thích Tệp kê khai

dòng 1

Tệp kê khai bắt đầu với một định nghĩa biến, $doc_root . Biến này sau đó được sử dụng trong khai báo tài nguyên.

dòng 3-5

Tài nguyên exec này thực hiện một apt-get update lệnh.

dòng 7-10

Tài nguyên gói này cài đặt gói apache2 , xác định rằng tài nguyên apt-get update là một yêu cầu, nghĩa là nó sẽ chỉ được thực thi sau khi tài nguyên yêu cầu được đánh giá.

dòng 12-17

Ta sử dụng tài nguyên tệp ở đây để tạo một folder mới sẽ đóng role là folder root tài liệu của ta . Tài nguyên file được dùng để tạo folder và file , đồng thời nó cũng được sử dụng để áp dụng các mẫu và sao chép file local vào server từ xa. Tác vụ này có thể được thực thi tại bất kỳ thời điểm nào của quá trình cung cấp, vì vậy ta không cần đặt bất kỳ require nào ở đây.

dòng 19-23

Ta sử dụng một tài nguyên tệp khác ở đây, lần này để sao chép tệp index.html local của ta vào root tài liệu bên trong server . Ta sử dụng tham số source để cho Puppet biết nơi tìm file root . Danh pháp này dựa trên cách Puppet xử lý các file local ; nếu bạn đã xem qua kho lưu trữ ví dụ Github , bạn sẽ thấy cấu trúc folder nên được tạo như thế nào để Puppet tìm thấy tài nguyên này. Thư mục root của tài liệu cần được tạo trước khi thực thi tài nguyên này, đó là lý do tại sao ta bao gồm tùy chọn require tham chiếu đến tài nguyên trước đó.

dòng 25-30

Tài nguyên tệp mới được sử dụng để áp dụng mẫu Apache và thông báo cho dịch vụ khởi động lại. Đối với ví dụ này, việc cung cấp của ta được tổ chức trong một module được gọi là chính và đó là lý do tại sao nguồn mẫu là main / vhost.erb . Ta sử dụng một require tuyên bố đảm bảo tài nguyên mẫu chỉ được thực hiện sau khi gói apache2 được cài đặt, nếu không cấu trúc folder được sử dụng bởi Apache có thể không có mặt được nêu ra.

dòng 32-35

Cuối cùng, tài nguyên dịch vụ khai báo dịch vụ apache2 , mà ta thông báo khởi động lại từ tài nguyên áp dụng mẫu server ảo.

Kết luận

Puppet là một công cụ quản lý cấu hình mạnh mẽ sử dụng DSL tùy chỉnh rõ ràng để quản lý tài nguyên server và tự động hóa các việc . Ngôn ngữ của nó cung cấp các tài nguyên nâng cao có thể cung cấp thêm tính linh hoạt cho các cài đặt cấp phép của bạn; Điều quan trọng cần nhớ là các tài nguyên không được đánh giá theo cùng thứ tự mà chúng được xác định, và vì lý do đó, bạn cần phải cẩn thận khi xác định dependencies giữa các tài nguyên để cài đặt chuỗi thực thi phù hợp.

Trong phần hướng dẫn tiếp theo của loạt bài này , ta sẽ cùng tìm hiểu về Chef, một công cụ quản lý cấu hình mạnh mẽ khác sử dụng ngôn ngữ lập trình Ruby để tự động hóa việc quản lý và cung cấp cơ sở hạ tầng.


Tags:

Các tin liên quan