mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-25 13:44:05 -08:00
Support using MX records for DNS discovery (#10099)
It's currently possible to use blackbox_exporter to probe MX records themselves. However it's not possible to do an end-to-end test, like is possible with SRV records. This makes it possible to use MX records as a source of hostnames in the same way as SRV records. Signed-off-by: David Leadbeater <dgl@dgl.cx>
This commit is contained in:
parent
a7f19b5775
commit
d677ec489e
|
@ -40,6 +40,8 @@ const (
|
|||
dnsSrvRecordPrefix = model.MetaLabelPrefix + "dns_srv_record_"
|
||||
dnsSrvRecordTargetLabel = dnsSrvRecordPrefix + "target"
|
||||
dnsSrvRecordPortLabel = dnsSrvRecordPrefix + "port"
|
||||
dnsMxRecordPrefix = model.MetaLabelPrefix + "dns_mx_record_"
|
||||
dnsMxRecordTargetLabel = dnsMxRecordPrefix + "target"
|
||||
|
||||
// Constants for instrumentation.
|
||||
namespace = "prometheus"
|
||||
|
@ -100,7 +102,7 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
}
|
||||
switch strings.ToUpper(c.Type) {
|
||||
case "SRV":
|
||||
case "A", "AAAA":
|
||||
case "A", "AAAA", "MX":
|
||||
if c.Port == 0 {
|
||||
return errors.New("a port is required in DNS-SD configs for all record types except SRV")
|
||||
}
|
||||
|
@ -136,6 +138,8 @@ func NewDiscovery(conf SDConfig, logger log.Logger) *Discovery {
|
|||
qtype = dns.TypeAAAA
|
||||
case "SRV":
|
||||
qtype = dns.TypeSRV
|
||||
case "MX":
|
||||
qtype = dns.TypeMX
|
||||
}
|
||||
d := &Discovery{
|
||||
names: conf.Names,
|
||||
|
@ -195,7 +199,7 @@ func (d *Discovery) refreshOne(ctx context.Context, name string, ch chan<- *targ
|
|||
}
|
||||
|
||||
for _, record := range response.Answer {
|
||||
var target, dnsSrvRecordTarget, dnsSrvRecordPort model.LabelValue
|
||||
var target, dnsSrvRecordTarget, dnsSrvRecordPort, dnsMxRecordTarget model.LabelValue
|
||||
|
||||
switch addr := record.(type) {
|
||||
case *dns.SRV:
|
||||
|
@ -206,6 +210,13 @@ func (d *Discovery) refreshOne(ctx context.Context, name string, ch chan<- *targ
|
|||
addr.Target = strings.TrimRight(addr.Target, ".")
|
||||
|
||||
target = hostPort(addr.Target, int(addr.Port))
|
||||
case *dns.MX:
|
||||
dnsMxRecordTarget = model.LabelValue(addr.Mx)
|
||||
|
||||
// Remove the final dot from rooted DNS names to make them look more usual.
|
||||
addr.Mx = strings.TrimRight(addr.Mx, ".")
|
||||
|
||||
target = hostPort(addr.Mx, d.port)
|
||||
case *dns.A:
|
||||
target = hostPort(addr.A.String(), d.port)
|
||||
case *dns.AAAA:
|
||||
|
@ -222,6 +233,7 @@ func (d *Discovery) refreshOne(ctx context.Context, name string, ch chan<- *targ
|
|||
dnsNameLabel: model.LabelValue(name),
|
||||
dnsSrvRecordTargetLabel: dnsSrvRecordTarget,
|
||||
dnsSrvRecordPortLabel: dnsSrvRecordPort,
|
||||
dnsMxRecordTargetLabel: dnsMxRecordTarget,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ func TestDNS(t *testing.T) {
|
|||
"__meta_dns_name": "web.example.com.",
|
||||
"__meta_dns_srv_record_target": "",
|
||||
"__meta_dns_srv_record_port": "",
|
||||
"__meta_dns_mx_record_target": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -110,6 +111,7 @@ func TestDNS(t *testing.T) {
|
|||
"__meta_dns_name": "web.example.com.",
|
||||
"__meta_dns_srv_record_target": "",
|
||||
"__meta_dns_srv_record_port": "",
|
||||
"__meta_dns_mx_record_target": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -140,12 +142,14 @@ func TestDNS(t *testing.T) {
|
|||
"__meta_dns_name": "_mysql._tcp.db.example.com.",
|
||||
"__meta_dns_srv_record_target": "db1.example.com.",
|
||||
"__meta_dns_srv_record_port": "3306",
|
||||
"__meta_dns_mx_record_target": "",
|
||||
},
|
||||
{
|
||||
"__address__": "db2.example.com:3306",
|
||||
"__meta_dns_name": "_mysql._tcp.db.example.com.",
|
||||
"__meta_dns_srv_record_target": "db2.example.com.",
|
||||
"__meta_dns_srv_record_port": "3306",
|
||||
"__meta_dns_mx_record_target": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -175,6 +179,7 @@ func TestDNS(t *testing.T) {
|
|||
"__meta_dns_name": "_mysql._tcp.db.example.com.",
|
||||
"__meta_dns_srv_record_target": "db1.example.com.",
|
||||
"__meta_dns_srv_record_port": "3306",
|
||||
"__meta_dns_mx_record_target": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -195,6 +200,45 @@ func TestDNS(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MX record query",
|
||||
config: SDConfig{
|
||||
Names: []string{"example.com."},
|
||||
Type: "MX",
|
||||
Port: 25,
|
||||
RefreshInterval: model.Duration(time.Minute),
|
||||
},
|
||||
lookup: func(name string, qtype uint16, logger log.Logger) (*dns.Msg, error) {
|
||||
return &dns.Msg{
|
||||
Answer: []dns.RR{
|
||||
&dns.MX{Preference: 0, Mx: "smtp1.example.com."},
|
||||
&dns.MX{Preference: 10, Mx: "smtp2.example.com."},
|
||||
},
|
||||
},
|
||||
nil
|
||||
},
|
||||
expected: []*targetgroup.Group{
|
||||
{
|
||||
Source: "example.com.",
|
||||
Targets: []model.LabelSet{
|
||||
{
|
||||
"__address__": "smtp1.example.com:25",
|
||||
"__meta_dns_name": "example.com.",
|
||||
"__meta_dns_srv_record_target": "",
|
||||
"__meta_dns_srv_record_port": "",
|
||||
"__meta_dns_mx_record_target": "smtp1.example.com.",
|
||||
},
|
||||
{
|
||||
"__address__": "smtp2.example.com:25",
|
||||
"__meta_dns_name": "example.com.",
|
||||
"__meta_dns_srv_record_target": "",
|
||||
"__meta_dns_srv_record_port": "",
|
||||
"__meta_dns_mx_record_target": "smtp2.example.com.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
|
@ -961,8 +961,8 @@ A DNS-based service discovery configuration allows specifying a set of DNS
|
|||
domain names which are periodically queried to discover a list of targets. The
|
||||
DNS servers to be contacted are read from `/etc/resolv.conf`.
|
||||
|
||||
This service discovery method only supports basic DNS A, AAAA and SRV record
|
||||
queries, but not the advanced DNS-SD approach specified in
|
||||
This service discovery method only supports basic DNS A, AAAA, MX and SRV
|
||||
record queries, but not the advanced DNS-SD approach specified in
|
||||
[RFC6763](https://tools.ietf.org/html/rfc6763).
|
||||
|
||||
The following meta labels are available on targets during [relabeling](#relabel_config):
|
||||
|
@ -970,13 +970,14 @@ The following meta labels are available on targets during [relabeling](#relabel_
|
|||
* `__meta_dns_name`: the record name that produced the discovered target.
|
||||
* `__meta_dns_srv_record_target`: the target field of the SRV record
|
||||
* `__meta_dns_srv_record_port`: the port field of the SRV record
|
||||
* `__meta_dns_mx_record_target`: the target field of the MX record
|
||||
|
||||
```yaml
|
||||
# A list of DNS domain names to be queried.
|
||||
names:
|
||||
[ - <string> ]
|
||||
|
||||
# The type of DNS query to perform. One of SRV, A, or AAAA.
|
||||
# The type of DNS query to perform. One of SRV, A, AAAA or MX.
|
||||
[ type: <string> | default = 'SRV' ]
|
||||
|
||||
# The port number used if the query type is not SRV.
|
||||
|
|
Loading…
Reference in a new issue