说明
  • k8s在发布编译型语言的应用时,几乎不用多考虑,就会选择将编译好jar/war包(java语言)或者二进制文件(golang/c++)直接打到镜像当中,生成新的应用镜像,然后将镜像推到镜像仓库,再触发k8s完成应用发布或者版本更新
  • 对于解释型语言的应用,对于一个php开发者来讲,有的时候,一次发布,可能就只修改了一个文件,通过传统的发布方式,完成一次发布可能只需要10秒钟。而如果只是修改了一个文件却需要将整个代码完整打包,生成一个新的镜像,打镜像推镜像的时间可能就需要1分钟,再加上镜像替换,流动更新的时间,整个更新操作的时间就会拉的更长。虽然这在生产环境中的表现可能还并不明显,但在需要持续集成,频繁迭代的测试环境中,这种表现在发布时间上的巨大心理落差几乎无法让开发人员接受。事实上,这也是大多数解释型语言的开发者抵制docker的一个原因之一。

那么到底有没有更好的解决办法呢?

单独发布代码

事实上,有很多公司在实际使用中针对解释型语言的应用都选择了使用容器标准化运行时环境,代码单独发布的方式。

具体的做法是,使用镜像打包标准的php运行环境,然后将代码直接发布到k8s的所有node节点上,然后在任意节点上启动php标准镜像,并挂载所在节点的指定代码目录即可。因为所有节点上都有代码,所以php容器可以在任意节点之间漂移。如果不想把代码发布到所有节点,只想发布到某几个节点,也很好解决,只需要给这几个节点打上label,然后限定php容器只运行在带有该label的节点上即可。

这么做的优点显而易见:

  1. 通过容器的方式标准化了php环境,而且简化了php环境的部署操作。
  2. php代码发布仍然采用传统的发布方式独立发布,不受打镜像推镜像的时间影响,做到了快速迭代。

缺点同样显而易见:

  1. 首先镜像和代码拆开发布的方式本身就不是容器化标准所推荐的方法
  2. 我们需要通过label的方式严格对node和pod的对应关系做限定,一旦出错,就会出现pod正常运行,访问报错的现象,因为pod无法正常挂载代码。
  3. 因为一台宿主机上只有一份代码,如果该台宿主机上同时运行了同一个应用的多个pod,那么这些pod将会挂载同一份代码,当多个进程同时读写同一份代码时,需要代码自行解决冲突,虽然这种情况其实很少出现(绝大多数时候,应用程序的开发者都会避免在代码目录执行写操作,而对于读操作,多进程是可以共存的)。当然另一个可行的解决办法是通过pod的反亲和性调度避免将同一个应用的多个pod运行在同一个node节点上,毫无疑问,这也增加了配置的复杂性。
应用容器主动拉取代码

事实上,这是合乎容器化标准的一种实现。

而要实现这种方式,需要解决两个问题:

  1. 应用容器第一次启动时,如何获取代码
  2. 应用代码更新时,容器如何更新代码

第一个问题,我们使用kubernetes的init container技术来解决(在某些应用场中,使用pod启动后的钩子事件也可以解决,但在类似lua的应用场中,在应用容器启动之前就需要代码就位的情况下,这种方式并不合适,所以init container才是最好的选择)。其原理是在应用容器启动之前,先启动一个初始化容器,然后在初始化容器中执行从git仓库,或者从发布服务器拉取代码的操作,将代码直接拉取到应用容器的存储位置,然后启动应用容器,这样应用容器一启动,就有了代码。

第二个问题,可以直接调用k8s api,获取到当前应用的所有pod信息,然后触发循环调用pod上的rsync,执行主动拉取操作。

事实上,在我们当前的测试环境的lua代码的发布场景中,尤其适用。因为我们在测试环境中,持续集成的过程是自动完成的,每分钟执行一次持续集成操作。会先从git仓库将代码拉取到发布节点,发布节点启动rsync server端。然后各node节点上配置定时任务,每分钟从发布节点同步代码。对于lua应用来讲,每次代码更新就需要执行一次Nginx重载。通过这种发布方式,我们可以实现只有在有代码更新时,才执行nginx重载,而不是每分钟一次。

缺点:

  1. 增加了发布服务器的压力,所有pod不再共享宿主机代码,而是每个pod一套独立代码,所有pod都会从发布服务器拉取代码,在pod数量较大时,对发布服务器的io是个考验。另外如果某节点宕机时,所有pod漂移到新节点上重新启动,会同一时间向发布服务器拉取代码,对发布服务器的io压力也会较大
  2. 其配置相对于独立发布代码的方式其实是同样复杂的,但是其不用限定pod与node的对应关系,增加了调度的灵活性。

下面是一个应用容器主动拉取代码的k8s deployment配置文件示例:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: dyland-lua-api-pre
namespace: php
spec:
replicas: 1
selector:
matchLabels:
name: dyland-lua-api-pre
envrion: php
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9913"
prometheus.io/scheme: "http"
prometheus.io/path: "/metrics"
labels:
name: dyland-lua-api-pre
envrion: php
version: ""
spec:
initContainers:
- name: rsync-code
image: hub.dz11.com/op-base/rsync:v3.1.3
command:
- "sh"
- "-c"
- >
/bin/echo '123456' > /home/www/server/rsync.pwd;
chmod 400 /home/www/server/rsync.pwd;
/usr/bin/rsync -avzLu --password-file=/home/www/server/rsync.pwd www@$(RSYNC_SERVER)::pre-lua/dyland-lua-api.pre.wh03 /home/www/server/ > /dev/stdout 2>&1;
env:
- name: RSYNC_SERVER
value: 192.168.1.10
volumeMounts:
- name: www-root
mountPath: "/hommee/www/server"
containers:
- name: dyland-lua-api-pre
image: hub.dz11.com/op-base/openresty:1.11.2.4
imagePullPolicy: Always
lifecycle:
postStart:
exec:
command:
- "sh"
- "-c"
- >
/bin/echo 'options single-request-reopen' >> /etc/resolv.conf;
ports:
- containerPort: 80
env:
- name: APP_NAME
value: dyland-lua-api.pre.wh03
volumeMounts:
- name: nginx-conf
mountPath: /usr/local/ngx_openresty/nginx/conf/vhost
- name: applogdir
mountPath: /home/www/logs/applogs
- name: srvlogdir
mountPath: /home/www/logs/srvlogs
- name: www-root
mountPath: /home/www/server
# mountPath: /home/www/server/dyland-lua-api.pre.wh03
- name: nginx-vts-exporter
image: hub.dz11.com/library/nginx-vts-exporter:v0.10.3
ports:
- containerPort: 9913
env:
- name: NGINX_HOST
value: "http://localhost/status/format/json"
volumes:
- name: nginx-conf
configMap:
name: dyland-lua-api-pre-configmap
- name: applogdir
hostPath:
path: /home/www/logs/applogs
- name: srvlogdir
hostPath:
path: /home/www/logs/srvlogs
- name: www-root
emptyDir: {}
# hostPath:
# path: /home/www/server/dyland-lua-api.pre.wh03
imagePullSecrets:
- name: dk-reg
nodeSelector:
testenv: pre

  

kubernetes发布解释型语言应用的最佳实践的更多相关文章

  1. K8S发布解释型语言应用的最佳实践

    说明 我们知道,k8s在发布编译型语言的应用时,几乎不用多考虑,就会选择将编译好jar/war包(java语言)或者二进制文件(golang/c++)直接打到镜像当中,生成新的应用镜像,然后将镜像推到 ...

  2. Kubernetes日志的6个最佳实践

    本文转自Rancher Labs Kubernetes可以帮助管理部署在Pod中的上百个容器的生命周期.它是高度分布式的并且各个部分是动态的.一个已经实现的Kubernetes环境通常涉及带有集群和节 ...

  3. 可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

    写在前面 为了不违反广告法,我竭尽全力,不过"最佳实践"确是标题党无疑,如果硬要说的话 只能是个人最佳实践. 问题引出 ​ 可能很多新手都会遇到同样的问题:我要我的Asp.net ...

  4. 基于kubernetes集群的Vitess最佳实践

    概要 本文主要说明基于kubernetes集群部署并使用Vitess; 本文假定用户已经具备了kubernetes集群使用环境,如果不具备请先参阅基于minikube的kubernetes集群搭建, ...

  5. 验证Kubernetes YAML的最佳实践和策略

    本文来自Rancher Labs Kubernetes工作负载最常见的定义是YAML格式的文件.使用YAML所面临的挑战之一是,它相当难以表达manifest文件之间的约束或关系. 如果你想检查所有部 ...

  6. Kubernetes YAML最佳实践和策略

    Kubernetes工作负载最常用YAML格式的文件来定义. YAML的问题之一就是很难描述清单文件之间的约束或关系. 如果你希望检查是否已从受信任的注册表中提取部署到群集中的所有映像,该怎么办? 如 ...

  7. Kubernetes 微服务最佳实践

    本文由个人笔记 ryan4yin/knowledge 整理而来 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes 配置」,是我个人的「最佳实践」. 其中大部 ...

  8. Kubernetes生产环境最佳实践

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 众所周知,Kubernetes很难! 以下是在生产中使用 ...

  9. 在 Kubernetes 容器集群,微服务项目最佳实践

    转载自:https://mp.weixin.qq.com/s/WYu3gDwKKf06f_FYbO9YRg 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes ...

随机推荐

  1. 除了BAT,计算机、软件专业的毕业生还有别的好去处吗?

    "学技术的同学应该关注36氪.pingwest,极客公园这些圈子里很有影响力的科技媒体" 转载--除了BAT,计算机.软件专业的毕业生还有别的好去处吗? 又到校招季,985理工科的 ...

  2. winform中的ComboBox同时设置text和value的方法

    winform中的ComboBox不能像webform中的dropdownlist控件一样,在属性中可以同时设置text和value值,可以通过编写一个新类来实现这个功能. 1.首先在form1中添加 ...

  3. “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第三篇(登录窗口的实现以及如何保存登录者的信息)

    一.前言: 1.再看这篇文章的时候,您是否已经完成前两篇介绍的文章里的功能了?(Tabs页的添加,Tabs页右键的关闭,主题的更换)                 2.今天来说说登录窗口吧,看截图: ...

  4. python接口自动化(三十五)-封装与调用--流程类接口关联(详解)

    简介 流程相关的接口,主要用 session 关联,如果写成函数(如上篇),s 参数每个函数都要带,每个函数多个参数,这时候封装成类会更方便.在这里我们还是以博客园为例,带着小伙伴们实践一下. 接口封 ...

  5. [WIP]laravel 构成的概念

    创建: 2019/06/21 生命周期  概论    检索service provider               service container                     se ...

  6. vue中通过cross-env插件配置三种环境(开发,测试,生产)打包,不用切换api

    1. 话不多说,第一步就是安装必要的插件 npm install cross-env --save 2.修改config里面的参数,这里只展示一个test,其他类似 3.修改package.json ...

  7. bzoj2039: [2009国家集训队]employ人员雇佣(最小割)

    传送门 膜一下大佬->这里 不难看出这是一个最小割的模型(然而我看不出来) 我们从源点向每一个点连边,容量为他能带来的总收益(也就是他能对其他所有经理产生的贡献) 然后从每一个点向汇点连边,容量 ...

  8. C语言经典算法100例(三)

    1.河内之塔 说明河内之塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市:1883年法国数学家 Edoua ...

  9. 在pom包中添加spring-boot-starter-test包引用

    有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发.调试.打包到最后的投产上线. 开发阶段 单元 ...

  10. @Inherited:允许子类继承父类的注解。

    在看定义注解的相关文章的时候,看到这个@Inherited注解,简单的说明并没有真正搞懂是什么意思.在网上搜索了一些相关的内容,现在把一篇文章转载过来.以便后面使用. 文章出处,转载地址:(http: ...