Redisのレプリケーションと独自のインスタンスによるフェイルオーバー

GitLabをクラウドプロバイダーでホストしている場合は、オプションでRedisのマネージドサービスを使うことができます。 例えば、AWSはRedisを実行するElastiCacheを提供しています。

あるいは、Omnibus GitLabパッケージとは別に独自のRedisインスタンスを管理することもできます。

要件

独自のRedisインスタンスを提供するための要件は次のとおりです:

  • Redisのバージョンは5.0以上を推奨します。これはGitLab 12.7以降のOmnibus GitLabパッケージに同梱されているものです。
  • Redis 3.2のサポートはGitLab 12.10で非推奨となり、GitLab 13.0で完全に削除される予定です。
  • GitLab 12.0 以降では、Redis バージョン 3.2 以降が必要です。 古い Redis バージョンでは、マージトレインに必要な SPOP へのオプションの count 引数がサポートされていません。
  • さらに、Redis 4以降が利用可能な場合、GitLabはRedis 4でのみ導入されたUNLINKUSAGE といった特定のコマンドを利用できます。
  • スタンドアロンRedisまたはSentinelを使用したRedis高可用性がサポートされています。 Redisクラスタはサポートされていません。
  • AWS ElastiCacheのようなクラウドプロバイダのマネージドRedisでも動作します。 これらのサービスが高可用性をサポートしている場合は、Redisクラスタタイプでないことを確認してください。

RedisノードのIPアドレスまたはホスト名、ポート、パスワード(必要な場合)をメモします。

クラウドプロバイダのマネージドサービスとしてのRedis

  1. 要件に従ってRedisをセットアップします。
  2. GitLabアプリケーションサーバーを設定し、/etc/gitlab/gitlab.rb ファイルで外部Redisサービスの適切な接続詳細を設定します:

    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'
    
  3. 変更を有効にするために再設定します:

    sudo gitlab-ctl reconfigure
    

独自のRedisサーバによるRedisのレプリケーションとフェイルオーバー

OmnibusのGitLabパッケージはGitLab専用に最適化されているので、OmnibusのGitLabパッケージを使うことを強くお勧めします。

また、設定ファイルのドキュメントで説明されている高度なRedis設定に従って、/home/git/gitlab/config/resque.yml への参照をすべて上書きすることもできます。

Omnibus Redis HA のレプリケーションとフェイルオーバーのドキュメントを読むことの重要性はいくら強調してもしきれません。 このガイドを読み進める前に必ずお読みください。

新しいRedisインスタンスのセットアップを進める前に、いくつかの要件を説明します:

  • このガイドのすべてのRedisサーバーは、ソケットの代わりにTCP接続を使用するように設定する必要があります。 TCP接続を使用するようにRedisを設定するには、Redis設定ファイルでbindport の両方を定義する必要があります。すべてのインターフェース(0.0.0.0)にバインドすることも、必要なインターフェース(内部ネットワークのものなど)のIPを指定することもできます。
  • Redis 3.2 以降、外部接続 (requirepass) を受け取るにはパスワードを定義する必要があります。
  • SentinelでRedisを使用している場合、同じインスタンスでレプリカのパスワード定義(masterauth)にも同じパスワードを定義する必要があります。

さらに、OmnibusRedis ドキュメントに記載されている前提条件を読んでください。

ステップ1.プライマリRedisインスタンスの設定

Redis のプライマリインスタンス IP が10.0.0.1であると仮定します:

  1. Redisをインストールします。
  2. /etc/redis/redis.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
    
  3. 変更を有効にするためにRedisサービスを再起動します。

ステップ2.レプリカRedisインスタンスの設定

RedisレプリカインスタンスのIPが10.0.0.2であると仮定します:

  1. Redisをインストールします。
  2. /etc/redis/redis.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
    
  3. 変更を有効にするためにRedisサービスを再起動します。
  4. 他のすべてのレプリカノードについて、もう一度手順を実行します。

ステップ3.Redis Sentinelインスタンスの設定

SentinelはRedisサーバーの特殊なタイプで、redis.confで定義できる基本的な設定オプションのほとんどを継承し、sentinel プレフィックスで始まる特殊なオプションも継承します。

Redis SentinelがRedisプライマリと同じインスタンスにIP10.0.0.1 でインストールされていると仮定します(一部の設定はプライマリと重複する可能性があります):

  1. RedisSentinelをインストールします。
  2. /etc/redis/sentinel.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 will be 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 will be reconfigured by the Sentinels anyway, but not with
    ##   the exact parallel-syncs progression as specified.
    sentinel failover_timeout 30000
    
  3. 変更を有効にするためにRedisサービスを再起動します。
  4. 他のすべてのセンチネルノードについて、もう一度手順を実行します。

ステップ 4. GitLab アプリケーションの設定

GitLabアプリケーションの観点からは、必要なのはSentinelノードの正しい認証情報だけです。

すべてのセンチネルノードのリストは必要ありませんが、障害が発生した場合、リストアップされたノードの少なくとも1つにアクセスする必要があります。

以下のステップはGitLabアプリケーションサーバーで実行する必要があり、理想的には同じマシンにRedisやSentinelsがあるべきではありません:

  1. resque.yml.exampleの例に従って/home/git/gitlab/config/resque.yml を編集し、Sentinelの行のコメントを解除して、正しいサーバー認証情報を指定します:

    # 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
    
  2. 変更を有効にするためにGitLabを再起動します。

プライマリ1台、レプリカ2台、センチネル3台の最小構成例

この例では、すべてのサーバーが10.0.0.x の範囲のIPを持つ内部ネットワーク・インターフェースを持っており、これらのIPを使って互いに接続できると考えます。

実際の使用では、他のマシンからの不正アクセスを防止したり、外部(インターネット)からのトラフィックをブロックするためのファイアウォールルールも設定します。

この例では、Sentinel 1はRedisプライマリと同じマシンに、Sentinel 2と Sentinel 3はそれぞれReplica 1と Replica 2と同じマシンに設定します。

各マシンと割り当てられたIPのリストと説明です:

  • 10.0.0.1Redis プライマリ + センチネル 1
  • 10.0.0.2Redisレプリカ1 + センチネル2
  • 10.0.0.3Redisレプリカ2 + センチネル3
  • 10.0.0.4GitLab アプリケーション

初期設定の後、Sentinelノードによってフェイルオーバーが開始されると、Redisノードは再設定され、プライマリは、新しいフェイルオーバーが再び開始されるまで、一方のノードから他方のノードに永続的に変更されます(redis.confを含む)。

新しいセンチネルノードがプライマリの監視を開始した後、またはフェイルオーバーが別のプライマリノードを促進した後、最初の実行後にオーバーライドされるsentinel.conf

RedisプライマリとSentinel 1の構成例

  1. /etc/redis/redis.conf

    bind 10.0.0.1
    port 6379
    requirepass redis-password-goes-here
    masterauth redis-password-goes-here
    
  2. /etc/redis/sentinel.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
    
  3. 変更を有効にするためにRedisサービスを再起動します。

Redisレプリカ1とSentinel 2の設定例

  1. /etc/redis/redis.conf

    bind 10.0.0.2
    port 6379
    requirepass redis-password-goes-here
    masterauth redis-password-goes-here
    replicaof 10.0.0.1 6379
    
  2. /etc/redis/sentinel.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
    
  3. 変更を有効にするためにRedisサービスを再起動します。

Redisレプリカ2とSentinel 3の設定例

  1. /etc/redis/redis.conf

    bind 10.0.0.3
    port 6379
    requirepass redis-password-goes-here
    masterauth redis-password-goes-here
    replicaof 10.0.0.1 6379
    
  2. /etc/redis/sentinel.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
    
  3. 変更を有効にするためにRedisサービスを再起動します。

GitLabアプリケーションの設定例

  1. /home/git/gitlab/config/resque.ymlを編集します:

    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
    
  2. 変更を有効にするためにGitLabを再起動します。

トラブルシューティング

Redisのトラブルシューティングガイドを参照してください。