- Kubernetes
- Docker
- DockerHub
- NodeJS
- MySQL
- AWS Cloud
Launch a Kubernetes cluster. I am using AWS EKS. Please be aware it's a paid service.
-
Clone this official hashicorp repository with terraform templates:
git clone https://github.com/hashicorp/learn-terraform-provision-eks-cluster
This example repository contains configuration to provision a VPC, security groups, and an EKS cluster with the following architecture:
-
Launch the terraform templates to create infrastructure and a Kubernetes cluster on AWS EKS.
terraform init terraform validate terraform apply
If you use AWS Cloud9 as an IDE you also have to disallow AWS Managed Temporary Credentials. Go to Cloud9 > Preferences > AWS Settings > AWS Managed Temporary Credentials and turn it off. Store your permanent AWS access credentials in the environment. Use
aws configure
command.
-
Launch a new EC2 instance or use the current Cloud9 instance. Here is the example of AWS CLI command to launch a t3.small EC2 instance:
aws ec2 run-instances --image-id ami-xxxxxxxx --count 1 --instance-type t3.small --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e
-
Configure it as a master node to work with a cluster named
education-eks-hCIH6McB
:aws eks update-kubeconfig --name education-eks-hCIH6McB
-
Install
kubectl
curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.27.1/2023-04-19/bin/linux/amd64/kubectl chmod +x ./kubectl mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc kubectl version --short --client
-
Make sure the master node can access the cluster
kubectl get svc
- For the deployment I will be pulling images from DockerHub which I created in the preceding project located here: https://github.com/otammato/FullStack_NodeJS_MySql_Docker.git
- Create a Kubernetes manifest and save it as
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: node-app
image: montcarotte/fullstack_nodejs_mysql_demo:node_app
ports:
- containerPort: 3000
env:
- name: APP_DB_HOST
value: mysql-service
- name: APP_DB_USER
value: "admin"
- name: mysql-server
image: montcarotte/fullstack_nodejs_mysql_demo:mysql_server_new
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "12345678" # the standard security practice for Kubernetes is to manage passwords through a separate secrets.yaml file. For the simplicity and demo purposes I am not doing it here.
---
apiVersion: v1
kind: Service
metadata:
name: node-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 3306
targetPort: 3306
This is a Kubernetes manifest file written in YAML. It defines a Deployment, two Services, and their associated configurations.
The Deployment named "my-deployment" specifies the desired state for running two replicas of a containerized application. It uses a selector to match the pods with the label "app: my-app." The template section defines the pod template for the Deployment. Inside the template, there are two containers defined. The first container is named "node-app" and uses the image "montcarotte/fullstack_nodejs_mysql_demo:node_app." It exposes port 3000 and sets environment variables for the application's database host and user. The second container is named "mysql-server" and uses the image "montcarotte/fullstack_nodejs_mysql_demo:mysql_server_new." It exposes port 3306 and sets the root password for the MySQL server.
Please note that this manifest file provides a simplified example, and in a real-world scenario, it is recommended to use secrets or other secure methods to manage sensitive information like passwords.
Following the Deployment, there are two Service definitions. The first one is named "node-app-service" and exposes port 80. It selects the pods with the label "app: my-app" and forwards traffic to port 3000 of those pods. The type of this Service is LoadBalancer, indicating that it will be externally accessible through a load balancer.
The second Service is named "mysql-service" and exposes port 3306. It also selects the pods with the label "app: my-app" and forwards traffic to port 3306 of those pods. This Service allows communication with the MySQL server container.
The manifest involves environment variables as the Node.js script suggests using ether the default variables or the provided ones for connecting to the database.
kubectl apply -f deployment.yaml
- Retrieve the information about all the Kubernetes resources in the cluster and note the LoadBalancer's external address
kubectl get all
- Insert the DNS address into a web browser
Check the container status:
kubectl get pods
To get the logs of a pod named "my-pod" in a specific namespace named "my-namespace":
kubectl logs <mysql-pod-name> -n <my-namespace-name>
If the pod has multiple containers, you can specify the container name using the -c flag.
kubectl logs <mysql-pod-name> -c mysql-server
Check connectivity: Validate the connectivity to the MySQL server from within the cluster. You can create a temporary pod to access the MySQL server container and test the connection.
kubectl run -it --rm --image=mysql:latest mysql-client -- mysql -h <mysql-service-name> -u root -p
To open an interactive shell (such as bash) inside a container,
kubectl exec -it my-pod -c my-container -- /bin/bash