使用Molecule进行测试Redis集群构建的playbook

Moleculeを使用して、Redis-Clusterを構築するplaybookのテストを行う

Molecule はAnsible のロールの開発とテストを支援するように設計されているAnsible のテストツールです。

通过使用Molecule,在Docker容器中执行Ansible角色并进行playbook验证成为可能。

「なるほど、分からん」という方は、下記をご一読いただければと思います。

    SlideShare: Molecule入門

今回は以前に作成したplaybook をカスタマイズして、Molecule を使い方を外部記憶として残そうと思います。

前提条件 (Qian ti tiao jian)

    • Ansible はインストール済みであるとする

 

    • config、inventory の設定は完了済みであるとする

 

    • 鍵生成、鍵交換、疎通確認は完了済みであるとする

 

    • proxy 環境下ではないものとする

 

    一つのサーバーにRedis のMaster とSlave を配置する

执行环境

# cat /etc/redhat-release 
CentOS Linux release 7.7.1908 (Core)

# ansible --version
ansible 2.9.1
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

構成図のイメージ

构图如下所示。使用molecule命令生成docker容器。

molecule.png

分子的安装

请按照以下步骤安装Molecule。

# yum install -y epel-release
# yum install -y gcc python-pip python-devel openssl-devel libselinux-python
# yum install -y docker        ※ 既にdokcer をインストール済みである場合、本手順は飛ばしてください
# pip install -U pip
# pip install -U setuptools
# pip install molecule docker-py pyparsing PyYAML

既然Molecule已经安装完成了,那么我们来确认一下Molecule的版本吧。

# molecule --version
molecule, version 2.22

我个人迷上的点

在使用 Molecule 时,推荐使用 docker 或 docker-py 其中之一。如果两者都已安装,应先卸载,再重新安装其中之一。本次使用 docker-py。

# pip uninstall docker
# pip uninstall docker-py
# pip install docker-py

关于本次测试的目标 playbook。

这次测试的目标Playbook是之前创建的用于构建Redis集群的Playbook。

    Ansibleを使用して、CentOS 7にRedis-Clusterを構築する

创建以下类似的目录结构,并将上述链接中的playbook内容提取为角色。

# tree -r /etc/ansible/roles/
/etc/ansible/roles/
├── redis-cluster
│   ├── start_redis_server
│   │   └── tasks
│   │       └── main.yml
│   ├── setup_redis_conf
│   │   └── tasks
│   │       └── main.yml
│   ├── install_redis
│   │   └── tasks
│   │       └── main.yml
│   ├── create_redis_user
│   │   └── tasks
│   │       └── main.yml
│   ├── create_redis_group
│   │   └── tasks
│   │       └── main.yml
│   ├── create_redis_config_directories
│   │   └── tasks
│   │       └── main.yml
│   └── copy_redis_conf
│       └── tasks
│           └── main.yml
└── common
    └── install_list_of_packages
        └── tasks
            └── main.yml

根据此,我们将创建使用以下类型角色的playbook。

- name: deploy Redis-Cluster
  hosts: localhost
  vars:
    ansible_become: yes
    install_list_of_packages:
      - epel-release
      - http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    redis_port_number:
      - 7000
      - 7001
      - 7002
      - 7003
      - 7004
      - 7005
  roles:
    - install_list_of_packages
    - install_redis
    - create_redis_group
    - create_redis_user
    - create_redis_config_directories
    - copy_redis_conf
    - setup_redis_conf
    - start_redis_server

在查看被称为 playbook 的角色时,顺便使用 ansible-lint 进行静态分析。

# cd /etc/ansible/playbook
# ansible-lint deploy_redis_cluster.yml -v
Examining deploy_redis_cluster.yml of type playbook
Examining ../roles/common/install_list_of_packages/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/install_redis/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/create_redis_group/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/create_redis_user/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/create_redis_config_directories/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/copy_redis_conf/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/setup_redis_conf/tasks/main.yml of type tasks
Examining ../roles/redis-cluster/start_redis_server/tasks/main.yml of type tasks
[301] Commands should not change things if nothing needs doing
../roles/redis-cluster/start_redis_server/tasks/main.yml:2
Task/Handler: Start Redis-Server

分子的测试准备

执行分子 init

执行以下命令,创建molecule目录。

# cd /etc/ansible/roles/redis-cluster
# molecule init scenario -r redis-cluster
--> Initializing new scenario default...
Initialized scenario in /etc/ansible/roles/redis-cluster/molecule/default successfully.

# ll | grep molecule
drwxr-xr-x 3 root root 21  2月 12 22:43 molecule

确认Molecule的目录结构

执行以下命令,确认 molecule 目录的结构。

# tree -r molecule/
molecule/
└── default
    ├── tests
    │   ├── test_default.py
    │   └── __pycache__
    │       └── test_default.cpython-36.pyc
    ├── playbook.yml
    ├── molecule.yml
    ├── INSTALL.rst
    └── Dockerfile.j2

各个文件的设置

为了运行 Molecule,需要配置以下三个文件。

molecule/
└── default
    ├── playbook.yml         # 検証するplaybook の内容
    ├── molecule.yml         # molecule を実行する際の設定ファイル
    └── Dockerfile.j2        # playbook の検証対象となるコンテナ起動に使用するdocker イメージの設定ファイル
    molecule/default/Dockerfile.j2
# Molecule managed

{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}

{% if item.env is defined %}
{% for var, value in item.env.items() %}
{% if value %}
ENV {{ var }} {{ value }}
{% endif %}
{% endfor %}
{% endif %}

RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates iproute2 && apt-get clean; \
    elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash iproute && dnf clean all; \
    elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash iproute && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
    elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml iproute2 && zypper clean -a; \
    elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
    elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates iproute2 && xbps-remove -O; fi

CMD ["/sbin/init"]
    molecule/default/molecule.yml
---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
platforms:
  - name: redis-cluster-instance            # コンテナの名前
    image: centos:7                         # 使用するイメージ
    pull: False
    command: /sbin/init                     # systemd を必要とする場合に必要なオプション
    tmps:                                   # systemd を必要とする場合に必要なオプション
      - /run                                # systemd を必要とする場合に必要なオプション
      - /tmp                                # systemd を必要とする場合に必要なオプション
    volumes:                                # systemd を必要とする場合に必要なオプション
      - /sys/fs/cgroup:/sys/fs/cgroup:ro    # systemd を必要とする場合に必要なオプション
provisioner:
  name: ansible
  log: true
  config_options:
    defaults:
      stdout_callback: yaml
      bin_ansible_callbacks: true
  lint:
    name: ansible-lint
verifier:
  name: testinfra
  lint:
    name: flake8
    molecule/default/playbook.yml
---
- name: Converge
  hosts: all
  vars:
    ansible_become: yes
    install_list_of_packages:
      - epel-release
      - http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    redis_port_number:
      - 7000
      - 7001
      - 7002
      - 7003
      - 7004
      - 7005
  roles:
    - ../roles/common/install_list_of_packages
    - ../roles/redis-cluster/install_redis
    - ../roles/redis-cluster/create_redis_group
    - ../roles/redis-cluster/create_redis_user
    - ../roles/redis-cluster/create_redis_config_directories
    - ../roles/redis-cluster/copy_redis_conf
    - ../roles/redis-cluster/setup_redis_conf
    - ../roles/redis-cluster/start_redis_server

创建一个用于分子测试的环境。

执行以下命令,创建用于Molecule测试的Docker容器。

# molecule create
--> Validating schema /etc/ansible/roles/redis-cluster/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    ├── dependency
    ├── create
    └── prepare

--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'create'
--> Sanity checks: 'docker'

    PLAY [Create] ******************************************************************

    TASK [Log into a Docker registry] **********************************************
    skipping: [localhost] => (item={'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']}) 

    TASK [Create Dockerfiles from image names] *************************************
    changed: [localhost] => (item={'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']})

    TASK [Determine which docker image info module to use] *************************
    ok: [localhost]

    TASK [Discover local Docker images] ********************************************
    ok: [localhost] => (item={u'changed': True, u'uid': 0, u'dest': u'/root/.cache/molecule/redis-cluster/default/Dockerfile_centos_7', u'owner': u'root', 'diff': [], u'size': 914, u'src': u'/root/.ansible/tmp/ansible-tmp-1581521805.53-277333827862458/source', 'ansible_loop_var': u'item', u'group': u'root', 'item': {'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']}, u'checksum': u'af0854dd479325baac9797c25a580b67bf4faa0e', u'md5sum': u'89ab4f11c078a9f793fa4f94a495193d', 'failed': False, u'state': u'file', u'gid': 0, u'mode': u'0644', u'invocation': {u'module_args': {u'directory_mode': None, u'force': True, u'remote_src': None, u'dest': u'/root/.cache/molecule/redis-cluster/default/Dockerfile_centos_7', u'selevel': None, u'_original_basename': u'Dockerfile.j2', u'delimiter': None, u'regexp': None, u'owner': None, u'follow': False, u'validate': None, u'local_follow': None, u'src': u'/root/.ansible/tmp/ansible-tmp-1581521805.53-277333827862458/source', u'group': None, u'unsafe_writes': None, u'checksum': u'af0854dd479325baac9797c25a580b67bf4faa0e', u'seuser': None, u'serole': None, u'content': None, u'setype': None, u'mode': None, u'attributes': None, u'backup': False}}})

    TASK [Build an Ansible compatible image (new)] *********************************
    ok: [localhost] => (item=molecule_local/centos:7)

    TASK [Build an Ansible compatible image (old)] *********************************
    skipping: [localhost] => (item=molecule_local/centos:7) 

    TASK [Create docker network(s)] ************************************************

    TASK [Determine the CMD directives] ********************************************
    ok: [localhost] => (item={'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']})

    TASK [Create molecule instance(s)] *********************************************
    changed: [localhost] => (item=redis-cluster-instance)

    TASK [Wait for instance(s) creation to complete] *******************************
    FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left).
    changed: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'429823489509.31439', 'item': {'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']}, u'started': 1, 'changed': True, 'failed': False, u'finished': 0, u'results_file': u'/root/.ansible_async/429823489509.31439'})

    PLAY RECAP *********************************************************************
    localhost                  : ok=7    changed=3    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.

检查是否生成了Docker容器。

# docker ps -a | grep molecule
CONTAINER ID        IMAGE                     COMMAND       CREATED             STATUS                   PORTS        NAMES
76b96d17d540        molecule_local/centos:7   "/sbin/init"  About a minute ago  Up About a minute                     moleredis-cluster-instance

分子静态分析

执行以下命令,使用Molecule进行角色的静态分析。

# molecule lint
--> Validating schema /etc/ansible/roles/redis-cluster/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    └── lint

--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in /etc/ansible/roles/redis-cluster/...
Lint completed successfully.
--> Executing Flake8 on files found in /etc/ansible/roles/redis-cluster/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on /etc/ansible/roles/redis-cluster/molecule/default/playbook.yml...
    [301] Commands should not change things if nothing needs doing
    start_redis_server/tasks/main.yml:2
    Task/Handler: Start Redis-Server

通过分子进行测试的执行

执行以下命令,对docker容器进行playbook验证。

# molecule converge
--> Validating schema /etc/ansible/roles/redis-cluster/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    ├── dependency
    ├── create
    ├── prepare
    └── converge

--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'create'
Skipping, instances already created.
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'

    PLAY [Converge] ****************************************************************

    TASK [Gathering Facts] *********************************************************
    ok: [redis-cluster-instance]

    TASK [../roles/common/install_list_of_packages : Install a list of packages] ***
    changed: [redis-cluster-instance]

    TASK [../roles/redis-cluster/install_redis : Install redis] ********************
    changed: [redis-cluster-instance]

    TASK [../roles/redis-cluster/create_redis_group : Ensure group "redis" exists] ***
    ok: [redis-cluster-instance]

    TASK [../roles/redis-cluster/create_redis_user : Create redis user] ************
    changed: [redis-cluster-instance]

    TASK [../roles/redis-cluster/create_redis_config_directories : mkdir redis config directory] ***
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/copy_redis_conf : Copy redis.conf] ****************
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting bind IPv4Address] ******
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting port number] ***********
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting cluster-enabled] *******
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting cluster-config-file] ***
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting cluster-node-timeout] ***
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting appendonly] ************
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/setup_redis_conf : Setting logfile] ***************
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    TASK [../roles/redis-cluster/start_redis_server : Start Redis-Server] **********
    changed: [redis-cluster-instance] => (item=7000)
    changed: [redis-cluster-instance] => (item=7001)
    changed: [redis-cluster-instance] => (item=7002)
    changed: [redis-cluster-instance] => (item=7003)
    changed: [redis-cluster-instance] => (item=7004)
    changed: [redis-cluster-instance] => (item=7005)

    PLAY RECAP *********************************************************************
    redis-cluster-instance     : ok=15   changed=13   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

一切都没问题,playbook已经完成。请执行以下命令登录到docker容器中。

# molecule login
--> Validating schema /etc/ansible/roles/redis-cluster/molecule/default/molecule.yml.
Validation completed successfully.

查询 Redis 版本。

让我们查看安装在Docker容器中的Redis版本。

[root@redis-cluster-instance /]# redis-cli --version
redis-cli 5.0.7
[root@redis-cluster-instance /]# redis-server --version
Redis server v=5.0.7 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=91145edf25c40cd7

搭建Redis-Cluster

那么,让我们在docker容器中运行以下命令,构建Redis-Cluster。

[root@redis-cluster-instance /]# redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 7bc5f80dd90213eeb3361571ea3dbbb3291e97d8 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
M: d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f 127.0.0.1:7001
   slots:[5461-10922] (5462 slots) master
M: d53abfb685e3592a40affcc763a39036f3027103 127.0.0.1:7002
   slots:[10923-16383] (5461 slots) master
S: 906638361f1c40cb349d0a4f507cadb497a7d02a 127.0.0.1:7003
   replicates d53abfb685e3592a40affcc763a39036f3027103
S: ebb4b50135a4ea7c0ad5061cc169d1a14f760fb1 127.0.0.1:7004
   replicates 7bc5f80dd90213eeb3361571ea3dbbb3291e97d8
S: 483c521c5a2b10d23f7335d57d960c274645f2b5 127.0.0.1:7005
   replicates d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 7bc5f80dd90213eeb3361571ea3dbbb3291e97d8 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: d53abfb685e3592a40affcc763a39036f3027103 127.0.0.1:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 483c521c5a2b10d23f7335d57d960c274645f2b5 127.0.0.1:7005
   slots: (0 slots) slave
   replicates d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f
S: ebb4b50135a4ea7c0ad5061cc169d1a14f760fb1 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 7bc5f80dd90213eeb3361571ea3dbbb3291e97d8
M: d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f 127.0.0.1:7001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 906638361f1c40cb349d0a4f507cadb497a7d02a 127.0.0.1:7003
   slots: (0 slots) slave
   replicates d53abfb685e3592a40affcc763a39036f3027103
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

Redis-Cluster的状态查询

让我们来检查一下在Docker容器中构建的Redis-Cluster的状态。

[root@redis-cluster-instance /]# redis-cli -p 7000 cluster nodes
d53abfb685e3592a40affcc763a39036f3027103 127.0.0.1:7002@17002 master - 0 1581523028526 3 connected 10923-16383
483c521c5a2b10d23f7335d57d960c274645f2b5 127.0.0.1:7005@17005 slave d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f 0 1581523028316 6 connected
ebb4b50135a4ea7c0ad5061cc169d1a14f760fb1 127.0.0.1:7004@17004 slave 7bc5f80dd90213eeb3361571ea3dbbb3291e97d8 0 1581523028113 5 connected
d59fe4d92511e504ba5cf7f9001cb8ea7def6b7f 127.0.0.1:7001@17001 master - 0 1581523026273 2 connected 5461-10922
906638361f1c40cb349d0a4f507cadb497a7d02a 127.0.0.1:7003@17003 slave d53abfb685e3592a40affcc763a39036f3027103 0 1581523028000 4 connected
7bc5f80dd90213eeb3361571ea3dbbb3291e97d8 127.0.0.1:7000@17000 myself,master - 0 1581523026000 1 connected 0-5460

刪除用於分子的測試環境。

执行下面的命令,删除用于Molecule测试的Docker容器。

[root@redis-cluster-instance /]# exit
exit
# molecule destroy
--> Validating schema /etc/ansible/roles/redis-cluster/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    ├── dependency
    ├── cleanup
    └── destroy

--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'cleanup'
Skipping, cleanup playbook not configured.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=redis-cluster-instance)

    TASK [Wait for instance(s) deletion to complete] *******************************
    changed: [localhost] => (item={'ansible_loop_var': u'item', u'ansible_job_id': u'412030201772.27418', 'item': {'pull': False, 'command': u'/sbin/init', 'name': u'redis-cluster-instance', 'volumes': [u'/sys/fs/cgroup:/sys/fs/cgroup:ro'], 'image': u'centos:7', 'tmps': [u'/run', u'/tmp']}, u'started': 1, 'changed': True, 'failed': False, u'finished': 0, u'results_file': u'/root/.ansible_async/412030201772.27418'})

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

--> Pruning extra files from scenario ephemeral directory

检查Docker容器是否被删除。

# docker ps -a | grep molecule
# 

总结

使用Molecule,我们能够对构建Redis-Cluster的playbook进行静态分析和角色测试。

使用Molecule,我很高兴能够在不污染新创建的实例或虚拟机的情况下进行playbook的试验和错误。如果失败了,可以通过删除和重新创建容器,在全新的状态下进行验证。下一步,我想将GitLab Runner与Molecule结合起来,实现playbook的CI/CD自动化测试。通过设置计划任务,每天午夜都可以进行测试,不再会对测试时间产生困惑。我认为实现类似下面URL中的状态会更好。

    ANSIBLE TOWER + GITLAB + MOLECULEで作るCI/CD環境

参考书籍·参考网址

    • Ansible構築・運用ガイドブック(Compass Booksシリーズ) インフラ自動化のための現場のノウハウ

 

    • SlideShare: Molecule入門

 

    • molecule でansible の role と playbook をテストする

 

    • molecule: Installation

 

    • molecule: Getting Started Guide

 

    • molecule: Command Line Reference

 

    • molecule: Common Molecule Use Cases

 

    BACK 2 CODE: Molecule
广告
将在 10 秒后关闭
bannerAds