An open API service indexing awesome lists of open source software.

https://github.com/devlights/try-ansible

This is a repository for learning Ansible using Gitpod. (for myself)
https://github.com/devlights/try-ansible

ansible docker

Last synced: about 2 months ago
JSON representation

This is a repository for learning Ansible using Gitpod. (for myself)

Awesome Lists containing this project

README

        

# try-ansible
This is a repository for learning Ansible using Gitpod. (for myself)

## How to run

```sh
# This is already done in Gitpod prebuild, so you don't need to do it normally.
$ make build
$ make start

# Enter the container for ansible
$ make exec

ansible@xxxx# ansible-playbook -i inventry.ini apt/playbook.yml
```

## 参考文献

- Ansible 実践ガイド 第3版 (ISBN: 9784295007647)

## 参考情報

- [Goメモ-165 (Go 1.18 Beta1 がリリース)](https://devlights.hatenablog.com/entry/2021/12/15/141759)
- [Docker で環境変数をホストからコンテナに渡す方法](https://qiita.com/KEINOS/items/518610bc2fdf5999acf2)
- [docker-composeの--build-argオプションを利用して、Dockerfileでビルドされるコンテナまで環境変数を渡す](https://qiita.com/yuta_vamdemic/items/7be33ade88a008255930)
- [docker-composeから環境変数をDockerfileに渡す方法](https://qiita.com/Targityen/items/2717511ca9f12c1c667f)
- [Dockerの--initフラグについて](https://christina04.hatenablog.com/entry/docker-init)
- [dockerコンテナ起動時にシェルを実行する](https://qiita.com/ken992/items/872a90736e6af26ef4ab)
- [Dockerのコンテナ起動時にバックグラウンド・プロセスとして動作するデーモンを起動させたい](https://eel3.hatenablog.com/entry/2020/09/12/110814)
- [SSHでログイン出来るコンテナの作り方(Ubuntu18対応版)](https://qiita.com/y-vectorfield/items/587d3f3a6eec8f251f3c)

## メモ

従来のオンプレミス環境におけるインフラ構築作業では、エンジニアが手動で複雑なオペレーションを実施するのが当然だった。

- ハードウェアのセットアップ
- OSのチューニング
- ミドルウェアのセットアップ

などなど

一度構築したものを保守期限が切れるまで長期的に利用し続けるというスタイルを「塩漬け状態」という。

この運用スタイルが一般的であった。(今でも普通に存在するスタイル)

クラウドの登場もあり、インフラリリースを効率よく管理するために開発されたのが、システムオペレーションの自動化ツールである。

以下を解決するためである。

- クラウドリソースのライフサイクルが短く、頻繁に変更される膨大なリソースを手作業で構成管理することが非効率
- クラウドネイティブな設計によって、特定のベンダーに依存しない、移行性の高い運用が必要になった
- インフラリソースがソフトウェアによって抽象化されたため、動的にインフラを扱えるようになった
- 頻繁にシステムの構築と破棄を繰り返しても、同じクオリティのリソース提供が求められる

この恩恵はクラウド環境でなく、オンプレミスな環境でも受けることができる。

### DevOps の 定義

参考文献では、以下のように定義している。

> ビジネスやプロジェクトを成功させるために、組織文化とツールの両面を継続的に改善することで、ビジネスアジリティを向上させ、リスクを低減する活動

#### 例

運用者は独自の自動化ツールで構築作業を行い、出来上がった仮想マシンに対して、開発者は独自の手法でアプリケーションをデプロイする。
役割や責任を分断するという意味では効果的であるが、最終的に特定の人にしか管理できない自動化を生んでしまう。
これでは組織全体のメリットが半減してしまう。
こうした課題を一つずつ可視化し、改善することがDevOpsにおける組織文化の改善。

### Infrastructure as Code (コードによるインフラ構築)

インフラリソースもアプリケーションと同様に、コードで記述された内容をもとに自動で管理しようとする仕組みを

```Infrastructure as Code```

と呼ぶ。

> インフラの構成管理をコードで記述し、ソフトウェア開発で実施されてきた開発プロセスをインフラシステム、アプリケーション、ミドルウェアのデプロイやコンフィギュレーションの管理に適用すること

上記で述べている、ソフトウェア開発のプロセスは、成果対象物のバージョン管理や、繰り返し可能なビルドやテストを意味する。

インフラリソースをコードで操作するということは、そのコード自体が「品質管理」「バージョン管理」「テスト」の対象になるということ。

### Infrastructure as Code の効果

- オペレーション工数の削減

従来、手動で行ってきた作業をコード化、自動化することにより、オペレーション工数及び納期の短縮が期待できる。

- オペレーション品質の向上

運用時に発生する障害のほとんどが単純な作業ミスであり、どのような対策を施しても人が介在する限り、完全に作業ミスを防ぐことは困難。

運用作業をコード化し、自動化することにより、オペレーション品質を均一に保つ効果が期待出来る。

- システム運用の標準の促進

自動化やバージョン管理を適切に行うことにより、システム運用のポリシーや業務標準化を形成できる。

- 作業統制の強化

作業オペレーションを自動化することにより、内部統制やセキュリティ対策面での効果が期待できる。

## Ansible とは

Ansibleは、Python製の構成管理自動化ツール。Ansibleを利用することによって、スクリプトや手動で行っていたオペレーションを自動化し、開発プロセスを効率化できる。

### 特徴

- 設定ファイルの可読性が高い(YAML形式)

Ansible では、処理を記述した設定ファイルは「YAML」形式で記述される。

YAMLの構文が理解できれば、特別なコーディングスキルがなくても、どのような処理を行っているのかを把握できる。

この可読性の高さが、DevOpsを実現するうえでとても重要な要素。

開発者と運用者の間で、「同じ言語を使い」、「同じ知識を学び」、「同じ情報を共有する」という習慣こそが、変化に柔軟な組織文化を創る。

さらに設定ファイルは「ただのテキストファイル」なので、バージョン管理した際に差分も正しく表示できる。

- エージェントレス

Ansibleは、構成管理対象のサーバ(ターゲットサーバ)に、エージェントソフトウェアをインストールする必要がない。

Ansibleが実行する処理内容は、管理サーバからSSH接続を介して安全に送信、実行される。

ターゲットサーバにはPythonがインストールされている必要があるが、現状の有名ディストリビューションは全て最初からPythonがインストールされている。

- マルチレイヤの対応

Ansible は、デフォルトの機能だけでも構成管理対象のレイヤが広い。インフラエンジニア、アプリケーションエンジニアの隔てなく利用できるツールとなっている。

## 冪等性

冪等性(べきとうせい)は、ある操作や同一の設定を、何度繰り返しても、一度行った操作は実行結果が変わらないという概念。

これは、多くの構成管理ツールで実装されている特徴であり、Ansible では各モジュールの中で実装されている。

各種プロダクトを管理する上で、この冪等性が担保されていなければ、思いも寄らない設定トラブルを引き起こしてしまう可能性がある。

冪等性が担保されているツールを利用すれば、何度処理を実行しても同じ結果が得られる。

## Ansibleのアーキテクチャ

Ansibleは、処理の指示を出す「コントロールノード」から、処理の対象となる「ターゲットノード」へSSH経由でタスクを送信する。

ターゲットノード側に特別な設定は不要(Windowsの場合を除く)

コントロールノードに Ansible をインストールして、インベントリ(Inventory)とプレイブック(Playbook)の2つを用意する。

プレイブックを実行する際に利用するコマンドは ```ansible-playbook``` となっている。

```sh
$ ansible-playbook -i インベントリファイル プレイブックファイル
```

## インベントリ

インベントリは、ターゲットノードをリストして記載するファイル。

インベントリに記載されたホストが実行対象となる。

単一のノードだけでなく、グループを定義することも可能。

インベントリは、ターゲットノードの接続情報を記載したファイル。
ターゲットノードのIPアドレスや、ホスト名(FQDN)を列挙することにより対象ホストを特定するため
スタティックインベントリ(Static Inventory) と呼ばれる。

## プレイブック

プレイブックは、ターゲットノード側で実行したい処理の流れを記載するファイル。

このファイルに記載されたタスクが、インベントリに記載されたホスト上で実行される。

プレイブックの定義は YAML の書式で定義する。

## Ansibleでの実行処理

Ansibleは、YAMLのプレイブックをそのまま実行しているわけではなく、実行処理を始める前に
プレイブックをコントロールノード側で ```Python``` の実行コードに変換する。

その後、ターゲットノードに対して ```sftp``` で実行コードを転送後に、ターゲットノード上で実行する。

なので、Ansibleはエージェントレスの実装となっている。つまり、ターゲットノードには ```Python``` の実行環境が必要となっている。

## モジュール

モジュールは、プレイブックやAnsible APIの中で呼ばれる再利用可能な処理ユニット。共通ライブラリという感じ。

モジュールは、特殊なモジュール(例えば Command モジュールなど)を除き、冪等性が担保されている、また再利用可能であることを基本として設計されている。

## プラグイン

プラグインは、Ansibleのコア機能の拡張や、追加機能を提供するコンポーネント。
モジュールは、プレイブックのタスクとして宣言されるが、プラグインはAnsibleを構成するコア機能に付随する。

## Ansible CLI

Ansible CLI とは、Ansibleを利用するためのコマンドラインインターフェースである。
Ansibleを操作するためのコマンドラインとしては2つ用意されており

- ansible
- ansible-playbook

となっている。

```ansible``` コマンドは、アドホック(その場限りの)コマンドで、```ansible-playbook```はプレイブックを利用して一連の処理を流したい場合に利用する。

基本、```ansible-playbook``` を用いて運用する。

### ansible コマンドの例

```sh
$ ansible -i インベントリ ホストグループ -m モジュール名
```

### ansible-playbook コマンドの例

```sh
$ ansible-playbook -i インベントリ プレイブック
```

## Ansible の 設定ファイル (ansible.cfg)

Ansibleの設定ファイルは ```ansible.cfg``` という名前のファイルとなっている。
このファイルは置く場所によって読み込まれる優先順位が異なる。

1. 環境変数 ```ANSIBLE_CONFIG``` にファイルパスを設定

```sh
$ export ANSIBLE_CONFIG=/usr/local/ansible/conf/ansible.cfg
```

2. カレントディレクトリに存在する設定 (./ansible.cfg)

3. ホームディレクトリに存在する設定 ($HOME/.ansible.cfg)

4. ```/etc/ansible/ansible.cfg```

設定ファイルの書き方は以下のようになる。

```ini
[defaults]

forks=15
log_path=$HOME/.ansible/ansible.log
host_key_checking=False
gathering=smart
```

- forks
- ターゲットノードの並列処理を行うプロセス数を設定する
- デフォルト値は5
- log_path
- ansible実行コマンドログの配置場所を指定する。
- host_key_checking
- ターゲットノードにSSH接続する際の公開鍵のフィンガープリントチェックを行うかどうか
- デフォルト値はTrue
- gathering
- ターゲットノードの詳細情報取得に関する設定を行う。
- implicit
- キャッシュが無視され、常に情報収集を行う
- explicit
- キャッシュを利用し、情報収集が行われない
- smart
- 新規に接続した時は情報収集を行い、キャッシュがある場合は情報収集を行わない
- gather_subset
- ターゲットノードの詳細情報取得を制限できる
- all
- 全て
- network
- 最小限の情報とネットワーク情報
- hardware
- ハードウェア情報を収集する
- virtual
- 最小限の情報と仮想マシンに関する情報
- transport
- ターゲットノードへの接続方法の設定
- smart
- OpenSSHが利用できる場合はOpenSSH、そうでなければ Python の Paramiko を利用
- paramiko
- Python のライブラリ。アクションの度にターゲットノードへ接続する
- local
- SSHを利用せずに、直接ローカルホストへ接続する

## プレイブックと実行結果の関係

以下のようなプレイブックがあるとする。

```yaml
- hosts: demo
tasks:
- name: copy file
ansible.builtin.copy:
src: /playbooks/inventory.ini
dest: $HOME
mode: 0644
- name: confirm
ansible.builtin.command:
cmd: ls -l
register: ret
- name: output
ansible.builtin.debug:
msg: "{{ ret.stdout_lines }}"

```

実行すると以下のようになる。

```sh
root@2222164ef5f5:/playbooks# ansible-playbook -i inventory.ini fileop/copy_nobackup/playbook.yml

PLAY [demo] **************************************************************

TASK [Gathering Facts] ***************************************************
ok: [demo001]

TASK [copy file] *********************************************************
changed: [demo001]

TASK [confirm] ***********************************************************
changed: [demo001]

TASK [output] ************************************************************
ok: [demo001] => {
"msg": [
"total 4",
"-rw-r--r-- 1 root root 178 Nov 2 07:52 inventory.ini"
]
}

PLAY RECAP ***************************************************************
demo001 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```

プレイブックの実行は大きく以下に分類される。

### PLAY

ターゲットノードグループ毎に行うタスクのまとまりを示す。1つのプレイブックの中で複数のPLAYを実行することも可能。

### TASK

個々のタスクは、全てのターゲットノードで実行される。タスクがある分だけモジュールが実行される。

### PLAY RECAP

最終的な実行結果が表示される。

意味は以下のようになる。

- ok
- 成功
- 既に定義されている状態となっているため、処理を行わなかった
- changed
- 成功
- タスクで指定したステータスと異なっていたため、変更を行った
- skip
- 成功
- タスクの実行条件に合致しなかったため、処理を行わなかった
- unreachable
- 失敗
- ターゲットノードに接続できなかった
- failed
- 失敗
- タスクを行った結果、エラーが発生し、定義された状態にならなかった