56 KiB
Installazione Piattaforma – Istruzioni
Nota: Documento generato a partire dal file sorgente fornito (
doc.txt). Le sezioni e i blocchi di codice sono mantenuti fedeli all'originale. Se desideri, posso rifinire l'impaginazione (sottosezioni, sommario, evidenziazione dei comandi perbash,yaml, ecc.).
---
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=*****
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 let’s 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: ****************
---
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 '****************';
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: ****************
email: gitadmin@italiadatacenter.com
config:
database:
DB_TYPE: postgres
HOST: pg-devops-rw.devops.svc:5432
NAME: giteadb
USER: gitea
PASSWD: ****************
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: "****************"
# -----------------------
# 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: "****************"
database: registry
sslmode: require
# -----------------------
# REDIS (EXTERNAL)
# -----------------------
redis:
type: external
external:
addr: redis.redis.svc.cluster.local:6379
password: "****************"
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 '****************';
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=******************************** \
--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=******************************** \
--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: *****
---
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=*****" -- 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: ****************
---
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 '****************';
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="******"
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: ****************
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 ****************
###########################################################################################################################
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: *****************
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: *****************
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: *****************
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: *****************
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=**************** \
-n sonarqube
########### creazione database ################
kubectl cnpg psql pg-devops -n devops
CREATE DATABASE sonarqube;
CREATE USER sonarqube WITH PASSWORD '****************';
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="****************"
########### 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