Code Monkey home page Code Monkey logo

redis-operator's Introduction

Redis Operator

Build Status Go Report Card GolangCI LICENSE GoDoc Releases

Project status: alpha

The basic features have been completed, and while no breaking API changes are currently planned, the API can change in a backwards incompatible way before the project is declared stable.

Overview

Redis Operator can be considered a Kubernetes-native replacement for Redis Sentinel. It creates the Redis instances and maintains high availability and automatic failover.

Fundamental things to know about Redis Operator:

  • 3 is a minimum number of Redis instances. Having 3 instances allows to always maintain a simple master-replica pair thus making it possible to replicate data even with Redis persistence turned off.
  • Redis Operator is stateless. It means that it does not store any information about Redis instances internally. If an instance of the operator terminates in the middle of the failover process it will reconnect to Redis instances and reconfigure them if it is still required.
  • Redis Operator is not a distributed system. It leverages a simple leader election protocol. You can run multiple instances of Redis Operator. Detailed description of leader election can be found here.
  • One Redis Operator deployment is designed to rule multiple Redis replication setups. However you should bear in mind that current implementation is limited to reconfiguring one Redis replication at a time.
  • Redis Operator does not provide continuous monitoring, notification and service discovery. Those are provided by Kubernetes itself.
  • Redis clients don't need Sentinel support. Appropriate role labels are added to each pod and end users are encouraged to use services to connect to master or replica nodes.
  • Redis 5.0 is the minimum supported version.

Getting Started

Deploying the Redis operator

  1. Create all the necessary resources and deploy the operator:

    kubectl apply -k deploy
  2. Verify that the operator is running:

    $ kubectl -n redis-operator get deployment
    NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    redis-operator   1         1         1            1           5m

Deploying Redis

Redis can be deployed by creating a Redis Custom Resource(CR).

  1. Create a Redis CR that deploys a 3 node Redis replication in high availablilty mode:

    kubectl apply -f example/k8s_v1alpha1_redis_cr.yaml
  2. Wait until the redis-example-... pods for the Redis replication are up and check the status of 'redis'. It will show the name for the Pod of the current master instance and the total number of replicas in the setup:

    $ kubectl get redis example
    NAME      MASTER            REPLICAS   DESIRED   AGE
    example   redis-example-0   3          3         5m
  3. Verify that Redis is working as expected:

    $ kubectl exec $(k get redis example -o jsonpath={.status.master}) -c redis redis-cli set lol woot
    OK
    $ kubectl delete pod -l redis=example,role=master
    pod "redis-example-0" deleted
    $ kubectl exec $(k get redis example -o jsonpath={.status.master}) -c redis redis-cli get lol
    woot
  4. Scale the deployment:

    $ kubectl scale redis example --replicas 4
    redis.k8s.amaiz.com/example scaled
    $ kubectl get redis
    NAME      MASTER            REPLICAS   DESIRED   AGE
    example   redis-example-1   4          4         10m
  5. Redis Operator creates the following resources owned by the corresponding Redis CR. Please note that the name of Redis (example in this case) is used as an infix or suffix for the names of the generated resources:

    • Secret redis-example (in case the password is set up)
    • ConfigMap redis-example
    • PodDisruptionBudget redis-example
    • StatefulSet redis-example
    • Services:
      • redis-example - covers all instances
      • redis-example-headless - covers all instances, headless
      • redis-example-master - service for access to the master instance
  6. Finally, to remove this particular example instance of the Redis CR, you can simply delete it, and Redis Operator will take care of cleanup for you.

    $ kubectl get redis
    NAME      MASTER            REPLICAS   DESIRED   AGE
    example   redis-example-1   4          4         10m
    $ kubectl delete redis example
    redis.k8s.amaiz.com "example" deleted

Configuring Redis

All configuration of Redis is done via editing the Redis resourse file. Fully annotated example can be found in the examples directory of the repo.

Uninstalling Redis operator

Delete the operators and CRDs. Kubernetes will garbage collect all operator-managed resources:

kubectl delete namespace redis-operator
kubectl delete crd redis.k8s.amaiz.com

Design and goals

The main goal of the project is to create a Kubernetes native service for managing highly available Redis deployments. Sentinel is great for simple Redis replication but it does not fit into Kubernetes model for a number of reasons:

  • yet another distributed system to maintain. In order to support automatic failover and high availability of Redis one should figure out some way to support automatic failover and high availability of Sentinel.
  • feature overlap. Monitoring(periodic instance health check), notifications(events) and service discovery are something Kubernetes already provides out of the box and can be leveraged by implementing your own controller and Custom Resources.
  • Sentinel allows to resist without human intervention to certain kind of failures. The goal of the operator is to create a Redis deployment that would resist without human intervention to most kind of failures.

Another imporatant goal of this project is to resist failures even with persistence turned off. In some scenarios persisting data on disk is not permitted and all the data should reside only in-memory no matter what. And at the same time losing this data is undesirable.

Automatic failover algorithm details

Redis Operator is not a distributed system. Instead it leverages the Kuberenetes API to perform a leader election upon startup. Current implementation of the leader election algorithm precludes the possibility of 2 instances mistakenly running as leaders (split brain).

Redis Operator watches for changes to the Redis resource as well as the resources managed by the operator and owned by Redis, e.g. ConfigMaps, Secrets, Services, PodDisruptionBudgets and StatefulSets. Should anything happen to any of the above the operator will check the state of the Kubernetes resources along with the state of Redis replication and reconfigure them if needed.

All the managed resources are created or updated in the first place. The resources already present are always compared to the resources generated by the operator and updated if they differ.

Once all the resources are in sync the list of Redis instances is compiled from the list of Pods owned by the corresponding StatefulSet. Only Pods with all containers running and ready are taken into account.

Minimum failover size is 2. 2 represents a simple master-replica pair essential for running replication. If the number of instances is less than the minimum failover size no reconfiguration will be performed. With this in mind it is absolutely normal to lose all instances but one at the same time. Even with persistence turned off the data will be preserved and replicated across all Pods that come in place of the terminated ones.

Redis Operator is stateless. It means that the state of replication is determined every time the list of Redis instances is analyzed.

The state of replication is determined based on the INFO REPLICATION output of every instance from the list.

A healthy replication is the state when there is a single master and all other instances are connected to it. In this case the operator will do nothing.

Master is an instance with at least one connected replica. If there is no masters found then there is one of two cases met:

  • the master is lost. Then there's at least one replica and one of the replicas should be promoted to master
  • all instances are masters. This is considered to be the initial state thus any instance can be chosen as a master

In case the master has been lost the list of candidate instances are sorted according to their replica priority and replication offset. Instances with replica priority equal to 0 are filtered out prior to sorting.

A replica with the lowest priority and/or higher replication offset is promoted to master.

With the master in place all other instances that do not report themselves as the master's replicas are reconfigured appropriately. All replicas in question are reconfigured simultaneously.

Once the reconfiguration has been finished all Pods are labeled appropriately with role=master or role=replica labels. Current master's Pod name and the total quantity of connected instances are written to the status field of the Redis resource. The ConfigMap is updated with the master's IP address.

Plans

Short term

  • add more testing

redis-operator's People

Contributors

aignatov avatar akamyshnikova avatar cameronbraid avatar nrvnrvn avatar step76 avatar timbarrass-finbourne avatar toha10 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis-operator's Issues

Redis not contactable via dns.

Firstly. Great work on producing this operator. It looks very promising, and is exactly what I've been looking for.

I've deployed the operator and an example database having modified the the name.
I was unable to connect to it from an app, so began some investigation, the output of which follows:

$ kubectl -n test exec -ti redis-test-0 -c redis -- sh
/data $ redis-cli -c
127.0.0.1:6379> get foo
"bar"
127.0.0.1:6379> exit
/data $ redis-cli -c -h redis-test
redis-test:6379> get foo
Error: Protocol error, got "H" as reply type byte
/data $ redis-cli -c -h redis-test.test
redis-test.test:6379> get foo
Error: Protocol error, got "H" as reply type byte
/data $ redis-cli -c -h redis-test.test.svc
redis-test.test.svc:6379> get foo
Error: Protocol error, got "H" as reply type byte
/data $ redis-cli -c -h redis-test.test.svc.cluster.local
redis-test.test.svc.cluster.local:6379> get foo
Error: Protocol error, got "H" as reply type byte
/data $ nslookup redis-test
nslookup: can't resolve '(null)': Name does not resolve

Name:      redis-test
Address 1: 10.3.161.25 redis-test.test.svc.cluster.local
/data $

As you can see, using localhost, I can connect and query (added foo earlier) . But if I try and use the service name in any way, it fails.

I noticed that the pods don't have any ports exposed, so I tried editing the statefulset yaml and adding 6379, but got exactly the same result. Also tried with and without the password..

Any ideas?

Support setting the redis save config option

the redis save option in the config file allows multiple lines: e.g.

save 900 1
save 300 10
save 60 10000

because this operator uses a key-value map for the config we are only allowed a single save option.

Service is configured with port 9121/TCP instead of 6379/TCP

How to reproduce:

Install the Redis Operator by apply'ing all the YAML in deploy/.

Try to create the following Redis instance:

apiVersion: k8s.amaiz.com/v1alpha1
kind: Redis
metadata:
  name: example
spec:
  replicas: 3
  redis:
    image: redis:5-alpine

Then I try to connect to the redis-example or redis-example-master services:

$ kubectl get svc
NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes               ClusterIP   10.96.0.1      <none>        443/TCP    23h
redis-example            ClusterIP   10.101.33.59   <none>        6379/TCP   7m13s
redis-example-headless   ClusterIP   None           <none>        6379/TCP   7m13s
redis-example-master     ClusterIP   10.98.50.4     <none>        6379/TCP   7m13s
$ telnet  10.101.33.59 6379
Trying 10.101.33.59...
telnet: Unable to connect to remote host: Connection refused

Extra information:

The service appears to be sending connections to port 9121 instead of 6379:

$ kubectl describe svc redis-example
Name:              redis-example
Namespace:         default
Labels:            redis=example
Annotations:       <none>
Selector:          redis=example
Type:              ClusterIP
IP:                10.101.33.59
Port:              redis  6379/TCP
TargetPort:        9121/TCP
Endpoints:         10.32.0.4:9121,10.38.0.2:9121,10.46.0.2:9121
Session Affinity:  None
Events:            <none>

After quickly grepping the code, it looks like 9121 is the port of the exporter.
So this might be because I haven't enabled the exporter.
I'll try to enable it and report what happens.

How to manage multiple _loadmodule_

As stated in the title I need to add in the config of Redis two loadmodule directives.
If I compile the yaml with a section like this

config:
  loadmodule: "first module"
  loadmodule: "second module"

only the second module will be loaded and the first one is discarded because in YAML only the first occurrence is retained.

I thought about generating a custom config file in a init container and the include it, but the include keyword is forbidden.

Do you think I can try some workaround?

Can I contribute to the operator with a patch to address this issue? How could be changed the config management in a way to support this kind of configuration? I was thinking to add a specific module section, what do you think about?

Redis password problem

When I set the secret of password, the auth command can be executed correctly, but it can still be logged in without password.

image

.rdb permission denied

I've enabled persistence and I can see the pv and pvc and the mount /data but I get permission denied, I can't see where else I needed to configure anything.

Please help 👍 @nrvnrvn
When redis is running did i need to check user is a member of some kind of group to access the /data r/w volume?
If I jump on a terminal I can't create a test file in that /data mount and my linux skills are years ago :) so I'm not sure where to check.

Example is not working in k8s 1.21

Hello!

First, I have to say thank you for the effort on this solution.

I'm trying to deploy a new cluster over k8s 1.21 but the pods are not able to start. Seems that the liveness and Readiness are failing over the redis container. I was able to start the pods removing the checking configuration, so the pod is able to start (starting redis correctly), but the operator is not able to set a master (the "error":"minimum replication size is not met, only 0 are healthy" message is not appearing anymore).

Please let me know if I can give you any logs or help you anyhow.

Is there a way to make the rollout always in-sync?

Hi,

Curious: I'm seeing this on Kafka cluster tool (Strimzi), they provide a way to not rely on the "pod disruption budget" to make sure 2/3 instances are always up.

What I mean by this is that usually:

  • Kubernetes will do the rollout of pods
  • It adds a new pod and once ready, it removes an old one
  • But this does not take in account the time needed for all instances to sync between each other

There is a chance where Kubernetes will have for sure 2/3 pods "ready", but only "1/3" synchronous compared to before the rollout. Worst in case the rollout is really speed (they all become ready fast, without the time to sync with the last instances that had data before being drained).

Here their tool: https://github.com/strimzi/drain-cleaner

I didn't face this issue your Redis operator but what I understand it's possible (so just asking and pointing this). Just wanted to know what you think about this, and if you already thought about this :) ?

Thank you,

cc @nrvnrvn

internal/informers error

Hi @nrvnrvn the operator seems to get unstable with this error.
(We upgraded some time ago to K8s AKS version 1.18.8 and the cluster seemed to be working fine then errored, any clues what this process is doing that couldn't reach 10.0.0.1?

1123 23:41:35.966281 1 reflector.go:134] pkg/cache/internal/informers_map.go:196: Failed to list *v1.Pod: Get https://10.0.0.1:443/api/v1/pods?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout
E1123 23:41:35.968999 1 reflector.go:134] pkg/cache/internal/informers_map.go:126: Failed to list *v1.ConfigMap: Get https://10.0.0.1:443/api/v1/configmaps?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout
E1123 23:41:36.019562 1 reflector.go:134] pkg/cache/internal/informers_map.go:126: Failed to list *v1.Service: Get https://10.0.0.1:443/api/v1/services?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout
E1123 23:41:36.020778 1 reflector.go:134] pkg/cache/internal/informers_map.go:126: Failed to list *v1.StatefulSet: Get https://10.0.0.1:443/apis/apps/v1/statefulsets?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout
E1123 23:41:36.021841 1 reflector.go:134] pkg/cache/internal/informers_map.go:126: Failed to list *v1alpha1.Redis: Get https://10.0.0.1:443/apis/k8s.amaiz.com/v1alpha1/redis?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout
E1123 23:41:36.023000 1 reflector.go:134] pkg/cache/internal/informers_map.go:126: Failed to list *v1beta1.PodDisruptionBudget: Get https://10.0.0.1:443/apis/policy/v1beta1/poddisruptionbudgets?limit=500&resourceVersion=0: dial tcp 10.0.0.1:443: i/o timeout

Failed to update Pods in Kubernetes 1.19

My cluster just got upgraded to 1.19 and since then the operator is throwing and error trying to update Pods' PodSpec.SecurityContext.SeccompProfile field as it's immutable.

Here's the full error:

{"level":"error","ts":"2021-02-23T10:26:26.380Z","logger":"kubebuilder.controller","msg":"Reconciler error","controller":"redis-controller","request":"cache/redis","error":"failed to update Pods: Pod \"redis-redis-0\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
core.PodSpec{
	... // 10 identical fields
	AutomountServiceAccountToken: nil,
	NodeName:                     \"gke-leadpoint-cpu-2ef04e66-ssc3\",
	SecurityContext: &core.PodSecurityContext{
		... // 11 identical fields
		FSGroupChangePolicy: nil,
		Sysctls:             nil,
-┬а		SeccompProfile:      nil,
+┬а		SeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},
	},
	ImagePullSecrets: nil,
	Hostname:         \"redis-redis-0\",
	... // 15 identical fields
}
; Pod \"redis-redis-2\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
core.PodSpec{
	... // 10 identical fields
	AutomountServiceAccountToken: nil,
	NodeName:                     \"gke-leadpoint-memory-2db8b3f6-oe3m\",
	SecurityContext: &core.PodSecurityContext{
		... // 11 identical fields
		FSGroupChangePolicy: nil,
		Sysctls:             nil,
-┬а		SeccompProfile:      nil,
+┬а		SeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},
	},
	ImagePullSecrets: nil,
	Hostname:         \"redis-redis-2\",
	... // 15 identical fields
}
; Pod \"redis-redis-1\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
core.PodSpec{
	... // 10 identical fields
	AutomountServiceAccountToken: nil,
	NodeName:                     \"gke-leadpoint-memory-2db8b3f6-no3n\",
	SecurityContext: &core.PodSecurityContext{
		... // 11 identical fields
		FSGroupChangePolicy: nil,
		Sysctls:             nil,
-┬а		SeccompProfile:      nil,
+┬а		SeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},
	},
	ImagePullSecrets: nil,
	Hostname:         \"redis-redis-1\",
	... // 15 identical fields
}
;","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error
	vendor/github.com/go-logr/zapr/zapr.go:128
github.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
	vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:217
github.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1
	vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:158
github.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
	vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133
github.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil
	vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134
github.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until
	vendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}

Redis Master does not come up

I ran through the steps, but there are no redis instances available.

kubectl create namespace redis-operator
kubectl apply -Rf deploy
kubectl -n redis-operator get deployment
kubectl create -f example/k8s_v1alpha1_redis_cr.yaml
kubectl get redis example

NAME      MASTER   REPLICAS   DESIRED   AGE
example                       3         10h

Additional Info

kubectl version
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.3", GitCommit:"721bfa751924da8d1680787490c54b9179b1fed0", GitTreeState:"clean", BuildDate:"2019-02-04T04:49:22Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.7-3+1a4d39a9763d23", GitCommit:"1a4d39a9763d23548d16e262d6dbe0fb2198a8ce", GitTreeState:"clean", BuildDate:"2019-03-27T01:47:38Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}

Can you pls take a look ?

Let me know if you need any logs/additional detail.

any plans to change : current implementation is limited to reconfiguring one Redis replication at a time

The readme states

One Redis Operator deployment is designed to rule multiple Redis replication setups. However you should bear in mind that current implementation is limited to reconfiguring one Redis replication at a time

First of all to clarify what this means. Am I correct in saying that I cant create two

apiVersion: k8s.amaiz.com/v1alpha1
kind: Redis
...

custom resources and have the operator manage them both ?

Are there plans to remove this limitation ?

Operator gets stuck at syncing the statefull set when container resources are specified in a non "normal" form

With this in my crd

 redis:
    image: redis:6.2.6-alpine
    initialDelaySeconds: 10
    resources:
      limits:
        cpu: 1000m
        memory: 2Gi
      requests:
        cpu: 500m
        memory: 0.8Gi

the stateful set gets created with

        resources:
          limits:
            cpu: "1"
            memory: 2Gi
          requests:
            cpu: 500m
            memory: 858993459200m

and the operator keeps logging
... "logger":"controller_redis","msg":"Applied *v1.StatefulSet","Namespace ...
every 2 seconds

if I change my definition to

      limits:
        cpu: "1"
        memory: 2Gi
      requests:
        cpu: 500m
        memory: 800Mi

the stateful set is created with identical values and the operator moves on to the next step.

P.S. To help other people find this issue: everything was "running" but there was no master label assigned to any of the pods, so I was unable to connect and the pod logs all showed the instances running as standalone servers, the ConfigMap did not have the replicaof line.

I guess something is normalising the resource values as the stateful set is created, but not normalising them before the diff check.

Please add support redis cluster.

@asumner as of now it does not support redis cluster unfortunately.

But I will be happy to add support for it.

This operator's initial goal was to support 1 master <-> N replicas architecture in the same way Sentinel provides it but without the burden of maintaining Sentinel itself.

Redis Cluster is N masters * N replicas and requires a bit different approach to setting up and managing.

If you need support for sharding and all the rest Cluster features immediately this operator is not for you. :(

If soon is a matter of couple of months then I will be happy to help you with it :)

Originally posted by @nrvnrvn in #18 (comment)

Persistent Volumes

Do you have a good example of how to add Persistent Volumes to a cluster? I've noticed that there is some data volume template in the definition, but don't really know how to configure it.

Cheers,

PersistentVolume mounted to /data with root group, not following securityContext.fsGroup

Seems like securityContext.fsGroup is not applied to the volume.

When I uncomment persistentVolumeClaimTemplate in https://github.com/amaizfinance/redis-operator/blob/master/example/k8s_v1alpha1_redis_cr.yaml, it correctly mounts the volume to redis /data directory. But it has only root owner and group and redis cannot write to this directory. Seems like securityContext.fsGroup is not applied to the volume. Like it is not passed to StatefulSet securityContext.fsGroup.

redis:
     securityContext:
           fsGroup: 7777777

Deploying example not working

Steps to reproduce:
DigitalOcean Kubernetes v1.19.3

  1. Apply kustomization.yaml
bases:
  - github.com/amaizfinance/redis-operator/deploy?ref=master
  1. Apply example/k8s_v1alpha1_redis_cr.yaml
  2. No master gets elected, no election happens

Output:

(⎈ |do-nyc3-automuteus:automuteus-redis-ha)~/g/automuteus-infra » k get pod,redis                                      master ✗
NAME                  READY   STATUS    RESTARTS   AGE
pod/redis-example-0   2/2     Running   0          5m2s
pod/redis-example-1   2/2     Running   0          4m43s
pod/redis-example-2   2/2     Running   0          4m27s

NAME                          MASTER   REPLICAS   DESIRED   AGE
redis.k8s.amaiz.com/example                       3         5m2s

Logs operator :

redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.409Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.422Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.433Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.446Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.452Z","logger":"controller_redis","msg":"Applied *v1.ConfigMap","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.463Z","logger":"controller_redis","msg":"Applied *v1beta1.PodDisruptionBudget","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.495Z","logger":"controller_redis","msg":"Applied *v1.StatefulSet","Namespace":"automuteus-redis-ha","Redis":"example"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.597Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.615Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.624Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.740Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:16.744Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:19.192Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:35.778Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 1 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:35.811Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 1 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:35.830Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 1 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"info","ts":"2020-11-10T23:04:39.674Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"automuteus-redis-ha","Redis":"example","error":"minimum replication size is not met, only 1 are healthy"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"error","ts":"2020-11-10T23:04:53.317Z","logger":"kubebuilder.controller","msg":"Reconciler error","controller":"redis-controller","request":"automuteus-redis-ha/example","error":"failed to update Pods: Pod \"redis-example-1\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1e\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-1\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-0\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-0\",\n  \t... // 15 identical fields\n  }\n;","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\tvendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:217\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:158\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"error","ts":"2020-11-10T23:04:54.371Z","logger":"kubebuilder.controller","msg":"Reconciler error","controller":"redis-controller","request":"automuteus-redis-ha/example","error":"failed to update Pods: Pod \"redis-example-2\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-2\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-1\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1e\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-1\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-0\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-0\",\n  \t... // 15 identical fields\n  }\n;","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\tvendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:217\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:158\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"error","ts":"2020-11-10T23:05:12.267Z","logger":"kubebuilder.controller","msg":"Reconciler error","controller":"redis-controller","request":"automuteus-redis-ha/example","error":"failed to update Pods: Pod \"redis-example-0\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-0\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-2\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-2\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-1\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1e\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-1\",\n  \t... // 15 identical fields\n  }\n;","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\tvendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:217\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:158\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}
redis-operator-5675f8ccd-gszsm redis-operator {"level":"error","ts":"2020-11-10T23:05:13.297Z","logger":"kubebuilder.controller","msg":"Reconciler error","controller":"redis-controller","request":"automuteus-redis-ha/example","error":"failed to update Pods: Pod \"redis-example-2\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-2\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-0\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1g\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-0\",\n  \t... // 15 identical fields\n  }\n; Pod \"redis-example-1\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 10 identical fields\n  \tAutomountServiceAccountToken: nil,\n  \tNodeName:                     \"pool-kf1t8lj0w-3kj1e\",\n  \tSecurityContext: &core.PodSecurityContext{\n  \t\t... // 11 identical fields\n  \t\tFSGroupChangePolicy: nil,\n  \t\tSysctls:             nil,\n- \t\tSeccompProfile:      nil,\n+ \t\tSeccompProfile:      &core.SeccompProfile{Type: \"RuntimeDefault\"},\n  \t},\n  \tImagePullSecrets: nil,\n  \tHostname:         \"redis-example-1\",\n  \t... // 15 identical fields\n  }\n;","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\tvendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:217\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:158\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:134\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:88"}

Redis logs

redis-example-1 redis 1:C 10 Nov 2020 23:04:40.264 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-example-1 redis 1:C 10 Nov 2020 23:04:40.264 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis-example-1 redis 1:C 10 Nov 2020 23:04:40.264 # Configuration loaded
redis-example-1 exporter time="2020-11-10T23:04:44Z" level=info msg="Redis Metrics Exporter v1.11.1    build date: 2020-08-28-17:21:19    sha1: 3d94cd439e70d3ab478bfa65c1f131ab978a60ad    Go: go1.15    GOOS: linux    GOARCH: amd64"
redis-example-1 exporter time="2020-11-10T23:04:44Z" level=info msg="Providing metrics at :9121/metrics"
redis-example-1 redis 1:M 10 Nov 2020 23:04:40.356 * Running mode=standalone, port=6379.
redis-example-1 redis 1:M 10 Nov 2020 23:04:40.357 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis-example-1 redis 1:M 10 Nov 2020 23:04:40.357 # Server initialized
redis-example-1 redis 1:M 10 Nov 2020 23:04:40.357 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
redis-example-1 redis 1:M 10 Nov 2020 23:04:40.358 * Ready to accept connections
redis-example-1 redis 1:S 10 Nov 2020 23:04:51.070 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
redis-example-1 redis 1:S 10 Nov 2020 23:04:51.071 * REPLICAOF 10.244.2.40:6379 enabled (user request from 'id=5 addr=10.244.2.63:56970 fd=8 name= age=0 idle=0 flags=x db=0 sub=0 psub=0 multi=2 qbuf=122 qbuf-free=32646 argv-mem=4 obl=27 oll=0 omem=0 tot-mem=61468 events=r cmd=exec user=default')
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.165 * Connecting to MASTER 10.244.2.40:6379
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.166 * MASTER <-> REPLICA sync started
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.252 * Non blocking connect for SYNC fired the event.
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.255 * Master replied to PING, replication can continue...
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.259 * Trying a partial resynchronization (request 3c0c7132f4d0a76889d82a5867e8487cd36e56b3:1).
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.265 * Full resync from master: 6d8165b7d4cf8a33431579b0722238f74145b459:0
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.265 * Discarding previously cached master state.
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.322 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.323 * MASTER <-> REPLICA sync: Flushing old data
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.323 * MASTER <-> REPLICA sync: Loading DB in memory
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.355 * Loading RDB produced by version 6.0.9
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.355 * RDB age 0 seconds
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.355 * RDB memory usage when created 1.85 Mb
redis-example-1 redis 1:S 10 Nov 2020 23:04:52.355 * MASTER <-> REPLICA sync: Finished with success
redis-example-2 redis 1:C 10 Nov 2020 23:04:52.739 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-example-2 redis 1:C 10 Nov 2020 23:04:52.739 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis-example-2 redis 1:C 10 Nov 2020 23:04:52.739 # Configuration loaded
redis-example-2 redis 1:M 10 Nov 2020 23:04:52.741 * Running mode=standalone, port=6379.
redis-example-2 redis 1:M 10 Nov 2020 23:04:52.827 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis-example-2 redis 1:M 10 Nov 2020 23:04:52.827 # Server initialized
redis-example-2 redis 1:M 10 Nov 2020 23:04:52.827 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
redis-example-2 redis-example-2 exporter time="2020-11-10T23:04:53Z" level=info msg="Redis Metrics Exporter v1.11.1    build date: 2020-08-28-17:21:19    sha1: 3d94cd439e70d3ab478bfa65c1f131ab978a60ad    Go: go1.15    GOOS: linux    GOARCH: amd64"
redis-example-2 exporter time="2020-11-10T23:04:53Z" level=info msg="Providing metrics at :9121/metrics"
redis 1:M 10 Nov 2020 23:04:52.828 * Ready to accept connections
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.138 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.138 * REPLICAOF 10.244.2.40:6379 enabled (user request from 'id=6 addr=10.244.2.63:44632 fd=8 name= age=0 idle=0 flags=x db=0 sub=0 psub=0 multi=2 qbuf=122 qbuf-free=32646 argv-mem=4 obl=27 oll=0 omem=0 tot-mem=61468 events=r cmd=exec user=default')
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.961 * Connecting to MASTER 10.244.2.40:6379
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.962 * MASTER <-> REPLICA sync started
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.962 * Non blocking connect for SYNC fired the event.
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.962 * Master replied to PING, replication can continue...
redis-example-2 redis 1:S 10 Nov 2020 23:05:12.962 * Trying a partial resynchronization (request c0baa0b78d691bc078e06bf443220fbebe8fe262:1).
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.027 * Full resync from master: 6d8165b7d4cf8a33431579b0722238f74145b459:28
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.027 * Discarding previously cached master state.
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.048 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.049 * MASTER <-> REPLICA sync: Flushing old data
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.049 * MASTER <-> REPLICA sync: Loading DB in memory
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.055 * Loading RDB produced by version 6.0.9
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.055 * RDB age 1 seconds
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.056 * RDB memory usage when created 1.88 Mb
redis-example-2 redis 1:S 10 Nov 2020 23:05:13.056 * MASTER <-> REPLICA sync: Finished with success
redis-example-0 redis 1:C 10 Nov 2020 23:04:18.631 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-example-0 redis 1:C 10 Nov 2020 23:04:18.631 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis-example-0 redis 1:C 10 Nov 2020 23:04:18.631 # Configuration loaded
redis-example-0 redis 1:M 10 Nov 2020 23:04:18.633 * Running mode=standalone, port=6379.
redis-example-0 redis 1:M 10 Nov 2020 23:04:18.633 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis-example-0 redis-example-0 exporter time="2020-11-10T23:04:19Z" level=info msg="Redis Metrics Exporter v1.11.1    build date: 2020-08-28-17:21:19    sha1: 3d94cd439e70d3ab478bfa65c1f131ab978a60ad    Go: go1.15    GOOS: linux    GOARCH: amd64"
redis 1:M 10 Nov 2020 23:04:18.633 # Server initialized
redis-example-0 redis 1:M 10 Nov 2020 23:04:18.633 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
redis-example-0 redis 1:M 10 Nov 2020 23:04:18.633 * Ready to accept connections
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.282 * Replica 10.244.2.181:6379 asks for synchronization
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.282 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '3c0c7132f4d0a76889d82a5867e8487cd36e56b3', my replication IDs are '599151193739e42bb7efd6e30649af575fa5fe60' and '0000000000000000000000000000000000000000')
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.282 * Replication backlog created, my new replication IDs are '6d8165b7d4cf8a33431579b0722238f74145b459' and '0000000000000000000000000000000000000000'
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.282 * Starting BGSAVE for SYNC with target: disk
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.283 * Background saving started by pid 36
redis-example-0 redis 36:C 10 Nov 2020 23:04:52.285 * DB saved on disk
redis-example-0 redis 36:C 10 Nov 2020 23:04:52.285 * RDB: 0 MB of memory used by copy-on-write
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.343 * Background saving terminated with success
redis-example-0 redis 1:M 10 Nov 2020 23:04:52.343 * Synchronization with replica 10.244.2.181:6379 succeeded
redis-example-0 redis 1:M 10 Nov 2020 23:05:12.962 * Replica 10.244.2.41:6379 asks for synchronization
redis-example-0 redis 1:M 10 Nov 2020 23:05:12.962 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'c0baa0b78d691bc078e06bf443220fbebe8fe262', my replication IDs are '6d8165b7d4cf8a33431579b0722238f74145b459' and '0000000000000000000000000000000000000000')
redis-example-0 redis 1:M 10 Nov 2020 23:05:12.962 * Starting BGSAVE for SYNC with target: disk
redis-example-0 redis 1:M 10 Nov 2020 23:05:12.963 * Background saving started by pid 62
redis-example-0 redis 62:C 10 Nov 2020 23:05:12.965 * DB saved on disk
redis-example-0 redis 62:C 10 Nov 2020 23:05:12.966 * RDB: 0 MB of memory used by copy-on-write
redis-example-0 redis 1:M 10 Nov 2020 23:05:13.048 * Background saving terminated with success
redis-example-0 redis 1:M 10 Nov 2020 23:05:13.048 * Synchronization with replica 10.244.2.41:6379 succeeded
redis-example-0 exporter time="2020-11-10T23:04:19Z" level=info msg="Providing metrics at :9121/metrics"

How do I use dump.rdb for data recovery

specific operation:

  1. redis-cli bgsave command is used to backup redis data and dump.rdb backup file into the backup directory
  2. clear the redis database
  3. replace the backup dump.rdb file with the existing dump.rdb file(all three redis nodes operate)
  4. delete the pod of the current redis master (kubectl delete pod redis-0)

redis master has been switched to redis-1, the dump.rdb file in master-1 is newly generated, the dump.rdb file you backed up earlier was not loaded, so the data recovery failed

What's the best way to enable logging of GET/SET?

Hi @nrvnrvn ,

I would like to have your thoughts so in development environment I can debug all GET/SET from the Redis cluster through the operator.

This one can be done by running a command redis-cli monitor (https://redis.io/commands/MONITOR) that watches all events and logs them (can be written to a file if wanted). But I don't know what would be the best practice to make it "embedded" with the operator.

Should the operator launch another container just doing sleep X && redis-cli monitor (the sleep would be to wait for the other container Redis server to be ready)? Or do you see something better? Maybe I should create this deployment on my own without relying on the operator?

In both cases, should my redis-cli monitor watches all the cluster, or just the master?

Thank you,

How do i connect to redis from outside kubernetes

I see service is being created with port 6379. but i don't see any container ports defined in statefulset template once created.

when i use redis-cli externally to connect it says Could not connect to Redis No route to host

v1 roadmap

This is an umbrella issue to hold a checklist of tasks for a v1 release.

  • refactor pkg/redis. It works fine and it was written with Redis Sentinel in mind but it is worth reviewing the implementation in order to make it less coupled internally and more testable and transparent.
  • loose control over created resources, especially StatefulSet. Current approach cherry picks bits from the StatefulSet spec and it makes sense to turn Redis CRD into a thin StatefulSet wrapper to give end users more control over the generated StatefulSet hence Pods and containers (#9 is an example feature request and it is clear that it is not the last. Other kubernetes operators dealing with the same problem end up with a messed API. Feel free to look at the most popular operators, their type definitions and requests to add missing container and Pod Spec fields and you will understand what I mean).
  • remove redis exporter container. There are different scenarios of gathering metrics, and side-container pattern is just one of them. Provide a short instruction on how to connect an exporter.
  • research switching to kubebuilder v2. operator-sdk is built on top of kubebuilder but skews drastically in terms of features adding very little in exchange (see operator-framework/operator-sdk/issues/1758)
  • allow concurrent reconciliation (see #13)

This list is subject to be extended. Discussion is open. Any feedback is welcome!

Bump operator-sdk version

Project development requires usage higher version of operator-sdk and kubernetes.

Update operator-sdk to 0.19.x and go to 1.16, unlocking following updates.

Pods are healthy, but operator says: minimum replication size is not met, only 0 are healthy

Kubernetes 1.20.4
Redis-operator manifests:

kustomize build github.com/sim1/katalog/redis-operator/default?ref=0.0.4

(upstream kustomize remote + 0.2.0 -> latest image tag rewrite due to #24)

Manifest:

---
apiVersion: k8s.amaiz.com/v1alpha1
kind: Redis
metadata:
  # the .metadata.labels will be added to all generated resources along with the
  # redis=example label
  labels:
    component: redis
  # the name of the Redis resource will be used as a label for all generated resources,
  # and as the infix or suffix for them.
  name: super
spec:
  replicas: 3
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - podAffinityTerm:
            labelSelector:
              matchExpressions:
                - key: component
                  operator: In
                  values:
                    - redis
            topologyKey: kubernetes.io/hostname
          weight: 70
  annotations:
    cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
    seccomp.security.alpha.kubernetes.io/pod: runtime/default

  dataVolumeClaimTemplate:
    metadata:
      name: redis-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

  # Redis container definition (required)
  # image, resources and securityContext are the same as found in v1.Container.
  # More info: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#container-v1-core
  redis:
    image: redis:alpine
    initialDelaySeconds: 10
    resources:
      requests:
        memory: 50Mi
      limits:
        cpu: 500m
        memory: 256Mi
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - all
      readOnlyRootFilesystem: true
      runAsUser: 7777777
      runAsGroup: 7777777
      fsGroup: 7777777
      runAsNonRoot: true

Logs:

~ » k get svc,ep,pod
NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/redis-super            ClusterIP   10.35.154.189   <none>        6379/TCP   118s
service/redis-super-headless   ClusterIP   None            <none>        6379/TCP   118s
service/redis-super-master     ClusterIP   10.44.178.120   <none>        6379/TCP   118s

NAME                             ENDPOINTS                                                    AGE
endpoints/redis-super            100.64.187.97:6379,100.65.142.252:6379,100.65.142.253:6379   118s
endpoints/redis-super-headless   100.64.187.97:6379,100.65.142.252:6379,100.65.142.253:6379   118s
endpoints/redis-super-master     <none>                                                       118s

NAME                         READY   STATUS                       RESTARTS   AGE
pod/redis-super-0            1/1     Running                      0          118s
pod/redis-super-1            1/1     Running                      0          82s
pod/redis-super-2            1/1     Running                      0          45s
pod/super-774fd5458f-pvzn7   0/2     CreateContainerConfigError   0          118s
~ » k get svc,ep,pod
NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/redis-super            ClusterIP   10.35.154.189   <none>        6379/TCP   119s
service/redis-super-headless   ClusterIP   None            <none>        6379/TCP   119s
service/redis-super-master     ClusterIP   10.44.178.120   <none>        6379/TCP   119s

NAME                             ENDPOINTS                                                    AGE
endpoints/redis-super            100.64.187.97:6379,100.65.142.252:6379,100.65.142.253:6379   119s
endpoints/redis-super-headless   100.64.187.97:6379,100.65.142.252:6379,100.65.142.253:6379   119s
endpoints/redis-super-master     <none>                                                       119s

NAME                         READY   STATUS                       RESTARTS   AGE
pod/redis-super-0            1/1     Running                      0          119s
pod/redis-super-1            1/1     Running                      0          83s
pod/redis-super-2            1/1     Running                      0          46s
pod/super-774fd5458f-pvzn7   0/2     CreateContainerConfigError   0          119s
~ » kns redis-operator
stern Set context namespace to "redis-operator"
.
~ » stern .
+ redis-operator-6bd5b89477-74lp9 › redis-operator
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:54.120Z","logger":"cmd","msg":"Redis-Operator Version: latest"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:54.120Z","logger":"cmd","msg":"Go Version: go1.15.1"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:54.121Z","logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:54.121Z","logger":"cmd","msg":"Version of operator-sdk: v0.17.1"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:54.121Z","logger":"leader","msg":"Trying to become the leader."}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:56.728Z","logger":"leader","msg":"No pre-existing lock was found."}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:56.773Z","logger":"leader","msg":"Became the leader."}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:59.309Z","logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":"0.0.0.0:8383"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:26:59.310Z","logger":"cmd","msg":"Registering Components."}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.590Z","logger":"metrics","msg":"Metrics Service object created","Service.Name":"redis-operator-metrics","Service.Namespace":"redis-operator"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.590Z","logger":"cmd","msg":"Starting the Cmd."}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.591Z","logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.591Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.692Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:04.995Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:05.095Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:05.196Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:05.298Z","logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"redis-controller","source":"kind source: /, Kind="}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:05.401Z","logger":"controller-runtime.controller","msg":"Starting Controller","controller":"redis-controller"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:27:05.401Z","logger":"controller-runtime.controller","msg":"Starting workers","controller":"redis-controller","worker count":1}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.265Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.307Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.349Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.442Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.485Z","logger":"controller_redis","msg":"Applied *v1.ConfigMap","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.519Z","logger":"controller_redis","msg":"Applied *v1beta1.PodDisruptionBudget","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.651Z","logger":"controller_redis","msg":"Applied *v1.StatefulSet","Namespace":"super","Redis":"super"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.856Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.859Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.972Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:50.999Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:51.001Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:51.029Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:51.030Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:37:53.534Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:38:31.895Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:38:36.898Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:39:12.902Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:39:22.904Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:39:32.907Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:39:50.139Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}


redis-operator-6bd5b89477-74lp9 redis-operator {"level":"info","ts":"2021-02-27T18:40:05.142Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"super","Redis":"super","error":"minimum replication size is not met, only 0 are healthy"}
^C
~ » k get pod -n super
NAME                     READY   STATUS                       RESTARTS   AGE
redis-super-0            1/1     Running                      0          2m48s
redis-super-1            1/1     Running                      0          2m12s
redis-super-2            1/1     Running                      0          95s
super-774fd5458f-pvzn7   0/2     CreateContainerConfigError   0          2m48s
~ »

redis-cluster-2 CrashLoopBackOff after deployment

If I deploy redis with 3 replica, I am frequently getting CrashLoopBackOff error for redis-cluster-2 but all other pods are running find including operator. When I described the failed pod, I can see the blow logs:

Last State: Terminated
Reason: ContainerCannotRun
Message: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused "rootfs_linux.go:58: mounting \"/var/lib/kubelet/pods/3ba5043e-ed13-4a47-8554-f29bb14dec94/volume-subpaths/redis-cluster-config/redis/0\" to rootfs \"/u01/data/docker/overlay2/a75dd75f91d5e32c330de89c49c13e9302447a2b3fe4550c9c48e0c0b8f63dfa/merged\" at \"/u01/data/docker/overlay2/a75dd75f91d5e32c330de89c49c13e9302447a2b3fe4550c9c48e0c0b8f63dfa/merged/config/redis.conf\" caused \"no such file or directory\""": unknown

But if I restart the pod by deleting it, it's running fine. Any idea why it's failing for the initial deployment? might be some timing issue for creating configMap ?

Example in Readme does not work

$ kubectl apply -f example/k8s_v1alpha1_redis_cr.yaml

Makes the redis-operator fail with this error (kubectl logs -n redis-operator pod/redis-operator-xx-yy):

"error":"failed to fetch password: Secret \"redis-password-secret\" not found"

Commenting out the secret-section in the example YAML greatly improves things :)

"go mod tidy" fails in current version

The following issue happens when you run command below. As result this project can't be built
➜ git:(master) go mod tidy -v
go: github.com/operator-framework/[email protected] requires
github.com/operator-framework/[email protected] requires
github.com/operator-framework/[email protected] requires
github.com/operator-framework/[email protected] requires
bitbucket.org/ww/[email protected]: reading https://api.bitbucket.org/2.0/repositories/ww/goautoneg?fields=scm: 404 Not Found

Looks like it requires bumping of operator-sdk

Clean install does not work

Applying the crds and required operator resources in it's own namespace does create the operator and a cluster. However nothing can connect to that cluster reliably because "master" service points to a redis slave instance.

{"level":"info","ts":"2020-05-11T01:40:25.649Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.663Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.683Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.709Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.739Z","logger":"controller_redis","msg":"Applied *v1.Service","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.747Z","logger":"controller_redis","msg":"Applied *v1.Secret","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.754Z","logger":"controller_redis","msg":"Applied *v1.ConfigMap","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:25.766Z","logger":"controller_redis","msg":"Applied *v1beta1.PodDisruptionBudget","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:26.005Z","logger":"controller_redis","msg":"Applied *v1.StatefulSet","Namespace":"default","Redis":"shared-redis"}
{"level":"info","ts":"2020-05-11T01:40:26.304Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 0 are healthy"}
{"level":"info","ts":"2020-05-11T01:40:26.542Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 0 are healthy"}
{"level":"info","ts":"2020-05-11T01:40:29.198Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 0 are healthy"}
{"level":"info","ts":"2020-05-11T01:40:39.630Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 0 are healthy"}
{"level":"info","ts":"2020-05-11T01:41:00.368Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 0 are healthy"}
{"level":"info","ts":"2020-05-11T01:41:14.977Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 1 are healthy"}
{"level":"info","ts":"2020-05-11T01:41:15.190Z","logger":"controller_redis","msg":"Error creating Redis replication, requeue","Namespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 1 are healthy"}
{"level":"info","ts":"2020-05-11T01:41:41.590Z","logger":"controller_redis","msgamespace":"default","Redis":"shared-redis","error":"minimum replication size is not met, only 1 are healthy"}
{"level":"info","ts":"2020-05-11T01:41:59.595Z","logger":"controller_redis","msg":"no master discovered, requeue","Namespace":"default","Redis":"shared-redis","error":"no master discovered","replication":[{"Host":"10.60.1.15","Port":"6379"},{"Host":"10.60.0.24","Port":"6379"}]}
{"level":"info","ts":"2020-05-11T01:42:05.958Z","logger":"controller_redis","msg":"no master discovered, requeue","Namespace":"default","Redis":"shared-redis","error":"no master discovered","replication":[{"Host":"10.60.1.15","Port":"6379"},{"Host":"10.60.0.24","Port":"6379"}]}
{"level":"info","ts":"2020-05-11T01:42:35.246Z","logger":"controller_redis","msg":"no master discovered, requeue","Namespace":"default","Redis":"shared-redis","error":"no master discovered","replication":[{"Host":"10.60.1.15","Port":"6379"},{"Host":"10.60.0.24","Port":"6379"},{"Host":"10.60.2.20","Port":"6379"}]}
{"level":"info","ts":"2020-05-11T01:42:41.245Z","logger":"controller_redis","msg":"no master discovered, requeue","Namespace":"default","Redis":"shared-redis","error":"no master discovered","replication":[{"Host":"10.60.1.15","Port":"6379"},{"Host":"10.60.0.24","Port":"6379"},{"Host":"10.60.2.20","Port":"6379"}]}
{"level":"info","ts":"2020-05-11T01:47:19.691Z","logger":"controller_redis","msg":"no master discovered, requeue","Namespace":"default","Redis":"shared-redis","error":"no master discovered","replication":[{"Host":"10.60.0.24","Port":"6379"},{"Host":"10.60.2.20","Port":"6379"}]}

The operator seems to know there is no master, and there seems to be no election going on.

redis-shared-redis                      ClusterIP   10.64.6.241    <none>        6379/TCP                      22m
redis-shared-redis-headless             ClusterIP   None           <none>        6379/TCP                      22m
redis-shared-redis-master               ClusterIP   10.64.4.69     <none>        6379/TCP                      22m

The cluster ends up with an IP for master despite none of them being masters.

Operator unable to find secret defined in secret ref

Issue

Deploying the example and creating a Redis object works great and creates a redis deployment, but uncommenting the secretref causes the CRD to never finish creating the Redis statefulset and the operator pod has has the following log messages:

{"level":"error","ts":"2022-07-03T14:25:57.927Z","logger":"controller-runtime.controller","msg":"Reconciler error","controller":"redis-controller","request":"redis-operator/staging","error":"failed to fetch password: Secret \"\" not found","stacktrace":"github.com/amaizfinance/redis-operator/vendor/github.com/go-logr/zapr.(*zapLogger).Error\n\tvendor/github.com/go-logr/zapr/zapr.go:128\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:258\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:232\ngithub.com/amaizfinance/redis-operator/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker\n\tvendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:211\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:155\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:156\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.JitterUntil\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:133\ngithub.com/amaizfinance/redis-operator/vendor/k8s.io/apimachinery/pkg/util/wait.Until\n\tvendor/k8s.io/apimachinery/pkg/util/wait/wait.go:90"}

We have tried deploying the secret to both the destination namespace and the operator namespace, both fail to find it.Also manually editing the Redis CRD Object to modify the secretref field causes it to be set to {} after saving the kubectl edit.

I've also tried setting json: x-kubernetes-preserve-unknown-fields: true on the CRD source itself to see if kubernetes was pruning the field but observed no change in the CRD.

Kubernetes Version:
Client Version: v1.22.4
Server Version: v1.22.7+k3s1

Master service not available

When I was testing the redis master slave switch, I manually stopped the kubelet of the node where the current redis master is located and found the service unavailable. The endpoints of redis-master does not contain pod information
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.