通过Telepresence在Kubernetes上建立微服务的开发环境
这篇文章涉及以下三个方面。
-
- Microservices on Kubernetes の開発環境の課題と Telepresence の概要
-
- Telepresence を使い、ローカルのコンテナから Kubernetes 上のサービスにアクセスするサンプル
- Telepresence を利用した、Spring Bootの開発環境のサンプルと解説
背景概况
在Kubernetes上进行微服务的开发环境所面临的挑战。
在 Kubernetes 上开发微服务时,如何为某个服务准备依赖关系是一个问题。
当试图在本地准备所有依赖时,会出现模拟云提供资源或计算机资源不足的问题。
如果在Kubernetes上尝试进行全部开发,那么在开发过程中很难进行调试。
为了能够适当地进行调试,开发人员需要全面了解Kubernetes。
这个问题涉及了Telepresence的开发者Datawire的微服务架构指南,《Development environments for Kubernetes》中概述了其中包含的其他优点和缺点。
遠隔存在技術(Telepresence)是指在不同地點之間透過科技實現身临其境的感覺。
作为解决上述问题的方法之一,可以通过将个人电脑与Kubernetes连接,并在本地进行开发,同时使用VPN查看Kubernetes上的依赖关系。
能够实现这一目标的就是 “远程交互”(Telepresence)。
“远程交互”是一个开源软件(OSS),也是 CNCF 沙盒项目的其中之一。
验证环境
本次我们在以下环境下进行了验证。
$ telepresence --version
0.97
$ docker --version
Docker version 18.09.2, build 6247962
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.1", GitCommit:"eec55b9ba98609a46fee712359c7b5b365bdd920", GitTreeState:"clean", BuildDate:"2018-12-13T19:44:10Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Kubernetes正在使用Amazon EKS。
演示示范
我们将执行Telepresence的文档示例。
部署样本应用程序
首先根据 Telepresence 的文档,部署示例应用程序。
$ kubectl run qotm --image=datawire/qotm:1.3 --port=5000 --expose
远程互动的实际样例
使用Telepresence,可以通过–docker-run选项在本地启动一个可以与Kubernetes通信的容器。
比如,可以按照以下方式启动。
$ telepresence --docker-run --rm -it alpine sh
使用curl命令,确认访问刚刚部署的示例应用程序。
# apk add --no-cache curl
# curl http://qotm:5000/
{"hostname":"qotm-5969b5f959-vv82j","ok":true,"quote":"The light at the end of the tunnel is interdependent on the relatedness of motivation, subcultures, and management.","time":"2019-02-26T07:13:41.112912","version":"1.3"}
以这种方式,可以非常轻松地访问在Kubernetes上的应用程序。
远程存在 -docker-run之后的部分通常会提供与普通的docker run命令相同的选项。
当我们实际查看Telepresence的帮助文件时…
$ telepresence -h
usage: telepresence [-h] [--version] [--verbose] [--logfile LOGFILE]
[--method {inject-tcp,vpn-tcp,container}]
[--new-deployment DEPLOYMENT_NAME | --swap-deployment DEPLOYMENT_NAME[:CONTAINER]
| --deployment EXISTING_DEPLOYMENT_NAME]
[--context CONTEXT] [--namespace NAMESPACE]
[--expose PORT[:REMOTE_PORT]]
[--also-proxy CLOUD_HOSTNAME] [--mount PATH_OR_BOOLEAN]
[--env-json FILENAME] [--env-file FILENAME]
[--run-shell | --run ... | --docker-run ...]
:
:
:
--docker-run ... Run a Docker container, by passing the arguments to
'docker run', e.g. '--docker-run -i -t ubuntu:16.04
/bin/bash'. Requires --method container.
这段文字的意思是要求给Docker运行命令(docker run)提供参数。
通过 telepresence –docker-run 命令,在内部执行 docker run 命令,并且可以通过 ./telepresence.log 查看执行的详细内容。
$ cat ./telepresence.log
:
:
:
256.9 TEL | Main process (docker run --name=telepresence-1551165091-314365-90696 --network=container:telepresence-1551165070-841074-90696 -e=TELEPRESENCE_POD -e=TELEPRESENCE_CONTAINER -e=KUBERNETES_SERVICE_PORT -e=KUBERNETES_PORT_443_TCP_PROTO -e=QOTM_SERVICE_HOST -e=QOTM_PORT_5000_TCP -e=QOTM_PORT_5000_TCP_PORT -e=QOTM_PORT_5000_TCP_ADDR -e=KUBERNETES_SERVICE_HOST -e=KUBERNETES_PORT_443_TCP -e=KUBERNETES_PORT_443_TCP_PORT -e=KUBERNETES_PORT_443_TCP_ADDR -e=QOTM_PORT -e=QOTM_PORT_5000_TCP_PROTO -e=KUBERNETES_SERVICE_PORT_HTTPS -e=KUBERNETES_PORT -e=QOTM_SERVICE_PORT -e=TELEPRESENCE_ROOT -e=TELEPRESENCE_METHOD --volume=/tmp/tel-5i3c8wyy/fs:/tmp/tel-5i3c8wyy/fs --init --rm -it alpine sh)
:
:
:
我们可以看出,通过在Telepresence上添加环境变量等选项后执行docker run。
搭建Spring Boot的开发环境
我們已經理解了Telepresence的概述,現在開始實際搭建Spring Boot的開發環境。
创建Shell脚本
構築開発环境只需准备以下的shell脚本。
#!/bin/bash
#
# 開発環境のコンテナを起動するスクリプト
#
# 引数1. 開発対象のプロジェクトホームディレクトリ
#
# <実行例>
# ./develop.sh .
#
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace
readonly DEVELOP_PROJECT_DIR="$1"
readonly DEVELOP_PROJECT_ABSOLUTE_DIR=$(cd ${DEVELOP_PROJECT_DIR}; pwd)
readonly IMAGE='openjdk:8u191-jdk-alpine3.8'
readonly APP_PORT='8080'
readonly DEBUG_PORT='5005'
readonly CONTAINER_WORKING_DIR='/opt/work'
telepresence \
--docker-run \
--rm \
-p "${APP_PORT}":"${APP_PORT}" \
-p "${DEBUG_PORT}":"${DEBUG_PORT}" \
-v "${DEVELOP_PROJECT_ABSOLUTE_DIR}":"${CONTAINER_WORKING_DIR}" \
-v ~/.m2:/root/.m2 \
-w "${CONTAINER_WORKING_DIR}" \
"${IMAGE}" \
./mvnw spring-boot:run \
-Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${DEBUG_PORT}"
解释
我将按顺序解释上述Shell脚本的要点。
使用spring-boot-devtools实现热部署
写代码并构建容器进行运行检验会花费太多时间,因此我们使用spring-boot-devtools。
在pom.xml中添加spring-boot-devtools,然后使用./mvnw spring-boot:run命令来启动,这样可以实时反映源代码的变化。
关键点在于 `-v “${DEVELOP_PROJECT_ABSOLUTE_DIR}”:”${CONTAINER_WORKING_DIR}”` 这部分,它将项目主目录挂载到容器的工作目录。
通过这个方法,即使不在容器中进行开发,也可以在本地使用IDE进行开发。
※ 使用 IntelliJ 操作 spring-boot-devtools 时,请注意需要在 IntelliJ 中进行额外设置。
–删除选项
我在本地运行容器时基本上都会加上 –rm 选项。
通过加上 –rm 选项,容器会在停止时被删除。
这样可以防止电脑上积累不需要的容器。
使用挂载m2目录来利用Maven缓存。
如果每次使用 –rm 来重新创建容器,那么 .m2 目录下的 Maven 缓存将无法工作,导致每次启动都需要花费较长时间。
通过将~/.m2:/root/.m2挂载成.m2目录,解决了这个问题。
不推荐在不使用 –rm 选项的情况下重复使用容器的解决方案,因为这样会导致不删除容器的动机,可能会导致不具备可复现性的开发环境。
调试器的执行
在容器上运行应用程序时,调试器仍然可以正常使用。
只需在启动命令中添加”-Drun.jvmArguments=”-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${DEBUG_PORT}”选项,并使用”-p “${DEBUG_PORT}”:”${DEBUG_PORT}””的方式将调试器端口转发到主机上。
这样,IDE的调试器就可以正常工作了。
总结
如果仅使用 –docker-run,Telepresence 的学习成本非常低。虽然还有一些高级应用方法,比如在 Kubernetes 上进行部署替换,但首先尝试使用 –docker-run 似乎是个不错的选择。
这次我们以Spring Boot开发环境为例,但要在容器上搭建开发环境,需要了解一些诀窍。
例如,如果要在容器上使用webpack-dev-server,如果不进行配置更改,它将无法实现热重载。
要想熟练运用Kubernetes及其相关工具,似乎需要实际构建并积累经验。
在释义提及的话题中,是否应该将Telepresence进行容器化,只需要一个选择。
在使用Amazon EKS + Mac上的Telepresence时,会涉及许多工具,具体如下。
-
- Docker
-
- AWS CLI
-
- kubectl
-
- aws-iam-authenticator
-
- osxfuse
- Telepresence
无论如何,安装Docker是必要的,但对于所有开发者安装其他5个工具可能有些麻烦。
因此,考虑将除了Docker以外的5个工具都容器化并分发。
容器化的好处是什么?
-
- 開発環境セットアップの手間が減る
- 開発者から Kubernetes を隠蔽できる
我认为是这样的点。
一方,不使用容器化的好处是
-
- 興味を持った開発者にとって開発環境を理解するコストが下がる
- 開発者が少しずつ Kubernetes にふれ、学んでいく可能性がある
我认为是这一点。
通过将远程存在技术容器化,可提高可携性,但也可能导致Dev-Ops分离等问题。这是一个并非所有情况都适用容器化的例子。
可以提供一个参考
-
- Telepresence
-
- 開発用マシンからKubernetesのクラスタ内ネットワークに透過的にアクセスする
- Telepresence で EKS 上の k8s クラスタをデバッグする