Deploy nginx container with self-signed certificate on RKE2 Kubernetes distribution
Introduction
Following RKE2 Kubernetes distribution installation instructions in the last post, here I will show how to run simple nginx container.
OS used: Debian 12
Software used: RKE2 1.30.2, Helm 3.16.2, cert-manager 1.16.1
Source
- Official Kubernetes documentation
- If you don't know how Kubernetes works then watch this great tutorial by TechWorld with Nana - Kubernetes Tutorial for Beginners - FULL COURSE in 4 Hours
Running simple container
To run nginx container few Kubernetes files need to be created. Order in which Kubernetes elements are created is important (for example Persistent Volume Claim must be created before Deployment). Following files will be created with Kubernetes objects listed in each file:
01_nginx-test-namespace.yml- Namespace
02_self-signed-cert.yml- Issuer for self-signed certificate
03_nginx-test-volume.yml- Persistent Volume
- Persistent Volume Claim
04_nginx-test-deployment.yml- Deployment
- Service
- Ingress
Creating namespace
First create folder in which you will put your Kubernetes files:
$ mkdir -m 700 ~/test-stack
Next prepare file with new namespace which will be used for grouping Kubernetes elements:
$ vim ~/test-stack/01_nginx-test-namespace.yml
apiVersion: v1
kind: Namespace
metadata:
name: test-space
Installing Helm and cert-manager
For accessing webpage using HTTPS you need SSL certificate. This example will use self-signed certificate and to automate this process cert-manager will be used.
Install cert-mananger using Helm package manager for Kubernetes with following commands (commands taken from Official Helm documentation and Official cert-manager documentation):
- 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 && \
rm ./get_helm.sh
- Install
cert-manager:
$ helm repo add jetstack https://charts.jetstack.io --force-update
$ helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.1 \
--set crds.enabled=true
Enable autocompletion for helm
To enable helm bash autocompletion for user (when using Tab key) run command to add entry to your .bashrc:
$ echo -e "\n# helm completion bash" >> ~/.bashrc && \
echo 'source <(helm completion bash)' >>~/.bashrc
echo -e - enable interpretation of backslash escapes
Login again or run following command to enable bash autocompletion in current session:
$ source ~/.bashrc
Creating Issuer for self-signed certificate
Create file to issue self-signed certificate.
$ vim ~/test-stack/02_self-signed-cert.yml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: test-space
spec:
selfSigned: {}
Note
cert-manager Issuer can be type Issuer or ClusterIssuer. Here is description from the official documentation:
An
Issueris a namespaced resource, and it is not possible to issue certificates from an Issuer in a different namespace. This means you will need to create an Issuer in each namespace you wish to obtain Certificates in.If you want to create a single Issuer that can be consumed in multiple namespaces, you should consider creating a
ClusterIssuerresource. This is almost identical to the Issuer resource, however is non-namespaced so it can be used to issue Certificates across all namespaces.
Creating Kubernetes Volume
Create folder for data available to container:
html- folder with web page
$ sudo mkdir -p /mnt/nginx-test/html
Create volume configuration file:
$ vim ~/test-stack/03_nginx-test-volume.yml
apiVersion: storage.k8s.io/v1
kind: storageClass
metadata:
name: nginx-test-storage
namespace: test-space
provisioner: kubernetes.io/no-provisioner # storageClass setting for local storage
volumeBindingMode: WaitForFirstConsumer # storageClass setting for local storage
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-test-html-pv
namespace: test-space
spec:
capacity:
storage: 1Gi # for local storage it's just a label and don't cap space available for container
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: nginx-test-storage
local:
path: /mnt/nginx-test/html # path on your server
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- yourhostname # host name of your server
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-test-html-pvc
namespace: test-space
spec:
accessModes:
- ReadWriteOnce
storageClassName: nginx-test-storage
resources:
requests:
storage: 1Gi # for local storage it's just a label and don't cap space available for container
Creating Kubernetes Deployment
$ vim ~/test-stack/04_nginx-test-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test-deployment
namespace: test-space
labels:
app: nginx-test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx-test-deployment
template:
metadata:
labels:
app: nginx-test-deployment
spec:
containers:
- name: nginx
image: nginx:1.27.2 # image you want to use
ports:
- containerPort: 80
volumeMounts: # VolumeMounts are the paths that your application uses inside container
- name: nginx-test-html-volume
mountPath: /usr/share/nginx/html # the path that your application uses inside container
volumes:
- name: nginx-test-html-volume
persistentVolumeClaim:
claimName: nginx-test-html-pvc # should match name of the PersistentVolumeClaim
---
apiVersion: v1
kind: Service
metadata:
name: nginx-test-service
namespace: test-space
spec:
selector:
app: nginx-test-deployment
ports:
- name: http
port: 80
targetPort: 80 # should match containerPort in Deployment
protocol: TCP # protocol that will be used
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test-ingress
namespace: test-space
annotations:
cert-manager.io/cluster-issuer: "issuer" # should match name of issuer
spec:
tls:
- hosts:
- myservername.example.com # replace with your domain
secretName: nginx-test-self-signed-tls # this is the name of certificate that will be created
rules:
- host: myservername.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-test-service # reference to created Service
port:
number: 80 # Service port number
Info
- If using an
Issuerupdate the Ingress annotation tocert-manager.io/issuer. - If using a
ClusterIssuerupdate the Ingress annotation tocert-manager.io/cluster-issuer.
Adding address to local DNS
Add address that you put in Ingress to your local DNS server, for example:
DNS A record: myservername.example.com | IPv4 address: 192.168.1.46.
Running Kubernetes Deployment
It's important to create Kubernetes elements in a specific order, that is why files are numbered and should be run in sequence:
$ kubectl apply -f ~/test-stack/01_nginx-test-namespace.yml && \
kubectl apply -f ~/test-stack/02_self-signed-cert.yml && \
kubectl apply -f ~/test-stack/03_nginx-test-volume.yml && \
kubectl apply -f ~/test-stack/04_nginx-test-deployment.yml
Serving your own webpage with nginx
Create your simple webpage:
$ sudo vim /mnt/nginx-test/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>My Simple Website</h1>
<p>Simple website.</p>
</body>
</html>
Enter the address of your service into web browser: https://myservername.example.com. You should see a warning message about HTTPS because you are using self-signed certificate and after you accept it your webpage should be shown.
Appendix
Upgrade helm
To upgrade helm to new version just perform install operation. Helm is a single binary file and this will replace it to new version:
$ 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 && \
rm ./get_helm.sh
Upgrade cert-manager
Use following command to upgrade cert-manager:
$ helm repo update && \
helm upgrade --reset-then-reuse-values --namespace cert-manager --version <version> cert-manager jetstack/cert-manager
<version> - enter new version of cert-manager