【Ansible】CentOS 6 用「(libselinux-python) aren't installed!」解決 Playbook
皆様こんにちは。
つけ麺とパスタが発作的に食べたくなる システムソリューション部所属の なか です。
手動で管理していた CentOS 6 環境を Ansible で更新・変更しようとした時、「(libselinux-python) aren't installed!」というエラーが発生しやすいです。
このエラーは手動で対応する事も多いかと思います。
ただ「数が多くて Ansible で管理したいのに、その前に全台手動で対応する必要がある」というのは手間ですよね。
であれば「それも Ansible で解決したら楽だよね」と考え、 Playbook を書きました。
今回は「 CentOS 6 用「(libselinux-python) aren't installed!」解決Playbook」を紹介&解説する内容となります。
前置き
- CentOS 6 での運用を推奨している訳ではございません。
あくまでもやむを得ない理由で存在する、CentOS 6 への応急対応用となります。 - サポートがなくなったバージョンを利用しています。
こちらも応急対応用であり、推奨する意図はございません。
基本的な原因
(libselinux-python) aren't installed!
ファイル操作といった変更のかかるモジュールを使用した際に、
- ターゲット側の SELinux が完全に無効化されていない状態
- かつ(※1) libselinux-python パッケージが入っていない(※2)
場合に発生するエラーです。
※1. SELinux が無効化されている場合は、このエラーは発生しません。
※2. Ansible は Python で動いているため、その Python が SELinux の操作を行うために必要な物。
※ Python 3 の場合は「python3-libselinux」ですが、 CentOS 6 向けには一般的に提供されていない模様です。
手動での解決法
# sudo yum install libselinux-python
「libselinux-python」をターゲット側に入れれば、基本的には解消されます。
※ Python 3 の場合は「python3-libselinux」
ただし、 CentOS 6 は EOL のため リポジトリがデフォルトのままだと yum が使えない可能性が高いです。
そうなると利用可能なリポジトリから、wget & rpm でローカルインストールを行う必要があります。
そのため、複数環境で手動対応は割と大変です。
Q. なぜ Playbook で変更させるの?
A. Ansible で作業を行いたいのに、事前に手動作業をするのは面倒……という理由だけでなく
「手動が必要なら全部手動でやるか」となりやすいので、本末転倒になるのを防ぐためです。ですので、「 Ansible で安定的に出来ることは積極的にそっちに寄せていきたい」というスタンスです。
Q. CentOS 7 には対応させないの?
A. バージョン差異対応は Playbook を分け、 include/import の段階で、判定 / 分岐させる方がスマートかなという考えです。
対応させるか悩みましたが、既に「yum」が使えない場合の分岐が含まれていて、少々複雑化しています。
リポジトリがOSバージョンによって、ディレクトリ階層名が変わる事があるため、更に分岐が増えます。
一つの Playbook 内でバージョン分岐を作ると、可読性と保守性が落ちると判断したため含めませんでした。
実行環境
■ Linux 環境
OS :AlmaLinux release 8.5(WSL2環境)
Shell:Bash
Docker :26.1.0, build 9714adc■ Ansible 環境(WSL2内Dockerコンテナ)
OS:AlmaLinux release 8.9
Ansible:Ansible-core 2.12.10■ Windows 環境
OS :Windows11 Pro(バージョン:23H2)
言語設定 :日本語に変更■ CentOS 6 環境(Vagrant + VirtualBox)
OS: CentOS 6.9(bento / centos-6.9)
Vagrant :2.4.1
VirtualBox :7.0.18 r162988(Qt5.15.2)
IP :192.168.33.15
Ansible 2.12 環境の構築手順
CentOS 6 環境は Python のバージョンが古い事が基本のため、 Ansible は対応した旧バージョン(2.12)を利用します。
前々回の記事にて、 Ansible 2.12 の構築方法を解説しましたので、こちらをご参考ください。
Playbook
CentOS 6 環境へ Playbook を実行する際、「一番最初に include/import しておけば、エラーを起こさずに実行できる」という予防的に利用する事を意識した内容になっています。
※ 勿論、エラーが出てから事後的に、この Playbook を利用する事でも解決する事は可能です。
libselinux-python_wget.yml
main.yml 側で import_tasks 使って、この Playbook を読み込む形式です。
(筆者が再利用性・可読性・保守性を高めるために、役割事に Playbook を分けたい派のため)
--- ## 変数default # wget_repo | default ("http://ftp.iij.ad.jp/pub/linux/centos-vault") - name: Check SELinux ansible.builtin.command: cmd: getenforce register: SELinux_result - ansible.builtin.debug: var: SELinux_result.stdout - name: Check libeselinux-python ansible.builtin.shell: cmd: rpm -aq | grep libselinux-python register: rpm_result ignore_errors: yes - ansible.builtin.debug: var: rpm_result.stdout # SELinuxがdisabledであれば、追加なしでAnsibleは実行可能なため実行しない # 合わせて、libselinux-python が既に導入されていれば実行しない - name: yum install libselinux-python ansible.builtin.yum: name: libselinux-python state: present register: yum_libselinux_result ignore_errors: yes when: not ( SELinux_result.stdout is search("disabled") ) and not ( rpm_result.stdout is search("libselinux-python*")) # yumでのインストールが失敗に終わった場合、wgetで導入する - name: Setup libselinux-python when: yum_libselinux_result is failed and not ( rpm_result.stdout is search("libselinux-python*")) block: # バージョン差異によって、パッケージ名も変わるためPackage一覧のHTMLを変数に格納 -name: Get OS_version Packages ansible.builtin.uri: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/" method: GET return_content: yes register: packages_content # HTMLの中から「libselinux-python」のrpm名を取得 - name: Extract rpm_name ansible.builtin.set_fact: rpm_name: "{{ packages_content.content | regex_search('libselinux-python-(.*?)\\.x86_64\\.rpm') }}" - ansible.builtin.debug: var: rpm_name # 取得したrpm名でダウンロード - name: Download libselinux-python ansible.builtin.get_url: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/{{ rpm_name }}" dest: "/tmp/{{ rpm_name }}" # yumが使えない状況用のため、rpmでインストール - name: Install libselinux-python ansible.builtin.command: rpm -ivh /tmp/"{{ rpm_name }}"
意図は大体コメントに書いてますが、下記でも説明いたします。
# wget_repo:| default ("http://ftp.iij.ad.jp/pub/linux/centos-vault")
yum が使えない場合、直接リポジトリから libselinux-python を取得します。
その際に利用するリポジトリを変数で指定していますが、指定がない場合は、IIJ社の物を利用している事を最初にコメントで明記しています。
- name:Check SELinux
- name:Check libeselinux-python
SELinux が無効化されている環境では、「libselinux-python」無しで稼働するので不要です。
まずは状態を確認してから判定用の変数に入れています。
また、CentOS 6 が yum が使えない状態を考慮して、Shellモジュールから rpm を使ったインストール済かの確認を行います。
こちらも判定用に変数に保存しています。
- name:yum install libselinux-python
SELinux の状態が「disabled」以外かつ、「libselinux-python」がインストールされていない場合に実行します。
yum モジュールでインストールを試み、導入 or 既にインストール済となればOK。
「yum」が使えずに失敗した場合は「ignore_errors: yes」で続行しつつ、タスクが失敗した事を判定用の変数に入れ、以降のタスクで直接リポジトリから取得を試みます。
- name:Setup libselinux-python
when:yum_libselinux_result is failed
block:
「yum」でのインストールに失敗した場合に実行(when条件)。
直接リポジトリからパッケージを取得して、rpmでインストールするためのタスク群(Block)です。
まずは、 ansible_facts の「ansible_distribution_version」を利用して、OSのマイナーバージョンに一致したリポジトリのディレクトリ階層から、「libselinux-python」の正式なパッケージ名を取得し変数に保存。
その後、その変数を使って get_uri モジュールでダウンロードを行い、 command モジュール経由の rpm でローカルインストールを行います。
実行例
検証環境用インベントリファイル
CentOS 6(bento / centos-6.9) のデフォルトがパスワード認証だった事もありますが、パスワード認証(非推奨です)の環境は存在しうるため、今回はこの状態で検証。
-- all: vars: ansible_user: vagrant hosts: targetnode: ansible_host: 192.168.33.15 ansible_ssh_pass: vagrant
main.yml
main.yml 側でタスクは記述せず、 import_tasks で Playbook を読み込ませる書き方にしています。
(筆者が再利用性・可読性・保守性を高めるために、役割事に Playbook を分けたい派のため)
- name: libselinux-python hosts: targetnode< become: yes vars: wget_repo: "http://ftp.iij.ad.jp/pub/linux/centos-vault" tasks - name: Include libeselinux-python(wget) ansible.builtin.import_tasks: libselinux-python_wget.yml
Playbook 実行
記事においては、以前の Ansible バージョンを搭載したコンテナ上から実行させます。
[root@筆者コンテナ環境 work]# ansible-playbook -i hosts main.yml
最後に
手間は掛かりますが、定型化できる作業を Ansible に落とし込んでみました。
以降は何度も再利用できますし、 Ansible に慣れていく意味でも勉強になったので良かったです。
CentOS 6 環境は「yum」が使えない確率も高く、 Ansible 導入のハードルが高くなりがちなので
この記事を読んだ方に、多少でも Ansible を触るキッカケや役に立つ知識 / 情報となれれば幸いです。
ここまで読んで頂きありがとうございました!
参考資料
ansible.builtin.yum module – Manages packages with the yum package manager
https://docs.ansible.com/ansible/9/collections/ansible/builtin/yum_module.html