github.com/argoproj/argo-cd@v1.8.7/cmd/argocd-application-controller/commands/argocd_application_controller.go (about)

     1  package commands
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  	"time"
     7  
     8  	"github.com/argoproj/pkg/stats"
     9  	"github.com/go-redis/redis/v8"
    10  	log "github.com/sirupsen/logrus"
    11  	"github.com/spf13/cobra"
    12  	"k8s.io/client-go/kubernetes"
    13  	"k8s.io/client-go/tools/clientcmd"
    14  
    15  	"github.com/argoproj/argo-cd/common"
    16  	"github.com/argoproj/argo-cd/controller"
    17  	"github.com/argoproj/argo-cd/controller/sharding"
    18  	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
    19  	appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
    20  	"github.com/argoproj/argo-cd/reposerver/apiclient"
    21  	cacheutil "github.com/argoproj/argo-cd/util/cache"
    22  	appstatecache "github.com/argoproj/argo-cd/util/cache/appstate"
    23  	"github.com/argoproj/argo-cd/util/cli"
    24  	"github.com/argoproj/argo-cd/util/env"
    25  	"github.com/argoproj/argo-cd/util/errors"
    26  	kubeutil "github.com/argoproj/argo-cd/util/kube"
    27  	"github.com/argoproj/argo-cd/util/settings"
    28  )
    29  
    30  const (
    31  	// CLIName is the name of the CLI
    32  	cliName = "argocd-application-controller"
    33  	// Default time in seconds for application resync period
    34  	defaultAppResyncPeriod = 180
    35  )
    36  
    37  func NewCommand() *cobra.Command {
    38  	var (
    39  		clientConfig             clientcmd.ClientConfig
    40  		appResyncPeriod          int64
    41  		repoServerAddress        string
    42  		repoServerTimeoutSeconds int
    43  		selfHealTimeoutSeconds   int
    44  		statusProcessors         int
    45  		operationProcessors      int
    46  		logFormat                string
    47  		logLevel                 string
    48  		glogLevel                int
    49  		metricsPort              int
    50  		kubectlParallelismLimit  int64
    51  		cacheSrc                 func() (*appstatecache.Cache, error)
    52  		redisClient              *redis.Client
    53  	)
    54  	var command = cobra.Command{
    55  		Use:               cliName,
    56  		Short:             "Run ArgoCD Application Controller",
    57  		Long:              "ArgoCD application controller is a Kubernetes controller that continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). This command runs Application Controller in the foreground.  It can be configured by following options.",
    58  		DisableAutoGenTag: true,
    59  		RunE: func(c *cobra.Command, args []string) error {
    60  			cli.SetLogFormat(logFormat)
    61  			cli.SetLogLevel(logLevel)
    62  			cli.SetGLogLevel(glogLevel)
    63  
    64  			config, err := clientConfig.ClientConfig()
    65  			errors.CheckError(err)
    66  			errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
    67  
    68  			kubeClient := kubernetes.NewForConfigOrDie(config)
    69  			appClient := appclientset.NewForConfigOrDie(config)
    70  
    71  			namespace, _, err := clientConfig.Namespace()
    72  			errors.CheckError(err)
    73  
    74  			resyncDuration := time.Duration(appResyncPeriod) * time.Second
    75  			repoClientset := apiclient.NewRepoServerClientset(repoServerAddress, repoServerTimeoutSeconds)
    76  			ctx, cancel := context.WithCancel(context.Background())
    77  			defer cancel()
    78  
    79  			cache, err := cacheSrc()
    80  			errors.CheckError(err)
    81  			cache.Cache.SetClient(cacheutil.NewTwoLevelClient(cache.Cache.GetClient(), 10*time.Minute))
    82  
    83  			settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace)
    84  			kubectl := kubeutil.NewKubectl()
    85  			clusterFilter := getClusterFilter()
    86  			appController, err := controller.NewApplicationController(
    87  				namespace,
    88  				settingsMgr,
    89  				kubeClient,
    90  				appClient,
    91  				repoClientset,
    92  				cache,
    93  				kubectl,
    94  				resyncDuration,
    95  				time.Duration(selfHealTimeoutSeconds)*time.Second,
    96  				metricsPort,
    97  				kubectlParallelismLimit,
    98  				clusterFilter)
    99  			errors.CheckError(err)
   100  			cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
   101  
   102  			vers := common.GetVersion()
   103  			log.Infof("Application Controller (version: %s, built: %s) starting (namespace: %s)", vers.Version, vers.BuildDate, namespace)
   104  			stats.RegisterStackDumper()
   105  			stats.StartStatsTicker(10 * time.Minute)
   106  			stats.RegisterHeapDumper("memprofile")
   107  
   108  			go appController.Run(ctx, statusProcessors, operationProcessors)
   109  
   110  			// Wait forever
   111  			select {}
   112  		},
   113  	}
   114  
   115  	clientConfig = cli.AddKubectlFlagsToCmd(&command)
   116  	command.Flags().Int64Var(&appResyncPeriod, "app-resync", defaultAppResyncPeriod, "Time period in seconds for application resync.")
   117  	command.Flags().StringVar(&repoServerAddress, "repo-server", common.DefaultRepoServerAddr, "Repo server address.")
   118  	command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", 60, "Repo server RPC call timeout seconds.")
   119  	command.Flags().IntVar(&statusProcessors, "status-processors", 1, "Number of application status processors")
   120  	command.Flags().IntVar(&operationProcessors, "operation-processors", 1, "Number of application operation processors")
   121  	command.Flags().StringVar(&logFormat, "logformat", "text", "Set the logging format. One of: text|json")
   122  	command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
   123  	command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level")
   124  	command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDMetrics, "Start metrics server on given port")
   125  	command.Flags().IntVar(&selfHealTimeoutSeconds, "self-heal-timeout-seconds", 5, "Specifies timeout between application self heal attempts")
   126  	command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", 20, "Number of allowed concurrent kubectl fork/execs. Any value less the 1 means no limit.")
   127  	cacheSrc = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
   128  		redisClient = client
   129  	})
   130  	return &command
   131  }
   132  
   133  func getClusterFilter() func(cluster *v1alpha1.Cluster) bool {
   134  	replicas := env.ParseNumFromEnv(common.EnvControllerReplicas, 0, 0, math.MaxInt32)
   135  	shard := env.ParseNumFromEnv(common.EnvControllerShard, -1, -math.MaxInt32, math.MaxInt32)
   136  	var clusterFilter func(cluster *v1alpha1.Cluster) bool
   137  	if replicas > 1 {
   138  		if shard < 0 {
   139  			var err error
   140  			shard, err = sharding.InferShard()
   141  			errors.CheckError(err)
   142  		}
   143  		log.Infof("Processing clusters from shard %d", shard)
   144  		clusterFilter = sharding.GetClusterFilter(replicas, shard)
   145  	} else {
   146  		log.Info("Processing all cluster shards")
   147  	}
   148  	return clusterFilter
   149  }