Provisionando Redis Sentinel para uma aplicação voltada a transações com cartão.
Tags: redis, f5, terraform, ansible
Published: 2022-07-28 22:17:00

**Motivação**
Nesse artigo quero compartilhar como construí uma infraestrutura de Redis Sentinel altamente disponivel em uma cloud privada baseada em VMWare com cisco ACI na camada de rede, em uma arquitetura de microserviços voltada para autorização de transações com cartão.


> Os dados de host, IP e outras informações apresentados no decorrer desse post são fictícios ou foram mascarados por motivos de segurança


**Como é um fluxo de uma transação com cartão**
Antes de aprofundar na solução do Redis Sentinel, um resumo rápido sobre o contexto de um fluxo de autorização de uma transação de cartão feita via TEF (as famosas maquininhas) e qual o impacto do Redis.

Basicamente uma compra é feita via cartão em uma maquininha no estabelecimento comercial, a partir daí a transação passa pelo adquirente (fornecedor das TEFs), pela bandeira do cartão, pela processadora da transação e por fim no emissor do cartão que vai autorizar ou não a compra e aí o retorno até a maquininha, onde o recebemos no visor a resposta. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5mnml764tdpffax7kdf.png)

**Onde entra o Redis nessa história**
O serviço do Redis Sentinel entra no ponto da resposta do emissor para a processadora, autorizando ou não a compra, onde essa resposta tem que ser em até 2 segundos e com média diária de 1 milhão de transações dia. 

O Redis Sentinel entra no ecosistema do microserviço responsável por tratar a transação e responder de volta para a processadora. 

O Redis mantém um tipo de cache em memória, onde salva algumas informações importantes, por exemplo, IDs do cartão da processadora, associado ao usuário do lado do emissor, também tem os dados da conta bancária na aplicação de core bancário (agência e conta), dados de pacote de serviço, etc. , reduzindo drasticamente a busca desses dados entre vários microserviços e banco de dados. 

Os dados em memória são persistidos e sincronizados em disco entre as máquinas onde existe o serviço do Redis. 

**O desafio para criar a solução do Redis Sentinel**

Recebemos a demanda para criar uma solução com Redis com disponibilidade e resiliência, subindo a infraestrutura no nossa recém-criada cloud privada baseada em VMWare vRealize 7.x na camada de virtualização de máquinas e na camada de rede uma SDN Cisco ACI Anywhere. 

Abaixo segue o diagrama de como ficou a arquitetura final.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jxpfehmdd6iowa4wecn8.png)

**Entrada GSLB e Load Balance no F5**
Como podemos ver no diagrama acima, em cada datacenter foi criado um Load Balancer no F5 (ver print da conf mais abaixo) para balancear as requisições entre as máquinas virtuais na porta 5679 (redis service).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjoz6ih5msmu953kt9i1.png)

O campo _send string_ contém a string do Redis que retorna a informação se o server é um master ou slave, no F5 configuramos o receive string como 'role:master', assim o LB estará "Up" se encontrar o master.

A gestão e eleição do master entre as 4 VM's fica a cargo do serviço do sentinel.

 Na frente desses 2 LB's, foi criado uma entrada GSLB (Global Server Load Balance)(ver print da conf mais abaixo), também uma feature no F5 para receber as requisições do microserviço vindas do orquestrador de container Mesos e balancear entre os 2 datacenters.

Do lado do cliente Redis na aplicação a configuração da conexão vai passar somente o hostname definido no GSLB e a porta do Redis, onde o GSLB vai encaminhar direto para o server onde estará o master do redis. Diferente de outras soluções com Redis Sentinel onde na configuração do cliente redis é passado o IP/hostname de todos os nodes sentinel que são validados durante a conexão inicial para encontrar qual deles é o master. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m4tljn4mla28emscak0o.png)

**Provisionamento da Máquinas Virtuais**
O provisionamento das máquinas virtuais nesse ambiente VMWare VRA7 foi feito com terraform

O código terraform utilizado pode ser consultado no meu github: [redis-sentinel-vmware-iac](https://github.com/laerteg/redis-sentinel-vmware-iac)

Para a execução do terraform, clonado repositório do github e executado terraform, no exemplo abaixo provisionado as máquinas no Datacenter A (ex: dca).

```
$ git clone git@github.com:laerteg/redis-sentinel-vmware-iac.git
$ cd terraform/prod/redis-dca
$ terraform init
$ terraform plan -var-file="../../dc/dca-prod.tfvars" -var-file="../../service/redis/variables.tfvars"
$ terraform apply -var-file="../../dc/dca-prod.tfvars" -var-file="../../service/redis/variables.tfvars"
```

**Gestão de Configuração com Ansible**

Após criadas as máquinas virtuais via terraform, a parte de configuração e instalação do Redis Sentinel foi feita utilizando Ansible.

Para a execução do ansible, clonado [repositório](https://github.com/laerteg/redis-sentinel-vmware-iac) do github e executado terraform, no exemplo abaixo provisionado as máquinas no Datacenter A (ex: dca).

Antes de executar o playbook do ansible, alguns ajustes foram necessários:

- Ajustar o inventário do ansible (hosts) com os IPs das instâncias criadas;

- Editar o arquivo main.yml e ajustar as variáveis de acordo com o projeto:

**mymaster_ip**:   colocar o IP da instância que será o Master inicial.
**quorum_num**:  colocar o numero do quorum que será utilizado para eleição do novo master em caso de problemas. (Ex: Redis com 4 instâncias quorum = 2).
**newrelic_key**:  inserir o código do new_relic de acordo com o ambiente (Prod ou QA).
**env**:  ambiente do Redis. (Ex: prod ou QA).
**persist_data**:  Se o redis terá persistencia de dados ou não.  Opções:  'yes'  ou 'no'.

> Inicialmente foi definido **quorum_num = 3** porém quando o Datacenter B ficou sem conectividade, o sentinel não conseguiu fazer a re-eleição do master pois haviam somente 2 nodes do Datacenter A, com quorum de 2, o sentinel conseguiu eleger um master e um slave..

Abaixo exemplo de execução do playbook do ansible:

```
$ git clone git@github.com:laerteg/redis-sentinel-vmware-iac.git
$ 
$ cd ansible/install_redis
$ ansible-playbook -i hosts main.yml
```

**Validações e Troubleshooting**
Para verificações e testes com as portas TCP 5679 e 25679 entre as máquinas:

nmap
ncat, nc

Para verificações do sistema redis, utilizado redis-cli.

```
$ redis-cli  -h  10.181.26.109  info  replication

# Replication
role:master
connected_slaves:2
slave0:ip=10.181.26.110,port=6379,state=online,offset=165366625665,lag=1
slave1:ip=10.181.26.120,port=6379,state=online,offset=165366625804,lag=0
master_replid:119a4cc3b2c5cc8e374423ab9034acd540befbad
master_replid2:cb7cc24457975dde598db2b78b54afe76b9f630d
master_repl_offset:165366625818
```
Na saída acima podemos verificar que o node do Redis em questão é um master e tem 2 slaves conectados via sentinel.

```
$ redis-cli  -h  10.181.26.110  info  replication

# Replication
role:slave
master_host:10.181.26.109
master_port:6379
master_link_status:up
```
Na saída acima podemos verificar que o node do Redis em questão é um slave, qual é o master, porta e conexão com master Up.

```
$ redis-cli -h 10.181.26.109 -p 26379 sentinel masters

1) "name"
2)"mymaster"
3) "ip"
4) "10.181.26.109"
5) "port"
6) "6379"
...
...
17) "last-ok-ping-reply"
18) "73"
19) "last-ping-reply"
20) "73"
21) "down-after-milliseconds"
22) "10000"
23) "info-refresh"
24) "216"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "4313841777"
29) "config-epoch"
30) "3"
31) "num-slaves"
32) "2"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "30000"
39) "parallel-syncs"
40) "1"
```
Nesta saída acima podemos ver várias informações sobre o master sentinel, slaves conectados, etc.. No caso de problemas de conectividade entre os nodes apareceríam informações conforme abaixo:

```
10) "s_down,master,disconnected"
33) "num-slaves"
34) "0"
35) "num-other-sentinels"
36) "0"
```

**Passo a passo - Instalação do Redis Sentinel**

**Ajustes no Kernel do S.O.**

- Desabilitar Transparent Huge Pages (THP)

echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled   (após reboot volta opção 'always')

Para desabilitar o THP após reboot do servidor, criar arquivo **/etc/init.d/after.local** com o seguinte conteudo:
```
# Disable THP for REDIS

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag
fi
```
- Ulimit, Max Connections, overcommit memory, etc..
```
# sysctl -w vm.min_free_kbytes=1448
# sysctl -w vm.overcommit_memory=1
# sysctl -w net.core.somaxconn=65365
# sysctl -w fs.file-max=100000
# ulimit -H -n 32768
# ulimit -S -n 24576
```

- /etc/security/limits.conf
```
soft nofile 24576
hard nofile 32768
redis soft nofile 24576
redis hard nofile 32768
```
- Listar e Atualizar limits.conf

```
sysctl -a (show variables)
sysctl -p (reload conf)
```
- Verificar limits de um processo
```
ps -ef | grep redis | awk '{print $2}'
60224

sudo grep 'open files' /proc/60224/limits
Max open files 24576 32768 files
```
**Instalação do pacote Redis no SUSE Linux**

`# zypper addrepo https://download.opensuse.org/repositories/server:database/SLE_15_SP1/server:database.repo`

`# zypper search-packages -d redis`
```
Package Module or Repository SUSEConnect Activation Command
-------------------------------------------- ------------------------------------------------------- ---------------------------------------------------------

redis-4.0.11-bp151.2.1.x86_64 susemanager:suse-packagehub-15-sp1-standard-pool-x86_64

redis-5.0.8-129.3.x86_64 server_database
```

`# zypper refresh`
`# zypper install redis`
`# zypper packages --installed-only`

```
i+ | server_database | redis | 5.0.8-129.3 | x86_64
v | SUSE-PackageHub-15-SP1-Standard-Pool for x86_64 | redis | 4.0.11-bp151.2.1 | x86_64
```

`#/usr/sbin> ls -la | grep redis`
```
lrwxrwxrwx 1 root root 7 abr 1 01:18 rcredis -> service
lrwxrwxrwx 1 root root 12 abr 1 01:18 redis-check-aof -> redis-server
lrwxrwxrwx 1 root root 12 abr 1 01:18 redis-check-rdb -> redis-server
lrwxrwxrwx 1 root root 12 abr 1 01:18 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 1781592 abr 1 01:18 redis-server
```

`#/usr/bin> ls -la | grep redis`
```
-rwxr-xr-x 1 root root 646712 abr 1 01:18 redis-benchmark
lrwxrwxrwx 1 root root 20 abr 1 01:18 redis-check-aof -> ../sbin/redis-server
lrwxrwxrwx 1 root root 20 abr 1 01:18 redis-check-rdb -> ../sbin/redis-server
-rwxr-xr-x 1 root root 812944 abr 1 01:18 redis-cli
```

Criação de Usuário e Grupo redis

`# groupadd -r redis`
`# useradd --system -g redis  -d /home/redis`

Criação Diretório de Configuração

`# mkdir -p /etc/redis`
`# chown redis:redis /etc/redis`

Criação Diretório de Dump (*.RDB e *.AOF)

`# mkdir -p /var/lib/redis`
`# chown redis:redis /var/lib/redis`

Criação Diretório de Logs

`# touch /var/log/redis.log`
`# touch /var/log/sentinel.log`
`# chown redis:redis /var/log/redis.log`
`# chown redis:redis /var/log/sentinel.log`

>**NOTA**:  o serviço do Redis/Sentinel é sensível as pastas onde escreve como /etc/redis, /var/lib, /var/log, etc.. em caso de não ter permissão, o serviço não ativa.

|             |Master & Slave                                      |
|-------------|----------------------------------------------------|
|**redis.conf**   |bind 127.0.0.1  <LOCAL_IP_ADDRESS>                  |
|             |protected-mode no                                   |
|             |port 6379                                           |
|             |daemonize yes                                       |
|             |supervised systemd                                  |
|             |pidfile "/opt/redis/run/redis_6379.pid"             |
|             |logfile "/opt/redis/log/redis.log"                  |
|             |save 900 1    (cada 900s se 1 chave mudar)          |
|             |save 300 10   (cada 300s se 10 chaves mudarem)      |
|             |save 60 10000 (cada 60s se 10000 chaves mudarem)    |
|             |dbfilename "dump.rdb"                               |
|             |appendonly yes                                      |
|             |appendfilename "NOME_PROJETO.aof"                   |
|-------------|----------------------------------------------------|
|**sentinel.conf**|# Deixar o bind ser feito em todas interfaces       |
|             |#bind 127.0.0.1                                     |
|             |protected-mode no                                   |
|             |# The port that sentinel instance will run on       |
|             |port 26379                                          |
|             |supervised systemd                                  |
|             |pidfile /opt/redis/run/redis-sentinel.pid           |
|             |logfile "/opt/redis/log/sentinel.log"               |
|             |# IP Redis Master inicial, porta e quorum           |
|             |sentinel monitor mymaster \<IP_MASTER\>  6379 \<QUORUM\>|
|             |sentinel down-after-milliseconds mymaster 5000      |

**supervised systemd:** se comentado serviço systemctl não sobe
**Persistencia dos dados:** Se for ligar, as 3 linhas abaixo devem ser descomentadas
- save 900 1      (cada 15min se 1 chave mudar)
- save 300 10   (cada  5min se 10 chaves mudarem)
- save 60 10000   (cada 1min se 10000 chaves mudarem)

**dbfilename "dump.rdb":** dados persistidos são escritos no dump
**appendonly yes:** habilita escrita do arquivo AOF
**appendfilename "NOME_PROJETO.aof":** nome do arquivo AOF (default: "appendonly.aof").
**QUORUM:** Com minimo de 2 nodes e quorum igual a 2, o sentinel consegue eleger um master.

**Configuração dos Serviços Systemctl**

`/etc/systemd/system/redis.service`
```
[Unit]
Description=Redis In-Memory Data Store
After=network.target

[Service]
#Type=notify
Type=forking
LimitNOFILE=64000
User=redis
Group=redis
ExecStart=/usr/sbin/redis-server /opt/redis/conf/redis.conf
ExecStop=/usr/bin/redis-cli -h 127.0.0.1 shutdown
Restart=always

[Install]
WantedBy=multi-user.target
```

`/etc/systemd/system/sentinel.service`
```
[Unit]
Description=Sentinel for Redis
After=network.target

[Service]
Type=notify
LimitNOFILE=64000
User=redis
Group=redis
PIDFile=/opt/redis/run/sentinel.pid
ExecStart=/usr/sbin/redis-sentinel /opt/redis/conf/sentinel.conf
ExecStop=/bin/kill -s TERM $MAINPID
Restart=always

[Install]
WantedBy=multi-user.target
```

Como usuário ROOT habilitar e iniciar serviço redis em todos os nodes:

```
# systemctl enable redis.service
# systemctl start redis.service
```

Saída de log do serviço redis:
```
47705:C 07 Apr 2020 12:26:07.485 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
47705:C 07 Apr 2020 12:26:07.485 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=47705, just started
47705:C 07 Apr 2020 12:26:07.485 # Configuration loaded
47705:C 07 Apr 2020 12:26:07.485 * supervised by systemd, will signal readiness
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.8 00000000/0) 64 bit
 _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 47705
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

47705:S 07 Apr 2020 12:26:07.486 # Server initialized
47705:S 07 Apr 2020 12:26:07.486 * Ready to accept connections
47705:S 07 Apr 2020 12:26:07.486 * Connecting to MASTER 10.181.26.110:6379
47705:S 07 Apr 2020 12:26:07.486 * MASTER <-> REPLICA sync started
47705:S 07 Apr 2020 12:26:07.486 * Non blocking connect for SYNC fired the event.
47705:S 07 Apr 2020 12:26:07.487 * Master replied to PING, replication can continue...
47705:S 07 Apr 2020 12:26:07.487 * Partial resynchronization not possible (no cached master)
47705:S 07 Apr 2020 12:26:07.488 * Full resync from master: e1a164521f59ed78711cc7e3a186dda89562021d:0
47705:S 07 Apr 2020 12:26:07.575 * MASTER <-> REPLICA sync: receiving 175 bytes from master
```

Como usuário ROOT habilitar e iniciar serviço sentinel em todos os nodes:

```
#systemctl enable sentinel.service
#systemctl start sentinel.service
```

Saída de log do serviço sentinel:
```
112167:X 14 Apr 2020 11:44:24.554 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
112167:X 14 Apr 2020 11:44:24.554 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=112167, just started
112167:X 14 Apr 2020 11:44:24.554 # Configuration loaded
112167:X 14 Apr 2020 11:44:24.554 * supervised by systemd, will signal readiness
112167:X 14 Apr 2020 11:44:24.555 * Running mode=sentinel, port=26379.
112167:X 14 Apr 2020 11:44:24.555 # Sentinel ID is dac84d11847121c48bc18e6ddb37b7cdd800e276
112167:X 14 Apr 2020 11:44:24.555 # +monitor master mymaster 10.181.26.110 6379 quorum 3
112167:X 14 Apr 2020 11:44:24.557 * +slave slave 10.181.26.107:6379 10.181.26.107 6379 @ mymaster 10.181.26.110 6379
112167:X 14 Apr 2020 11:44:24.558 * +slave slave 10.181.26.108:6379 10.181.26.108 6379 @ mymaster 10.181.26.110 6379
112167:X 14 Apr 2020 11:44:24.559 * +slave slave 10.181.26.109:6379 10.181.26.109 6379 @ mymaster 10.181.26.110 6379
112167:X 14 Apr 2020 11:44:25.163 * +sentinel sentinel 5eff2261037d126bea40bbd5cd64523b1cfe1604 10.181.26.108 26379 @ mymaster 10.181.26.110 6379
112167:X 14 Apr 2020 11:44:26.427 * +sentinel sentinel 1ded330e6ac1da4f4430d72a5cb257546ebe0d9e 10.181.26.109 26379 @ mymaster 10.181.26.110 6379
112167:X 14 Apr 2020 11:44:35.955 * +sentinel sentinel aaeeb987bb282d63fa32788c660a748b377b11bb 10.181.26.109 26379 @ mymaster 10.181.26.110 6379
```


Para verificar possiveis problemas durante inicialização dos serviços utilizar JOURNALCTL:
```
$ journalctl -u redis
$ journalctl -xe
```

Ou verificar os arquivos de log do serviço.

Em caso de alteração do arquivo de serviço, carregar novamente e fazer o restart dos serviços:
```
# systemctl daemon-reload
# systemctl restart redis.service
```

**Benchmark do REDIS**
Na própria instalação do Redis existe uma ferramenta para fazer um benchmark contra a instalação do Redis e avaliar por exemplo se ele vai dar conta de certo número de requisições com chaves de tamanho X.
```
redis-benchmark -q -n <requests> -c <conexões> -P <pipeline x instruções paralelas>

q = quiet
n = num. requests (default = 100000)
c = conexões client paralelas
P = Pipeline x comandos paralelos (default 1 = no pipeline)
d = tamanho da chave
t = subconjunto de comandos (GET, SET)
```
Exemplo: 1000 requisições de comando set/get com chaves no valor de 50Mb.
```
$ redis-benchmark -h 10.181.26.110 -t set,get -d 50 -n 1000 -q

SET: 71428.57 requests per second
GET: 71428.57 requests per second
```

**Latência das Operações**
O redis-cli tem opção pra ver latencia das operações sendo executados pelo redis, no exemplo o primeiro temos uma média de 0,04 microsegundos de latencia de uma operação.
```
$ redis-cli -h 10.181.26.110 --latency

min: 0, max: 1, avg: 0.04 (1313 samples)^C
```
Esse segundo exemplo é a latencia intrinseca, ou seja latencia daquilo que está fora do scopo do redis, por exemplo das camadas de virtualização, SO, etc.
```
$ redis-cli -h 10.181.26.110 --intrinsic-latency 30

Max latency so far: 1 microseconds.
Max latency so far: 6 microseconds.
Max latency so far: 7 microseconds.
Max latency so far: 9 microseconds.
Max latency so far: 24 microseconds.
Max latency so far: 29 microseconds.
Max latency so far: 165 microseconds.
Max latency so far: 636 microseconds.
Max latency so far: 713 microseconds.
748875096 total runs (avg latency: 0.0401 microseconds / 40.06 nanoseconds per run).
Worst run took 17798x longer than the average latency.
```

>A média da latencia-intrinseca / media da latencia = % de tempo total da requisição é gasto pelo sistema em processos que não são controlados pelo Redis.
Por exemplo:  media latencia = 0,18 microseg / media latencia-intrinseca = 0,06 microseg.
Significa que 30% do tempo total  de uma requisição, é gasto com processos fora do redis.

**Monitoração da Infraestrutura Redis**

Nesse projeto optamos por configurar nos nodes do Redis o envio das métricas de infraestrutura para o New Relic.

Instalação do módulo do NewRelic e especifico para o Redis:
Adicionar repositório SUSE:
```
$ sudo rpm --import https://download.newrelic.com/infrastructure_agent/gpg/newrelic-infra.gpg
$ sudo curl -o /etc/zypp/repos.d/newrelic-infra.repo https://download.newrelic.com/infrastructure_agent/linux/zypp/sles/12.4/x86_64/newrelic-infra.repo
```
Instalar pacote padrão do NewRelic e específico Redis:
```
$ sudo zypper -n install newrelic-infra
$ sudo zypper -n install nri-redis
```
NOTA: o serviço systemd do NR é ativado durante a instalação do pacote.

`/etc/systemd/system/newrelic-infra.service`

Configuração do New Relic:

Editar o arquivo /etc/newrelic-infra.yml e inserir a chave do NR correta. No nosso caso temos uma chave para QA e outra para Prod.
```
license_key: 1234567890abcdef
log_file: /var/log/newrelic-infra.log
log_to_stdout: false
```

Remover o arquivo Sample para Docker:
```
rm  /etc/newrelic-infra/integrations.d/docker-config.yml-sample
```

Copiar o arquivo SAMPLE de configuraçao do Redis de exemplo para o arquivo  a ser usado pelo NR:
```
# cd  /etc/newrelic-infra/integrations.d/
# cp  redis-config.yml.sample  redis-config.yml
```

Editar o arquivo alterando os campos hostname e environment de acordo com cada node e ambiente:
```
integration_name: com.newrelic.redis

instances:
  - name: redis-metrics
    command: metrics
    arguments:
      hostname: 10.181.26.110
      port: 6379
      keys: '{"0":["<KEY_1>"],"1":["<KEY_2>"]}'
      remote_monitoring: true
    labels:
      environment: production

  - name: redis-inventory
    command: inventory
    arguments:
      hostname: 10.181.26.110
      port: 6379
      remote_monitoring: true
    labels:
      environment: production
```
Após os ajustes reiniciar o serviço do New Relic:
```
$ sudo  systemctl restart newrelic-infra
```

> O código Ansible para a configuração do New Relic está no 
[repositório](https://github.com/laerteg/redis-sentinel-vmware-iac).

Espero que esse conteúdo possa dar algum insight para alguém que esteja pensando em uma solução com Redis nos mesmos moldes em que tive que desenhar lá trás, na ocasião não encontrei muita informação. Nos dias de hoje temos outras opções mas na ocasião foi a que fez sentido e está dando conta do recado até hoje.

Boa leitura.