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

Allow passing in extra user-data to cloud-init #3633

Merged
merged 10 commits into from
Nov 10, 2017

Conversation

rdrgmnzs
Copy link
Contributor

This allows for the utilization of multipart mime to pass extra data to cloud-init.

This gives you the ability to utilize cloud-init features such as setting up a CM or monitoring so that existing infrastructure components can be leveraged.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 16, 2017
@rdrgmnzs
Copy link
Contributor Author

/assign @justinsb

@KashifSaadat
Copy link
Contributor

Hey @brdude. The PR looks good, however is there specific behaviour you're looking to achieve by adding to the user-data that couldn't already be done via use of Hooks within the Cluster Spec? https://github.com/kubernetes/kops/blob/master/docs/cluster_spec.md#hooks

I think we should be cautious with allowing people to modify the user-data, as there is a 16KB limit with AWS so you could potentially break the cluster provisioning process.

@rdrgmnzs
Copy link
Contributor Author

rdrgmnzs commented Oct 16, 2017

@KashifSaadat it's not so much that it could not be done but the fact that the level of engineering required to port everything that currently exists in the infrastructure that uses user-data would be a huge burden and take an immense amount of engineering.

Examples of what currently is done by user-data and what it's used for in my infra:

  • Configuration management setup.
  • Monitoring setup
  • Amongst others things.

Would checking the size of user-data at creation time and failing if it exceeds the size be an appropriate solution here?

@chrislovecnm
Copy link
Contributor

/assign @justinsb

PTAL when you have a chance. I am kinda on the fence with this one. If it goes through we need to not have the user blow up there user data.

@rdrgmnzs
Copy link
Contributor Author

@chrislovecnm when you say blow up their user data, are you referring to the size of the user data or if there is an error in their user data?

For the first we can add a check to ensure the user-data does not exceed 16KB, for the second if a part of the user data is broken cloud-init will just fail for that piece but still run the other cloud-init data componets passed to it.

@chrislovecnm
Copy link
Contributor

For the first we can add a check to ensure the user-data does not exceed 16KB

^ yes

Let @justinsb take a look and get his feedback. Not saying no, it just appears we are giving the user the same functionality to do the same thing. Just my thought.

@justinsb
Copy link
Member

I think we're trying to encourage hooks and daemonsets. cloud-init isn't something I think we can support for the long-haul (e.g. the differences between what coreos supports & debian supports).

As a compromise, how about we produce those example hooks or daemonsets for the use cases you're trying to achieve? e.g. there's a daemonset for NewRelic at https://github.com/kubernetes/examples/blob/master/staging/newrelic/README.md It is different from cloud-init, but it lets us use kubernetes management for these things, rather than having two classes of components.

@rdrgmnzs
Copy link
Contributor Author

rdrgmnzs commented Oct 21, 2017

@justinsb at least for my use case unfortunately the NewRelic daemon set wouldn't solve our issues. We actually use user-data for other things besides cloud-init. We have daemon sets on boxes that do access management based on the user-data, since it cannot be changed without a reboot. We also have another daemon that uses other parts of user-data for identity management and ownership identification. These are just a couple examples.

The reason I used cloud-init as the factor in the title is because that is what most people use it for.

Unfortunately I had not realized that coreOS does not support multi-part mime. Would setting this up so that we only encode the user-data as a multipart mime if the user passes in EXTRA_USER_DATA be an acceptable middle ground? This way support for both types of user-data (Debian and CoreOS) would be possible.


### Adding additonal user-data

Aditional user-user data can be passed to the host provissioning by utilizing the environment variable EXTRA_USER_DATA. By setting `EXTRA_USER_DATA` to `<file>:<content-type>` kops will load these aditional files and pass them on to the hosts. A list of valid content-types can be found [here](http://cloudinit.readthedocs.io/en/latest/topics/format.html#mime-multi-part-archive)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: typo provisioning

@justinsb
Copy link
Member

justinsb commented Nov 4, 2017

So actually I think this is OK, but with one tweak: I think we should not set up multipart if EXTRA_USER_DATA is not passed. Then for most people, there will be no change, and if you opt-in, you get multipart.

Then a few suggestions:

  • I suggest calling the env var KOPS_EXTRA_USER_DATA, just in case someone has EXTRA_USER_DATA set (not sure how likely this is, but the KOPS_ prefix makes this reasonable IMO). But...
  • ... I would also consider that this may belong in the cluster spec or instancegroup spec? Otherwise you have to pass KOPS_EXTRA_USER_DATA to every kops command. But on the other hand for your use case I'm guessing that you don't want the user data in the instance group spec maybe?

Sorry this took so long for me to get my head around. If we can change it so that we don't do multipart unless the variable is set, lgtm!

@justinsb
Copy link
Member

justinsb commented Nov 4, 2017

Going to close & reopen to retrigger e2e as well

@justinsb justinsb closed this Nov 4, 2017
@justinsb justinsb reopened this Nov 4, 2017
@rdrgmnzs rdrgmnzs changed the title Allow passing in extra user-data to cloud-init WIP: Allow passing in extra user-data to cloud-init Nov 4, 2017
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 4, 2017
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Nov 7, 2017
@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Nov 7, 2017
@rdrgmnzs
Copy link
Contributor Author

rdrgmnzs commented Nov 7, 2017

Going to close & reopen to retrigger e2e

@rdrgmnzs rdrgmnzs closed this Nov 7, 2017
@rdrgmnzs rdrgmnzs reopened this Nov 7, 2017
@rdrgmnzs rdrgmnzs changed the title Allow passing in extra user-data to cloud-init WIP: Allow passing in extra user-data to cloud-init Nov 8, 2017
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 8, 2017
@rdrgmnzs rdrgmnzs changed the title WIP: Allow passing in extra user-data to cloud-init Allow passing in extra user-data to cloud-init Nov 8, 2017
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 8, 2017

func validateExtraUserData(userData *kops.ExtraUserDataSpec) error {
if userData.Name == "" {
return field.Required(field.NewPath("ExtraUserData Name"), "extraUserData Name field must be set")
Copy link
Member

Choose a reason for hiding this comment

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

So we are supposed to pass the parent field.Path into a validate function, and then it is fieldPath.Child("Name") i.e. just the name of the field.

@@ -160,7 +160,12 @@ func (b *BootstrapScript) ResourceNodeUp(ig *kops.InstanceGroup, cs *kops.Cluste
},
}

templateResource, err := NewTemplateResource("nodeup", resources.AWSNodeUpTemplate, functions, nil)
AWSNodeUpTemplate, err := resources.AWSNodeUpTemplate(ig)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: typically we prefer lower case for local variables, e.g. awsNodeUpTempler, err...

@@ -170,3 +180,70 @@ __EOF_KUBE_ENV
download-release
echo "== nodeup node config done =="
`

// AWSNodeUpTemplate returns a Mime Multi Part Archive container the nodeup (bootstrap) script
// and any aditional User Data passed to it in files using the env variable KOPS_EXTRA_USER_DATA
Copy link
Member

Choose a reason for hiding this comment

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

Nit: comment is out of date (KOPS_EXTRA_USER_DATA)


mimeWriter := multipart.NewWriter(writer)

// we explicitly set the buoudaries to make testing easier.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: typo in boundaries

case "text/cloud-config":
case "text/part-handler":
case "text/x-shellscript":
case "text/cloud-boothook":
Copy link
Member

Choose a reason for hiding this comment

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

Do you need all of these? My concern is that if we specify e.g. x-shellscript, it might interfere with normal boot in non-trivial ways.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only one I need personally is "text/cloud-config". Just though I'd add all the valid types to have inclusive support since we're already putting support in. However I have nothibg against removing x-shellscript.

Copy link
Member

Choose a reason for hiding this comment

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

I think we probably should, for safety, but I also want to get this PR in, so maybe we look at that in a separate PR :-)

Copy link
Member

Choose a reason for hiding this comment

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

(We can always add things to the set of permitted types, much harder to remove things)

@@ -17,15 +17,14 @@ limitations under the License.
package scheme

import (
os "os"
Copy link
Member

Choose a reason for hiding this comment

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

We're trying to move to goimports formatted code... not sure what happened here :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah not sure what happened either I believe this was done when I generated the API for userData :-/

// and any aditional User Data passed to it in files using the env variable KOPS_EXTRA_USER_DATA
func AWSNodeUpTemplate(ig *kops.InstanceGroup) (string, error) {

UserDataTemplate := NodeUpTemplate
Copy link
Member

Choose a reason for hiding this comment

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

Nit: userDataTemplate

@@ -109,6 +109,18 @@ type InstanceGroupSpec struct {
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
// Taints indicates the kubernetes taints for nodes in this group
Taints []string `json:"taints,omitempty"`
// ExtraUserData is any extra user-data to be passed to the host
ExtraUserData []ExtraUserDataSpec `json:"extraUserData,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

For better or worse, we've called this additionalX previously...

How do you feel about:

AdditionalUserData []UserDataSpec json:"additionalUserData,omitempty"``

}

// ExtraUserDataSpec defines a user-data section
type ExtraUserDataSpec struct {
Copy link
Member

Choose a reason for hiding this comment

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

This can also be AdditionalUserDataSpec or just UserDataSpec, or maybe even UserData.

My 2c: UserData

@justinsb
Copy link
Member

justinsb commented Nov 9, 2017

Looks great - API is the one thing we really can't change easily, so how would you feel about naming the field additionalUserData - I think we've used "additional" rather than "extra" everywhere else. Everything else is just nits / suggestions for the future :-)

@rdrgmnzs
Copy link
Contributor Author

rdrgmnzs commented Nov 9, 2017

Quick note, looks like AdditionalSANs did not have API machinery ran on it so this includes changes for that as well.

@rdrgmnzs rdrgmnzs force-pushed the extra_user-data branch 2 times, most recently from f077e79 to 6aa7de8 Compare November 9, 2017 21:27
@chrislovecnm
Copy link
Contributor

@brdude I will PR api machinery update ... and open api as well.

@chrislovecnm
Copy link
Contributor

@brdude #3815 will do the update. Thanks for the catch. We have an open issue to test API machinery generation during CI.

@justinsb
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 10, 2017
@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: justinsb

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 10, 2017
@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue.

@k8s-github-robot k8s-github-robot merged commit 8739632 into kubernetes:master Nov 10, 2017
dgem added a commit to dgem/kops that referenced this pull request Nov 14, 2017
k8s-github-robot pushed a commit that referenced this pull request Nov 14, 2017
Automatic merge from submit-queue.

Update Additional user-data per #3853

Looking at https://godoc.org/k8s.io/kops/pkg/apis/kops#InstanceGroupSpec and #3633, the field is `AdditionalUserData` not `ExtraUserData`

This addresses #3853
@rdrgmnzs rdrgmnzs deleted the extra_user-data branch April 19, 2018 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants