Skip to content

Commit 1245d42

Browse files
author
OpenShift Bot
committed
Merge pull request #5613 from smarterclayton/dns_broken
Merged by openshift-bot
2 parents 192bef7 + eb5c744 commit 1245d42

File tree

3 files changed

+172
-102
lines changed

3 files changed

+172
-102
lines changed

pkg/dns/server.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package dns
33
import (
44
client "k8s.io/kubernetes/pkg/client/unversioned"
55

6+
"github.com/golang/glog"
7+
68
"github.com/coreos/go-etcd/etcd"
79
"github.com/prometheus/client_golang/prometheus"
810
backendetcd "github.com/skynetservices/skydns/backends/etcd"
@@ -12,8 +14,9 @@ import (
1214
// NewServerDefaults returns the default SkyDNS server configuration for a DNS server.
1315
func NewServerDefaults() (*server.Config, error) {
1416
config := &server.Config{
15-
Domain: "cluster.local.",
16-
Local: "openshift.default.svc.cluster.local.",
17+
Domain: "cluster.local.",
18+
Local: "openshift.default.svc.cluster.local.",
19+
Verbose: bool(glog.V(4)),
1720
}
1821
return config, server.SetDefaults(config)
1922
}

pkg/dns/serviceresolver.go

Lines changed: 132 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ package dns
22

33
import (
44
"fmt"
5+
"hash/fnv"
6+
"net"
57
"strings"
68

9+
"github.com/golang/glog"
10+
711
kapi "k8s.io/kubernetes/pkg/api"
812
"k8s.io/kubernetes/pkg/api/errors"
913
kclient "k8s.io/kubernetes/pkg/client/unversioned"
@@ -48,32 +52,58 @@ func NewServiceResolver(config *server.Config, accessor ServiceAccessor, endpoin
4852
// Records implements the SkyDNS Backend interface and returns standard records for
4953
// a name.
5054
//
51-
// The standard pattern is <prefix>.<service_name>.<namespace>.(svc|endpoints).<base>
55+
// The standard pattern is <prefix>.<service_name>.<namespace>.(svc|endpoints|pod).<base>
5256
//
5357
// * prefix may be any series of prefix values
58+
// * _endpoints is a special prefix that returns the same as <service_name>.<namespace>.svc.<base>
5459
// * service_name and namespace must locate a real service
60+
// * unless a fallback is defined, in which case the fallback name will be looked up
5561
// * svc indicates standard service rules apply (portalIP or endpoints as A records)
5662
// * reverse lookup of IP is only possible for portalIP
5763
// * SRV records are returned for each host+port combination as:
5864
// _<port_name>._<port_protocol>.<dns>
5965
// _<port_name>.<endpoint_id>.<dns>
60-
// * endpoint_id is "portal" when portalIP is set
6166
// * endpoints always returns each individual endpoint as A records
67+
// * SRV records for endpoints are similar to SVC, but are prefixed with a single label
68+
// that is a hash of the endpoint IP
69+
// * pods is of the form <IP_with_dashes>.<namespace>.pod.<base> and resolves to <IP>
6270
//
63-
func (b *ServiceResolver) Records(name string, exact bool) ([]msg.Service, error) {
64-
if !strings.HasSuffix(name, b.base) {
71+
func (b *ServiceResolver) Records(dnsName string, exact bool) ([]msg.Service, error) {
72+
if !strings.HasSuffix(dnsName, b.base) {
6573
return nil, nil
6674
}
67-
prefix := strings.Trim(strings.TrimSuffix(name, b.base), ".")
75+
prefix := strings.Trim(strings.TrimSuffix(dnsName, b.base), ".")
6876
segments := strings.Split(prefix, ".")
6977
for i, j := 0, len(segments)-1; i < j; i, j = i+1, j-1 {
7078
segments[i], segments[j] = segments[j], segments[i]
7179
}
7280
if len(segments) == 0 {
7381
return nil, nil
7482
}
83+
glog.V(4).Infof("Answering query %s:%t", dnsName, exact)
84+
switch base := segments[0]; base {
85+
case "pod":
86+
if len(segments) != 3 {
87+
return nil, nil
88+
}
89+
namespace, encodedIP := segments[1], segments[2]
90+
ip := convertDashIPToIP(encodedIP)
91+
if net.ParseIP(ip) == nil {
92+
return nil, nil
93+
}
94+
return []msg.Service{
95+
{
96+
Host: ip,
97+
Port: 0,
98+
99+
Priority: 10,
100+
Weight: 10,
101+
Ttl: 30,
102+
103+
Key: msg.Path(buildDNSName(b.base, "pod", namespace, getHash(ip))),
104+
},
105+
}, nil
75106

76-
switch segments[0] {
77107
case "svc", "endpoints":
78108
if len(segments) < 3 {
79109
return nil, nil
@@ -94,56 +124,64 @@ func (b *ServiceResolver) Records(name string, exact bool) ([]msg.Service, error
94124
return nil, nil
95125
}
96126

97-
retrieveEndpoints := segments[0] == "endpoints" || (len(segments) > 3 && segments[3] == "_endpoints")
127+
subdomain := buildDNSName(b.base, base, namespace, name)
128+
endpointPrefix := base == "endpoints"
129+
retrieveEndpoints := endpointPrefix || (len(segments) > 3 && segments[3] == "_endpoints")
98130

99131
// if has a portal IP and looking at svc
100132
if svc.Spec.ClusterIP != kapi.ClusterIPNone && !retrieveEndpoints {
101-
if len(svc.Spec.Ports) == 0 {
102-
return nil, nil
133+
defaultService := msg.Service{
134+
Host: svc.Spec.ClusterIP,
135+
Port: 0,
136+
137+
Priority: 10,
138+
Weight: 10,
139+
Ttl: 30,
103140
}
104-
services := []msg.Service{}
105-
for _, p := range svc.Spec.Ports {
106-
port := p.Port
107-
if port == 0 {
108-
port = p.TargetPort.IntVal
109-
}
110-
if port == 0 {
111-
continue
112-
}
113-
if len(p.Protocol) == 0 {
114-
p.Protocol = kapi.ProtocolTCP
115-
}
116-
portName := p.Name
117-
if len(portName) == 0 {
118-
portName = fmt.Sprintf("unknown-port-%d", port)
119-
}
120-
srvName := fmt.Sprintf("%s.portal.%s", portName, name)
121-
keyName := fmt.Sprintf("_%s._%s.%s", portName, p.Protocol, name)
122-
services = append(services,
123-
msg.Service{
124-
Host: svc.Spec.ClusterIP,
125-
Port: port,
141+
defaultHash := getHash(defaultService.Host)
142+
defaultName := buildDNSName(subdomain, defaultHash)
143+
defaultService.Key = msg.Path(defaultName)
126144

127-
Priority: 10,
128-
Weight: 10,
129-
Ttl: 30,
145+
if len(svc.Spec.Ports) == 0 {
146+
return []msg.Service{defaultService}, nil
147+
}
130148

131-
Text: "",
132-
Key: msg.Path(srvName),
133-
},
134-
msg.Service{
135-
Host: srvName,
136-
Port: port,
149+
services := []msg.Service{}
150+
if len(segments) == 3 {
151+
for _, p := range svc.Spec.Ports {
152+
port := p.Port
153+
if port == 0 {
154+
port = p.TargetPort.IntVal
155+
}
156+
if port == 0 {
157+
continue
158+
}
159+
if len(p.Protocol) == 0 {
160+
p.Protocol = kapi.ProtocolTCP
161+
}
162+
portName := p.Name
163+
if len(portName) == 0 {
164+
portName = fmt.Sprintf("unknown-port-%d", port)
165+
}
166+
keyName := buildDNSName(subdomain, "_"+strings.ToLower(string(p.Protocol)), "_"+portName)
167+
services = append(services,
168+
msg.Service{
169+
Host: svc.Spec.ClusterIP,
170+
Port: port,
137171

138-
Priority: 10,
139-
Weight: 10,
140-
Ttl: 30,
172+
Priority: 10,
173+
Weight: 10,
174+
Ttl: 30,
141175

142-
Text: "",
143-
Key: msg.Path(keyName),
144-
},
145-
)
176+
Key: msg.Path(keyName),
177+
},
178+
)
179+
}
180+
}
181+
if len(services) == 0 {
182+
services = append(services, defaultService)
146183
}
184+
glog.V(4).Infof("Answered %s:%t with %#v", dnsName, exact, services)
147185
return services, nil
148186
}
149187

@@ -152,79 +190,53 @@ func (b *ServiceResolver) Records(name string, exact bool) ([]msg.Service, error
152190
if err != nil {
153191
return nil, err
154192
}
155-
targets := make(map[string]int)
193+
156194
services := make([]msg.Service, 0, len(endpoints.Subsets)*4)
157-
count := 1
158195
for _, s := range endpoints.Subsets {
159196
for _, a := range s.Addresses {
160-
shortName := ""
161-
if a.TargetRef != nil {
162-
name := fmt.Sprintf("%s-%s", a.TargetRef.Name, a.TargetRef.Namespace)
163-
if c, ok := targets[name]; ok {
164-
shortName = fmt.Sprintf("e%d", c)
165-
} else {
166-
shortName = fmt.Sprintf("e%d", count)
167-
targets[name] = count
168-
count++
169-
}
170-
} else {
171-
shortName = fmt.Sprintf("e%d", count)
172-
count++
197+
defaultService := msg.Service{
198+
Host: a.IP,
199+
Port: 0,
200+
201+
Priority: 10,
202+
Weight: 10,
203+
Ttl: 30,
173204
}
174-
hadPort := false
205+
defaultHash := getHash(defaultService.Host)
206+
defaultName := buildDNSName(subdomain, defaultHash)
207+
defaultService.Key = msg.Path(defaultName)
208+
175209
for _, p := range s.Ports {
176210
port := p.Port
177211
if port == 0 {
178212
continue
179213
}
180-
hadPort = true
181214
if len(p.Protocol) == 0 {
182215
p.Protocol = kapi.ProtocolTCP
183216
}
184217
portName := p.Name
185218
if len(portName) == 0 {
186219
portName = fmt.Sprintf("unknown-port-%d", port)
187220
}
188-
srvName := fmt.Sprintf("%s.%s.%s", portName, shortName, name)
189-
services = append(services, msg.Service{
190-
Host: a.IP,
191-
Port: port,
192221

193-
Priority: 10,
194-
Weight: 10,
195-
Ttl: 30,
196-
197-
Text: "",
198-
Key: msg.Path(srvName),
199-
})
200-
keyName := fmt.Sprintf("_%s._%s.%s", portName, p.Protocol, name)
222+
keyName := buildDNSName(subdomain, "_"+strings.ToLower(string(p.Protocol)), "_"+portName, defaultHash)
201223
services = append(services, msg.Service{
202-
Host: srvName,
224+
Host: a.IP,
203225
Port: port,
204226

205227
Priority: 10,
206228
Weight: 10,
207229
Ttl: 30,
208230

209-
Text: "",
210-
Key: msg.Path(keyName),
231+
Key: msg.Path(keyName),
211232
})
212233
}
213-
214-
if !hadPort {
215-
services = append(services, msg.Service{
216-
Host: a.IP,
217-
218-
Priority: 10,
219-
Weight: 10,
220-
Ttl: 30,
221-
222-
Text: "",
223-
Key: msg.Path(name),
224-
})
234+
if len(services) == 0 {
235+
services = append(services, defaultService)
225236
}
226237
}
227238
}
239+
glog.V(4).Infof("Answered %s:%t with %#v", dnsName, exact, services)
228240
return services, nil
229241
}
230242
return nil, nil
@@ -246,16 +258,16 @@ func (b *ServiceResolver) ReverseRecord(name string) (*msg.Service, error) {
246258
if len(svc.Spec.Ports) > 0 {
247259
port = svc.Spec.Ports[0].Port
248260
}
261+
hostName := buildDNSName(b.base, "svc", svc.Namespace, svc.Name)
249262
return &msg.Service{
250-
Host: fmt.Sprintf("%s.%s.svc.%s", svc.Name, svc.Namespace, b.base),
263+
Host: hostName,
251264
Port: port,
252265

253266
Priority: 10,
254267
Weight: 10,
255268
Ttl: 30,
256269

257-
Text: "",
258-
Key: msg.Path(name),
270+
Key: msg.Path(name),
259271
}, nil
260272
}
261273

@@ -278,3 +290,29 @@ func extractIP(reverseName string) (string, bool) {
278290
}
279291
return strings.Join(segments, "."), true
280292
}
293+
294+
// buildDNSName reverses the labels order and joins them with dots.
295+
func buildDNSName(labels ...string) string {
296+
var res string
297+
for _, label := range labels {
298+
if len(res) == 0 {
299+
res = label
300+
} else {
301+
res = fmt.Sprintf("%s.%s", label, res)
302+
}
303+
}
304+
return res
305+
}
306+
307+
// return a hash for the key name
308+
func getHash(text string) string {
309+
h := fnv.New32a()
310+
h.Write([]byte(text))
311+
return fmt.Sprintf("%x", h.Sum32())
312+
}
313+
314+
// convertDashIPToIP takes an encoded IP (with dashes) and replaces them with
315+
// dots.
316+
func convertDashIPToIP(ip string) string {
317+
return strings.Join(strings.Split(ip, "-"), ".")
318+
}

0 commit comments

Comments
 (0)