Azure Kubernetes (AKS) does not release public IPs - azure

We are using managed Kubernetes in Azure (AKS) and have run out of public IP addresses. We only need one, but AKS creates a new public IP every time we deploy a service and it does not delete it when the service is deleted. For example:
apiVersion: v1
kind: Service
metadata:
name: somename
spec:
ports:
- port: 443
targetPort: 443
selector:
app: somename
# Also tried this to reuse public IP in AKS MC resource group
# https://learn.microsoft.com/en-my/azure/aks/static-ip
# loadBalancerIP: x.x.x.x
type: LoadBalancer
Every time this is deployed (kubectl create -f svc.yml) a new public IP is created. When it is deleted (kubectl delete -f svc.yml) the IP remains. Trying to reuse one of the existing IPs with loadBalanceIP as in the comments above fails, "Public ip address ... is referenced by multiple ipconfigs in resource ...".
We have created a service request but it takes ages, so I'm hoping this will be faster. I don't dare to just delete the public IPs in the AKS managed resource as that may cause issues down the line.
Is there a way to safely release or reuse the public IPs? We are using Kubernetes version 1.7.12. We have deleted the deployment referenced by the service as well, it makes no difference.

It should delete the IPs after some time (like 5 minutes tops). So the issue you are having is a bug. You can check k8s events to find the error and look at it.
Also, its perfectly safe to delete Azure resources. k8s wont freak out if they are gone.
Tested with k8s 1.9.1

Related

how to provide inbound access from public internet to an app hosted in an Azure private kubernetes cluster

I deployed an application in an Azure K8S cluster, using NGINX as gateway, with a public static IP, based on AKS & PUBLIC-IP and on AKS & NGINX.
Now I need to deploy the application in an Azure private cluster, ie, running in a private vnet (see CREATE PRIVATE AKS); attempting to assign a public static IP to NGINX does not work, which can be expected as the load-balancer expects a private IP, not a public IP.
How can I provide inbound access to my app hosted in a private cluster, using NGINX and a public static IP?
Hi you have two ways two achieve that...Depending on your needs (and Azure costs...):
1-Use Azure Application Gateway. For myself I use Terraform. And here you can the see official documentation regarding internal IP address.
Now you can use this one as your new Ingress (and get rid of NGINX) like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: guestbook
annotations:
kubernetes.io/ingress.class: azure/application-gateway
spec:
rules:
- http:
paths:
- backend:
serviceName: frontend
servicePort: 80
Or you could use NGINX internally as your ingress like explained on option 2.
2- First you must have a Public IP with a Load Balancer associated with it.The backend from that LB must be up to your needs.
But here is the trick...Do not create NGINX with that public IP but with an internal IP and an internal load balancer, you can see how to do that in the following url:
https://learn.microsoft.com/en-us/azure/aks/ingress-internal-ip
And the important thing you must do is the nginx ovveride on the helm parameters:
controller:
service:
loadBalancerIP: 10.240.0.42
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
Of course the internal VNET must be created an the load balancer IP must be a correct one.
And the final trick now that you have NGINX listening behind a private IP is to verify your traffic from the Public IP is redirected to that internal VNET...Of course it depends on how you have infrastructure setup behind that LB that holds the public IP.
As stated in the comment above you can do the same via Application Gateway in Azure. But if you are going to only use AKS you might want to just use Application Gateway as your ingress controller which is already created with the private cluster.
Please follow this to achieve the same https://microsoft.github.io/AzureTipsAndTricks/blog/tip256.html
Based on your description i understand that you want to have ingress traffic through your NGINX ingress controller which has a Loadbalancer service with static IP. If your deployment is correctly configured the a Loadbalancer service should be assigned to your NGINX ingress controller with a public IP. Since i dont know your namespaces, naming of deployments etc try:
kubectl get services --all-namespaces | grep -i loadbalancer
You should be able to find that an nginx loadbalancer service has a public IP. Now since NGINX is your ingress controller this means that you have a Layer 7 loadbalancer as ingress so you need to create an ingress route to your application running in AKS. This is documented here from Azure NGINX ingress but also here Ingress K8s

How to setup Aks Ingress with Azure Private DNS

I created AKS with internal ingress Nginx. This comes up like below in the cluster.
Then I created Azure private DNS Service. In the Azure private DNS service, I created a 'Record set' like
Blockquote
Technically, i should be able to access LoadBalancer External ip with promotion.mydomain.com (as example). Insted of this, I'm having '502 Bad Gateway' error when i hit http://promotion.mydomain.com in the browser. Any advice?
I faced the same issue and have been able to solve it recently.
I created another Ingress but in the desired namespace (mine was default) with the following definition :
(I have enabled tls but you can remove that part)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: my-custom-ingress
spec:
tls:
- hosts:
- foo.mydomain.com
secretName: my-tls-secret
rules:
- host: foo.mydomain.com
http:
paths:
- path: /
backend:
serviceName: my-foo-app-service-nodeport
servicePort: 4444
First of all find the EXTERNAL IP of your nginx ingress and keep it in mind:
kubectl get svc --namespace ingress-basic
Then in the Azure DNS zone you can attach the domain to an Azure Resource :
Open azure portal.
Go in the MC_... resource group created by your AKS cluster.
Find the LoadBalancer resource and click it.
On the LoadBalancer, go into "Frontend IP Configuration". You'll then see a list of public IP with a related ResourceId (example: 11.22.33.44 (xxx-yyyy-bbb))
Find the IP that is corresponding to the LoadBalancer IP you found on the LoadBalancer (before step 1) and memorize the associated object id.
Open you Azure DNS zone and create new domain (or edit one)
Set "Alias Record Set: Yes" then "Alias type: Resource"
Under "Azure Resource" find the resource that has the ResourceId you found in step 5 and select it.
Save
Now it should work.
I see your purpose is to create AKS with internal Ingress Nginx and use the custom DNS. And I see your Ingress external IP is 10.240.0.42. It seems it's a private IP of the subnet which you AKS nodes in.
So I think you need to create An Azure Application Gateway or Azure Load Balancer to route your request from the Internet to your internal Ingress Nginx interface. And the A record also needs to be changed, you need to change the IP into the public IP of the one which you choose from Azure Application Gateway and Azure Load Balancer. I think you know you need to update your custom DNS setting in the DNS server which you DNS in.
When all things are being done. The requests routing path will like this:
Internet ( your custom DNS)
Azure DNS Server
Azure Public IP of the Application Gateway or Load Balancer ( this is what I think you missed)
10.240.0.42 ( ingress Nginx internal IP)
AKS Ingress Nginx
Service
Deployment or Pod

Error deploy Azure kubernetes ingress with static IP

Good guys
Let's see if someone can help me.
I have configured Azure Kubernetes (AKS) in version 1.13
I am trying to create an Ingress with static IP, but it is impossible for me.
I am use kubectl create -f static-ip-svc.yaml
#File
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-lb
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
externalTrafficPolicy: Local
type: LoadBalancer
loadBalancerIP: 40.121.219.126
ports:
- port: 80
name: http
targetPort: 80
- port: 443
name: https
targetPort: 443
selector:
# Selects nginx-ingress-controller pods
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
and show error:
Type Reason Age From
Message ---- ------ ---- ----
------- Normal EnsuringLoadBalancer 8s (x4 over 43s) service-controller Ensuring load balancer Warning
CreatingLoadBalancerFailed 7s (x4 over 43s) service-controller
Error creating load balancer (will retry): failed to ensure load
balancer for service default/nginx-ingress-lb: timed out waiting for
the condition
For you, to create an Ingress with static IP, there are two ways to achieve it. But firstly, you need to know the info that resource groups for Azure Kubernetes service and its infrastructure.
The info is Why are two resource groups created with AKS? It explains that there are two resource groups, one for the Azure Kubernetes service itself and another for its infrastructure. So that there are two ways to create an Ingress with static IP.
Here the two ways:
Use the static IP which created in the group named MC_xxxx_xxxx_location.
Use the static IP which created in another group except for the group MC_xxxx_xxxx_location. In this way, you need to assign enough permission to the service principal of AKS, at least is "Network Contributor".
You get more details about "Use a static public IP address with the Azure Kubernetes Service (AKS) load balancer" here. I think you use the second way but you do not assign enough permission so that you got the error. Check the steps and try again following the steps.

how to set dns to azure kubenetes(acs) services?

I am new to azure. I created an azure acs with kubenetes by using the following config(part of the whole file).
- apiVersion: v1
kind: Service
metadata:
name: my-web
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
app: my-web
The service can be visited, but only via IP address. There is no secondary dns(like: xxx.azurewebsite.com) generated. Currently, I use A record points to the ip address. It works, but I am afraid the ip address will be changed, and I have to manually change the dns A record. Just asking if there is a way to generate some stable dns for acs services?
Just asking if there is a way to generate some stable dns for acs
services?
We can via Azure portal to change the public IP address to static, in this way, restart the service will not change the IP.
But in Azure, if we delete the k8s service, the Public IP address will collected by Azure platform, and we will lose this IP address. For now, Azure does not support to keep the public IP address for k8s service.

Does NodePort work on Azure Container Service (Kubernetes)

I have got the following service for Kubernetes dashboard
Name: kubernetes-dashboard
Namespace: kube-system
Labels: k8s-app=kubernetes-dashboard
kubernetes.io/cluster-service=true
Annotations: kubectl.kubernetes.io/last-applied-configuration={"kind":"Service","apiVersion":"v1","metadata":{"name":"kubernetes-dashboard","namespace":"kube-system","creationTimestamp":null,"labels":{"k8s-app":"k...
Selector: k8s-app=kubernetes-dashboard
Type: NodePort
IP: 10.0.106.144
Port: <unset> 80/TCP
NodePort: <unset> 30177/TCP
Endpoints: 10.244.0.11:9090
Session Affinity: None
Events: <none>
According to the documentation, I ran
az acs kubernetes browse
and it works on http://localhost:8001/ui
But I want to access it outside the cluster too. The describe output says that it is exposed using NodePort on port 30177.
But I'm not able to access it on http://<any node IP>:30177
As we know, expose the service to internet, we can use nodeport and LoadBalancer.
As far as I know, Azure does not support nodeport type now.
But I want to access it outside the cluster too.
we can use LoadBalancer to re-create the kubernetes dashboard, here are my steps:
Delete kubernetes-dashboard via kubernetes UI: select Namespace to kube-system, then select services, then delete it:
Modify Kubernetes-dashboard-service.yaml: SSH master VM, then change type from nodeport to LoadBalancer:
root#k8s-master-47CAB7F6-0:/etc/kubernetes/addons# vi kubernetes-dashboard-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: "true"
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 9090
selector:
k8s-app: kubernetes-dashboard
type: LoadBalancer
start kubernetes browse from CLI 2.0:
C:\Users>az acs kubernetes browse -g k8s -n containerservice-k8s
Then SSH to master VM to check the status:
Now, we can via the Public IP address to browse the UI:
Update:
The following image shows the architecture of azure container service cluster(Kubernetes), we should use Load-Balancer to expose the service to internet.
On second thought, this actually is expected to NOT work. The only public IP in the cluster, by default, is for the load balancer on the masters. And that load balancer obviously is not configured to forward random ports (like 30000-32767 for example). Further, none of the nodes directly have a public IP, so by definition NodePort is not going to work external to the cluster.
The only way you're going to make this work is by giving the nodes public IP addresses directly. This is not encouraged for a variety of reasons.
If you merely want to avoid waiting... then I suggest:
Don't delete the Service. Most dev scenarios should just be kubectl apply -f <directory> in which case you don't really need to wait for the Service to re-provision
Use Ingress along with 'nginx-ingress-controller' so that you only need to wait for the full LB+NSG+PublicIP provisioning once, and then can just add/remove Ingress objects in your dev scenario.
Use minikube for development scenarios, or manually add public ips to the nodes to make the NodePort scenario work.
You can't expose the service via nodeport by running the kubectl expose command, you get a VIP address outside the range of the subnets your cluster sits on... Instead, deploy a service through a yaml file and you can specify an internal load balancer as a type..., which will give you a local IP on the Master subnet, which you can connect to via the internal network...
Or, you can just expose the service with an external load balancer and get a public ip. available on the www.

Resources