Merge pull request #2468 from noahdesu/ceph-dashboard-port-ssl

add ceph dashboard port/ssl options
This commit is contained in:
Travis Nielsen authored and GitHub committed 2019-01-09 15:58:02 -07:00
commit 92db90bdb2
11 files changed
+129 -21

No files matched your search

+17 -2
View File
@@ -51,14 +51,29 @@ kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o yaml | grep "pas
## Configure the Dashboard
If you are accessing the dashboard via a reverse proxy, you may wish to serve it under a URL prefix.
To get the dashboard to use hyperlinks that include your prefix, you can set the `urlPrefix` setting:
The following dashboard configuration settings are supported:
```yaml
spec:
dashboard:
urlPrefix: /ceph-dashboard
port: 8443
ssl: true
```
* `urlPrefix` If you are accessing the dashboard via a reverse proxy, you may
wish to serve it under a URL prefix. To get the dashboard to use hyperlinks
that include your prefix, you can set the `urlPrefix` setting.
* `port` The port that the dashboard is served on may be changed from the
default using the `port` setting. The corresponding K8s service exposing the
port will automatically be updated.
* `ssl` The dashboard may be served without SSL (useful for when you deploy the
dashboard behind a proxy already served using SSL) by setting the `ssl` option
to be false. Note that the ssl setting will be ignored in Luminous as well as
Mimic 13.2.2 or older where it is not supported
## Viewing the Dashboard External to the Cluster
Commonly you will want to view the dashboard from outside the cluster. For example, on a development machine with the
+3
View File
@@ -11,6 +11,9 @@
- Use `Readiness` and `Liveness` probes.
- Updated automatically on Object Store CRD changes.
- Added the dashboard `port` configuration setting.
- Added the dashboard `ssl` configuration setting.
## Breaking Changes
- Rook no longer supports Kubernetes `1.8` and `1.9`.
@@ -32,6 +32,10 @@ spec:
type: boolean
urlPrefix:
type: string
port:
type: integer
minimum: 0
maximum: 65535
dataDirHostPath:
pattern: ^/(\S+)
type: string
@@ -179,6 +179,10 @@ spec:
enabled: true
# serve the dashboard under a subpath (useful when you are accessing the dashboard via a reverse proxy)
# urlPrefix: /ceph-dashboard
# serve the dashboard at the given port.
# port: 8443
# serve the dashboard using SSL
# ssl: true
network:
# toggle to use hostNetwork
hostNetwork: false
@@ -36,6 +36,8 @@ spec:
type: boolean
urlPrefix:
type: string
port:
type: integer
dataDirHostPath:
pattern: ^/(\S+)
type: string
+4
View File
@@ -94,6 +94,10 @@ type DashboardSpec struct {
Enabled bool `json:"enabled,omitempty"`
// A prefix for all URLs to use the dashboard with a reverse proxy
UrlPrefix string `json:"urlPrefix,omitempty"`
// The dashboard webserver port
Port int `json:"port,omitempty"`
// Whether SSL should be used
SSL *bool `json:"ssl,omitempty"`
}
type ClusterStatus struct {
+22
View File
@@ -21,6 +21,7 @@ import (
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
@@ -262,6 +263,27 @@ func clusterChanged(oldCluster, newCluster cephv1.ClusterSpec, clusterRef *clust
changeFound = true
}
if oldCluster.Dashboard.Port != newCluster.Dashboard.Port {
logger.Infof("dashboard port has changed from \"%d\" to \"%d\"", oldCluster.Dashboard.Port, newCluster.Dashboard.Port)
changeFound = true
}
if (oldCluster.Dashboard.SSL == nil && newCluster.Dashboard.SSL != nil) ||
(oldCluster.Dashboard.SSL != nil && newCluster.Dashboard.SSL == nil) ||
(oldCluster.Dashboard.SSL != nil && newCluster.Dashboard.SSL != nil &&
*oldCluster.Dashboard.SSL != *newCluster.Dashboard.SSL) {
oldSSL := "<default>"
if oldCluster.Dashboard.SSL != nil {
oldSSL = strconv.FormatBool(*oldCluster.Dashboard.SSL)
}
newSSL := "<default>"
if newCluster.Dashboard.SSL != nil {
newSSL = strconv.FormatBool(*newCluster.Dashboard.SSL)
}
logger.Infof("dashboard ssl option has changed from \"%s\" to \"%s\"", oldSSL, newSSL)
changeFound = true
}
if oldCluster.Mon.Count != newCluster.Mon.Count {
logger.Infof("number of mons have changed from %d to %d. The health check will update the mons...", oldCluster.Mon.Count, newCluster.Mon.Count)
clusterRef.mons.MonCountMutex.Lock()
+47 -10
View File
@@ -21,6 +21,7 @@ import (
"fmt"
"math/rand"
"os/exec"
"strconv"
"syscall"
"time"
@@ -54,7 +55,7 @@ func init() {
func (c *Cluster) configureDashboard(port int) error {
// enable or disable the dashboard module
if err := c.toggleDashboardModule(); err != nil {
if err := c.toggleDashboardModule(port); err != nil {
return err
}
@@ -66,6 +67,17 @@ func (c *Cluster) configureDashboard(port int) error {
return fmt.Errorf("failed to create dashboard mgr service. %+v", err)
}
logger.Infof("dashboard service already exists")
original, err := c.context.Clientset.CoreV1().Services(c.Namespace).Get(dashboardService.Name, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get dashboard service. %+v", err)
}
if original.Spec.Ports[0].Port != int32(port) {
logger.Infof("dashboard port changed. updating service")
original.Spec.Ports[0].Port = int32(port)
if _, err := c.context.Clientset.CoreV1().Services(c.Namespace).Update(original); err != nil {
return fmt.Errorf("failed to update dashboard mgr service. %+v", err)
}
}
} else {
logger.Infof("dashboard service started")
}
@@ -81,7 +93,7 @@ func (c *Cluster) configureDashboard(port int) error {
}
// Ceph docs about the dashboard module: http://docs.ceph.com/docs/luminous/mgr/dashboard/
func (c *Cluster) toggleDashboardModule() error {
func (c *Cluster) toggleDashboardModule(dashboardPort int) error {
if c.dashboard.Enabled {
if err := client.MgrEnableModule(c.context, c.Namespace, dashboardModuleName, true); err != nil {
return fmt.Errorf("failed to enable mgr dashboard module. %+v", err)
@@ -91,7 +103,7 @@ func (c *Cluster) toggleDashboardModule() error {
return fmt.Errorf("failed to initialize dashboard. %+v", err)
}
if err := c.configureDashboardModule(); err != nil {
if err := c.configureDashboardModule(dashboardPort); err != nil {
return fmt.Errorf("failed to configure mgr dashboard module. %+v", err)
}
} else {
@@ -102,11 +114,34 @@ func (c *Cluster) toggleDashboardModule() error {
return nil
}
func (c *Cluster) configureDashboardModule() error {
func (c *Cluster) configureDashboardModule(dashboardPort int) error {
// url prefix
hasChanged, err := client.MgrSetAllConfig(c.context, c.Namespace, c.cephVersion.Name, "mgr/dashboard/url_prefix", c.dashboard.UrlPrefix)
if err != nil {
return err
}
// server port
port := strconv.Itoa(dashboardPort)
changed, err := client.MgrSetAllConfig(c.context, c.Namespace, c.cephVersion.Name, "mgr/dashboard/server_port", port)
if err != nil {
return err
}
hasChanged = hasChanged || changed
// ssl support
var ssl string
if c.dashboard.SSL == nil {
ssl = ""
} else {
ssl = strconv.FormatBool(*c.dashboard.SSL)
}
changed, err = client.MgrSetAllConfig(c.context, c.Namespace, c.cephVersion.Name, "mgr/dashboard/ssl", ssl)
if err != nil {
return err
}
hasChanged = hasChanged || changed
if hasChanged {
logger.Infof("dashboard config has changed")
return c.restartDashboard()
@@ -128,12 +163,14 @@ func (c *Cluster) initializeSecureDashboard() error {
return fmt.Errorf("failed to generate a password. %+v", err)
}
alreadyCreated, err := c.createSelfSignedCert()
if err != nil {
return fmt.Errorf("failed to create a self signed cert. %+v", err)
}
if alreadyCreated {
return nil
if c.dashboard.SSL == nil || *c.dashboard.SSL {
alreadyCreated, err := c.createSelfSignedCert()
if err != nil {
return fmt.Errorf("failed to create a self signed cert. %+v", err)
}
if alreadyCreated {
return nil
}
}
if err := c.setLoginCredentials(password); err != nil {
@@ -103,9 +103,10 @@ func TestStartSecureDashboard(t *testing.T) {
dashboardInitWaitTime = 0
err := c.configureDashboard(dashboardPortHttp)
assert.Nil(t, err)
// the dashboard is enabled, then disabled and enabled again to restart it with the cert
assert.Equal(t, 2, enables)
assert.Equal(t, 1, disables)
// the dashboard is enabled, then disabled and enabled again to restart
// it with the cert, and another restart when setting the dashboard port
assert.Equal(t, 3, enables)
assert.Equal(t, 2, disables)
assert.Equal(t, 2, moduleRetries)
svc, err := c.context.Clientset.CoreV1().Services(c.Namespace).Get("rook-ceph-mgr-dashboard", metav1.GetOptions{})
@@ -116,8 +117,8 @@ func TestStartSecureDashboard(t *testing.T) {
c.dashboard.Enabled = false
err = c.configureDashboard(dashboardPortHttp)
assert.Nil(t, err)
assert.Equal(t, 2, enables)
assert.Equal(t, 2, disables)
assert.Equal(t, 3, enables)
assert.Equal(t, 3, disables)
svc, err = c.context.Clientset.CoreV1().Services(c.Namespace).Get("rook-ceph-mgr-dashboard", metav1.GetOptions{})
assert.NotNil(t, err)
+11 -3
View File
@@ -90,9 +90,17 @@ var updateDeploymentAndWait = k8sutil.UpdateDeploymentAndWait
func (c *Cluster) Start() error {
logger.Infof("start running mgr")
dashboardPort := dashboardPortHttps
if c.cephVersion.Name == cephv1.Luminous {
dashboardPort = dashboardPortHttp
var dashboardPort int
if c.dashboard.Port == 0 {
// select default ports
if c.cephVersion.Name == cephv1.Luminous {
dashboardPort = dashboardPortHttp
} else {
dashboardPort = dashboardPortHttps
}
} else {
// crd validates port >= 0
dashboardPort = c.dashboard.Port
}
for i := 0; i < c.Replicas; i++ {
+9 -1
View File
@@ -61,6 +61,7 @@ func TestStartMGR(t *testing.T) {
testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
c.dashboard.UrlPrefix = "/test"
c.dashboard.Port = 12345
err = c.Start()
assert.Nil(t, err)
validateStart(t, c)
@@ -92,9 +93,16 @@ func validateStart(t *testing.T, c *Cluster) {
_, err := c.context.Clientset.CoreV1().Services(c.Namespace).Get("rook-ceph-mgr", metav1.GetOptions{})
assert.Nil(t, err)
_, err = c.context.Clientset.CoreV1().Services(c.Namespace).Get("rook-ceph-mgr-dashboard", metav1.GetOptions{})
ds, err := c.context.Clientset.CoreV1().Services(c.Namespace).Get("rook-ceph-mgr-dashboard", metav1.GetOptions{})
if c.dashboard.Enabled {
assert.Nil(t, err)
if c.dashboard.Port == 0 {
// port=0 -> default port
assert.Equal(t, ds.Spec.Ports[0].Port, int32(dashboardPortHttps))
} else {
// non-zero ports are configured as-is
assert.Equal(t, ds.Spec.Ports[0].Port, int32(c.dashboard.Port))
}
} else {
assert.True(t, errors.IsNotFound(err))
}