Estou executando o K3S Kubernetes em um servidor de cluster que consiste em uma mistura de nós Raspberry 4 e Raspberry 5.
Quero instalar o aplicativo de rede Unifi no servidor de cluster e progredi bastante na configuração junto com MetalLB
o Longhorn
Ansible Cert-Manager
.
Estou usando a imagem Docker do linuxserver.io para meu servidor de cluster e é necessário instalar um pod separado contendo MongoDB
.
Pesquisando on-line sobre como instalar o MongoDB me deu o seguinte arquivo Ansible:
- name: Generate MongoDB secrets
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
namespace: default
type: Opaque
data:
password: VmVyeVNlY3JldFBhc3NvcmQ= # "VerySecretPassword" encoded in Base64
- name: Create Unifi DB init script
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-init-script
namespace: default
data:
init-script.js: |-
db.getSiblingDB("unifi-db").createUser({user: "unifi", pwd: "unifi", roles: [{role: "dbOwner", db: "unifi-db"}]});
db.getSiblingDB("unifi-db_stat").createUser({user: "unifi", pwd: "unifi", roles: [{role: "dbOwner", db: "unifi-db_stat"}]});
- name: Create MongoDB service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: mongodb-svc
namespace: default
labels:
app: mongodb
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 27017
targetPort: 27017
selector:
app: mongodb
- name: Create MongoDB statefull set
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
namespace: default
labels:
app: mongodb
spec:
serviceName: mongodb-svc
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo:4.4.18 # Do NOT set it to 'latest'. I'll explain below.
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
value: admin
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: password
volumeMounts:
- name: mongodb-data
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: mongodb-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
- name: Initialize MongoDB
kubernetes.core.k8s:
state: present
definition:
apiVersion: batch/v1
kind: Job
metadata:
name: mongodb-init-job
namespace: default
spec:
template:
metadata:
name: mongodb-init-pod
spec:
restartPolicy: OnFailure
containers:
- name: mongodb-init-container
image: mongo:4.4.18 # Again: Do NOT set it to 'latest'.
command: [ "mongo", "--host", "mongodb-0.mongodb-svc.default.svc.cluster.local", "--authenticationDatabase", "admin", "--username", "admin", "--password", "$(MONGO_INITDB_ROOT_PASSWORD)", "/mongo-init-script/init-script.js" ]
env:
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: password
volumeMounts:
- name: mongo-init-script
mountPath: /mongo-init-script
volumes:
- name: mongo-init-script
configMap:
name: mongodb-init-script
A seção funciona bem.
A saída de kubectl logs mongodb-init-job-f5f54
é a seguinte:
MongoDB shell version v4.4.18
connecting to: mongodb://mongodb-0.mongodb-svc.default.svc.cluster.local:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("39ad2f51-07a9-4e67-8c5b-68f6fff92872") }
MongoDB server version: 4.4.18
Successfully added user: {
"user" : "unifi",
"roles" : [
{
"role" : "dbOwner",
"db" : "unifi-db"
}
]
}
Successfully added user: {
"user" : "unifi",
"roles" : [
{
"role" : "dbOwner",
"db" : "unifi-db_stat"
}
]
}
O que significa que eu poderia fazer login admin
e criar um usuário MongoDB chamado unifi
com senha unifi
que tenha acesso ao banco de dados unifi-db
.
Também sei que é acessível via DNS configurando o host do banco de dados para mongodb-0.mongodb-svc.default.svc.cluster.local
usar port 27017
.
A razão pela qual escolhi instalar a versão 4.4.18 do MongoDB é porque embora o Unifi Network Application suporte até a versão 7.0, não é o mesmo caso do suporte do MongoDB para as placas Raspberry Pi.
O MongoDB só pode ser executado até a versão 4.4.18 no Raspberry Pi.
O próximo passo é fazer com que o aplicativo de rede Unifi seja executado em meu servidor de cluster.
Estou usando as seguintes tarefas para fazer isso:
---
- name: Define storage space for Unifi
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: unifi-cluster-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 5Gi
- name: Add unifi deployment
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: unifi
namespace: default
labels:
app: unifi
spec:
replicas: 1
selector:
matchLabels:
app: unifi
template:
metadata:
labels:
app: unifi
spec:
volumes:
- name: unifi-config
persistentVolumeClaim:
claimName: unifi-cluster-pvc
containers:
- name: unifi
image: lscr.io/linuxserver/unifi-network-application:latest
ports:
- containerPort: 3478
protocol: UDP
- containerPort: 10001
protocol: UDP
- containerPort: 5514
protocol: UDP
- containerPort: 8080
- containerPort: 8443
- containerPort: 8843
- containerPort: 8880
- containerPort: 6789
volumeMounts:
- name: unifi-config
mountPath: /config
env:
- name: PUID
value: "1000"
- name: GUID
value: "1000"
- name: MONGO_USER
value: "unifi"
- name: MONGO_PASS
value: "unifi"
- name: MONGO_HOST
value: "mongodb-0.mongodb-svc.default.svc.cluster.local"
- name: MONGO_PORT
value: "27017"
- name: MONGO_DBNAME
value: "unifi-db"
- name: MONGO_TLS
value: "false"
- name: Define unifi service ports
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: unifi
namespace: default
spec:
type: LoadBalancer
selector:
app: unifi
ports:
- name: "8080"
port: 8080
targetPort: 8080
- name: "8443"
port: 8443
targetPort: 8443
- name: "8843"
port: 8843
targetPort: 8843
- name: "8880"
port: 8880
targetPort: 8880
- name: "6789"
port: 6789
targetPort: 6789
- name: "3478"
port: 3478
protocol: UDP
targetPort: 3478
- name: "10001"
port: 10001
protocol: UDP
targetPort: 10001
- name: "5514"
port: 5514
protocol: UDP
targetPort: 5514
- name: Add unifi ingress
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: unifi
namespace: default
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
cert-manager.io/cluster-issuer: letsencrypt-staging
cert-manager.io/acme-challenge-type: dns01
spec:
ingressClassName: nginx
tls:
- hosts:
- unifi.example.com
secretName: unifi-tls
rules:
- host: 'unifi.example.com'
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: unifi
port:
number: 8443
A execução do comando kubectl get pods
me dá a seguinte saída:
NAME READY STATUS RESTARTS AGE
mongodb-0 1/1 Running 0 64m
unifi-5dcdbfb6d9-8wbbp 1/1 Running 0 64m
mongodb-init-job-f5f54 0/1 Completed 2 64m
E posso fazer login no unifi-db
banco de dados com o comando:kubectl exec mongodb-0 -it -- mongo -u unifi -p unifi unifi-db
O comando:show collections
Dá-me, entre outros, o seguinte:
account
admin
alarm
crashlog
dashboard
device
...
Até agora tudo bem.
No entanto, não consigo colocar o site do aplicativo de rede Unifi em funcionamento.
A saída do comando kubectl log unifi-5dcdbfb6d9-8wbbp
fornece, entre outras, esta mensagem:
Error creating bean with name 'statDbService'
defined in com.ubnt.service.DatabaseSpringContext:
Command failed with error 13 (Unauthorized): 'not
authorized on unifi-db_stat to execute command {
listCollections: 1, cursor: {}, nameOnly: true, $db:
"unifi-db_stat", lsid: { id: UUID("99b4d07f-b3f3-49c9-9979-dbdd27445881")
} }' on server mongodb-0.mongodb-svc.default.svc.cluster.local:27017.
The full response is {"ok": 0.0, "errmsg": "not authorized on unifi-db_stat
to execute command { listCollections: 1, cursor: {}, nameOnly: true, $db:
\"unifi-db_stat\", lsid: { id: UUID(\"99b4d07f-b3f3-49c9-9979-dbdd27445881\")
} }", "code": 13, "codeName": "Unauthorized"}
Como posso resolver esse problema?
Lendo a documentação sobre como funciona a atribuição de funções no MongoDB, posso ler que definir a função de um usuário como dbOwner
é basicamente uma passagem de acesso total, pois combina as funções de readWrite
e dbAdmin
em userAdmin
uma função.
Uma das permissões que você obtém é listCollections
a , referenciada no código de erro acima.
Então, o que está acontecendo?
Hmm... Parece ser um problema conhecido.
Pesquisar mais online me fez tropeçar neste comentário no GitHub
Então, em vez de ter um script de inicialização parecido com este:
Em vez disso, deveria ser assim:
Estou longe de uma exportação no MongoDB, então não sei onde está a sutileza entre os dois javascripts.
Minha
ConfigMap
chamada modificadamongodb-init-script
agora fica assim:E depois de fazer uma redefinição completa do meu servidor de cluster e executar meu manual novamente, consegui ver a página do aplicativo de rede Unifi em meu navegador. :-)