func (r *BlueGreenReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
log.Info("Reconcile Start", "name", req.Name, "namespace", req.Namespace)
defer log.Info("Reconcile Finished", "name", req.Name, "namespace", req.Namespace)
bluegreen := new(v1.BlueGreen)
if err := r.Client.Get(ctx, req.NamespacedName, bluegreen); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Create or Update Service
svc := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: req.Namespace, Name: req.Name}}
if _, err := ctrl.CreateOrUpdate(ctx, r.Client, svc, func() error {
if err := ctrl.SetControllerReference(bluegreen, svc, r.Scheme); err != nil {
return fmt.Errorf("fail to set owner reference for a service: %w", err)
}
svc.Spec.Ports = []corev1.ServicePort{
{Name: "http", Protocol: corev1.ProtocolTCP, Port: 80},
}
svc.Spec.Selector = map[string]string{
"app.kubernetes.io/managed-by": "app.demo.kakao.com",
"app.kubernetes.io/name": req.Name,
"app.kubernetes.io/phase": string(bluegreen.Spec.RouteTo),
}
return nil
}); err != nil {
return ctrl.Result{}, fmt.Errorf("fail to create (or update) service: %w", err)
}
// Create or Update BlueDeployment
for _, tgt := range []struct {
Phase v1.BlueOrGreen
Spec *corev1.PodSpec
}{
{Phase: v1.Blue, Spec: bluegreen.Spec.BlueSpec},
{Phase: v1.Green, Spec: bluegreen.Spec.GreenSpec},
} {
if tgt.Spec == nil {
continue
}
deploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: req.Namespace, Name: deploymentName(req.Name, tgt.Phase)}}
if _, err := ctrl.CreateOrUpdate(ctx, r.Client, deploy, func() error {
if err := ctrl.SetControllerReference(bluegreen, deploy, r.Scheme); err != nil {
return fmt.Errorf("fail to set owner reference for a deployment: %w", err)
}
label := map[string]string{
"app.kubernetes.io/managed-by": "app.demo.kakao.com",
"app.kubernetes.io/name": req.Name,
"app.kubernetes.io/phase": string(tgt.Phase),
}
deploy.Spec.Selector = &metav1.LabelSelector{MatchLabels: label}
deploy.Spec.Template = corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: label},
Spec: *tgt.Spec,
}
return nil
}); err != nil {
return ctrl.Result{}, fmt.Errorf("fail to create (or update) deployment: %w", err)
}
}
bluegreen.Status = v1.BlueGreenStatus{
RouteTo: &bluegreen.Spec.RouteTo,
}
if err := r.Client.Status().Update(ctx, bluegreen); err != nil {
return ctrl.Result{}, fmt.Errorf("fail to update bluegreen status: %w", err)
}
return ctrl.Result{}, nil
}
func (r *BlueGreenReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
log.Info("Reconcile Start", "name", req.Name, "namespace", req.Namespace)
defer log.Info("Reconcile Finished", "name", req.Name, "namespace", req.Namespace)
bluegreen := new(v1.BlueGreen)
if err := r.Client.Get(ctx, req.NamespacedName, bluegreen); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Create or Update Service
if err := r.CreateOrUpdateService(ctx, bluegreen); err != nil {
return ctrl.Result{}, err
}
// Create or Update BlueDeployment
if spec := bluegreen.Spec.BlueSpec; spec != nil {
if err := r.CreateOrUpdateDeployment(ctx, bluegreen, v1.Blue, *spec); err != nil {
return ctrl.Result{}, err
}
}
// Create or Update GreenDeployment
if spec := bluegreen.Spec.GreenSpec; spec != nil {
if err := r.CreateOrUpdateDeployment(ctx, bluegreen, v1.Green, *spec); err != nil {
return ctrl.Result{}, err
}
}
bluegreen.Status = v1.BlueGreenStatus{
RouteTo: &bluegreen.Spec.RouteTo,
}
return ctrl.Result{}, r.Client.UpdateStatus(ctx, req, bluegreen.Status)
}
수십번의 메소드 호출
->
세번의 메소드 호출
방법. 1 - Mock
Deployment
Service
Deployment
Service