はじめに
本記事は、下記の続きです。
KVMホストに Ansible をインストールし、上記で構築した OpenStack を操作することが目標です。
Ansible のインストール
KVMホストに Ansible をインストールします。
python -m venv venv_ansible
source venv_ansible/bin/activate
vi requirements.txt
openstacksdk
ansible
ansible-core
pip install -r requirements.txt
今回はバージョンを指定しませんでしたが、以下のバージョンがインストールされました。
$ pip freeze | egrep "openstack|ansible"
ansible==8.7.0
ansible-core==2.15.9
openstackclient==4.0.0
openstacksdk==3.0.0
Ansible から OpenStack を操作するには、 openstack.cloud という collection が必要なのですが、すでにインストールされています。
$ ansible-galaxy collection list | grep openstack
openstack.cloud               2.2.0 
認証情報の設定
前回の記事で構築した OpenStack 環境では、 openstackclient という pod から OpenStack を操作することができます。
openstackclient に接続し、認証情報を ~/.config/openstack/ にコピーします。
mkdir ~/.config
oc cp openstackclient:.config/openstack ~/.config
clouds.yaml と secure.yaml がコピーされました。
clouds.yaml の中を見ると、 auth_url が以下のようになっています。
            auth_url: https://keystone-public-openstack.apps-crc.testing
プロトコルが https なので、rootCA もコピーする必要があります。
openssl コマンドで確認すると、 rootca-public という rootCA が必要のようです。
$ openssl s_client -connect keystone-public-openstack.apps-crc.testing:443
CONNECTED(00000003)
depth=1 CN = rootca-public
verify return:1
depth=0 
verify return:1
---
Certificate chain
 0 s:
   i:CN = rootca-public
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: ecdsa-with-SHA256
   v:NotBefore: Mar 16 08:36:24 2024 GMT; NotAfter: Mar 16 08:36:24 2025 GMT
 1 s:CN = rootca-public
   i:CN = rootca-public
   a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA256
   v:NotBefore: Mar 16 08:34:29 2024 GMT; NotAfter: Mar 15 08:34:29 2029 GMT
---
Server certificate
(以下略)
rootca-public のインストール
rootCA は /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem にありますので、確認します。
$ oc rsh openstackclient cat /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem 
# rootca-public
-----BEGIN CERTIFICATE-----
(中略)
-----END CERTIFICATE-----
# rootca-internal
-----BEGIN CERTIFICATE-----
(中略)
-----END CERTIFICATE-----
# rootca-ovn
-----BEGIN CERTIFICATE-----
(中略)
-----END CERTIFICATE-----
# ACCVRAIZ1
(以下略)
今回必要なのは rootca-public だけですが、念のため rootca-public, rootca-internal, rootca-ovn のCA認証情報を /etc/pki/ca-trust/source/anchors/rootca.pem にコピーし、以下を実行します。
sudo update-ca-trust
次に、Python のCA認証情報は別ファイルで管理されているので、そちらにも反映します。
反映の手順は下記記事を参考にしました。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import certifi
cabundle = certifi.where()
local_rootCA = '/etc/pki/ca-trust/source/anchors/rootca.pem'
print( 'read from {}'.format( local_rootCA ) )
with open( local_rootCA, 'rb' ) as infile:
    myrootca = infile.read()
print( 'append to {}'.format( cabundle ) )
with open( cabundle, 'ab' ) as outfile:
    outfile.write( myrootca )
print( '{} has been imported.'.format( local_rootCA ) )
python local_ca_install.py
cirrosイメージ入手
リソースを作成する前に cirrosイメージを入手しておきます。
wget https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img
これで準備ができました。
Ansibleによる OpenStack の各種リソース作成
以下のリソースを作成します。
| 項目 | リソース名 | 備考 | 
|---|---|---|
| project | demo-project | |
| user | demo-user | |
| network | demo-net | |
| subnet | demo-subnet | allocation_pool: 10.0.0.100-10.0.0.250 | 
| router | demo-router | public に接続する | 
| security group | demo-sg | ssh, icmp を許可 | 
| flavor | demo-flavor | |
| keypair | demo-key | 秘密鍵は demo-key-private.pem として保存 | 
| image | demo-cirros | |
| volume | demo-volume | demo-cirros の bootable volume | 
| server | demo-instance | 
---
- hosts: localhost
  tasks:
    - name: admin - create project
      openstack.cloud.project:
        cloud: overcloud
        state: present
        name: demo-project
        description: demo-project
        domain_id: Default
        enabled: True
 
    - name: admin - create user
      openstack.cloud.identity_user:
        cloud: overcloud
        state: present
        name: demo-user
        password: secret
        domain: Default
    - name: admin - grant demo role on the user demo in the project demo-project
      openstack.cloud.role_assignment:
        cloud: overcloud
        user: demo-user
        role: member
        domain: Default
        project: demo-project
 
    - name: set_fact user authentication
      set_fact:
        auth_user:
          auth_url: https://keystone-public-openstack.apps-crc.testing
          password: secret
          project_domain_name: Default
          project_name: demo-project
          user_domain_name: Default
          username: demo-user
 
    - name: user - create network
      openstack.cloud.network:
        auth: "{{ auth_user }}"
        state: present
        name: demo-net
    - name: user - create subnet
      openstack.cloud.subnet:
        auth: "{{ auth_user }}"
        state: present
        name: demo-subnet
        network_name: demo-net
        cidr: 10.0.0.0/24
        dns_nameservers: 192.168.122.1
        enable_dhcp: true
        allocation_pool_start: 10.0.0.100
        allocation_pool_end: 10.0.0.250
 
    - name: user - create router
      openstack.cloud.router:
        auth: "{{ auth_user }}"
        state: present
        name: demo-router
        network: public
        interfaces:
          - demo-subnet
 
    - name: user - create security group
      openstack.cloud.security_group:
        auth: "{{ auth_user }}"
        state: present
        name: demo-sg
 
    - name: user - add security group rule (ssh)
      openstack.cloud.security_group_rule:
        auth: "{{ auth_user }}"
        state: present
        security_group: demo-sg
        protocol: tcp
        port_range_min: 22
        port_range_max: 22
        remote_ip_prefix: 0.0.0.0/0
 
    - name: user - add security group rule (icmp)
      openstack.cloud.security_group_rule:
        auth: "{{ auth_user }}"
        state: present
        security_group: demo-sg
        protocol: icmp
        port_range_min: -1
        port_range_max: -1
        remote_ip_prefix: 0.0.0.0/0
 
    - name: admin - create flavor
      openstack.cloud.compute_flavor:
        cloud: overcloud
        state: present
        name: demo-flavor
        ram: 1024
        vcpus: 1
        disk: 0
 
    - name: user - create keypair
      openstack.cloud.keypair:
        auth: "{{ auth_user }}"
        state: present
        name: demo-key
      register: keypair_info
 
    - name: create private key
      copy:
        content: "{{ keypair_info['keypair']['private_key'] }}"
        dest: ./demo-key-private.pem
        mode: 0600
 
    - name: user - upload cirros image
      openstack.cloud.image:
        auth: "{{ auth_user }}"
        state: present
        name: demo-cirros
        container_format: bare
        disk_format: qcow2
        filename: cirros-0.6.2-x86_64-disk.img
 
    - name: user - create volume
      openstack.cloud.volume:
        auth: "{{ auth_user }}"
        state: present
        volume_type: nfs
        size: 40
        bootable: true
        image: demo-cirros
        display_name: demo-volume
 
    - name: user - create VM
      openstack.cloud.server:
        auth: "{{ auth_user }}"
        name: demo-instance
        boot_volume: demo-volume
        flavor: ce9ed399-b30b-4f92-83a6-917ad1966e72
        key_name: demo-key
        security_groups: demo-sg
        network: demo-net
        floating_ip_pools: public
        state: present
※最後のインスタンスを作成するところ、flavorの指定が UUID でないといけないようで、使いにくい……。
では実行します。
ansible-playbook all-in-one.yml -v
openstackclient に接続して確認します。
$ oc rsh openstackclient 
sh-5.1$ openstack server list --all
+--------------------------------------+---------------+--------+----------------------------------------+--------------------------+-------------+
| ID                                   | Name          | Status | Networks                               | Image                    | Flavor      |
+--------------------------------------+---------------+--------+----------------------------------------+--------------------------+-------------+
| 87a8dbaf-8cbf-4d9f-9a5d-83eac9296615 | demo-instance | ACTIVE | demo-net=10.0.0.147, 192.168.122.208   | N/A (booted from volume) | demo-flavor |
+--------------------------------------+---------------+--------+----------------------------------------+--------------------------+-------------+
sh-5.1$ ping -c 2 192.168.122.208
PING 192.168.122.208 (192.168.122.208) 56(84) bytes of data.
64 bytes from 192.168.122.208: icmp_seq=1 ttl=62 time=1.97 ms
64 bytes from 192.168.122.208: icmp_seq=2 ttl=62 time=1.12 ms
--- 192.168.122.208 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 1.117/1.543/1.970/0.426 ms
sh-5.1$ exit
$ ssh -i demo-key-private.pem cirros@192.168.122.208
The authenticity of host '192.168.122.208 (192.168.122.208)' can't be established.
ED25519 key fingerprint is SHA256:rviyA0kkufqxpfwJZ0Kb0EbbvGlMr5EWMmrsRXZ6x0A.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.122.208' (ED25519) to the list of known hosts.
$ cat /etc/os-release
PRETTY_NAME="CirrOS 0.6.2"
NAME="CirrOS"
VERSION_ID="0.6.2"
ID=cirros
HOME_URL="https://cirros-cloud.net"
BUG_REPORT_URL="https://github.com/cirros-dev/cirros/issues"
Ansibleによる OpenStack の各種リソース削除
詳細は省略しますが、作成のときと逆の順番で削除していきます。
---
- hosts: localhost
  tasks:
    - name: set_fact user authentication
      set_fact:
        auth_user:
          auth_url: https://keystone-public-openstack.apps-crc.testing
          password: secret
          project_domain_name: Default
          project_name: demo-project
          user_domain_name: Default
          username: demo-user
 
    - name: user - delete VM
      openstack.cloud.server:
        auth: "{{ auth_user }}"
        state: absent
        name: demo-instance
(以下略)