feat: overhaul into ArgoCD GitOps architecture

- app-of-apps root Application + AppProject under clusters/minikube
- managed Applications: VPA, GreenKube (multi-source chart+values), demo app, platform ingresses
- annotated demo workload for the GreenKube PR bot
- bootstrap script: minikube, ingress-nginx, cert-manager, ArgoCD, Gitea, repo seeding
- remove imperative scripts and unused values files
This commit is contained in:
Hugo Lelievre
2026-09-27 12:19:04 +02:00
parent d206b10509
commit 24432a26c6
36 changed files with 947 additions and 4420 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
kube-prometheus/
*secret.yaml
*secret.yaml
.bootstrap-state/
+108
View File
@@ -0,0 +1,108 @@
# local-k8s — GitOps for the local GreenKube Minikube cluster
This repository is the **single source of truth** for the workloads running in the
local Minikube cluster. Declarative state is reconciled by **ArgoCD** (app-of-apps):
the root Application watches `clusters/minikube/apps/` and creates one child
Application per component.
```text
bootstrap/bootstrap.sh # day-0: cluster + ingress + cert-manager + ArgoCD + Gitea
│
▼
clusters/minikube/root-app.yaml # applied by the bootstrap, points at the in-cluster Gitea repo
│
▼
clusters/minikube/apps/*.yaml # child Applications (VPA, GreenKube, demo workloads)
```
Everything under `clusters/` is reconciled continuously. Editing a manifest in
this repository (directly or through a GreenKube pull request) is the only way
to change the cluster.
## Why Gitea?
ArgoCD needs a Git server it can reach; the GreenKube PR bot needs a Git API it
can open pull requests against. Running **Gitea inside the cluster** keeps the
loop self-contained and fully testable offline:
```text
GreenKube UI ──► PR bot ──► Gitea PR ──► merge ──► ArgoCD sync ──► cluster
▲ │
└────────────── apply detection & verification ◄──────────────┘
```
On a real installation, point the Applications and the
`greenkube.cloud/git-repo` annotations at your GitHub/GitLab repository instead.
## Bootstrap
Prerequisites: Docker, Minikube, kubectl and Helm.
```bash
./bootstrap/bootstrap.sh
```
The script is idempotent and performs the day-0 steps that cannot be
GitOps-managed (a Git server and ArgoCD must exist before they can be
self-managed):
1. starts Minikube if needed;
2. installs ingress-nginx and cert-manager (and the `letsencrypt-prod` issuer);
3. installs ArgoCD (pinned version);
4. installs Gitea and creates the `greenkube` user + API token;
5. pushes this repository and the GreenKube source repository (`dev` branch)
to Gitea;
6. creates the `greenkube-gitops` namespace secret (`GIT_TOKEN`, Postgres
credentials);
7. applies the AppProject and the root Application.
After that, ArgoCD owns the rest.
### Access
```bash
kubectl port-forward svc/argocd-server -n argocd 8080:443
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d
```
Gitea is reachable from the host after
`kubectl port-forward -n gitea svc/gitea-http 3000:3000`.
## Managed applications
| Application | Source | Namespace | Notes |
|---|---|---|---|
| `vpa` | Fairwinds chart | `vpa` | Vertical Pod Autoscaler in recommendation mode (updater disabled) |
| `greenkube-gitops` | `greenkube/greenkube` chart (Gitea, `dev`) + values from this repo | `greenkube-gitops` | GreenKube itself, with the PR bot enabled |
| `demo-app` | this repo | `demo` | Annotated workload used to exercise rightsizing + the PR bot |
The monitoring stack (kube-prometheus, OpenCost), ingress-nginx, cert-manager
and Gitea are **bootstrap components** and are intentionally not managed by
ArgoCD yet: they were installed before the GitOps migration. They can be
adopted one by one later; the demo workloads only depend on Prometheus,
OpenCost and metrics-server being available.
## GreenKube source annotations
The PR bot finds the manifest of a workload through annotations:
| Annotation | Required | Meaning |
|---|---|---|
| `greenkube.cloud/git-repo` | yes | Git remote URL (Gitea by default) |
| `greenkube.cloud/git-path` | no | Manifest path; discovery scans the repo when omitted |
| `greenkube.cloud/git-branch` | no | Base branch override (defaults to `main`) |
Each managed workload must carry the annotation of the repository that
contains **its own manifest** — that is what makes the pull request possible.
## Repository layout
```text
bootstrap/bootstrap.sh Day-0 installer (idempotent)
clusters/minikube/
├── project.yaml ArgoCD AppProject
├── root-app.yaml App-of-apps root Application
├── apps/ One ArgoCD Application per component
├── values/ Helm values per component
└── manifests/ Raw manifests (demo workloads)
```
-27
View File
@@ -1,27 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- argocd.greenkube.cloud
secretName: argocd-tls
rules:
- host: "argocd.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
+325
View File
@@ -0,0 +1,325 @@
#!/usr/bin/env bash
#
# Day-0 bootstrap for the GitOps-managed Minikube platform.
#
# Installs the components that cannot manage themselves (Gitea and ArgoCD),
# seeds the Gitea repositories from the local working trees and applies the
# app-of-apps root Application. Everything after that is reconciled by ArgoCD.
#
# The script is idempotent: re-running it never overwrites an existing cluster
# component or secret.
set -euo pipefail
# ---------------------------------------------------------------------------
# Configuration (override with environment variables)
# ---------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
GREENKUBE_REPO="${GREENKUBE_REPO:-$(cd "${REPO_ROOT}/../GreenKube" 2>/dev/null && pwd || true)}"
STATE_DIR="${REPO_ROOT}/.bootstrap-state"
GITEA_NAMESPACE="${GITEA_NAMESPACE:-gitea}"
GITEA_RELEASE="${GITEA_RELEASE:-gitea}"
GITEA_CHART_VERSION="${GITEA_CHART_VERSION:-12.7.0}"
GITEA_PORT="${GITEA_PORT:-13000}"
GITEA_OWNER="${GITEA_OWNER:-greenkube}"
GITEA_USER_PASSWORD="${GITEA_USER_PASSWORD:-greenkube-bot-password}"
GITEA_TOKEN_NAME="${GITEA_TOKEN_NAME:-greenkube-bot}"
ARGOCD_VERSION="${ARGOCD_VERSION:-v2.13.3}"
ARGOCD_NAMESPACE="${ARGOCD_NAMESPACE:-argocd}"
GREENKUBE_NAMESPACE="${GREENKUBE_NAMESPACE:-greenkube-gitops}"
GREENKUBE_SECRET="${GREENKUBE_SECRET:-greenkube-gitops-secrets}"
GREENKUBE_DB_USER="${GREENKUBE_DB_USER:-greenkube}"
INGRESS_NGINX_VERSION="${INGRESS_NGINX_VERSION:-4.14.3}"
CERT_MANAGER_VERSION="${CERT_MANAGER_VERSION:-v1.15.1}"
GITEA_BASE="http://127.0.0.1:${GITEA_PORT}"
GITEA_IN_CLUSTER_HOST="gitea-http.${GITEA_NAMESPACE}.svc.cluster.local:3000"
log() { printf '\033[1;32m[bootstrap]\033[0m %s\n' "$*" >&2; }
warn() { printf '\033[1;33m[bootstrap]\033[0m %s\n' "$*" >&2; }
die() { printf '\033[1;31m[bootstrap]\033[0m %s\n' "$*" >&2; exit 1; }
require() {
for tool in "$@"; do
command -v "$tool" >/dev/null 2>&1 || die "Missing required tool: $tool"
done
}
# ---------------------------------------------------------------------------
# 1. Cluster
# ---------------------------------------------------------------------------
ensure_minikube() {
if minikube status >/dev/null 2>&1; then
log "Minikube is running."
else
log "Starting Minikube..."
minikube start --driver=qemu --cpus=6 --memory=16g --network=builtin
fi
kubectl cluster-info >/dev/null
}
# ---------------------------------------------------------------------------
# 2. Day-0 ingress and certificates
# ---------------------------------------------------------------------------
ensure_helm_repos() {
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx >/dev/null 2>&1 || true
helm repo add jetstack https://charts.jetstack.io >/dev/null 2>&1 || true
helm repo add gitea-charts https://dl.gitea.com/charts/ >/dev/null 2>&1 || true
helm repo update >/dev/null
}
ensure_ingress_nginx() {
if helm status ingress-nginx -n ingress-nginx >/dev/null 2>&1; then
log "ingress-nginx already installed; leaving it untouched."
return
fi
log "Installing ingress-nginx ${INGRESS_NGINX_VERSION}..."
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--version "${INGRESS_NGINX_VERSION}" \
--set controller.service.type=NodePort \
--set controller.service.nodePorts.http=31000 \
--set controller.service.nodePorts.https=31443 \
--set controller.config.use-forwarded-headers=true \
--wait --timeout 10m
}
ensure_cert_manager() {
if helm status cert-manager -n cert-manager >/dev/null 2>&1; then
log "cert-manager already installed; leaving it untouched."
else
log "Installing cert-manager ${CERT_MANAGER_VERSION}..."
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--version "${CERT_MANAGER_VERSION}" --set crds.enabled=true \
--wait --timeout 10m
fi
kubectl apply -f "${REPO_ROOT}/clusters/minikube/manifests/ingresses/cluster-issuer.yaml"
}
# ---------------------------------------------------------------------------
# 3. ArgoCD
# ---------------------------------------------------------------------------
ensure_argocd() {
if kubectl -n "${ARGOCD_NAMESPACE}" get deployment argocd-server >/dev/null 2>&1; then
log "ArgoCD already installed in namespace ${ARGOCD_NAMESPACE}."
else
log "Installing ArgoCD ${ARGOCD_VERSION}..."
kubectl create namespace "${ARGOCD_NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -n "${ARGOCD_NAMESPACE}" -f \
"https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml"
fi
kubectl -n "${ARGOCD_NAMESPACE}" rollout status deployment/argocd-server --timeout=10m
}
# ---------------------------------------------------------------------------
# 4. Gitea
# ---------------------------------------------------------------------------
gitea_admin_password() {
mkdir -p "${STATE_DIR}"
local file="${STATE_DIR}/gitea-admin-password"
if [[ -f "${file}" ]]; then
cat "${file}"
else
local password
password="$(head -c 18 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20)"
printf '%s' "${password}" > "${file}"
chmod 600 "${file}"
printf '%s' "${password}"
fi
}
ensure_gitea() {
if helm status "${GITEA_RELEASE}" -n "${GITEA_NAMESPACE}" >/dev/null 2>&1; then
log "Gitea already installed."
else
log "Installing Gitea ${GITEA_CHART_VERSION}..."
local admin_password
admin_password="$(gitea_admin_password)"
cat > "${STATE_DIR}/gitea-values.yaml" <<EOF
gitea:
admin:
username: gitea-admin
password: "${admin_password}"
email: admin@greenkube.local
config:
server:
DOMAIN: ${GITEA_IN_CLUSTER_HOST%:*}
ROOT_URL: http://${GITEA_IN_CLUSTER_HOST}/
persistence:
enabled: true
size: 2Gi
EOF
helm upgrade --install "${GITEA_RELEASE}" gitea-charts/gitea \
--namespace "${GITEA_NAMESPACE}" --create-namespace \
--version "${GITEA_CHART_VERSION}" \
-f "${STATE_DIR}/gitea-values.yaml" \
--wait --timeout 10m
fi
kubectl -n "${GITEA_NAMESPACE}" rollout status deployment/gitea --timeout=10m
}
GITEA_PF_PID=""
start_gitea_port_forward() {
kubectl -n "${GITEA_NAMESPACE}" port-forward "svc/gitea-http" "${GITEA_PORT}:3000" >/dev/null 2>&1 &
GITEA_PF_PID=$!
for _ in $(seq 1 60); do
if curl -sf "${GITEA_BASE}/api/v1/version" >/dev/null 2>&1; then
return 0
fi
sleep 1
done
die "Gitea API did not become reachable on ${GITEA_BASE}."
}
stop_gitea_port_forward() {
if [[ -n "${GITEA_PF_PID}" ]]; then
kill "${GITEA_PF_PID}" >/dev/null 2>&1 || true
wait "${GITEA_PF_PID}" 2>/dev/null || true
fi
}
trap stop_gitea_port_forward EXIT
gitea_admin_api() {
local method="$1"; shift
local path="$1"; shift
curl -sf -X "${method}" \
-u "gitea-admin:$(gitea_admin_password)" \
-H "Content-Type: application/json" \
"${GITEA_BASE}/api/v1${path}" "$@" 2>/dev/null || true
}
ensure_gitea_user() {
if gitea_admin_api GET "/users/${GITEA_OWNER}" | grep -q '"login"'; then
log "Gitea user '${GITEA_OWNER}' exists."
return
fi
log "Creating Gitea user '${GITEA_OWNER}'..."
gitea_admin_api POST "/admin/users" -d "{
\"username\": \"${GITEA_OWNER}\",
\"login_name\": \"${GITEA_OWNER}\",
\"email\": \"${GITEA_OWNER}@greenkube.local\",
\"password\": \"${GITEA_USER_PASSWORD}\",
\"must_change_password\": false
}" >/dev/null
}
GITEA_TOKEN_FILE="${STATE_DIR}/gitea-token"
ensure_gitea_token() {
mkdir -p "${STATE_DIR}"
if [[ -s "${GITEA_TOKEN_FILE}" ]] && \
curl -sf -H "Authorization: token $(cat "${GITEA_TOKEN_FILE}")" \
"${GITEA_BASE}/api/v1/user" >/dev/null 2>&1; then
cat "${GITEA_TOKEN_FILE}"
return
fi
log "Creating Gitea API token for '${GITEA_OWNER}'..."
local response token
response="$(gitea_admin_api POST "/users/${GITEA_OWNER}/tokens" -d "{
\"name\": \"${GITEA_TOKEN_NAME}\",
\"scopes\": [\"write:repository\", \"read:repository\", \"write:user\", \"read:user\"]
}")"
token="$(printf '%s' "${response}" | sed -n 's/.*"sha1":"\([^"]*\)".*/\1/p')"
[[ -n "${token}" ]] || die "Could not create a Gitea API token. Response: ${response}"
printf '%s' "${token}" > "${GITEA_TOKEN_FILE}"
chmod 600 "${GITEA_TOKEN_FILE}"
printf '%s' "${token}"
}
ensure_gitea_repo() {
local name="$1" default_branch="$2"
if gitea_admin_api GET "/repos/${GITEA_OWNER}/${name}" | grep -q '"name"'; then
log "Gitea repository ${GITEA_OWNER}/${name} exists."
return
fi
log "Creating Gitea repository ${GITEA_OWNER}/${name}..."
gitea_admin_api POST "/admin/users/${GITEA_OWNER}/repos" -d "{
\"name\": \"${name}\",
\"default_branch\": \"${default_branch}\",
\"private\": false,
\"auto_init\": false
}" >/dev/null
}
push_repo() {
local local_path="$1" remote_name="$2" branch="$3" token="$4"
local remote_url="http://${GITEA_OWNER}:${token}@127.0.0.1:${GITEA_PORT}/${GITEA_OWNER}/${remote_name}.git"
log "Pushing ${local_path} (${branch}) → ${GITEA_OWNER}/${remote_name}..."
git -C "${local_path}" push --force "${remote_url}" "${branch}:${branch}" >/dev/null
}
# ---------------------------------------------------------------------------
# 5. GreenKube credentials
# ---------------------------------------------------------------------------
ensure_greenkube_secret() {
local token="$1"
local password_file="${STATE_DIR}/greenkube-db-password"
local db_password
if kubectl -n "${GREENKUBE_NAMESPACE}" get secret "${GREENKUBE_SECRET}" >/dev/null 2>&1; then
log "GreenKube secret ${GREENKUBE_NAMESPACE}/${GREENKUBE_SECRET} already exists."
return
fi
if [[ -f "${password_file}" ]]; then
db_password="$(cat "${password_file}")"
else
db_password="$(head -c 18 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 24)"
printf '%s' "${db_password}" > "${password_file}"
chmod 600 "${password_file}"
fi
kubectl create namespace "${GREENKUBE_NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
log "Creating GreenKube secret (Git token + Postgres credentials)..."
kubectl -n "${GREENKUBE_NAMESPACE}" create secret generic "${GREENKUBE_SECRET}" \
--from-literal=GIT_TOKEN="${token}" \
--from-literal=POSTGRES_PASSWORD="${db_password}" \
--from-literal="DB_CONNECTION_STRING=postgresql://${GREENKUBE_DB_USER}:${db_password}@greenkube-gitops-postgres:5432/greenkube"
}
# ---------------------------------------------------------------------------
# 6. Root application
# ---------------------------------------------------------------------------
apply_root_application() {
log "Applying AppProject and root Application..."
kubectl apply -f "${REPO_ROOT}/clusters/minikube/project.yaml"
kubectl apply -f "${REPO_ROOT}/clusters/minikube/root-app.yaml"
}
main() {
require minikube kubectl helm git curl
ensure_minikube
ensure_helm_repos
ensure_ingress_nginx
ensure_cert_manager
ensure_argocd
ensure_gitea
start_gitea_port_forward
ensure_gitea_user
local token
token="$(ensure_gitea_token)"
ensure_gitea_repo "local-k8s" "main"
if [[ -n "${GREENKUBE_REPO}" && -d "${GREENKUBE_REPO}/.git" ]]; then
ensure_gitea_repo "greenkube" "dev"
else
warn "GreenKube repository not found at '${GREENKUBE_REPO}'; skipping its push."
fi
push_repo "${REPO_ROOT}" "local-k8s" "main" "${token}"
if [[ -n "${GREENKUBE_REPO}" && -d "${GREENKUBE_REPO}/.git" ]]; then
push_repo "${GREENKUBE_REPO}" "greenkube" "dev" "${token}"
fi
stop_gitea_port_forward
ensure_greenkube_secret "${token}"
apply_root_application
log "Bootstrap complete."
log "ArgoCD admin password:"
kubectl -n "${ARGOCD_NAMESPACE}" get secret argocd-initial-admin-secret \
-o jsonpath='{.data.password}' 2>/dev/null | base64 -d || warn "ArgoCD secret not found."
printf '\n'
log "Watch reconciliation: kubectl -n argocd get applications -w"
}
main "$@"
+38
View File
@@ -0,0 +1,38 @@
# Vertical Pod Autoscaler in recommendation mode.
# The updater is disabled: GreenKube reads VPA recommendations (updateMode: Off)
# and surfaces them as recommendations instead of letting VPA mutate pods.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: vpa
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: platform
source:
repoURL: https://charts.fairwinds.com/stable
chart: vpa
targetRevision: 5.1.0
helm:
values: |
admissionController:
enabled: true
recommender:
enabled: true
updater:
enabled: false
metrics-server:
enabled: false
destination:
server: https://kubernetes.default.svc
namespace: vpa
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
+36
View File
@@ -0,0 +1,36 @@
# GreenKube itself, with the GitOps PR bot enabled.
#
# The chart lives in the GreenKube source repository (pushed to Gitea on
# bootstrap) while the environment-specific values live here, so the same
# chart can target different clusters without duplicating Helm values.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: greenkube-gitops
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: platform
sources:
- repoURL: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/greenkube.git
targetRevision: dev
path: helm-chart
helm:
valueFiles:
- $values/clusters/minikube/values/greenkube.yaml
- repoURL: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: greenkube-gitops
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
+29
View File
@@ -0,0 +1,29 @@
# Annotated demo workload used to exercise the GreenKube optimization engine,
# the VPA connector and the GitOps PR bot end to end.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-app
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: platform
source:
repoURL: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
targetRevision: main
path: clusters/minikube/manifests/demo-app
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: demo
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
@@ -0,0 +1,30 @@
# Platform ingresses and the Let's Encrypt ClusterIssuer.
# These resources predate the GitOps migration and are adopted with
# automated.prune=false so a mistaken removal here cannot delete a live ingress.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-ingresses
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: platform
source:
repoURL: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
targetRevision: main
path: clusters/minikube/manifests/ingresses
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: false
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
@@ -0,0 +1,47 @@
# Deliberately over-requested workload used to demonstrate the GreenKube
# optimization engine and the GitOps PR bot.
#
# The greenkube.cloud/git-* annotations point the bot at this very file in the
# local-k8s repository. When a rightsizing recommendation is turned into a pull
# request, only the resources.requests block below changes.
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-web
namespace: demo
labels:
app.kubernetes.io/name: demo-web
app.kubernetes.io/part-of: greenkube-demo
annotations:
greenkube.cloud/git-repo: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
greenkube.cloud/git-path: clusters/minikube/manifests/demo-app/deployment.yaml
greenkube.cloud/git-branch: main
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: demo-web
template:
metadata:
labels:
app.kubernetes.io/name: demo-web
spec:
containers:
- name: web
image: nginxinc/nginx-unprivileged:1.27-alpine
ports:
- name: http
containerPort: 8080
resources:
requests:
cpu: 500m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: demo
labels:
app.kubernetes.io/part-of: greenkube-demo
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: demo-web
namespace: demo
labels:
app.kubernetes.io/name: demo-web
app.kubernetes.io/part-of: greenkube-demo
spec:
selector:
app.kubernetes.io/name: demo-web
ports:
- name: http
port: 80
targetPort: http
@@ -0,0 +1,26 @@
# Recommendation-mode VPA for the demo workload. GreenKube reads its targets
# (Phase 6 VPA connector) and suppresses the native rightsizing advice for the
# same workload to avoid duplicate or contradictory recommendations.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: demo-web
namespace: demo
labels:
app.kubernetes.io/part-of: greenkube-demo
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: demo-web
updatePolicy:
updateMode: "Off"
resourcePolicy:
containerPolicies:
- containerName: web
minAllowed:
cpu: 10m
memory: 16Mi
maxAllowed:
cpu: "1"
memory: 512Mi
@@ -2,6 +2,8 @@ apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
labels:
app.kubernetes.io/part-of: local-k8s
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
@@ -9,6 +11,6 @@ spec:
privateKeySecretRef:
name: letsencrypt-http01-private-key
solvers:
- http01:
ingress:
class: nginx
- http01:
ingress:
class: nginx
@@ -0,0 +1,186 @@
# Ingresses for the platform components. These resources predate the GitOps
# migration and are adopted by ArgoCD (syncPolicy.prune=false) so that removing
# an entry here never deletes a live ingress unexpectedly.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- argocd.greenkube.cloud
secretName: argocd-tls
rules:
- host: argocd.greenkube.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- grafana.greenkube.cloud
secretName: grafana-tls
rules:
- host: grafana.greenkube.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- prometheus.greenkube.cloud
secretName: prometheus-tls
rules:
- host: prometheus.greenkube.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus-k8s
port:
number: 9090
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: opencost-ingress
namespace: opencost
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- opencost.greenkube.cloud
secretName: opencost-tls
rules:
- host: opencost.greenkube.cloud
http:
paths:
- path: /allocation
pathType: Prefix
backend:
service:
name: opencost
port:
number: 9003
- path: /
pathType: Prefix
backend:
service:
name: opencost
port:
number: 9090
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: es-ingress
namespace: elastic-greenkube
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- elasticsearch.greenkube.cloud
secretName: es-cluster-tls
rules:
- host: elasticsearch.greenkube.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mon-cluster-es-es-http
port:
number: 9200
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kibana-ingress
namespace: elastic-greenkube
labels:
app.kubernetes.io/part-of: local-k8s
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- kibana.greenkube.cloud
secretName: kibana-cluster-tls
rules:
- host: kibana.greenkube.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mon-kibana-kb-http
port:
number: 5601
+22
View File
@@ -0,0 +1,22 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: platform
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
spec:
description: Local Minikube platform managed by the app-of-apps root Application.
sourceRepos:
- http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
- http://gitea-http.gitea.svc.cluster.local:3000/greenkube/greenkube.git
- https://charts.fairwinds.com/stable
destinations:
- namespace: "*"
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: "*"
kind: "*"
namespaceResourceWhitelist:
- group: "*"
kind: "*"
+31
View File
@@ -0,0 +1,31 @@
# App-of-apps root Application.
#
# Applied once by bootstrap/bootstrap.sh. Every Application under
# clusters/minikube/apps/ is then created and kept in sync by ArgoCD.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
labels:
app.kubernetes.io/part-of: local-k8s
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: platform
source:
repoURL: http://gitea-http.gitea.svc.cluster.local:3000/greenkube/local-k8s.git
targetRevision: main
path: clusters/minikube/apps
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
+41
View File
@@ -0,0 +1,41 @@
# Environment-specific values for the GreenKube instance managed by ArgoCD.
# The chart itself is pulled from the GreenKube repository (Gitea, branch dev).
image:
repository: greenkube/greenkube
# Built locally and loaded into Minikube with `minikube image load`.
tag: gitops-dev
pullPolicy: Never
# Credentials (GIT_TOKEN, POSTGRES_PASSWORD, DB_CONNECTION_STRING) are created
# by bootstrap/bootstrap.sh — never committed to Git.
secrets:
existingSecret: greenkube-gitops-secrets
config:
clusterName: minikube
db:
type: postgres
prometheus:
url: http://prometheus-k8s.monitoring.svc.cluster.local:9090
opencost:
url: http://opencost.opencost.svc.cluster.local:9003
recommendations:
# Phase 6 connectors: enabled by default, they detect their CRDs at runtime.
vpaEnabled: true
karpenterEnabled: true
# Short verification window so the demo loop completes quickly.
verification:
windowHours: 0.05
minSamples: 1
minSavingsRatio: 0.1
git:
provider: gitea
apiBaseUrl: http://gitea-http.gitea.svc.cluster.local:3000
defaultBranch: main
monitoring:
serviceMonitor:
enabled: false
postgres:
enabled: true
-12
View File
@@ -1,12 +0,0 @@
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: mon-cluster-es
namespace: elastic-greenkube
spec:
version: 8.14.1 # Choisissez la version d'Elasticsearch que vous souhaitez
nodeSets:
- name: default
count: 1 # Pour un test, un seul noeud suffit. Pour de la production, mettez-en 3.
config:
node.store.allow_mmap: false # Réglage souvent nécessaire sur K8s
-28
View File
@@ -1,28 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: es-ingress
namespace: elastic-greenkube
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- elasticsearch.greenkube.cloud
secretName: es-cluster-tls
rules:
- host: "elasticsearch.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
# L'opérateur crée un service avec le nom du cluster + "-es-http"
name: mon-cluster-es-es-http
port:
number: 9200
-373
View File
@@ -1,373 +0,0 @@
# nameOverride is the short name for the deployment. Leave empty to let Helm generate a name using chart values.
nameOverride: "elastic-operator"
# fullnameOverride is the full name for the deployment. Leave empty to let Helm generate a name using chart values.
fullnameOverride: "elastic-operator"
# managedNamespaces is the set of namespaces that the operator manages. Leave empty to manage all namespaces.
managedNamespaces: []
# installCRDs determines whether Custom Resource Definitions (CRD) are installed by the chart.
# Note that CRDs are global resources and require cluster admin privileges to install.
# If you are sharing a cluster with other users who may want to install ECK on their own namespaces, setting this to true can have unintended consequences.
# 1. Upgrades will overwrite the global CRDs and could disrupt the other users of ECK who may be running a different version.
# 2. Uninstalling the chart will delete the CRDs and potentially cause Elastic resources deployed by other users to be removed as well.
installCRDs: true
# replicaCount is the number of operator pods to run.
replicaCount: 1
image:
# repository is the container image prefixed by the registry name.
repository: docker.elastic.co/eck/eck-operator
# pullPolicy is the container image pull policy.
pullPolicy: IfNotPresent
# tag is the container image tag. If not defined, defaults to chart appVersion.
tag: null
# fips specifies whether the operator will use a FIPS compliant container image for its own StatefulSet image.
# This setting does not apply to Elastic Stack applications images.
# Can be combined with config.ubiOnly.
fips: false
# priorityClassName defines the PriorityClass to be used by the operator pods.
priorityClassName: ""
# imagePullSecrets defines the secrets to use when pulling the operator container image.
imagePullSecrets: []
# resources define the container resource limits for the operator.
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 100m
memory: 150Mi
# statefulsetAnnotations define the annotations that should be added to the operator StatefulSet.
statefulsetAnnotations: {}
# statefulsetLabels define additional labels that should be added to the operator StatefulSet.
statefulsetLabels: {}
# podAnnotations define the annotations that should be added to the operator pod.
podAnnotations: {}
## podLabels define additional labels that should be added to the operator pod.
podLabels: {}
# podSecurityContext defines the pod security context for the operator pod.
podSecurityContext:
runAsNonRoot: true
# securityContext defines the security context of the operator container.
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
# nodeSelector defines the node selector for the operator pod.
nodeSelector: {}
# tolerations defines the node tolerations for the operator pod.
tolerations: []
# affinity defines the node affinity rules for the operator pod.
affinity: {}
# podDisruptionBudget configures the minimum or the maxium available pods for voluntary disruptions,
# set to either an integer (e.g. 1) or a percentage value (e.g. 25%).
podDisruptionBudget:
enabled: false
minAvailable: 1
# maxUnavailable: 3
# additional environment variables for the operator container.
env: []
# additional volume mounts for the operator container.
volumeMounts: []
# additional volumes to add to the operator pod.
volumes: []
# createClusterScopedResources determines whether cluster-scoped resources (ClusterRoles, ClusterRoleBindings) should be created.
createClusterScopedResources: true
# Automount API credentials for the Service Account into the pod.
automountServiceAccountToken: true
serviceAccount:
# create specifies whether a service account should be created for the operator.
create: true
# Specifies whether a service account should automount API credentials.
automountServiceAccountToken: true
# annotations to add to the service account
annotations: {}
# name of the service account to use. If not set and create is true, a name is generated using the fullname template.
name: ""
tracing:
# enabled specifies whether APM tracing is enabled for the operator.
enabled: false
# config is a map of APM Server configuration variables that should be set in the environment.
config:
ELASTIC_APM_SERVER_URL: http://localhost:8200
ELASTIC_APM_SERVER_TIMEOUT: 30s
refs:
# enforceRBAC specifies whether RBAC should be enforced for cross-namespace associations between resources.
enforceRBAC: false
webhook:
# enabled determines whether the webhook is installed.
enabled: true
# caBundle is the PEM-encoded CA trust bundle for the webhook certificate. Only required if manageCerts is false and certManagerCert is null.
caBundle: Cg==
# certManagerCert is the name of the cert-manager certificate to use with the webhook.
certManagerCert: null
# certsDir is the directory to mount the certificates.
certsDir: "/tmp/k8s-webhook-server/serving-certs"
# failurePolicy of the webhook.
failurePolicy: Ignore
# manageCerts determines whether the operator manages the webhook certificates automatically.
manageCerts: true
# namespaceSelector corresponds to the namespaceSelector property of the webhook.
# Setting this restricts the webhook to act only on objects submitted to namespaces that match the selector.
namespaceSelector: {}
# objectSelector corresponds to the objectSelector property of the webhook.
# Setting this restricts the webhook to act only on objects that match the selector.
objectSelector: {}
# port is the port that the validating webhook binds to.
port: 9443
# secret specifies the Kubernetes secret to be mounted into the path designated by the certsDir value to be used for webhook certificates.
certsSecret: ""
# hostNetwork allows a Pod to use the Node network namespace.
# This is required to allow for communication with the kube API when using some alternate CNIs in conjunction with webhook enabled.
# If hostNetwork is enabled, dnsPolicy defaults to ClusterFirstWithHostNet unless explicitly set.
# CAUTION: Proceed at your own risk. This setting has security concerns such as allowing malicious users to access workloads running on the host.
hostNetwork: false
# dnsPolicy defines the DNS policy for the operator pod.
# Check https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy for more details.
dnsPolicy: ""
# dnsConfig defines the DNS configuration for the operator pod.
# Check https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config for more details.
# dnsConfig:
# nameservers:
# - 169.254.20.10
# searches:
# - svc.cluster.local
# options:
# - name: ndots
# value: "2"
dnsConfig: {}
softMultiTenancy:
# enabled determines whether the operator is installed with soft multi-tenancy extensions.
# This requires network policies to be enabled on the Kubernetes cluster.
enabled: false
# kubeAPIServerIP is required when softMultiTenancy is enabled.
kubeAPIServerIP: null
telemetry:
# disabled determines whether the operator periodically updates ECK telemetry data for Kibana to consume.
disabled: false
# distributionChannel denotes which distribution channel was used to install the operator.
distributionChannel: "helm"
# config values for the operator.
config:
# logVerbosity defines the logging level. Valid values are as follows:
# -2: Errors only
# -1: Errors and warnings
# 0: Errors, warnings, and information
# number greater than 0: Errors, warnings, information, and debug details.
logVerbosity: "0"
# (Deprecated: use metrics.port: will be removed in v2.14.0) metricsPort defines the port to expose operator metrics. Set to 0 to disable metrics reporting.
metricsPort: 0
metrics:
# port defines the port to expose operator metrics. Set to 0 to disable metrics reporting.
port: "0"
# secureMode contains the options for enabling and configuring RBAC and TLS/HTTPs for the metrics endpoint.
secureMode:
# secureMode.enabled specifies whether to enable RBAC and TLS/HTTPs for the metrics endpoint.
# * This option makes most sense when using a ServiceMonitor to scrape the metrics and is therefore mutually exclusive with the podMonitor.enabled option.
# * This option also requires using cluster scoped resources (ClusterRole, ClusterRoleBinding) to
# grant access to the /metrics endpoint. (createClusterScopedResources: true is required)
#
enabled: false
tls:
# certificateSecret is the name of the tls secret containing the custom TLS certificate and key for the secure metrics endpoint.
#
# * This is an optional setting and is only required if you are using a custom TLS certificate. A self-signed certificate will be generated by default.
# * TLS secret key must be named tls.crt.
# * TLS key's secret key must be named tls.key.
# * It is assumed to be in the same namespace as the ServiceMonitor.
#
# example: kubectl create secret tls eck-metrics-tls-certificate -n elastic-system \
# --cert=/path/to/tls.crt --key=/path/to/tls.key
certificateSecret: ""
# containerRegistry to use for pulling Elasticsearch and other application container images.
containerRegistry: docker.elastic.co
# containerRepository to use for pulling Elasticsearch and other application container images.
# containerRepository: ""
# containerSuffix suffix to be appended to container images by default. Cannot be combined with -ubiOnly flag
# containerSuffix: ""
# maxConcurrentReconciles is the number of concurrent reconciliation operations to perform per controller.
maxConcurrentReconciles: "3"
# caValidity defines the validity period of the CA certificates generated by the operator.
caValidity: 8760h
# caRotateBefore defines when to rotate a CA certificate that is due to expire.
caRotateBefore: 24h
# caDir defines the directory containing a CA certificate (tls.crt) and its associated private key (tls.key) to be used for all managed resources.
# Setting this makes caRotateBefore and caValidity values ineffective.
caDir: ""
# certificatesValidity defines the validity period of certificates generated by the operator.
certificatesValidity: 8760h
# certificatesRotateBefore defines when to rotate a certificate that is due to expire.
certificatesRotateBefore: 24h
# disableConfigWatch specifies whether the operator watches the configuration file for changes.
disableConfigWatch: false
# exposedNodeLabels is an array of regular expressions of node labels which are allowed to be copied as annotations on Elasticsearch Pods.
exposedNodeLabels: [ "topology.kubernetes.io/.*", "failure-domain.beta.kubernetes.io/.*" ]
# ipFamily specifies the IP family to use. Possible values: IPv4, IPv6 and "" (auto-detect)
ipFamily: ""
# setDefaultSecurityContext determines whether a default security context is set on application containers created by the operator.
# *note* that the default option now is "auto-detect" to attempt to set this properly automatically when both running
# in an openshift cluster, and a standard kubernetes cluster. Valid values are as follows:
# "auto-detect" : auto detect
# "true" : set pod security context when creating resources.
# "false" : do not set pod security context when creating resources.
setDefaultSecurityContext: "auto-detect"
# kubeClientTimeout sets the request timeout for Kubernetes API calls made by the operator.
kubeClientTimeout: 60s
# elasticsearchClientTimeout sets the request timeout for Elasticsearch API calls made by the operator.
elasticsearchClientTimeout: 180s
# validateStorageClass specifies whether storage classes volume expansion support should be verified.
# Can be disabled if cluster-wide storage class RBAC access is not available.
validateStorageClass: true
# enableLeaderElection specifies whether leader election should be enabled
enableLeaderElection: true
# Interval between observations of Elasticsearch health, non-positive values disable asynchronous observation.
elasticsearchObservationInterval: 10s
# ubiOnly specifies whether the operator will use only UBI container images to deploy Elastic Stack applications as well as for its own StatefulSet image. UBI images are only available from 7.10.0 onward.
# Cannot be combined with the containerSuffix value.
ubiOnly: false
# Prometheus PodMonitor configuration
# Reference: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#podmonitor
podMonitor:
# enabled determines whether a podMonitor should deployed to scrape the eck metrics.
# This requires the prometheus operator and the config.metrics.port not to be 0
enabled: false
# labels adds additional labels to the podMonitor
labels: {}
# annotations adds additional annotations to the podMonitor
annotations: {}
# namespace determines in which namespace the podMonitor will be deployed.
# If not set the podMonitor will be created in the namespace where the Helm release is installed into
# namespace: monitoring
# interval specifies the interval at which metrics should be scraped
interval: 5m
# scrapeTimeout specifies the timeout after which the scrape is ended
scrapeTimeout: 30s
# podTargetLabels transfers labels on the Kubernetes Pod onto the target.
podTargetLabels: []
# podMetricsEndpointConfig allows to add an extended configuration to the podMonitor
podMetricsEndpointConfig: {}
# honorTimestamps: true
# Prometheus ServiceMonitor configuration
# Only used when config.enableSecureMetrics is true
# Reference: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#servicemonitor
serviceMonitor:
# This option requires the following settings within Prometheus to function:
# 1. RBAC settings for the Prometheus instance to access the metrics endpoint.
#
# - nonResourceURLs:
# - /metrics
# verbs:
# - get
#
# 2. If using the Prometheus Operator and your Prometheus instance is not in the same namespace as the operator you will need
# the Prometheus Operator configured with the following Helm values:
#
# prometheus:
# prometheusSpec:
# serviceMonitorNamespaceSelector: {}
# serviceMonitorSelectorNilUsesHelmValues: false
#
# allows to disable the serviceMonitor, enabled by default for backwards compatibility
enabled: true
# namespace determines in which namespace the serviceMonitor will be deployed.
# If not set the serviceMonitor will be created in the namespace where the Helm release is installed into
# namespace: monitoring
# caSecret is the name of the secret containing the custom CA certificate used to generate the custom TLS certificate for the secure metrics endpoint.
#
# * This *must* be the name of the secret containing the CA certificate used to sign the custom TLS certificate for the metrics endpoint.
# * This secret *must* be in the same namespace as the Prometheus instance that will scrape the metrics.
# * If using the Prometheus operator this secret must be within the `spec.secrets` field of the `Prometheus` custom resource such that it is mounted into the Prometheus pod at `caMountDirectory`, which defaults to /etc/prometheus/secrets/{secret-name}.
# * This is an optional setting and is only required if you are using a custom TLS certificate.
# * Key must be named ca.crt.
#
# example: kubectl create secret generic eck-metrics-tls-ca -n monitoring \
# --from-file=ca.crt=/path/to/ca.pem
caSecret: ""
# caMountDirectory is the directory at which the CA certificate is mounted within the Prometheus pod.
#
# * You should only need to adjust this if you are *not* using the Prometheus operator.
caMountDirectory: "/etc/prometheus/secrets/"
# insecureSkipVerify specifies whether to skip verification of the TLS certificate for the secure metrics endpoint.
#
# * If this setting is set to false, then the following settings are required:
# - certificateSecret
# - caSecret
insecureSkipVerify: true
# Globals meant for internal use only
global:
# manifestGen specifies whether the chart is running under manifest generator.
# This is used for tasks specific to generating the all-in-one.yaml file.
manifestGen: false
# createOperatorNamespace defines whether the operator namespace manifest should be generated when in manifestGen mode.
# Usually we do want that to happen (e.g. all-in-one.yaml) but, sometimes we don't (e.g. E2E tests).
createOperatorNamespace: true
# kubeVersion is the effective Kubernetes version we target when generating the all-in-one.yaml.
kubeVersion: 1.21.0
-337
View File
@@ -1,337 +0,0 @@
# Default values for external-dns.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
global:
# -- Global image pull secrets.
imagePullSecrets: [] # @schema item: object
image: # @schema additionalProperties: false
# -- Image repository for the `external-dns` container.
repository: registry.k8s.io/external-dns/external-dns
# -- Image tag for the `external-dns` container, this will default to `.Chart.AppVersion` if not set.
tag: # @schema type:[string, null]
# -- Image pull policy for the `external-dns` container.
pullPolicy: IfNotPresent # @schema enum:[IfNotPresent, Always];
# -- Image pull secrets.
imagePullSecrets: [] # @schema item: object
# -- (string) Override the name of the chart.
nameOverride: # @schema type:[string, null]; default: null
# -- (string) Override the full name of the chart.
fullnameOverride: # @schema type:[string, null]; default: null
# -- Labels to add to all chart resources.
commonLabels: {}
serviceAccount:
# -- If `true`, create a new `ServiceAccount`.
create: true
# -- Labels to add to the service account.
labels: {}
# -- Annotations to add to the service account. Templates are allowed in both the key and the value. Example: `example.com/annotation/{{ .Values.nameOverride }}: {{ .Values.nameOverride }}`
annotations: {}
# -- (string) If this is set and `serviceAccount.create` is `true` this will be used for the created `ServiceAccount` name, if set and `serviceAccount.create` is `false` then this will define an existing `ServiceAccount` to use.
name: # @schema type:[string, null]; default: null
# -- Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `ServiceAccount`.
automountServiceAccountToken: true
service:
# -- Service annotations.
annotations: {}
# -- Service HTTP port.
port: 7979 # @schema minimum:0; default:7979
# -- Service IP families (e.g. IPv4 and/or IPv6).
ipFamilies: [] # @schema type: [array, null]; item: string; itemEnum: ["IPv4", "IPv6"]; minItems:0; maxItems:2; uniqueItems: true;
# - IPv4
# - IPv6
# -- Service IP family policy.
ipFamilyPolicy: # @schema type: [string, null]; enum:[SingleStack, PreferDualStack, RequireDualStack, null];
rbac: # @schema additionalProperties: true
# -- If `true`, create a `ClusterRole` & `ClusterRoleBinding` with access to the Kubernetes API.
create: true
# -- Additional rules to add to the `ClusterRole`.
additionalPermissions: []
# -- Annotations to add to the `Deployment`.
deploymentAnnotations: {}
# -- Extra containers to add to the `Deployment`.
extraContainers: []
# -- [Deployment Strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).
deploymentStrategy: # @schema additionalProperties: true
type: Recreate # @schema enum:[Recreate, RollingUpdate]; type:string; default: Recreate
# -- (int) Specify the number of old `ReplicaSets` to retain to allow rollback of the `Deployment``.
revisionHistoryLimit: # @schema type:[integer, null];minimum:0
# -- Labels to add to the `Pod`.
podLabels: {}
# -- Annotations to add to the `Pod`.
podAnnotations: {}
# -- (bool) Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`.
automountServiceAccountToken: true
# -- If `true`, the `Pod` will have [process namespace sharing](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/) enabled.
shareProcessNamespace: false
# -- [Pod security context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core), this supports full customisation.
# @default -- See _values.yaml_
podSecurityContext:
runAsNonRoot: true
fsGroup: 65534
seccompProfile:
type: RuntimeDefault
# -- (string) Priority class name for the `Pod`.
priorityClassName: # @schema type:[string, null]; default: null
# -- (int) Termination grace period for the `Pod` in seconds.
terminationGracePeriodSeconds: # @schema type:[integer, null]
# -- (string) [DNS policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy) for the pod, if not set the default will be used.
dnsPolicy: # @schema type:[string, null]; default: null
# -- (object) [DNS config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config) for the pod, if not set the default will be used.
dnsConfig: # @schema type:[object, null]; default: null
# -- [Init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) to add to the `Pod` definition.
initContainers: []
# -- [Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `external-dns` container.
# @default -- See _values.yaml_
securityContext:
privileged: false
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
capabilities:
drop: ["ALL"]
# -- [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `external-dns` container.
env:
- name: OVH_ENDPOINT
value: "ovh-eu"
- name: OVH_APPLICATION_KEY
valueFrom:
secretKeyRef:
# Le nom de votre Secret
name: ovh-credentials
# La clé dans le Secret qui contient la valeur
key: appKey
- name: OVH_APPLICATION_SECRET
valueFrom:
secretKeyRef:
name: ovh-credentials
key: appSecret
- name: OVH_CONSUMER_KEY
valueFrom:
secretKeyRef:
name: ovh-credentials
key: consumerKey
# -- [Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
# @default -- See _values.yaml_
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 2
successThreshold: 1
# -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
# @default -- See _values.yaml_
readinessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
# -- Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`.
extraVolumes: []
# -- Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container.
extraVolumeMounts: []
# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `external-dns` container.
resources: {}
# -- Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).
nodeSelector: {}
# -- Affinity settings for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided for pod affinity or pod anti-affinity one will be created from the pod selector labels.
affinity: {}
# -- Topology spread constraints for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided one will be created from the pod selector labels.
topologySpreadConstraints: []
# -- Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).
tolerations: []
serviceMonitor:
# -- If `true`, create a `ServiceMonitor` resource to support the _Prometheus Operator_.
enabled: false
# -- Additional labels for the `ServiceMonitor`.
additionalLabels: {}
# -- Annotations to add to the `ServiceMonitor`.
annotations: {}
# -- (string) If set create the `ServiceMonitor` in an alternate namespace.
namespace: # @schema type:[string, null]; default: null
# -- (string) If set override the _Prometheus_ default interval.
interval: # @schema type:[string, null]; default: null
# -- (string) If set override the _Prometheus_ default scrape timeout.
scrapeTimeout: # @schema type:[string, null]; default: null
# -- (string) If set overrides the _Prometheus_ default scheme.
scheme: # @schema type:[string, null]; default: null
# -- Configure the `ServiceMonitor` [TLS config](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig).
tlsConfig: {}
# -- (string) Provide a bearer token file for the `ServiceMonitor`.
bearerTokenFile: # @schema type:[string, null]; default: null
# -- [Relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) to apply to samples before ingestion.
relabelings: []
# -- [Metric relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) to apply to samples before ingestion.
metricRelabelings: []
# -- Provide target labels for the `ServiceMonitor`.
targetLabels: []
# -- Log level.
logLevel: info # @schema enum:[panic, debug, info, warning, error, fatal]; type:string; default: "info"
# -- Log format.
logFormat: text # @schema enum:["text", "json"]; type:string; default: "text"
# -- Interval for DNS updates.
interval: 1m
# -- If `true`, triggers run loop on create/update/delete events in addition of regular interval.
triggerLoopOnEvent: false
# -- if `true`, _ExternalDNS_ will run in a namespaced scope (`Role`` and `Rolebinding`` will be namespaced too).
namespaced: false
# -- _Gateway API_ gateway namespace to watch.
gatewayNamespace: # @schema type:[string, null]; default: null
# -- _Kubernetes_ resources to monitor for DNS entries.
sources:
- service
- ingress
# -- How DNS records are synchronized between sources and providers; available values are `create-only`, `sync`, & `upsert-only`.
policy: sync # @schema enum:[create-only, sync, upsert-only]; type:string; default: "upsert-only"
# -- Specify the registry for storing ownership and labels.
# Valid values are `txt`, `aws-sd`, `dynamodb` & `noop`.
registry: txt # @schema enum:[txt, aws-sd, dynamodb, noop]; default: "txt"
# -- (string) Specify an identifier for this instance of _ExternalDNS_ when using a registry other than `noop`.
txtOwnerId: # @schema type:[string, null]; default: null
# -- (string) Specify a prefix for the domain names of TXT records created for the `txt` registry.
# Mutually exclusive with `txtSuffix`.
txtPrefix: # @schema type:[string, null]; default: null
# -- (string) Specify a suffix for the domain names of TXT records created for the `txt` registry.
# Mutually exclusive with `txtPrefix`.
txtSuffix: # @schema type:[string, null]; default: null
# -- Limit possible target zones by domain suffixes.
domainFilters:
- greenkube.cloud
# -- Intentionally exclude domains from being managed.
excludeDomains: []
# -- Filter resources queried for endpoints by label selector
labelFilter: # @schema type: [string,null]; default: null
# -- Record types to manage (default: A, AAAA, CNAME)
managedRecordTypes: [] # @schema type: [array, null]; item: string; uniqueItems: true;
provider: # @schema type: [object, string];
# -- _ExternalDNS_ provider name; for the available providers and how to configure them see [README](https://github.com/kubernetes-sigs/external-dns/blob/master/charts/external-dns/README.md#providers).
name: ovh
webhook:
image:
# -- (string) Image repository for the `webhook` container.
repository: # @schema type:[string, null]; default: null
# -- (string) Image tag for the `webhook` container.
tag: # @schema type:[string, null]; default: null
# -- Image pull policy for the `webhook` container.
pullPolicy: IfNotPresent
# -- [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `webhook` container.
env: []
# -- Extra arguments to provide for the `webhook` container.
args: []
# -- Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `webhook` container.
extraVolumeMounts: []
# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `webhook` container.
resources: {}
# -- [Pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `webhook` container.
# @default -- See _values.yaml_
securityContext: {}
# -- [Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
# @default -- See _values.yaml_
livenessProbe:
httpGet:
path: /healthz # @schema type:[string, null]; default: null
port: http-webhook # @schema type:[integer,string]; default: string
initialDelaySeconds: 10 # @schema type:[integer, null]; default: null
periodSeconds: 10 # @schema type:[integer, null]; default: null
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
failureThreshold: 2 # @schema type:[integer, null]; default: null
successThreshold: 1 # @schema type:[integer, null]; default: null
# -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `webhook` container.
# @default -- See _values.yaml_
readinessProbe:
httpGet:
path: /healthz # @schema type:[string, null]; default: null
port: http-webhook # @schema type:[integer,string]; default: string
initialDelaySeconds: 5 # @schema type:[integer, null]; default: null
periodSeconds: 10 # @schema type:[integer, null]; default: null
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
failureThreshold: 6 # @schema type:[integer, null]; default: null
successThreshold: 1 # @schema type:[integer, null]; default: null
service:
# -- Webhook exposed HTTP port for the service.
port: 8080
# -- Optional [Service Monitor](https://prometheus-operator.dev/docs/operator/design/#servicemonitor) configuration for the `webhook` container.
# @default -- See _values.yaml_
serviceMonitor:
interval:
scheme:
tlsConfig: {}
bearerTokenFile:
scrapeTimeout:
metricRelabelings: []
relabelings: []
# -- Extra arguments to provide to _ExternalDNS_.
# An array or map can be used, with maps allowing for value overrides; maps also support slice values to use the same arg multiple times.
extraArgs: {} # @schema type: [array, null, object]; item: string; uniqueItems: true;
secretConfiguration:
# -- If `true`, create a `Secret` to store sensitive provider configuration (**DEPRECATED**).
enabled: false
# -- Mount path for the `Secret`, this can be templated.
mountPath: # @schema type:[string, null]; default: null
# -- Sub-path for mounting the `Secret`, this can be templated.
subPath: # @schema type:[string, null]; default: null
# -- `Secret` data.
data: {}
# -- (bool) No effect - reserved for use in sub-charting.
enabled: # @schema type: [boolean, null]; description: No effect - reserved for use in sub-charting
-26
View File
@@ -1,26 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- grafana.greenkube.cloud
secretName: grafana-tls
rules:
- host: "grafana.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
-1068
View File
File diff suppressed because it is too large Load Diff
-14
View File
@@ -1,14 +0,0 @@
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
name: mon-kibana
namespace: elastic-greenkube
spec:
version: 8.14.1
count: 1
# On lie Kibana à notre cluster Elasticsearch
elasticsearchRef:
name: mon-cluster-es
config:
server:
publicBaseUrl: "https://kibana.greenkube.cloud"
-28
View File
@@ -1,28 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kibana-ingress
namespace: elastic-greenkube
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- kibana.greenkube.cloud
secretName: kibana-cluster-tls
rules:
- host: "kibana.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
# L'opérateur crée ce service pour Kibana
name: mon-kibana-kb-http
port:
number: 5601
-7
View File
@@ -1,7 +0,0 @@
# Fichier de configuration pour un cluster avec 1 master et 2 workers
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane # Ce nœud sera le master (control-plane)
- role: worker # Un premier worker
- role: worker # Un deuxième worker
@@ -1,45 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-prometheus
namespace: monitoring
spec:
# Cible les pods Prometheus
podSelector:
matchLabels:
app.kubernetes.io/name: prometheus
policyTypes:
- Ingress
ingress:
- from:
# Autorise le trafic depuis le namespace de l'ingress
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 9090
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-grafana
namespace: monitoring
spec:
# Cible les pods Grafana
podSelector:
matchLabels:
app.kubernetes.io/name: grafana
policyTypes:
- Ingress
ingress:
- from:
# Autorise le trafic depuis le namespace de l'ingress
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 3000
-1241
View File
File diff suppressed because it is too large Load Diff
-38
View File
@@ -1,38 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: opencost-ingress
namespace: opencost
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- opencost.greenkube.cloud
secretName: opencost-tls
rules:
- host: "opencost.greenkube.cloud"
http:
paths:
# Règle N°1 : Le trafic pour l'API sur le chemin /allocation
# est envoyé au service sur le port 9003.
- path: /allocation
pathType: Prefix
backend:
service:
name: opencost
port:
number: 9003 # <-- Le port de l'API
# Règle N°2 : Tout le reste du trafic (pour l'interface utilisateur)
# est envoyé au service sur le port 9090.
- path: /
pathType: Prefix
backend:
service:
name: opencost
port:
number: 9090 # <-- Le port de l'UI
-22
View File
@@ -1,22 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-opencost-to-prometheus
namespace: monitoring
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: prometheus
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: opencost
podSelector:
matchLabels:
app.kubernetes.io/name: opencost
ports:
- protocol: TCP
port: 9090 # Vers le port web de Prometheus
-624
View File
@@ -1,624 +0,0 @@
# -- Overwrite the default name of the chart
nameOverride: ""
# -- Overwrite all resources name created by the chart
fullnameOverride: ""
# -- Override the deployment namespace
namespaceOverride: ""
# -- Override the default name of cluster - Can be found in /etc/kubernetes/admin.conf: clusters -> cluster -> name
clusterName: "cluster.local"
loglevel: info
plugins:
enabled: false
install:
enabled: true
fullImageName: curlimages/curl:latest
securityContext:
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
folder: /opt/opencost/plugin
# leave this commented to always download most recent version of plugins
# version: <INSERT_SPECIFIC_PLUGINS_VERSION>
configs:
# datadog: |
# {
# "datadog_site": "<INSERT_DATADOG_SITE>",
# "datadog_api_key": "<INSERT_DATADOG_API_KEY>",
# "datadog_app_key": "<INSERT_DATADOG_APP_KEY>"
# }
# -- List of secret names to use for pulling the images
imagePullSecrets: []
serviceAccount:
# -- Specifies whether a service account should be created
create: true
# -- Annotations to add to the service account
annotations: {}
# eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eksctl-opencost
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# -- Whether pods running as this service account should have an API token automatically mounted
automountServiceAccountToken: true
# NetworkPolicies for ingress
networkPolicies:
# -- Specifies whether networkpolicies should be created
enabled: false
# -- Internal Prometheus settings related to NetworkPolicies
prometheus:
# -- Namespace where internal Prometheus is installed
namespace: prometheus-system
# -- Pod port of in-cluster Prometheus
port: 9090
# -- Labels applied to the Prometheus server pod(s)
labels:
app.kubernetes.io/name: prometheus
# -- Extra egress rule
extraEgress: []
# -- Strategy to be used for the Deployment
updateStrategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
# -- Annotations to add to the all the resources
annotations: {}
# -- Annotations to add to the OpenCost Pod
podAnnotations: {}
# -- Annotations to add to the Secret
secretAnnotations: {}
# -- Labels to add to the OpenCost Pod
podLabels: {}
# -- Pod priority
priorityClassName: ~
# -- Enable automounting of service account token at the pod level
podAutomountServiceAccountToken: true
# -- Holds pod-level security attributes and common container settings
podSecurityContext: {}
# fsGroup: 2000
service:
enabled: true
# -- Annotations to add to the service
annotations: {}
# -- Labels to add to the service account
labels: {}
# -- Kubernetes Service type
type: ClusterIP
# -- NodePort if service type is NodePort
nodePort: {}
# -- extra ports. Useful for sidecar pods such as oauth-proxy
extraPorts: []
# - name: oauth-proxy
# port: 8081
# targetPort: 8081
# - name: oauth-metrics
# port: 8082
# targetPort: 8082
# -- LoadBalancer Source IP CIDR if service type is LoadBalancer and cloud provider supports this
loadBalancerSourceRanges: []
# Create cluster role policies
rbac:
enabled: true
# PodDisruptionBudget for high availability
pdb:
enabled: false
# -- Minimum number of pods that must be available after the eviction
minAvailable: ~
# -- Maximum number of pods that can be unavailable after the eviction
maxUnavailable: ~
opencost:
# -- <SECRET_NAME> for the secret containing the Cloud Costs cloud-integration.json https://www.opencost.io/docs/configuration/#cloud-costs
# -- kubectl create secret generic <SECRET_NAME> --from-file=cloud-integration.json -n opencost
cloudIntegrationSecret: ""
exporter:
# API_PORT for the cost-model to listen on
apiPort: 9003
# debugPort: 40000 # for development purposes (debugging with delve) and not for production.
# -- The GCP Pricing API requires a key. This is supplied just for evaluation.
cloudProviderApiKey: ""
# -- Default cluster ID to use if cluster_id is not set in Prometheus metrics.
defaultClusterId: 'default-cluster'
image:
# -- Exporter container image registry
registry: ghcr.io
# -- Exporter container image name
repository: opencost/opencost
# -- Exporter container image tag
tag: "1.117.3@sha256:09fae89c4544ec2a891e2902e88ce3137d7032c6edbe0fd97441aaee7bdbea54"
# -- Exporter container image pull policy
pullPolicy: IfNotPresent
# -- Override the full image name for development purposes
fullImageName: null
# -- List of extra arguments for the command, e.g.: log-format=json
extraArgs: []
# -- Optional command to override the default container command
command: []
# -- Number of OpenCost replicas to run
replicas: 1
resources:
# -- CPU/Memory resource requests
requests:
cpu: '10m'
memory: '55Mi'
# -- CPU/Memory resource limits
limits:
memory: '1Gi'
# Startup probe configuration
startupProbe:
# -- Whether probe is enabled
enabled: true
# -- Probe path
path: /healthz
# -- Number of seconds before probe is initiated
initialDelaySeconds: 10
# -- Probe frequency in seconds
periodSeconds: 5
# -- Number of failures for probe to be considered failed
failureThreshold: 30
# Liveness probe configuration
livenessProbe:
# -- Whether probe is enabled
enabled: true
# -- Probe path
path: /healthz
# -- Number of seconds before probe is initiated
initialDelaySeconds: 10
# -- Probe frequency in seconds
periodSeconds: 20
# -- Number of failures for probe to be considered failed
failureThreshold: 3
# Readiness probe configuration
readinessProbe:
# -- Whether probe is enabled
enabled: true
# -- Probe path
path: /healthz
# -- Number of seconds before probe is initiated
initialDelaySeconds: 10
# -- Probe frequency in seconds
periodSeconds: 10
# -- Number of failures for probe to be considered failed
failureThreshold: 3
# -- The security options the container should be run with
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# Path of CSV file
csv_path: ""
prometheusDataSource:
# Set the resolution in second that prometheus queries will be performed at
queryResolutionSeconds: 300
# Collector DataSource collects cluster data without a dependency on Prometheus
# It is recommended that persistence is enabled alongside it to preserve the state
# between pod restarts
collectorDataSource:
enabled: false
# -- define the interval at which the collector scrapes for data points (10s, 15s, 1m)
scrapeInterval: 30s
# -- The port at which network pods are open to egress
networkPort: 3001
# -- The number of 10m intervals the Collector DataSource should maintain
retention10m: 36
# -- The number of 1h intervals the Collector DataSource should maintain
retention1h: 49
# -- The number of 1d intervals the Collector DataSource should maintain
retention1d: 15
# Persistent volume claim for storing the data. eg: csv file
persistence:
enabled: false
# -- The path that the PV will be mounted to the exporter at
mountPath: /mnt/export
# -- Annotations for persistent volume
annotations: {}
# -- Access mode for persistent volume
accessMode: ""
# -- Storage class for persistent volume
storageClass: ""
# -- Size for persistent volume
size: ""
aws:
# -- AWS secret access key
secret_access_key: ""
# -- AWS secret key id
access_key_id: ""
# -- A list of volume mounts to be added to the pod
extraVolumeMounts: []
# -- List of additional environment variables to set in the container
env: []
# -- Any extra environment variables you would like to pass on to the pod
extraEnv: {}
# FOO: BAR
# For example, if accessing mimir directly and getting 401 Unauthorized
# PROMETHEUS_HEADER_X_SCOPE_ORGID: anonymous
apiIngress:
# -- Ingress for OpenCost API
enabled: false
# -- Ingress controller which implements the resource
ingressClassName: ""
# -- Annotations for Ingress resource
annotations: {}
# kubernetes.io/tls-acme: "true"
# -- A list of host rules used to configure the Ingress
# @default -- See [values.yaml](values.yaml)
hosts:
- host: example.local
paths:
- path: /
pathType: Prefix
# -- Redirect ingress to an extraPort defined on the service such as oauth-proxy
servicePort: http
# servicePort: oauth-proxy
# -- Ingress TLS configuration
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
customPricing:
# -- Enables custom pricing configuration
enabled: false
# -- Customize the configmap name used for custom pricing
configmapName: custom-pricing-model
# -- Path for the pricing configuration.
configPath: /tmp/custom-config
# -- Configures the pricing model provided in the values file.
createConfigmap: true
# -- Sets the provider type for the custom pricing file.
provider: custom
# -- More information about these values here: https://www.opencost.io/docs/configuration/on-prem#custom-pricing-using-the-opencost-helm-chart
costModel:
description: Modified pricing configuration.
CPU: 1.25
spotCPU: 0.006655
RAM: 0.50
spotRAM: 0.000892
GPU: 0.95
storage: 0.25
zoneNetworkEgress: 0.01
regionNetworkEgress: 0.01
internetNetworkEgress: 0.12
retention1d: 15
retention1h: 49
carbonCost:
# -- Enable carbon cost exposed in the API
enabled: false
cloudCost:
# -- Enable cloud cost ingestion and querying, dependant on valid integration credentials
enabled: false
# -- Number of hours between each run of the Cloud Cost pipeline
refreshRateHours: 6
# -- Number of days into the past that a Cloud Cost standard run will query for
runWindowDays: 3
# -- The number of standard runs before a Month-to-Date run occurs
monthToDateInterval: 6
# -- The max number of days that any single query will be made to construct Cloud Costs
queryWindowDays: 7
metrics:
kubeStateMetrics:
# -- (bool) Enable emission of pod annotations
emitPodAnnotations: ~
# -- (bool) Enable emission of namespace annotations
emitNamespaceAnnotations: ~
# -- (bool) Enable emission of KSM v1 metrics
emitKsmV1Metrics: ~
# -- (bool) Enable only emission of KSM v1 metrics that do not exist in KSM 2 by default
emitKsmV1MetricsOnly: ~
serviceMonitor:
# -- Create ServiceMonitor resource for scraping metrics using PrometheusOperator
enabled: false
# -- Additional labels to add to the ServiceMonitor
additionalLabels: {}
# -- Specify if the ServiceMonitor will be deployed into a different namespace (blank deploys into same namespace as chart)
namespace: ""
# -- Interval at which metrics should be scraped
scrapeInterval: 30s
# -- Timeout after which the scrape is ended
scrapeTimeout: 10s
# -- HonorLabels chooses the metric's labels on collisions with target labels
honorLabels: true
# -- RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds relabelings for a few standard Kubernetes fields
relabelings: []
# -- MetricRelabelConfigs to apply to samples before ingestion
metricRelabelings: []
# -- extra Endpoints to add to the ServiceMonitor. Useful for scraping sidecars
extraEndpoints: []
# - port: oauth-metrics
# path: /metrics
# -- HTTP scheme used for scraping. Defaults to `http`
scheme: http
# -- TLS configuration for scraping metrics
tlsConfig: {}
# caFile: /etc/prom-certs/root-cert.pem
# certFile: /etc/prom-certs/cert-chain.pem
# insecureSkipVerify: true
# keyFile: /etc/prom-certs/key.pem
config:
# -- Enables creating the metrics.json configuration as a ConfigMap
enabled: false
# -- Customize the configmap name used for metrics
configmapName: custom-metrics
# -- List of metrics to be disabled
disabledMetrics: []
# - <metric-to-be-disabled>
# - <metric-to-be-disabled>
prometheus:
# -- Secret name that contains credentials for Prometheus
secret_name: ~
# -- Existing secret name that contains credentials for Prometheus
existingSecretName: ~
# -- Prometheus Basic auth username
username: ""
# -- Key in the secret that references the username
username_key: DB_BASIC_AUTH_USERNAME
# -- Prometheus Basic auth password
password: ""
# -- Key in the secret that references the password
password_key: DB_BASIC_AUTH_PW
# -- Prometheus Bearer token
bearer_token: ""
bearer_token_key: DB_BEARER_TOKEN
# -- If true, opencost will use kube-rbac-proxy to authenticate with in cluster Prometheus for openshift
kubeRBACProxy: false
# -- Whether to disable SSL certificate verification
insecureSkipVerify: false
external:
# -- Use external Prometheus (eg. Grafana Cloud)
enabled: false
# -- External Prometheus url
url: "https://prometheus.example.com/prometheus"
internal:
# -- Use in-cluster Prometheus
enabled: true
# -- Service name of in-cluster Prometheus
serviceName: prometheus-k8s
# -- Namespace of in-cluster Prometheus
namespaceName: monitoring
# -- Service port of in-cluster Prometheus
port: 9090
# -- Path to access the Prometheus API, this is neccesary if the Prometheus server is behind a reverse proxy(mimir) or has a different path.
path: ""
# -- Scheme to use for in-cluster Prometheus
scheme: http
amp:
# -- Use Amazon Managed Service for Prometheus (AMP)
enabled: false # If true, opencost will be configured to remote_write and query from Amazon Managed Service for Prometheus.
# -- Workspace ID for AMP
workspaceId: ""
thanos:
enabled: false
queryOffset: ''
maxSourceResolution: ''
internal:
enabled: true
serviceName: my-thanos-query
namespaceName: opencost
port: 10901
scheme: http
external:
enabled: false
url: 'https://thanos-query.example.com/thanos'
ui:
# -- Enable OpenCost UI
enabled: true
image:
# -- UI container image registry
registry: ghcr.io
# -- UI container image name
repository: opencost/opencost-ui
# -- UI container image tag
# @default -- `""` (use appVersion in Chart.yaml)
tag: "1.117.3@sha256:727b95405e8c749ddbaa3bd97b93d9c0e246faeb9be9d370dd93ae6b31cdb0c2"
# -- UI container image pull policy
pullPolicy: IfNotPresent
# -- Override the full image name for development purposes
fullImageName: null
resources:
# -- CPU/Memory resource requests
requests:
cpu: '10m'
memory: '55Mi'
# -- CPU/Memory resource limits
limits:
memory: '1Gi'
# used in the default.nginx.conf if you want to switch for using with Docker
# apiServer: 0.0.0.0
uiPort: 9090
# Base path for serving the UI.
# Requires building a custom image using the build argument "ui_path".
uiPath: /
# Set to true to use IPv6
useIPv6: true
# Liveness probe configuration
livenessProbe:
# -- Whether probe is enabled
enabled: true
# -- Probe path
path: /healthz
# -- Number of seconds before probe is initiated
initialDelaySeconds: 30
# -- Probe frequency in seconds
periodSeconds: 10
# -- Number of failures for probe to be considered failed
failureThreshold: 3
# Readiness probe configuration
readinessProbe:
# -- Whether probe is enabled
enabled: true
# -- Probe path
path: /healthz
# -- Number of seconds before probe is initiated
initialDelaySeconds: 30
# -- Probe frequency in seconds
periodSeconds: 10
# -- Number of failures for probe to be considered failed
failureThreshold: 3
# -- The security options the container should be run with
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# -- A list of environment variables to be added to the pod
extraEnv: []
# -- A list of volume mounts to be added to the pod
extraVolumeMounts: []
# set to true to set upstream to use <service>.<namespace>.svc.cluster.local instead of just <service>.<namespace>
useDefaultFqdn: false
# Set the model fqdn to use for the upstream
# modelFqdn: opencost.opencost.svc.cluster.local:9003
ingress:
# -- Ingress for OpenCost UI
enabled: false
# -- Ingress controller which implements the resource
ingressClassName: ""
# -- Annotations for Ingress resource
annotations: {}
# kubernetes.io/tls-acme: "true"
# -- A list of host rules used to configure the Ingress
# @default -- See [values.yaml](values.yaml)
hosts:
- host: example.local
paths:
- /
# -- Redirect ingress to an extraPort defined on the service such as oauth-proxy
servicePort: http-ui
# servicePort: oauth-proxy
# -- Ingress TLS configuration
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
route:
# -- OpenShift route for OpenCost UI
enabled: false
# -- Annotations for Ingress resource
annotations: {}
# haproxy.router.openshift.io/timeout: 1m
# @default -- See [values.yaml](values.yaml)
host: example.local
path:
# -- Redirect ingress to an extraPort defined on the service such as oauth-proxy
targetPort: http-ui
# targetPort: oauth-proxy
# -- Ingress TLS configuration
tls: []
# insecureEdgeTerminationPolicy: Redirect
# termination: edge
sigV4Proxy:
image: public.ecr.aws/aws-observability/aws-sigv4-proxy:latest
imagePullPolicy: IfNotPresent
name: aps
port: 8005
region: us-west-2 # The AWS region
host: aps-workspaces.us-west-2.amazonaws.com # The hostname for AMP service.
# role_arn: arn:aws:iam::<account>:role/role-name # The AWS IAM role to assume.
extraEnv: # Pass extra env variables to sigV4Proxy
# - name: AWS_ACCESS_KEY_ID
# value: <access_key>
# - name: AWS_SECRET_ACCESS_KEY
# value: <secret_key>
resources: {}
# limits:
# cpu: 200m
# memory: 500Mi
# requests:
# cpu: 20m
# memory: 32Mi
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 65534
# -- Toleration labels for pod assignment
tolerations: []
# -- Node labels for pod assignment
nodeSelector: {}
# -- Affinity settings for pod assignment
affinity: {}
# -- Assign custom TopologySpreadConstraints rules
topologySpreadConstraints: []
# -- extra sidecars to add to the pod. Useful for things like oauth-proxy for the UI
extraContainers: []
# - name: oauth-proxy
# image: quay.io/oauth2-proxy/oauth2-proxy:v7.5.1
# args:
# - --upstream=http://127.0.0.1:9090
# - --http-address=0.0.0.0:8081
# - --metrics-address=0.0.0.0:8082
# - ...
# ports:
# - name: oauth-proxy
# containerPort: 8081
# protocol: TCP
# - name: oauth-metrics
# containerPort: 8082
# protocol: TCP
# resources: {}
platforms:
openshift:
# -- Enable OpenShift specific configurations
enabled: false
# OPTIONAL. The following configs only to be enabled when using a Prometheus instance already installed in the cluster.
# -- If true, the helm chart will create a ClusterRoleBinding to grant the OpenCost ServiceAccount access to query Prometheus.
createMonitoringClusterRoleBinding: false
# -- If true, create a Role and RoleBinding to allow Prometheus to list and watch OpenCost resources.
createMonitoringResourceReaderRoleBinding: false
# -- Name of the Prometheus serviceaccount to bind to the Resource Reader Role Binding.
monitoringServiceAccountName: prometheus-k8s
# -- Namespace of the Prometheus serviceaccount to bind to the Resource Reader Role Binding.
monitoringServiceAccountNamespace: openshift-monitoring
# -- If true, set Security Context Constraints on serviceaccount for read/write premissions
enableSCC: false
# -- If true, enable internal prom access
enablePromAccess: false
# -- A list of volumes to be added to the pod
extraVolumes: []
-26
View File
@@ -1,26 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- prometheus.greenkube.cloud
secretName: prometheus-tls
rules:
- host: "prometheus.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus-k8s
port:
number: 9090
-266
View File
@@ -1,266 +0,0 @@
#!/bin/bash
# Arrête le script si une commande échoue
set -e
# --- Configuration ---
# N'hésitez pas à ajuster ces valeurs selon vos besoins
MINIKUBE_CPUS=6
MINIKUBE_MEMORY="16g"
MINIKUBE_DRIVER="qemu"
MINIKUBE_NODE_NAME="minikube" # Le nom par défaut du nœud dans Minikube
# --- Couleurs pour les logs ---
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # Pas de couleur
# ==============================================================================
# FONCTIONS D'INSTALLATION
# ==============================================================================
start_cluster() {
echo -e "🚀 ${GREEN}Vérification et démarrage du cluster Minikube...${NC}"
if ! minikube status &> /dev/null; then
echo "Minikube n'est pas démarré. Lancement..."
minikube start --driver=${MINIKUBE_DRIVER} --cpus=${MINIKUBE_CPUS} --memory=${MINIKUBE_MEMORY} --network=builtin
else
echo "Minikube est déjà en cours d'exécution."
fi
echo -e "✅ ${GREEN}Cluster Minikube prêt.${NC}"
}
install_ingress() {
echo -e "🚀 ${GREEN}Installation de l'Ingress Controller NGINX via le chart Helm...${NC}"
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx &> /dev/null
helm repo update
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.service.type=NodePort \
--set controller.service.nodePorts.http=31000 \
--set controller.service.nodePorts.https=31443 \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.config.use-forwarded-headers="true" \
--wait
echo -e "✅ ${GREEN}Ingress NGINX installé sur le NodePort 31000.${NC}"
}
install_cert_manager() {
echo -e "🚀 ${GREEN}Installation de Cert Manager...${NC}"
helm repo add jetstack https://charts.jetstack.io &> /dev/null
helm repo update
if helm list -n cert-manager | grep -q cert-manager; then
echo -e "⏭️ ${YELLOW}Cert Manager déjà installé, mise à jour...${NC}"
helm upgrade cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.15.1 \
--set installCRDs=true \
--wait
else
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.15.1 \
--set installCRDs=true \
--wait
fi
echo -e "✅ ${GREEN}Cert Manager installé.${NC}"
if [ -f "ovh/ovh-issuer.yaml" ]; then
echo -e "🚀 ${GREEN}Création du ClusterIssuer 'letsencrypt-prod'...${NC}"
kubectl apply -f ovh/ovh-issuer.yaml
echo -e "✅ ${GREEN}ClusterIssuer 'letsencrypt-prod' créé.${NC}"
else
echo -e "⚠️ ${YELLOW}Fichier ovh/ovh-issuer.yaml non trouvé. Étape ignorée.${NC}"
fi
}
install_metrics_server() {
echo -e "🚀 ${GREEN}Installation du Metrics Server...${NC}"
if kubectl get deployment metrics-server -n kube-system &> /dev/null; then
echo -e "⏭️ ${YELLOW}Metrics Server déjà installé, vérification de la configuration...${NC}"
else
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
fi
echo "Patch du Metrics Server pour un usage local..."
if ! kubectl get deployment metrics-server -n kube-system -o jsonpath='{.spec.template.spec.containers[0].args}' | grep -q "kubelet-insecure-tls"; then
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'
else
echo -e "⏭️ ${YELLOW}Patch déjà appliqué.${NC}"
fi
echo -e "✅ ${GREEN}Metrics Server installé.${NC}"
}
install_kube_prometheus() {
echo -e "🚀 ${GREEN}Installation de la stack Kube-Prometheus...${NC}"
if [ ! -d "kube-prometheus" ]; then
echo "Clonage du dépôt kube-prometheus..."
git clone https://github.com/prometheus-operator/kube-prometheus.git
else
echo -e "⏭️ ${YELLOW}Dépôt kube-prometheus déjà présent.${NC}"
fi
kubectl apply --server-side -f kube-prometheus/manifests/setup
kubectl wait --for condition=Established --all crd --timeout=60s
kubectl apply -f kube-prometheus/manifests/
if [ -f "nginx/network-policy-nginx-monitoring.yaml" ]; then
kubectl apply -f nginx/network-policy-nginx-monitoring.yaml
fi
if [ -f "prometheus/ingress.yaml" ]; then
kubectl apply -f prometheus/ingress.yaml
fi
if [ -f "grafana/ingress.yaml" ]; then
kubectl apply -f grafana/ingress.yaml
fi
echo -e "✅ ${GREEN}Kube-Prometheus installé.${NC}"
}
install_argocd() {
echo -e "🚀 ${GREEN}Installation d'ArgoCD...${NC}"
kubectl create namespace argocd 2>/dev/null || true
if kubectl get deployment argocd-server -n argocd &> /dev/null; then
echo -e "⏭️ ${YELLOW}ArgoCD déjà installé, mise à jour...${NC}"
fi
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml 2>&1 | grep -v "Too long: may not be more than" || true
kubectl wait --namespace argocd \
--for=condition=available deployment/argocd-server \
--timeout=180s
if [ -f "argocd/ingress.yaml" ]; then
kubectl apply -f argocd/ingress.yaml
fi
echo -e "✅ ${GREEN}ArgoCD installé. Récupère le mot de passe initial avec :${NC}"
echo "kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=\"{.data.password}\" | base64 -d; echo"
}
install_opencost() {
echo -e "🚀 ${GREEN}Installation d'OpenCost...${NC}"
helm repo add opencost-charts https://opencost.github.io/opencost-helm-chart &> /dev/null
helm repo update
helm upgrade --install opencost opencost-charts/opencost \
--namespace opencost \
--create-namespace \
-f opencost/values.yaml \
--wait
if [ -f "opencost/network-policy-monitoring.yaml" ]; then
kubectl apply -f opencost/network-policy-monitoring.yaml
fi
if [ -f "opencost/ingress.yaml" ]; then
kubectl apply -f opencost/ingress.yaml
fi
echo -e "✅ ${GREEN}OpenCost installé.${NC}"
}
install_elastic_stack() {
echo -e "🚀 ${GREEN}Installation d'Elasticsearch & Kibana...${NC}"
helm repo add elastic https://helm.elastic.co &> /dev/null
helm repo update
if [ -f "elasticsearch/values.yaml" ]; then
helm upgrade --install elastic-operator elastic/eck-operator -n elastic-system --create-namespace -f elasticsearch/values.yaml --wait
else
helm upgrade --install elastic-operator elastic/eck-operator -n elastic-system --create-namespace --wait
fi
kubectl create namespace elastic-greenkube 2>/dev/null || true
if [ -f "elasticsearch/es-cluster.yaml" ]; then
kubectl apply -f elasticsearch/es-cluster.yaml
fi
if [ -f "elasticsearch/ingress.yaml" ]; then
kubectl apply -f elasticsearch/ingress.yaml
fi
if [ -d "kibana" ]; then
kubectl apply -f kibana/
echo -e "⏳ ${YELLOW}Attente que Kibana soit prêt...${NC}"
sleep 10
kubectl wait --namespace elastic-greenkube \
--for=condition=ready pod \
--selector=common.k8s.elastic.co/type=kibana \
--timeout=120s
fi
echo -e "✅ ${GREEN}Elasticsearch & Kibana installés.${NC}"
}
install_opentelemetry() {
echo -e "🚀 ${GREEN}Installation d'OpenTelemetry...${NC}"
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts &> /dev/null
helm repo update
if [ -f "otel/values.yaml" ]; then
helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
--namespace otel \
--create-namespace \
-f otel/values.yaml \
--wait
else
helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
--namespace otel \
--create-namespace \
--wait
fi
echo -e "✅ ${GREEN}OpenTelemetry installé.${NC}"
}
label_node() {
echo -e "🚀 ${GREEN}Ajout du label de zone au nœud ${MINIKUBE_NODE_NAME}...${NC}"
kubectl label node "${MINIKUBE_NODE_NAME}" topology.kubernetes.io/zone=europe-west9-a --overwrite
echo -e "✅ ${GREEN}Label ajouté.${NC}"
}
final_instructions() {
MINIKUBE_IP=$(minikube ip)
echo -e "\n🎉 ${GREEN}Ton environnement de développement est prêt !${NC}"
echo -e "----------------------------------------------------------------"
echo -e "Il reste deux actions manuelles à faire :"
echo ""
echo -e "${YELLOW}ACTION 1 : (Si ce n'est pas déjà fait) Modifier votre fichier /etc/hosts.${NC}"
echo -e "L'adresse IP de Minikube (${MINIKUBE_IP}) doit être associée à vos noms d'hôte."
echo -e "👉 ${GREEN}Exécutez la commande suivante si nécessaire :${NC}"
HOSTS_ENTRIES="argocd.greenkube.cloud grafana.greenkube.cloud prometheus.greenkube.cloud elasticsearch.greenkube.cloud kibana.greenkube.cloud opencost.greenkube.cloud otel.greenkube.cloud"
echo -e "${GREEN}sudo -- sh -c 'echo \"\n# Minikube GreenKube environment\n${MINIKUBE_IP} ${HOSTS_ENTRIES}\" >> /etc/hosts'${NC}"
echo ""
echo -e "----------------------------------------------------------------"
echo ""
echo -e "${YELLOW}ACTION 2 : Lancer le pont réseau pour rendre le cluster accessible.${NC}"
echo -e "Cette commande doit tourner en continu dans un **nouveau terminal dédié**."
echo ""
echo -e "👉 ${GREEN}Copiez-collez et exécutez cette commande dans un nouveau terminal :${NC}"
echo -e "${GREEN}kubectl port-forward --namespace ingress-nginx --address 0.0.0.0 service/ingress-nginx-controller 31000:80${NC}"
echo ""
echo -e "Une fois le pont réseau actif, vous pourrez accéder à vos applications, par exemple : http://argocd.greenkube.cloud"
echo "----------------------------------------------------------------"
}
# ==============================================================================
# SCRIPT PRINCIPAL
# ==============================================================================
main() {
start_cluster
install_ingress
install_cert_manager
install_metrics_server
install_kube_prometheus
install_argocd
install_opencost
install_elastic_stack
install_opentelemetry
label_node
final_instructions
}
# Lancement du script
main
-170
View File
@@ -1,170 +0,0 @@
#!/bin/bash
# Arrête le script si une commande échoue
set -e
echo "🚀 Démarrage du cluster Kubernetes avec Kind..."
# 1. Création du cluster avec la config pour l'Ingress Controller
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 31000
hostPort: 31000
protocol: TCP
EOF
echo "✅ Cluster créé."
echo "🚀 Installation de l'Ingress Controller NGINX..."
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/kind/deploy.yaml
echo "⏳ Attente que le déploiement de l'Ingress Controller soit prêt..."
kubectl wait --namespace ingress-nginx \
--for=condition=available deployment/ingress-nginx-controller \
--timeout=120s
echo "⏳ Attente que les webhooks de l'Ingress Controller soient prêts..."
kubectl wait --namespace ingress-nginx \
--for=condition=complete job \
--all \
--timeout=120s
kubectl patch service ingress-nginx-controller -n ingress-nginx -p '{"spec":{"ports":[{"port":80,"nodePort":31000}]}}'
kubectl patch configmap ingress-nginx-controller -n ingress-nginx --type merge -p '{"data":{"use-forwarded-headers":"true"}}'
echo "✅ Ingress NGINX installé."
echo "🚀 Installation de Cert Manager..."
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.15.1 \
--set installCRDs=true
echo "⏳ Attente que les pods de Cert Manager soient prêts..."
# Ici aussi, on pourrait attendre le déploiement. Mais laissons comme ça pour l'instant.
kubectl wait --namespace cert-manager \
--for=condition=ready pod \
--selector=app.kubernetes.io/instance=cert-manager \
--timeout=120s
echo "✅ Cert Manager installé."
if [ -f "ovh/ovh-issuer.yaml" ]; then
echo "🚀 Création du ClusterIssuer 'letsencrypt-prod'..."
kubectl apply -f ovh/ovh-issuer.yaml
echo "✅ ClusterIssuer 'letsencrypt-prod' créé."
else
echo "⚠️ Fichier ovh/ovh-issuer.yaml non trouvé. Étape ignorée."
fi
echo "🚀 Installation du Metrics Server..."
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
echo "Patching du Metrics Server pour un usage local (kind)..."
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'
echo "✅ Metrics Server installé."
echo "🚀 Installation de la stack Kube-Prometheus..."
if [ ! -d "kube-prometheus" ]; then
echo "Clonage du dépôt kube-prometheus..."
git clone https://github.com/prometheus-operator/kube-prometheus.git
fi
kubectl apply --server-side -f kube-prometheus/manifests/setup
kubectl wait --for condition=Established --all crd --timeout=60s
kubectl apply -f kube-prometheus/manifests/
kubectl apply -f nginx/network-policy-nginx-monitoring.yaml
kubectl apply -f prometheus/ingress.yaml
kubectl apply -f grafana/ingress.yaml
echo "✅ Kube-Prometheus installé."
# echo "🚀 Installation de Harbor (Registry d'images)..."
# if [ -f "harbor/values.yaml" ]; then
# helm repo add harbor https://helm.goharbor.io
# helm repo update
# helm install harbor harbor/harbor \
# --create-namespace \
# --namespace harbor \
# --values harbor/values.yaml \
# --timeout 10m \
# --wait
# echo "✅ Harbor installé."
# else
# echo "⚠️ Fichier harbor/values.yaml non trouvé. Installation de Harbor ignorée."
# fi
echo "🚀 Installation d'ArgoCD..."
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl apply -f argocd/ingress.yaml
echo "ArgoCD installé. Récupère le mot de passe initial avec :"
echo "kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d"
echo "✅ ArgoCD installé."
echo "🚀 Installation d'OpenCost..."
helm install opencost opencost-charts/opencost --namespace opencost --create-namespace -f opencost/values.yaml
kubectl apply -f opencost/network-policy-monitoring.yaml
kubectl apply -f opencost/ingress.yaml
echo "✅ OpenCost installé."
echo "Ajout du label de zone au noeud (utile pour GreenKube)..."
kubectl label node kind-control-plane topology.kubernetes.io/zone=europe-west9-a
# echo "🚀 Installation de Kepler pour le monitoring énergétique..."
# helm repo add kepler https://sustainable-computing-io.github.io/kepler-helm-chart
# helm repo update
# helm install kepler kepler/kepler \
# --namespace kepler \
# --create-namespace \
# --set env.KEPLER_FAKE_CPU_METER=true
# echo "✅ Kepler installé."
echo "🚀 Installation d'Elasticsearch..."
helm repo add elastic https://helm.elastic.co
helm repo update
helm install elastic-operator elastic/eck-operator -n elastic-system --create-namespace -f elasticsearch/values.yaml
echo "⏳ Attente que les pods d'Elasticsearch soient prêts..."
kubectl wait --namespace elastic-system \
--for=condition=ready pod \
--selector=app.kubernetes.io/name=elastic-operator \
--timeout=120s
kubectl create namespace elastic-greenkube || echo "Le namespace elastic-greenkube existe déjà, on continue..."
kubectl apply -f elasticsearch/es-cluster.yaml
kubectl apply -f elasticsearch/ingress.yaml
echo "✅ Elasticsearch installé."
echo "🚀 Installation de Kibana..."
kubectl apply -f kibana/
sleep 10
echo "⏳ Attente que les pods de Kibana soient prêts..."
kubectl wait --namespace elastic-greenkube \
--for=condition=ready pod \
--selector=common.k8s.elastic.co/type=kibana \
--timeout=120s
echo "✅ Kibana installé."
echo "🎉 Ton environnement de développement est prêt !"
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
set -e
echo "🔥 Destruction du cluster Kind..."
kind delete cluster
echo "✅ Cluster détruit. À la prochaine !"
-59
View File
@@ -1,59 +0,0 @@
# Fichier : test-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: welcome-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: welcome # <-- DOIT CORRESPONDRE
template:
metadata:
labels:
app: welcome # <-- À CE LABEL
spec:
containers:
- name: web
image: nginxdemos/hello:plain-text
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: welcome-service
namespace: default
spec:
type: ClusterIP
selector:
app: welcome # <-- CE SÉLECTEUR
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: welcome-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: "test.greenkube.cloud"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: welcome-service
port:
number: 80