天天看點

k8s :建構系統前言建構流程總結

前言

大型軟體(linux,android .etc)一般都有自己的建構系統,k8s 也 不例外,本文簡要介紹 k8s 建構系統

建構流程

release

以 quick-release 為例,在指令行執行以下指令

# make quick-release           

make 在源代碼根目錄 Makefile 檔案中定位到 quick-release 目标,該目标的動作是執行 build/release.sh 腳本

# kubernetes/Makefile
.PHONY: release-skip-tests quick-release
ifeq ($(PRINT_HELP),y)
release-skip-tests quick-release:
 @echo "$$RELEASE_SKIP_TESTS_HELP_INFO" else release-skip-tests quick-release: KUBE_RELEASE_RUN_TESTS = n
release-skip-tests quick-release: KUBE_FASTBUILD = true release-skip-tests quick-release:
 build/release.sh <--- 執行 kubernetes/build/release.sh
endif           

release.sh 将建構過程拆分成一個個步驟,每個步驟對應一個 shell function

# kubernetes/build/release.sh
...
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command make cross
...
kube::build::copy_output
kube::release::package_tarballs           

verify_prereqs 對建構環境進行檢查,比如是否缺少一些工具軟體

build_image 建立建構需要的 docker 鏡像 ???

run_build_command make cross 啟動容器,運作 make cross

copy_output, package_tar 處理建構生成的各個檔案

這裡比較有意思的是 k8s 使用 docker 容器進行建構,可能是為了交叉編譯吧

建構鏡像

kube::build::build_image 方法建構基礎鏡像,同步 kubernetes 源代碼到 data container(資料卷容器)

function kube::build::build_image() {
 mkdir -p "${LOCAL_OUTPUT_BUILD_CONTEXT}" # Make sure the context directory owned by the right user for syncing sources to container.
 chown -R ${USER_ID}:${GROUP_ID} "${LOCAL_OUTPUT_BUILD_CONTEXT}"

 cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/" # 準備鏡像建構所需檔案
 cp build/build-image/Dockerfile "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
 cp build/build-image/rsyncd.sh "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
 dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
 chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"

 kube::build::update_dockerfile
 kube::build::set_proxy
 # 建構鏡像
 kube::build::docker_build "${KUBE_BUILD_IMAGE}" "${LOCAL_OUTPUT_BUILD_CONTEXT}" 'false'
 ...
 # 建構資料卷鏡像,注意 ensure 這個詞~資料卷鏡像是可以複用的
 kube::build::ensure_data_container
 # 同步 kubernetes 源代碼到資料卷鏡像
 kube::build::sync_to_container
}           

k8s 建構過程中使用了以下幾種容器:

  • 資料卷容器:存儲 k8s 源代碼,其它容器啟動時通過 --volume-from 共享資料卷
  • rsyncd 容器:運作 rsyncd 服務(一種檔案同步服務),将 k8s 源代碼從 host 同步到資料卷容器中
  • 建構容器:運作建構指令

源代碼同步

上文說到 k8s 建構的時候會啟動一個容器運作 rsyncd 服務,将 k8s 源代碼同步到資料卷容器,那麼源代碼碼會被同步到哪裡呢?

# kubernete/build/common.sh function kube::build::sync_to_container() {
 kube::log::status "Syncing sources to container"

 kube::build::start_rsyncd_container

 kube::build::rsync \
 --delete \
 --filter='H /.git' \
 --filter='- /.make/' \
 --filter='- /_tmp/' \
 --filter='- /_output/' \
 --filter='- /' \
 --filter='H zz_generated.*' \
 --filter='H generated.proto' \
 "${KUBE_ROOT}/" "rsync://k8s@${KUBE_RSYNC_ADDR}/k8s/"
}           

kube::build::rsync 方法将 KUBE_ROOT 目錄下的源代碼同步到 k8s@${KUBE_RSYNC_ADDR}/k8s/

檢視 rsync 配置檔案可以知道 k8s 這個虛拟目錄對應的實際目錄

# kubernetes/build/build-image/rsyncd.sh
...
VOLUME=${HOME}

cat <<EOF >"${CONFFILE}"
pid file = ${PIDFILE}
use chroot = no log file = /dev/stdout reverse lookup = no
munge symlinks = no
port = 8730
[k8s]
 numeric ids = true
 $USER_CONFIG
 hosts deny = *
 hosts allow = ${ALLOW} ${ALLOW_HOST-}
 auth users = k8s
 secrets file = ${SECRETS}
 read only = false
 path = ${VOLUME} <-- k8s 對應的路徑 ${VOLUME} = ${HOME}
 filter = - /.make/ - /_tmp/
EOF           

這個 HOME 變量一般指向 使用者主目錄,但是從 go語言工程目錄結構 來看 HOME 應該指向類似 $GOPATH/src/k8s.io/kubernetes 的目錄,是以經驗和直覺告訴我們肯定有什麼地方設定了 HOME 變量,通過搜尋源代碼,證明确實如此

# kubernetes/build/build-image/Dockerfile ... ENV HOME /go/src/k8s.io/kubernetes WORKDIR ${HOME} ...           

總結

通過分析 k8s 建構系統,可以學習像 Google 這樣的大廠是如何規劃大型軟體工程結構,建構,釋出

本文轉自中文社群-

k8s :建構系統