Skip to content

Ansible+Serverspecコンテナを作成

サーバ構築およびパラメータ確認を目的とした自動化コンテナを作成する。

1. podmanインストール

rootでpodmanをインストールする。

dnf install -y podman

2. TERAIAコンテナを作成する

ディレクトリ構成

TERAIA_container
├── Dockerfile
└── TERASOLUNA_IA_Core_v2.4.0.zip

Dockerfile

# ベースイメージ
FROM quay.io/centos/centos:stream9

# パッケージインストール
RUN dnf install -y epel-release && \
    dnf install -y unzip tar jq && \
    dnf install -y ansible python3-pip && \
    dnf install -y ruby ruby-devel gcc make redhat-rpm-config && \
    rm -rf /var/cashe/dnf && \
    pip3 install pywinrm && \
    gem install serverspec rake highline winrm ed25519 bcrypt_pbkdf rexml && \
    ansible-galaxy collection install ansible.windows community.windows

# ZIPファイルをコンテナ内にコピー
COPY TERASOLUNA_IA_Core_v2.4.0.zip /workdir/TERASOLUNA_IA_Core_v2.4.0.zip

# ZIPファイルを解凍し、setup.shに実行権限を付与する
RUN unzip /workdir/TERASOLUNA_IA_Core_v2.4.0.zip -d /workdir && \
    chmod +x /workdir/TERASOLUNA_IA_Core_v2.4.0/setup.sh

# setup.shを適切なディレクトリで実行する
RUN cd /workdir/TERASOLUNA_IA_Core_v2.4.0 && \
    ./setup.sh && \
    rm -rf /workdir


# コンテナを実行する際のコマンド (bashシェルを実行)
CMD ["/bin/bash"]

ビルド

# ビルド
podman build -t teraia-container .
# 確認
podman images

コンテナ起動(終了はCtrl+D)

podman run --rm -it teraia-container

特定のディレクトリをマウントしてコンテナ起動

# ディレクトリ作成
mkdir -p /tmp/TERA_IA
# 権限付与
chmod -R 777 /tmp/TERA_IA

# 起動
podman run --rm -it --userns=keep-id -v /tmp/TERA_IA:/TERA_IA:Z teraia-container
  • --userns=keep-id:ホストのユーザーIDとグループIDを保持するオプション。このオプションを使用することで、ホストOSのディレクトリの所有者と同じIDをコンテナ内で使用します。
  • -v /tmp/TERA_IA:/TERA_IA:Z:ホストの/tmp/TERA_IAディレクトリをコンテナの/TERA_IAディレクトリにマウントし、SELinuxのセキュリティコンテキストを適切に設定します。(Zオプションが必要)

コンテナイメージを保存してファイルにする。

# エクスポートしてファイルに保存
podman save -o teraia_container.tar localhost/teraia-container

# インポート
podman load -i teraia_container.tar

GCSへのアップロード

サーバから直接ファイルをダウンロードする場合は時間を要する場合があるため、Cloud Storage等のストレージを経由する。 以下コマンドでアップロードができる。

gsutil cp teraia_container.tar gs://【バケット名】

資材の作成

playbookなどの資材を集めたディレクトリを、コンテナを動作させるホストOSに以下のように作成する。

/var/TERA_IA/playbooks/RHEL8
├── ansible.cfg
├── base.yml
├── CHANGELOG.md
├── ENV.yml
├── inventories
│   ├── group_vars
│   ├── hosts
│   └── host_vars     // SDFファイルからansibleで解釈可能なファイルが自動生成される
│       ├── NSON_RHEL92.yml
│       └── CSC_RHEL92.yml
├── res_ansible-playbook.log
├── roles
│   └── RHEL8
│       ├── defaults
│       │   └── main.yml
│       ├── tasks     // RHEL84_original.sdfで賄えないパラメータは、playbookを作成してここに入れる
│       │   ├── anacrontab.yml
│       │   ├── cron_daily.yml
│       │   ├── cron_d.yml
│       │   ├── cron_hourly.yml
│       │   ├── crontab.yml
│       │   ├── default_target.yml
│       │   ├── directories.yml
│       │   ├── group.yml
│       │   ├── grub.yml
│       │   ├── hostname.yml
│       │   ├── hosts_file.yml
│       │   ├── interfaces.yml
│       │   ├── journald.yml
│       │   ├── kdump.yml
│       │   ├── logrotate.yml
│       │   ├── main.yml
│       │   ├── NetworkManager.yml
│       │   ├── nsswitch_conf.yml
│       │   ├── NTP.yml
│       │   ├── packages_DNF.yml
│       │   ├── packages_groups.yml
│       │   ├── PAM.yml
│       │   ├── profile.yml
│       │   ├── resolv_conf.yml
│       │   ├── rsyslog.yml
│       │   ├── selinux.yml
│       │   ├── services.yml
│       │   ├── snmpd_conf.yml
│       │   ├── snmpd.yml
│       │   ├── sshd_config.yml
│       │   ├── sudoers.yml
│       │   ├── tuned.yml
│       │   ├── user.yml
│       │   └── yum_repos.yml
│       └── templates
│           └── LOOP_TEPMLATES
│               ├── type-I.j2
│               ├── type-K2.j2
│               ├── type-K.j2
│               ├── type-L.j2
│               └── type-R.j2
├── sdfs                      // パラメータシート(SDFファイル)はここに入れる
│   ├── conf
│   │   ├── ENV.conf
│   │   ├── NSON_RHEL92.conf  // 操作対象ホストが増えた場合はここに設定ファイルを追加していく
│   │   └── CSC_RHEL92.conf
│   └── RHEL84.sdf
└── site.yml

鍵生成・登録

# Ansibleサーバで公開鍵・秘密鍵を作成
chmod 700 /TERA_IA/key
ssh-keygen -t rsa -f /TERA_IA/key/setup-key -N ""

# Ansibleサーバから構築対象サーバに公開鍵を転送
ssh-copy-id -i /TERA_IA/key/setup-key.pub cloud-user@【構築対象サーバ】

# Ansibleサーバ自身にも公開鍵を登録
cat /TERA_IA/key/setup-key.pub >> /root/.ssh/authorized_keys

/etc/hosts編集

名前解決したいサーバを追記する。

172.19.232.90   Playbook-rhel

コンテナ起動

ルートユーザで実行する。

# インポート
podman load -i teraia_container.tar

podman run --rm -it -v /TERA_IA:/TERA_IA:Z teraia-container

hostsファイル生成

cd /TERA_IA/playbooks/RHEL8
/opt/coralis_tools/ansible/sdf2ansiblefiles.sh ./sdfs/conf/ENV.conf

実行

cd /var/TERA_IA/playbooks/RHEL8

# 構文チェック
ansible-playbook -i ./inventories/hosts ./site.yml --check

# 実行
ansible-playbook -i ./inventories/hosts ./site.yml

host.listの作成

Serverspecによる試験

:caption: 失敗したとき

[root@480fedb352f6 spec_files]# rake spec
#############################################################################
   Target host: Playbook-rhel
#############################################################################
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-support-3.13.1/lib:/usr/local/share/gems/gems/rspec-core-3.13.0/lib /usr/local/share/gems/gems/rspec-core-3.13.0/exe/rspec ./spec/Linux/code/spec_file/begin_test_spec.rb
=============================================================================
 Test target: directories
=============================================================================

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be owned by "root" (FAILED - 1)

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be grouped into "root" (FAILED - 2)

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be mode 755 (FAILED - 3)

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be owned by "root" (FAILED - 4)

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be grouped into "root" (FAILED - 5)

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be mode 700 (FAILED - 6)

Failures:

  1) <<< File_ATTRIBUTE >>> File "/root/work" is expected to be owned by "root"
     On host `Playbook-rhel'
     Failure/Error: it { should be_owned_by     value } if key == 'owner'
       expected `File "/root/work".owned_by?("root")` to be truthy, got false
       /bin/sh -c stat\ -c\ \%U\ /root/work\ \|\ grep\ --\ \\\^root\\\$

     # ./spec/Linux/code/test_pattern/common.rb:169:in `block (3 levels) in File_ATTRIBUTE'

  2) <<< File_ATTRIBUTE >>> File "/root/work" is expected to be grouped into "root"
     On host `Playbook-rhel'
     Failure/Error: it { should be_grouped_into value } if key == 'group'
       expected `File "/root/work".grouped_into?("root")` to be truthy, got false
       /bin/sh -c stat\ -c\ \%G\ /root/work\ \|\ grep\ --\ \\\^root\\\$

     # ./spec/Linux/code/test_pattern/common.rb:170:in `block (3 levels) in File_ATTRIBUTE'

  3) <<< File_ATTRIBUTE >>> File "/root/work" is expected to be mode 755
     On host `Playbook-rhel'
     Failure/Error: it { should be_mode         value } if key == 'mode'
       expected `File "/root/work".mode?(755)` to be truthy, got false
       /bin/sh -c stat\ -c\ \%a\ /root/work\ \|\ grep\ --\ \\\^755\\\$

     # ./spec/Linux/code/test_pattern/common.rb:171:in `block (3 levels) in File_ATTRIBUTE'

  4) <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be owned by "root"
     On host `Playbook-rhel'
     Failure/Error: it { should be_owned_by     value } if key == 'owner'
       expected `File "/root/work2".owned_by?("root")` to be truthy, got false
       /bin/sh -c stat\ -c\ \%U\ /root/work2\ \|\ grep\ --\ \\\^root\\\$

     # ./spec/Linux/code/test_pattern/common.rb:169:in `block (3 levels) in File_ATTRIBUTE'

  5) <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be grouped into "root"
     On host `Playbook-rhel'
     Failure/Error: it { should be_grouped_into value } if key == 'group'
       expected `File "/root/work2".grouped_into?("root")` to be truthy, got false
       /bin/sh -c stat\ -c\ \%G\ /root/work2\ \|\ grep\ --\ \\\^root\\\$

     # ./spec/Linux/code/test_pattern/common.rb:170:in `block (3 levels) in File_ATTRIBUTE'

  6) <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be mode 700
     On host `Playbook-rhel'
     Failure/Error: it { should be_mode         value } if key == 'mode'
       expected `File "/root/work2".mode?(700)` to be truthy, got false
       /bin/sh -c stat\ -c\ \%a\ /root/work2\ \|\ grep\ --\ \\\^700\\\$

     # ./spec/Linux/code/test_pattern/common.rb:171:in `block (3 levels) in File_ATTRIBUTE'

Finished in 2.1 seconds (files took 0.68981 seconds to load)
6 examples, 6 failures

Failed examples:

rspec './spec/Linux/code/test_pattern/common.rb[1:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work" is expected to be owned by "root"
rspec './spec/Linux/code/test_pattern/common.rb[2:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work" is expected to be grouped into "root"
rspec './spec/Linux/code/test_pattern/common.rb[3:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work" is expected to be mode 755
rspec './spec/Linux/code/test_pattern/common.rb[4:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be owned by "root"
rspec './spec/Linux/code/test_pattern/common.rb[5:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be grouped into "root"
rspec './spec/Linux/code/test_pattern/common.rb[6:1:1]' # <<< File_ATTRIBUTE >>> File "/root/work2" is expected to be mode 700
:caption: 成功したとき

[root@480fedb352f6 spec_files]# rake spec
#############################################################################
   Target host: Playbook-rhel
#############################################################################
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-support-3.13.1/lib:/usr/local/share/gems/gems/rspec-core-3.13.0/lib /usr/local/share/gems                                                                                                          /gems/rspec-core-3.13.0/exe/rspec ./spec/Linux/code/spec_file/begin_test_spec.rb
=============================================================================
 Test target: directories
=============================================================================

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be owned by "root"

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be grouped into "root"

<<< File_ATTRIBUTE >>>
  File "/root/work"
    is expected to be mode 755

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be owned by "root"

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be grouped into "root"

<<< File_ATTRIBUTE >>>
  File "/root/work2"
    is expected to be mode 700

Finished in 1.98 seconds (files took 0.64302 seconds to load)
6 examples, 0 failures