summaryrefslogtreecommitdiff
path: root/doc/administration/redis/replication_and_failover_external.md
blob: 23c9ce33c2d111ae0c72e636c7d249b68e42e9cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
---
type: howto
stage: Systems
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

# Redis replication and failover providing your own instance **(FREE SELF)**

If you're hosting GitLab on a cloud provider, you can optionally use a managed
service for Redis. For example, AWS offers ElastiCache that runs Redis.

Alternatively, you may opt to manage your own Redis instance separate from the
Omnibus GitLab package.

## Requirements

The following are the requirements for providing your own Redis instance:

- Find the minimum Redis version that is required in the
  [requirements page](../../install/requirements.md).
- Standalone Redis or Redis high availability with Sentinel are supported. Redis
  Cluster is not supported.
- Managed Redis from cloud providers such as AWS ElastiCache works fine. If these
  services support high availability, be sure it is **not** the Redis Cluster type.

Note the Redis node's IP address or hostname, port, and password (if required).

## Redis as a managed service in a cloud provider

1. Set up Redis according to the [requirements](#requirements).
1. Configure the GitLab application servers with the appropriate connection details
   for your external Redis service in your `/etc/gitlab/gitlab.rb` file:

    ```ruby
    redis['enable'] = false

    gitlab_rails['redis_host'] = 'redis.example.com'
    gitlab_rails['redis_port'] = 6379

    # Required if Redis authentication is configured on the Redis node
    gitlab_rails['redis_password'] = 'Redis Password'
    ```

1. Reconfigure for the changes to take effect:

   ```shell
   sudo gitlab-ctl reconfigure
   ```

## Redis replication and failover with your own Redis servers

This is the documentation for configuring a scalable Redis setup when
you have installed Redis all by yourself and not using the bundled one that
comes with the Omnibus packages, although using the Omnibus GitLab packages is
highly recommend as we optimize them specifically for GitLab, and we take
care of upgrading Redis to the latest supported version.

Note also that you may elect to override all references to
`/home/git/gitlab/config/resque.yml` in accordance with the advanced Redis
settings outlined in
[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/README.md).

We cannot stress enough the importance of reading the
[replication and failover](replication_and_failover.md) documentation of the
Omnibus Redis HA as it provides some invaluable information to the configuration
of Redis. Read it before going forward with this guide.

Before proceeding on setting up the new Redis instances, here are some
requirements:

- All Redis servers in this guide must be configured to use a TCP connection
  instead of a socket. To configure Redis to use TCP connections you need to
  define both `bind` and `port` in the Redis configuration file. You can bind to all
  interfaces (`0.0.0.0`) or specify the IP of the desired interface
  (for example, one from an internal network).
- Since Redis 3.2, you must define a password to receive external connections
  (`requirepass`).
- If you are using Redis with Sentinel, you also need to define the same
  password for the replica password definition (`masterauth`) in the same instance.

In addition, read the prerequisites as described in the
[Omnibus Redis document](replication_and_failover.md#requirements) since they provide some
valuable information for the general setup.

### Step 1. Configuring the primary Redis instance

Assuming that the Redis primary instance IP is `10.0.0.1`:

1. [Install Redis](../../install/installation.md#7-redis).
1. Edit `/etc/redis/redis.conf`:

   ```conf
   ## Define a `bind` address pointing to a local IP that your other machines
   ## can reach you. If you really need to bind to an external accessible IP, make
   ## sure you add extra firewall rules to prevent unauthorized access:
   bind 10.0.0.1

   ## Define a `port` to force redis to listen on TCP so other machines can
   ## connect to it (default port is `6379`).
   port 6379

   ## Set up password authentication (use the same password in all nodes).
   ## The password should be defined equal for both `requirepass` and `masterauth`
   ## when setting up Redis to use with Sentinel.
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here
   ```

1. Restart the Redis service for the changes to take effect.

### Step 2. Configuring the replica Redis instances

Assuming that the Redis replica instance IP is `10.0.0.2`:

1. [Install Redis](../../install/installation.md#7-redis).
1. Edit `/etc/redis/redis.conf`:

   ```conf
   ## Define a `bind` address pointing to a local IP that your other machines
   ## can reach you. If you really need to bind to an external accessible IP, make
   ## sure you add extra firewall rules to prevent unauthorized access:
   bind 10.0.0.2

   ## Define a `port` to force redis to listen on TCP so other machines can
   ## connect to it (default port is `6379`).
   port 6379

   ## Set up password authentication (use the same password in all nodes).
   ## The password should be defined equal for both `requirepass` and `masterauth`
   ## when setting up Redis to use with Sentinel.
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here

   ## Define `replicaof` pointing to the Redis primary instance with IP and port.
   replicaof 10.0.0.1 6379
   ```

1. Restart the Redis service for the changes to take effect.
1. Go through the steps again for all the other replica nodes.

### Step 3. Configuring the Redis Sentinel instances

Sentinel is a special type of Redis server. It inherits most of the basic
configuration options you can define in `redis.conf`, with specific ones
starting with `sentinel` prefix.

Assuming that the Redis Sentinel is installed on the same instance as Redis
primary with IP `10.0.0.1` (some settings might overlap with the primary):

1. [Install Redis Sentinel](https://redis.io/docs/manual/sentinel/).
1. Edit `/etc/redis/sentinel.conf`:

   ```conf
   ## Define a `bind` address pointing to a local IP that your other machines
   ## can reach you. If you really need to bind to an external accessible IP, make
   ## sure you add extra firewall rules to prevent unauthorized access:
   bind 10.0.0.1

   ## Define a `port` to force Sentinel to listen on TCP so other machines can
   ## connect to it (default port is `6379`).
   port 26379

   ## Set up password authentication (use the same password in all nodes).
   ## The password should be defined equal for both `requirepass` and `masterauth`
   ## when setting up Redis to use with Sentinel.
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here

   ## Define with `sentinel auth-pass` the same shared password you have
   ## defined for both Redis primary and replicas instances.
   sentinel auth-pass gitlab-redis redis-password-goes-here

   ## Define with `sentinel monitor` the IP and port of the Redis
   ## primary node, and the quorum required to start a failover.
   sentinel monitor gitlab-redis 10.0.0.1 6379 2

   ## Define with `sentinel down-after-milliseconds` the time in `ms`
   ## that an unresponsive server is considered down.
   sentinel down-after-milliseconds gitlab-redis 10000

   ## Define a value for `sentinel failover_timeout` in `ms`. This has multiple
   ## meanings:
   ##
   ## * The time needed to re-start a failover after a previous failover was
   ##   already tried against the same primary by a given Sentinel, is two
   ##   times the failover timeout.
   ##
   ## * The time needed for a replica replicating to a wrong primary according
   ##   to a Sentinel current configuration, to be forced to replicate
   ##   with the right primary, is exactly the failover timeout (counting since
   ##   the moment a Sentinel detected the misconfiguration).
   ##
   ## * The time needed to cancel a failover that is already in progress but
   ##   did not produced any configuration change (REPLICAOF NO ONE yet not
   ##   acknowledged by the promoted replica).
   ##
   ## * The maximum time a failover in progress waits for all the replicas to be
   ##   reconfigured as replicas of the new primary. However even after this time
   ##   the replicas are reconfigured by the Sentinels anyway, but not with
   ##   the exact parallel-syncs progression as specified.
   sentinel failover_timeout 30000
   ```

1. Restart the Redis service for the changes to take effect.
1. Go through the steps again for all the other Sentinel nodes.

### Step 4. Configuring the GitLab application

You can enable or disable Sentinel support at any time in new or existing
installations. From the GitLab application perspective, all it requires is
the correct credentials for the Sentinel nodes.

While it doesn't require a list of all Sentinel nodes, in case of a failure,
it needs to access at least one of listed ones.

The following steps should be performed in the GitLab application server
which ideally should not have Redis or Sentinels in the same machine:

1. Edit `/home/git/gitlab/config/resque.yml` following the example in
   [`resque.yml.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/resque.yml.example), and uncomment the Sentinel lines, pointing to
   the correct server credentials:

   ```yaml
   # resque.yaml
   production:
     url: redis://:redi-password-goes-here@gitlab-redis/
     sentinels:
       -
         host: 10.0.0.1
         port: 26379  # point to sentinel, not to redis port
       -
         host: 10.0.0.2
         port: 26379  # point to sentinel, not to redis port
       -
         host: 10.0.0.3
         port: 26379  # point to sentinel, not to redis port
   ```

1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.

## Example of minimal configuration with 1 primary, 2 replicas and 3 sentinels

In this example we consider that all servers have an internal network
interface with IPs in the `10.0.0.x` range, and that they can connect
to each other using these IPs.

In a real world usage, you would also set up firewall rules to prevent
unauthorized access from other machines, and block traffic from the
outside ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)).

For this example, **Sentinel 1** is configured in the same machine as the
**Redis Primary**, **Sentinel 2** and **Sentinel 3** in the same machines as the
**Replica 1** and **Replica 2** respectively.

Here is a list and description of each **machine** and the assigned **IP**:

- `10.0.0.1`: Redis Primary + Sentinel 1
- `10.0.0.2`: Redis Replica 1 + Sentinel 2
- `10.0.0.3`: Redis Replica 2 + Sentinel 3
- `10.0.0.4`: GitLab application

After the initial configuration, if a failover is initiated
by the Sentinel nodes, the Redis nodes are reconfigured and the **Primary**
changes permanently (including in `redis.conf`) from one node to the other,
until a new failover is initiated again.

The same thing happens with `sentinel.conf` that is overridden after the
initial execution, after any new sentinel node starts watching the **Primary**,
or a failover promotes a different **Primary** node.

### Example configuration for Redis primary and Sentinel 1

1. In `/etc/redis/redis.conf`:

   ```conf
   bind 10.0.0.1
   port 6379
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here
   ```

1. In `/etc/redis/sentinel.conf`:

   ```conf
   bind 10.0.0.1
   port 26379
   sentinel auth-pass gitlab-redis redis-password-goes-here
   sentinel monitor gitlab-redis 10.0.0.1 6379 2
   sentinel down-after-milliseconds gitlab-redis 10000
   sentinel failover_timeout 30000
   ```

1. Restart the Redis service for the changes to take effect.

### Example configuration for Redis replica 1 and Sentinel 2

1. In `/etc/redis/redis.conf`:

   ```conf
   bind 10.0.0.2
   port 6379
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here
   replicaof 10.0.0.1 6379
   ```

1. In `/etc/redis/sentinel.conf`:

   ```conf
   bind 10.0.0.2
   port 26379
   sentinel auth-pass gitlab-redis redis-password-goes-here
   sentinel monitor gitlab-redis 10.0.0.1 6379 2
   sentinel down-after-milliseconds gitlab-redis 10000
   sentinel failover_timeout 30000
   ```

1. Restart the Redis service for the changes to take effect.

### Example configuration for Redis replica 2 and Sentinel 3

1. In `/etc/redis/redis.conf`:

   ```conf
   bind 10.0.0.3
   port 6379
   requirepass redis-password-goes-here
   masterauth redis-password-goes-here
   replicaof 10.0.0.1 6379
   ```

1. In `/etc/redis/sentinel.conf`:

   ```conf
   bind 10.0.0.3
   port 26379
   sentinel auth-pass gitlab-redis redis-password-goes-here
   sentinel monitor gitlab-redis 10.0.0.1 6379 2
   sentinel down-after-milliseconds gitlab-redis 10000
   sentinel failover_timeout 30000
   ```

1. Restart the Redis service for the changes to take effect.

### Example configuration of the GitLab application

1. Edit `/home/git/gitlab/config/resque.yml`:

   ```yaml
   production:
     url: redis://:redis-password-goes-here@gitlab-redis/
     sentinels:
       -
         host: 10.0.0.1
         port: 26379  # point to sentinel, not to redis port
       -
         host: 10.0.0.2
         port: 26379  # point to sentinel, not to redis port
       -
         host: 10.0.0.3
         port: 26379  # point to sentinel, not to redis port
   ```

1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.

## Troubleshooting

See the [Redis troubleshooting guide](troubleshooting.md).