Azure上K8s集群LoadBalancer IP pending,求助通过Ingress暴露流量
Hey there! Let's work through this together—Kubernetes the Hard Way is awesome for learning, but those cloud-native LoadBalancer integrations don't come pre-installed, which is exactly why you're seeing that <pending> ExternalIP. Let's switch gears to Ingress, which is a reliable way to expose your services without relying on cloud provider LoadBalancer controllers.
Why Your LoadBalancer Isn't Working
Kubernetes LoadBalancer services depend on a cloud provider-specific controller to provision a public load balancer (like Azure's Standard Load Balancer). Since you built your cluster manually via Kubernetes the Hard Way, this controller isn't included out of the box. Your cluster has no way to communicate with Azure's API to create the load balancer, hence the stuck <pending> status. Even setting externalIPs won't work unless your node network is explicitly configured to route that IP to your pods.
Step 1: Update Your Nginx Service to ClusterIP
Ingress routes traffic to ClusterIP services (the default service type if you don't specify), so let's adjust your existing service first. Replace your nginx-service.yaml with this:
apiVersion: v1 kind: Service metadata: labels: app: nginx-service name: nginx-service spec: type: ClusterIP # Changed from LoadBalancer ports: - name: "80" port: 80 targetPort: 80 - name: "443" port: 443 targetPort: 443 selector: app: nginx-service
Apply the change with:
kubectl apply -f nginx-service.yaml
Step 2: Install the Nginx Ingress Controller
Ingress needs a controller to handle incoming traffic routing. Let's deploy the official Nginx Ingress Controller manually (no external links required):
2.1 Create the Ingress Namespace
Save this as ingress-namespace.yaml:
apiVersion: v1 kind: Namespace metadata: name: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx
Apply it:
kubectl apply -f ingress-namespace.yaml
2.2 Set Up RBAC Permissions
Save this as ingress-rbac.yaml:
apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx name: ingress-nginx rules: - apiGroups: [""] resources: ["configmaps", "endpoints", "nodes", "pods", "secrets"] verbs: ["list", "watch"] - apiGroups: [""] resources: ["nodes"] verbs: ["get"] - apiGroups: [""] resources: ["services"] verbs: ["get", "list", "watch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["create", "patch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses/status"] verbs: ["update"] - apiGroups: ["networking.k8s.io"] resources: ["ingressclasses"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: [""] resources: ["namespaces"] verbs: ["get"] - apiGroups: [""] resources: ["configmaps", "pods", "secrets", "endpoints"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["services"] verbs: ["get", "list", "watch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses/status"] verbs: ["update"] - apiGroups: ["networking.k8s.io"] resources: ["ingressclasses"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx
Apply it:
kubectl apply -f ingress-rbac.yaml
2.3 Deploy the Controller & Service
Save this as ingress-controller.yaml:
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginx spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller spec: containers: - name: controller image: registry.k8s.io/ingress-nginx/controller:v1.8.2 args: - /nginx-ingress-controller - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx securityContext: capabilities: add: ["NET_BIND_SERVICE"] runAsUser: 101 ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: httpGet: path: /healthz port: 10254 initialDelaySeconds: 10 readinessProbe: httpGet: path: /healthz port: 10254 initialDelaySeconds: 10 serviceAccountName: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginx spec: type: LoadBalancer ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller
Apply it:
kubectl apply -f ingress-controller.yaml
Wait for the controller pod to be ready:
kubectl wait --namespace ingress-nginx \ --for=condition=ready pod \ --selector=app.kubernetes.io/component=controller \ --timeout=120s
Step 3: Create an Ingress Resource
Now create an Ingress manifest (nginx-ingress.yaml) to route traffic to your Nginx service. This example handles HTTP traffic; we can add HTTPS later if needed:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: your-domain.com # Replace with your domain (or remove this line to use the public IP directly) http: paths: - path: / pathType: Prefix backend: service: name: nginx-service port: number: 80
Apply the Ingress:
kubectl apply -f nginx-ingress.yaml
Step 4: Access Your Service
Retrieve the public IP assigned to the Ingress controller:
kubectl get service ingress-nginx-controller -n ingress-nginx
Use this EXTERNAL-IP to access your Nginx app via browser or curl:
curl http://<ingress-external-ip>
You should see the Nginx default page if everything is configured correctly.
Troubleshooting Quick Checks
- If the Ingress IP is still
<pending>, verify the controller pods are running:kubectl get pods -n ingress-nginx - Ensure your Azure nodes have public IPs or are in a subnet with outbound internet access
- For HTTPS, you can add TLS certificates by updating the Ingress manifest with a
tlssection and referencing a secret containing your certs
内容的提问来源于stack exchange,提问作者Manoj Kumar Maharana

