Closed RoyKimYYZ closed 3 years ago
Anybody have success with setting up Redis Sentinel (3 nodes) in Kubernetes and using StackExchange.Redis in an asp .net core app? I like to see working example of AppSettings.json with the hosts/endpoints. I deployed Redis Sentinel using the bitnami helm chart.
I'm strugglig with this as well, how far have you come?
Anybody have success with setting up Redis Sentinel (3 nodes) in Kubernetes and using StackExchange.Redis in an asp .net core app? I like to see working example of AppSettings.json with the hosts/endpoints. I deployed Redis Sentinel using the bitnami helm chart.
this is the correct way: (see my comment below) https://github.com/StackExchange/StackExchange.Redis/issues/1534
I used the following connectionString:
cache-sentinel-dev-redis.cache.svc.cluster.local:26379,serviceName=mymaster
Basicly:
<service>.<namespace>.svc.cluster.local:26379,serviceName=mymaster
Do note that I only messed around a little with sentinel, and that this is not production tested. In my tests (rolling restarts of sentinels, caches, nodes, ...) I found that adding the following did help in keeping it working / stable (as the pods got new ip's around):
_connection = await ConnectionMultiplexer.ConnectAsync(_options.Value.Uri).ConfigureAwait(false);
_connection.ConnectionFailed += ConnectionOnConnectionFailed;
...
private void ConnectionOnConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
if (e.FailureType == ConnectionFailureType.AuthenticationFailure)
return;
_logger.LogWarning(e.Exception, "Connection issue encountered for endpoint: {0}, failure type: {1}, connection type: {2}", e.EndPoint.ToString(), e.FailureType.ToString(), e.ConnectionType.ToString());
_connection.Configure();
}
I used the following connectionString:
cache-sentinel-dev-redis.cache.svc.cluster.local:26379,serviceName=mymaster
Basicly:
<service>.<namespace>.svc.cluster.local:26379,serviceName=mymaster
Do note that I only messed around a little with sentinel, and that this is not production tested. In my tests (rolling restarts of sentinels, caches, nodes, ...) I found that adding the following did help in keeping it working / stable (as the pods got new ip's around):
_connection = await ConnectionMultiplexer.ConnectAsync(_options.Value.Uri).ConfigureAwait(false); _connection.ConnectionFailed += ConnectionOnConnectionFailed; ... private void ConnectionOnConnectionFailed(object sender, ConnectionFailedEventArgs e) { if (e.FailureType == ConnectionFailureType.AuthenticationFailure) return; _logger.LogWarning(e.Exception, "Connection issue encountered for endpoint: {0}, failure type: {1}, connection type: {2}", e.EndPoint.ToString(), e.FailureType.ToString(), e.ConnectionType.ToString()); _connection.Configure(); }
well I guess I will give this a try. Do you have any fast way to simulate those rolling restarts of sentinels? (I'm using redis-ha in my k8s server) see https://github.com/StackExchange/StackExchange.Redis/issues/1584
You can do that with:
kubectl rollout restart deployment/xxxx
kubectl rollout restart daemonset/xxxx
kubectl rollout restart statefulset/xxxx
...
Or do a rolling restart of your nodes
Or simulate a failover https://redis.io/topics/sentinel#testing-the-failover
You can do that with:
kubectl rollout restart deployment/xxxx kubectl rollout restart daemonset/xxxx kubectl rollout restart statefulset/xxxx ...
Or do a rolling restart of your nodes
Or simulate a failover https://redis.io/topics/sentinel#testing-the-failover
Amazing! I used rollout of the statefulset, failover from redis-cli didn't work for me.
The fix seems to work, you saved the day!
bedankt ;)
@RoyKimYYZ did you come any further? I'm still having the issue even with the event. I'm thinking of recreating the Connection when a failure in the readinessprobe is detected. Doesn't feel right though.
@emi662002 do you mind sharing the yaml files? thx
@emi662002 do you mind sharing the yaml files? thx
What are you looking for?, I don't think yamls are relevant to this issue but I'll see if I can help.
@emi662002 I try connecting to redis with the connection scheme but no luck. wonder what I?did wrong. the port I used is the redis port 6379. the serviceName=mymaster, the client will get a connection to sentinel but I saw in the log that first the connection is established but then the next line says redishubmanager cannot connect to redis. any idea why?
StackExchange.Redis.RedisConnectionException: No connection is available to service this operation: PUBLISH DTH.Management.API.Hub.ManagementEventHub:group:sale-3d194d9c-6767-4dd0-b80d-f994edc50d10; │
│ ---> StackExchange.Redis.RedisConnectionException: UnableToConnect on redis.redis.svc.cluster.local:5000,serviceName=mymaster:6379/Interactive, Initializing/NotStarted, last: NONE, origin: BeginConn │
│ at StackExchange.Redis.TaskExtensions.TimeoutAfter(Task task, Int32 timeoutMs) in C:\projects\stackexchange-redis\src\StackExchange.Redis\TaskExtensions.cs:line 48 │
│ at StackExchange.Redis.ConnectionMultiplexer.WaitAllIgnoreErrorsAsync(Task[] tasks, Int32 timeoutMilliseconds, TextWriter log, String caller, Int32 callerLineNumber) in C:\projects\stackexchange-r │
│ --- End of inner exception stack trace --- │
│ at StackExchange.Redis.ConnectionMultiplexer.ThrowFailed[T](TaskCompletionSource1 source, Exception unthrownException) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultipl │ │ --- End of stack trace from previous location --- │ │ at Microsoft.AspNetCore.SignalR.StackExchangeRedis.RedisHubLifetimeManager
1.PublishAsync(String channel, Byte[] payload) │
│ at DTH.Management.API.Hub.ManagementEventHub.ChaChing(TotalToDateDto totalToDate) in /app/DTH.Management.API/Hub/ManagementEventHub.cs:line 26 │
│ at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher1.ExecuteMethod(ObjectMethodExecutor methodExecutor, Hub hub, Object[] arguments) │ │ at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher
1.<>c__DisplayClass16_0.<
see the error message above. text in bold. redis.redis.svc.cluster.local:5000,serviceName=mymaster.
Question is: is it the sentinel service name or the redis service name and port?
StackExchange.Redis.RedisConnectionException: No connection is available to service this operation: PUBLISH DTH.Management.API.Hub.ManagementEventHub:group:sale-3d194d9c-6767-4dd0-b80d-f994edc50d10; │ │ ---> StackExchange.Redis.RedisConnectionException: UnableToConnect on redis.redis.svc.cluster.local:5000,serviceName=mymaster:6379/Interactive, Initializing/NotStarted, last: NONE, origin: BeginConn │ │ at StackExchange.Redis.TaskExtensions.TimeoutAfter(Task task, Int32 timeoutMs) in C:\projects\stackexchange-redis\src\StackExchange.Redis\TaskExtensions.cs:line 48 │ │ at StackExchange.Redis.ConnectionMultiplexer.WaitAllIgnoreErrorsAsync(Task[] tasks, Int32 timeoutMilliseconds, TextWriter log, String caller, Int32 callerLineNumber) in C:\projects\stackexchange-r │ │ --- End of inner exception stack trace --- │ │ at StackExchange.Redis.ConnectionMultiplexer.ThrowFailed[T](TaskCompletionSource
1 source, Exception unthrownException) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultipl │ │ --- End of stack trace from previous location --- │ │ at Microsoft.AspNetCore.SignalR.StackExchangeRedis.RedisHubLifetimeManager
1.PublishAsync(String channel, Byte[] payload) │ │ at DTH.Management.API.Hub.ManagementEventHub.ChaChing(TotalToDateDto totalToDate) in /app/DTH.Management.API/Hub/ManagementEventHub.cs:line 26 │ │ at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher1.ExecuteMethod(ObjectMethodExecutor methodExecutor, Hub hub, Object[] arguments) │ │ at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher
1.<>c__DisplayClass16_0.<g__ExecuteInvocation|0>d.MoveNext()see the error message above. text in bold. redis.redis.svc.cluster.local:5000,serviceName=mymaster.
Question is: is it the sentinel service name or the redis service name and port?
6379 is the default redis port 26379 is the default sentinel port
your connection string should have this as redis server for example: redis-ha-dev-announce-0:26379,redis-ha-dev-announce-1:26379,redis-ha-dev-announce-2:26379
on the internals the connection multiplexer will ask a master from the sentinels and use that connection this is how you use it: (simplified version)
` var options = new ConfigurationOptions { AbortOnConnectFail = false, AllowAdmin = false, ClientName = this.ClientName, ConnectTimeout = 60000, Password = this.AccessKey, ConnectRetry = 5, ServiceName = "mymaster", Proxy = Proxy.None };
foreach (var s in this.RedisServers.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
options.EndPoints.Add(s);
}
var sentinelConnection = ConnectionMultiplexer.SentinelConnect(this.RedisOptions);
var masterConfig = new ConfigurationOptions { ServiceName = "mymaster" };
this.connection = sentinelConnection.GetSentinelMasterConnection(masterConfig);
`
Anybody have success with setting up Redis Sentinel (3 nodes) in Kubernetes and using StackExchange.Redis in an asp .net core app? I like to see working example of AppSettings.json with the hosts/endpoints. I deployed Redis Sentinel using the bitnami helm chart.