简体   繁体   中英

Can't access my app deployed on an AKS cluster, from the azure public ip

I'm very new to Cloud providers and I'm trying to setup a cluster on Azure. I setup the infra with terraform, and I create a ResourceGroup, a static Azure PublicIP (sku basic), a Azure Load Balancer(sku basic, connected to the public ip, front end port: 80, backend port 3000) and a AKS cluster. With Skaffold I then deploy on the AKS cluster a ClusterIP ( port: 3000, targetPort: 3000 that selects the server pods), the server Deployment( which listens to port 3000) plus the secrets.

The deployment goes well and logging the server pods shows the app is running correctly and listening on por 3000, but when I try to access the server either with the address ( 20.218.249.246:80/api where 80 is the load balancer front end port and the /api is the base for the router) or the dns (fixit.germanywestcentral.cloudapp.azure.com:80/api) from the Azure console the connection fails after timeout. I deployed a Kube.netes Load balancer to test the cluster and from its external ip I can indeed access the server. looking in the troubleshot guides I see that the check on the cluster's load balancer passes as it uses a Standard load balancer, but I did create a Basic one in terraform.

load balance check故障排除检查 public ip 公网IP load balancer负载平衡器 cluster簇 resource group资源组

It would seem by the check that my cluster is not using the load balancer I created as the one it is using is Standard and the one I created is Basic.

Am I missing out something in setting up the cluster or the ip on Azure? Many thanks for the help, here are the files

resource group

resource "azurerm_resource_group" "resource_group" {
  name     = var.resource_group_name
  location = var.location
    tags = {
    Environment = "Production"
    Team = "DevOps"
  }
}

public ip

resource "azurerm_public_ip" "public-ip" {
  name                = "fixit-public-ip"
  location            = var.location
  resource_group_name = var.resource_group_name
  allocation_method   = "Static"
  domain_name_label = "fixit"
  # sku = "Standard"
  # fixit.germanywestcentral.cloudapp.azure.com

}

load balancer

resource "azurerm_lb" "load-balancer" {
  name                = "fixit-load-balancer"
  location            = var.location
  resource_group_name = var.resource_group_name
  # sku = "Standard"

  frontend_ip_configuration {
    name                 = "PublicIPAddress"
    public_ip_address_id = azurerm_public_ip.public-ip.id
  }
  
  
}
resource "azurerm_lb_backend_address_pool" "address-pool" {
  name                = "fixit-backend-pool"
  loadbalancer_id     = azurerm_lb.load-balancer.id
  
}

resource "azurerm_lb_rule" "load-balancer-rule" {
  name = "fixit-load-balancer-rule"
  loadbalancer_id = azurerm_lb.load-balancer.id
  frontend_ip_configuration_name = "PublicIPAddress"
  protocol                       = "Tcp"
  frontend_port                  = 80
  # backend_port                   = 27017
  backend_port                   = 3000
  # disable_outbound_snat = true

}

cluster

resource "azurerm_kubernetes_cluster" "server_cluster" {
  name                = "server_cluster"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
  dns_prefix          = "fixit"
  kubernetes_version = var.kubernetes_version
  # sku_tier = "Paid"

  default_node_pool {
    name       = "default"
    node_count = 1
    min_count = 1
    max_count = 3
    # vm_size    = "standard_b2s_v5"
    vm_size    = "standard_e2bs_v5"
    type = "VirtualMachineScaleSets"
    enable_auto_scaling = true
    enable_host_encryption = false
    # os_disk_size_gb = 30
    enable_node_public_ip = true
    
  }

  identity {
    type = "SystemAssigned"
  }

  tags = {
    Environment = "Production"
  }

  linux_profile {
    admin_username = "azureuser"
    ssh_key {
        key_data = var.ssh_key
    }
  }
  network_profile {
      network_plugin = "kubenet"
      # load_balancer_sku = "standard"
    
  }
  
}

cluster ip

apiVersion: v1
kind: Service
metadata:
  name: server-clusterip-service
spec:
  type: ClusterIP cloud provider's load balancer
  selector:
    app: fixit-server-pod
  ports:
    - name: server-clusterip-service
      protocol: TCP
      port: 3000 # service port
      targetPort: 3000 # por on which the app is listening to

server

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fixit-server
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: fixit-server-pod
  template:
    metadata:
      labels:
        app: fixit-server-pod
    spec:
      imagePullSecrets:
        - name: docker-secret
      containers:
        - name: fixit-server-container
          image: vinnytwice/fixit-server:dev
          imagePullPolicy: 'Always'
          env:
            # - name: SERVER_DEV_IMAGE_TAG
            #   value: 'dev'

            # server
            - name: APP_LISTENING_PORT
              value: '3000'
            - name: API_KEY
              valueFrom:
                secretKeyRef:
                  name: server-secret
                  key: api-key
            # stripe
            - name: STRIPE_KEY
              valueFrom:
                secretKeyRef:
                  name: stripe-secret
                  key: stripe-key
            # mongo db connection string
            - name: MONGO_USERNAME_K8S
              valueFrom:
                secretKeyRef:
                  key: mongo-username-k8s
                  name: server-secret

            - name: MONGO_HOSTNAME_K8S
              valueFrom:
                secretKeyRef:
                  key: mongo-hostname-k8s
                  name: server-secret

            - name: MONGO_PORT_K8S
              valueFrom:
                secretKeyRef:
                  name: server-secret
                  key: mongo-port-k8s

            # neo4j connection string
            - name: MONGO_DB_K8S
              valueFrom:
                secretKeyRef:
                  key: mongo-db-k8s
                  name: server-secret

            - name: NEO4J_AURA_URI
               valueFrom:
                 secretKeyRef:
                   key: neo4j-aura-uri
                   name: neo4j-secret
            - name: NEO4J_AURA_USERNAME
               valueFrom:
                 secretKeyRef:
                   key: neo4j-aura-username
                   name: neo4j-secret
            - name: NEO4J_AURA_PASSWORD
               valueFrom:
                 secretKeyRef:
                   key: neo4j-aura-password
                   name: neo4j-secret
          resources:
            limits:
              memory: '2Gi'
              cpu: '500m'
              # cpu: '1.0'

I finally found the problem. It was my setup of course. I wasn't installing any ingress controller so of course the ingress service wasn't working at all, the proper implementation is to install an ingress controller https://learn.microsoft.com/en-us/azure/aks/ingress-basic?tabs=azure-cli , which hooks up the the internal cluster load balancer, so there is no need to create one. Now, the ingress controller will accept an ip address for the load balancer, but you have to create the PublicIP in the node resource group because is going to look for it there and not in the resource group , got it after checking the difference between the two here https://learn.microsoft.com/en-us/azure/aks/faq#why-are-two-resource-groups-created-with-aks .

So the working configuration is now:

main

terraform {
  required_version = ">=1.1.0"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
       version = "~> 3.0.2"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
  subscription_id   = var.azure_subscription_id
  tenant_id         = var.azure_subscription_tenant_id
  client_id         = var.service_principal_appid
  client_secret     = var.service_principal_password
}


provider "kubernetes" {
  host = "${module.cluster.host}"
  client_certificate = "${base64decode(module.cluster.client_certificate)}"
  client_key = "${base64decode(module.cluster.client_key)}"
  cluster_ca_certificate = "${base64decode(module.cluster.cluster_ca_certificate)}"
}

provider "helm" {
  kubernetes {
    host                   = "${module.cluster.host}"
    client_certificate     = "${base64decode(module.cluster.client_certificate)}"
    client_key             = "${base64decode(module.cluster.client_key)}"
    cluster_ca_certificate = "${base64decode(module.cluster.cluster_ca_certificate)}"
  }
}



module "cluster" {
  source = "./modules/cluster"
  location = var.location
  vm_size = var.vm_size
  resource_group_name = var.resource_group_name
  node_resource_group_name = var.node_resource_group_name
  kubernetes_version = var.kubernetes_version
  ssh_key = var.ssh_key
  sp_client_id = var.service_principal_appid
  sp_client_secret = var.service_principal_password
}




module "ingress-controller" {
  source = "./modules/ingress-controller"
  public_ip_address = module.cluster.public_ip_address
  depends_on = [
    module.cluster.public_ip_address
  ]
}

cluster

resource "azurerm_resource_group" "resource_group" {
  name     = var.resource_group_name
  location = var.location
    tags = {
    Environment = "test"
    Team = "DevOps"
  }
}
resource "azurerm_kubernetes_cluster" "server_cluster" {
  name                = "server_cluster"
  ### choose the resource goup to use for the cluster
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
  ### decide the name of the cluster "node" resource group, if unset will be named automatically 
  node_resource_group = var.node_resource_group_name
  dns_prefix          = "fixit"
  kubernetes_version = var.kubernetes_version
  # sku_tier = "Paid"

  default_node_pool {
    name       = "default"
    node_count = 1
    min_count = 1
    max_count = 3
    vm_size = var.vm_size

    type = "VirtualMachineScaleSets"
    enable_auto_scaling = true
    enable_host_encryption = false
    # os_disk_size_gb = 30
  }

  service_principal {
    client_id = var.sp_client_id
    client_secret = var.sp_client_secret
  }

  tags = {
    Environment = "Production"
  }

  linux_profile {
    admin_username = "azureuser"
    ssh_key {
        key_data = var.ssh_key
    }
  }
  network_profile {
      network_plugin = "kubenet"
      load_balancer_sku = "basic" 
    
  }
  http_application_routing_enabled = false
  depends_on = [
    azurerm_resource_group.resource_group
  ]
}

resource "azurerm_public_ip" "public-ip" {
  name                = "fixit-public-ip"
  location            = var.location
  # resource_group_name = var.resource_group_name
  resource_group_name = var.node_resource_group_name
  allocation_method   = "Static"
  domain_name_label = "fixit"
  # sku = "Standard"

depends_on = [
  azurerm_kubernetes_cluster.server_cluster
]
}

ingress controller

resource "helm_release" "nginx" {
  name      = "ingress-nginx"
  repository = "ingress-nginx"
  chart     = "ingress-nginx/ingress-nginx"
  namespace = "default"

  set {
    name  = "controller.service.externalTrafficPolicy"
    value = "Local"
  }

  set {
    name = "controller.service.annotations.service.beta.kubernetes.io/azure-load-balancer-internal"
    value = "true"
  }

  set {
    name  = "controller.service.loadBalancerIP"
    value = var.public_ip_address
  }

  set {
    name  = "controller.service.annotations.service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path"
    value = "/healthz"
  }
} 

ingress service

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-service
  # namespace: default
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2$3$4
spec:
  ingressClassName: nginx
  rules:
    # - host: fixit.westeurope.cloudapp.azure.com #dns from Azure PublicIP


### Node.js server
  - http:
      paths:
      - path: /(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: server-clusterip-service
            port:
              number: 80 

  - http:
      paths:
      - path: /server(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: server-clusterip-service
            port:
              number: 80
...

other services omitted

Hope this can help getting the setup right. Cheers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM