In this article, we will see how to install and get a WordPress site running on Azure Kubernetes Services,
- WordPress (To host the Website)
- Nginx (For Load balancing )
- Cert Manager ( Create and Issue let’s encrypt Certificates)
- Kubeapps ( Bitnami Packages)
Let’s create a resource group az-pr-uaen-web-rg and create an Azure Kubernetes Cluster in the specified resource group

Choose an appropriate SKU and leave the default autoscale

Leave things default

Choose a security group for Kubernetes Administration

Leave kubenet networking

not using calico or container registry in this scenario.

leave the secret store CSI driver disabled by default

Azure Kubernetes Cluster is created .


Let’s install Microsoft CLI and Chocolatey on the local machine.
Chocolatey Software | Installing Chocolatey

Install Kubernetes Helm using Choco
choco install kubernetes-helm

Install Bitnami repo using helm
helm repo add bitnami https://charts.bitnami.com/bitnami

Download kubectl.exe to run kubectl commands
curl -LO "https://dl.k8s.io/release/v1.24.0/bin/windows/amd64/kubectl.exe"

Download and install kubelogin if you want to authenticate to AKS using Azure AD

Login to aks cluster
az aks get-credentials --resource-group az-pr-uaen-web-rg --name az-aks-azure365pro --admin

if you have multiple subscriptions
az login Get the subscription ID you are working on az account list -o table --all az account set --subscription e08f63cf-xxxx-44e3-ba41-xxxxxxx az aks get-credentials --resource-group az-pr-uaen-web-rg --name az-aks-azure365pro --admin kubectl get namespaces
To list all namespaces

Add Bitnami repo
create kubeapps namespace
Install bitnami kubeapps
helm repo add bitnami https://charts.bitnami.com/bitnami kubectl create namespace az-kubeapps helm install kubeapps bitnami/kubeapps -n az-kubeapps

Now kubeapps is installed – We will configure things to access them using an nginx load balancer.

kubectl create serviceaccount kubeapps-operator kubectl create clusterrolebinding kubeapps-operator --clusterrole=cluster-admin --serviceaccount=default:kubeapps-operator kubectl get secret $(kubectl get serviceaccount kubeapps-operator -o jsonpath='{.secrets[].name}') -o jsonpath='{.data.token}' -o go-template='{{.data.token | base64decode}}'
if you run on Windows 10
‘base64decode}}” is not recognized as an internal or external command, operable program, or batch file.
switch to Powershell
.\kubectl.exe get secret $(.\kubectl.exe get serviceaccount kubeapps-operator -o jsonpath='{.secrets[].name}') -o jsonpath='{.data.token}' -o go-template='{{.data.token | base64decode}}'
A secret token has to be generated like below to get inside kubeapps , Copy the token to a safe location

To update helm repo
helm repo update
Install Nginx controller / Please note we are utilizing the native Nginx controller here.
kubectl create namespace az-nginx helm install az-nginx bitnami/nginx-ingress-controller -n az-nginx


Now Nginx is available with an external IP
kubectl get svc -n az-nginx kubectl get svc --all-namespaces

Expose kubeapps at port 80 just to access for now. later we can apply SSL
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubeapps
namespace: kubeapps
spec:
ingressClassName: nginx
rules:
– host: kubeapps.azure365pro.com
http:
paths:
– pathType: Prefix
backend:
service:
name: kubeapps
port:
number: 80
path: /
kubectl apply -f .\kubeapps-ingress.yaml –namespace az-kubeapps

Deleting bad ingress rules – For Examples only
kubectl get all,nodes,ing -A -o wide

To list Helm installations

To uninstall Helm installations – For examples only
helm uninstall az-nginx




Choosing to install with Cluster IP as we will use the nginx IP to publish and Expose using lets encrypt SSL .


ingress without SSL – YAML samples

Install cert-manager with InstallCRDs true

issuer.yaml with staging lets encrypt . Once you confirm things are working as expected. you can get the live URL updated.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# Update with real email
email: info@azure365pro.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
# To use on production , use the following line instead:
#server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: issuer-letsencrypt-staging
solvers:
– http01:
ingress:
class: nginx
Created issuer
Listing Secrets
kubectl apply -f issuer.yaml -n az-cert
kubectl get secrets -n az-cert

cert.yaml for cluster issuer – secret and WordPress should be in the same namespace inorder to work seamlessly.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: az-wp-1
spec:
secretName: virtualpetals-tls
dnsNames:
– www.virtualpetals.com
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
kubectl apply -f cert.yaml -n az-wp

Applying TLS rules on nginx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: az-wp
namespace: az-wp
spec:
ingressClassName: nginx
tls:
– hosts:
– www.virtualpetals.com
secretName: virtualpetals-tls
rules:
– host: www.virtualpetals.com
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: az-wp-1-wordpress
port:
number: 80
kubectl apply -f wp-ingress.yaml -n az-wp

To describe ingress using ing

To check current YAML Config

As we are using a staging issuer, It shows staging. Once we feel SSL is getting assigned and staging getting issued.
We are good to convert to production

Good to know – To list and delete files from a running container
kubectl exec az-wp-1-wordpress-6cb985c596-84j8j -n az-wp -- ls /bitnami/wordpress/wp-content/plugins/really-simple-ssl kubectl exec az-wp-1-wordpress-6cb985c596-84j8j -n az-wp -- sh -c 'rm -rf /bitnami/wordpress/wp-content/plugins/really-simple-ssl/*'
Getting the production URL live and disabling the staging URL
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
# Update with real email
email: info@azure365pro.com
#server: https://acme-staging-v02.api.letsencrypt.org/directory
# To use on production , use the following line instead:
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: issuer-letsencrypt-production
solvers:
– http01:
ingress:
class: nginx
kubectl apply -f issuer-prod.yaml -n az-cert

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: az-wp-0
namespace: az-wp
spec:
secretName: virtualpetals-tls-pr
dnsNames:
– www.virtualpetals.com
– virtualpetals.com
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer

To increase body size in ingress for bulk uploads for example.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: az-wp
namespace: az-wp
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: 400m
spec:
ingressClassName: nginx
tls:
– hosts:
– www.virtualpetals.com
– virtualpetals.com
secretName: virtualpetals-tls-pr
rules:
– host: “www.virtualpetals.com”
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: az-wp-1-wordpress
port:
number: 80
– host: “virtualpetals.com”
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: az-wp-1-wordpress
port:
number: 80

Now website is up using Azure Kubernetes Services.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: az-wp-1
spec:
secretName: kubeapps.azure365pro.com
dnsNames:
– kubeapps.azure365pro.com
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
kubectl apply -f cert-prod-kubeapps.yaml -n az-kubeapps


Now you can see Kubeapps is live with SSL / WordPress is live with SSL / Nginx is configured with Cert Manager.