This commit is contained in:
commit
7c5cad55e1
10
.drone.yml
Normal file
10
.drone.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: gitleaks
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: gitleaks
|
||||||
|
image: zricethezav/gitleaks
|
||||||
|
commands:
|
||||||
|
- gitleaks detect --source=/drone/src
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*secrets.yml
|
||||||
|
*secret.yml
|
||||||
|
*.swp
|
||||||
|
*.save
|
||||||
|
*.1
|
12
CONTRIBUTORS.md
Normal file
12
CONTRIBUTORS.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Kubernetes cluster configuration contributors
|
||||||
|
|
||||||
|
Following people have helped one or the other way making
|
||||||
|
this Git repository happen:
|
||||||
|
|
||||||
|
* Lauri Võsandi <lauri@k-space.ee>
|
||||||
|
* Madis Mägi <madis@k-space.ee>
|
||||||
|
* Marvin Martinson <marvin@k-space.ee>
|
||||||
|
* Nejc Povsse <nejcp@k-space.ee>
|
||||||
|
* Song Meo <songmeo@k-space.ee>
|
||||||
|
* Rasmus Kallas <rasmus@k-space.ee>
|
||||||
|
* Kristjan Kuusk <kkuusk@k-space.ee>
|
20
LICENSE.md
Normal file
20
LICENSE.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2012-2022 Lauri Võsandi and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
258
README.md
Normal file
258
README.md
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# Kubernetes cluster manifests
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This is the Kubernetes manifests of services running on k-space.ee domains:
|
||||||
|
|
||||||
|
- [Authelia](https://auth.k-space.ee) for authentication
|
||||||
|
- [Drone.io](https://drone.k-space.ee) for building Docker images
|
||||||
|
- [Harbor](https://harbor.k-space.ee) for hosting Docker images
|
||||||
|
- [ArgoCD](https://argocd.k-space.ee) for deploying Kubernetes manifests and
|
||||||
|
Helm charts into the cluster
|
||||||
|
- [camtiler](https://cams.k-space.ee) for cameras
|
||||||
|
- [Longhorn Dashboard](https://longhorn.k-space.ee) for administering
|
||||||
|
Longhorn storage
|
||||||
|
- [Kubernetes Dashboard](https://kubernetes-dashboard.k-space.ee/) for read-only overview
|
||||||
|
of the Kubernetes cluster
|
||||||
|
- [Wildduck Webmail](https://webmail.k-space.ee/)
|
||||||
|
|
||||||
|
Most endpoints are protected by OIDC autentication or Authelia SSO middleware.
|
||||||
|
|
||||||
|
|
||||||
|
## Cluster access
|
||||||
|
|
||||||
|
General discussion is happening in the `#kube` Slack channel.
|
||||||
|
|
||||||
|
For bootstrap access obtain `/etc/kubernetes/admin.conf` from one of the master
|
||||||
|
nodes and place it under `~/.kube/config` on your machine.
|
||||||
|
|
||||||
|
Once Authelia is working, OIDC access for others can be enabled with
|
||||||
|
running following on Kubernetes masters:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
patch /etc/kubernetes/manifests/kube-apiserver.yaml - << EOF
|
||||||
|
@@ -23,6 +23,10 @@
|
||||||
|
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
|
||||||
|
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
|
||||||
|
- --etcd-servers=https://127.0.0.1:2379
|
||||||
|
+ - --oidc-issuer-url=https://auth.k-space.ee
|
||||||
|
+ - --oidc-client-id=kubelogin
|
||||||
|
+ - --oidc-username-claim=preferred_username
|
||||||
|
+ - --oidc-groups-claim=groups
|
||||||
|
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
|
||||||
|
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
|
||||||
|
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||||
|
EOF
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
systemctl restart kubelet
|
||||||
|
```
|
||||||
|
|
||||||
|
Afterwards following can be used to talk to the Kubernetes cluster using
|
||||||
|
OIDC credentials:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl krew install oidc-login
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
cat << EOF > ~/.kube/config
|
||||||
|
apiVersion: v1
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EVXdNakEzTXpVMU1Wb1hEVE15TURReU9UQTNNelUxTVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS2J2CjY3UFlXVHJMc3ZCQTZuWHUvcm55SlVhNnppTnNWTVN6N2w4ekhxM2JuQnhqWVNPUDJhN1RXTnpUTmZDanZBWngKTmlNbXJya1hpb2dYQWpVVkhSUWZlYm81TFIrb0JBOTdLWlcrN01UMFVJRXBuWVVaaTdBRHlaS01vcEJFUXlMNwp1SlU5UDhnNUR1T29FRHZieGJSMXFuV1JZRXpteFNmSFpocllpMVA3bFd4emkxR243eGRETFZaMjZjNm0xR3Y1CnViRjZyaFBXK1JSVkhiQzFKakJGeTBwRXdhYlUvUTd0Z2dic0JQUjk5NVZvMktCeElBelRmbHhVanlYVkJ3MjEKU2d3ZGI1amlpemxEM0NSbVdZZ0ZrRzd0NTVZeGF3ZmpaQjh5bW4xYjhUVjkwN3dRcG8veU8zM3RaaEE3L3BFUwpBSDJYeDk5bkpMbFVGVUtSY1A4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZKNnZKeVk1UlJ1aklQWGxIK2ZvU3g2QzFRT2RNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQ04zcGtCTVM3ekkrbUhvOWdTZQp6SzdXdjl3bXlCTVE5Q3crQXBSNnRBQXg2T1VIN0d1enc5TTV2bXNkYjkrYXBKMHBlZFB4SUg3YXZ1aG9SUXNMCkxqTzRSVm9BMG9aNDBZV3J3UStBR0dvdkZuaWNleXRNcFVSNEZjRXc0ZDRmcGl6V3d0TVNlRlRIUXR6WG84V2MKNFJGWC9xUXNVR1NWa01PaUcvcVVrSFpXQVgyckdhWXZ1Tkw2eHdSRnh5ZHpsRTFSUk56TkNvQzVpTXhjaVRNagpackEvK0pqVEFWU2FuNXZnODFOSmthZEphbmNPWmEwS3JEdkZzd1JJSG5CMGpMLzh3VmZXSTV6czZURU1VZUk1ClF6dU01QXUxUFZ4VXZJUGhlMHl6UXZjWDV5RlhnMkJGU3MzKzJBajlNcENWVTZNY2dSSTl5TTRicitFTUlHL0kKY0pjPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||||
|
server: https://master.kube.k-space.ee:6443
|
||||||
|
name: kubernetes
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: kubernetes
|
||||||
|
user: oidc
|
||||||
|
name: default
|
||||||
|
current-context: default
|
||||||
|
kind: Config
|
||||||
|
preferences: {}
|
||||||
|
users:
|
||||||
|
- name: oidc
|
||||||
|
user:
|
||||||
|
exec:
|
||||||
|
apiVersion: client.authentication.k8s.io/v1beta1
|
||||||
|
args:
|
||||||
|
- oidc-login
|
||||||
|
- get-token
|
||||||
|
- --oidc-issuer-url=https://auth.k-space.ee
|
||||||
|
- --oidc-client-id=kubelogin
|
||||||
|
- --oidc-use-pkce
|
||||||
|
- --oidc-extra-scope=profile,email,groups
|
||||||
|
- --listen-address=127.0.0.1:27890
|
||||||
|
command: kubectl
|
||||||
|
env: null
|
||||||
|
provideClusterInfo: false
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
For access control mapping see [cluster-role-bindings.yml](cluster-role-bindings.yml)
|
||||||
|
|
||||||
|
|
||||||
|
# Technology mapping
|
||||||
|
|
||||||
|
Our self-hosted Kubernetes stack compared to AWS based deployments:
|
||||||
|
|
||||||
|
| Hipster startup | Self-hosted hackerspace | Purpose |
|
||||||
|
|-----------------|-------------------------------------|---------------------------------------------------------------------|
|
||||||
|
| AWS EC2 | Proxmox | Virtualization layer |
|
||||||
|
| AWS EKS | kubeadm | Provision Kubernetes master nodes |
|
||||||
|
| AWS EBS | Longhorn | Block storage for arbitrary applications needing persistent storage |
|
||||||
|
| AWS NLB | MetalLB | L2/L3 level load balancing |
|
||||||
|
| AWS ALB | Traefik | Reverse proxy also known as ingress controller in Kubernetes jargon |
|
||||||
|
| AWS ECR | Harbor | Docker registry |
|
||||||
|
| AWS DocumentDB | MongoDB | NoSQL database |
|
||||||
|
| AWS S3 | Minio | Object storage |
|
||||||
|
| GitHub OAuth2 | Samba (Active Directory compatible) | Source of truth for authentication and authorization |
|
||||||
|
| Dex | Authelia | ACL mapping and OIDC provider which integrates with GitHub/Samba |
|
||||||
|
| GitHub | Gitea | Source code management, issue tracking |
|
||||||
|
| GitHub Actions | Drone | Build Docker images |
|
||||||
|
| Gmail | Wildduck | E-mail |
|
||||||
|
| AWS Route53 | Bind and RFC2136 | DNS records and Let's Encrypt DNS validation |
|
||||||
|
| AWS VPC | Calico | Overlay network |
|
||||||
|
|
||||||
|
|
||||||
|
External dependencies running as classic virtual machines:
|
||||||
|
|
||||||
|
- Samba as Authelia's source of truth
|
||||||
|
- Bind as DNS server
|
||||||
|
|
||||||
|
|
||||||
|
## Adding applications
|
||||||
|
|
||||||
|
Deploy applications via [ArgoCD](https://argocd.k-space.ee)
|
||||||
|
|
||||||
|
We use Treafik with Authelia for Ingress.
|
||||||
|
Applications where possible and where applicable should use `Remote-User`
|
||||||
|
authentication. This prevents application exposure on public Internet.
|
||||||
|
Otherwise use OpenID Connect for authentication,
|
||||||
|
see Argo itself as an example how that is done.
|
||||||
|
|
||||||
|
See `kspace-camtiler/ingress.yml` for commented Ingress example.
|
||||||
|
|
||||||
|
Note that we do not use IngressRoute objects because they don't
|
||||||
|
support `external-dns` out of the box.
|
||||||
|
Do NOT add nginx annotations, we use Traefik.
|
||||||
|
Do NOT manually add DNS records, they are added by `external-dns`.
|
||||||
|
Do NOT manually create Certificate objects,
|
||||||
|
these should be handled by `tls:` section in Ingress.
|
||||||
|
|
||||||
|
|
||||||
|
## Cluster formation
|
||||||
|
|
||||||
|
Create Ubuntu 20.04 VM-s on Proxmox with local storage.
|
||||||
|
|
||||||
|
After machines have booted up and you can reach them via SSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable required kernel modules
|
||||||
|
cat > /etc/modules << EOF
|
||||||
|
overlay
|
||||||
|
br_netfilter
|
||||||
|
EOF
|
||||||
|
cat /etc/modules | xargs -L 1 -t modprobe
|
||||||
|
|
||||||
|
# Finetune sysctl:
|
||||||
|
cat > /etc/sysctl.d/99-k8s.conf << EOF
|
||||||
|
net.ipv4.conf.all.accept_redirects = 0
|
||||||
|
net.bridge.bridge-nf-call-iptables = 1
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
net.bridge.bridge-nf-call-ip6tables = 1
|
||||||
|
EOF
|
||||||
|
sysctl --system
|
||||||
|
|
||||||
|
# Disable Ubuntu caching DNS resolver
|
||||||
|
systemctl disable systemd-resolved.service
|
||||||
|
systemctl stop systemd-resolved
|
||||||
|
rm -fv /etc/resolv.conf
|
||||||
|
cat > /etc/resolv.conf << EOF
|
||||||
|
nameserver 1.1.1.1
|
||||||
|
nameserver 8.8.8.8
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Disable multipathd as Longhorn handles that itself
|
||||||
|
systemctl mask multipathd
|
||||||
|
systemctl disable multipathd
|
||||||
|
systemctl stop multipathd
|
||||||
|
|
||||||
|
# Disable Snapcraft
|
||||||
|
systemctl mask snapd
|
||||||
|
systemctl disable snapd
|
||||||
|
systemctl stop snapd
|
||||||
|
|
||||||
|
# Permit root login
|
||||||
|
sed -i -e 's/PermitRootLogin no/PermitRootLogin without-password/' /etc/ssh/sshd_config
|
||||||
|
systemctl reload ssh
|
||||||
|
cat << EOF > /root/.ssh/authorized_keys
|
||||||
|
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBD4/e9SWYWYoNZMkkF+NirhbmHuUgjoCap42kAq0pLIXFwIqgVTCre03VPoChIwBClc8RspLKqr5W3j0fG8QwnQAAAAEc3NoOg== lauri@lauri-x13
|
||||||
|
EOF
|
||||||
|
userdel -f ubuntu
|
||||||
|
apt-get remove -yq cloud-init
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Install packages, for Raspbian set `OS=Debian_11`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OS=xUbuntu_20.04
|
||||||
|
VERSION=1.23
|
||||||
|
cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
|
||||||
|
deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /
|
||||||
|
EOF
|
||||||
|
cat <<EOF | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
|
||||||
|
deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /
|
||||||
|
EOF
|
||||||
|
|
||||||
|
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -
|
||||||
|
curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | sudo apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers-cri-o.gpg add -
|
||||||
|
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
|
||||||
|
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -yqq apt-transport-https curl cri-o cri-o-runc kubelet=1.23.5-00 kubectl=1.23.5-00 kubeadm=1.23.5-00
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable crio --now
|
||||||
|
apt-mark hold kubelet kubeadm kubectl
|
||||||
|
sed -i -e 's/unqualified-search-registries = .*/unqualified-search-registries = ["docker.io"]/' /etc/containers/registries.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
On master:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubeadm init --token-ttl=120m --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint "master.kube.k-space.ee:6443" --upload-certs --apiserver-cert-extra-sans master.kube.k-space.ee --node-name master1.kube.k-space.ee
|
||||||
|
```
|
||||||
|
|
||||||
|
For the `kubeadm join` command specify FQDN via `--node-name $(hostname -f)`.
|
||||||
|
|
||||||
|
After forming the cluster add taints:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for j in $(seq 1 9); do
|
||||||
|
kubectl label nodes worker${j}.kube.k-space.ee node-role.kubernetes.io/worker=''
|
||||||
|
done
|
||||||
|
|
||||||
|
for j in $(seq 1 3); do
|
||||||
|
kubectl taint nodes mon${j}.kube.k-space.ee dedicated=monitoring:NoSchedule
|
||||||
|
kubectl label nodes mon${j}.kube.k-space.ee dedicated=monitoring
|
||||||
|
done
|
||||||
|
|
||||||
|
for j in $(seq 1 4); do
|
||||||
|
kubectl taint nodes storage${j}.kube.k-space.ee dedicated=storage:NoSchedule
|
||||||
|
kubectl label nodes storage${j}.kube.k-space.ee dedicated=storage
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
On Raspberry Pi you need to take additonal steps:
|
||||||
|
|
||||||
|
* Manually enable cgroups by appending
|
||||||
|
`cgroup_memory=1 cgroup_enable=memory` to `/boot/cmdline.txt`,
|
||||||
|
* Disable swap with `swapoff -a; apt-get purge -y dphys-swapfile`
|
||||||
|
* For mounting Longhorn volumes on Rasbian install `open-iscsi`
|
||||||
|
|
||||||
|
For `arm64` nodes add suitable taint to prevent scheduling non-multiarch images on them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl taint nodes worker9.kube.k-space.ee arch=arm64:NoSchedule
|
||||||
|
```
|
4
argocd/.gitignore
vendored
Normal file
4
argocd/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
argocd.yml
|
||||||
|
repo-credentials.yml
|
||||||
|
id_*
|
||||||
|
ssh_known_hosts
|
59
argocd/README.md
Normal file
59
argocd/README.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Workflow
|
||||||
|
|
||||||
|
Most applications in our Kubernetes cluster are managed by ArgoCD.
|
||||||
|
|
||||||
|
|
||||||
|
# Deployment
|
||||||
|
|
||||||
|
To deploy ArgoCD:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add argo-cd https://argoproj.github.io/argo-helm
|
||||||
|
kubectl create secret -n argocd generic argocd-secret # Initialize empty secret for sessions
|
||||||
|
helm template -n argocd --release-name k6 argo-cd/argo-cd --include-crds -f values.yaml > argocd.yml
|
||||||
|
kubectl apply -f argocd.yml -n argocd
|
||||||
|
kubectl -n argocd rollout restart deployment/k6-argocd-redis
|
||||||
|
kubectl -n argocd rollout restart deployment/k6-argocd-repo-server
|
||||||
|
kubectl -n argocd rollout restart deployment/k6-argocd-server
|
||||||
|
kubectl -n argocd rollout restart deployment/k6-argocd-notifications-controller
|
||||||
|
kubectl -n argocd rollout restart statefulset/k6-argocd-application-controller
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Refer to Authelia README for OIDC secret setup
|
||||||
|
|
||||||
|
|
||||||
|
# Setting up Git secrets
|
||||||
|
|
||||||
|
Generate SSH key to access Gitea:
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh-keygen -t ecdsa -f id_ecdsa -C argocd.k-space.ee -P ''
|
||||||
|
kubectl -n argocd create secret generic gitea-kube \
|
||||||
|
--from-literal=type=git \
|
||||||
|
--from-literal=url=git@git.k-space.ee:k-space/kube \
|
||||||
|
--from-file=sshPrivateKey=id_ecdsa
|
||||||
|
kubectl -n argocd create secret generic gitea-kube-staging \
|
||||||
|
--from-literal=type=git \
|
||||||
|
--from-literal=url=git@git.k-space.ee:k-space/kube-staging \
|
||||||
|
--from-file=sshPrivateKey=id_ecdsa
|
||||||
|
kubectl label -n argocd secret gitea-kube argocd.argoproj.io/secret-type=repository
|
||||||
|
kubectl label -n argocd secret gitea-kube-staging argocd.argoproj.io/secret-type=repository
|
||||||
|
rm -fv id_ecdsa
|
||||||
|
```
|
||||||
|
|
||||||
|
Have Gitea admin reset password for user `argocd` and log in with that account.
|
||||||
|
Add the SSH key for user `argocd` from file `id_ecdsa.pub`.
|
||||||
|
Delete any other SSH keys associated with Gitea user `argocd`.
|
||||||
|
|
||||||
|
|
||||||
|
# Adding applications
|
||||||
|
|
||||||
|
To add application make sure it's manifest is placed as `application.yml` in
|
||||||
|
the relevant namespace:
|
||||||
|
|
||||||
|
```
|
||||||
|
./update.sh
|
||||||
|
kubectl apply -n argocd -f applications --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not manually add manifests under `applications/`
|
17
argocd/application.tpl
Normal file
17
argocd/application.tpl
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: foobar
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: foobar
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: foobar
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/authelia.yml
Normal file
17
argocd/applications/authelia.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: authelia
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: authelia
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: authelia
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/camtiler.yml
Normal file
17
argocd/applications/camtiler.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: camtiler
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: camtiler
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/drone-execution.yml
Normal file
17
argocd/applications/drone-execution.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: drone-execution
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: drone-execution
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: drone-execution
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/drone.yml
Normal file
17
argocd/applications/drone.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: drone
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: drone
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: drone
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/etherpad.yml
Normal file
17
argocd/applications/etherpad.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: etherpad
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: etherpad
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: etherpad
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/external-dns.yml
Normal file
17
argocd/applications/external-dns.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: external-dns
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: external-dns
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: external-dns
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/harbor.yml
Normal file
17
argocd/applications/harbor.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: harbor
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: harbor
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: harbor
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/keel.yml
Normal file
17
argocd/applications/keel.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: keel
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: keel
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/kubernetes-dashboard.yml
Normal file
17
argocd/applications/kubernetes-dashboard.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: kubernetes-dashboard
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/logging.yml
Normal file
17
argocd/applications/logging.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: logging
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: logging
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: logging
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/metallb-system.yml
Normal file
17
argocd/applications/metallb-system.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: metallb-system
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: metallb-system
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: metallb-system
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/monitoring.yml
Normal file
17
argocd/applications/monitoring.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: monitoring
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: monitoring
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: monitoring
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/mysql-operator.yml
Normal file
17
argocd/applications/mysql-operator.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: mysql-operator
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: mysql-operator
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/phpmyadmin.yml
Normal file
17
argocd/applications/phpmyadmin.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: phpmyadmin
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: phpmyadmin
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: phpmyadmin
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/reloader.yml
Normal file
17
argocd/applications/reloader.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: reloader
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: reloader
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: reloader
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/rosdump.yml
Normal file
17
argocd/applications/rosdump.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: rosdump
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: rosdump
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: rosdump
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
17
argocd/applications/wildduck.yml
Normal file
17
argocd/applications/wildduck.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: wildduck
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'git@git.k-space.ee:k-space/kube.git'
|
||||||
|
path: wildduck
|
||||||
|
targetRevision: HEAD
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: wildduck
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
9
argocd/update.sh
Executable file
9
argocd/update.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
path=$(dirname $(dirname $(realpath $0)))
|
||||||
|
for j in $path/*/application.yml; do
|
||||||
|
app=$(dirname $j)
|
||||||
|
test -f "$app/values.yml" && continue
|
||||||
|
test -f "$app/values.yaml" && continue
|
||||||
|
appname=$(basename $app)
|
||||||
|
cat application.tpl | sed -e "s/foobar/$appname/g" > applications/$appname.yml
|
||||||
|
done
|
122
argocd/values.yaml
Normal file
122
argocd/values.yaml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
global:
|
||||||
|
logLevel: warn
|
||||||
|
|
||||||
|
# We use Authelia OIDC instead of Dex
|
||||||
|
dex:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Maybe one day switch to Redis HA?
|
||||||
|
redis-ha:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
# HTTPS is implemented by Traefik
|
||||||
|
extraArgs:
|
||||||
|
- --insecure
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- argocd.k-space.ee
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- argocd.k-space.ee
|
||||||
|
secretName: argocd-server-tls
|
||||||
|
configEnabled: true
|
||||||
|
config:
|
||||||
|
admin.enabled: "false"
|
||||||
|
url: https://argocd.k-space.ee
|
||||||
|
application.instanceLabelKey: argocd.argoproj.io/instance
|
||||||
|
oidc.config: |
|
||||||
|
name: Authelia
|
||||||
|
issuer: https://auth.k-space.ee
|
||||||
|
clientID: argocd
|
||||||
|
cliClientID: argocd
|
||||||
|
clientSecret: $oidc.config.clientSecret
|
||||||
|
requestedIDTokenClaims:
|
||||||
|
groups:
|
||||||
|
essential: true
|
||||||
|
requestedScopes:
|
||||||
|
- openid
|
||||||
|
- profile
|
||||||
|
- email
|
||||||
|
- groups
|
||||||
|
resource.customizations: |
|
||||||
|
# https://github.com/argoproj/argo-cd/issues/1704
|
||||||
|
networking.k8s.io/Ingress:
|
||||||
|
health.lua: |
|
||||||
|
hs = {}
|
||||||
|
hs.status = "Healthy"
|
||||||
|
return hs
|
||||||
|
|
||||||
|
# Members of ArgoCD Admins group in AD/Samba are allowed to administer Argo
|
||||||
|
rbacConfig:
|
||||||
|
policy.default: role:readonly
|
||||||
|
policy.csv: |
|
||||||
|
# Map AD groups to ArgoCD roles
|
||||||
|
g, Developers, role:developers
|
||||||
|
g, ArgoCD Admins, role:admin
|
||||||
|
# Allow developers to read objects
|
||||||
|
p, role:developers, applications, get, */*, allow
|
||||||
|
p, role:developers, certificates, get, *, allow
|
||||||
|
p, role:developers, clusters, get, *, allow
|
||||||
|
p, role:developers, repositories, get, *, allow
|
||||||
|
p, role:developers, projects, get, *, allow
|
||||||
|
p, role:developers, accounts, get, *, allow
|
||||||
|
p, role:developers, gpgkeys, get, *, allow
|
||||||
|
p, role:developers, logs, get, */*, allow
|
||||||
|
p, role:developers, applications, restart, default/camtiler, allow
|
||||||
|
p, role:developers, applications, override, default/camtiler, allow
|
||||||
|
p, role:developers, applications, action/apps/Deployment/restart, default/camtiler, allow
|
||||||
|
p, role:developers, applications, sync, default/camtiler, allow
|
||||||
|
p, role:developers, applications, update, default/camtiler, allow
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "8083"
|
||||||
|
|
||||||
|
# We don't use ApplicationSet CRD-s (yet)
|
||||||
|
applicationSet:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
repoServer:
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "8084"
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "9001"
|
||||||
|
|
||||||
|
controller:
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "8082"
|
||||||
|
|
||||||
|
configs:
|
||||||
|
secret:
|
||||||
|
createSecret: false
|
||||||
|
knownHosts:
|
||||||
|
data:
|
||||||
|
ssh_known_hosts: |
|
||||||
|
# Copy-pasted from `ssh-keyscan git.k-space.ee`
|
||||||
|
git.k-space.ee ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCF1+/TDRXuGwsu4SZQQwQuJusb7W1OciGAQp/ZbTTvKD+0p7fV6dXyUlWjdFmITrFNYDreDnMiOS+FvE62d2Z0=
|
||||||
|
git.k-space.ee ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsLyRuubdIUnTKEqOipu+9x+FforrC8+oxulVrl0ECgdIRBQnLQXIspTNwuC3MKJ4z+DPbndSt8zdN33xWys8UNEs3V5/W6zsaW20tKiaX75WK5eOL4lIDJi/+E97+c0aZBXamhxTrgkRVJ5fcAkY6C5cKEmVM5tlke3v3ihLq78/LpJYv+P947NdnthYE2oc+XGp/elZ0LNfWRPnd///+ykbwWirvQm+iiDz7PMVKkb+Q7l3vw4+zneKJWAyFNrm+aewyJV9lFZZJuHliwlHGTriSf6zhMAWyJzvYqDAN6iT5yi9KGKw60J6vj2GLuK4ULVblTyP9k9+3iELKSWW5
|
||||||
|
git.k-space.ee ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL1jaIn/5dZcqN+cwcs/c2xMVJH/ReA84v8Mm73jqDAG
|
2
authelia/.gitignore
vendored
Normal file
2
authelia/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
application-secrets.y*ml
|
||||||
|
oidc-secrets.y*ml
|
173
authelia/README.md
Normal file
173
authelia/README.md
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
# Authelia
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Authelia works in conjunction with Traefik to provide SSO with
|
||||||
|
credentials stored in Samba (Active Directory compatible) directory tree.
|
||||||
|
|
||||||
|
Samba resides outside Kubernetes cluster as it's difficuilt to containerize
|
||||||
|
while keeping it usable from outside the cluster due to Samba's networking.
|
||||||
|
|
||||||
|
The MariaDB instance is used to store MFA tokens.
|
||||||
|
Redis is used to store session info.
|
||||||
|
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Inspect changes with `git diff` and proceed to deploy:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n authelia -f application.yml -f keydb.yml -f mariadb.yml
|
||||||
|
kubectl create secret generic -n authelia mysql-secrets \
|
||||||
|
--from-literal=rootPassword=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
kubectl create secret generic -n authelia mariadb-secrets \
|
||||||
|
--from-literal=MYSQL_ROOT_PASSWORD=$(cat /dev/urandom | base64 | head -c 30) \
|
||||||
|
--from-literal=MYSQL_PASSWORD=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
kubectl create secret generic -n authelia redis-secrets \
|
||||||
|
--from-literal=REDIS_PASSWORD=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
kubectl -n authelia rollout restart deployment/authelia
|
||||||
|
```
|
||||||
|
|
||||||
|
To change secrets create `secret.yml`:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
type: Opaque
|
||||||
|
metadata:
|
||||||
|
name: application-secrets
|
||||||
|
data:
|
||||||
|
JWT_TOKEN: ...
|
||||||
|
SESSION_ENCRYPTION_KEY: ...
|
||||||
|
STORAGE_PASSWORD: ...
|
||||||
|
STORAGE_ENCRYPTION_KEY: ...
|
||||||
|
LDAP_PASSWORD: ...
|
||||||
|
STORAGE_PASSWORD: ...
|
||||||
|
SMTP_PASSWORD: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply with:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n authelia -f application-secrets.yml
|
||||||
|
kubectl annotate -n authelia secret application-secrets reloader.stakater.com/match=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## OIDC secrets
|
||||||
|
|
||||||
|
OIDC secrets are separated from the main configuration until
|
||||||
|
Authelia will add CRD-s for these.
|
||||||
|
|
||||||
|
Generally speaking for untrusted applications, that is stuff that is running
|
||||||
|
outside the Kubernetes cluster eg web browser based (JS) and
|
||||||
|
local command line clients one
|
||||||
|
should use `public: true` and omit `secret: ...`.
|
||||||
|
|
||||||
|
Populate `oidc-secrets.yml` with approximately following:
|
||||||
|
|
||||||
|
```
|
||||||
|
identity_providers:
|
||||||
|
oidc:
|
||||||
|
clients:
|
||||||
|
- id: kubelogin
|
||||||
|
description: Kubernetes cluster
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: two_factor
|
||||||
|
redirect_uris:
|
||||||
|
- http://localhost:27890
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- groups
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
- id: proxmox
|
||||||
|
description: Proxmox Virtual Environment
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: two_factor
|
||||||
|
redirect_uris:
|
||||||
|
- https://pve.k-space.ee
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- groups
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
- id: argocd
|
||||||
|
description: ArgoCD
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: two_factor
|
||||||
|
redirect_uris:
|
||||||
|
- https://argocd.k-space.ee/auth/callback
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- groups
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
- id: harbor
|
||||||
|
description: Harbor
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: two_factor
|
||||||
|
redirect_uris:
|
||||||
|
- https://harbor.k-space.ee/c/oidc/callback
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- groups
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
- id: gitea
|
||||||
|
description: Gitea
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: one_factor
|
||||||
|
redirect_uris:
|
||||||
|
- https://git.k-space.ee/user/oauth2/authelia/callback
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- profile
|
||||||
|
- email
|
||||||
|
- groups
|
||||||
|
grant_types:
|
||||||
|
- refresh_token
|
||||||
|
- authorization_code
|
||||||
|
response_types:
|
||||||
|
- code
|
||||||
|
userinfo_signing_algorithm: none
|
||||||
|
- id: grafana
|
||||||
|
description: Grafana
|
||||||
|
secret: ...
|
||||||
|
authorization_policy: one_factor
|
||||||
|
redirect_uris:
|
||||||
|
- https://grafana.k-space.ee/login/generic_oauth
|
||||||
|
scopes:
|
||||||
|
- openid
|
||||||
|
- groups
|
||||||
|
- email
|
||||||
|
- profile
|
||||||
|
```
|
||||||
|
|
||||||
|
To upload the file to Kubernetes secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n authelia delete secret oidc-secrets
|
||||||
|
kubectl -n authelia create secret generic oidc-secrets \
|
||||||
|
--from-file=oidc-secrets.yml=oidc-secrets.yml
|
||||||
|
kubectl annotate -n authelia secret oidc-secrets reloader.stakater.com/match=true
|
||||||
|
kubectl -n authelia rollout restart deployment/authelia
|
||||||
|
```
|
||||||
|
|
||||||
|
Synchronize OIDC secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n argocd delete secret argocd-secret
|
||||||
|
kubectl -n argocd create secret generic argocd-secret \
|
||||||
|
--from-literal=server.secretkey=$(cat /dev/urandom | base64 | head -c 30) \
|
||||||
|
--from-literal=oidc.config.clientSecret=$( \
|
||||||
|
kubectl get secret -n authelia oidc-secrets -o json \
|
||||||
|
| jq '.data."oidc-secrets.yml"' -r | base64 -d | yq -o json \
|
||||||
|
| jq '.identity_providers.oidc.clients[] | select(.id == "argocd") | .secret' -r)
|
||||||
|
kubectl -n monitoring delete secret oidc-secret
|
||||||
|
kubectl -n monitoring create secret generic oidc-secret \
|
||||||
|
--from-literal=GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=$( \
|
||||||
|
kubectl get secret -n authelia oidc-secrets -o json \
|
||||||
|
| jq '.data."oidc-secrets.yml"' -r | base64 -d | yq -o json \
|
||||||
|
| jq '.identity_providers.oidc.clients[] | select(.id == "grafana") | .secret' -r)
|
||||||
|
```
|
409
authelia/application.yml
Normal file
409
authelia/application.yml
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
type: Opaque
|
||||||
|
metadata:
|
||||||
|
name: authelia-certificates
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
data:
|
||||||
|
ldaps.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZJekNDQXd1Z0F3SUJBZ0lVRzNaYnI0MGVVMlRHak1Lek5XaDhOTDJkRDRZd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1dVMkZ0WW1FZ1lYUWdZV1F1YXkxemNHRmpaUzVsWlRBZUZ3MHlNVEV5TVRRdwpOekk0TlRGYUZ3MHlOakV5TVRNd056STROVEZhTUNFeEh6QWRCZ05WQkFNTUZsTmhiV0poSUdGMElHRmtMbXN0CmMzQmhZMlV1WldVd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUURub3hEZFlicjAKVFJHOEErdk0xT0I1Rzg4Z05YL1pXeFNLb0VaM2p0ekF0NEc3blV0aUhoVzI1cUhEeXZGVGEzTzJiMUFVSEhzbwpVQXpVTWNVV1FRb3J2RjF4L1VsYitpcnk0QkxFTklaVTdYMVpxb2ZKYXgwZTcrbit1YVM3R015dnB4VXliNGlYCkd3djdZZEh5SmM4WjZROHd2MTdNV2F2ejNaOE5CWFdoeG1xc3ljTlphVkl2S1lNRVpGazNUTnA3T20vSTFpdkYKWDJuNVNtb2d2NmdBVmpVODhSeWc2NlRFVStiaGY5QWdiU0VxWjhMaVd6c20xdHc0WnJXMDVVK25JVjRzTHdlaQp2SXppblFMYmFMTkc2ZUl0cUtQZGVsWWhRNHlCeHM3QXpTOCtieVVBZk9jRktzUTI5alFVdUxNbE1pUmt6MjV5Cnc5UUZxSGVuRjNIYXJqU1JTL3ZZV3J3K0RNbmo2Tit3QVdtd21SR3NzVmxPMjFSLzAzNThBK0h5VzhyLzlsTm8KV1FoMmt3VGRPdjdxMzFwRmZQQUhHUkFITnZUN0dRKzVCeFFjdG83cG1GQ2t2OTdpbmhiZG50d2ViSmM1VWI3NQpBeHNWVC9uNk9aTjJSU09NV0RKY1pjVkpXYjQxdTNTL2lBVHlvbDBuOEZMRlRRZm9xdXdvVkQ1UnpwU0NsVm50Cjd1eENyaGNsYXhTYnhUUDhqa29ERXQzc1NycWoySm5PNlhtQ3R2VlZkMmQvWVZQQ21qQm54TWc1bld1WEwwZTgKNkh3MTd5TGtYeFgzVERkdjF2VThvYTdpTmZyNmc3Vlcrd2ZsUkJoVW5WRUluNXZEdm80STVSdWRXaEJxcHN6VQo3bGQrUDVjZE5GWEdjUlRQdFFlbXkxUllKMG5ZejkybGtRSURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVVjZ1JrCnZ4U3V1QnNFaktzbXQvN3dpRHIxbHVRd0h3WURWUjBqQkJnd0ZvQVVjZ1JrdnhTdXVCc0VqS3NtdC83d2lEcjEKbHVRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVNlNXM1aU04QjQ2agp6bXZMOUQ4dUJrQ0VIOW9mMnc1VFluL1NPZkFRVnhBOGxBYndORitlWmgyakdGSUN6citNYmlTMlhZdkxJNnVrClZ5cFJrN28vdExmdmY0alpqZnRpeEliWEM1MjYrUk1xOEcvV2xGbzJnWFZ0eW5BcXp5bXJVYjV1MVZJcG53QWYKNTBzNHlDOURFUXF1aGErYzJCWTBRQ3ZySnUvYy9KTUs3QTdYOFdRSzVDUy8wZkNPdzBPY2xkZzA0c3VWVlU2eQp0MEZmV0kvTlhURFFrU2JWVXN5OElmaXd4a0o5NmNsTjFNWVArQ015Mkh1eWF0aTZySnhVZFBEbS9tYzdRWXNPClNTSzQyNXJQOFFZMmduNlNXUXJXdUJic2dLSEpoVzRBYjdTTldkb0Q0QytwVDA2V1MzVXphMnhZd09TV1IvTWMKR1V5YXRwLzlxR05tOWM1d2RFQ3FtdkVQc2twQkp5ZWR6MUk2V2lxdjRuK0UvRk9qRGl0VVpFd3BFZXRUQktXZgoyRnZRa1pGRmpRU3VIdG5KT040cVRvWmlaNW4vbis4Z1k2Z1Y5Wnd0NHM5OGlpdnUwTFc4UlZGSTNkS0tiYm5lCkY1KzltNE9vMjF0SlU2QThXVGpqVXpLUnFKdEZSa1JpWGtOTGRoY2MrdTdMOFFlZTFOUjIyalg5N2NaVDNGUGoKYmpOUlpId3k5K1dhMG1zcC9EYUR5RnlaOStPUUhReUJJazdCSS9LdU0rT2dta3dlSHBNSE5CMUs1NHZQenZKawpHaFN1QUNIeTRybmdvQTBvMzNhZzJ6a3lEY3NocVRtK2Q3UXFWOWUzU2pONFpUUXlTeWNpa0I1bFJKVHAydVFkCk5jVjBtcG5nREl1aFVlSFRKWkJ0SVZCZnp4bHdHd2c9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: authelia-config
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
annotations:
|
||||||
|
reloader.stakater.com/match: "true"
|
||||||
|
data:
|
||||||
|
authelia-config.yml: |
|
||||||
|
---
|
||||||
|
log:
|
||||||
|
level: warn
|
||||||
|
certificates_directory: /certificates
|
||||||
|
theme: light
|
||||||
|
default_redirection_url: https://members.k-space.ee
|
||||||
|
totp:
|
||||||
|
issuer: K-SPACE
|
||||||
|
authentication_backend:
|
||||||
|
ldap:
|
||||||
|
implementation: activedirectory
|
||||||
|
url: ldaps://ad.k-space.ee
|
||||||
|
base_dn: dc=ad,dc=k-space,dc=ee
|
||||||
|
username_attribute: sAMAccountName
|
||||||
|
additional_users_dn: ou=Membership
|
||||||
|
users_filter: (&({username_attribute}={input})(objectCategory=person)(objectClass=user))
|
||||||
|
additional_groups_dn: cn=Users
|
||||||
|
groups_filter: (&(member={dn})(objectclass=group))
|
||||||
|
group_name_attribute: cn
|
||||||
|
mail_attribute: mail
|
||||||
|
display_name_attribute: displayName
|
||||||
|
user: cn=authelia,cn=Users,dc=ad,dc=k-space,dc=ee
|
||||||
|
session:
|
||||||
|
domain: k-space.ee
|
||||||
|
same_site: lax
|
||||||
|
expiration: 1M
|
||||||
|
inactivity: 120h
|
||||||
|
remember_me_duration: "0"
|
||||||
|
redis:
|
||||||
|
host: redis
|
||||||
|
port: 6379
|
||||||
|
regulation:
|
||||||
|
ban_time: 5m
|
||||||
|
find_time: 2m
|
||||||
|
max_retries: 3
|
||||||
|
storage:
|
||||||
|
mysql:
|
||||||
|
host: mariadb
|
||||||
|
database: authelia
|
||||||
|
username: authelia
|
||||||
|
notifier:
|
||||||
|
disable_startup_check: true
|
||||||
|
smtp:
|
||||||
|
host: mail.k-space.ee
|
||||||
|
port: 465
|
||||||
|
username: authelia
|
||||||
|
sender: authelia@k-space.ee
|
||||||
|
subject: "[Authelia] {title}"
|
||||||
|
startup_check_address: lauri@k-space.ee
|
||||||
|
access_control:
|
||||||
|
default_policy: deny
|
||||||
|
rules:
|
||||||
|
# Longhorn dashboard
|
||||||
|
- domain: longhorn.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
subject: group:Longhorn Admins
|
||||||
|
- domain: longhorn.k-space.ee
|
||||||
|
policy: deny
|
||||||
|
# Members site
|
||||||
|
- domain: members.k-space.ee
|
||||||
|
policy: bypass
|
||||||
|
resources:
|
||||||
|
- ^/?$
|
||||||
|
- domain: members.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
resources:
|
||||||
|
- ^/login/authelia/?$
|
||||||
|
- domain: members.k-space.ee
|
||||||
|
policy: bypass
|
||||||
|
# Webmail
|
||||||
|
- domain: webmail.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
# Etherpad
|
||||||
|
- domain: pad.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
resources:
|
||||||
|
- ^/p/board-
|
||||||
|
subject: group:Board Members
|
||||||
|
- domain: pad.k-space.ee
|
||||||
|
policy: deny
|
||||||
|
resources:
|
||||||
|
- ^/p/board-
|
||||||
|
- domain: pad.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
resources:
|
||||||
|
- ^/p/members-
|
||||||
|
- domain: pad.k-space.ee
|
||||||
|
policy: deny
|
||||||
|
resources:
|
||||||
|
- ^/p/members-
|
||||||
|
- domain: pad.k-space.ee
|
||||||
|
policy: bypass
|
||||||
|
# phpMyAdmin
|
||||||
|
- domain: phpmyadmin.k-space.ee
|
||||||
|
policy: two_factor
|
||||||
|
# Require login for everything else protected by traefik-sso middleware
|
||||||
|
- domain: '*.k-space.ee'
|
||||||
|
policy: one_factor
|
||||||
|
...
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
sessionAffinity: None
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
annotations:
|
||||||
|
reloader.stakater.com/search: "true"
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
replicas: 2
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
enableServiceLinks: false
|
||||||
|
containers:
|
||||||
|
- name: authelia
|
||||||
|
image: authelia/authelia:4
|
||||||
|
command:
|
||||||
|
- authelia
|
||||||
|
- --config=/config/authelia-config.yml
|
||||||
|
- --config=/config/oidc-secrets.yml
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "4.00"
|
||||||
|
memory: 125Mi
|
||||||
|
requests:
|
||||||
|
cpu: "0.25"
|
||||||
|
memory: 50Mi
|
||||||
|
env:
|
||||||
|
- name: AUTHELIA_SERVER_DISABLE_HEALTHCHECK
|
||||||
|
value: "true"
|
||||||
|
- name: AUTHELIA_JWT_SECRET_FILE
|
||||||
|
value: /secrets/JWT_TOKEN
|
||||||
|
- name: AUTHELIA_SESSION_SECRET_FILE
|
||||||
|
value: /secrets/SESSION_ENCRYPTION_KEY
|
||||||
|
- name: AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE
|
||||||
|
value: /secrets/LDAP_PASSWORD
|
||||||
|
- name: AUTHELIA_SESSION_REDIS_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: redis-secrets
|
||||||
|
key: REDIS_PASSWORD
|
||||||
|
- name: AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE
|
||||||
|
value: /secrets/STORAGE_ENCRYPTION_KEY
|
||||||
|
- name: AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE
|
||||||
|
value: /mariadb-secrets/MYSQL_PASSWORD
|
||||||
|
- name: AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE
|
||||||
|
value: /secrets/OIDC_HMAC_SECRET
|
||||||
|
- name: AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE
|
||||||
|
value: /secrets/OIDC_PRIVATE_KEY
|
||||||
|
- name: AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE
|
||||||
|
value: /secrets/SMTP_PASSWORD
|
||||||
|
- name: TZ
|
||||||
|
value: Europe/Tallinn
|
||||||
|
startupProbe:
|
||||||
|
failureThreshold: 6
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 5
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 30
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 5
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 9091
|
||||||
|
protocol: TCP
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /config/authelia-config.yml
|
||||||
|
name: authelia-config
|
||||||
|
readOnly: true
|
||||||
|
subPath: authelia-config.yml
|
||||||
|
- mountPath: /config/oidc-secrets.yml
|
||||||
|
name: oidc-secrets
|
||||||
|
readOnly: true
|
||||||
|
subPath: oidc-secrets.yml
|
||||||
|
- mountPath: /secrets
|
||||||
|
name: secrets
|
||||||
|
readOnly: true
|
||||||
|
- mountPath: /certificates
|
||||||
|
name: certificates
|
||||||
|
readOnly: true
|
||||||
|
- mountPath: /mariadb-secrets
|
||||||
|
name: mariadb-secrets
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: authelia-config
|
||||||
|
configMap:
|
||||||
|
name: authelia-config
|
||||||
|
- name: secrets
|
||||||
|
secret:
|
||||||
|
secretName: application-secrets
|
||||||
|
items:
|
||||||
|
- key: JWT_TOKEN
|
||||||
|
path: JWT_TOKEN
|
||||||
|
- key: SESSION_ENCRYPTION_KEY
|
||||||
|
path: SESSION_ENCRYPTION_KEY
|
||||||
|
- key: STORAGE_ENCRYPTION_KEY
|
||||||
|
path: STORAGE_ENCRYPTION_KEY
|
||||||
|
- key: STORAGE_PASSWORD
|
||||||
|
path: STORAGE_PASSWORD
|
||||||
|
- key: LDAP_PASSWORD
|
||||||
|
path: LDAP_PASSWORD
|
||||||
|
- key: OIDC_PRIVATE_KEY
|
||||||
|
path: OIDC_PRIVATE_KEY
|
||||||
|
- key: OIDC_HMAC_SECRET
|
||||||
|
path: OIDC_HMAC_SECRET
|
||||||
|
- key: SMTP_PASSWORD
|
||||||
|
path: SMTP_PASSWORD
|
||||||
|
- name: certificates
|
||||||
|
secret:
|
||||||
|
secretName: authelia-certificates
|
||||||
|
- name: mariadb-secrets
|
||||||
|
secret:
|
||||||
|
secretName: mariadb-secrets
|
||||||
|
- name: redis-secrets
|
||||||
|
secret:
|
||||||
|
secretName: redis-secrets
|
||||||
|
- name: oidc-secrets
|
||||||
|
secret:
|
||||||
|
secretName: oidc-secrets
|
||||||
|
items:
|
||||||
|
- key: oidc-secrets.yml
|
||||||
|
path: oidc-secrets.yml
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
kubernetes.io/tls-acme: "true"
|
||||||
|
traefik.ingress.kubernetes.io/router.entryPoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: authelia-chain-k6-authelia@kubernetescrd
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: auth.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: authelia
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- auth.k-space.ee
|
||||||
|
secretName: authelia-tls
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: forwardauth-k6-authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
forwardAuth:
|
||||||
|
address: http://authelia.authelia.svc.cluster.local/api/verify?rd=https://auth.k-space.ee/
|
||||||
|
trustForwardHeader: true
|
||||||
|
authResponseHeaders:
|
||||||
|
- Remote-User
|
||||||
|
- Remote-Name
|
||||||
|
- Remote-Email
|
||||||
|
- Remote-Groups
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: headers-k6-authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
headers:
|
||||||
|
browserXssFilter: true
|
||||||
|
customFrameOptionsValue: "SAMEORIGIN"
|
||||||
|
customResponseHeaders:
|
||||||
|
Cache-Control: "no-store"
|
||||||
|
Pragma: "no-cache"
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: chain-k6-authelia-auth
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
chain:
|
||||||
|
middlewares:
|
||||||
|
- name: forwardauth-k6-authelia
|
||||||
|
namespace: authelia
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: chain-k6-authelia
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: authelia
|
||||||
|
spec:
|
||||||
|
chain:
|
||||||
|
middlewares:
|
||||||
|
- name: headers-k6-authelia
|
||||||
|
namespace: authelia
|
||||||
|
---
|
||||||
|
apiVersion: mysql.oracle.com/v2
|
||||||
|
kind: InnoDBCluster
|
||||||
|
metadata:
|
||||||
|
name: mysql-cluster
|
||||||
|
spec:
|
||||||
|
secretName: mysql-secrets
|
||||||
|
instances: 3
|
||||||
|
router:
|
||||||
|
instances: 2
|
||||||
|
tlsUseSelfSigned: true
|
||||||
|
datadirVolumeClaimTemplate:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "1Gi"
|
||||||
|
podSpec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app.kubernetes.io/managed-by
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- mysql-operator
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
1
authelia/keydb.yml
Symbolic link
1
authelia/keydb.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/keydb.yml
|
1
authelia/mariadb.yml
Symbolic link
1
authelia/mariadb.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/mariadb.yml
|
1
camtiler/.gitignore
vendored
Normal file
1
camtiler/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
deployments/
|
29
camtiler/README.md
Normal file
29
camtiler/README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
To apply changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n camtiler -f application.yml -f mongoexpress.yml -f mongodb-support.yml -f networkpolicy-base.yml -f minio-support.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
To deploy changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n camtiler rollout restart deployment.apps/camtiler
|
||||||
|
```
|
||||||
|
|
||||||
|
To initialize secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create secret generic -n camtiler mongodb-application-readwrite-password --from-literal="password=$(cat /dev/urandom | base64 | head -c 30)"
|
||||||
|
kubectl create secret generic -n camtiler mongodb-application-readonly-password --from-literal="password=$(cat /dev/urandom | base64 | head -c 30)"
|
||||||
|
kubectl create secret generic -n camtiler minio-secret \
|
||||||
|
--from-literal=accesskey=application \
|
||||||
|
--from-literal=secretkey=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
kubectl create secret generic -n camtiler minio-env-configuration \
|
||||||
|
--from-literal="MINIO_BROWSER=off" \
|
||||||
|
--from-literal="MINIO_ROOT_USER=root" \
|
||||||
|
--from-literal="MINIO_ROOT_PASSWORD=$(cat /dev/urandom | base64 | head -c 30)" \
|
||||||
|
--from-literal="MINIO_STORAGE_CLASS_STANDARD=EC:4"
|
||||||
|
kubectl -n camtiler create secret generic camera-secrets \
|
||||||
|
--from-literal=username=... \
|
||||||
|
--from-literal=password=...
|
||||||
|
```
|
474
camtiler/application.yml
Normal file
474
camtiler/application.yml
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: camtiler
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: camtiler
|
||||||
|
component: camtiler
|
||||||
|
spec:
|
||||||
|
serviceAccountName: camtiler
|
||||||
|
containers:
|
||||||
|
- name: camtiler
|
||||||
|
image: harbor.k-space.ee/k-space/camera-tiler:latest
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-frontend
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: log-viewer-frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: log-viewer-frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: log-viewer-frontend
|
||||||
|
image: harbor.k-space.ee/k-space/log-viewer-frontend:latest
|
||||||
|
# securityContext:
|
||||||
|
# readOnlyRootFilesystem: true
|
||||||
|
# runAsNonRoot: true
|
||||||
|
# runAsUser: 1000
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-backend
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: log-viewer-backend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: log-viewer-backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: log-backend-backend
|
||||||
|
image: harbor.k-space.ee/k-space/log-viewer:latest
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
env:
|
||||||
|
- name: MONGO_URI
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mongodb-application-readwrite
|
||||||
|
key: connectionString.standard
|
||||||
|
- name: MINIO_BUCKET
|
||||||
|
value: application
|
||||||
|
- name: MINIO_HOSTNAME
|
||||||
|
value: cams-s3.k-space.ee
|
||||||
|
- name: MINIO_PORT
|
||||||
|
value: "443"
|
||||||
|
- name: MINIO_SCHEME
|
||||||
|
value: "https"
|
||||||
|
- name: MINIO_SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: minio-secret
|
||||||
|
key: secretkey
|
||||||
|
- name: MINIO_ACCESS_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: minio-secret
|
||||||
|
key: accesskey
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-frontend
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: log-viewer-frontend
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3003
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-backend
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: log-viewer-backend
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3002
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
labels:
|
||||||
|
component: camtiler
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: camtiler
|
||||||
|
component: camtiler
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5001
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["list"]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: camtiler
|
||||||
|
apiGroup: ""
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: camtiler
|
||||||
|
apiGroup: ""
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: camtiler
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
|
||||||
|
# Following specifies the certificate issuer defined in
|
||||||
|
# ../cert-manager/issuer.yml
|
||||||
|
# This is where the HTTPS certificates for the
|
||||||
|
# `tls:` section below are obtained from
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
|
||||||
|
# This tells Traefik this Ingress object is associated with the
|
||||||
|
# https:// entrypoint
|
||||||
|
# Global http:// to https:// redirect is enabled in
|
||||||
|
# ../traefik/values.yml using `globalArguments`
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
|
||||||
|
# Following enables Authelia intercepting middleware
|
||||||
|
# which makes sure user is authenticated and then
|
||||||
|
# proceeds to inject Remote-User header for the application
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
|
||||||
|
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
|
||||||
|
# Following tells external-dns to add CNAME entry which makes
|
||||||
|
# cams.k-space.ee point to same IP address as traefik.k-space.ee
|
||||||
|
# The A record for traefik.k-space.ee is created via annotation
|
||||||
|
# added in ../traefik/ingress.yml
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: cams.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/tiled"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: camtiler
|
||||||
|
port:
|
||||||
|
number: 5001
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/events"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: log-viewer-backend
|
||||||
|
port:
|
||||||
|
number: 3002
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: log-viewer-frontend
|
||||||
|
port:
|
||||||
|
number: 3003
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- cams.k-space.ee
|
||||||
|
secretName: camtiler-tls
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: camera-operator
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 1
|
||||||
|
serviceName: camera-operator
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: camera-operator
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: camera-operator
|
||||||
|
spec:
|
||||||
|
serviceAccount: camera-operator
|
||||||
|
containers:
|
||||||
|
- name: camera-operator
|
||||||
|
image: harbor.k-space.ee/k-space/camera-operator:latest
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
env:
|
||||||
|
- name: MY_POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: camera-operator
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- list
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- list
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- k-space.ee
|
||||||
|
resources:
|
||||||
|
- cams
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: camera-operator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: camera-operator
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: camera-operator
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: camera-operator
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: camera-motion-detect
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
component: camdetect
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
component: camtiler
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: monitoring
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: prometheus
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
# Permit access to cameras outside the cluster
|
||||||
|
cidr: 100.102.0.0/16
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: mongodb-svc
|
||||||
|
ports:
|
||||||
|
- port: 27017
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
v1.min.io/tenant: minio
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: camera-tiler
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
component: camtiler
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
component: camdetect
|
||||||
|
ports:
|
||||||
|
- port: 5000
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: monitoring
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: prometheus
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-backend
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: log-viewer-backend
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: mongodb-svc
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
v1.min.io/tenant: minio
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: log-viewer-frontend
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: log-viewer-frontend
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: minio
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: cams-s3.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: minio
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- cams-s3.k-space.ee
|
||||||
|
secretName: cams-s3-tls
|
1
camtiler/minio-support.yml
Symbolic link
1
camtiler/minio-support.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/minio-support.yml
|
1
camtiler/mongodb-support.yml
Symbolic link
1
camtiler/mongodb-support.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../mongodb-operator/mongodb-support.yml
|
1
camtiler/mongoexpress.yml
Symbolic link
1
camtiler/mongoexpress.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/mongoexpress.yml
|
1
camtiler/networkpolicy-base.yml
Symbolic link
1
camtiler/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
126
camtiler/persistence.yml
Normal file
126
camtiler/persistence.yml
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
apiVersion: mongodbcommunity.mongodb.com/v1
|
||||||
|
kind: MongoDBCommunity
|
||||||
|
metadata:
|
||||||
|
name: mongodb
|
||||||
|
spec:
|
||||||
|
members: 3
|
||||||
|
type: ReplicaSet
|
||||||
|
version: "5.0.9"
|
||||||
|
security:
|
||||||
|
authentication:
|
||||||
|
modes: ["SCRAM"]
|
||||||
|
users:
|
||||||
|
- name: readwrite
|
||||||
|
db: application
|
||||||
|
passwordSecretRef:
|
||||||
|
name: mongodb-application-readwrite-password
|
||||||
|
roles:
|
||||||
|
- name: readWrite
|
||||||
|
db: application
|
||||||
|
scramCredentialsSecretName: mongodb-application-readwrite
|
||||||
|
- name: readonly
|
||||||
|
db: application
|
||||||
|
passwordSecretRef:
|
||||||
|
name: mongodb-application-readonly-password
|
||||||
|
roles:
|
||||||
|
- name: readOnly
|
||||||
|
db: application
|
||||||
|
scramCredentialsSecretName: mongodb-application-readonly
|
||||||
|
statefulSet:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- mongodb-svc
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: logs-volume
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 512Mi
|
||||||
|
- metadata:
|
||||||
|
name: data-volume
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
---
|
||||||
|
apiVersion: minio.min.io/v2
|
||||||
|
kind: Tenant
|
||||||
|
metadata:
|
||||||
|
name: minio
|
||||||
|
annotations:
|
||||||
|
prometheus.io/path: /minio/prometheus/metrics
|
||||||
|
prometheus.io/port: "9000"
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
spec:
|
||||||
|
credsSecret:
|
||||||
|
name: minio-secret
|
||||||
|
buckets:
|
||||||
|
- name: application
|
||||||
|
requestAutoCert: false
|
||||||
|
users:
|
||||||
|
- name: minio-user-0
|
||||||
|
pools:
|
||||||
|
- name: pool-0
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: v1.min.io/tenant
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- minio
|
||||||
|
- key: v1.min.io/pool
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- pool-0
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 512Mi
|
||||||
|
servers: 4
|
||||||
|
volumesPerServer: 1
|
||||||
|
volumeClaimTemplate:
|
||||||
|
metadata:
|
||||||
|
name: data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '30Gi'
|
||||||
|
storageClassName: local-path
|
||||||
|
status: {}
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
26
cert-manager/README.md
Normal file
26
cert-manager/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# cert-manager
|
||||||
|
|
||||||
|
`cert-manager` is used to obtain TLS certificates from Let's Encrypt.
|
||||||
|
|
||||||
|
Added manifest with:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -L https://github.com/jetstack/cert-manager/releases/download/v1.6.1/cert-manager.yaml -O
|
||||||
|
```
|
||||||
|
|
||||||
|
To update certificate issuer
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -f namespace.yml -f cert-manager.yaml
|
||||||
|
kubectl apply -f issuer.yml
|
||||||
|
kubectl -n cert-manager create secret generic tsig-secret \
|
||||||
|
--from-literal=TSIG_SECRET=<secret>
|
||||||
|
```
|
||||||
|
|
||||||
|
Workaround for webhook timeout issue https://github.com/jetstack/cert-manager/issues/2602
|
||||||
|
It's not very clear why this is happening, deserves further investigation - presumably Calico related somehow:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl delete mutatingwebhookconfiguration.admissionregistration.k8s.io cert-manager-webhook
|
||||||
|
kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io cert-manager-webhook
|
||||||
|
```
|
16233
cert-manager/cert-manager.crds.yaml
Normal file
16233
cert-manager/cert-manager.crds.yaml
Normal file
File diff suppressed because it is too large
Load Diff
17329
cert-manager/cert-manager.yaml
Normal file
17329
cert-manager/cert-manager.yaml
Normal file
File diff suppressed because it is too large
Load Diff
19
cert-manager/issuer.yml
Normal file
19
cert-manager/issuer.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: default
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
email: info@k-space.ee
|
||||||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: example-issuer-account-key
|
||||||
|
solvers:
|
||||||
|
- dns01:
|
||||||
|
rfc2136:
|
||||||
|
nameserver: 193.40.103.2
|
||||||
|
tsigKeyName: acme.
|
||||||
|
tsigAlgorithm: HMACSHA512
|
||||||
|
tsigSecretSecretRef:
|
||||||
|
name: tsig-secret
|
||||||
|
key: TSIG_SECRET
|
90
cluster-role-bindings.yml
Normal file
90
cluster-role-bindings.yml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
---
|
||||||
|
# AD/Samba group "Kubernetes Admins" members have full access
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-admins
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: "Kubernetes Admins"
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
# AD/Samba group "Developers" members have view access for everything
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-developers
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: Developers
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: view
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: developers
|
||||||
|
namespace: camtiler
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: Developers
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: developers
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: developers
|
||||||
|
namespace: members-site
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: Developers
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: developers
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: developers
|
||||||
|
rules:
|
||||||
|
- verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- pods/attach
|
||||||
|
- pods/exec
|
||||||
|
- pods/portforward
|
||||||
|
- pods/proxy
|
||||||
|
- verbs:
|
||||||
|
- patch
|
||||||
|
apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
- statefulsets
|
||||||
|
- deployments/scale
|
||||||
|
- statefulsets/scale
|
||||||
|
- verbs:
|
||||||
|
- delete
|
||||||
|
apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- pods
|
13
drone-execution/README.md
Normal file
13
drone-execution/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
To deply:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n drone-execution -f application.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
To bootstrap secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create secret generic -n drone-execution application-secrets \
|
||||||
|
--from-literal=DRONE_RPC_SECRET=$(kubectl get secret -n drone application-secrets -o jsonpath="{.data.DRONE_RPC_SECRET}" | base64 -d) \
|
||||||
|
--from-literal=DRONE_SECRET_PLUGIN_TOKEN=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
```
|
177
drone-execution/application.yml
Normal file
177
drone-execution/application.yml
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: application-config
|
||||||
|
data:
|
||||||
|
DRONE_DEBUG: "false"
|
||||||
|
DRONE_TRACE: "false"
|
||||||
|
DRONE_NAMESPACE_DEFAULT: "drone-execution"
|
||||||
|
DRONE_RPC_HOST: "drone.k-space.ee"
|
||||||
|
DRONE_RPC_PROTO: "https"
|
||||||
|
PLUGIN_MTU: "1300"
|
||||||
|
DRONE_SECRET_PLUGIN_ENDPOINT: "http://secrets:3000"
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
namespace: "drone-execution"
|
||||||
|
labels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- pods/log
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- update
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
namespace: drone-execution
|
||||||
|
labels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: drone-runner-kube
|
||||||
|
namespace: drone-execution
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: drone-runner-kube
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
labels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: drone-runner-kube
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
spec:
|
||||||
|
serviceAccountName: drone-runner-kube
|
||||||
|
terminationGracePeriodSeconds: 3600
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
securityContext:
|
||||||
|
{}
|
||||||
|
image: drone/drone-runner-kube
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: application-config
|
||||||
|
- secretRef:
|
||||||
|
name: application-secrets
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: drone-kubernetes-secrets
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: drone-kubernetes-secrets
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: drone-kubernetes-secrets
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: secrets
|
||||||
|
image: drone/kubernetes-secrets
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: application-secrets
|
||||||
|
key: DRONE_SECRET_PLUGIN_TOKEN
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: drone-kubernetes-secrets
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: drone-kubernetes-secrets
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: drone-runner-kube
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
---
|
||||||
|
# Following should block access to pods in other namespaces, but should permit
|
||||||
|
# Git checkout, pip install, talking to Traefik via public IP etc
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: drone-runner-kube
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
1
drone-execution/networkpolicy-base.yml
Symbolic link
1
drone-execution/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
25
drone/.helmignore
Normal file
25
drone/.helmignore
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
||||||
|
# Chart dirs/files
|
||||||
|
docs/
|
||||||
|
ci/
|
161
drone/README.md
Normal file
161
drone/README.md
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
To deploy:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n drone -f application.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
To bootstrap secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create secret generic -n drone application-secrets \
|
||||||
|
--from-literal=DRONE_GITEA_CLIENT_ID=... \
|
||||||
|
--from-literal=DRONE_GITEA_CLIENT_SECRET=... \
|
||||||
|
--from-literal=DRONE_RPC_SECRET=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
```
|
||||||
|
|
||||||
|
# Integrating with Docker registry
|
||||||
|
|
||||||
|
We use harbor.k-space.ee to host own images.
|
||||||
|
|
||||||
|
Set up robot account `robot$k-space+drone` in Harbor first.
|
||||||
|
|
||||||
|
In Drone associate `docker_username` and `docker_password` secrets with the
|
||||||
|
`k-space`.
|
||||||
|
|
||||||
|
Instead of click marathon you can also pull the CLI configuration for Drone
|
||||||
|
from https://drone.k-space.ee/account
|
||||||
|
|
||||||
|
```
|
||||||
|
drone orgsecret add k-space docker_username 'robot$k-space+drone'
|
||||||
|
drone orgsecret add k-space docker_password '...'
|
||||||
|
```
|
||||||
|
|
||||||
|
# Integrating with e-mail
|
||||||
|
|
||||||
|
To (re)set e-mail credentials:
|
||||||
|
|
||||||
|
```
|
||||||
|
drone orgsecret add k-space email_password '...'
|
||||||
|
```
|
||||||
|
|
||||||
|
To issue build hit the button in Drone web interface or alternatively:
|
||||||
|
|
||||||
|
```
|
||||||
|
drone build create k-space/...
|
||||||
|
```
|
||||||
|
|
||||||
|
# Using templates
|
||||||
|
|
||||||
|
Templates unfortunately aren't pulled in from this Git repo.
|
||||||
|
|
||||||
|
Current `docker.yaml` template includes following:
|
||||||
|
|
||||||
|
```
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: build-arm64
|
||||||
|
platform:
|
||||||
|
arch: arm64
|
||||||
|
os: linux
|
||||||
|
node_selector:
|
||||||
|
kubernetes.io/arch: arm64
|
||||||
|
tolerations:
|
||||||
|
- key: arch
|
||||||
|
operator: Equal
|
||||||
|
value: arm64
|
||||||
|
effect: NoSchedule
|
||||||
|
steps:
|
||||||
|
- name: submodules
|
||||||
|
image: alpine/git
|
||||||
|
commands:
|
||||||
|
- touch .gitmodules
|
||||||
|
- sed -i -e 's/git@git.k-space.ee:/https:\\/\\/git.k-space.ee\\//g' .gitmodules
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- echo "ENV GIT_COMMIT=$(git rev-parse HEAD)" >> Dockerfile
|
||||||
|
- echo "ENV GIT_COMMIT_TIMESTAMP=$(git log -1 --format=%cd --date=iso-strict)" >> Dockerfile
|
||||||
|
- cat Dockerfile
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
repo: harbor.k-space.ee/${DRONE_REPO}
|
||||||
|
tags: latest-arm64
|
||||||
|
registry: harbor.k-space.ee
|
||||||
|
squash: true
|
||||||
|
experimental: true
|
||||||
|
mtu: 1300
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: build-amd64
|
||||||
|
platform:
|
||||||
|
arch: amd64
|
||||||
|
os: linux
|
||||||
|
node_selector:
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
steps:
|
||||||
|
- name: submodules
|
||||||
|
image: alpine/git
|
||||||
|
commands:
|
||||||
|
- touch .gitmodules
|
||||||
|
- sed -i -e 's/git@git.k-space.ee:/https:\\/\\/git.k-space.ee\\//g' .gitmodules
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- echo "ENV GIT_COMMIT=$(git rev-parse HEAD)" >> Dockerfile
|
||||||
|
- echo "ENV GIT_COMMIT_TIMESTAMP=$(git log -1 --format=%cd --date=iso-strict)" >> Dockerfile
|
||||||
|
- cat Dockerfile
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
repo: harbor.k-space.ee/${DRONE_REPO}
|
||||||
|
tags: latest-amd64
|
||||||
|
registry: harbor.k-space.ee
|
||||||
|
squash: true
|
||||||
|
experimental: true
|
||||||
|
mtu: 1300
|
||||||
|
storage_driver: vfs
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: manifest
|
||||||
|
steps:
|
||||||
|
- name: manifest
|
||||||
|
image: plugins/manifest
|
||||||
|
settings:
|
||||||
|
target: harbor.k-space.ee/${DRONE_REPO}:latest
|
||||||
|
template: harbor.k-space.ee/${DRONE_REPO}:latest-ARCH
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
depends_on:
|
||||||
|
- build-amd64
|
||||||
|
- build-arm64
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: gitlint
|
||||||
|
steps:
|
||||||
|
- name: gitlint
|
||||||
|
image: harbor.k-space.ee/k-space/gitlint-bundle
|
||||||
|
# https://git.k-space.ee/k-space/gitlint-bundle
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: flake8
|
||||||
|
steps:
|
||||||
|
- name: flake8
|
||||||
|
image: harbor.k-space.ee/k-space/flake8-bundle
|
||||||
|
# https://git.k-space.ee/k-space/flake8-bundle
|
||||||
|
```
|
109
drone/application.yml
Normal file
109
drone/application.yml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: application-config
|
||||||
|
data:
|
||||||
|
DRONE_GITEA_SERVER: "https://git.k-space.ee"
|
||||||
|
DRONE_GIT_ALWAYS_AUTH: "false"
|
||||||
|
DRONE_PROMETHEUS_ANONYMOUS_ACCESS: "true"
|
||||||
|
DRONE_SERVER_HOST: "drone.k-space.ee"
|
||||||
|
DRONE_SERVER_PROTO: "https"
|
||||||
|
DRONE_USER_CREATE: "username:lauri,admin:true"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: drone
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: drone
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: drone
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: minor
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
serviceName: drone
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: drone
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: drone
|
||||||
|
annotations:
|
||||||
|
prometheus.io/port: "80"
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
securityContext:
|
||||||
|
{}
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
securityContext:
|
||||||
|
{}
|
||||||
|
image: drone/drone:2
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: application-secrets
|
||||||
|
- configMapRef:
|
||||||
|
name: application-config
|
||||||
|
volumeMounts:
|
||||||
|
- name: drone-data
|
||||||
|
mountPath: /data
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: drone-data
|
||||||
|
spec:
|
||||||
|
storageClassName: longhorn
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 8Gi
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: drone
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- "drone.k-space.ee"
|
||||||
|
secretName: drone-tls
|
||||||
|
rules:
|
||||||
|
- host: "drone.k-space.ee"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: /
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: drone
|
||||||
|
port:
|
||||||
|
number: 80
|
12
etherpad/README.md
Normal file
12
etherpad/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
To apply changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n etherpad -f application.yml -f networkpolicy-base.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Initialize MySQL secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create secret generic -n etherpad mariadb-secrets \
|
||||||
|
--from-literal=MYSQL_ROOT_PASSWORD=$(cat /dev/urandom | base64 | head -c 30) \
|
||||||
|
--from-literal=MYSQL_PASSWORD=$(cat /dev/urandom | base64 | head -c 30)
|
206
etherpad/application.yml
Normal file
206
etherpad/application.yml
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: etherpad
|
||||||
|
namespace: etherpad
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: minor
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
# Etherpad does NOT support running multiple replicas due to
|
||||||
|
# in-application caching https://github.com/ether/etherpad-lite/issues/3680
|
||||||
|
replicas: 1
|
||||||
|
serviceName: etherpad
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: etherpad
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: etherpad
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: etherpad
|
||||||
|
image: etherpad/etherpad:1
|
||||||
|
securityContext:
|
||||||
|
# Etherpad writes session key during start
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 5001
|
||||||
|
ports:
|
||||||
|
- containerPort: 9001
|
||||||
|
env:
|
||||||
|
- name: DB_TYPE
|
||||||
|
value: mysql
|
||||||
|
- name: DB_HOST
|
||||||
|
value: 172.20.36.1
|
||||||
|
- name: DB_NAME
|
||||||
|
value: kspace_etherpad
|
||||||
|
- name: DB_USER
|
||||||
|
value: kspace_etherpad
|
||||||
|
- name: PAD_OPTIONS_NO_COLORS
|
||||||
|
value: "true"
|
||||||
|
- name: PAD_OPTIONS_USE_MONOSPACE_FONT
|
||||||
|
value: "true"
|
||||||
|
- name: PAD_OPTIONS_SHOW_CHAT
|
||||||
|
value: "false"
|
||||||
|
- name: TRUST_PROXY
|
||||||
|
value: "true"
|
||||||
|
- name: ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: application-secrets
|
||||||
|
key: ADMIN_PASSWORD
|
||||||
|
- name: DB_PASS
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mariadb-secrets
|
||||||
|
key: MYSQL_PASSWORD
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: etherpad
|
||||||
|
namespace: etherpad
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: etherpad
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9001
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: etherpad
|
||||||
|
namespace: etherpad
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: pad.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: etherpad
|
||||||
|
port:
|
||||||
|
number: 9001
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- pad.k-space.ee
|
||||||
|
secretName: pad-tls
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: etherpad
|
||||||
|
namespace: etherpad
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: etherpad
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9001
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 172.20.36.1/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: etherpad
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- # TODO: Not sure why mysql-operator needs to be able to connect
|
||||||
|
from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: kubernetes.io/metadata.name
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- mysql-operator
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
||||||
|
- # Allow connecting from other MySQL pods in same namespace
|
||||||
|
from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/managed-by: mysql-operator
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
||||||
|
egress:
|
||||||
|
- # Allow connecting to other MySQL pods in same namespace
|
||||||
|
to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/managed-by: mysql-operator
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
||||||
|
---
|
||||||
|
apiVersion: mysql.oracle.com/v2
|
||||||
|
kind: InnoDBCluster
|
||||||
|
metadata:
|
||||||
|
name: mysql-cluster
|
||||||
|
spec:
|
||||||
|
secretName: mysql-secrets
|
||||||
|
instances: 3
|
||||||
|
router:
|
||||||
|
instances: 1
|
||||||
|
tlsUseSelfSigned: true
|
||||||
|
datadirVolumeClaimTemplate:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "10Gi"
|
||||||
|
podSpec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app.kubernetes.io/managed-by
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- mysql-operator
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
1
etherpad/networkpolicy-base.yml
Symbolic link
1
etherpad/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
15
external-dns/README.md
Normal file
15
external-dns/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Before applying replace the secret with the actual one.
|
||||||
|
|
||||||
|
For debugging add `- --log-level=debug`:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n external-dns -f external-dns.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Insert TSIG secret:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n external-dns create secret generic tsig-secret \
|
||||||
|
--from-literal=TSIG_SECRET=<secret>
|
||||||
|
```
|
84
external-dns/application.yml
Normal file
84
external-dns/application.yml
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: external-dns
|
||||||
|
namespace: external-dns
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- apiGroups:
|
||||||
|
- extensions
|
||||||
|
- networking.k8s.io
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: external-dns
|
||||||
|
namespace: external-dns
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: external-dns-viewer
|
||||||
|
namespace: external-dns
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: external-dns
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: external-dns
|
||||||
|
namespace: external-dns
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: external-dns
|
||||||
|
namespace: external-dns
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: external-dns
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: external-dns
|
||||||
|
spec:
|
||||||
|
serviceAccountName: external-dns
|
||||||
|
containers:
|
||||||
|
- name: external-dns
|
||||||
|
image: k8s.gcr.io/external-dns/external-dns:v0.10.2
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: tsig-secret
|
||||||
|
args:
|
||||||
|
- --registry=txt
|
||||||
|
- --txt-prefix=external-dns-
|
||||||
|
- --txt-owner-id=k8s
|
||||||
|
- --provider=rfc2136
|
||||||
|
- --source=ingress
|
||||||
|
- --source=service
|
||||||
|
- --domain-filter=k-space.ee
|
||||||
|
- --rfc2136-host=193.40.103.2
|
||||||
|
- --rfc2136-port=53
|
||||||
|
- --rfc2136-zone=k-space.ee
|
||||||
|
- --rfc2136-tsig-keyname=acme
|
||||||
|
- --rfc2136-tsig-secret-alg=hmac-sha512
|
||||||
|
- --rfc2136-tsig-secret=$(TSIG_SECRET)
|
||||||
|
# https://github.com/kubernetes-sigs/external-dns/issues/2446
|
1
harbor/.gitignore
vendored
Normal file
1
harbor/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
harbor.yml
|
10
harbor/README.md
Normal file
10
harbor/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Deploy with:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create namespace harbor
|
||||||
|
kubectl apply -n harbor -f application.yml -f application-secrets.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
After deployment login with Harbor admin credentials and configure OIDC:
|
||||||
|
|
||||||
|
![OIDC configuration](harbor-oidc-config.png)
|
1078
harbor/application.yml
Normal file
1078
harbor/application.yml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
harbor/harbor-oidc-config.png
Normal file
BIN
harbor/harbor-oidc-config.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
10
keel/README.md
Normal file
10
keel/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
To generate secrets and to deploy:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create secret generic -n $(basename $(pwd)) application-secrets \
|
||||||
|
--from-literal=BASIC_AUTH_PASSWORD=$(cat /dev/urandom | base64 | head -c 30) \
|
||||||
|
--from-literal=MAIL_SMTP_PASS=... \
|
||||||
|
--from-literal=SLACK_TOKEN=...
|
||||||
|
kubectl apply -n keel -f application.yml
|
||||||
|
kubectl -n keel rollout restart deployment.apps/keel
|
||||||
|
```
|
176
keel/application.yml
Normal file
176
keel/application.yml
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
namespace: keel
|
||||||
|
labels:
|
||||||
|
app: keel
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- namespaces
|
||||||
|
verbs:
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- extensions
|
||||||
|
- apps
|
||||||
|
- batch
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- replicasets
|
||||||
|
- replicationcontrollers
|
||||||
|
- statefulsets
|
||||||
|
- deployments
|
||||||
|
- daemonsets
|
||||||
|
- jobs
|
||||||
|
- cronjobs
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- delete # required to delete pods during force upgrade of the same tag
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- pods/portforward
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: keel
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: keel
|
||||||
|
namespace: keel
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
namespace: keel
|
||||||
|
labels:
|
||||||
|
app: keel
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 9300
|
||||||
|
targetPort: 9300
|
||||||
|
protocol: TCP
|
||||||
|
name: keel
|
||||||
|
selector:
|
||||||
|
app: keel
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: keel
|
||||||
|
labels:
|
||||||
|
app: keel
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
serviceName: keel
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: keel
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: keel
|
||||||
|
spec:
|
||||||
|
serviceAccountName: keel
|
||||||
|
containers:
|
||||||
|
- name: keel
|
||||||
|
image: keelhq/keel:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command: ["/bin/keel"]
|
||||||
|
volumeMounts:
|
||||||
|
env:
|
||||||
|
- name: NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POLL
|
||||||
|
value: "true"
|
||||||
|
- name: HELM_PROVIDER
|
||||||
|
value: "false"
|
||||||
|
- name: TILLER_NAMESPACE
|
||||||
|
value: "kube-system"
|
||||||
|
- name: TILLER_ADDRESS
|
||||||
|
value: "tiller-deploy:44134"
|
||||||
|
- name: NOTIFICATION_LEVEL
|
||||||
|
value: "info"
|
||||||
|
- name: BASIC_AUTH_USER
|
||||||
|
value: admin
|
||||||
|
- name: SLACK_CHANNELS
|
||||||
|
value: kube-prod
|
||||||
|
- name: SLACK_BOT_NAME
|
||||||
|
value: keel.k-space.ee
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: application-secrets
|
||||||
|
ports:
|
||||||
|
- containerPort: 9300
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 9300
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 9300
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 10
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- name: keel-data
|
||||||
|
mountPath: /data
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: keel-data
|
||||||
|
spec:
|
||||||
|
storageClassName: longhorn
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
18
kubernetes-dashboard/README.md
Normal file
18
kubernetes-dashboard/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
|
||||||
|
helm template --release-name k6 -n kube-dashboard kubernetes-dashboard/kubernetes-dashboard -f values.yaml > application.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
# Apply the changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f application.yml -n kubernetes-dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
# Get token
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n kubernetes-dashboard get secret $(kubectl -n kube-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
|
||||||
|
```
|
293
kubernetes-dashboard/application.yml
Normal file
293
kubernetes-dashboard/application.yml
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-certs
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
# kubernetes-dashboard-csrf
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-csrf
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
# kubernetes-dashboard-key-holder
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-key-holder
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard-settings
|
||||||
|
data:
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: "kubernetes-dashboard-metrics"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/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: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: "kubernetes-dashboard-metrics"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kubernetes-dashboard-metrics
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: 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"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
rules:
|
||||||
|
# Other resources
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["nodes", "namespaces", "pods", "serviceaccounts", "services", "configmaps", "endpoints", "persistentvolumeclaims", "replicationcontrollers", "replicationcontrollers/scale", "persistentvolumeclaims", "persistentvolumes", "bindings", "events", "limitranges", "namespaces/status", "pods/log", "pods/status", "replicationcontrollers/status", "resourcequotas", "resourcequotas/status"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["daemonsets", "deployments", "deployments/scale", "replicasets", "replicasets/scale", "statefulsets"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["autoscaling"]
|
||||||
|
resources: ["horizontalpodautoscalers"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["batch"]
|
||||||
|
resources: ["cronjobs", "jobs"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["extensions"]
|
||||||
|
resources: ["daemonsets", "deployments", "deployments/scale", "networkpolicies", "replicasets", "replicasets/scale", "replicationcontrollers/scale"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["networking.k8s.io"]
|
||||||
|
resources: ["ingresses", "networkpolicies"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["policy"]
|
||||||
|
resources: ["poddisruptionbudgets"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["storageclasses", "volumeattachments"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["clusterrolebindings", "clusterroles", "roles", "rolebindings", ]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kubernetes-dashboard
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
app.kubernetes.io/component: kubernetes-dashboard
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
app.kubernetes.io/component: kubernetes-dashboard
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
app.kubernetes.io/component: kubernetes-dashboard
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 0
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
app.kubernetes.io/component: kubernetes-dashboard
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-dashboard
|
||||||
|
app.kubernetes.io/component: kubernetes-dashboard
|
||||||
|
spec:
|
||||||
|
serviceAccountName: kubernetes-dashboard
|
||||||
|
containers:
|
||||||
|
- name: kubernetes-dashboard
|
||||||
|
image: "kubernetesui/dashboard:v2.4.0"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
args:
|
||||||
|
- --namespace=kubernetes-dashboard
|
||||||
|
- --metrics-provider=none
|
||||||
|
- --enable-skip-login
|
||||||
|
- --disable-settings-authorizer
|
||||||
|
- --enable-insecure-login
|
||||||
|
- --system-banner="Just hit skip!"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 9090
|
||||||
|
protocol: TCP
|
||||||
|
volumeMounts:
|
||||||
|
- name: kubernetes-dashboard-certs
|
||||||
|
mountPath: /certs
|
||||||
|
# Create on-disk volume to store exec logs
|
||||||
|
- mountPath: /tmp
|
||||||
|
name: tmp-volume
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
scheme: HTTP
|
||||||
|
path: /
|
||||||
|
port: 9090
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 30
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2
|
||||||
|
memory: 200Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 200Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsGroup: 2001
|
||||||
|
runAsUser: 1001
|
||||||
|
volumes:
|
||||||
|
- name: kubernetes-dashboard-certs
|
||||||
|
secret:
|
||||||
|
secretName: kubernetes-dashboard-certs
|
||||||
|
- name: tmp-volume
|
||||||
|
emptyDir: {}
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
certManager: "true"
|
||||||
|
rewriteTarget: "true"
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: dashboard.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- dashboard.k-space.ee
|
||||||
|
secretName: dashboard-tls
|
21
local-path-storage/README.md
Normal file
21
local-path-storage/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Local path provisioner
|
||||||
|
|
||||||
|
Rancher's `local-path-storage` storage class enables dynamic provisioning of
|
||||||
|
persistent volumes on Kubernetes worker.
|
||||||
|
|
||||||
|
```
|
||||||
|
curl https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml -O
|
||||||
|
kubectl apply -n local-path-storage -f local-path-storage.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
# Known issues
|
||||||
|
|
||||||
|
* No volume stats exported via `kubelet_volume_stats_used_bytes` metric
|
||||||
|
* No capacity limit imposed. Not possible with ext4 filesystem,
|
||||||
|
with [XFS might be possible](https://github.com/rancher/local-path-provisioner/tree/master/examples/quota)
|
||||||
|
* No easy way to back up the volumes
|
||||||
|
|
||||||
|
Possible alternatives:
|
||||||
|
|
||||||
|
* Longhorn with no redundancy
|
||||||
|
* [metal-stack/csi-lvm](https://github.com/metal-stack/csi-lvm)
|
157
local-path-storage/local-path-storage.yaml
Normal file
157
local-path-storage/local-path-storage.yaml
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: local-path-storage
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: local-path-provisioner-service-account
|
||||||
|
namespace: local-path-storage
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: local-path-provisioner-role
|
||||||
|
rules:
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ "nodes", "persistentvolumeclaims", "configmaps" ]
|
||||||
|
verbs: [ "get", "list", "watch" ]
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ "endpoints", "persistentvolumes", "pods" ]
|
||||||
|
verbs: [ "*" ]
|
||||||
|
- apiGroups: [ "" ]
|
||||||
|
resources: [ "events" ]
|
||||||
|
verbs: [ "create", "patch" ]
|
||||||
|
- apiGroups: [ "storage.k8s.io" ]
|
||||||
|
resources: [ "storageclasses" ]
|
||||||
|
verbs: [ "get", "list", "watch" ]
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: local-path-provisioner-bind
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: local-path-provisioner-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: local-path-provisioner-service-account
|
||||||
|
namespace: local-path-storage
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: local-path-provisioner
|
||||||
|
namespace: local-path-storage
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: local-path-provisioner
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: local-path-provisioner
|
||||||
|
spec:
|
||||||
|
serviceAccountName: local-path-provisioner-service-account
|
||||||
|
containers:
|
||||||
|
- name: local-path-provisioner
|
||||||
|
image: rancher/local-path-provisioner:v0.0.22
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command:
|
||||||
|
- local-path-provisioner
|
||||||
|
- --debug
|
||||||
|
- start
|
||||||
|
- --config
|
||||||
|
- /etc/config/config.json
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /etc/config/
|
||||||
|
env:
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: local-path-config
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: storage.k8s.io/v1
|
||||||
|
kind: StorageClass
|
||||||
|
metadata:
|
||||||
|
name: local-path
|
||||||
|
provisioner: rancher.io/local-path
|
||||||
|
volumeBindingMode: WaitForFirstConsumer
|
||||||
|
reclaimPolicy: Delete
|
||||||
|
---
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: local-path-config
|
||||||
|
namespace: local-path-storage
|
||||||
|
data:
|
||||||
|
config.json: |-
|
||||||
|
{
|
||||||
|
"nodePathMap":[
|
||||||
|
{
|
||||||
|
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
|
||||||
|
"paths":["/opt/local-path-provisioner"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
setup: |-
|
||||||
|
#!/bin/sh
|
||||||
|
while getopts "m:s:p:" opt
|
||||||
|
do
|
||||||
|
case $opt in
|
||||||
|
p)
|
||||||
|
absolutePath=$OPTARG
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
sizeInBytes=$OPTARG
|
||||||
|
;;
|
||||||
|
m)
|
||||||
|
volMode=$OPTARG
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -m 0777 -p ${absolutePath}
|
||||||
|
teardown: |-
|
||||||
|
#!/bin/sh
|
||||||
|
while getopts "m:s:p:" opt
|
||||||
|
do
|
||||||
|
case $opt in
|
||||||
|
p)
|
||||||
|
absolutePath=$OPTARG
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
sizeInBytes=$OPTARG
|
||||||
|
;;
|
||||||
|
m)
|
||||||
|
volMode=$OPTARG
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf ${absolutePath}
|
||||||
|
helperPod.yaml: |-
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: helper-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: helper-pod
|
||||||
|
image: busybox
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
|
1
logging/.gitignore
vendored
Normal file
1
logging/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
mongoexpress.yml
|
52
logging/README.md
Normal file
52
logging/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Logging infrastructure
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Fluent Bit picks up the logs from Kubernetes workers and sends them to Graylog
|
||||||
|
using GELF over TCP 12201.
|
||||||
|
|
||||||
|
Graylog ingests the logs and stores them in Elasticsearch.
|
||||||
|
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
To deploy:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create namespace logging
|
||||||
|
kubectl apply -n logging -f mongodb-support.yml -f application.yml -f networkpolicy-base.yml
|
||||||
|
kubectl rollout restart -n logging daemonset/fluent-bit
|
||||||
|
```
|
||||||
|
|
||||||
|
To set secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
GRAYLOG_ROOT_PASSWORD=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
echo "Graylog admin password: $GRAYLOG_ROOT_PASSWORD"
|
||||||
|
kubectl create secret generic -n logging graylog-secrets \
|
||||||
|
--from-literal=GRAYLOG_ROOT_PASSWORD_SHA2=$(echo -en $GRAYLOG_ROOT_PASSWORD | sha256sum | cut -d" " -f1) \
|
||||||
|
--from-literal=GRAYLOG_PASSWORD_SECRET=$(cat /dev/urandom | base64 | head -c 30)
|
||||||
|
kubectl create secret generic -n logging mongodb-application-readwrite-password --from-literal="password=$(cat /dev/urandom | base64 | head -c 30)"
|
||||||
|
kubectl create secret generic -n logging mongodb-application-readonly-password --from-literal="password=$(cat /dev/urandom | base64 | head -c 30)"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Graylog setup
|
||||||
|
|
||||||
|
Note that Graylog is running without disk journal to
|
||||||
|
prevent SSD thrashing and to save some disk space.
|
||||||
|
This will be problematic when there are loads for logs coming in and
|
||||||
|
ElasticSearch is unable to process the entries in timely manner.
|
||||||
|
ElasticSearch default index is tuned to match the persistent volume allocated
|
||||||
|
on Longhorn to prevent running out disk space on that PV.
|
||||||
|
|
||||||
|
After Graylog deployment following steps were manually performed via web interface:
|
||||||
|
|
||||||
|
* Add Syslog TCP input for external Linux hosts
|
||||||
|
* Add Syslog UDP input for Mikrotik networking gear
|
||||||
|
* Add GELF TCP input for Kubernetes workers
|
||||||
|
* Trusted header authentication was enabled and set to `Remote-User`
|
||||||
|
https://graylog.k-space.ee/system/authentication/authenticator/edit
|
||||||
|
Note that user accounts are not provisioned automatically.
|
||||||
|
Users need to be manually created in Graylog with matching `Username`.
|
||||||
|
Automatic user account provisioning is supported in Graylog Enterprise version
|
634
logging/application.yml
Normal file
634
logging/application.yml
Normal file
@ -0,0 +1,634 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit-read
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- namespaces
|
||||||
|
- pods
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit-read
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: fluent-bit-read
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: fluent-bit
|
||||||
|
namespace: logging
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit-config
|
||||||
|
namespace: logging
|
||||||
|
labels:
|
||||||
|
app: fluent-bit
|
||||||
|
annotations:
|
||||||
|
reloader.stakater.com/match: "true"
|
||||||
|
data:
|
||||||
|
fluent-bit.conf: |
|
||||||
|
[SERVICE]
|
||||||
|
Flush 1
|
||||||
|
Log_Level warn
|
||||||
|
Daemon off
|
||||||
|
Parsers_File parsers.conf
|
||||||
|
HTTP_Server On
|
||||||
|
HTTP_Listen 0.0.0.0
|
||||||
|
HTTP_Port 2020
|
||||||
|
@INCLUDE input-kubernetes.conf
|
||||||
|
@INCLUDE filter-kubernetes.conf
|
||||||
|
@INCLUDE output-graylog.conf
|
||||||
|
input-kubernetes.conf: |
|
||||||
|
# Following assembles the log fragments of the Kubernetes runtime
|
||||||
|
# https://github.com/fluent/fluent-bit/blob/d3c71f2ed4ff3625b85715aaefe6bc76b2ac3c2e/src/multiline/flb_ml_parser_docker.c#L57
|
||||||
|
[INPUT]
|
||||||
|
name tail
|
||||||
|
tag kube.*
|
||||||
|
path /var/log/containers/*.log
|
||||||
|
multiline.parser cri
|
||||||
|
db /var/log/flb_kube.db
|
||||||
|
mem_buf_limit 5MB
|
||||||
|
skip_long_lines on
|
||||||
|
refresh_interval 10
|
||||||
|
filter-kubernetes.conf: |
|
||||||
|
# Following reassembles stack traces
|
||||||
|
[FILTER]
|
||||||
|
name multiline
|
||||||
|
match *
|
||||||
|
multiline.key_content log
|
||||||
|
multiline.parser go,python,java
|
||||||
|
# Following annotates the Kubernetes logs using Kubernetes API-s
|
||||||
|
[FILTER]
|
||||||
|
Name kubernetes
|
||||||
|
Match kube.*
|
||||||
|
Kube_URL https://kubernetes.default.svc:443
|
||||||
|
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
Kube_Tag_Prefix kube.var.log.containers.
|
||||||
|
Merge_Log On
|
||||||
|
K8S-Logging.Parser On
|
||||||
|
K8S-Logging.Exclude Off
|
||||||
|
# Following unnests the kubernetes map
|
||||||
|
[FILTER]
|
||||||
|
Name nest
|
||||||
|
Match kube.*
|
||||||
|
Operation lift
|
||||||
|
Nested_under kubernetes
|
||||||
|
Add_prefix kubernetes_
|
||||||
|
output-graylog.conf: |
|
||||||
|
[OUTPUT]
|
||||||
|
Name gelf
|
||||||
|
Match *
|
||||||
|
Host graylog-gelf-tcp
|
||||||
|
Port 12201
|
||||||
|
Mode tcp
|
||||||
|
Gelf_Host_Key kubernetes_host
|
||||||
|
Gelf_Short_Message_Key log
|
||||||
|
Retry_Limit no_limits
|
||||||
|
parsers.conf: |
|
||||||
|
# http://rubular.com/r/tjUt3Awgg4
|
||||||
|
[PARSER]
|
||||||
|
Name cri
|
||||||
|
Format regex
|
||||||
|
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$
|
||||||
|
Time_Key time
|
||||||
|
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit
|
||||||
|
namespace: logging
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: patch
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
annotations:
|
||||||
|
reloader.stakater.com/search: "true"
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: fluent-bit
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: fluent-bit
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "2020"
|
||||||
|
prometheus.io/path: /api/v1/metrics/prometheus
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: fluent-bit
|
||||||
|
image: fluent/fluent-bit:1.9
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 2020
|
||||||
|
volumeMounts:
|
||||||
|
- name: varlog
|
||||||
|
mountPath: /var/log
|
||||||
|
- name: varlibdockercontainers
|
||||||
|
mountPath: /var/lib/docker/containers
|
||||||
|
readOnly: true
|
||||||
|
- name: fluent-bit-config
|
||||||
|
mountPath: /fluent-bit/etc/
|
||||||
|
volumes:
|
||||||
|
- name: varlog
|
||||||
|
hostPath:
|
||||||
|
path: /var/log
|
||||||
|
- name: varlibdockercontainers
|
||||||
|
hostPath:
|
||||||
|
path: /var/lib/docker/containers
|
||||||
|
- name: fluent-bit-config
|
||||||
|
configMap:
|
||||||
|
name: fluent-bit-config
|
||||||
|
serviceAccountName: fluent-bit
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/master
|
||||||
|
operator: Exists
|
||||||
|
effect: NoSchedule
|
||||||
|
- operator: "Exists"
|
||||||
|
effect: "NoExecute"
|
||||||
|
- operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: fluent-bit
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: fluent-bit
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: monitoring
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: prometheus
|
||||||
|
ports:
|
||||||
|
- port: 2020
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: graylog
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 12201
|
||||||
|
- # Kubernetes API endpoint kubernetes.default.svc.cluster.local
|
||||||
|
# Determine IP-s and ports with: kubectl get ep -n default kubernetes
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 172.21.3.0/24
|
||||||
|
ports:
|
||||||
|
- port: 6443
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
labels:
|
||||||
|
app: elasticsearch
|
||||||
|
spec:
|
||||||
|
serviceName: elasticsearch
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: elasticsearch
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: elasticsearch
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: elasticsearch
|
||||||
|
image: elasticsearch:7.17.3
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
env:
|
||||||
|
- name: discovery.type
|
||||||
|
value: single-node
|
||||||
|
- name: xpack.security.enabled
|
||||||
|
value: "false"
|
||||||
|
ports:
|
||||||
|
- containerPort: 9200
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /_cluster/health
|
||||||
|
port: 9200
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "2147483648"
|
||||||
|
volumeMounts:
|
||||||
|
- name: elasticsearch-data
|
||||||
|
mountPath: /usr/share/elasticsearch/data
|
||||||
|
- name: elasticsearch-tmp
|
||||||
|
mountPath: /tmp/
|
||||||
|
volumes:
|
||||||
|
- emptyDir: {}
|
||||||
|
name: elasticsearch-keystore
|
||||||
|
- emptyDir: {}
|
||||||
|
name: elasticsearch-tmp
|
||||||
|
- emptyDir: {}
|
||||||
|
name: elasticsearch-logs
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: elasticsearch-data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- "ReadWriteOnce"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "10Gi"
|
||||||
|
storageClassName: longhorn
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
labels:
|
||||||
|
app: elasticsearch
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: api
|
||||||
|
port: 80
|
||||||
|
targetPort: 9200
|
||||||
|
selector:
|
||||||
|
app: elasticsearch
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: graylog-gelf-tcp
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: graylog-gelf-tcp
|
||||||
|
port: 12201
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 12201
|
||||||
|
selector:
|
||||||
|
app: graylog
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: graylog-syslog-tcp
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
annotations:
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: syslog.k-space.ee
|
||||||
|
metallb.universe.tf/allow-shared-ip: syslog.k-space.ee
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
externalTrafficPolicy: Local
|
||||||
|
loadBalancerIP: 172.20.51.4
|
||||||
|
ports:
|
||||||
|
- name: graylog-syslog
|
||||||
|
port: 514
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
app: graylog
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: graylog-syslog-udp
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
annotations:
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: syslog.k-space.ee
|
||||||
|
metallb.universe.tf/allow-shared-ip: syslog.k-space.ee
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
externalTrafficPolicy: Local
|
||||||
|
loadBalancerIP: 172.20.51.4
|
||||||
|
ports:
|
||||||
|
- name: graylog-syslog
|
||||||
|
port: 514
|
||||||
|
protocol: UDP
|
||||||
|
selector:
|
||||||
|
app: graylog
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: graylog
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: graylog
|
||||||
|
port: 9000
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
app: graylog
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: graylog
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: minor
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
serviceName: graylog
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: graylog
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: graylog
|
||||||
|
annotations:
|
||||||
|
prometheus.io/port: "9833"
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1100
|
||||||
|
volumes:
|
||||||
|
- name: graylog-config
|
||||||
|
downwardAPI:
|
||||||
|
items:
|
||||||
|
- path: id
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
containers:
|
||||||
|
- name: graylog
|
||||||
|
image: graylog/graylog:4.3
|
||||||
|
env:
|
||||||
|
- name: GRAYLOG_MONGODB_URI
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mongodb-application-readwrite
|
||||||
|
key: connectionString.standard
|
||||||
|
- name: GRAYLOG_PROMETHEUS_EXPORTER_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: GRAYLOG_PROMETHEUS_EXPORTER_BIND_ADDRESS
|
||||||
|
value: "0.0.0.0:9833"
|
||||||
|
- name: GRAYLOG_NODE_ID_FILE
|
||||||
|
value: /config/id
|
||||||
|
- name: GRAYLOG_HTTP_EXTERNAL_URI
|
||||||
|
value: "https://graylog.k-space.ee/"
|
||||||
|
- name: GRAYLOG_TRUSTED_PROXIES
|
||||||
|
value: "0.0.0.0/0"
|
||||||
|
- name: GRAYLOG_ELASTICSEARCH_HOSTS
|
||||||
|
value: "http://elasticsearch"
|
||||||
|
- name: GRAYLOG_MESSAGE_JOURNAL_ENABLED
|
||||||
|
value: "false"
|
||||||
|
- name: GRAYLOG_ROTATION_STRATEGY
|
||||||
|
value: "size"
|
||||||
|
- name: GRAYLOG_ELASTICSEARCH_MAX_SIZE_PER_INDEX
|
||||||
|
value: "268435456"
|
||||||
|
- name: GRAYLOG_ELASTICSEARCH_MAX_NUMBER_OF_INDICES
|
||||||
|
value: "16"
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: graylog-secrets
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1100
|
||||||
|
ports:
|
||||||
|
- containerPort: 9000
|
||||||
|
name: graylog
|
||||||
|
- containerPort: 9833
|
||||||
|
name: graylog-metrics
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/system/lbstatus
|
||||||
|
port: 9000
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 30
|
||||||
|
failureThreshold: 3
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/system/lbstatus
|
||||||
|
port: 9000
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
volumeMounts:
|
||||||
|
- name: graylog-config
|
||||||
|
mountPath: /config
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: graylog
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: graylog.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: graylog
|
||||||
|
port:
|
||||||
|
number: 9000
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- graylog.k-space.ee
|
||||||
|
secretName: graylog-tls
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: graylog
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: graylog
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: elasticsearch
|
||||||
|
ports:
|
||||||
|
- port: 9200
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: mongodb-svc
|
||||||
|
ports:
|
||||||
|
- port: 27017
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 172.23.0.0/16
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 172.21.0.0/16
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 100.102.0.0/16
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 514
|
||||||
|
- protocol: TCP
|
||||||
|
port: 514
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: fluent-bit
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 12201
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: monitoring
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: prometheus
|
||||||
|
ports:
|
||||||
|
- port: 9833
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9000
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: elasticsearch
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: elasticsearch
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: graylog
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
# geoip.elastic.co updates
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
ports:
|
||||||
|
- port: 443
|
||||||
|
---
|
||||||
|
apiVersion: mongodbcommunity.mongodb.com/v1
|
||||||
|
kind: MongoDBCommunity
|
||||||
|
metadata:
|
||||||
|
name: mongodb
|
||||||
|
spec:
|
||||||
|
members: 3
|
||||||
|
type: ReplicaSet
|
||||||
|
version: "5.0.9"
|
||||||
|
security:
|
||||||
|
authentication:
|
||||||
|
modes: ["SCRAM"]
|
||||||
|
users:
|
||||||
|
- name: readwrite
|
||||||
|
db: application
|
||||||
|
passwordSecretRef:
|
||||||
|
name: mongodb-application-readwrite-password
|
||||||
|
roles:
|
||||||
|
- name: readWrite
|
||||||
|
db: application
|
||||||
|
scramCredentialsSecretName: mongodb-application-readwrite
|
||||||
|
- name: readonly
|
||||||
|
db: application
|
||||||
|
passwordSecretRef:
|
||||||
|
name: mongodb-application-readonly-password
|
||||||
|
roles:
|
||||||
|
- name: readOnly
|
||||||
|
db: application
|
||||||
|
scramCredentialsSecretName: mongodb-application-readonly
|
||||||
|
statefulSet:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- mongodb-svc
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: logs-volume
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 512Mi
|
||||||
|
- metadata:
|
||||||
|
name: data-volume
|
||||||
|
spec:
|
||||||
|
storageClassName: local-path
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
1
logging/mongodb-support.yml
Symbolic link
1
logging/mongodb-support.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../mongodb-operator/mongodb-support.yml
|
1
logging/networkpolicy-base.yml
Symbolic link
1
logging/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
20
longhorn-system/README.md
Normal file
20
longhorn-system/README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Longhorn distributed block storage system
|
||||||
|
|
||||||
|
The manifest was fetched from
|
||||||
|
https://raw.githubusercontent.com/longhorn/longhorn/v1.2.4/deploy/longhorn.yaml
|
||||||
|
and then heavily modified.
|
||||||
|
|
||||||
|
To deploy Longhorn use following:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n longhorn-system apply -f longhorn.yaml -f ingress.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
After deploying specify `dedicated=storage:NoSchedule`
|
||||||
|
for `Kubernetes Taint Toleration` under `Setting -> General` on
|
||||||
|
[Longhorn Dashboard](https://longhorn.k-space.ee/).
|
||||||
|
Proceed to tag suitable nodes with `storage` and disable Longhorn scheduling on others.
|
||||||
|
|
||||||
|
# Known issues
|
||||||
|
|
||||||
|
* Longhorn does not support [trim](https://github.com/longhorn/longhorn/issues/836)
|
28
longhorn-system/ingress.yml
Normal file
28
longhorn-system/ingress.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: longhorn-dashboard
|
||||||
|
namespace: longhorn-system
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: longhorn.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: longhorn-frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- longhorn.k-space.ee
|
||||||
|
secretName: longhorn-tls
|
1214
longhorn-system/longhorn.yaml
Normal file
1214
longhorn-system/longhorn.yaml
Normal file
File diff suppressed because it is too large
Load Diff
27
longhorn-system/values.yaml
Normal file
27
longhorn-system/values.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
persistence:
|
||||||
|
defaultClassReplicaCount: 2
|
||||||
|
|
||||||
|
defaultSettings:
|
||||||
|
defaultDataLocality: best-effort
|
||||||
|
taintToleration: "dedicated=storage:NoSchedule"
|
||||||
|
systemManagedComponentsNodeSelector: "dedicated:storage"
|
||||||
|
|
||||||
|
longhornDriver:
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
|
||||||
|
longhornUI:
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
host: longhorn.k-space.ee
|
||||||
|
tls: true
|
||||||
|
tlsSecret: longhorn-tls
|
29
metallb-system/README.md
Normal file
29
metallb-system/README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# MetalLB
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
MetalLB exposes services to the outside world.
|
||||||
|
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
To update manifests:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -O https://raw.githubusercontent.com/metallb/metallb-operator/v0.13.4/bin/metallb-operator.yaml
|
||||||
|
kubectl apply -f metallb-operator.yaml
|
||||||
|
kubectl apply -f application.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Set up BGP secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl delete secret -n metallb-system mikrotik-router
|
||||||
|
kubectl create secret -n metallb-system generic mikrotik-router --type=kubernetes.io/basic-auth --from-literal=password=...
|
||||||
|
```
|
||||||
|
|
||||||
|
Eventually the external IP should show up here:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get svc -n traefik
|
||||||
|
```
|
60
metallb-system/application.yml
Normal file
60
metallb-system/application.yml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: MetalLB
|
||||||
|
metadata:
|
||||||
|
name: metallb
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
node-role.kubernetes.io/worker: ""
|
||||||
|
---
|
||||||
|
# Slice of the private Zoo subnet using MetalLB L2 method
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: IPAddressPool
|
||||||
|
metadata:
|
||||||
|
name: zoo
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
addresses:
|
||||||
|
- 172.20.51.0/24
|
||||||
|
---
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: L2Advertisement
|
||||||
|
metadata:
|
||||||
|
name: zoo
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
ipAddressPools:
|
||||||
|
- zoo
|
||||||
|
---
|
||||||
|
# Slice of public EEnet subnet using MetalLB L3 method
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: IPAddressPool
|
||||||
|
metadata:
|
||||||
|
name: eenet
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
addresses:
|
||||||
|
- 193.40.103.36/30
|
||||||
|
---
|
||||||
|
apiVersion: metallb.io/v1beta2
|
||||||
|
kind: BGPPeer
|
||||||
|
metadata:
|
||||||
|
name: mikrotik-router
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
myASN: 65530
|
||||||
|
peerASN: 65530
|
||||||
|
peerAddress: 172.20.0.1
|
||||||
|
passwordSecret:
|
||||||
|
name: mikrotik-router
|
||||||
|
namespace: metallb-system
|
||||||
|
---
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: BGPAdvertisement
|
||||||
|
metadata:
|
||||||
|
name: eenet
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
ipAddressPools:
|
||||||
|
- eenet
|
2200
metallb-system/metallb-operator.yaml
Normal file
2200
metallb-system/metallb-operator.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1
mongodb-operator/.gitignore
vendored
Normal file
1
mongodb-operator/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
application.yml
|
36
mongodb-operator/README.md
Normal file
36
mongodb-operator/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# MongoDB Community Kubernetes Operator
|
||||||
|
|
||||||
|
To update operator itself:
|
||||||
|
|
||||||
|
```
|
||||||
|
helm repo add mongodb https://mongodb.github.io/helm-charts
|
||||||
|
helm template -n mongodb-operator community-operator mongodb/community-operator -f values.yaml > application.yml
|
||||||
|
kubectl create namespace mongodb-operator
|
||||||
|
kubectl apply -f application.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
To update RBAC rules:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/role.yaml > mongodb-support.yml
|
||||||
|
echo "---" >> mongodb-support.yml
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/role_binding.yaml >> mongodb-support.yml
|
||||||
|
echo "---" >> mongodb-support.yml
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/role_binding_database.yaml >> mongodb-support.yml
|
||||||
|
echo "---" >> mongodb-support.yml
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/role_database.yaml >> mongodb-support.yml
|
||||||
|
echo "---" >> mongodb-support.yml
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/service_account.yaml >> mongodb-support.yml
|
||||||
|
echo "---" >> mongodb-support.yml
|
||||||
|
curl https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/master/config/rbac/service_account_database.yaml >> mongodb-support.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
# Instantiating databases
|
||||||
|
|
||||||
|
For each application:
|
||||||
|
|
||||||
|
```
|
||||||
|
ln -s ../mongodb/mongo-support.yml
|
||||||
|
kubectl apply -f mongo-support.yml
|
||||||
|
kubectl create secret generic -n default mongodb-application-user-password --from-literal="password=$(cat /dev/urandom | base64 | head -c 30)"
|
||||||
|
```
|
126
mongodb-operator/mongodb-support.yml
Normal file
126
mongodb-operator/mongodb-support.yml
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: mongodb-kubernetes-operator
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- services
|
||||||
|
- configmaps
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- statefulsets
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- mongodbcommunity.mongodb.com
|
||||||
|
resources:
|
||||||
|
- mongodbcommunity
|
||||||
|
- mongodbcommunity/status
|
||||||
|
- mongodbcommunity/spec
|
||||||
|
- mongodbcommunity/finalizers
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- list
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mongodb-kubernetes-operator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: mongodb-kubernetes-operator
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: mongodb-kubernetes-operator
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mongodb-database
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: mongodb-database
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: mongodb-database
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: mongodb-database
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: mongodb-kubernetes-operator
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: mongodb-database
|
||||||
|
---
|
||||||
|
# Allow any pod in this namespace to connect to MongoDB and
|
||||||
|
# allow cluster members to talk to eachother
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: mongodb-operator
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: mongodb-svc
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector: {}
|
||||||
|
ports:
|
||||||
|
- port: 27017
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: mongodb-svc
|
||||||
|
ports:
|
||||||
|
- port: 27017
|
2
mongodb-operator/values.yaml
Normal file
2
mongodb-operator/values.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
operator:
|
||||||
|
watchNamespace: '*'
|
3
mysql-operator/README.md
Normal file
3
mysql-operator/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
helm template mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --include-crds > application.yml
|
||||||
|
kubectl apply -n mysql-operator -f application.yml -f application-extras.yml -f networkpolicy-base.yml
|
||||||
|
|
16
mysql-operator/application-extras.yml
Normal file
16
mysql-operator/application-extras.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- # TODO: Not sure why mysql-operator needs to be able to connect
|
||||||
|
to:
|
||||||
|
- namespaceSelector: {}
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
608
mysql-operator/application.yml
Normal file
608
mysql-operator/application.yml
Normal file
@ -0,0 +1,608 @@
|
|||||||
|
---
|
||||||
|
# Source: crds/crd.yaml
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: innodbclusters.mysql.oracle.com
|
||||||
|
spec:
|
||||||
|
group: mysql.oracle.com
|
||||||
|
versions:
|
||||||
|
- name: v2
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
required: ["spec"]
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
maxLength: 40
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
required: ["secretName"]
|
||||||
|
properties:
|
||||||
|
secretName:
|
||||||
|
type: string
|
||||||
|
description: "Name of a generic type Secret containing root/default account password"
|
||||||
|
tlsCASecretName:
|
||||||
|
type: string
|
||||||
|
description: "Name of a generic type Secret containing CA (ca.pem) and optional CRL (crl.pem) for SSL"
|
||||||
|
tlsSecretName:
|
||||||
|
type: string
|
||||||
|
description: "Name of a TLS type Secret containing Server certificate and private key for SSL"
|
||||||
|
tlsUseSelfSigned:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "Enables use of self-signed TLS certificates, reducing or disabling TLS based security verifications"
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
pattern: '^\d+\.\d+\.\d+(-.+)?'
|
||||||
|
description: "MySQL Server version"
|
||||||
|
edition:
|
||||||
|
type: string
|
||||||
|
pattern: "^(community|enterprise)$"
|
||||||
|
description: "MySQL Server Edition (community or enterprise)"
|
||||||
|
imageRepository:
|
||||||
|
type: string
|
||||||
|
description: "Repository from where images must be pulled from; defaults to mysql for community and container-registry.oracle.com/mysql for enterprise"
|
||||||
|
imagePullPolicy:
|
||||||
|
type: string
|
||||||
|
description: "Defaults to Always, but set to IfNotPresent in deploy-operator.yaml when deploying Operator"
|
||||||
|
imagePullSecrets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
serviceAccountName:
|
||||||
|
type: string
|
||||||
|
baseServerId:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
maximum: 4294967195
|
||||||
|
default: 1000
|
||||||
|
description: "Base value for MySQL server_id for instances in the cluster"
|
||||||
|
datadirVolumeClaimTemplate:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
description: "Template for a PersistentVolumeClaim, to be used as datadir"
|
||||||
|
mycnf:
|
||||||
|
type: string
|
||||||
|
description: "Custom configuration additions for my.cnf"
|
||||||
|
instances:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maximum: 9
|
||||||
|
default: 1
|
||||||
|
description: "Number of MySQL replica instances for the cluster"
|
||||||
|
podSpec:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
initDB:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
clone:
|
||||||
|
type: object
|
||||||
|
required: ["donorUrl", "secretKeyRef"]
|
||||||
|
properties:
|
||||||
|
donorUrl:
|
||||||
|
type: string
|
||||||
|
description: "URL of the cluster to clone from"
|
||||||
|
rootUser:
|
||||||
|
type: string
|
||||||
|
default: "root"
|
||||||
|
description: "User name used for cloning"
|
||||||
|
secretKeyRef:
|
||||||
|
type: object
|
||||||
|
required: ["name"]
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: "Secret name with key 'rootPassword' storing the password for the user specified in rootUser"
|
||||||
|
dump:
|
||||||
|
type: object
|
||||||
|
required: ["storage"]
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: "Name of the dump. Not used by the operator, but a descriptive hint for the cluster administrator"
|
||||||
|
path:
|
||||||
|
type: string
|
||||||
|
description: "Path to the dump in the PVC. Use when specifying persistentVolumeClaim. Omit for ociObjectStorage."
|
||||||
|
storage:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
ociObjectStorage:
|
||||||
|
type: object
|
||||||
|
required: ["bucketName", "prefix", "credentials"]
|
||||||
|
properties:
|
||||||
|
bucketName:
|
||||||
|
type: string
|
||||||
|
description: "Name of the bucket where the dump is stored"
|
||||||
|
prefix:
|
||||||
|
type: string
|
||||||
|
description: "Path in the bucket where the dump files are stored"
|
||||||
|
credentials:
|
||||||
|
type: string
|
||||||
|
description: "Secret name with data for accessing the bucket"
|
||||||
|
persistentVolumeClaim:
|
||||||
|
type: object
|
||||||
|
description : "Specification of the PVC to be used. Used 'as is' in the cloning pod."
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
router:
|
||||||
|
type: object
|
||||||
|
description: "MySQL Router specification"
|
||||||
|
properties:
|
||||||
|
instances:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
default: 1
|
||||||
|
description: "Number of MySQL Router instances to deploy"
|
||||||
|
tlsSecretName:
|
||||||
|
type: string
|
||||||
|
description: "Name of a TLS type Secret containing MySQL Router certificate and private key used for SSL"
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
pattern: '^\d+\.\d+\.\d+(-.+)?'
|
||||||
|
description: "Override MySQL Router version"
|
||||||
|
podSpec:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
backupProfiles:
|
||||||
|
type: array
|
||||||
|
description: "Backup profile specifications for the cluster, which can be referenced from backup schedules and one-off backup jobs"
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required: ["name"]
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: "Embedded backup profile, referenced as backupProfileName elsewhere"
|
||||||
|
dumpInstance:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
dumpOptions:
|
||||||
|
type: object
|
||||||
|
description: "A dictionary of key-value pairs passed directly to MySQL Shell's DumpInstance()"
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
storage:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
ociObjectStorage:
|
||||||
|
type: object
|
||||||
|
required: ["bucketName", "prefix", "credentials"]
|
||||||
|
properties:
|
||||||
|
bucketName:
|
||||||
|
type: string
|
||||||
|
description: "Bucket name where backup is stored"
|
||||||
|
prefix:
|
||||||
|
type: string
|
||||||
|
description: "Path in bucket where backup is stored"
|
||||||
|
credentials:
|
||||||
|
type: string
|
||||||
|
description: "Secret name with data for accessing the bucket"
|
||||||
|
persistentVolumeClaim:
|
||||||
|
type: object
|
||||||
|
description : "Specification of the PVC to be used. Used 'as is' in pod executing the backup."
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
snapshot:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
storage:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
ociObjectStorage:
|
||||||
|
type: object
|
||||||
|
required: ["bucketName", "prefix", "credentials"]
|
||||||
|
properties:
|
||||||
|
bucketName:
|
||||||
|
type: string
|
||||||
|
description: "Bucket name where backup is stored"
|
||||||
|
prefix:
|
||||||
|
type: string
|
||||||
|
description: "Path in bucket where backup is stored"
|
||||||
|
credentials:
|
||||||
|
type: string
|
||||||
|
description: "Secret name with data for accessing the bucket"
|
||||||
|
persistentVolumeClaim:
|
||||||
|
type: object
|
||||||
|
description : "Specification of the PVC to be used. Used 'as is' in pod executing the backup."
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
backupSchedules:
|
||||||
|
type: array
|
||||||
|
description: "Schedules for periodically executed backups"
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required: ["name", "schedule"]
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: "Name of the backup schedule"
|
||||||
|
schedule:
|
||||||
|
type: string
|
||||||
|
description: "The schedule of the job, syntax as a cron expression"
|
||||||
|
backupProfileName:
|
||||||
|
type: string
|
||||||
|
description: "Name of the backupProfile to be used"
|
||||||
|
backupProfile:
|
||||||
|
type: object
|
||||||
|
description: "backupProfile specification if backupProfileName is not specified"
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
deleteBackupData:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "Whether to delete the backup data in case the MySQLBackup object created by the job is deleted"
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
description: "Whether the schedule is enabled or not"
|
||||||
|
status:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
additionalPrinterColumns:
|
||||||
|
- name: Status
|
||||||
|
type: string
|
||||||
|
description: Status of the InnoDB Cluster
|
||||||
|
jsonPath: .status.cluster.status
|
||||||
|
- name: Online
|
||||||
|
type: integer
|
||||||
|
description: Number of ONLINE InnoDB Cluster instances
|
||||||
|
jsonPath: .status.cluster.onlineInstances
|
||||||
|
- name: Instances
|
||||||
|
type: integer
|
||||||
|
description: Number of InnoDB Cluster instances configured
|
||||||
|
jsonPath: .spec.instances
|
||||||
|
- name: Routers
|
||||||
|
type: integer
|
||||||
|
description: Number of Router instances configured for the InnoDB Cluster
|
||||||
|
jsonPath: .spec.router.instances
|
||||||
|
- name: Age
|
||||||
|
type: date
|
||||||
|
jsonPath: .metadata.creationTimestamp
|
||||||
|
scope: Namespaced
|
||||||
|
names:
|
||||||
|
kind: InnoDBCluster
|
||||||
|
listKind: InnoDBClusterList
|
||||||
|
singular: innodbcluster
|
||||||
|
plural: innodbclusters
|
||||||
|
shortNames:
|
||||||
|
- ic
|
||||||
|
- ics
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: mysqlbackups.mysql.oracle.com
|
||||||
|
spec:
|
||||||
|
group: mysql.oracle.com
|
||||||
|
scope: Namespaced
|
||||||
|
names:
|
||||||
|
kind: MySQLBackup
|
||||||
|
listKind: MySQLBackupList
|
||||||
|
singular: mysqlbackup
|
||||||
|
plural: mysqlbackups
|
||||||
|
shortNames:
|
||||||
|
- mbk
|
||||||
|
versions:
|
||||||
|
- name: v2
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
required: ["clusterName"]
|
||||||
|
properties:
|
||||||
|
clusterName:
|
||||||
|
type: string
|
||||||
|
backupProfileName:
|
||||||
|
type: string
|
||||||
|
backupProfile:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
addTimestampToBackupDirectory:
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
deleteBackupData:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
status:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
startTime:
|
||||||
|
type: string
|
||||||
|
completionTime:
|
||||||
|
type: string
|
||||||
|
elapsedTime:
|
||||||
|
type: string
|
||||||
|
output:
|
||||||
|
type: string
|
||||||
|
method:
|
||||||
|
type: string
|
||||||
|
source:
|
||||||
|
type: string
|
||||||
|
bucket:
|
||||||
|
type: string
|
||||||
|
ociTenancy:
|
||||||
|
type: string
|
||||||
|
spaceAvailable:
|
||||||
|
type: string
|
||||||
|
size:
|
||||||
|
type: string
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
additionalPrinterColumns:
|
||||||
|
- name: Cluster
|
||||||
|
type: string
|
||||||
|
description: Name of the target cluster
|
||||||
|
jsonPath: .spec.clusterName
|
||||||
|
- name: Status
|
||||||
|
type: string
|
||||||
|
description: Status of the Backup
|
||||||
|
jsonPath: .status.status
|
||||||
|
- name: Output
|
||||||
|
type: string
|
||||||
|
description: Name of the produced file/directory
|
||||||
|
jsonPath: .status.output
|
||||||
|
- name: Age
|
||||||
|
type: date
|
||||||
|
jsonPath: .metadata.creationTimestamp
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: clusterkopfpeerings.zalando.org
|
||||||
|
spec:
|
||||||
|
scope: Cluster
|
||||||
|
group: zalando.org
|
||||||
|
names:
|
||||||
|
kind: ClusterKopfPeering
|
||||||
|
plural: clusterkopfpeerings
|
||||||
|
singular: clusterkopfpeering
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: kopfpeerings.zalando.org
|
||||||
|
spec:
|
||||||
|
scope: Namespaced
|
||||||
|
group: zalando.org
|
||||||
|
names:
|
||||||
|
kind: KopfPeering
|
||||||
|
plural: kopfpeerings
|
||||||
|
singular: kopfpeering
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/service_account_operator.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator-sa
|
||||||
|
namespace: mysql-operator
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/cluster_role_operator.yaml
|
||||||
|
# The main role for the operator
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods/status"]
|
||||||
|
verbs: ["get", "patch", "update", "watch"]
|
||||||
|
# Kopf needs patch on secrets or the sidecar will throw
|
||||||
|
# The operator needs this verb to be able to pass it to the sidecar
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get", "create", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps"]
|
||||||
|
verbs: ["get", "create", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["serviceaccounts"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["create", "patch", "update"]
|
||||||
|
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||||
|
resources: ["rolebindings"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: ["policy"]
|
||||||
|
resources: ["poddisruptionbudgets"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: ["batch"]
|
||||||
|
resources: ["jobs"]
|
||||||
|
verbs: ["create"]
|
||||||
|
- apiGroups: ["batch"]
|
||||||
|
resources: ["cronjobs"]
|
||||||
|
verbs: ["create", "update", "delete"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments", "statefulsets"]
|
||||||
|
verbs: ["get", "create", "patch", "watch", "delete"]
|
||||||
|
- apiGroups: ["mysql.oracle.com"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["*"]
|
||||||
|
- apiGroups: ["zalando.org"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["get", "patch", "list", "watch"]
|
||||||
|
# Kopf: runtime observation of namespaces & CRDs (addition/deletion).
|
||||||
|
- apiGroups: [apiextensions.k8s.io]
|
||||||
|
resources: [customresourcedefinitions]
|
||||||
|
verbs: [list, watch]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [namespaces]
|
||||||
|
verbs: [list, watch]
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/cluster_role_sidecar.yaml
|
||||||
|
# role for the server sidecar
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: mysql-sidecar
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods/status"]
|
||||||
|
verbs: ["get", "patch", "update", "watch"]
|
||||||
|
# Kopf needs patch on secrets or the sidecar will throw
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get", "create", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["configmaps"]
|
||||||
|
verbs: ["get", "create", "list", "watch", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["serviceaccounts"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["create", "patch", "update"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments"]
|
||||||
|
verbs: ["get", "patch"]
|
||||||
|
- apiGroups: ["mysql.oracle.com"]
|
||||||
|
resources: ["innodbclusters"]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
- apiGroups: ["mysql.oracle.com"]
|
||||||
|
resources: ["mysqlbackups"]
|
||||||
|
verbs: ["create", "get", "list", "patch", "update", "watch", "delete"]
|
||||||
|
- apiGroups: ["mysql.oracle.com"]
|
||||||
|
resources: ["mysqlbackups/status"]
|
||||||
|
verbs: ["get", "patch", "update", "watch"]
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/cluster_role_binding_operator.yaml
|
||||||
|
# Give access to the operator
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator-rolebinding
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: mysql-operator-sa
|
||||||
|
namespace: mysql-operator
|
||||||
|
# TODO The following entry is for dev purposes only and must be deleted
|
||||||
|
#- kind: Group
|
||||||
|
# name: system:serviceaccounts
|
||||||
|
# apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: mysql-operator
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/service.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
namespace: mysql-operator
|
||||||
|
labels:
|
||||||
|
name: mysql-operator
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 9443
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
name: mysql-operator
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
||||||
|
namespace: mysql-operator
|
||||||
|
labels:
|
||||||
|
version: "8.0.30-2.0.5"
|
||||||
|
app.kubernetes.io/name: mysql-operator
|
||||||
|
app.kubernetes.io/instance: mysql-operator
|
||||||
|
app.kubernetes.io/version: "8.0.30-2.0.5"
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/managed-by: helm
|
||||||
|
app.kubernetes.io/created-by: helm
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: mysql-operator
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: mysql-operator
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: mysql-operator
|
||||||
|
image: mysql/mysql-operator:8.0.30-2.0.5
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
args: ["mysqlsh", "--log-level=@INFO", "--pym", "mysqloperator", "operator"]
|
||||||
|
env:
|
||||||
|
- name: MYSQLSH_USER_CONFIG_HOME
|
||||||
|
value: /mysqlsh
|
||||||
|
|
||||||
|
|
||||||
|
- name: MYSQL_OPERATOR_IMAGE_PULL_POLICY
|
||||||
|
value: IfNotPresent
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- name: mysqlsh-home
|
||||||
|
mountPath: /mysqlsh
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
privileged: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
volumes:
|
||||||
|
- name: mysqlsh-home
|
||||||
|
emptyDir: {}
|
||||||
|
serviceAccountName: mysql-operator-sa
|
||||||
|
---
|
||||||
|
# Source: mysql-operator/templates/cluster_kopf_keepering.yaml
|
||||||
|
apiVersion: zalando.org/v1
|
||||||
|
kind: ClusterKopfPeering
|
||||||
|
metadata:
|
||||||
|
name: mysql-operator
|
1
mysql-operator/networkpolicy-base.yml
Symbolic link
1
mysql-operator/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
5
phpmyadmin/README.md
Normal file
5
phpmyadmin/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# phpMyAdmin
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n phpmyadmin -f application.yml
|
||||||
|
```
|
108
phpmyadmin/application.yml
Normal file
108
phpmyadmin/application.yml
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: phpmyadmin
|
||||||
|
labels:
|
||||||
|
app: phpmyadmin
|
||||||
|
spec:
|
||||||
|
# phpMyAdmin session handling is not really compatible with more replicas
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: phpmyadmin
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: phpmyadmin
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: phpmyadmin
|
||||||
|
image: phpmyadmin/phpmyadmin
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: PMA_ARBITRARY
|
||||||
|
value: "1"
|
||||||
|
- name: PMA_HOSTS
|
||||||
|
value: mysql-cluster.etherpad.svc.cluster.local,mariadb.authelia,mariadb.nextcloud,172.20.36.1
|
||||||
|
- name: PMA_ABSOLUTE_URI
|
||||||
|
value: https://phpmyadmin.k-space.ee/
|
||||||
|
- name: UPLOAD_LIMIT
|
||||||
|
value: 10G
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: phpmyadmin
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: default
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: phpmyadmin.k-space.ee
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: phpmyadmin
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- phpmyadmin.k-space.ee
|
||||||
|
secretName: phpmyadmin-tls
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: phpmyadmin
|
||||||
|
labels:
|
||||||
|
app: phpmyadmin
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: phpmyadmin
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: phpmyadmin
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: phpmyadmin
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
egress:
|
||||||
|
- # Allow connecting to MySQL instance in any namespace
|
||||||
|
to:
|
||||||
|
- namespaceSelector: {}
|
||||||
|
ports:
|
||||||
|
- port: 3306
|
||||||
|
- # Allow connecting to any MySQL instance outside the cluster
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
1
phpmyadmin/networkpolicy-base.yml
Symbolic link
1
phpmyadmin/networkpolicy-base.yml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../shared/networkpolicy-base.yml
|
109
reloader/application.yml
Normal file
109
reloader/application.yml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: reloader
|
||||||
|
name: reloader
|
||||||
|
namespace: reloader
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: reloader
|
||||||
|
name: reloader-role
|
||||||
|
namespace: reloader
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
- daemonsets
|
||||||
|
- statefulsets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
- daemonsets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: reloader
|
||||||
|
name: reloader-role-binding
|
||||||
|
namespace: reloader
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: reloader-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: reloader
|
||||||
|
namespace: reloader
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: reloader
|
||||||
|
name: reloader
|
||||||
|
namespace: reloader
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: reloader
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: reloader
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: "stakater/reloader:v0.0.118"
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: reloader
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 9090
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /metrics
|
||||||
|
port: http
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /metrics
|
||||||
|
port: http
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65534
|
||||||
|
serviceAccountName: reloader
|
3
rosdump/.gitignore
vendored
Normal file
3
rosdump/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
rosdump
|
||||||
|
rosdump.pub
|
||||||
|
ssh_known_hosts
|
68
rosdump/README.md
Normal file
68
rosdump/README.md
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# Intro
|
||||||
|
|
||||||
|
This is how we make backups of Mikrotik device configurations using Kubernetes
|
||||||
|
Cronjob. This is easy to monitor with Prometheus and integrates well with the
|
||||||
|
rest of our montioring system. Also the script/manifest is less than 100 lines,
|
||||||
|
easy to follow and to fix.
|
||||||
|
|
||||||
|
Note that this does not have anything to do with
|
||||||
|
[ecadlabs/rosdump](https://github.com/ecadlabs/rosdump)
|
||||||
|
we initially used which just generated empty commits and
|
||||||
|
there was no easy way to monitor.
|
||||||
|
|
||||||
|
We also considered [ytti/oxidized](https://github.com/ytti/oxidized),
|
||||||
|
but it does not export Prometheus metrics either.
|
||||||
|
|
||||||
|
|
||||||
|
# Deployment
|
||||||
|
|
||||||
|
To apply changes run in this directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -n rosdump -f cronjob.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
To trigger cronjob:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl create job -n rosdump --from=cronjob/rosdump-cronjob rosdump-job-oneshot
|
||||||
|
```
|
||||||
|
|
||||||
|
For alerting:
|
||||||
|
|
||||||
|
```
|
||||||
|
absent(kube_cronjob_status_last_successful_time{cronjob="rosdump-cronjob"})
|
||||||
|
```
|
||||||
|
|
||||||
|
# Updating SSH public keys
|
||||||
|
|
||||||
|
Whenever Mikrotik targets are added/removed or if their SSH keys change,
|
||||||
|
use following to apply changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
(for j in $(kubectl get cm -n rosdump rosdump-config -o json | jq -r '.data.targets'); do ssh-keyscan -t rsa $j; done) > ssh_known_hosts
|
||||||
|
kubectl delete -n rosdump configmap rosdump-known-hosts
|
||||||
|
kubectl create -n rosdump configmap rosdump-known-hosts --from-file=ssh_known_hosts
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure strong crypto is enabled on Mikrotik side:
|
||||||
|
|
||||||
|
```
|
||||||
|
/ip ssh set strong-crypto=yes allow-none-crypto=no
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# Replacing SSH private key
|
||||||
|
|
||||||
|
This affects access to both Gitea and Mikrotik targets.
|
||||||
|
|
||||||
|
Generate new key and inject it to Kubernetes cluster:
|
||||||
|
|
||||||
|
```
|
||||||
|
rm -fv rosdump
|
||||||
|
ssh-keygen -P '' -b 2048 -m PEM -t rsa -f rosdump -C rosdump
|
||||||
|
kubectl delete -n rosdump secret rosdump-secrets
|
||||||
|
kubectl create -n rosdump secret generic rosdump-secrets --from-file=ssh_identity=rosdump
|
||||||
|
```
|
||||||
|
|
||||||
|
Proceed to replace the public key in Gitea with one from `rosdump.pub`
|
110
rosdump/application.yml
Normal file
110
rosdump/application.yml
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: rosdump-config
|
||||||
|
data:
|
||||||
|
script.sh: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
if [ -d rosdump ]; then
|
||||||
|
echo "Pulling Git repo"
|
||||||
|
cd rosdump
|
||||||
|
git pull
|
||||||
|
else
|
||||||
|
echo "Cloning Git repo"
|
||||||
|
git clone git@git.k-space.ee:k-space/rosdump.git
|
||||||
|
cd rosdump
|
||||||
|
fi
|
||||||
|
git rm *.k-space.ee
|
||||||
|
for target in $(cat /config/targets | grep -v '^#'); do
|
||||||
|
echo "Exporting configuration for $target"
|
||||||
|
ssh rosdump@$target '/export' | grep -v '^# serial number =' | grep -v '^#.* by RouterOS' > $target
|
||||||
|
git add $target
|
||||||
|
done
|
||||||
|
if [[ `git status --porcelain` ]]; then
|
||||||
|
echo "Attempting Git check in"
|
||||||
|
git commit -m "Update $(git ls-files -m) file(s)"
|
||||||
|
git push
|
||||||
|
else
|
||||||
|
echo "No changes to commit"
|
||||||
|
fi
|
||||||
|
targets: |
|
||||||
|
router.mgmt.k-space.ee
|
||||||
|
sw_core01.mgmt.k-space.ee
|
||||||
|
sw_core02.mgmt.k-space.ee
|
||||||
|
sw_mgmt.mgmt.k-space.ee
|
||||||
|
sw_poe.mgmt.k-space.ee
|
||||||
|
sw_ha.mgmt.k-space.ee
|
||||||
|
sw_cyber.mgmt.k-space.ee
|
||||||
|
sw_chaos.mgmt.k-space.ee
|
||||||
|
sw_asocial.mgmt.k-space.ee
|
||||||
|
sw_kitchen.mgmt.k-space.ee
|
||||||
|
---
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: rosdump-cronjob
|
||||||
|
spec:
|
||||||
|
schedule: "0 * * * *"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
activeDeadlineSeconds: 300
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: monitoring
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: monitoring
|
||||||
|
effect: NoSchedule
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
containers:
|
||||||
|
- name: rosdump
|
||||||
|
image: harbor.k-space.ee/k-space/microscript-base
|
||||||
|
imagePullPolicy: Always
|
||||||
|
args:
|
||||||
|
- bash
|
||||||
|
- /config/script.sh
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
projected:
|
||||||
|
sources:
|
||||||
|
- secret:
|
||||||
|
name: rosdump-secrets
|
||||||
|
items:
|
||||||
|
- key: ssh_identity
|
||||||
|
path: ssh_identity
|
||||||
|
mode: 0600
|
||||||
|
- configMap:
|
||||||
|
name: rosdump-known-hosts
|
||||||
|
items:
|
||||||
|
- key: ssh_known_hosts
|
||||||
|
path: ssh_known_hosts
|
||||||
|
- configMap:
|
||||||
|
name: rosdump-config
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: rosdump
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 193.40.103.0/24
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 172.23.0.0/24
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 100.102.1.0/24
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 22
|
72
shared/README.md
Normal file
72
shared/README.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# KeyDB
|
||||||
|
|
||||||
|
KeyDB can be instantiated by symlinking the generated keydb.yml,
|
||||||
|
in future this could be handled by an operator.
|
||||||
|
|
||||||
|
```
|
||||||
|
helm template keydb enapter/keydb --set persistentVolume.enabled=false > keydb.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
# To regenerate base network policies
|
||||||
|
|
||||||
|
It's quite odd there is no better way to generate these.
|
||||||
|
|
||||||
|
|
||||||
|
cat << EOF > networkpolicy-base.yml
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: kubedns
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: kubeprobe
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
EOF
|
||||||
|
for j in $(kubectl get nodes -o json | jq '.items[] | .spec.podCIDR' -r | cut -d "/" -f 1 | sed -e 's/\.0$/\.1\/32/' | xargs); do
|
||||||
|
cat << EOF >> networkpolicy-base.yml
|
||||||
|
- from:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: $j
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
cat << EOF >> networkpolicy-base.yml
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: kubeapi
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- ports:
|
||||||
|
- port: 6443
|
||||||
|
to:
|
||||||
|
EOF
|
||||||
|
for j in $(kubectl get ep -n default kubernetes -o json | jq '.subsets[].addresses[].ip' -r | xargs); do
|
||||||
|
cat << EOF >> networkpolicy-base.yml
|
||||||
|
- ipBlock:
|
||||||
|
cidr: $j/32
|
||||||
|
EOF
|
||||||
|
done
|
77
shared/backup-service.yml
Normal file
77
shared/backup-service.yml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backup-service
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: backup-service
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: backup-service
|
||||||
|
spec:
|
||||||
|
serviceAccount: backup-service
|
||||||
|
containers:
|
||||||
|
- name: backup-service
|
||||||
|
image: harbor.k-space.ee/k-space/backup-service
|
||||||
|
ports:
|
||||||
|
- name: backup-service
|
||||||
|
containerPort: 5000
|
||||||
|
env:
|
||||||
|
- name: TOKEN
|
||||||
|
value: CYdCDFIvGX
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: backup-service
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: backup-service
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- namespaces
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- mongodbcommunity.mongodb.com
|
||||||
|
resources:
|
||||||
|
- mongodbcommunity
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- mysql.oracle.com
|
||||||
|
resources:
|
||||||
|
- innodbclusters
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: backup-service
|
||||||
|
namespace: shared
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: backup-service
|
||||||
|
namespace: shared
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: backup-service
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
244
shared/keydb.yml
Normal file
244
shared/keydb.yml
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
---
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
spec:
|
||||||
|
maxUnavailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: redis-utils
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
server.sh: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
host="$(hostname)"
|
||||||
|
port="6379"
|
||||||
|
replicas=()
|
||||||
|
for node in {0..2}; do
|
||||||
|
if [ "${host}" != "redis-${node}" ]; then
|
||||||
|
replicas+=("--replicaof redis-${node}.redis-headless ${port}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exec keydb-server /etc/keydb/redis.conf \
|
||||||
|
--active-replica "yes" \
|
||||||
|
--multi-master "yes" \
|
||||||
|
--appendonly "no" \
|
||||||
|
--bind "0.0.0.0" \
|
||||||
|
--port "${port}" \
|
||||||
|
--protected-mode "no" \
|
||||||
|
--server-threads "2" \
|
||||||
|
--masterauth "${REDIS_PASSWORD}" \
|
||||||
|
--requirepass "${REDIS_PASSWORD}" \
|
||||||
|
"${replicas[@]}"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: redis-health
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
data:
|
||||||
|
ping_readiness_local.sh: |-
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
[[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}"
|
||||||
|
response="$(
|
||||||
|
timeout -s 3 "${1}" \
|
||||||
|
keydb-cli \
|
||||||
|
-h localhost \
|
||||||
|
-p 6379 \
|
||||||
|
ping
|
||||||
|
)"
|
||||||
|
if [ "${response}" != "PONG" ]; then
|
||||||
|
echo "${response}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ping_liveness_local.sh: |-
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
[[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}"
|
||||||
|
response="$(
|
||||||
|
timeout -s 3 "${1}" \
|
||||||
|
keydb-cli \
|
||||||
|
-h localhost \
|
||||||
|
-p 6379 \
|
||||||
|
ping
|
||||||
|
)"
|
||||||
|
if [ "${response}" != "PONG" ] && [[ ! "${response}" =~ ^.*LOADING.*$ ]]; then
|
||||||
|
echo "${response}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cleanup_tempfiles.sh: |-
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
find /data/ -type f \( -name "temp-*.aof" -o -name "temp-*.rdb" \) -mmin +60 -delete
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: redis-headless
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- name: "server"
|
||||||
|
port: 6379
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: redis
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
annotations:
|
||||||
|
{}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: "server"
|
||||||
|
port: 6379
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: redis
|
||||||
|
- name: "redis-exporter"
|
||||||
|
port: 9121
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: redis-exporter
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
sessionAffinity: ClientIP
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
serviceName: redis-headless
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/port: "8083"
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: redis
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app.kubernetes.io/name
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- 'redis'
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
weight: 100
|
||||||
|
containers:
|
||||||
|
- name: redis
|
||||||
|
image: eqalpha/keydb:x86_64_v6.3.1
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command:
|
||||||
|
- /utils/server.sh
|
||||||
|
ports:
|
||||||
|
- name: redis
|
||||||
|
containerPort: 6379
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 5
|
||||||
|
# One second longer than command timeout should prevent generation of zombie processes.
|
||||||
|
timeoutSeconds: 6
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 5
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- /health/ping_liveness_local.sh 5
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 5
|
||||||
|
# One second longer than command timeout should prevent generation of zombie processes.
|
||||||
|
timeoutSeconds: 2
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 5
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- /health/ping_readiness_local.sh 1
|
||||||
|
startupProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
# One second longer than command timeout should prevent generation of zombie processes.
|
||||||
|
timeoutSeconds: 2
|
||||||
|
failureThreshold: 24
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- /health/ping_readiness_local.sh 1
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
securityContext:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: health
|
||||||
|
mountPath: /health
|
||||||
|
- name: redis-data
|
||||||
|
mountPath: /data
|
||||||
|
- name: utils
|
||||||
|
mountPath: /utils
|
||||||
|
readOnly: true
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: redis-secrets
|
||||||
|
|
||||||
|
- name: redis-exporter
|
||||||
|
image: quay.io/oliver006/redis_exporter
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
containerPort: 9121
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: redis-secrets
|
||||||
|
imagePullSecrets:
|
||||||
|
[]
|
||||||
|
securityContext:
|
||||||
|
{}
|
||||||
|
volumes:
|
||||||
|
- name: health
|
||||||
|
configMap:
|
||||||
|
name: redis-health
|
||||||
|
defaultMode: 0755
|
||||||
|
- name: utils
|
||||||
|
secret:
|
||||||
|
secretName: redis-utils
|
||||||
|
defaultMode: 0755
|
||||||
|
items:
|
||||||
|
- key: server.sh
|
||||||
|
path: server.sh
|
||||||
|
- name: redis-data
|
||||||
|
emptyDir: {}
|
104
shared/mariadb.yml
Normal file
104
shared/mariadb.yml
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# MariaDB 10.5 is supported until 2025
|
||||||
|
# Note that MariaDB 10.6 breaks with Nextcloud
|
||||||
|
# https://help.nextcloud.com/t/update-to-next-cloud-21-0-2-has-get-an-error/117028/7
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: mariadb
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: patch
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
serviceName: mariadb
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: mariadb
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: mariadb
|
||||||
|
annotations:
|
||||||
|
prometheus.io/port: '9104'
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: exporter
|
||||||
|
image: prom/mysqld-exporter:latest
|
||||||
|
env:
|
||||||
|
- name: DATA_SOURCE_NAME
|
||||||
|
value: exporter@tcp(127.0.0.1)/
|
||||||
|
- name: mariadb
|
||||||
|
image: mariadb:10.5
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
- name: MYSQL_ROOT_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mariadb-secrets
|
||||||
|
key: MYSQL_ROOT_PASSWORD
|
||||||
|
- name: MYSQL_USER
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: MYSQL_DATABASE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: MYSQL_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mariadb-secrets
|
||||||
|
key: MYSQL_PASSWORD
|
||||||
|
volumeMounts:
|
||||||
|
- name: mariadb-data
|
||||||
|
mountPath: /var/lib/mysql
|
||||||
|
- name: mariadb-init
|
||||||
|
mountPath: /docker-entrypoint-initdb.d
|
||||||
|
volumes:
|
||||||
|
- name: mariadb-init
|
||||||
|
configMap:
|
||||||
|
name: mariadb-init-config
|
||||||
|
|
||||||
|
# Make sure MariaDB instances run on storage{1..3} nodes, as close
|
||||||
|
# as possible to Longhorn instances
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: mariadb-data
|
||||||
|
spec:
|
||||||
|
storageClassName: longhorn
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: mariadb
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 3306
|
||||||
|
selector:
|
||||||
|
app: mariadb
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: mariadb-init-config
|
||||||
|
data:
|
||||||
|
initdb.sql: |
|
||||||
|
CREATE USER 'exporter'@'127.0.0.1' WITH MAX_USER_CONNECTIONS 3;
|
||||||
|
GRANT PROCESS, REPLICATION CLIENT, SLAVE MONITOR, SELECT ON *.* TO 'exporter'@'127.0.0.1';
|
81
shared/memcached.yml
Normal file
81
shared/memcached.yml
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
metadata:
|
||||||
|
name: memcached
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: memcached
|
||||||
|
labels:
|
||||||
|
app: memcached
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
serviceName: memcached
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: memcached
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: memcached
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1001
|
||||||
|
affinity:
|
||||||
|
podAffinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: memcached
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
weight: 1
|
||||||
|
serviceAccountName: memcached
|
||||||
|
containers:
|
||||||
|
- name: memcached
|
||||||
|
image: memcached:1-alpine
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1001
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 11211
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 6
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 11211
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
periodSeconds: 5
|
||||||
|
resources:
|
||||||
|
limits: {}
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 256Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
volumes:
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: memcached
|
||||||
|
labels:
|
||||||
|
app: memcached
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: memcache
|
||||||
|
port: 11211
|
||||||
|
selector:
|
||||||
|
app: memcached
|
38
shared/minio-support.yml
Normal file
38
shared/minio-support.yml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: minio-operator
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
v1.min.io/tenant: minio
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: minio-operator
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 4222
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
v1.min.io/tenant: minio
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector: {}
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: traefik
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
89
shared/minio.yml
Normal file
89
shared/minio.yml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: minio
|
||||||
|
annotations:
|
||||||
|
keel.sh/policy: force
|
||||||
|
keel.sh/trigger: poll
|
||||||
|
keel.sh/pollSchedule: "@midnight"
|
||||||
|
spec:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
serviceName: minio
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: minio
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: minio
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: minio
|
||||||
|
image: minio/minio:latest
|
||||||
|
command: ["minio"]
|
||||||
|
ports:
|
||||||
|
- name: minio
|
||||||
|
containerPort: 9000
|
||||||
|
- name: minio-console
|
||||||
|
containerPort: 9001
|
||||||
|
args: ["server", "/data", "--console-address", ":9001"]
|
||||||
|
env:
|
||||||
|
- name: MINIO_ROOT_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: minio-secrets
|
||||||
|
key: MINIO_ROOT_PASSWORD
|
||||||
|
- name: MINIO_ROOT_USER
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data
|
||||||
|
name: minio-data
|
||||||
|
|
||||||
|
# Make sure Minio instances run on storage{1..3} nodes, as close
|
||||||
|
# as possible to Longhorn instances
|
||||||
|
tolerations:
|
||||||
|
- key: dedicated
|
||||||
|
operator: Equal
|
||||||
|
value: storage
|
||||||
|
effect: NoSchedule
|
||||||
|
nodeSelector:
|
||||||
|
dedicated: storage
|
||||||
|
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: minio-data
|
||||||
|
spec:
|
||||||
|
storageClassName: longhorn
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 50Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: minio
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9000
|
||||||
|
selector:
|
||||||
|
app: minio
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: minio-console
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9001
|
||||||
|
selector:
|
||||||
|
app: minio
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user