diff --git a/README.md b/README.md index 8030acd..55af4be 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,23 @@ Uma ferramenta de governança de recursos para clusters OpenShift que vai além ## 🛠️ Instalação -### 1. Build da Imagem +### 🚀 Deploy Rápido (Recomendado) + +```bash +# 1. Clone o repositório +git clone +cd RequestsAndLimits + +# 2. Faça login no OpenShift +oc login + +# 3. Deploy completo (cria tudo automaticamente) +./scripts/deploy-complete.sh +``` + +### 📋 Deploy Manual + +#### 1. Build da Imagem ```bash # Build local @@ -36,7 +52,15 @@ Uma ferramenta de governança de recursos para clusters OpenShift que vai além ./scripts/build.sh latest seu-usuario ``` -### 2. Deploy no OpenShift +#### 2. Deploy no OpenShift + +```bash +# Aplicar todos os recursos +oc apply -f k8s/ + +# Aguardar deployment +oc rollout status deployment/resource-governance -n resource-governance +``` #### 🚀 CI/CD Automático (Recomendado para Produção) ```bash diff --git a/app/core/config.py b/app/core/config.py index 97eb6f1..132e0b6 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -15,7 +15,7 @@ class Settings(BaseSettings): token: Optional[str] = None # Prometheus settings - prometheus_url: str = "http://prometheus.openshift-monitoring.svc.cluster.local:9090" + prometheus_url: str = "http://prometheus-k8s.openshift-monitoring.svc.cluster.local:9091" # Validation settings cpu_limit_ratio: float = 3.0 # Default limit:request ratio for CPU diff --git a/app/core/kubernetes_client.py b/app/core/kubernetes_client.py index 5631685..6e65f0e 100644 --- a/app/core/kubernetes_client.py +++ b/app/core/kubernetes_client.py @@ -30,7 +30,27 @@ class K8sClient: config.load_kube_config(config_file=settings.kubeconfig_path) else: # Use in-cluster configuration - config.load_incluster_config() + try: + config.load_incluster_config() + except config.ConfigException: + # If in-cluster config fails, try to use service account token + try: + with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f: + token = f.read().strip() + + with open('/var/run/secrets/kubernetes.io/serviceaccount/namespace', 'r') as f: + namespace = f.read().strip() + + # Create configuration with token + configuration = client.Configuration() + configuration.host = f"https://kubernetes.default.svc" + configuration.ssl_ca_cert = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt' + configuration.api_key = {"authorization": f"Bearer {token}"} + client.Configuration.set_default(configuration) + + except FileNotFoundError: + # Fallback to default configuration + config.load_kube_config() # Initialize API clients self.v1 = client.CoreV1Api() diff --git a/app/core/prometheus_client.py b/app/core/prometheus_client.py index fdd0ff2..d26ae1a 100644 --- a/app/core/prometheus_client.py +++ b/app/core/prometheus_client.py @@ -22,7 +22,23 @@ class PrometheusClient: async def initialize(self): """Initialize Prometheus client""" try: - self.session = aiohttp.ClientSession() + # Create session with SSL verification disabled for self-signed certificates + connector = aiohttp.TCPConnector(ssl=False) + + # Get service account token for authentication + token = None + try: + with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f: + token = f.read().strip() + except FileNotFoundError: + logger.warning("Service account token not found, proceeding without authentication") + + # Create headers with token if available + headers = {} + if token: + headers['Authorization'] = f'Bearer {token}' + + self.session = aiohttp.ClientSession(connector=connector, headers=headers) # Test connection async with self.session.get(f"{self.base_url}/api/v1/query?query=up") as response: diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml index a94cb1c..f679654 100644 --- a/k8s/configmap.yaml +++ b/k8s/configmap.yaml @@ -21,7 +21,7 @@ data: SYSTEM_NAMESPACE_PREFIXES: '["kube-", "openshift-", "knative-", "default", "kube-system", "kube-public", "kube-node-lease"]' # URL do Prometheus - PROMETHEUS_URL: "http://prometheus.openshift-monitoring.svc.cluster.local:9090" + PROMETHEUS_URL: "https://prometheus-k8s.openshift-monitoring.svc.cluster.local:9091" # Configurações de relatório REPORT_EXPORT_PATH: "/tmp/reports" diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index f7dcd58..d7cf687 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -125,7 +125,14 @@ spec: volumeMounts: - name: reports mountPath: /tmp/reports + - name: service-account-token + mountPath: /var/run/secrets/kubernetes.io/serviceaccount + readOnly: true volumes: - name: reports emptyDir: {} + - name: service-account-token + secret: + secretName: resource-governance-sa-token + optional: false restartPolicy: Always diff --git a/k8s/rbac.yaml b/k8s/rbac.yaml index c708e88..707f080 100644 --- a/k8s/rbac.yaml +++ b/k8s/rbac.yaml @@ -60,33 +60,18 @@ subjects: name: resource-governance-sa namespace: resource-governance --- -# Role para acessar recursos do Prometheus (se necessário) +# ClusterRoleBinding para acessar o Prometheus apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRoleBinding metadata: - name: resource-governance-prometheus-role - namespace: resource-governance - labels: - app.kubernetes.io/name: resource-governance - app.kubernetes.io/component: governance -rules: -# Permissões para acessar serviços do Prometheus -- apiGroups: [""] - resources: ["services", "endpoints"] - verbs: ["get", "list", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: resource-governance-prometheus-binding - namespace: resource-governance + name: resource-governance-monitoring labels: app.kubernetes.io/name: resource-governance app.kubernetes.io/component: governance roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role - name: resource-governance-prometheus-role + kind: ClusterRole + name: cluster-monitoring-view subjects: - kind: ServiceAccount name: resource-governance-sa diff --git a/scripts/deploy-complete.sh b/scripts/deploy-complete.sh index 1ae0736..144daaa 100755 --- a/scripts/deploy-complete.sh +++ b/scripts/deploy-complete.sh @@ -1,7 +1,8 @@ #!/bin/bash -# Script completo de deploy para OpenShift Resource Governance Tool -# Para ser executado por qualquer cluster-admin +# Script completo de deploy do OpenShift Resource Governance Tool +# Inclui criação de namespace, RBAC, ConfigMap, Secret e Deployment + set -e # Cores para output @@ -13,101 +14,88 @@ NC='\033[0m' # No Color # Configurações NAMESPACE="resource-governance" -APP_NAME="resource-governance" -SECRET_NAME="docker-hub-secret" +SERVICE_ACCOUNT="resource-governance-sa" +SECRET_NAME="resource-governance-sa-token" -echo -e "${BLUE}🚀 Deploy Completo - OpenShift Resource Governance Tool${NC}" -echo -e "${BLUE}====================================================${NC}" +echo -e "${BLUE}🚀 Deploying OpenShift Resource Governance Tool${NC}" -# Verificar se está logado no OpenShift +# Verificar se está conectado ao cluster if ! oc whoami > /dev/null 2>&1; then - echo -e "${RED}❌ Não está logado no OpenShift. Faça login primeiro.${NC}" - echo -e "${YELLOW}💡 Execute: oc login ${NC}" + echo -e "${RED}❌ Not connected to OpenShift cluster. Please run 'oc login' first.${NC}" exit 1 fi -echo -e "${GREEN}✅ Logado como: $(oc whoami)${NC}" +echo -e "${GREEN}✅ Connected to OpenShift cluster as $(oc whoami)${NC}" -# Verificar se tem permissões de cluster-admin -if ! oc auth can-i create namespaces > /dev/null 2>&1; then - echo -e "${RED}❌ Permissões insuficientes. Este script requer cluster-admin.${NC}" - exit 1 -fi - -echo -e "${GREEN}✅ Permissões de cluster-admin confirmadas${NC}" - -# Criar namespace -echo -e "${YELLOW}📁 Criando namespace $NAMESPACE...${NC}" -oc apply -f k8s/namespace.yaml +# Criar namespace se não existir +echo -e "${YELLOW}📦 Creating namespace...${NC}" +oc create namespace $NAMESPACE --dry-run=client -o yaml | oc apply -f - # Aplicar RBAC -echo -e "${YELLOW}🔐 Configurando RBAC...${NC}" +echo -e "${YELLOW}🔐 Applying RBAC...${NC}" oc apply -f k8s/rbac.yaml # Aplicar ConfigMap -echo -e "${YELLOW}⚙️ Configurando ConfigMap...${NC}" +echo -e "${YELLOW}⚙️ Applying ConfigMap...${NC}" oc apply -f k8s/configmap.yaml -# Configurar ImagePullSecret -echo -e "${YELLOW}🔑 Configurando ImagePullSecret para Docker Hub...${NC}" -echo -e "${BLUE}💡 Digite suas credenciais do Docker Hub:${NC}" -read -p "Username: " DOCKER_USERNAME -read -s -p "Password/Token: " DOCKER_PASSWORD -echo +# Criar secret do token do ServiceAccount +echo -e "${YELLOW}🔑 Creating ServiceAccount token...${NC}" -# Criar o secret -oc create secret docker-registry $SECRET_NAME \ - --docker-server=docker.io \ - --docker-username=$DOCKER_USERNAME \ - --docker-password=$DOCKER_PASSWORD \ - --docker-email=$DOCKER_USERNAME@example.com \ - -n $NAMESPACE \ - --dry-run=client -o yaml | oc apply -f - +# Verificar se o secret já existe +if oc get secret $SECRET_NAME -n $NAMESPACE > /dev/null 2>&1; then + echo -e "${YELLOW}⚠️ Secret $SECRET_NAME already exists, skipping creation${NC}" +else + # Criar token do ServiceAccount + TOKEN=$(oc create token $SERVICE_ACCOUNT -n $NAMESPACE --duration=8760h) + + # Criar secret com o token + oc create secret generic $SECRET_NAME -n $NAMESPACE \ + --from-literal=token="$TOKEN" \ + --from-literal=ca.crt="$(oc get secret -n $NAMESPACE -o jsonpath='{.items[0].data.ca\.crt}' | base64 -d)" \ + --from-literal=namespace="$NAMESPACE" + + echo -e "${GREEN}✅ ServiceAccount token created${NC}" +fi -# Adicionar o secret ao service account -oc patch serviceaccount resource-governance-sa -n $NAMESPACE -p '{"imagePullSecrets": [{"name": "'$SECRET_NAME'"}]}' - -echo -e "${GREEN}✅ ImagePullSecret configurado${NC}" - -# Aplicar DaemonSet -echo -e "${YELLOW}📦 Deployando DaemonSet...${NC}" -oc apply -f k8s/daemonset.yaml +# Aplicar Deployment +echo -e "${YELLOW}🚀 Applying Deployment...${NC}" +oc apply -f k8s/deployment.yaml # Aplicar Service -echo -e "${YELLOW}🌐 Configurando Service...${NC}" +echo -e "${YELLOW}🌐 Applying Service...${NC}" oc apply -f k8s/service.yaml # Aplicar Route -echo -e "${YELLOW}🛣️ Configurando Route...${NC}" +echo -e "${YELLOW}🛣️ Applying Route...${NC}" oc apply -f k8s/route.yaml -# Aguardar pods ficarem prontos -echo -e "${YELLOW}⏳ Aguardando pods ficarem prontos...${NC}" -oc wait --for=condition=ready pod -l app.kubernetes.io/name=$APP_NAME -n $NAMESPACE --timeout=300s +# Aguardar deployment estar pronto +echo -e "${YELLOW}⏳ Waiting for deployment to be ready...${NC}" +oc rollout status deployment/resource-governance -n $NAMESPACE --timeout=300s -# Verificar status -echo -e "${YELLOW}📊 Verificando status do deploy...${NC}" -oc get all -n $NAMESPACE +# Verificar status dos pods +echo -e "${YELLOW}📊 Checking pod status...${NC}" +oc get pods -n $NAMESPACE -l app.kubernetes.io/name=resource-governance + +# Verificar logs para erros +echo -e "${YELLOW}📋 Checking application logs...${NC}" +POD_NAME=$(oc get pods -n $NAMESPACE -l app.kubernetes.io/name=resource-governance -o jsonpath='{.items[0].metadata.name}') +if [ -n "$POD_NAME" ]; then + echo -e "${BLUE}Recent logs from $POD_NAME:${NC}" + oc logs $POD_NAME -n $NAMESPACE --tail=10 +fi # Obter URL da aplicação -ROUTE_URL=$(oc get route $APP_NAME -n $NAMESPACE -o jsonpath='{.spec.host}' 2>/dev/null || echo "N/A") - -echo -e "${GREEN}🎉 Deploy concluído com sucesso!${NC}" -echo -e "${BLUE}====================================================${NC}" -echo -e "${GREEN}✅ Namespace: $NAMESPACE${NC}" -echo -e "${GREEN}✅ DaemonSet: $APP_NAME${NC}" -echo -e "${GREEN}✅ Service: $APP_NAME${NC}" -echo -e "${GREEN}✅ Route: $APP_NAME${NC}" -if [ "$ROUTE_URL" != "N/A" ]; then - echo -e "${GREEN}🌐 URL da aplicação: https://$ROUTE_URL${NC}" +echo -e "${YELLOW}🌍 Getting application URL...${NC}" +ROUTE_URL=$(oc get route resource-governance -n $NAMESPACE -o jsonpath='{.spec.host}') +if [ -n "$ROUTE_URL" ]; then + echo -e "${GREEN}✅ Application deployed successfully!${NC}" + echo -e "${GREEN}🌐 URL: https://$ROUTE_URL${NC}" + echo -e "${GREEN}📊 Health check: https://$ROUTE_URL/api/v1/health${NC}" +else + echo -e "${YELLOW}⚠️ Route not found, checking service...${NC}" + oc get svc -n $NAMESPACE fi -echo -e "${BLUE}====================================================${NC}" -# Mostrar comandos úteis -echo -e "${YELLOW}📋 Comandos úteis:${NC}" -echo -e "${BLUE} Ver logs: oc logs -f daemonset/$APP_NAME -n $NAMESPACE${NC}" -echo -e "${BLUE} Ver pods: oc get pods -n $NAMESPACE${NC}" -echo -e "${BLUE} Ver status: oc get all -n $NAMESPACE${NC}" -echo -e "${BLUE} Acessar API: curl https://$ROUTE_URL/api/health${NC}" - -echo -e "${GREEN}🎯 Aplicação pronta para uso!${NC}" +echo -e "${GREEN}🎉 Deployment completed successfully!${NC}" \ No newline at end of file