Jenkins+Packer build docker image trouble in Google Container Engine

tl;dr

本篇只是簡述採坑的過程,沒有最終解法,只是提醒看到這篇的朋友,在標準解決方案出來之前,先不要嘗試這個解決方案了。

目標:用 Jenkins + Packer 搭配 GKE 來建置 docker image

初衷

又到了每年一度的搬家盛事了(辛酸),今年,我們終於要從多災多難的某 S 平台搬到好像很潮的 Google Cloud Platform (GCP) 了。當然,第一件事就是要試著在由 Google 幫你管理的 kubernetes cluster 的 Google Container Engine (GKE) 上建製之前已經完全容器化的系統。

馬上就找到有篇文章就是 Google 推薦介紹在 k8s 上自動化 build image 的文章,「Automated Image Builds with Jenkins, Packer, and Kubernetes」,帶著初次在 GCP 上飛高高的興奮感,立馬跟著實作!

目標

  • 透過 Jenkins Master / Slave 模式建置 docker image
  • 可以在 Jenkins Master 偵測到 git repo 變更時,透過 Jenkins – Kubernetes Plugin 即時啟動一個新的 Jenkins Slave container 進行 build docker image 的作業
  • Jenkins slave 要能使用 packer build docker image

採坑1 – memory 不夠,一直被 Jenkins slave 一直被 kill

官方文章有提供 Jenkins 的 k8s yaml spec 方便你直接用 kubect create -f jenkins.yaml 就能裝好 Jenkins,但是他也在 k8s spec 裡面指定了 memory resource 的限制。這會造成當你在按下 build now 的時候,jenkins 會因為 memory 因為超過 cgroup 的 limit 而被砍掉。但是實際上你看不到什麼 error log,只會一直從 GCP load balancer 看到 500 error 或是 timed out。所以記得把官方的 1.5G memory 限制,調整到至少 2G 以上,被砍掉的機率才會降低。

採坑2 – 官方文章的 Jenkins slave image 沒有 packer

Configuring Jenkins for Container Engine 中在介紹設定 Kubernetes Plugin 時,需要指定 Jenkins slave launch 起來的 container 需要使用的 image,官方這邊是使用

gcr.io/cloud-solutions-images/jenkins-k8s-slave

但是,jenkins-k8s-slave image 並沒有幫你裝好 packer 在裡頭的,但這算是小事,只要自己重包一下就可以解決。
慶幸的是官方有提供 jenkins-k8s-slave 的 Dockerfile,他的 git repo 在這邊,抓來改一改,把 packer 放進去,再 push 回 GCR ,再從 Jenkins 的設定換成自己的 image 就好

https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git

採坑3 – packer 找不到要上傳到 image 的檔案

在 Jenkins slave 中的 packer 要 upload 我們需要預放到 image 的檔案時,會碰到 file not found 的錯誤

cp: cannot stat '/packer-files/upload123456789': No such file or directory
.... 中間略過 ....
ui error: Build 'docker' errored: Upload failed with non-zero exit status: 2

這個問題,主要是因為 packer 是用下 run_command 的方式去把要上傳到 image 的 file ,透過 docker 的 volume mount 的方式掛載到目標 image 後,再透過從 container 中下 cp 指令去複製到你指定的位置。

但由於我們是透過 Jenkins slave 裡面的 docker-cli,去連接到 Jenkins slave container host 上的 docker engine 進行 build 的動作,推測 packer 用 run_command 的方法,會造成 mount 要 build 的 file 到 host 上的目錄,但是實際上我們是要把 packer 所在的 container 的 file mount 到目標 image,所以就會有一些權限以及 mount 來 mount 去,最後 mount 到迷路的問題。

但最好一點的解法,就是目前官方正在使用 go-dockerclient 去重寫整個 packer 內的 communicator。
這邊的詳細討論,可以看下面「快速結論」中所附上的 Github link,裡面有對應的討論。

快速結論

想要讓 packer build docker image 在 container 中,目前是無解的。請期待官方正式 merge 或是有沒有人有興趣幫忙 merge 這部分的 code 囉,github issue 在這邊 WIP: Switch Docker Driver to use the API instead of CLI #4186

注意哦,這個問題只在使用 packer 的 docker provisioner 來 build image 時才會有問題喔!

最後結論

最後筆者只好選擇放棄 GKE + Jenkins Master / Slave + Packer 這個解決方案了,為了快速驗證能不能將整個系統搬到 GCP,先用暫時的方案,讓原本在 S社 的 Jenkins ,從外部 (external) push docker image 到 GCR (Google Container Registry),而這中間碰到的問題以及暫時的解法,就在下一篇介紹給大家吧!

廣告

One thought on “Jenkins+Packer build docker image trouble in Google Container Engine

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s