使用helm-controller-简化容器云平台应用商店的开发开发手册
熟练的阅读并且进行相应的开发,大概需要对以下知识的了解:
- k8s rest api 模型需要了解。
- http协议需要熟练掌握。
- openapi规范了解。
- linux熟练掌握。
- helm的理论架构了解。
- k8s crd 的理解,controller概念掌握,rbac权限模型的理解。
- helm私库index.yaml的理解与使用。
- core dns的配置与使用。
整体结构图
helm是啥
helm是k8s的包管理器,也是k8s平台复杂应用部署事实上的标准。包含了应用打包,部署,升级,回滚,卸载等符合生命周期管理的功能。
架构变动
helm从v2到v3的版本升级,移除了重要的一个组件tiller,整体架构更简洁。
helm架构在云管理平台开发中的不足
helm至今为止,官方仍然没有ga版的api。chart的下载,部署,升级,卸载,全部依赖cli。在多集群环境下cli很难满足平台的业务要求。
通过查看github issue,社区大概有两种解决思路:
- 封装cli成api。这种方式仍然存在每个集群需要通过ssh或者ansible的方式部署helm二进制文件到master节点上,给底层部署工作添加负担。
- CRD。将helm的核心能力打包成docker镜像,部署到k8s集群中,以controller的方式提供能力。利用crd的方式完成release的部署,卸载,升级,回滚等业务动作。
cli方式最大的问题就在于不符合云原生的思想,而且cli的方式和helm版本锁定,如果要升级helm,需要重新适配解析console内容。 crd的问题在于,官方目前还没有ga。但仍然期待controller的方式。
我们团队最初使用第一种方式进行了尝试,但效果不理想。恰巧当时发现灵雀云开源了helm v3 controller captain,所以基于社区captain的进行了第二次尝试,并最终完成了功能开发。
当时,在github搜索helm controller
,发现了两个仓库,一个是rancher提供的controller,一个是灵雀云提供的。经过简单的测试,captain一次性安装并测试成功,并结合内部的讨论,最终决定基于captain进行开发。
captain
github: https://github.com/alauda/captain
介绍
The Helm 3 Design Proposal exists for a while and currently it is still under heavy development. Captain comes as the first implementation of Helm v3 Controller based on the Proposal. This project is based on the core helm v3 code, acting as a library. Since it's not officially released yet (alpha stage for now), some modifications were made to help implement this controller on a fork: alauda/helm (will be deprecated once Helm's library is released).
captain是灵雀云开源的helm v3 controller
。其内部依赖helm library。所以核心的逻辑与helm client是一致的。等到后期helm官方正式ga后,可以迁移回官方正式版本,这对于以面向接口编程的java来说,so easy。
基于Apache 2.0协议开源
captain内部将helm部署成deployment。
快速安装测试
安装步骤:
kubectl create ns captain-system kubectl create clusterrolebinding captain --serviceaccount=captain-system:default --clusterrole=cluster-admin kubectl apply -n captain-system -f https://raw.githubusercontent.com/alauda/captain/master/artifacts/all/deploy.yaml
卸载:
kubectl delete -n captain-system -f https://raw.githubusercontent.com/alauda/captain/master/artifacts/all/deploy.yaml kubectl delete ns captain-system
安装nginx chart
kind: HelmRequest apiVersion: app.alauda.io/v1alpha1 metadata: name: nginx-ingress spec: chart: stable/nginx-ingress
查看部署结果
root@VM-16-12-ubuntu:~/demo# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-ingress-controller-57987f445c-9rhv5 1/1 Running 0 16s nginx-ingress-default-backend-7679dbd5c9-wkkss 1/1 Running 0 16s root@VM-16-12-ubuntu:~/demo# kubectl get hr NAME CHART VERSION NAMESPACE ALLCLUSTER PHASE AGE nginx-ingress stable/nginx-ingress default Synced 23s
chart repo问题
captain默认自带stable的helm官方仓库,helm官方的仓库地址本身没有问题,但是chart镜像中如果使用了被墙了的docker镜像,无法下载。测试的时候是使用的aliyun提供的仓库地址https://developer.aliyun.com/hub/。这样captain controller才能顺利的将chart镜像下载成功。
当测试结束时,我们需要将k8s与内网的chart私库进行打通,需要新建一个ChartRepo的yaml文件
apiVersion: app.alauda.io/v1alpha1 kind: ChartRepo metadata: name: cloud namespace: captain-system spec: url: https://harbor.offline/chartrepo/library
然后使用kubectl create -f fileName
添加到k8s中,需要注意的是,我们使用了harbor做docker镜像和helm镜像的管理,因为docker的问题,我们使用了自签的证书,captain在根据地址同步的时候,会校验证书,这个问题我们也和官方进行了沟通,得到了解决,目前captain已经ga,可以直接使用,不需要担心证书的问题。
RBAC权限问题
云平台的管理中,我们通过servicecount进行k8s api的使用,当安装了captain之后,不同于命令行使用user account,我们需要额外的一步追加权限的动作
kubectl create clusterrolebinding default --serviceaccount=default:default --clusterrole=cluster-admin
captain sdk问题
captain 官方目前只提供了go和python的sdk,基于此,我们肯定要封装一个captain的java sdk。
在架构底层,我们使用k8s官方的sdk进行开发。
基于crd和k8s openapi的简单了解,结合官方的说明,尝试性的进行了sdk生成的动作,结果失败了,详细见issue我们也联系了作者,得知captain并没有基于schema做校验,内部使用了webhook进行的校验。基于这样的背景,直接使用openapi规范生成sdk的路不通,后面我们直接使用了kubectl -v9
的方式进行报文的验证,以及代码的开发。
使用kubectl命令行进行任意操作时,追加-v9
参数,可以获取详细的http报文信息
root@master:/home/kylin# kubectl get pod -v9 I0414 22:42:53.981748 16582 loader.go:359] Config loaded from file: /root/.kube/config I0414 22:42:54.042173 16582 round_trippers.go:419] curl -k -v -XGET -H "Accept: application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json" -H "User-Agent: kubectl/v1.15.5 (linux/amd64) kubernetes/20c265f" 'https://192.168.4.139:6443/api/v1/namespaces/default/pods?limit=500' I0414 22:42:54.077898 16582 round_trippers.go:438] GET https://192.168.4.139:6443/api/v1/namespaces/default/pods?limit=500 200 OK in 35 milliseconds I0414 22:42:54.077959 16582 round_trippers.go:444] Response Headers: I0414 22:42:54.078006 16582 round_trippers.go:447] Content-Type: application/json I0414 22:42:54.078054 16582 round_trippers.go:447] Date: Tue, 14 Apr 2020 14:42:54 GMT I0414 22:42:54.078394 16582 request.go:947] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1beta1","metadata":{"selfLink":"/api/v1/namespaces/default/pods","resourceVersion":"14332801"},"columnDefinitions":完整报文太长,略去!}]}}}]} I0414 22:42:54.092067 16582 get.go:564] no kind "Table" is registered for version "meta.k8s.io/v1beta1" in scheme "k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go:30" NAME READY STATUS RESTARTS AGE busybox 1/1 Running 970 39d nginx-1585049022-b4f4c56c9-dvspz 1/1 Running 24 12d nginx-deployment-5bd886c88c-28d6q 0/1 Pending 0 2d1h nginx-deployment-5bd886c88c-968pd 0/1 MatchNodeSelector 0 4d3h nginx-deployment-5bd886c88c-dnh8q 0/1 MatchNodeSelector 0 4d3h nginx-deployment-5bd886c88c-pk9xz 0/1 Pending 0 2d1h
再结合k8s官方的java sdk提供的CustomObjectsApi。比较轻松的就开发了一整套chart镜像生命周期对应的接口。
部署
var customObjectsApi = new CustomObjectsApi(apiClient); var json = new JsonObjectBuilder() .set("apiVersion", "app.alauda.io/v1alpha1") .set("kind", "HelmRequest") .set("metadata", new JsonObjectBuilder().set("name", name).build()) .set("spec", new JsonObjectBuilder() .set("chart", chart) .set("namespace", namespace) .set("releaseName", name) .set("values", Map2JsonUtil.map2Json(params)) .set("version", version) ).build(); customObjectsApi.createNamespacedCustomObject("app.alauda.io","v1alpha1", "default", "helmrequests", json, null);
卸载
var customObjectsApi = new CustomObjectsApi(apiClient); customObjectsApi.deleteNamespacedCustomObject("app.alauda.io", "v1alpha1", "default","helmrequests", "test-nginx",new V1DeleteOptions().gracePeriodSeconds(0L).propagationPolicy("Foreground"),null, null, null);
升级
这里可以选择打patch或者直接replace,和k8s的概念是一致的。
回滚
captain并没有像deployment原生的提供了对回滚的支持,需要自己将每次安装或者升级的参数进行外部保存,再重新replace指定版本的参数,进行模拟回滚。
其他说明
- 整体上,我们使用了三周的时间完成了应用商店第一版的开发,以及页面接口联调。这比使用cli方式的预期快了很多,而且我们的ansbile部署脚本上只需要再额外添加两行安装captain的脚本。
- 使用私有helm repo,默认情况下,集群内的coredns将非集群内的地址转发到本机的
/etc/resolv.conf
,这个时候一定要确保k8s宿主机的/etc/resolv.conf
dns地址修改为内网的dns server地址。否则captain controller找不到私有的helm repo,错误是 timeout。 - 在开发过程中,如果遇到问题无法定位,可以直接查看captain-controller的log,来进行处理。
- 网络问题最好部署一个busybox,内置了nslookup,wget等工具。方便网络检测。
使用apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - name: busybox image: busybox:1.28.4 command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always
kubectl create -f busybox.yaml
完成busybox部署,使用kubectl exec -it busybox sh
进入容器内部,使用nslookup
,wget
等进行网络检测。
本文由博客群发一文多发等运营工具平台 OpenWrite 发布
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
kryo 各数据类型的序列化编码机制(揭晓为什么高效的原理)
用过 dubbo 的开发人员,在选取序列化时都会根据“经验”来选 kryo 为序列化框架,其原因是序列化协议非常高效,超过 java 原生序列化协议、hessian2 协议,那 kryo 为什么高效呢? 序列化协议,所谓的高效,通常应该从两方面考虑: 序列化后的二进制序列大小。 序列化、反序列化的速率。 > 本节将重点探讨,kryo在减少序列化化二进制流上做的努力。 序列化:将各种数据类型(基本类型、包装类型、对象、数组、集合)等序列化为 byte 数组的过程。 反序列化:将 byte 数组转换为各种数据类型(基本类型、包装类型、对象、数组、集合)。 java 中定义的数据类型所对应的序列化器 在Kryo 的构造函数中构造,其代码截图: 接下来将详细介绍java常用的数据类型的序列化机制,即Kryo是如何编码二进制流。 1、DefaultSerializers$IntSerializer int类型序列化 static public class IntSerializer extends Serializer<integer> { { setImmutable(tru...
- 下一篇
ThreadLocal的内存泄露的原因分析以及如何避免
前言 在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。 内存泄露 内存泄露为程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光, 广义并通俗的说,就是:不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。 强引用与弱引用 强引用,使用最普遍的引用,一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。 如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。 弱引用,JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。可以在缓存中使用弱引用。 GC回收机制-如何找到需要回收的对象 JV...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题