Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

WIP: Adding initial proof of concept creating nested CRDs for each object #1

Conversation

christopherhein
Copy link
Contributor

Adding an initial Proof of Concept for CAPN style, this is not full featured but currently implements part of the ControlPlane provider, the idea is that when a control plane is created it can downstream create the objects/components which are reconciled separately allowing us to swap out specific implementations, for example this currently will take an NestedControlPlane and will kick off creating a NestedPKI (Not necessarily the greatest name but solves to prove the model) the NestedPKI controller will create all the object necessary like the rootca, apiserver crt and key, etc crt and key. This pulls a lot from the original VC for implementation but could be easily replaced if you needed to implement a custom PKI generator.

This PR doesn't necessarily need to be merged but serves to help explain one path.

Signed-off-by: Chris Hein [email protected]

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Oct 20, 2020
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: christopherhein

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

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 20, 2020
@christopherhein
Copy link
Contributor Author

/hold

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Oct 20, 2020
@christopherhein christopherhein marked this pull request as draft October 20, 2020 16:52
// annotations that are not visible to Nested Cluster but are kept in
// super master. For example, the annotations added by syncer controller.
// +optional
OpaqueMetaPrefixes []string `json:"opaqueMetaPrefixes,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this should be removed an implemented somewhere else since this specific to VC

// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=nestedpkis,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=nestedpkis/status,verbs=get;update;patch

func (r *NestedPKIReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could we implement some of these functions with cert-manager

Copy link
Contributor Author

Choose a reason for hiding this comment

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

// cluster PKI, if not set the PKI will expire after 1 year.
// +optional
// +kubebuilder:default=365
PKIExpireDays int64 `json:"pkiExpireDays,omitempty"`
Copy link

Choose a reason for hiding this comment

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

I saw PKI and had some quick thoughts:

  • it feels rather coarse to set the expiry at the granularity of the whole PKI, rather than specific credentials
  • are you thinking about rotation yet?
  • Why put this in NestedControlPlaneSpec instead of NestedPKI?

Copy link

Choose a reason for hiding this comment

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

I think we should err on the side of caution with adding fields. If we don't need to expose this as a user-configurable option yet, I think we should not do it. The above questions raise great points, and I am not sure we have enough of an understanding of the problem space to know where best to put it just yet.

Why put this in NestedControlPlaneSpec instead of NestedPKI?

👍 - I also think this is a question we should answer more generally. What is the purpose of the NestedControlPlane vs the NestedControlPlaneTemplate resource? What defines what should go where?

// TemplateRef allows you to specify the control plane template to create
// the control plane.
// +optional
TemplateRef *corev1.ObjectReference `json:"configRef,omitempty"`
Copy link

Choose a reason for hiding this comment

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

just to clarify on what a template is here:
is the NestedControlPlane controller meant to create additional CR instances out of this templateRef as in https://github.com/kubernetes-sigs/cluster-api/blob/master/controllers/machineset_controller.go#L344?
Or is this referencing a CR which fields input will just be consumed by the controller? If this is the latter we should may reconsider having "template" in the naming.

Copy link
Contributor

@charleszheng44 charleszheng44 Oct 23, 2020

Choose a reason for hiding this comment

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

This TemplateRef will refer to an NestedControlPlaneTemplate object. There may exist multiple NestedControlPlaneTemplate objects, and each NestedControlPlane object will refer to one of them. The NestedControlPlane controller will then create CR NestedKAS, NestedEtcd and NestedKCM, And the NestedKAS, NestedEtcd and the NestedKCM controllers will actually start each component.

// receive requests and that the VPC infra is ready.
// +optional
Ready bool `json:"ready"`

Copy link

Choose a reason for hiding this comment

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

should probably also include a field to signal error here. E.g

	// ErrorMessage indicates that there is a terminal problem reconciling the
	// state, and will be set to a descriptive error message.

Probably to be done in hand with conditions.
	// +optional
	FailureMessage *string `json:"failureMessage,omitempty"`

Though this can probably be detailed later when introducing conditions

// +kubebuilder:printcolumn:name="ClusterNamespace",type="string",JSONPath=".status.clusterNamespace",description="Namespace of the cluster",priority=1

// NestedControlPlane is the Schema for the nestedcontrolplanes API
type NestedControlPlane struct {
Copy link

Choose a reason for hiding this comment

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

Just out of curiosity if there has been any discussion for naming nested vs hosted?

Copy link

@munnerz munnerz left a comment

Choose a reason for hiding this comment

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

I've not reviewed all changes in here as I think we need to take a step back and write up a document outlining what CRDs we are adding and their intended purpose/meaning.

As it stands it seems like we're adding in a lot of things that we know we want to implement, without first establishing the baseline definitions for what does what, and how it works.

There's a few points in here that intend to make it 'general purpose' so anyone can bring along their own implementation of how to provision a nested cluster. What's the model that an implementor should take to do this? Is it to create their own CRD types and reference them from templates? Is it to just build a controller that watches for NestedCluster resources and take appropriate action?

// prefixes used for all Namespaces in the cluster.
// e.g. {namespace}-{vcp.uid}-{vc-namespace}
// +optional
ClusterNamespace string `json:"clusterNamespace,omitempty"`
Copy link

Choose a reason for hiding this comment

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

What's the vcp.uid? We should make these doc comments as clear as possible for the 'layman' user and avoid ambiguous terms if possible 😄

This also makes up the prefixes used for all Namespaces in the cluster. e.g. {namespace}-{vcp.uid}-{vc-namespace}

This seems okay for now. In future though it may be worth having some kind of namespacePrefix field to explicitly set this to some other value. It may be worth noting here that whilst it is true today, it should not be relied upon? If so, can we expose the chosen prefix through a status field to make it easier for other consumers of this API to make use of/build upon?

Copy link

Choose a reason for hiding this comment

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

Also, I think there needs to be a length restriction on this field. We should also call out how the length of this field influences the restrictions on namespace names within nested clusters too.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for the namespacePrefix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to call out this is typically defaulted and that it needs to have a max length validation and warning about it's usage for conflicting namespace prefixes, also rename to NamespacePrefix

// cluster. e.g. a pod dns will be
// {some-pod}.{some-namespace}.svc.{ClusterDomain}
// +kubebuilder:default=cluster.local
ClusterDomain string `json:"clusterDomain,omitempty"`
Copy link

Choose a reason for hiding this comment

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

I think this should also have // +optional tags? Though perhaps kubebuilder automatically marks this as optional if it is omitempty? 👀

// TemplateRef allows you to specify the control plane template to create
// the control plane.
// +optional
TemplateRef *corev1.ObjectReference `json:"configRef,omitempty"`
Copy link

Choose a reason for hiding this comment

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

Is this a reference to an object that itself describes how to provision the cluster? Does this refer to a NestedControlPlaneTemplate? I see this is marked optional - what happens if it is not specified?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should create a default NestedControlPlaneTemplate, which will be used when the TemplateRef is not set.

// cluster PKI, if not set the PKI will expire after 1 year.
// +optional
// +kubebuilder:default=365
PKIExpireDays int64 `json:"pkiExpireDays,omitempty"`
Copy link

Choose a reason for hiding this comment

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

I think we should err on the side of caution with adding fields. If we don't need to expose this as a user-configurable option yet, I think we should not do it. The above questions raise great points, and I am not sure we have enough of an understanding of the problem space to know where best to put it just yet.

Why put this in NestedControlPlaneSpec instead of NestedPKI?

👍 - I also think this is a question we should answer more generally. What is the purpose of the NestedControlPlane vs the NestedControlPlaneTemplate resource? What defines what should go where?

// meta data are generated by super master controllers, which are needed by
// nested cluster to interact with external systems.
// +optional
TransparentMetaPrefixes []string `json:"transparentMetaPrefixes,omitempty"`
Copy link

Choose a reason for hiding this comment

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

I'm not too sure what this means - does "back populated" mean synced? It'd really help if we had a proposal document that explained some of this stuff and set out some definitions.

// Ready denotes that the NestedControlPlane API Server is ready to
// receive requests and that the VPC infra is ready.
// +optional
Ready bool `json:"ready"`
Copy link

Choose a reason for hiding this comment

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

I don't think this field should exist as-is. If we are going to have an overarching concept of readiness, it should be denoted as a condition. That said, I think we should be careful to clearly define what we call ready or not. If an apiserver is failing 50% of requests, is it ready?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can probably use ReadyReplicas since we'll likely have multiple replicas, this is pulled from the Control Plane types for CAPI -https://cluster-api.sigs.k8s.io/developer/architecture/controllers/control-plane.html#required-status-fields

// Components allows you to specify the multiple components necessary to
// provision a Virtual Control Plane
// +optional
Components []configv1alpha1.Addon `json:"components,omitempty"`
Copy link

Choose a reason for hiding this comment

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

How does KubernetesVersion and Components relate? What if I define a component that uses an image on version 1.16 of k8s, and the KubernetesVersion is set to 1.18?

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, the Components should have higher privilege, sometimes users may wanna try out customized component.

In additon, Maybe we can use the KubernetesVersion as the default component version? say, the KubernetesVersion is set to 1.16 while only the KAS and etcd addon is provided, then the default 1.16 KCM template will be used.

// Default allows you to set this NestedTemplate as a a default template,
// by setting this to true any new NestedClusters will be created without
// a TemplateRef will be deployed with this template.
Default bool `json:"default,omitempty"`
Copy link

Choose a reason for hiding this comment

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

I'd expect something like default templates to be a feature we add further down the line - initially, in this early development phase, requiring users to specify something explicitly works fine. If we introduce this without consideration, we end out not answering questions like "what if multiple templates exist that are all marked default?"

Copy link
Contributor

Choose a reason for hiding this comment

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

Use a validating webhook to prevent multiple templates from being marked as default?

// prefixes used for all Namespaces in the cluster.
// e.g. {namespace}-{vcp.uid}-{vc-namespace}
// +optional
ClusterNamespace string `json:"clusterNamespace,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for the namespacePrefix

// TemplateRef allows you to specify the control plane template to create
// the control plane.
// +optional
TemplateRef *corev1.ObjectReference `json:"configRef,omitempty"`
Copy link
Contributor

@charleszheng44 charleszheng44 Oct 23, 2020

Choose a reason for hiding this comment

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

This TemplateRef will refer to an NestedControlPlaneTemplate object. There may exist multiple NestedControlPlaneTemplate objects, and each NestedControlPlane object will refer to one of them. The NestedControlPlane controller will then create CR NestedKAS, NestedEtcd and NestedKCM, And the NestedKAS, NestedEtcd and the NestedKCM controllers will actually start each component.

// TemplateRef allows you to specify the control plane template to create
// the control plane.
// +optional
TemplateRef *corev1.ObjectReference `json:"configRef,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should create a default NestedControlPlaneTemplate, which will be used when the TemplateRef is not set.

Ready bool `json:"ready"`

// Conditions specifies the cpnditions for the managed control plane
// Conditions clusterv1.Conditions `json:"conditions,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we going to use the Conditions? I think it could be useful for debugging and monitoring.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, we need to have conditions on these types. This should follow the base required fields from CAPI - https://cluster-api.sigs.k8s.io/developer/architecture/controllers/control-plane.html

// Components allows you to specify the multiple components necessary to
// provision a Virtual Control Plane
// +optional
Components []configv1alpha1.Addon `json:"components,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, the Components should have higher privilege, sometimes users may wanna try out customized component.

In additon, Maybe we can use the KubernetesVersion as the default component version? say, the KubernetesVersion is set to 1.16 while only the KAS and etcd addon is provided, then the default 1.16 KCM template will be used.

// Default allows you to set this NestedTemplate as a a default template,
// by setting this to true any new NestedClusters will be created without
// a TemplateRef will be deployed with this template.
Default bool `json:"default,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Use a validating webhook to prevent multiple templates from being marked as default?

// +kubebuilder:resource:scope=Namespaced,categories=cluster-api;capn;capi,shortName=ne

// NestedEtcd is the Schema for the nestedetcds API
type NestedEtcd struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

There will also be a NestedKAS and a NestedKCM, right?

@christopherhein
Copy link
Contributor Author

/close

@k8s-ci-robot
Copy link
Contributor

@christopherhein: Closed this PR.

In response to this:

/close

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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.

6 participants