operator: Add support for gRPC over TLS for Loki components (#6224)

pull/5921/head^2
Periklis Tsirakidis 3 years ago committed by GitHub
parent f657122ccd
commit f91f6a354b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      operator/CHANGELOG.md
  2. 1
      operator/bundle/manifests/loki-operator.clusterserviceversion.yaml
  3. 1
      operator/config/overlays/openshift/manager_run_flags_patch.yaml
  4. 4
      operator/internal/manifests/build.go
  5. 190
      operator/internal/manifests/build_test.go
  6. 30
      operator/internal/manifests/compactor.go
  7. 83
      operator/internal/manifests/distributor.go
  8. 18
      operator/internal/manifests/gateway.go
  9. 29
      operator/internal/manifests/gateway_tenants.go
  10. 49
      operator/internal/manifests/gateway_tenants_test.go
  11. 2
      operator/internal/manifests/gateway_test.go
  12. 30
      operator/internal/manifests/indexgateway.go
  13. 78
      operator/internal/manifests/ingester.go
  14. 10
      operator/internal/manifests/internal/gateway/build.go
  15. 26
      operator/internal/manifests/openshift/build.go
  16. 16
      operator/internal/manifests/openshift/build_test.go
  17. 8
      operator/internal/manifests/openshift/configure.go
  18. 32
      operator/internal/manifests/openshift/options.go
  19. 4
      operator/internal/manifests/openshift/service_ca.go
  20. 2
      operator/internal/manifests/openshift/serviceaccount_test.go
  21. 2
      operator/internal/manifests/openshift/var.go
  22. 1
      operator/internal/manifests/options.go
  23. 81
      operator/internal/manifests/querier.go
  24. 41
      operator/internal/manifests/query-frontend.go
  25. 71
      operator/internal/manifests/ruler.go
  26. 48
      operator/internal/manifests/service.go
  27. 16
      operator/internal/manifests/service_monitor.go
  28. 6
      operator/internal/manifests/storage/schema_test.go
  29. 27
      operator/internal/manifests/var.go
  30. 4
      operator/main.go

@ -1,5 +1,6 @@
## Main
- [6224](https://github.com/grafana/loki/pull/6224) **periklis**: Add support for GRPC over TLS for Loki components
- [5952](https://github.com/grafana/loki/pull/5952) **Red-GV**: Add api to change storage schema version
- [6363](https://github.com/grafana/loki/pull/6363) **periklis**: Allow optional installation of webhooks (Kind)
- [6362](https://github.com/grafana/loki/pull/6362) **periklis**: Allow reduced tenant OIDC authentication requirements

@ -1179,6 +1179,7 @@ spec:
- --with-lokistack-gateway
- --with-lokistack-gateway-route
- --with-cert-signing-service
- --with-tls-grpc-services
- --with-service-monitors
- --with-tls-service-monitors
- --with-prometheus-alerts

@ -11,6 +11,7 @@ spec:
- "--with-lokistack-gateway"
- "--with-lokistack-gateway-route"
- "--with-cert-signing-service"
- "--with-tls-grpc-services"
- "--with-service-monitors"
- "--with-tls-service-monitors"
- "--with-prometheus-alerts"

@ -83,6 +83,10 @@ func BuildAll(opts Options) ([]client.Object, error) {
res = append(res, gatewayObjects...)
}
if opts.Stack.Tenants != nil {
res = configureLokiStackObjsForMode(res, opts)
}
if opts.Flags.EnableServiceMonitors {
res = append(res, BuildServiceMonitors(opts)...)
}

@ -166,7 +166,7 @@ func TestBuildAll_WithFeatureFlags_EnableCertificateSigningService(t *testing.T)
},
},
{
desc: "enabled certificate signing service for every http service",
desc: "enabled certificate signing service for every http and grpc service",
BuildOptions: Options{
Name: "test",
Namespace: "test",
@ -190,18 +190,25 @@ func TestBuildAll_WithFeatureFlags_EnableCertificateSigningService(t *testing.T)
err := ApplyDefaultSettings(&tst.BuildOptions)
require.NoError(t, err)
httpServices := []*corev1.Service{
svcs := []*corev1.Service{
NewDistributorGRPCService(tst.BuildOptions),
NewDistributorHTTPService(tst.BuildOptions),
NewIngesterGRPCService(tst.BuildOptions),
NewIngesterHTTPService(tst.BuildOptions),
NewQuerierGRPCService(tst.BuildOptions),
NewQuerierHTTPService(tst.BuildOptions),
NewQueryFrontendGRPCService(tst.BuildOptions),
NewQueryFrontendHTTPService(tst.BuildOptions),
NewCompactorGRPCService(tst.BuildOptions),
NewCompactorHTTPService(tst.BuildOptions),
NewIndexGatewayGRPCService(tst.BuildOptions),
NewIndexGatewayHTTPService(tst.BuildOptions),
NewRulerHTTPService(tst.BuildOptions),
NewRulerGRPCService(tst.BuildOptions),
NewGatewayHTTPService(tst.BuildOptions),
}
for _, service := range httpServices {
for _, service := range svcs {
if !tst.BuildOptions.Flags.EnableCertificateSigningService {
require.Equal(t, service.ObjectMeta.Annotations, map[string]string{})
} else {
@ -263,7 +270,7 @@ func TestBuildAll_WithFeatureFlags_EnableTLSServiceMonitorConfig(t *testing.T) {
continue
}
secretName := fmt.Sprintf("%s-http-tls", name)
secretName := fmt.Sprintf("%s-http", name)
expVolume := corev1.Volume{
Name: secretName,
VolumeSource: corev1.VolumeSource{
@ -277,17 +284,186 @@ func TestBuildAll_WithFeatureFlags_EnableTLSServiceMonitorConfig(t *testing.T) {
expVolumeMount := corev1.VolumeMount{
Name: secretName,
ReadOnly: false,
MountPath: "/etc/proxy/secrets",
MountPath: "/var/run/tls/http",
}
require.Contains(t, vms, expVolumeMount)
require.Contains(t, args, "-server.http-tls-cert-path=/etc/proxy/secrets/tls.crt")
require.Contains(t, args, "-server.http-tls-key-path=/etc/proxy/secrets/tls.key")
require.Contains(t, args, "-server.http-tls-cert-path=/var/run/tls/http/tls.crt")
require.Contains(t, args, "-server.http-tls-key-path=/var/run/tls/http/tls.key")
require.Equal(t, corev1.URISchemeHTTPS, rps)
require.Equal(t, corev1.URISchemeHTTPS, lps)
}
}
func TestBuildAll_WithFeatureFlags_EnableTLSGRPCServices(t *testing.T) {
type test struct {
desc string
BuildOptions Options
}
table := []test{
{
desc: "disabled grpc over tls services",
BuildOptions: Options{
Name: "test",
Namespace: "test",
Stack: lokiv1beta1.LokiStackSpec{
Size: lokiv1beta1.SizeOneXSmall,
Rules: &lokiv1beta1.RulesSpec{
Enabled: true,
},
Template: &lokiv1beta1.LokiTemplateSpec{
Compactor: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Distributor: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Ingester: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Querier: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
QueryFrontend: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Gateway: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
IndexGateway: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Ruler: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
},
},
Flags: FeatureFlags{
EnableTLSGRPCServices: false,
},
},
},
{
desc: "enabled grpc over tls services",
BuildOptions: Options{
Name: "test",
Namespace: "test",
Stack: lokiv1beta1.LokiStackSpec{
Size: lokiv1beta1.SizeOneXSmall,
Rules: &lokiv1beta1.RulesSpec{
Enabled: true,
},
Template: &lokiv1beta1.LokiTemplateSpec{
Compactor: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Distributor: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Ingester: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Querier: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
QueryFrontend: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Gateway: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
IndexGateway: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
Ruler: &lokiv1beta1.LokiComponentSpec{
Replicas: 1,
},
},
},
Flags: FeatureFlags{
EnableTLSGRPCServices: true,
},
},
},
}
secretsMap := map[string]string{
// deployments
"test-distributor": "test-distributor-grpc",
"test-querier": "test-querier-grpc",
"test-query-frontend": "test-query-frontend-grpc",
// statefulsets
"test-ingester": "test-ingester-grpc",
"test-compactor": "test-compactor-grpc",
"test-index-gateway": "test-index-gateway-grpc",
"test-ruler": "test-ruler-grpc",
}
for _, tst := range table {
tst := tst
t.Run(tst.desc, func(t *testing.T) {
t.Parallel()
err := ApplyDefaultSettings(&tst.BuildOptions)
require.NoError(t, err)
objs, err := BuildAll(tst.BuildOptions)
require.NoError(t, err)
for _, o := range objs {
var (
name string
spec *corev1.PodSpec
)
switch obj := o.(type) {
case *appsv1.Deployment:
name = obj.Name
spec = &obj.Spec.Template.Spec
case *appsv1.StatefulSet:
name = obj.Name
spec = &obj.Spec.Template.Spec
default:
continue
}
t.Run(name, func(t *testing.T) {
secretName := secretsMap[name]
args := []string{
"-server.grpc-tls-cert-path=/var/run/tls/grpc/tls.crt",
"-server.grpc-tls-key-path=/var/run/tls/grpc/tls.key",
}
vm := corev1.VolumeMount{
Name: secretName,
ReadOnly: false,
MountPath: "/var/run/tls/grpc",
}
v := corev1.Volume{
Name: secretName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
},
},
}
if tst.BuildOptions.Flags.EnableTLSGRPCServices {
require.Subset(t, spec.Containers[0].Args, args)
require.Contains(t, spec.Containers[0].VolumeMounts, vm)
require.Contains(t, spec.Volumes, v)
} else {
require.NotSubset(t, spec.Containers[0].Args, args)
require.NotContains(t, spec.Containers[0].VolumeMounts, vm)
require.NotContains(t, spec.Volumes, v)
}
})
}
})
}
}
func TestBuildAll_WithFeatureFlags_EnableGateway(t *testing.T) {
type test struct {
desc string

@ -30,6 +30,12 @@ func BuildCompactor(opts Options) ([]client.Object, error) {
return nil, err
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureCompactorGRPCServicePKI(statefulSet, opts.Name); err != nil {
return nil, err
}
}
return []client.Object{
statefulSet,
NewCompactorGRPCService(opts),
@ -157,7 +163,8 @@ func NewCompactorStatefulSet(opts Options) *appsv1.StatefulSet {
// NewCompactorGRPCService creates a k8s service for the compactor GRPC endpoint
func NewCompactorGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelCompactorComponent, opts.Name)
serviceName := serviceNameCompactorGRPC(opts.Name)
labels := ComponentLabels(LabelCompactorComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -165,8 +172,9 @@ func NewCompactorGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameCompactorGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -178,7 +186,7 @@ func NewCompactorGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -186,8 +194,7 @@ func NewCompactorGRPCService(opts Options) *corev1.Service {
// NewCompactorHTTPService creates a k8s service for the ingester HTTP endpoint
func NewCompactorHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameCompactorHTTP(opts.Name)
l := ComponentLabels(LabelCompactorComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelCompactorComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -196,8 +203,8 @@ func NewCompactorHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -208,7 +215,7 @@ func NewCompactorHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -217,3 +224,8 @@ func configureCompactorServiceMonitorPKI(statefulSet *appsv1.StatefulSet, stackN
serviceName := serviceNameCompactorHTTP(stackName)
return configureServiceMonitorPKI(&statefulSet.Spec.Template.Spec, serviceName)
}
func configureCompactorGRPCServicePKI(sts *appsv1.StatefulSet, stackName string) error {
serviceName := serviceNameCompactorGRPC(stackName)
return configureGRPCServicePKI(&sts.Spec.Template.Spec, serviceName)
}

@ -4,7 +4,9 @@ import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
"github.com/grafana/loki/operator/internal/manifests/internal/config"
"github.com/imdario/mergo"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -23,6 +25,12 @@ func BuildDistributor(opts Options) ([]client.Object, error) {
}
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureDistributorGRPCServicePKI(deployment, opts.Name, opts.Namespace); err != nil {
return nil, err
}
}
return []client.Object{
deployment,
NewDistributorGRPCService(opts),
@ -45,12 +53,6 @@ func NewDistributorDeployment(opts Options) *appsv1.Deployment {
},
},
},
{
Name: storageVolumeName,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
},
Containers: []corev1.Container{
{
@ -90,11 +92,6 @@ func NewDistributorDeployment(opts Options) *appsv1.Deployment {
ReadOnly: false,
MountPath: config.LokiConfigMountDir,
},
{
Name: storageVolumeName,
ReadOnly: false,
MountPath: dataDirectory,
},
},
TerminationMessagePath: "/dev/termination-log",
TerminationMessagePolicy: "File",
@ -142,7 +139,8 @@ func NewDistributorDeployment(opts Options) *appsv1.Deployment {
// NewDistributorGRPCService creates a k8s service for the distributor GRPC endpoint
func NewDistributorGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelDistributorComponent, opts.Name)
serviceName := serviceNameDistributorGRPC(opts.Name)
labels := ComponentLabels(LabelDistributorComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -150,8 +148,9 @@ func NewDistributorGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameDistributorGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -163,7 +162,7 @@ func NewDistributorGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -171,8 +170,7 @@ func NewDistributorGRPCService(opts Options) *corev1.Service {
// NewDistributorHTTPService creates a k8s service for the distributor HTTP endpoint
func NewDistributorHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameDistributorHTTP(opts.Name)
l := ComponentLabels(LabelDistributorComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelDistributorComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -181,8 +179,8 @@ func NewDistributorHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -193,7 +191,7 @@ func NewDistributorHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -202,3 +200,48 @@ func configureDistributorServiceMonitorPKI(deployment *appsv1.Deployment, stackN
serviceName := serviceNameDistributorHTTP(stackName)
return configureServiceMonitorPKI(&deployment.Spec.Template.Spec, serviceName)
}
func configureDistributorGRPCServicePKI(deployment *appsv1.Deployment, stackName, stackNS string) error {
caBundleName := signingCABundleName(stackName)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: caBundleName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: caBundleName,
},
},
},
},
},
}
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: caBundleName,
ReadOnly: false,
MountPath: caBundleDir,
},
},
Args: []string{
// Enable GRPC over TLS for ingester client
"-ingester.client.tls-enabled=true",
fmt.Sprintf("-ingester.client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-ingester.client.tls-server-name=%s", fqdn(serviceNameIngesterGRPC(stackName), stackNS)),
},
}
if err := mergo.Merge(&deployment.Spec.Template.Spec, secretVolumeSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge volumes")
}
if err := mergo.Merge(&deployment.Spec.Template.Spec.Containers[0], secretContainerSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}
serviceName := serviceNameDistributorGRPC(stackName)
return configureGRPCServicePKI(&deployment.Spec.Template.Spec, serviceName)
}

@ -211,8 +211,7 @@ func NewGatewayDeployment(opts Options, sha1C string) *appsv1.Deployment {
// NewGatewayHTTPService creates a k8s service for the lokistack-gateway HTTP endpoint
func NewGatewayHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameGatewayHTTP(opts.Name)
l := ComponentLabels(LabelGatewayComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelGatewayComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -221,8 +220,8 @@ func NewGatewayHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -235,7 +234,7 @@ func NewGatewayHTTPService(opts Options) *corev1.Service {
Port: gatewayInternalPort,
},
},
Selector: l,
Selector: labels,
},
}
}
@ -349,9 +348,8 @@ func configureGatewayMetricsPKI(podSpec *corev1.PodSpec, serviceName string) err
}
}
secretName := signingServiceSecretName(serviceName)
certFile := path.Join(gateway.LokiGatewayTLSDir, gateway.LokiGatewayCertFile)
keyFile := path.Join(gateway.LokiGatewayTLSDir, gateway.LokiGatewayKeyFile)
certFile := path.Join(httpTLSDir, tlsCertFile)
keyFile := path.Join(httpTLSDir, tlsKeyFile)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
@ -359,7 +357,7 @@ func configureGatewayMetricsPKI(podSpec *corev1.PodSpec, serviceName string) err
Name: tlsSecretVolume,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
SecretName: serviceName,
},
},
},
@ -370,7 +368,7 @@ func configureGatewayMetricsPKI(podSpec *corev1.PodSpec, serviceName string) err
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
Args: []string{

@ -3,7 +3,6 @@ package manifests
import (
"github.com/ViaQ/logerr/v2/kverrors"
lokiv1beta1 "github.com/grafana/loki/operator/api/v1beta1"
"github.com/grafana/loki/operator/internal/manifests/internal/gateway"
"github.com/grafana/loki/operator/internal/manifests/openshift"
"github.com/imdario/mergo"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
@ -42,8 +41,6 @@ func ApplyGatewayDefaultOptions(opts *Options) error {
serviceNameGatewayHTTP(opts.Name),
gatewayHTTPPortName,
ComponentLabels(LabelGatewayComponent, opts.Name),
opts.Flags.EnableServiceMonitors,
opts.Flags.EnableCertificateSigningService,
tenantData,
)
@ -61,6 +58,7 @@ func configureDeploymentForMode(d *appsv1.Deployment, mode lokiv1beta1.ModeType,
case lokiv1beta1.Static, lokiv1beta1.Dynamic:
return nil // nothing to configure
case lokiv1beta1.OpenshiftLogging:
caBundleName := signingCABundleName(stackName)
serviceName := serviceNameGatewayHTTP(stackName)
secretName := signingServiceSecretName(serviceName)
serverName := fqdn(serviceName, stackNs)
@ -68,11 +66,12 @@ func configureDeploymentForMode(d *appsv1.Deployment, mode lokiv1beta1.ModeType,
d,
gatewayContainerName,
tlsSecretVolume,
gateway.LokiGatewayTLSDir,
gateway.LokiGatewayCertFile,
gateway.LokiGatewayKeyFile,
gateway.LokiGatewayCABundleDir,
gateway.LokiGatewayCAFile,
httpTLSDir,
tlsCertFile,
tlsKeyFile,
caBundleName,
caBundleDir,
caFile,
flags.EnableTLSServiceMonitorConfig,
flags.EnableCertificateSigningService,
secretName,
@ -95,12 +94,24 @@ func configureServiceForMode(s *corev1.ServiceSpec, mode lokiv1beta1.ModeType) e
return nil
}
func configureLokiStackObjsForMode(objs []client.Object, opts Options) []client.Object {
switch opts.Stack.Tenants.Mode {
case lokiv1beta1.Static, lokiv1beta1.Dynamic:
// nothing to configure
case lokiv1beta1.OpenshiftLogging:
openShiftObjs := openshift.BuildLokiStackObjects(opts.OpenShiftOptions)
objs = append(objs, openShiftObjs...)
}
return objs
}
func configureGatewayObjsForMode(objs []client.Object, opts Options) []client.Object {
switch opts.Stack.Tenants.Mode {
case lokiv1beta1.Static, lokiv1beta1.Dynamic:
// nothing to configure
case lokiv1beta1.OpenshiftLogging:
openShiftObjs := openshift.Build(opts.OpenShiftOptions)
openShiftObjs := openshift.BuildGatewayObjects(opts.OpenShiftOptions)
var cObjs []client.Object
for _, o := range objs {

@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/require"
lokiv1beta1 "github.com/grafana/loki/operator/api/v1beta1"
"github.com/grafana/loki/operator/internal/manifests/internal/gateway"
"github.com/grafana/loki/operator/internal/manifests/openshift"
appsv1 "k8s.io/api/apps/v1"
@ -132,19 +131,19 @@ func TestApplyGatewayDefaultsOptions(t *testing.T) {
TenantName: "application",
TenantID: "",
ServiceAccount: "lokistack-ocp-gateway",
RedirectURL: "http://lokistack-ocp-stack-ns.apps.example.com/openshift/application/callback",
RedirectURL: "https://lokistack-ocp-stack-ns.apps.example.com/openshift/application/callback",
},
{
TenantName: "infrastructure",
TenantID: "",
ServiceAccount: "lokistack-ocp-gateway",
RedirectURL: "http://lokistack-ocp-stack-ns.apps.example.com/openshift/infrastructure/callback",
RedirectURL: "https://lokistack-ocp-stack-ns.apps.example.com/openshift/infrastructure/callback",
},
{
TenantName: "audit",
TenantID: "",
ServiceAccount: "lokistack-ocp-gateway",
RedirectURL: "http://lokistack-ocp-stack-ns.apps.example.com/openshift/audit/callback",
RedirectURL: "https://lokistack-ocp-stack-ns.apps.example.com/openshift/audit/callback",
},
},
Authorization: openshift.AuthorizationSpec{
@ -258,8 +257,8 @@ func TestConfigureDeploymentForMode(t *testing.T) {
"--logs.tail.endpoint=http://example.com",
"--logs.write.endpoint=http://example.com",
fmt.Sprintf("--web.healthchecks.url=https://localhost:%d", gatewayHTTPPort),
"--tls.server.cert-file=/var/run/tls/tls.crt",
"--tls.server.key-file=/var/run/tls/tls.key",
"--tls.server.cert-file=/var/run/tls/http/tls.crt",
"--tls.server.key-file=/var/run/tls/http/tls.key",
"--tls.healthchecks.server-ca-file=/var/run/ca/service-ca.crt",
fmt.Sprintf("--tls.healthchecks.server-name=%s", "test-gateway-http.test-ns.svc.cluster.local"),
},
@ -267,7 +266,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
ReadinessProbe: &corev1.Probe{
@ -380,7 +379,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
ReadinessProbe: &corev1.Probe{
@ -428,8 +427,8 @@ func TestConfigureDeploymentForMode(t *testing.T) {
"--logs.tail.endpoint=http://example.com",
"--logs.write.endpoint=http://example.com",
fmt.Sprintf("--web.healthchecks.url=https://localhost:%d", gatewayHTTPPort),
"--tls.server.cert-file=/var/run/tls/tls.crt",
"--tls.server.key-file=/var/run/tls/tls.key",
"--tls.server.cert-file=/var/run/tls/http/tls.crt",
"--tls.server.key-file=/var/run/tls/http/tls.key",
"--tls.healthchecks.server-ca-file=/var/run/ca/service-ca.crt",
fmt.Sprintf("--tls.healthchecks.server-name=%s", "test-gateway-http.test-ns.svc.cluster.local"),
},
@ -437,7 +436,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
ReadinessProbe: &corev1.Probe{
@ -465,8 +464,8 @@ func TestConfigureDeploymentForMode(t *testing.T) {
"--web.listen=:8082",
"--web.internal.listen=:8083",
"--web.healthchecks.url=http://localhost:8082",
"--tls.internal.server.cert-file=/var/run/tls/tls.crt",
"--tls.internal.server.key-file=/var/run/tls/tls.key",
"--tls.internal.server.cert-file=/var/run/tls/http/tls.crt",
"--tls.internal.server.key-file=/var/run/tls/http/tls.key",
`--openshift.mappings=application=loki.grafana.com`,
`--openshift.mappings=infrastructure=loki.grafana.com`,
`--openshift.mappings=audit=loki.grafana.com`,
@ -511,7 +510,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
},
@ -562,7 +561,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: "tls-secret",
ReadOnly: true,
MountPath: "/var/run/tls",
MountPath: "/var/run/tls/http",
},
},
ReadinessProbe: &corev1.Probe{
@ -609,8 +608,8 @@ func TestConfigureDeploymentForMode(t *testing.T) {
"--logs.write.endpoint=https://example.com",
fmt.Sprintf("--web.healthchecks.url=https://localhost:%d", gatewayHTTPPort),
"--logs.tls.ca-file=/var/run/ca/service-ca.crt",
"--tls.server.cert-file=/var/run/tls/tls.crt",
"--tls.server.key-file=/var/run/tls/tls.key",
"--tls.server.cert-file=/var/run/tls/http/tls.crt",
"--tls.server.key-file=/var/run/tls/http/tls.key",
"--tls.healthchecks.server-ca-file=/var/run/ca/service-ca.crt",
fmt.Sprintf("--tls.healthchecks.server-name=%s", "test-gateway-http.test-ns.svc.cluster.local"),
},
@ -618,10 +617,10 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: "tls-secret",
ReadOnly: true,
MountPath: "/var/run/tls",
MountPath: "/var/run/tls/http",
},
{
Name: "gateway-ca-bundle",
Name: "test-ca-bundle",
ReadOnly: true,
MountPath: "/var/run/ca",
},
@ -651,8 +650,8 @@ func TestConfigureDeploymentForMode(t *testing.T) {
"--web.listen=:8082",
"--web.internal.listen=:8083",
"--web.healthchecks.url=http://localhost:8082",
"--tls.internal.server.cert-file=/var/run/tls/tls.crt",
"--tls.internal.server.key-file=/var/run/tls/tls.key",
"--tls.internal.server.cert-file=/var/run/tls/http/tls.crt",
"--tls.internal.server.key-file=/var/run/tls/http/tls.key",
`--openshift.mappings=application=loki.grafana.com`,
`--openshift.mappings=infrastructure=loki.grafana.com`,
`--openshift.mappings=audit=loki.grafana.com`,
@ -697,7 +696,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
{
Name: tlsSecretVolume,
ReadOnly: true,
MountPath: gateway.LokiGatewayTLSDir,
MountPath: httpTLSDir,
},
},
},
@ -707,12 +706,12 @@ func TestConfigureDeploymentForMode(t *testing.T) {
Name: "tls-secret-volume",
},
{
Name: "gateway-ca-bundle",
Name: "test-ca-bundle",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
DefaultMode: &defaultConfigMapMode,
LocalObjectReference: corev1.LocalObjectReference{
Name: "gateway-ca-bundle",
Name: "test-ca-bundle",
},
},
},
@ -728,7 +727,7 @@ func TestConfigureDeploymentForMode(t *testing.T) {
tc := tc
t.Run(tc.desc, func(t *testing.T) {
t.Parallel()
err := configureDeploymentForMode(tc.dpl, tc.mode, tc.flags, "test", "test-ns")
err := configureDeploymentForMode(tc.dpl, tc.mode, tc.flags, tc.stackName, tc.stackNs)
require.NoError(t, err)
require.Equal(t, tc.want, tc.dpl)
})

@ -165,7 +165,7 @@ func TestBuildGateway_HasExtraObjectsForTenantMode(t *testing.T) {
})
require.NoError(t, err)
require.Len(t, objs, 7)
require.Len(t, objs, 9)
}
func TestBuildGateway_WithExtraObjectsForTenantMode_RouteSvcMatches(t *testing.T) {

@ -29,6 +29,12 @@ func BuildIndexGateway(opts Options) ([]client.Object, error) {
return nil, err
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureIndexGatewayGRPCServicePKI(statefulSet, opts.Name); err != nil {
return nil, err
}
}
return []client.Object{
statefulSet,
NewIndexGatewayGRPCService(opts),
@ -157,7 +163,8 @@ func NewIndexGatewayStatefulSet(opts Options) *appsv1.StatefulSet {
// NewIndexGatewayGRPCService creates a k8s service for the index-gateway GRPC endpoint
func NewIndexGatewayGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelIndexGatewayComponent, opts.Name)
serviceName := serviceNameIndexGatewayGRPC(opts.Name)
labels := ComponentLabels(LabelIndexGatewayComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -165,8 +172,9 @@ func NewIndexGatewayGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameIndexGatewayGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -178,7 +186,7 @@ func NewIndexGatewayGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -186,8 +194,7 @@ func NewIndexGatewayGRPCService(opts Options) *corev1.Service {
// NewIndexGatewayHTTPService creates a k8s service for the index-gateway HTTP endpoint
func NewIndexGatewayHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameIndexGatewayHTTP(opts.Name)
l := ComponentLabels(LabelIndexGatewayComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelIndexGatewayComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -196,8 +203,8 @@ func NewIndexGatewayHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -208,7 +215,7 @@ func NewIndexGatewayHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -217,3 +224,8 @@ func configureIndexGatewayServiceMonitorPKI(statefulSet *appsv1.StatefulSet, sta
serviceName := serviceNameIndexGatewayHTTP(stackName)
return configureServiceMonitorPKI(&statefulSet.Spec.Template.Spec, serviceName)
}
func configureIndexGatewayGRPCServicePKI(sts *appsv1.StatefulSet, stackName string) error {
serviceName := serviceNameIndexGatewayGRPC(stackName)
return configureGRPCServicePKI(&sts.Spec.Template.Spec, serviceName)
}

@ -4,8 +4,12 @@ import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
"github.com/grafana/loki/operator/internal/manifests/internal/config"
"github.com/grafana/loki/operator/internal/manifests/storage"
"github.com/imdario/mergo"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
@ -29,6 +33,12 @@ func BuildIngester(opts Options) ([]client.Object, error) {
return nil, err
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureIngesterGRPCServicePKI(statefulSet, opts.Name, opts.Namespace); err != nil {
return nil, err
}
}
return []client.Object{
statefulSet,
NewIngesterGRPCService(opts),
@ -185,7 +195,8 @@ func NewIngesterStatefulSet(opts Options) *appsv1.StatefulSet {
// NewIngesterGRPCService creates a k8s service for the ingester GRPC endpoint
func NewIngesterGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelIngesterComponent, opts.Name)
serviceName := serviceNameIngesterGRPC(opts.Name)
labels := ComponentLabels(LabelIngesterComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -193,8 +204,9 @@ func NewIngesterGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameIngesterGRPC(opts.Name),
Labels: l,
Name: serviceNameIngesterGRPC(opts.Name),
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -206,7 +218,7 @@ func NewIngesterGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -214,8 +226,7 @@ func NewIngesterGRPCService(opts Options) *corev1.Service {
// NewIngesterHTTPService creates a k8s service for the ingester HTTP endpoint
func NewIngesterHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameIngesterHTTP(opts.Name)
l := ComponentLabels(LabelIngesterComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelIngesterComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -224,8 +235,8 @@ func NewIngesterHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -236,7 +247,7 @@ func NewIngesterHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -245,3 +256,52 @@ func configureIngesterServiceMonitorPKI(statefulSet *appsv1.StatefulSet, stackNa
serviceName := serviceNameIngesterHTTP(stackName)
return configureServiceMonitorPKI(&statefulSet.Spec.Template.Spec, serviceName)
}
func configureIngesterGRPCServicePKI(sts *appsv1.StatefulSet, stackName, stackNS string) error {
caBundleName := signingCABundleName(stackName)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: caBundleName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: caBundleName,
},
},
},
},
},
}
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: caBundleName,
ReadOnly: false,
MountPath: caBundleDir,
},
},
Args: []string{
// Enable GRPC over TLS for ingester client
"-ingester.client.tls-enabled=true",
fmt.Sprintf("-ingester.client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-ingester.client.tls-server-name=%s", fqdn(serviceNameIngesterGRPC(stackName), stackNS)),
// Enable GRPC over TLS for boltb-shipper index-gateway client
"-boltdb.shipper.index-gateway-client.tls-enabled=true",
fmt.Sprintf("-boltdb.shipper.index-gateway-client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-boltdb.shipper.index-gateway-client.tls-server-name=%s", fqdn(serviceNameIndexGatewayGRPC(stackName), stackNS)),
},
}
if err := mergo.Merge(&sts.Spec.Template.Spec, secretVolumeSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge volumes")
}
if err := mergo.Merge(&sts.Spec.Template.Spec.Containers[0], secretContainerSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}
serviceName := serviceNameIngesterGRPC(stackName)
return configureGRPCServicePKI(&sts.Spec.Template.Spec, serviceName)
}

@ -20,16 +20,6 @@ const (
LokiGatewayRegoFileName = "lokistack-gateway.rego"
// LokiGatewayMountDir is the path that is mounted from the configmap
LokiGatewayMountDir = "/etc/lokistack-gateway"
// LokiGatewayTLSDir is the path that is mounted from the configmap for TLS
LokiGatewayTLSDir = "/var/run/tls"
// LokiGatewayCABundleDir is the path that is mounted from the configmap for TLS
LokiGatewayCABundleDir = "/var/run/ca"
// LokiGatewayCAFile is the file name of the certificate authority file
LokiGatewayCAFile = "service-ca.crt"
// LokiGatewayCertFile is the file of the X509 server certificate file
LokiGatewayCertFile = "tls.crt"
// LokiGatewayKeyFile is the file name of the server private key
LokiGatewayKeyFile = "tls.key"
)
var (

@ -2,27 +2,23 @@ package openshift
import "sigs.k8s.io/controller-runtime/pkg/client"
// Build returns a list of auxiliary openshift/k8s objects
// BuildGatewayObjects returns a list of auxiliary openshift/k8s objects
// for lokistack gateway deployments on OpenShift.
func Build(opts Options) []client.Object {
objs := []client.Object{
func BuildGatewayObjects(opts Options) []client.Object {
return []client.Object{
BuildRoute(opts),
BuildServiceAccount(opts),
BuildClusterRole(opts),
BuildClusterRoleBinding(opts),
BuildMonitoringRole(opts),
BuildMonitoringRoleBinding(opts),
}
}
if opts.BuildOpts.EnableServiceMonitors {
objs = append(
objs,
BuildMonitoringRole(opts),
BuildMonitoringRoleBinding(opts),
)
}
if opts.BuildOpts.EnableCertificateSigningService {
objs = append(objs, BuildServiceCAConfigMap(opts))
// BuildLokiStackObjects returns a list of auxiliary openshift/k8s objects
// for lokistack deployments on OpenShift.
func BuildLokiStackObjects(opts Options) []client.Object {
return []client.Object{
BuildServiceCAConfigMap(opts),
}
return objs
}

@ -12,9 +12,9 @@ import (
)
func TestBuild_ServiceAccountRefMatches(t *testing.T) {
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, false, false, map[string]TenantData{})
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, map[string]TenantData{})
objs := Build(opts)
objs := BuildGatewayObjects(opts)
sa := objs[1].(*corev1.ServiceAccount)
rb := objs[3].(*rbacv1.ClusterRoleBinding)
@ -24,9 +24,9 @@ func TestBuild_ServiceAccountRefMatches(t *testing.T) {
}
func TestBuild_ClusterRoleRefMatches(t *testing.T) {
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, false, false, map[string]TenantData{})
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, map[string]TenantData{})
objs := Build(opts)
objs := BuildGatewayObjects(opts)
cr := objs[2].(*rbacv1.ClusterRole)
rb := objs[3].(*rbacv1.ClusterRoleBinding)
@ -35,9 +35,9 @@ func TestBuild_ClusterRoleRefMatches(t *testing.T) {
}
func TestBuild_MonitoringClusterRoleRefMatches(t *testing.T) {
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, true, false, map[string]TenantData{})
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, map[string]TenantData{})
objs := Build(opts)
objs := BuildGatewayObjects(opts)
cr := objs[4].(*rbacv1.Role)
rb := objs[5].(*rbacv1.RoleBinding)
@ -46,9 +46,9 @@ func TestBuild_MonitoringClusterRoleRefMatches(t *testing.T) {
}
func TestBuild_ServiceAccountAnnotationsRouteRefMatches(t *testing.T) {
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, false, false, map[string]TenantData{})
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, map[string]TenantData{})
objs := Build(opts)
objs := BuildGatewayObjects(opts)
rt := objs[0].(*routev1.Route)
sa := objs[1].(*corev1.ServiceAccount)

@ -42,7 +42,7 @@ func ConfigureGatewayDeployment(
d *appsv1.Deployment,
gwContainerName string,
secretVolumeName, tlsDir, certFile, keyFile string,
caDir, caFile string,
caBundleVolumeName, caDir, caFile string,
withTLS, withCertSigningService bool,
secretName, serverName string,
gatewayHTTPPort int,
@ -68,12 +68,6 @@ func ConfigureGatewayDeployment(
gwArgs = append(gwArgs, fmt.Sprintf("--logs.tls.ca-file=%s/%s", caDir, caFile))
caBundleVolumeName := serviceCABundleName(Options{
BuildOpts: BuildOptions{
GatewayName: d.GetName(),
},
})
gwContainer.VolumeMounts = append(gwContainer.VolumeMounts, corev1.VolumeMount{
Name: caBundleVolumeName,
ReadOnly: true,

@ -34,14 +34,12 @@ type AuthorizationSpec struct {
// extra lokistack gateway k8s objects (e.g. ServiceAccount, Route, RBAC)
// on openshift.
type BuildOptions struct {
LokiStackName string
LokiStackNamespace string
GatewayName string
GatewaySvcName string
GatewaySvcTargetPort string
Labels map[string]string
EnableServiceMonitors bool
EnableCertificateSigningService bool
LokiStackName string
LokiStackNamespace string
GatewayName string
GatewaySvcName string
GatewaySvcTargetPort string
Labels map[string]string
}
// TenantData defines the existing cookieSecret for lokistack reconcile.
@ -54,8 +52,6 @@ func NewOptions(
stackName, stackNamespace string,
gwName, gwBaseDomain, gwSvcName, gwPortName string,
gwLabels map[string]string,
enableServiceMonitors bool,
enableCertSigningService bool,
tenantConfigMap map[string]TenantData,
) Options {
host := ingressHost(stackName, stackNamespace, gwBaseDomain)
@ -71,21 +67,19 @@ func NewOptions(
TenantName: name,
TenantID: name,
ServiceAccount: gwName,
RedirectURL: fmt.Sprintf("http://%s/openshift/%s/callback", host, name),
RedirectURL: fmt.Sprintf("https://%s/openshift/%s/callback", host, name),
CookieSecret: cookieSecret,
})
}
return Options{
BuildOpts: BuildOptions{
LokiStackName: stackName,
LokiStackNamespace: stackNamespace,
GatewayName: gwName,
GatewaySvcName: gwSvcName,
GatewaySvcTargetPort: gwPortName,
Labels: gwLabels,
EnableServiceMonitors: enableServiceMonitors,
EnableCertificateSigningService: enableCertSigningService,
LokiStackName: stackName,
LokiStackNamespace: stackNamespace,
GatewayName: gwName,
GatewaySvcName: gwSvcName,
GatewaySvcTargetPort: gwPortName,
Labels: gwLabels,
},
Authentication: authn,
Authorization: AuthorizationSpec{

@ -6,8 +6,8 @@ import (
)
// BuildServiceCAConfigMap returns a k8s configmap for the LokiStack
// gateway serviceCA configmap. This configmap is used to configure
// the gateway to proxy server-side TLS encrypted requests to Loki.
// serviceCA configmap. This configmap is used to configure
// the gateway and components to verify TLS certificates.
func BuildServiceCAConfigMap(opts Options) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{

@ -8,7 +8,7 @@ import (
)
func TestBuildServiceAccount_AnnotationsMatchDefaultTenants(t *testing.T) {
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, false, false, map[string]TenantData{})
opts := NewOptions("abc", "ns", "abc", "example.com", "abc", "abc", map[string]string{}, map[string]TenantData{})
sa := BuildServiceAccount(opts)
require.Len(t, sa.GetAnnotations(), len(defaultTenants))

@ -54,7 +54,7 @@ func serviceAccountName(opts Options) string {
}
func serviceCABundleName(opts Options) string {
return fmt.Sprintf("%s-ca-bundle", opts.BuildOpts.GatewayName)
return fmt.Sprintf("%s-ca-bundle", opts.BuildOpts.LokiStackName)
}
func serviceAccountAnnotations(opts Options) map[string]string {

@ -38,6 +38,7 @@ type FeatureFlags struct {
EnableCertificateSigningService bool
EnableServiceMonitors bool
EnableTLSServiceMonitorConfig bool
EnableTLSGRPCServices bool
EnablePrometheusAlerts bool
EnableGateway bool
EnableGatewayRoute bool

@ -4,8 +4,11 @@ import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
"github.com/grafana/loki/operator/internal/manifests/internal/config"
"github.com/grafana/loki/operator/internal/manifests/storage"
"github.com/imdario/mergo"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -28,6 +31,12 @@ func BuildQuerier(opts Options) ([]client.Object, error) {
return nil, err
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureQuerierGRPCServicePKI(deployment, opts.Name, opts.Namespace); err != nil {
return nil, err
}
}
return []client.Object{
deployment,
NewQuerierGRPCService(opts),
@ -136,7 +145,8 @@ func NewQuerierDeployment(opts Options) *appsv1.Deployment {
// NewQuerierGRPCService creates a k8s service for the querier GRPC endpoint
func NewQuerierGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelQuerierComponent, opts.Name)
serviceName := serviceNameQuerierGRPC(opts.Name)
labels := ComponentLabels(LabelQuerierComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -144,8 +154,9 @@ func NewQuerierGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameQuerierGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -157,7 +168,7 @@ func NewQuerierGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -165,8 +176,7 @@ func NewQuerierGRPCService(opts Options) *corev1.Service {
// NewQuerierHTTPService creates a k8s service for the querier HTTP endpoint
func NewQuerierHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameQuerierHTTP(opts.Name)
l := ComponentLabels(LabelQuerierComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelQuerierComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -175,8 +185,8 @@ func NewQuerierHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -187,7 +197,7 @@ func NewQuerierHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -196,3 +206,56 @@ func configureQuerierServiceMonitorPKI(deployment *appsv1.Deployment, stackName
serviceName := serviceNameQuerierHTTP(stackName)
return configureServiceMonitorPKI(&deployment.Spec.Template.Spec, serviceName)
}
func configureQuerierGRPCServicePKI(deployment *appsv1.Deployment, stackName, stackNS string) error {
caBundleName := signingCABundleName(stackName)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: caBundleName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: caBundleName,
},
},
},
},
},
}
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: caBundleName,
ReadOnly: false,
MountPath: caBundleDir,
},
},
Args: []string{
// Enable GRPC over TLS for ingester client
"-ingester.client.tls-enabled=true",
fmt.Sprintf("-ingester.client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-ingester.client.tls-server-name=%s", fqdn(serviceNameIngesterGRPC(stackName), stackNS)),
// Enable GRPC over TLS for query frontend client
"-querier.frontend-client.tls-enabled=true",
fmt.Sprintf("-querier.frontend-client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-querier.frontend-client.tls-server-name=%s", fqdn(serviceNameQueryFrontendGRPC(stackName), stackNS)),
// Enable GRPC over TLS for boltb-shipper index-gateway client
"-boltdb.shipper.index-gateway-client.tls-enabled=true",
fmt.Sprintf("-boltdb.shipper.index-gateway-client.tls-ca-path=%s", signingCAPath()),
fmt.Sprintf("-boltdb.shipper.index-gateway-client.tls-server-name=%s", fqdn(serviceNameIndexGatewayGRPC(stackName), stackNS)),
},
}
if err := mergo.Merge(&deployment.Spec.Template.Spec, secretVolumeSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge volumes")
}
if err := mergo.Merge(&deployment.Spec.Template.Spec.Containers[0], secretContainerSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}
serviceName := serviceNameQuerierGRPC(stackName)
return configureGRPCServicePKI(&deployment.Spec.Template.Spec, serviceName)
}

@ -23,6 +23,12 @@ func BuildQueryFrontend(opts Options) ([]client.Object, error) {
}
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureQueryFrontendGRPCServicePKI(deployment, opts.Name); err != nil {
return nil, err
}
}
return []client.Object{
deployment,
NewQueryFrontendGRPCService(opts),
@ -45,12 +51,6 @@ func NewQueryFrontendDeployment(opts Options) *appsv1.Deployment {
},
},
},
{
Name: storageVolumeName,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
},
Containers: []corev1.Container{
{
@ -102,11 +102,6 @@ func NewQueryFrontendDeployment(opts Options) *appsv1.Deployment {
ReadOnly: false,
MountPath: config.LokiConfigMountDir,
},
{
Name: storageVolumeName,
ReadOnly: false,
MountPath: dataDirectory,
},
},
TerminationMessagePath: "/dev/termination-log",
TerminationMessagePolicy: "File",
@ -154,7 +149,8 @@ func NewQueryFrontendDeployment(opts Options) *appsv1.Deployment {
// NewQueryFrontendGRPCService creates a k8s service for the query-frontend GRPC endpoint
func NewQueryFrontendGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelQueryFrontendComponent, opts.Name)
serviceName := serviceNameQueryFrontendGRPC(opts.Name)
labels := ComponentLabels(LabelQueryFrontendComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -162,8 +158,9 @@ func NewQueryFrontendGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameQueryFrontendGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -175,7 +172,7 @@ func NewQueryFrontendGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -183,8 +180,7 @@ func NewQueryFrontendGRPCService(opts Options) *corev1.Service {
// NewQueryFrontendHTTPService creates a k8s service for the query-frontend HTTP endpoint
func NewQueryFrontendHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameQueryFrontendHTTP(opts.Name)
l := ComponentLabels(LabelQueryFrontendComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelQueryFrontendComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -193,8 +189,8 @@ func NewQueryFrontendHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -205,7 +201,7 @@ func NewQueryFrontendHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -214,3 +210,8 @@ func configureQueryFrontendServiceMonitorPKI(deployment *appsv1.Deployment, stac
serviceName := serviceNameQueryFrontendHTTP(stackName)
return configureServiceMonitorPKI(&deployment.Spec.Template.Spec, serviceName)
}
func configureQueryFrontendGRPCServicePKI(deployment *appsv1.Deployment, stackName string) error {
serviceName := serviceNameQueryFrontendGRPC(stackName)
return configureGRPCServicePKI(&deployment.Spec.Template.Spec, serviceName)
}

@ -4,7 +4,9 @@ import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
"github.com/grafana/loki/operator/internal/manifests/internal/config"
"github.com/imdario/mergo"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
@ -24,6 +26,12 @@ func BuildRuler(opts Options) ([]client.Object, error) {
}
}
if opts.Flags.EnableTLSGRPCServices {
if err := configureRulerGRPCServicePKI(statefulSet, opts.Name); err != nil {
return nil, err
}
}
return []client.Object{
statefulSet,
NewRulerGRPCService(opts),
@ -201,7 +209,8 @@ func NewRulerStatefulSet(opts Options) *appsv1.StatefulSet {
// NewRulerGRPCService creates a k8s service for the ruler GRPC endpoint
func NewRulerGRPCService(opts Options) *corev1.Service {
l := ComponentLabels(LabelRulerComponent, opts.Name)
serviceName := serviceNameRulerGRPC(opts.Name)
labels := ComponentLabels(LabelRulerComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -209,8 +218,9 @@ func NewRulerGRPCService(opts Options) *corev1.Service {
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceNameRulerGRPC(opts.Name),
Labels: l,
Name: serviceName,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
@ -222,7 +232,7 @@ func NewRulerGRPCService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: grpcPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -230,8 +240,7 @@ func NewRulerGRPCService(opts Options) *corev1.Service {
// NewRulerHTTPService creates a k8s service for the ruler HTTP endpoint
func NewRulerHTTPService(opts Options) *corev1.Service {
serviceName := serviceNameRulerHTTP(opts.Name)
l := ComponentLabels(LabelRulerComponent, opts.Name)
a := serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService)
labels := ComponentLabels(LabelRulerComponent, opts.Name)
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
@ -240,8 +249,8 @@ func NewRulerHTTPService(opts Options) *corev1.Service {
},
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
Labels: l,
Annotations: a,
Labels: labels,
Annotations: serviceAnnotations(serviceName, opts.Flags.EnableCertificateSigningService),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -252,7 +261,7 @@ func NewRulerHTTPService(opts Options) *corev1.Service {
TargetPort: intstr.IntOrString{IntVal: httpPort},
},
},
Selector: l,
Selector: labels,
},
}
}
@ -262,6 +271,50 @@ func configureRulerServiceMonitorPKI(statefulSet *appsv1.StatefulSet, stackName
return configureServiceMonitorPKI(&statefulSet.Spec.Template.Spec, serviceName)
}
func configureRulerGRPCServicePKI(sts *appsv1.StatefulSet, stackName string) error {
caBundleName := signingCABundleName(stackName)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: caBundleName,
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: caBundleName,
},
},
},
},
},
}
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: caBundleName,
ReadOnly: false,
MountPath: caBundleDir,
},
},
Args: []string{
// Enable GRPC over TLS for ruler client
"-ruler.client.tls-enabled=true",
fmt.Sprintf("-ruler.client.tls-ca-path=%s", signingCAPath()),
},
}
if err := mergo.Merge(&sts.Spec.Template.Spec, secretVolumeSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge volumes")
}
if err := mergo.Merge(&sts.Spec.Template.Spec.Containers[0], secretContainerSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}
serviceName := serviceNameRulerGRPC(stackName)
return configureGRPCServicePKI(&sts.Spec.Template.Spec, serviceName)
}
func ruleVolumeItems(tenants map[string]TenantConfig) []corev1.KeyToPath {
var items []corev1.KeyToPath

@ -0,0 +1,48 @@
package manifests
import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
"github.com/imdario/mergo"
corev1 "k8s.io/api/core/v1"
)
func configureGRPCServicePKI(podSpec *corev1.PodSpec, serviceName string) error {
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: serviceName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: serviceName,
},
},
},
},
}
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: serviceName,
ReadOnly: false,
MountPath: grpcTLSDir,
},
},
Args: []string{
fmt.Sprintf("-server.grpc-tls-cert-path=%s", path.Join(grpcTLSDir, tlsCertFile)),
fmt.Sprintf("-server.grpc-tls-key-path=%s", path.Join(grpcTLSDir, tlsKeyFile)),
},
}
if err := mergo.Merge(podSpec, secretVolumeSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge volumes")
}
if err := mergo.Merge(&podSpec.Containers[0], secretContainerSpec, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}
return nil
}

@ -1,6 +1,9 @@
package manifests
import (
"fmt"
"path"
"github.com/ViaQ/logerr/v2/kverrors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -146,14 +149,13 @@ func newServiceMonitor(namespace, serviceMonitorName string, labels labels.Set,
}
func configureServiceMonitorPKI(podSpec *corev1.PodSpec, serviceName string) error {
secretName := signingServiceSecretName(serviceName)
secretVolumeSpec := corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: secretName,
Name: serviceName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
SecretName: serviceName,
},
},
},
@ -162,14 +164,14 @@ func configureServiceMonitorPKI(podSpec *corev1.PodSpec, serviceName string) err
secretContainerSpec := corev1.Container{
VolumeMounts: []corev1.VolumeMount{
{
Name: secretName,
Name: serviceName,
ReadOnly: false,
MountPath: secretDirectory,
MountPath: httpTLSDir,
},
},
Args: []string{
"-server.http-tls-cert-path=/etc/proxy/secrets/tls.crt",
"-server.http-tls-key-path=/etc/proxy/secrets/tls.key",
fmt.Sprintf("-server.http-tls-cert-path=%s", path.Join(httpTLSDir, tlsCertFile)),
fmt.Sprintf("-server.http-tls-key-path=%s", path.Join(httpTLSDir, tlsKeyFile)),
},
}
uriSchemeContainerSpec := corev1.Container{

@ -193,7 +193,7 @@ func TestValidate_RetroactivelyAddSchema(t *testing.T) {
EffectiveDate: "2021-05-01",
},
}
applied := schemaMap {
applied := schemaMap{
"2020-10-01": lokiv1beta1.ObjectStorageSchemaV11,
"2021-10-01": lokiv1beta1.ObjectStorageSchemaV12,
}
@ -213,7 +213,7 @@ func TestValidate_RetroactivelyAddSchema_ConflictingVersion(t *testing.T) {
EffectiveDate: "2021-10-01",
},
}
applied := schemaMap {
applied := schemaMap{
"2020-10-01": lokiv1beta1.ObjectStorageSchemaV11,
"2021-10-01": lokiv1beta1.ObjectStorageSchemaV12,
}
@ -229,7 +229,7 @@ func TestValidate_RetroactivelyRemoveSchema(t *testing.T) {
EffectiveDate: "2020-10-01",
},
}
applied := schemaMap {
applied := schemaMap{
"2020-10-01": lokiv1beta1.ObjectStorageSchemaV11,
"2021-10-01": lokiv1beta1.ObjectStorageSchemaV12,
}

@ -2,6 +2,7 @@ package manifests
import (
"fmt"
"path"
"github.com/grafana/loki/operator/internal/manifests/openshift"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
@ -31,12 +32,11 @@ const (
walVolumeName = "wal"
configVolumeName = "config"
storageVolumeName = "storage"
rulesStorageVolumeName = "rules"
storageVolumeName = "storage"
walDirectory = "/tmp/wal"
dataDirectory = "/tmp/loki"
secretDirectory = "/etc/proxy/secrets"
rulesStorageDirectory = "/tmp/rules"
// EnvRelatedImageLoki is the environment variable to fetch the Loki image pullspec.
@ -74,6 +74,19 @@ const (
LabelRulerComponent string = "ruler"
// LabelGatewayComponent is the label value for the lokiStack-gateway component
LabelGatewayComponent string = "lokistack-gateway"
// httpTLSDir is the path that is mounted from the secret for TLS
httpTLSDir = "/var/run/tls/http"
// grpcTLSDir is the path that is mounted from the secret for TLS
grpcTLSDir = "/var/run/tls/grpc"
// tlsCertFile is the file of the X509 server certificate file
tlsCertFile = "tls.crt"
// tlsKeyFile is the file name of the server private key
tlsKeyFile = "tls.key"
// LokiStackCABundleDir is the path that is mounted from the configmap for TLS
caBundleDir = "/var/run/ca"
// caFile is the file name of the certificate authority file
caFile = "service-ca.crt"
)
var (
@ -99,7 +112,7 @@ func commonLabels(stackName string) map[string]string {
func serviceAnnotations(serviceName string, enableSigningService bool) map[string]string {
annotations := map[string]string{}
if enableSigningService {
annotations[openshift.ServingCertKey] = signingServiceSecretName(serviceName)
annotations[openshift.ServingCertKey] = serviceName
}
return annotations
}
@ -240,6 +253,14 @@ func signingServiceSecretName(serviceName string) string {
return fmt.Sprintf("%s-tls", serviceName)
}
func signingCABundleName(stackName string) string {
return fmt.Sprintf("%s-ca-bundle", stackName)
}
func signingCAPath() string {
return path.Join(caBundleDir, caFile)
}
func fqdn(serviceName, namespace string) string {
return fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, namespace)
}

@ -47,6 +47,7 @@ func main() {
enableCertSigning bool
enableServiceMonitors bool
enableTLSServiceMonitors bool
enableTLSGRPCServices bool
enableGateway bool
enableGatewayRoute bool
enablePrometheusAlerts bool
@ -66,6 +67,8 @@ func main() {
flag.BoolVar(&enableServiceMonitors, "with-service-monitors", false, "Enables service monitoring")
flag.BoolVar(&enableTLSServiceMonitors, "with-tls-service-monitors", false,
"Enables loading of a prometheus service monitor.")
flag.BoolVar(&enableTLSGRPCServices, "with-tls-grpc-services", false,
"Enables TLS for Loki GRPC services.")
flag.BoolVar(&enableGateway, "with-lokistack-gateway", false,
"Enables the manifest creation for the entire lokistack-gateway.")
flag.BoolVar(&enableGatewayRoute, "with-lokistack-gateway-route", false,
@ -118,6 +121,7 @@ func main() {
EnableCertificateSigningService: enableCertSigning,
EnableServiceMonitors: enableServiceMonitors,
EnableTLSServiceMonitorConfig: enableTLSServiceMonitors,
EnableTLSGRPCServices: enableTLSGRPCServices,
EnablePrometheusAlerts: enablePrometheusAlerts,
EnableGateway: enableGateway,
EnableGatewayRoute: enableGatewayRoute,

Loading…
Cancel
Save