Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions controllers/clusterwidenetworkpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ type ClusterwideNetworkPolicyReconciler struct {
Ctx context.Context
Recorder record.EventRecorder

Interval time.Duration
DnsProxy *dns.DNSProxy
SkipDNS bool
Interval time.Duration
FQDNStateSyncInterval time.Duration
DnsProxy *dns.DNSProxy
SkipDNS bool
}

// SetupWithManager configures this controller to run in schedule
Expand Down Expand Up @@ -145,7 +146,7 @@ func (r *ClusterwideNetworkPolicyReconciler) manageDNSProxy(

if enableDNS && r.DnsProxy == nil {
r.Log.Info("DNS Proxy is initialized")
if r.DnsProxy, err = dns.NewDNSProxy(r.Ctx, f.Spec.DNSServerAddress, f.Spec.DNSPort, r.ShootClient, ctrl.Log.WithName("DNS proxy")); err != nil {
if r.DnsProxy, err = dns.NewDNSProxy(r.Ctx, f.Spec.DNSServerAddress, f.Spec.DNSPort, r.FQDNStateSyncInterval, r.ShootClient, ctrl.Log.WithName("DNS proxy")); err != nil {
return fmt.Errorf("failed to init DNS proxy: %w", err)
}
go r.DnsProxy.Run()
Expand Down
33 changes: 18 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ func init() {

func main() {
var (
logLevel string
isVersion bool
metricsAddr string
enableIDS bool
enableSignatureCheck bool
hostsFile string
firewallName string
kubeconfigPath = os.Getenv("KUBECONFIG")
logLevel string
isVersion bool
metricsAddr string
enableIDS bool
enableSignatureCheck bool
hostsFile string
firewallName string
fqdnStateSyncInterval time.Duration
kubeconfigPath = os.Getenv("KUBECONFIG")
)

flag.StringVar(&logLevel, "log-level", "info", "the log level of the controller")
Expand All @@ -73,6 +74,7 @@ func main() {
flag.StringVar(&hostsFile, "hosts-file", "/etc/hosts", "The hosts file to manipulate for the droptailer.")
flag.BoolVar(&enableSignatureCheck, "enable-signature-check", true, "Set this to false to ignore signature checking.")
flag.StringVar(&firewallName, "firewall-name", "", "the name of the firewall resource in the seed cluster to reconcile (defaults to hostname)")
flag.DurationVar(&fqdnStateSyncInterval, "fqdnstate-sync-interval", 10*time.Second, "minimum interval between fqdn state configmap syncs")

if _, err := os.Stat(seedKubeconfigPath); err == nil || os.IsExist(err) {
// controller-runtime registered this flag already, so we can use it
Expand Down Expand Up @@ -265,13 +267,14 @@ func main() {

// ClusterwideNetworkPolicy Reconciler
if err = (&controllers.ClusterwideNetworkPolicyReconciler{
SeedClient: seedMgr.GetClient(),
ShootClient: shootMgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ClusterwideNetworkPolicy"),
Ctx: ctx,
Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck
FirewallName: firewallName,
SeedNamespace: seedNamespace,
SeedClient: seedMgr.GetClient(),
ShootClient: shootMgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ClusterwideNetworkPolicy"),
Ctx: ctx,
Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck
FirewallName: firewallName,
SeedNamespace: seedNamespace,
FQDNStateSyncInterval: fqdnStateSyncInterval,
}).SetupWithManager(shootMgr); err != nil {
l.Error("unable to create clusterwidenetworkpolicy controller", "error", err)
panic(err)
Expand Down
111 changes: 79 additions & 32 deletions pkg/dns/dnscache.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,29 @@ type cacheEntry struct {
type DNSCache struct {
sync.RWMutex

log logr.Logger
fqdnToEntry map[string]cacheEntry
setNames map[string]struct{}
dnsServerAddr string
shootClient client.Client
ctx context.Context
ipv4Enabled bool
ipv6Enabled bool
log logr.Logger
fqdnToEntry map[string]cacheEntry
setNames map[string]struct{}
dnsServerAddr string
shootClient client.Client
ctx context.Context
ipv4Enabled bool
ipv6Enabled bool
fqdnStateSyncInterval time.Duration
stateDirty bool
}

func newDNSCache(ctx context.Context, dns string, ipv4Enabled, ipv6Enabled bool, shootClient client.Client, log logr.Logger) (*DNSCache, error) {
func newDNSCache(ctx context.Context, dns string, ipv4Enabled, ipv6Enabled bool, fqdnStateSyncInterval time.Duration, shootClient client.Client, log logr.Logger) (*DNSCache, error) {
c := DNSCache{
log: log,
fqdnToEntry: map[string]cacheEntry{},
setNames: map[string]struct{}{},
dnsServerAddr: dns,
shootClient: shootClient,
ctx: ctx,
ipv4Enabled: ipv4Enabled,
ipv6Enabled: ipv6Enabled,
log: log,
fqdnToEntry: map[string]cacheEntry{},
setNames: map[string]struct{}{},
dnsServerAddr: dns,
shootClient: shootClient,
ctx: ctx,
ipv4Enabled: ipv4Enabled,
ipv6Enabled: ipv6Enabled,
fqdnStateSyncInterval: fqdnStateSyncInterval,
}

nn := types.NamespacedName{Name: fqdnStateConfigmapName, Namespace: fqdnStateNamespace}
Expand All @@ -150,20 +153,19 @@ func newDNSCache(ctx context.Context, dns string, ipv4Enabled, ipv6Enabled bool,
c.log.Error(err, "error reading fqndstate configmap")
return nil, err
}
if scm.Data == nil {
if apierrors.IsNotFound(err) || scm.Data == nil {
c.log.V(4).Info("DEBUG fqdnstate cm not found or contains no data", "cm", scm)
return &c, nil

}
if scm.Data[fqdnStateConfigmapKey] == "" {
} else if scm.Data[fqdnStateConfigmapKey] == "" {
c.log.Error(fmt.Errorf("error reading fqdnstate configmap, ignoring content"), "fqdnstate configmap does not contain the right key", "configmap", scm, "key", fqdnStateConfigmapKey)
return &c, nil
}
c.log.V(4).Info("DEBUG state stored in fqdnstate cm, trying to unmarshal", fqdnStateConfigmapKey, scm.Data[fqdnStateConfigmapKey])
err = yaml.UnmarshalStrict([]byte(scm.Data[fqdnStateConfigmapKey]), &c.fqdnToEntry)
if err != nil {
c.log.Info("could not unmarshal state from fqdnstate configmap, ignoring content.", "error", err)
} else {
c.log.V(4).Info("DEBUG state stored in fqdnstate cm, trying to unmarshal", fqdnStateConfigmapKey, scm.Data[fqdnStateConfigmapKey])
err = yaml.UnmarshalStrict([]byte(scm.Data[fqdnStateConfigmapKey]), &c.fqdnToEntry)
if err != nil {
c.log.Info("could not unmarshal state from fqdnstate configmap, ignoring content.", "error", err)
}
}

c.startFQDNStateSyncLoop()
return &c, nil
}

Expand Down Expand Up @@ -215,6 +217,8 @@ func (c *DNSCache) writeStateToConfigmap() error {
return err
}

c.markStateSynced()

return nil
}

Expand All @@ -227,12 +231,12 @@ func (c *DNSCache) writeStateToConfigmap() error {
}

debugLog.Info("DEBUG updated cm", "old data", cm.Data, "new data", data)
c.markStateSynced()

return nil
}

debugLog.Info("DEBUG no need to update cm, already up to date")

return nil
}

Expand Down Expand Up @@ -461,9 +465,7 @@ func (c *DNSCache) Update(lookupTime time.Time, qname string, msg *dnsgo.Msg, fq
}

if ipEntriesUpdated {
if err := c.writeStateToConfigmap(); err != nil {
c.log.V(4).Info("DEBUG could not write updated DNS cache to state configmap", "configmap", fqdnStateConfigmapName, "namespace", fqdnStateNamespace, "error", err)
}
c.markStateDirty()
}

return found, nil
Expand Down Expand Up @@ -596,3 +598,48 @@ func createRenderIPSetFromIPEntry(version IPVersion, entry *iPEntry) RenderIPSet
Version: version,
}
}

func (c *DNSCache) startFQDNStateSyncLoop() {
if c.fqdnStateSyncInterval <= 0 {
c.log.Info("fqdnstate sync interval is set to 0 or negative, skipping state sync loop")
return
}
c.log.Info("starting fqdnstate sync loop", "interval", c.fqdnStateSyncInterval)

ticker := time.NewTicker(c.fqdnStateSyncInterval)
go func() {
defer ticker.Stop()
for {
select {
case <-c.ctx.Done():
return
case <-ticker.C:
if !c.isStateDirty() {
continue
}
if err := c.writeStateToConfigmap(); err != nil {
c.log.V(4).Info("DEBUG periodic sync of fqdnstate configmap failed", "configmap", fqdnStateConfigmapName, "namespace", fqdnStateNamespace, "error", err)
}
}
}
}()
}

func (c *DNSCache) markStateDirty() {
c.Lock()
c.stateDirty = true
c.Unlock()
}

func (c *DNSCache) markStateSynced() {
c.Lock()
c.stateDirty = false
c.Unlock()
}

func (c *DNSCache) isStateDirty() bool {
c.RLock()
defer c.RUnlock()

return c.stateDirty
}
4 changes: 2 additions & 2 deletions pkg/dns/dnsproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type DNSProxy struct {
handler DNSHandler
}

func NewDNSProxy(ctx context.Context, dns string, port *uint, shootClient client.Client, log logr.Logger) (*DNSProxy, error) {
func NewDNSProxy(ctx context.Context, dns string, port *uint, fqdnStateSyncInterval time.Duration, shootClient client.Client, log logr.Logger) (*DNSProxy, error) {
if dns == "" {
dns = defaultDNSServerAddr
}
Expand All @@ -59,7 +59,7 @@ func NewDNSProxy(ctx context.Context, dns string, port *uint, shootClient client
}

backgroundCtx, cancel := context.WithCancel(ctx)
cache, err := newDNSCache(backgroundCtx, dns, true, false, shootClient, log.WithName("DNS cache"))
cache, err := newDNSCache(backgroundCtx, dns, true, false, fqdnStateSyncInterval, shootClient, log.WithName("DNS cache"))
if err != nil {
cancel()
return nil, err
Expand Down
Loading