搭建 K8s 容器化应用的开发调试环境
对开发人员而言,Kubernetes(简称 k8s)真的是想说爱你不容易。因为 k8s 基本与我们的业务无关,它的关注点是容器编排,涉及到的都是系统的网络、存储、计算等基础资源,是我们比较陌生的领域;另外,因为众所周知的原因,谷歌系的网站基本上在国内没法访问,这就导致了很多对 k8s 的探索都是止步于安装,无果而终。本文是笔者踩坑无数后,在 k8s 路上的一点收获,在 Win10 上搭建单机的 k8s 环境,进行容器化应用的开发、调试与部署。
1、容器化带来的问题
把应用容器化是为了方便测试和部署,解决开发人员“我这里可以呀”而测试或用户“我这里不行”的问题。我们开发出来的软件需要比较良好的可部署性,容器化与无服务器架构是实现这个目标的发展方向和趋势。Docker 和 Kubernetes 是容器化和容器编排的行业标准,在现阶段也相对成熟;无服务器(Serverless)目前支持的业务场景还比较有限,也缺少行业标准,容易被厂商锁定。
作为开发人员,我们当然还需要良好的可调试性。那种把应用编译部署到容器后,有问题只能看容器里应用输出的日志,而无法做代码跟踪、断点调试的方案,都不是我们想要的。
这里说的应用容器化后影响调试,是不包括单体应用的,主要是说部署在容器里并且跟其他容器里的应用有交互的应用,也就是服务间相互调用,微服务就是最典型的例子。比如你用 docker compose 启动微服务的其它应用,然后试图在 IntelliJ IDEA 里跟踪调试某个服务,这时你会发现,IDEA 跟 docker compose 启动的服务不在一个世界,网络不通。Docker 可以暴露端口供外部调用,但 IDEA 里启动的这个应用没法暴露给容器世界里的服务,微服务的服务发现(Eureka Server、Zookeeper 等)只能发现容器世界里的服务。
Java 或者其它支持远程调试的语言,虽然提供了一种可行的方式,但在应用部署到容器后,特别是 k8s 环境,要连接远程调试端口也变得困难了,何况远程调试本身就没有本机来得简单快捷。K8s 对容器进行调度、编排,带来了比 docker 更高级的功能,但同时也增加了系统的复杂性。
良好的可部署性和可调试性,鱼与熊掌,可以兼得吗?我们不相信世上有可以解决一切问题的银弹,但却总是走在寻找银弹的路上^_^
2、解决方案概述
笔者给的这个兼顾可部署性和可调试性的开发环境搭建方案,重点是用 k3s 来解决 Kubernetes 的安装难题,用 Telepresence 来打通容器和 IDE 进行代码的跟踪调试,用 Skaffold 来自动化处理容器构建和部署。
如果你有更好的建议,还望不吝赐教👏
K3s 是经 CNCF 一致性认证的 Kubernetes 发行版,重点是 k3s 被打包成单个小于 60MB 的二进制文件,从而简化了安装、运行和升级 k8s 集群所需的依赖性和步骤,也就是说 k3s 是开箱即用的,不再需要去联网下载相关镜像,“完美”解决了 k8s 的安装难题;
Telepresence 为部署在 k8s 环境里的应用提供快速本地化开发功能,其基本原理是在 k8s 集群中部署双向网络代理,使得本机环境的服务和 k8s 集群里的服务完全互访,包括 k8s 的环境变量、Secrets 和 ConfigMap 等;
Skaffold 是谷歌提供的开发支持工具,主要是跟谷歌提供的云服务(Google Cloud)结合来加速应用的容器化构建、部署,这里我们只用它的基础功能就行了,自动构建并部署到应用到 k8s 集群。
3、安装 Docker Desktop
下载链接: https://hub.docker.com/editions/community/docker-ce-desktop-windows
系统要求:Microsoft Windows 10 Professional or Enterprise 64-bit, or Windows 10 Home 64-bit with WSL 2.
Docker 在后续的容器镜像构建(build)会用到,所以这里先提出来做好准备。在 Windows 开发环境做容器化部署,Docker Desktop 也是必备软件了。
这里再推荐一个终端工具:Windows Terminal,笔者觉得比 cmd 和 power shell 用着舒服多了,可以在 Microsoft Store 上搜索安装。微软的 store 有一个 bug,就是很容易“无法加载页面,请稍候重试”,解决办法是打开 IE(Internet Explorer),在“Internet 选项”的“高级”里勾选 TLS1.1 和 TLS1.2,“应用”即可解决问题。
真的是 IE 不死,bug 长存啊😂微软 Store 的这个 bug,笔者没去细究,可能是国内的某些安全工具在坑微软,或者某些银行软件做的修改,但是微软这个软件帝国,自己的 Store 门被堵了也无动于衷,真是够稳重的啊👍
给一个在 Windows Terminal 里查看 Docker Desktop 是否就绪的截图:
4、安装 Multipass
Multipass 是 Ubuntu 发行商 Canonical 旗下的一款产品,是一个轻量级 Linux 虚拟机命令行管理工具。通过 Multipass,用户可以用一条命令启动虚拟机镜像,并在短短数秒内让 Linux 在 Mac 和 Windows 上运行起来。显然这里的 Linux 是专指 Ubuntu,你如果喜欢其它的 Linux,也有熟悉的方式和趁手的工具,可以略过这一部分。Canonical 这些大厂,为了推广自己的产品,也是够拼的。
Multipass 的官网:https://multipass.run/
Windows 版的下载地址:https://multipass.run/download/windows
系统要求:Windows 10 专业版、企业版、教育版,或者安装了 VirtualBox。
Multipass 安装就绪后,就可以用命令来管理 ubuntu 虚拟机了:
multipass help 查看帮助,授人以鱼不如授人以渔
multipass list 查看现有的虚拟机实例
multipass find 查看可用的镜像
multipass launch 创建并启动 Ubuntu 实例
multipass shell 连接实例进行 shell 操作
multipass start 启动虚拟机
multipass stop 停止虚拟机
multipass delete 删除虚拟机
multipass recover 恢复删除的虚拟机
multipass purge 彻底清除删除的虚拟机
接下来我们用 Multipass 创建一个 LTS 版的 Ubuntu 20.04,取名为 test,shell 进去修改 root 的密码,然后试一下 multipass 对虚拟机的管理:启动、停止、删除等:
安装好 Docker Desktop 和 Multipass 后,就可以进入正题,开始安装 K3s、Telepresence 和 Skaffold,搭建有良好可调试性的 k8s 开发环境。
5、安装 K3s
先用 Multipass 创建并启动 Ubuntu 虚拟机,作为安装 k3s 的 Linux 服务器:
连接虚拟机 k3s-1 上的 ubuntu 并修改 root 的密码,以便后续使用 root 进行操作:
如果习惯了 XShell 等终端工具,可以参考这篇文章:https://www.kindlehub.mobi/t/topic/1134
K3s 的官网:https://www.rancher.cn/k3s/
技术文档:https://docs.rancher.cn/docs/k3s/quick-start/_index
国内用户,可以使用以下方法加速安装:
安装成功的话会输出如下内容:
检查 k3s 是否运行正常:
6、在本机上安装 kubectl
Kubectl 是 Kubernetes 工具,使用 kubectl 可以对 k8s 集群运行命令,比如部署应用、监测和管理集群资源以及查看日志等。
要在本机(windows 10)上访问 k3s-1 虚拟机里安装的 kubernetes 集群,需要先安装 windows 版的 kubectl,kubectl 是用 golang 开发的,只有一个执行程序,可以直接下载,然后在环境变量 path 里增加 kubectl 执行程序的路径即可。
下载链接:https://dl.k8s.io/release/v1.22.0/bin/windows/amd64/kubectl.exe
安装指导:https://kubernetes.io/zh/docs/tasks/tools/install-kubectl-windows/
Kubectl 安装好后,还需要配置一下,告诉它待连接的 k8s 集群的相关参数。这个配置文件的位置是:
Windows 上 kubectl 的配置文件是“~/.kube/config”(这里的~只在 power shell 里有效,跟当前登录的用户名有关,在资源管理器里要替换为实际的路径),远端 Ubuntu 主机(虚拟机 k3s-1)里 k3s 的 KUBECONFIG 是在这个文件里:/etc/rancher/k3s/k3s.yaml,所以现在要做的就是把 k3s.yaml 里的内容,复制到 config 里。
记得要改 Server 的 IP 地址,在 k3s.yaml 文件里指向的 k8s 集群 Server 地址是 127.0.0.1,在 windows 的~/.kube/config 里则要修改为虚拟机 k3s-1 的地址:
用 Multipass list 查看 k3s-1 的 IP 地址,以及配置好之后,在 windows 本机上验证一下:
7、用 kubectl 管理 k8s
Kubernetes 的基础知识这里简单讲一下:
Node,一个节点就是是一台主机(虚拟主机或者物理主机),一个 k8s 集群可以管理若干主机;
Pod,在英文中的原意是豆荚的意思,在 k8s 的一个 pod 中可以运行一个或者多个容器,并且 k8s 会为每个 pod 都分配一个集群内唯一的 IP 地址;K8s 一般会为一个服务部署多个 pod 副本,副本的数量可以增加或减少,构成一个 pod 集群来对外提供服务,所以要访问 k8s 集群里的服务,直接写某个 pod 的地址是不行的;
Service,是 k8s 中的一个核心资源,主要就是解决上述服务访问的问题。Service 一旦创建就会分配固定的 IP 地址,并且在它的整个生命周期里都不会改变。
Ingress,可以简单理解为 Nginx 或微服务里的网关(Zuul,Gateway),如果说 Service 是解决 k8s 集群内服务访问的问题,Ingress 就是把 Service 暴露到集群外部,供外部访问集群提供的服务。
当然 k8s 集群还有一些其它的概念,比如存储 PV、PVC,Secrets,ConfigMap 等,这些我们都可以简单理解为 k8s 管理的资源,这些资源汇集起来构成整个集群。
有了用 k3s 运行的 k8s 集群,也了解了一些基本的概念,接下来我们实际部署一个简单的服务,进一步体验一下 k8s 的容器编排能力。
以 bootcamp 为例,这是 k8s 世界的 Hello World。
7.1 创建 Pod
先编写一个部署文件(bootcamp-deployment.yaml):
上述配置里资源(resource)的内存(memory)单位 Mi=1024*1024 字节,cpu 的 50m 则表示 50/1000 个 cpu 内核(Core),也可以表示为 0.05
在 windows 本机使用 kubectl 运行部署命令:
Deployment 对应的是 Pod
7.2 创建 Service
编写 Service 文件(bootcamp-svc.yaml):
同样用 kubectl apply 发布这个 Service(k8s 世界里通常把 service 简称为 svc):
7.3 创建 Ingress
k3s 内置的 Ingress Controller 是 Traefik,也有基于 Nginx 的 Ingress,Traefik 在代理容器化应用时具有一定的优势,既支持 Docker 也支持 k8s,在容器里部署的应用实例数量变化时,Traefik 可以自动感知,不需要调整配置参数。但不管是哪个具体的 Ingress 实现,创建 Ingress 的操作都是一样的(bootcamp-ingress.yaml):
还是 kubectl apply 来发布这个 Ingress:
7.4 访问(内网、外网)
至此,已经把应用部署到 k8s 的 Pod,并创建了供内部访问的 Service,也通过 Ingress 把服务暴露给外部。现在就来验证一下,在 Ubuntu 主机上,用 curl 在内部通过 Service 的固定 IP 访问:
在 Windows 10 本机上,先修改 hosts(需要用管理员权限打开文本编辑工具才修改,C:\Windows\System32\drivers\etc\hosts),添加域名解析:
然后在浏览器访问http://bootcamp.me
这样我们的 bootcamp 就完成部署了!接下来我们稍微接触一点 k8s 的高端能力,看看它的容器编排能力。
7.5 手动扩容(Scale)
手工增加或者缩小 bootcamp 的 Pod 副本数量,这个能力非常实用,某个服务的负载高了,就增加 Pod 副本数量来支撑业务的正常运转,负载小就减少副本数量,把资源让出来。
使用 kubectl scale 命令,手动扩容和缩容:
7.6 自动扩容(Autoscale)
有了手动扩容,来一个自动扩容就是很自然的事情了。K8s 的 Horizontal Pod Autoscaler(HPA)的控制器,用来实现基于 CPU 使用率进行自动 Pod 扩容和缩容的功能。
HPA 是通过循环控制来实现的,默认 30 秒检查一次应用使用资源的情况(cpu 使用率),扩容的时间间隔是 3 分钟,缩容则是 5 分钟。所以在进行上述操作的时候,不会立即看到效果。
7.7 清理(善后工作)
测试的最后,把前面创建的这些资源都释放掉,完成 bootcamp 的有始有终。Say Hello 之后 Say Bye Bye
K8s 的资源删除有两种方式,一种用 kubectl 执行 delete 命令,带上资源类型和资源名称这两个参数:
另一种方式是使用 yaml 文件来传递资源类型和名称这两个参数:
如果在 Windows 的 hosts 文件里配置了 bootcamp.me 的域名解析,也别忘了把它删除掉。
7.8 小结
K8s 对容器的管理能力,确实够强大,但也够复杂,但相信软件发展的趋势,好的东西总是会向前发展并简化。
8、安装 Teleprensence
Telepresence 是一款为 Kubernetes 或者 Openshift 微服务开发提供快速本地化支持的开源软件。
8.1 安装
官网链接:https://www.telepresence.io/
安装指引:https://www.telepresence.io/docs/latest/howtos/intercepts/?os=windows
Windows 版的下载地址:
https://app.getambassador.io/download/tel2/windows/amd64/latest/telepresence.zip
安装比较简单,下载后解压,在 Power Shell 下执行 install-telepresence.ps1
默认安装在 C:\telepresence
查看帮助:
8.2 连接 K8s 集群(Connect)
连接(代理)K8s 集群(跟 kubectl 一样,也是从~/.kube/config 文件里获取 K8s 集群的信息进行连接):
Connect 成功后,就可以在本机上访问远端 K8s 集群里的 Service 了。测试一下,还有用 bootcamp。前面我们已经把 bootcamp 删除了,但是有了 k8s,重新部署很轻松:
退出 Telepresence 的 connect:
8.3 接管 K8s 集群的流量(Intercept)
接管(拦截)K8s 集群里的访问流量,通过代理转到本机:
telepresence intercept <service-name> --port <local-port>[:<remote-port>] --env-file <path-to-env-file>
拦截(intercept)操作,稍微要复杂一点,流量拦截到本机后,需要本机启动一个相应的服务来处理这些流量。如果是调试的话,就应该是用 IDE 的调试模式来启动 bootcamp,这里我们用 docker 启动。
为了更直观地看到本地 8081 端口的 bootcamp 接管了访问流量,可以看看 docker 的日志:
结束 Intercept:
9、安装 Skaffold
Skaffold 可以自动构建镜像,推送到镜像仓库,部署应用。如果团队已经有这方面的规范流程了,则可以评估一下,看是否需要用 Skaffold 来代替。比如 Maven 插件 fabric8,或者类似 Jenkins 这样的 CI/CD 工具。
9.1 安装
Skaffold 的安装跟 kubectl 类似,就是一个独立的可执行程序,下载后设置一下环境变量 path 即可。下载下来是 skaffold-windows-amd64.exe,为了后续操作方便,请改名为 skaffold.exe,这样设置了 path 后,在 Power Shell 里可以直接使用了。
下载: https://storage.googleapis.com/skaffold/releases/latest/skaffold-windows-amd64.exe
官方的安装指引: https://skaffold.dev/docs/install/
9.2 准备镜像仓库
Skaffold 的操作的对象是应用的容器镜像(Docker Image),所以需要一个 K8s 集群和本机环境都可以访问的容器镜像仓库,以这个仓库为中转,完成应用容器镜像的推送和部署。
如果不是纯学习,就移动办公而言,或者为了自己工作学习的方便,在互联网上弄一个镜像仓库还是很有必要的。像阿里云提供的容器镜像服务,或者腾讯云、华为云等,都有提供类似的服务。
阿里云的个人版容器镜像服务,只是学习的话,这点流量就是免费白嫖
也可以使用 Docker 的 registry 镜像,搭建自己的私有镜像仓库,这里就不赘述了。后续的操作以阿里云的镜像容器服务为例,主要参考 Skaffold 的官网教程: https://skaffold.dev/docs/quickstart/
先 clone 官网的例子:
从文件看非常简单,重点是 Dockerfile 和 yaml 文件,那个 main.go 虽然表明这个例子是 go 语言开发的,但是不需要你懂 go,也不需要安装 go 的相关程序。
9.3 准备访问镜像仓库的 secret
K8s 的 Secret 用来管理敏感数据,这里我们创建一个存放镜像仓库账号密码的 Secret,供 Deployment 从镜像仓库拉取镜像时提供访问凭证。
编辑 getting-started 文件夹下的 k8s-pod.yaml,把访问镜像仓库的 secret 配置上去。
9.4 Skaffold run
运行 Skaffold run 命令会执行一次构建和部署。容器镜像的构建请查看 getting-started 文件夹下的 Dockerfile 文件,做了两件事情,先编译 main.go,然后用编译得到的可执行程序创建 Docker 镜像。部署则是先推送镜像到镜像仓库,然后 deployment 到 k8s 集群。
9.5 其他
Skaffold dev 则是一直监控代码的修改,反复构建、部署。
Skaffold debug 需要下载这个镜像:gcr.io/k8s-skaffold/skaffold-debug-support/go,无法下载,此路不通。
另外,Skaffold 还开发了 IntelliJ IDEA 的插件,在 IDE 里辅助开发,主要是结合谷歌云进行快速部署,被墙了所以没啥用。
10、总结及后续
不管怎么说,这个 Kubernetes 的开发环境算是搭建起来了。
K3s 总体来讲很不错,给了国内开发人员一个容易上手的 K8s,降低了难度,一旦入门,慢慢探索,总会越来越好。
Telepresence 解决了调试的一个大问题,特别是团队协作的时候,大家基于云部署一个云端的 k8s 开发环境,在联调方面省很多事,也减少了开发终端的负担;或者生产环境解决问题的时候,除了远程调试,也多出一个手段。
Skaffold 本身还是优秀的,只不过跟谷歌云结合的比较多,对国内开发人员来说有点鸡肋。
本文有点技术选型的意思,后续有时间考虑结合微服务的开发来实际应用一下,看看还有哪些坑。。。
版权声明: 本文为 InfoQ 作者【xiaoboey】的原创文章。
原文链接:【http://xie.infoq.cn/article/df6407274cb6938dbf25910f9】。文章转载请联系作者。
评论