Ansible の Playbook ミッション コントロール

1. Ansible タスク制御の基本概要

ここではPlayBookのミッションコントロールを中心に紹介します。
ミッション制御は、プログラミング言語の if ... 、 for ... などの論理制御ステートメントに似ています。
ここでは、PlayBook でミッション コントロールがどのように適用されるかを示す実際のアプリケーション ケースを示します。
以下の PlayBook では、tomcat、www、mysql の 3 人のユーザーを作成しました。Nginx ソフトウェア パッケージをインストールし、Nginx メイン構成ファイルと仮想ホスト構成ファイルを同時に更新し、最後に Nginx サービスを開始します。
PlayBook 全体には文法上の問題はありませんが、ロジックと記述の点で注意と最適化が必要な領域がまだいくつかあります。

  • Nginx の起動ロジックには考慮が欠けています。Nginx 設定ファイルの構文が間違っていると、Nginx の起動に失敗し、PlayBook の実行に失敗します。
  • ユーザーをバッチで作成するには、手順のリストが厳格すぎます。さらに複数のユーザーを作成すると、終了するのが難しくなります。

コードは以下のように表示されます。

---
- name: task control playbook example
 hosts: webservers
 tasks:
 - name: create tomcat user
   user: name=tomcat state=present
 
 - name: create www user
   user: name=www state=present
 
 - name: create mysql user
   user: name=mysql state=present
 
 - name: yum nginx webserver
   yum: name=nginx state=present
 
 - name: update nginx main config
   copy: src=nginx.conf dest=/etc/nginx/
 
 - name: add virtualhost config
   copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
 
 - name: start nginx server
   service: name=nginx state=started

準備:

cat nginx.conf

user www;
worker_processes 2;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
    
    
 worker_connections 1024;
}
http {
    
    
 include /etc/nginx/mime.types;
 default_type application/octet-stream;
log_format main '$remote_addr - $remote_user
[$time_local] "$request" '
 '$status $body_bytes_sent
"$http_referer" '
 '"$http_user_agent"
"$http_x_forwarded_for"';
 sendfile on;
 tcp_nopush on;
 keepalive_timeout 0;
 gzip on;
 gzip_min_length 1k;
 gzip_buffers 8 64k;
 gzip_http_version 1.0;
 gzip_comp_level 5;
 gzip_types text/plain application/x-javascript
text/css application/json application/xml
application/x-shockwave-flash application/javascript
image/svg+xml image/x-icon;
 gzip_vary on;
 include /etc/nginx/conf.d/*.conf;
}
cat www.qfedu.com.conf

server {
    
    
 listen 80;
 server_name www.qfedu.com;
 root /usr/share/nginx/html;
 access_log /var/log/nginx/www.qfedu.comaccess_log main;
error_log /var/log/nginx/www.qfedu.comerror_log;
 add_header Access-Control-Allow-Origin *;
 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
    
    
 expires 1d;
 }
 location ~ .*\.(js|css)?$ {
    
    
 expires 1d;
 }
}

2. 状態判断

最初の問題を解決する

Nginx の起動ロジックには考慮が欠けています。Nginx 設定ファイルの構文が間違っていると、Nginx の起動に失敗し、PlayBook の実行に失敗します。
開始前に Nginx 設定ファイルの構文が正しいことを検証できた場合は、検証に合格した場合にのみ Nginx を起動または再起動します。そうでない場合は、Nginx の起動プロセスをスキップします。これにより、Nginx 構成ファイルの構文の問題により Nginx を起動できないリスクが回避されます。

Nginxの構文チェック
- name: check nginx syntax
 shell: /usr/sbin/nginx -t

では、Nginx の文法チェックのタスクと Nginx が開始するタスクをどのように関連付ければよいのでしょうか?
文法チェックのタスクの結果を取得し、「NGINX の開始タスク」が規定に従って実行されているかどうかを判断できれば良いでしょう。結果と計画。構文チェック タスクの結果を取得するにはどうすればよいですか? この時点で、前に学習した Ansible の登録変数を使用できます。

タスクタスクの結果を取得する
- name: check nginx syntax
 shell: /usr/sbin/nginx -t
 register: nginxsyntax
デバッグモジュールを使用して、返された結果のデータ構造を確認します

このとき疑問に思うことがあるかもしれませんが、タスクの結果は得られたものの、その結果にはどのような内容が含まれているのか、その内容に応じて次のPlayBookでどのように活用すればよいのでしょうか?

- name: print nginx syntax result
 debug: var=nginxsyntax

デバッグ モジュールを通じて、返された結果を出力します。nginxsyntax.rc が 0 の場合、構文チェックは正しく行われます。

"nginxsyntax": {
    
    
 "changed": true,
 "cmd": "/usr/sbin/nginx -t",
 "delta": "0:00:00.012045",
 "end": "2017-08-12 20:19:04.650718",
 "rc": 0,
 "start": "2017-08-12 20:19:04.638673",
 "stderr": "nginx: the configuration file
/etc/nginx/nginx.conf syntax is ok\nnginx:
configuration file /etc/nginx/nginx.conf test is
successful",
"stderr_lines": [
 "nginx: the configuration file
/etc/nginx/nginx.conf syntax is ok",
 "nginx: configuration file
/etc/nginx/nginx.conf test is successful"
 ],
 "stdout": "",
 "stdout_lines": []
 }
構文チェックの結果を利用するには、条件判定(when)命令を使用します。
- name: check nginx syntax
 shell: /usr/sbin/nginx -t
 register: nginxsyntax
 - name: print nginx syntax
 debug: var=nginxsyntax
 
 - name: start nginx server
 service: name=nginx state=started
 when: nginxsyntax.rc == 0
改善された PlayBook
---
- name: task control playbook example
 hosts: webservers
 gather_facts: no
 tasks:
  - name: create tomcat user
    user: name=tomcat state=present
  
  - name: create www user
    user: name=www state=present
  
  - name: create mysql user
    user: name=mysql state=present
 
  - name: yum nginx webserver
    yum: name=nginx state=present
  
  - name: update nginx main config
    copy: src=nginx.conf dest=/etc/nginx/
  
  - name: add virtualhost config
    copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
 
  - name: check nginx syntax
    shell: /usr/sbin/nginx -t
    register: nginxsyntax
 
  - name: print nginx syntax
    debug: var=nginxsyntax
 
  - name: start nginx server
    service: name=nginx state=started
    when: nginxsyntax.rc == 0
要約する

上記のロジックでは、構文チェックに合格する限り、「nginx サーバーの起動」タスクが実行されます。この問題を解くにあたり、 when 条件判定と登録変数の組み合わせを学びました。条件判断が複雑なロジックをサポートできることを学びます。たとえば、論理演算子 and は現在使用されています。
さらに、When は次の演算子をサポートします。

==
!=
> >=
< <=
is defined
is not defined
true
false
#⽀持逻辑运算符: and or

3. ループ制御

2番目の問題を解決する

ユーザーをバッチで作成するには、手順のリストが厳格すぎます。さらに複数のユーザーを作成すると、終了するのが困難になります。
ユーザーを作成するときに PlayBook の実装を無視する場合は、シェルを使用していくつかのユーザーをバッチで作成するだけです。通常、どのように記述しますか?
たとえば、次のスクリプトです。

#! /bin/bash

createuser="tomcat mysql www"
for i in `echo $createuser`
do
 useradd $i
done

PlayBook にそのようなループ コントロールがあれば、シェルを書くだけでマルチユーザーの作成作業も完了します。
PlayBook で with_items を使用してループ制御を実装します。ループ中の中間変数 (上記のシェル ループの $i 変数) はキーワード項目のみにすることができ、自由にカスタマイズすることはできません。

上記を踏まえて改良したPlayBook

ここでは、スクリプト変数 createuser (リスト) が定義されており、この変数が with_items をループしてユーザーを作成する目的を達成しています。

- name: variable playbook example
 hosts: webservers
 gather_facts: no
 vars:
   createuser:
    - tomcat
    - www
    - mysql
 tasks:
   - name: create user
     user: name={
    
    {
    
     item }} state=present
     with_items: "{
    
    { createuser }}"
   
   - name: yum nginx webserver
     yum: name=nginx state=present
   
   - name: update nginx main config
     copy: src=nginx.conf dest=/etc/nginx/
 
   - name: add virtualhost config
     copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
   
   - name: check nginx syntax
     shell: /usr/sbin/nginx -t
     register: nginxsyntax
 
   - name: print nginx syntax
     debug: var=nginxsyntax

   - name: start nginx server
     service: name=nginx state=started
     when: nginxsyntax.rc == 0

上記の問題を解決した後、PlayBook 全体が大幅に改善されました。

新しいバージョンのサイクル
- name: loop item
  hosts: all
  gather_facts: no
  vars:
    some_list:
     - "a"
     - "b"
     - "c"
    num_list:
     - 1
     - 2
     - 3
     - 5
 tasks:
 - name: show item
   debug:
     var: "{
    
    { item }}"
   loop: "{
    
    { some_list }}"
 
- name: show item when item > 3
  debug:
   var: "{
    
    { item }}"
  loop: "{
    
    { num_list }}"
  when: item > 3

このような状況を考えてみましょう。Nginx
構成ファイルを更新した後、PlayBook を通じて運用サーバーに新しい構成を公開し、Nginx サービスをリロードする必要があります。しかし、現在の PlayBook を例にとると、Nginx 構成ファイルが変更されるたびに、それを介して本番環境にリリースできますが、PlayBook 全体を 1 回実行する必要があるため、事実上、変更の範囲と変更のリスクが拡大します。
次の Tags 属性により、この問題を解決できます。

4、Tagsプロパティ

Play の tags 属性を使用すると、現在の PlayBook の変更によって生じる変更範囲の拡大とリスクの変更の問題を解決できます。
改良された PlayBook では、ファイル公開 TASK タスク
「update nginx main config」および「add virtualhost config」に
属性タグが追加され、属性値は updateconfig になります。
さらに、「nginx サーバーのリロード」TASK タスクを追加しました。構成ファイルが更新されたら、Nginx サービスをリロードします。
そのリロードは、開始されている Nginx サービスに依存します。したがって、Nginx サービス自体が起動していることを証明するには、Nngix pid ファイルの存在をさらに判断する必要があり、Nginx サービスは起動している場合にのみリロードできます。

ファイルが存在するかどうかを確認するには、stat モジュールを使用します。
- name: check nginx running
  stat: path=/var/run/nginx.pid
  register: nginxrunning

結果を観察すると、nginxrunning.stat.exists の値が起動ステータスを示す場合は true、シャットダウン ステータスを示す場合は false であることがわかります。
次に、この結果に基づいて Nginx サービスをリロードするかどうかを決定できます。

プレイブックの改善
- name: tags playbook example
  hosts: webservers
  gather_facts: no
  vars:
   createuser:
     - tomcat
     - www
     - mysql
  tasks:
     - name: create user
       user: name={
    
    {
    
     item }} state=present
       with_items: "{
    
    { createuser }}"
 
     - name: yum nginx webserver
       yum: name=nginx state=present
 
     - name: update nginx main config
       copy: src=nginx.conf dest=/etc/nginx/
       tags: updateconfig
 
     - name: add virtualhost config
       copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
       tags: updateconfig
 
     - name: check nginx syntax
       shell: /usr/sbin/nginx -t
       register: nginxsyntax
       tags: updateconfig
 
     - name: check nginx running
       stat: path=/var/run/nginx.pid
       register: nginxrunning
       tags: updateconfig
 
     - name: print nginx syntax
       debug: var=nginxsyntax
 
     - name: print nginx syntax
       debug: var=nginxrunning
 
     - name: reload nginx server
       service: name=nginx state=started
       when: nginxsyntax.rc == 0 and
             nginxrunning.stat.exists == true
      tags: updateconfig
 
    - name: start nginx server
      service: name=nginx state=started
      when:
        - nginxsyntax.rc == 0
        - nginxrunning.stat.exists == false
      tags: updateconfig
PlayBookを実行するタグを指定する

タスクタスクの updateconfig でタグ付けされたタスクのみが実行中に実行されるように、実行中にタグを指定する必要があります。

ansible-playbook -i hosts site.yml -t updateconfig

5 **、ハンドラー属性 **

現在の Playbook を観察すると、設定ファイルが変更されていない場合でも、タスク「nginx サーバーの再読み込み」が毎回トリガーされることがわかりません。
設定ファイルが変更された場合にのみ「nginx サーバーのリロード」タスクをトリガーする方法が最も完璧な実装です。ここで、handlers 属性を使用できます。

プレイブックの改善
 - name: handlers playbook example
   hosts: webservers
   gather_facts: no
   vars:
     createuser:
        - tomcat
        - www
        - mysql
   tasks:
     - name: create user
       user: name={
    
    {
    
     item }} state=present
       with_items: "{
    
    { createuser }}"
    
     - name: yum nginx webserver
       yum: name=nginx state=present
 
     - name: update nginx main config
       copy: src=nginx.conf dest=/etc/nginx/
       tags: updateconfig
       notify: reload nginx server
 
    - name: add virtualhost config
      copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
      tags: updateconfig
      notify: reload nginx server
 
   - name: check nginx syntax
     shell: /usr/sbin/nginx -t
     register: nginxsyntax
     tags: updateconfig
  
   - name: check nginx running
     stat: path=/var/run/nginx.pid
     register: nginxrunning
     tags: updateconfig
 
   - name: start nginx server
     service: name=nginx state=started
     when:
      - nginxsyntax.rc == 0
      - nginxrunning.stat.exists == false
 handlers:
   - name: reload nginx server
    service: name=nginx state=reloaded
    when:
      - nginxsyntax.rc == 0
      - nginxrunning.stat.exists == true

改善された PlayBook では、TASK タスク「update nginx main config」および「add virtualhost config」をファイルパブリッシングに通知する新しい属性を「reload nginx server」の値で追加しました。
この2つのファイルが発行するTASKに対する通知機構を設定するということで、Ansibleはファイルの内容が変わった(ファイルのMD5が変わった)と判断した場合に、あるタスクに通知する通知Signalを送信します。ハンドラー。どのタスクをハンドラーに送信するかは、notify "reload nginx server" の値によって決まります。通知が送信されると、ハンドラーは送信された通知に従って、ハンドラー内の関連タスクの中から「reload nginx server」という名前のタスクを検索します。そのような名前の TASK が見つかると、それが実行されます。見つからない場合は何もしません。このようなメカニズムを実装したい場合は、notify 属性によって設定された値に注意を払う必要があり、それがハンドラー内の TASK 名に対応していることを確認する必要があります。

実行する

初めて実行すると、構成ファイルが変更されていない場合、ハンドラー内の TASK タスクがまったくトリガーされていないことがわかります。

ansible-playbook -i hosts site.yml -t updateconfig

MD5 チェック値が変更される限り、Nginx 構成ファイルを手動でわずかに変更します。この時点で再度実行すると、ハンドラー内の TASK タスクがトリガーされたことがわかります

ansible-playbook -i hosts site.yml -t updateconfig

おすすめ

転載: blog.csdn.net/xiaoyu070321/article/details/131366846