Skip to content

Commit

Permalink
salt, ui: deploy UI using *Ingress*es
Browse files Browse the repository at this point in the history
The Kubernetes API, SaltAPI, Prometheus and the actual UI are now
exposed using the `nginx-control-plane` *Ingress* controller, and as
such accessible through the control-plane network IP of the 'bootstrap'
node, port 8443.

Note: this also updates Cypress to a (for now) unreleased version,
because the current released version doesn't support self-signed TLS
certificates when using an IP-based host as a test target (which is the
case in our setup). This was reported upstream in
cypress-io/cypress#771 and fixed in
cypress-io/cypress#4947. The information as to
how to install an unreleased version of Cypress I got from
cypress-io/cypress#4525. We also ensure all
shared libraries this version of Cypress uses are installed in the test
environment.

Fixes: #1602
See: #1602
Fixes: #1797
See: #1797
Fixes: #1799
See: #1799
Fixes: #1800
See: #1800
See: cypress-io/cypress#4947
See: cypress-io/cypress#771
See: cypress-io/cypress#4525
  • Loading branch information
NicolasT committed Oct 1, 2019
1 parent 7d5301d commit 98b7171
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 126 deletions.
9 changes: 6 additions & 3 deletions buildchain/buildchain/salt_tree.py
Expand Up @@ -216,9 +216,12 @@ def _get_parts(self) -> Iterator[str]:
'prometheus-nodeport.sls'),
Path('salt/metalk8s/addons/prometheus-operator/deployed/storageclass.sls'),

Path('salt/metalk8s/addons/ui/deployed.sls'),
Path('salt/metalk8s/addons/ui/files/metalk8s-ui-deployment.yaml'),
Path('salt/metalk8s/addons/ui/precheck.sls'),
Path('salt/metalk8s/addons/ui/deployed/dependencies.sls'),
Path('salt/metalk8s/addons/ui/deployed/ingress.sls'),
Path('salt/metalk8s/addons/ui/deployed/init.sls'),
Path('salt/metalk8s/addons/ui/deployed/files/metalk8s-ui-deployment.yaml'),
Path('salt/metalk8s/addons/ui/deployed/namespace.sls'),
Path('salt/metalk8s/addons/ui/deployed/ui.sls'),

Path('salt/metalk8s/addons/volumes/deployed.sls'),
targets.TemplateFile(
Expand Down
27 changes: 5 additions & 22 deletions docs/quickstart/services.rst
Expand Up @@ -12,42 +12,25 @@ and can be used for operating, extending and upgrading a MetalK8s cluster.

Gather required information
^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Get the workload plane IP of the bootstrap node.
#. Get the control plane IP of the bootstrap node.

.. code-block:: shell
root@bootstrap $ salt-call grains.get metalk8s:workload_plane_ip
root@bootstrap $ salt-call grains.get metalk8s:control_plane_ip
local:
<the workload plane IP>
#. Retrieve the active ``NodePort`` number for the UI (here ``30923``):

.. code-block:: shell
root@boostrap $ kubectl --kubeconfig=/etc/kubernetes/admin.conf get svc metalk8s-ui -n metalk8s-ui
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
metalk8s-ui NodePort 10.104.61.208 <none> 80:30923/TCP 3h
<the control plane IP>
Use MetalK8s UI
^^^^^^^^^^^^^^^
Once you have gathered the IP address and the port number, open your
web browser and navigate to the URL ``http://<ip>:<port>``, replacing
web browser and navigate to the URL ``https://<ip>:8443``, replacing
placeholders with the values retrieved before.

The login page is loaded, and should resemble the following:

.. image:: img/ui/login.png

In the bottom left corner of the page, click the link
``Accept SSL Certificate for Kubernetes``. In the new tab, click the button
``Advanced...``, then select ``Accept the risk and continue``.

Follow the same steps for the second link, ``Accept SSL Certificate for Salt``.

Go back to the first tab, then log in with the default login / password
(admin / admin).
Log in with the default login / password (admin / admin).

The landing page should look like this:

Expand Down
2 changes: 2 additions & 0 deletions eve/main.yml
Expand Up @@ -333,6 +333,8 @@ stages:
command: bash cypress.sh
workdir: build/ui
haltOnFailure: true
env:
IN_CI: 'True'
- ShellCommand:
name: Prepare upload folder
command: >
Expand Down
55 changes: 55 additions & 0 deletions salt/metalk8s/addons/ui/deployed/dependencies.sls
@@ -0,0 +1,55 @@
#!kubernetes kubeconfig=/etc/kubernetes/admin.conf&context=kubernetes-admin@kubernetes

kind: Service
apiVersion: v1
metadata:
name: kubernetes-api
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
spec:
type: ExternalName
externalName: kubernetes.default.svc.cluster.local
ports:
- name: https
port: 443
---
kind: Service
apiVersion: v1
metadata:
name: salt-api
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
spec:
type: ExternalName
externalName: salt-master.kube-system.svc.cluster.local
ports:
- name: https
port: 4507
---
kind: Service
apiVersion: v1
metadata:
name: prometheus-api
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
spec:
type: ExternalName
externalName: prometheus-operator-prometheus.metalk8s-monitoring.svc.cluster.local
ports:
- name: http
port: 9090
78 changes: 78 additions & 0 deletions salt/metalk8s/addons/ui/deployed/ingress.sls
@@ -0,0 +1,78 @@
#!kubernetes kubeconfig=/etc/kubernetes/admin.conf&context=kubernetes-admin@kubernetes

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: metalk8s-ui-proxies-https
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
annotations:
nginx.ingress.kubernetes.io/rewrite-target: '/$2'
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
kubernetes.io/ingress.class: "nginx-control-plane"
spec:
rules:
- http:
paths:
- path: /api/kubernetes(/|$)(.*)
backend:
serviceName: kubernetes-api
servicePort: 443
- path: /api/salt(/|$)(.*)
backend:
serviceName: salt-api
servicePort: 4507
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: metalk8s-ui-proxies-http
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
annotations:
nginx.ingress.kubernetes.io/rewrite-target: '/$2'
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
kubernetes.io/ingress.class: "nginx-control-plane"
spec:
rules:
- http:
paths:
- path: /api/prometheus(/|$)(.*)
backend:
serviceName: prometheus-api
servicePort: 9090
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: metalk8s-ui
namespace: metalk8s-ui
labels:
app: metalk8s-ui
app.kubernetes.io/managed-by: salt
app.kubernetes.io/name: metalk8s-ui
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
kubernetes.io/ingress.class: "nginx-control-plane"
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: metalk8s-ui
servicePort: 80
5 changes: 5 additions & 0 deletions salt/metalk8s/addons/ui/deployed/init.sls
@@ -0,0 +1,5 @@
include:
- .namespace
- .dependencies
- .ui
- .ingress
10 changes: 10 additions & 0 deletions salt/metalk8s/addons/ui/deployed/namespace.sls
@@ -0,0 +1,10 @@
#!kubernetes kubeconfig=/etc/kubernetes/admin.conf&context=kubernetes-admin@kubernetes

kind: Namespace
apiVersion: v1
metadata:
name: metalk8s-ui
labels:
app.kubernetes.io/managed-by: salt
app.kubernetes.io/part-of: metalk8s
heritage: metalk8s
@@ -1,19 +1,9 @@
include:
- .precheck
- .namespace

{%- set kubeconfig = "/etc/kubernetes/admin.conf" %}
{%- set context = "kubernetes-admin@kubernetes" %}

{%- set apiserver = 'https://' ~ pillar.metalk8s.api_server.host ~ ':6443' %}
{%- set saltapi = 'https://' ~ pillar.metalk8s.endpoints['salt-master'].ip ~ ':' ~ pillar.metalk8s.endpoints['salt-master'].ports.api %}
{%- set prometheus = 'http://' ~ grains.metalk8s.workload_plane_ip ~ ':30222' %}

Create metalk8s-ui namespace:
metalk8s_kubernetes.namespace_present:
- name: metalk8s-ui
- kubeconfig: {{ kubeconfig }}
- context: {{ context }}

Create metalk8s-ui deployment:
metalk8s_kubernetes.deployment_present:
- name: metalk8s-ui
Expand All @@ -40,7 +30,7 @@ Create metalk8s-ui service:
targetPort: 80
selector:
app: metalk8s-ui
type: NodePort
type: ClusterIP

Create metalk8s-ui ConfigMap:
metalk8s_kubernetes.configmap_present:
Expand All @@ -51,9 +41,9 @@ Create metalk8s-ui ConfigMap:
- data:
config.json: |
{
"url": "{{ apiserver }}",
"url_salt": "{{ saltapi }}",
"url_prometheus": "{{ prometheus }}"
"url": "/api/kubernetes",
"url_salt": "/api/salt",
"url_prometheus": "/api/prometheus"
}

Create ui-branding ConfigMap:
Expand Down
7 changes: 0 additions & 7 deletions salt/metalk8s/addons/ui/precheck.sls

This file was deleted.

1 change: 1 addition & 0 deletions salt/metalk8s/deployed.sls
Expand Up @@ -8,3 +8,4 @@ include:
- metalk8s.addons.nginx-ingress.deployed
- metalk8s.addons.nginx-ingress-control-plane.deployed
- metalk8s.addons.volumes.deployed
- metalk8s.addons.ui.deployed
20 changes: 0 additions & 20 deletions salt/metalk8s/orchestrate/bootstrap/init.sls
Expand Up @@ -154,26 +154,6 @@ Deploy Kubernetes objects:
- require:
- http: Wait for API server to be available

Precheck for MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.precheck
- saltenv: {{ saltenv }}
- retry:
attempts: 5
- require:
- salt: Deploy Kubernetes objects

Deploy MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.deployed
- saltenv: {{ saltenv }}
- require:
- salt: Precheck for MetalK8s UI

Store MetalK8s version in annotations:
metalk8s_kubernetes.namespace_annotation_present:
- name: "kube-system"
Expand Down
24 changes: 0 additions & 24 deletions salt/metalk8s/orchestrate/downgrade/init.sls
Expand Up @@ -92,27 +92,3 @@ Deploy Kubernetes objects:
- saltenv: metalk8s-{{ dest_version }}
- require:
- salt: Downgrade etcd cluster

{#- UI is not present before version 2.4 #}
{%- set version_list = (dest_version|string).split('.') %}
{%- if version_list[0] == "2" and version_list[1]|int >= 4 %}
Precheck for MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.precheck
- saltenv: metalk8s-{{ dest_version }}
- retry:
attempts: 5
- require:
- salt: Deploy Kubernetes objects

Deploy MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.deployed
- saltenv: metalk8s-{{ dest_version }}
- require:
- salt: Precheck for MetalK8s UI
{%- endif %}
20 changes: 0 additions & 20 deletions salt/metalk8s/orchestrate/upgrade/init.sls
Expand Up @@ -87,23 +87,3 @@ Deploy Kubernetes objects:
- saltenv: metalk8s-{{ dest_version }}
- require:
- salt: Upgrade etcd cluster

Precheck for MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.precheck
- saltenv: metalk8s-{{ dest_version }}
- retry:
attempts: 5
- require:
- salt: Deploy Kubernetes objects

Deploy MetalK8s UI:
salt.runner:
- name: state.orchestrate
- mods:
- metalk8s.addons.ui.deployed
- saltenv: metalk8s-{{ dest_version }}
- require:
- salt: Precheck for MetalK8s UI
12 changes: 5 additions & 7 deletions tests/post/steps/test_ui.py
Expand Up @@ -16,15 +16,13 @@ def reach_UI(host):
with host.sudo():
output = host.check_output(' '.join([
'salt-call', '--local', '--out=json',
'grains.get', 'metalk8s:workload_plane_ip',
'grains.get', 'metalk8s:control_plane_ip',
]))
ip = json.loads(output)['local']

cmd_port = ('kubectl --kubeconfig=/etc/kubernetes/admin.conf'
' get svc -n metalk8s-ui metalk8s-ui --no-headers'
' -o custom-columns=":spec.ports[0].nodePort"')
port = host.check_output(cmd_port)

response = requests.get('http://{ip}:{port}'.format(ip=ip, port=port))
response = requests.get(
'https://{ip}:8443'.format(ip=ip),
verify=False,
)

assert response.status_code == 200, response.text

0 comments on commit 98b7171

Please sign in to comment.