Cannot apply SSL cert to Kubernetes LoadBalancing Service on Kubernetes - azure

Issue
I am having trouble applying TLS to the DNS name of my LoadBalancer service for my Kubernetes cluster, and I am at a bit of a loss.
This is the first time I have worked with Kubernetes as well as Azure's Manage Container Services. For reasons that are out of my control this api is required to run on Azure's Managed Container Services.
Environment
Cluster is running on Azure using Managed Container Services (preview). I created my environment by following the steps here: https://learn.microsoft.com/en-us/azure/aks/tutorial-kubernetes-deploy-cluster
I created a static IP in Azure to use in the yaml for the loadbalancer service. Furthermore, I created a myprefix.cloudapp.azure.com DNS name for the IP using the following commands (https://learn.microsoft.com/en-us/azure/aks/static-ip)
IP="XX.XX.XX.XX"
DNSNAME="myprefix"
RESOURCEGROUP=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[resourceGroup]" --output tsv)
PIPNAME=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[name]" --output tsv)
az network public-ip update --resource-group $RESOURCEGROUP --name $PIPNAME --dns-name $DNSNAME
Deployment
This is the yaml I am using for my deployment:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: my-node-express-api-deployment
spec:
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 5
template:
metadata:
labels:
app: my-node-express-api
spec:
containers:
- name: my-node-express-api-container
image: myrepo/my-node-express-api-image:latest
ports:
- containerPort: 3000
volumes:
- name: tls
secret:
secretName: my-tls-secret
Service
This is the yaml for my LoadBalancing Service
apiVersion: v1
kind: Service
metadata:
name: my-node-express-api-loadbalancer
spec:
loadBalancerIP: 52.176.148.91
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
port: 443
targetPort: 3000
selector:
app: my-node-express-api
Secret
Yaml for secret
apiVersion: v1
kind: Secret
metadata:
name: my-tls-secret
namespace: default
data:
tls.crt: (base64 for myprefix.cloudapp.azure.com.crt)
tls.key: (base64 for myprefix.cloudapp.azure.com.key)
Note:
Everything works correctly over http when I remove the Secret from my deployment and remove port 443 from the LoadBalancer Service.

On Azure, if you need TLS termination on kubernetes, you can use Nginx Ingress controller(Now, Microsoft working with Azure ingress controller which uses Application gateway).
To archive this, we can follow those steps:
1 Deploy the Nginx Ingress controller
2 Create TLS certificates
3 Deploy test http service
4 configure TLS termination
More information about configure Nginx ingress controller for TLS termination on kubernetes on Azure, please refer to this blog.

Related

How to use static External IP for Azure kubernetes LoadBalancer?

I created a deployment at AKS:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: frontend
strategy:
type: Recreate
template:
metadata:
labels:
io.kompose.service: frontend
spec:
containers:
- image: app:latest
name: frontend
volumeMounts:
- mountPath: /app/db
name: db
- mountPath: /root/.aspnet/https
name: https
readOnly: true
env:
- name: ASPNETCORE_URLS
value: "https://+;http://+"
- name: ASPNETCORE_HTTPS_PORT
value: "443"
- name: ASPNETCORE_Kestrel__Certificates__Default__Path
value: "/root/.aspnet/https/cert.pfx"
- name: ASPNETCORE_Kestrel__Certificates__Default__Password
valueFrom:
secretKeyRef:
name: certificate-pass
key: pass
restartPolicy: Always
serviceAccountName: ""
volumes:
- name: db
persistentVolumeClaim:
claimName: db
- name: https
secret:
secretName: certificate
items:
- key: file
path: cert.pfx
and a service:
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
io.kompose.service: frontend
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
type: LoadBalancer
Service is created successfully. I can access it using provided External IP:
Now I want to make this IP static. There is an official docs which tells how to make it: Use a static public IP address and DNS label with the Azure Kubernetes Service (AKS) load balancer
There is also an article which technically duplicates the docs, but in a bit more details: Use a static public IP address outside of the node resource group with the Azure Kubernetes Service (AKS) load balancer
I am able to create an IP address, but when I reach az role assignment create command it fails ($GROUP here is just a placeholder for real Resource group literal):
$ CLIENT_ID=$(az aks show --resource-group Default --name k8s --query "servicePrinci
palProfile.clientId" --output tsv)
$ SUB_ID=$(az account show --query "id" --output tsv)
$ az role assignment create --assignee $CLIENT_ID --role "Network Contributor" --scope /subscriptions/$SUB_ID/resourceGroups/$GROUP
If the assignee is an appId, make sure the corresponding service principal is created with 'az ad sp create --id $CLIENT_ID
When I try proposed command if fails:
$ az ad sp create --id $CLIENT_ID
Another object with the same value for property servicePrincipalNames already exists.
I found similar issue at GitHub Azure/azure-cli repo, but there is no answer.
If I skip this step and set loadBalancerIP: XXX.XXX.XXX.XXX at config level, load balancer has a new property Load balancer IP, but External IP is not changed:
How to mitigate this error?
According to the messages you provide, I'm very confused about why you need to run the command az ad sp create --id $CLIENT_ID, both the docs do not show the necessity to run this command.
As I know, you only need to assign the "Network Contributor" role of the group other than the AKS node group to the service principal of the AKS. That's the right step you need to do. I think you need to read the docs again with more attention.
I had to use literal value instead of a variable $CLIENT_ID. That helped.

Replacing ip address in kubernetes with custom name

I have created a sample spring boot app and did the following:-
1.created a docker image
2.created an Azure container registry and did a docker push to this
3.Created a cluster in Azure Kubernetes service and deployed it successfully.I have chosen external endpoint option for this.
Kubernetes external end point
say for service to service call i dont want to use IP like http://20.37.134.68:80 but another custom name how can i do it?
Also if i chose internal then is there any way to replace the name.
Tried editing YAML with endpoint name property but failed.Any ideas?
I think you mixing some concept, so I'll try to explain and help you to reach what you want.
When you deploy a container image in a Kubernetes cluster, in the most cases you will use a pod or deployment spec, that basically is a yaml file with all your deployment/pod configuration, name, image name etc. Here is an example of a simple echo-server app:
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
spec:
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: mendhak/http-https-echo
ports:
- name: http
containerPort: 80
Observe the fields name in the file. Here you can configure the name for your deployment and for your containers.
In order to expose your application, you will need to use a service. Services can be internal and external. Here you can find all service types.
For a internal service, you need to use the service type ClusterIP (default), it means only your cluster will reach the pods. To reach your service from other pods, you can use the service name composed by my-svc.my-namespace.svc.cluster-domain.example.
Here is an example of a service for the deployment above:
apiVersion: v1
kind: Service
metadata:
name: echo-svc
spec:
selector:
app: echo
ports:
- protocol: TCP
port: 80
targetPort: 80
To expose your service externally, you have the option to use a service type NodePort, LoadBalancer or use an ingress.
You can configure your DNS name in the ingress rules and make path rules if you want, or even configure a HTTPS for your application. There are few options to ingresses in kubernetes, and one of the most popular is nginx-ingress.
Here is an example of how to configure a simple ingress for our example service:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "false"
name: echo-ingress
spec:
rules:
- host: myapp.mydomain.com
http:
paths:
- path: "/"
backend:
serviceName: echo-svc
servicePort: 80
In the example, i'm using the dns name myapp.mydomain.com, so it means you can only will reach your application by this name.
After create the ingress, you can see the external ip with the command kubectl get ing, and you can create a A entry in your dns server.

Kubernetes manifest on Azure for port 443

Battling with Kubernetes manifest on Azure. I have a simple api app running on port 443 (https). I simply want to run and replicate this app 3 times within a kubernetes cluster with a load balancer.
Kubernetes cluster:
My manifest file:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: apiApp
spec:
replicas: 3
template:
metadata:
labels:
app: apiApp
spec:
containers:
- name: apiApp
image: {image name on Registry}
ports:
- containerPort: 443
hostPort: 443
---
apiVersion: v1
kind: Service
metadata:
name: apiApp
spec:
type: LoadBalancer
ports:
- name: https
port: 443
targetPort: 443
selector:
app: apiApp
In the above manifest the loadbalancer does not seem to find the app on port 443 within the container.
1) How can I create this manifest to link load balancer to port 443 of the containers and also expose the load balancer to the outside world on port 443.
2)How would manifest look like in multi cluster environment (same conditions as above)
For your issue, I did the test with the load balancer follow the document Deploy an Azure Kubernetes Service (AKS) cluster.
This example only has one pod, so I scale up the pod in to 3 with the command kubectl scale --replicas=3 deployment/azure-vote-front. The yaml file about scales and Load Balancer will like the screenshot below.
When the Cluster finish, I can access the service from Internet via Web Browse. And you can use the command az aks browse to go into the Kubernets dashboard to get a overview of the Kubernets Cluster.
Update
The Azure Kubernets Cluster is just a resource group like below and so as the load balancer:

HTTPS with Azure Container Services and Kubernetes

Can anyone show how to setup https on kubernetes in ACS?
Most tutorials suggest to use LetsEncrypt but does not seem to fit my case as I have an existing .pfx i would like to use.
I created the az acs using the following cli command:
az acs create --orchestrator-type kubernetes --resource-group
myResourceGroup --name myAppName --generate-ssh-keys
and once everything got created i used the following command to spin up my services and deployments
kubectl create -f myApp.yaml
where myApp.yaml reads as following:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myApp-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: myApp
spec:
containers:
- name: myApp
image: myAppcontainerregistry.azurecr.io/myApp-images:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myAppservice
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: myApp
which gets my app working as intended for http:// but I am not too sure what my next steps are to get https:// working. Any helpful links also are appreciated.
P.s. my app is a net core 2.0 hosted in kestrel.
Maybe we can use Nginx Ingress Controller to archive that in ACS.
The Ingress Controller works like this:
We can follow this steps to do it:
1 Deploy the Nginx Ingress controller
2 Create TLS certificates
3 Deploy test http service
4 configure TLS termination
More information about configure Nginx Ingress Controller for TLS termination on Kubernetes on Azure, please refer to this blog.
Here a similar case, please refer to it.
By the way, here a example about configure Ingress on kubernetes using Azure Container service, please refer to it.

Accessing docker container over https on Azure subdomain

As an experiment I'm trying to run a docker container on Azure using the Azure Container Service and Kubernetes as the orchestrator. I'm running the official nginx image. Here are the steps I am taking:
az group create --name test-group --location westus
az acs create --orchestrator-type=kubernetes --resource-group=test-group --name=k8s-cluster --generate-ssh-keys
I created Kubernetes deployment and service files from a docker compose file using Kompose.
deployment file
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
kompose.service.type: LoadBalancer
creationTimestamp: null
labels:
io.kompose.service: test
name: test
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: test
spec:
containers:
- image: nginx:latest
name: test
ports:
- containerPort: 80
resources: {}
restartPolicy: Always
status: {}
service file
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.service.type: LoadBalancer
creationTimestamp: null
labels:
io.kompose.service: test
name: test
spec:
ports:
- name: "80"
port: 80
targetPort: 80
selector:
io.kompose.service: test
type: LoadBalancer
status:
loadBalancer: {}
I can then start everything up:
kubectl create -f test-service.yaml,test-deployment.yaml
Once an IP has been exposed I assign a dns prefix to it so I can access my running container like so: http://nginx-test.westus.cloudapp.azure.com/.
My question is, how can I access the service using https? At https://nginx-test.westus.cloudapp.azure.com/
I don't think I'm supposed to configure nginx for https, since the certificate is not mine. I've tried changing the load balancer to send 443 traffic to port 80, but I receive a timeout error.
I tried mapping port 443 to port 80 in my Kubernetes service config.
ports:
- name: "443"
port: 443
targetPort: 80
But that results in:
SSL peer was not expecting a handshake message it received. Error code: SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT
How can I view my running container at https://nginx-test.westus.cloudapp.azure.com/?
If I understand it correctly, I think you are looking for Nginx Ingress controller.
If we need TLS termination on Kubernetes, we can use ingress controller, on Azure we can use Nginx Ingress controller.
To archive this, we can follow those steps:
1 Deploy the Nginx Ingress controller
2 Create TLS certificates
3 Deploy test http service
4 configure TLS termination
More information about configure Nginx Ingress Controller for TLS termination on Kubernetes on Azure, please refer to this blog.
root#k8s-master-6F403744-0:~/ingress/examples/deployment/nginx# kubectl get services --namespace kube-system -w
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend 10.0.113.185 <none> 80/TCP 42m
heapster 10.0.4.232 <none> 80/TCP 1h
kube-dns 10.0.0.10 <none> 53/UDP,53/TCP 1h
kubernetes-dashboard 10.0.237.125 <nodes> 80:32229/TCP 1h
nginx-ingress-ssl 10.0.92.57 40.71.37.243 443:30215/TCP 13m

Resources