add support for scaleway service discovery (#8555)

Co-authored-by: Patrik <patrik@ptrk.io>
Co-authored-by: Julien Pivotto <roidelapluie@inuits.eu>

Signed-off-by: Rémy Léone <rleone@scaleway.com>
This commit is contained in:
Rémy Léone 2021-03-10 15:10:17 +01:00 committed by GitHub
parent ad5ed416ba
commit f690b811c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 742 additions and 1 deletions

View file

@ -40,6 +40,7 @@ import (
"github.com/prometheus/prometheus/discovery/kubernetes"
"github.com/prometheus/prometheus/discovery/marathon"
"github.com/prometheus/prometheus/discovery/openstack"
"github.com/prometheus/prometheus/discovery/scaleway"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/prometheus/prometheus/discovery/triton"
"github.com/prometheus/prometheus/discovery/zookeeper"
@ -742,6 +743,42 @@ var expectedConf = &Config{
},
},
},
{
JobName: "scaleway",
HonorTimestamps: true,
ScrapeInterval: model.Duration(15 * time.Second),
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
HTTPClientConfig: config.HTTPClientConfig{FollowRedirects: true},
MetricsPath: DefaultScrapeConfig.MetricsPath,
Scheme: DefaultScrapeConfig.Scheme,
ServiceDiscoveryConfigs: discovery.Configs{
&scaleway.SDConfig{
APIURL: "https://api.scaleway.com",
AccessKey: "SCWXXXXXXXXXXXXXXXXX",
HTTPClientConfig: config.HTTPClientConfig{FollowRedirects: true},
Port: 80,
Project: "11111111-1111-1111-1111-111111111112",
RefreshInterval: model.Duration(60 * time.Second),
Role: "instance",
SecretKey: "11111111-1111-1111-1111-111111111111",
Zone: "fr-par-1",
},
&scaleway.SDConfig{
APIURL: "https://api.scaleway.com",
AccessKey: "SCWXXXXXXXXXXXXXXXXX",
HTTPClientConfig: config.HTTPClientConfig{FollowRedirects: true},
Port: 80,
Project: "11111111-1111-1111-1111-111111111112",
RefreshInterval: model.Duration(60 * time.Second),
Role: "baremetal",
SecretKey: "11111111-1111-1111-1111-111111111111",
Zone: "fr-par-1",
},
},
},
},
AlertingConfig: AlertingConfig{
AlertmanagerConfigs: []*AlertmanagerConfig{
@ -826,7 +863,7 @@ func TestElideSecrets(t *testing.T) {
yamlConfig := string(config)
matches := secretRe.FindAllStringIndex(yamlConfig, -1)
require.Equal(t, 10, len(matches), "wrong number of secret matches found")
require.Equal(t, 12, len(matches), "wrong number of secret matches found")
require.NotContains(t, yamlConfig, "mysecret",
"yaml marshal reveals authentication credentials.")
}

View file

@ -298,6 +298,17 @@ scrape_configs:
eureka_sd_configs:
- server: 'http://eureka.example.com:8761/eureka'
- job_name: scaleway
scaleway_sd_configs:
- role: instance
project_id: 11111111-1111-1111-1111-111111111112
access_key: SCWXXXXXXXXXXXXXXXXX
secret_key: 11111111-1111-1111-1111-111111111111
- role: baremetal
project_id: 11111111-1111-1111-1111-111111111112
access_key: SCWXXXXXXXXXXXXXXXXX
secret_key: 11111111-1111-1111-1111-111111111111
alerting:
alertmanagers:
- scheme: https

4
config/testdata/scaleway_role.bad.yml vendored Normal file
View file

@ -0,0 +1,4 @@
scrape_configs:
- scaleway_sd_configs:
- role: invalid

View file

@ -29,6 +29,7 @@ import (
_ "github.com/prometheus/prometheus/discovery/kubernetes" // register kubernetes
_ "github.com/prometheus/prometheus/discovery/marathon" // register marathon
_ "github.com/prometheus/prometheus/discovery/openstack" // register openstack
_ "github.com/prometheus/prometheus/discovery/scaleway" // register scaleway
_ "github.com/prometheus/prometheus/discovery/triton" // register triton
_ "github.com/prometheus/prometheus/discovery/zookeeper" // register zookeeper
)

View file

@ -0,0 +1,192 @@
// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scaleway
import (
"context"
"fmt"
"net"
"net/http"
"strconv"
"strings"
"time"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/common/version"
"github.com/prometheus/prometheus/discovery/refresh"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/scaleway/scaleway-sdk-go/api/baremetal/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)
type baremetalDiscovery struct {
*refresh.Discovery
client *scw.Client
port int
zone string
project string
accessKey string
secretKey string
nameFilter string
tagsFilter []string
}
const (
baremetalLabelPrefix = metaLabelPrefix + "baremetal_"
baremetalIDLabel = baremetalLabelPrefix + "id"
baremetalPublicIPv4Label = baremetalLabelPrefix + "public_ipv4"
baremetalPublicIPv6Label = baremetalLabelPrefix + "public_ipv6"
baremetalNameLabel = baremetalLabelPrefix + "name"
baremetalOSNameLabel = baremetalLabelPrefix + "os_name"
baremetalOSVersionLabel = baremetalLabelPrefix + "os_version"
baremetalProjectLabel = baremetalLabelPrefix + "project_id"
baremetalStatusLabel = baremetalLabelPrefix + "status"
baremetalTagsLabel = baremetalLabelPrefix + "tags"
baremetalTypeLabel = baremetalLabelPrefix + "type"
baremetalZoneLabel = baremetalLabelPrefix + "zone"
)
func newBaremetalDiscovery(conf *SDConfig) (*baremetalDiscovery, error) {
d := &baremetalDiscovery{
port: conf.Port,
zone: conf.Zone,
project: conf.Project,
accessKey: conf.AccessKey,
secretKey: string(conf.SecretKey),
nameFilter: conf.NameFilter,
tagsFilter: conf.TagsFilter,
}
rt, err := config.NewRoundTripperFromConfig(conf.HTTPClientConfig, "scaleway_sd", false, false)
if err != nil {
return nil, err
}
profile, err := loadProfile(conf)
if err != nil {
return nil, err
}
d.client, err = scw.NewClient(
scw.WithHTTPClient(&http.Client{
Transport: rt,
Timeout: time.Duration(conf.RefreshInterval),
}),
scw.WithUserAgent(fmt.Sprintf("Prometheus/%s", version.Version)),
scw.WithProfile(profile),
)
if err != nil {
return nil, fmt.Errorf("error setting up scaleway client: %w", err)
}
return d, nil
}
func (d *baremetalDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
api := baremetal.NewAPI(d.client)
req := &baremetal.ListServersRequest{}
if d.nameFilter != "" {
req.Name = scw.StringPtr(d.nameFilter)
}
if d.tagsFilter != nil {
req.Tags = d.tagsFilter
}
servers, err := api.ListServers(req, scw.WithAllPages(), scw.WithContext(ctx))
if err != nil {
return nil, err
}
offers, err := api.ListOffers(&baremetal.ListOffersRequest{}, scw.WithAllPages())
if err != nil {
return nil, err
}
osFullList, err := api.ListOS(&baremetal.ListOSRequest{}, scw.WithAllPages())
if err != nil {
return nil, err
}
var targets []model.LabelSet
for _, server := range servers.Servers {
labels := model.LabelSet{
baremetalIDLabel: model.LabelValue(server.ID),
baremetalNameLabel: model.LabelValue(server.Name),
baremetalZoneLabel: model.LabelValue(server.Zone.String()),
baremetalStatusLabel: model.LabelValue(server.Status),
baremetalProjectLabel: model.LabelValue(server.ProjectID),
}
for _, offer := range offers.Offers {
if server.OfferID == offer.ID {
labels[baremetalTypeLabel] = model.LabelValue(offer.Name)
break
}
}
if server.Install != nil {
for _, os := range osFullList.Os {
if server.Install.OsID == os.ID {
labels[baremetalOSNameLabel] = model.LabelValue(os.Name)
labels[baremetalOSVersionLabel] = model.LabelValue(os.Version)
break
}
}
}
if len(server.Tags) > 0 {
// We surround the separated list with the separator as well. This way regular expressions
// in relabeling rules don't have to consider tag positions.
tags := separator + strings.Join(server.Tags, separator) + separator
labels[baremetalTagsLabel] = model.LabelValue(tags)
}
for _, ip := range server.IPs {
switch v := ip.Version.String(); v {
case "IPv4":
if _, ok := labels[baremetalPublicIPv4Label]; ok {
// If the server has multiple IPv4, we only take the first one.
// This should not happen.
continue
}
labels[baremetalPublicIPv4Label] = model.LabelValue(ip.Address.String())
// We always default the __address__ to IPv4.
addr := net.JoinHostPort(ip.Address.String(), strconv.FormatUint(uint64(d.port), 10))
labels[model.AddressLabel] = model.LabelValue(addr)
case "IPv6":
if _, ok := labels[baremetalPublicIPv6Label]; ok {
// If the server has multiple IPv6, we only take the first one.
// This should not happen.
continue
}
labels[baremetalPublicIPv6Label] = model.LabelValue(ip.Address.String())
if _, ok := labels[model.AddressLabel]; !ok {
// This server does not have an IPv4 or we have not parsed it
// yet.
addr := net.JoinHostPort(ip.Address.String(), strconv.FormatUint(uint64(d.port), 10))
labels[model.AddressLabel] = model.LabelValue(addr)
}
default:
return nil, fmt.Errorf("unknown IP version: %s", v)
}
}
targets = append(targets, labels)
}
return []*targetgroup.Group{{Source: "scaleway", Targets: targets}}, nil
}

View file

@ -0,0 +1,155 @@
// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scaleway
import (
"context"
"fmt"
"net"
"net/http"
"strconv"
"strings"
"time"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/common/version"
"github.com/prometheus/prometheus/discovery/refresh"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)
const (
instanceLabelPrefix = metaLabelPrefix + "instance_"
instanceIDLabel = instanceLabelPrefix + "id"
instancePrivateIPv4 = instanceLabelPrefix + "private_ipv4"
instancePublicIPv4 = instanceLabelPrefix + "public_ipv4"
instancePublicIPv6 = instanceLabelPrefix + "public_ipv6"
instanceImageNameLabel = instanceLabelPrefix + "image_name"
instanceNameLabel = instanceLabelPrefix + "name"
instanceProjectLabel = instanceLabelPrefix + "project_id"
instanceStateLabel = instanceLabelPrefix + "status"
instanceTagsLabel = instanceLabelPrefix + "tags"
instanceTypeLabel = instanceLabelPrefix + "type"
instanceZoneLabel = instanceLabelPrefix + "zone"
)
type instanceDiscovery struct {
*refresh.Discovery
client *scw.Client
port int
zone string
project string
accessKey string
secretKey string
nameFilter string
tagsFilter []string
}
func newInstanceDiscovery(conf *SDConfig) (*instanceDiscovery, error) {
d := &instanceDiscovery{
port: conf.Port,
zone: conf.Zone,
project: conf.Project,
accessKey: conf.AccessKey,
secretKey: string(conf.SecretKey),
nameFilter: conf.NameFilter,
tagsFilter: conf.TagsFilter,
}
rt, err := config.NewRoundTripperFromConfig(conf.HTTPClientConfig, "scaleway_sd", false, false)
if err != nil {
return nil, err
}
profile, err := loadProfile(conf)
if err != nil {
return nil, err
}
d.client, err = scw.NewClient(
scw.WithHTTPClient(&http.Client{
Transport: rt,
Timeout: time.Duration(conf.RefreshInterval),
}),
scw.WithUserAgent(fmt.Sprintf("Prometheus/%s", version.Version)),
scw.WithProfile(profile),
)
if err != nil {
return nil, fmt.Errorf("error setting up scaleway client: %w", err)
}
return d, nil
}
func (d *instanceDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
api := instance.NewAPI(d.client)
req := &instance.ListServersRequest{}
if d.nameFilter != "" {
req.Name = scw.StringPtr(d.nameFilter)
}
if d.tagsFilter != nil {
req.Tags = d.tagsFilter
}
servers, err := api.ListServers(req, scw.WithAllPages(), scw.WithContext(ctx))
if err != nil {
return nil, err
}
var targets []model.LabelSet
for _, server := range servers.Servers {
labels := model.LabelSet{
instanceIDLabel: model.LabelValue(server.ID),
instanceImageNameLabel: model.LabelValue(server.Image.Name),
instanceNameLabel: model.LabelValue(server.Name),
instanceProjectLabel: model.LabelValue(server.Project),
instanceStateLabel: model.LabelValue(server.State),
instanceTypeLabel: model.LabelValue(server.CommercialType),
instanceZoneLabel: model.LabelValue(server.Zone.String()),
}
if len(server.Tags) > 0 {
// We surround the separated list with the separator as well. This way regular expressions
// in relabeling rules don't have to consider tag positions.
tags := separator + strings.Join(server.Tags, separator) + separator
labels[instanceTagsLabel] = model.LabelValue(tags)
}
if server.IPv6 != nil {
labels[instancePublicIPv6] = model.LabelValue(server.IPv6.Address.String())
}
if server.PublicIP != nil {
labels[instancePublicIPv4] = model.LabelValue(server.PublicIP.Address.String())
}
if server.PrivateIP != nil {
labels[instancePrivateIPv4] = model.LabelValue(*server.PrivateIP)
addr := net.JoinHostPort(*server.PrivateIP, strconv.FormatUint(uint64(d.port), 10))
labels[model.AddressLabel] = model.LabelValue(addr)
targets = append(targets, labels)
}
}
return []*targetgroup.Group{{Source: "scaleway", Targets: targets}}, nil
}

View file

@ -0,0 +1,200 @@
// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scaleway
import (
"context"
"time"
"github.com/go-kit/kit/log"
"github.com/pkg/errors"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/discovery"
"github.com/prometheus/prometheus/discovery/refresh"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/scaleway/scaleway-sdk-go/scw"
)
// metaLabelPrefix is the meta prefix used for all meta labels.
// in this discovery.
const (
metaLabelPrefix = model.MetaLabelPrefix + "scaleway_"
separator = ","
)
// role is the role of the target within the Scaleway Ecosystem.
type role string
// The valid options for role.
const (
// Scaleway Elements Baremetal
// https://www.scaleway.com/en/bare-metal-servers/
roleBaremetal role = "baremetal"
// Scaleway Elements Instance
// https://www.scaleway.com/en/virtual-instances/
roleInstance role = "instance"
)
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *role) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal((*string)(c)); err != nil {
return err
}
switch *c {
case roleInstance, roleBaremetal:
return nil
default:
return errors.Errorf("unknown role %q", *c)
}
}
// DefaultSDConfig is the default Scaleway Service Discovery configuration.
var DefaultSDConfig = SDConfig{
Port: 80,
RefreshInterval: model.Duration(60 * time.Second),
HTTPClientConfig: config.DefaultHTTPClientConfig,
Zone: scw.ZoneFrPar1.String(),
APIURL: "https://api.scaleway.com",
}
type SDConfig struct {
// Project: The Scaleway Project ID used to filter discovery on.
Project string `yaml:"project_id"`
// APIURL: URL of the Scaleway API to use.
APIURL string `yaml:"api_url,omitempty"`
// Zone: The zone of the scrape targets.
// If you need to configure multiple zones use multiple scaleway_sd_configs
Zone string `yaml:"zone"`
// AccessKey used to authenticate on Scaleway APIs.
AccessKey string `yaml:"access_key"`
// SecretKey used to authenticate on Scaleway APIs.
SecretKey config.Secret `yaml:"secret_key"`
// NameFilter to filter on during the ListServers.
NameFilter string `yaml:"name_filter,omitempty"`
// TagsFilter to filter on during the ListServers.
TagsFilter []string `yaml:"tags_filter,omitempty"`
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
RefreshInterval model.Duration `yaml:"refresh_interval"`
Port int `yaml:"port"`
// Role can be either instance or baremetal
Role role `yaml:"role"`
}
func (c SDConfig) Name() string {
return "scaleway"
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
*c = DefaultSDConfig
type plain SDConfig
err := unmarshal((*plain)(c))
if err != nil {
return err
}
if c.Role == "" {
return errors.New("role missing (one of: instance, baremetal)")
}
if c.Project == "" {
return errors.New("project_id is mandatory")
}
if c.SecretKey == "" {
return errors.New("secret_key is mandatory")
}
if c.AccessKey == "" {
return errors.New("access_key is mandatory")
}
profile, err := loadProfile(c)
if err != nil {
return err
}
_, err = scw.NewClient(
scw.WithProfile(profile),
)
if err != nil {
return err
}
return c.HTTPClientConfig.Validate()
}
func (c SDConfig) NewDiscoverer(options discovery.DiscovererOptions) (discovery.Discoverer, error) {
return NewDiscovery(&c, options.Logger)
}
// SetDirectory joins any relative file paths with dir.
func (c *SDConfig) SetDirectory(dir string) {
c.HTTPClientConfig.SetDirectory(dir)
}
func init() {
discovery.RegisterConfig(&SDConfig{})
}
// Discovery periodically performs Scaleway requests. It implements
// the Discoverer interface.
type Discovery struct {
}
func NewDiscovery(conf *SDConfig, logger log.Logger) (*refresh.Discovery, error) {
r, err := newRefresher(conf)
if err != nil {
return nil, err
}
return refresh.NewDiscovery(
logger,
"scaleway",
time.Duration(conf.RefreshInterval),
r.refresh,
), nil
}
type refresher interface {
refresh(context.Context) ([]*targetgroup.Group, error)
}
func newRefresher(conf *SDConfig) (refresher, error) {
switch conf.Role {
case roleBaremetal:
return newBaremetalDiscovery(conf)
case roleInstance:
return newInstanceDiscovery(conf)
}
return nil, errors.New("unknown Scaleway discovery role")
}
func loadProfile(sdConfig *SDConfig) (*scw.Profile, error) {
// Profile coming from Prometheus Configuration file
prometheusConfigProfile := &scw.Profile{
DefaultZone: scw.StringPtr(sdConfig.Zone),
APIURL: scw.StringPtr(sdConfig.APIURL),
SecretKey: scw.StringPtr(string(sdConfig.SecretKey)),
AccessKey: scw.StringPtr(sdConfig.AccessKey),
DefaultProjectID: scw.StringPtr(sdConfig.Project),
SendTelemetry: scw.BoolPtr(false),
}
return prometheusConfigProfile, nil
}

View file

@ -246,6 +246,10 @@ nerve_sd_configs:
openstack_sd_configs:
[ - <openstack_sd_config> ... ]
# List of Scaleway service discovery configurations.
scaleway_sd_configs:
[ - <scaleway_sd_config> ... ]
# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
[ - <serverset_sd_config> ... ]
@ -1523,6 +1527,93 @@ See [the Prometheus eureka-sd configuration file](/documentation/examples/promet
for a practical example on how to set up your Eureka app and your Prometheus
configuration.
### `<scaleway_sd_config>`
Scaleway SD configurations allow retrieving scrape targets from [Scaleway instances](https://www.scaleway.com/en/virtual-instances/) and [baremetal services](https://www.scaleway.com/en/bare-metal-servers/).
The following meta labels are available on targets during [relabeling](#relabel_config):
#### Instance role
* `__meta_scaleway_instance_id`: the id of the instance
* `__meta_scaleway_instance_private_ipv4`: the private ipv4 address of the instance
* `__meta_scaleway_instance_public_ipv4`: the public ipv4 address of the instance
* `__meta_scaleway_instance_public_ipv6`: the public ipv6 address of the instance
* `__meta_scaleway_instance_image_name`: name of the server image
* `__meta_scaleway_instance_name`: name of the server
* `__meta_scaleway_instance_project_id`: project id of the server
* `__meta_scaleway_instance_status`: status of the server
* `__meta_scaleway_instance_tags`: the list of tags of the target joined by the tag separator
* `__meta_scaleway_instance_type`: commercial type of the server
* `__meta_scaleway_instance_zone`: zone of the instance (ex: `fr-par-1`, complete list on <https://developers.scaleway.com/en/>)
This role uses the private IPv4 address by default. This can be
changed with relabelling, as demonstrated in [the Prometheus scaleway-sd
configuration file](/documentation/examples/prometheus-scaleway.yml).
#### Baremetal role
* `__meta_scaleway_baremetal_id`: the id of the server
* `__meta_scaleway_baremetal_public_ipv4`: the public ipv4 address of the server
* `__meta_scaleway_baremetal_public_ipv6`: the public ipv6 address of the server
* `__meta_scaleway_baremetal_ipaddress_order`: zero-based order of the address in the server
* `__meta_scaleway_baremetal_name`: name of the server
* `__meta_scaleway_baremetal_os_name`: name of the os used
* `__meta_scaleway_baremetal_os_version`: version of the os used
* `__meta_scaleway_baremetal_project_id`: project id of the server
* `__meta_scaleway_baremetal_status`: status of the server
* `__meta_scaleway_baremetal_tags`: tag list of the server
* `__meta_scaleway_baremetal_type`: commercial type of the server
* `__meta_scaleway_baremetal_zone`: zone of the server (ex: `fr-par-1`, complete list on <https://developers.scaleway.com/en/>)
This role uses the public IPv4 address by default. This can be
changed with relabelling, as demonstrated in [the Prometheus scaleway-sd
configuration file](/documentation/examples/prometheus-scaleway.yml).
See below for the configuration options for Scaleway discovery:
```yaml
# Access key to use. https://console.scaleway.com/project/credentials
access_key: <string>
# Secret key to use when listing targets. https://console.scaleway.com/project/credentials
secret_key: <secret>
# Project ID of the targets.
project_id: <string>
# Role of the targets to retrieve. Must be `instance` or `baremetal`.
role: <string>
# The port to scrape metrics from.
[ port: <int> | default = 80 ]
# API URL to use when doing the server listing requests.
[ api_url: <string> | default = "https://api.scaleway.com" ]
# Zone is the availability zone of your targets (e.g. fr-par-1).
[ zone: <string> | default = fr-par-1 ]
# NameFilter specify a name filter (works as a LIKE) to apply on the server listing request.
[ name_filter: <string> ]
# TagsFilter specify a tag filter (a server needs to have all defined tags to be listed) to apply on the server listing request.
tags_filter:
[ - <string> ]
# Refresh interval to re-read the targets list.
[ refresh_interval: <duration> | default = 60s ]
# Configure whether HTTP requests follow HTTP 3xx redirects.
[ follow_redirects: <bool> | default = true ]
# Optional proxy URL.
[ proxy_url: <string> ]
# TLS configuration.
tls_config:
[ <tls_config> ]
```
### `<static_config>`
@ -1746,6 +1837,10 @@ nerve_sd_configs:
openstack_sd_configs:
[ - <openstack_sd_config> ... ]
# List of Scaleway service discovery configurations.
scaleway_sd_configs:
[ - <scaleway_sd_config> ... ]
# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
[ - <serverset_sd_config> ... ]

View file

@ -0,0 +1,41 @@
# A example scrape configuration for running Prometheus with Scaleway.
scrape_configs:
- job_name: 'prometheus'
scaleway_sd_configs:
- role: instance
# You can find you project ID here: https://console.scaleway.com/project/settings
project_id: 11111111-1111-1111-1111-111111111111
# Replace with Scaleway Credentials: https://console.scaleway.com/project/credentials
access_key: SCWXXXXXXXXXXXXXXXXX
secret_key: 11111111-1111-1111-1111-111111111111
relabel_configs:
# Only scrape targets that have a tag 'prometheus'.
- source_labels: [__meta_scaleway_instance_tags]
regex: '.*,prometheus,.*'
action: keep
# Use the public IPv6 address and port 9100 to scrape the target.
- source_labels: [__meta_scaleway_instance_public_ipv6]
target_label: __address__
replacement: '[$1]:9090'
# Add the zone as label
- source_labels: [__meta_scaleway_instance_zone]
target_label: scw_zone
- job_name: 'node'
scaleway_sd_configs:
- role: baremetal
# You can find you project ID here: https://console.scaleway.com/project/settings
project_id: 11111111-1111-1111-1111-111111111111
zone: fr-par-2
# Replace with Scaleway Credentials: https://console.scaleway.com/project/credentials
access_key: SCWXXXXXXXXXXXXXXXXX
secret_key: 11111111-1111-1111-1111-111111111111
relabel_configs:
# Filter out servers that are not physically in the datacenter.
- source_labels: [__meta_scaleway_baremetal_status]
regex: '(delivering|out_of_stock)'
action: drop
# Use the public IPv6 address and port 9100 to scrape the target.
- source_labels: [__meta_scaleway_baremetal_public_ipv6]
target_label: __address__
replacement: '[$1]:9100'

1
go.mod
View file

@ -50,6 +50,7 @@ require (
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.18.0
github.com/prometheus/exporter-toolkit v0.5.1
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
github.com/stretchr/testify v1.7.0

4
go.sum
View file

@ -161,6 +161,8 @@ github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245 h1:9cOfvEwjQxdwKu
github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/godo v1.57.0 h1:uCpe0sRIZ/sJWxWDsJyBPBjUfSvxop+WHkHiSf+tjjM=
github.com/digitalocean/godo v1.57.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU=
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.3+incompatible h1:+HS4XO73J41FpA260ztGujJ+0WibrA2TPJEnWNSyGNE=
@ -739,6 +741,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44 h1:3egqo0Vut6daANFm7tOXdNAa8v5/uLU+sgCJrc88Meo=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=