Using SaltStack to deploy Auto-scaling EC2

Standard

SaltStack Master: 172.66.1.100

Create AMI by default VM:

root@ip-x.x.x.x:~# cat /etc/rc.local
/root/PkgInit.sh;
/root/SaltMinionInit.sh;
/root/SaltCall.sh;
 
root@ip-x.x.x.x:~# cat /root/PkgInit.sh 
add-apt-repository ppa:saltstack/salt -y;
apt-get update;
apt-get install salt-minion -y;
apt-get install awscli -y;
 
root@ip-x.x.x.x:~# cat /root/SaltMinionInit.sh
INSTANCE_ID=$(ec2metadata --instance-id);
REGION=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | grep region | awk -F\" '{print $4}');
TAG=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" --region=$REGION --output=text --max-items=1 | cut -f5);
/bin/echo -e "master: 172.66.1.100\ngrains:\n  roles:\n    - "$TAG > /etc/salt/minion;
service salt-minion restart;
 
root@ip-x.x.x.x:~# cat /root/SaltCall.sh
sleep 15s;
salt-call state.highstate;

Setup Saltstack Master:

root@ip-172-66-1-100:~# add-apt-repository ppa:saltstack/salt
root@ip-172-66-1-100:~# apt-get update
root@ip-172-66-1-100:~# apt-get install salt-master
root@ip-172-66-1-100:~# cat /etc/salt/master | grep -v '^#' | grep -v '^$'
file_roots:
  base:
    - /srv/salt
pillar_roots:
  base:
    - /srv/pillar
reactor:
  - 'salt/auth':
    - /srv/reactor/auth-pending.sls
 
# Automating Key Acceptance
# salt-run state.event pretty=True
root@ip-172-66-1-100:~# cat /srv/reactor/auth-pending.sls
{% if 'act' in data and data['act'] == 'pend' and data['id'].startswith('ip-172') %}
minion_add:
  wheel.key.accept:
    - match: {{ data['id'] }}
{% endif %}
 
# Get grains item
root@ip-172-66-1-100:~# salt '*' grains.item os
ip-172-66-2-214:
    ----------
    os:
        Ubuntu
ip-172-66-4-93:
    ----------
    os:
        Ubuntu
root@ip-172-66-1-100:/srv/reactor# salt '*' grains.item roles
ip-172-66-2-214:
    ----------
    roles:
        - YeMaosheng_com
ip-172-66-4-93:
    ----------
    roles:
        - YeMaosheng_com
 
root@ip-172-66-1-100:~# salt -G 'roles:YeMaosheng_com' state.highstate -t 60 test=True
root@ip-172-66-1-100:~# salt -G 'roles:YeMaosheng_com' state.highstate
root@ip-172-66-1-100:~# salt-run manage.down removekeys=True
root@ip-172-66-1-100:~# salt-run state.event pretty=True

网站所用EC2的安装及发布配置

├── pillar
│   ├── yemaosheng_com
│   │   ├── nginx.sls
│   │   ├── php56.sls
│   │   └── website.sls
│   └── top.sls
├── reactor
│   └── auth-pending.sls
└── salt
    ├── crontab
    │   └── init.sls
    ├── mysql-client
    │   └── init.sls
    ├── nginx
    │   ├── configs
    │   │   └── yemaosheng_com
    │   │       ├── blockrules.conf
    │   │       ├── nginx.conf
    │   │       └── sites-enabled
    │   │           └── yemaosheng.com
    │   └── init.sls
    ├── php56
    │   ├── configs
    │   │   └── yemaosheng_com
    │   │       └── php5-fpm
    │   │           └── www.conf
    │   └── init.sls
    ├── top.sls
    ├── website
    │   ├── configs
    │   │   └── yemaosheng_com
    │   │       ├── dhparam.pem
    │   │       └── sslkey
    │   └── init.sls
    └── websitefiles
        └── yemaosheng_com -> /var/www/yemaosheng_com
 
cat /srv/salt/top.sls 
base:
 'roles:yemaosheng_com':
 - match: grain
 - mysql-client
 - php56
 - nginx
 - website
 - crontab
 
cat /srv/pillar/top.sls 
base : 
 'roles:yemaosheng_com':
 - match: grain
 - yemaosheng_com.nginx
 - yemaosheng_com.php56
 - yemaosheng_com.website
 
cat /srv/pillar/yemaosheng_com/nginx.sls 
nginx_conf: nginx/configs/yemaosheng_com/nginx.conf
nginx_site-enable: nginx/configs/yemaosheng_com/sites-enabled
 
cat /srv/salt/nginx/init.sls 
{% set site_name = pillar['site_name'] %}
 
nginx:
  pkg:
    - name: nginx
    - installed
 
nginx_conf:
  service.running:
    - name: nginx
    - enable: True
    - reload: True
    - watch:
      - file: /etc/nginx/*
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://{{ pillar['nginx_conf'] }}
    - user: root
    - group: root
    - mode: '0640'
    - require:
      - pkg: nginx
 
{% if site_name == 'yemaosheng_com' %}
upload_sslkey_to_nginx:
  file.recurse:
    - name: /srv/ssl
    - user: root
    - group: root
    - file_mode: '0644'
    - source: salt://website/configs/yemaosheng_com/sslkey
    - include_empty: True
 
upload_dhparam_to_nginx:
  file.managed:
    - name: /etc/nginx/dhparam.pem
    - source: salt://website/configs/yemaosheng_com/dhparam.pem
    - user: root
    - group: root
    - mode: '0644'
    - require:
      - pkg: nginx
{% endif %}
 
/etc/nginx/sites-enabled:
  service.running:
    - name: nginx
    - enable: True
    - reload: True
    - watch:
      - file: /etc/nginx/sites-enabled
  file.recurse:
    - name: /etc/nginx/sites-enabled
    - user: root
    - group: root
    - dir_mode: 2775
    - file_mode: '0644'
    - source: salt://{{ pillar['nginx_site-enable'] }}
    - include_empty: True
    - clean: True
    - require:
      - pkg: nginx

Configuring bind and saltstack on CentOS6.4

Standard
[master]$ yum install bind bind-utils;
 
[master]$ vi /etc/named.conf
options {
 ...
 listen-on port 53 { any; };
 allow-query     { any; };
 ...
}
...
 
[master]$ vi /etc/named.rfc1912.zones
...
zone "test.local" IN {
        type master;
        file "test.local.zone";
};
zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "1.168.192.zone";
};
[master]$ vi /var/named/1.168.192.zone   
$TTL 3H
@ IN SOA ns.test.local. root.test.local. (
2015012815       ; serial
3H      ; refresh
15M     ; retry
1W      ; expire
3H )    ; minimum
@ IN NS ns.test.local.
185 IN PTR ns.test.local.
185 IN PTR master.test.local.
186 IN PTR web01.test.local.
187 IN PTR web02.test.local.
 
[master]$ vi /var/named/test.local.zone        
$TTL 3H
@ IN SOA ns.test.local. root.test.local. (
2015012815       ; serial
3H      ; refresh
15M     ; retry
1W      ; expire
3H )    ; minimum
@ IN NS ns.test.local.
@ IN MX 10 mail.test.local.
ns IN A 192.168.1.185
master IN A 192.168.1.185
web01 IN A 192.168.1.186
web02 IN A 192.168.1.187
 
[master]$ vi /etc/resolv.conf 
nameserver 127.0.0.1
 
[master]$ /etc/init.d/named start
[master]$ wget http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
[master]$ rpm -ivh epel-release-6-8.noarch.rpm
[master]$ yum install salt-master
[master]$ /etc/init.d/salt-master start
[web01]$ vi /etc/resolv.conf 
nameserver 192.168.1.185
 
[web01]$ wget http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
[web01]$ rpm -ivh epel-release-6-8.noarch.rpm
[web01]$ yum install salt-minion
 
[web01]$ vi /etc/salt/minion
...
  master: master.test.local
  grains:
    roles:
      - yemaosheng_com
...
 
[web01]$ /etc/init.d/salt-minion start
[master]$ key -L
[master]$ key -A
[master]$ salt '*' test.ping
[master]$ salt 'web*' cmd.run 'df -h'
[master]$ salt '*' grains.items
[master]$ salt '*' grains.item roles
[master]$ salt '*' service.get_all
[master]$ salt '*' sys.doc
 
[master]$ cd /srv/salt/; tree
├── dev
│    └── phpModules
│         ├── gd.sls
│         └── mbstring.sls
├── prod
│    └── phpModules
│         └── gd.sls
└── top.sls
 
[master]$ cat top.sls
base:
 'web1':
  - dev.phpModules.*
 'web2':
  - prod.phpModules.*
 
[master]$ cat dev/phpModules/gd.sls 
gd:
 pkg:
  - name: php-gd
  - installed
 
[master]$ cat dev/phpModules/mbstring.sls 
mbstring:
 pkg:
  - name: php-mbstring
  - installed
 
[master]$ salt '*' state.highstate test
 
[master]$ vi /etc/salt/master
file_roots:
  base:
    - /srv/salt/
  dev:
    - /srv/salt/dev/
  prod:
    - /srv/salt/prod/
 
[master]$ cat /srv/salt/top.sls 
base:
 'web1':
  - prod.phpModules.*
dev:
 'web2':
  - phpModules.*
 
[master]$ salt '*' state.highstate test
 
[master]$ tree
├── dev
│    └── phpModules
│        ├── gd.sls
│        └── mbstring.sls
├── prod
│    ├── files
│    │   └── PS1.sh
│    ├── initShell
│    │   └── PS1Colors.sls
│    └── phpModules
│        └── gd.sls
└── top.sls
 
[master]$ cat prod/files/PS1.sh 
if [ `id -u` == '0' ]; then
 export PS1="\[\e[1;31m\][\u@\h \W]\$ \[\e[m\]"
else
 export PS1="\[\e[1;32m\][\u@\h \W]\$ \[\e[m\]"
fi
 
[master]$ cat prod/initShell/PS1Colors.sls 
PS1Colors:
 file.managed:
  - name: /etc/profile.d/PS1.sh
  - source: salt://files/PS1.sh
  - mode: 644
  - owner: root
  - group: root
 
[master]$ vi top.sls 
dev:
 'web1':
  - phpModules.*
prod:
 'web*':
  - initShell.*
 
[master]$ salt '*' state.highstate test

Install nginx & php on Ubuntu

/srv/salt# tree
├── files
│   ├── nginx
│   │   ├── nginx.conf
│   │   └── sites-enabled
│   │       └── default
│   ├── php5-fpm
│   │   └── www.conf
│   └── websitefiles
│       └── test
│           └── index.php
├── top.sls
├── webserver.sls
└── websitefiles.sls
 
cat top.sls 
base:
 'roles:sub1':
 - match: grain
 - webserver
 - websitefiles
 
 'roles:sub2':
 - match: grain
 - webserver
 
cat webserver.sls 
nginx:
  pkg:
    - name: nginx
    - installed
  service:
    - name: nginx
    - running
    - enable: True
    - reload: True
    - watch:
      - file: /etc/nginx/*
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://files/nginx/nginx.conf
    - user: root
    - group: root
    - mode: '0640'
    - require:
      - pkg: nginx
 
/etc/nginx/sites-enabled:
  file.recurse:
    - name: /etc/nginx/sites-enabled
    - user: root
    - group: root
    - dir_mode: 2775
    - file_mode: '0644'
    - source: salt://files/nginx/sites-enabled
    - include_empty: True
    - clean: True
 
mysql-client:
  pkg:
    - name: mysql-client
    - installed
 
php5:
  pkg:
    - name: php5
    - pkgs:
      - php5-common
      - php5-fpm
      - php5-cli
      - php5-dev
      - php5-curl
      - php5-gd
      - php5-imagick
      - php5-mcrypt
      - php5-mysql
      - php5-memcache
      - php5-memcached
      - php5-json
    - installed
  service:
    - name: php5-fpm
    - running
    - enable: True
    - reload: True
    - watch:
      - file: /etc/php5/fpm/pool.d/www.conf
  file.managed:
    - name: /etc/php5/fpm/pool.d/www.conf
    - source: salt://files/php5-fpm/www.conf
    - user: root
    - group: root
    - mode: '0640'
    - require:
      - pkg: php5
 
cat websitefiles.sls 
{% set site_user = 'www-data' %}
{% set site_name = 'test' %}
{% set sites_dir = '/usr/share/nginx/html' %}
 
test-project:
  file.recurse:
    - name: {{ sites_dir }}/{{ site_name }}
    - user: {{ site_user }}
    - group: {{ site_user }}
    - dir_mode: 2775
    - file_mode: '0644'
    - template: jinja
    - source: salt://files/websitefiles/{{ site_name }}
    - include_empty: True
    - clean: True
 
salt -G 'roles:sub1' state.highstate