Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Initial kubeadm api proposal #100

Closed
wants to merge 5 commits into from

Conversation

luxas
Copy link
Member

@luxas luxas commented Jan 2, 2017

This is far from done, but posting progress on my work on the kubeadm API here.

This is kind of a kubeadm-to-beta design doc which we have to discuss in detail.
I'll improve it as we go.

cc @jbeda @mikedanese @dgoodwin @errordeveloper @lukemarsden @dgoodwin @kad @roberthbailey


First, certificates should be created in a directory.
There should be:
- a CA certificate (`ca.pem`) with its private key (`ca-key.pem`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should try to name these ca.key and ca.crt. While they are pem encoded, these are the more common names for this type of file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, updated the proposal and will update the code as well

First, certificates should be created in a directory.
There should be:
- a CA certificate (`ca.pem`) with its private key (`ca-key.pem`)
- Is the public key necessary to have here (`ca-pub.pem`)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ca.crt contains the public key.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was what I thought. I just couldn't understand why we had both ca.pem and ca-pub.pem, I'm gonna remove the public key only one because it's unnecessary

- a CA certificate (`ca.pem`) with its private key (`ca-key.pem`)
- Is the public key necessary to have here (`ca-pub.pem`)?
- an API Server certificate (`apiserver.pem`) signed with `ca.pem` as the CA with its private key (`apiserver-key.pem`)
- a Service Account private key that's used for signing Service Accounts' tokens.
Copy link
Member

@mikedanese mikedanese Jan 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've used the apiserver.key to do this so far. It works fine so I suggest dropping sa.key

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between having a dedicated private key or reusing the apiserver's?
Is there any difference in security?

- TODO: Is the certificate for the serviceaccount private key necessary?

Also, we should make sure that both RSA and ECDSA private keys work with kubeadm and have tests for both.
We probably want to expose the private key bitsize also.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How and why?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we set the bitsize to be large enough, we shouldn't need to expose other options (it's just more confusing/complexity for users). If you really want a different bitsize, you should follow the "bring your own cert" path instead of letting us generate certs, as then you have complete control over the algorithm and the bitsize.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've been trying to find the balance all the time for what should and should not be exposed.
While reading your arguments, it's clear that this falls under the bring-your-own certs thing.
I appreciate that feedback extra much

Also, we should make sure that both RSA and ECDSA private keys work with kubeadm and have tests for both.
We probably want to expose the private key bitsize also.

One more option that could be useful to many would be to let the user specify their own ca.pem and ca-key.pem,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I thought this was already possible. This is absolutely a requirement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these exist in the location that kubeadm would create them, then kubeadm should just use them. No need to copy. This should be the general pattern for how we implement phases w.r.t. reentrance

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not possible right now (like other things that are half-implemented). Updated the statement.

`admin.conf` and `kubelet.conf` in `/etc/kubernetes/` by default.

A general question here, do we want the KubernetesDir to be configurable at all or does it only add complexity/confusion if a user ever changed that path?
I lean towards having that as a constant, since that seems to be the case with a lot of other deployments and the gain is very small.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also lean towards leaving this unconfigurable. If there is an uproar we can always make it configurable later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, then we agree 👍


// Phases
Certificates Certificates `json:"certificates"`
MakeKubeConfig MakeKubeConfig `json:"makeKubeConfig"`
Copy link
Member

@mikedanese mikedanese Jan 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop the Make verb. The naming of the phases should be consistent. Also consider a Phases subobject where these are pointers so we can infer whether they are provided.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, let's discuss the second sentence more generally

## Kubeadm Phases and API

### Refactoring kubeadm
We all want kubeadm modular and componentized, here’s the proposal for that!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/,/;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


### Refactoring kubeadm
We all want kubeadm modular and componentized, here’s the proposal for that!
I’m not writing down all reasons for doing this; they are already available in the blog post: https://docs.google.com/document/d/1bpEGhdg8t-2Ae-IL_ezZIPklMHpZLWwnoAPMgLwT3oU
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linkify blog post rather than putting the https after the :

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should really soon be up on the site so waiting a little bit before updating that, it was never meant to be the doc, but in absence of the real blog post, I temporarily linked to the doc


So far (for kubeadm) I've identified these:

#### Certificates
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjcullen

We should also create certificates for master -> kubelet connections, which for kube-up we are doing with a second "CA universe".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the code for this? Is using a separate CA required?
I'd very much like to have more information about how you have it setup on GCE regarding that.

- TODO: Is the certificate for the serviceaccount private key necessary?

Also, we should make sure that both RSA and ECDSA private keys work with kubeadm and have tests for both.
We probably want to expose the private key bitsize also.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we set the bitsize to be large enough, we shouldn't need to expose other options (it's just more confusing/complexity for users). If you really want a different bitsize, you should follow the "bring your own cert" path instead of letting us generate certs, as then you have complete control over the algorithm and the bitsize.

that require a specific CA but lets the apiserver and serviceaccount keys/certs be generated by kubeadm.

**Inputs**
- `AdvertiseAddresses` is needed for knowing which IPs the certs should be signed for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these inputs separated this way? They are all specifying "names which should be signed" and should be possible to group into a single input (and let the code determine if they are ip addresses or dns names and do the right thing).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just the way the arguments are exposed now, my intention was indeed to have just a common field for both DNS and IPs. Suggestions on the name?

I lean towards having that as a constant, since that seems to be the case with a lot of other deployments and the gain is very small.

There also is the question whether this phase should generate both the kubelet and the admin config. Or should those be two different phases/steps?
How can we make the kubelet have just a little permissions but still use it for bootstrapping the api server? Can start the master ("bootstrap") kubelet with full access,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does bootkube do anything here? I agree that we want the kubelet to end up with "dropped permissions" even if it has to start out with root permissions to get things up and running.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, bootkube has only one kubeconfig file for everything as I interpreted the code

@luxas
Copy link
Member Author

luxas commented Jan 5, 2017

Thanks @roberthbailey and @mikedanese!

Answered your comments and updated a somehow updated version.
Much still to write down for me however.

I appreciate the comments; let's do this together and come up with a rock-solid API!

Copy link
Contributor

@pires pires left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am concerned about the API clarity as while reviewing it, it seemed somewhat confusing.

The document, so far, lgtm.

metav1.TypeMeta `json:",inline"`

// Data shared between phases. Used for defaulting
Master Master `json:"master"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MasterConfiguration.Master is not clear about its intents. Why is it there in the first place?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not by far done; I'm trying to see how I can move stuff around to get rid of it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from the current api

CertificatesDir string `json:"certificatesDir"`

// Phases
Certificates Certificates `json:"certificates"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certificates is not clear about its intents. If we have certificates then why do we need CertificatesDir? And while I may understand the design, the API itself doesn't seem self-explanatory and I believe will create confusion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might group all phases under a Phase(s) struct to make things more clear.
Here, Certificates stands for the first phase whose task is to create certs.
CertificatesDir is a param to the Certificates phase that says where certs should be put


// Shared
// TODO: This field should be HA friendly
type Master struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MasterParameters or similar?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this should change indeed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MasterConfiguration is the convention we use for other componentconfig structs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that stays the same.

This Master struct that's here was named API before, but should not exist at all I think

@luxas
Copy link
Member Author

luxas commented Jan 5, 2017

The main problem here @pires is that we want to avoid duplication in the API while we still want to allow different phases. A simple example:

Phase A needs input foo and bar. If we just run phase A we give the PhaseA struct to kubeadm and it will run that phase, example:

kubeadm phase phasea --config a.yaml

a.yaml

phaseA:
   foo: "abc"
   bar: "def"

This is pretty straightforward, right? (When there are real values of course)

Then imagine Phase B, that takes bar and baz as inputs. Oops, the param bar is required by both phases. Anyway, it doesn't matter when running only phase B:

kubeadm phase phaseb --config b.yaml

b.yaml

phaseB:
   bar: "def"
   baz: "ghi"

This is yet ok. What's problematic though, is when two or more phases share input args and kubeadm init is run, that does everything.

Then we'll have something like this:

kubeadm init --config init.yaml

init.yaml

masterConfiguration:
  phaseA:
    foo: "abc"
    **bar: "def"**
  phaseB:
    **bar: "def"**
    baz: "ghi"

Now things get messy. As an user, I shouldn't have to make sure that the bar values are consistent in both places, I don't care. I just want to specify it once. But code-wise, we have to get that value from somewhere.

We could do like this, and let the phase-individual bar params take input from a shared, top-level bar param, but that's very confusing (now we have three properties!):
init.yaml

masterConfiguration:
  bar: "def"
  phaseA:
    foo: "abc"
    <bar is unset, but the field exists here and defaults to the top-level value>
  phaseB:
    <bar is unset, but the field exists here and defaults to the top-level value>
    baz: "ghi"

Do anyone have a suggestion how we should design so we don't face that problem?
@mikedanese ^?

luxas added a commit to luxas/kubernetes that referenced this pull request Jan 10, 2017
…exist) and only four files instead of 8 previously. Basically implements what has been discussed so far in kubernetes/kubeadm#100
luxas added a commit to luxas/kubernetes that referenced this pull request Jan 13, 2017
…exist) and only four files instead of 8 previously. Basically implements what has been discussed so far in kubernetes/kubeadm#100
k8s-github-robot pushed a commit to kubernetes/kubernetes that referenced this pull request Jan 23, 2017
Automatic merge from submit-queue (batch tested with PRs 39199, 37273, 29183, 39638, 40199)

Refactor/improve the kubeadm generation of certificates

**What this PR does / why we need it**: 

Continues to refactor/improve kubeadm towards beta.

**Special notes for your reviewer**:

Modify the certs that are generated; generate on demand (if not exist) and only four files instead of eight previously. Basically implements what has been discussed so far in kubernetes/kubeadm#100

**Release note**:

```release-note
NONE
```

cc @mikedanese @pires @lukemarsden @errordeveloper @dgoodwin @roberthbailey
Addons Addons `json:"addons"`
}

type Phase struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PhaseMetadata?

@luxas
Copy link
Member Author

luxas commented Feb 21, 2017

Closing in favor for: #156

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants