Change:
When you setup TLS assets, you need to make sure each master API server is using the same ones, unless you were running a single master. But this is a super common mistake, and it often breaks things. Because the masters validating tokens using that key, the controller-manager also has this service-account key, and it’s responsible for creating tokens for service accounts. So, depending on which apiserver the pod is talking to, that service-account token may, or may not work. This most commonly surfaces in kube2sky (the dns addon). Result: Tokens are invalidated regularly (~10 minutes) Expected: Warning about system having different certs (or some alert). Would this ever be a valid configuration?
Is this specifically for an HA setup (since you mention multiple apiservers)? Or do you mean that each master component should have the same cert?
Correct - it's the HA deployment.
I don't think that the apiservers should necessarily cross-check each other (and all other system components like the controller manager) and alert. If you are running an HA deployment, you should have something else making sure that your deployment is correct. On cluster creation, the startup scripts should do it.
I guess what I'm saying is that we know this is going to be a problem. There's almost no way to make this NOT a problem, yet it is a very easy bug to get into. So... with that in mind, what's the path for doing this? When you add a second master to your HA config, how does it establish trust with the first HA? Could we check at that point?
Yup, we do this on provision time with Ansible.

Discussion:
//	// Before this function is called, currentObj has been reset to etcd's current //	// contents for "myKey". // <del> //	cur := input.(*MyType) // Gauranteed to work. </del> <ins> //	cur := input.(*MyType) // Guaranteed to work. </ins> // //	// Make a *modification*. //	cur.Counter++

return err } <ins> if string(data) == origBody { return nil } </ins> _, err = h.Client.CompareAndSwap(key, string(data), 0, origBody, index) if IsEtcdTestFailed(err) { continue

package tools import ( <ins> "errors" </ins> "fmt" "reflect" "sync"

} } <ins> func TestAtomicUpdateNoChange(t *testing.T) { fakeClient := MakeFakeEtcdClient(t) fakeClient.TestIndex = true helper := EtcdHelper{fakeClient, scheme, api.NewJSONBaseResourceVersioner()} // Create a new node. fakeClient.ExpectNotFoundGet("/some/key") obj := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 1} err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) { return obj, nil }) if err != nil { t.Errorf("Unexpected error %#v", err) } // Update an existing node with the same data callbackCalled := false objUpdate := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 1} fakeClient.Err = errors.New("should not be called") err = helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) { callbackCalled = true return objUpdate, nil }) if err != nil { t.Errorf("Unexpected error %#v", err) } if !callbackCalled { t.Errorf("tryUpdate callback should have been called.") } } </ins> func TestAtomicUpdate_CreateCollision(t *testing.T) { fakeClient := MakeFakeEtcdClient(t) fakeClient.TestIndex = true