はじめに
インフラエンジニアの長田です。これまでマイクロアドのインフラ環境ではCentOS7を使っていましたが、現在はUbuntu20.04への乗り換えを順次進めています。
それに伴い、CentOS用に作ってきたAnsibleロールのUbuntu対応やGitHubリポジトリの構成見直し、新しいバージョンのAnsibleへの追随など様々なリファクタリングを進めています。
また、複数のansible-core、Moleculeバージョンで同時にテストするために、Pythonのテスト用仮想環境を管理するtoxというツールを活用しています。
Ubuntuへの対応
これまでマイクロアドのインフラ環境ではCentOS7を使っていましたが、現在はUbuntuへの乗り換えを順次進めています。 それにあたり、これまでCentOS用に作り込んでいたAnsibleロールをUbuntuでも動作するように作り替える必要があり、以下のような修正をしています。
varsディレクトリ配下に、OS毎に異なるファイルパスなどを定義する変数ファイルを作成するtasksディレクトリ配下に、OS別のタスクファイルを作成するtasks/main.ymlに、上記のファイルをincludeするタスクを記述する
以下は、PostgreSQLをインストールするロールからOS毎に異なる内容の抜粋です。OSのディストリビューション名を取得する変数 ansible_distribution によって、includeする変数ファイルとタスクファイルを分岐させています。
- defaults/main.yml (OS共通のデフォルト変数)
--- postgresql_version: 14
- vars/CentOS.yml
--- postgresql_datadir: "/var/lib/pgsql/data"
- vars/Ubuntu.yml
--- postgresql_datadir: "/var/lib/postgresql/{{ postgresql_version }}/main"
- tasks/package-CentOS.yml
--- - name: PostgreSQLをインストール ansible.builtin.package: name: - "postgresql{{ postgresql_version }}" - "postgresql{{ postgresql_version }}-devel" - "postgresql{{ postgresql_version }}-server" - "postgresql{{ postgresql_version }}-libs" - "postgresql{{ postgresql_version }}-contrib"
- tasks/package-Ubuntu.yml
--- - name: PostgreSQLをインストール ansible.builtin.apt: name: - "postgresql-{{ postgresql_version }}" - "postgresql-client-{{ postgresql_version }}" - "postgresql-client-common" - "postgresql-common" state: present update_cache: true
- tasks/main.yml
--- - name: OS毎の変数を取得 ansible.builtin.include_vars: "{{ ansible_distribution }}.yml" - name: OS毎のインストールタスクを実行 ansible.builtin.include_tasks: "package-{{ ansible_distribution }}.yml"
ロールのリポジトリ分離
これまで、マイクロアドのインフラチームで管理しているAnsibleのリソースはgroup_varsやロール、プレイブックを含め、全て単一のリポジトリで管理していました。
しかし、CIによるテストの動作制御や、後述する複数バージョンのansible-core、Moleculeでのテストが行いずらいといった問題が生じてきました。そこで、ロールについては1ロール1リポジトリの形式に分離することとしました。
これにより、ロール毎に異なるバージョンでのCI実行が容易になり、移植性が向上しました。
- 既存のリソース構成(抜粋)
. ├── group_vars │ └── some_host ├── roles │ └── some_role └── playbook.yml
- リポジトリ分離後のリソース構成
# ansibleリポジトリ . ├── group_vars │ └── some_host ├── roles │ └── requirements.yml └── playbook.yml
- 分離したロールのリポジトリ(抜粋)
.
├── README.md
├── defaults
│ └── main.yml
├── meta
│ └── main.yml
├── molecule
├── tasks
│ ├── main.yml
│ ├── package-CentOS.yml
│ └── package-Ubuntu.yml
├── tox.ini
└── vars
├── CentOS.yml
└── Ubuntu.yml
roles/requirements.ymlには、リポジトリ分離したロールをインストールするための情報を記載しています。ロール名の先頭には ma_ansible というnamespaceを付与し、次に説明する meta/main.yml の記述と一致させてロールをインストールできるようにします。
--- roles: - name: "ma_ansible.some_role" src: "git+<ロールリポジトリのURL>"
また、リポジトリ分離したロール側には meta/main.yml を作成し、元のリポジトリからCollectionとしてインストールできるようにしています。この中の namespace に、上述した ma_ansible を指定します。
--- galaxy_info: role_name: "some_role" namespace: ma_ansible company: MicroAd, Inc. author: "Yasuhiro Nagata" description: "〇〇〇をインストールするロール" license: "MicroAd, Inc." platforms: - name: EL versions: - '7' - name: Ubuntu versions: - focal min_ansible_version: 2.9.27
ansible-coreおよびMoleculeのアップグレード、複数バージョンでの同時テスト
現在、マイクロアドでは主にansible-core 2.9を使っていますが、すでにEOLを迎えているため、アップグレードを進めています。
理想的には最新バージョンを使用したいですが、Python3.9以上のバージョンが必要です。テスト環境で複数バージョンのPythonを使用する方法が定まっていないため、ひとまず現環境で使用しているPython3.8で動作するansible-core 2.12へアップグレードしています。
マイクロアドでは全てのAnsibleロールにMoleculeでのテストを実装しており、こちらについても新しいバージョンへの追従を進めています。
Moleculeの最新バージョンは直近2つのメジャーバージョンしかサポートしないため、一旦はansible-core 2.12に合わせたもので動作する内容に作り替えています。
この際、上述したtoxを使って molecule test を実行しています。toxの仮想環境設定は以下のようなiniファイルで行っています。
- tox.ini
[tox]
envlist = py38-ansible{209,212}
skipsdist = true
[testenv]
parallel_show_output = true
deps =
#ansible-core 2.9
ansible209: ansible==2.9.27
ansible209: rich<11.0.0
ansible209: ansible-lint==4.3.7
ansible209: jmespath==0.9.5
ansible209: molecule==3.2.4
# ansible-core 2.12
ansible212: ansible==5.10
ansible212: ansible-lint==6.12.2
ansible212: jmespath
ansible212: molecule==3.6
-r {toxinidir}/requirements_tox.txt
setenv =
PATH = {toxworkdir}/bin{:}{env:PATH}
ANSIBLE_FORCE_COLOR = True
ROLE_CURDIR={env:ROLE_CURDIR}
TEST_ENVNAME={envname}
MOLECULE_EPHEMERAL_DIRECTORY={toxworkdir}/tmp/{envname}
PY_COLORS={env:color}
commands =
molecule test
CIでのテストは、Makefileのタスクを呼び出してtoxを実行しています。また、ローカルでテストする場合、テストが失敗した場合にMolecule実行環境のコンテナ内がどうなっているかを確認したいケースがあるため、venvで仮想環境を構築する方法も併用しています。Makefileのタスクでvenv環境の構築と、 molecule test --destroy=never 相当のコマンドを実行できるようにしています。
- Makefile
# CIで実行するタスク
.PHONY: test
test:
@tox --parallel --quiet --parallel-live true auto
# ローカル実行用venv環境の構築
.PHONY: venv-init
venv-init:
ifeq ($(shell uname),Linux)
# Ubuntu
ifeq ($(shell source /etc/os-release && echo "$$ID"),ubuntu)
@python3 -m venv .venv && \
source .venv/bin/activate && \
.venv/bin/pip install --upgrade pip && \
.venv/bin/pip install -r requirements_venv.txt ;
endif
# macOSの場合
else ifeq ($(shell uname),Darwin)
@python3 -m venv .venv && \
source .venv/bin/activate && \
.venv/bin/pip install --upgrade pip && \
.venv/bin/pip install -r requirements_venv.txt ;
endif
# テスト実行用コマンド(moleculeコンテナを削除しない)
.PHONY: test-destroy-never
test-destroy-never:
@TEST_ENVNAME=py38-ansible209 molecule test --destroy=never
おわりに
今後、Ubuntu22.04への対応や更に先のansible-coreのバージョンへのアップグレードも進めたいと考えています。
インフラのコードも放置すれば技術的負債となりかねないため、これからも改善を進めていきます。