2015年11月13日 星期五

Ansible 筆記 - 建立自己的 roles ,以架設 Nginx 為例 @ Ubuntu 14.04

目前的目錄結構:

$ tree
.
├── add_authorized_key.yml
├── ansible-deploy.pem
├── ansible-deploy.pub
├── etc
│   └── ansible
│       └── hosts
└── mysite.yml

$ mkdir -p roles && cd roles && ansible-galaxy init nginx && cd - && tree .
- nginx was created successfully
.
├── add_authorized_key.yml
├── ansible-deploy.pem
├── ansible-deploy.pub
├── etc
│   └── ansible
│       └── hosts
├── roles
│   └── nginx
│       ├── defaults
│       │   └── main.yml
│       ├── files
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── README.md
│       ├── tasks
│       │   └── main.yml
│       ├── templates
│       └── vars
│           └── main.yml
└── mysite.yml

11 directories, 11 files


開始撰寫 mysite.yml 跟 nginx 相關資料:

$ cat mysite.yml
---
- hosts: mysite
  remote_user: ubuntu
  sudo: yes

  roles:
    - nginx

  tasks:
    - name: ubuntu system upgrade
      apt: upgrade=dist

$ ansible-playbook mysite.yml -i etc/ansible/hosts --private-key=ansible-deploy.pem

PLAY [mysite] **************************************************

GATHERING FACTS ***************************************************************
ok: [XX.XX.XX.XX]

TASK: [ubuntu system upgrade] *************************************************
ok: [XX.XX.XX.XX]

PLAY RECAP ********************************************************************
XX.XX.XX.XX             : ok=2    changed=0    unreachable=0    failed=0


代表目標機器已經更新好系統了,而剛剛添加的 roles/nginx 目前還是個空殼所以沒有任何動作。

接著要研究一下 Nginx 官方安裝位置:http://nginx.org/packages 和 http://nginx.org/en/linux_packages.html 對照表。此例需要添加官方 repo 的原始指令方式:

$ vim /etc/apt/sources.list
deb http://nginx.org/packages/ubuntu/ trusty nginx
deb-src http://nginx.org/packages/ubuntu/ trusty nginx


指令方式:

$ echo "deb http://nginx.org/packages/ubuntu/ trusty nginx" | sudo tee -a /etc/apt/sources.list
$ echo "deb-src http://nginx.org/packages/ubuntu/ trusty nginx" | sudo tee -a /etc/apt/sources.list
$ sudo apt-get update


而在 ansible 則是透過:

- name: Add Nginx Official Repo - deb
  apt_repository: repo='deb http://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx' state=present

- name: Add Nginx Official Repo - deb-src
  apt_repository: repo='deb-src http://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx' state=present

# http://docs.ansible.com/ansible/apt_key_module.html
- name: Add Nginx Official Repo - package signing key
  apt_key: url=http://nginx.org/packages/keys/nginx_signing.key state=present

#- name: Add Nginx Official Repo - ppa:nginx/stable
#  apt_repository: repo='ppa:nginx/stable'

- name: Update cache
  apt: update_cache=yes

- name: Install Nginx
  apt:
    pkg: nginx
    state: installed


到現在為止,整個 nginx role 的安裝設定:

$ tree .
.
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   ├── main.yml
│   └── task-Ubuntu.yml
├── templates
└── vars
    └── main.yml

7 directories, 7 files

$ cat tasks/main.yml
---
# tasks file for nginx

- include: task-Ubuntu.yml
  when: ansible_distribution == 'Ubuntu'

$ cat tasks/task-Ubuntu.yml
---
# http://docs.ansible.com/ansible/apt_repository_module.html
- name: Add Nginx Official Repo - deb
  apt_repository: repo='deb http://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx' state=present

- name: Add Nginx Official Repo - deb-src
  apt_repository: repo='deb-src http://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx' state=present

# http://docs.ansible.com/ansible/apt_key_module.html
# $ curl -s 'http://nginx.org/packages/keys/nginx_signing.key' | sudo apt-key add -
- name: Add Nginx Official Repo - package signing key
  apt_key: url=http://nginx.org/packages/keys/nginx_signing.key state=present

#- name: Add Nginx Official Repo - ppa:nginx/stable
#  apt_repository: repo='ppa:nginx/stable'

- name: Update cache
  apt: update_cache=yes

- name: Install Nginx
  apt:
    pkg: nginx
    state: installed


其中 ansible_distribution_release, ansible_distribution 環境變數,可以透過 ansible -i host mysite -m setup 得知。接著再次執行 ansible-playbook ,過程就會安裝 nginx 啦(changed=4 都落在 nginx role 動作) :

$ ansible-playbook mysite.yml -i etc/ansible/hosts --private-key=ansible-deploy.pem

PLAY [mysite] **************************************************

GATHERING FACTS ***************************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb] *********************************
changed: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb-src] *****************************
changed: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - package signing key] *****************
changed: [XX.XX.XX.XX]

TASK: [nginx | Update cache] **************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Install Nginx] *************************************************
changed: [XX.XX.XX.XX]

TASK: [ubuntu system upgrade] *************************************************
ok: [XX.XX.XX.XX]

PLAY RECAP ********************************************************************
XX.XX.XX.XX             : ok=7    changed=4    unreachable=0    failed=0


最後要客製化 Nginx 的話,就變成要改寫設定檔了,改寫設定檔前,當然要來個設定檔測試,這時規劃在 roles/nginx/handlers/main.yml 設定一些事件處理:

$ cat handlers/main.yml
---
# handlers file for nginx

- name: set nginx auto start
  service: name=nginx state=started enabled=yes

- name: restart nginx
  service: name=nginx state=restarted

- name: test nginx config
  shell: service nginx configtest
  register: result
  changed_when: "result.rc != 0"
  always_run: yes


接著回到 mysite.yml 設定檔,可以添加:

- hosts: mysite
  remote_user: ubuntu
  sudo: yes

  roles:
    - nginx

  tasks:
    - name: ubuntu system upgrade
      apt: upgrade=dist update_cache=yes

    - name: ensure nginx auto start
      service: name=nginx state=started enabled=yes

    - name: test webserver configure files
      always_run: yes
      shell: date
      notify: test nginx config


如此一來,除了安裝 nginx 、更新系統外,還會多了測試 nginx configure files:

$ ansible-playbook mysite.yml -i etc/ansible/hosts --private-key=ansible-deploy.pem

PLAY [mysite] **************************************************

GATHERING FACTS ***************************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb] *********************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb-src] *****************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - package signing key] *****************
ok: [XX.XX.XX.XX]

TASK: [nginx | Update cache] **************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Install Nginx] *************************************************
ok: [XX.XX.XX.XX]

TASK: [ubuntu system upgrade] *************************************************
ok: [XX.XX.XX.XX]

TASK: [ensure nginx auto start] ***********************************************
ok: [XX.XX.XX.XX]

TASK: [test webserver configure files] ****************************************
changed: [XX.XX.XX.XX]

NOTIFIED: [nginx | test nginx config] *****************************************
ok: [XX.XX.XX.XX]

PLAY RECAP ********************************************************************
XX.XX.XX.XX             : ok=10   changed=1    unreachable=0    failed=0


這邊發動測試 nginx 測試檔是綁定在一個 date 指令上,因為 date 每次結果都不一樣,將導致永遠都是 changed=1 結果。以上就完成了建立一個 role 並且納入使用的方式。

接著試試設定的部分吧!把一些設定檔那來做模板(templates),未來可以透過引入 nginx role 時,搭配指定參數後,即可產生客製化的設定檔:

先將機器上的 nginx 設定檔搬到 roles/nginx/templates 中,且檔案結尾改成 .j2 ,這是因為 ansible template 採用 Jinja2 方案。

$ scp -r -i ansible-deploy.pem ubuntu@XX.XX.XX.XX:/etc/nginx/conf.d  roles/nginx/templates/
$ cp roles/nginx/templates/conf.d/default.conf roles/nginx/templates/default.conf.j2
$ tree roles/nginx/templates/
roles/nginx/templates/
├── conf.d
│   ├── default.conf
│   └── example_ssl.conf
└── default.conf.j2


之後就是把機器上的 default.conf 覆蓋掉或是刪掉並搭配新增一則 mysite.conf 來啟用 nginx 了,在此先沿用覆蓋方式。

接著在 mysite.yml 或是 roles/nginx/task/task-Ubuntu.yml 中,就可以引入從 template 取得資料來蓋掉系統檔案,若在 mysite.yml 中:

- name: Update Nginx configure files
  template: src=roles/nginx/templates/default.conf.j2 dest=/etc/nginx/conf.d/default.conf


在 roles/nginx/task/task-Ubuntu.yml:

- name: Update Nginx configure files
  template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf


通常都會寫在 roles/nginx/task/main.yml 為多,而上述是因為有偵測系統狀況決定 nginx 設定檔位置,因此我一樣寫在 task-Ubuntu.yml 中。接下來可以朝改寫 default.conf.j2 內變數地用法,將一些常見數值改成變動的,並且在 roles/nginx/defaults/main.yml 定義好,如此一來,在 mysite.yml 引用 roles nginx 時,也就可達成動態變動的方式。

例如:

$ tree .
.
├── ansible-deploy.pem
├── ansible-deploy.pub
├── etc
│   └── ansible
│       └── hosts
├── roles
│   └── nginx
│       ├── defaults
│       │   └── main.yml
│       ├── files
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── README.md
│       ├── tasks
│       │   ├── main.yml
│       │   └── task-Ubuntu.yml
│       ├── templates
│       │   ├── conf.d
│       │   │   ├── default.conf
│       │   │   └── example_ssl.conf
│       │   └── default.conf.j2
│       └── vars
│           └── main.yml
└── mysite.yml

$ cat roles/nginx/templates/default.conf.j2
server {
    listen       {{ nginx_listen }};
    server_name  {{ nginx_server_name }};

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   {{ nginx_document_root }};
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}


提供了 nginx_listen、nginx_server_name 和 nginx_document_root 三個變數,並且定義預設數值:

$ cat roles/nginx/defaults/main.yml
---
# defaults file for nginx
nginx_listen: 80
nginx_server_name: localhost
nginx_document_root: /usr/share/nginx/html


如此一來,在 mysite.yml 中,引入 roles 可以改成:

$ cat mysite.yml
---
- hosts: mysite
  remote_user: ubuntu
  sudo: yes

  roles:
    - { role: 'nginx', nginx_listen: 8080 }

  tasks:
    - name: ubuntu system upgrade
      apt: upgrade=dist update_cache=yes

    - name: test webserver configure files
      always_run: yes
      shell: date
      notify: test nginx config

    - name: reload webserver configure files
      always_run: yes
      shell: date
      notify: restart nginx


透過 ansible-playbook mysite.yml 後,可以去該 server:/etc/nginx/conf.d/default.conf 觀看到數值啦

$ ansible-playbook mysite.yml -i etc/ansible/hosts --private-key=ansible-deploy.pem
PLAY [mysite] **************************************************

GATHERING FACTS ***************************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb] *********************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - deb-src] *****************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Add Nginx Official Repo - package signing key] *****************
ok: [XX.XX.XX.XX]

TASK: [nginx | Update cache] **************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Install Nginx] *************************************************
ok: [XX.XX.XX.XX]

TASK: [nginx | Update Nginx configure files] **********************************
ok: [XX.XX.XX.XX]

TASK: [ubuntu system upgrade] *************************************************
ok: [XX.XX.XX.XX]

TASK: [ensure nginx auto start] ***********************************************
ok: [XX.XX.XX.XX]

TASK: [test webserver configure files] ****************************************
changed: [XX.XX.XX.XX]

TASK: [reload webserver configure files] **************************************
changed: [XX.XX.XX.XX]

NOTIFIED: [nginx | restart nginx] *********************************************
changed: [XX.XX.XX.XX]

NOTIFIED: [nginx | test nginx config] *****************************************
ok: [XX.XX.XX.XX]

PLAY RECAP ********************************************************************
XX.XX.XX.XX             : ok=13   changed=3    unreachable=0    failed=0

2015年11月11日 星期三

Ansible 筆記 - 透過 ansible 指令、ansible-playbook 執行批次腳本等用法快速上手 @ Ubuntu 14.04

剛接手一份用 Puppet 維護的服務,結果 Puppet 還沒玩熟,就先來改玩一下 Ansible,而 Ansible 也是一套機器部署的軟體,最大特色是不需要 master-slave(client) 架構,也就是被管理的機器不用安裝 ansible 啦!另外還有類似市集功能,例如你想要找 nginx 的設定方式,那只要上市集找一下,接著把它下載回來,套用一下,即可部署,十分便利。

首先先摸一下 ansible 指令,熟了再把玩 ansible-playbook 批次指令,之後再從 ansible-galaxy 從市集找設定檔。

安裝 ansible ( http://docs.ansible.com/ansible/intro_installation.html#id17 ):

$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible
$ ansible --version
ansible 1.9.4


接著,來試試 ansible 指令吧!這個指令的用法就像執行 ssh remote commands 一樣:

$ ansible localhost -m raw -a "date"
localhost | success | rc=0 >>
Wed Nov 11 11:01:21 UTC 2015

$ ansible localhost -m setup
...用 JSON Format 列出系統資訊...

$ ansible localhost -m setup | grep -i ubuntu
        "ansible_distribution": "Ubuntu",
            "description": "Ubuntu 14.04.3 LTS",
            "id": "Ubuntu",


然而,localhost 是一個默認的字眼,若要對遠端機器操作時,必須先寫定 hosts 對應表,預設是使用 /etc/ansible/hosts 位置,但也可以透過 -i filename 來使用,這裡使用 -i 來試試,並用 127.0.0.1 為例。

$ cat hosts
[webserver]
127.0.0.1

$ ansible -i etc/ansible/hosts webservers --list-hosts
    127.0.0.1

$ ansible -i etc/ansible/hosts webservers -m raw -a "date"
127.0.0.1 | FAILED | rc=255 >>

$ ansible -i etc/ansible/hosts --private-key=~/.ssh/id_rsa webservers -m raw -a "date"
127.0.0.1 | success | rc=0 >>
Wed Nov 11 11:27:36 UTC 2015

$ ansible -i etc/ansible/hosts --private-key=~/.ssh/id_rsa webservers -m setup | grep -i cpu
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz",
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz"
        "ansible_processor_vcpus": 2,


其中 -m 代表要採用的模組,而 -a 是該模組的參數資訊。 raw 代表 -a 後頭的指令就給他執行下去就對了。所以一些常用的 ssh remote command 則是可以用 -m raw 來替代。其中 --private-key 是指定登入用的 key,而 -u 還可以指定登入的使用者。

接下來透過 yml 檔案描述來批次處理大量指令:

$ cat webserver.yml
---
- hosts: webserver
  tasks:
  - shell: date

$ ansible-playbook -i etc/ansible/hosts --private-key=~/.ssh/id_rsa webserver.yml
PLAY [webserver] **************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [shell date] ************************************************************
changed: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1            : ok=2    changed=1    unreachable=0    failed=0


以上是非常簡單的批次任務,在複雜下去之前,先介紹一招透過 yml 檔案來新增 ssh remote key 方式(等同於 ssh-copy-id 功能):

$ cat add_authorized_key.yml
- hosts: '{{host}}'
  remote_user: '{{user}}'
  vars:
      ssh_private_key_path: '{{ ssh_key_file }}'

  tasks:
  - name: Add RSA key to the remote host
    authorized_key: user='{{user}}' key="{{lookup('file', ssh_private_key_path )}}"

$ ansible-playbook add_authorized_key.yml -i hosts

PLAY [{{host}}] ***************************************************************
skipping: no hosts matched

PLAY RECAP ********************************************************************

$ ansible-playbook add_authorized_key.yml -i hosts --ask-pass --extra-vars "user=ubuntu host=localhost ssh_key_file=ansible-deploy.pub"                                                                                                            
SSH password:

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Add RSA key to the remote host] ****************************************
changed: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0


這個過程就是透過 add_authorized_key.yml 腳本,以及搭配的參數去執行,將 ansible-deploy.pub 檔案添加至 ubuntu@localhost 的 ~/.ssh/authorized_key 且確保此動作重複執行也不會添加重複筆數,在執行一次得到的結果:

$ ansible-playbook add_authorized_key.yml -i hosts --extra-vars "user=ubuntu host=localhost ssh_key_file=ansible-deploy.pub"                                                                                                            
SSH password:

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Add RSA key to the remote host] ****************************************
changed: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0


可以清楚看到最後一個回報的 changed=0 ,代表此執行執行成功但沒有改變東西。且由於 key 已經添加,這次可以去掉 --ask-pass 的用法。這件事代表可以每次都重跑一樣的工作,但已經生效的不會再重做。

接著來寫個範本是每次執行都會把 EC2 系統更新至最新版(-u 代表要用 ubuntu 帳號登入,-s 則是用 sudo 執行):

$ cat update-ec2-ubuntu.yml
---
- hosts: ec2-servers
  tasks:
  - apt: upgrade=dist

$ ansible-playbook update-ec2-ubuntu.yml -i hosts --private-key=ansible-deploy.pem -u ubuntu -s
PLAY [ec2-servers] **************************************************

GATHERING FACTS ***************************************************************
ok: [XX.XX.XX.XX]

TASK: [apt upgrade=dist] ******************************************************

changed: [XX.XX.XX.XX]

PLAY RECAP ********************************************************************
XX.XX.XX.XX             : ok=2    changed=1    unreachable=0    failed=0


同理再跑一次,可以看到 changed=0,代表第二次已沒有需要更新的。

未來則就可以依照需求撰寫各台機器的部署腳本,其中還有更豐富的 roles 跟 ansible-galaxy 還沒把玩,晚點再來試試吧。

2015年11月10日 星期二

[Linux] 架設 Jenkins 筆記,以 Git plugin 與 PHP CodeIgniter - command-line interface (CLI) 定期任務為例 @ Ubuntu 14.04

架設還滿簡單的,幾行指令搞定:

$ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
$ sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins
$ sudo service jenkins start


如此一來,預設在 http://localhost:8080 就可以瀏覽到。

接著安裝一些工具,之後會用到:

$ sudo apt-get install git

接著紀錄一下自己的操作設定:
  • 管理 Jenkins -> 設定全域安全性
    • 勾選 Disable remember me
    • 安全性領域
      • 使用 Jenkins 內建使用者資料庫
    • 授權
      • 矩陣型安全性
        • 關閉 匿名使用者 所有權限
  • 管理 Jenkins -> 管理外掛程式
    • 更新
      • 把所有項目更新
    • 可用的
      • 搜尋 GIT plugin 跟 GIT client plugin 並安裝(若系統沒有 git,安裝完可以在 Jenkins 組態裡看到一些錯誤訊息)
其中授權那塊,必須先建立使用者,可以先從"登入成功的使用者可以做任何事"開始設定,過程會導入到建立使用者的流程。若有設定錯誤的地方導致無法管理時,可以修改 /var/lib/jenkins/config.xml 將 <useSecurity>true</useSecurity> 改成 <useSecurity>false</useSecurity> 後,再重新啟動 jenkins (sudo service jenkins restart)即可解決。

如此一來,就建立好 Jenkins 環境,而新工作也能夠用 git 了!擬個範例試試:假設專案在 bitbucket 管理,並使用 PHP CodeIgniter 架構,定期透過此專案來執行分析任務

作法:
  • Jenkins -> 新增作業 -> 填寫作業名稱(StudyJenkinsRoutine) -> 建置 Free-Style 軟體專案
    • 原始碼管理
      • Git
        • Repository URL: git@bitbucket.org:group/project.git
        • Credentials -> Add -> SSH Username with private key -> Enter directly (搭配 Bitbucket SSH 存取即可)
        • Additional Behaviours -> Advanced sub-modules behaviors -> 勾選 Recursively update submodules
    • 建置觸發程序
      • 定期建置(每十五分鐘跑一次,語法跟 crontab 一樣,但會建議用 H/15 來使用)
        • */15 * * * *  
    • 建置
      • 執行 Shell
        • php $WORKSPACE/index.php controller/function
如此一來,透過 Jenkins 的 Web 介面就可以設定與執行一些功能了,唯一留意的是執行工作上是否擁有相關的環境資源,例如範例是執行 PHP Framework 做事,那就得確保 php5-cli 裝了沒,若做的事跟資料庫相關,又得確定 php5-mysql 裝了沒等等。此外,上頭執行的 Shell 有用到 Jenkins 環境變數,要留意有些資料是跟 Jenkins 建立的工作名稱是相關的,例如工作名稱若有空白、等號以及相關的特殊符號時,極有可能會影響 shell script 的執行的。

關於 Jenkins 相關的路徑安排都跟 jenkins 帳號相關,例如 Jenkins 家目錄在 /var/lib/jenkins ,而添加一個任務名為 StudyJenkinsRoutine 時,其 $WORKSPACE 會是 /var/lib/jenkins/jobs/StudyJenkinsRoutine/workspace 的,這個位置也是 git clone 的資料所在。

最後,如果 Jenkins 是架設在 AWS EC2 上,若可以搭配 ELB 跟 SSL 憑證時,可以偷懶使用 ELB 將 https 流量導向到 Jenkins 8080 ,可以無痛提供 https 服務囉。

2015年11月4日 星期三

[PHP] 把玩 PHP AWS SDK - 列出 EC2 指定規格列表、 ELB 底下的機器列表 @ Ubuntu 14.04

之前用一些 tool-based 的工具做了一些事情,例如呼叫完指令再動態抽 JSON 資料:
  • $ aws elb describe-load-balancers --load-balancer-name "XXX"
  • $ aws ec2 describe-instances --instance-ids  "XXX"
來試試 AWS SDK 來做事吧,先挑 PHP !

為了高移植性,我採用下載 aws.phar 的模式:
接著則是簡單的登入資料填寫一下:

<?php
require 'aws.phar';

$config = array(
'version' => 'latest',
'credentials' => array(
'key' => 'key',
'secret' => 'secret',
),
'region' => 'us-west-2',
);


列出 EC2 - m1.small instance:

<?php
$ec2Client = Aws\Ec2\Ec2Client::factory($config);

// http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Ec2.Ec2Client.html
$result = $ec2Client->DescribeInstances(array(
        'Filters' => array(
                 array('Name' => 'instance-type', 'Values' => array('m1.small')),
        )
));

print_r($result);


想要列出 EC2 - 指定 Load Balancer 下的機器:

<?php
$client = Aws\ElasticLoadBalancing\ElasticLoadBalancingClient::factory($config);
$result = $client->DescribeLoadBalancers( array(
        'LoadBalancerNames' => array('Load Balancer Name')
));
print_r($result['LoadBalancerDescriptions'][0]['Instances']);
print_r($result);


其中,雖然 $result 都是 Aws\Result Object ,且裡頭都是 [data:Aws\Result:private] => Array ,但可以透過 array access 的方式去存取囉。

接下來就可以試試連續動作,從 ELB 得知機器後,再得到機器的 public ip:

<?php

require 'aws.phar';

$ELB_NAME = 'XXXX';
$client = Aws\ElasticLoadBalancing\ElasticLoadBalancingClient::factory($config);
$result = $client->DescribeLoadBalancers( array('LoadBalancerNames' => array($ELB_NAME)));
if (isset($result['LoadBalancerDescriptions']) && is_array($result['LoadBalancerDescriptions']) && count($result['LoadBalancerDescriptions']) && isset($result['LoadBalancerDescriptions'][0]['Instances'])) {
$instances = $result['LoadBalancerDescriptions'][0]['Instances'];
//print_r($instances);
$ec2_id = array();
foreach($instances as $ec2)
if (isset($ec2['InstanceId']))
array_push($ec2_id, $ec2['InstanceId']);
if (count($ec2_id) > 0) {
$client = Aws\Ec2\Ec2Client::factory($setup);
$result = $client->DescribeInstances(array(
'Filters' => array(
array('Name' => 'instance-id', 'Values' => $ec2_id),
)
));
}
$public_ip = array();
if (isset($result['Reservations'])) {
foreach($result['Reservations'] as $target) {
//print_r($target['Instances'][0]['PublicIpAddress']);
array_push($public_ip, $target['Instances'][0]['PublicIpAddress']);
}
}
//print_r($result['Reservations']);
print_r($public_ip);
}

2015年11月3日 星期二

[Linux] 透過 rpmbuild 建立 RPM @ CentOS 6.6

RPM 的製作過程真叫人又愛又恨 XD 好多細節啊。例如執行 rpmbuild 的角色,通常會在家目錄出現 rpmbuild 目錄結構等,整體上建立 rpm 有四個步驟:
  1. 建立相關的目錄結構  rpmbuild/BUILD rpmbuild/BUILDROOT rpmbuild/RPMS rpmbuild/SOURCES rpmbuild/SPECS  rpmbuild/SRPMS
  2. 將資料擺進 rpmbuild/SOURCES 位置
  3. 撰寫 rpmbuild/SPECS/example.spec
  4. 切換進 rpmbuild/SPECS 執行 rpmbuild -bb example.spec
若上述一切正常,在 rpmbuild/RPMS/ 裡的目錄長出 rpm 檔案。

這邊要筆記的是 example.spec 這個檔案格式:
  • % 開頭的是 spec 的保留指令(Macro),例如 %define 是定義變數,而 %description, %prep, %setup, %build, %install, %files, %changelog, %clean 則是對應的狀態
    • %prep 下方的位置代表預備動作
    • %setup 代表進行 Source 解壓縮
    • %build 例如執行 make 指令
    • %install 開始執行建立 RPM 的動作,可把所需檔案進行搬移
    • %files 成列出真正要打包的檔案列表,若沒列的話,RPM 會產生不了
    • %clean 打包完 rpm 後的動作,例如清掉資料等
  • 其他資訊
除了這些以外,spec 還定義了 package info:
  • Summary: 
  • Name:
  • Version: 1.0
  • Release: 1
  • Vendor: vendor
  • Packager: packager
  • License: BSD
  • Group: Applications/File
  • SOURCE: your_source_be_extraced_at_setup_macro.tar.gz
  • BuildArch: noarch
  • BuildRoot: %BuildRoot
範例:

%define Name test-repo
%define Source test-repo.tar.gz
%define Version 1.0
%define Release 1
%define RPM_ARCH x64_86
%define OWNER root
%define Vendor no
%define Packager no
%define License MIT
%define Group Applications/File

%define INSTALL_DIR /opt/%NAME

%define _topdir /tmp/rpm-build
%define RPM_BUILD_ROOT _topdir
%define BuildRoot /tmp/rpm-build/BUILDROOT/%Name-%Version-%Release.%RPM_ARCH

Summary: %Name
Name: %Name
Version: %Version
Release: %Release
Vendor: %Vendor
Packager: %Packager
License: %License
Group: %Group
SOURCE: %Source

%description

%prep

%setup -q

%build

%install
install -d %BuildRoot/%INSTALL_DIR
cp -r $PACKAGE_DIR/*.* %BuildRoot/%INSTALL_DIR

%files
%INSTALL_DIR
%defattr(-,%OWNER,%OWNER,-)

%changelog


最後,我打包成一個 bash script 來筆記 :p 有需要可以試試看,但要留意 bash script 有刪檔的動作,若擔心可以先把刪檔的動作註解起來:

$ git clone https://github.com/changyy/rpm-builder
$ cd rpm-builder
$ bash rpm_build_for_files_archive.sh
Usage> bash rpm_build_for_files_archive.sh SOURCE_DIR RPM_OUTPUT_DIR RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_VERSION RPM_PACKAGE_INSTALL_DIR

$ bash rpm_build_for_files_archive.sh /etc/yum.repos.d/ /tmp test-yum 1.0 1 /opt


產出 /tmp/test-yum-repos-1.0-1.noarch.rpm ,會安裝在 /opt/test-yum 目錄

最後提一下 rpm 相關指令,方便 debug 用途:
  • 安裝
    • $ rpm -ivh your.rpm
  • 解除安裝 
    • $ rpm -e your_package_name
  • 查詢描述資料
    • $ rpm -qi your_package_name
  • 列出 rpm 所安裝的檔案清單
    • $ rpm -q --filesbypkg your_package_name
  • 查詢檔案是屬於哪個 rpm 
    • $ rpm -qf /opt/path/filename
  • 列出所有已安裝的 rpm 清單,可搭配 grep 挑選關鍵字出來
    • $ rpm -qa