#!/usr/bin/env ansible-playbook --- #==============================================================# # File : redis.yml # Desc : init redis cluster / node / instance # Ctime : 2020-11-22 # Mtime : 2026-08-06 # Path : redis.yml # Docs : https://pigsty.io/docs/redis/playbook # License : Apache-2.0 @ https://pigsty.io/docs/about/license/ # Copyright : 2018-2026 Ruohang Feng / Vonng (rh@vonng.com) #==============================================================# #--------------------------------------------------------------- # usage #--------------------------------------------------------------- # How to create redis clusters ? # # init all redis instances on group # ./redis.yml -l # create redis cluster # # init redis node (package,dir,exporter) # ./redis.yml -l 10.10.10.10 # create redis cluster # # init all redis instances specific node # ./redis.yml -l 10.10.10.10 # create redis cluster # # init one specific instance 10.10.10.10:6379 # ./redis.yml -l 10.10.10.11 -e redis_port=6379 -t redis # #--------------------------------------------------------------# # Utils #--------------------------------------------------------------# # # bin/redis-add redis-ms # create redis cluster 'redis-ms' # bin/redis-add 10.10.10.10 # create redis node '10.10.10.10' # bin/redis-add 10.10.10.10 6379 # create redis instance '10.10.10.10:6379' # #--------------------------------------------------------------# # Tasks #--------------------------------------------------------------# # redis_node : init redis node # - redis_install : install redis & redis-exporter # - redis_user : create os user redis # - redis_dir : redis fhs directories # redis_exporter : config and launch redis_exporter # - redis_exporter_config : generate redis_exporter config # - redis_exporter_launch : launch redis_exporter # redis_instance : config and launch redis cluster/node/instance # - redis_config : generate redis instance config # - redis_launch : launch redis instance # redis_register : register redis metrics & logs # - add_metrics : register redis metrics to victoria # - add_logs : register redis logs to vector # redis_ha : setup redis sentinel # redis_join : join redis cluster #--------------------------------------------------------------# #--------------------------------------------------------------# # Init Redis Cluster / Node / Instance [redis] #--------------------------------------------------------------# - name: REDIS hosts: all become: true gather_facts: no tags: redis pre_tasks: [ { name: skip non-redis hosts ,meta: end_host ,when: redis_cluster is not defined ,tags: always } ] roles: - { role: node_id ,when: redis_cluster is defined } - { role: redis ,when: redis_cluster is defined } #--------------------------------------------------------------# # setup redis sentinel targets [redis_ha] #--------------------------------------------------------------# - name: REDIS HA hosts: all become: true gather_facts: no tags: redis-ha pre_tasks: [ { name: skip non-redis hosts ,meta: end_host ,when: redis_cluster is not defined ,tags: always } ] tasks: - name: skip if not a redis sentinel cluster when: redis_port is defined or redis_mode|default('standalone') != 'sentinel' or redis_sentinel_monitor is not defined or redis_sentinel_monitor|length == 0 meta: end_host - name: setup redis ha with sentinel when: redis_cluster is defined and redis_port is not defined run_once: true block: - name: render redis sentinel monitor commands copy: dest: /tmp/{{ redis_cluster }}.monitor mode: 0700 content: | {% macro abort(error) %}{{ None['[ERROR] ' ~ error][0] }}{% endmacro %} {% for master in redis_sentinel_monitor %} {% if 'name' not in master or 'host' not in master %} {{ abort("redis_sentinel_monitor require master name and host") }} {% endif %} SENTINEL REMOVE {{ master.name }} {% if not master.remove|default(false) %} SENTINEL MONITOR {{ master.name }} {{ master.host }} {{ master.port|default(6379) }} {{ master.quorum|default(1) }} {% endif %} {% if 'password' in master and master.password != '' %} SENTINEL SET {{ master.name }} auth-pass {{ master.password }} {% endif %} {% endfor %} diff: false - name: render redis sentinel monitor scripts copy: dest: /tmp/{{ redis_cluster }}-ha.sh mode: 0700 content: | {% set redis_meta = hostvars|json_query(cluster_query) %} #!/bin/bash set -eo pipefail {% for i in redis_meta %} {% for port, _ in i.redis_instances.items() %} {% set auth = ('REDISCLI_AUTH=' ~ (i.redis_password|quote) ~ ' ') if i.redis_password|default('') != '' else '' %} cat /tmp/{{ redis_cluster }}.monitor | {{ auth }}{{ redis_type|default('redis') }}-cli -h {{ i.inventory_hostname }} -p {{ port }} {% endfor %} {% endfor %} vars: { cluster_query: "[@.*][0][?redis_cluster=='{{ redis_cluster }}']" } diff: false - name: execute redis sentinel monitor script shell: "/tmp/{{ redis_cluster }}-ha.sh" args: { executable: /bin/bash } always: - name: remove redis sentinel temp files file: path={{ item }} state=absent loop: [ "/tmp/{{ redis_cluster }}.monitor", "/tmp/{{ redis_cluster }}-ha.sh" ] #--------------------------------------------------------------# # join redis instances for cluster [redis_join] #--------------------------------------------------------------# - name: REDIS JOIN hosts: all become: true gather_facts: no tags: redis-join pre_tasks: [ { name: skip non-redis hosts ,meta: end_host ,when: redis_cluster is not defined ,tags: always } ] tasks: - name: skip if not a redis native cluster when: redis_port is defined or redis_mode|default('standalone') != 'cluster' meta: end_host - name: perform redis cluster join when: redis_cluster is defined run_once: true block: - name: fetch redis cluster membership when: redis_port is not defined connection: local set_fact: redis_cluster_members={{ hostvars| json_query(redis_cluster_members_query) }} vars: redis_cluster_members_query: "[@.*][0][?redis_cluster=='{{ redis_cluster }}']" - name: remove legacy redis cluster join script when: redis_port is not defined file: path=/tmp/{{ redis_cluster }}-join.sh state=absent - name: execute redis cluster join when: redis_port is not defined shell: | {% set seed = redis_cluster_members|first %} {% set seed_port = seed.redis_instances.keys()|first %} /bin/{{ redis_type|default('redis') }}-cli -h {{ seed.inventory_hostname }} -p {{ seed_port }} cluster info | grep -q '^cluster_state:ok' && exit 0 /bin/{{ redis_type|default('redis') }}-cli --cluster create --cluster-yes \ {% for node in redis_cluster_members %} {% for port in node.redis_instances %} {{ node.inventory_hostname }}:{{ port }} \ {% endfor %} {% endfor %} --cluster-replicas {{ redis_cluster_replicas|default(1) }} args: { executable: /bin/bash } environment: "{{ {'REDISCLI_AUTH': redis_password} if redis_password|default('')|length > 0 else {} }}" no_log: "{{ redis_password|default('')|length > 0 }}" ...