【Ansible 2.12】EOL した CentOS 6 で yum を使えるようにする Playbook
皆様こんにちは。
Ansible で業務効率の改善を図りたいシステムソリューション部所属の なか です。
以前「EOL した CentOS 6 で yum を使えるようにする【リポジトリ変更】 」という記事をかきました。
EOL した CentOS 6 のデフォルトリポジトリは利用不可になっており、yum はエラーで使えません。
そのため、リポジトリを現在も利用可能な物に変更する内容です。
ただ、上記の記事では「手動」での変更作業でした。
もし CentOS 6 のサーバーが複数存在する環境だと、「手動」で全台対応するのは骨が折れます。
また、複数台を手動だと事故の確率も高いため、「コード」で対応させたいと思います。
今回は、「コード」「Ansible」の「EOLした CentOS 6 で yum を使えるようにする Playbook 」を紹介&実行方法の解説となります。
前置き
- CentOS 6 での運用を推奨している訳ではございません。
あくまでもやむを得ない理由で存在する、CentOS 6 への応急対応用となります。 - サポートがなくなったバージョンを利用しています。
こちらも応急対応用であり、推奨する意図はございません。
前提の説明
Q. なぜ Playbook で変更させるの?
A.
1.「手動だと作業台数に比例して、作業時間も拡大していくため」
→ Ansible であれば台数が増えても、手動に比べれば非常に短い時間で対応可能です。
そのため、台数が多くなるほど作業効率が非常に良いです。作業に人員が1日張り付きになるのを避ける事ができます。
2.「複数台への手動作業は、事故が起こりやすいため」
→ 作業を連続で行っていると、どうしても流れ作業になりがちで、作業ミスが非常に起こりやすくなります。これを Playbook 化する事で、全台に対してミスなく同じ変更作業が行えます。
3.「Playbook も手順書として再利用・継承できるため」
→ 手順書が残らないケース・流用するにも修正が必要なケースがあります。
ですが、Playbook であれば、対象を変えるだけでそのまま利用できる事が多く「腐りにくい」です。
Q. (それでも)手動でやりたい場合は?
A. 以前書いた記事にて手動手順を解説しています。
コチラをご参考ください。
Q. 「(libselinux-python) aren't installed!」エラーが出たら手動の方が楽そう
A. このエラーは、SELinux が完全に無効化されていない状態かつ「libselinux-python」パッケージがない場合に起きる物と存じます。
「エラー修正のために手動で作業した流れでやってしまう方が楽」
といった本末転倒は起きやすいでしょう。そのため、併用できる解決用 Playbook を、前回の記事で紹介しておりますので、ご活用ください。
【Ansible】CentOS 6 用「(libselinux-python) aren't installed!」解決 Playbook
実行環境
■ Linux 環境
OS : AlmaLinux release 8.10(WSL2環境)
Shell : Bash
Docker version 26.1.3, build b72abbb■ 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
手動の作業で実施していた
・「リポジトリのバックアップ」
・「バージョンの指定」
・「 Base リポジトリの書き換え」
・「 yum キャッシュの削除」
上記4ステップを、1枚の Playbook に落とし込みました。
centos6_repo_change.yml
main.yml 側で import_tasks 使って、この Playbook を読み込む形式にしています。
(筆者が再利用性・可読性・保守性を高めるために、役割事に Playbook を分けたい派のため)
--- ## 変数default # repo_source | default('/etc/yum.repos.d/CentOS-Base.repo') # repo_dest | default(default_repo_path) # repo_url | default('http://ftp.iij.ad.jp/pub/linux/centos-vault/$releasever')" # Base.repoバックアップ # 当日のバックアップが既に存在している場合は取得しない - name: Check backup for base.repo ansible.builtin.stat: path: "{{ repo_dest | default('/etc/yum.repos.d/CentOS-Base.repo_' + lookup('pipe', 'date +\"%Y%m%d\"')) }}" register: backup_base_repo_result< - name: Backup base.repo ansible.builtin.copy: src: "{{ repo_source | default('/etc/yum.repos.d/CentOS-Base.repo') }}" dest: "{{ repo_dest | default('/etc/yum.repos.d/CentOS-Base.repo_' + lookup('pipe', 'date +\"%Y%m%d\"')) }}" mode: "0644" remote_src: yes when: not backup_base_repo_result.stat.exists # releaseverが存在しない場合、現状バージョン数値を入れて作成 - name: Set releasever ansible.builtin.shell: cmd: echo "{{ ansible_distribution_version }}" > /etc/yum/vars/releasever args: creates: /etc/yum/vars/releasever - ansible.builtin.debug: var: ansible_distribution_version # repoのmirrorlistをコメントアウト&baseurlを利用可能なリポジトリに書き換えて有効化 - name: Replace mirrorlist ansible.builtin.replace: path: "{{ repo_source | default('/etc/yum.repos.d/CentOS-Base.repo') }}" regexp: "{{ item.regexp }}" replace: "{{ item.replace }}" loop: - regexp: '^mirrorlist=http://mirrorlist.centos.org' replace: '#mirrorlist=http://mirrorlist.centos.org' - regexp: '^#baseurl=http://mirror.centos.org/centos/\$releasever' replace: "baseurl={{ repo_url | default('http://ftp.iij.ad.jp/pub/linux/centos-vault/$releasever') }}" register: replace_result # リポジトリを変更した際は、yumのキャッシュを削除 - name: Clean yum cache ansible.builtin.command: cmd: yum clean all when: replace_result is changed
## 変数 default
変数の default値を明示。
別途 vars関係で指定したい際に、把握しやすくするための目安としても記載しています。
# Base.repo バックアップ
stat モジュールで存在を確認して、register で変数に格納します。
それを when で判定を行って当日のリポジトリのバックアップが無いとなれば取得します。
以降もパス先やリポジトリ等は、変数化かつ default フィルターで、変数の default 値を指定。
加えて、 lookup プラグインを使ったバックアップについては、ファイル名に年・月・日を末尾に加えて、”判別しやすくなる”ように設定しました。
# releasever が存在しない場合、現状バージョン数値を入れて作成
yum を利用する際にバージョンを固定するため、変数ファイルを作成します。
ansible.builtin.shell モジュールを使い、判定と処理を行っています。
この モジュールは OS側の機能を使うため、冪等性のチェックが行われません。
しかし、 args -> creates パラメータにて 「指定ファイル存在しない場合には実行しないという」条件で指定できるため、意図した状況に制御できるため利用いたしました。
ansible_distribution_version
Ansible 側のファクト変数の一部「ansible_distribution_version」を使う事で、実行環境の現在のOSバージョン(今回だと6.9)を取得できます。
上記を使い echo コマンド経由で ファイルを作成する処理にしています。
念の為、 ansible.builtin.debug モジュールで、変数の中身をコンソールに表示させます。
# repo の mirrorlist をコメントアウト & baseurl を利用可能なリポジトリに書き換えて有効化
ansible.builtin.replace モジュールで、表題のように2箇所を書き換えています。
手動の手順時に sed コマンドで書き換えている部分に相当しています。
2箇所を指定するために、 loop を使用していますが with_items でも実行可能です。
実行結果を register で保存し、次の処理の when で利用します。
# リポジトリを変更した際は、yumのキャッシュを削除
when: replace_result is changed
yum のキャッシュの削除する yum clean all に相当する機能が、yum モジュールにはありません。
そのため、shell と同じくOSのコマンドを実行する、ansible.builtin.command モジュールを利用しています。
先程のリポジトリを書き換える replace モジュールを使用した際の結果を register で保存し、「changed」(変更)が確認できた場合のみ実行するようにしています。
余談: shell モジュールと Command モジュールの違い
Shell モジュールは Shell 経由のため、OS内の環境変数やパイプ等の利用が可能です。
環境内で普段使っているようなワンライナー等も実行可能なので便利です。
Command モジュールは Shell を経由しないため、環境変数等は利用できない仕様です。
これは利点でもあり、環境特有の変数によって、意図しない動作を行う可能性をなくせます。
ただし、これらは Ansible ではなく 対象OSのコマンドを利用しているため冪等性が確保できません。
あくまでモジュールで対応できない場合の最終手段となります。
実行例
検証環境用インベントリファイル
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 を分けたい派のため)
変数については、Playbook 内の default で指定した値を使用しているため、未指定でも実行可能です。
ただし変数で変更可能な項目・内容について、直感的にわかりやすいと考えて敢えて記載しています。
- name: main.yml hosts: targetnode become: yes vars: wget_repo: "http://ftp.iij.ad.jp/pub/linux/centos-vault" repo_source: "/etc/yum.repos.d/CentOS-Base.repo" repo_dest: "/etc/yum.repos.d/CentOS-Base.repo_{{ lookup('pipe', 'date +\"%Y%m%d\"') }}" repo_url: '{{ wget_repo }}/$releasever' tasks: #SELinuxがdisabled以外かつ、libselinux-pythonが無い場合に導入する - name: Include libeselinux-python(wget) ansible.builtin.import_tasks: libselinux-python_wget.yml #Centos6のBaseの初期リポジトリを変更する - name: Include centos6_repo_change ansible.builtin.import_tasks: centos6_repo_change.yml
libselinux-python_wget.yml は、上で紹介した前回記事、SElinux 関係のエラー対策のための Playbook です。
centos6_repo_change.yml が今回紹介した Playbook となります。
Playbook 実行
記事においては、上記で紹介した別記事の、以前の Ansible バージョンを搭載したコンテナ上から実行させます。
実行前に検証機で yum が使えないことを確認してから実行。
■事前確認 [vagrant@targetnode ~]$ yum info php Loaded plugins: fastestmirror Determining fastest mirrors Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os&infra=stock error was 14: PYCURL ERROR 6 - "Couldn't resolve host 'mirrorlist.centos.org'" Error: Cannot find a valid baseurl for repo: base ※リポジトリが使えなくなっているためエラーが出て使えません
■Playbook実行 [root@筆者コンテナ環境 work]# ansible-playbook -i hosts main.yml ~省略~ PLAY RECAP ************************************************************************************************************************** targetnode : ok=17 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=2 ※2つのPlaybookの結果が出力されています
■事後確認 [vagrant@targetnode ~]$ yum info php Loaded plugins: fastestmirror Determining fastest mirrors base | 3.7 kB 00:00 base/primary_db | 4.7 MB 00:00 extras | 3.4 kB 00:00 extras/primary_db | 30 kB 00:00 updates | 3.4 kB 00:00 updates/primary_db | 8.1 MB 00:00 Available Packages Name : php Arch : x86_64 Version : 5.3.3 ~省略~
Playbook 実行後の状態では、リポジトリのエラーが解消されメタデータの取得が行われています。
その後に yum info php の結果が出力されていますので、無事 yum が使えるようになった事が確認できました。
最後に
以前実際に、Ansible で何とかした時の経験を元に書いたのが今回の内容となります。
当時の Playbook は急いで作った事で、今より荒い内容で再利用性が低い物でしたが、今回ブログに書くにあたり改善出来て良かったです。
何事も対応が必要になった際に用意すると慌てますし、その場でしか使えない物になりがちかなと思います。
余裕があるときには、汎用的な内容の Playbook は用意しておくと良いかもしれません。
この記事を読んだ方に、多少でも Ansible を触るキッカケや役に立つ知識/情報やお役に立てれば幸いです。
ここまで読んで頂きありがとうございました!
参考資料
ansible.builtin.yum module – Manages packages with the yum package manager
https://docs.ansible.com/ansible/9/collections/ansible/builtin/yum_module.html
ansible.builtin.replace module – Replace all instances of a particular string in a file using a back-referenced regular expression
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
CentOS 6 リポジトリ アドレスを変更するにはどうすればよいですか? | Alibaba Cloud
https://www.alibabacloud.com/help/en/ecs/user-guide/change-the-centos-6-source-address