kubernetes 开发环境搭建与社区贡献
2021-08-31 tech kubernetes go 29 mins 30 图 10158 字
一、go 环境搭建
从1.22.1 升级日志 更新来看,使用了 Golang 1.16.7 的环境。
1.1 备份当前的 go 环境
先确认系统路径PATH 有没有包含 goroot,没有的话加上。一般如果已经存在了都会有的:
可以看到我这里系统路径已经包含了goroot和gopath的路径。
主要思路是把 goroot / gopath 做备份,保留环境变量不变,将它们文件和文件夹重命名加个后缀版本号,再在用软链接 ln -s
指向它们。
1.2 安装 Golang 1.16.7
我是 debian 9 x86 环境。
# 也可以直接访问 https://golang.org/dl/ 手动下载
wget https://golang.org/dl/go1.16.7.linux-amd64.tar.gz
tar zxvf go1.16.7.linux-amd64.tar.gz
mv go /var/local/go1.16.7 # 我习惯使用/var/local保存自己安装的软件
# 该整的软链接整一下
rm /var/local/go /home/kelu/Workspace/go
ln -s /var/local/go1.16.7 /var/local/go
ls -s /home/kelu/Workspace/gopath/go1.16.7 /home/kelu/Workspace/go
确认安装ok
go version
二、kubernetes 源码编译
官方开发参考文档: https://github.com/kubernetes/community/blob/master/contributors/devel/development.md
2.1 下载源码
直奔 https://github.com/kubernetes/kubernetes/releases/tag/v1.22.1
2.2 其它环境准备
- 系统配置,准备好 8G内存和50G存储。
- GNU development tools:
sudo apt update
sudo apt install build-essential
- docker
- rsync, 文件同步,一般都装了的。
- jq, JSON 处理包。
apt-get install jq
. 官方文档 - gcloud,如果构建 e2e 测试,需要安装GCP的 CLI
- go
- pyyaml,某些测试用,
pip install pyyaml
官方文档 - etcd,这个版本是 3.5.0,新版本改进了安全性、性能、监控和开发人员体验。
./hack/install-etcd.sh
2.3 尝试编译
使用 kubernetes自带的 Makefile,使用make
即可编译。可以通过查看Makefile
文件代码,查看编译执行脚本。
也可以对不同的模块可以进行单独的编译。
2.3.1 round 1
在docker中执行跨平台编译出二进制文件。
./build/run.sh make
发现 docker pull 阶段没法拉镜像,需要添加代理:
systemctl cat docker
# /lib/systemd/system/docker.service
修改此文件: vi /lib/systemd/system/docker.service
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080/"
Environment="HTTPS_PROXY=http://proxy.example.com:8080/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
如果是 sock5 代理,把 http://
改成 socks5://
即可.
重启docker:
docker pull k8s.gcr.io/v2/build-image/kube-cross/manifests/v1.16.7-1
下载有点久阿,要有亿点耐心。
2.3.2 round 2
继续上路:
./build/run.sh make
编译完成的二进制文件在/_output
目录下。
2.3.3 round 3 构建单个/跨平台构建
除了使用上边的 ./build/run.sh make
,还可以直接使用make命令进行编译,编译出来的目录稍有不同:
make WHAT=cmd/kubectl
make all # 编译所有
make cross # 跨平台编译
make cross KUBE_BUILD_PLATFORMS=windows/amd64 # 特定平台编译
make help # 编译帮助
# 如果需要使用dlv进行远程调试,make需要添加一些参数,使得我们可以dlv attach进来:
make WHAT=cmd/kube-apiserver GOGCFLAGS="-N -l" GOLDFLAGS=""
2.3.4 构建镜像
KUBE_BUILD_PLATFORMS=linux/amd64 KUBE_BUILD_CONFORMANCE=n KUBE_BUILD_HYPERKUBE=n make release-images GOFLAGS=-v GOGCFLAGS="-N -l"
UBE_BUILD_CONFORMANCE=n
和KUBE_BUILD_HYPERKUBE=n
参数配置是否构建hyperkube-amd64
和conformance-amd64
镜像,默认是 y 构建,设置为 n 不需要构建。make release-images
表示执行编译并生成镜像 tar 包。
编译的 kubernetes 组件 docker 镜像以 tar 包的形式发布在 kubernetes/_output/release-images/amd64
目录中。
三、kubernetes 开发
3.1 github开发流
https://github.com/kubernetes/community/blob/master/contributors/guide/github-workflow.md
3.2 开发环境搭建
我使用 vscode 作为 ide
# 注意本地环境要做好国外代理,有时候证书工具下载不下来。
./hack/install-etcd.sh
./hack/local-up-cluster.sh
# 打开新的terminal
cd $GOPATH/src/k8s.io/kubernetes
export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig
# 使用kubectl
cluster/kubectl.sh get cs
cluster/kubectl.sh get ns
cluster/kubectl.sh get nodes
cluster/kubectl.sh run nginx --image=nginx
cluster/kubectl.sh get po -A
这样一个简易的本地环境就起来了。
一共运行了 7 个进程:
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- sudo kubelet
- kubelet
- sudo kube-proxy
- kube-proxy
下面以调试 apiserver 作为例子:
# kill 掉 apiserver, 注意保存apiserver的启动命令。
ps aux | grep apiserver
kill -9 xxx
# 运行命令备忘:
/var/local/go/src/k8s.io/kubernetes/_output/local/bin/linux/amd64/kube-apiserver --authorization-mode=Node,RBAC --cloud-provider= --cloud-config= --v=3 --vmodule= --audit-policy-file=/tmp/kube-audit-policy-file --audit-log-path=/tmp/kube-apiserver-audit.log --authorization-webhook-config-file= --authentication-token-webhook-config-file= --cert-dir=/var/run/kubernetes --egress-selector-config-file=/tmp/kube_egress_selector_configuration.yaml --client-ca-file=/var/run/kubernetes/client-ca.crt --kubelet-client-certificate=/var/run/kubernetes/client-kube-apiserver.crt --kubelet-client-key=/var/run/kubernetes/client-kube-apiserver.key --service-account-key-file=/tmp/kube-serviceaccount.key --service-account-lookup=true --service-account-issuer=https://kubernetes.default.svc --service-account-jwks-uri=https://kubernetes.default.svc/openid/v1/jwks --service-account-signing-key-file=/tmp/kube-serviceaccount.key --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,Priority,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --disable-admission-plugins= --admission-control-config-file= --bind-address=0.0.0.0 --secure-port=6443 --tls-cert-file=/var/run/kubernetes/serving-kube-apiserver.crt --tls-private-key-file=/var/run/kubernetes/serving-kube-apiserver.key --storage-backend=etcd3 --storage-media-type=application/vnd.kubernetes.protobuf --etcd-servers=http://127.0.0.1:2379 --service-cluster-ip-range=10.0.0.0/24 --feature-gates=AllAlpha=false --external-hostname=localhost --requestheader-username-headers=X-Remote-User --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-client-ca-file=/var/run/kubernetes/request-header-ca.crt --requestheader-allowed-names=system:auth-proxy --proxy-client-cert-file=/var/run/kubernetes/client-auth-proxy.crt --proxy-client-key-file=/var/run/kubernetes/client-auth-proxy.key --cors-allowed-origins="/127.0.0.1(:[0-9]+)?$,/localhost(:[0-9]+)?$"
编译apiserver:
make WHAT=cmd/kube-apiserver GOGCFLAGS="-N -l" GOLDFLAGS=""
可以看到是刚刚编译的apiserver,时间稍微落后一点:
运行命令:
dlv exec --headless --listen=:2345 --api-version=2 /var/local/go/src/k8s.io/kubernetes/_output/local/bin/linux/amd64/kube-apiserver -- --authorization-mode=Node,RBAC --cloud-provider= --cloud-config= --v=3 --vmodule= --audit-policy-file=/tmp/kube-audit-policy-file --audit-log-path=/tmp/kube-apiserver-audit.log --authorization-webhook-config-file= --authentication-token-webhook-config-file= --cert-dir=/var/run/kubernetes --egress-selector-config-file=/tmp/kube_egress_selector_configuration.yaml --client-ca-file=/var/run/kubernetes/client-ca.crt --kubelet-client-certificate=/var/run/kubernetes/client-kube-apiserver.crt --kubelet-client-key=/var/run/kubernetes/client-kube-apiserver.key --service-account-key-file=/tmp/kube-serviceaccount.key --service-account-lookup=true --service-account-issuer=https://kubernetes.default.svc --service-account-jwks-uri=https://kubernetes.default.svc/openid/v1/jwks --service-account-signing-key-file=/tmp/kube-serviceaccount.key --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,Priority,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --disable-admission-plugins= --admission-control-config-file= --bind-address=0.0.0.0 --secure-port=6443 --tls-cert-file=/var/run/kubernetes/serving-kube-apiserver.crt --tls-private-key-file=/var/run/kubernetes/serving-kube-apiserver.key --storage-backend=etcd3 --storage-media-type=application/vnd.kubernetes.protobuf --etcd-servers=http://127.0.0.1:2379 --service-cluster-ip-range=10.0.0.0/24 --feature-gates=AllAlpha=false --external-hostname=localhost --requestheader-username-headers=X-Remote-User --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-client-ca-file=/var/run/kubernetes/request-header-ca.crt --requestheader-allowed-names=system:auth-proxy --proxy-client-cert-file=/var/run/kubernetes/client-auth-proxy.crt --proxy-client-key-file=/var/run/kubernetes/client-auth-proxy.key --cors-allowed-origins="/127.0.0.1(:[0-9]+)?$,/localhost(:[0-9]+)?$"
settings.json
配置如下:
{
"go.delveConfig": {
"debugAdapter": "legacy",
}
}
调试配置如下:
此时可以看到,dlv 开始刷日志了,我们连上了!
尝试暂停debug,看看左侧堆栈:
尝试打个断点,成功!
3.3 golang相关能力与代码规范
- go module 官方wiki: https://github.com/golang/go/wiki/Modules
- k8s go module:https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/vendor.md
-
参考我这篇文章——《go 零散笔记》
- 官方的代码规范:https://github.com/golang/go/wiki/CodeReviewComments
四、kubernetes 测试
4.1 验证
verify 很烧 cpu,注意自己的机器性能,请酌情验证,我机器已经死机好几次了,16c16g的机器。
4.2 单元测试
todo
4.3 集成测试
todo
4.4 e2e测试
todo
五、kubernetes 贡献
5.1 签贡献者协议(Contributor License Agreement)
https://github.com/kubernetes/community/blob/master/CLA.md#the-contributor-license-agreement
- 验证邮箱(该邮箱要跟GitHub账户邮箱一致)
- 重设密码
- 电子签署SLA文件
linux基金会个人账号信息:https://identity.linuxfoundation.org/user
5.2 选择一个issue/todo
在 Kubernetes issue 列表,用标签过滤问题列表,例如 “good first issue”,“help wanted”,这些标签表明这个问题对新手友好。
也可以搜索代码库里的TODO。
这里有两位大佬的first blood:
5.3 处理issue流程
- 先熟读当前issue上下文或者pr,理解问题的背景和要解决的难题。
- 如果它是一个 bug,就要验证你是否能复现这个 bug。请注意这可能需要投入大量时间.
- 在 Slack 上联系问题(issue)的创建者来验证你的想法。
- 一周之内没有收到反馈,直接提交 PR 。
- 开发,coding
- 本地单元测试/集成测试(最好做一下)
- 跑通
make verify
(可能需要 30-40 分钟) - 跑通
make test
- 跑通
make test-integration
- 跑通
- 提pr
- 至少两周内提交 PR 或者提供状态更新。
- 在相关的sig Slack 频道找 Kubernetes Github 组织的成员给pr打标签 /ok-to-test。
5.4 贡献者相关链接
参考资料:
- 给kubernetes项目贡献代码 - zeusro
- 全职工作者如何为 Kubernetes 做贡献
- 国内环境下 Kubernetes 源码编译及运行
- 为Kubernetes贡献的正确姿势 - xsky
- 骑上独角兽:Kubernetes新手贡献指南 译文 与 原文
- 为Kubernetes贡献的正确姿势
- Kubernetes 贡献指南
- K8s 系列(二) - K8s PR 怎样才能被 merge?
- Kubernetesで気になってるGitHub Issue・PR集
- kubernetes github issue good first issue
- 如何参与 Apache 项目社区 - PingCAP tison
- 基于Kubernetes1.20.1版本开发调试环境搭建
六、社区其它内容
6.1 社区行为准则
https://github.com/cncf/foundation/blob/master/code-of-conduct-languages/zh.md
Kubernetes 社区行为准则遵循 CNCF的行为准则,CNCF的行为准则也受 Linux 基金会行为准则约束。
CNCF 不可接受的参与者行为(v1.0):
- 使用性语言或图像
- 人身攻击
- 挑衅、侮辱或贬低性评论
- 公开或私下骚扰
- 未经明确许可,发布他人的私人信息,比如地址或电子邮箱
- 其它不道德或不专业的行为
Linux 基金会活动是旨在用于开源社区内的专业网络和协作的工作会议。它们的存在是为了鼓励思想和表达的开放交流,并需要一个承认每个人和团体的内在价值的环境。
不可接受的行为:
- 骚扰
- 基于性别、性别认同和表达、性取向、残疾、外貌、体型、种族、年龄、宗教或任何其他受举办会议或法律保护的内容
- 使用辱骂性、冒犯性或有辱人格的语言
- 恐吓、跟踪、骚扰性的摄影或录音
- 不当的身体接触
- 性图像、不受欢迎的性挑逗或性要求
- 参展商
- 不应在其展位中使用色情图片、活动或其他材料
- 不得使用色情服装、制服、服装或以其他方式营造色情环境。
- 演讲者不应在其演讲中使用性语言、图像或任何会构成上述定义的骚扰的语言或图像。
6.2 社区价值观
- 分布式优于集中
- 社区胜过产品或公司
- 流程自动化
- 包容胜于独占
- 进化胜于停滞
6.3 社区期望
https://github.com/kubernetes/community/blob/master/contributors/guide/expectations.md
- 必须 code review
- Reviewer 与提交者交流要注意社区形象
6.4 社区成员与职责
https://github.com/kubernetes/community/blob/master/community-membership.md
- Member
- Reviewer
- Approver
- Subproject owner