Ansible 使用 dnf 安裝 Redis Cluster (Redis6)

之前筆記 Ansible 安裝 Redis Cluster 紀錄到在 CentOS 7 上透過 Ansible 使用 yum 來安裝 Redis Cluster,但最近 production 環境已經升級成 CentOS 8 + dnf,所以來更新一下 Ansible script,避免之後想抄又要東翻西找XD

基本環境說明

  1. Azure VM B2s (2 vcpu,4GiB memory)
  2. OpenLogic CentOS 8.2
  3. Redis 6.0.8
  4. ansible 2.10.2

Ansible 腳本

  1. 專案結構

    • roles
      • redis-cluster
        • defaults
          • main.yml
        • handlers
          • main.yml
        • tasks
          • checkdir.yml
          • createcluster.yml
          • installredis.yml
          • installtools.yml
          • main.yml
          • prepareservice.yml
          • prepareredisconfig.yml
          • uninstall.yml
          • upgrade.yml
        • templates
          • config.j2
          • service.j2
        • vars
          • main.yml
        • inventories
          • dev.ini
        • README.md
    • ansible.cfg
    • main.yml
  2. 完整內容

    • roles

      • redis-cluster

        • defaults

          • main.yml
            ---
            purpose: update
          
        • handlers

          • main.yml
            ---
            - name: "Restart Redis Service"
              listen: restart-service
              systemd:
                name: "redis_{{item}}"
                daemon_reload: yes
                enabled: yes
                state: restarted
              with_items: "{{redis_ports}}"
          
        • tasks

          • checkdir.yml
            ---
            - name: Ensures dir exists
              file:
                path: "{{ folder }}"
                state: directory
                mode: 0755
                owner: redis
                group: redis
                recurse: yes
          
          • createcluster.yml
            ---
            - name: Create Cluster debug
              debug:
                msg: redis-cli -a {{redispass}} --cluster-replicas 1 --cluster create {% for redis_node in groups['redis_all'] %} {% for redis_port in hostvars[redis_node].redis_ports %} {{ hostvars[redis_node].ip }}:{{ redis_port }} {% endfor %}{% endfor %}
          
            - name: Create Cluster
              shell: |
                echo "yes" |redis-cli -a {{redispass}} --cluster-replicas 1 --cluster create {% for redis_node in groups['redis_all'] %} {% for redis_port in hostvars[redis_node].redis_ports %} {{ hostvars[redis_node].ip }}:{{ redis_port }} {% endfor %}{% endfor %}
          
          • installredis.yml
            ---
            - name: Install Redis
              dnf:
                name: "{{redisversion}}"
                enablerepo:  remi
                state: latest
          
          • installtools.yml
            - name: Install rpm
              dnf:
                name: 'https://rpms.remirepo.net/enterprise/remi-release-8.rpm'
                state: present
                disable_gpg_check: yes
          
            - name: Enable remi repo
              shell: dnf module enable -y redis:remi-6.0
          
            - name: Insall Redis
              include_tasks: installredis.yml
          
            - name: check dir
              include_tasks: checkdir.yml
              vars:
                folder: "/etc/redis"
          
            - name: Remove default redis service
              ignore_errors: yes
              shell: |
                systemctl disable redis 
          
            - name: Delete redis service
              ignore_errors: yes
              file:
                path: "{{ item }}"
                state: absent
              with_items:
                - /usr/lib/systemd/system/redis.service
                - /etc/systemd/system/redis.service.d
                - /etc/systemd/system/redis-sentinel.service.d
          
            - name: Disable SELinux
              shell: |
                setenforce 0
                sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
          
            - name: Allow Overcommit Memory
              sysctl:
                name: vm.overcommit_memory
                value: "1"
                state: present
                reload: yes
                ignoreerrors: yes
          
            - name: Stop and disable firewalld.
              service:
                name: firewalld
                state: stopped
                enabled: False
          
          • main.yml
            ---
            - name: Uninstall
              include_tasks: uninstall.yml
              when: purpose == 'uninstall' or purpose == 'reinstall'
          
            - name: Install rpm and redis
              include_tasks: installtools.yml
              when: purpose == 'install'
          
            - name: Upgrde redis
              include_tasks: upgrade.yml
              when: purpose == 'upgrade'
          
            - name: create linux user
              shell: |
                groupadd --system redis
                useradd -s /sbin/nologin --system -g redis redis
              ignore_errors: yes
              when: purpose == 'install'
          
            - name: Generate redis config file
              include_tasks: prepareredisconfig.yml
              when: purpose != 'uninstall'
          
            - name: Generate service file
              include_tasks: prepareservice.yml
              when: purpose == 'install' or purpose == 'reinstall'
          
            - name: Restart Service
              debug:
                msg: restart service
              notify: restart-service
              changed_when: true
              when: purpose != 'uninstall'
          
            - meta: flush_handlers
          
            - name: Run cluster creation script
              include_tasks: createcluster.yml
              run_once: true
              when: purpose == 'install' or purpose == 'reinstall'
          
          • prepareredisconfig.yml
            ---
            - name: check dir - /etc/redis/redis_{{ item }}
              include_tasks: checkdir.yml
              vars:
                folder: "/etc/redis/redis_{{ item }}"
              with_items: "{{ redis_ports }}"
          
            - name: Prepare Configs
              vars:
                redis_port: "{{item}}"
              template:
                src: config.j2
                dest: "/etc/redis/redis_{{ item }}.conf"
                owner: redis
              notify: restart-service
              with_items:  "{{redis_ports}}"
          
          • prepareservice.yml
            ---
            - name: Prepare services
              vars:
                redis_port: "{{item}}"
              template:
                src: service.j2
                dest: "/etc/systemd/system/redis_{{item}}.service"
                owner: redis
                group: redis
              with_items: "{{redis_ports}}"
          
          • uninstall.yml
            - name: Stop Service
                service:
                  name: "redis_{{item}}"
                  state: stopped
                with_items: "{{ redis_ports }}"
          
              - name: Disable Service
                shell: systemctl disable redis_{{item}}
                with_items: "{{ redis_ports }}"
          
              - name: Delete config
                file:
                  path: "/etc/redis/redis_{{item}}.conf"
                  state: absent
                with_items: "{{ redis_ports }}"
          
              - name: Delete service
                file:
                  path: "/etc/systemd/system/redis_{{item}}.service"
                  state: absent
                with_items: "{{ redis_ports }}"
          
              - name: Recursively remove directory
                file:
                  path: /etc/redis/redis_{{item}}
                  state: absent
                with_items: "{{ redis_ports }}"
          
              - name: Remove directory
                file:
                  path: /etc/redis/
                  state: absent
          
          • upgrade.yml
            ---
            - include_tasks: installredis.yml
          
        • templates

          • config.j2
            dir /etc/redis/redis_{{redis_port}}
            bind {{ip}} 127.0.0.1
            requirepass {{redispass}}
            masterauth {{redispass}}
            port {{redis_port}}
            pidfile /var/run/redis_{{redis_port}}.pid
            maxclients 100000
            # 啟用 redis cluster
            cluster-enabled yes
            # 每個 node 需要獨立,cluster 自行維護使用,不需人為介入
            cluster-config-file nodes_{{redis_port}}.conf
            # node 判斷失效的時間
            cluster-node-timeout 5000
            maxmemory-policy volatile-lru
            loglevel notice
          
          • service.j2
            [Unit]
            Description=Redis persistent key-value database
            After=network.target
            After=network-online.target
            Wants=network-online.target
          
            [Service]
            ExecStart=/usr/bin/redis-server /etc/redis/redis_{{redis_port}}.conf --supervised systemd
          
            ExecStop=/usr/libexec/redis-shutdown redis/redis_{{redis_port}}
            Type=notify
            User=redis
            Group=redis
            RuntimeDirectory=redis_{{redis_port}}
            RuntimeDirectoryMode=0755
            LimitNOFILE=10000000
            LimitCORE=infinity
            LimitNPROC=infinity
            LimitMEMLOCK=infinity
          
            [Install]
            WantedBy=multi-user.target
          
        • vars

          • main.yml
            redispass: pass.123
            redisversion: redis-0:6.0.8-1.el8.remi.x86_64
          
        • inventories

          • dev.ini

          ansible_host 是外網 ip 而 ip 則為內網 ip,如果 ansible client 是在內網,可以精簡為 ansible_host 就好

            [redis_all]
            redis1 ansible_host=10.0.1.5 ip=10.0.1.5 ansible_ssh_user=root ansible_ssh_pass=pass.123 redis_ports=7000,7003
            redis2 ansible_host=10.0.1.6 ip=10.0.1.6  ansible_ssh_user=root ansible_ssh_pass=pass.123 redis_ports=7001,7004
            redis3 ansible_host=10.0.1.7 ip=10.0.1.7 ansible_ssh_user=root ansible_ssh_pass=pass.123 redis_ports=7002,7005
          
        • README.md

          ## 全新安裝
        
              ```bash
              ansible-playbook -i roles/redis-replication/inventories/dev.ini -e "purpose=install" main.yml
              ```
        
          ## 重新安裝
        
              > 先 uninstall 並排除安裝基本套件
        
              ```bash
              ansible-playbook -i roles/redis-replication/inventories/dev.ini -e "purpose=reinstall" main.yml
              ```
        
          ## 更新 config
        
              ```bash
              ansible-playbook -i roles/redis-replication/inventories/dev.ini main.yml
              ```
        
          ## 升級
        
              ```
              ansible-playbook -i roles/redis-replication/inventories/dev.ini -e "purpose=upgrade" main.yml
              ```
          ## restart service
        
              ```
              ansible-playbook -i roles/redis-replication/inventories/dev.ini -e "purpose=restart" main.yml
              ```
        
    • ansible.cfg

      [defaults]
      host_key_checking = False
      roles_path = ./roles
      
    • main.yml

      - hosts: redis_all
        roles:
          - redis-cluster
    

心得

大致上流程與之前筆記 Ansible 安裝 Redis Cluster 相同,主要變動的部份是

  1. dnf module 的註冊與啟用
  2. 使用 dnf 的 module 進行安裝

完整程式可以參考 yowko/ansible-dnf-install-redis-cluster

參考資訊

  1. Ansible 安裝 Redis Cluster
  2. yowko/ansible-dnf-install-redis-cluster