github.com/Azure/aad-pod-identity@v1.8.17/cmd/mic/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "net/http" 6 _ "net/http/pprof" // #nosec 7 "os" 8 "strings" 9 "time" 10 11 "github.com/Azure/aad-pod-identity/pkg/log" 12 "github.com/Azure/aad-pod-identity/pkg/metrics" 13 "github.com/Azure/aad-pod-identity/pkg/mic" 14 "github.com/Azure/aad-pod-identity/pkg/probes" 15 "github.com/Azure/aad-pod-identity/version" 16 17 "k8s.io/client-go/rest" 18 "k8s.io/client-go/tools/clientcmd" 19 "k8s.io/klog/v2" 20 ) 21 22 var ( 23 kubeconfig string 24 cloudconfig string 25 forceNamespaced bool 26 versionInfo bool 27 syncRetryDuration time.Duration 28 leaderElectionCfg mic.LeaderElectionConfig 29 httpProbePort string 30 enableProfile bool 31 enableScaleFeatures bool 32 createDeleteBatch int64 33 clientQPS float64 34 prometheusPort string 35 immutableUserMSIs string 36 cmConfig mic.CMConfig 37 typeUpgradeConfig mic.TypeUpgradeConfig 38 updateUserMSIConfig mic.UpdateUserMSIConfig 39 identityAssignmentReconcileInterval time.Duration 40 ) 41 42 func main() { 43 klog.InitFlags(nil) 44 defer klog.Flush() 45 46 logOptions := log.NewOptions() 47 logOptions.AddFlags() 48 49 hostName, err := os.Hostname() 50 if err != nil { 51 klog.Fatalf("failed to get hostname, error: %+v", err) 52 } 53 flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to the kube config") 54 flag.StringVar(&cloudconfig, "cloudconfig", "", "Path to cloud config e.g. Azure.json file") 55 flag.BoolVar(&forceNamespaced, "forceNamespaced", false, "Forces namespaced identities, binding, and assignment") 56 flag.BoolVar(&versionInfo, "version", false, "Prints the version information") 57 flag.DurationVar(&syncRetryDuration, "syncRetryDuration", 3600*time.Second, "The interval in seconds at which sync loop should periodically check for errors and reconcile.") 58 59 // Leader election parameters 60 flag.StringVar(&leaderElectionCfg.Instance, "leader-election-instance", hostName, "leader election instance name. default is 'hostname'") 61 flag.StringVar(&leaderElectionCfg.Namespace, "leader-election-namespace", "default", "namespace to create leader election objects") 62 flag.StringVar(&leaderElectionCfg.Name, "leader-election-name", "aad-pod-identity-mic", "leader election name") 63 flag.DurationVar(&leaderElectionCfg.Duration, "leader-election-duration", time.Second*15, "leader election duration") 64 65 // Probe port 66 flag.StringVar(&httpProbePort, "http-probe-port", "8080", "http liveliness probe port") 67 68 // Prometheus port 69 flag.StringVar(&prometheusPort, "prometheus-port", "8888", "Prometheus port for metrics") 70 71 // Profile 72 flag.BoolVar(&enableProfile, "enableProfile", false, "Enable/Disable pprof profiling") 73 74 // Enable scale features handles the label based azureassignedidentity. 75 flag.BoolVar(&enableScaleFeatures, "enableScaleFeatures", false, "Enable/Disable new features used for clusters at scale") 76 77 // createDeleteBatch can be used for tuning the number of outstanding api server operations we do per node/VMSS. 78 flag.Int64Var(&createDeleteBatch, "createDeleteBatch", 20, "Per node/VMSS create/delete batches") 79 80 // Client QPS is used to configure the client-go QPS throttling and bursting. 81 flag.Float64Var(&clientQPS, "clientQps", 5, "Client QPS used for throttling of calls to kube-api server") 82 83 // Identities that should be never removed from Azure AD (used defined managed identities) 84 flag.StringVar(&immutableUserMSIs, "immutable-user-msis", "", "prevent deletion of these IDs from the underlying VM/VMSS") 85 86 // Config map for aad-pod-identity 87 flag.StringVar(&cmConfig.Name, "config-map-name", "aad-pod-identity-config", "Configmap name") 88 // Config map details for the type changes in the context of client-go upgrade. 89 flag.StringVar(&typeUpgradeConfig.TypeUpgradeStatusKey, "type-upgrade-status-key", "type-upgrade-status", "Configmap key for type upgrade status") 90 flag.BoolVar(&typeUpgradeConfig.EnableTypeUpgrade, "enable-type-upgrade", true, "Enable type upgrade") 91 92 // Parameters for retrying cloudprovider's UpdateUserMSI function 93 flag.IntVar(&updateUserMSIConfig.MaxRetry, "update-user-msi-max-retry", 2, "The maximum retry of UpdateUserMSI call") 94 flag.DurationVar(&updateUserMSIConfig.RetryInterval, "update-user-msi-retry-interval", 1*time.Second, "The duration to wait before retrying UpdateUserMSI") 95 96 // Parameters for reconciling identity assignment on Azure 97 flag.DurationVar(&identityAssignmentReconcileInterval, "identity-assignment-reconcile-interval", 3*time.Minute, "The interval between reconciling identity assignment on Azure based on an existing list of AzureAssignedIdentities") 98 99 flag.Parse() 100 101 if err := logOptions.Apply(); err != nil { 102 klog.Fatalf("unable to apply logging options, error: %+v", err) 103 } 104 105 podns := os.Getenv("MIC_POD_NAMESPACE") 106 if podns == "" { 107 klog.Fatalf("namespace not specified. Please add meta.namespace as env variable MIC_POD_NAMESPACE") 108 } 109 cmConfig.Namespace = podns 110 111 if versionInfo { 112 version.PrintVersionAndExit() 113 } 114 klog.Infof("starting mic process. Version: %v. Build date: %v", version.MICVersion, version.BuildDate) 115 if cloudconfig == "" { 116 klog.Warningf("--cloudconfig not passed will use aadpodidentity-admin-secret") 117 } 118 if kubeconfig == "" { 119 klog.Warningf("--kubeconfig not passed will use InClusterConfig") 120 } 121 if enableProfile { 122 profilePort := "6060" 123 klog.Infof("starting profiling on port %s", profilePort) 124 go func() { 125 addr := "localhost:" + profilePort 126 if err := http.ListenAndServe(addr, nil); err != nil { 127 klog.Errorf("failed to listen and serve %s, error: %+v", addr, err) 128 } 129 }() 130 } 131 132 if enableScaleFeatures { 133 klog.Infof("enableScaleFeatures is DEPRECATED for MIC and isn't required. This flag will be removed in the next release.") 134 } 135 136 klog.Infof("kubeconfig (%s) cloudconfig (%s)", kubeconfig, cloudconfig) 137 config, err := buildConfig(kubeconfig) 138 if err != nil { 139 klog.Fatalf("failed to build config from %s, error: %+v", kubeconfig, err) 140 } 141 config.UserAgent = version.GetUserAgent("MIC", version.MICVersion) 142 143 forceNamespaced = forceNamespaced || "true" == os.Getenv("FORCENAMESPACED") 144 klog.Infof("running MIC in namespaced mode: %v", forceNamespaced) 145 146 config.QPS = float32(clientQPS) 147 config.Burst = int(clientQPS) 148 klog.Infof("client QPS set to: %v. Burst to: %v", config.QPS, config.Burst) 149 150 var immutableUserMSIsList []string 151 if immutableUserMSIs != "" { 152 immutableUserMSIsList = strings.Split(immutableUserMSIs, ",") 153 } 154 155 micConfig := &mic.Config{ 156 CloudCfgPath: cloudconfig, 157 RestConfig: config, 158 IsNamespaced: forceNamespaced, 159 SyncRetryInterval: syncRetryDuration, 160 LeaderElectionCfg: &leaderElectionCfg, 161 CreateDeleteBatch: createDeleteBatch, 162 ImmutableUserMSIsList: immutableUserMSIsList, 163 CMcfg: &cmConfig, 164 TypeUpgradeCfg: &typeUpgradeConfig, 165 UpdateUserMSICfg: &updateUserMSIConfig, 166 IdentityAssignmentReconcileInterval: identityAssignmentReconcileInterval, 167 } 168 169 micClient, err := mic.NewMICClient(micConfig) 170 if err != nil { 171 klog.Fatalf("failed to create MIC client, error: %+v", err) 172 } 173 174 // Health probe will always report success once its started. 175 // MIC instance will report the contents as "Active" only once its elected the leader 176 // and starts the sync loop. 177 probes.InitAndStart(httpProbePort, &micClient.SyncLoopStarted) 178 179 // Register and expose metrics views 180 if err = metrics.RegisterAndExport(prometheusPort); err != nil { 181 klog.Fatalf("failed to register and export metrics on port %s, error: %+v", prometheusPort, err) 182 } 183 184 // Starts the leader election loop 185 micClient.Run() 186 klog.Info("aad-pod-identity controller initialized!!") 187 select {} 188 } 189 190 // Create the client config. Use kubeconfig if given, otherwise assume in-cluster. 191 func buildConfig(kubeconfigPath string) (*rest.Config, error) { 192 if kubeconfigPath != "" { 193 return clientcmd.BuildConfigFromFlags("", kubeconfigPath) 194 } 195 return rest.InClusterConfig() 196 }