Skip to content

Commit

Permalink
Merge pull request #3330 from gambol99/limit_dns_controller
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue. .

DNS Controller Limitation

The current implementation does not place any limitation on the dns annontation which the dns-controller can consume. In a multi-tenented environment we have to ensure certain safe guards are met, so users can't by accident or intentionally alter our internal dns. Note; the current behaviour has not been changed;

- added the --watch-namespace option to the dns controller and WatchNamespace to the spec
- cleaned up area of the code where possible or related
- fixed an vetting issues that i came across on the journey
- renamed the dns-controller watcher files
  • Loading branch information
Kubernetes Submit Queue authored Sep 22, 2017
2 parents 79cc0fc + b647956 commit e96c13b
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 249 deletions.
99 changes: 45 additions & 54 deletions dns-controller/cmd/dns-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,50 @@ import (
"os"
"strings"

"github.com/golang/glog"
"github.com/spf13/pflag"
"k8s.io/client-go/kubernetes"
"k8s.io/kops/dns-controller/pkg/dns"
"k8s.io/kops/dns-controller/pkg/watchers"
"k8s.io/kops/protokube/pkg/gossip"
gossipdns "k8s.io/kops/protokube/pkg/gossip/dns"
gossipdnsprovider "k8s.io/kops/protokube/pkg/gossip/dns/provider"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
"k8s.io/kops/protokube/pkg/gossip/mesh"

"k8s.io/client-go/kubernetes"
"github.com/golang/glog"
"github.com/spf13/pflag"
"k8s.io/client-go/rest"
"k8s.io/kops/protokube/pkg/gossip/mesh"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
_ "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/aws/route53"
k8scoredns "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/coredns"
_ "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/google/clouddns"
)

var (
flags = pflag.NewFlagSet("", pflag.ExitOnError)

// value overwritten during build. This can be used to resolve issues.
flags = pflag.NewFlagSet("", pflag.ExitOnError)
BuildVersion = "0.1"
)

func main() {
fmt.Printf("dns-controller version %s\n", BuildVersion)
var dnsServer, dnsProviderID, gossipListen, gossipSecret, watchNamespace string
var gossipSeeds, zones []string
var watchIngress bool

// Be sure to get the glog flags
glog.Flush()

dnsProviderId := "aws-route53"
flags.StringVar(&dnsProviderId, "dns", dnsProviderId, "DNS provider we should use (aws-route53, google-clouddns, coredns, gossip)")

gossipListen := "0.0.0.0:3998"
flags.StringVar(&gossipListen, "gossip-listen", gossipListen, "The address on which to listen if gossip is enabled")

var gossipSeeds []string
flag.StringVar(&dnsServer, "dns-server", "", "DNS Server")
flags.BoolVar(&watchIngress, "watch-ingress", true, "Configure hostnames found in ingress resources")
flags.StringSliceVar(&gossipSeeds, "gossip-seed", gossipSeeds, "If set, will enable gossip zones and seed using the provided addresses")

var gossipSecret string
flags.StringVar(&gossipSecret, "gossip-secret", gossipSecret, "Secret to use to secure gossip")

var zones []string
flags.StringSliceVarP(&zones, "zone", "z", []string{}, "Configure permitted zones and their mappings")

watchIngress := true
flags.BoolVar(&watchIngress, "watch-ingress", watchIngress, "Configure hostnames found in ingress resources")

dnsServer := ""
flag.StringVar(&dnsServer, "dns-server", dnsServer, "DNS Server")

flags.StringVar(&dnsProviderID, "dns", "aws-route53", "DNS provider we should use (aws-route53, google-clouddns, coredns, gossip)")
flags.StringVar(&gossipListen, "gossip-listen", "0.0.0.0:3998", "The address on which to listen if gossip is enabled")
flags.StringVar(&gossipSecret, "gossip-secret", gossipSecret, "Secret to use to secure gossip")
flags.StringVar(&watchNamespace, "watch-namespace", "", "Limits the functionality for pods, services and ingress to specific namespace, by default all")
// Trick to avoid 'logging before flag.Parse' warning
flag.CommandLine.Parse([]string{})

flag.Set("logtostderr", "true")

flags.AddGoFlagSet(flag.CommandLine)

flags.Parse(os.Args)

zoneRules, err := dns.ParseZoneRules(zones)
Expand All @@ -96,33 +82,28 @@ func main() {
os.Exit(1)
}

kubeClient, err := kubernetes.NewForConfig(config)
client, err := kubernetes.NewForConfig(config)
if err != nil {
glog.Fatalf("error building REST client: %v", err)
}

//kubeExtensionsClient, err := client_extensions.NewForConfig(config)
//if err != nil {
// glog.Fatalf("error building extensions REST client: %v", err)
//}

var dnsProviders []dnsprovider.Interface
if dnsProviderId != "gossip" {
if dnsProviderID != "gossip" {
var file io.Reader
if dnsProviderId == k8scoredns.ProviderName {
if dnsProviderID == k8scoredns.ProviderName {
var lines []string
lines = append(lines, "etcd-endpoints = "+dnsServer)
lines = append(lines, "zones = "+zones[0])
config := "[global]\n" + strings.Join(lines, "\n") + "\n"
file = bytes.NewReader([]byte(config))
}
dnsProvider, err := dnsprovider.GetDnsProvider(dnsProviderId, file)
dnsProvider, err := dnsprovider.GetDnsProvider(dnsProviderID, file)
if err != nil {
glog.Errorf("Error initializing DNS provider %q: %v", dnsProviderId, err)
glog.Errorf("Error initializing DNS provider %q: %v", dnsProviderID, err)
os.Exit(1)
}
if dnsProvider == nil {
glog.Errorf("DNS provider was nil %q: %v", dnsProviderId, err)
glog.Errorf("DNS provider was nil %q: %v", dnsProviderID, err)
os.Exit(1)
}
dnsProviders = append(dnsProviders, dnsProvider)
Expand Down Expand Up @@ -172,30 +153,40 @@ func main() {
os.Exit(1)
}

nodeController, err := watchers.NewNodeController(kubeClient, dnsController)
if err != nil {
glog.Errorf("Error building node controller: %v", err)
// @step: initialize the watchers
if err := initializeWatchers(client, dnsController, watchNamespace, watchIngress); err != nil {
glog.Errorf("%s", err)
os.Exit(1)
}

podController, err := watchers.NewPodController(kubeClient, dnsController)
// start and wait on the dns controller
dnsController.Run()
}

// initializeWatchers is responsible for creating the watchers
func initializeWatchers(client kubernetes.Interface, dnsctl *dns.DNSController, namespace string, watchIngress bool) error {
glog.V(1).Info("initializing the watch controllers, namespace: %q", namespace)

nodeController, err := watchers.NewNodeController(client, dnsctl)
if err != nil {
return fmt.Errorf("failed to initialize the node controller, error: %v", err)
}

podController, err := watchers.NewPodController(client, dnsctl, namespace)
if err != nil {
glog.Errorf("Error building pod controller: %v", err)
os.Exit(1)
return fmt.Errorf("failed to initialize the pod controller, error: %v", err)
}

serviceController, err := watchers.NewServiceController(kubeClient, dnsController)
serviceController, err := watchers.NewServiceController(client, dnsctl, namespace)
if err != nil {
glog.Errorf("Error building service controller: %v", err)
os.Exit(1)
return fmt.Errorf("failed to initialize the service controller, error: %v", err)
}

var ingressController *watchers.IngressController
if watchIngress {
ingressController, err = watchers.NewIngressController(kubeClient, dnsController)
ingressController, err = watchers.NewIngressController(client, dnsctl, namespace)
if err != nil {
glog.Errorf("Error building ingress controller: %v", err)
os.Exit(1)
return fmt.Errorf("failed to initialize the ingress controller, error: %v", err)
}
} else {
glog.Infof("Ingress controller disabled")
Expand All @@ -205,9 +196,9 @@ func main() {
go podController.Run()
go serviceController.Run()

if ingressController != nil {
if watchIngress {
go ingressController.Run()
}

dnsController.Run()
return nil
}
8 changes: 4 additions & 4 deletions dns-controller/pkg/watchers/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ limitations under the License.

package watchers

// AnnotationNameDnsExternal is used to set up a DNS name for accessing the resource from outside the cluster
// AnnotationNameDNSExternal is used to set up a DNS name for accessing the resource from outside the cluster
// For a service of Type=LoadBalancer, it would map to the external LB hostname or IP
const AnnotationNameDnsExternal = "dns.alpha.kubernetes.io/external"
const AnnotationNameDNSExternal = "dns.alpha.kubernetes.io/external"

// AnnotationNameDnsInternal is used to set up a DNS name for accessing the resource from inside the cluster
// AnnotationNameDNSInternal is used to set up a DNS name for accessing the resource from inside the cluster
// This is only supported on Pods currently, and maps to the Internal address
const AnnotationNameDnsInternal = "dns.alpha.kubernetes.io/internal"
const AnnotationNameDNSInternal = "dns.alpha.kubernetes.io/internal"
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,33 @@ import (
"time"

"github.com/golang/glog"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/apis/extensions/v1beta1"

"k8s.io/kops/dns-controller/pkg/dns"
"k8s.io/kops/dns-controller/pkg/util"
)

// IngressController watches for Ingress objects with dns labels
type IngressController struct {
util.Stoppable
kubeClient kubernetes.Interface
scope dns.Scope
client kubernetes.Interface
namespace string
scope dns.Scope
}

// newIngressController creates a ingressController
func NewIngressController(kubeClient kubernetes.Interface, dns dns.Context) (*IngressController, error) {
// NewIngressController creates a IngressController
func NewIngressController(client kubernetes.Interface, dns dns.Context, namespace string) (*IngressController, error) {
scope, err := dns.CreateScope("ingress")
if err != nil {
return nil, fmt.Errorf("error building dns scope: %v", err)
}
c := &IngressController{
kubeClient: kubeClient,
scope: scope,
client: client,
namespace: namespace,
scope: scope,
}

return c, nil
Expand All @@ -67,7 +69,7 @@ func (c *IngressController) runWatcher(stopCh <-chan struct{}) {
var listOpts metav1.ListOptions
glog.V(4).Infof("querying without label filter")

ingressList, err := c.kubeClient.ExtensionsV1beta1().Ingresses("").List(listOpts)
ingressList, err := c.client.ExtensionsV1beta1().Ingresses(c.namespace).List(listOpts)
if err != nil {
return false, fmt.Errorf("error listing ingresss: %v", err)
}
Expand All @@ -80,7 +82,7 @@ func (c *IngressController) runWatcher(stopCh <-chan struct{}) {

listOpts.Watch = true
listOpts.ResourceVersion = ingressList.ResourceVersion
watcher, err := c.kubeClient.ExtensionsV1beta1().Ingresses("").Watch(listOpts)
watcher, err := c.client.ExtensionsV1beta1().Ingresses(c.namespace).Watch(listOpts)
if err != nil {
return false, fmt.Errorf("error watching ingresss: %v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,33 @@ import (
"fmt"
"time"

"k8s.io/kops/dns-controller/pkg/dns"
"k8s.io/kops/dns-controller/pkg/util"
kopsutil "k8s.io/kops/pkg/apis/kops/util"

"github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/kops/dns-controller/pkg/dns"
"k8s.io/kops/dns-controller/pkg/util"
kopsutil "k8s.io/kops/pkg/apis/kops/util"
)

// NodeController watches for nodes
type NodeController struct {
util.Stoppable
kubeClient kubernetes.Interface
scope dns.Scope
client kubernetes.Interface
scope dns.Scope
}

// newNodeController creates a nodeController
func NewNodeController(kubeClient kubernetes.Interface, dns dns.Context) (*NodeController, error) {
// NewNodeController creates a NodeController
func NewNodeController(client kubernetes.Interface, dns dns.Context) (*NodeController, error) {
scope, err := dns.CreateScope("node")
if err != nil {
return nil, fmt.Errorf("error building dns scope: %v", err)
}
c := &NodeController{
kubeClient: kubeClient,
scope: scope,
client: client,
scope: scope,
}

return c, nil
Expand All @@ -68,7 +69,7 @@ func (c *NodeController) runWatcher(stopCh <-chan struct{}) {
glog.V(4).Infof("querying without field filter")

// Note we need to watch all the nodes, to set up alias targets
nodeList, err := c.kubeClient.CoreV1().Nodes().List(listOpts)
nodeList, err := c.client.CoreV1().Nodes().List(listOpts)
if err != nil {
return false, fmt.Errorf("error listing nodes: %v", err)
}
Expand All @@ -81,7 +82,7 @@ func (c *NodeController) runWatcher(stopCh <-chan struct{}) {

listOpts.Watch = true
listOpts.ResourceVersion = nodeList.ResourceVersion
watcher, err := c.kubeClient.CoreV1().Nodes().Watch(listOpts)
watcher, err := c.client.CoreV1().Nodes().Watch(listOpts)
if err != nil {
return false, fmt.Errorf("error watching nodes: %v", err)
}
Expand Down Expand Up @@ -152,7 +153,7 @@ func (c *NodeController) updateNodeRecords(node *v1.Node) {
// }
//}
//
//dnsLabelInternal := node.Annotations[AnnotationNameDnsInternal]
//dnsLabelInternal := node.Annotations[AnnotationNameDNSInternal]
//if dnsLabelInternal != "" {
// var ips []string
// for _, a := range node.Status.Addresses {
Expand Down
Loading

0 comments on commit e96c13b

Please sign in to comment.