AWS Chef ตอน 4 : deploy your website

เอาล่ะ!!! และแล้วก็มาถึงขั้นตอนการติดตั้ง website ของเรากันแล้วนะครับ เสร็จจากตอน 3 ทุกคนควรจะมี instance ของตัวเองรันบน aws พร้อมกับ new user directory แล้วก็ folder ที่เก็บเว็บไซ์ที่เราสามารถ access ได้ผ่าน url กันแล้วนะครับ

มาถึงรอบนี้ ผมจะขอแนะนำการ deploy ด้วย chef และ git ซึ่งข้อดี คือ คุณสามารถจะเก็บ site ของคุณไว้บน repository ได้ไม่หายไปไหน ทำงานจากที่ไหนก็ได้ฮะ

  1. เร่ิมด้วยไปสมัคร account ของ bitbucket นะครับ (ที่ใช้ก็เพราะมันเป็น private repo คนอื่นมาดูของเราไม่ได้)
  2. เริ่มจัดการเรื่องของ ssh private/public key ที่ใช้ access git นะครับ อ้างอิงได้จาก ที่นี่ ทำตามขั้นตอนในนั้นจนจบเลยครับ โดยนิดนึงตอนรัน ssh-keygen อย่าใส่ passphrase ครับ ให้กด enter ผ่านไปเลย เราจะได้  private/plublic key มา (id_rsa.pub & id_rsa) และที่สำคัญอย่าลืมเอา id_rsa.pub (public key) ไปโปะบน bitbucket ของเราด้วยนะครับ ไม่งั้นก็จะ access ผ่าน ssh จาก node ด้วย id_rsa (private key) ไม่ได้ครับ
  3. จากนั้น เพื่อความปลอดภัย เราจะ encrypt ตัว private key และ public key ไว้ อีกขั้นหนึ่ง เราจะถือ secret key file ไว้อันนึง ซึ่งจะต้องเอาไปใช้ในการ decrypt เอา private key ออกมาใช้บน node นั้นๆครับ
    1. เริ่มด้วยสร้าง secret key file ของเราครับ
      openssl rand -base64 512 > ~/Workspace/chef-repo/.chef/encrypted_data_bag_secret
      
    2. เราจะสร้าง data_bag ซึ่งใช้เก็บ private/public key ของเรา โดยมี secret key file มา encrypt ข้อมูลของเราอีกครับ
      1. จำ id_rsa.pub และ id_rsa
        cat ~/.ssh/id_rsa.pub
        sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g' ~/.ssh/id_rsa
        
      2. เซต default editor
         export EDITOR='vim' 
      3. สร้าง data_bag ด้วยคำสั่ง knife ซึ่งจะเปิด editor ขึ้นมาให้เราเอาข้อมูล id_rsa.pub และ ​id_rsa ไปใส่
        cd ~/Workspace/chef-repo
        knife data bag create –secret-file .chef/encrypted_data_bag_secret secrets sshkey
        
        {
        "id":"sshkey"
        "id_rsa.pub":"<your key>"
        "id_rsa" : "<your key>"
        }
        
      4. เซฟแล้วปิด เราก็จะได้ databag มาอยู่ใน data_bags/secrets/sshkey.json ครับ ซึ่งลองเปิดดูข้างในก็จะถูก encrypt ไปซะแล้ว ต้องใช้คำสั่งข้างล่าง + secret key file ถึงจะสามารถดูข้างในได้ครับ
        knife data bag show --secret-file .chef/encrypted_data_bag_secret secrets sshkey
        
      5. จากนั้นก็ export ออกมาใส่ไว้ใน folder เพื่อใช้ในภายภาคหน้า
        cd ~/Workspace/chef-repo/
        mkdir -p data_bags/secrets
        knife data bag show secrets sshkey -Fj > data_bags/secrets/sshkey.json
        
    3. แล้วก็มาต่อด้วยการใช้ databag ที่เราสร้างขึ้นที่มีข้อมูลของ id_rsa และ id_rsa.pub ไปเปาะลง node ของเรากันครับ
      1. สร้าง template สำหรับ id_rsa.pub file และ id_rsa file
        cd ~/Workspace/chef-repo/cookbooks/mysite
        mkdir -p templates/default
        cd templates/default
        echo "<%= @public_key %>" > id_rsa.pub.erb
        echo "<%= @private_key %>" > id_rsa.erb
        
      2. เพิ่มส่วน โปะ private key และ public key ลงใน cookbook
        # dealing with ssh private/public key for accessing git
        # create directory .ssh
        directory "#{mysite_root}/.ssh" do
         owner mysite_user
         group mysite_group
         mode "0700"
        end
        
        # add id_rsa.pub & id_rsa to .ssh to access git freely
        sshkey = Chef::EncryptedDataBagItem.load("secrets", "sshkey")
        template "#{mysite_root}/.ssh/id_rsa.pub" do
         source "id_rsa.pub.erb"
         owner mysite_user
         group mysite_group
         mode "0600"
         variables :public_key => sshkey['id_rsa.pub']
        end
        
        template "#{mysite_root}/.ssh/id_rsa" do
         source "id_rsa.erb"
         owner mysite_user
         group mysite_group
         mode "0600"
         variables :private_key => sshkey['id_rsa']
        end
        
      3. ส่ง secret key file ไปให้ ​node
        # send secret key file to node
        rsync -avz -e "ssh -i ~/.ssh/<chef private key>.pem" .chef/encrypted_data_bag_secret ubuntu@<your node ip>:/tmp
        # access node and move file to the right place
        ssh -v -i ~/.ssh/<chef private key>.pem ubuntu@<your node ip>
        sudo mv /tmp/encrypted_data_bag_secret /etc/chef
        
  4. ต่อมา เราจะต้องเพิ่ม bitbucket เป็น known_hosts บน node ของเราก่อนนะครับ หากเราลองดูเองโดยปกติ ถ้าไป ssh ไปที่ host ไหนเป็นครั้งแรก จะต้องมีถามเสมอว่า yes/no เสมอ เพื่อจำ fingerprints ของ host นั้นๆ ซึ่ง chef ไม่สามารถตอบ yes/no ได้เอง ดังนั้น เราต้องใช้ workaround ใส่ known_hosts เข้าไปเองดังนี้ครับ
    # add bitbucket host to ssh known_hosts file
    bitbucket_host = "bitbucket.org"
    bitbucket_key = `ssh-keyscan #{bitbucket_host} 2>&1`
    ssh_known_hosts_file = "#{mysite_root}/.ssh/known_hosts"
    bitbucket_only_key = bitbucket_key.split("\n")[1] || ''
    
    bash "insert_known_host" do
      user mysite_user
      code <<-EOS
        echo "#{bitbucket_only_key}" >> "#{ssh_known_hosts_file}"
      EOS
      not_if "grep -q '#{bitbucket_only_key}' '#{ssh_known_hosts_file}'"
    end
    
    # add git package then use git to sync files to targeted directory
    package 'git'
    git_repo = "git@bitbucket.org:<your_username>/<your_repo_name>.git"
    git "#{mysite_root}/web_src" do
     repository git_repo
     reference "master"
     user mysite_user
     group mysite_group
     action :sync
    end
    
  5. โค้ดเป็นอันเสร็จเรียบร้อย ก็ upload cookbook แล้วรันเลยครับ!
    cd ~/Workspace/chef-repo/
    knife cookbook upload -a
    knife ssh name:<your node name> "sudo chef-client" -x ubuntu # if you use ubuntu on aws
    
  6. ตอนนี้ เวบไซด์ของคุณจาก bitbucket repo จะต้องมีโผล่ให้เห็นเมื่อ access url แล้วนะครับ หลังจากนี้ หากคุณมีการเปลี่ยนแปลงโค้ดเวบไซด์ของคุณ บน bitbucket ก็สามารถรันคำสั่งข้างล่าง ทุกอย่างก็จะอัพเดทให้หมดครับ หรือ จะทำลาย aws node นี้ทิ้งแล้วไปสร้างใหม่ ก็แค่ add node ใหม่เข้าไปบน Chef-server แล้วก็รัน knife ssh … … เป็นอันจบ!
    knife ssh name:<your node name> "sudo chef-client" -x ubntu # if you use ubuntu on aws
    

เป็นยังไงบ้างครับ ลองทำกันได้รึเปล่า หากมีติดหรือพลาดตรงไหน หรือ มีไอเดีย คำแนะนำ ก็คอมเม้นมาได้เลยครับ

ใน AWS Chef ตอน 1-4 นี้ โดยความจริงแล้ว ค่อนข้างจะ specific ไปหน่อย อย่างเช่น ชื่อเว็บต้อง fix ใน code แต่จริงๆแล้ว Chef สามารถ flexible ได้อย่างไม่จำกัดเท่าที่ ruby จะทำได้ ตอนต่อๆไป ผมจะแนะนำการใช้ attribute ในสไตล์ต่างๆ ที่ช่วยให้คุณเอา cookbook ที่สร้างไปแล้ว สามารถนำกลับมาใช้ใหม่ได้ง่ายๆ แค่เปลี่ยน attribute จากไฟล์ภายนอก โดยไม่ต้องยุ่งกับโค้ดครับ

อีกอย่างนึง คือ หากคนที่รู้จัก Chef มาก่อนอาจจะค้านว่า แค่ mysite อันเดียวต้องถึงกับใช้ Chef-server เลยหรอ อาจจะดูมากไปหน่อย ใช้ Chef-solo ก็ได้ ( Chef-solo คือ Chef อีกประเภทนึงที่รันแบบเดี่ยวไม่ต้องพึ่ง Chef-server ) แต่ประเด็นของผมในตอนนี้ คือ การแนะนำเข้าสู่ Chef World ซึ่ง Chef-server จะมีประโยชน์แน่ๆในภายภาคหน้าหากคุณ​ทำงานในระบบ Cloud ที่มีหลาย servers หลาย software components ทำงานด้วยกันครับ ในตอนหน้าๆ ก็อยากจะพูดถึง Chef-solo และวิธีใช้ และความแตกต่างของทั้งสองอันด้วยครับ

Reference:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s