Skip to content

Commit

Permalink
Merge pull request #10 from Otus-DevOps-2023-05/ansible-4
Browse files Browse the repository at this point in the history
Ansible 4
  • Loading branch information
arybach authored Nov 17, 2023
2 parents 4049811 + dcce047 commit 7e982d5
Show file tree
Hide file tree
Showing 81 changed files with 1,638 additions and 191 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ packer/variables.json
*.tfvars
.terraform/
terraform/terraform-provider-yandex
*.retry
vault.key
1 change: 1 addition & 0 deletions ansible/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.retry
jdauphant.nginx
204 changes: 149 additions & 55 deletions ansible/README.md
Original file line number Diff line number Diff line change
@@ -1,97 +1,191 @@
### db module is not needed here as we are deploying monolith repo to appserver
### create vpc, subnet, security group and app + db instances
```
[0] % cd terraform/stage
cd terraform/stage/modules/vpc
# this will create vpc and security group
terraform apply -var-file=terraform.tfvars
cd ../../stage
# this will fetch security group id and subnet id with data block as passing through variables doesn't work
terraform apply -var-file=terraform.tfvars
Outputs:
external_ip_address_app = "158.160.42.222"
external_ip_address_db = "158.160.96.120"
internal_ip_address_app = "10.128.0.20"
internal_ip_address_db = "10.128.0.33"
external_ip_address_app = "158.160.115.53"
external_ip_address_db = "158.160.126.90"
internal_ip_address_app = "192.168.10.12"
internal_ip_address_db = "192.168.10.17"
```

### modify ansible/inventory.ini file:
### modify ansible/environments/stage/inventory.ini or ansible/environments/prod/inventory.ini file:
```
[app]
appserver ansible_host=158.160.42.222
appserver ansible_host=158.160.115.53 ansible_user=ubuntu ansible_internal_ip=192.168.10.12
[db]
dbserver ansible_host=158.160.96.120
dbserver ansible_host=158.160.126.90 ansible_user=ubuntu ansible_internal_ip=192.168.10.17
```

### check ansible playbook
### run ansible playbook (takes a realy long time as it builds ancient Python 3.6.15 from source)
```
[0] % ansible-playbook reddit_app.yml --check --limit db
cd ../../ansible
# this won't work:
ansible-playbook -i environments/stage/inventory playbooks/site.yml
PLAY [Configure hosts & deploy application] **********************************************************************************************************
# it only works with full path specified:
ansible-playbook -i /media/groot/data/arybach_infra/ansible/environments/stage/inventory.ini ./playbooks/site.yml
TASK [Gathering Facts] *******************************************************************************************************************************
ok: [dbserver]
or
# this won't work:
ansible-playbook -i environments/prod/inventory playbooks/site.yml
TASK [Change mongo config file] **********************************************************************************************************************
changed: [dbserver]
# it only works with full path specified:
ansible-playbook -i /media/groot/data/arybach_infra/ansible/environments/prod/inventory.ini ./playbooks/site.yml
```
### output
```
...
TASK [app : Fetch the latest version of application code] ***********************************************************************************************************
>> Newly checked out 0a4d3a148dccd6fd3e536b70ac8665c296efe159
changed: [appserver]
RUNNING HANDLER [restart mongod] *********************************************************************************************************************
changed: [dbserver]
TASK [app : Install specified python requirements for Python 3] *****************************************************************************************************
changed: [appserver]
PLAY RECAP *******************************************************************************************************************************************
dbserver : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```
TASK [app : Add config for DB connection] ***************************************************************************************************************************
--- before
+++ after: /home/groot/.ansible/tmp/ansible-local-142927og5spg3m/tmplyove8r5/db_config.j2
@@ -0,0 +1 @@
+DATABASE_URL=mongodb://192.168.10.17
### after adding puma.service file and puma tasks to reddit_app.yml:
changed: [appserver]
```
[0] % yc compute instance list | grep 158.160.96.120
| fhmmr7aqbffvb513ffnc | reddit-db | ru-central1-a | RUNNING | 158.160.96.120 | 10.128.0.33 |
# then copy internal ip 10.128.0.33 to db_host var in reddit_app/yml
# Note: for monolith repo we would set db_host to 10.128.0.20 - as it's running on the localhost
TASK [app : Add COMMENT_DATABASE_HOST to .bashrc] *******************************************************************************************************************
--- before: /home/ubuntu/.bashrc (content)
+++ after: /home/ubuntu/.bashrc (content)
@@ -113,5 +113,6 @@
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
+export COMMENT_DATABASE_HOST=192.168.10.17
changed: [appserver]
% ansible-playbook reddit_app.yml --limit app --tags app-tag
TASK [app : Add POST_DATABASE_HOST to .bashrc] **********************************************************************************************************************
--- before: /home/ubuntu/.bashrc (content)
+++ after: /home/ubuntu/.bashrc (content)
@@ -114,5 +114,6 @@
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export COMMENT_DATABASE_HOST=192.168.10.17
+export POST_DATABASE_HOST=192.168.10.17
PLAY [Configure hosts & deploy application] **********************************************************************************************************
changed: [appserver]
TASK [app : Bundle install for the UI service] **********************************************************************************************************************
changed: [appserver]
TASK [Gathering Facts] *******************************************************************************************************************************
ok: [appserver]
TASK [app : Copy Puma service file] *********************************************************************************************************************************
--- before
+++ after: /media/groot/data/arybach_infra/ansible/roles/app/files/puma.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Puma HTTP Server
+After=network.target
+
+[Service]
+Type=simple
+EnvironmentFile=/home/ubuntu/db_config
+User=ubuntu
+WorkingDirectory=/home/ubuntu/reddit/ui
+ExecStart=/bin/bash -lc 'puma'
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
TASK [Copy Puma service file] ************************************************************************************************************************
changed: [appserver]
TASK [Add config for DB connection] ******************************************************************************************************************
TASK [app : Enable and start Puma service] **************************************************************************************************************************
changed: [appserver]
RUNNING HANDLER [reload systemd] *********************************************************************************************************************
RUNNING HANDLER [app : reload puma] *********************************************************************************************************************************
changed: [appserver]
PLAY RECAP *******************************************************************************************************************************************
appserver : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
PLAY RECAP **********************************************************************************************************************************************************
appserver : ok=23 changed=19 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
dbserver : ok=9 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```
### after adding bundle install and cloning reddit git repo tasks to reddit_app.yml:

### open appserver ip port 9292 with web browser
everything works except for the comments - bug in the https://github.com/express42/reddit.git repo (branch microservices)

![Alt text](image.png)

### add users and encrypt keys
```
% ansible-playbook reddit_app.yml --limit app --tags deploy-tag
cd ../../ansible
PLAY [Configure hosts & deploy application] **********************************************************************************************************
ansible-vault encrypt environments/prod/credentials.yml
> Encryption successful
TASK [Gathering Facts] *******************************************************************************************************************************
ok: [appserver]
ansible-vault encrypt environments/stage/credentials.yml
> Encryption successful
```
### then run
ansible-playbook -i /media/groot/data/arybach_infra/ansible/environments/stage/inventory.ini ./playbooks/users.yml

TASK [Install git] ***********************************************************************************************************************************
changed: [appserver]
### output
```
TASK [create users] *************************************************************************************************************************************************
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from Python 3.13. Install
the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from Python 3.13. Install
the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
changed: [appserver] => (item={'key': 'admin', 'value': {'password': 'qwerty123', 'groups': 'sudo'}})
changed: [dbserver] => (item={'key': 'admin', 'value': {'password': 'qwerty123', 'groups': 'sudo'}})
changed: [appserver] => (item={'key': 'qauser', 'value': {'password': 'test123'}})
changed: [dbserver] => (item={'key': 'qauser', 'value': {'password': 'test123'}})
PLAY RECAP **********************************************************************************************************************************************************
appserver : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
dbserver : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```

TASK [Fetch the latest version of application code] **************************************************************************************************
changed: [appserver]
### check the vm
```
ssh -i ~/.ssh/yc [email protected]
TASK [Bundle install] ********************************************************************************************************************************
changed: [appserver]
cat /etc/passwd | grep qauser
qauser:x:1002:1003::/home/qauser:
```

RUNNING HANDLER [reload puma] ************************************************************************************************************************
ok: [appserver]
### install nginx community role
ansible-galaxy install -r environments/stage/requirements.yml

PLAY RECAP *******************************************************************************************************************************************
appserver : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```
Starting galaxy role install process
- downloading role 'nginx', owned by jdauphant
- downloading role from https://github.com/jdauphant/ansible-role-nginx/archive/v2.21.1.tar.gz
- extracting jdauphant.nginx to /media/groot/data/arybach_infra/ansible/roles/jdauphant.nginx
- jdauphant.nginx (v2.21.1) was installed successfully
```
### run nginx playbook
```
ansible-playbook -i /media/groot/data/arybach_infra/ansible/environments/stage/inventory.ini ./playbooks/nginx.yml
```
### after that the app opens on the ip port 80:
![Alt text](image-1.png)

### run without tags for proper deploy
### clean up:
```
% ansible-playbook reddit_app.yml
cd ../terraform/stage
terraform destroy -var-file=terraform.tfvars
cd ../modules/vpc
terraform destroy -var-file=terraform.tfvars
```
![Alt text](image.png)
81 changes: 81 additions & 0 deletions ansible/Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
ENV['PATH'] = "/home/groot/miniconda/bin/:#{ENV['PATH']}"

Vagrant.configure("2") do |config|
# Define the box to use for both VMs globally
config.vm.box = "ubuntu/xenial64"

# Provisioning script to enable passwordless sudo and set a password for ubuntu user
$setup_script = <<-SCRIPT
#!/bin/bash
# Set password for ubuntu user
echo 'ubuntu:YOUR_PASSWORD' | sudo chpasswd
# Add ubuntu user to sudoers with no password prompt
echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/ubuntu
# Set correct permissions on the sudoers file
sudo chmod 0440 /etc/sudoers.d/ubuntu
# Output the contents for debugging
echo 'Contents of /etc/sudoers.d/ubuntu:'
cat /etc/sudoers.d/ubuntu
# Test sudo access
echo 'Testing sudo access for ubuntu user:'
sudo -u ubuntu sudo -l
SCRIPT

# Define the dbserver VM
config.vm.define "dbserver" do |db|
db.vm.hostname = "dbserver"
# Update the IP to match the allowed range
db.vm.network "private_network", ip: "192.168.56.10"

# Run the provisioning script to enable passwordless sudo
db.vm.provision "shell", inline: $setup_script

# Ansible provider
db.vm.provision "ansible" do |ansible|
ansible.playbook = "playbooks/site.yml"
ansible.groups = {
"db" => ["dbserver"],
"db:vars" => {"mongo_bind_ip" => "0.0.0.0"}
}
ansible.extra_vars = {
"db_host" => "192.168.56.10",
"deploy_user" => "ubuntu"
}
ansible.compatibility_mode = "2.0" # Here is where you set the compatibility mode
end

db.vm.provider "virtualbox" do |v|
v.memory = 2048
end
end

# Define the appserver VM
config.vm.define "appserver" do |app|
app.vm.hostname = "appserver"
# Update the IP to match the allowed range
app.vm.network "private_network", ip: "192.168.56.20"
# remove this line if not using nginx
app.vm.network "forwarded_port", guest: 9292, host: 9292

# Run the provisioning script to enable passwordless sudo
app.vm.provision "shell", inline: $setup_script

# Ansible provider
app.vm.provision "ansible" do |ansible|
ansible.playbook = "playbooks/site.yml"
ansible.groups = {
"app" => ["appserver"]
}
ansible.extra_vars = {
"db_host" => "192.168.56.10",
"app_host" => "192.168.56.20",
"deploy_user" => "ubuntu"
}
ansible.compatibility_mode = "2.0" # Again set the compatibility mode here
end

app.vm.provider "virtualbox" do |v|
v.memory = 8192
end
end
end
17 changes: 15 additions & 2 deletions ansible/ansible.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
[defaults]
inventory = ./inventory.ini
inventory = ./environments/stage/inventory.ini
remote_user = ubuntu
private_key_file = ~/.ssh/tumblebuns
private_key_file = ~/.ssh/yc
host_key_checking = False
retry_files_enabled = False
vault_password_file = vault.key
roles_path = /media/groot/data/arybach_infra/ansible/roles
#roles_path = ./roles

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

[diff]
always = True
context = 5
7 changes: 0 additions & 7 deletions ansible/clone.yml

This file was deleted.

10 changes: 10 additions & 0 deletions ansible/environments/prod/credentials.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$ANSIBLE_VAULT;1.1;AES256
34343363346636656465316332666538626235303830343533653736383339306665323737363265
6534343639376665633333623938613932396530616536650a363536623237616232313132326339
30333761316461353366666234386130383232356530623631663230623134336464623234663437
3864336365383437350a333633646636616238326663303465393938313437393632383561633736
31643963623132313635616338666437353964326333383138376235643766393638633966303732
63623635353732363433313861663033363662336632366439623663316536313264363432346537
63346634323630643662313764303334656335366336313434333432323835643138636632333133
32653363386138626236323534323965623231373234326137653430383966393061343137653133
3464
2 changes: 2 additions & 0 deletions ansible/environments/prod/group_vars/all
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
vars:
env: prod
8 changes: 8 additions & 0 deletions ansible/environments/prod/group_vars/app
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vars:
db_host: "{{ hostvars['dbserver']['ansible_internal_ip'] }}"

nginx_sites:
default:
- listen 80
- server_name "reddit"
- location / { proxy_pass http://127.0.0.1:4567; }
2 changes: 2 additions & 0 deletions ansible/environments/prod/group_vars/db
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
vars:
mongo_bind_ip: 0.0.0.0
5 changes: 5 additions & 0 deletions ansible/environments/prod/inventory.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[app]
appserver ansible_host=158.160.115.53 ansible_user=ubuntu ansible_internal_ip=192.168.10.12

[db]
dbserver ansible_host=158.160.126.90 ansible_user=ubuntu ansible_internal_ip=192.168.10.17
Loading

0 comments on commit 7e982d5

Please sign in to comment.