Kubernetes提示和技巧:关于本地开发和网真



人们越来越多地被问到Kubernetes中微服务的发展。 开发人员,尤其是解释型语言,希望通过他们最喜欢的IDE快速修复代码,而无需等待构建/部署看到结果-只需按F5键即可。 当涉及到整体应用程序时,足以在本地提升数据库和Web服务器(在Docker,VirtualBox中...),此后-立即享受开发工作。 随着将单片锯切成微服务以及Kubernetes的问世,随着相互依赖的出现,事情变得更加复杂了 。 这些微服务越多,问题就越多。 要再次享受开发的乐趣,您需要筹集一个或两个以上的Docker容器,有时甚至要增加十二个以上……总的来说,这可能要花费很多时间,因为您还需要保持最新状态。

在不同的时间,我们尝试了不同的解决方案。 我将从累积的解决方法或简单的“拐杖”开始。

1.拐杖


大多数IDE都可以使用FTP / SFTP在服务器上直接编辑代码。 这种方式非常明显,我们立即决定使用它。 其实质如下:

  1. 在开发环境(开发/审查)的窗格中,启动了一个附加容器,该容器可通过SSH进行访问并转发将提交/部署应用程序的开发人员的公共SSH密钥。
  2. 在初始化阶段(在prepare-app容器内),我们将代码传输到emptyDir ,以便可以使用应用程序和SSH服务器从容器访问代码。



为了更好地了解这种方案的技术实现,我将给出Kubernetes中涉及的YAML配置的片段。

构型


1.1。 values.yaml


 ssh_pub_key: vasya.pupkin: <ssh public key in base64> 

此处vasya.pupkin是变量${GITLAB_USER_LOGIN}

1.2。 deployment.yaml


 ... {{ if eq .Values.global.debug "yes" }} volumes: - name: ssh-pub-key secret: defaultMode: 0600 secretName: {{ .Chart.Name }}-ssh-pub-key - name: app-data emptyDir: {} initContainers: - name: prepare-app {{ tuple "backend" . | include "werf_container_image" | indent 8 }} volumeMounts: - name: app-data mountPath: /app-data command: ["bash", "-c", "cp -ar /app/* /app-data/" ] {{ end }} containers: {{ if eq .Values.global.debug "yes" }} - name: ssh image: corbinu/ssh-server volumeMounts: - name: ssh-pub-key readOnly: true mountPath: /root/.ssh/authorized_keys subPath: authorized_keys - name: app-data mountPath: /app ports: - name: ssh containerPort: 22 protocol: TCP {{ end }} - name: backend volumeMounts: {{ if eq .Values.global.debug "yes" }} - name: app-data mountPath: /app {{ end }} command: ["/usr/sbin/php-fpm7.2", "--fpm-config", "/etc/php/7.2/php-fpm.conf", "-F"] ... 

1.3。 secret.yaml


 {{ if eq .Values.global.debug "yes" }} apiVersion: v1 kind: Secret metadata: name: {{ .Chart.Name }}-ssh-pub-key type: Opaque data: authorized_keys: "{{ first (pluck .Values.global.username .Values.ssh_pub_key) }}" {{ end }} 

最后一点


之后,只剩下将必要的变量传递给gitlab-ci.yml

 dev: stage: deploy script: - type multiwerf && source <(multiwerf use 1.0 beta) - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose) - werf deploy --namespace ${CI_PROJECT_NAME}-stage --set "global.env=stage" --set "global.git_rev=${CI_COMMIT_SHA}" --set "global.debug=yes" --set "global.username=${GITLAB_USER_LOGIN}" tags: - build 

瞧,启动部署的开发人员可以通过SFTP从桌面使用服务的名称( 我们已经告诉过您如何安全地授予对群集的访问权限)进行连接,并编辑代码,而无需等待将其传递给群集。

这是一个完全可行的解决方案,但是从实现的角度来看,它具有明显的缺点:

  • 需要完善Helm图表,这使其阅读更加复杂;
  • 只有部署了该服务的人才能使用它;
  • 您需要记住要使用代码将其与本地目录同步并在Git中提交。

2.网真


网真项目已经存在了很长一段时间,但正如他们所说,在我们的实践中认真尝试了一下,“没有伸手可及”。 但是,需求已经完成,现在我们很高兴分享对博客读者有用的经验-特别是因为中心上没有其他有关网真的材料。

简而言之,它并不那么可怕。 所有需要开发人员执行的操作,我们都放置在Helm-chart的文本文件中,名为NOTES.txt 。 因此,在Kubernetes中部署服务后,开发人员会在GitLab作业日志中看到有关启动本地开发环境的说明:

 !!!   ,   Kubernetes !!! *   * *       VPN * *     kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ ) * *  config-  kubectl (  ~/.kube/config) * *     telepresence ( https://www.telepresence.io/reference/install ) * *    Docker * *    reporter     https://gitlab.site.com/group/app * *    registry  /  GitLab (  ): ######################################################################### docker login registry.site.com ######################################################################### *   ######################################################################### telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8 ######################################################################### 


除了最后一步,我们将不详述本手册中描述的步骤。 网真启动期间会发生什么?

使用网真


在开始时(通过上述说明中指定的最后一个命令),我们设置:

  • 启动微服务的名称空间(名称空间);
  • 部署的名称以及我们要渗透的容器。

其余参数是可选的。 如果我们的服务与Kubernetes API交互并为其创建了ServiceAccount ,则需要在桌面上安装证书/令牌。 为此,请使用选项--mount=true (或--mount=/dst_path ),该选项会将根(/)从Kubernetes中的容器安装到我们的桌面。 之后,我们可以(取决于操作系统和应用程序的启动方式)使用集群中的“密钥”。

首先,考虑最通用的应用程序启动选项-在Docker容器中。 为此,请使用--docker-run开关,并使用以下代码将目录装入容器中: -v `pwd`:/app

请注意,这意味着从项目目录开始。 应用程序代码将安装在容器中的/app目录中。

下一步: -v /tmp/app/var/run/secrets:/var/run/secrets将带有证书/令牌的目录装入容器。

最后,此选项之后是将在其中启动应用程序的映像。 注意 :构建映像时,必须指定CMDENTRYPOINT

实际上,接下来会发生什么?

  • 在Kubernetes中,对于指定的Deployment,副本数量将更改为0.相反,将启动新的Deployment-带有替换的backend容器。
  • 在桌面上,将启动2个容器:第一个容器-使用网真(它将代理来自/到Kubernetes的请求),第二个容器-正在开发应用程序。
  • 如果exec'nitsya与应用程序一起位于容器中,则我们将有权访问在部署期间Helm传递的所有ENV变量以及所有可用的服务。 剩下的就是在您喜欢的IDE中编辑代码并享受结果。
  • 在工作结束时,只需关闭运行Telepresence的终端(使用Ctrl + C结束会话),Docker容器将在桌面上停止,一切将恢复为Kubernetes中的原始状态。 剩下的就是提交,发布MR并将其传递给审阅/合并/ ...(取决于您的工作流程)。

如果我们不想在Docker容器中运行该应用程序(例如,我们不是使用PHP开发该应用程序,而是使用Go进行开发,并且仍在本地收集它),则启动网真将变得更加容易:

 telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name }}:backend --mount=true 

如果应用程序访问Kubernetes API,则需要使用keys挂载目录 。 对于Linux,有一个proot实用程序:

 proot -b $TELEPRESENCE_ROOT/var/run/secrets/:/var/run/secrets bash 

在不使用--docker-run选项的情况下启动网真之后,所有环境变量将在当前终端中可用,因此您需要在其中启动应用程序。

注意 :例如,在使用PHP时,您需要记住禁用各种op_cache,apc和其他加速器进行开发-否则,编辑代码将不会产生所需的结果。

总结


Kubernetes的本地开发是一个问题,解决方案的需求与该平台的普及程度成正比。 在收到开发人员(来自我们的客户)的相关请求后,我们开始采用第一种可用的方法来解决它们,但是这种方法并不能在很长的距离内证明自己。 幸运的是,这不仅在现在而且不仅在我们身上变得显而易见,因此世界上已经出现了更合适的方式,并且网真是其中最著名的方式(顺便说一句 ,Google还提供了一个折页 )。 我们使用它的经验还不是很好,但是它已经为我们推荐“同事”提供了理由-试试吧!

聚苯乙烯


K8s提示和技巧周期中的其他内容:

Source: https://habr.com/ru/post/zh-CN446788/


All Articles