Deploy golang and python django app with terraform and ansible
Deploy golang and python django app with terraform and ansible
Продолжаем серию заметок по коварным дебрям devops
В предыдущей заметке развернули go приложение аки сервис
В этот раз добавим приложение python django
Проксирование - nginx, погнали
Часть 1 Terraform
Создается виртуалка на digital ocean
Назначается dns запись aws
Вызывается ansible
terraform.tfvars
do_token="***"
local_ssh_key_path="~/.ssh/id_rsa.pub"
email="email_at_domain_local"
aws_access_key = "***"
aws_secret_key = "***"
variables.tf
variable "do_token" {}
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "aws_region" {
default = "eu-west-1"
}
variable "local_ssh_public_key" {
default = "~/.ssh/id_rsa.pub"
}
variable "local_ssh_private_key" {
default = "~/.ssh/id_rsa"
}
variable "devs" {
description = "Settings"
type = map(any)
default = {
your_login = "your_user_name",
general_domain = "domain.local"
}
}
provider.tf
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
}
provider "digitalocean" {
token = var.do_token
}
provider "aws" {
access_key = var.aws_access_key
secret_key = var.aws_secret_key
region = var.aws_region
}
resources.tf
resource "digitalocean_volume" "temp_vol1" {
region = "nyc1"
name = "temp_vol1"
size = 5
initial_filesystem_type = "ext4"
}
resource "digitalocean_ssh_key" "local_ssh_pkey" {
name = "local_ssh_public_key"
public_key = file(var.local_ssh_public_key)
}
resource "digitalocean_droplet" "foobar" {
name = "foobar"
size = "s-1vcpu-1gb"
image = "ubuntu-22-04-x64"
region = "nyc1"
ssh_keys = [digitalocean_ssh_key.local_ssh_pkey.id]
volume_ids = [digitalocean_volume.temp_vol1.id]
}
locals {
vps_ip = digitalocean_droplet.foobar.ipv4_address
}
data "aws_route53_zone" "zone" {
name = var.devs.general_domain
}
resource "aws_route53_record" "record" {
zone_id = data.aws_route53_zone.zone.id
name = var.devs.your_login
allow_overwrite = true
type = "A"
ttl = "300"
records = [local.vps_ip]
}
resource "local_file" "hosts" {
filename = "${path.module}/hosts.yml"
content = templatefile("${path.module}/hosts.tmpl",
{
droplet = digitalocean_droplet.foobar
}
)
provisioner "local-exec" {
command = "ANSIBLE_CONFIG=${path.module}/ansible.cfg ansible-playbook playbook.yaml -i hosts.yml"
}
}
hosts.tmpl
all:
hosts:
${droplet.name}:
ansible_ssh_host: ${droplet.ipv4_address}
ansible_ssh_private_key_file: /root/.ssh/id_rsa
ansible_ssh_public_key_file: /root/.ssh/id_rsa.pub
Часть 2 Ansible
ansible.cfg
[defaults]
host_key_checking=false
inventory=./hosts.yml
playbook.yaml
- hosts:
- all
become: true
roles:
- role: go
- role: uwsgi_nginx
roles/go/files/go_app.service
[Unit]
Description=openroad flow backend server daemon
[Service]
Type=simple
ExecStart=/tmp/main
Restart=on-failure
RestartSec=10s
WorkingDirectory=/tmp
[Install]
WantedBy=multi-user.target
roles/go/files/main.go
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
// API routes
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
})
http.HandleFunc("/hi", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi")
})
port := ":80"
fmt.Println("Server is running on port" + port)
// Start server on port specified above
log.Fatal(http.ListenAndServe(port, nil))
}
roles/go/handlers/main.yml
---
- name: Start go_app
systemd:
name: go_app
state: started
enabled: yes
roles/go/tasks/main.yml
---
- name: Install golang
apt:
name: golang
state: present
update_cache: true
- name: Copy golang script
copy:
src: "{{ role_path }}/files/main.go"
dest: /tmp/main.go
- name: Build golang script
shell: cd /tmp && go build /tmp/main.go
#- name: Start golang script
# shell: go run /tmp/main.go
- name: Copy golang service
copy:
src: "{{ role_path }}/files/go_app.service"
dest: "/etc/systemd/system/go_app.service"
- name: Apply daemon-reload
command: systemctl daemon-reload
notify:
- Start go_app
roles/uwsgi_nginx/files/uwsgi.service
[Unit]
Description=uWSGI Emperor service
After=syslog.target
[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown www-data:www-data /run/uwsgi'
##Simple python app
##ExecStart=uwsgi --ini /var/www/uwsgi/uwsgi.ini
##Django python app
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/emperor.ini
Type=notify
NotifyAccess=all
Restart=always
KillSignal=SIGQUIT
[Install]
WantedBy=multi-user.target
roles/uwsgi_nginx/files/uwsgi.ini
[uwsgi]
master = True
socket = 127.0.0.1:82
wsgi-file = /var/www/uwsgi/index.py
logto = uwsgi.log
pidfile = uwsgi.pid
plugins = python3
roles/uwsgi_nginx/files/uwsgi.ini
[uwsgi]
master = True
socket = 127.0.0.1:82
wsgi-file = /var/www/uwsgi/index.py
logto = uwsgi.log
pidfile = uwsgi.pid
plugins = python3
roles/uwsgi_nginx/files/emperor.ini
[uwsgi]
emperor = /etc/uwsgi/apps-enabled/
vassals-inherit = /etc/uwsgi/vassal-default.ini
roles/uwsgi_nginx/files/django.ini
[uwsgi]
http = 127.0.0.1:83
chdir=/var/www/uwsgi
module=hello_world.wsgi:application
uid = www-data
gid = www-data
chown-socket = www-data:www-data
chmod-socket = 664
master = True
vacuum = True
roles/uwsgi_nginx/files/hw.conf
server {
listen 80;
server_name your_user_name.domain.local;
location /go {
proxy_pass http://127.0.0.1:81;
}
# location /py {
# include uwsgi_params;
# uwsgi_pass 127.0.0.1:82;
# }
location /dj {
proxy_pass http://127.0.0.1:83;
}
}
roles/uwsgi_nginx/files/index.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
test = 'hello world'
return test.encode("utf-8")
roles/uwsgi_nginx/files/urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from . import views
urlpatterns = [
url('', views.hello),
]
roles/uwsgi_nginx/files/views.py
from django.http import HttpResponse
def hello( request ) :
return HttpResponse( u'Hello World!' )
roles/uwsgi_nginx/vars/main.yml
---
proj_dir: /var/www/uwsgi
proj_name: hello_world
app_name: myapp
uwsgi_dir: /etc/uwsgi
roles/uwsgi_nginx/handlers/main.yml
---
- name: nginx start
systemd:
name: nginx
enabled: yes
state: started
- name: uwsgi start
systemd:
name: uwsgi
state: started
enabled: yes
roles/uwsgi_nginx/tasks/main.yml
---
- name: Install packages
apt:
pkg:
- nginx
- uwsgi
- uwsgi-plugin-python3
- python3-django
state: latest
update_cache: true
- name: Nginx app conf
copy:
src: hw.conf
dest: /etc/nginx/sites-enabled/hw.conf
notify:
- nginx start
- name: Create uwsgi dir
file:
path: "{{proj_dir}}"
state: directory
- name: Copy uwsgi ini
copy:
src: "uwsgi.ini"
dest: "{{proj_dir}}/uwsgi.ini"
- name: Copy uwsgi index.py
copy:
src: "index.py"
dest: "{{proj_dir}}/index.py"
- name: Copy uwsgi service
copy:
src: "uwsgi.service"
dest: "/etc/systemd/system/uwsgi.service"
- name: Apply daemon-reload
command: systemctl daemon-reload
- name: django startproject
shell: |
cd {{proj_dir}} && django-admin startproject {{proj_name}} .
cd {{proj_dir}} && python3 manage.py migrate
- name: add urls to project
copy:
src: urls.py
dest: "{{proj_dir}}/{{proj_name}}/urls.py"
- name: add views to project
copy:
src: views.py
dest: "{{proj_dir}}/{{proj_name}}/views.py"
- name: migrate
shell: |
cd {{proj_dir}}
python3 manage.py makemigrations
python3 manage.py migrate
- name: add emperor to uwsgi
copy:
src: emperor.ini
dest: "{{uwsgi_dir}}/emperor.ini"
- name: add vassal-default to uwsgi
copy:
src: vassal-default.ini
dest: "{{uwsgi_dir}}/vassal-default.ini"
- name: add django.ini
copy:
src: django.ini
dest: "{{proj_dir}}/django.ini"
- name: Enable django proj
shell: |
ln -s {{/var/www/uwsgi}}/django.ini /etc/uwsgi/apps-enabled/django.ini
notify:
- uwsgi start
- name: restart nginx
service:
name: nginx
state: restarted
become: yes
# terraform init
# terraform apply
Комментарии пользователей
Анонимам нельзя оставоять комментарии, зарегистрируйтесь!