Skip to content

PMM-14170: Add Valkey setup and configuration scripts #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: v3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions pmm_qa/pmm-framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,31 @@ def setup_dockerclients(db_type, db_version=None, db_config=None, args=None):
# Call the function to run the setup_docker_client_images script
execute_shell_scripts(shell_scripts, shell_scripts_path, env_vars, args)

def setup_valkey(db_type, db_version=None, db_config=None, args=None):

# Check if PMM server is running
container_name = get_running_container_name()
if container_name is None and args.pmm_server_ip is None:
print(f"Check if PMM Server is Up and Running..Exiting")
exit()

# Gather Version details
valkey_version = os.getenv('VALKEY_VERSION') or db_version or database_configs[db_type]["versions"][-1]

# Define environment variables for playbook
env_vars = {
'PMM_SERVER_IP': args.pmm_server_ip or container_name or '127.0.0.1',
'VALKEY_VERSION': valkey_version,
'CLIENT_VERSION': get_value('CLIENT_VERSION', db_type, args, db_config),
'ADMIN_PASSWORD': os.getenv('ADMIN_PASSWORD') or args.pmm_server_password or 'admin',
'PMM_QA_GIT_BRANCH': os.getenv('PMM_QA_GIT_BRANCH') or 'v3'
}

# Ansible playbook filename
playbook_filename = 'valkey/valkey.yml'

# Call the function to run the Ansible playbook
run_ansible_playbook(playbook_filename, env_vars, args)

# Set up databases based on arguments received
def setup_database(db_type, db_version=None, db_config=None, args=None):
Expand Down Expand Up @@ -834,6 +859,8 @@ def setup_database(db_type, db_version=None, db_config=None, args=None):
setup_ssl_mlaunch(db_type, db_version, db_config, args)
elif db_type == 'BUCKET':
setup_bucket(db_type, db_version, db_config, args)
elif db_type == 'VALKEY':
setup_valkey(db_type, db_version, db_config, args)
else:
print(f"Database type {db_type} is not recognised, Exiting...")
exit(1)
Expand Down
4 changes: 4 additions & 0 deletions pmm_qa/scripts/database_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,9 @@
},
"BUCKET": {
"configurations": {"BUCKET_NAMES": 'bcp'}
},
"VALKEY": {
"versions": ["7-alpine", "8-bookworm"],
"configurations": {"CLIENT_VERSION": "3-dev-latest", "SETUP_TYPE": "", "TARBALL": ""}
}
}
15 changes: 15 additions & 0 deletions pmm_qa/valkey/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash -e

docker exec -it pmm-server pmm-admin remove valkey valkey-primary-svc || :
docker exec -it pmm-server pmm-admin remove valkey valkey-replica1-svc || :
docker exec -it pmm-server pmm-admin remove valkey valkey-replica2-svc || :
docker exec -it pmm-server pmm-admin remove valkey sentinel1-svc || :
docker exec -it pmm-server pmm-admin remove valkey sentinel2-svc || :
docker exec -it pmm-server pmm-admin remove valkey sentinel3-svc || :

docker rm -vf valkey-primary valkey-replica-1 valkey-replica-2 || :
docker rm -vf sentinel-1 sentinel-2 sentinel-3 || :

docker volume rm -f valkey-primary-data valkey-replica-1-data valkey-replica-2-data || :

rm -rf "$HOME/valkey"
22 changes: 22 additions & 0 deletions pmm_qa/valkey/sentinel.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# sentinel.conf
bind 0.0.0.0

port 26379

# Monitor the master
sentinel monitor valkey-primary valkey-primary 6379 {{ sentinel_quorum }}
sentinel auth-user valkey-primary default
sentinel auth-pass valkey-primary "{{ valkey_password }}"
sentinel resolve-hostnames yes

# Failover timeouts
sentinel down-after-milliseconds valkey-primary 5000
sentinel failover-timeout valkey-primary 10000
sentinel parallel-syncs valkey-primary 1

# Security
protected-mode no

# Logging
loglevel notice
logfile ""
27 changes: 27 additions & 0 deletions pmm_qa/valkey/valkey-primary.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Basic Valkey configuration for primary
bind 0.0.0.0
port 6379

requirepass "{{ valkey_password }}"
masterauth "{{ valkey_password }}"

# Persistence
save 900 1
save 300 10
save 60 10000

# Replication
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5

# Security
protected-mode no

# Logging
loglevel notice
logfile ""

# Memory management
maxmemory-policy allkeys-lru
28 changes: 28 additions & 0 deletions pmm_qa/valkey/valkey-replica.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Basic Valkey configuration for replica
bind 0.0.0.0
port 6379

requirepass "{{ valkey_password }}"
masterauth "{{ valkey_password }}"

# Replication
replicaof valkey-primary 6379
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5

# Persistence
save 900 1
save 300 10
save 60 10000

# Security
protected-mode no

# Logging
loglevel notice
logfile ""

# Memory management
maxmemory-policy allkeys-lru
209 changes: 209 additions & 0 deletions pmm_qa/valkey/valkey.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
- name: Deploy Valkey Cluster with Sentinel
hosts: localhost
gather_facts: false
vars:
valkey_version: "{{ lookup('env', 'VALKEY_VERSION') | default('7-alpine', true) }}"
valkey_image: "valkey/valkey:{{ valkey_version }}"
valkey_network_name: "pmm-qa"
valkey_password: ""
valkey_data_dir: "{{ lookup('env', 'HOME') }}/valkey/data"
valkey_config_dir: "{{ lookup('env', 'HOME') }}/valkey/config"
valkey_primary_port: 6379
valkey_replica_count: 2
valkey_replica_start_port: 6380
sentinel_count: 3
sentinel_start_port: 26379
sentinel_quorum: 2

pmm_server_name: "pmm-server"

tasks:
- name: Create Docker network
community.docker.docker_network:
name: "{{ valkey_network_name }}"
driver: bridge
state: present

- name: Create config directory
file:
path: "{{ valkey_config_dir }}"
state: directory
mode: '0755'

- name: Create a config directory per Sentinel
file:
path: "{{ valkey_config_dir }}/sentinel-{{ item }}"
state: directory
mode: '0755'
loop: "{{ range(1, sentinel_count + 1) | list }}"

- name: Create data directory
file:
path: "{{ valkey_data_dir }}"
state: directory
mode: '0755'

- name: Generate Valkey primary configuration
template:
src: valkey-primary.conf.j2
dest: "{{ valkey_config_dir }}/valkey-primary.conf"
mode: '0644'

- name: Generate Valkey replica configurations
template:
src: valkey-replica.conf.j2
dest: "{{ valkey_config_dir }}/valkey-replica-{{ item }}.conf"
mode: '0644'
loop: "{{ range(1, valkey_replica_count + 1) | list }}"

- name: Generate Sentinel configurations
template:
src: sentinel.conf.j2
dest: "{{ valkey_config_dir }}/sentinel-{{ item }}/sentinel.conf"
mode: '0664'
loop: "{{ range(1, sentinel_count + 1) | list }}"

- name: Generate a password if not provided
when: valkey_password == ""
set_fact:
valkey_password: "{{ lookup('community.general.random_string', length=20, min_special=5, min_upper=2, override_special='!?()[]{}:;/|@#$%&^*<>=_+-') }}"

- name: Display generated Valkey password
debug:
msg: "Generated Valkey password: {{ valkey_password }}"

- name: Create Docker volume for primary data
community.docker.docker_volume:
name: "valkey-primary-data"
state: present

- name: Create Docker volumes for replica data
community.docker.docker_volume:
name: "valkey-replica-{{ item }}-data"
state: present
loop: "{{ range(1, valkey_replica_count + 1) | list }}"

- name: Start Valkey primary container
community.docker.docker_container:
name: "valkey-primary"
image: "{{ valkey_image }}"
state: started
restart_policy: unless-stopped
networks:
- name: "{{ valkey_network_name }}"
ports:
- "{{ valkey_primary_port }}:6379"
volumes:
- "valkey-primary-data:/data"
- "{{ valkey_config_dir }}/valkey-primary.conf:/usr/local/etc/valkey/valkey.conf:ro"
command: ["valkey-server", "/usr/local/etc/valkey/valkey.conf"]
healthcheck:
test: ["CMD", "valkey-cli", "-a", "{{ valkey_password }}", "ping"]
interval: 10s
timeout: 5s
retries: 5

- name: Wait for the primary to be ready
wait_for:
host: localhost
port: "{{ valkey_primary_port }}"
timeout: 30
delay: 1

- name: Start Valkey replica containers
community.docker.docker_container:
name: "valkey-replica-{{ item }}"
image: "{{ valkey_image }}"
state: started
restart_policy: unless-stopped
networks:
- name: "{{ valkey_network_name }}"
ports:
- "{{ valkey_replica_start_port + item - 1 }}:6379"
volumes:
- "valkey-replica-{{ item }}-data:/data"
- "{{ valkey_config_dir }}/valkey-replica-{{ item }}.conf:/usr/local/etc/valkey/valkey.conf:ro"
command: ["valkey-server", "/usr/local/etc/valkey/valkey.conf"]
healthcheck:
test: ["CMD", "valkey-cli", "-a", "{{ valkey_password }}", "ping"]
interval: 10s
timeout: 5s
retries: 5
loop: "{{ range(1, valkey_replica_count + 1) | list }}"

- name: Wait for replicas to be ready
wait_for:
host: localhost
port: "{{ valkey_replica_start_port + item - 1 }}"
timeout: 30
delay: 1
loop: "{{ range(1, valkey_replica_count + 1) | list }}"

- name: Start Sentinel containers
community.docker.docker_container:
name: "sentinel-{{ item }}"
image: "{{ valkey_image }}"
state: started
restart_policy: unless-stopped
networks:
- name: "{{ valkey_network_name }}"
ports:
- "{{ sentinel_start_port + item - 1 }}:26379"
volumes:
- "{{ valkey_config_dir }}/sentinel-{{ item }}:/usr/local/etc/valkey"
command: ["valkey-sentinel", "/usr/local/etc/valkey/sentinel.conf"]
healthcheck:
test: ["CMD", "valkey-cli", "-p", "{{ sentinel_start_port }}", "ping"]
interval: 10s
timeout: 5s
retries: 5
loop: "{{ range(1, sentinel_count + 1) | list }}"

- name: Wait for Sentinels to be ready
wait_for:
host: localhost
port: "{{ sentinel_start_port + item - 1 }}"
timeout: 30
delay: 1
loop: "{{ range(1, sentinel_count + 1) | list }}"

- name: Verify cluster status
community.docker.docker_container_exec:
container: "valkey-primary"
command: valkey-cli -a "{{ valkey_password }}" info replication
register: cluster_status

- name: Display cluster status
debug:
msg: "{{ cluster_status.stdout_lines }}"

- name: Run Sentinel status command
community.docker.docker_container_exec:
container: "sentinel-1"
command: valkey-cli -p {{ sentinel_start_port }} sentinel masters
register: sentinel_status

- name: Display Sentinel status
debug:
msg: "{{ sentinel_status.stdout_lines }}"

- name: Add the primary to monitoring
community.docker.docker_container_exec:
container: "{{ pmm_server_name }}"
command: pmm-admin add valkey --cluster=valkey-cluster --replication-set=valkey-repl --environment=valkey-test --username=default --password="{{ valkey_password }}" --service-name=valkey-primary-svc --host=valkey-primary --port=6379 --custom-labels='role=primary'
ignore_errors: yes

- name: Add the replicas to monitoring
community.docker.docker_container_exec:
container: "{{ pmm_server_name }}"
command: pmm-admin add valkey --cluster=valkey-cluster --replication-set=valkey-repl --environment=valkey-test --username=default --password="{{ valkey_password }}" --service-name=valkey-replica{{ item }}-svc --host=valkey-replica-{{ item }} --port=6379 --custom-labels='role=replica'
loop: "{{ range(1, valkey_replica_count + 1) | list }}"
ignore_errors: yes

- name: Add Sentinels to monitoring
community.docker.docker_container_exec:
container: "{{ pmm_server_name }}"
command: pmm-admin add valkey --cluster=valkey-cluster --environment=valkey-test --username=default --password="{{ valkey_password }}" --service-name=sentinel{{ item }}-svc --host=sentinel-{{ item }} --port={{ sentinel_start_port }} --custom-labels='role=sentinel'
loop: "{{ range(1, sentinel_count + 1) | list }}"
ignore_errors: yes
Loading