Modern DevOps eszközök és technikák
Continuous Delivery
Our highest priority is to satisfy the customer
through early and continuous delivery of valuable software.
Create a repetable, reliable process for releasing software
Automate almost everything
Keep everything in version control
If it hurts, do it more frequently, and bring the pain forward
Build quality in
Done means released
Continuous Improvement
Build Pipeline
DEV + OPS + QA
Infrastructure as Code
Infrastructure as Code
- Code is version controlled
- Code changes can be reviewed by anyone
- Code is repeatable
- Code is testable
Immutable infrastructure
(Phoenix Server Pattern)
variables = JSON.parse(File.read("variables.json"))
args_name = ""
args_value = []
for i in 2..variables.count-1
args_name = args_name + "${#{i-1}} "
args_value.push(variables.values[i])
end
Vagrant.configure("2") do |config|
config.vm.box = "woohoolabs/api"
config.ssh.forward_agent = true
config.ssh.port = variables["ssh_port"]
config.exec.commands %w(go), directory: "/website"
config.vm.provider :virtualbox do |vb, override|
override.vm.network "private_network", ip: variables["private_ip"]
override.vm.network "forwarded_port", guest: 22, host: variables["ssh_port"], protocol: "tcp"
override.vm.synced_folder "./", "/vagrant", disabled: true
override.vm.synced_folder "./", "/website", owner: "vagrant", group: "www-data", mount_options: ["dmode=775,fmode=775"]
end
config.vm.provision :shell do |sh|
sh.inline = "go cd provision #{args_name}| tee -a ~/provision.log"
sh.args = args_value
sh.privileged = false
end
end
{
"variables": {
"api_box_name": "api",
"api_box_version": "2.7",
"api_web_project_root_path": "/website",
"api_web_project_web_absolute_path": "/website/web",
"api_web_project_var_absolute_path": "/etc/website/var",
"api_dev_web_box_name": "api-dev",
"api_dev_web_build_env": "dev",
"api_dev_web_ssh_user": "vagrant",
"api_dev_web_ssh_password": "vagrant",
"api_prod_web_box_name": "api-prod-web",
"api_prod_web_build_env": "prod",
"api_prod_web_ssh_user": "ubuntu",
"api_prod_web_ssh_port": "22",
"api_prod_web_aws_access_key": "{{env `AWS_ACCESS_KEY`}}",
"api_prod_web_aws_secret_key": "{{env `AWS_SECRET_KEY`}}",
"api_prod_web_aws_region": "eu-central-1",
"api_prod_web_aws_source_ami": "ami-70f9cb6d",
"api_prod_web_aws_instance_type": "t2.micro"
},
"builders": [
{
"name": "api-prod-web",
"ami_name": "{{user `api_prod_web_box_name`}}-{{user `api_box_version`}}-{{ timestamp }}",
"ami_description": "Ubuntu 14.04 64 bit web server for Woohoo Labs. API",
"type": "amazon-ebs",
"access_key": "{{user `api_prod_web_aws_access_key`}}",
"secret_key": "{{user `api_prod_web_aws_secret_key`}}",
"region": "{{user `api_prod_web_aws_region`}}",
"source_ami": "{{user `api_prod_web_aws_source_ami`}}",
"instance_type": "{{user `api_prod_web_aws_instance_type`}}",
"ssh_username": "{{user `api_prod_web_ssh_user`}}",
"ssh_port": "{{user `api_prod_web_ssh_port`}}",
"enhanced_networking": true,
"tags": {
"build_env": "prod",
"build_type": "web",
"build_version": "{{user `api_box_version`}}",
"build_time": "{{ timestamp }}"
}
},
{
"name": "api-dev",
"type": "virtualbox-iso",
"boot_command": [
"<esc><wait><esc><wait><enter><wait>",
"/install/vmlinuz",
" auto",
" console-setup/ask_detect=false",
" console-setup/layoutcode=hu",
" console-setup/modelcode=pc105",
" debconf/frontend=noninteractive",
" debian-installer=en_US",
" fb=false",
" initrd=/install/initrd.gz",
" kbd-chooser/method=hu",
" keyboard-configuration/layout=HUNGARY",
" keyboard-configuration/variant=HUNGARY",
" locale=en_US",
" hostname={{user `api_box_name`}}.{{user `api_dev_web_build_env`}}",
" netcfg/get_domain=site",
" netcfg/get_hostname=vagrant",
" noapic",
" preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg",
"<enter><wait>",
" -- <wait>"
],
"boot_wait": "10s",
"disk_size": 8000,
"guest_additions_path": "VBoxGuestAdditions_{{.Version}}.iso",
"guest_os_type": "Ubuntu_64",
"http_directory": "provisioners",
"iso_urls": [
"http://releases.ubuntu.com/14.04/ubuntu-14.04.2-server-amd64.iso",
"http://hu.releases.ubuntu.com/14.04/ubuntu-14.04.2-server-amd64.iso"
],
"iso_checksum": "3bfa6eac84d527380d0cc52db9092cde127f161e",
"iso_checksum_type": "sha1",
"output_directory": "{{user `api_dev_web_box_name`}}",
"shutdown_command": "echo 'vagrant'|sudo -S -E shutdown -P now",
"ssh_username": "{{user `api_dev_web_ssh_user`}}",
"ssh_password": "{{user `api_dev_web_ssh_password`}}",
"ssh_port": 22,
"ssh_wait_timeout": "10000s",
"headless": true,
"hard_drive_interface": "sata",
"vboxmanage": [
[
"modifyvm",
"{{user `api_dev_web_box_name`}}",
"--memory",
"1024"
],
[
"modifyvm",
"{{user `api_dev_web_box_name`}}",
"--cpus",
"2"
]
],
"virtualbox_version_file": ".vbox_version",
"vm_name": "{{user `api_dev_web_box_name`}}"
}
],
"post-processors": [
{
"type": "vagrant",
"output": "{{user `api_box_name`}}-{{user `api_box_version`}}-{{ .Provider }}.box"
}
],
"provisioners": [
{
"type": "shell",
"scripts": [
"provisioners/project/setup-envvars-build.sh",
"provisioners/server-web/add-dependencies.sh",
"provisioners/os/setup-os.sh",
"provisioners/os/setup-sshd.sh",
"provisioners/os/setup-sudoers.sh"
],
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log",
"override": {
"api-prod-web": {
"environment_vars": [
"BUILD_NAME={{user `api_prod_web_box_name`}}",
"BUILD_ENV={{user `api_prod_web_build_env`}}",
"BUILD_VERSION={{user `api_box_version`}}",
"SSH_USER={{user `api_prod_web_ssh_user`}}",
"PROJECT_DIR={{user `api_web_project_root_path`}}",
"WEB_DIR={{user `api_web_project_web_absolute_path`}}",
"VAR_DIR={{user `api_web_project_var_absolute_path`}}"
]
},
"api-dev": {
"environment_vars": [
"BUILD_NAME={{user `api_dev_web_box_name`}}",
"BUILD_ENV={{user `api_dev_web_build_env`}}",
"BUILD_VERSION={{user `api_box_version`}}",
"SSH_USER={{user `api_dev_web_ssh_user`}}",
"PROJECT_DIR={{user `api_web_project_root_path`}}",
"WEB_DIR={{user `api_web_project_web_absolute_path`}}",
"VAR_DIR={{user `api_web_project_var_absolute_path`}}"
]
}
}
},
{
"type": "shell",
"override": {
"api-prod-web": {
"scripts": [
"provisioners/os/setup-amazon.sh",
"provisioners/server-web/install-mysql-client.sh"
]
},
"api-dev": {
"scripts": [
"provisioners/os/setup-vagrant.sh",
"provisioners/server-web/install-mysql-server.sh"
]
}
},
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log"
},
{
"type": "shell",
"scripts": [
"provisioners/server-web/install-locales.sh",
"provisioners/server-web/install-web.sh",
"provisioners/server-web/install-beanstalkd.sh",
"provisioners/server-web/install-redis.sh",
"provisioners/server-web/install-mail.sh",
"provisioners/server-web/install-dev.sh",
"provisioners/project/setup-project.sh",
"provisioners/os/minimize.sh",
"provisioners/project/get-build-version.sh"
],
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log"
}
]
}
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.aws_region}"
}
resource "aws_security_group" "web" {
name = "api_staging_security_group"
description = "Default security group for the API"
# SSH access from anywhere
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTP access from anywhere
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTPS access from anywhere
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# MySQL access from anywhere
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTP access to anywhere
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTPS access to anywhere
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# MySQL access to anywhere
egress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
connection {
user = "ubuntu"
key_file = "${var.aws_key_path}"
}
instance_type = "${var.aws_instance_type}"
ami = "${var.aws_ami}"
key_name = "${var.aws_key_name}"
security_groups = ["${aws_security_group.web.name}"]
tags {
Name = "api-${var.app_env}-web-${var.deploy_time}"
App_Env = "${var.app_env}"
Deploy_Time = "${var.deploy_time}"
Deploy_Commit = "${var.deploy_commit}"
}
# Copies the Go script to the machine - cwd must be in the Terraform config folder
provisioner "file" {
source = "../../../../go"
destination = "~/go"
}
provisioner "remote-exec" {
inline = [
"chmod 750 ~/go",
"~/go cd checkout ${var.deploy_commit} /website ${var.bitbucket_username} ${var.bitbucket_password} | tee -a /home/ubuntu/provision.log",
"chmod 750 /website/go & rm ~/go & chmod 750 -R /website/app/build/images/provisioners",
"go cd provision ${var.app_env} ${var.beanstalkd_host} ${var.beanstalkd_port} ${aws_db_instance.web.address} ${aws_db_instance.web.port} ${var.db_common_name} ${var.db_common_user} ${var.db_common_password} ${var.redis_scheme} ${var.redis_host} ${var.redis_port} ${var.open_weather_map_api_key} ${var.blackfire_server_id} ${var.blackfire_server_token} ${var.blackfire_client_id} ${var.blackfire_client_token} | tee -a /home/ubuntu/provision.log",
"go cd auto-migrate '${var.db_root}' '${var.db_root_password}' | tee -a /home/ubuntu/provision.log"
]
}
}
resource "aws_db_instance" "web" {
identifier = "api-staging-rds"
allocated_storage = 5
engine = "mysql"
engine_version = "5.6.22"
instance_class = "db.t2.micro"
username = "${var.db_root}"
password = "${var.db_root_password}"
parameter_group_name = "default.mysql5.6"
availability_zone= "${var.aws_region}b"
backup_retention_period = 0
maintenance_window = "fri:08:22-fri:08:52"
multi_az = false
port = "${var.db_port}"
}
output "web-zone" {
value = "${aws_instance.web.availability_zone}"
}
output "web-ip" {
value = "${aws_instance.web.public_ip}"
}
output "web-dns" {
value = "${aws_instance.web.public_dns}"
}
output "db-address" {
value = "${aws_db_instance.web.address}"
}
People don't scale - machines do
Jeff Atwood
Források
- http://www.amazon.com/Continuous-Delivery-Deployment-Automation-Signature/dp/0321601912
- http://slideshare.net/PuppetLabs/infrastructure-as-code-why-it-matters-51737991
- https://thoughtworks.com/insights/blog/infrastructure-code-reason-smile
- https://thoughtworks.com/insights/blog/moving-to-phoenix-server-pattern-introduction
- http://mitchellh.com/comparing-filesystem-performance-in-virtual-machines
Modern DevOps Eszközök és Technikák
By Máté Kocsis
Modern DevOps Eszközök és Technikák
- 387