はじめに
こんにちはnaya(@NayaTaiyo)です。前回はVagrantでWordPressを構築しましたが、今回はAnsibleを利用して、ユーザー作成とSSH鍵認証を自動化してみました。Ansibleは汎用性が高く、人によって設定方法が異なるため、本手順に記載のある設定方法はあくまでも参考までにご確認いただければと思います。
Ansibleとは
Ansibleは、サーバやネットワーク機器などの構築を自動化するためのOSSツールです。SSHエージェントレスでのデプロイとシンプルなyamlファイルで実装することができます。以下IaCについて説明します。
- Infrastructure as Code(IaC)とは?
従来は手動で設定していたインフラの構成や管理を、コードとして定義・Gitで管理する手法です。IaCを使うと、サーバーやネットワーク、データベース、といったインフラ要素のプロビジョニングや設定をコードベースで自動化・統一化できます。
Ansibleの基本用語
- インベントリ(hosts)
インベントリは、Ansibleが管理する対象ホストの一覧を定義したファイルです。ホストをグループ化することで、特定のサーバー群に対して操作を行うことができます。本記事では、hosts
ファイルのことを指します。また、hosts
で指定したホスト環境で使用できる変数を定義する group_vars
ディレクトリもあります。
- 設定ファイル(ansible.cfg)
ansible.cfg
は、Ansibleの動作に関する設定を記述するファイルです。
- モジュール(Module)
モジュールは、Ansibleが実行する個々の機能や操作を定義したものです。ユーザーの作成やパッケージのインストールなど、さまざまなタスクを実行するためのモジュールが用意されています。
- タスク(Task)
タスクは、モジュールを使用して実行される具体的な操作です。Playbook内で順番に定義され、上から順に実行されます。
- プレイブック(Playbook)
プレイブックは、YAML形式で記述された設定ファイルで、実行するタスクの一覧を定義します。Playbookを実行することで、指定したタスクが対象ホストに適用されます。
- ロール(Role)
Ansibleの「ロール(Role)」は、Ansibleプレイブックの設定やタスクを再利用可能な単位にまとめる機能です。ロールは、特定の目的の設定を整理し、複雑なインフラ構成を管理しやすくするために使用されます。ロールを使うことで、設定の再利用が容易になり、可読性が向上します。
構築環境
- ホストOS: Windows11
- Vagrant 2.4.1
- VirtualBox 7.0.14
- リモートマシンOS:Linux
- Amazon Linux 2 202404.23.0版
- Vagrantfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Vagrant.configure(2) do |config| config.ssh.insert_key = false config.vm.define "dev_techbull" do |dev_techbull| dev_techbull.vm.hostname = "wp.techbull.cloud" dev_techbull.vm.box = "bento/amazonlinux-2" dev_techbull.vm.network "private_network", ip: "192.168.50.4" end config.vm.define "ansible01" do |ansible01| ansible01.vm.hostname = "ansible01" ansible01.vm.box = "bento/amazonlinux-2" ansible01.vm.network "private_network", ip: "192.168.50.5" ansible01.vm.synced_folder ".", "/home/techbull/techbull", owner: "techbull", group: "techbull" end end |
ディレクトリ構造
本記事のディレクトリ構造になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
project_root/ ├── ansible.cfg ├── playbook.yml ├── inventory/ │ ├── hosts │ └── group_vars/ │ └── all.yml └── roles/ ├── user/ │ ├── tasks/ │ │ └── main.yml │ └── vars/ │ └── main.yml │ └── password.yml └── ssh/ ├── files/ │ └── sshd_config ├── handlers/ │ └── main.yml ├── tasks/ │ └── main.yml └── vars/ └── main.yml |
Ansible実装手順
- Ansibleのインストール
まず、Ansibleを管理用PCやサーバーにインストールします。ここでは、Amazon Linux2を例に説明します。なお、仮想マシンについては接続設定はすでに設定されており、互いに通信ができる状態です。
1 2 |
# yum install [epelリポジトリパッケージのリンク] # yum install ansible |
- インベントリファイルの作成
対象ホストを定義するインベントリファイルを作成します。デフォルトでは/etc/ansible/hosts
が使用されますが、独自のファイルを作成することも可能です。例として、project_root/inventory/
配下にhosts
というファイルを作成します。
1 |
$ vi project_root/inventory/hosts |
1 2 3 |
[web] #Ansibleで接続する対象ホスト名 wp.techbull.cloud |
- ansible.cfgの作成(project_root/ansible.cfg)
対象ホストを定義したhostsファイルだけだと、playbook動作時に読み込まないためproject_root/
配下にansible.cfg
を作成して設定を記載します。
1 2 3 4 5 6 7 8 |
[defaults] inventory = ~/project_root/inventory/hosts log_path = /var/log/ansible.log interpreter_python = auto_silent [privilege_escalation] become = True [ssh_connection] scp_if_ssh = True |
[説明]
- inventory ={ファイルパス}
- インベントリファイルのパスを指定
- log_path = {ファイルパス}
- Ansibleのログファイルの出力先を指定
- interpreter_python = auto_silent
- Pythonインタープリタを自動で選択し、警告メッセージを表示しない設定。
- become = {True/false}
- Ansibleのタスクをrootで実行
- scp_if_ssh = {True/false}
- ファイル転送メソッドとしてscpを使用
※ansible.cfgについての注意
こちらのansible.cfgについてはアクセス権限777を与えるとplaybookを実行時にエラーが起きてしまうのと、以下の読み込みの優先順位があるため気を付けましょう。
- ANSIBLE_CONFIG (環境変数にansible.cfgのパスが設定されている場合)
- ansible.cfg (現在のディレクトリー)
- ~/.ansible.cfg (ホームディレクトリー)
- /etc/ansible/ansible.cfg
例えば、ANSIBLE_CONFIG
に設定されているパスがproject_root/ansible/ansible.cfg
の場合は、現在のディレクトリがproject_root/
配下であってもplaybook実行時に優先的にANSIBLE_CONFIG
に格納されているパスのansible.cfg
を読み込んでしまうので注意。
- group_varsの作成
- project_root/group_vars/all.yml
1 2 3 4 5 |
--- #ユーザー名とグループ名のリストを作成 user_group_lists: - username: "techbull" groupname: "techbull" |
- Playbookの作成(project_root/playbook.yml)
ユーザーの新規作成、SSH鍵認証を設定するするためのplaybookを作成します。ファイル名はplaybook.ymlとします。
1 2 3 4 5 6 |
--- - name: add user and ssh key authentication hosts: all roles: - user - ssh |
[説明]
- name: {タスク名}
- タスク名を指定
- hosts: {ホスト名/ホストグループ名/all}
- playbook実行対象ホスト名/ホストグループ名を指定。allだと全ホスト
- roles: {ロール名}
- playbook実行ロールの指定
各ロールの設定を行う
- userロール(project_root/roles/user/vars/main.yml)
新規ユーザの追加を行うロールファイルの作成を行います。
1 2 3 |
--- #コマンド実行権限を付与するユーザ名を指定 sudoers_user: "techbull" |
- project_root/roles/user/tasks/main.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
--- # vars配下にある変数定義ファイルを呼び出し - name: Load variables from file include_vars: file: vars/main.yml # リモートマシンの/etc/sudoersファイルに指定ユーザーへのコマンド権限を付与設定を追記 - name: command permission grant lineinfile: path: /etc/sudoers line: "{{ item }}" state: present validate: 'visudo -cf %s' loop: - "{{ sudoers_user }} ALL=(ALL) NOPASSWD:ALL" - name: create group group: name: "{{ item.groupname }}" state: present loop: "{{ user_group_lists }}" # ユーザ作成後パスワード更新 - name: create user user: name: "{{ item.username }}" group: "{{ item.groupname }}" password: "{{ user_password | password_hash('sha512') }}" shell: /bin/bash state: present update_password: on_create loop: "{{ user_group_lists }}" |
[説明]
- lineinfile:
- ファイルの編集、追記、削除を行う
- group:
- playbook実行対象ホスト名/ホストグループ名を指定。allだと全ホスト
- user:
- 新規ユーザーの設定と作成
- loop:
- 同じ処理を複数回繰り返すために使用する機能”{{ item }}”や”{{ item.変数名 }}”で値を取り出す
- path: {ファイルパス}
- lineinfileの対象ファイルパス
- line: {編集する内容}
- ファイルの編集内容
- state: {present/absent}
present
は存在しない場合は作成や追記。absent
は存在する場合は削除。
- validate: {オプション}
- 指定したファイルの構文エラーチェックを行う
- password :{ パスワード | password_hash(‘sha512’) }
- ユーザのパスワードを設定。パスワードは
SHA512
などで暗号化された形式で指定する必要があります。
- ユーザのパスワードを設定。パスワードは
- shell: {シェルのパス}
- ユーザーが使用するデフォルトのシェルを指定
- update_password: {always/on_create/no}
- パスワードを更新する。
always
は毎回更新、on_create
は初回設定時のみ更新、no
は更新しない
- パスワードを更新する。
※loop処理を使用している理由は、作成するユーザーやグループが増えた場合を想定して追加しております。
- sshロールの作成
ssh公開鍵認証の設定を行うロールのファイルを作成します。
- project_root/roles/ssh/vars/main.yml
1 2 |
--- ssh_key: "{{ lookup('file', '/home/ユーザ名/.ssh/authorized_keys') }}" |
lookupでauthorized_keysファイルの中身を出力して結果をssh_keyに格納
- project_root/roles/user/vars/password.yml
1 2 3 |
--- #更新用パスワード user_password: "hoge" |
- project_root/roles/ssh/files/sshd_config
1 2 3 4 5 6 7 8 |
HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key SyslogFacility AUTHPRIV PermitRootLogin no PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys |
[説明]
- HostKey{鍵ファイルパス}
- サーバーが使用するホストキーのファイルパス
- SyslogFacility {ログファシリティ}
- SSHサーバーがログを出力するログファシリティ
- PermitRootLogin yes/no
- rootユーザでのSSHログイン有/無
- PubkeyAuthentication yes/no
- 公開鍵認証有/無
- AuthorizedKeysFile {ファイルパス}
- 公開鍵ファイルのファイルパス
- project_root/roles/ssh/tasks/main.yml
1 2 3 4 5 6 7 8 9 10 |
--- #wp.techbull.cloudにsshd_configをコピー - name: copy sshd_config copy: src: "{{ item.src }}" dest: "/etc/ssh/{{ item.dest }}" loop: - { src: roles/ssh/files/sshd_config, dest: . } #sshd.serviceの再起動 notify: Restart SSH |
- project_root/roles/ssh/handlers/main.yml
1 2 3 4 5 |
--- - name: Restart SSH systemd: name: sshd state: restarted |
- playbookの実行
1 |
$ cd ~/project_root/ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ ansible-playbook playbook.yml PLAY [add user and ssh key authentication] ****************************************************** TASK [Gathering Facts] ************************************************************************** ok: [wp.techbull.cloud] TASK [user : Load variables from file] ********************************************************** TASK [user : lineinfile] ************************************************************************ changed: [wp.techbull.cloud] => (item=techull ALL=(ALL) NOPASSWD:ALL) TASK [user : create group] ********************************************************************** changed: [wp.techbull.cloud] => (item={u'username': u'techull', u'groupname': u'techull'}) TASK [create user] ****************************************************************************** changed: [wp.techbull.cloud] => (item={u'username': u'techull', u'groupname': u'techull'}) TASK [Add SSh key for the user] ***************************************************************** changed: [wp.techbull.cloud] => (item={u'username': u'techull', u'groupname': u'techull'}) TASK [copy sshd_config] ************************************************************************* changed: [wp.techbull.cloud] => (item={u'dest': u'.', u'src': u'roles/ssh/files/sshd_config'}) RUNNING HANDLER [ssh : Restart SSH] ************************************************************* changed: [wp.techbull.cloud] PLAY RECAP ************************************************************************************** wp.techbull.cloud : ok=8 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 |
まとめ
Ansibleを使用することで、複数のサーバーに対して一括でユーザーを作成するなど、管理作業を効率化できます。本記事では、Ansibleの基本用語とともに、新規ユーザーを作成する手順とSSH鍵認証の設定を紹介しました。
また、Ansibleでは数多くのモジュールを実装しているのでこれを機に、様々なモジュールを使って実装してみるのも面白いと思います!私は、コードを書く経験が今までほとんどなかったので、勉強したての時はエラーが発生しまくりでとても苦戦した記憶がありました。コードへの理解は数をこなして勉強していくのが大事だと思うので最初は苦戦するかもですが皆さんもぜひ一緒に学んでいきましょう!
■参考リンク
2000年生まれ。社会人2年目の駆け出しエンジニア。SESにてインフラエンジニアとして従事。この先、設計や構築の案件に関われるようなエンジニアになりたいという思いからTechBullに加入し、日々勉強中。主に駆け出しエンジニアに向けて、手助けになるような記事を執筆中。