Skip to content

Commit

Permalink
Merge pull request #47081 from luxas/kubeadm_postinst_idempotency
Browse files Browse the repository at this point in the history
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, #46879 and a beta.1 release, kubeadm will be fully upgradeable from v1.6 to v1.7 using only kubeadm init.

Last piece of kubernetes/kubeadm#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: kubernetes/kubeadm#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
  • Loading branch information
Kubernetes Submit Queue authored Jun 7, 2017
2 parents 20bf5f2 + 1b93a6a commit 7e0c9e7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 14 deletions.
1 change: 1 addition & 0 deletions cmd/kubeadm/app/phases/addons/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ go_library(
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/util: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/runtime:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
Expand Down
42 changes: 34 additions & 8 deletions cmd/kubeadm/app/phases/addons/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ package addons
import (
"fmt"
"net"

"runtime"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kuberuntime "k8s.io/apimachinery/pkg/runtime"
clientset "k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -80,13 +80,13 @@ func CreateEssentialAddons(cfg *kubeadmapi.MasterConfiguration, client *clientse
if err != nil {
return err
}
fmt.Println("[addons] Created essential addon: kube-proxy")
fmt.Println("[addons] Applied essential addon: kube-proxy")

err = CreateKubeDNSAddon(dnsDeploymentBytes, dnsServiceBytes, client)
if err != nil {
return err
}
fmt.Println("[addons] Created essential addon: kube-dns")
fmt.Println("[addons] Applied essential addon: kube-dns")
return nil
}

Expand All @@ -97,7 +97,13 @@ func CreateKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client *clients
}

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{}
Expand All @@ -107,7 +113,13 @@ func CreateKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client *clients
kubeproxyDaemonSet.Spec.Template.Spec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration}

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
}
Expand All @@ -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 {
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{}
Expand All @@ -136,7 +153,16 @@ func CreateKubeDNSAddon(deploymentBytes, serviceBytes []byte, client *clientset.
}

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
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/kubeadm/app/phases/addons/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ metadata:
kubernetes.io/name: "KubeDNS"
name: kube-dns
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:
clusterIP: {{ .DNSIP }}
ports:
Expand Down
36 changes: 30 additions & 6 deletions cmd/kubeadm/app/phases/apiconfig/clusterroles.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,14 @@ func createRoles(clientset *clientset.Clientset) error {
},
}
for _, role := range roles {
if _, err := clientset.RbacV1beta1().Roles(metav1.NamespacePublic).Create(&role); err != nil {
return err
if _, err := clientset.RbacV1beta1().Roles(role.ObjectMeta.Namespace).Create(&role); err != nil {
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
Expand Down Expand Up @@ -134,8 +140,14 @@ func createRoleBindings(clientset *clientset.Clientset) error {
}

for _, roleBinding := range roleBindings {
if _, err := clientset.RbacV1beta1().RoleBindings(metav1.NamespacePublic).Create(&roleBinding); err != nil {
return err
if _, err := clientset.RbacV1beta1().RoleBindings(roleBinding.ObjectMeta.Namespace).Create(&roleBinding); err != nil {
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
Expand All @@ -155,7 +167,13 @@ func createClusterRoles(clientset *clientset.Clientset) error {

for _, roleBinding := range clusterRoles {
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
Expand Down Expand Up @@ -216,7 +234,13 @@ func createClusterRoleBindings(clientset *clientset.Clientset) error {

for _, clusterRoleBinding := range clusterRoleBindings {
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
Expand Down

0 comments on commit 7e0c9e7

Please sign in to comment.