mirror of https://github.com/k3s-io/k3s
Merge pull request #48480 from liggitt/namespace-reconcile
Automatic merge from submit-queue (batch tested with PRs 48480, 48353) Ensure namespace exists as part of RBAC reconciliation reconciliation can race with the controller that creates the namespaces containing the bootstrap roles. if it loses, it gets a NotFound error trying to create the namespaced role/rolebinding. Fixes https://github.com/kubernetes/kubeadm/issues/335 ```release-note RBAC role and role-binding reconciliation now ensures namespaces exist when reconciling on startup. ```pull/6/head
commit
b12314e246
|
@ -37,6 +37,7 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
|
|
|
@ -17,8 +17,11 @@ limitations under the License.
|
|||
package reconciliation
|
||||
|
||||
import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
|
@ -59,7 +62,8 @@ func (o RoleRuleOwner) SetRules(in []rbac.PolicyRule) {
|
|||
}
|
||||
|
||||
type RoleModifier struct {
|
||||
Client internalversion.RolesGetter
|
||||
Client internalversion.RolesGetter
|
||||
NamespaceClient core.NamespaceInterface
|
||||
}
|
||||
|
||||
func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||
|
@ -71,6 +75,11 @@ func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
|||
}
|
||||
|
||||
func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
||||
ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
||||
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, err := c.Client.Roles(in.GetNamespace()).Create(in.(RoleRuleOwner).Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -17,9 +17,12 @@ limitations under the License.
|
|||
package reconciliation
|
||||
|
||||
import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
|
@ -68,7 +71,8 @@ func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) {
|
|||
}
|
||||
|
||||
type RoleBindingClientAdapter struct {
|
||||
Client internalversion.RoleBindingsGetter
|
||||
Client internalversion.RoleBindingsGetter
|
||||
NamespaceClient core.NamespaceInterface
|
||||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
||||
|
@ -80,6 +84,11 @@ func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, erro
|
|||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) {
|
||||
ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
||||
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, err := c.Client.RoleBindings(in.GetNamespace()).Create(in.(RoleBindingAdapter).RoleBinding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -14,6 +14,7 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
||||
"//pkg/client/retry:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrole:go_default_library",
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/retry"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
||||
|
@ -134,6 +135,13 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
// intializing roles is really important. On some e2e runs, we've seen cases where etcd is down when the server
|
||||
// starts, the roles don't initialize, and nothing works.
|
||||
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
|
||||
|
||||
coreclientset, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
||||
|
@ -212,7 +220,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
for _, role := range roles {
|
||||
opts := reconciliation.ReconcileRoleOptions{
|
||||
Role: reconciliation.RoleRuleOwner{Role: &role},
|
||||
Client: reconciliation.RoleModifier{Client: clientset},
|
||||
Client: reconciliation.RoleModifier{Client: clientset, NamespaceClient: coreclientset.Namespaces()},
|
||||
Confirm: true,
|
||||
}
|
||||
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
|
@ -242,7 +250,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
for _, roleBinding := range roleBindings {
|
||||
opts := reconciliation.ReconcileRoleBindingOptions{
|
||||
RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: &roleBinding},
|
||||
Client: reconciliation.RoleBindingClientAdapter{Client: clientset},
|
||||
Client: reconciliation.RoleBindingClientAdapter{Client: clientset, NamespaceClient: coreclientset.Namespaces()},
|
||||
Confirm: true,
|
||||
}
|
||||
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
|
|
Loading…
Reference in New Issue