Skip to content

Commit

Permalink
Merge pull request #74 from spotahome/devops-810-change-custom-config…
Browse files Browse the repository at this point in the history
…-usage

[DEVOPS-810] Change custom config usage
  • Loading branch information
jchanam authored Aug 24, 2018
2 parents adbe748 + 3cabc3b commit 4c30bb5
Show file tree
Hide file tree
Showing 20 changed files with 209 additions and 58 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@ In order to have persistance, a PersistentVolumeClaim usage is allowed. The full

**IMPORTANT**: By default, the persistent volume claims will be deleted when the Redis Failover is. If this is not the expected usage, a `keepAfterDeletion` flag can be added under the `storage` section of Redis. [An example is given](example/redisfailover/persistant-storage-no-pvc-deletion.yaml).

### Custom configurations
It is possible to configure both Redis and Sentinel. This is done with the `customConfig` option inside their spec. It is a list of configurations and their values.

Example:
```yaml
sentinel:
customConfig:
- "down-after-milliseconds 2000"
- "failover-timeout 3000"
redis:
customConfig:
- "maxclients 100"
- "hz 50"
```
**Important*: this options will be set via `config set` or `sentinel set mymaster`. In the Sentinel options, there are some "conversions" to be made.

- Configuration on the `sentinel.conf`: `sentinel down-after-milliseconds mymaster 2000`
- Configuration on the `configOptions`: `down-after-milliseconds 2000`

**Important 2**: do **NOT** change the options used for control the redis/sentinel such as `port`, `bind`, `dir`, etc.

### Connection
In order to connect to the redis-failover and use it, a [Sentinel-ready](https://redis.io/topics/sentinel-clients) library has to be used. This will connect through the Sentinel service to the Redis node working as a master.
The connection parameters are the following:
Expand Down
8 changes: 4 additions & 4 deletions api/redisfailover/v1alpha2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ type RedisSettings struct {
ExporterVersion string `json:"exporterVersion,omitempty"`
Image string `json:"image,omitempty"`
Version string `json:"version,omitempty"`
ConfigMap string `json:"configMap,omitempty"`
CustomConfig []string `json:"customConfig,omitempty"`
ShutdownConfigMap string `json:"shutdownConfigMap,omitempty"`
Storage RedisStorage `json:"storage,omitempty"`
}

// SentinelSettings defines the specification of the sentinel cluster
type SentinelSettings struct {
Replicas int32 `json:"replicas,omitempty"`
Resources RedisFailoverResources `json:"resources,omitempty"`
ConfigMap string `json:"configMap,omitempty"`
Replicas int32 `json:"replicas,omitempty"`
Resources RedisFailoverResources `json:"resources,omitempty"`
CustomConfig []string `json:"customConfig,omitempty"`
}

// RedisFailoverResources sets the limits and requests for a container
Expand Down
12 changes: 11 additions & 1 deletion api/redisfailover/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions example/redisfailover/all-options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ spec:
cpu: 100m
limits:
memory: 100Mi
customConfig: [] # Optional. Empty by default.
redis:
replicas: 3 # Optional. 3 by default, can be set higher.
image: redis # Optional. "redis" by default.
Expand All @@ -27,4 +28,5 @@ spec:
exporterVersion: v0.11.3 # Optional. v0.11.3 by default.
storage:
emptyDir: {} # Optional. emptyDir by default.
customConfig: [] # Optional. Empty by default.

2 changes: 1 addition & 1 deletion mocks/log/Logger.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mocks/operator/redisfailover/RedisFailover.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mocks/operator/redisfailover/service/RedisFailoverCheck.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions mocks/operator/redisfailover/service/RedisFailoverClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion mocks/operator/redisfailover/service/RedisFailoverHeal.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mocks/service/k8s/CRD.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mocks/service/k8s/Services.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion mocks/service/redis/Client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions operator/redisfailover/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ func (r *RedisFailoverHandler) CheckAndHeal(rf *redisfailoverv1alpha2.RedisFailo
return err3
}
}

redises, err := r.rfChecker.GetRedisesIPs(rf)
if err != nil {
return err
}
for _, rip := range redises {
if err := r.rfHealer.SetRedisCustomConfig(rip, rf); err != nil {
return err
}
}

sentinels, err := r.rfChecker.GetSentinelsIPs(rf)
if err != nil {
return err
Expand Down Expand Up @@ -95,6 +106,11 @@ func (r *RedisFailoverHandler) CheckAndHeal(rf *redisfailoverv1alpha2.RedisFailo
}
}
}
for _, sip := range sentinels {
if err := r.rfHealer.SetSentinelCustomConfig(sip, rf); err != nil {
return err
}
}
r.mClient.SetClusterOK(rf.Namespace, rf.Name)
return nil
}
3 changes: 3 additions & 0 deletions operator/redisfailover/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ func TestCheckAndHeal(t *testing.T) {
mrfc.On("CheckAllSlavesFromMaster", master, rf).Once().Return(errors.New(""))
mrfh.On("SetMasterOnAll", master, rf).Once().Return(nil)
}
mrfc.On("GetRedisesIPs", rf).Once().Return([]string{master}, nil)
mrfh.On("SetRedisCustomConfig", master, rf).Once().Return(nil)
mrfc.On("GetSentinelsIPs", rf).Once().Return([]string{sentinel}, nil)
if test.sentinelMonitorOK {
mrfc.On("CheckSentinelMonitor", sentinel, master).Once().Return(nil)
Expand All @@ -159,6 +161,7 @@ func TestCheckAndHeal(t *testing.T) {
mrfc.On("CheckSentinelSlavesNumberInMemory", sentinel, rf).Once().Return(errors.New(""))
mrfh.On("RestoreSentinel", sentinel).Once().Return(nil)
}
mrfh.On("SetSentinelCustomConfig", sentinel, rf).Once().Return(nil)
}

handler := rfOperator.NewRedisFailoverHandler(config, mrfs, mrfc, mrfh, mk, metrics.Dummy, log.Dummy)
Expand Down
23 changes: 5 additions & 18 deletions operator/redisfailover/service/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,8 @@ func (r *RedisFailoverKubeClient) EnsureSentinelService(rf *redisfailoverv1alpha

// EnsureSentinelConfigMap makes sure the sentinel configmap exists
func (r *RedisFailoverKubeClient) EnsureSentinelConfigMap(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) error {
if rf.Spec.Sentinel.ConfigMap != "" {
if _, err := r.K8SService.GetConfigMap(rf.Namespace, rf.Spec.Sentinel.ConfigMap); err != nil {
return err
}
} else {
cm := generateSentinelConfigMap(rf, labels, ownerRefs)
return r.K8SService.CreateOrUpdateConfigMap(rf.Namespace, cm)
}
return nil
cm := generateSentinelConfigMap(rf, labels, ownerRefs)
return r.K8SService.CreateOrUpdateConfigMap(rf.Namespace, cm)
}

// EnsureSentinelDeployment makes sure the sentinel deployment exists in the desired state
Expand All @@ -84,17 +77,11 @@ func (r *RedisFailoverKubeClient) EnsureRedisStatefulset(rf *redisfailoverv1alph

// EnsureRedisConfigMap makes sure the sentinel configmap exists
func (r *RedisFailoverKubeClient) EnsureRedisConfigMap(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) error {
if rf.Spec.Redis.ConfigMap != "" {
if _, err := r.K8SService.GetConfigMap(rf.Namespace, rf.Spec.Redis.ConfigMap); err != nil {
return err
}
} else {
cm := generateRedisConfigMap(rf, labels, ownerRefs)
return r.K8SService.CreateOrUpdateConfigMap(rf.Namespace, cm)
}
return nil
cm := generateRedisConfigMap(rf, labels, ownerRefs)
return r.K8SService.CreateOrUpdateConfigMap(rf.Namespace, cm)
}

// EnsureRedisShutdownConfigMap makes sure the redis configmap with shutdown script exists
func (r *RedisFailoverKubeClient) EnsureRedisShutdownConfigMap(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) error {
if rf.Spec.Redis.ShutdownConfigMap != "" {
if _, err := r.K8SService.GetConfigMap(rf.Namespace, rf.Spec.Redis.ShutdownConfigMap); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions operator/redisfailover/service/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func generateRedisService(rf *redisfailoverv1alpha2.RedisFailover, labels map[st
}

func generateSentinelConfigMap(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) *corev1.ConfigMap {
name := GetSentinelConfigMapName(rf)
name := GetSentinelName(rf)
namespace := rf.Namespace

labels = util.MergeLabels(labels, generateLabels(sentinelRoleName, rf.Name))
Expand All @@ -104,7 +104,7 @@ sentinel parallel-syncs mymaster 2`,
}

func generateRedisConfigMap(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) *corev1.ConfigMap {
name := GetRedisConfigMapName(rf)
name := GetRedisName(rf)
namespace := rf.Namespace

labels = util.MergeLabels(labels, generateLabels(redisRoleName, rf.Name))
Expand Down Expand Up @@ -260,7 +260,7 @@ func generateRedisStatefulSet(rf *redisfailoverv1alpha2.RedisFailover, labels ma

func generateSentinelDeployment(rf *redisfailoverv1alpha2.RedisFailover, labels map[string]string, ownerRefs []metav1.OwnerReference) *appsv1beta2.Deployment {
name := GetSentinelName(rf)
configMapName := GetSentinelConfigMapName(rf)
configMapName := GetSentinelName(rf)
namespace := rf.Namespace

spec := rf.Spec
Expand Down Expand Up @@ -585,7 +585,7 @@ func getRedisVolumeMounts(rf *redisfailoverv1alpha2.RedisFailover) []corev1.Volu
}

func getRedisVolumes(rf *redisfailoverv1alpha2.RedisFailover) []corev1.Volume {
configMapName := GetRedisConfigMapName(rf)
configMapName := GetRedisName(rf)
shutdownConfigMapName := GetRedisShutdownConfigMapName(rf)

executeMode := int32(0744)
Expand Down
2 changes: 1 addition & 1 deletion operator/redisfailover/service/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

func TestRedisStatefulSetStorageGeneration(t *testing.T) {
configMapName := rfservice.GetRedisConfigMapName(generateRF())
configMapName := rfservice.GetRedisName(generateRF())
shutdownConfigMapName := rfservice.GetRedisShutdownConfigMapName(generateRF())
executeMode := int32(0744)
tests := []struct {
Expand Down
16 changes: 15 additions & 1 deletion operator/redisfailover/service/heal.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type RedisFailoverHeal interface {
SetMasterOnAll(masterIP string, rFailover *redisfailoverv1alpha2.RedisFailover) error
NewSentinelMonitor(ip string, monitor string, rFailover *redisfailoverv1alpha2.RedisFailover) error
RestoreSentinel(ip string) error
SetSentinelCustomConfig(ip string, rFailover *redisfailoverv1alpha2.RedisFailover) error
SetRedisCustomConfig(ip string, rFailover *redisfailoverv1alpha2.RedisFailover) error
}

// RedisFailoverHealer is our implementation of RedisFailoverCheck interface
Expand Down Expand Up @@ -79,7 +81,7 @@ func (r *RedisFailoverHealer) SetMasterOnAll(masterIP string, rf *redisfailoverv
return nil
}

// NewSentinelMonitor clear the number of sentinels on memory
// NewSentinelMonitor changes the master that Sentinel has to monitor
func (r *RedisFailoverHealer) NewSentinelMonitor(ip string, monitor string, rf *redisfailoverv1alpha2.RedisFailover) error {
r.logger.Debug("Sentinel is not monitoring the correct master, changing...")
quorum := strconv.Itoa(int(getQuorum(rf)))
Expand All @@ -91,3 +93,15 @@ func (r *RedisFailoverHealer) RestoreSentinel(ip string) error {
r.logger.Debugf("Restoring sentinel %s...", ip)
return r.redisClient.ResetSentinel(ip)
}

// SetSentinelCustomConfig will call sentinel to set the configuration given in config
func (r *RedisFailoverHealer) SetSentinelCustomConfig(ip string, rf *redisfailoverv1alpha2.RedisFailover) error {
r.logger.Debugf("Setting the custom config on sentinel %s...", ip)
return r.redisClient.SetCustomSentinelConfig(ip, rf.Spec.Sentinel.CustomConfig)
}

// SetRedisCustomConfig will call redis to set the configuration given in config
func (r *RedisFailoverHealer) SetRedisCustomConfig(ip string, rf *redisfailoverv1alpha2.RedisFailover) error {
r.logger.Debugf("Setting the custom config on redis %s...", ip)
return r.redisClient.SetCustomRedisConfig(ip, rf.Spec.Redis.CustomConfig)
}
Loading

0 comments on commit 4c30bb5

Please sign in to comment.