最近 Kubernetes 的发展,以及在我司的大量应用,自己也迫不及待想要尝尝鲜,虽然我的博客是基于 Hexo 的纯静态站点,但这并不能阻挡我把它迁移上 Kubernetes!毕竟... 相比于 GitHub Pages 灵活性更好可控性更高,emmmm... 好了我编不下去了,总之,生命在于折腾?,我们开始吧。
本文涉及的代码(也就是我的博客)完全开源:https://github.com/wi1dcard/blog。
构建 Docker 镜像
要上 Kubernetes,首先要做的就是给项目打包镜像。Dockerfile 非常简单:
# 采用 nginx:stable-alpine 作为基础镜像 FROM nginx:stable-alpine # 复制 ./public 到镜像内 /usr/share/nginx/html COPY ./public /usr/share/nginx/html # 提示暴露 TCP 协议 80 端口 EXPOSE 80/tcp
我选用 Docker Hub 作为 Docker Registry,如果你有私有项目、权限控制等相关需求,Quay.io 或许是更好的选择。
CI 构建
当然啦,构建这种事情肯定是交给 CI。不推荐每次变更手动 Build,费时费力易出错。
目前我给博客用的是 Travis CI。我也考虑过:
- Circle CI,试用后感觉配置文件(以我个人的风格来看)有点反直觉,放弃。
- GitLab CI,目前我认为最好的 CI/CD,我具备 CI/CD 需求的私人项目都在 GitLab。但是考虑到 (1) 要将博客代码开源,(2) GitLab CI for GitHub repos 需要付费,(3) 两套 VCS 感觉怪怪的,因此放弃。
- GitHub Actions,正在 Beta 中,打败各路 CI/CD 的种子选手之一。只可惜文档还不够齐全,稳定欠佳,只好暂时放弃。
- Docker Hub,若是只用来构建公开镜像感觉还不错,但 (1) CI 和 Docker Registry 强绑定,想要换 Registry(比如上文中提到的 Quay.io)会很繁琐,(2) 构建速度巨慢... 慢... 慢... 大概是用户太多吧,情有可原,(3) 镜像打包完成后需要使用 Helm 部署(即 CD)到集群,明显不适合该场景。
你可以在 这里 找到我的 Travis 配置。其中定义了三个环境变量:
env: global: - DOCKER_USERNAME=wi1dcard # 我的 Docker Hub 用户名 - DOCKER_IMAGE=$DOCKER_USERNAME/blog # Docker 镜像名 - DOCKER_TAG=build-$TRAVIS_BUILD_NUMBER # Docker 镜像 Tag
这些变量会在之后用到。
注意 $DOCKER_TAG,它的值是动态的,即每次构建都会变化,由 Travis CI 的 预定义环境变量 拼接而成。
在 before_script 内,定义了构建过程的脚本:
before_script: - build/build.sh
由于构建、发布过程比较复杂,同时为了未来(可能)迁移到 GitLab CI,我没有将所有脚本罗列在 .travis.yml 里,像 alipay-sdk-php 等开源项目那样。
所有与 CI 相关的内容我都放在了 build/ 目录。
build/build.sh 的主要任务是:
- 安装依赖,例如 Hexo。
- 执行 lint) 过程,检查 Markdown 语法等。
- 渲染静态站点,生成 PDF 格式简历。
- 构建 Docker 镜像。
发布 Docker 镜像
与 CD 相关的内容我放在了 deploy/ 目录。正如 .travis.yml 定义的那样,部署脚本位于 deploy/deploy.sh:
script: - deploy/deploy.sh
首先,登录 Docker Hub,接着推送镜像:
echo "Logging in Docker Hub..." echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin echo "Pushing images to Docker Hub..." docker push "$DOCKER_IMAGE"
注意,这里用到了之前定义的环境变量。其中,$DOCKER_PASSWORD 我定义在 Travis CI 的私有环境变量内:
还有两个环境变量 INGRESS_HOST 和 KUBECONFIG_BASE64 稍后会用到。
关于 Immutable
你可以在 这里 查看推送的镜像和 Tags。
还记得 $DOCKER_TAG 的值是动态的吗,所以每次 CI 构建产生的镜像都会有唯一的 Tag 与它的 Build ID 对应。
这对我来说好处显而易见:
- Immutable。每次构建的镜像就像 Git Commit 一样留下不可变更的印记。
- 清晰明了,不易混淆。你无法快速得知当前 lastet 具体是哪一次构建的产物。
- 便于回滚。虽然你可以重新构建镜像,但如果你将每次构建的镜像保留,那么就可以快速地、完美地回滚到任意版本(尤其能够防止同一 Git Commit 多次 Build 产生不同的 Image)。
(未完待续)
© 著作权归作者所有
发表评论