Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update druid api for TLS and remaining ops-requests #1314

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 63 additions & 24 deletions apis/kubedb/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -966,15 +966,16 @@ const (
DruidConfigDirRouters = "/opt/druid/conf/druid/cluster/query/router"
DruidCConfigDirMySQLMetadata = "/opt/druid/extensions/mysql-metadata-storage"

DruidVolumeOperatorConfig = "operator-config-volume"
DruidVolumeMainConfig = "main-config-volume"
DruidVolumeCustomConfig = "custom-config"
DruidMetadataTLSVolume = "metadata-tls-volume"
DruidVolumeOperatorConfig = "operator-config-volume"
DruidVolumeMainConfig = "main-config-volume"
DruidVolumeCustomConfig = "custom-config"
DruidMetadataTLSVolume = "metadata-tls-volume"
DruidMetadataTLSTempVolume = "metadata-tls-volume-temp"

DruidOperatorConfigDir = "/tmp/config/operator-config"
DruidMainConfigDir = "/opt/druid/conf"
DruidCustomConfigDir = "/tmp/config/custom-config"
DruidMetadataTLSConfigDir = "/tmp/metadata-tls"
DruidOperatorConfigDir = "/tmp/config/operator-config"
DruidMainConfigDir = "/opt/druid/conf"
DruidCustomConfigDir = "/tmp/config/custom-config"
DruidMetadataTLSTempConfigDir = "/tmp/metadata-tls"

DruidVolumeCommonConfig = "common-config-volume"
DruidCommonConfigFile = "common.runtime.properties"
Expand All @@ -1000,14 +1001,23 @@ const (
EnvDruidCoordinatorAsOverlord = "DRUID_COORDINATOR_AS_OVERLORD"
EnvDruidMetadataTLSEnable = "DRUID_METADATA_TLS_ENABLE"
EnvDruidMetadataStorageType = "DRUID_METADATA_STORAGE_TYPE"
EnvDruidKeyStorePassword = "DRUID_KEY_STORE_PASSWORD"

DruidPortCoordinators = 8081
DruidPortOverlords = 8090
DruidPortHistoricals = 8083
DruidPortMiddleManagers = 8091
DruidPortBrokers = 8082
DruidPortRouters = 8888
DruidExporterPort = 9104
DruidPlainTextPortCoordinators = 8081
DruidPlainTextPortOverlords = 8090
DruidPlainTextPortHistoricals = 8083
DruidPlainTextPortMiddleManagers = 8091
DruidPlainTextPortBrokers = 8082
DruidPlainTextPortRouters = 8888

DruidTLSPortCoordinators = 8281
DruidTLSPortOverlords = 8290
DruidTLSPortHistoricals = 8283
DruidTLSPortMiddleManagers = 8291
DruidTLSPortBrokers = 8282
DruidTLSPortRouters = 9088

DruidExporterPort = 9104

DruidMetadataStorageTypePostgres = "Postgres"

Expand All @@ -1030,24 +1040,49 @@ const (
DruidMetadataStorageConnectorPasswordEnvConfig = "{\"type\": \"environment\", \"variable\": \"DRUID_METADATA_STORAGE_PASSWORD\"}"
DruidMetadataStorageCreateTables = "druid.metadata.storage.connector.createTables"

// Druid TLS
DruidKeystorePasswordKey = "keystore_password"
DruidTrustStorePasswordKey = "truststore_password"
DruidKeystoreSecretKey = "keystore-cred"

DruidEnablePlaintextPort = "druid.enablePlaintextPort"
DruidEnableTLSPort = "druid.enableTlsPort"
DruidKeyStorePath = "druid.server.https.keyStorePath"
DruidKeyStoreType = "druid.server.https.keyStoreType"
DruidCertAlias = "druid.server.https.certAlias"
DruidKeyStorePassword = "druid.server.https.keyStorePassword"
DruidRequireClientCertificate = "druid.server.https.requireClientCertificate"
DruidTrustStoreType = "druid.server.https.trustStoreType"

DruidTrustStorePassword = "druid.client.https.trustStorePassword"
DruidTrustStorePath = "druid.client.https.trustStorePath"
DruidClientTrustStoreType = "druid.client.https.trustStoreType"
DruidClientValidateHostNames = "druid.client.https.validateHostnames"

DruidKeyStoreTypeJKS = "jks"
DruidKeyStorePasswordEnvConfig = "{\"type\": \"environment\", \"variable\": \"DRUID_KEY_STORE_PASSWORD\"}"

DruidValueTrue = "true"
DruidValueFalse = "false"

DruidCertDir = "/opt/druid/ssl"
DruidCertMetadataSubDir = "metadata"

// MySQL TLS
DruidMetadataMySQLUseSSL = "druid.metadata.mysql.ssl.useSSL"
DruidMetadataMySQLClientCertKeyStoreURL = "druid.metadata.mysql.ssl.clientCertificateKeyStoreUrl"
DruidMetadataMySQLClientCertKeyStorePath = "/opt/druid/conf/tls/metadatakeystore.jks"
DruidMetadataMySQLClientCertKeyStoreType = "druid.metadata.mysql.ssl.clientCertificateKeyStoreType"
DruidMetadataMySQLClientCertKeyStoreTypeJKS = "JKS"
DruidMetadataMySQLClientCertKeyStorePassword = "druid.metadata.mysql.ssl.clientCertificateKeyStorePassword"
DruidMetadataMySQLClientCertKeyStorePasswordValue = "password"

// Postgres TLS
DruidMetadataPostgresUseSSL = "druid.metadata.postgres.ssl.useSSL"
DruidMetadataPGUseSSLMode = "druid.metadata.postgres.ssl.sslMode"
DruidMetadataPGSSLCert = "druid.metadata.postgres.ssl.sslCert"
DruidMetadataPGSSLCertPath = "/opt/druid/conf/tls/tls.crt"
DruidMetadataPGSSLKey = "druid.metadata.postgres.ssl.sslKey"
DruidMetadataPGSSLKeyPath = "/opt/druid/conf/tls/tls.key"
DruidMetadataPGSSLRootCert = "druid.metadata.postgres.ssl.sslRootCert"
DruidMetadataPGSSLRootCertPath = "/opt/druid/conf/tls/ca.cert"
DruidMetadataPostgresUseSSL = "druid.metadata.postgres.ssl.useSSL"
DruidMetadataPGUseSSLMode = "druid.metadata.postgres.ssl.sslMode"
DruidMetadataPGUseSSLModeVerifyFull = "verify-full"
DruidMetadataPGSSLCert = "druid.metadata.postgres.ssl.sslCert"
DruidMetadataPGSSLKey = "druid.metadata.postgres.ssl.sslKey"
DruidMetadataPGSSLRootCert = "druid.metadata.postgres.ssl.sslRootCert"

// Deep Storage
DruidDeepStorageTypeKey = "druid.storage.type"
Expand Down Expand Up @@ -1102,6 +1137,7 @@ const (
DruidExtensionBasicSecurity = "druid-basic-security"
DruidExtensionMultiStageQuery = "druid-multi-stage-query"
DruidExtensionPrometheusEmitter = "prometheus-emitter"
DruidExtensionSSLContext = "simple-client-sslcontext"
DruidService = "druid.service"

// Monitoring Configurations
Expand All @@ -1122,6 +1158,9 @@ const (
DruidMonitoringTaskCountStatsMonitor = "org.apache.druid.server.metrics.TaskCountStatsMonitor"
DruidMonitoringSysMonitor = "org.apache.druid.java.util.metrics.SysMonitor"

DruidDimensionMapDir = "/opt/druid/conf/metrics.json"
DruidEmitterPrometheusStrategyValue = "exporter"

/// Coordinators Configurations
DruidCoordinatorStartDelay = "druid.coordinator.startDelay"
DruidCoordinatorPeriod = "druid.coordinator.period"
Expand Down
141 changes: 110 additions & 31 deletions apis/kubedb/v1alpha2/druid_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package v1alpha2
import (
"context"
"fmt"
"path/filepath"
"strconv"
"strings"

Expand Down Expand Up @@ -125,14 +126,18 @@ func (d *Druid) ServiceLabels(alias ServiceAlias, extraLabels ...map[string]stri
return d.offShootLabels(meta_util.OverwriteKeys(d.OffShootSelectors(), extraLabels...), svcTemplate.Labels)
}

func (r *Druid) Finalizer() string {
return fmt.Sprintf("%s/%s", apis.Finalizer, r.ResourceSingular())
func (d *Druid) Finalizer() string {
return fmt.Sprintf("%s/%s", apis.Finalizer, d.ResourceSingular())
}

func (d *Druid) DefaultUserCredSecretName(username string) string {
return meta_util.NameWithSuffix(d.Name, strings.ReplaceAll(fmt.Sprintf("%s-cred", username), "_", "-"))
}

func (d *Druid) DruidSecretName(suffix string) string {
return strings.Join([]string{d.Name, suffix}, "-")
}

type DruidStatsService struct {
*Druid
}
Expand Down Expand Up @@ -204,21 +209,23 @@ func (d *Druid) PodControllerLabels(nodeType DruidNodeRoleType, extraLabels ...m
}

func (d *Druid) GetNodeSpec(nodeType DruidNodeRoleType) (*DruidNode, *DruidDataNode) {
if nodeType == DruidNodeRoleCoordinators {
switch nodeType {
case DruidNodeRoleCoordinators:
return d.Spec.Topology.Coordinators, nil
} else if nodeType == DruidNodeRoleOverlords {
case DruidNodeRoleOverlords:
return d.Spec.Topology.Overlords, nil
} else if nodeType == DruidNodeRoleMiddleManagers {
case DruidNodeRoleMiddleManagers:
return nil, d.Spec.Topology.MiddleManagers
} else if nodeType == DruidNodeRoleHistoricals {
case DruidNodeRoleHistoricals:
return nil, d.Spec.Topology.Historicals
} else if nodeType == DruidNodeRoleBrokers {
case DruidNodeRoleBrokers:
return d.Spec.Topology.Brokers, nil
} else if nodeType == DruidNodeRoleRouters {
case DruidNodeRoleRouters:
return d.Spec.Topology.Routers, nil
default:
klog.Errorf("unknown druid node role %s\n", nodeType)
return nil, nil
}

panic("Node role name does not match any known types")
}

func (d *Druid) ServiceAccountName() string {
Expand All @@ -235,19 +242,42 @@ func (d *Druid) DruidNodeRoleStringSingular(nodeRole DruidNodeRoleType) string {
}

func (d *Druid) DruidNodeContainerPort(nodeRole DruidNodeRoleType) int32 {
if nodeRole == DruidNodeRoleCoordinators {
return kubedb.DruidPortCoordinators
} else if nodeRole == DruidNodeRoleOverlords {
return kubedb.DruidPortOverlords
} else if nodeRole == DruidNodeRoleMiddleManagers {
return kubedb.DruidPortMiddleManagers
} else if nodeRole == DruidNodeRoleHistoricals {
return kubedb.DruidPortHistoricals
} else if nodeRole == DruidNodeRoleBrokers {
return kubedb.DruidPortBrokers
if !d.Spec.EnableSSL {
switch nodeRole {
case DruidNodeRoleCoordinators:
return kubedb.DruidPlainTextPortCoordinators
case DruidNodeRoleOverlords:
return kubedb.DruidPlainTextPortOverlords
case DruidNodeRoleMiddleManagers:
return kubedb.DruidPlainTextPortMiddleManagers
case DruidNodeRoleHistoricals:
return kubedb.DruidPlainTextPortHistoricals
case DruidNodeRoleBrokers:
return kubedb.DruidPlainTextPortBrokers
case DruidNodeRoleRouters:
return kubedb.DruidPlainTextPortRouters
default:
klog.Errorf("unknown druid node role %s\n", nodeRole)
}
} else {
switch nodeRole {
case DruidNodeRoleCoordinators:
return kubedb.DruidTLSPortCoordinators
case DruidNodeRoleOverlords:
return kubedb.DruidTLSPortOverlords
case DruidNodeRoleMiddleManagers:
return kubedb.DruidTLSPortMiddleManagers
case DruidNodeRoleHistoricals:
return kubedb.DruidTLSPortHistoricals
case DruidNodeRoleBrokers:
return kubedb.DruidTLSPortBrokers
case DruidNodeRoleRouters:
return kubedb.DruidTLSPortRouters
default:
klog.Errorf("unknown node role %s\n", nodeRole)
}
}
// Routers
return kubedb.DruidPortRouters
return -1
}

func (d *Druid) SetHealthCheckerDefaults() {
Expand Down Expand Up @@ -320,7 +350,8 @@ func (d *Druid) GetMetadataStorageType(metadataStorage string) DruidMetadataStor
metadataStorage == kubedb.DruidMetadataStorageTypePostgres || metadataStorage == strings.ToLower(string(kubedb.DruidMetadataStorageTypePostgres)) {
return DruidMetadataStoragePostgreSQL
} else {
panic(fmt.Sprintf("Unknown metadata storage type: %s", metadataStorage))
klog.Errorf("Unknown metadata storage type: %s", metadataStorage)
return ""
}
}

Expand Down Expand Up @@ -365,32 +396,55 @@ func (d *Druid) OffshootSelectors(extraSelectors ...map[string]string) map[strin
return meta_util.OverwriteKeys(selector, extraSelectors...)
}

func (d Druid) OffshootLabels() map[string]string {
func (d *Druid) OffshootLabels() map[string]string {
return d.offshootLabels(d.OffshootSelectors(), nil)
}

func (e Druid) offshootLabels(selector, override map[string]string) map[string]string {
func (d *Druid) offshootLabels(selector, override map[string]string) map[string]string {
selector[meta_util.ComponentLabelKey] = kubedb.ComponentDatabase
return meta_util.FilterKeys(kubedb.GroupName, selector, meta_util.OverwriteKeys(nil, e.Labels, override))
return meta_util.FilterKeys(kubedb.GroupName, selector, meta_util.OverwriteKeys(nil, d.Labels, override))
}

// CertificateName returns the default certificate name and/or certificate secret name for a certificate alias
func (d *Druid) CertificateName(alias DruidCertificateAlias) string {
return meta_util.NameWithSuffix(d.Name, fmt.Sprintf("%s-cert", string(alias)))
}

// GetCertSecretName returns the secret name for a certificate alias if any,
// otherwise returns default certificate secret name for the given alias.
func (d *Druid) GetCertSecretName(alias DruidCertificateAlias) string {
if d.Spec.TLS != nil {
name, ok := kmapi.GetCertificateSecretName(d.Spec.TLS.Certificates, string(alias))
if ok {
return name
}
}
return d.CertificateName(alias)
}

func (d *Druid) SetDefaults() {
if d.Spec.DeletionPolicy == "" {
d.Spec.DeletionPolicy = TerminationPolicyDelete
}

if d.Spec.DisableSecurity == nil {
d.Spec.DisableSecurity = pointer.BoolP(false)
}

if !*d.Spec.DisableSecurity {
if !d.Spec.DisableSecurity {
if d.Spec.AuthSecret == nil {
d.Spec.AuthSecret = &v1.LocalObjectReference{
Name: d.DefaultUserCredSecretName(kubedb.DruidUserAdmin),
}
}
}

if d.Spec.EnableSSL {
if d.Spec.KeystoreCredSecret == nil {
d.Spec.KeystoreCredSecret = &SecretReference{
LocalObjectReference: core.LocalObjectReference{
Name: d.DruidSecretName(kubedb.DruidKeystoreSecretKey),
},
}
}
}

var druidVersion catalog.DruidVersion
err := DefaultClient.Get(context.TODO(), types.NamespacedName{
Name: d.Spec.Version,
Expand Down Expand Up @@ -523,6 +577,18 @@ func (d *Druid) SetDefaults() {
}
d.Spec.Monitor.SetDefaults()
}

if d.Spec.EnableSSL {
d.SetTLSDefaults()
}
}

func (d *Druid) SetTLSDefaults() {
if d.Spec.TLS == nil || d.Spec.TLS.IssuerRef == nil {
return
}
d.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(d.Spec.TLS.Certificates, string(DruidServerCert), d.CertificateName(DruidServerCert))
d.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(d.Spec.TLS.Certificates, string(DruidClientCert), d.CertificateName(DruidClientCert))
}

func (d *Druid) SetDefaultsToMetadataStorage() {
Expand Down Expand Up @@ -725,3 +791,16 @@ func (d *Druid) GetZooKeeperName() string {
func (d *Druid) GetInitConfigMapName() string {
return d.OffShootName() + "-init-script"
}

// CertSecretVolumeName returns the CertSecretVolumeName
// Values will be like: client-certs, server-certs etc.
func (d *Druid) CertSecretVolumeName(alias DruidCertificateAlias) string {
return string(alias) + "-certs"
}

// CertSecretVolumeMountPath returns the CertSecretVolumeMountPath
// if configDir is "/var/druid/ssl",
// mountPath will be, "/var/druid/ssl/<alias>".
func (d *Druid) CertSecretVolumeMountPath(configDir string, cert string) string {
return filepath.Join(configDir, cert)
}
23 changes: 19 additions & 4 deletions apis/kubedb/v1alpha2/druid_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type DruidSpec struct {
// disable security. It disables authentication security of user.
// If unset, default is false
// +optional
DisableSecurity *bool `json:"disableSecurity,omitempty"`
DisableSecurity bool `json:"disableSecurity,omitempty"`

// Database authentication secret
// +optional
Expand All @@ -79,9 +79,16 @@ type DruidSpec struct {
// +optional
ConfigSecret *core.LocalObjectReference `json:"configSecret,omitempty"`

//// TLS contains tls configurations
//// +optional
//TLS *kmapi.TLSConfig `json:"tls,omitempty"`
// To enable ssl for http layer
EnableSSL bool `json:"enableSSL,omitempty"`

// Keystore encryption secret
// +optional
KeystoreCredSecret *SecretReference `json:"keystoreCredSecret,omitempty"`

// TLS contains tls configurations
// +optional
TLS *kmapi.TLSConfig `json:"tls,omitempty"`

// MetadataStorage contains information for Druid to connect to external dependency metadata storage
// +optional
Expand Down Expand Up @@ -274,3 +281,11 @@ const (
DruidDeepStorageAzure DruidDeepStorageType = "azure"
DruidDeepStorageHDFS DruidDeepStorageType = "hdfs"
)

// +kubebuilder:validation:Enum=server;client
type DruidCertificateAlias string

const (
DruidServerCert DruidCertificateAlias = "server"
DruidClientCert DruidCertificateAlias = "client"
)
Loading
Loading