Friday, May 1, 2020

Automated deployment of ELK stack and Nginx on AWS ec2 using Terraform and Ansible in 1 hour

Summary:


This post will walk through steps about Automated deployment of ELK stack and Nginx on AWS ec2 instance using Terraform and Ansible in 1 hour.




Environment:

  • AWS ec2 instance

ELK Stack
  •     Elasticsearch master node - 1
  •     Elasticsearch data node - 2
  •     Nginx web server - 1

Jump host with Vagrant Centos 7 running on laptop


Prerequisites:
  • Install Ansible, Terraform, and git on jump host

# ansible --version
ansible 2.9.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]


# terraform version
Terraform v0.12.20



Download the Terraform IaC and Ansible playbook from git repository 

# git clone https://github.com/vdsridevops/aws-elk.git



# tree
.
├── ansible-playbook
│   ├── elk_post_setup.yml
│   ├── elk_setup.yml
│   ├── group_vars
│   │   └── env_variables
│   ├── hosts
│   ├── nginx.yml
│   ├── roles
│   │   ├── elasticsearch
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── elasticsearch-data
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   ├── elasticsearchConf.j2
│   │   │   │   ├── filebeatConf.j2
│   │   │   │   ├── filebeat-elasticsearchConf.j2
│   │   │   │   └── metricbeatConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── elasticsearch-master
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   ├── elasticsearchConf.j2
│   │   │   │   ├── filebeatConf.j2
│   │   │   │   ├── filebeat-elasticsearchConf.j2
│   │   │   │   ├── filebeat-kibanaConf.j2
│   │   │   │   ├── filebeat-logstashConf.j2
│   │   │   │   └── metricbeatConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── elk-post
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── elk-pre
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── java
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   ├── main.yml
│   │   │   │   └── main.yml.backup
│   │   │   ├── templates
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── kibana
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   └── kibanaConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── kibana-proxy
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   └── kibanaproxyConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── logstash
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   └── logstash-nginxConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── nginx
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   ├── nginx-filebeat
│   │   │   ├── defaults
│   │   │   │   └── main.yml
│   │   │   ├── files
│   │   │   ├── handlers
│   │   │   │   └── main.yml
│   │   │   ├── meta
│   │   │   │   └── main.yml
│   │   │   ├── README.md
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   ├── templates
│   │   │   │   ├── filebeatConf.j2
│   │   │   │   └── nginxConf.j2
│   │   │   ├── tests
│   │   │   │   ├── inventory
│   │   │   │   └── test.yml
│   │   │   └── vars
│   │   │       └── main.yml
│   │   └── nginx-metricbeat
│   │       ├── defaults
│   │       │   └── main.yml
│   │       ├── files
│   │       ├── handlers
│   │       │   └── main.yml
│   │       ├── meta
│   │       │   └── main.yml
│   │       ├── README.md
│   │       ├── tasks
│   │       │   └── main.yml
│   │       ├── templates
│   │       │   └── metricbeatConf.j2
│   │       ├── tests
│   │       │   ├── inventory
│   │       │   └── test.yml
│   │       └── vars
│   │           └── main.yml
│   └── terraform.tfstate
├── ec2_private_ip
├── ec2_public_ip
├── main.tf
├── modules
│   ├── elk-data-compute
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── userdata.tpl
│   │   └── variables.tf
│   ├── elk-master-compute
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── userdata.tpl
│   │   └── variables.tf
│   ├── networking
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   └── nginx-compute
│       ├── main.tf
│       ├── main.tf.backup
│       ├── outputs.tf
│       ├── userdata.tpl
│       └── variables.tf
├── outputs.tf
├── README.md
├── terraform.tfvars
├── variables.tf
└── versions.tf



Terraform Modules used:

elk-master-compute
elk-data-compute
networking  
nginx-compute


Ansible playbook used:

elk_setup.yml
elk_post_setup.yml
nginx.yml


Ansible roles used:

java 
elk-pre  
elasticsearch
elasticsearch-master
elasticsearch-data 
kibana        
logstash  
nginx-filebeat
kibana-proxy  
nginx     
nginx-metricbeat
elk-post  


Automated deployment using Terraform:

# terraform init

# terraform plan

# terraform apply


Verification:

# terraform apply
module.nginx-compute.data.template_file.userdata[0]: Refreshing state...
module.elk-data-compute.data.template_file.userdata[0]: Refreshing state...
module.elk-master-compute.data.template_file.userdata[0]: Refreshing state...
module.elk-data-compute.data.template_file.userdata[1]: Refreshing state...
module.nginx-compute.data.aws_ami.server_ami: Refreshing state...
module.elk-data-compute.data.aws_ami.server_ami: Refreshing state...
module.elk-master-compute.data.aws_ami.server_ami: Refreshing state...
.
.
.
.
.
null_resource.ansible-play (local-exec): TASK [elk-post : Restart metricbeat.service] ***********************************
null_resource.ansible-play: Still creating... [48m10s elapsed]
null_resource.ansible-play: Still creating... [48m20s elapsed]
null_resource.ansible-play (local-exec): changed: [34.237.139.245]

null_resource.ansible-play (local-exec): PLAY RECAP *********************************************************************
null_resource.ansible-play (local-exec): 34.237.139.245             : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

null_resource.ansible-play: Creation complete after 48m28s [id=6441365952312601129]

Apply complete! Resources: 15 added, 0 changed, 0 destroyed.

Outputs:

ELK_Data_Private_Instance_IPs = 10.123.1.111, 10.123.1.214
ELK_Data_Public_Instance_IDs = i-0ebd111d7e15307ba, i-00362d9b29fc9014a
ELK_Data_Public_Instance_IPs = 3.231.153.252, 34.205.45.150
ELK_Master_Private_Instance_IPs = 10.123.1.188
ELK_Master_Public_Instance_IDs = i-09fbf1695c39c7b18
ELK_Master_Public_Instance_IPs = 34.237.139.245
Nginx_Private_Instance_IPs = 10.123.1.168
Nginx_Public_Instance_IDs = i-03d72aff55185e704
Nginx_Public_Instance_IPs = 34.205.26.55
Public_Security_Group = sg-087dda768288d485d
Public_Subnets = subnet-07c90e18bce73ebec
Subnet_IPs = 10.123.1.0/24



Kibana UI:







Monday, February 10, 2020

Automated deployment of HDFS cluster, Kubernetes cluster, and Google Compute Engine instance using Terraform and Ansible in 20 minutes

Summary:

This post will walk through steps about Automated deployment of HDFS cluster, Kubernetes cluster, and Google Compute Engine instance's using Terraform and Ansible in 20 minutes.


Environment:
  • Google compute engine (not GKE)
  • Hadoop HDFS cluster running on Kubernetes cluster
  •     Zoo keeper - 3
  •     Name node - 2
  •     Data node - 3
  •     Journal node - 3
  • Kubernetes cluster running on GCE
  •     Master node -1
  •     Worker node - 3
  • Jump host with Vagrant Centos 7 running on laptop




Prerequisites:

  • Install Ansible, Terraform, and git on jump host

# ansible --version
ansible 2.9.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]


# terraform version
Terraform v0.12.20



  • Download the Terraform IaC and Ansible playbook from git repository 
 https://github.com/vdsridevops/terraform-k8s-gce-hdfs.git

# git clone https://github.com/vdsridevops/terraform-k8s-gce-hdfs.git
Cloning into 'terraform-k8s-gce-hdfs'...
remote: Enumerating objects: 56, done.
remote: Counting objects: 100% (56/56), done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 56 (delta 6), reused 56 (delta 6), pack-reused 0
Unpacking objects: 100% (56/56), done.



Directory structure:

# tree
.
├── ansible_hosts
├── ansible_playbook
│   ├── ansible_hosts
│   ├── group_vars
│   │   └── env_variables
│   ├── hosts
│   │   ├── playbooks
│   │   ├── configure_hdfs_nodes.yml
│   │   ├── configure_master_node.yml
│   │   ├── configure_worker_nodes.yml
│   │   ├── post_configure_k8s_cluster.yml
│   │   ├── pre_configure_hdfs_nodes.yml
│   │   ├── prerequisites.yml
│   │   └── setting_up_nodes.yml
│   ├── post_configure_nodes.yml
│   ├── setup_hdfs_nodes.yml
│   ├── setup_master_node.yml
│   ├── setup_worker_nodes.yml
│   └── storageclass.yaml
├── clean.sh
├── main.tf
├── modules
│   ├── gce-hdfs-disk
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── gce-k8s-master
│   │   ├── main.tf
│   │   └── variables.tf
│   └── gce-k8s-worker
│       ├── main.tf
│       └── variables.tf
├── README.md
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf

7 directories, 30 files



  • Change the variable.tf according to your environment on Terraform root and modules.

  • Change environment variable file on ansible playbook according to your environment.

Terraform plan graph:





Left side continuation

 

Right side continuation



Terraform Modules used:

gce-hdfs-disk

gce-hdfs-disk module for to create  presistent disk on google cloud engine for to use it on Hadoop HDFS cluster

# gcloud compute disks list
NAME                    LOCATION    LOCATION_SCOPE  SIZE_GB  TYPE         STATUS
hdfs-journalnode-k8s-0  us-west1-a  zone            20       pd-standard  READY
hdfs-journalnode-k8s-1  us-west1-a  zone            20       pd-standard  READY
hdfs-journalnode-k8s-2  us-west1-a  zone            20       pd-standard  READY
hdfs-krb5-k8s           us-west1-a  zone            20       pd-standard  READY
hdfs-namenode-k8s-0     us-west1-a  zone            100      pd-standard  READY
hdfs-namenode-k8s-1     us-west1-a  zone            100      pd-standard  READY
kubernetes-master       us-west1-a  zone            10       pd-standard  READY
kubernetes-worker1      us-west1-a  zone            10       pd-standard  READY
kubernetes-worker2      us-west1-a  zone            10       pd-standard  READY
kubernetes-worker3      us-west1-a  zone            10       pd-standard  READY
zookeeper-0             us-west1-a  zone            5        pd-standard  READY
zookeeper-1             us-west1-a  zone            5        pd-standard  READY
zookeeper-2             us-west1-a  zone            5        pd-standard  READY




gce-k8s-master

gce-k8s-master module for to deploy Kubernetes master node on google cloud engine.
Centos 7 image with ssh key copy.
Install Kubernetes and initialize as master.



gce-k8s-worker

gce-k8s-worker module for to deploy Kubernetes 3 x worker node's on google cloud engine.
Centos 7 image with ssh key copy.
Install Kubernetes and add as worker to master.

Ansible playbook used:


  • prerequisites.yml
  • setting_up_nodes.yml
  • configure_master_node.yml
  • configure_worker_nodes.yml
  • post_configure_k8s_cluster.yml
  • pre_configure_hdfs_nodes.yml
  • configure_hdfs_nodes.yml


Automated deployment using Terraform:

# terraform init

# terraform plan

# terraform apply


Verification: