fix: quit minikube service when there is no available pods

pull/15079/head
Товарищ программист 2022-10-06 15:59:56 +08:00 committed by Steven Powell
parent 7489d959a8
commit 55868b1736
15 changed files with 107 additions and 0 deletions
cmd/minikube/cmd
pkg/minikube
reason
service
site/content/en/docs/contrib
test/integration

View File

@ -148,6 +148,10 @@ You may select another namespace by using 'minikube service {{.service}} -n <nam
out.String(fmt.Sprintf("%s\n", serviceURLs))
}
}
// check whether all pods of this service is crashed
if err := service.CheckServicePods(cname, svc.Name, namespace); err != nil {
exit.Error(reason.SvcUnreachable, "service not available", err)
}
}
if driver.NeedsPortForward(co.Config.Driver) && services != nil {

View File

@ -423,6 +423,8 @@ var (
SvcCheckTimeout = Kind{ID: "SVC_CHECK_TIMEOUT", ExitCode: ExSvcTimeout}
// minikube was unable to access a service
SvcTimeout = Kind{ID: "SVC_TIMEOUT", ExitCode: ExSvcTimeout}
// minikube finds that the service has not available pods
SvcUnreachable = Kind{ID: "SVC_UNREACHABLE", ExitCode: ExSvcNotFound}
// minikube failed to list services for the specified namespace
SvcList = Kind{ID: "SVC_LIST", ExitCode: ExSvcError}
// minikube failed to start a tunnel

View File

@ -373,3 +373,36 @@ func DeleteSecret(cname string, namespace, name string) error {
return nil
}
// check whether there are running pods for a service
func CheckServicePods(cname, svcName, namespace string) error {
clientset, err := K8s.GetCoreClient(cname)
if err != nil {
return errors.Wrap(err, "failed to get k8s client")
}
svc, err := clientset.Services(namespace).Get(context.Background(), svcName, meta.GetOptions{})
if err != nil {
return errors.Wrap(err, "Get service")
}
// There are four types of service in k8s: NodePort, ClusterIp, LoadBalancer and ExternalName
// However, NodePort means that this service will not be exposed outside the cluster
// while ExternalName means that this service is not provided by this k8s cluster
// So we only check when service type is NodePort or LoadBalancer
if svc.Spec.Type != core.ServiceTypeNodePort && svc.Spec.Type != core.ServiceTypeLoadBalancer {
return nil
}
pods, err := clientset.Pods(namespace).List(context.Background(), meta.ListOptions{
LabelSelector: labels.Set(svc.Spec.Selector).AsSelector().String(),
})
if err != nil {
return errors.Wrap(err, "List Pods")
}
for _, pod := range pods.Items {
if pod.Status.Phase == core.PodRunning {
return nil
}
}
return fmt.Errorf("no running pod for service %s found", svcName)
}

View File

@ -697,6 +697,9 @@ verifies that minikube pause works
## TestInsufficientStorage
makes sure minikube status displays the correct info if there is insufficient disk space on the machine
## TestInvalidService
makes sure minikube will not start a tunnel for a unavailable service who has no running pods
## TestRunningBinaryUpgrade
upgrades a running legacy cluster to minikube at HEAD

View File

@ -106,6 +106,7 @@ func TestFunctional(t *testing.T) {
{"ComponentHealth", validateComponentHealth},
{"LogsCmd", validateLogsCmd},
{"LogsFileCmd", validateLogsFileCmd},
{"InvalidService", validateInvalidService},
}
for _, tc := range tests {
tc := tc
@ -2308,3 +2309,27 @@ func validateLicenseCmd(ctx context.Context, t *testing.T, _ string) {
t.Errorf("expected license file to contain %q, but was not found", expectedString)
}
}
// validateInvalidService makes sure minikube will not start a tunnel for an unavailable service that has no running pods
func validateInvalidService(ctx context.Context, t *testing.T, profile string) {
// try to start an invalid service. This service is linked to a pod whose image name is invalid, so this pod will never become running
rrApply, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "apply", "-f", filepath.Join(*testdataDir, "invalidsvc.yaml")))
defer func() {
// Cleanup test configurations in advance of future tests
rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "delete", "-f", filepath.Join(*testdataDir, "invalidsvc.yaml")))
if err != nil {
t.Fatalf("clean up %s failed: %v", rr.Command(), err)
}
}()
if err != nil {
t.Fatalf("%s failed: %v", rrApply.Command(), err)
}
time.Sleep(3 * time.Second)
// try to expose a service, this action is supposed to fail
rrService, err := Run(t, exec.CommandContext(context.TODO(), Target(), "service", "invalid-svc", "-p", profile))
if err == nil || rrService.ExitCode == 0 {
t.Fatalf("%s should have failed: ", rrService.Command())
}
}

View File

@ -0,0 +1,31 @@
apiVersion: v1
kind: Pod
metadata:
labels:
run: invalid-svc
name: invalid-svc
namespace: default
spec:
containers:
- name: nginx
image: nonexistingimage:latest
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
labels:
run: invalid-svc
name: invalid-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: invalid-svc
sessionAffinity: None
type: NodePort

View File

@ -953,6 +953,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "dry-run Modus. Validiert die Konfiguration, aber ändert den System Zustand nicht",
"dry-run validation complete!": "dry-run Validierung komplett!",
"enable failed": "aktivieren fehlgeschlagen",
"error checking service": "",
"error creating clientset": "Fehler beim Anlegen des Clientsets",
"error creating urls": "",
"error getting defaults: {{.error}}": "",

View File

@ -951,6 +951,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",

View File

@ -934,6 +934,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "mode simulation. Valide la configuration, mais ne modifie pas l'état du système",
"dry-run validation complete!": "validation de la simulation terminée !",
"enable failed": "échec de l'activation",
"error checking service": "",
"error creating clientset": "erreur lors de la création de l'ensemble de clients",
"error creating urls": "erreur lors de la création d'urls",
"error getting defaults: {{.error}}": "erreur lors de l'obtention des valeurs par défaut : {{.error}}",

View File

@ -893,6 +893,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "dry-run モード。設定は検証しますが、システムの状態は変更しません",
"dry-run validation complete!": "dry-run の検証が終了しました!",
"enable failed": "有効化に失敗しました",
"error checking service": "",
"error creating clientset": "clientset 作成中にエラー",
"error creating urls": "URL 作成でエラー",
"error getting defaults: {{.error}}": "デフォルト取得中にエラー: {{.error}}",

View File

@ -953,6 +953,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "dry-run 검증 완료!",
"enable failed": "활성화가 실패하였습니다",
"error checking service": "",
"error creating clientset": "clientset 생성 오류",
"error creating machine client": "머신 client 생성 오류",
"error creating urls": "",

View File

@ -963,6 +963,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",

View File

@ -883,6 +883,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",

View File

@ -883,6 +883,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",

View File

@ -1071,6 +1071,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "开启失败",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",