aboutsummaryrefslogtreecommitdiff
path: root/middleware/kubernetes/kubernetes.go
diff options
context:
space:
mode:
authorGravatar Michael Richmond <mrichmon@users.noreply.github.com> 2016-08-05 18:19:51 -0700
committerGravatar GitHub <noreply@github.com> 2016-08-05 18:19:51 -0700
commit6d90b745e0faf5b73472e918cd72965dc0d93348 (patch)
tree9b86325e955a9fe5759c78f90dbe20eadbf5093d /middleware/kubernetes/kubernetes.go
parent604d2a3730fb0ce0939f19f8ec545e7719226f67 (diff)
downloadcoredns-6d90b745e0faf5b73472e918cd72965dc0d93348.tar.gz
coredns-6d90b745e0faf5b73472e918cd72965dc0d93348.tar.zst
coredns-6d90b745e0faf5b73472e918cd72965dc0d93348.zip
Switch over to k8s notification API (#202)
* Merge notification code by @aledbf and update for recent changes. * Fix travis environment to correctly build with k8s.io and forked repositories. * Refactored kubernetes Corefile parser * Added lots of Corefile parsing tests
Diffstat (limited to 'middleware/kubernetes/kubernetes.go')
-rw-r--r--middleware/kubernetes/kubernetes.go173
1 files changed, 71 insertions, 102 deletions
diff --git a/middleware/kubernetes/kubernetes.go b/middleware/kubernetes/kubernetes.go
index 6288cb394..a8d33bb7e 100644
--- a/middleware/kubernetes/kubernetes.go
+++ b/middleware/kubernetes/kubernetes.go
@@ -4,33 +4,70 @@ package kubernetes
import (
"errors"
"log"
+ "strings"
"time"
"github.com/miekg/coredns/middleware"
- k8sc "github.com/miekg/coredns/middleware/kubernetes/k8sclient"
"github.com/miekg/coredns/middleware/kubernetes/msg"
"github.com/miekg/coredns/middleware/kubernetes/nametemplate"
"github.com/miekg/coredns/middleware/kubernetes/util"
"github.com/miekg/coredns/middleware/proxy"
"github.com/miekg/dns"
+ "k8s.io/kubernetes/pkg/api"
+ "k8s.io/kubernetes/pkg/client/unversioned"
+ "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
+ clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
+)
+
+const (
+ defaultResyncPeriod = 5 * time.Minute
)
type Kubernetes struct {
Next middleware.Handler
Zones []string
Proxy proxy.Proxy // Proxy for looking up names during the resolution process
- APIConn *k8sc.K8sConnector
+ APIEndpoint string
+ APIConn *dnsController
+ ResyncPeriod time.Duration
NameTemplate *nametemplate.NameTemplate
Namespaces []string
}
+func (g *Kubernetes) StartKubeCache() error {
+ // For a custom api server or running outside a k8s cluster
+ // set URL in env.KUBERNETES_MASTER
+ loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
+ overrides := &clientcmd.ConfigOverrides{}
+ if len(g.APIEndpoint) > 0 {
+ overrides.ClusterInfo = clientcmdapi.Cluster{Server: g.APIEndpoint}
+ }
+ clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)
+ config, err := clientConfig.ClientConfig()
+ if err != nil {
+ log.Printf("[debug] error connecting to the client: %v", err)
+ return err
+ }
+ kubeClient, err := unversioned.New(config)
+
+ if err != nil {
+ log.Printf("[ERROR] Failed to create kubernetes notification controller: %v", err)
+ return err
+ }
+ g.APIConn = newdnsController(kubeClient, g.ResyncPeriod)
+
+ go g.APIConn.Run()
+
+ return err
+}
+
// getZoneForName returns the zone string that matches the name and a
// list of the DNS labels from name that are within the zone.
// For example, if "coredns.local" is a zone configured for the
// Kubernetes middleware, then getZoneForName("a.b.coredns.local")
// will return ("coredns.local", ["a", "b"]).
-func (g Kubernetes) getZoneForName(name string) (string, []string) {
+func (g *Kubernetes) getZoneForName(name string) (string, []string) {
var zone string
var serviceSegments []string
@@ -51,7 +88,14 @@ func (g Kubernetes) getZoneForName(name string) (string, []string) {
// If exact is true, it will lookup just
// this name. This is used when find matches when completing SRV lookups
// for instance.
-func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
+func (g *Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
+ // TODO: refector this.
+ // Right now GetNamespaceFromSegmentArray do not supports PRE queries
+ if strings.HasSuffix(name, arpaSuffix) {
+ ip, _ := extractIP(name)
+ records := g.getServiceRecordForIP(ip, name)
+ return records, nil
+ }
var (
serviceName string
namespace string
@@ -99,6 +143,7 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
return nil, nil
}
+ log.Printf("before g.Get(namespace, nsWildcard, serviceName, serviceWildcard): %v %v %v %v", namespace, nsWildcard, serviceName, serviceWildcard)
k8sItems, err := g.Get(namespace, nsWildcard, serviceName, serviceWildcard)
log.Printf("[debug] k8s items: %v\n", k8sItems)
if err != nil {
@@ -115,7 +160,7 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
}
// TODO: assemble name from parts found in k8s data based on name template rather than reusing query string
-func (g Kubernetes) getRecordsForServiceItems(serviceItems []k8sc.ServiceItem, values nametemplate.NameValues) []msg.Service {
+func (g *Kubernetes) getRecordsForServiceItems(serviceItems []api.Service, values nametemplate.NameValues) []msg.Service {
var records []msg.Service
for _, item := range serviceItems {
@@ -131,7 +176,7 @@ func (g Kubernetes) getRecordsForServiceItems(serviceItems []k8sc.ServiceItem, v
// Create records for each exposed port...
for _, p := range item.Spec.Ports {
log.Printf("[debug] port: %v\n", p.Port)
- s := msg.Service{Host: clusterIP, Port: p.Port}
+ s := msg.Service{Host: clusterIP, Port: int(p.Port)}
records = append(records, s)
}
}
@@ -141,22 +186,24 @@ func (g Kubernetes) getRecordsForServiceItems(serviceItems []k8sc.ServiceItem, v
}
// Get performs the call to the Kubernetes http API.
-func (g Kubernetes) Get(namespace string, nsWildcard bool, servicename string, serviceWildcard bool) ([]k8sc.ServiceItem, error) {
- serviceList, err := g.APIConn.GetServiceList()
+func (g *Kubernetes) Get(namespace string, nsWildcard bool, servicename string, serviceWildcard bool) ([]api.Service, error) {
+ serviceList := g.APIConn.GetServiceList()
+ /* TODO: Remove?
if err != nil {
log.Printf("[ERROR] Getting service list produced error: %v", err)
return nil, err
}
+ */
- var resultItems []k8sc.ServiceItem
+ var resultItems []api.Service
for _, item := range serviceList.Items {
- if symbolMatches(namespace, item.Metadata.Namespace, nsWildcard) && symbolMatches(servicename, item.Metadata.Name, serviceWildcard) {
+ if symbolMatches(namespace, item.Namespace, nsWildcard) && symbolMatches(servicename, item.Name, serviceWildcard) {
// If namespace has a wildcard, filter results against Corefile namespace list.
// (Namespaces without a wildcard were filtered before the call to this function.)
- if nsWildcard && (len(g.Namespaces) > 0) && (!util.StringInSlice(item.Metadata.Namespace, g.Namespaces)) {
- log.Printf("[debug] Namespace '%v' is not published by Corefile\n", item.Metadata.Namespace)
+ if nsWildcard && (len(g.Namespaces) > 0) && (!util.StringInSlice(item.Namespace, g.Namespaces)) {
+ log.Printf("[debug] Namespace '%v' is not published by Corefile\n", item.Namespace)
continue
}
resultItems = append(resultItems, item)
@@ -179,102 +226,24 @@ func symbolMatches(queryString string, candidateString string, wildcard bool) bo
return result
}
-// TODO: Remove these unused functions. One is related to Ttl calculation
-// Implement Ttl and priority calculation based on service count before
-// removing this code.
-/*
-// splitDNSName separates the name into DNS segments and reverses the segments.
-func (g Kubernetes) splitDNSName(name string) []string {
- l := dns.SplitDomainName(name)
-
- for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
- l[i], l[j] = l[j], l[i]
- }
-
- return l
+// kubernetesNameError checks if the error is ErrorCodeKeyNotFound from kubernetes.
+func isKubernetesNameError(err error) bool {
+ return false
}
-*/
-// skydns/local/skydns/east/staging/web
-// skydns/local/skydns/west/production/web
-//
-// skydns/local/skydns/*/*/web
-// skydns/local/skydns/*/web
-/*
-// loopNodes recursively loops through the nodes and returns all the values. The nodes' keyname
-// will be match against any wildcards when star is true.
-func (g Kubernetes) loopNodes(ns []*etcdc.Node, nameParts []string, star bool, bx map[msg.Service]bool) (sx []msg.Service, err error) {
- if bx == nil {
- bx = make(map[msg.Service]bool)
- }
-Nodes:
- for _, n := range ns {
- if n.Dir {
- nodes, err := g.loopNodes(n.Nodes, nameParts, star, bx)
- if err != nil {
- return nil, err
- }
- sx = append(sx, nodes...)
- continue
- }
- if star {
- keyParts := strings.Split(n.Key, "/")
- for i, n := range nameParts {
- if i > len(keyParts)-1 {
- // name is longer than key
- continue Nodes
- }
- if n == "*" || n == "any" {
- continue
- }
- if keyParts[i] != n {
- continue Nodes
- }
- }
- }
- serv := new(msg.Service)
- if err := json.Unmarshal([]byte(n.Value), serv); err != nil {
- return nil, err
- }
- b := msg.Service{Host: serv.Host, Port: serv.Port, Priority: serv.Priority, Weight: serv.Weight, Text: serv.Text, Key: n.Key}
- if _, ok := bx[b]; ok {
- continue
- }
- bx[b] = true
- serv.Key = n.Key
- serv.Ttl = g.Ttl(n, serv)
- if serv.Priority == 0 {
- serv.Priority = priority
- }
- sx = append(sx, *serv)
+func (g *Kubernetes) getServiceRecordForIP(ip, name string) []msg.Service {
+ svcList, err := g.APIConn.svcLister.List()
+ if err != nil {
+ return nil
}
- return sx, nil
-}
-// Ttl returns the smaller of the kubernetes TTL and the service's
-// TTL. If neither of these are set (have a zero value), a default is used.
-func (g Kubernetes) Ttl(node *etcdc.Node, serv *msg.Service) uint32 {
- kubernetesTtl := uint32(node.TTL)
-
- if kubernetesTtl == 0 && serv.Ttl == 0 {
- return ttl
- }
- if kubernetesTtl == 0 {
- return serv.Ttl
- }
- if serv.Ttl == 0 {
- return kubernetesTtl
- }
- if kubernetesTtl < serv.Ttl {
- return kubernetesTtl
+ for _, service := range svcList.Items {
+ if service.Spec.ClusterIP == ip {
+ return []msg.Service{msg.Service{Host: ip}}
+ }
}
- return serv.Ttl
-}
-*/
-// kubernetesNameError checks if the error is ErrorCodeKeyNotFound from kubernetes.
-func isKubernetesNameError(err error) bool {
- return false
+ return nil
}
const (
8b48d841077bf4cc3040&follow=1'>Collapse)AuthorFilesLines 2025-03-31[ci] release (#13513)astro@5.5.6@astrojs/vue@5.0.9@astrojs/svelte@7.0.9@astrojs/studio@0.1.6@astrojs/solid-js@5.0.7@astrojs/react@4.2.3@astrojs/preact@4.0.8@astrojs/netlify@6.2.5@astrojs/mdx@4.2.3@astrojs/markdoc@0.13.3@astrojs/db@0.14.10@astrojs/cloudflare@12.4.0@astrojs/alpinejs@0.4.5Gravatar Houston (Bot) 54-178/+238 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2025-03-31fix: update `vite` to latest version (#13526)Gravatar Junseong Park 15-101/+118 * fix: update `vite` to latest version * apply suggestion Co-authored-by: ematipico <602478+ematipico@users.noreply.github.com> 2025-03-31[ci] formatGravatar Emanuele Stoppa 3-4/+2 2025-03-31fix(i18n): return value from `preferredLocale` (#13524)Gravatar Emanuele Stoppa 5-15/+51 * fix(i18n): return value from `preferredLocale` * revert change Co-authored-by: florian-lefebvre <69633530+florian-lefebvre@users.noreply.github.com> 2025-03-31chore(tailwind): delete integration (#13511)Gravatar Florian Lefebvre 16-1083/+1 2025-03-31fix(deps): update all non-major dependencies (#13521)Gravatar renovate[bot] 14-163/+163 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> 2025-03-31[ci] formatGravatar Matt Kane 3-4/+3 2025-03-31feat(cloudflare): add KV session storage support (#13514)Gravatar Matt Kane 19-487/+490 * feat(cloudflare): add KV session storage support * Change code block language to JSONC * Comments * Use user-defined binding name * Use createCodegenDir * Remove unused import 2025-03-31fix(deps): update astro client runtimes (#13522)Gravatar renovate[bot] 4-6/+7 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> 2025-03-27fix(deps): update astro dependencies (#13498)Gravatar renovate[bot] 47-412/+427 * fix(deps): update astro dependencies * fix types shenanigans --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Emanuele Stoppa <my.burning@gmail.com> 2025-03-27[ci] formatGravatar Emanuele Stoppa 3-8/+7 2025-03-27refactor(actions): use `Omit` to avoid leaking types to shared context (#13429)Gravatar Emanuele Stoppa 5-11/+41 * wip * fix(actions): avoid mutation of action context * chore: revert changes * add changeset * Update .changeset/calm-beans-roll.md Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev> --------- Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev> 2025-03-26[ci] release (#13504)astro@5.5.5@astrojs/vue@5.0.8@astrojs/tailwind@6.0.2@astrojs/svelte@7.0.8@astrojs/studio@0.1.5@astrojs/solid-js@5.0.6@astrojs/react@4.2.2@astrojs/preact@4.0.7@astrojs/netlify@6.2.4@astrojs/mdx@4.2.2@astrojs/markdoc@0.13.2@astrojs/db@0.14.9@astrojs/cloudflare@12.3.1@astrojs/alpinejs@0.4.4Gravatar Houston (Bot) 56-132/+197 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2025-03-26[ci] formatGravatar Florian Lefebvre 2-2/+2 2025-03-26fix(astro): dynamically import actions (#13510)Gravatar Florian Lefebvre 12-51/+96 * feat: update test * feat: dynamic import * chore: changeset * Update .changeset/clever-tigers-dig.md 2025-03-26[ci] formatGravatar Matt Kane 2-2/+2 2025-03-26fix: cache raw cookie value and decode when getting (#13485)Gravatar Matt Kane 3-17/+37 * fix: cache raw cookie value and decode when getting * Add test * Add comment 2025-03-25fix: update vite (#13505)Gravatar Emanuele Stoppa 16-104/+123 * fix: update vite * use dedupe 2025-03-24[ci] formatGravatar Emanuele Stoppa 1-1/+1 2025-03-24fix(app): call renderer when routes don't match (#13483)Gravatar Emanuele Stoppa 4-1/+30 * fix(app): call renderer when routes don't match * chore: pick 404 exactly * chore: pick route differently Co-authored-by: ascorbic <213306+ascorbic@users.noreply.github.com> 2025-03-21[ci] release (#13460)astro@5.5.4@astrojs/vercel@8.1.3@astrojs/tailwind@6.0.1@astrojs/svelte@7.0.7@astrojs/preact@4.0.6@astrojs/cloudflare@12.3.0Gravatar Houston (Bot) 45-118/+119 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2025-03-21fix: better error handling on Stackblitz (#13484)Gravatar Matt Kane 2-0/+12 * fix: better error handling on Stackblitz * Remove unused imports 2025-03-21Repair server islands to work with client router (#13481)Gravatar Martin Trapp 2-6/+11 * rerun server island scripts when used with client router 2025-03-21fix: generate correct external redirects (#13480)Gravatar Matt Kane 3-4/+21 2025-03-21fix(deps): update all non-major dependencies (#13440)Gravatar renovate[bot] 24-435/+436 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> 2025-03-21[ci] formatGravatar Florian Lefebvre 2-2/+2 2025-03-21feat(cloudflare): global env (#13444)Gravatar Florian Lefebvre 6-47/+130 * feat(cloudflare): global env * fix: test 2025-03-21fix(deps): update astro client runtimes (#13474)Gravatar renovate[bot] 7-345/+348 * fix(deps): update astro client runtimes * fix: pin vite-plugin-vue --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev> 2025-03-20Small change to linking style (#13472)Gravatar Chris Swithinbank 1-1/+1 Co-authored-by: sarah11918 <5098874+sarah11918@users.noreply.github.com> 2025-03-20Add deprecation notice to Tailwind integration README (#13471)Gravatar Chris Swithinbank 2-6/+11 * Add deprecation notice to Tailwind integration README * Add changeset * Use `[docs]` link style again * update link to more direct content --------- Co-authored-by: Sarah Rainsberger <5098874+sarah11918@users.noreply.github.com> Co-authored-by: anaxite <89195061+anaxite@users.noreply.github.com> Co-authored-by: sarah11918 <5098874+sarah11918@users.noreply.github.com> Co-authored-by: Adammatthiesen <30383579+Adammatthiesen@users.noreply.github.com> Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com> 2025-03-20[ci] formatGravatar Matt Kane 2-2/+1 2025-03-20fix(preact,svelte): empty target container before rendering `client:only` ↵Gravatar Matt Kane 5-5/+41 island (#13470) * fix(preact,svelte): empty target container before rendering `client:only` island * Remove log 2025-03-20chore(renovate): group updates (#13466)Gravatar Emanuele Stoppa 1-11/+58 2025-03-19[ci] formatGravatar Matt Kane 1-3/+2 2025-03-19fix: don't attempt to move files after build with base (#13463)Gravatar Matt Kane 8-13/+66 * fix: don't attempt to move files after build with base * Remove console * Reword changeset * Remove unused import 2025-03-19[ci] formatGravatar Emanuele Stoppa 2-6/+18 2025-03-19fix(routing): don't add site to static redirects (#13447)Gravatar Emanuele Stoppa 7-10/+49 * fix(routing): don't add site to static redirects * chore: fix canonical tag * chore: fix canonical tag Co-authored-by: ascorbic <213306+ascorbic@users.noreply.github.com> 2025-03-18[ci] formatGravatar Matt Kane 2-2/+1 2025-03-18fix: set correct statusText for custom error pages (#13457)Gravatar Matt Kane 4-2/+19 * fix: set correct statusText for custom error pages * Set conditionally 2025-03-18chore(deps): update github-actions (#13459)Gravatar renovate[bot] 9-13/+13 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> 2025-03-18chore(deps): update github-actions (#13458)Gravatar renovate[bot] 1-5/+5 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> 2025-03-18[ci] formatGravatar Emanuele Stoppa 1-1/+3 2025-03-18chore: remove deprecated package (#13455)Gravatar Emanuele Stoppa 3-23/+16 2025-03-18fix(deps): update dependency miniflare to v4 (#13441)Gravatar renovate[bot] 2-31/+31 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>