On this page

Overview

This guide walks you through the complete process of securing your Kubernetes Ingress using cert-manager with GlobalSign’s Atlas-ACME server and the HTTP-01 challenge type. At the completion of this article, you'll learn how to: 

  • Set up a Kubernetes cluster with Kops and AWS 
  • Install and configure cert-manager 
  • Set up NGINX Ingress Controller 
  • Configure GlobalSign ACME Issuer and Certificate 
  • Secure an Ingress resource with a trusted TLS certificate 

What is Ingress?

Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

Here is a simple example where an Ingress sends all its traffic to one service:                 

cert-manager-http-1                                


Prerequisites

Ensure the following tools are installed and configured on your system: 

Install Unzip

sudo apt install unzip

Install AWS CLI

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install

Install Helm

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

There are few policies required to run the cluster successfully which should be assigned to a user and a role for the cluster:

IAM URL: https://console.aws.amazon.com/iamv2/home#/home

Create a user for k8s cluster and assign the below policies:

  1. Go to Users
  2. Add users
  3. Give a name to user
  4. Select Access key - Programmatic access
  5. Permissions
  6. Select Attach existing policies directly and select the below policies for this user.

              a.) VPC full access

              b.) EC2 full access

              c.) S3 full access

              d.) Route53 full access

              e.) IAM full access

Create a role for k8s cluster and assign the below policies:

  1. Go to IAM dashboard https://console.aws.amazon.com/iamv2/home#/home
  2. Roles
  3. Create role
  4. Form common use case select EC2 and go to next screen for permissions
  5. Select the below permissions for this user

              a.) VPC full access

              b.) EC2 full access

              c.) S3 full access

              d.) Route53 full access

              e.) IAM full access

Launch an Ec2-Instance and assign this role to the instance.

Install kubectl

# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s
https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

#make the downloaded file executable
chmod +x kubectl
#Move the executable to the /usr/local/bin
sudo mv kubectl /usr/local/bin 

Install kops

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' - f 4)/kops-linux-amd64
#Make the binary executable
chmod +x kops-linux-amd64
#Move the executable to /usr/local/bin
sudo mv kops-linux-amd64 /usr/local/bin/kops 

In order to work further need to login with the above created programmatic user:

aws configure

#enter the Access key ID and Secret access key.

#Provide the region details i.e., us-east-1 or any other

#Give output format as "json".

#Create a S3 bucket through S3 bucket console: https://s3.console.aws.amazon.com/s3/home?region=us-east-1

#Create a private hosted zone from Route53 console: https://console.aws.amazon.com/route53/v2/home#Dashboard

#Generate public and private keys

ssh-keygen


Set Up Kubernetes Cluster 

export KOPS_STATE_STORE="s3://your-s3-bucket-name"
export MASTER_SIZE=${MASTER_SIZE:-m4.large}
export NODE_SIZE=${NODE_SIZE:-m4.large}
export ZONES="us-east-1a,us-east-1b,us-east-1c"

kops create cluster pki.atlasqa.co.uk --node-count 3 --zones $ZONES --node-size $NODE_SIZE --master-size $MASTER_SIZE --master-zones $ZONES --dns public --dns-zone pki.atlasqa.co.uk --cloud aws 

#It will describe everything that it will create within the cluster. In next step kops will update the cluster and resources would be created.

kops update cluster --name pki.atlasqa.co.uk --yes --admin 

#It will take around 20min to get all the resources ready within the cluster.
#Check the cluster status after 20min with below command

kops validate cluster --name pki.atlasqa.co.uk 

cert-manager-http-2.png

The cluster is setup, there are 3 node machines running in us-east-1 region and 3 master running in us-east-1 as per the availability zones.

Install cert-manager 

kubectl create namespace cert-manager
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.7.1/cert-manager.yaml
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --version v1.7.1 -n cert-manager 

Install Ingress Controller 

Install Nginx-ingress-controller in namespace cert-manager and create A record to your DNS Zone

helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace cert-manager 

Add the following to the cluster under spec of conf file to create nginx-ingress resource as the elastic load balancer.

kops edit cluster

cluster-config


spec:

  additionalPolicies:

    master: |

      [

        {

          "Effect": "Allow",

          "Action": "iam:CreateServiceLinkedRole",

          "Resource": "arn:aws:iam::*:role/aws-service-role/*"

         },

         {

           "Effect": "Allow",

           "Action": [

             "ec2:DescribeAccountAttributes",

             "ec2:DescribeInternetGateways"

            ],

           "Resource": "*"

         }

      ]

 

After adding above configuration update the cluster:

kops update cluster --name ClusterName --yes

Add an A record to your DNS zone

kubectl get svc -n cert-manager

cert-manager-http-3.png


Configure GlobalSign Atlas-ACME Issuer 

Step 1: Set Up account binding key as a secret within Kubernetes

kubectl create secret generic eab-secret --from-literal secret=HMAC_key -n cert-manager

Step 2: Set up the GlobalSign as issuer/ClusterIssuer 

kubectl apply -f issuer.yml -n cert-manager

issuer.yml


apiVersion: cert-manager.io/v1 
kind: Issuer 
metadata: 
  name: eab-issuer 
  namespace: cert-manager 
spec: 
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: eab-issuer
  namespace: cert-manager
spec:
  acme:
    email: user@example.com
    server: https://******/directory
    externalAccountBinding:
      keyID: **************
      keySecretRef:
        name: eab-secret
        key: secret
      keyAlgorithm: HS256
    privateKeySecretRef:
      name: acme-account-secret-issuer
    solvers:
    - http01:
        ingress:
          class: nginx

cert-manager-http-4.png

Step 3. Create certificate resource

kubectl apply -f cert.yml -n cert-manager

cert.yml


apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: eab-cert
  namespace: cert-manager
spec:
  secretName: acme-account-secret
  duration: 2160h
  renewBefore: 360h

  commonName: pki.atlasqa.co.uk

  dnsNames:

  - pki.atlasqa.co.uk

  issuerRef:

    name: eab-issuer

 

Step 4. Securing ingress resource

ingress.yml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  annotations:

    cert-manager.io/issuer: eab-issuer

    kubernetes.io/ingress.class: nginx

    cert-manager.io/acme-challenge-type: http01

  name: nginx

  namespace: cert-manager

spec:

  rules:

  - host: pki.atlasqa.co.uk

    http:

      paths:

      - pathType: Prefix

        path: /

        backend:

          service:

            name: nginx

            port:

              number: 80

  tls:

  - hosts:

    - pki.atlasqa.co.uk

    secretName: hvca-cert-secret