Cómo desplegar Portainer Business 2.0 detrás de Traefik, con soporte SSL en Kubernetes.
En este artículo te muestro como desplegar Portainer Business 2.0 en Kubernetes.
Hace unos meses Portainer lanzo la versión Community Edition 2.0 y como gran novedad incluía el soporte para Kubernetes, convirtiendose así en la única herramienta de management de contenedores que cubría Docker Standalone, Swarm y Kubernetes.
Hace unos días, lanzaron una versión paga, llamada Business, la misma esta enfocada a negocios y empresas que necesitan funcionalidades empresariales tales como gestión de la identidad (por OAuth, LDAP, Active Directory), Manejo de registries, manejo de cuotas para el caso de Kubernetes, pero por sobre todo, soporte técnico que viene en dos opciones, 24x7 o 9x5.
No quiero que este post sea un aviso publicitario, así que si quieren saber más los invito a la siguiente web:
¿Qué necesitamos?
Para arrancar, necesitaremos una licencia de Portainer Business, asumiendo que ya la tienes, lo que necesitamos es descargar el YAML que correremos en nuestro nodo de Kubernetes, que dependiendo de nuestra preferencia puede exponer Portainer por NodePort o a través de un Load Balancer.
Si bien la opción de Load Balancer es tentadora y use como base ese archivo, no me da mucha gracia exponer el puerto 9000 y 8000 directamente, sino que prefiero que sea Traefik el que gestione todo.
$ wget https://raw.githubusercontent.com/xe-nvdk/easy-kubernetes-cookbook/main/portainer-business-v2.0/portainer-lb-ee.yml
Este archivo, ya esta modificado con todo lo que necesitamos, tanto desde el lado del volumen, el IngressRoute y la configuración SSL para que Traefik le de un certificado valido.
Empecemos
Para arrancar, vamos a crear el directorio donde persistiremos los datos de Portainer:
$ mkdir -p /mnt/data/portainer
Luego, editaremos el YML, dejándolo de esta manera, particularmente le hice unos cambios a la definición del namespace, volumen y agregue los IngressRoute para el Frontend y Edge, recuerden que vamos a desplegarlo detrás de Traefik quien no solo hará de Reverse Proxy sino que también nos manejará los certificados SSL de Let's Encrypt.
# Source: portainer/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: portainer-sa-clusteradmin
namespace: default
labels:
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
app.kubernetes.io/version: "2.0.0"
---
# Source: portainer/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: portainer
labels:
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
app.kubernetes.io/version: "2.0.0"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
namespace: default
name: portainer-sa-clusteradmin
---
# Source: portainer/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: portainer
namespace: default
labels:
io.portainer.kubernetes.application.stack: portainer
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
app.kubernetes.io/version: "2.0.0"
spec:
ports:
- port: 9000
targetPort: 9000
protocol: TCP
name: http
- port: 8000
targetPort: 8000
protocol: TCP
name: edge
selector:
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
---
# Source: portainer/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: portainer
namespace: default
labels:
io.portainer.kubernetes.application.stack: portainer
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
app.kubernetes.io/version: "2.0.0"
spec:
replicas: 1
strategy:
type: "Recreate"
selector:
matchLabels:
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
template:
metadata:
labels:
app.kubernetes.io/name: portainer
app.kubernetes.io/instance: portainer
spec:
serviceAccountName: portainer-sa-clusteradmin
volumes:
- name: "portainer-data"
hostPath:
path: /mnt/data/portainer
type: Directory
containers:
- name: portainer
image: "portainer/portainer-ee:2.0.0"
imagePullPolicy: IfNotPresent
volumeMounts:
- name: portainer-data
mountPath: /data
ports:
- name: http
containerPort: 9000
protocol: TCP
- name: tcp-edge
containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
path: /
port: 9000
readinessProbe:
httpGet:
path: /
port: 9000
resources:
{}
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: portainer-front-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(`portainer.yourdomain.com`)
kind: Rule
services:
- name: portainer
port: 9000
tls:
certResolver: myresolver
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: portainer-edge-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(`edge.portainer.yourdomain.com`)
kind: Rule
services:
- name: portainer
port: 8000
tls:
certResolver: myresolver
Despleguemos...
Una vez que tenemos el YAML modificado a nuestro parecer, ejecutaremos:
$ kubectl apply -f portainer-lb-ee.yml
El resultado deberá parecerse a esto:
serviceaccount/portainer-sa-clusteradmin created
clusterrolebinding.rbac.authorization.k8s.io/portainer created
service/portainer created
deployment.apps/portainer created
ingressroute.traefik.containo.us/portainer-front-tls created
ingressroute.traefik.containo.us/portainer-edge-tls created
Esperamos un minuto a que descargue la imagen y Kubernetes haga toda su magia. Podemos comprobar si ya nuestro Pod está corriendo...
$ kubectl get pods
La terminal nos debería devolver algo como esto:
Todo parece estar bien, procedamos a terminar de configurar Portainer. Para eso, abrimos el navegador y vamos a la URL que especificamos en nuestro YML.
Configurando Portainer
La primer imágen es conocidos por todos, es donde definimos usuario y contraseña. Algo que me gusta hacer es cambiar el nombre de usuario del administrador, en vez de que diga se llame "admin", que tenga mi nombre u otro random.
Lo siguiente es especificar la licencia, la misma se compra en el sitio de Portainer y se licencia por cantidad de nodos, lo interesante es que el precio baja mientras más nodos tengamos.
Lo siguiente para hacer es seleccionar nuestro Endpoint, como en nuestro caso lo estamos corriendo en Kubernetes, esa será nuestra elección:
Hacemos un clic en "Connect" y veremos una pantalla de configuración, donde podremos definir si queremos que nuestros usuarios use el namespace "default" o no, si habilitaremos cuotas, si permitiremos que hagan overcommit, si vas a permitir a usuarios usen balanceadores externos, si quieres definir un controlador de Ingress y otras opciones como el uso de Storage:
Una vez que tenemos todo definido, hacemos un click en "Save Configuration" y veremos a Portainer listo para comenzar a trabajar:
Para ir cerrando
Como ves, no es para nada complicado y Portainer es una excelente opción si vos o tus usuarios no son muy amigos de archivos YML, pero por sobre todo, queres tener cierto control sobre lo que despliegan tus usuarios, en donde y como.
El archivo YML, lo dejo en este Github, en donde estoy armando un Cookbook para tener todo bien ordenado y listo para cuando yo u otras personas que lo encuentren lo necesiten:
Si todo fue bien, comparte este artículo, si algo salió mal, deja un comentario aquí abajo.