mirror of https://github.com/portainer/portainer
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
366 lines
19 KiB
366 lines
19 KiB
<page-header
|
|
ng-if="ctrl.state.viewReady"
|
|
title="'Kubernetes features configuration'"
|
|
breadcrumbs="[
|
|
{ label:'Environments', link:'portainer.endpoints' },
|
|
{
|
|
label:ctrl.endpoint.Name,
|
|
link: 'portainer.endpoints.endpoint',
|
|
linkParams:{id: ctrl.endpoint.Id}
|
|
},
|
|
'Kubernetes configuration'
|
|
]"
|
|
reload="true"
|
|
>
|
|
</page-header>
|
|
|
|
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>
|
|
|
|
<div ng-if="ctrl.state.viewReady">
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<rd-widget>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal" name="kubernetesClusterSetupForm">
|
|
<div class="col-sm-12 form-section-title"> Networking </div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12 text-muted small">
|
|
<p> Enabling the load balancer feature will allow users to expose application they deploy over an external IP address assigned by cloud provider. </p>
|
|
<p class="mt-1 vertical-center">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
Ensure that your cloud provider allows you to create load balancers if you want to use this feature. Might incur costs.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left col-sm-3 col-lg-2 px-0"> Allow users to use external load balancer </label>
|
|
<label class="switch mb-0 col-sm-8">
|
|
<input type="checkbox" ng-model="ctrl.formValues.UseLoadBalancer" /><span class="slider round" data-cy="kubeSetup-loadBalancerToggle"></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12 text-muted small">
|
|
<p> Configuring ingress controllers will allow users to expose application they deploy over a HTTP route. </p>
|
|
<p class="mt-1 vertical-center">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
Ingress classes must be manually specified for each controller you want to use in the cluster. Make sure that each controller is running inside your cluster.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left">Ingress controller</label>
|
|
<span class="label label-default interactive vertical-center" style="margin-left: 10px" ng-click="ctrl.addIngressClass()" data-cy="kubeSetup-congifIngressButton">
|
|
<pr-icon icon="'plus'" feather="true" size="'sm'" class="vertical-center"></pr-icon> configure ingress controller
|
|
</span>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-inline" style="margin-top: 10px">
|
|
<div ng-repeat-start="ingressClass in ctrl.formValues.IngressClasses" style="margin-top: 2px">
|
|
<div class="col-sm-7 input-group input-group-sm" ng-class="{ striked: ingressClass.NeedsDeletion }">
|
|
<span class="input-group-addon">Ingress class</span>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
name="ingress_class_name_{{ $index }}"
|
|
ng-model="ingressClass.Name"
|
|
placeholder="nginx"
|
|
ng-pattern="/^[a-z]([-a-z0-9]*[a-z0-9])?$/"
|
|
ng-change="ctrl.onChangeIngressClassName($index)"
|
|
required
|
|
data-cy="kubeSetup-ingressClassName"
|
|
/>
|
|
</div>
|
|
<div class="col-sm-3 input-group input-group-sm" ng-class="{ striked: ingressClass.NeedsDeletion }">
|
|
<span class="input-group-addon">Type</span>
|
|
<select
|
|
class="form-control"
|
|
name="ingress_class_type_{{ $index }}"
|
|
ng-model="ingressClass.Type"
|
|
ng-options="value as value for (key, value) in ctrl.IngressClassTypes"
|
|
required
|
|
data-cy="kubeSetup-ingressType"
|
|
>
|
|
<option selected disabled hidden value="">Select a type</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-sm-1 input-group input-group-sm">
|
|
<button
|
|
ng-if="!ingressClass.NeedsDeletion"
|
|
class="btn btn-dangerlight btn-only-icon"
|
|
type="button"
|
|
ng-click="ctrl.removeIngressClass($index)"
|
|
data-cy="kubeSetup-deleteIngress"
|
|
>
|
|
<pr-icon icon="'trash-2'" feather="true"></pr-icon>
|
|
</button>
|
|
<button ng-if="ingressClass.NeedsDeletion" class="btn btn-only-icon btn-light" type="button" ng-click="ctrl.restoreIngressClass($index)">
|
|
<pr-icon icon="'rotate-ccw'" feather="true"></pr-icon>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
ng-repeat-end
|
|
ng-show="
|
|
kubernetesClusterSetupForm['ingress_class_name_' + $index].$invalid ||
|
|
kubernetesClusterSetupForm['ingress_class_type_' + $index].$invalid ||
|
|
ctrl.state.duplicates.ingressClasses.refs[$index] !== undefined
|
|
"
|
|
>
|
|
<div class="col-sm-7 input-group">
|
|
<div
|
|
class="small"
|
|
style="margin-top: 5px"
|
|
ng-if="kubernetesClusterSetupForm['ingress_class_name_' + $index].$invalid || ctrl.state.duplicates.ingressClasses.refs[$index] !== undefined"
|
|
>
|
|
<div ng-messages="kubernetesClusterSetupForm['ingress_class_name_'+$index].$error">
|
|
<p ng-message="required" class="vertical-center text-muted"
|
|
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Ingress class name is required.</p
|
|
>
|
|
<p ng-message="pattern" class="vertical-center text-muted"
|
|
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This field must consist of lower case alphanumeric characters or '-', start
|
|
with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123').</p
|
|
>
|
|
</div>
|
|
<p ng-if="ctrl.state.duplicates.ingressClasses.refs[$index] !== undefined" class="vertical-center text-muted">
|
|
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This ingress class is already defined.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-3 input-group">
|
|
<div class="small" style="margin-top: 5px" ng-if="kubernetesClusterSetupForm['ingress_class_type_' + $index].$invalid">
|
|
<div ng-messages="kubernetesClusterSetupForm['ingress_class_type_'+$index].$error">
|
|
<p ng-message="required" class="vertical-center text-muted"
|
|
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Ingress class type is required.</p
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group" ng-if="ctrl.hasTraefikIngress()">
|
|
<span class="col-sm-12 text-muted small">
|
|
<p>
|
|
<i class="fa fa-flask blue-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
|
Traefik support is experimental.
|
|
</p>
|
|
</span>
|
|
</div>
|
|
|
|
<!-- auto update window -->
|
|
<div class="col-sm-12 form-section-title"> Change Window Settings </div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<por-switch-field
|
|
checked="ctrl.state.autoUpdateSettings.Enabled"
|
|
name="'disableSysctlSettingForRegularUsers'"
|
|
label="'Enable Change Window'"
|
|
feature-id="ctrl.limitedFeatureAutoWindow"
|
|
tooltip="'Specify a timeframe during which automatic updates can occur in this environment.'"
|
|
on-change="(ctrl.onToggleAutoUpdate)"
|
|
label-class="'col-sm-3 col-lg-2 px-0 !m-0'"
|
|
switch-class="'col-sm-8'"
|
|
>
|
|
</por-switch-field>
|
|
</div>
|
|
</div>
|
|
|
|
<time-window-picker ng-show="ctrl.state.autoUpdateSettings.Enabled" time-window="ctrl.state.autoUpdateSettings" time-zone="ctrl.state.timeZone"></time-window-picker>
|
|
|
|
<!-- #region SECURITY -->
|
|
<div class="col-sm-12 form-section-title"> Security </div>
|
|
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small">
|
|
By default, all the users have access to the default namespace. Enable this option to set accesses on the default namespace.
|
|
</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left col-sm-3 col-lg-2 px-0"> Restrict access to the default namespace </label>
|
|
<label class="switch col-sm-8">
|
|
<input type="checkbox" ng-model="ctrl.formValues.RestrictDefaultNamespace" /><span class="slider round" data-cy="kubeSetup-restrictDefaultNsToggle"></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<!-- #endregion -->
|
|
|
|
<div class="col-sm-12 form-section-title"> Resources and Metrics </div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12 text-muted small">
|
|
<p>
|
|
By ENABLING resource over-commit, you are able to assign more resources to namespaces than is physically available in the cluster. This may lead to unexpected
|
|
deployment failures if there is insufficient resource to service demand.
|
|
</p>
|
|
<p class="mt-1 vertical-center">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
By DISABLING resource over-commit (highly recommended), you are only able to assign resources to namespaces that are less (in aggregate) than the cluster total
|
|
minus any system resource reservation.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="col-sm-12">
|
|
<por-switch-field
|
|
data-cy="'kubeSetup-resourceOverCommitToggle'"
|
|
label="'Allow resource over-commit'"
|
|
name="'resource-over-commit-switch'"
|
|
feature-id="ctrl.limitedFeature"
|
|
checked="ctrl.formValues.EnableResourceOverCommit"
|
|
on-change="(ctrl.onChangeEnableResourceOverCommit)"
|
|
label-class="'col-sm-3 col-lg-2 px-0 !m-0'"
|
|
switch-class="'col-sm-8'"
|
|
></por-switch-field>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-12 text-muted small">
|
|
<p> Enabling this feature will allow users to use specific features like autoscaling and to see container and node resource usage. </p>
|
|
<p class="vertical-center mt-1">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
Ensure that <a href="https://kubernetes.io/docs/tasks/debug-application-cluster/resource-metrics-pipeline/#metrics-server" target="_blank">metrics server</a> or
|
|
<a href="https://github.com/kubernetes-sigs/prometheus-adapter" target="_blank">prometheus</a> is running inside your cluster.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left col-sm-3 col-lg-2 px-0"> Enable features using the metrics API </label>
|
|
<label class="switch col-sm-8">
|
|
<input type="checkbox" ng-model="ctrl.formValues.UseServerMetrics" ng-change="ctrl.enableMetricsServer()" />
|
|
<span class="slider round" data-cy="kubeSetup-metricsToggle"></span>
|
|
</label>
|
|
</div>
|
|
<div ng-if="ctrl.state.metrics.pending && ctrl.state.metrics.userClick" class="col-sm-12 small text-muted" style="margin-top: 5px">
|
|
Checking metrics API... <i class="fa fa-spinner fa-spin" style="margin-left: 2px"></i>
|
|
</div>
|
|
<div
|
|
ng-if="!ctrl.state.metrics.pending && ctrl.state.metrics.isServerRunning && ctrl.state.metrics.userClick"
|
|
class="col-sm-12 small text-muted vertical-center"
|
|
style="margin-top: 5px"
|
|
>
|
|
<pr-icon icon="'check'" mode="'success'" feather="true"></pr-icon> Successfully reached metrics API
|
|
</div>
|
|
<div
|
|
ng-if="!ctrl.state.metrics.pending && !ctrl.state.metrics.isServerRunning && ctrl.state.metrics.userClick"
|
|
class="col-sm-12 small text-muted vertical-center mt-2"
|
|
>
|
|
<pr-icon icon="'x'" mode="'danger'" feather="true"></pr-icon> Unable to reach metrics API, make sure metrics server is properly deployed inside that cluster.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title"> Available storage options </div>
|
|
|
|
<div class="form-group" ng-if="!ctrl.storageClassAvailable()">
|
|
<div class="col-sm-12 small text-muted vertical-center">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
Unable to detect any storage class available to persist data. Users won't be able to persist application data inside this cluster.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group" ng-if="ctrl.storageClassAvailable()">
|
|
<span class="col-sm-12 text-muted small">
|
|
<p>
|
|
Select which storage options will be available for use when deploying applications. Have a look at your storage driver documentation to figure out which access
|
|
policy to configure and if the volume expansion capability is supported.
|
|
</p>
|
|
<p>
|
|
You can find more information about access modes
|
|
<a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes" target="_blank">in the official Kubernetes documentation</a>.
|
|
</p>
|
|
</span>
|
|
</div>
|
|
|
|
<div class="form-group" ng-if="ctrl.storageClassAvailable()">
|
|
<div style="margin-top: 10px" class="col-sm-12">
|
|
<table class="table" style="table-layout: fixed">
|
|
<tbody>
|
|
<tr class="text-muted">
|
|
<td>Storage</td>
|
|
<td>Shared access policy</td>
|
|
<td>Volume expansion</td>
|
|
</tr>
|
|
<tr ng-repeat="class in ctrl.StorageClasses">
|
|
<td>
|
|
<div class="flex-center justify-left">
|
|
<label class="switch mr-2 mb-0">
|
|
<input type="checkbox" ng-model="class.selected" /><span class="slider round" data-cy="kubeSetup-storageToggle{{ class.Name }}"></span>
|
|
</label>
|
|
<span>{{ class.Name }}</span>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<span
|
|
isteven-multi-select
|
|
input-model="class.availableAccessModes"
|
|
output-model="class.AccessModes"
|
|
button-label="Name"
|
|
item-label="Description"
|
|
tick-property="selected"
|
|
directive-id="{{ class.Name }}"
|
|
helper-elements=""
|
|
translation="{nothingSelected: 'Not configured'}"
|
|
data-cy="kubeSetup-storageAccessSelect{{ class.Name }}"
|
|
>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<div style="margin: 5px">
|
|
<label class="switch mr-2 mb-0"
|
|
><input type="checkbox" ng-model="class.AllowVolumeExpansion" /><span
|
|
class="slider round"
|
|
data-cy="kubeSetup-storageExpansionToggle{{ class.Name }}"
|
|
></span>
|
|
</label>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="col-sm-12">
|
|
<span ng-if="!ctrl.hasValidStorageConfiguration()" class="text-muted small vertical-center mt-2">
|
|
<pr-icon icon="'alert-circle'" mode="'warning'" feather="true"></pr-icon>
|
|
Shared access policy configuration required
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 form-section-title"> Actions </div>
|
|
<!-- actions -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button
|
|
type="submit"
|
|
class="btn btn-primary btn-sm"
|
|
ng-click="ctrl.configure()"
|
|
ng-disabled="ctrl.state.actionInProgress || !kubernetesClusterSetupForm.$valid || !ctrl.hasValidStorageConfiguration()"
|
|
button-spinner="ctrl.state.actionInProgress"
|
|
analytics-on
|
|
analytics-if="ctrl.restrictDefaultToggledOn()"
|
|
analytics-category="kubernetes"
|
|
analytics-event="kubernetes-configure"
|
|
analytics-properties="{ metadata: { restrictAccessToDefaultNamespace: ctrl.formValues.RestrictDefaultNamespace } }"
|
|
data-cy="kubeSetup-saveConfigurationButton"
|
|
>
|
|
<span ng-hide="ctrl.state.actionInProgress">Save configuration</span>
|
|
<span ng-show="ctrl.state.actionInProgress">Saving configuration...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|
|
</div>
|