Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save owensengoku/c799b1524df4daf34ca09927d54a6c1d to your computer and use it in GitHub Desktop.
Save owensengoku/c799b1524df4daf34ca09927d54a6c1d to your computer and use it in GitHub Desktop.
Azure kubernetes service (AKS) + Azure application gateway + Letsencrypt ingress setup (production setup) (AGIC) automatic ssl certificate generation.
# prereq:
# 1. aks cluster
# 2. azure gateway V2 (rules setup not important, will be overwritten)
# 3. both of the above in the same Virtual network in azure. (different subnets).
$subscriptionId = '<azure-subscription-guid>';
$resourceGroup = '<resource-group-name>';
$rbac = $true; # on k8s cluster
$aksName = '<azure-kubernetes-cluster-name>';
$aksApiUrl = '<azure-kubernetes-service-api-url>';
$agName = '<azure-application-gateway-name>';
$agId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Network/applicationGateways/$agName";
$ingressName = 'ingress-azure'; # kubernetes name for the ingress controller.
$jetstackGithubBranch = 'release-0.13';
$jetstackVersion = '0.13.1';
$emailForLetsEncrypt = '<your-email-address>';
$azureIdentityName = '<identity name>'
# Disable line below when azure identity alreacy exists.
az identity create -g "$resourceGroup" -n $azureIdentityName -o json
$azureIdentityId = az identity show --name $azureIdentityName -g $resourceGroup -o tsv --query id
$azureIdentityClientId = az identity show -g rg-vaigo -n id-vaigo-test-gateway --quer clientId -o tsv
# necessary helm templates
helm repo add application-gateway-kubernetes-ingress https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/
helm repo add jetstack https://charts.jetstack.io
helm repo update
# add k8s custom resource definitions
kubectl apply -f "https://raw.githubusercontent.com/jetstack/cert-manager/$jetstackGithubBranch/deploy/manifests/00-crds.yaml" --validate=false
if($rbac){
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment-rbac.yaml
} else {
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment.yaml
}
# give k8s access to the Azure identity:
# skipping guide (step 3-5) install aks azure identity because this is also part of ingres helm template
$aksIdentityClientId = az aks show -g $resourceGroup -n $aksName --query servicePrincipalProfile.clientId -o tsv
az role assignment create --role "Managed Identity Operator" --assignee $aksIdentityClientId --scope $azureIdentityId
# give azure gateway access to identity:
az role assignment create --role Contributor --assignee $azureIdentityClientId --scope $agId
az role assignment create --role Reader --assignee $azureIdentityClientId --scope "/subscriptions/434d7026-8d36-47e4-9684-00b120c7a3f7/resourceGroups/$resourceGroup"
$rbacString= If ($rbac) {"true"} Else {"false"}
# install ingress for azure gateway, add option: --set kubernetes.watchNamespace=default if you want to only watch single namespace
$ingressK8sConfig = helm template $ingressName application-gateway-kubernetes-ingress/ingress-azure --namespace default --debug --set appgw.name=$agName --set appgw.resourceGroup=$resourceGroup --set appgw.subscriptionId=$subscriptionId --set appgw.shared=false armAuth.type=aadPodIdentity armAuth.identityResourceID=$azureIdentityId armAuth.identityClientID=$azureIdentityClientId --set rbac.enabled=$rbacString --set verbosityLevel=3 --set aksClusterConfiguration.apiServerAddress=$aksApiUrl
$ingressK8sConfig | Out-File -FilePath .\ingress-azure.yml
# if this throws an error you can might have to replace apiVersion of the deployment to apps/v1 (remove beta notation).
kubectl apply -f .\ingress-azure.yml
# cert manager
kubectl create namespace cert-manager
# Label the cert-manager namespace to disable resource validation
kubectl label namespace cert-manager cert-manager.io/disable-validation=true
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version "v$jetstackVersion"
@"
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: isuer-letsencrypt-staging
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: $emailForLetsEncrypt
# ACME server URL for Let’s Encrypt’s staging environment.
# The staging environment will not issue trusted certificates but is
# used to ensure that the verification process is working properly
# before moving to production
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource used to store the account's private key.
name: secret-letsencrypt-staging
# Enable the HTTP-01 challenge provider
# you prove ownership of a domain by ensuring that a particular
# file is present at the domain
solvers:
- http01:
ingress:
class: azure/application-gateway
---
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: issuer-letsencrypt-prod
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: $emailForLetsEncrypt
# ACME server URL for Let’s Encrypt’s staging environment.
# The staging environment will not issue trusted certificates but is
# used to ensure that the verification process is working properly
# before moving to production
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource used to store the account's private key.
name: secret-letsencrypt-prod
# Enable the HTTP-01 challenge provider
# you prove ownership of a domain by ensuring that a particular
# file is present at the domain
solvers:
- http01:
ingress:
class: azure/application-gateway
"@ | Out-File -FilePath .\cert-manager-issuers.yml
kubectl apply -f .\cert-manager-issuers.yml
# now annotate ingress to get an ssl certificate:
# `cert-manager.io/cluster-issuer: isuer-letsencrypt-staging` for testing
# `cert-manager.io/cluster-issuer: isuer-letsencrypt-prod` for production!
$domain = 'test.yourdomain.com';
$name = 'test-yourdomain-com'
$pointToService = '<your-k8s-service-name>'; # can just be a ClusterIp service
@"
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-$name
# namespace: test you may put it in any namspace.
annotations:
kubernetes.io/ingress.class: azure/application-gateway
cert-manager.io/cluster-issuer: isuer-letsencrypt-staging
cert-manager.io/acme-challenge-type: http01
spec:
tls:
- hosts:
- $domain
secretName: secret-$name
rules:
- host: $domain
http:
paths:
- backend:
serviceName: $pointToService
servicePort: 80
"@ | Out-File -FilePath ".\$name.yml"
kubectl apply -f ".\$name.yml"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment