Skip to content

Commit

Permalink
DNS Controller Limitation
Browse files Browse the repository at this point in the history
The current implementation does not place any limitation on the dns annontation which the dns-controller can consume. In a multi-tenented environment was have to ensure certain safe guards are met, so users can't byt 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
gambol99 committed Sep 2, 2017
1 parent 2fd0ddb commit 589e6e0
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 253 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 589e6e0

Please sign in to comment.