github.com/fafucoder/cilium@v1.6.11/operator/api.go (about)

     1  // Copyright 2019 Authors of Cilium
     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 main
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net/http"
    21  
    22  	"github.com/cilium/cilium/pkg/k8s"
    23  	"github.com/cilium/cilium/pkg/kvstore"
    24  )
    25  
    26  // startServer starts an api server listening on the given address.
    27  func startServer(shutdownSignal <-chan struct{}, allSystemsGo <-chan struct{}, addrs ...string) {
    28  	http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
    29  		select {
    30  		// only start serving the real health check once all systems all up and running
    31  		case <-allSystemsGo:
    32  			healthHandler(w, r)
    33  		default:
    34  			healthHandlerOK(w, r)
    35  		}
    36  	})
    37  
    38  	errs := make(chan error, 1)
    39  	nServers := 0
    40  
    41  	// Since we are opening this on localhost only, we need to make sure
    42  	// we can open for both v4 and v6 localhost. In case the user is running
    43  	// v4-only or v6-only.
    44  	for _, addr := range addrs {
    45  		if addr == "" {
    46  			continue
    47  		}
    48  		nServers++
    49  		srv := &http.Server{Addr: addr}
    50  		errCh := make(chan error, 1)
    51  
    52  		go func() {
    53  			err := srv.ListenAndServe()
    54  			if err != nil {
    55  				errCh <- err
    56  				errs <- err
    57  			}
    58  		}()
    59  		go func() {
    60  			select {
    61  			case <-shutdownSignal:
    62  				if err := srv.Shutdown(context.Background()); err != nil {
    63  					log.WithError(err).Error("apiserver shutdown")
    64  				}
    65  			case err := <-errCh:
    66  				log.Warnf("Unable to start status api: %s", err)
    67  			}
    68  		}()
    69  		log.Infof("Starting apiserver on address %s", addr)
    70  	}
    71  
    72  	for err := range errs {
    73  		nServers--
    74  		if nServers == 0 {
    75  			log.Fatalf("Unable to start status api: %s", err)
    76  		}
    77  	}
    78  }
    79  
    80  func healthHandlerOK(w http.ResponseWriter, r *http.Request) {
    81  	w.WriteHeader(http.StatusOK)
    82  	if _, err := w.Write([]byte("ok")); err != nil {
    83  		log.WithError(err).Error("Failed to write liveness-probe response")
    84  	}
    85  }
    86  
    87  func healthHandler(w http.ResponseWriter, r *http.Request) {
    88  	statusCode := http.StatusOK
    89  	reply := "ok"
    90  
    91  	if err := checkStatus(); err != nil {
    92  		statusCode = http.StatusInternalServerError
    93  		reply = err.Error()
    94  		log.WithError(err).Warn("Health check status")
    95  	}
    96  
    97  	w.WriteHeader(statusCode)
    98  	if _, err := w.Write([]byte(reply)); err != nil {
    99  		log.WithError(err).Error("Failed to write liveness-probe response")
   100  	}
   101  }
   102  
   103  // checkStatus checks the connection status to the kvstore and
   104  // k8s apiserver and returns an error if any of them is unhealthy
   105  func checkStatus() error {
   106  	if kvstoreEnabled() {
   107  		if client := kvstore.Client(); client == nil {
   108  			return fmt.Errorf("kvstore client not configured")
   109  		} else if _, err := client.Status(); err != nil {
   110  			return err
   111  		}
   112  	}
   113  
   114  	if _, err := k8s.Client().Discovery().ServerVersion(); err != nil {
   115  		return err
   116  	}
   117  
   118  	return nil
   119  }