Skip to content

Commit

Permalink
feat: sentinel support hostname resolve and annonce (OT-CONTAINER-KIT…
Browse files Browse the repository at this point in the history
…#1247)

* feat: Sentinel - support hostname resolve and annonce master

Signed-off-by: Michael Kanchuker <[email protected]>

* fix

Signed-off-by: yangw <[email protected]>

* fix

Signed-off-by: yangw <[email protected]>

---------

Signed-off-by: Michael Kanchuker <[email protected]>
Signed-off-by: yangw <[email protected]>
Co-authored-by: yangw <[email protected]>
  • Loading branch information
mkl262 and drivebyer authored Feb 28, 2025
1 parent 7c91822 commit aafc663
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 10 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ coverage.html
*~
.vscode

.DS_Store

docs/build
kubeconfig
kubeconfig
manager
4 changes: 4 additions & 0 deletions api/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,8 @@ type RedisSentinelConfig struct {
FailoverTimeout string `json:"failoverTimeout,omitempty"`
// +kubebuilder:default:="30000"
DownAfterMilliseconds string `json:"downAfterMilliseconds,omitempty"`
// +kubebuilder:default:="no"
ResolveHostnames string `json:"resolveHostnames,omitempty"`
// +kubebuilder:default:="no"
AnnounceHostnames string `json:"announceHostnames,omitempty"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -2631,6 +2631,12 @@ spec:
type: object
x-kubernetes-map-type: atomic
type: object
resolveHostnames:
default: "no"
type: string
announceHostnames:
default: "no"
type: string
required:
- redisReplicationName
type: object
Expand Down
2 changes: 2 additions & 0 deletions charts/redis-sentinel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ helm delete <my-release> --namespace <namespace>
| redisSentinel.resources | object | `{}` | |
| redisSentinel.serviceType | string | `"ClusterIP"` | |
| redisSentinel.tag | string | `"v7.0.15"` | |
| redisSentinelConfig.announceHostnames | string | `""` | |
| redisSentinelConfig.downAfterMilliseconds | string | `""` | |
| redisSentinelConfig.failoverTimeout | string | `""` | |
| redisSentinelConfig.masterGroupName | string | `""` | |
Expand All @@ -109,6 +110,7 @@ helm delete <my-release> --namespace <namespace>
| redisSentinelConfig.redisReplicationName | string | `"redis-replication"` | |
| redisSentinelConfig.redisReplicationPassword.secretKey | string | `""` | |
| redisSentinelConfig.redisReplicationPassword.secretName | string | `""` | |
| redisSentinelConfig.resolveHostnames | string | `""` | |
| securityContext | object | `{}` | |
| serviceAccountName | string | `""` | |
| serviceMonitor.enabled | bool | `false` | |
Expand Down
2 changes: 2 additions & 0 deletions charts/redis-sentinel/templates/redis-sentinel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ spec:
parallelSyncs: {{ .Values.redisSentinelConfig.parallelSyncs | default "1" | quote}}
failoverTimeout: {{ .Values.redisSentinelConfig.failoverTimeout | default "180000" | quote}}
downAfterMilliseconds: {{ .Values.redisSentinelConfig.downAfterMilliseconds | default "30000" | quote}}
resolveHostnames : {{ .Values.redisSentinelConfig.resolveHostnames | default "no" | quote}}
announceHostnames : {{ .Values.redisSentinelConfig.announceHostnames | default "no" | quote}}
{{- if eq .Values.externalConfig.enabled true }}
additionalSentinelConfig: {{ .Values.redisSentinel.name | default .Release.Name }}-ext-config
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions charts/redis-sentinel/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ redisSentinelConfig:
secretName: ""
secretKey: ""
masterGroupName: ""
resolveHostnames: ""
announceHostnames: ""
redisPort: ""
quorum: ""
parallelSyncs: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2524,6 +2524,9 @@ spec:
properties:
additionalSentinelConfig:
type: string
announceHostnames:
default: "no"
type: string
downAfterMilliseconds:
default: "30000"
type: string
Expand Down Expand Up @@ -2631,6 +2634,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
type: object
resolveHostnames:
default: "no"
type: string
required:
- redisReplicationName
type: object
Expand Down
2 changes: 2 additions & 0 deletions docs/content/en/docs/CRD Reference/Redis API/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ _Appears in:_
| `parallelSyncs` _string_ | |
| `failoverTimeout` _string_ | |
| `downAfterMilliseconds` _string_ | |
| `resolveHostnames` _string_ | |
| `announceHostnames` _string_ | |

#### RedisExporter

Expand Down
2 changes: 2 additions & 0 deletions docs/content/en/docs/Configuration/RedisReplication/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Redis replication configuration can be customized by [values.yaml](https://githu
| redisSentinelConfig.redisReplicationName | string | `"redis-replication"` | |
| redisSentinelConfig.redisReplicationPassword.secretKey | string | `""` | |
| redisSentinelConfig.redisReplicationPassword.secretName | string | `""` | |
| redisSentinelConfig.resolveHostnames | string | `"no"` | |
| redisSentinelConfig.announceHostnames | string | `"no"` | |
| securityContext | object | `{}` | |
| serviceAccountName | string | `""` | |
| serviceMonitor.enabled | bool | `false` | |
Expand Down
56 changes: 47 additions & 9 deletions pkg/k8sutils/redis-sentinel.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"

redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/util"
Expand Down Expand Up @@ -258,14 +259,21 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, cr
return &[]corev1.EnvVar{}
}

var IP string
if cr.Spec.RedisSentinelConfig.ResolveHostnames == "yes" {
IP = getRedisReplicationMasterName(ctx, client, cr, dcl)
} else {
IP = getRedisReplicationMasterIP(ctx, client, cr, dcl)
}

envVar := &[]corev1.EnvVar{
{
Name: "MASTER_GROUP_NAME",
Value: cr.Spec.RedisSentinelConfig.MasterGroupName,
},
{
Name: "IP",
Value: getRedisReplicationMasterIP(ctx, client, cr, dcl),
Value: IP,
},
{
Name: "PORT",
Expand All @@ -287,6 +295,14 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, cr
Name: "FAILOVER_TIMEOUT",
Value: cr.Spec.RedisSentinelConfig.FailoverTimeout,
},
{
Name: "RESOLVE_HOSTNAMES",
Value: cr.Spec.RedisSentinelConfig.ResolveHostnames,
},
{
Name: "ANNOUNCE_HOSTNAMES",
Value: cr.Spec.RedisSentinelConfig.AnnounceHostnames,
},
}

if cr.Spec.RedisSentinelConfig != nil && cr.Spec.RedisSentinelConfig.RedisReplicationPassword != nil {
Expand All @@ -298,13 +314,18 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, cr
return envVar
}

func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) string {
func getRedisReplicationMasterPod(ctx context.Context, client kubernetes.Interface, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) RedisDetails {
replicationName := cr.Spec.RedisSentinelConfig.RedisReplicationName
replicationNamespace := cr.Namespace

var replicationInstance redisv1beta2.RedisReplication
var realMasterPod string

emptyRedisInfo := RedisDetails{
PodName: "",
Namespace: "",
}

// Get Request on Dynamic Client
customObject, err := dcl.Resource(schema.GroupVersionResource{
Group: "redis.redis.opstreelabs.in",
Expand All @@ -314,7 +335,7 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac

if err != nil {
log.FromContext(ctx).Error(err, "Failed to Execute Get Request", "replication name", replicationName, "namespace", replicationNamespace)
return ""
return emptyRedisInfo
} else {
log.FromContext(ctx).V(1).Info("Successfully Execute the Get Request", "replication name", replicationName, "namespace", replicationNamespace)
}
Expand All @@ -323,19 +344,19 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac
replicationJSON, err := customObject.MarshalJSON()
if err != nil {
log.FromContext(ctx).Error(err, "Failed To Load JSON")
return ""
return emptyRedisInfo
}

// Unmarshal The JSON on Object
if err := json.Unmarshal(replicationJSON, &replicationInstance); err != nil {
log.FromContext(ctx).Error(err, "Failed To Unmarshal JSON over the Object")
return ""
return emptyRedisInfo
}

masterPods := GetRedisNodesByRole(ctx, client, &replicationInstance, "master")
if len(masterPods) == 0 {
log.FromContext(ctx).Error(errors.New("no master pods found"), "")
return ""
return emptyRedisInfo
}
for _, podName := range masterPods {
redisClient := configureRedisReplicationClient(ctx, client, &replicationInstance, podName)
Expand All @@ -348,12 +369,29 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac
}
if realMasterPod == "" {
log.FromContext(ctx).Error(errors.New("no real master pod found"), "")
return ""
return emptyRedisInfo
}

realMasterInfo := RedisDetails{
return RedisDetails{
PodName: realMasterPod,
Namespace: replicationNamespace,
}
return getRedisServerIP(ctx, client, realMasterInfo)
}

func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) string {
RedisDetails := getRedisReplicationMasterPod(ctx, client, cr, dcl)
if RedisDetails.PodName == "" || RedisDetails.Namespace == "" {
return ""
} else {
return getRedisServerIP(ctx, client, RedisDetails)
}
}

func getRedisReplicationMasterName(ctx context.Context, client kubernetes.Interface, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) string {
RedisDetails := getRedisReplicationMasterPod(ctx, client, cr, dcl)
if RedisDetails.PodName == "" || RedisDetails.Namespace == "" {
return ""
} else {
return fmt.Sprintf("%s.%s-headless.%s.svc", RedisDetails.PodName, cr.Spec.RedisSentinelConfig.RedisReplicationName, RedisDetails.Namespace)
}
}
10 changes: 10 additions & 0 deletions pkg/k8sutils/redis-sentinel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ func Test_getSentinelEnvVariable(t *testing.T) {
DownAfterMilliseconds: "30000",
ParallelSyncs: "1",
FailoverTimeout: "180000",
ResolveHostnames: "no",
AnnounceHostnames: "no",
},
},
},
Expand Down Expand Up @@ -368,6 +370,14 @@ func Test_getSentinelEnvVariable(t *testing.T) {
Name: "FAILOVER_TIMEOUT",
Value: "180000",
},
{
Name: "RESOLVE_HOSTNAMES",
Value: "no",
},
{
Name: "ANNOUNCE_HOSTNAMES",
Value: "no",
},
},
},
}
Expand Down

0 comments on commit aafc663

Please sign in to comment.