Skip to content

Instantly share code, notes, and snippets.

@gaorong
Created September 3, 2019 15:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gaorong/60e84a7534546f56431b9edc46727ffb to your computer and use it in GitHub Desktop.
Save gaorong/60e84a7534546f56431b9edc46727ffb to your computer and use it in GitHub Desktop.
this snippet is in order to reproduce kubelet's bug
package main
import (
"flag"
"os"
"time"
"github.com/golang/glog"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
)
const (
defaultResyncPeriod = 2 * time.Hour
)
var (
apiserverHost = flag.String("apiserver", "", "The address of the Kubernetes Apiserver ")
kubeconfig = flag.String("kubeconfig", "", "(optional) absolute path to the kubeconfig file")
)
func main() {
flag.Set("logtostderr", "true")
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags(*apiserverHost, *kubeconfig)
if err != nil {
glog.Exit("Error building kubeconfig: %v", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
glog.Exit("Error building kubernetes clientset: %v", err)
}
glog.Infof("start watching apiserver")
informerFactory := informers.NewSharedInformerFactory(clientset, defaultResyncPeriod)
podInformer := informerFactory.Core().V1().Pods()
stop := make(chan struct{})
go informerFactory.Start(stop)
informerFactory.WaitForCacheSync(stop)
glog.Infof("informer cache sync done")
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(i interface{}) {
pod, _ := i.(*v1.Pod)
glog.Infof("add func: %s/%s %s", pod.Namespace, pod.Name, pod.UID)
},
DeleteFunc: func(i interface{}) {
pod, _ := i.(*v1.Pod)
if pod.Status.PodIP == "" {
glog.Infof("~~~~~~~~~delete: get an empty IP: %s/%s %s ~~~~~~", pod.Namespace, pod.Name, pod.UID)
os.Exit(-1)
}
},
})
// pod create-wait-delete cycle
go func() {
timer := time.NewTicker(time.Second)
defer timer.Stop()
for range timer.C {
defaultPod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
Labels: map[string]string{
"app": "test",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "main",
Image: "busybox",
ImagePullPolicy: v1.PullNever,
},
},
},
}
for {
_, err = clientset.CoreV1().Pods("default").Create(defaultPod)
if err != nil {
glog.Infof("create pod failed: %v", err)
} else if err == nil {
break
}
time.Sleep(time.Second)
}
glog.Infof("create pod successfully")
pod := &v1.Pod{}
for {
pod, err = clientset.CoreV1().Pods("default").Get("test", metav1.GetOptions{})
if err != nil {
glog.Errorf("Failed to delete pod %s/%s: %v", pod.Namespace, pod.Name, err)
return
}
if pod.Status.Phase == v1.PodRunning {
break
}
time.Sleep(time.Second)
}
glog.Infof("pod running successfully")
for {
deleteOptions := metav1.DeleteOptions{}
// Use the pod UID as the precondition for deletion to prevent deleting a newly created pod with the same name and namespace.
deleteOptions.Preconditions = metav1.NewUIDPreconditions(string(pod.UID))
err = clientset.CoreV1().Pods(pod.Namespace).Delete(pod.Name, &deleteOptions)
if err != nil {
glog.Errorf("Failed to delete pod %s/%s: %v", pod.Namespace, pod.Name, err)
return
} else if err == nil {
break
}
}
for {
_, err = clientset.CoreV1().Pods("default").Get("test", metav1.GetOptions{})
if err != nil {
break
}
time.Sleep(time.Second)
}
glog.Infof("pod delete successfully")
}
}()
select {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment