kubernetes 平臺開發(fā)者的幾個小技巧
隨著Cloud Native逐漸深入人心以及kubernetes的流行,國內(nèi)外出現(xiàn)大量的kubernetes服務(wù)提供商,如紅帽,阿里,騰訊等, 同時許多互聯(lián)網(wǎng)公司也在定制kubernetes以滿足自身需求,kubernetes平臺開發(fā)者這個崗位的需求也逐漸增大, 那作為一名合格的kubernetes平臺開發(fā)者其實需要具備一些特殊技能的。
在你的項目使用依賴k8s.io/kubernetes主倉模塊
Kubernetes提供了很多公共庫供開發(fā)者使用, 比如client-go、apimachinery,但是官方不推薦直接依賴主倉k8s.io/kubernetes,雖然其代碼完全是開源的, 這樣做最主要原因是直接依賴k8s.io/kubernetes會導(dǎo)致你的項目過大,包含太多不必要的文件。
但是除了公共庫已經(jīng)拆分的通用模塊,主倉還有很多有意義的API接口(函數(shù)),比如包pkg/core/validation的ValidatePodCreate函數(shù)可以用來創(chuàng)建POD時, 做前校驗處理(cli-runtime庫定義了ContentValidator接口,建議使用該接口和dry-run機制),包pkg/apis/core/v1中Convert_v1_Pod_To_Core_Pod函數(shù)可以用來將corev1.Pod轉(zhuǎn)換為core.Pod等。這些包目前還沒有被抽離成單獨模塊。
如果我們直接go get k8s.io/[email protected]下載依賴,會出現(xiàn)以下錯誤:
BASH
? go-get-kubernetes go get k8s.io/kubernetes
go: k8s.io/kubernetes upgrade => v1.19.3
go get: k8s.io/[email protected] requires
k8s.io/[email protected]: reading k8s.io/api/go.mod at revision v0.0.0: unknown revision v0.0.0
錯誤的原因是在kubernetes主倉中,也使用了公共庫,不過go.mod文件中所有公共庫版本都指定為了v0.0.0(顯然這個版本不存在), 然后通過Go Module的replace機制,將版本替換為子目錄./staging/src/k8s.io對應(yīng)的依賴。
TEXT
module k8s.io/kubernetes
go 1.15
require (
...
k8s.io/api v0.0.0
k8s.io/apiextensions-apiserver v0.0.0
k8s.io/apimachinery v0.0.0
k8s.io/apiserver v0.0.0
k8s.io/cli-runtime v0.0.0
k8s.io/client-go v0.0.0
...
)
replace(
...
k8s.io/client-go => ./staging/src/k8s.io/client-go
k8s.io/cloud-provider => ./staging/src/k8s.io/cloud-provider
k8s.io/cluster-bootstrap => ./staging/src/k8s.io/cluster-bootstrap
k8s.io/code-generator => ./staging/src/k8s.io/code-generator
k8s.io/component-base => ./staging/src/k8s.io/component-base
...
)
那么如何解決呢,只需要復(fù)制保存以下腳本(來自社區(qū)相關(guān)Issue),在項目中執(zhí)行以下腳本:bash hack/go-get-kubernetes.sh v1.19.2, 注意替換你需要的版本。這個腳本通過修改go.mod文件保證能夠獲取相關(guān)依賴。
BASH
#!/bin/sh
set -euo pipefail
VERSION=${1#"v"}
if [ -z "$VERSION" ]; then
echo "Must specify version!"
exit 1
fi
MODS=($(
curl -sS https://raw.githubusercontent.com/kubernetes/kubernetes/v${VERSION}/go.mod |
sed -n 's|.*k8s.io/\(.*\) => ./staging/src/k8s.io/.*|k8s.io/\1|p'
))
for MOD in "${MODS[@]}"; do
V=$(
go mod download -json "${MOD}@kubernetes-${VERSION}" |
sed -n 's|.*"Version": "\(.*\)".*|\1|p'
)
go mod edit "-replace=${MOD}=${MOD}@${V}"
done
go get "k8s.io/kubernetes@v${VERSION}"
不過建議大家不要直接依賴主倉
Goland如何調(diào)試Kubernetes相關(guān)組件
學(xué)會調(diào)試kubernetes,對于我們學(xué)習(xí)kubernetes源碼及定制化kubernetes十分有幫助,其實剛開始接觸kubernetes項目,我和許多開發(fā)者一樣, 面對kubernetes這一復(fù)雜龐大的項目,不知道從何看起,也不知道如何調(diào)試它(當(dāng)然Kubectl除外),其實kubernetes的本地調(diào)試并沒有想象中的復(fù)雜。
首先假設(shè)你已經(jīng)在虛擬機通過kubeadm安裝了一套kubernetes集群,克隆了kubernetes代碼倉到本地和虛擬機上。這里我以APIServer組件為例,其他組件類似。
首先,查看安裝Kubernetes集群的版本,并在虛機上checkout對應(yīng)版本的代碼倉分支,然后編譯Kubernetes相關(guān)組件, 編譯時需要打開調(diào)試選項(參照Makefile的說明),這個編譯時間可能有點長,對應(yīng)的二進制產(chǎn)物在_output/bin目錄中,
BASH
# 編譯
? kubernetes git:(release-1.18) ? make all GOGCFLAGS=”-N -l”
? kubernetes git:(release-1.18) ? cd _output/bin
? bin git:(release-1.18) ? ll
總用量 1.8G
-rwxr-xr-x 1 root root 65M 9月 11 11:20 apiextensions-apiserver
-rwxr-xr-x 1 root root 6.0M 9月 10 16:56 conversion-gen
-rwxr-xr-x 1 root root 6.0M 9月 10 16:56 deepcopy-gen
-rwxr-xr-x 1 root root 6.0M 9月 10 16:56 defaulter-gen
-rwxr-xr-x 1 root root 172M 9月 11 11:21 e2e_node.test
-rwxr-xr-x 1 root root 157M 9月 11 11:21 e2e.test
-rwxr-xr-x 1 root root 59M 9月 11 11:21 gendocs
-rwxr-xr-x 1 root root 192M 9月 11 11:21 genkubedocs
-rwxr-xr-x 1 root root 200M 9月 11 11:21 genman
-rwxr-xr-x 1 root root 9.4M 9月 11 11:21 genswaggertypedocs
-rwxr-xr-x 1 root root 59M 9月 11 11:21 genyaml
-rwxr-xr-x 1 root root 11M 9月 11 11:21 ginkgo
-rwxr-xr-x 1 root root 3.6M 9月 10 16:07 go2make
-rwxr-xr-x 1 root root 2.0M 9月 10 16:57 go-bindata
-rwxr-xr-x 1 root root 2.8M 9月 11 11:21 go-runner
-rwxr-xr-x 1 root root 55M 9月 11 11:20 kubeadm
-rwxr-xr-x 1 root root 149M 9月 11 11:20 kube-apiserver
-rwxr-xr-x 1 root root 141M 9月 11 11:20 kube-controller-manager
-rwxr-xr-x 1 root root 60M 9月 11 11:20 kubectl
-rwxr-xr-x 1 root root 142M 9月 11 11:21 kubelet
-rwxr-xr-x 1 root root 139M 9月 11 11:21 kubemark
-rwxr-xr-x 1 root root 52M 9月 11 11:20 kube-proxy
-rwxr-xr-x 1 root root 59M 9月 11 11:20 kube-scheduler
-rwxr-xr-x 1 root root 7.2M 9月 11 11:21 linkcheck
-rwxr-xr-x 1 root root 2.3M 9月 11 11:20 mounter
-rwxr-xr-x 1 root root 9.9M 9月 10 16:56 openapi-gen
-rwxr-xr-x 1 root root 5.7M 9月 10 16:07 prerelease-lifecycle-gen
調(diào)試需要使用到Go調(diào)試工具delve,在kubernetes集群的控制節(jié)點上安裝delve, 這里使用go get的方式安裝。
BASH
# 在Module目錄外執(zhí)行,并將GOBIN目錄添加環(huán)境變量PATH中
? ~ go get github.com/go-delve/delve/cmd/dlv
? bin git:(release-1.18) ? dlv -h
Delve is a source level debugger for Go programs.
Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.
The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
Pass flags to the program you are debugging using `--`, for example:
`dlv exec ./hello -- server --config conf/config.toml`
通過Kubeadm安裝的集群,kubernetes控制平面的組件是以Static pod形式運行的, 對應(yīng)的yaml文件保存在 /etc/kubernetes/manifests,查看APIServer對應(yīng)的配置文件如下,我們需要拷貝APIServer的啟動參數(shù)。接下來,我們重命名/etc/kubernetes/manifests/kube-apiserver.yaml為kube-apiserver.yaml.old,觀察容器列表, 等待APIServer對應(yīng)的容器停止,通過delve啟動APIServer進行調(diào)試,注意相關(guān)參數(shù)配置。
BASH
dlv exec _output/bin/kube-apiserver --headless -l 192.168.5.82:2345 --api-version=2 \\
--advertise-address=192.168.5.82 \\
--allow-privileged=true \\
--authorization-mode=Node,RBAC\\
--client-ca-file=/etc/kubernetes/pki/ca.crt\\
--enable-admission-plugins=NodeRestriction\\
--enable-bootstrap-token-auth=true\\
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt\\
--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt\\
--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key\\
--etcd-servers=https://127.0.0.1:2379\\
--insecure-port=0\\
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver- kubelet-client.crt\\
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet- client.key\\
--kubelet-preferred-address-types=InternalIP,ExternalIP, Hostname\\
--proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client. crt\\
--proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client. key\\
--requestheader-allowed-names=front-proxy-client\\
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy- ca.crt\\
--requestheader-extra-headers-prefix=X-Remote-Extra-\\
--requestheader-group-headers=X-Remote-Group\\
--requestheader-username-headers=X-Remote-User\\
--secure-port=6443\\
--service-account-key-file=/etc/kubernetes/pki/sa.pub\\
--service-cluster-ip-range=10.96.0.0/16\\
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt\\
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key
server listening at: 192.168.5.82:2345
在本地開發(fā)環(huán)境也切到與虛機對應(yīng)的kubernetes分支,然后添加一個遠程調(diào)試的Configuration,配置對應(yīng)的主機和端口,并在相關(guān)位置打上斷點,開始調(diào)試。


到這里,就已經(jīng)成功對Kubernetes的APIServer進行調(diào)試?yán)病?/p>
原文鏈接:https://blog.happyhack.io/2020/10/30/kubernetes-develop-tips/
