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 < /dev/null < /dev/null < /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 < 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 < 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 < 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 < 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 < 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 < 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 - < 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 <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 < 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 < 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 - < "$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 </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 < "$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 < 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 < 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: "", 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** ------------------------------------------------------------------------------------------------------------------------------