Issue 1:
Hello!

I thought I'd open an issue, as I am currently working on this and hope to have a commit ready by the end of the day.

"kube-up" with AWS ought to build out a highly available and multi-AZ kubernetes cluster following AWS EC2 best practices. There are two large steps to this:

Multi-AZ minions

Highly available / Multi-AZ master

I am only focusing on goal #1 here. These changes center entirely in cluster/aws/util.sh. However, I will need to modify the actual provider code in Go because, while AWS ELBs are brought up with the proper subnets, it appears they do not have multi-availability zone routing enabled.

I am leaving the security groups in place and creating a secondary subnet and secondary autoscaling group. NUM_MINIONS is now split into NUM_MINIONS_PRIMARY_ZONE and NUM_MINIONS_SECONDARY_ZONE. The default AWS_REGION of "us-east-1" is supplemented by AWS_ZONE_PRIMARY of "a" and AWS_ZONE_SECONDARY of "c" (us-east-1 has no "b"...)

I wanted to pop this issue to collect thoughts from AWS users. If anyone is already doing multi-AZ kubernetes cluster, please let me know if you have run into any edge cases! I will issue a PR for this very shortly.

Thanks!

Issue 2:
With the introduction of the experimental api prefix, we introduce large amounts of duplicate code for our autogenerated conversions and deep-copy functions. This increases the size of our binaries, and is not elegant. For simplicity, I will only talk about deep-copies, but everything that follows should also apply to conversions. I propose that we eliminate the duplicates as follows:

We remove all autogenerated deep-copy functions from the source tree whenever we generate new deep-copy functions (or use a build tag to hide them from the go compiler)

We check whether the Scheme has a deep-copy function for the target type already registered, if not, we generate a deep-copy function

Whenever we a see that a deep-copy function has already been generated, we do the copy by calling into the conversion.Cloner

(In the case of handwritten conversions, we will need to make them switch to using the conversion.Scope instead of calling autogenerated functions directly).

Assuming that we create the deep-copy functions in the order following the import dependency tree, we should not have any duplicate deep-copy functions. However, this approach brings with it some overhead.

For both cleaning up our deep-copy functions and increasing performance in the face of this overhead, I propose we take the following steps:

Profile the apiserver to measure what time is spent doing deep-copies

Create some microbenchmarks to use as a baseline (initial work can be found here)

Create a new method DeepCopyTo and pass pointers to avoid needless copies

Switch to exception handling within the deep-copies (elaborated below)

Change autogenerated functions to use generic signatures instead of per-type ones i.e. instead of f(a, b *T) error, we have f(a, b interface{}) and use type assertions. This lets us reduce the amount of reflection that we use in exchange for boxing

In Go, exception handling is typically discouraged, but it is completely reasonable to use it so long as it doesn't cross an API boundary. For example, here it is used within the standard library. When we see an error during a copy, the copy operation cannot recover. This is the prime use-case for exception handling. We can similarly catch errors within Scheme.DeepCopy, and instead of doing explicit error checking all over the place, simply panic and convert it into an error in DeepCopy. We can also create a new function, MustDeepCopy, which does not catch the error for use within the deep-copy functions.

@wojtek-t @nikhiljindal