Files
italiadatacenter/doc.txt
alessandro 20d506407a primo
2026-07-17 09:42:52 +02:00

2377 lines
56 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Configurazione iniziale:
master node
3 server con queste caratteristiche:
2 vcpu, 4gb ram 20gb HD Ubuntu 25.10
Worker node
3 server con queste caratteristiche:
2 vcpu, 4gb ram 50gb HD Ubuntu 25.10
Load Balancer (HAproxy)
1 server con queste caratteristiche:
1 vcpu, 1gb ram 10gb HD Ubuntu 25.10
indirizzo pubblico definito sul gatewa ruotato sul Balancer, porte aperte:
80,443 per servizi applicativi
10000,10002,10003,10004 per kubeedge
------------------------------------------------------------------------------------------------------------------------------
Installazione:
Su ogni nodo master e worker
# 1. Aggiorna OS
sudo apt update && sudo apt -y upgrade # Ubuntu/Debian
sudo apt install -y iputils-ping
sudo apt install -y telnetd telnet
sudo snap install -y kubectl --classic
sudo apt install -y iptables
sudo apt install -y iptables-persistent
# 2. Disabilita SWAP (necessario)
sudo swapoff -a
sudo sed -i.bak '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# 3. Config kernel requisiti Kubernetes (es. bridge netfilter)
cat <<EOF | sudo tee /etc/sysctl.d/99-k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.inotify.max_user_watches = 524288
EOF
sudo sysctl --system
# 4. Sincronizza orologio
sudo apt install -y chrony
sudo systemctl enable --now chrony
#installa yq
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
sudo chmod a+x /usr/local/bin/yq
# 5. Imposta hostname (es.)
#sudo hostnamectl set-hostname $1
------------------------------------------------------------------------------------------------------------------------------
Sul master 1
# 1. Installa RKE2 (script ufficial)
curl -sfL https://get.rke2.io | sh -
sudo systemctl enable rke2-server.service
# 2. Crea config (personalizza token e tls-san se serve)
sudo mkdir -p /etc/rancher/rke2
sudo tee /etc/rancher/rke2/config.yaml > /dev/null <<EOF
# RKE2 Server Configuration - First Master Node
write-kubeconfig-mode: "0644"
# CRITICAL: Add all possible API server access points to the certificate
tls-san:
- "POC-Kube-Balancer"
- "10.20.1.100"
- "POC-Master0"
- "10.20.1.101"
- "POC-Master1"
- "10.20.1.102"
- "POC-Master2"
- "10.20.1.103"
- "POC-Worker0"
- "10.20.1.104"
- "POC-Worker1"
- "10.20.1.105"
- "POC-Worker2"
- "10.20.1.106"
# Network configuration
#cluster-cidr: "10.42.64.0/18"
#service-cidr: "10.42.0.0/18"
#cluster-dns: "10.42.0.10"
# Security hardening
#profile: "cis-1.6"
selinux: true
secrets-encryption: true
# Node configuration
node-taint:
- "CriticalAddonsOnly=true:NoExecute"
ingress-controller: none
EOF
# 3. Avvia RKE2 server
sudo systemctl start rke2-server
# Attendi che i pod kube-system siano up (sul master 1)
#installa kubectl
curl -LO https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
mkdir /root/.kube
cp /etc/rancher/rke2/rke2.yaml /root/.kube/config
echo "MASTER TOKEN TO COPY"
cat /var/lib/rancher/rke2/server/node-token
sui master 2 e 3:
# 1. Installa RKE2 (script ufficial)
curl -sfL https://get.rke2.io | sh -
sudo systemctl enable rke2-server.service
# 2. Crea config (personalizza token e tls-san se serve)
sudo mkdir -p /etc/rancher/rke2
sudo tee /etc/rancher/rke2/config.yaml > /dev/null <<EOF
# RKE2 Server Configuration - Additional Master
server: https://POC-Master0:9345 # Direct connection for initial join
token: "K10b8b252de84e5aab8bc1d2a8e4aad3e329ee84d638892b8638de0260b7cb8212a::server:34b189ab7b91fc924500ba0b3608b80b"
write-kubeconfig-mode: "0644"
# Same TLS SANs as master-1 - consistency is crucial!
tls-san:
- "POC-Kube-Balancer"
- "10.20.1.100"
- "POC-Master0"
- "10.20.1.101"
- "POC-Master1"
- "10.20.1.102"
- "POC-Master2"
- "10.20.1.103"
- "POC-Worker0"
- "10.20.1.104"
- "POC-Worker1"
- "10.20.1.105"
- "POC-Worker2"
- "10.20.1.106"
# Identical network configuration
#cluster-cidr: "10.42.64.0/18"
#service-cidr: "10.42.0.0/18"
#cluster-dns: "10.42.0.10"
# Same backup and security settings
#profile: "cis-1.6"
selinux: true
secrets-encryption: true
# Node configuration
node-taint:
- "CriticalAddonsOnly=true:NoExecute"
ingress-controller: none
EOF
# 3. Avvia RKE2 server
sudo systemctl start rke2-server
curl -LO https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
mkdir /root/.kube
cp /etc/rancher/rke2/rke2.yaml /root/.kube/config
#installa helm
# scarica helm (esempio Linux AMD64)
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
# verifica
helm version
------------------------------------------------------------------------------------------------------------------------------
su ogni nodo worker:
sudo apt install open-iscsi
systemctl enable open-iscsi
systemctl enable iscsid
systemctl restart iscsid.service
# Install RKE2 agent
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sudo sh -
# Create configuration
sudo mkdir -p /etc/rancher/rke2
# Worker configuration - connects through the load balancer!
sudo tee /etc/rancher/rke2/config.yaml > /dev/null << EOF
# RKE2 Agent Configuration
server: https://POC-Kube-Balancer:9345 # Using the main load balancer!
token: "K10b8b252de84e5aab8bc1d2a8e4aad3e329ee84d638892b8638de0260b7cb8212a::server:34b189ab7b91fc924500ba0b3608b80b"
# Node labels for workload scheduling
node-label:
- "node.kubernetes.io/worker=true"
- "workload-type=general"
# Optional: Reserve resources for system stability
# kubelet-arg:
# - "system-reserved=cpu=500m,memory=1Gi"
# - "kube-reserved=cpu=500m,memory=1Gi"
EOF
# Start the worker
sudo systemctl enable rke2-agent.service
sudo systemctl start rke2-agent.service
# Check status
sudo systemctl status rke2-agent.service
------------------------------------------------------------------------------------------------------------------------------
sul Balancer:
sudo apt update && sudo apt install -y haproxy
sudo tee /etc/haproxy/haproxy.cfg > /dev/null <<'EOF'
global
log /dev/log local0
maxconn 20000
tune.bufsize 16384
# SSL configuration for future HTTPS endpoints
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Modern SSL configuration - only secure protocols
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend rke2_registration_frontend
bind *:9345
mode tcp
option tcplog
default_backend rke2_registration_backend
#---------------------------------------------------------------------
# RKE2 Supervisor/Registration Backend
# Round-robin between masters for node registration
#---------------------------------------------------------------------
backend rke2_registration_backend
mode tcp
balance roundrobin
option tcp-check
# Health check ensures we only send traffic to healthy masters
server POC-Master0 POC-Master0:9345 check
server POC-Master1 POC-Master1:9345 check
server POC-Master2 POC-Master2:9345 check
#---------------------------------------------------------------------
# Kubernetes API Frontend
# This is where kubectl commands and apps connect
#---------------------------------------------------------------------
frontend k8s_api_frontend
bind *:6443
mode tcp
option tcplog
default_backend k8s_api_backend
#---------------------------------------------------------------------
# Kubernetes API Backend
# Distributes API requests across all masters
#---------------------------------------------------------------------
backend k8s_api_backend
mode tcp
balance roundrobin
option tcp-check
# TCP health checks on the API port
server POC-Master0 POC-Master0:6443 check
server POC-Master1 POC-Master1:6443 check
server POC-Master2 POC-Master2:6443 check
#---------------------------------------------------------------------
# Statistics Page (Optional but useful for monitoring)
#---------------------------------------------------------------------
listen stats
bind *:8080
stats enable
stats uri /stats
stats refresh 30s
stats show-node
stats auth admin:admin # Change this password!
#---------------------------------------------------------------------
# nginx ingress
# This is where kubectl commands and apps connect
#---------------------------------------------------------------------
frontend nginx_frontend_443
bind *:443
mode tcp
option tcplog
default_backend nginx_backend
frontend nginx_frontend_80
bind *:80
mode http
http-response set-header Access-Control-Allow-Origin %[hdr(origin)]
default_backend nginx_backend_http
#---------------------------------------------------------------------
# Kubernetes API Backend
# Distributes API requests across all masters
#---------------------------------------------------------------------
backend nginx_backend
mode tcp
balance roundrobin
option tcp-check
# TCP health checks on the API port
server POC-Master0 POC-Master0:30864 check
server POC-Master1 POC-Master1:30864 check
server POC-Master2 POC-Master2:30864 check
backend nginx_backend_http
mode http
balance roundrobin
# TCP health checks on the API port
server POC-Master0 POC-Master0:30864 check ssl verify none
server POC-Master1 POC-Master1:30864 check ssl verify none
server POC-Master2 POC-Master2:30864 check ssl verify none
EOF
sudo systemctl enable --now haproxy
------------------------------------------------------------------------------------------------------------------------------
Installazione componenti k8s
- **Rancher**
helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
kubectl create namespace cattle-system
helm install rancher rancher-stable/rancher \
--namespace cattle-system \
--set hostname=k8s.italiadatacenter.com \
--set bootstrapPassword=admin
patch gateway add under listener:
- allowedRoutes:
namespaces:
from: cattle-system
hostname: k8s.italiadatacenter.com
name: k8s-https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- group: ""
kind: Secret
name: k8s-secret
mode: Terminate
- allowedRoutes:
namespaces:
from: cattle-system
hostname: k8s.italiadatacenter.com
name: k8s-http
port: 80
protocol: HTTP
creazione httproute:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: rancher
namespace: cattle-system
spec:
hostnames:
- k8s.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: rancher
port: 80
------------------------------------------------------------------------------------------------------------------------------
- **CephCsi**
cat <<EOF > csi-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "004ee854-86cc-4ddc-b7d6-75e4fe962296",
"monitors": [
"72.20.1.33:6789",
"72.20.1.34:6789",
"72.20.1.35:6789"
]
}
]
metadata:
name: ceph-csi-config
EOF
kubectl apply -f csi-config-map.yaml
cat <<EOF > csi-kms-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
{}
metadata:
name: ceph-csi-encryption-kms-config
EOF
kubectl apply -f csi-kms-config-map.yaml
cat <<EOF > ceph-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
ceph.conf: |
[global]
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
# keyring is a required key and its value should be empty
keyring: |
metadata:
name: ceph-config
EOF
kubectl apply -f ceph-config-map.yaml
cat <<EOF > csi-rbd-secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: default
stringData:
userID: kubernetes
userKey: AQD2zo5pm8aZIRAAPzWS+dROeX7iJtv5EukfKA==
EOF
kubectl apply -f https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-provisioner-rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-nodeplugin-rbac.yaml
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
kubectl apply -f csi-rbdplugin-provisioner.yaml
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin.yaml
kubectl apply -f csi-rbdplugin.yaml
------- TEST-----
cat <<EOF > csi-rbd-sc.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: 004ee854-86cc-4ddc-b7d6-75e4fe962296
pool: k8s-rbd
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
EOF
kubectl apply -f csi-rbd-sc.yaml
cat <<EOF > raw-block-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: raw-block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
EOF
kubectl apply -f raw-block-pvc.yaml
------------------------------------------------------------------------------------------------------------------------------
- **Gateway API**
# Install Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
kubectl get crd | grep gateway
kubectl create namespace nginx-gateway
kubectl apply --server-side -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.4.1/deploy/crds.yaml
kubectl apply -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.4.1/deploy/nodeport/deploy.yaml
---- Gatway configuration ----
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: nginx-gateway
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
gatewayClassName: nginx
listeners:
- allowedRoutes:
namespaces:
from: All
hostname: poc1.italiadatacenter.com
name: https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- group: ""
kind: Secret
name: poc1-secret
mode: Terminate
- allowedRoutes:
namespaces:
from: All
hostname: poc1.italiadatacenter.com
name: http
port: 80
protocol: HTTP
----- Nodeport service ---
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: nginx-gateway
app.kubernetes.io/managed-by: nginx-gateway-nginx
app.kubernetes.io/name: main-gateway-nginx
gateway.networking.k8s.io/gateway-name: main-gateway
name: gateway-nginx-nodeport
namespace: nginx-gateway
spec:
ports:
- name: port-80
nodePort: 30864
port: 80
protocol: TCP
targetPort: 80
- name: port-443
nodePort: 30874
port: 443
protocol: TCP
targetPort: 443
selector:
app.kubernetes.io/instance: nginx-gateway
app.kubernetes.io/managed-by: nginx-gateway-nginx
app.kubernetes.io/name: main-gateway-nginx
gateway.networking.k8s.io/gateway-name: main-gateway
sessionAffinity: None
type: NodePort
EOF
----- httproute ---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: demo-apps
spec:
hostnames:
- poc2.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-v1
port: 80
--- work area
kubectl edit gateway main-gateway -n nginx-gateway
add
- allowedRoutes:
namespaces:
from: cattle-system
hostname: k8s.italiadatacenter.com
name: k8s-https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- group: ""
kind: Secret
name: k8s-secret
mode: Terminate
- allowedRoutes:
namespaces:
from: cattle-system
hostname: k8s.italiadatacenter.com
name: k8s-http
port: 80
protocol: HTTP
------------------------------------------------------------------------------------------------------------------------------
- **CertManager**
kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Install versione consigliata
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--set installCRDs=true \
--wait
# Verifica
kubectl -n cert-manager get pods
Crea cluster issuer per lets Encrypt:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: <insert a valid email-address>
privateKeySecretRef:
name: letsencrypt-production-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
gatewayHTTPRoute:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: main-gateway
namespace: nginx-gateway
------------------------------------------------------------------------------------------------------------------------------
---
## Servizi DevOps
-- **db devops**
apiVersion: v1
kind: Secret
metadata:
name: pg-app-user
namespace: demo-apps
type: kubernetes.io/basic-auth
stringData:
username: devops
password: KAYQE1QA7uwUZ8uI
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-devops
namespace: devops
spec:
instances: 3
storage:
size: 1Gi
storageClass: csi-rbdfs-sc
walStorage:
storageClass: csi-rbdfs-sc
size: 1Gi
bootstrap:
initdb:
database: devops
owner: admin
secret:
name: pg-app-user
postgresql:
parameters:
max_connections: "300"
shared_buffers: "1GB"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
- **Gitea**
kubectl cnpg psql pg-devops -n devops
CREATE DATABASE giteadb;
CREATE USER gitea WITH PASSWORD 'KAYQE1QA7uwUZ8uI';
GRANT ALL PRIVILEGES ON DATABASE giteadb TO gitea;
ALTER DATABASE giteadb OWNER TO gitea;
helm repo add gitea https://dl.gitea.io/charts/
helm repo update
kubectl create namespace gitea
cat <<EOF |cat >values.yaml -
replicaCount: 1
image:
repository: gitea/gitea
tag: 1.22.0
pullPolicy: IfNotPresent
strategy:
type: Recreate
service:
http:
type: ClusterIP
port: 3000
ssh:
type: ClusterIP
port: 22
redis-cluster:
enabled: false
redis:
enabled: false
ingress:
enabled: false
persistence:
enabled: true
storageClass: csi-rbdfs-sc
size: 10Gi
postgresql:
enabled: false
postgresql-ha:
enabled: false
gitea:
admin:
username: gitadmin
password: KAYQE1QA7uwUZ8uI
email: gitadmin@italiadatacenter.com
config:
database:
DB_TYPE: postgres
HOST: pg-devops-rw.devops.svc:5432
NAME: giteadb
USER: gitea
PASSWD: KAYQE1QA7uwUZ8uI
SSL_MODE: disable
server:
ROOT_URL: https://git.italiadatacenter.com/
SSH_DOMAIN: git.italiadatacenter.com
SSH_PORT: 22
security:
INSTALL_LOCK: true
EOF
helm upgrade --install gitea gitea-charts/gitea --namespace gitea -f values.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: gitea
namespace: gitea
spec:
hostnames:
- git.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: gitea-http
port: 3000
------------------------------------------------------------------------------------------------------------------------------
- **Harbor**
#HARBOR
kubectl create namespace harbor
helm repo add harbor https://helm.goharbor.io
helm repo update
cat <<EOF | cat > harbor-cert.yaml -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: harbor-tls
namespace: harbor
spec:
secretName: harbor-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- harbor.italiadatacenter.com
EOF
kubectl apply -f harbor-cert.yaml
cat <<EOF | cat > harborvalues.yaml -
# -----------------------
# EXPOSURE
# -----------------------
expose:
# Set how to expose the service. Set the type as "ingress", "clusterIP", "nodePort" or "loadBalancer"
# and fill the information in the corresponding section
type: clusterIP
externalURL: https://harbor.italiadatacenter.com
# -----------------------
# ADMIN
# -----------------------
harborAdminPassword: "KAYQE1QA7uwUZ8uI"
# -----------------------
# PERSISTENCE
# -----------------------
persistence:
enabled: true
persistentVolumeClaim:
registry:
storageClass: csi-rbdfs-sc
size: 50Gi
jobservice:
storageClass: csi-rbdfs-sc
size: 2Gi
trivy:
storageClass: csi-rbdfs-sc
size: 2Gi
# -----------------------
# POSTGRESQL (EXTERNAL)
# -----------------------
database:
type: external
external:
host: pg-devops-rw.devops.svc
port: 5432
username: harbor
password: "KAYQE1QA7uwUZ8uI"
database: registry
sslmode: require
# -----------------------
# REDIS (EXTERNAL)
# -----------------------
redis:
type: external
external:
addr: redis.redis.svc.cluster.local:6379
password: "KAYQE1QA7uwUZ8uI"
database: 0
# -----------------------
# DISABLE INTERNAL SERVICES
# -----------------------
postgresql:
enabled: false
redisInternal:
enabled: false
# -----------------------
# COMPONENTS
# -----------------------
trivy:
enabled: true
metrics:
enabled: false
EOF
kubectl cnpg psql pg-devops -n devops
CREATE DATABASE registry;
CREATE USER harbor WITH PASSWORD 'KAYQE1QA7uwUZ8uI';
GRANT ALL PRIVILEGES ON DATABASE registry TO harbor;
ALTER DATABASE registry OWNER TO harbor;
#test
kubectl run psql-test --rm -it --image=postgres:16 -- psql -h pg-prod-rw.database.svc -U harbor
kubectl run redis-test --rm -it --image=redis:7 -- redis-cli -h redis.redis.svc.cluster.local -a Japp0cam
helm install harbor harbor/harbor -n harbor -f harborvalues.yaml
--- httproute & body setting nginx ----
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: harbor
namespace: harbor
spec:
hostnames:
- harbor.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: harbor
port: 80
---
apiVersion: gateway.nginx.org/v1alpha1
kind: ClientSettingsPolicy
metadata:
name: gateway-client-settings
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: main-gateway
body:
maxSize: "0"
EOF
TEST:
#push
docker login harbor.italiadatacenter.com
docker pull nginx:1.25
docker tag nginx:1.25 harbor.italiadatacenter.com/library/nginx:1.25
docker push harbor.italiadatacenter.com/library/nginx:1.25
#pull
docker rmi harbor.italiadatacenter.com/library/nginx:1.25
docker pull harbor.italiadatacenter.com/library/nginx:1.25
#pull da k8s
#STEP 1 Creare Robot Account in Harbor
#Harbor UI → Projects → (es. library o apps) → Robot Accounts
#Nome: k8s-pull
#Permessi:
#✔️ Repository → Pull
kubectl create secret docker-registry harbor-pull \
-n default \
--docker-server=harbor.italiadatacenter.com \
--docker-username=robot$k8s-pull \
--docker-password=ir0ELEJEFg804qljh2p32ALzIsMJepWt \
--docker-email=harbor@italiadatacenter.com
#per namespace nuovi
kubectl patch serviceaccount default -n default -p '{"imagePullSecrets":[{"name":"harbor-pull"}]}'
#applicare per i vecchi:
kubectl patch serviceaccount default -n primo-dev -p '{"imagePullSecrets":[{"name":"harbor-pull"}]}'
#test
kubectl run test-nginx --image=harbor.italiadatacenter.com/library/nginx:1.25 --restart=Never -n poc
kubectl -n primo-dev create secret docker-registry harbor-pull \
--docker-server=harbor.italiadatacenter.com \
--docker-username=robot\$primo+primo \
--docker-password=agQLiKJ8K5qmBWhO1bHngzb9UorPLIw1 \
--docker-email=harbor@italiadatacenter.com
kubectl patch serviceaccount default -n primo-dev -p '{"imagePullSecrets":[{"name":"harbor-pull"}]}'
------------------------------------------------------------------------------------------------------------------------------
- **Gitea Act Runner**
Download act_runner binary
mv act_runner-0.3.0-linux-amd64 act_runner
chmod +x ./act_runner
./act_runner --version
./act_runner register
Git server: https.//git.italiadatacener.com
token: SiP2B1Wth0FwORkLrIX7WYhho78IVaW3ZppO9vrx
label: runner1:host
start:
nohup ./act_runner daemon &
Install node
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl ca-certificates gnupg
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
verifica
node -v
npm -v
Installa docker:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
------------------------------------------------------------------------------------------------------------------------------
- **Pipeline CICD**
------------------------------------------------------------------------------------------------------------------------------
customize.sh
#!/bin/bash
# Usage: ./customize.sh dev|qa|prod
echo "tetst" $IMAGE_TAG_backend
ENV=$1
VALUES_FILE="env/$ENV/values.env"
PROPERTIES_FILE="properties.env"
YAML_DIR="kubernetes"
# Estrai l'hash completo del commit e crea una variabile temporanea per la sostituzione
TAG=$(git rev-parse HEAD)
TMP_TAG_FILE=$(mktemp)
echo "TAG=$TAG" > "$TMP_TAG_FILE"
cat ./imglist >> "$TMP_TAG_FILE"
if [ ! -f "$VALUES_FILE" ]; then
echo "File $VALUES_FILE non trovato."
exit 1
fi
if [ ! -f "$PROPERTIES_FILE" ]; then
echo "File $PROPERTIES_FILE non trovato."
exit 1
fi
# Trova tutti i file .yaml nella directory kubernetes e sottodirectory
find "$YAML_DIR" -type f -name "*.yaml" | while read YAML_FILE; do
while IFS='=' read -r key value; do
sed -i "s|<$key>|$value|g" "$YAML_FILE"
done < "$VALUES_FILE"
while IFS='=' read -r key value; do
sed -i "s|<$key>|$value|g" "$YAML_FILE"
done < "$PROPERTIES_FILE"
# Sostituzione dinamica della chiave TAG
while IFS='=' read -r key value; do
sed -i "s|<$key>|$value|g" "$YAML_FILE"
done < "$TMP_TAG_FILE"
echo "Sostituzione completata per file $YAML_FILE ambiente $ENV."
cat $YAML_FILE
done
rm -f "$TMP_TAG_FILE"
---
deploy.sh
#!/bin/bash
# Esegue kubectl apply per ogni sottodirectory di kubernetes separatamente
YAML_DIR="kubernetes"
# Trova tutte le sottodirectory (inclusa la principale) che contengono file .yaml
find "$YAML_DIR" -type d | while read DIR; do
if ls "$DIR"/*.yaml 1> /dev/null 2>&1; then
echo "Deploy delle risorse nella directory $DIR..."
kubectl --kubeconfig=./kubeconfig apply -f "$DIR"
fi
done
echo "Deploy completato di tutte le directory YAML."
---
build_container.sh:
#!/bin/bash
set -e
set -o pipefail
echo "progetto" $1
REPO_NAME=$1
COMMIT_SHA=$(git rev-parse HEAD)
REGISTRY_URL=$2
for dir in containers/*/; do
CONTAINER_NAME=$(basename "$dir")
cp -R src/${CONTAINER_NAME}/. containers/${CONTAINER_NAME}/.
ls -la $dir
DOCKERFILE="$dir/dockerfile"
IMAGE_TAG="${REGISTRY_URL}/${REPO_NAME}/${CONTAINER_NAME}:${COMMIT_SHA}"
echo "IMAGE_TAG_${CONTAINER_NAME}=$IMAGE_TAG" >> ./imglist
if [ -f "$DOCKERFILE" ]; then
docker build -t "$IMAGE_TAG" -f "$DOCKERFILE" "$dir"
docker push "$IMAGE_TAG"
echo "Build e push completate: $IMAGE_TAG"
else
echo "Dockerfile non trovato in $dir"
fi
done
----
kube-provisioning.sh
#!/usr/bin/env bash
###########################################################
#./kube-provisioning.sh dev cicd-user kubeconfig-dev.yaml
#arg1 = namespace
#arg2 = env (dev|qa|prod)
###########################################################
set -euo pipefail
############################################
# CONFIG
############################################
NAMESPACE=${1:-dev}-$2
SERVICE_ACCOUNT="deployer"
KUBECONFIG_FILE=${NAMESPACE}.yaml
echo "Namespace: $NAMESPACE"
echo "ServiceAccount: $SERVICE_ACCOUNT"
echo "Output kubeconfig: $KUBECONFIG_FILE"
############################################
# CHECK REQUIREMENTS
############################################
if ! command -v kubectl >/dev/null 2>&1; then
echo "kubectl not found"
exit 1
fi
############################################
# CREATE NAMESPACE
############################################
kubectl get ns "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE"
############################################
# CREATE SERVICE ACCOUNT
############################################
kubectl -n "$NAMESPACE" get sa "$SERVICE_ACCOUNT" >/dev/null 2>&1 || \
kubectl -n "$NAMESPACE" create serviceaccount "$SERVICE_ACCOUNT"
############################################
# CREATE SECRET FOR SERVICE ACCOUNT TOKEN (legacy, validità illimitata)
############################################
SECRET_NAME="${SERVICE_ACCOUNT}-token"
if ! kubectl -n "$NAMESPACE" get secret "$SECRET_NAME" >/dev/null 2>&1; then
kubectl -n "$NAMESPACE" create secret generic "$SECRET_NAME" \
--type='kubernetes.io/service-account-token' \
--dry-run=client -o yaml > tmp-secret.yaml
# Inserisci correttamente l'annotazione YAML
yq eval ".metadata.annotations.\"kubernetes.io/service-account.name\" = \"$SERVICE_ACCOUNT\"" -i tmp-secret.yaml
kubectl apply -f tmp-secret.yaml
rm tmp-secret.yaml
fi
# Attendi che il token venga popolato nel secret
for i in {1..10}; do
TOKEN=$(kubectl -n "$NAMESPACE" get secret "$SECRET_NAME" -o jsonpath='{.data.token}' 2>/dev/null | base64 --decode || true)
if [[ -n "$TOKEN" ]]; then break; fi
sleep 1
done
if [[ -z "$TOKEN" ]]; then
echo "Errore: il token non è stato generato."
exit 1
fi
############################################
# CREATE ROLE
############################################
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: namespace-deployer
namespace: $NAMESPACE
rules:
- apiGroups: ["", "apps", "batch", "networking.k8s.io"]
resources: ["*"]
verbs: ["*"]
EOF
############################################
# CREATE ROLE BINDING
############################################
kubectl -n "$NAMESPACE" get rolebinding namespace-deployer-binding >/dev/null 2>&1 || \
kubectl create rolebinding namespace-deployer-binding \
--role=namespace-deployer \
--serviceaccount=${NAMESPACE}:${SERVICE_ACCOUNT} \
-n "$NAMESPACE"
############################################
# GET CLUSTER INFO
############################################
CLUSTER_NAME=$(kubectl config view --minify -o jsonpath='{.clusters[0].name}')
CLUSTER_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
CLUSTER_CA=$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
############################################
# GENERATE KUBECONFIG
############################################
cat <<EOF > "$KUBECONFIG_FILE"
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority-data: ${CLUSTER_CA}
server: ${CLUSTER_SERVER}
name: ${CLUSTER_NAME}
contexts:
- context:
cluster: ${CLUSTER_NAME}
namespace: ${NAMESPACE}
user: ${SERVICE_ACCOUNT}
name: ${SERVICE_ACCOUNT}-${CLUSTER_NAME}
current-context: ${SERVICE_ACCOUNT}-${CLUSTER_NAME}
users:
- name: ${SERVICE_ACCOUNT}
user:
token: ${TOKEN}
EOF
echo
echo "Kubeconfig generated:"
echo "$KUBECONFIG_FILE"
echo
echo "Test command:"
echo "kubectl --kubeconfig=$KUBECONFIG_FILE get pods"
---
## Servizi Database
- **CloudNativePG**
kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yaml--force-conflicts
curl -sSfL https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | sudo sh -s -- -b /usr/local/bin
kubectl create namespace database
database.yaml:
---
apiVersion: v1
kind: Secret
metadata:
name: pg-app-user
namespace: demo-apps
type: kubernetes.io/basic-auth
stringData:
username: admin
password: admin
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-test
namespace: demo-apps
spec:
instances: 3
storage:
size: 1Gi
storageClass: csi-rbdfs-sc
walStorage:
storageClass: csi-rbdfs-sc
size: 1Gi
bootstrap:
initdb:
database: testdb
owner: admin
secret:
name: pg-app-user
postgresql:
parameters:
max_connections: "300"
shared_buffers: "1GB"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
#test
kubectl run psql-client -n database --rm -it --image=postgres:16 --env="PGPASSWORD=admin" -- psql -h pg-test-rw.demo-apps.svc -U admin -d appdb
kubectl patch pvc pg-test-1-wal -n demo_apps -p '{"spec":{"resources":{"requests":{"storage":"32Gi"}}}}'
backup:
barmanObjectStore:
destinationPath: s3://pg-backups/prod
endpointURL: http://minio.minio.svc:9000
s3Credentials:
accessKeyId:
name: s3-creds
key: ACCESS_KEY
secretAccessKey:
name: s3-creds
key: SECRET_KEY
--- pgadmin -------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: pgadmin-deployment
spec:
replicas: 1
selector:
matchLabels:
app: pgadmin
template:
metadata:
labels:
app: pgadmin
spec:
containers:
- name: pgadmin
image: dpage/pgadmin4
ports:
- containerPort: 80
env:
- name: PGADMIN_DEFAULT_EMAIL
value: pgadmin@italiadatacenter.com
- name: PGADMIN_DEFAULT_PASSWORD
value: KAYQE1QA7uwUZ8uI
---
apiVersion: v1
kind: Service
metadata:
name: pgadmin-service
spec:
selector:
app: pgadmin
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: demo-apps
spec:
hostnames:
- poc3.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: pgadmin-service
port: 80
--------------------------------------------------------------------------------
cat <<EOF | kubectl -n database apply -f -
# This StorageClass is optimized for use with CloudNativePG.
# It disables storage-level replication and ensures data is local to the pod.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-cnpg-strict-local
provisioner: driver.longhorn.io
# allowVolumeExpansion is crucial for scaling database storage without downtime.
allowVolumeExpansion: true
# reclaimPolicy: Delete ensures that when a PVC is deleted, the underlying
# Longhorn volume is also removed, preventing orphaned storage.
reclaimPolicy: Delete
parameters:
# This is the most important setting. We rely on CloudNativePG for replication,
# so we only need one copy at the storage layer to avoid write amplification.
numberOfReplicas: "1"
# dataLocality: strict-local guarantees that the volume data will be stored
# on the same node as the pod that uses it. This is essential for performance
# and for aligning with a true shared-nothing architecture.
dataLocality: "strict-local"
# A longer timeout for stale replicas is suitable for database workloads.
staleReplicaTimeout: "2880" # 48 hours in minutes
# Default filesystem.
fsType: "ext4"
EOF
kubectl cnpg psql pg-devops -n devops
CREATE DATABASE giteadb;
CREATE USER gitea WITH PASSWORD 'KAYQE1QA7uwUZ8uI';
GRANT ALL PRIVILEGES ON DATABASE giteadb TO gitea;
ALTER DATABASE giteadb OWNER TO gitea;
cluster production ready:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: mycluster
namespace: database
spec:
instances: 3 # → 3 nodi per HA reale
primaryUpdateStrategy: unsupervised
failover: # → Failover automatico
promoteTimeout: 5m
targetPromotionRule: "prefer-high-promotion-score"
# ---------------------------
# STORAGE (PRODUCTION)
# ---------------------------
storage:
size: 200Gi
storageClass: fast-rbd # Ceph, SSD, GP3 ecc.
resizeInUse: true
walStorage: # Consigliato in produzione
size: 50Gi
storageClass: fast-rbd
# ---------------------------
# WAL ARCHIVING (S3/MINIO)
# ---------------------------
walArchive:
enabled: true
destinationPath: "s3://mybucket/wal/"
s3Credentials:
accessKeyId:
name: cnpg-s3-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: cnpg-s3-creds
key: SECRET_ACCESS_KEY
endpointURL: "https://s3.myregion.amazonaws.com"
region: "myregion"
encryption: AES256
# ---------------------------
# BACKUP AUTOMATICI
# ---------------------------
backup:
barmanObjectStore:
destinationPath: "s3://mybucket/basebackup/"
endpointURL: "https://s3.myregion.amazonaws.com"
s3Credentials:
accessKeyId:
name: cnpg-s3-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: cnpg-s3-creds
key: SECRET_ACCESS_KEY
wal:
compression: bzip2
encryption: AES256
retentionPolicy: "30d" # → 30 giorni di retention
monitoring:
enablePodMonitor: true
# ---------------------------
# TLS INTERNO (RACCOMANDATO)
# ---------------------------
certificates:
serverTLSSecret: cnpg-server-tls
clientTLSSecret: cnpg-client-tls
# ---------------------------
# RESOURCE MANAGEMENT
# ---------------------------
resources:
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "4"
memory: "8Gi"
# ---------------------------
# ANTI-AFFINITY & PDB
# ---------------------------
affinity:
enablePodAntiAffinity: true
topologyKey: "kubernetes.io/hostname"
podDisruptionBudget:
minAvailable: 2
# ---------------------------
# STARTUP & HEALTH
# ---------------------------
postgresql:
shared_preload_libraries:
- "pg_stat_statements"
- "auto_explain"
parameters:
max_connections: "300"
shared_buffers: "2GB"
effective_cache_size: "6GB"
maintenance_work_mem: "512MB"
wal_compression: "on"
wal_level: "replica"
max_wal_size: "4GB"
checkpoint_timeout: "15min"
synchronous_commit: "remote_apply"
# ---------------------------
# SYNCHRONOUS REPLICATION
# ---------------------------
replication:
synchronous:
mode: " quorum "
number: 1 # One sync replica; others async
# ---------------------------
# SERVICE & NETWORKING
# ---------------------------
service:
type: ClusterIP
primary:
type: ClusterIP
replicas:
type: ClusterIP
# ---------------------------
# ENCRYPTION AT REST (OPZIONALE)
# ---------------------------
encryption:
enabled: true
mode: aes256-gcm
------------------------------------------------------------------------------------------------------------------------------
- **MySql Operator**
helm repo add mysql-operator https://mysql.github.io/mysql-operator/
helm repo update
helm install my-mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --create-namespace
--db instance
kubectl create secret generic mypwds \
--from-literal=rootUser=root \
--from-literal=rootHost=% \
--from-literal=rootPassword="sakila"
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
name: mycluster
spec:
secretName: mypwds
tlsUseSelfSigned: true
instances: 3
router:
instances: 1
--- test
$> kubectl run --rm -it myshell --image=container-registry.oracle.com/mysql/community-operator -- mysqlsh root@mycluster --sql
If you don't see a command prompt, try pressing enter.
******
MySQL mycluster SQL> SELECT @@hostname
+-------------+
| @@hostname |
+-------------+
| mycluster-0 |
+-------------+
------------------------------------------------------------------------------------------------------------------------------
- **Redis**
------------------------------------------------------------------------------------------------------------------------------
kubectl create namespace redis
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
cat <<EOF | cat > redisvalues.yaml -
architecture: replication
auth:
enabled: true
password: KAYQE1QA7uwUZ8uI
master:
persistence:
enabled: true
storageClass: csi-rbdfs-sc
size: 5Gi
resources:
requests:
cpu: 100m
memory: 256Mi
replica:
replicaCount: 2
persistence:
enabled: true
storageClass: csi-rbdfs-sc
size: 5Gi
resources:
requests:
cpu: 100m
memory: 256Mi
sentinel:
enabled: true
replicas: 3
resources:
requests:
cpu: 50m
memory: 64Mi
metrics:
enabled: false
EOF
helm install redis bitnami/redis -n redis -f redisvalues.yaml
#test
kubectl run redis-client -n redis --rm -it --image=redis:7.2 -- redis-cli -h redis.redis.svc.cluster.local -a KAYQE1QA7uwUZ8uI
###########################################################################################################################
Redis(R) can be accessed via port 6379 on the following DNS name from within your cluster:
redis.redis.svc.cluster.local for read only operations
For read/write operations, first access the Redis(R) Sentinel cluster, which is available in port 26379 using the same domain name above.
To get your password run:
export REDIS_PASSWORD=$(kubectl get secret --namespace redis redis -o jsonpath="{.data.redis-password}" | base64 -d)
To connect to your Redis(R) server:
1. Run a Redis(R) pod that you can use as a client:
kubectl run --namespace redis redis-client --restart='Never' --env REDIS_PASSWORD=$REDIS_PASSWORD --image registry-1.docker.io/bitnami/redis:latest --command -- sleep infinity
Use the following command to attach to the pod:
kubectl exec --tty -i redis-client \
--namespace redis -- bash
2. Connect using the Redis(R) CLI:
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis -p 6379 # Read only operations
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis -p 26379 # Sentinel access
To connect to your database from outside the cluster execute the following commands:
kubectl port-forward --namespace redis svc/redis 6379:6379 &
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379
- **InfluxDB**
------------------------------------------------------------------------------------------------------------------------------
helm repo add influxdata https://helm.influxdata.com/
helm repo update
----
kubectl create namespace influxdb
----
influxdb-values.yaml:
image:
repository: influxdb
tag: 2.7
persistence:
enabled: true
size: 20Gi
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
service:
type: ClusterIP
port: 8086
adminUser:
organization: sts-lab
bucket: demo-bucket
user: admin
password: KAYQE1QA7uwUZ8uI5
token: my-super-token
----
helm install influxdb influxdata/influxdb2 --namespace influxdb -f influxdb-values.yaml
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: influxdb
spec:
hostnames:
- poc2.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: influxdb-influxdb2
port: 8086
****************** TEST ****************************
echo $(kubectl get secret influxdb-influxdb2-auth -o "jsonpath={.data['admin-password']}" --namespace influxdb | base64 --decode)
logon UI
http://localhost:8086
user: admin
password: KAYQE1QA7uwUZ8uI5
TEST API:
curl http://localhost:8086/health
link svc:
influxdb-influxdb2.influxdb.svc.cluster.local
- **MongoDB**
------------------------------------------------------------------------------------------------------------------------------
- **DbGate**
------------------------------------------------------------------------------------------------------------------------------
apiVersion: v1
kind: Namespace
metadata:
name: dbgate
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dbgate
namespace: dbgate
spec:
replicas: 1
selector:
matchLabels:
app: dbgate
template:
metadata:
labels:
app: dbgate
spec:
containers:
- name: dbgate
image: dbgate/dbgate:latest
ports:
- containerPort: 3000
env:
- name: CONNECTIONS
value: ""
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: dbgate
namespace: dbgate
spec:
selector:
app: dbgate
ports:
- port: 80
targetPort: 3000
type: ClusterIP
httproute:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: demo-apps
spec:
hostnames:
- poc3.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: dbgate
port: 3000
---
------------------------------------------------------------------------------------------------------------------------------
## Servizi Applicativi / Utility
- **NodeRed**
apiVersion: v1
kind: Namespace
metadata:
name: nodered
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: node-red-pvc
namespace: nodered
labels:
app: node-red
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-red
namespace: nodered
labels:
app: node-red
spec:
replicas: 1
selector:
matchLabels:
app: node-red
template:
metadata:
labels:
app: node-red
spec:
securityContext:
fsGroup: 1000
containers:
- name: nodered
image: nodered/node-red:4.1
args: ["--settings", "/config/settings.js"]
env:
- name: NODE_OPTIONS
value: "--trace-warnings"
ports:
- containerPort: 1880
securityContext:
runAsUser: 1000
runAsGroup: 1000
allowPrivilegeEscalation: false
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /
port: 1880
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 1880
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: node-red-storage
mountPath: /data
- name: node-red-settings
mountPath: /config/settings.js
subPath: settings.js
volumes:
- name: node-red-storage
persistentVolumeClaim:
claimName: node-red-pvc
- name: node-red-settings
configMap:
name: node-red-settings
---
apiVersion: v1
kind: ConfigMap
metadata:
name: node-red-settings
namespace: nodered
data:
settings.js: |
module.exports = {
httpAdminRoot: '/',
httpNodeRoot: '/',
userDir: '/data',
flowFile: 'flows.json',
credentialSecret: 'yzM0ol6Zn5kd1234',
adminAuth: {
type: "credentials",
users: [{
username: "admin",
password: "",
permissions: "*"
}]
},
uiPort: process.env.PORT || 1880,
mqttReconnectTime: 15000,
serialReconnectTime: 15000,
debugMaxLength: 1000,
functionGlobalContext: {},
exportGlobalContextKeys: false,
logging: {
console: {
level: "info",
metrics: false,
audit: false
}
},
editorTheme: {
projects: {
enabled: false
}
}
};
---
apiVersion: v1
kind: Service
metadata:
name: node-red-service
namespace: nodered
labels:
app: node-red
spec:
type: ClusterIP
ports:
- port: 1880
targetPort: 1880
protocol: TCP
name: http
selector:
app: node-red
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: node-red-hpa
namespace: nodered
labels:
app: node-red
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: node-red
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: node-red
namespace: nodered
spec:
hostnames:
- nodered.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: node-red-service
port: 1880
Istruzioni per set token influxdb
kubectl get pods -n nodered
kubectl exec -it node-red-bd88bc7df-knqfw -n nodered -- node-red admin hash-pw
kubectl edit configmap node-red-settings -n nodered --->(set campo password password: "<bcrypt-hash-here>", nella sezione adminAuth)
kubectl delete pods node-red-bd88bc7df-knqfw -n nodered
------------------------------------------------------------------------------------------------------------------------------
- **Grafana**
Aggiungere repository Helm Grafana
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
----
kubectl create namespace grafana
----
grafana-values.yaml:
replicas: 1
adminUser: admin
adminPassword: KAYQE1QA7uwUZ8uI5
service:
type: ClusterIP
port: 80
persistence:
enabled: true
size: 10Gi
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
---
helm install grafana grafana/grafana -n grafana -f grafana-values.yaml
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: grafana
spec:
hostnames:
- tekton.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: grafana
port: 80
****************** TEST ****************************
Accesso alla UI Grafana
Aprire browser:
http://localhost:3000
Login:
user: admin
password: KAYQE1QA7uwUZ8uI5
link svc:
grafana.grafana.svc.cluster.local
---------------------------------------
Aggiungere InfluxDB come datasource
In Grafana:
Connections
Data Sources
Add data source
InfluxDB
Configurazione:
URL
http://influxdb:8086
Organization:
demo-org
Token:
my-super-token
Bucket:
demo-bucket
Salva.
6⃣ Test datasource
Click:
Save & Test
Se corretto:
Datasource is working
7⃣ Creare dashboard
In Grafana:
Create
Dashboard
Add panel
Query esempio (InfluxDB Flux):
from(bucket: "demo-bucket")
|> range(start: -1h)
------------------------------------------------------------------------------------------------------------------------------
- **Prometheus**
------------------------------------------------------------------------------------------------------------------------------
- **SonarQube**
------------------------------------------------------------------------------------------------------------------------------
########### repo helm ################
helm repo add sonarqube https://SonarSource.github.io/helm-chart-sonarqube
helm repo update
########### creazione ns e secret db ################
kubectl create namespace sonarqube
kubectl create secret generic sonarqube-database-cred \
--from-literal=username=sonarqube \
--from-literal=password=KAYQE1QA7uwUZ8uI \
-n sonarqube
########### creazione database ################
kubectl cnpg psql pg-devops -n devops
CREATE DATABASE sonarqube;
CREATE USER sonarqube WITH PASSWORD 'KAYQE1QA7uwUZ8uI';
GRANT ALL PRIVILEGES ON DATABASE sonarqube TO sonarqube;
ALTER DATABASE sonarqube OWNER TO sonarqube;
########### Values.yaml per installazione helm ################
service:
type: ClusterIP
postgresql:
enabled: false
jdbcOverwrite:
enabled: true
jdbcUrl: "jdbc:postgresql://pg-devops-rw.devops.svc.cluster.local:5432/sonarqube"
jdbcUsername: "postgres"
jdbcSecretName: "sonarqube-database-cred"
jdbcSecretPasswordKey: "password"
readinessProbe:
initialDelaySeconds: 300 # Increase initial delay to accommodate the database start time
timeoutSeconds: 60
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
livenessProbe:
initialDelaySeconds: 360 # Ensure the application has enough time to start
timeoutSeconds: 60
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
startupProbe:
initialDelaySeconds: 300 # Allow for sufficient startup time
timeoutSeconds: 60
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
########### installazione helm ################
helm upgrade -f sonarvalues.yaml --install -n sonarqube sonarqube sonarqube/sonarqube --set community.enabled=true,monitoringPasscode="KAYQE1QA7uwUZ8uI"
########### httproute ################
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: sonarqube
namespace: sonarqube
spec:
hostnames:
- sonarqube.italiadatacenter.com
parentRefs:
- name: main-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: sonarqube-sonarqube
port: 9000
- **KubeEdge**
------------------------------------------------------------------------------------------------------------------------------
- **Knative**
------------------------------------------------------------------------------------------------------------------------------
- **Locust**
------------------------------------------------------------------------------------------------------------------------------