Skip to content

Commit 92111c7

Browse files
committed
recorded password in the file /etc/redis_password
1 parent 4fc8771 commit 92111c7

File tree

10 files changed

+194
-17
lines changed

10 files changed

+194
-17
lines changed

deploy/cluster/cluster_role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ rules:
1919
- ""
2020
resources:
2121
- configmaps
22+
- pods/exec
2223
- secrets
2324
- services
2425
- events

deploy/namespace/role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ rules:
1919
- ""
2020
resources:
2121
- configmaps
22+
- pods/exec
2223
- secrets
2324
- services
2425
- events

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
203203
github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
204204
github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
205205
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
206+
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s=
206207
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
207208
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
208209
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -211,7 +212,9 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
211212
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
212213
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
213214
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
215+
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
214216
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
217+
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhPhOPHULCQQDnGhRelpFWHMLhQVWDsS0v4=
215218
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
216219
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
217220
github.com/emicklei/go-restful v2.9.3+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=

pkg/apis/redis/v1alpha1/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const (
4545
ClusterStatusRebalancing ClusterStatus = "Rebalancing"
4646
// ClusterStatusRollingUpdate ClusterStatus RollingUpdate
4747
ClusterStatusRollingUpdate ClusterStatus = "RollingUpdate"
48+
// ClusterStatusResetPassword ClusterStatus ResetPassword
49+
ClusterStatusResetPassword ClusterStatus = "ResetPassword"
4850
)
4951

5052
// NodesPlacementInfo Redis Nodes placement mode information

pkg/controller/distributedrediscluster/distributedrediscluster_controller.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import (
88
"github.com/spf13/pflag"
99
"k8s.io/apimachinery/pkg/api/errors"
1010
"k8s.io/apimachinery/pkg/runtime"
11+
runtimeschema "k8s.io/apimachinery/pkg/runtime/schema"
12+
"k8s.io/apimachinery/pkg/runtime/serializer"
13+
"k8s.io/client-go/kubernetes/scheme"
1114
"sigs.k8s.io/controller-runtime/pkg/client"
15+
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
1216
"sigs.k8s.io/controller-runtime/pkg/controller"
1317
"sigs.k8s.io/controller-runtime/pkg/event"
1418
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -22,6 +26,7 @@ import (
2226
"github.com/ucloud/redis-cluster-operator/pkg/config"
2327
"github.com/ucloud/redis-cluster-operator/pkg/controller/heal"
2428
clustermanger "github.com/ucloud/redis-cluster-operator/pkg/controller/manager"
29+
"github.com/ucloud/redis-cluster-operator/pkg/exec"
2530
"github.com/ucloud/redis-cluster-operator/pkg/k8sutil"
2631
"github.com/ucloud/redis-cluster-operator/pkg/redisutil"
2732
"github.com/ucloud/redis-cluster-operator/pkg/resources/statefulsets"
@@ -56,11 +61,22 @@ func FlagSet() *pflag.FlagSet {
5661
// Add creates a new DistributedRedisCluster Controller and adds it to the Manager. The Manager will set fields on the Controller
5762
// and Start it when the Manager is Started.
5863
func Add(mgr manager.Manager) error {
59-
return add(mgr, newReconciler(mgr))
64+
gvk := runtimeschema.GroupVersionKind{
65+
Group: "",
66+
Version: "v1",
67+
Kind: "Pod",
68+
}
69+
restClient, err := apiutil.RESTClientForGVK(gvk, mgr.GetConfig(), serializer.NewCodecFactory(scheme.Scheme))
70+
if err != nil {
71+
return err
72+
}
73+
execer := exec.NewRemoteExec(restClient, mgr.GetConfig(), log)
74+
75+
return add(mgr, newReconciler(mgr, execer))
6076
}
6177

6278
// newReconciler returns a new reconcile.Reconciler
63-
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
79+
func newReconciler(mgr manager.Manager, execer exec.IExec) reconcile.Reconciler {
6480
reconiler := &ReconcileDistributedRedisCluster{client: mgr.GetClient(), scheme: mgr.GetScheme()}
6581
reconiler.statefulSetController = k8sutil.NewStatefulSetController(reconiler.client)
6682
reconiler.serviceController = k8sutil.NewServiceController(reconiler.client)
@@ -69,6 +85,7 @@ func newReconciler(mgr manager.Manager) reconcile.Reconciler {
6985
reconiler.crController = k8sutil.NewCRControl(reconiler.client)
7086
reconiler.ensurer = clustermanger.NewEnsureResource(reconiler.client, log)
7187
reconiler.checker = clustermanger.NewCheck(reconiler.client)
88+
reconiler.execer = execer
7289
return reconiler
7390
}
7491

@@ -137,6 +154,7 @@ type ReconcileDistributedRedisCluster struct {
137154
scheme *runtime.Scheme
138155
ensurer clustermanger.IEnsureResource
139156
checker clustermanger.ICheck
157+
execer exec.IExec
140158
statefulSetController k8sutil.IStatefulSetControl
141159
serviceController k8sutil.IServiceControl
142160
pdbController k8sutil.IPodDisruptionBudgetControl

pkg/controller/distributedrediscluster/status.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ func SetClusterUpdating(status *redisv1alpha1.DistributedRedisClusterStatus, rea
3838
status.Reason = reason
3939
}
4040

41+
func SetClusterResetPassword(status *redisv1alpha1.DistributedRedisClusterStatus, reason string) {
42+
status.Status = redisv1alpha1.ClusterStatusResetPassword
43+
status.Reason = reason
44+
}
45+
4146
func buildClusterStatus(clusterInfos *redisutil.ClusterInfos, pods []*corev1.Pod,
4247
cluster *redisv1alpha1.DistributedRedisCluster, reqLogger logr.Logger) *redisv1alpha1.DistributedRedisClusterStatus {
4348
oldStatus := cluster.Status

pkg/controller/distributedrediscluster/sync_handler.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ func (r *ReconcileDistributedRedisCluster) resetClusterPassword(ctx *syncContext
326326
return nil
327327
}
328328

329+
SetClusterResetPassword(&ctx.cluster.Status, "updating cluster's password")
330+
r.crController.UpdateCRStatus(ctx.cluster)
331+
329332
matchLabels := getLabels(ctx.cluster)
330333
redisClusterPods, err := r.statefulSetController.GetStatefulSetPodsByLabels(namespace, matchLabels)
331334
if err != nil {
@@ -342,12 +345,21 @@ func (r *ReconcileDistributedRedisCluster) resetClusterPassword(ctx *syncContext
342345
return err
343346
}
344347

345-
admin, err := newRedisAdmin(clusterPods(redisClusterPods.Items), oldPassword, config.RedisConf(), ctx.reqLogger)
348+
podSet := clusterPods(redisClusterPods.Items)
349+
admin, err := newRedisAdmin(podSet, oldPassword, config.RedisConf(), ctx.reqLogger)
346350
if err != nil {
347351
return err
348352
}
349353
defer admin.Close()
350354

355+
// Update the password recorded in the file /etc/redis_password, redis pod preStop hook
356+
// need /etc/redis_password do CLUSTER FAILOVER
357+
cmd := fmt.Sprintf("echo %s > /etc/redis_password", newPassword)
358+
if err := r.execer.ExecCommandInPodSet(podSet, "/bin/sh", "-c", cmd); err != nil {
359+
return err
360+
}
361+
362+
// Reset all redis pod's password.
351363
if err := admin.ResetPassword(newPassword); err != nil {
352364
return err
353365
}

pkg/exec/exec.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package exec
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"net/url"
7+
"strings"
8+
9+
"github.com/go-logr/logr"
10+
corev1 "k8s.io/api/core/v1"
11+
"k8s.io/client-go/kubernetes/scheme"
12+
"k8s.io/client-go/rest"
13+
"k8s.io/client-go/tools/remotecommand"
14+
)
15+
16+
// IExec is an injectable interface for running remote exec commands.
17+
type IExec interface {
18+
// ExecCommandInPodSet exec cmd in pod set.
19+
ExecCommandInPodSet(podSet []*corev1.Pod, cmd ...string) error
20+
}
21+
22+
type remoteExec struct {
23+
restGVKClient rest.Interface
24+
logger logr.Logger
25+
config *rest.Config
26+
}
27+
28+
// NewRemoteExec returns a new IExec which will exec remote cmd.
29+
func NewRemoteExec(restGVKClient rest.Interface, config *rest.Config, logger logr.Logger) IExec {
30+
return &remoteExec{
31+
restGVKClient: restGVKClient,
32+
logger: logger,
33+
config: config,
34+
}
35+
}
36+
37+
// ExecOptions passed to ExecWithOptions.
38+
type ExecOptions struct {
39+
Command []string
40+
41+
Namespace string
42+
PodName string
43+
ContainerName string
44+
45+
Stdin io.Reader
46+
CaptureStdout bool
47+
CaptureStderr bool
48+
// If false, whitespace in std{err,out} will be removed.
49+
PreserveWhitespace bool
50+
}
51+
52+
// ExecCommandInPodSet implements IExec interface.
53+
func (e *remoteExec) ExecCommandInPodSet(podSet []*corev1.Pod, cmd ...string) error {
54+
for _, pod := range podSet {
55+
if _, err := e.ExecCommandInContainer(pod.Namespace, pod.Name, pod.Spec.Containers[0].Name, cmd...); err != nil {
56+
return err
57+
}
58+
}
59+
return nil
60+
}
61+
62+
// ExecCommandInContainer executes a command in the specified container.
63+
func (e *remoteExec) ExecCommandInContainer(namespace, podName, containerName string, cmd ...string) (string, error) {
64+
stdout, stderr, err := e.ExecCommandInContainerWithFullOutput(namespace, podName, containerName, cmd...)
65+
if stderr != "" {
66+
e.logger.Info("ExecCommand", "command", cmd, "stderr", stderr)
67+
}
68+
return stdout, err
69+
}
70+
71+
// ExecCommandInContainerWithFullOutput executes a command in the
72+
// specified container and return stdout, stderr and error
73+
func (e *remoteExec) ExecCommandInContainerWithFullOutput(namespace, podName, containerName string, cmd ...string) (string, string, error) {
74+
return e.ExecWithOptions(ExecOptions{
75+
Command: cmd,
76+
Namespace: namespace,
77+
PodName: podName,
78+
ContainerName: containerName,
79+
80+
Stdin: nil,
81+
CaptureStdout: true,
82+
CaptureStderr: true,
83+
PreserveWhitespace: false,
84+
})
85+
}
86+
87+
// ExecWithOptions executes a command in the specified container,
88+
// returning stdout, stderr and error. `options` allowed for
89+
// additional parameters to be passed.
90+
func (e *remoteExec) ExecWithOptions(options ExecOptions) (string, string, error) {
91+
const tty = false
92+
93+
req := e.restGVKClient.Post().
94+
Resource("pods").
95+
Name(options.PodName).
96+
Namespace(options.Namespace).
97+
SubResource("exec").
98+
Param("container", options.ContainerName)
99+
100+
req.VersionedParams(&corev1.PodExecOptions{
101+
Container: options.ContainerName,
102+
Command: options.Command,
103+
Stdin: options.Stdin != nil,
104+
Stdout: options.CaptureStdout,
105+
Stderr: options.CaptureStderr,
106+
TTY: tty,
107+
}, scheme.ParameterCodec)
108+
109+
var stdout, stderr bytes.Buffer
110+
err := execute("POST", req.URL(), e.config, options.Stdin, &stdout, &stderr, tty)
111+
112+
if options.PreserveWhitespace {
113+
return stdout.String(), stderr.String(), err
114+
}
115+
return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err
116+
}
117+
118+
func execute(method string, url *url.URL, config *rest.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error {
119+
exec, err := remotecommand.NewSPDYExecutor(config, method, url)
120+
if err != nil {
121+
return err
122+
}
123+
return exec.Stream(remotecommand.StreamOptions{
124+
Stdin: stdin,
125+
Stdout: stdout,
126+
Stderr: stderr,
127+
Tty: tty,
128+
})
129+
}

pkg/resources/configmaps/configmap.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,23 @@ func NewConfigMapForCR(cluster *redisv1alpha1.DistributedRedisCluster, labels ma
2424
shutdownContent := `#!/bin/sh
2525
CLUSTER_CONFIG="/data/nodes.conf"
2626
failover() {
27-
echo "Do CLUSTER FAILOVER"
28-
masterID=$(cat ${CLUSTER_CONFIG} | grep "myself" | awk '{print $1}')
29-
echo "Master: ${masterID}"
30-
slave=$(cat ${CLUSTER_CONFIG} | grep ${masterID} | grep "slave" | awk 'NR==1{print $2}' | sed 's/:6379@16379//')
31-
echo "Slave: ${slave}"
32-
if [[ -z "${REDIS_PASSWORD}" ]]; then
33-
redis-cli -h ${slave} CLUSTER FAILOVER
34-
else
35-
redis-cli -h ${slave} -a "${REDIS_PASSWORD}" CLUSTER FAILOVER
36-
fi
37-
echo "Wait for MASTER <-> SLAVE syncFinished"
38-
sleep 20
27+
echo "Do CLUSTER FAILOVER"
28+
masterID=$(cat ${CLUSTER_CONFIG} | grep "myself" | awk '{print $1}')
29+
echo "Master: ${masterID}"
30+
slave=$(cat ${CLUSTER_CONFIG} | grep ${masterID} | grep "slave" | awk 'NR==1{print $2}' | sed 's/:6379@16379//')
31+
echo "Slave: ${slave}"
32+
password=$(cat /etc/redis_password)
33+
if [[ -z "${password}" ]]; then
34+
redis-cli -h ${slave} CLUSTER FAILOVER
35+
else
36+
redis-cli -h ${slave} -a "${password}" CLUSTER FAILOVER
37+
fi
38+
echo "Wait for MASTER <-> SLAVE syncFinished"
39+
sleep 20
3940
}
4041
if [ -f ${CLUSTER_CONFIG} ]; then
41-
cat ${CLUSTER_CONFIG} | grep "myself" | grep "master" && \
42-
failover
42+
cat ${CLUSTER_CONFIG} | grep "myself" | grep "master" && \
43+
failover
4344
fi`
4445

4546
// Fixed Nodes.conf does not update IP address of a node when IP changes after restart,

pkg/resources/statefulsets/statefulset.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,11 @@ func redisServerContainer(cluster *redisv1alpha1.DistributedRedisCluster, passwo
258258
Resources: *cluster.Spec.Resources,
259259
// TODO store redis data when pod stop
260260
Lifecycle: &corev1.Lifecycle{
261+
PostStart: &corev1.Handler{
262+
Exec: &corev1.ExecAction{
263+
Command: []string{"/bin/sh", "-c", "echo ${REDIS_PASSWORD} > /etc/redis_password"},
264+
},
265+
},
261266
PreStop: &corev1.Handler{
262267
Exec: &corev1.ExecAction{
263268
Command: []string{"/bin/sh", "/conf/shutdown.sh"},

0 commit comments

Comments
 (0)