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

feat(api): add full proxy mode to api module #8766

Merged
merged 3 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion docs/common/arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Dashboard containers accept multiple arguments that can be used to customize the
| tls-key-file | - | File containing the default x509 private key matching --tls-cert-file. |
| auto-generate-certificates | false | When set to true, Dashboard will automatically generate certificates used to serve HTTPS. |
| apiserver-host | - | The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and local discovery is attempted. |
| heapster-host | - | The address of the Heapster Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8082. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and service proxy will be used. |
| sidecar-host | - | The address of the Sidecar Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8000. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and service proxy will be used. |
| metrics-provider | sidecar | Select provider type for metrics. 'none' will not check metrics. |
| metric-client-check-period | 30 | Time in seconds that defines how often configured metric client health check should be run. |
Expand All @@ -23,6 +22,7 @@ Dashboard containers accept multiple arguments that can be used to customize the
| metrics-scraper-service-name | kubernetes-dashboard-metrics-scraper | Name of the dashboard metrics scraper service. |
| disable-csrf-protection | false | Allows disabling CSRF protection. |
| csrf-key | - | Base64 encoded random 256 bytes key. Can be loaded from 'CSRF_KEY' environment variable. |
| act-as-proxy | false | Forces dashboard to work in full proxy mode, meaning that any in-cluster calls are disabled. |
| v | 1 | Number for the log level verbosity (default 1) | |

## Auth module arguments
Expand Down
2 changes: 0 additions & 2 deletions hack/scripts/conf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ RELEASE_VERSION=2.5.0
ARCH=$(uname | awk '{print tolower($0)}')

# Local cluster configuration (check start-cluster.sh script for more details).
HEAPSTER_VERSION="v1.5.4"
HEAPSTER_PORT=8082
KIND_VERSION="v0.19.0"
K8S_VERSION="v1.29.2"
KIND_BIN=${CACHE_DIR}/kind-${KIND_VERSION}
Expand Down
21 changes: 0 additions & 21 deletions hack/scripts/start-cluster.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,9 @@
ROOT_DIR="$(cd $(dirname "${BASH_SOURCE}")/../.. && pwd -P)"
. "${ROOT_DIR}/hack/scripts/conf.sh"

function start-ci-heapster {
echo "\nRunning heapster in standalone mode"
docker run --net=host -d registry.k8s.io/heapster-amd64:${HEAPSTER_VERSION} \
--heapster-port ${HEAPSTER_PORT} \
--source=kubernetes:http://127.0.0.1:8080?inClusterConfig=false&auth=""

echo "\nWaiting for heapster to be started"
for i in {1..150}
do
HEAPSTER_STATUS=$(curl -sb -H "Accept: application/json" "127.0.0.1:${HEAPSTER_PORT}/healthz")
if [ "${HEAPSTER_STATUS}" == "ok" ]; then
break
fi
sleep 2
done
echo "\nHeapster is up and running"
}

function start-kind {
${KIND_BIN} create cluster --name="k8s-cluster-ci" --image="kindest/node:${K8S_VERSION}" --config="${ROOT_DIR}/hack/scripts/kind-config"
ensure-kubeconfig
if [ "${CI}" = true ] ; then
start-ci-heapster
fi
echo "\nKubernetes cluster is ready to use"
}

Expand Down
5 changes: 2 additions & 3 deletions hack/test-resources/kubernetes-dashboard-local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ rules:
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
resourceNames: ["dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
resourceNames: ["dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
Expand Down
48 changes: 32 additions & 16 deletions modules/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,19 @@ func main() {
client.WithInsecureTLSSkipVerify(args.ApiServerSkipTLSVerify()),
)

versionInfo, err := client.InClusterClient().Discovery().ServerVersion()
if err != nil {
handleFatalInitError(err)
if !args.IsProxyEnabled() {
ensureAPIServerConnectionOrDie()
} else {
klog.Info("Running in proxy mode. InClusterClient connections will be disabled.")
}

klog.InfoS("Successful initial request to the apiserver", "version", versionInfo.String())

// Init integrations
integrationManager := integration.NewIntegrationManager()

switch metricsProvider := args.MetricsProvider(); metricsProvider {
case "sidecar":
integrationManager.Metric().ConfigureSidecar(args.SidecarHost()).
EnableWithRetry(integrationapi.SidecarIntegrationID, time.Duration(args.MetricClientHealthCheckPeriod()))
case "none":
klog.Info("Metrics provider disabled")
default:
klog.InfoS("Invalid metrics provider", "provider", metricsProvider)
klog.Info("Using default metrics provider", "provider", "sidecar")
integrationManager.Metric().ConfigureSidecar(args.SidecarHost()).
EnableWithRetry(integrationapi.SidecarIntegrationID, time.Duration(args.MetricClientHealthCheckPeriod()))
if !args.IsProxyEnabled() {
configureMetricsProvider(integrationManager)
} else {
klog.Info("Skipping metrics configuration. Metrics not available in proxy mode.")
}

apiHandler, err := handler.CreateHTTPAPIHandler(integrationManager)
Expand Down Expand Up @@ -109,6 +101,30 @@ func serveTLS(certificates []tls.Certificate) {
go func() { klog.Fatal(server.ListenAndServeTLS("", "")) }()
}

func ensureAPIServerConnectionOrDie() {
versionInfo, err := client.InClusterClient().Discovery().ServerVersion()
if err != nil {
handleFatalInitError(err)
}

klog.InfoS("Successful initial request to the apiserver", "version", versionInfo.String())
}

func configureMetricsProvider(integrationManager integration.Manager) {
switch metricsProvider := args.MetricsProvider(); metricsProvider {
case "sidecar":
integrationManager.Metric().ConfigureSidecar(args.SidecarHost()).
EnableWithRetry(integrationapi.SidecarIntegrationID, time.Duration(args.MetricClientHealthCheckPeriod()))
case "none":
klog.Info("Metrics provider disabled")
default:
klog.InfoS("Invalid metrics provider", "provider", metricsProvider)
klog.Info("Using default metrics provider", "provider", "sidecar")
integrationManager.Metric().ConfigureSidecar(args.SidecarHost()).
EnableWithRetry(integrationapi.SidecarIntegrationID, time.Duration(args.MetricClientHealthCheckPeriod()))
}
}

/**
* Handles fatal init error that prevents server from doing any work. Prints verbose error
* message and quits the server.
Expand Down
5 changes: 5 additions & 0 deletions modules/api/pkg/args/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var (
argNamespace = pflag.String("namespace", helpers.GetEnv("POD_NAMESPACE", "kubernetes-dashboard"), "Namespace to use when accessing Dashboard specific resources, i.e. metrics scraper service")
argMetricsScraperServiceName = pflag.String("metrics-scraper-service-name", "kubernetes-dashboard-metrics-scraper", "name of the dashboard metrics scraper service")
argDisableCSRFProtection = pflag.Bool("disable-csrf-protection", false, "allows disabling CSRF protection")
argIsProxyEnabled = pflag.Bool("act-as-proxy", false, "forces dashboard to work in full proxy mode, meaning that any in-cluster calls are disabled")
)

func init() {
Expand Down Expand Up @@ -147,3 +148,7 @@ func Namespace() string {
func IsCSRFProtectionEnabled() bool {
return !*argDisableCSRFProtection
}

func IsProxyEnabled() bool {
return *argIsProxyEnabled
}
2 changes: 1 addition & 1 deletion modules/api/pkg/handler/apihandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const (
ResponseLogString = "[%s] Outcoming response to %s with %d status code"
)

// APIHandler is a representation of API handler. Structure contains clientapi, Heapster clientapi and clientapi configuration.
// APIHandler is a representation of API handler. Structure contains clientapi and clientapi configuration.
type APIHandler struct {
iManager integration.Manager
}
Expand Down
Loading