From 77fa364fb6310d58c966029276ee5bf4370629d4 Mon Sep 17 00:00:00 2001 From: Qing Hao Date: Wed, 17 Jul 2019 11:21:47 +0800 Subject: [PATCH] add configmap (#91) --- Dockerfile | 2 +- cmd/nginx/flags.go | 4 ++++ pkg/ingress/controller/controller.go | 1 + pkg/ingress/controller/listers.go | 35 ++++++++++++++++++++++++++++ pkg/ingress/controller/nginx.go | 24 ++++++++++++++++++- pkg/ingress/types.go | 1 + 6 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 313822ca67..977ee355f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ LABEL org.label-schema.vendor="IBM" \ ENV AUTH_ERROR_PAGE_DIR_PATH=/opt/ibm/router/nginx/conf/errorpages SECRET_KEY_FILE_PATH=/etc/cfc/conf/auth-token-secret OIDC_ENABLE=false ADMINROUTER_ACTIVATE_AUTH_MODULE=true PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/ibm/router/nginx/sbin -RUN yum update \ +RUN yum update -y \ && yum install -y openssl python python-devl \ && curl -o /etc/yum.repos.d/alsadi-dumb-init-epel-7.repo -sSL https://copr.fedorainfracloud.org/coprs/alsadi/dumb-init/repo/epel-7/alsadi-dumb-init-epel-7.repo \ && yum install -y dumb-init \ diff --git a/cmd/nginx/flags.go b/cmd/nginx/flags.go index 3842c177aa..953c31d69c 100644 --- a/cmd/nginx/flags.go +++ b/cmd/nginx/flags.go @@ -42,6 +42,9 @@ func parseFlags() (bool, *controller.Configuration, error) { "Kubernetes cluster and local discovery is attempted.") kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.") + configMap = flags.String("configmap", "", + `Name of the ConfigMap that contains the custom configuration to use`) + httpPort = flags.Int("http-port", 8080, `Indicates the port to use for HTTP traffic`) httpsPort = flags.Int("https-port", 8443, `Indicates the port to use for HTTPS traffic`) @@ -101,6 +104,7 @@ func parseFlags() (bool, *controller.Configuration, error) { ElectionID: *electionID, ResyncPeriod: *resyncPeriod, Namespace: *watchNamespace, + ConfigMapName: *configMap, SyncRateLimit: *syncRateLimit, DefaultSSLCertificate: *defSSLCertificate, ListenPorts: &ngx_config.ListenPorts{ diff --git a/pkg/ingress/controller/controller.go b/pkg/ingress/controller/controller.go index 3e038c416a..b087413eb8 100644 --- a/pkg/ingress/controller/controller.go +++ b/pkg/ingress/controller/controller.go @@ -48,6 +48,7 @@ type Configuration struct { Client clientset.Interface ResyncPeriod time.Duration + ConfigMapName string Namespace string diff --git a/pkg/ingress/controller/listers.go b/pkg/ingress/controller/listers.go index ed31476508..db18e37f3d 100644 --- a/pkg/ingress/controller/listers.go +++ b/pkg/ingress/controller/listers.go @@ -38,6 +38,7 @@ type cacheController struct { Endpoint cache.Controller Service cache.Controller Secret cache.Controller + Configmap cache.Controller } func (c *cacheController) Run(stopCh chan struct{}) { @@ -45,6 +46,7 @@ func (c *cacheController) Run(stopCh chan struct{}) { go c.Endpoint.Run(stopCh) go c.Service.Run(stopCh) go c.Secret.Run(stopCh) + go c.Configmap.Run(stopCh) // Wait for all involved caches to be synced, before processing items from the queue is started if !cache.WaitForCacheSync(stopCh, @@ -52,6 +54,7 @@ func (c *cacheController) Run(stopCh chan struct{}) { c.Endpoint.HasSynced, c.Service.HasSynced, c.Secret.HasSynced, + c.Configmap.HasSynced, ) { runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync")) } @@ -164,6 +167,34 @@ func (n *NGINXController) createListers(stopCh chan struct{}) (*ingress.StoreLis }, } + mapEventHandler := cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + upCmap := obj.(*apiv1.ConfigMap) + mapKey := fmt.Sprintf("%s/%s", upCmap.Namespace, upCmap.Name) + if mapKey == n.cfg.ConfigMapName { + glog.V(2).Infof("adding configmap %v to backend", mapKey) + n.SetConfig(upCmap) + n.SetForceReload(true) + } + }, + UpdateFunc: func(old, cur interface{}) { + if !reflect.DeepEqual(old, cur) { + upCmap := cur.(*apiv1.ConfigMap) + mapKey := fmt.Sprintf("%s/%s", upCmap.Namespace, upCmap.Name) + if mapKey == n.cfg.ConfigMapName { + glog.V(2).Infof("updating configmap backend (%v)", mapKey) + n.SetConfig(upCmap) + n.SetForceReload(true) + } + // updates to configuration configmaps can trigger an update + if mapKey == n.cfg.ConfigMapName { + n.recorder.Eventf(upCmap, apiv1.EventTypeNormal, "UPDATE", fmt.Sprintf("ConfigMap %v", mapKey)) + n.syncQueue.Enqueue(cur) + } + } + }, + } + watchNs := apiv1.NamespaceAll if n.cfg.Namespace != apiv1.NamespaceAll { watchNs = n.cfg.Namespace @@ -186,6 +217,10 @@ func (n *NGINXController) createListers(stopCh chan struct{}) (*ingress.StoreLis cache.NewListWatchFromClient(n.cfg.Client.CoreV1().RESTClient(), "secrets", watchNs, fields.Everything()), &apiv1.Secret{}, n.cfg.ResyncPeriod, secrEventHandler) + lister.ConfigMap.Store, controller.Configmap = cache.NewInformer( + cache.NewListWatchFromClient(n.cfg.Client.CoreV1().RESTClient(), "configmaps", watchNs, fields.Everything()), + &apiv1.ConfigMap{}, n.cfg.ResyncPeriod, mapEventHandler) + lister.Service.Store, controller.Service = cache.NewInformer( cache.NewListWatchFromClient(n.cfg.Client.CoreV1().RESTClient(), "services", n.cfg.Namespace, fields.Everything()), &apiv1.Service{}, n.cfg.ResyncPeriod, eventHandler) diff --git a/pkg/ingress/controller/nginx.go b/pkg/ingress/controller/nginx.go index a3d091272c..6db9292623 100644 --- a/pkg/ingress/controller/nginx.go +++ b/pkg/ingress/controller/nginx.go @@ -10,6 +10,7 @@ package controller import ( "bytes" + "encoding/base64" "errors" "fmt" "io/ioutil" @@ -331,6 +332,27 @@ func (n *NGINXController) start(cmd *exec.Cmd) { }() } +// SetConfig sets the configured configmap +func (n *NGINXController) SetConfig(cmap *apiv1.ConfigMap) { + n.configmap = cmap + + m := map[string]string{} + if cmap != nil { + m = cmap.Data + } + + c := ngx_template.ReadConfig(m) + if c.SSLSessionTicketKey != "" { + d, err := base64.StdEncoding.DecodeString(c.SSLSessionTicketKey) + if err != nil { + glog.Warningf("unexpected error decoding key ssl-session-ticket-key: %v", err) + c.SSLSessionTicketKey = "" + } + ioutil.WriteFile("/etc/nginx/tickets.key", d, 0644) + } + +} + // OnUpdate is called periodically by syncQueue to keep the configuration in sync. // // 1. converts configmap configuration to custom configuration object @@ -340,7 +362,7 @@ func (n *NGINXController) start(cmd *exec.Cmd) { // returning nill implies the backend will be reloaded. // if an error is returned means requeue the update func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error { - cfg := ngx_config.NewDefault() + cfg := ngx_template.ReadConfig(n.configmap.Data) cfg.Resolver = n.resolver // the limit of open files is per worker process diff --git a/pkg/ingress/types.go b/pkg/ingress/types.go index 013ba875ae..56739df062 100644 --- a/pkg/ingress/types.go +++ b/pkg/ingress/types.go @@ -44,6 +44,7 @@ type StoreLister struct { Service store.ServiceLister Endpoint store.EndpointLister Secret store.SecretLister + ConfigMap store.ConfigMapLister IngressAnnotation store.IngressAnnotationsLister }