diff --git a/cmd/operator/main.go b/cmd/operator/main.go
index 2b7c5d887..dc3d734e9 100644
--- a/cmd/operator/main.go
+++ b/cmd/operator/main.go
@@ -50,7 +50,7 @@ func init() {
 	flagset.StringVar(&cfg.TLSConfig.CAFile, "ca-file", "", "- NOT RECOMMENDED FOR PRODUCTION - Path to TLS CA file.")
 	flagset.StringVar(&cfg.KubeletObject, "kubelet-service", "", "Service/Endpoints object to write kubelets into in format \"namespace/name\"")
 	flagset.BoolVar(&cfg.TLSInsecure, "tls-insecure", false, "- NOT RECOMMENDED FOR PRODUCTION - Don't verify API server's CA certificate.")
-	flagset.StringVar(&cfg.PrometheusConfigReloader, "prometheus-config-reloader", "quay.io/coreos/prometheus-config-reloader:v0.0.3", "Config and rule reload image")
+	flagset.StringVar(&cfg.PrometheusConfigReloader, "prometheus-config-reloader", "quay.io/coreos/prometheus-config-reloader:v0.0.4", "Config and rule reload image")
 	flagset.StringVar(&cfg.ConfigReloaderImage, "config-reloader-image", "quay.io/coreos/configmap-reload:v0.0.1", "Reload Image")
 	flagset.StringVar(&cfg.AlertmanagerDefaultBaseImage, "alertmanager-default-base-image", "quay.io/prometheus/alertmanager", "Alertmanager default base image")
 	flagset.StringVar(&cfg.PrometheusDefaultBaseImage, "prometheus-default-base-image", "quay.io/prometheus/prometheus", "Prometheus default base image")
diff --git a/contrib/prometheus-config-reloader/examples/prometheus-config-reloader.yaml b/contrib/prometheus-config-reloader/examples/prometheus-config-reloader.yaml
index 29b5afbd1..9469b240d 100644
--- a/contrib/prometheus-config-reloader/examples/prometheus-config-reloader.yaml
+++ b/contrib/prometheus-config-reloader/examples/prometheus-config-reloader.yaml
@@ -30,7 +30,7 @@ spec:
           mountPath: /etc/prometheus/rules
           readOnly: true
       - name: prometheus-config-reloader
-        image: quay.io/coreos/prometheus-config-reloader:v0.0.3
+        image: quay.io/coreos/prometheus-config-reloader:v0.0.4
         args:
         - '-config-volume-dir=/etc/prometheus/config'
         - '-rule-volume-dir=/etc/prometheus/rules'
diff --git a/contrib/prometheus-config-reloader/main.go b/contrib/prometheus-config-reloader/main.go
index 7834b9c9e..92bcb2460 100644
--- a/contrib/prometheus-config-reloader/main.go
+++ b/contrib/prometheus-config-reloader/main.go
@@ -186,7 +186,6 @@ func (rf *ruleFetcher) refresh(ctx context.Context, cms []*configMapRef) error {
 				return err
 			}
 		}
-		return nil
 	}
 
 	if err := os.RemoveAll(rf.outDir); err != nil {
diff --git a/pkg/prometheus/operator.go b/pkg/prometheus/operator.go
index 6c643fef9..29799f7d3 100644
--- a/pkg/prometheus/operator.go
+++ b/pkg/prometheus/operator.go
@@ -45,8 +45,6 @@ import (
 )
 
 const (
-	configFilename = "prometheus.yaml"
-
 	resyncPeriod = 5 * time.Minute
 )
 
@@ -1015,10 +1013,12 @@ func (c *Operator) createConfig(p *monitoringv1.Prometheus, ruleFileConfigMaps [
 		return err
 	}
 
-	generatedConf := s.Data[configFilename]
-	generatedConfigMaps := s.Data[configMapsFilename]
-	curConfig, curConfigFound := curSecret.Data[configFilename]
-	curConfigMaps, curConfigMapsFound := curSecret.Data[configMapsFilename]
+	var (
+		generatedConf                     = s.Data[configFilename]
+		generatedConfigMaps               = s.Data[ruleConfigmapsFilename]
+		curConfig, curConfigFound         = curSecret.Data[configFilename]
+		curConfigMaps, curConfigMapsFound = curSecret.Data[ruleConfigmapsFilename]
+	)
 	if curConfigFound && curConfigMapsFound {
 		if bytes.Equal(curConfig, generatedConf) && bytes.Equal(curConfigMaps, generatedConfigMaps) {
 			c.logger.Log("msg", "updating config skipped, no configuration change")
diff --git a/pkg/prometheus/promcfg.go b/pkg/prometheus/promcfg.go
index 0c2d8da35..f2ae06c86 100644
--- a/pkg/prometheus/promcfg.go
+++ b/pkg/prometheus/promcfg.go
@@ -37,7 +37,7 @@ func sanitizeLabelName(name string) string {
 }
 
 func configMapRuleFileFolder(configMapNumber int) string {
-	return fmt.Sprintf("/etc/prometheus/rules/rules-%d/", configMapNumber)
+	return fmt.Sprintf("/etc/prometheus/config_out/rules/rules-%d/", configMapNumber)
 }
 
 func stringMapToMapSlice(m map[string]string) yaml.MapSlice {
@@ -78,6 +78,18 @@ func addTLStoYaml(cfg yaml.MapSlice, tls *v1.TLSConfig) yaml.MapSlice {
 	return cfg
 }
 
+func buildExternalLabels(p *v1.Prometheus) yaml.MapSlice {
+	m := map[string]string{}
+
+	m["prometheus"] = fmt.Sprintf("%s/%s", p.Namespace, p.Name)
+	m["prometheus_replica"] = "$(POD_NAME)"
+
+	for n, v := range p.Spec.ExternalLabels {
+		m[n] = v
+	}
+	return stringMapToMapSlice(m)
+}
+
 func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleConfigMaps int, basicAuthSecrets map[string]BasicAuthCredentials) ([]byte, error) {
 	versionStr := p.Spec.Version
 	if versionStr == "" {
@@ -106,7 +118,7 @@ func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleCo
 		Value: yaml.MapSlice{
 			{Key: "evaluation_interval", Value: evaluationInterval},
 			{Key: "scrape_interval", Value: scrapeInterval},
-			{Key: "external_labels", Value: stringMapToMapSlice(p.Spec.ExternalLabels)},
+			{Key: "external_labels", Value: buildExternalLabels(p)},
 		},
 	})
 
@@ -231,20 +243,17 @@ func generateServiceMonitorConfig(version semver.Version, m *v1.ServiceMonitor,
 	// Filter targets by services selected by the monitor.
 
 	// Exact label matches.
-	labelKeys := make([]string, len(m.Spec.Selector.MatchLabels))
-	i = 0
-	for k, _ := range m.Spec.Selector.MatchLabels {
-		labelKeys[i] = k
-		i++
+	var labelKeys []string
+	for k := range m.Spec.Selector.MatchLabels {
+		labelKeys = append(labelKeys, k)
 	}
 	sort.Strings(labelKeys)
-	for i := range labelKeys {
-		k := labelKeys[i]
-		v := m.Spec.Selector.MatchLabels[k]
+
+	for _, k := range labelKeys {
 		relabelings = append(relabelings, yaml.MapSlice{
 			{Key: "action", Value: "keep"},
 			{Key: "source_labels", Value: []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(k)}},
-			{Key: "regex", Value: v},
+			{Key: "regex", Value: m.Spec.Selector.MatchLabels[k]},
 		})
 	}
 	// Set based label matching. We have to map the valid relations
diff --git a/pkg/prometheus/promcfg_test.go b/pkg/prometheus/promcfg_test.go
index cf5ca28a6..d0d1da1e8 100644
--- a/pkg/prometheus/promcfg_test.go
+++ b/pkg/prometheus/promcfg_test.go
@@ -117,7 +117,9 @@ func TestAlertmanagerBearerToken(t *testing.T) {
 	expected := `global:
   evaluation_interval: 30s
   scrape_interval: 30s
-  external_labels: {}
+  external_labels:
+    prometheus: default/test
+    prometheus_replica: $(POD_NAME)
 scrape_configs: []
 alerting:
   alertmanagers:
diff --git a/pkg/prometheus/statefulset.go b/pkg/prometheus/statefulset.go
index c9b0c47ad..cb8c2bbde 100644
--- a/pkg/prometheus/statefulset.go
+++ b/pkg/prometheus/statefulset.go
@@ -36,15 +36,17 @@ import (
 )
 
 const (
-	governingServiceName = "prometheus-operated"
-	DefaultVersion       = "v2.2.1"
-	defaultRetention     = "24h"
-	configMapsFilename   = "configmaps.json"
-	prometheusConfDir    = "/etc/prometheus/config"
-	prometheusConfFile   = prometheusConfDir + "/prometheus.yaml"
-	prometheusStorageDir = "/prometheus"
-	prometheusRulesDir   = "/etc/prometheus/rules"
-	prometheusSecretsDir = "/etc/prometheus/secrets/"
+	governingServiceName   = "prometheus-operated"
+	DefaultVersion         = "v2.2.1"
+	defaultRetention       = "24h"
+	storageDir             = "/prometheus"
+	confDir                = "/etc/prometheus/config"
+	confOutDir             = "/etc/prometheus/config_out"
+	rulesDir               = "/etc/prometheus/config_out/rules"
+	secretsDir             = "/etc/prometheus/secrets/"
+	configFilename         = "prometheus.yaml"
+	configEnvsubstFilename = "prometheus.env.yaml"
+	ruleConfigmapsFilename = "configmaps.json"
 )
 
 var (
@@ -274,8 +276,8 @@ func makeConfigSecret(p *monitoringv1.Prometheus, configMaps []*v1.ConfigMap, co
 			},
 		},
 		Data: map[string][]byte{
-			configFilename:     []byte{},
-			configMapsFilename: b,
+			configFilename:         []byte{},
+			ruleConfigmapsFilename: b,
 		},
 	}, nil
 }
@@ -325,9 +327,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 		promArgs = append(promArgs,
 			"-storage.local.retention="+p.Spec.Retention,
 			"-storage.local.num-fingerprint-mutexes=4096",
-			fmt.Sprintf("-storage.local.path=%s", prometheusStorageDir),
+			fmt.Sprintf("-storage.local.path=%s", storageDir),
 			"-storage.local.chunk-encoding-version=2",
-			fmt.Sprintf("-config.file=%s", prometheusConfFile))
+			fmt.Sprintf("-config.file=%s", path.Join(confOutDir, configEnvsubstFilename)),
+		)
 		// We attempt to specify decent storage tuning flags based on how much the
 		// requested memory can fit. The user has to specify an appropriate buffering
 		// in memory limits to catch increased memory usage during query bursts.
@@ -356,8 +359,8 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 		securityContext = &v1.PodSecurityContext{}
 	case 2:
 		promArgs = append(promArgs,
-			fmt.Sprintf("-config.file=%s", prometheusConfFile),
-			fmt.Sprintf("-storage.tsdb.path=%s", prometheusStorageDir),
+			fmt.Sprintf("-config.file=%s", path.Join(confOutDir, configEnvsubstFilename)),
+			fmt.Sprintf("-storage.tsdb.path=%s", storageDir),
 			"-storage.tsdb.retention="+p.Spec.Retention,
 			"-web.enable-lifecycle",
 			"-storage.tsdb.no-lockfile",
@@ -430,7 +433,7 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 			},
 		},
 		{
-			Name: "rules",
+			Name: "config-out",
 			VolumeSource: v1.VolumeSource{
 				EmptyDir: &v1.EmptyDirVolumeSource{},
 			},
@@ -439,18 +442,13 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 
 	promVolumeMounts := []v1.VolumeMount{
 		{
-			Name:      "config",
+			Name:      "config-out",
 			ReadOnly:  true,
-			MountPath: prometheusConfDir,
-		},
-		{
-			Name:      "rules",
-			ReadOnly:  true,
-			MountPath: prometheusRulesDir,
+			MountPath: confOutDir,
 		},
 		{
 			Name:      volumeName(p.Name),
-			MountPath: prometheusStorageDir,
+			MountPath: storageDir,
 			SubPath:   subPathForStorage(p.Spec.Storage),
 		},
 	}
@@ -467,26 +465,27 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 		promVolumeMounts = append(promVolumeMounts, v1.VolumeMount{
 			Name:      "secret-" + s,
 			ReadOnly:  true,
-			MountPath: prometheusSecretsDir + s,
+			MountPath: secretsDir + s,
 		})
 	}
 
 	configReloadVolumeMounts := []v1.VolumeMount{
 		{
 			Name:      "config",
-			ReadOnly:  true,
-			MountPath: prometheusConfDir,
+			MountPath: confDir,
 		},
 		{
-			Name:      "rules",
-			MountPath: prometheusRulesDir,
+			Name:      "config-out",
+			MountPath: confOutDir,
 		},
 	}
 
 	configReloadArgs := []string{
-		fmt.Sprintf("-reload-url=%s", localReloadURL),
-		fmt.Sprintf("-config-volume-dir=%s", prometheusConfDir),
-		fmt.Sprintf("-rule-volume-dir=%s", prometheusRulesDir),
+		fmt.Sprintf("--reload-url=%s", localReloadURL),
+		fmt.Sprintf("--config-file=%s", path.Join(confDir, configFilename)),
+		fmt.Sprintf("--rule-list-file=%s", path.Join(confDir, ruleConfigmapsFilename)),
+		fmt.Sprintf("--config-envsubst-file=%s", path.Join(confOutDir, configEnvsubstFilename)),
+		fmt.Sprintf("--rule-dir=%s", rulesDir),
 	}
 
 	var livenessProbeHandler v1.Handler
@@ -551,10 +550,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 			}
 		}
 	}
+
 	podLabels["app"] = "prometheus"
 	podLabels["prometheus"] = p.Name
 
-	finalLabels := c.Labels.Merge(podLabels)
 	return &appsv1.StatefulSetSpec{
 		ServiceName:         governingServiceName,
 		Replicas:            p.Spec.Replicas,
@@ -562,12 +561,9 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 		UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
 			Type: appsv1.RollingUpdateStatefulSetStrategyType,
 		},
-		Selector: &metav1.LabelSelector{
-			MatchLabels: finalLabels,
-		},
 		Template: v1.PodTemplateSpec{
 			ObjectMeta: metav1.ObjectMeta{
-				Labels:      finalLabels,
+				Labels:      c.Labels.Merge(podLabels),
 				Annotations: podAnnotations,
 			},
 			Spec: v1.PodSpec{
@@ -582,8 +578,16 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
 						ReadinessProbe: readinessProbe,
 						Resources:      p.Spec.Resources,
 					}, {
-						Name:         "prometheus-config-reloader",
-						Image:        c.PrometheusConfigReloader,
+						Name:  "prometheus-config-reloader",
+						Image: c.PrometheusConfigReloader,
+						Env: []v1.EnvVar{
+							{
+								Name: "POD_NAME",
+								ValueFrom: &v1.EnvVarSource{
+									FieldRef: &v1.ObjectFieldSelector{FieldPath: "metadata.name"},
+								},
+							},
+						},
 						Args:         configReloadArgs,
 						VolumeMounts: configReloadVolumeMounts,
 						Resources: v1.ResourceRequirements{
diff --git a/pkg/prometheus/statefulset_test.go b/pkg/prometheus/statefulset_test.go
index 86bde1430..3d189a612 100644
--- a/pkg/prometheus/statefulset_test.go
+++ b/pkg/prometheus/statefulset_test.go
@@ -159,14 +159,9 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
 						{
 							VolumeMounts: []v1.VolumeMount{
 								{
-									Name:      "config",
+									Name:      "config-out",
 									ReadOnly:  true,
-									MountPath: "/etc/prometheus/config",
-									SubPath:   "",
-								}, {
-									Name:      "rules",
-									ReadOnly:  true,
-									MountPath: "/etc/prometheus/rules",
+									MountPath: "/etc/prometheus/config_out",
 									SubPath:   "",
 								}, {
 									Name:      "prometheus--db",
@@ -192,7 +187,7 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
 							},
 						},
 						{
-							Name: "rules",
+							Name: "config-out",
 							VolumeSource: v1.VolumeSource{
 								EmptyDir: &v1.EmptyDirVolumeSource{},
 							},
@@ -227,8 +222,15 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
 
 	require.NoError(t, err)
 
-	if !reflect.DeepEqual(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes) || !reflect.DeepEqual(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts) {
-		t.Fatal("Volumes mounted in a Pod are not created correctly initially.")
+	if !reflect.DeepEqual(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes) {
+		t.Fatalf("Unexpected volumes: want %v, got %v",
+			expected.Spec.Template.Spec.Volumes,
+			sset.Spec.Template.Spec.Volumes)
+	}
+	if !reflect.DeepEqual(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts) {
+		t.Fatalf("Unexpected volume mounts: want %v, got %v",
+			expected.Spec.Template.Spec.Containers[0].VolumeMounts,
+			sset.Spec.Template.Spec.Containers[0].VolumeMounts)
 	}
 }