mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Merge pull request #47081 from luxas/kubeadm_postinst_idempotency
Automatic merge from submit-queue (batch tested with PRs 47024, 47050, 47086, 47081, 47013) kubeadm: Make the creation of the RBAC rules phase idempotent **What this PR does / why we need it**: Bugfix: Currently kubeadm fails with a non-zero code if resources it's trying to create already exist. This PR fixes that by making kubeadm try to Update resources that already exist. After this PR, https://github.com/kubernetes/kubernetes/pull/46879 and a beta.1 release, kubeadm will be fully upgradeable from v1.6 to v1.7 using only kubeadm init. Last piece of https://github.com/kubernetes/kubeadm/issues/288 **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # Fixes: https://github.com/kubernetes/kubeadm/issues/288 **Special notes for your reviewer**: **Release note**: ```release-note kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ``` @pipejakob @mikedanese @timothysc
This commit is contained in:
commit
7e0c9e7919
@ -21,6 +21,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/images:go_default_library",
|
"//cmd/kubeadm/app/images:go_default_library",
|
||||||
"//cmd/kubeadm/app/util:go_default_library",
|
"//cmd/kubeadm/app/util:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
|
@ -19,9 +19,9 @@ package addons
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
@ -80,13 +80,13 @@ func CreateEssentialAddons(cfg *kubeadmapi.MasterConfiguration, client *clientse
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("[addons] Created essential addon: kube-proxy")
|
fmt.Println("[addons] Applied essential addon: kube-proxy")
|
||||||
|
|
||||||
err = CreateKubeDNSAddon(dnsDeploymentBytes, dnsServiceBytes, client)
|
err = CreateKubeDNSAddon(dnsDeploymentBytes, dnsServiceBytes, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("[addons] Created essential addon: kube-dns")
|
fmt.Println("[addons] Applied essential addon: kube-dns")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,13 @@ func CreateKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client *clients
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(kubeproxyConfigMap); err != nil {
|
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(kubeproxyConfigMap); err != nil {
|
||||||
return fmt.Errorf("unable to create a new kube-proxy configmap: %v", err)
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create a new kube-proxy configmap: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Update(kubeproxyConfigMap); err != nil {
|
||||||
|
return fmt.Errorf("unable to update the kube-proxy configmap: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeproxyDaemonSet := &extensions.DaemonSet{}
|
kubeproxyDaemonSet := &extensions.DaemonSet{}
|
||||||
@ -107,7 +113,13 @@ func CreateKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client *clients
|
|||||||
kubeproxyDaemonSet.Spec.Template.Spec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration}
|
kubeproxyDaemonSet.Spec.Template.Spec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration}
|
||||||
|
|
||||||
if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Create(kubeproxyDaemonSet); err != nil {
|
if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Create(kubeproxyDaemonSet); err != nil {
|
||||||
return fmt.Errorf("unable to create a new kube-proxy daemonset: %v", err)
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create a new kube-proxy daemonset: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Update(kubeproxyDaemonSet); err != nil {
|
||||||
|
return fmt.Errorf("unable to update the kube-proxy daemonset: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -125,9 +137,14 @@ func CreateKubeDNSAddon(deploymentBytes, serviceBytes []byte, client *clientset.
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: All these .Create(foo) calls should instead be more like "kubectl apply -f" commands; they should not fail if there are existing objects with the same name
|
|
||||||
if _, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Create(kubednsDeployment); err != nil {
|
if _, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Create(kubednsDeployment); err != nil {
|
||||||
return fmt.Errorf("unable to create a new kube-dns deployment: %v", err)
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create a new kube-dns deployment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Update(kubednsDeployment); err != nil {
|
||||||
|
return fmt.Errorf("unable to update the kube-dns deployment: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kubednsService := &v1.Service{}
|
kubednsService := &v1.Service{}
|
||||||
@ -136,7 +153,16 @@ func CreateKubeDNSAddon(deploymentBytes, serviceBytes []byte, client *clientset.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := client.CoreV1().Services(metav1.NamespaceSystem).Create(kubednsService); err != nil {
|
if _, err := client.CoreV1().Services(metav1.NamespaceSystem).Create(kubednsService); err != nil {
|
||||||
return fmt.Errorf("unable to create a new kube-dns service: %v", err)
|
// Ignore if the Service is invalid with this error message:
|
||||||
|
// Service "kube-dns" is invalid: spec.clusterIP: Invalid value: "10.96.0.10": provided IP is already allocated
|
||||||
|
|
||||||
|
if !apierrors.IsAlreadyExists(err) && !apierrors.IsInvalid(err) {
|
||||||
|
return fmt.Errorf("unable to create a new kube-dns service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.CoreV1().Services(metav1.NamespaceSystem).Update(kubednsService); err != nil {
|
||||||
|
return fmt.Errorf("unable to create/update the kube-dns service: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -271,6 +271,9 @@ metadata:
|
|||||||
kubernetes.io/name: "KubeDNS"
|
kubernetes.io/name: "KubeDNS"
|
||||||
name: kube-dns
|
name: kube-dns
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
|
# Without this resourceVersion value, an update of the Service between versions will yield:
|
||||||
|
# Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update
|
||||||
|
resourceVersion: "0"
|
||||||
spec:
|
spec:
|
||||||
clusterIP: {{ .DNSIP }}
|
clusterIP: {{ .DNSIP }}
|
||||||
ports:
|
ports:
|
||||||
|
@ -105,8 +105,14 @@ func createRoles(clientset *clientset.Clientset) error {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, role := range roles {
|
for _, role := range roles {
|
||||||
if _, err := clientset.RbacV1beta1().Roles(metav1.NamespacePublic).Create(&role); err != nil {
|
if _, err := clientset.RbacV1beta1().Roles(role.ObjectMeta.Namespace).Create(&role); err != nil {
|
||||||
return err
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create RBAC role: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := clientset.RbacV1beta1().Roles(role.ObjectMeta.Namespace).Update(&role); err != nil {
|
||||||
|
return fmt.Errorf("unable to update RBAC role: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -134,8 +140,14 @@ func createRoleBindings(clientset *clientset.Clientset) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, roleBinding := range roleBindings {
|
for _, roleBinding := range roleBindings {
|
||||||
if _, err := clientset.RbacV1beta1().RoleBindings(metav1.NamespacePublic).Create(&roleBinding); err != nil {
|
if _, err := clientset.RbacV1beta1().RoleBindings(roleBinding.ObjectMeta.Namespace).Create(&roleBinding); err != nil {
|
||||||
return err
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create RBAC rolebinding: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := clientset.RbacV1beta1().RoleBindings(roleBinding.ObjectMeta.Namespace).Update(&roleBinding); err != nil {
|
||||||
|
return fmt.Errorf("unable to update RBAC rolebinding: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -155,7 +167,13 @@ func createClusterRoles(clientset *clientset.Clientset) error {
|
|||||||
|
|
||||||
for _, roleBinding := range clusterRoles {
|
for _, roleBinding := range clusterRoles {
|
||||||
if _, err := clientset.RbacV1beta1().ClusterRoles().Create(&roleBinding); err != nil {
|
if _, err := clientset.RbacV1beta1().ClusterRoles().Create(&roleBinding); err != nil {
|
||||||
return err
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create RBAC clusterrole: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := clientset.RbacV1beta1().ClusterRoles().Update(&roleBinding); err != nil {
|
||||||
|
return fmt.Errorf("unable to update RBAC clusterrole: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -216,7 +234,13 @@ func createClusterRoleBindings(clientset *clientset.Clientset) error {
|
|||||||
|
|
||||||
for _, clusterRoleBinding := range clusterRoleBindings {
|
for _, clusterRoleBinding := range clusterRoleBindings {
|
||||||
if _, err := clientset.RbacV1beta1().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
|
if _, err := clientset.RbacV1beta1().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
|
||||||
return err
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("unable to create RBAC clusterrolebinding: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := clientset.RbacV1beta1().ClusterRoleBindings().Update(&clusterRoleBinding); err != nil {
|
||||||
|
return fmt.Errorf("unable to update RBAC clusterrolebinding: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user