Search Google

Friday, November 27, 2015

BJ4...

BJ4...

Not so long ago...

Ways of doing DevOps

Remove blocking factors on artifact

Remove blocking factors on human resource

Remove blocking factors on environment

Life-cycle for a CR used to be

New life-cycle for a CR

I am not a DevOps engineer


圖片來源:

  • http://iosallinone.blogspot.tw/2014/06/5-favorite-devops-memes.html
  • http://www.devopsdays.org/events/2013-mountainview/
  • http://frankhinek.com/wp-content/uploads/2014/10/2014-10-07_devops-tools-feat.png
  • https://developer.ibm.com/bluemix/2015/05/06/share-xcode-projects-bluemix-devops-services/
  • http://dev2ops.org/wp-content/uploads/2014/06/DevOpsEntOpsObjects.jpg
  • http://devops.com/2014/03/27/devops-lessons-learned-the-devops-engineer/
  • http://peggyriley.com/2015/09/06/the-shark-and-the-iceberg-2/


Sunday, September 27, 2015

[How-To] 在Mac OSX下使用雙網卡連內外網

今天要跟各位捧有們分享如何在Mac OSX下使用雙網卡同時連上內外網
是的, 我已經聽到各位心中的疑惑 -- 這麼簡單的事情也需要你來分享?!
沒錯, 在Windows / Linux下只需要透過route add / route delete的指令就可以辦到, 但是在Mac OSX中我試過了就是不管用, 上stackoverflow發問還被標負評, 在這裡先向以前被我不相信的捧油們說聲抱歉!

好的, 在Mac OSX下揪竟要下什麼指令才能夠達成使用雙網卡同時連上內外網呢?
當然route add還是需要的, 只不過在Windows / Linux下使用的route delete就要改成route flush...
WTF?! route的manual裡的說明看起來delete跟flush明明是一樣的作用, 只不過delete只刪一個routing gateway而flush是把整張routing table中的gateway設定全部清掉, 如下圖:

圖一

以下是實驗的結果
首先先讓Mac同時連上LAN與WiFi, 從下圖可以看到LAN (en5)與WiFi (en0)同時都在連線
圖二
192.168.0.1是家中的寬頻分享器, 192.168.43.1則是手機分享出來的WiFi熱點, 我們先用ping看看Internet與Intranet的連線狀況
圖三
很好, 都有通, 因為二者都能上Internet所以用traceroute檢查到底是走一張網卡出去
圖三之一
很不幸, 剛才走的en5, 這樣完全沒有達到雙網卡的目的
為了要確定Internet的traffic是從en0出去, 我們先用route delete指令將en5的default routing拿掉
route delete -net 0.0.0.0 192.168.0.1
於是routing table變成下圖的樣子, default routing通通走到en0去
圖四
這時候完全ping不到google >"<
圖五
如果我們改用route flush呢?
route -n flush
flush之後的routing table裡面完全看不到default gateway的設定
圖六
接著我們用routing add把自己需要的routing再加回去
route add -net 0.0.0.0 192.168.43.1
route add 192.168.0.0/16 1921.68.0.1
輸入完上面的指令後我們會看到routing table其實跟圖四一樣
圖七
這時候我們再用ping測試會看到Intetnet與Intranet都通了!
圖八
再用traceroute檢查確定往google的traffic走的是en0
圖八之一
這次traffic總算是走en0到google, 以上就是今天的分享

至於為什麼route delete不能用而route flush管用?! 讓我們再找時間一起慢慢參透~

Monday, August 17, 2015

object xxx corrupted on Git server...

下午完成今天預定的SIT測項回到專案室後不久就聽到有人在召喚我 -- "James, 連不上Git啦"

心想該不會是server重開之後IP又跑走了吧, 接著putty借由顯示出login提示字元馬上打槍了, 我的第一個猜測, 嘴巴不禁嘀咕著 -- "那我們就來fetch all看看吧", 話才剛說完就立刻看到下面的錯誤訊息:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
"C:\Program Files (x86)\Git\bin\git.exe" fetch --progress "--all"
Fetching origin
fatal: object 43670bde54a8e639e3ad06e0ca9b95f3e8d790e8 is corrupted
fatal: Could not read from remote repository.


Please make sure you have the correct access rights
and the repository exists.
error: Could not fetch origin
Done
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
反正出來跑遲早要還, 怎麼還? 通常問Google就好了
沒想這個錯誤居然是如此的generic, 可能造成的原因一籮筐, 找了半天看到一堆git指令
git fsck --full
git cat-file xxx
git repack
git ...
等做法, 但是沒一個管用的, 不過倒是對一個關鍵字印象深刻 -- "empty file"
好吧, 那就試試看把這些empty file先備份再移除看看會發生什麼事情, 但是找了半天卻找不到傳說中名稱為"43670bde54a8e639e3ad06e0ca9b95f3e8d790e8"的檔案, 說時遲那時快, 看到objects目錄下有一堆二位數hex編碼的目錄, 想說好吧那就來找找"./43/670bde54a8e639e3ad06e0ca9b95f3e8d790e8", 果然一猜就中(樂透運都這樣被用掉了吧), 仔細一看檔案大小果然是0 byte, 移除之後很開心地執行git fsck想說這樣就結束了...
事情果然沒有"拱廊"所想的那麼"甘丹", 又看到下一個object xxx is corrupted!
就這麼輪迴幾次後終於受不了, 最後大開殺戒以find . -size 0K -exec rm -f {} \;做了結.
把empty file清乾淨之後馬上又做一次git fetch --all, 立即看到不同的錯誤(表示有進展了, 值得開心 ~~), 這次的錯誤是reference的hash不存在, 好在這個提示就夠清楚明白, 把refs目錄下面meta data file裡的hash換成第二新(僅次於43670bde54a8e639e3ad06e0ca9b95f3e8d790e8)的hash後再執行git fetch --all果然可以用.
接著找出最後commit + push的人並把該更新的檔案重新commit + push一次, 終於替拯救Git server行動劃下完美句點.

Thursday, July 30, 2015

淺談Context based Java batch自動測試與JMX

今天要跟大家分享目前自動測試Context based Java batch的做法與使用的工具.  這裡說的Context based Java batch指的是所有batch job都是從Spring context將MBean export後透過JMX呼叫執行.  說到JMX第一個想到的通常就是JConsole.


我們的案例中export出三個MBean, JmxJobListMBean是用來檢視job清單, JmxJobRunner是用來執行job.

透過JmxJobListMBean的listJob可以得到一份job名稱的清單.

知道要執行的job名稱後再呼叫JmxJobRunner的runJob來執行job名稱對應的service.

將job名稱與參數分別填入p1, p2欄位後執行runJob即可取得執行結果

到目前為止我們已經透過JConsole呼叫MBean export出來的功能成功地執行batch job, 但是使用JConsole代表著需要人工執行, 如果不想自己寫code但又想要透過script自動執行驗證時又該怎麼做呢?  這時候我們可以用Jmxterm來達成, 下面是透過Jmxterm執行上述batch job的做法

首先使用下列指令建立與JMX server的連線
java -jar jmxterm-1.0-alpha-4-uber.jar -n -u ${user} -p ${password} -l ${jmx_server_ip}:${jmx_server_port}

接著執行下列指令取得job名稱清單
 run -b bean:name=JmxJobListMBean -d bean listJob

最後執行下列指令將參入帶入job名稱對應的service並執行
 run -b bean:name=JmxJobRunner -d bean runJob ${job名稱} ${參數}

下圖中有上述指令與執行結果


OK, 現在我們可以不用人工的方式透過JMX執行batch job了, 接下來我們要再結合JMeter達成自動執行+驗正執行結果.  我們會用到JMeter的OS process sampler執行上述指令, 待OS process sampler執行結束後再搭配其他sampler (eg. JDBC)或是單純使用post process assertion檢查執行結果是否如預期.


搭配JMeter OS process sampler後比較特別的地方是在原本與JMX server建立連線的指令後面多加了"-i jmxterm.txt", 這個新加的參數表示會把jmxterm.txt檔案內容餵進與JMX server建立的連線中執行.  所以jmxterm.txt的內容就是執行runJob的指令, eg.
run -b bean:name=JmxJobRunner -d bean runJob ${job名稱} ${參數}



Saturday, July 18, 2015

Bluemix業配文+入門教學

身為I社的一份子, 當公司全力在推CAMSS的時候一定也要來盡點心力, 我想大家對於中規中舉的介紹早已麻木, 所以就讓擅長打野武士戰法的我來跟大家介紹如何開開心心地以非正規的方式使用Bluemix提供的免費功能~

今天要介紹的功能是大部分webapp所環繞著的三大要素
1. Runtime server
2. Git server
3. DB server

1. Runtime server目前涵蓋了以下幾種大家常見的環境:
雖然我個人偏好在local跑Runtime server, 畢竟要設定或debug時還是比較方便, 但是如果可以在Bluemix上面跟客戶做完最後一哩路測試等於可以省去系統轉移+後續測試所需的工, 因為測試完之後只需要將帳號轉移給業主管理就結束了, 光是這點我想對許多SOHO族是相當有利, 而業主每個月付的費用就是原本需要花費的web hosting service費用.


想知道更多關於如何開始使用Runtime server請點這

2. 為什麼要特別提到Git server呢? 不就是做版本控管嗎?
是的, 在開發的過程中大家多多少少會需要做source code的版本控管, 也因為近年來許多opensource project陸續放到GitHub上讓越來越多人使用Git做版本控管.
要使用Git做版本控管一定要有個Git server, 如果用免費版的GitHub就表示所有放上去的source code自動成為opensource, 如果不想讓自己的source code變成opensource通常有兩種方式: (a) 付錢成為GitHub的付費使用者就可以把repository/project轉成私人模式, (b) 自己架Git server.
對於不想付費又不想自己架Git server的使用者而言, Bluemix提供的DevOps服務就顯得格外有用. 透過Bluemix的DevOps服務可以建立private Git server做版本控管同時保有source code的ownership.
想知道如何從local git client使用Bluemix提供的Git server請點這

3. webapp絕大部分應該都會需要用到DB, 以往我們難免需要自己在local電腦上架個DB server或付費租用線上DB才能開始開發測試. 今天Bluemix真正實現了"只要有心人人都可以有100MB的免費DB空間可用"!
這個部份比較tricky, 正規文件裡面並沒有特別說明(匆匆帶過倒是有), 所以在這裡特別說明如何從local端存取Bluemix提供的DB instance.
首先我們需要先有一個Runtime server instance (可以參照第1點結尾的連結), 這樣申請下來的DB server才有地方可掛 --> 才有地方可以看設定.
接著點擊上圖紅色框框申請DB server instance, 要注意的是下圖中的兩個紅色框框. 上面的紅色框框指定新申請的DB server instance要掛到哪一個Runtimer server instance, 下面的紅色框框指名要使用免費方案 --> 100MB空間 + 10 concurrent connections
到目前為止我們知道我們有了一個Runtime server + 一個DB server, 接下來我們要透過Runtime server的設定取得DB server的連線資訊. 從Bluemix的儀表板中看到一個Runtime server instance:

點進上圖下方紅色框框代表的Runtime server instance之後可以看到該instance的配置
到這裡我們就已經快要完成取經任務, 只要再點進上圖中左方panel中的"環境變數"就可以看到DB的設定參數!

有了上圖中右邊兩個紅色框框的資訊我們就可以從local直接透過Internet存取這100MB的free DB.

當然, 不把DB掛進Runtime server也可以透過DB service提供的web UI進行"簡單"的操作
如果想要透過這個web UI匯入格式稍微複雜一點的資料就會碰壁, web UI畢竟無法提供command line指令的細顆粒度微調, 所以我還是偏好直接透過Data Server Runtime Client直接建立remote connection操作的野武士戰法.

相信沒有直接按"End"鍵一路看到這裡的捧友們此時對於如何使用Bluemix提供的service已經有更深一層的了解, 雖然不是太正規的用法, 但是我相信對於中小企業的企業主與SOHO族們應該相當有幫助.

我們下回見~

Thursday, April 23, 2015

距離上次分享Linux container相關文章已經五年多了, 沒想到五年後居然有人用Linux container搞出了大名堂, 是的, 就是Docker!  最近越來越常聽到大家在討論Docker, 但是也很常聽到有人在問Docker跟VM到底哪裡不同.


舉個例子來說明:

在以前如果想要在同一台電腦上面同時虛擬化AP server + APP, DB, Mail server applications, 我們需要在Hosting OS上面跑三個VM instances (如下圖左邊的VMs), 每一個VM instance雖然只執行各自被指派的任務 (如下圖左邊填滿橘色, 綠色, 灰色的部分), 但是從OS層來說卻是在同一台實體機器上執行了四份OS, 相同的libraries被重覆載入四次 (如下圖左邊藍色的部分), 所以記憶體, CPU等資源等於浪費了.

有了Container (如下圖右邊的Containers)我們就不需要浪費資源在各application共用的部分, 下圖右邊的Containers所要表現的就是我們不再需要為了執行虛擬化的application而重複地在各個虛擬環境中執行OS, 各虛擬環境透過使用Hosting OS已經載入過的libraries替我們節省實體機器上的資源, 當然, 這只是眾多優點中的一個而已.


另外一個優點就是透過maintain Dockerfile (點我看sample)能幫助我們更清楚地知道每個application的環境是如何建立出來的, 包含需要安裝哪些套件, 需要先設定什麼樣的參數與執行什麼樣的指令.  
Dockerfile中可以reference既有的docker image讓我們動態且快速的調整出不同情況下所需的虛擬環境, 而且Dockerfile很小的文字檔, 需要的人很快就可以取得並在自己的環境把image build出來, 而不需要隨便就傳個幾GB的流量.

概念上的說明進行到這裡就好, 關於Docker的基本設定+使用google已經提供很多資訊了, 下面是我實際設定+使用過程中預到的問題以及小筆記:


// unable to run firefox from docker

// configure docker to use devicemapper rather than aufs (某些application需要在devicemapper模式下才能在docker中執行, eg. DB2)
https://gist.github.com/pcolazurdo/e61cfb84812a70b93e74
umount -l $(grep 'aufs' /proc/mounts | awk '{print $2}' | sort -r)
rm -rf /var/lib/docker
vi /etc/init.d/docker
touch /var/lib/boot2docker/profile
在profile中加入
#!/bin/sh
EXTRA_ARGS="--storage-opt dm.basesize=20G --storage-driver=devicemapper"

// create local docker registry (for local push/pull, 如果想讓開發測試團隊在內網就能夠分享docker images, 自己建個docker registry是個不錯的選擇)
http://cloudcounselor.com/2014/01/07/docker-private-registry-on-centos-rhel-6-5/

// private docker-registry
yum install -y docker-registry
default port: 5000
default repository location: /var/lib/docker-registry
編輯/var/lib/boot2docker/profile:
EXTRA_ARGS="--storage-opt dm.basesize=40G --storage-driver=devicemapper --insecure-registry localdocker:5000"
編輯/etc/hosts:
{intranet IP} localdocker
編輯/etc/hosts後要重啓docker:
/etc/init.d/docker stop
/etc/init.d/docker start
push to private docker-registry: docker push localdocker:5000/{repository}:{tag}
pull from private docker-registry: docker pull localdocker:5000/{repository}:{tag}

// docker-registry rest api (用來管理local docker registry裡的docker images+版本)
https://docs.docker.com/reference/api/registry_api/#delete-a-repository-tag
eg. get tags of mydb2:
GET http://localdocker:5000/v1/repositories/library/mydb2/tags
eg. remove ssosdpbase tag from db2-trinity:
DELETE http://localdocker:5000/v1/repositories/library/mydb2/tags/base
remove repository:
DELETE http://localdocker:5000/v1/repositories/mydb2