Ansibleのwhen条件・loop・tagsでPlaybookを制御する方法|環境ごとの分岐と対象タスクを絞り込む設計パターン

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > Ansibleのwhen条件・loop・tagsでPlaybookを制御する方法|環境ごとの分岐と対象タスクを絞り込む設計パターン
「本番サーバーとテスト環境で別々のパッケージをインストールしたい」
「ユーザーアカウントを10件、同じ設定で一括作成したい。コピペを繰り返すのはつらい」
「Playbookが100行を超えてきた。今日はNginxの設定変更だけ反映して、他のタスクはスキップしたい」
「設定ファイルの書き込みが失敗したとき、自動でバックアップから元に戻したい」

Ansibleを本格的に使い始めると、必ずこうした要求に直面します。単純な「命令を並べるだけ」のPlaybookは、環境差分への対応・複数リソースの一括操作・部分実行・エラー時の自動回復が必要になった瞬間に限界を迎えます。

この記事では、Ansibleの制御フロー3本柱であるwhen条件式(実行分岐)・loop繰り返し処理tags部分実行を体系的に解説します。さらに本番運用で欠かせないblock・rescue・alwaysによるエラーハンドリング設計も含め、RHEL 10 / Rocky Linux 9の実行例とともに説明します。

この記事のポイント

・whenはOS種別・ファクト変数・register結果・グループ判定など多様な条件を記述できる
・loopはリスト・辞書を使った繰り返しで複数ユーザー・パッケージの一括操作を簡潔に書ける
・tagsで「インストールだけ」「設定だけ」を選択実行でき大規模Playbookの運用効率が上がる
・block/rescue/alwaysはPythonのtry/except/finallyに相当するエラーハンドリング構造
・3つを組み合わせれば環境別インストール・一括作成・差分適用を1Playbookで表現できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

Ansibleの制御フローが必要になる理由|シンプルPlaybookの限界

Ansibleを使い始めた頃は、タスクを上から順に並べるだけで十分でした。しかし運用が進むにつれ、次のような「壁」に必ずぶつかります。

環境差分の壁: 本番はRHEL 10、開発はUbuntu 24.04。OSが違えばパッケージ名もサービス管理コマンドも違う。
繰り返しの壁: Webアプリ用ユーザーを5件作りたい。内容が少し違う5つのタスクをコピペするのは保守性がゼロ。
部分適用の壁: 設定ファイルだけ更新したい。インストール済みのパッケージに触りたくない。
障害回復の壁: 設定変更が失敗した後、サービスが壊れたまま放置される。失敗時の自動ロールバックをPlaybookに組み込めない。

これら4つの壁を突き破るのがwhenlooptagsblock/rescue/alwaysです。4つを使いこなすことで、Playbookは「手順書の写し」から「設計として表現されたインフラの状態」に昇格します。

when条件式でタスクの実行を制御する方法

whenはタスクに実行条件を付けるキーワードです。条件がfalseのときはタスクがスキップされ、「changed」も「failed」も起きません。

1. Ansibleファクト変数を使ったOS別分岐

最も多く使われるパターンが、Ansibleが自動収集するファクト変数によるOS判定です。

--- - name: OSに応じたNginxインストール hosts: webservers tasks: - name: Nginxをインストールする(RHEL系) ansible.builtin.dnf: name: nginx state: present when: ansible_os_family == "RedHat" - name: Nginxをインストールする(Debian系) ansible.builtin.apt: name: nginx state: present when: ansible_os_family == "Debian"

実行すると、対象ホストのOSに合致しないタスクは「skipping」として表示されます。

TASK [Nginxをインストールする(RHEL系)] ***** ok: [web01.example.com] TASK [Nginxをインストールする(Debian系)] ***** skipping: [web01.example.com]

主要なファクト変数と使いどころは次のとおりです。

ansible_os_family: "RedHat" / "Debian" / "Suse" など。パッケージ管理の分岐に使う
ansible_distribution: "Rocky" / "AlmaLinux" / "Ubuntu" など。より細かい分岐に使う
ansible_distribution_major_version: "9" / "10" など。バージョン別対応に使う
ansible_hostname: ホスト名。特定ホストにのみ適用するタスクに使う

2. register変数を使った前タスクの結果による分岐

registerでタスクの結果を変数に格納し、後続タスクのwhenで参照するパターンです。既存の状態を確認してから次の処理を決める「チェックアンドアクト」の実装に使います。

--- - name: サービス状態を確認してから設定を反映する hosts: webservers tasks: - name: サービス情報を収集する ansible.builtin.service_facts: - name: httpdが起動中の場合のみ設定ファイルを更新する ansible.builtin.template: src: httpd.conf.j2 dest: /etc/httpd/conf/httpd.conf validate: "httpd -t -f %s" when: "'httpd.service' in ansible_facts.services and ansible_facts.services['httpd.service'].state == 'running'" notify: restart httpd - name: MySQLが存在するか確認する ansible.builtin.command: cmd: rpm -q mariadb-server register: mysql_check failed_when: false changed_when: false - name: MySQLが未インストールの場合のみインストールする ansible.builtin.dnf: name: mariadb-server state: present when: mysql_check.rc != 0

Apacheの設定ファイル操作の詳細(タイムアウト値・KeepAlive等)についてはApache タイムアウト設定の詳細も参照してください。

3. グループ判定とカスタム変数による分岐

インベントリのグループや独自変数を使った分岐は、環境ごとの設定差分を管理する定番パターンです。

--- - name: 環境別セキュリティ設定 hosts: all tasks: - name: 本番環境のWebサーバーのみSELinuxをenforcingにする ansible.builtin.command: cmd: setenforce 1 when: - inventory_hostname in groups['webservers'] - server_env == "production" - name: ステージング以外では詳細ログを無効化する ansible.builtin.lineinfile: path: /etc/nginx/nginx.conf regexp: '^access_log' line: "access_log off;" when: server_env != "staging"

複数条件のリスト記法(暗黙のand)
whenをリスト形式で書くと、全条件のAND(論理積)になります。

# リスト形式 = すべての条件を満たす場合のみ実行(AND) when: - ansible_os_family == "RedHat" - ansible_distribution_major_version | int >= 9 - server_role is defined # OR条件は括弧で明示する when: server_role == "web" or server_role == "proxy"

loopで繰り返し処理を設計する方法

loopはAnsible 2.5以降の推奨繰り返し記法です。旧来のwith_itemsと同じ役割ですが、より統一的に使えます。

1. シンプルリストのloop(パッケージ一括インストール)

- name: 必要なパッケージをまとめてインストールする ansible.builtin.dnf: name: "{{ item }}" state: present loop: - nginx - mariadb-server - php-fpm - firewalld

ただしdnfモジュールはnameにリストを直接渡す書き方の方が効率的です。loopは1パッケージごとにモジュールを1回起動しますが、リスト渡しは1回のdnf呼び出しで済みます。

# より効率的な書き方(loopより推奨) - name: 必要なパッケージをまとめてインストールする ansible.builtin.dnf: name: - nginx - mariadb-server - php-fpm - firewalld state: present

loopが本領を発揮するのは、「タスク単位で1リソースしか扱えないモジュール」(userモジュールなど)での繰り返しです。

2. 辞書リストのloop(ユーザー一括作成)

辞書(キーと値のペア)のリストをloopに渡すと、item.キー名で各フィールドにアクセスできます。

- name: Webアプリ用ユーザーを一括作成する ansible.builtin.user: name: "{{ item.name }}" groups: "{{ item.groups }}" comment: "{{ item.comment }}" state: present loop: - { name: "appuser", groups: "nginx", comment: "Web Application User" } - { name: "deployer", groups: "wheel,nginx", comment: "Deploy Bot User" } - { name: "monitor", groups: "systemd-journal", comment: "Monitoring Agent" } # 実行結果の例 TASK [Webアプリ用ユーザーを一括作成する] ***** changed: [web01.example.com] => (item={'name': 'appuser', 'groups': 'nginx', ...}) changed: [web01.example.com] => (item={'name': 'deployer', 'groups': 'wheel,nginx', ...}) changed: [web01.example.com] => (item={'name': 'monitor', 'groups': 'systemd-journal', ...})

3. loop_control.labelで出力を見やすくする

辞書リストのloopはデフォルトだと全フィールドが出力されて見づらいです。loop_control.labelで表示内容を絞り込めます。

- name: Nginxバーチャルホストの設定ファイルを配置する ansible.builtin.template: src: "vhost.conf.j2" dest: "/etc/nginx/conf.d/{{ item.domain }}.conf" loop: - { domain: "app.example.com", port: 8080, upstream: "app_pool" } - { domain: "api.example.com", port: 8081, upstream: "api_pool" } - { domain: "admin.example.com",port: 8082, upstream: "admin_pool" } loop_control: label: "{{ item.domain }}" # ← ドメイン名だけ表示 # label指定後の出力(すっきり) changed: [web01] => (item=app.example.com) changed: [web01] => (item=api.example.com) changed: [web01] => (item=admin.example.com)

4. loopとwhenを組み合わせる

loopwhenを組み合わせると、「リストの中から条件に合うものだけ処理する」ことができます。

- name: 本番環境用ユーザーのみ作成する ansible.builtin.user: name: "{{ item.name }}" state: present loop: - { name: "appuser", env: "production" } - { name: "testuser", env: "staging" } - { name: "devuser", env: "development"} when: item.env == server_env loop_control: label: "{{ item.name }} ({{ item.env }})"

loopとwhenのパターンを実機で試したい方は、>> Ansibleハンズオン講座の詳細を見る をご覧ください。

tagsでPlaybookを部分実行する設計パターン

tagsはタスク・プレイ・roleに「ラベル」を付ける機能です。実行時に--tags--skip-tagsを指定することで、Playbook全体から特定の処理だけを選んで実行できます。

1. タグの付け方(タスクレベルとプレイレベル)

--- - name: Webサーバーのフルセットアップ hosts: webservers tags: webserver # ← プレイ全体にタグを付ける tasks: - name: Nginxをインストールする ansible.builtin.dnf: name: nginx state: present tags: [install, nginx] # ← タスクに複数のタグを付ける - name: Nginx設定ファイルを配置する ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf tags: [config, nginx] notify: nginx restart - name: Nginxを起動・自動起動有効にする ansible.builtin.service: name: nginx state: started enabled: true tags: [service, nginx] - name: ログ収集用の監視エージェントをインストールする ansible.builtin.dnf: name: node_exporter state: present tags: [install, monitoring]

2. --tagsと--skip-tagsで実行対象を絞り込む

# インストールタスクだけ実行する ansible-playbook site.yml --tags install # 設定ファイル更新だけ実行する(サービス再起動なし) ansible-playbook site.yml --tags config # Nginx関連タスクだけ実行する ansible-playbook site.yml --tags nginx # 複数のタグを指定する(いずれかに一致するタスクを実行) ansible-playbook site.yml --tags "install,config" # 監視エージェントをスキップしてWebサーバーのみセットアップ ansible-playbook site.yml --skip-tags monitoring # 利用可能なタグを事前確認する(実行はしない) ansible-playbook site.yml --list-tags # 出力例 play #1 (webservers): Webサーバーのフルセットアップ TASK TAGS: [config, install, monitoring, nginx, service, webserver]

3. alwaysとneverの特殊タグ

alwaysタグを付けたタスクは、--skip-tagsでも除外されず必ず実行されます。逆にneverタグを付けたタスクは、--tags neverを明示しない限り実行されません。

- name: 実行前の事前確認(常に実行する) ansible.builtin.debug: msg: "対象ホスト: {{ inventory_hostname }}, 環境: {{ server_env }}" tags: always # ← どんな--skip-tagsでも必ず実行 - name: 本番環境の全データを削除する(明示的に指定した時のみ実行) ansible.builtin.file: path: /var/lib/app/data state: absent tags: never # ← --tags neverを指定した時のみ実行(誤実行防止)

alwaysタグの典型的なユースケースは「前提確認タスク」(Ansibleバージョンの確認・ファクト収集・必須変数のバリデーション)です。neverタグは「通常は実行しない危険な処理」(DBリセット・全ファイル削除)の誤実行防止に使います。

4. タグ設計のベストプラクティス

タグは「多すぎても少なすぎても使いにくい」ツールです。実務では次の2階層設計が管理しやすいです。

機能タグ(何をするか): install / config / service / cleanup
コンポーネントタグ(何に対して): nginx / mysql / firewalld / monitoring

この設計だと「Nginxの設定だけ変更する」は--tags "config,nginx"、「サービス起動系を全部スキップ」は--skip-tags serviceと直感的に指定できます。

when・loop・tagsを組み合わせた実務設計パターン

3つを組み合わせた実例として、「本番・ステージング・開発の3環境に対して、複数のWebアプリユーザーを環境別条件でセットアップする」Playbookを示します。

--- - name: 環境別Webアプリセットアップ hosts: all vars: app_users: - { name: "appuser", env: "production", uid: 1001 } - { name: "stagingapp",env: "staging", uid: 1002 } - { name: "devapp", env: "development", uid: 1003 } tasks: - name: OS別にNginxをインストールする ansible.builtin.package: name: nginx state: present when: ansible_os_family in ["RedHat", "Debian"] tags: [install, nginx] - name: 対象環境のWebアプリユーザーを作成する ansible.builtin.user: name: "{{ item.name }}" uid: "{{ item.uid }}" state: present loop: "{{ app_users }}" when: item.env == server_env loop_control: label: "{{ item.name }} ({{ item.env }})" tags: [setup, users] - name: 本番環境のみSSHパスワード認証を無効化する ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: '^PasswordAuthentication' line: "PasswordAuthentication no" when: - ansible_os_family == "RedHat" - server_env == "production" notify: restart sshd tags: [security, ssh, config] - name: ファイアウォールでHTTP・HTTPSを開放する ansible.builtin.command: cmd: "firewall-cmd --add-service={{ item }} --permanent" loop: - http - https when: inventory_hostname in groups['webservers'] tags: [config, firewalld]

実行時は次のように環境変数とタグを組み合わせてコントロールします。

# 本番環境でインストールとユーザー作成のみ実行 ansible-playbook site.yml -e "server_env=production" --tags "install,setup" # ステージングでセキュリティ設定だけ更新 ansible-playbook site.yml -e "server_env=staging" --tags security

ファイアウォールのfirewall-cmdコマンドの動作確認にはLinux ポート確認の全コマンド(ss・lsofによる開放確認)も活用してください。Ansibleタスクが成功しても実際にポートが開いているかはssコマンドで確認するのが確実です。

block・rescue・alwaysでエラーハンドリングを追加する方法

when・loop・tagsでPlaybookを構造化しても、タスクが失敗したときの処理まで書かなければ本番運用には耐えられません。「設定ファイルの書き込みが失敗したのにサービスが再起動されてしまった」「一部のホストで失敗したのに展開が続いてしまった」——こうした障害を防ぐのがblockrescuealwaysです。Pythonのtry / except / finallyに相当するAnsibleのエラーハンドリング構造です。

1. block・rescue・alwaysの基本構造

# block/rescue/always の基本構造 - name: Webサーバー設定の適用(エラーハンドリング付き) block: - name: 設定ファイルをデプロイする ansible.builtin.template: src: httpd.conf.j2 dest: /etc/httpd/conf/httpd.conf owner: root group: root mode: '0644' - name: 設定の構文チェックを実行する ansible.builtin.command: cmd: httpd -t changed_when: false - name: httpdを再起動する ansible.builtin.service: name: httpd state: restarted rescue: - name: 設定ファイルをバックアップから復元する ansible.builtin.copy: src: /etc/httpd/conf/httpd.conf.bak dest: /etc/httpd/conf/httpd.conf remote_src: yes - name: httpdを元の設定で再起動する ansible.builtin.service: name: httpd state: restarted - name: デプロイ失敗を明示的に通知する ansible.builtin.fail: msg: "rollback completed, but original deploy failed on {{ inventory_hostname }}" always: - name: 一時ファイルを削除する ansible.builtin.file: path: /tmp/httpd_deploy_lock state: absent ignore_errors: yes

block: 複数タスクをグループ化する。block内のいずれかのタスクが失敗するとrescueに制御が移る
rescue: 失敗時のみ実行される回復処理。注意: rescueが正常終了するとPlaybookは「回復した」とみなして次へ続行する。「ロールバックは成功したがデプロイ自体は失敗した」として後続を止めたい場合は末尾にansible.builtin.failを必ず入れる
always: block成功・rescue完了のどちらでも必ず実行されるクリーンアップ処理。always内タスクも失敗しうるためignore_errors: yesを添えて波及を防ぐ

2. ignore_errors・failed_when・changed_whenの使い分け

blockを使わず局所的にエラーを制御したい場合は、以下の3つのフラグを使い分けます。

# ignore_errors: 特定タスクのみエラーを無視して続行する - name: 既存のcronジョブを削除する(存在しなくても続行) ansible.builtin.cron: name: "old-backup-job" state: absent ignore_errors: yes # failed_when: 失敗条件を自分で定義する - name: プロセスの起動確認(grepはプロセスなし時にrc=1を返す) ansible.builtin.command: cmd: pgrep -x httpd register: httpd_check failed_when: httpd_check.rc != 0 and httpd_check.rc != 1 # rc=0: プロセスあり、rc=1: プロセスなし(想定内)、それ以外: 異常 # changed_when: commandモジュールの変更判定を自分で制御する - name: カスタムスクリプトで設定を変更する ansible.builtin.command: cmd: /opt/scripts/update-config.sh register: update_result changed_when: "'Updated' in update_result.stdout" # 出力にUpdatedが含まれる場合のみchangedとして扱う # changed_when: false で副作用なしチェックコマンドをok扱いにする - name: 設定の整合性チェックを実行する ansible.builtin.command: cmd: /opt/scripts/check-config.sh changed_when: false

実務上の使い分けの鉄則は「影響範囲を最小限に絞る」です。ignore_errorsを乱用すると本物のエラーが握りつぶされるため、blockのrescueで代替できる場合はblockを優先します。failed_whenはregister変数と組み合わせて「終了コード0なのに実は失敗」「終了コード1だが想定内」を正確に表現できます。changed_when: falseは副作用のないチェックコマンドに付けて、不要な「changed」判定を防ぎます。

block/rescue/alwaysを使った本番対応のPlaybook設計を実機で体験したい方は、>> Ansibleハンズオン講座の詳細を見る をご覧ください。

トラブルシュート|when・loop・tagsでよくある失敗と対処法

1. when条件が期待通りに評価されない

症状: ansible_distribution_major_version == 9 と書いたのに条件が一致しない。

原因と対処: ファクト変数が文字列として返ってくるケースがあります。整数比較が必要な場合はJinja2フィルタで変換します。

# NG: 文字列と整数を比較しているため期待通りに動かないことがある when: ansible_distribution_major_version == 9 # OK: | int フィルタで整数に変換してから比較する when: ansible_distribution_major_version | int == 9 # OK: 文字列として比較する when: ansible_distribution_major_version == "9"

2. loopとregisterの結果がうまく取得できない

症状: loopの中でregisterした変数を次のタスクで参照すると、最後のループ結果しか入っていない。

対処: loopと組み合わせたregisterは、変数名.resultsにリスト形式で全ループ結果が格納されます。

- name: 複数のサービス状態を確認する ansible.builtin.service_facts: register: all_services - name: サービス起動確認の結果をデバッグ出力する ansible.builtin.debug: msg: "{{ item.key }}: {{ item.value.state }}" loop: "{{ ansible_facts.services | dict2items }}" when: item.key in ['nginx.service', 'mariadb.service', 'firewalld.service'] loop_control: label: "{{ item.key }}"

3. tagsがinclude_tasksで効かない

症状: include_tasksでインクルードしたファイル内のタスクにtags: configを付けても、--tags configで実行されない。

原因: include_tasksは動的インクルードのため、Playbookの解析時点ではタグが認識されません。静的インクルードのimport_tasksを使うか、include_tasks自体にタグを付けます。

# import_tasks(静的): インクルード先のタグが --tags で認識される - name: Nginx設定タスクをインクルードする ansible.builtin.import_tasks: tasks/nginx_config.yml # include_tasks(動的): include自体にタグを付けることで対応する - name: Nginx設定タスクをインクルードする ansible.builtin.include_tasks: tasks/nginx_config.yml tags: [config, nginx]

4. rescue後にPlaybookが続行してしまう

症状: block内のタスクが失敗してrescueが動いたが、rescueが正常終了したのでPlaybookが次のタスクへ進んでしまった。

原因と対処: rescueが正常終了するとAnsibleは「回復した」と判断し、後続タスクへ進みます。「ロールバックは成功したがデプロイ自体は失敗した」として後続を停止させたい場合は、rescueの末尾にansible.builtin.failを明示的に入れてください。

rescue: - name: ロールバック処理を実行する ansible.builtin.copy: src: /etc/app/config.bak dest: /etc/app/config remote_src: yes # これがないとrescue後にPlaybookが続行される(要注意) - name: デプロイ失敗を明示的に通知する ansible.builtin.fail: msg: "Deployment failed and rolled back on {{ inventory_hostname }}"

NTPサーバー設定に関連する時刻同期の詳細については、ntpd 時刻同期設定も参照してください。Ansibleのchronyやntpdインストール処理でwhen条件(OS判定)と組み合わせるケースはよくあるパターンです。

本記事のまとめ

やりたいこと 使う機能と書き方
OS種別でタスクを分岐させる when: ansible_os_family == "RedHat"
コマンド結果で次のタスクを制御する register: 変数名when: 変数名.rc == 0
複数の条件をすべて満たす場合に実行する when: にリスト形式で条件を並べる(暗黙のand)
同じ処理を複数のリソースに適用する loop: [item1, item2, ...]{{ item }}
辞書リストで複数フィールドを繰り返す loop: [{name: x, value: y}, ...]{{ item.name }}
loop出力を見やすくする loop_control: {label: "{{ item.name }}"}
インストールだけ・設定だけを実行する tags: [install, config]ansible-playbook --tags install
特定のコンポーネントだけスキップする ansible-playbook --skip-tags monitoring
常に実行するタスクを指定する tags: always
明示的に指定した時のみ実行する tags: never
失敗時に自動でロールバックする blockで処理をまとめ、rescueに回復処理を書く
成否に関わらず後処理を必ず実行する alwaysにクリーンアップ処理を書く(ignore_errors: yesも添える)
特定タスクのエラーを無視して続行する ignore_errors: yes
コマンドの失敗・成功条件を自分で定義する failed_when: 変数.rc != 0またはchanged_when: false
when・loop・tagsの3つをマスターすると、Playbookの品質が一段階上がります。「OS別に分岐する」「複数リソースを一括操作する」「特定の処理だけ実行する」——これらは実務で毎日のように必要になる操作です。さらにblock・rescue・alwaysによるエラーハンドリングを加えることで、本番サーバーへの展開でも安全に自動化できる設計になります。最初は1つずつ試して、徐々に組み合わせていくのが習得の近道です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。