Update dashboard content

This commit is contained in:
Jerome Petazzoni
2020-10-20 21:19:08 +02:00
parent 0040313371
commit 1300d76890
4 changed files with 482 additions and 20 deletions

View File

@@ -0,0 +1,336 @@
# This file is based on the following manifest:
# https://github.com/kubernetes/dashboard/blob/master/aio/deploy/recommended.yaml
# It adds a ServiceAccount that has cluster-admin privileges on the cluster,
# and exposes the dashboard on a NodePort. It makes it easier to do quick demos
# of the Kubernetes dashboard, without compromising the security too much.
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
# Allow Metrics Scraper to get metrics from the Metrics server
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.0.0
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.4
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: cluster-admin
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: cluster-admin
namespace: kubernetes-dashboard

View File

@@ -2,47 +2,65 @@
- Kubernetes resources can also be viewed with a web dashboard
- That dashboard is usually exposed over HTTPS
(this requires obtaining a proper TLS certificate)
- Dashboard users need to authenticate
- We are going to take a *dangerous* shortcut
(typically with a token)
- The dashboard should be exposed over HTTPS
(to prevent interception of the aforementioned token)
- Ideally, this requires obtaining a proper TLS certificate
(for instance, with Let's Encrypt)
---
## The insecure method
## Three ways to install the dashboard
- We could (and should) use [Let's Encrypt](https://letsencrypt.org/) ...
- Our `k8s` directory has no less than three manifests!
- ... but we don't want to deal with TLS certificates
- `dashboard-recommended.yaml`
- We could (and should) learn how authentication and authorization work ...
(purely internal dashboard; user must be created manually)
- ... but we will use a guest account with admin access instead
- `dashboard-with-token.yaml`
.footnote[.warning[Yes, this will open our cluster to all kinds of shenanigans. Don't do this at home.]]
(dashboard exposed with NodePort; creates an admin user for us)
- `dashboard-insecure.yaml` aka *YOLO*
(dashboard exposed over HTTP; gives root access to anonymous users)
---
## Running a very insecure dashboard
## `dashboard-insecure.yaml`
- We are going to deploy that dashboard with *one single command*
- This will allow anyone to deploy anything on your cluster
- This command will create all the necessary resources
(without any authentication whatsoever)
(the dashboard itself, the HTTP wrapper, the admin/guest account)
- **Do not** use this, except maybe on a local cluster
- All these resources are defined in a YAML file
(or a cluster that you will destroy a few minutes later)
- All we have to do is load that YAML file with with `kubectl apply -f`
- On "normal" clusters, use `dashboard-with-token.yaml` instead!
---
## What's in the manifest?
- The dashboard itself
- An HTTP/HTTPS unwrapper (using `socat`)
- The guest/admin account
.exercise[
- Create all the dashboard resources, with the following command:
```bash
kubectl apply -f ~/container.training/k8s/insecure-dashboard.yaml
kubectl apply -f ~/container.training/k8s/dashboard-insecure.yaml
```
]
@@ -89,11 +107,26 @@ The dashboard will then ask you which authentication you want to use.
--
.warning[By the way, we just added a backdoor to our Kubernetes cluster!]
.warning[Remember, we just added a backdoor to our Kubernetes cluster!]
---
## Running the Kubernetes dashboard securely
## Closing the backdoor
- Seriously, don't leave that thing running!
.exercise[
- Remove what we just created:
```bash
kubectl delete -f ~/container.training/k8s/dashboard-insecure.yaml
```
]
---
## The risks
- The steps that we just showed you are *for educational purposes only!*
@@ -105,6 +138,99 @@ The dashboard will then ask you which authentication you want to use.
---
## `dashboard-with-token.yaml`
- This is a less risky way to deploy the dashboard
- It's not completely secure, either:
- we're using a self-signed certificate
- this is subject to eavesdropping attacks
- Using `kubectl port-forward` or `kubectl proxy` is even better
---
## What's in the manifest?
- The dashboard itself (but exposed with a `NodePort`)
- A ServiceAccount with `cluster-admin` privileges
(named `kubernetes-dashboard:cluster-admin`)
.exercise[
- Create all the dashboard resources, with the following command:
```bash
kubectl apply -f ~/container.training/k8s/dashboard-with-token.yaml
```
]
---
## Obtaining the token
- The manifest creates a ServiceAccount
- Kubernetes will automatically generate a token for that ServiceAccount
.exercise[
- Display the token:
```bash
kubectl --namespace=kubernetes-dashboard \
describe secret cluster-admin-token
```
]
The token should start with `eyJ...` (it's a JSON Web Token).
Note that the secret name will actually be `cluster-admin-token-xxxxx`.
<br/>
(But `kubectl` prefix matches are great!)
---
## Connecting to the dashboard
.exercise[
- Check which port the dashboard is on:
```bash
kubectl get svc --namespace=kubernetes-dashboard
```
]
You'll want the `3xxxx` port.
.exercise[
- Connect to http://oneofournodes:3xxxx/
<!-- ```open http://node1:3xxxx/``` -->
]
The dashboard will then ask you which authentication you want to use.
---
## Dashboard authentication
- Select "token" authentication
- Copy paste the token (starting with `eyJ...`) obtained earlier
- We're logged in!
---
## Other dashboards
- [Kube Web View](https://codeberg.org/hjacobs/kube-web-view)