Skip to content

Commit da1a67e

Browse files
committed
Start adding KubeadmControlPlane controller
1 parent 065e0e0 commit da1a67e

File tree

5 files changed

+183
-17
lines changed

5 files changed

+183
-17
lines changed

api/v1alpha3/kubeadm_control_plane_types.go

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ import (
2323
"sigs.k8s.io/cluster-api/errors"
2424
)
2525

26+
const (
27+
KubeadmControlPlaneFinalizer = "kubeadmcontrolplane.cluster.x-k8s.io"
28+
)
29+
2630
// KubeadmControlPlaneSpec defines the desired state of KubeadmControlPlane.
2731
type KubeadmControlPlaneSpec struct {
2832
// Number of desired machines. Defaults to 1. When stacked etcd is used only

config/rbac/role.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,19 @@ rules:
7070
- get
7171
- list
7272
- watch
73+
- apiGroups:
74+
- cluster.x-k8s.io
75+
resources:
76+
- kubeadmcontrolplanes
77+
- kubeadmcontrolplanes/status
78+
verbs:
79+
- create
80+
- delete
81+
- get
82+
- list
83+
- patch
84+
- update
85+
- watch
7386
- apiGroups:
7487
- cluster.x-k8s.io
7588
resources:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controllers
18+
19+
import (
20+
"context"
21+
22+
"github.com/go-logr/logr"
23+
"github.com/pkg/errors"
24+
apierrors "k8s.io/apimachinery/pkg/api/errors"
25+
"k8s.io/client-go/tools/record"
26+
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
27+
"sigs.k8s.io/cluster-api/util"
28+
"sigs.k8s.io/cluster-api/util/patch"
29+
ctrl "sigs.k8s.io/controller-runtime"
30+
"sigs.k8s.io/controller-runtime/pkg/client"
31+
"sigs.k8s.io/controller-runtime/pkg/controller"
32+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
33+
)
34+
35+
// +kubebuilder:rbac:groups=core,resources=events,verbs=get;list;watch;create;patch
36+
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;patch
37+
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=kubeadmcontrolplanes;kubeadmcontrolplanes/status,verbs=get;list;watch;create;update;patch;delete
38+
39+
// KubeadmControlPlaneReconciler reconciles a KubeadmControlPlane object
40+
type KubeadmControlPlaneReconciler struct {
41+
Client client.Client
42+
Log logr.Logger
43+
44+
controller controller.Controller
45+
recorder record.EventRecorder
46+
}
47+
48+
func (r *KubeadmControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
49+
c, err := ctrl.NewControllerManagedBy(mgr).
50+
For(&clusterv1.KubeadmControlPlane{}).
51+
WithOptions(options).
52+
Build(r)
53+
54+
if err != nil {
55+
return errors.Wrap(err, "failed setting up with a controller manager")
56+
}
57+
58+
r.controller = c
59+
r.recorder = mgr.GetEventRecorderFor("kubeadm-control-plane-controller")
60+
61+
return nil
62+
}
63+
64+
func (r *KubeadmControlPlaneReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr error) {
65+
ctx := context.Background()
66+
67+
// Fetch the KubeadmControlPlane instance.
68+
kubeadmControlPlane := &clusterv1.KubeadmControlPlane{}
69+
if err := r.Client.Get(ctx, req.NamespacedName, kubeadmControlPlane); err != nil {
70+
if apierrors.IsNotFound(err) {
71+
// Object not found, return. Created objects are automatically garbage collected.
72+
// For additional cleanup logic use finalizers.
73+
return ctrl.Result{}, nil
74+
}
75+
76+
// Error reading the object - requeue the request.
77+
return ctrl.Result{}, err
78+
}
79+
80+
// Initialize the patch helper.
81+
patchHelper, err := patch.NewHelper(kubeadmControlPlane, r.Client)
82+
if err != nil {
83+
return ctrl.Result{}, err
84+
}
85+
86+
defer func() {
87+
// Always reconcile the Status.Phase field.
88+
89+
// Always attempt to Patch the KubeadmControlPlane object and status after each reconciliation.
90+
if err := patchHelper.Patch(ctx, kubeadmControlPlane); err != nil {
91+
if reterr == nil {
92+
reterr = err
93+
}
94+
}
95+
}()
96+
97+
// Handle deletion reconciliation loop.
98+
if !kubeadmControlPlane.ObjectMeta.DeletionTimestamp.IsZero() {
99+
return r.reconcileDelete(ctx, kubeadmControlPlane)
100+
}
101+
102+
// Handle normal reconciliation loop.
103+
return r.reconcile(ctx, kubeadmControlPlane)
104+
}
105+
106+
// reconcile handles cluster reconciliation.
107+
func (r *KubeadmControlPlaneReconciler) reconcile(_ context.Context, kubeadmControlPlane *clusterv1.KubeadmControlPlane) (ctrl.Result, error) {
108+
logger := r.Log.WithValues("kubeadmControlPlane", kubeadmControlPlane.Name, "namespace", kubeadmControlPlane.Namespace)
109+
110+
// If object doesn't have a finalizer, add one.
111+
if !util.Contains(kubeadmControlPlane.Finalizers, clusterv1.KubeadmControlPlaneFinalizer) {
112+
kubeadmControlPlane.Finalizers = append(kubeadmControlPlane.Finalizers, clusterv1.KubeadmControlPlaneFinalizer)
113+
}
114+
115+
err := errors.New("Not Implemented")
116+
logger.Error(err, "Not Implemented")
117+
return ctrl.Result{}, err
118+
119+
}
120+
121+
// reconcileDelete handles cluster deletion.
122+
func (r *KubeadmControlPlaneReconciler) reconcileDelete(_ context.Context, kubeadmControlPlane *clusterv1.KubeadmControlPlane) (reconcile.Result, error) {
123+
logger := r.Log.WithValues("kubeadmControlPlane", kubeadmControlPlane.Name, "namespace", kubeadmControlPlane.Namespace)
124+
125+
err := errors.New("Not Implemented")
126+
logger.Error(err, "Not Implemented")
127+
if err != nil {
128+
return ctrl.Result{}, err
129+
}
130+
131+
kubeadmControlPlane.Finalizers = util.Filter(kubeadmControlPlane.Finalizers, clusterv1.KubeadmControlPlaneFinalizer)
132+
return ctrl.Result{}, nil
133+
}

docs/proposals/20191017-kubeadm-based-control-plane.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ reviewers:
1818
- "@hardikdr"
1919
- "@sbueringer"
2020
creation-date: 2019-10-17
21-
last-updated: 2019-11-13
21+
last-updated: 2019-12-04
2222
status: implementable
2323
---
2424

@@ -224,16 +224,16 @@ type KubeadmControlPlaneStatus struct {
224224
// +optional
225225
Ready bool `json:"ready,omitempty"`
226226

227-
// ErrorReason indicates that there is a problem reconciling the
227+
// FailureReason indicates that there is a problem reconciling the
228228
// state, and will be set to a token value suitable for
229229
// programmatic interpretation.
230230
// +optional
231-
ErrorReason KubeadmControlPlaneStatusError `json:"errorReason,omitempty"`
231+
FailureReason KubeadmControlPlaneStatusError `json:"errorReason,omitempty"`
232232

233-
// ErrorMessage indicates that there is a problem reconciling the
233+
// FailureMessage indicates that there is a problem reconciling the
234234
// state, and will be set to a descriptive error message.
235235
// +optional
236-
ErrorMessage *string `json:"errorMessage,omitempty"`
236+
FailureMessage *string `json:"errorMessage,omitempty"`
237237

238238
// +kubebuilder:object:root=true
239239
// +kubebuilder:resource:path=controlplanes,shortName=cp,scope=Namespaced,categories=cluster-api
@@ -348,7 +348,7 @@ And the following defaulting:
348348
##### Create
349349
350350
- After a KubeadmControlPlane object is created, it must bootstrap a control plane with a given number of replicas.
351-
- If an error occurs, `KubeadmControlPlane.Status.ErrorStatus` and `KubeadmControlPlane.Status.ErrorMessage` are populated.
351+
- If an error occurs, `KubeadmControlPlane.Status.FailureReason` and `KubeadmControlPlane.Status.FailureMessage` are populated.
352352
- `KubeadmControlPlane.Spec.Replicas` must be an odd number.
353353
- Can create an arbitrary number of control planes if etcd is external to the control plane, which will be determined by introspecting `KubeadmControlPlane.Spec.KubeadmConfigSpec`.
354354
- Creating a KubeadmControlPlane with > 1 replicas is equivalent to creating a KubeadmControlPlane with 1 replica followed by scaling the KubeadmControlPlane to the desired number of replicas
@@ -577,3 +577,6 @@ For the purposes of designing upgrades, two existing lifecycle managers were exa
577577
## Implementation History
578578
579579
- [x] 10/17/2019: Initial Creation
580+
- [x] 11/19/2019: Initial KubeadmControlPlane types added [#1765](https://github.com/kubernetes-sigs/cluster-api/pull/1765)
581+
- [x] 12/04/2019: Updated References to ErrorMessage/ErrorReason to FailureMessage/FailureReason
582+
- [] 12/04/2019: Initial stubbed KubeadmControlPlane controller added [#1826](https://github.com/kubernetes-sigs/cluster-api/pull/1826)

main.go

+24-11
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,18 @@ func init() {
5555

5656
func main() {
5757
var (
58-
metricsAddr string
59-
enableLeaderElection bool
60-
watchNamespace string
61-
profilerAddress string
62-
clusterConcurrency int
63-
machineConcurrency int
64-
machineSetConcurrency int
65-
machineDeploymentConcurrency int
66-
kubeadmConfigConcurrency int
67-
syncPeriod time.Duration
68-
webhookPort int
58+
metricsAddr string
59+
enableLeaderElection bool
60+
watchNamespace string
61+
profilerAddress string
62+
clusterConcurrency int
63+
machineConcurrency int
64+
machineSetConcurrency int
65+
machineDeploymentConcurrency int
66+
kubeadmConfigConcurrency int
67+
kubeadmControlPlaneConcurrency int
68+
syncPeriod time.Duration
69+
webhookPort int
6970
)
7071

7172
flag.StringVar(&metricsAddr, "metrics-addr", ":8080",
@@ -95,6 +96,9 @@ func main() {
9596
flag.IntVar(&kubeadmConfigConcurrency, "kubeadmconfig-concurrency", 10,
9697
"Number of kubeadm configs to process simultaneously")
9798

99+
flag.IntVar(&kubeadmControlPlaneConcurrency, "kubeadmcontrolplane-concurrency", 1,
100+
"Number of kubeadm control planes to process simultaneously")
101+
98102
flag.DurationVar(&syncPeriod, "sync-period", 10*time.Minute,
99103
"The minimum interval at which watched resources are reconciled (e.g. 15m)")
100104

@@ -168,6 +172,15 @@ func main() {
168172
os.Exit(1)
169173
}
170174

175+
// KubeadmControlPlane controllers.
176+
if err = (&controllers.KubeadmControlPlaneReconciler{
177+
Client: mgr.GetClient(),
178+
Log: ctrl.Log.WithName("controllers").WithName("KubeadmControlPlane"),
179+
}).SetupWithManager(mgr, concurrency(kubeadmControlPlaneConcurrency)); err != nil {
180+
setupLog.Error(err, "unable to create controller", "controller", "KubeadmControlPlane")
181+
os.Exit(1)
182+
}
183+
171184
if webhookPort != 0 {
172185
if err = (&clusterv1alpha2.Cluster{}).SetupWebhookWithManager(mgr); err != nil {
173186
setupLog.Error(err, "unable to create webhook", "webhook", "Cluster")

0 commit comments

Comments
 (0)