diff --git a/cluster/validation.go b/cluster/validation.go index 2c8705d4..0bb4d80b 100644 --- a/cluster/validation.go +++ b/cluster/validation.go @@ -6,6 +6,8 @@ import ( "fmt" "strings" + "github.com/rancher/rke/k8s" + "github.com/blang/semver" "github.com/rancher/rke/log" "github.com/rancher/rke/metadata" @@ -674,6 +676,30 @@ func validatePodSecurityPolicy(c *Cluster) error { return errors.New("PodSecurityPolicy has been removed and can not be enabled since k8s v1.25") } } + // check if there is any PSP resource when upgrading a cluster to k8s v1.25 and above + if parsedRangeAtLeast125(parsedVersion) { + kubeClient, err := k8s.NewClient(c.LocalKubeConfigPath, c.K8sWrapTransport) + if err != nil { + // we can not tell this is invoked when creating a new cluster or updating an existing one, so skip this check + logrus.Warnf("Skip the check for PSP resource due to the failire of initializing the kubernetes client") + return nil + } + pspList, _ := k8s.GetPSPList(kubeClient) + // ignore the error because the "no such resource type" error is definitely returned in k8s v1.25 and above + items := pspList.Items + if len(items) == 0 { + return nil + } + // a PSP "psp.flannel.unprivileged" from old Flannel templates is created when using Flannel as the network plugin + // we should ignore it if it is the only one PSP in the cluster + if len(items) == 1 && items[0].Name == "psp.flannel.unprivileged" && c.Network.Plugin == FlannelNetworkPlugin { + return nil + } + msg := fmt.Sprintf("PodSecurityPolicy(PSP) resource is detected in the cluster, "+ + "please remove them before upgrading the cluster version to %s", c.Version) + return errors.New(msg) + } + return nil } diff --git a/k8s/psp.go b/k8s/psp.go index 64afd643..444beacf 100644 --- a/k8s/psp.go +++ b/k8s/psp.go @@ -30,3 +30,9 @@ func updatePodSecurityPolicy(k8sClient *kubernetes.Clientset, p interface{}) err return nil } + +// GetPSPList returns the PodSecurityPolicyList containing all PSPs in the cluster and an error. +// The list could be empty if there is no PSP in the cluster. +func GetPSPList(k8sClient *kubernetes.Clientset) (*v1beta1.PodSecurityPolicyList, error) { + return k8sClient.PolicyV1beta1().PodSecurityPolicies().List(context.TODO(), metav1.ListOptions{}) +}