LaVOZs

The World’s Largest Online Community for Developers

'; amazon web services - AWS ElastiCache Redis can't connect from Laravel nad from redis-cli - LavOzs.Com

I'm having a problem connecting to ElastiCache Redis from Laravel application installed on EC2 instance or even using redis-cli from EC2 instance.

Laravel

I tried to use predis with configurations in database.php like

    'redis' => [
    'client' => 'predis',
    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
        'read_write_timeout' => -1,
        'timeout' => 0
    ],
],

and got 'Error while reading line from the server. [tcp:server here]'

I tried with phpRedis extension with same configurations only change 'client' => 'phpredis' and got error read error on connection {"exception":"[object] (RedisException(code: 0): read error on connection at vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php:69)

Redis cli

Using redis cli redis-cli -h host_here -p 6379 -a password_here I see prompt like host:6379> but typing any command throws error Error: Connection reset by peer

ElastiCache Redis configurations

enter image description here

My EC2 and elastic cache are in the same VPC and using telnet I can connect to redis instance

~$ telnet host 6379
Trying 172.31.23.113...
Connected to host.
Escape character is '^]'.

Thanks for any help!

Related: Laravel + Redis Cache via SSL?

To which I've answered here: https://stackoverflow.com/a/48876398/663058

Relevant details below:

Since you have clustering and TLS then you'll need a different config entirely:

'redis' => [
        'client' => 'predis',
        'cluster' => env('REDIS_CLUSTER', false),

        // Note! for single redis nodes, the default is defined here.
        // keeping it here for clusters will actually prevent the cluster config
        // from being used, it'll assume single node only.
        //'default' => [
        //    ...
        //],

        // #pro-tip, you can use the Cluster config even for single instances!
        'clusters' => [
            'default' => [
                [
                    'scheme'   => env('REDIS_SCHEME', 'tcp'),
                    'host'     => env('REDIS_HOST', 'localhost'),
                    'password' => env('REDIS_PASSWORD', null),
                    'port'     => env('REDIS_PORT', 6379),
                    'database' => env('REDIS_DATABASE', 0),
                ],
            ],
            'options' => [ // Clustering specific options
                'cluster' => 'redis', // This tells Redis Client lib to follow redirects (from cluster)
            ]
        ],
        'options' => [
            'parameters' => [ // Parameters provide defaults for the Connection Factory
                'password' => env('REDIS_PASSWORD', null), // Redirects need PW for the other nodes
                'scheme'   => env('REDIS_SCHEME', 'tcp'),  // Redirects also must match scheme
            ],
            'ssl'    => ['verify_peer' => false], // Since we dont have TLS cert to verify
        ]
    ]

Explaining the above:

  • 'client' => 'predis': This specifies the PHP Library Redis driver to use (predis).
  • 'cluster' => 'redis': This tells Predis to assume server-side clustering. Which just means "follow redirects" (e.g. -MOVED responses). When running with a cluster, a node will respond with a -MOVED to the node that you must ask for a specific key.
    • If you don't have this enabled with Redis Clusters, Laravel will throw a -MOVED exception 1/n times, n being the number of nodes in Redis cluster (it'll get lucky and ask the right node every once in awhile)
  • 'clusters' => [...]: Specifies a list of nodes, but setting just a 'default' and pointing it to the AWS 'Configuration endpoint' will let it find any/all other nodes dynamically (recommended for Elasticache, because you don't know when nodes are comin' or goin').
  • 'options': For Laravel, can be specified at the top-level, cluster-level, and node option. (they get combined in Illuminate before being passed off to Predis)
  • 'parameters': These 'override' the default connection settings/assumptions that Predis uses for new connections. Since we set them explicitly for the 'default' connection, these aren't used. But for a cluster setup, they are critical. A 'master' node may send back a redirect (-MOVED) and unless the parameters are set for password and scheme it'll assume defaults, and that new connection to the new node will fail.

I know this is pretty old but I was having the same issue myself. If anyone encounters this issue then see the solution here and here.

It seems that when you enable Encryption in-transit in AWS Elasticache it prevents you from using redis-cli as it doesn't support TLS connections. Switching to another client should work. This answer has a list of TLS enabled clients.

Edit:

Did some more digging and found that using stunnel you can wrap your connection of redis-cli with ssl. Here is a guide for doing it.

If you are using predis as client.

Then you can change Redis connection in config/database.php

'redis' => [
        'client' => 'predis',
        'default' => [
            'scheme' => 'tls',
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],
    ],

You can add 'scheme' in that.

I am using Laravel 5.8 And then everything works great within Laravel.

But yes, as Redis doesn't provide TLS connection so redis-cli will still not work.

Related
Connecting to Elasticache Redis Cluster from Peered VPC
EC2 instance can't access to elasticache
How to connect to AWS elasticache?
Cannot connect Redis Cluster in Elasticache to PHP using phpredis library
Elasticache PHP Redis AWS Moved Exception in Laravel
Cannot connect to Redis from Laravel Application
Configuring Redis as Cache interface in a Laravel 5 Application