@@ -17,6 +17,7 @@ limitations under the License.
1717package kube
1818
1919import (
20+ "bytes"
2021 "context"
2122 "fmt"
2223 "strconv"
@@ -29,6 +30,10 @@ import (
2930 corev1 "k8s.io/api/core/v1"
3031 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3132 "k8s.io/apimachinery/pkg/types"
33+ "k8s.io/client-go/kubernetes"
34+ "k8s.io/client-go/kubernetes/scheme"
35+ "k8s.io/client-go/rest"
36+ "k8s.io/client-go/tools/remotecommand"
3237 ctrl "sigs.k8s.io/controller-runtime"
3338 "sigs.k8s.io/controller-runtime/pkg/client"
3439 ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -153,6 +158,72 @@ func RollingUpdate(ctx context.Context, cl client.Client, stsName, namespace str
153158 return nil
154159}
155160
161+ // SighupSignalToPods sends SIGHUP signal to all the pods in the statefulset.
162+ func SighupSignalToPods (ctx context.Context , config * rest.Config , cl client.Client , stsName , namespace string ) error {
163+
164+ clientset , err := kubernetes .NewForConfig (config )
165+ if err != nil {
166+ return err
167+ }
168+
169+ var sts v1.StatefulSet
170+ if err := cl .Get (ctx , types.NamespacedName {Namespace : namespace , Name : stsName }, & sts ); err != nil {
171+ return err
172+ }
173+
174+ containerName := sts .Spec .Template .Spec .Containers [0 ].Name
175+ command := []string {"/bin/bash" , "-c" , "echo 'Send SIGHUP to cockroach'; kill -s 1 $(ls -l /proc/*/exe | grep cockroach | awk '{print $2}')" }
176+ for i := int32 (0 ); i < sts .Status .Replicas ; i ++ {
177+ replicaName := stsName + "-" + strconv .Itoa (int (i ))
178+
179+ stdout , stderr , err := execCommandInPod (clientset , config , namespace , replicaName , containerName , command )
180+ if err != nil {
181+ logrus .Errorf ("Failed to send SIGHUP signal to pod [%s], error: %v, stdout: %s, stderr: %s" , replicaName , err , stdout , stderr )
182+ }
183+ logrus .Info (stdout )
184+
185+ // Sleeping for 1 second to allow the pod to receive the signal
186+ time .Sleep (1 * time .Second )
187+ }
188+
189+ return nil
190+ }
191+
192+ // execCommandInPod executes the provided command in the given pod and returns the stdout and stderr.
193+ func execCommandInPod (clientset * kubernetes.Clientset , config * rest.Config , namespace , podName , containerName string , command []string ) (string , string , error ) {
194+ logrus .Infof ("Running command %s in pod %s in container %s" , command , podName , containerName )
195+
196+ req := clientset .CoreV1 ().RESTClient ().Post ().
197+ Resource ("pods" ).
198+ Name (podName ).
199+ Namespace (namespace ).
200+ SubResource ("exec" ).
201+ Param ("container" , containerName ).
202+ VersionedParams (& corev1.PodExecOptions {
203+ Command : command ,
204+ Stdin : false ,
205+ Stdout : true ,
206+ Stderr : true ,
207+ TTY : true ,
208+ }, scheme .ParameterCodec )
209+
210+ exec , err := remotecommand .NewSPDYExecutor (config , "POST" , req .URL ())
211+ if err != nil {
212+ return "" , "" , err
213+ }
214+
215+ var stdout , stderr bytes.Buffer
216+ err = exec .Stream (remotecommand.StreamOptions {
217+ Stdout : & stdout ,
218+ Stderr : & stderr ,
219+ })
220+ if err != nil {
221+ return stdout .String (), stderr .String (), err
222+ }
223+
224+ return stdout .String (), stderr .String (), nil
225+ }
226+
156227func WaitForPodReady (ctx context.Context , cl client.Client , name , namespace string , podUpdateTimeout ,
157228 podMaxPollingInterval time.Duration ) error {
158229 f := func () error {
0 commit comments