1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-15 16:56:24 +00:00

feat: enable config reload via signal

This commit adds the option to reload Prometheus configuration using
signal instead of the /-/reload endpoint.

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
Simon Pasquier 2023-06-15 17:39:12 +02:00
parent 34941afa1a
commit a143c8da5d
22 changed files with 550 additions and 177 deletions

97
Documentation/api.md generated
View file

@ -2547,6 +2547,21 @@ that will be kept in memory. 0 means no limit.</p>
</tr>
<tr>
<td>
<code>reloadStrategy</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ReloadStrategyType">
ReloadStrategyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.</p>
</td>
</tr>
<tr>
<td>
<code>baseImage</code><br/>
<em>
string
@ -6892,6 +6907,21 @@ that will be kept in memory. 0 means no limit.</p>
<p>It requires Prometheus &gt;= v2.47.0.</p>
</td>
</tr>
<tr>
<td>
<code>reloadStrategy</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ReloadStrategyType">
ReloadStrategyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="monitoring.coreos.com/v1.Condition">Condition
@ -10793,6 +10823,21 @@ that will be kept in memory. 0 means no limit.</p>
</tr>
<tr>
<td>
<code>reloadStrategy</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ReloadStrategyType">
ReloadStrategyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.</p>
</td>
</tr>
<tr>
<td>
<code>baseImage</code><br/>
<em>
string
@ -11720,6 +11765,28 @@ string
</tr>
</tbody>
</table>
<h3 id="monitoring.coreos.com/v1.ReloadStrategyType">ReloadStrategyType
(<code>string</code> alias)</h3>
<p>
(<em>Appears on:</em><a href="#monitoring.coreos.com/v1.CommonPrometheusFields">CommonPrometheusFields</a>)
</p>
<div>
</div>
<table>
<thead>
<tr>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr><td><p>&#34;HTTP&#34;</p></td>
<td><p>HTTPReloadStrategyType reloads the configuration using the /-/reload HTTP endpoint.</p>
</td>
</tr><tr><td><p>&#34;ProcessSignal&#34;</p></td>
<td><p>ProcessSignalReloadStrategyType reloads the configuration by sending a SIGHUP signal to the process.</p>
</td>
</tr></tbody>
</table>
<h3 id="monitoring.coreos.com/v1.RemoteReadSpec">RemoteReadSpec
</h3>
<p>
@ -16144,6 +16211,21 @@ that will be kept in memory. 0 means no limit.</p>
<p>It requires Prometheus &gt;= v2.47.0.</p>
</td>
</tr>
<tr>
<td>
<code>reloadStrategy</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ReloadStrategyType">
ReloadStrategyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -20331,6 +20413,21 @@ that will be kept in memory. 0 means no limit.</p>
<p>It requires Prometheus &gt;= v2.47.0.</p>
</td>
</tr>
<tr>
<td>
<code>reloadStrategy</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ReloadStrategyType">
ReloadStrategyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="monitoring.coreos.com/v1alpha1.PushoverConfig">PushoverConfig

16
bundle.yaml generated
View file

@ -18963,6 +18963,14 @@ spec:
when the field is set to the empty string (`\"\"`). \n Default:
\"prometheus\""
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteWrite:
description: Defines the list of remote write configurations.
items:
@ -27961,6 +27969,14 @@ spec:
can be set to a standard I/O stream, e.g. `/dev/stdout`, to log
query information to the default Prometheus log stream."
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteRead:
description: Defines the list of remote read configurations.
items:

View file

@ -49,6 +49,9 @@ const (
defaultRetryInterval = 5 * time.Second // 5 seconds was the value previously hardcoded in github.com/thanos-io/thanos/pkg/reloader.
defaultReloadTimeout = 30 * time.Second // 30 seconds was the default value
httpReloadMethod = "http"
signalReloadMethod = "signal"
statefulsetOrdinalEnvvar = "STATEFULSET_ORDINAL_NUMBER"
)
@ -67,6 +70,9 @@ func main() {
watchedDir := app.Flag("watched-dir", "directory to watch non-recursively").Strings()
reloadMethod := app.Flag("reload-method", "method used to reload the configuration").Default(httpReloadMethod).Enum(httpReloadMethod, signalReloadMethod)
processName := app.Flag("process-executable-name", "executable name used to match the process when using the signal reload method").Default("prometheus").String()
createStatefulsetOrdinalFrom := app.Flag(
"statefulset-ordinal-from-envvar",
fmt.Sprintf("parse this environment variable to create %s, containing the statefulset ordinal number", statefulsetOrdinalEnvvar)).
@ -93,9 +99,12 @@ func main() {
fmt.Sprintf("log level to use. Possible values: %s", strings.Join(logging.AvailableLogLevels, ", "))).
Default(logging.LevelInfo).StringVar(&logConfig.Level)
reloadURL := app.Flag("reload-url", "reload URL to trigger Prometheus reload on").
reloadURL := app.Flag("reload-url", "URL to trigger the configuration").
Default("http://127.0.0.1:9090/-/reload").URL()
runtimeInfoURL := app.Flag("runtimeinfo-url", "URL to check the status of the runtime configuration").
Default("http://127.0.0.1:9090/api/v1/status/runtimeinfo").URL()
versionutil.RegisterIntoKingpinFlags(app)
if _, err := app.Parse(os.Args[1:]); err != nil {
@ -140,23 +149,30 @@ func main() {
)
{
opts := reloader.Options{
CfgFile: *cfgFile,
CfgOutputFile: *cfgSubstFile,
WatchedDirs: *watchedDir,
DelayInterval: *delayInterval,
WatchInterval: *watchInterval,
RetryInterval: *retryInterval,
}
switch *reloadMethod {
case signalReloadMethod:
opts.RuntimeInfoURL = *runtimeInfoURL
opts.ProcessName = *processName
default:
opts.ReloadURL = *reloadURL
opts.HTTPClient = createHTTPClient(reloadTimeout)
}
rel := reloader.New(
logger,
r,
&reloader.Options{
ReloadURL: *reloadURL,
CfgFile: *cfgFile,
CfgOutputFile: *cfgSubstFile,
WatchedDirs: *watchedDir,
DelayInterval: *delayInterval,
WatchInterval: *watchInterval,
RetryInterval: *retryInterval,
},
&opts,
)
client := createHTTPClient(reloadTimeout)
rel.SetHttpClient(client)
g.Add(func() error {
return rel.Watch(ctx)
}, func(error) {

View file

@ -4366,6 +4366,14 @@ spec:
when the field is set to the empty string (`\"\"`). \n Default:
\"prometheus\""
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteWrite:
description: Defines the list of remote write configurations.
items:

View file

@ -4854,6 +4854,14 @@ spec:
can be set to a standard I/O stream, e.g. `/dev/stdout`, to log
query information to the default Prometheus log stream."
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteRead:
description: Defines the list of remote read configurations.
items:

View file

@ -4367,6 +4367,14 @@ spec:
when the field is set to the empty string (`\"\"`). \n Default:
\"prometheus\""
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteWrite:
description: Defines the list of remote write configurations.
items:

View file

@ -4855,6 +4855,14 @@ spec:
can be set to a standard I/O stream, e.g. `/dev/stdout`, to log
query information to the default Prometheus log stream."
type: string
reloadStrategy:
description: Defines the strategy used to reload the Prometheus configuration.
If not specified, the configuration is reloaded using the /-/reload
HTTP endpoint.
enum:
- HTTP
- ProcessSignal
type: string
remoteRead:
description: Defines the list of remote read configurations.
items:

3
go.mod
View file

@ -28,7 +28,7 @@ require (
github.com/prometheus/exporter-toolkit v0.10.0
github.com/prometheus/prometheus v0.48.0
github.com/stretchr/testify v1.8.4
github.com/thanos-io/thanos v0.32.5
github.com/thanos-io/thanos v0.32.5-0.20231124114724-023faa2d67a3
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/net v0.18.0
golang.org/x/sync v0.5.0
@ -51,6 +51,7 @@ require (
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
)

6
go.sum
View file

@ -415,6 +415,8 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@ -538,8 +540,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/thanos-io/thanos v0.32.5 h1:khHvuEAbUKox9DQI9cSmLes4F9G3MqWPxcdrf2tYY0w=
github.com/thanos-io/thanos v0.32.5/go.mod h1:POOrd2N/0wRQKkg1MJTvU29X+IVs7iMjSoN08q8V1Mo=
github.com/thanos-io/thanos v0.32.5-0.20231124114724-023faa2d67a3 h1:jrrcsbgX3/SsaCNi+jSIyCyuOOvLGgmlKmaOHf/uEOo=
github.com/thanos-io/thanos v0.32.5-0.20231124114724-023faa2d67a3/go.mod h1:DzjNla690uSQazyHrLGK6FeOn3VfV2ReA57Pi7SgZ+8=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=

View file

@ -3886,6 +3886,14 @@
"description": "Name of Prometheus external label used to denote the Prometheus instance name. The external label will _not_ be added when the field is set to the empty string (`\"\"`). \n Default: \"prometheus\"",
"type": "string"
},
"reloadStrategy": {
"description": "Defines the strategy used to reload the Prometheus configuration. If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.",
"enum": [
"HTTP",
"ProcessSignal"
],
"type": "string"
},
"remoteWrite": {
"description": "Defines the list of remote write configurations.",
"items": {

View file

@ -4376,6 +4376,14 @@
"description": "queryLogFile specifies where the file to which PromQL queries are logged. \n If the filename has an empty path, e.g. 'query.log', The Prometheus Pods will mount the file into an emptyDir volume at `/var/log/prometheus`. If a full path is provided, e.g. '/var/log/prometheus/query.log', you must mount a volume in the specified directory and it must be writable. This is because the prometheus container runs with a read-only root filesystem for security reasons. Alternatively, the location can be set to a standard I/O stream, e.g. `/dev/stdout`, to log query information to the default Prometheus log stream.",
"type": "string"
},
"reloadStrategy": {
"description": "Defines the strategy used to reload the Prometheus configuration. If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.",
"enum": [
"HTTP",
"ProcessSignal"
],
"type": "string"
},
"remoteRead": {
"description": "Defines the list of remote read configurations.",
"items": {

View file

@ -616,6 +616,38 @@ type CommonPrometheusFields struct {
//
// +optional
KeepDroppedTargets *uint64 `json:"keepDroppedTargets,omitempty"`
// Defines the strategy used to reload the Prometheus configuration.
// If not specified, the configuration is reloaded using the /-/reload HTTP endpoint.
// +optional
ReloadStrategy *ReloadStrategyType `json:"reloadStrategy,omitempty"`
}
// +kubebuilder:validation:Enum=HTTP;ProcessSignal
type ReloadStrategyType string
const (
// HTTPReloadStrategyType reloads the configuration using the /-/reload HTTP endpoint.
HTTPReloadStrategyType ReloadStrategyType = "HTTP"
// ProcessSignalReloadStrategyType reloads the configuration by sending a SIGHUP signal to the process.
ProcessSignalReloadStrategyType ReloadStrategyType = "ProcessSignal"
)
func (cpf *CommonPrometheusFields) PrometheusURIScheme() string {
if cpf.Web != nil && cpf.Web.TLSConfig != nil {
return "https"
}
return "http"
}
func (cpf *CommonPrometheusFields) WebRoutePrefix() string {
if cpf.RoutePrefix != "" {
return cpf.RoutePrefix
}
return "/"
}
// +genclient

View file

@ -893,6 +893,11 @@ func (in *CommonPrometheusFields) DeepCopyInto(out *CommonPrometheusFields) {
*out = new(uint64)
**out = **in
}
if in.ReloadStrategy != nil {
in, out := &in.ReloadStrategy, &out.ReloadStrategy
*out = new(ReloadStrategyType)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonPrometheusFields.

View file

@ -102,6 +102,7 @@ type CommonPrometheusFieldsApplyConfiguration struct {
LabelNameLengthLimit *uint64 `json:"labelNameLengthLimit,omitempty"`
LabelValueLengthLimit *uint64 `json:"labelValueLengthLimit,omitempty"`
KeepDroppedTargets *uint64 `json:"keepDroppedTargets,omitempty"`
ReloadStrategy *monitoringv1.ReloadStrategyType `json:"reloadStrategy,omitempty"`
}
// CommonPrometheusFieldsApplyConfiguration constructs an declarative configuration of the CommonPrometheusFields type for use with
@ -771,3 +772,11 @@ func (b *CommonPrometheusFieldsApplyConfiguration) WithKeepDroppedTargets(value
b.KeepDroppedTargets = &value
return b
}
// WithReloadStrategy sets the ReloadStrategy field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ReloadStrategy field is set to the value of the last call.
func (b *CommonPrometheusFieldsApplyConfiguration) WithReloadStrategy(value monitoringv1.ReloadStrategyType) *CommonPrometheusFieldsApplyConfiguration {
b.ReloadStrategy = &value
return b
}

View file

@ -719,6 +719,14 @@ func (b *PrometheusSpecApplyConfiguration) WithKeepDroppedTargets(value uint64)
return b
}
// WithReloadStrategy sets the ReloadStrategy field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ReloadStrategy field is set to the value of the last call.
func (b *PrometheusSpecApplyConfiguration) WithReloadStrategy(value monitoringv1.ReloadStrategyType) *PrometheusSpecApplyConfiguration {
b.ReloadStrategy = &value
return b
}
// WithBaseImage sets the BaseImage field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the BaseImage field is set to the value of the last call.

View file

@ -697,3 +697,11 @@ func (b *PrometheusAgentSpecApplyConfiguration) WithKeepDroppedTargets(value uin
b.KeepDroppedTargets = &value
return b
}
// WithReloadStrategy sets the ReloadStrategy field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ReloadStrategy field is set to the value of the last call.
func (b *PrometheusAgentSpecApplyConfiguration) WithReloadStrategy(value monitoringv1.ReloadStrategyType) *PrometheusAgentSpecApplyConfiguration {
b.ReloadStrategy = &value
return b
}

View file

@ -50,14 +50,22 @@ type ConfigReloader struct {
logFormat string
logLevel string
reloadURL url.URL
runtimeInfoURL url.URL
runOnce bool
shard *int32
volumeMounts []v1.VolumeMount
watchedDirectories []string
useSignal bool
}
type ReloaderOption = func(*ConfigReloader)
func ReloaderUseSignal() ReloaderOption {
return func(c *ConfigReloader) {
c.useSignal = true
}
}
// ReloaderRunOnce sets the runOnce option for the config-reloader container
func ReloaderRunOnce() ReloaderOption {
return func(c *ConfigReloader) {
@ -101,9 +109,16 @@ func ReloaderConfig(rc ContainerConfig) ReloaderOption {
}
// ReloaderURL sets the reloaderURL option for the config-reloader container
func ReloaderURL(reloadURL url.URL) ReloaderOption {
func ReloaderURL(u url.URL) ReloaderOption {
return func(c *ConfigReloader) {
c.reloadURL = reloadURL
c.reloadURL = u
}
}
// RuntimeInfoURL sets the runtimeInfoURL option for the config-reloader container
func RuntimeInfoURL(u url.URL) ReloaderOption {
return func(c *ConfigReloader) {
c.runtimeInfoURL = u
}
}
@ -200,8 +215,17 @@ func CreateConfigReloader(name string, options ...ReloaderOption) v1.Container {
args = append(args, fmt.Sprintf("--web-config-file=%s", configReloader.webConfigFile))
}
if len(configReloader.reloadURL.String()) > 0 {
args = append(args, fmt.Sprintf("--reload-url=%s", configReloader.reloadURL.String()))
if configReloader.useSignal {
args = append(args, "--reload-method=signal")
if len(configReloader.runtimeInfoURL.String()) > 0 {
args = append(args, fmt.Sprintf("--runtimeinfo-url=%s", configReloader.runtimeInfoURL.String()))
}
} else {
// Don't set the --reload-method argument in case the operator is
// configured with an older version of the config reloader.
if len(configReloader.reloadURL.String()) > 0 {
args = append(args, fmt.Sprintf("--reload-url=%s", configReloader.reloadURL.String()))
}
}
if len(configReloader.configFile) > 0 {

View file

@ -16,14 +16,13 @@ package prometheusagent
import (
"fmt"
"net/url"
"path"
"strings"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/ptr"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
monitoringv1alpha1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1alpha1"
@ -188,13 +187,8 @@ func makeStatefulSetSpec(
return nil, err
}
webRoutePrefix := "/"
if cpf.RoutePrefix != "" {
webRoutePrefix = cpf.RoutePrefix
}
cpf.EnableFeatures = append(cpf.EnableFeatures, "agent")
promArgs := prompkg.BuildCommonPrometheusArgs(cpf, cg, webRoutePrefix)
promArgs := prompkg.BuildCommonPrometheusArgs(cpf, cg)
promArgs = appendAgentArgs(promArgs, cg, cpf.WALCompression)
var ports []v1.ContainerPort
@ -247,7 +241,7 @@ func makeStatefulSetSpec(
// Prometheus is effectively ready.
// We don't want to use the /-/healthy handler here because it returns OK as
// soon as the web server is started (irrespective of the WAL replay).
readyProbeHandler := prompkg.ProbeHandler("/-/ready", cpf, webConfigGenerator, webRoutePrefix)
readyProbeHandler := prompkg.ProbeHandler("/-/ready", cpf, webConfigGenerator)
startupProbe := &v1.Probe{
ProbeHandler: readyProbeHandler,
TimeoutSeconds: prompkg.ProbeTimeoutSeconds,
@ -263,7 +257,7 @@ func makeStatefulSetSpec(
}
livenessProbe := &v1.Probe{
ProbeHandler: prompkg.ProbeHandler("/-/healthy", cpf, webConfigGenerator, webRoutePrefix),
ProbeHandler: prompkg.ProbeHandler("/-/healthy", cpf, webConfigGenerator),
TimeoutSeconds: prompkg.ProbeTimeoutSeconds,
PeriodSeconds: 5,
FailureThreshold: 6,
@ -291,11 +285,6 @@ func makeStatefulSetSpec(
var additionalContainers, operatorInitContainers []v1.Container
prometheusURIScheme := "http"
if cpf.Web != nil && cpf.Web.TLSConfig != nil {
prometheusURIScheme = "https"
}
var watchedDirectories []string
configReloaderVolumeMounts := []v1.VolumeMount{
{
@ -314,18 +303,13 @@ func makeStatefulSetSpec(
}
operatorInitContainers = append(operatorInitContainers,
operator.CreateConfigReloader(
"init-config-reloader",
operator.ReloaderConfig(c.ReloaderConfig),
operator.ReloaderRunOnce(),
operator.LogFormat(cpf.LogFormat),
operator.LogLevel(cpf.LogLevel),
operator.VolumeMounts(configReloaderVolumeMounts),
operator.ConfigFile(path.Join(prompkg.ConfDir, prompkg.ConfigFilename)),
operator.ConfigEnvsubstFile(path.Join(prompkg.ConfOutDir, prompkg.ConfigEnvsubstFilename)),
operator.WatchedDirectories(watchedDirectories),
prompkg.BuildConfigReloader(
p,
c,
true,
configReloaderVolumeMounts,
watchedDirectories,
operator.Shard(shard),
operator.ImagePullPolicy(cpf.ImagePullPolicy),
),
)
@ -340,8 +324,6 @@ func makeStatefulSetSpec(
return nil, err
}
boolFalse := false
boolTrue := true
operatorContainers := append([]v1.Container{
{
Name: "prometheus",
@ -356,30 +338,20 @@ func makeStatefulSetSpec(
Resources: cpf.Resources,
TerminationMessagePolicy: v1.TerminationMessageFallbackToLogsOnError,
SecurityContext: &v1.SecurityContext{
ReadOnlyRootFilesystem: &boolTrue,
AllowPrivilegeEscalation: &boolFalse,
ReadOnlyRootFilesystem: ptr.To(true),
AllowPrivilegeEscalation: ptr.To(false),
Capabilities: &v1.Capabilities{
Drop: []v1.Capability{"ALL"},
},
},
},
operator.CreateConfigReloader(
"config-reloader",
operator.ReloaderConfig(c.ReloaderConfig),
operator.ReloaderURL(url.URL{
Scheme: prometheusURIScheme,
Host: c.LocalHost + ":9090",
Path: path.Clean(webRoutePrefix + "/-/reload"),
}),
operator.ListenLocal(cpf.ListenLocal),
operator.LocalHost(c.LocalHost),
operator.LogFormat(cpf.LogFormat),
operator.LogLevel(cpf.LogLevel),
operator.ConfigFile(path.Join(prompkg.ConfDir, prompkg.ConfigFilename)),
operator.ConfigEnvsubstFile(path.Join(prompkg.ConfOutDir, prompkg.ConfigEnvsubstFilename)),
operator.WatchedDirectories(watchedDirectories), operator.VolumeMounts(configReloaderVolumeMounts),
prompkg.BuildConfigReloader(
p,
c,
false,
configReloaderVolumeMounts,
watchedDirectories,
operator.Shard(shard),
operator.ImagePullPolicy(cpf.ImagePullPolicy),
),
}, additionalContainers...)
@ -407,11 +379,12 @@ func makeStatefulSetSpec(
Annotations: podAnnotations,
},
Spec: v1.PodSpec{
ShareProcessNamespace: prompkg.ShareProcessNamespace(p),
Containers: containers,
InitContainers: initContainers,
SecurityContext: cpf.SecurityContext,
ServiceAccountName: cpf.ServiceAccountName,
AutomountServiceAccountToken: &boolTrue,
AutomountServiceAccountToken: ptr.To(true),
NodeSelector: cpf.NodeSelector,
PriorityClassName: cpf.PriorityClassName,
TerminationGracePeriodSeconds: &terminationGracePeriod,

View file

@ -16,7 +16,6 @@ package prometheus
import (
"fmt"
"net/url"
"path"
"strings"
@ -25,6 +24,7 @@ import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/ptr"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/prometheus-operator/prometheus-operator/pkg/k8sutil"
@ -262,11 +262,7 @@ func makeStatefulSetSpec(
return nil, err
}
webRoutePrefix := "/"
if cpf.RoutePrefix != "" {
webRoutePrefix = cpf.RoutePrefix
}
promArgs := prompkg.BuildCommonPrometheusArgs(cpf, cg, webRoutePrefix)
promArgs := prompkg.BuildCommonPrometheusArgs(cpf, cg)
promArgs = appendServerArgs(promArgs, cg, retention, retentionSize, rules, query, allowOverlappingBlocks, enableAdminAPI, cpf.WALCompression)
var ports []v1.ContainerPort
@ -320,7 +316,7 @@ func makeStatefulSetSpec(
// Prometheus is effectively ready.
// We don't want to use the /-/healthy handler here because it returns OK as
// soon as the web server is started (irrespective of the WAL replay).
readyProbeHandler := prompkg.ProbeHandler("/-/ready", cpf, webConfigGenerator, webRoutePrefix)
readyProbeHandler := prompkg.ProbeHandler("/-/ready", cpf, webConfigGenerator)
startupProbe := &v1.Probe{
ProbeHandler: readyProbeHandler,
TimeoutSeconds: prompkg.ProbeTimeoutSeconds,
@ -336,7 +332,7 @@ func makeStatefulSetSpec(
}
livenessProbe := &v1.Probe{
ProbeHandler: prompkg.ProbeHandler("/-/healthy", cpf, webConfigGenerator, webRoutePrefix),
ProbeHandler: prompkg.ProbeHandler("/-/healthy", cpf, webConfigGenerator),
TimeoutSeconds: prompkg.ProbeTimeoutSeconds,
PeriodSeconds: 5,
FailureThreshold: 6,
@ -365,12 +361,7 @@ func makeStatefulSetSpec(
var additionalContainers, operatorInitContainers []v1.Container
prometheusURIScheme := "http"
if cpf.Web != nil && cpf.Web.TLSConfig != nil {
prometheusURIScheme = "https"
}
thanosContainer, err := createThanosContainer(&disableCompaction, p, thanos, c, prometheusURIScheme, webRoutePrefix)
thanosContainer, err := createThanosContainer(&disableCompaction, p, thanos, c)
if err != nil {
return nil, err
}
@ -416,18 +407,13 @@ func makeStatefulSetSpec(
}
operatorInitContainers = append(operatorInitContainers,
operator.CreateConfigReloader(
"init-config-reloader",
operator.ReloaderConfig(c.ReloaderConfig),
operator.ReloaderRunOnce(),
operator.LogFormat(cpf.LogFormat),
operator.LogLevel(cpf.LogLevel),
operator.VolumeMounts(configReloaderVolumeMounts),
operator.ConfigFile(path.Join(prompkg.ConfDir, prompkg.ConfigFilename)),
operator.ConfigEnvsubstFile(path.Join(prompkg.ConfOutDir, prompkg.ConfigEnvsubstFilename)),
operator.WatchedDirectories(watchedDirectories),
prompkg.BuildConfigReloader(
p,
c,
true,
configReloaderVolumeMounts,
watchedDirectories,
operator.Shard(shard),
operator.ImagePullPolicy(cpf.ImagePullPolicy),
),
)
@ -437,13 +423,10 @@ func makeStatefulSetSpec(
}
containerArgs, err := operator.BuildArgs(promArgs, cpf.AdditionalArgs)
if err != nil {
return nil, err
}
boolFalse := false
boolTrue := true
operatorContainers := append([]v1.Container{
{
Name: "prometheus",
@ -458,30 +441,20 @@ func makeStatefulSetSpec(
Resources: cpf.Resources,
TerminationMessagePolicy: v1.TerminationMessageFallbackToLogsOnError,
SecurityContext: &v1.SecurityContext{
ReadOnlyRootFilesystem: &boolTrue,
AllowPrivilegeEscalation: &boolFalse,
ReadOnlyRootFilesystem: ptr.To(true),
AllowPrivilegeEscalation: ptr.To(false),
Capabilities: &v1.Capabilities{
Drop: []v1.Capability{"ALL"},
},
},
},
operator.CreateConfigReloader(
"config-reloader",
operator.ReloaderConfig(c.ReloaderConfig),
operator.ReloaderURL(url.URL{
Scheme: prometheusURIScheme,
Host: c.LocalHost + ":9090",
Path: path.Clean(webRoutePrefix + "/-/reload"),
}),
operator.ListenLocal(cpf.ListenLocal),
operator.LocalHost(c.LocalHost),
operator.LogFormat(cpf.LogFormat),
operator.LogLevel(cpf.LogLevel),
operator.ConfigFile(path.Join(prompkg.ConfDir, prompkg.ConfigFilename)),
operator.ConfigEnvsubstFile(path.Join(prompkg.ConfOutDir, prompkg.ConfigEnvsubstFilename)),
operator.WatchedDirectories(watchedDirectories), operator.VolumeMounts(configReloaderVolumeMounts),
prompkg.BuildConfigReloader(
p,
c,
false,
configReloaderVolumeMounts,
watchedDirectories,
operator.Shard(shard),
operator.ImagePullPolicy(cpf.ImagePullPolicy),
),
}, additionalContainers...)
@ -509,11 +482,12 @@ func makeStatefulSetSpec(
Annotations: podAnnotations,
},
Spec: v1.PodSpec{
ShareProcessNamespace: prompkg.ShareProcessNamespace(p),
Containers: containers,
InitContainers: initContainers,
SecurityContext: cpf.SecurityContext,
ServiceAccountName: cpf.ServiceAccountName,
AutomountServiceAccountToken: &boolTrue,
AutomountServiceAccountToken: ptr.To(true),
NodeSelector: cpf.NodeSelector,
PriorityClassName: cpf.PriorityClassName,
TerminationGracePeriodSeconds: &terminationGracePeriod,
@ -647,8 +621,7 @@ func createThanosContainer(
disableCompaction *bool,
p monitoringv1.PrometheusInterface,
thanos *monitoringv1.ThanosSpec,
c *prompkg.Config,
prometheusURIScheme, webRoutePrefix string) (*v1.Container, error) {
c *prompkg.Config) (*v1.Container, error) {
var container *v1.Container
cpf := p.GetCommonPrometheusFields()
@ -675,7 +648,7 @@ func createThanosContainer(
}
thanosArgs := []monitoringv1.Argument{
{Name: "prometheus.url", Value: fmt.Sprintf("%s://%s:9090%s", prometheusURIScheme, c.LocalHost, path.Clean(webRoutePrefix))},
{Name: "prometheus.url", Value: fmt.Sprintf("%s://%s:9090%s", cpf.PrometheusURIScheme(), c.LocalHost, path.Clean(cpf.WebRoutePrefix()))},
{Name: "prometheus.http-client", Value: `{"tls_config": {"insecure_skip_verify":true}}`},
{Name: "grpc-address", Value: fmt.Sprintf("%s:10901", grpcBindAddress)},
{Name: "http-address", Value: fmt.Sprintf("%s:10902", httpBindAddress)},

View file

@ -2075,6 +2075,83 @@ func TestConfigReloader(t *testing.T) {
}
}
func TestConfigReloaderWithSignal(t *testing.T) {
expectedShardNum := 0
logger := newLogger()
p := monitoringv1.Prometheus{
Spec: monitoringv1.PrometheusSpec{
CommonPrometheusFields: monitoringv1.CommonPrometheusFields{
ReloadStrategy: func(r monitoringv1.ReloadStrategyType) *monitoringv1.ReloadStrategyType { return &r }(monitoringv1.ProcessSignalReloadStrategyType),
},
},
}
cg, err := prompkg.NewConfigGenerator(logger, &p, false)
require.NoError(t, err)
sset, err := makeStatefulSet(
"test",
&p,
p.Spec.BaseImage, p.Spec.Tag, p.Spec.SHA,
p.Spec.Retention,
p.Spec.RetentionSize,
p.Spec.Rules,
p.Spec.Query,
p.Spec.AllowOverlappingBlocks,
p.Spec.EnableAdminAPI,
p.Spec.QueryLogFile,
p.Spec.Thanos,
p.Spec.DisableCompaction,
defaultTestConfig,
cg,
nil,
"",
int32(expectedShardNum),
nil)
require.NoError(t, err)
expectedArgsConfigReloader := []string{
"--listen-address=:8080",
"--reload-method=signal",
"--runtimeinfo-url=http://localhost:9090/api/v1/status/runtimeinfo",
"--config-file=/etc/prometheus/config/prometheus.yaml.gz",
"--config-envsubst-file=/etc/prometheus/config_out/prometheus.env.yaml",
}
for _, c := range sset.Spec.Template.Spec.Containers {
switch c.Name {
case "config-reloader":
require.Equal(t, expectedArgsConfigReloader, c.Args)
for _, env := range c.Env {
if env.Name == "SHARD" {
require.Equal(t, strconv.Itoa(expectedShardNum), env.Value)
}
}
case "prometheus":
require.NotContains(t, c.Args, "--web.enable-lifecycle")
}
}
expectedArgsInitConfigReloader := []string{
"--watch-interval=0",
"--listen-address=:8080",
"--config-file=/etc/prometheus/config/prometheus.yaml.gz",
"--config-envsubst-file=/etc/prometheus/config_out/prometheus.env.yaml",
}
for _, c := range sset.Spec.Template.Spec.InitContainers {
if c.Name == "init-config-reloader" {
require.Equal(t, expectedArgsInitConfigReloader, c.Args)
for _, env := range c.Env {
if env.Name == "SHARD" {
require.Equal(t, strconv.Itoa(expectedShardNum), env.Value)
}
}
}
}
}
func TestThanosGetConfigInterval(t *testing.T) {
sset, err := makeStatefulSetFromPrometheus(monitoringv1.Prometheus{
Spec: monitoringv1.PrometheusSpec{

View file

@ -204,12 +204,15 @@ func queryLogFilePath(queryLogFile string) string {
}
// BuildCommonPrometheusArgs builds a slice of arguments that are common between Prometheus Server and Agent.
func BuildCommonPrometheusArgs(cpf monitoringv1.CommonPrometheusFields, cg *ConfigGenerator, webRoutePrefix string) []monitoringv1.Argument {
func BuildCommonPrometheusArgs(cpf monitoringv1.CommonPrometheusFields, cg *ConfigGenerator) []monitoringv1.Argument {
promArgs := []monitoringv1.Argument{
{Name: "web.console.templates", Value: "/etc/prometheus/consoles"},
{Name: "web.console.libraries", Value: "/etc/prometheus/console_libraries"},
{Name: "config.file", Value: path.Join(ConfOutDir, ConfigEnvsubstFilename)},
{Name: "web.enable-lifecycle"},
}
if ptr.Deref(cpf.ReloadStrategy, monitoringv1.HTTPReloadStrategyType) == monitoringv1.HTTPReloadStrategyType {
promArgs = append(promArgs, monitoringv1.Argument{Name: "web.enable-lifecycle"})
}
if cpf.Web != nil {
@ -234,7 +237,7 @@ func BuildCommonPrometheusArgs(cpf monitoringv1.CommonPrometheusFields, cg *Conf
promArgs = append(promArgs, monitoringv1.Argument{Name: "web.external-url", Value: cpf.ExternalURL})
}
promArgs = append(promArgs, monitoringv1.Argument{Name: "web.route-prefix", Value: webRoutePrefix})
promArgs = append(promArgs, monitoringv1.Argument{Name: "web.route-prefix", Value: cpf.WebRoutePrefix()})
if cpf.LogLevel != "" && cpf.LogLevel != "info" {
promArgs = append(promArgs, monitoringv1.Argument{Name: "log.level", Value: cpf.LogLevel})
@ -375,8 +378,8 @@ func VolumeClaimName(p monitoringv1.PrometheusInterface, cpf monitoringv1.Common
return volName
}
func ProbeHandler(probePath string, cpf monitoringv1.CommonPrometheusFields, webConfigGenerator *ConfigGenerator, webRoutePrefix string) v1.ProbeHandler {
probePath = path.Clean(webRoutePrefix + probePath)
func ProbeHandler(probePath string, cpf monitoringv1.CommonPrometheusFields, webConfigGenerator *ConfigGenerator) v1.ProbeHandler {
probePath = path.Clean(cpf.WebRoutePrefix() + probePath)
handler := v1.ProbeHandler{}
if cpf.ListenLocal {
probeURL := url.URL{
@ -427,3 +430,69 @@ func BuildPodMetadata(cpf monitoringv1.CommonPrometheusFields, cg *ConfigGenerat
return podAnnotations, podLabels
}
func BuildConfigReloader(
p monitoringv1.PrometheusInterface,
c *Config,
initContainer bool,
mounts []v1.VolumeMount,
watchedDirectories []string,
opts ...operator.ReloaderOption,
) v1.Container {
cpf := p.GetCommonPrometheusFields()
reloaderOptions := []operator.ReloaderOption{
operator.ReloaderConfig(c.ReloaderConfig),
operator.LogFormat(cpf.LogFormat),
operator.LogLevel(cpf.LogLevel),
operator.VolumeMounts(mounts),
operator.ConfigFile(path.Join(ConfDir, ConfigFilename)),
operator.ConfigEnvsubstFile(path.Join(ConfOutDir, ConfigEnvsubstFilename)),
operator.WatchedDirectories(watchedDirectories),
operator.ImagePullPolicy(cpf.ImagePullPolicy),
}
reloaderOptions = append(reloaderOptions, opts...)
name := "config-reloader"
if initContainer {
name = "init-config-reloader"
reloaderOptions = append(reloaderOptions, operator.ReloaderRunOnce())
return operator.CreateConfigReloader(name, reloaderOptions...)
}
if ptr.Deref(cpf.ReloadStrategy, monitoringv1.HTTPReloadStrategyType) == monitoringv1.ProcessSignalReloadStrategyType {
reloaderOptions = append(reloaderOptions,
operator.ReloaderUseSignal(),
)
reloaderOptions = append(reloaderOptions,
operator.RuntimeInfoURL(url.URL{
Scheme: cpf.PrometheusURIScheme(),
Host: c.LocalHost + ":9090",
Path: path.Clean(cpf.WebRoutePrefix() + "/api/v1/status/runtimeinfo"),
}),
)
} else {
reloaderOptions = append(reloaderOptions,
operator.ListenLocal(cpf.ListenLocal),
operator.LocalHost(c.LocalHost),
)
reloaderOptions = append(reloaderOptions,
operator.ReloaderURL(url.URL{
Scheme: cpf.PrometheusURIScheme(),
Host: c.LocalHost + ":9090",
Path: path.Clean(cpf.WebRoutePrefix() + "/-/reload"),
}),
)
}
return operator.CreateConfigReloader(name, reloaderOptions...)
}
func ShareProcessNamespace(p monitoringv1.PrometheusInterface) *bool {
return ptr.To(
ptr.Deref(
p.GetCommonPrometheusFields().ReloadStrategy,
monitoringv1.HTTPReloadStrategyType,
) == monitoringv1.ProcessSignalReloadStrategyType,
)
}

View file

@ -1161,18 +1161,31 @@ func testPromStorageUpdate(t *testing.T) {
}
func testPromReloadConfig(t *testing.T) {
t.Parallel()
testCtx := framework.NewTestCtx(t)
defer testCtx.Cleanup(t)
ns := framework.CreateNamespace(context.Background(), t, testCtx)
framework.SetupPrometheusRBAC(context.Background(), t, testCtx, ns)
for _, tc := range []struct {
reloadStrategy monitoringv1.ReloadStrategyType
}{
{
reloadStrategy: monitoringv1.HTTPReloadStrategyType,
},
{
reloadStrategy: monitoringv1.ProcessSignalReloadStrategyType,
},
} {
tc := tc
t.Run(fmt.Sprintf("%s reload strategy", tc.reloadStrategy), func(t *testing.T) {
t.Parallel()
testCtx := framework.NewTestCtx(t)
defer testCtx.Cleanup(t)
ns := framework.CreateNamespace(context.Background(), t, testCtx)
framework.SetupPrometheusRBAC(context.Background(), t, testCtx, ns)
name := "test"
p := framework.MakeBasicPrometheus(ns, name, name, 1)
p.Spec.ServiceMonitorSelector = nil
p.Spec.PodMonitorSelector = nil
name := "test"
p := framework.MakeBasicPrometheus(ns, name, name, 1)
p.Spec.ServiceMonitorSelector = nil
p.Spec.PodMonitorSelector = nil
p.Spec.ReloadStrategy = ptr.To(tc.reloadStrategy)
firstConfig := `
firstConfig := `
global:
scrape_interval: 1m
scrape_configs:
@ -1183,43 +1196,43 @@ scrape_configs:
- 111.111.111.111:9090
`
var bufOne bytes.Buffer
if err := operator.GzipConfig(&bufOne, []byte(firstConfig)); err != nil {
t.Fatal(err)
}
firstConfigCompressed := bufOne.Bytes()
var bufOne bytes.Buffer
if err := operator.GzipConfig(&bufOne, []byte(firstConfig)); err != nil {
t.Fatal(err)
}
firstConfigCompressed := bufOne.Bytes()
cfg := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("prometheus-%s", name),
},
Data: map[string][]byte{
"prometheus.yaml.gz": firstConfigCompressed,
"configmaps.json": []byte("{}"),
},
}
cfg := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("prometheus-%s", name),
},
Data: map[string][]byte{
"prometheus.yaml.gz": firstConfigCompressed,
"configmaps.json": []byte("{}"),
},
}
svc := framework.MakePrometheusService(p.Name, "not-relevant", v1.ServiceTypeClusterIP)
svc := framework.MakePrometheusService(p.Name, "not-relevant", v1.ServiceTypeClusterIP)
if _, err := framework.KubeClient.CoreV1().Secrets(ns).Create(context.Background(), cfg, metav1.CreateOptions{}); err != nil {
t.Fatal(err)
}
if _, err := framework.KubeClient.CoreV1().Secrets(ns).Create(context.Background(), cfg, metav1.CreateOptions{}); err != nil {
t.Fatal(err)
}
if _, err := framework.CreatePrometheusAndWaitUntilReady(context.Background(), ns, p); err != nil {
t.Fatal(err)
}
if _, err := framework.CreatePrometheusAndWaitUntilReady(context.Background(), ns, p); err != nil {
t.Fatal(err)
}
if finalizerFn, err := framework.CreateOrUpdateServiceAndWaitUntilReady(context.Background(), ns, svc); err != nil {
t.Fatal(err)
} else {
testCtx.AddFinalizerFn(finalizerFn)
}
if finalizerFn, err := framework.CreateOrUpdateServiceAndWaitUntilReady(context.Background(), ns, svc); err != nil {
t.Fatal(err)
} else {
testCtx.AddFinalizerFn(finalizerFn)
}
if err := framework.WaitForActiveTargets(context.Background(), ns, svc.Name, 1); err != nil {
t.Fatal(err)
}
if err := framework.WaitForActiveTargets(context.Background(), ns, svc.Name, 1); err != nil {
t.Fatal(err)
}
secondConfig := `
secondConfig := `
global:
scrape_interval: 1m
scrape_configs:
@ -1231,24 +1244,26 @@ scrape_configs:
- 111.111.111.112:9090
`
var bufTwo bytes.Buffer
if err := operator.GzipConfig(&bufTwo, []byte(secondConfig)); err != nil {
t.Fatal(err)
}
secondConfigCompressed := bufTwo.Bytes()
var bufTwo bytes.Buffer
if err := operator.GzipConfig(&bufTwo, []byte(secondConfig)); err != nil {
t.Fatal(err)
}
secondConfigCompressed := bufTwo.Bytes()
cfg, err := framework.KubeClient.CoreV1().Secrets(ns).Get(context.Background(), cfg.Name, metav1.GetOptions{})
if err != nil {
t.Fatal(fmt.Errorf("could not retrieve previous secret: %w", err))
}
cfg, err := framework.KubeClient.CoreV1().Secrets(ns).Get(context.Background(), cfg.Name, metav1.GetOptions{})
if err != nil {
t.Fatal(fmt.Errorf("could not retrieve previous secret: %w", err))
}
cfg.Data["prometheus.yaml.gz"] = secondConfigCompressed
if _, err := framework.KubeClient.CoreV1().Secrets(ns).Update(context.Background(), cfg, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
cfg.Data["prometheus.yaml.gz"] = secondConfigCompressed
if _, err := framework.KubeClient.CoreV1().Secrets(ns).Update(context.Background(), cfg, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
if err := framework.WaitForActiveTargets(context.Background(), ns, svc.Name, 2); err != nil {
t.Fatal(err)
if err := framework.WaitForActiveTargets(context.Background(), ns, svc.Name, 2); err != nil {
t.Fatal(err)
}
})
}
}