当我们开发完一个operator应用,并使用集群外运行(make run)的方式,完成测试后,就需要将operator进行打包,使其能部署在任意一台k8s机器上。
因此我们需要用到kubebuilder自己生成的Dockerfile,来打docker镜像。Dockerfile就在源代码的根目录下。可按照自己项目的需求自定做修改。
Dockerfile的源码如下,我们做一下简单分析:
# Build the manager binary
FROM golang:1.17 as builder
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn,direct
WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download
# Copy the go source
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532
ENTRYPOINT ["/manager"]
可以看到该文件采用了分段打包的方法,首先基于golang:1.17的镜像做代码的编译,此时会下载很多依赖,导致镜像很大。因此便有了第二段打包过程,基于gcr.io/distroless/static:nonroot将编译好的可执行文件manager拷贝过来,完成打包。通过这种方法,将编译过程和可执行程序分开,使得我们最终使用的镜像很小。
打包命令参考Makefile,通过执行make docker-build docker-push IMG=镜像名称:镜像tag即可完成打包与上传。如果需要上传,需要在打包前docker login一下。
.PHONY: docker-build
docker-build: test ## Build docker image with the manager.
docker build --network host -t ${IMG} .
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
docker push ${IMG}
当我们完成镜像打包与上传后,便可以部署测试了。部署有两种方式,第一种是使用make deploy将控制器部署到本地集群中,这种方式要求代码和k8s集群在同一台机器上,类似于make run的方法。第二种是通过yaml文件的方式去部署,可部署到任意机器。
接下来先看第一种,执行make deploy命令,之后kubebuilder get po -A,可以看到生成了一个pod。
这个就是我们自己写的operator。这个过程中可能会看到拉取镜像失败的错误,这是因为网络原因,无法下载gcr.io/kubebuilder/kube-rbac-proxy镜像,此时可以去dockerhub上搜索kube-rbac-proxy,找一个别人搬运过来的即可。
再来看看第二种方法,我们首先分析一下make deploy命令,打开Makefile,源码如下:
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -
可以看到这个命令的本质是使用kustomize工具,减config目录下的yaml文件做一个整合,然后kubectl apply -f 这个yaml。因此如果我们执行前两条命令:
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default
不就能生成一个yaml文件了吗,之后我们拿着这个yaml文件,就可以在任意机器apply,从而摆脱make deploy。
我们执行一下:
cd config/manager && bin/kustomize edit set image controller=镜像名:镜像tag
bin/kustomize build config/default
此时就可以看到在标准输出中打印出了一个yaml文件,我们将其复制粘贴到一个文件中,保存一下即可。