Deploying Nginx on Kubernetes: Exploring Various Methods
Mastering Nginx Deployment in Kubernetes: A Comprehensive Guide to Pods, Deployments, and Beyond
Explore the essential steps and best practices for deploying the popular web server, Nginx, on Kubernetes. This quick guide provides a straightforward walkthrough, offering insights into setting up Nginx within a Kubernetes environment. Whether you’re a Kubernetes beginner or looking for a fast deployment solution, this guide simplifies the process, ensuring you have Nginx up and running in no time.
In Kubernetes, there are different resources you can use to deploy and manage applications. Here are several ways to deploy an Nginx pod using various Kubernetes resources:
- Pod
- Replication Cotroller
- Replicaset
- Deployment
- Statefulset
- Daemonset
- Helm
Prerequisites:
- Kubernetes environment
- Kubectl CLI installed
- Helm CLI installed
1. Pod
The fundamental unit in Kubernetes. Dive into the basics with this quick guide on deploying Nginx as a Pod. While Pods might not be the go-to choice for production, understanding this fundamental unit is crucial for Kubernetes mastery.
In Kubernetes, you can deploy an Nginx pod using both imperative and declarative approaches. Let’s go through both methods:
a. Imperative Way:
Imperative commands are those where you directly instruct Kubernetes to perform a specific action.
Using kubectl run:
kubectl run nginx-pod --image=nginx --restart=Never --port=80 -n default
This command creates a pod named nginx-pod
in default
namespace using the Nginx Docker image. The --restart=Never
flag indicates that it's a one-time job and won't be restarted automatically if it fails or stops.
Verify the Pod is Running using below command:
kubectl get pods
This will show you the status of your pods.
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 3s
Now pod is up and running let’s create a service to access application externally
Using kubectl run:
kubectl expose pod nginx-pod --type=NodePort --port=80 --name=nginx-service
This command exposes the Nginx pod using a NodePort service, making it accessible externally on a specific port.
Verify the service is created using below command:
kubectl get svc
This will show you the service that is created for nginx
k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h31m
nginx-service NodePort 10.109.112.35 <none> 80:30684/TCP 104s
Now, let’s attempt to reach the Nginx application through the browser. I’m utilizing the following commands since I’m using Minikube for my Kubernetes cluster.
minikube service nginx-service --url
http://127.0.0.1:49867
❗ Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
Accessing the Nginx application is possible by visiting the provided URL, which is localhost:49867.
b. Declarative Way:
Declarative configuration involves creating a YAML file that describes the desired state of the resource.
In the world of YAML manifests, the simplicity of defining a Pod is evident:
Create a YAML file for nginx pod (nginx-pod.yaml):
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
Apply the YAML file using below command:
kubectl apply -f nginx-pod.yaml -n default
This command tells Kubernetes to create or update the resource described in the YAML file. Which means it will create a nginx pod in default namespace
Verify the Pod is Running using below command:
kubectl get pods
This will show you the status of your pods.
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 3s
Now pod is up and running let’s create a service to access application externally
Create a YAML file for nginx service (nginx-service.yaml):
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Apply the YAML file using below command:
kubectl apply -f nginx-service.yaml -n default
This will create a nginx-svc in default namespace.
Verify the service is created using below command:
kubectl get svc
This will show you the service that is created for nginx
k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h47m
nginx-svc NodePort 10.103.151.51 <none> 80:32382/TCP 11s
Now we can access nginx application externally same as above.
Both approaches achieve the same result, but the declarative method is preferred for many reasons, including better version control, ease of automation, and better collaboration within a team.
Cleanup
Imperative Cleanup:
# Delete the service
kubectl delete service nginx-service
# Delete the pod
kubectl delete pod nginx-pod
Declarative Cleanup:
# Delete the service using the YAML file
kubectl delete -f nginx-service.yaml
# Delete the pod using the YAML file
kubectl delete -f nginx-pod.yaml
These commands will remove the Service and Pod that you created for Nginx. After running these commands, you can verify that the resources have been deleted by checking the status:
# Verify that the service is deleted
kubectl get services
# Verify that the pod is deleted
kubectl get pods
Make sure that there are no remaining resources related to Nginx in your Kubernetes cluster.
2. ReplicationController (Deprecated):
A ReplicationController ensures that a specified number of pod replicas are running at any one time. In other words, a ReplicationController makes sure that a pod or a homogeneous set of pods is always up and available.
Let’s explore the step-by-step process of deploying Nginx using a ReplicationController and ensuring accessibility through a Service.
Create a YAML file for nginx ReplicationController (nginx-ReplicationController.yaml):
In your YAML manifest, define the ReplicationController. This example ensures two replicas of the Nginx container:
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-replication-controller
labels:
app: nginx
spec:
replicas: 2
selector:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
This ReplicationController ensures the desired number of replicas (in this case, 2) and selects Pods based on the specified label (app: nginx
).
Apply the YAML file using below command:
kubectl apply -f nginx-ReplicationController.yaml -n default
Verify the Pod is Running using below command:
kubectl get pods
This will show you the status of your pods.
k get pods
NAME READY STATUS RESTARTS AGE
nginx-replication-controller-fw7jw 1/1 Running 0 11m
nginx-replication-controller-xgbcg 1/1 Running 0 11m
Expose Nginx with a Service:
Now, let’s create a Service to expose the Nginx replicas (nginx-svc.yaml) :
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Apply the YAML file using below command:
kubectl apply -f nginx-service.yaml -n default
This will create a nginx-svc in default namespace.
Verify the service is created using below command:
kubectl get svc
Now we can access nginx application externally same as above.
3. ReplicaSet:
ReplicaSets are a more powerful and flexible replacement for ReplicationControllers. They provide additional features like selector options and rolling updates.
In your YAML manifest, define the ReplicaSet. This example ensures two replicas of the Nginx container and provides selector options for future updates:
Create nginxReplicaSet.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
Create nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply above yaml files using below command
kubectl apply -f nginx-replicaset.yaml
kubectl apply -f nginx-svc.yaml
Check the running pods and services using below command
kubectl get all
Output
k get all
NAME READY STATUS RESTARTS AGE
pod/nginx-replicaset-b2jfm 1/1 Running 0 2m12s
pod/nginx-replicaset-qhjnn 1/1 Running 0 2m12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h38m
service/nginx-svc NodePort 10.99.173.144 <none> 80:31669/TCP 92s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-replicaset 2 2 2 2m12s
Now nginx is up and running, we can access nginx application externally same as above(step 1).
4. Deployment
When it comes to deploying applications on Kubernetes, Deployments are the go-to resource for many reasons. Deployments are a higher-level abstraction that includes ReplicaSets. They provide features like rolling updates, rollback, and scaling.
Create nginx-deploy.yaml
In your YAML manifest, define the Deployment. This example ensures two replicas of the Nginx container and sets up labels for easy management:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
Create nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply above yaml files using below command
kubectl apply -f nginx-deploy.yaml
kubectl apply -f nginx-svc.yaml
Check the running pods and services using below command in default namespace
kubectl get all
Output
k get all
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-86dcbffdfb-gkmx4 1/1 Running 0 2m44s
pod/nginx-deployment-86dcbffdfb-n5mlf 1/1 Running 0 2m44s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
service/nginx-svc NodePort 10.98.167.30 <none> 80:30135/TCP 2m44s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 2/2 2 2 2m44s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-86dcbffdfb 2 2 2 2m44s
You’ve successfully deployed Nginx on Kubernetes using a Deployment and exposed it with a Service. Take advantage of rolling updates and effortless scaling provided by the Deployment resource, elevating your Kubernetes deployment strategy.
This knowledge equips you with advanced tools for managing your Nginx instances in a dynamic and scalable manner.
Now nginx is up and running, we can access nginx application externally same as above(step 1).
5. Statefulset
Like a Deployment, a StatefulSet manages Pods that are based on an identical container spec. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of its Pods. These pods are created from the same spec, but are not interchangeable: each has a persistent identifier that it maintains across any rescheduling.
For stateful applications or those requiring stable network identifiers and persistent storage, StatefulSets are the ideal choice.
Create nginx-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-sts
labels:
app: nginx
spec:
replicas: 2
serviceName: nginx
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
This StatefulSet
ensures two replicas and sets up a stable network identifier for each pod, crucial for stateful applications.
The serviceName
in a StatefulSet is used to create a headless service that can be used to discover and communicate with individual pods managed by the StatefulSet. The serviceName
specifies the name of the service that is responsible for the network identity of the pods.
Create nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply above yaml files using below command
kubectl apply -f nginx-sts.yaml
kubectl apply -f nginx-svc.yaml
Check the running pods and services using below command in default namespace
kubectl get all
Output
k get all
NAME READY STATUS RESTARTS AGE
pod/nginx-sts-0 1/1 Running 0 4s
pod/nginx-sts-1 1/1 Running 0 2s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
service/nginx-svc NodePort 10.96.188.107 <none> 80:32599/TCP 4s
NAME READY AGE
statefulset.apps/nginx-sts 2/2 4s
Now nginx is up and running, we can access nginx application externally same as above(step 1).
6. Daemonset
DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them. As nodes are removed from the cluster, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created.
Some typical uses of a DaemonSet are:
- running a cluster storage daemon on every node
- running a logs collection daemon on every node
- running a node monitoring daemon on every node
Let’s create nginx-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
This DaemonSet ensures one replica on each node, maintaining a copy of the pod across your entire cluster.
Create nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply above yaml files using below command
kubectl apply -f nginx-daemonset.yaml
kubectl apply -f nginx-svc.yaml
Check the running pods and services using below command in default namespace
kubectl get all -l app=nginx
Output
kubectl get all -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-daemonset-j9nvr 1/1 Running 0 5m53s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nginx-daemonset 1 1 1 1 1 <none> 5m53s
Now nginx is up and running, we can access nginx application externally same as above(step 1).
7. Helm
For streamlined and repeatable Kubernetes deployments, Helm Charts provide a powerful packaging format. Let’s walk through the detailed steps of deploying Nginx using Helm, a package manager for Kubernetes applications.
Helm is a Kubernetes package manager that simplifies deploying and managing applications. It uses charts — packages of pre-configured Kubernetes resources — to define, install, and upgrade even the most complex Kubernetes applications.
Before you begin, ensure you have Helm installed on your local machine. You can install Helm by following the instructions here.
Create a Helm Chart for Nginx using below command.
helm create nginx-chart
Helm will create a new directory in your project called nginx-chart
with the structure shown below.
mychart
|-- Chart.yaml
|-- charts
|-- templates
| |-- NOTES.txt
| |-- _helpers.tpl
| |-- deployment.yaml
| |-- ingress.yaml
| `-- service.yaml
`-- values.yaml
Here remove all files under templates/ and update with the below files.
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
{{- include "nginx-chart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "nginx-chart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "nginx-chart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default "latest" }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-svc
labels:
{{- include "nginx-chart.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "nginx-chart.selectorLabels" . | nindent 4 }}
_helper.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "nginx-chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "nginx-chart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "nginx-chart.labels" -}}
helm.sh/chart: {{ include "nginx-chart.chart" . }}
{{ include "nginx-chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "nginx-chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nginx-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app: {{ .Release.Name }}
{{- end }}
NOTES.txt
1. Get the application URL by running this commands:
minikube service {{ .Release.Name }}-svc --url
Now override the values.yaml file with below content:
# Default values for nginx-chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
service:
type: NodePort
port: 80
Now helm chart is ready to deploy, use below command to install the chart in default namespace.
helm install <release-name> <chart-name> -n <namespace>
In our case
helm install nginx nginx-chart -n default
This will give the below output:
helm install nginx nginx-chart
NAME: nginx
LAST DEPLOYED: Fri Jan 12 18:20:16 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running this commands:
minikube service nginx-svc --url
Now helm chart is installed, let’s verify the newly created pods and service using below command:
k get all -l app=nginx
Output:
k get all -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-5598bb99d7-8krw4 1/1 Running 0 95s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-svc NodePort 10.96.185.42 <none> 80:31026/TCP 95s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 95s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-5598bb99d7 1 1 1 95s
Now nginx is up and running, we can access nginx application externally same as above(step 1).
Cleanup:
Use below command to uninstall helm chart so that it will delete all dependent resources i.e., service and deployment.
helm uninstall <release-name>
In our case:
helm uninstall nginx
References
If you found this blog insightful and would like to discuss AWS, cloud strategies, Kubernetes, or any related topics further, I’d love to connect with you on LinkedIn.
Feel free to reach out, share your thoughts, or ask any questions. Let’s grow and learn together in the vast world of cloud computing!
Happy deploying! 🚀
Happy Kubernetings! 🚀
Tidak ada komentar:
Posting Komentar