istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/autoregistration/internal/health/controller.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package health
    16  
    17  import (
    18  	"google.golang.org/protobuf/types/known/timestamppb"
    19  
    20  	"istio.io/api/meta/v1alpha1"
    21  	"istio.io/istio/pilot/pkg/autoregistration/internal/state"
    22  	"istio.io/istio/pilot/pkg/model"
    23  	"istio.io/istio/pilot/pkg/model/status"
    24  	"istio.io/istio/pkg/kube/controllers"
    25  	istiolog "istio.io/istio/pkg/log"
    26  )
    27  
    28  var log = istiolog.RegisterScope("wle", "wle controller debugging")
    29  
    30  type HealthEvent struct {
    31  	// whether or not the agent thought the target is healthy
    32  	Healthy bool `json:"healthy,omitempty"`
    33  	// error message propagated
    34  	Message string `json:"errMessage,omitempty"`
    35  }
    36  
    37  type HealthCondition struct {
    38  	proxy     *model.Proxy
    39  	entryName string
    40  	condition *v1alpha1.IstioCondition
    41  }
    42  
    43  // Controller knows how to update health status of a workload.
    44  type Controller struct {
    45  	stateStore *state.Store
    46  
    47  	// healthCondition is a fifo queue used for updating health check status
    48  	healthCondition controllers.Queue
    49  }
    50  
    51  // NewController returns a new Controller instance.
    52  func NewController(stateStore *state.Store, maxRetries int) *Controller {
    53  	c := &Controller{
    54  		stateStore: stateStore,
    55  	}
    56  	c.healthCondition = controllers.NewQueue("healthcheck",
    57  		controllers.WithMaxAttempts(maxRetries),
    58  		controllers.WithGenericReconciler(c.updateWorkloadEntryHealth))
    59  	return c
    60  }
    61  
    62  func (c *Controller) Run(stop <-chan struct{}) {
    63  	c.healthCondition.Run(stop)
    64  }
    65  
    66  // QueueWorkloadEntryHealth enqueues the associated WorkloadEntries health status.
    67  func (c *Controller) QueueWorkloadEntryHealth(proxy *model.Proxy, event HealthEvent) {
    68  	// we assume that the workload entry exists
    69  	// if auto registration does not exist, try looking
    70  	// up in NodeMetadata
    71  	entryName, _ := proxy.WorkloadEntry()
    72  	if entryName == "" {
    73  		log.Errorf("unable to derive WorkloadEntry for health update for %v", proxy.ID)
    74  		return
    75  	}
    76  
    77  	condition := transformHealthEvent(proxy, entryName, event)
    78  	c.healthCondition.Add(condition)
    79  }
    80  
    81  func transformHealthEvent(proxy *model.Proxy, entryName string, event HealthEvent) HealthCondition {
    82  	cond := &v1alpha1.IstioCondition{
    83  		Type: status.ConditionHealthy,
    84  		// last probe and transition are the same because
    85  		// we only send on transition in the agent
    86  		LastProbeTime:      timestamppb.Now(),
    87  		LastTransitionTime: timestamppb.Now(),
    88  	}
    89  	out := HealthCondition{
    90  		proxy:     proxy,
    91  		entryName: entryName,
    92  		condition: cond,
    93  	}
    94  	if event.Healthy {
    95  		cond.Status = status.StatusTrue
    96  		return out
    97  	}
    98  	cond.Status = status.StatusFalse
    99  	cond.Message = event.Message
   100  	return out
   101  }
   102  
   103  // updateWorkloadEntryHealth updates the associated WorkloadEntries health status
   104  // based on the corresponding health check performed by istio-agent.
   105  func (c *Controller) updateWorkloadEntryHealth(obj any) error {
   106  	condition := obj.(HealthCondition)
   107  	return c.stateStore.UpdateHealth(condition.proxy.ID, condition.entryName, condition.proxy.Metadata.Namespace, condition.condition)
   108  }