Commit c429a074 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #40917 from irfanurrehman/fed-init-flags-1

Automatic merge from submit-queue (batch tested with PRs 40917, 41181, 41123, 36592, 41183) [Federation] Add override flags options to kubefed init **What this PR does / why we need it**: Allows modification of startup flags (of apiserver and controller manager) through kubefed **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # https://github.com/kubernetes/kubernetes/issues/40398 **Special notes for your reviewer**: I haven't removed the existing redundant flags now (for example --dns-zone-name) intentionally to avoid breaking any existing tests that might use them. I guess that would be better done as a follow up PR. @madhusudancs @marun @nikhiljindal **Release note**: ``` It is now possible for the user to modify any startup flag of federation-apiserver and federation-controller-manager when deployed through kubefed. There are two new options introduced in kubefed: --apiserver-arg-overrides and --controllermanager-arg-overrides Any number of actual federation-apiserver or federation-controller-manager flags can be specified using these options. Example: kubefed init "-other options-" ----apiserver-arg-overrides "--flag1=value1,--flag2=value2" ```
parents f17a5d38 9a56a753
...@@ -54,6 +54,7 @@ go_test( ...@@ -54,6 +54,7 @@ go_test(
"//vendor:k8s.io/apimachinery/pkg/api/resource", "//vendor:k8s.io/apimachinery/pkg/api/resource",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/util/diff", "//vendor:k8s.io/apimachinery/pkg/util/diff",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/client-go/dynamic", "//vendor:k8s.io/client-go/dynamic",
"//vendor:k8s.io/client-go/rest/fake", "//vendor:k8s.io/client-go/rest/fake",
"//vendor:k8s.io/client-go/tools/clientcmd", "//vendor:k8s.io/client-go/tools/clientcmd",
......
...@@ -57,6 +57,7 @@ import ( ...@@ -57,6 +57,7 @@ import (
"k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"sort"
) )
const ( const (
...@@ -141,6 +142,8 @@ func NewCmdInit(cmdOut io.Writer, config util.AdminConfig) *cobra.Command { ...@@ -141,6 +142,8 @@ func NewCmdInit(cmdOut io.Writer, config util.AdminConfig) *cobra.Command {
cmd.Flags().String("etcd-pv-capacity", "10Gi", "Size of persistent volume claim to be used for etcd.") cmd.Flags().String("etcd-pv-capacity", "10Gi", "Size of persistent volume claim to be used for etcd.")
cmd.Flags().Bool("etcd-persistent-storage", true, "Use persistent volume for etcd. Defaults to 'true'.") cmd.Flags().Bool("etcd-persistent-storage", true, "Use persistent volume for etcd. Defaults to 'true'.")
cmd.Flags().Bool("dry-run", false, "dry run without sending commands to server.") cmd.Flags().Bool("dry-run", false, "dry run without sending commands to server.")
cmd.Flags().String("apiserver-arg-overrides", "", "comma separated list of federation-apiserver arguments to override: Example \"--arg1=value1,--arg2=value2...\"")
cmd.Flags().String("controllermanager-arg-overrides", "", "comma separated list of federation-controller-manager arguments to override: Example \"--arg1=value1,--arg2=value2...\"")
cmd.Flags().String("storage-backend", "etcd2", "The storage backend for persistence. Options: 'etcd2' (default), 'etcd3'.") cmd.Flags().String("storage-backend", "etcd2", "The storage backend for persistence. Options: 'etcd2' (default), 'etcd3'.")
cmd.Flags().String(apiserverServiceTypeFlag, string(v1.ServiceTypeLoadBalancer), "The type of service to create for federation API server. Options: 'LoadBalancer' (default), 'NodePort'.") cmd.Flags().String(apiserverServiceTypeFlag, string(v1.ServiceTypeLoadBalancer), "The type of service to create for federation API server. Options: 'LoadBalancer' (default), 'NodePort'.")
cmd.Flags().String(apiserverAdvertiseAddressFlag, "", "Preferred address to advertise api server nodeport service. Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.") cmd.Flags().String(apiserverAdvertiseAddressFlag, "", "Preferred address to advertise api server nodeport service. Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.")
...@@ -184,6 +187,14 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman ...@@ -184,6 +187,14 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
return fmt.Errorf("%s should be passed only with '%s=NodePort'", apiserverAdvertiseAddressFlag, apiserverServiceTypeFlag) return fmt.Errorf("%s should be passed only with '%s=NodePort'", apiserverAdvertiseAddressFlag, apiserverServiceTypeFlag)
} }
} }
apiserverArgOverrides, err := marshallOverrides(cmdutil.GetFlagString(cmd, "apiserver-arg-overrides"))
if err != nil {
return fmt.Errorf("Error marshalling --apiserver-arg-overrides: %v", err)
}
cmArgOverrides, err := marshallOverrides(cmdutil.GetFlagString(cmd, "controllermanager-arg-overrides"))
if err != nil {
return fmt.Errorf("Error marshalling --controllermanager-arg-overrides: %v", err)
}
hostFactory := config.HostFactory(initFlags.Host, initFlags.Kubeconfig) hostFactory := config.HostFactory(initFlags.Host, initFlags.Kubeconfig)
hostClientset, err := hostFactory.ClientSet() hostClientset, err := hostFactory.ClientSet()
...@@ -245,7 +256,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman ...@@ -245,7 +256,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
} }
// 6. Create federation API server // 6. Create federation API server
_, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, advertiseAddress, storageBackend, pvc, dryRun) _, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, advertiseAddress, storageBackend, apiserverArgOverrides, pvc, dryRun)
if err != nil { if err != nil {
return err return err
} }
...@@ -266,7 +277,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman ...@@ -266,7 +277,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
} }
// 7c. Create federation controller manager deployment. // 7c. Create federation controller manager deployment.
_, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider, sa.Name, dryRun) _, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider, sa.Name, cmArgOverrides, dryRun)
if err != nil { if err != nil {
return err return err
} }
...@@ -518,24 +529,29 @@ func createPVC(clientset *client.Clientset, namespace, svcName, etcdPVCapacity s ...@@ -518,24 +529,29 @@ func createPVC(clientset *client.Clientset, namespace, svcName, etcdPVCapacity s
return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc) return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc)
} }
func createAPIServer(clientset *client.Clientset, namespace, name, image, credentialsName, advertiseAddress, storageBackend string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) { func createAPIServer(clientset *client.Clientset, namespace, name, image, credentialsName, advertiseAddress, storageBackend string, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) {
command := []string{ command := []string{
"/hyperkube", "/hyperkube",
"federation-apiserver", "federation-apiserver",
"--bind-address=0.0.0.0", }
"--etcd-servers=http://localhost:2379", argsMap := map[string]string{
"--secure-port=443", "--bind-address": "0.0.0.0",
"--client-ca-file=/etc/federation/apiserver/ca.crt", "--etcd-servers": "http://localhost:2379",
"--tls-cert-file=/etc/federation/apiserver/server.crt", "--secure-port": "443",
"--tls-private-key-file=/etc/federation/apiserver/server.key", "--client-ca-file": "/etc/federation/apiserver/ca.crt",
"--admission-control=NamespaceLifecycle", "--tls-cert-file": "/etc/federation/apiserver/server.crt",
fmt.Sprintf("--storage-backend=%s", storageBackend), "--tls-private-key-file": "/etc/federation/apiserver/server.key",
"--admission-control": "NamespaceLifecycle",
} }
argsMap["--storage-backend"] = storageBackend
if advertiseAddress != "" { if advertiseAddress != "" {
command = append(command, fmt.Sprintf("--advertise-address=%s", advertiseAddress)) argsMap["--advertise-address"] = advertiseAddress
} }
args := argMapsToArgStrings(argsMap, argOverrides)
command = append(command, args...)
dep := &extensions.Deployment{ dep := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
...@@ -676,7 +692,24 @@ func createRoleBindings(clientset *client.Clientset, namespace, saName string, d ...@@ -676,7 +692,24 @@ func createRoleBindings(clientset *client.Clientset, namespace, saName string, d
return newRole, newRolebinding, err return newRole, newRolebinding, err
} }
func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider, saName string, dryRun bool) (*extensions.Deployment, error) { func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider, saName string, argOverrides map[string]string, dryRun bool) (*extensions.Deployment, error) {
command := []string{
"/hyperkube",
"federation-controller-manager",
}
argsMap := map[string]string{
"--kubeconfig": "/etc/federation/controller-manager/kubeconfig",
"--dns-provider-config": "",
}
argsMap["--master"] = fmt.Sprintf("https://%s", svcName)
argsMap["--dns-provider"] = dnsProvider
argsMap["--federation-name"] = name
argsMap["--zone-name"] = dnsZoneName
args := argMapsToArgStrings(argsMap, argOverrides)
command = append(command, args...)
dep := &extensions.Deployment{ dep := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: cmName, Name: cmName,
...@@ -693,18 +726,9 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa ...@@ -693,18 +726,9 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa
Spec: api.PodSpec{ Spec: api.PodSpec{
Containers: []api.Container{ Containers: []api.Container{
{ {
Name: "controller-manager", Name: "controller-manager",
Image: image, Image: image,
Command: []string{ Command: command,
"/hyperkube",
"federation-controller-manager",
fmt.Sprintf("--master=https://%s", svcName),
"--kubeconfig=/etc/federation/controller-manager/kubeconfig",
fmt.Sprintf("--dns-provider=%s", dnsProvider),
"--dns-provider-config=",
fmt.Sprintf("--federation-name=%s", name),
fmt.Sprintf("--zone-name=%s", dnsZoneName),
},
VolumeMounts: []api.VolumeMount{ VolumeMounts: []api.VolumeMount{
{ {
Name: kubeconfigName, Name: kubeconfigName,
...@@ -746,6 +770,41 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa ...@@ -746,6 +770,41 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa
return clientset.Extensions().Deployments(namespace).Create(dep) return clientset.Extensions().Deployments(namespace).Create(dep)
} }
func marshallOverrides(overrideArgString string) (map[string]string, error) {
if overrideArgString == "" {
return nil, nil
}
argsMap := make(map[string]string)
overrideArgs := strings.Split(overrideArgString, ",")
for _, overrideArg := range overrideArgs {
splitArg := strings.Split(overrideArg, "=")
if len(splitArg) != 2 {
return nil, fmt.Errorf("wrong format for override arg: %s", overrideArg)
}
key := strings.TrimSpace(splitArg[0])
val := strings.TrimSpace(splitArg[1])
if len(key) == 0 {
return nil, fmt.Errorf("wrong format for override arg: %s, arg name cannot be empty", overrideArg)
}
argsMap[key] = val
}
return argsMap, nil
}
func argMapsToArgStrings(argsMap, overrides map[string]string) []string {
for key, val := range overrides {
argsMap[key] = val
}
args := []string{}
for key, value := range argsMap {
args = append(args, fmt.Sprintf("%s=%s", key, value))
}
// This is needed for the unit test deep copy to get an exact match
sort.Strings(args)
return args
}
func waitForPods(clientset *client.Clientset, fedPods []string, namespace string) error { func waitForPods(clientset *client.Clientset, fedPods []string, namespace string) error {
err := wait.PollInfinite(podWaitInterval, func() (bool, error) { err := wait.PollInfinite(podWaitInterval, func() (bool, error) {
podCheck := len(fedPods) podCheck := len(fedPods)
......
...@@ -23,6 +23,7 @@ api-server-advertise-address ...@@ -23,6 +23,7 @@ api-server-advertise-address
api-server-service-type api-server-service-type
api-token api-token
api-version api-version
apiserver-arg-overrides
apiserver-count apiserver-count
apiserver-count apiserver-count
audit-log-maxage audit-log-maxage
...@@ -114,6 +115,7 @@ container-runtime ...@@ -114,6 +115,7 @@ container-runtime
container-runtime-endpoint container-runtime-endpoint
contain-pod-resources contain-pod-resources
contention-profiling contention-profiling
controllermanager-arg-overrides
controller-start-interval controller-start-interval
cors-allowed-origins cors-allowed-origins
cpu-cfs-quota cpu-cfs-quota
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment