分享

K8S中文社区


公众号:
k8schina

功能介绍
docker、Kubernetes、微服务等云计算技术

经典文章推荐:

东方国信基于kubernetes构建容器云平台的实践和思考

本次,我分享的主题是《东方国信基于Kubernetes构建容器云平台的实践和思考》。

先讲一下背景,国信之前的软件部署方式是找台机器,把war包或者jar包往机器上一扔,启动就可以了,所有功能都在一个包里面,模块之间相互耦合,导致新功能开发上线周期很长,客户的需求得不到及时满足。

所以我们把我们的应用微服务化改造,微服务化以后,原来一个应用现在变成了十几个,每个应用功能相对独立,开发人员需要了解的东西变少,开发新功能也比以前简单了;

但是软件部署运维变得困难了,原来一个软件包,现在成了十几个。了解过DevOps的同学一定知道,开发和运维之间有一道墙,现在这道墙更高了。

所以我们希望有一款产品能解决我们这些痛点,最后我们把目标锁定在docker和kubernetes上,我们希望基于这个平台来实现DevOps的部分流程,来减轻部署运维的负担,同时能提高我们的资源利用率。

最后我们制定了下面这样一个架构:

20171213111457.jpg

这张图的最左边是我们控制台,叫BCM,用户所有的操作都在BCM的界面上面完成,包括镜像的构建,服务的发布、升级等,这种界面的东西各公司根据业务和服务对象不同会有所不同,但是主要功能都差不多,所以不展开说了,后面会贴几张界面。

我们先说最核心的k8s部分,因为所有工作都是围绕着k8s展开的。

云平台的主体基于K8S+Docker构建;通过KubeDNS来为集群内的应用程序提供域名解析;

通过heapster收集性能信息,写入influxDB,然后是BCM读取influxDB信息进行展示,我们没有使用grafana,主要是考虑到我们的平台是多租户的,不同的租户只能看到自己系统的性能指标;

而且我们通过对kubelet和heapster的修改,增加了对容器内应用的线程数和socket连接数的监控,为什么要增加?

因为我们在使用过程中发现有些应用代码质量不高,乱用线程,有的文件句柄打开后忘记关闭,导致运行一段时间后连接数据库失败,所以我们增加了这两项监控,当然严格执行代码质量检查和review才是更重要的。

大家也看到我们使用了prometheus,我们主要使用了prometheus对cpu和内存使用率进行告警,同时对prometheus和alertmanager增加了配置接口,在应用部署时,把阈值配置下去,同时重载prometheus的配置,完成监控功能。

我们使用fluent来收集容器的日志,写入elasticsearch,通过kibana进行检索。

同时bcm的web界面上可以查看实时日志,这本来是个小功能,但是开发过程也是一波三折,开始我们使用了k8s的api进行日志获取,当日志文件很大的时候,发现读取很慢,接着我们又修改成通过docker的api获取,但是还是很慢。有时候我们只想查看一个特定时间段的日志,这个日志量应该不会太大,应该很快才对。

于是我们查看了docker源码,发现有两点需要优化,第一是读取缓冲区,太小了,只有1KB;

第二就是每次都从第一条日志进行读取,反序列后进行时间比较,看看是否在时间段内,其实docker不支持结束时间,我们自己加的。

针对第一点,修改方法很简单,增大一下读取缓冲区就可以了;

第二点,修改策略是把日志分成多个文件,并且记录每个文件的开始日志时间和结束日志时间,通过查询记录信息,定位到第一个需要读取的日志文件和最后一个需要读取的文件,减少不必要的io。
更多:
https://www.kubernetes.org.cn/3314.html



本帖被以下淘专辑推荐:

已有(12)人评论

跳转到指定楼层
yuwenge 发表于 2018-4-10 21:32:36
谷歌大神详解 Kubernetes 配置管理最佳方法


Kubernetes Concepts1、Kubernetes 中的概念
我们先来说一下 Kubernetes 中几个重要的概念:第一个要说也是最重要的就是 Declarative,Declarative 的意思是申明的、陈述的,与之相反的是 Imperative,Imperative 意思是命令式的。首先说一下 Kubernetes 设计完全是按照 Declarative 设计的。但为了初学者的学习方便,也是支持 Imperative。Declarative 对 Kubernetes 的功能非常重要,比如说它的自育性、自治能力都完全是依赖于 Declarative。第二个概念是 Level-triggered,Edge-triggered 。第三个概念是异步的。这些概念在后面会详细的介绍。
1.jpg
2、Declarative 与 Imperrative 的对比
首先看一下 Declarative 和 Imperative 的区别和对比。Declarative 的定义是用户设定期望的状态,系统会知道它需要执行什么操作,来达到期望的状态。比如说我们看下面的例子。用户期望的状态是三个,系统观察到的状态是两个。于是系统就会知道创建一个新的来达到最终状态是三个。而对于 Imperative,需要用户告诉系统需要做什么。比如说用户说创建一个新的 Container,系统才会创建一个新的 Container。
2.jpg
3、Spec 与 Status 的对比
大部分的 Kubernetes API 都有 Spec 和 Status 两个 Field。Spec 是让用户写入期望的状态,系统可以通过 Spec 读出用户的期望。Status 是系统写入观察到的状态,用户可以从中读出系统当前是什么状态。
3.jpg
4、Reconcile
这两个 Field 对于 Reconciliation Loop 是非常重要的,接下来看一下什么叫 Reconcile?
4.jpg
Reconcile 中文意思是 “调和”,“和解” 的意思,简单的说就是它不断使系统当的状态,向用户期望的状态移动。比如说右边的例子,用户期望的 Replica 是三个,Controller 通过 Watch 发现期望的状态是 3 个,但实际观测到的 Replica 的是 2 个,所以它就会 Create 一个新的 Pod。然后 Controller 会继续 Watch 这些 Pod,当它发现 Create 完成了,就会更新 Status 到 3 个,使 Status 和 Spec 达到一致的状态。
5、Level-triggered 与 Edge-triggered 的对比
接下来再来说一下 Level–triggered 和 Edge-triggered 的区别。首先说一下 Kubernetes 是 Level-triggered。先看一下右边的例子。最上面是用户期望的状态变化。中间的是某一个 Edge-triggered Controller 的变化。最下面是 Level-triggered 的 Controller 的状态。在第二条虚线这个时刻,用户希望更新应用的版本,从 V1 到 V2,然而在第一条虚线和第三条虚线中间,我们的 Controller 死了。
对于 Edge-triggered 的 Controller 就会错过这个用户的更新请求,状态就没有变化。对于我们的 Level-triggered 的 Controller 就会在重新启动的时候发现用户的请求变化,就会更新版本到 V2。在这个时候用户想 Scale 他的应用的 Replica 到 3 个,这时候我们可以看到 Edge-triggered 的 Controller 就会直接 Scale V1,最终达到一个错误的状态。Level-triggered 的 Controller 就会最终达到正确的状态。
5.jpg
Kubelet Commands
Kubectl 的 Commands 可以被分为三类:Imperative Commands、Imperative Object Configuration 和 Declarative Object Configuration。
1、Imperative Commands
第一类是叫做 Imperative Commands。Imperative 的 Commands 主要就是通过命令行的 Flag 直接进行 Imperative 的操作,Create 或者是 delete 之类的。例子是 Kubectl run, Expose,或者是 Create deployment,它就会把底层对于对象配置的操作对用户隐藏了起来。
6.jpg
接下来我们再来看一下它们优缺点的对比。Edge-triggered 的 Controller 优点就是直接、简单,易于实现。缺点就是如果错过了一个 Edge,可能就会导致一个最终的错误的状态。Level-triggered Controller 的优点就是不用担心这个,Edge-triggered Controller 另外一个缺点是不会采用直接的路径达到当前的状态,比如说当前的版本是 V1,用户想要更新到 V2,紧接着用户发现了什么问题,马上想更新到 V3。对一个 Edge-triggered 的 Controller 就会完成 V2 的更新,然后再去更新 V3。而如果对一个 Level-triggered 的 Controller 会在接收到 V3 的更新请求的时候直接开始更新,而不会等完成 V2 再更新 V3。

2、Imperative Object Configuration
第二类要说的是 Imperative 对象配置,Object configuration 的意思是一个对象可以被定义为 yaml 或者 json 的格式存储在文件中,我们叫它 Object Configuration。Imperative Object Configuration 是直接对 Object Configuration 进行 Imperative 的操作,比如说 Kubectl create, Replace,Delete。
7.jpg
然后说一下第一类和第二类的对比。第一种 Imperative 的 Commands 优点是简单直接易学易记,缺点是没有办法使用 Change review,就是先更改再去批准流程,而且没有办法使用 Audittrails。Audit trails 的意思就是审计追踪又可以叫做 Audit log,它会记录系统的各种变化。第三个缺点是没法提供一个模板。相对于 Imperative Commands, Imperative Object Configuration 的优点是可以进行版本控制,比如说可以用 Git,也可以用 Change review 这个流程,也可以用 Autid trails,它的确定就是需要用户对于对象的 Schema 有一个基本的理解,另一个缺点就是需要用户写 yaml 文件。
8.jpg
3、Declarative Object Configration
第三类是 Kubectl 的 Commands 是 Declarative 的对象配置。它也是直接对 Object Configuration 进行操作的。用户不需要指定要 Create,Update 还是Delete,Commands 直接会帮你决定谁用哪一种。例子就是 ubectl apply –prune-f。
接下来对比第二类和第三类的区别。Imperative Object Configuration 对于 Declarative 的优点就是简单一些,稍微易理解一些。但它的缺点就是对于一个目录的配置文件只能选择同一种操作。它的第二个缺点就是其他用户的更新,必须被反应在配置文件中,不然其他用户的更新就会在下一次的更新中被丢掉。
9.jpg
接下来说一下 Declarative Object Configuration的优点。它的优点就是其他用户的更新可以被保留下来,比如说我的 Autoscaler 帮你管理的 Replica 这个 Field,你管理其他的 Field,你们之间就不会有冲突。第二个优点是对同一个目录下的对象可以有不同的操作,可以是 Create、Patch、Delete,缺点就是这个行为稍微难理解一些,需要时间来学习。
10.jpg

更多内容
https://www.kubernetes.org.cn/3031.html



回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:35:02
基于 Kubernetes 的 Jenkins 构建集群实践

作者:李华强-乐视致新
在大型团队的 CI 构建里具有丰富最佳实践的经验。今天我给大家分享的更多是聚焦在 Jenkins本身,结合我在 Jenkins 实际使用过程中和整个 Jenkins Slave 管理演化的过程的案例,这样能给大家带来更好的借鉴和参考体验。
下面是主要要分享的四大内容:
  • Jenkins分布式构建架构
  • 基于Lable的Slave集群管理
  • 基于Docker插件的容器化实践
  • 基于Kubernetes的容器化实践

一. Jenkins分布式构建架构1.1 架构图
1.jpg
Jenkins 分布式架构一个 Master 和多个 Slave Node 分布式的架构。
在 Jenkins Master 上管理你的项目,可以把你的一些构建任务分担到不同的 Slave Node 上运行,Master 的性能就提高了。
如果单纯的使用 Master 去构建,除了要承担项目上的编译、测试等开销外,还会大大的影响 Jenkins 应用本身占用 memory 和 CPU 资源。

1.2 Jenkins Slave 连接方式
2.jpg

Jenkins Slave 连接方式常使用下面两种:
  • 通过 SSH 启动 Slave 代理
    • 在 Jenkins 上直接配置,相当于从 Master 往 Slave 上连接,从 Master 上主动发起的请求。
  • 通过 JNLP 启动代理
  • 基于 Java Web Start 的 JNLP 的连接,从 Slave 往 Master 主动的方式。
这两种主要的连接方式,在后面的集群 slave 的管理方案中都会涉及到。
1.3 Jenkins 调度策略
3.jpg

  • 用户视角
    • 直接使用 slave name,构建使用指定 slave
    • 使用 label,构建多数使用同一个的 slave,偶尔使用其他 slave
  • 系统实现
    • consistent hashing algorithm (node,available executors,job name)
    • 每一个 Job 都有一个对应所有 Node 的优先级列表
  • 其它插件

在使用的过程中,是不是都会经常感觉到下面两种情形:
  • 如果一个项目的构建指定了一个 Slave,那么这个项目所有的每次构建都只用这个Slave构建。
  • 如果使用了label 去管理多个 Slave,给一个项目的构建指定了这个 label,会发现这个项目的多次构建,大多数都是使用同一个 Slave,并没有使用 label 里的其它 Slave。
从 Jenkins 本身的实现角度来说,Jenkins 分配它的调度策略的时候,有一个一致性的哈希算法,会将你添加的 Slave,也可以称为 node 节点,以及 node 上面可用的 executors,包括 job name,最后算出来一个相当于你的 job 和所有 Slave 对应的优先级列表,会选择优先级最高的Slave去构建,当不满足条件或者没有可用的 executors 时,才会选用下一个节点。这个是 Jenkins 默认的调度策略,可通过其它插件来改变这个策略,如 Least Load 插件,选择一个数目最少的最空闲的节点。


更多链接:https://www.kubernetes.org.cn/2995.html
回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:37:47
原生加速中国区Kubernetes安装

教你如何在中国区加速部署k8s,且实现自定义设置拥有k8s镜像的仓库与其命名空间。

概述
Kubernetes是一个强大的容器编排工具,帮助用户在可伸缩性系统上可靠部署和运行容器化应用。在容器领域内,K8s已毋庸置疑成为了容器编排和管理的社区标准,连Docker官方都已宣布支持K8s。在容器编排领域的战火已然分出结果,尘埃落定,K8s得到了包括Google、Huawei、Microsoft、IBM、AWS、Rancher、Redhat、CoreOS等在内的容器玩家的一致认可。

Rancher容器管理平台原生支持K8s,使用户可以简单轻松地部署K8s集群。

然而对于中国玩家而言,由于谷歌镜像仓库的原因,很多时候K8S的使用体验并不顺滑。在往期发布的文章(《Rancher-k8s加速安装文档》)中,我们有讲解过如何通过修改应用商店地址来实现加速部署kubernetes。虽然这种方法能够实现kubernetes的加速部署,但是因为自定义的商店仓库无法与官方仓库实时同步,很多组件(网络、健康检查等)将无法保证及时的更新。因此,为了解决这个问题,我们在官方catalog模板的基础上做了修改,增加了可以自定义仓库地址和命名空间的功能。这样,我们在部署kubernetes时可以自定义设置拥有kubernetes镜像的仓库与其命名空间。

环境准备
1.png
安装前准备(重要):
  • Rancher-server:v1.6.11现在还是rc版本,安装过程中可能会有一些错误提示。
  • 如果出现这个警告,需要删除所有容器并更换Docker版本,Docker尽量选择1.12.3
2.png
  • 配置好各节点间的hosts文件;
  • 如果是克隆的主机,请检查有没有/var/lib/rancher/state/这个文件夹,如果有则删除;
  • 如果以前有通过Rancher安装过kubernetes,请执行命令:
[mw_shl_code=bash,true]docker rm -f -v $(docker ps -aq)
docker volume rm $(docker volume ls)
rm -rf /var/etcd/[/mw_shl_code]


更多参考
https://www.kubernetes.org.cn/2955.html


回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:39:27
搜狗BizCloud:基于Kubernetes的私有云实践


【编者的话】随着搜狗业务的快速增长,需要更有效地控制成本,提升研发效率,我们基于Docker和Kubernetes构建了一站式私有云管理平台——BizCloud,此平台涵盖服务管理、弹性伸缩、灰度发布、自动运维、持续集成等功能。本文将简要介绍BizCloud的设计思路、架构及服务发现、授权、灰度发布等核心功能的实现。
BizCloud简介
我们基础环境非常复杂,目前有多个版本操作系统共存,应用也常常存在着多个版本同时测试或部署,在多版本并行测试过程中,经常出现环境借用的情况,因操作系统和基础软件不一致的问题,会出现线下测试没问题,但上线后出问题;其次,线上的实体机在业务低峰时使用率较低,存在较大的提升空间;服务上下线也涉及到一系列机器的申请回收流程,需要手工执行,系统的弹性伸缩能力不足。这种种问题都是我们设计私有云的原因,也就是要做到保持环境一致、提升资源利用率,并提升弹性计算能力。
为了解决上述问题,我们使用目前非常流行的容器技术Docker和容器编排工具Kubernetes,研发了商业云平台BizCloud。但Docker和Kubernenets只提供了一个基础功能:容器运行和容器编排,如何能快速地学会使用,并为大家所接受才是关键。
在自研BizCloud过程中,一个重点就是要对接、打通现存的系统和流程,尽量保持用户操作习惯,服务在容器化的过程中,尽可能不需要调整,这样系统才易于推广落地;另一方面,我们要支持服务一键自动部署(QA特别需要这样的功能),服务出现故障后,如系统宕机或服务挂掉后,服务能自动迁移,而且我们需要支持灰度发布,尽量实现运维的自动化。
商业平台系统的整体架构如下图所示。共分为三层,IaaS层、PaaS层、SaaS层:在IaaS层,我们使用Docker+Kubernetes封装了部门的基础资源,提供容器化服务;PaaS层提供了很多基础服务和基础框架,并且也实现了一些自动化工具,包括刚才提到过的统一服务管理中心,统一配置中心,项目管理系统、SOA服务框架等,贯穿了应用开发、测试、运维整个生命周期的一体化平台,其中的红色部分,包括服务管理、编译中心、商业云平台都是为BizCloud而新开发的模块;第三层SaaS主要是一些商业平台业务系统。本文的分享也主要集中在PaaS层的研发实践上。
1.jpg

更多参考https://www.kubernetes.org.cn/2831.html

















回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:40:32
Kubernetes高可用负载均衡与集群外服务访问实践

Kubernetes在设计之初就充分考虑了针对容器的服务发现与负载均衡机制,提供了Service资源,并通过kube-proxy配合cloud provider来适应不同的应用场景。随着kubernetes用户的激增,用户场景的不断丰富,产生了一些新的负载均衡机制。

一、Kubernetes平台Service的特点
Service是对一组提供相同功能的Pods的抽象,并为它们提供一个统一的入口。借助Service,应用可以方便的实现服务发现与负载均衡,并实现应用的零宕机升级。Service通过标签来选取服务后端,一般配合Replication Controller或者Deployment来保证后端容器的正常运行。

目前 kubernetes 共有三种服务暴露的方式:

LoadBlancer Service
NodePort Service
Ingress
LoadBlancer Service是kubernetes深度结合云平台的一个组件;当使LoadBlancer Service暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前LoadBlancer Service支持的云平台已经相对完善,比如国外的GCE、DigitalOcean,国内的 阿里云,私有云 OpenStack 等等,由于LoadBlancer Service深度结合了云平台,所以只能在一些云平台上来使用。

NodePort Service,实质上就是通过在集群的每个node上暴露一个端口,然后将这个端口映射到某个具体的service来实现的,虽然每个node的端口有很多(默认的取值范围是 30000-32767),但是由于安全性和易用性(服务多了就乱了,还有端口冲突问题)实际使用可能并不多。

Ingress可以实现使用nginx等开源的反向代理负载均衡器实现对外暴露服务,可以理解Ingress就是用于配置域名转发,在nginx中就类似upstream,它与ingress-controller结合使用,通过ingress-controller监控到pod及service的变化,动态地将ingress中的转发信息写到诸如nginx、apache、haproxy等组件中实现方向代理和负载均衡。

更多参考
https://www.kubernetes.org.cn/2812.html


回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:42:36
简化Kubernetes应用部署工具-Helm安装



【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文展示了Helm的Client、Server与本地Chart仓库的安装过程。
Helm安装Helm CLINET安装
Helm Client安装过程如下:
[mw_shl_code=bash,true]mv linux-amd64/helm /usr/local/bin/helm[/mw_shl_code]


Helm TILLER安装
Helm Tiller是Helm的server,Tiller有多种安装方式,比如本地安装或以pod形式部署到Kubernetes集群中。本文以pod安装为例,安装Tiller的最简单方式是helm init, 该命令会检查helm本地环境设置是否正确,helm init会连接kubectl默认连接的kubernetes集群(可以通过kubectl config view查看),一旦连接集群成功,tiller会被安装到kube-system namespace中。
执行helm init,该命令会在当前目录下创建helm文件夹即~/.helm,并且通过Kubernetes Deployment 部署tiller. 检查Tiller是否成功安装:
[mw_shl_code=bash,true]$ kubectl get po -n kube-system
NAME                             READY   STATUS   RESTARTS   AGE
tiller-deploy-1046433508-rj51m   1/1     Running  0          3m[/mw_shl_code]
Tiller其他安装形式:
  • 安装金丝雀build: –canary-image
  • 安装指定image:–tiller-image
  • 指定某一个Kubernetes集群:–kube-context
  • 指定namespace安装:–tiller-namespace
Helm TILLER删除
由于 Tiller的数据存储于Kubernetes ConfigMap中,所以删除、升降级Tiller,原Helm部署的应用数据并不会丢失。
删除Tiller:
[mw_shl_code=bash,true]helm reset
[/mw_shl_code]
更多链接
https://www.kubernetes.org.cn/2704.html

回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:45:51

Kubernetes 在知乎上的应用


从 Mesos 到 Kubernetes
之前的调度框架是基于 Mesos 自研的。采用的语言是 Python。运行了大概两年多的时间了,也一直比较稳定。但随着业务的增长,现有的框架的问题逐渐暴露。
  • 调度速度遇到瓶颈,影响大业务的部署速度。
  • 不能很好的支持有状态服务。
解决上述问题的方案有两个,一个是对现有系统进行改进重构,另一个是迁移到 Kubernetes。我们最终选择迁移到 Kubernetes,主要基于以下考虑。
  • Kubernetes 的架构设计简单明了,容器管理的抽像做的很好,重易进行复用和二次开发,没有必要造重复的轮子。比较典型的像Pod、Mesos 也已经引进了类似概念。
  • Kubernetes 已经逐渐成为业界主流。社区很活跃,新的特性不断地被添加进来,这导致 Kubernetes 变的越来越重,但基本的架构和核心功能是一直比较稳定的。
  • 相对于 Mesos 来讲,基于 Kubernetes 的开发成本是要低一些的,尤其是在熟悉之后。便于 k8s 的推广使用。除了主要的业务运行平台 bay,我们的负载均衡平台、Kafka 平台以及定时任务平台全部都是基本 Kubernetes 的。

整体架构
1.jpg

资源层
这一层主要是集群资源,主要包括内存、CPU、存储、网络等。主要运行的组件有 Docker daemon、kubelet、cAdvisor、CNI 网络插件等,主要为上层提供资源。

控制层(Kubernetes master)
控制层主要包括 Kubernetes 的 master 组件,Scheduler、Controller、API Server。提供对 Kubernetes 集群资源的控制。


接入层(Watch Service、API)
这一层包含的东西比较多,主要包含各个平台用于接入 Kubernetes 集群所开发的组件。主要包含以下组件:
  • 容器平台 bay 。
    一是用来向部署系统提供容器/容器组的创建、更新、删除、扩容等接口,是对 Kubernetes 原生 API 的一层封装,主要是为了与部署系统对接。二是用来注册服务发现、业务监控报警等所需要的配置。
  • 负载均衡平台(Load Balance)。
    我们的负载均衡平台采用的主要是 Haproxy。也是跑在容器里的。由于负载均衡系统的特殊性,并没有跑在容器平台 bay 上面,而是单独开发了一个平台对 HAProxy 进行管理。可以方便的创建和管理 HAProxy 集群,并在业务流量发生变化的时候进行自动或者手动扩容。
  • Kafka 平台(Kafka)。 主要提供在 Kubernetes 上创建管理 Kafka 集群的服务。我们在 Kubernetes 之上开发了一套基于本地磁盘的调度框架,可以使 pod 根据集群中的本地磁盘信息进行调度。没有使用共享存储系统主要是为了性能考虑。最新的 Kubernetes 好像也加入了类似本地磁盘的调度特性,不过在我们开发的时候是还没有支持的。
  • 定时任务平台。
    这个平台是在 Kubernetes 支持 Cron job 之前开发的。也是最早接入 Kubernetes 的服务。

管理层(Castle Black;Monitor;Auto Scale)
主要是根据接入层提供的一些配置或者信息来完成特定的功能。
  • Castle Black,这个服务是一个比较关键的服务。这个服务通过 Kubernetes 的 watch API,及时的同步业务容器的信息,根据容器信息进行服务注册和反注册。我们主要是注册 Consul 和 DNS。Kafka 平台和负载均衡平台也依赖于这个服务进行服务注册。同时对外提供查询接口,可以查询业务的实时容器信息。
  • Monitor,这个主要是业务容器的监控,主要包含该业务总容器数、不正常容器数以及注册信息是否一致等信息,CPU 和内存等资源的监控我们采用 cAdvisor 和我们内部的监控系统来实现。
  • Auto Scale,我们没有使用 Kubernetes 本身的自动扩容机制,而是单独进行了开发,主要是为了支持更加灵活的扩容策略。

配置层(etcd)
应用层的组件所需要的配置信息全部由接入层的服务写入到 etcd 中。应用层组件通过 watch etcd 来及时获取配置的更新。
下面这张图说明了在我们的容器平台上,上面描述的一些组件是如何结合在一起,使业务可以对外提供服务的。通过 bay 平台向 Kubernetes APIServer发送请求,创建 deployment,pod 创建成功并且健康检查通过后,Castle Black watch 到 pod 信息,将 IP,port 等信息注册到 Consul 上,HAProxy watch 对应的 Consul key,将 pod 加入其后端列表,并对外提供服务。
2.jpg

监控与报警cAdvisor
我们的监控指标的收集主要是采用 CAvisor。没有采用 Heapster 的主要原因有以下几点:
  • 针对 CAvisor 我们进行了二次开发,与内部指标系统结合的也比较好,应用的时间也较长。
  • Heapster 采用 pull 模型,虽然是并行 pull,但在集群规模较大的情况下,有成为性能瓶颈的可能,而且目前无法进行横向扩展。
  • Heapster 中默认提供的很多聚合指标我们是不需要的。也没有维护两个监控系统的必要。

内部指标与报警系统
指标和报警都是用的我们内部比较成熟的系统。

日志收集
Logspout Kafka ES/HDFS,日志收集我们使用的也是 ELK,但跟通常的 ELK 有所不同。我们这里的 L 用的是 Logspout,一个主要用于收集容器日志的开源软件。我们对其进行了二次开发,使之可以支持动态 topic 收集。我们通过环境变量的形式把 topic 注入到容器中。logspout 会自动发现这个容器并提取出 topic,将该容器的日志发送到 Kafka 对应的 topic 上。因此我们每个业务日志都有自己的 topic,而不是打到一个大的 topic 里面。日志打到 Kafka 里之后,会有相应的 consumer 消费日志,落地 ES 和 HDFS。ES 主要用来作日志查询,HDFS 主要用来做日志备份。
整个日志收集流程如下图所求:

3.jpg

网络方案
CNI Bridge host-local,网络部分我们做的比较简单。首先我们的每个主机都给分配了一个 C 段的 IP 池,这个地址段里的每个 IP 都是可以跨主机路由的。IP 地址从 X.X.X.2 到 X.X.X.255,容器可以使用的地址是 X.X.X.3 到 X.X.X.224,这个 IP 数量是足够的。然后在主机上创建一个该地址段的 Linux Bridge。容器的 IP 就从 X.X.X.3 到 X.X.X.224 这个地址空间内分配,容器的 veth pair 的一段挂在 Linux Bridge 上,通过 Linux Brigde 进行跨主机通信。性能方面基本没有损耗。

具体的实现我们采用了 Bridge 和 host-local 这两个 CNI 插件,Bridge 主要用来挂载/卸载容器的 veth pair 到 Linux Bridge 上,host-local 主要利用本地的配置来给容器分配 IP。

上述流程如下图所示:
4.jpg
IP 池的分配由我们的云服务商提供,我们不需要管具体的 IP 池的分配与路由配置。

上面主要介绍了知乎在容器和 Kubernetes 应用的一些现状,在这个过程中我们也踩了不少坑,在这里与大家分享一下。

etcdv3 版本问题
Kubernetes 的较新版本默认使用的存储后端是 etcd3。etcd 选用的版本不对,是会有坑的。etcd 3.10 之前的版本,V3 的 delete api 默认是不会返回被删除的 value 的。导致 Kubernetes API server 会收不到 delete event。被占用的资源会得不到释放。最终导致资源耗尽。scheduler 无法再调度任何任务。详细信息可以看这个 issue(https://github.com/coreos/etcd/issues/4620)。

Pod Eviction
这个是 Kubernetes 的一个特性,如果由于网络或者机器原因,node 离线了,变为 unready 状态。Kubernetes 的 node controller 会将该 node 上的 pod 删除,称作 pod eviction。这个特性应该说是合理的,但在大概是 1.5 版本之前,当集群中所有的 node 都变为 unready 状态的时候,所有 node 上的 pod 都会被删除。这个其实是不合理的,因为出现这种情况大概率是 API Server 的机器网络出了问题,所以这个时候不应该把所有 node 上的 pod 全部删除。最新的版本将这个特性进行了改进,集群中 ready 的 node 达到一定数量的情况下,才对 not ready 的 node 进行 pod eviction。这个就比较合理了。另外提醒大家一定要做好 API Server 的高可用。

CNI 插件 Docker daemon 重启 IP 泄露
在使用 CNI 网络插件的时候,如果 Docker daemon 发生了重启,会重新分配新的 IP,但旧的 IP 不会被释放,会导致 IP 地址的泄漏。由于时间和精力问题,我们采取了比较 tricky 的方式,在 Docker dameon 启动之前,我们会默认把本机的 IP 全部释放掉。这个是通过 Supervisor 的启动脚本来实现的。希望后续 Kubernetes 社区可以从根本上解决这个问题。

Docker bug
Docker 使用过程中也遇到了一些 bug。比如 docker ps 会卡住, 使用 portmapping 会遇到端口泄漏的问题等。我们内部自己维护了一个分支,修复了类似的问题。Docker daemon 是基础,它的稳定性一定要有保证,整个系统的稳定性才有保证。

Rate Limit
Kubernetes 的 Controller manager、Scheduler、以及 API Server 都是有默认的 rate limit 的,在集群规模较大的时候,默认的 rate limit 肯定是不够用的,需要自己进行调整。




链接
https://www.kubernetes.org.cn/2508.html
回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:47:21
Hadoop 运行在 Kubernetes平台实践

Hadoop与Kubernetes就好像江湖里的两大绝世高手,一个是成名已久的长者,至今仍然名声远扬,一个则是初出茅庐的青涩少年,骨骼惊奇,不走寻常路,一出手便惊诧了整个武林。Hadoop与Kubernetes之间有很深的渊源,因为都出自IT豪门——Google,只不过,后者是亲儿子,正因为有大佬背书,所以Kubernetes一出山,江湖各路门派便都蜂拥而至,拥护称王。

不知道是因为Hadoop是干儿子的缘故还是因为“廉颇老矣”,总之,Hadoop朋友圈的后辈们如Spark、Storm等早都有了在Kubernetes上部署运行的各种资料和案例,但Hadoop却一直游离于Kubernetes体系之外,本文我们给出Hadoop在Kubernetes上的实践案例,以弥补这种缺憾。
Hadoop容器化的资料不少,但Hadoop部署在Kubernetes上的资料几乎没有,这主要是以下几个原因导致的:

第一, Hadoop集群重度依赖DNS机制,一些组件还使用了反向域名解析,以确定集群中的节点身份,这对Hadoop在Kubernetes上的建模和运行带来极大挑战,需要深入了解Hadoop集群工作原理并且精通Kubernetes,才能很好解决这一难题。

第二, Hadoop新的Map-Reduce计算框架Yarn的模型出现的比较晚,它的集群机制要比HDFS复杂,资料也相对较少,增加了Hadoop整体建模与迁移Kubernetes平台的难度。

第三, Hadoop与Kubernetes分别属于两个不同的领域,一个是传统的大数据领域,一个是新兴的容器与微服务架构领域,这两个领域之间交集本来很小,加之Hadoop最近几年已经失去焦点(这点从百度搜索关键词就能发现),所以,没有多少人关注和研究Hadoop在Kubernetes的部署问题,也是情理之中的事情。


更多https://www.kubernetes.org.cn/3795.html


回复

使用道具 举报

yuwenge 发表于 2018-4-10 21:48:12
本帖最后由 yuwenge 于 2018-4-10 22:13 编辑

Kubernetes v1.10+Keepalived HA集群墙内部署实践

导读:众所周知,K8S安装难点在于镜像下载。查询网上许多关于K8S安装部署的文章,作者要么是将镜像下载使用的工作交给了读者完成,要么是放在共享云盘中,由读者下载后导入使用。都知道,如果你不是该云盘提供商的会员,镜像下载速度堪比蜗牛。总之,三个字:”不方便“。基于最大化便利刚接触K8S的同行快速上手实践的目的,在参阅了众多同行关于K8S部署的文章,并经过反复实验验证后,将本人的实验成果在这里分享,希望可以帮助有需要的朋友。由于时间仓促,一些对本文撰写有价值的文章没有仔细考证作者和出处,在本文末尾的参阅文章中可能没有注明。如你发现本文中一些内容的原创属于你本人,请邮件联系本人处理。并在此感谢对本文创作产生帮助的作者。谢谢!

本文K8S集群高可用方案采用Keepalived。

实验环境:
1、3台centos 1611版本虚拟机,mini安装。Linux localhost 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

2、docker version
Client:
Version: 1.13.1
API version: 1.26
Package version: <unknown>
Go version: go1.8.3
Git commit: 774336d/1.13.1
Built: Wed Mar 7 17:06:16 2018
OS/Arch: linux/amd64

Server:
Version: 1.13.1
API version: 1.26 (minimum version 1.12)
Package version: <unknown>
Go version: go1.8.3
Git commit: 774336d/1.13.1
Built: Wed Mar 7 17:06:16 2018
OS/Arch: linux/amd64
Experimental: false

3、etcd Version: 3.1.13

4、kubeadm,kubelet,kubectl,kube-cni版本如下:
-rw-r–r– 1 root root 18176678 Mar 30 00:08 5844c6be68e95a741f1ad403e5d4f6962044be060bc6df9614c2547fdbf91ae5-kubelet-1.10.0-0.x86_64.rpm
-rw-r–r– 1 root root 17767206 Mar 30 00:07 8b0cb6654a2f6d014555c6c85148a5adc5918de937f608a30b0c0ae955d8abce-kubeadm-1.10.0-0.x86_64.rpm
-rw-r–r– 1 root root 7945458 Mar 30 00:07 9ff2e28300e012e2b692e1d4445786f0bed0fd5c13ef650d61369097bfdd0519-kubectl-1.10.0-0.x86_64.rpm
-rw-r–r– 1 root root 9008838 Mar 5 21:56 fe33057ffe95bfae65e2f269e1b05e99308853176e24a4d027bc082b471a07c0-kubernetes-cni-0.6.0-0.x86_64.rpm

5、k8s网络组件:flannel:v0.10.0-amd64

6、实验网络规划如下:
host1 172.18.0.154/22
host2 172.18.0.155/22
host3 172.18.0.156/22
VIP 172.18.0.192/22

文章视频链接:https://pan.baidu.com/s/1XVagd765eGacuoR_cgesiQ

安装步骤:

0、请先从该链接下载后面步骤所需脚本https://pan.baidu.com/s/1oK7PRLeeYHrouNCRgIQlcQ

1、在3台主机中执行基础环境配置脚本 base-env-config.sh。

2、在主机1执行脚本 host1-base-env.sh

3、在主机2执行脚本 host2-base-env.sh

4、在主机3执行脚本 host3-base-env.sh

5、在host1主机执行如下命令
[root@host1 ~]# scp -r /etc/etcd/ssl root@172.18.0.155:/etc/etcd/

[root@host1 ~]# scp -r /etc/etcd/ssl root@172.18.0.156:/etc/etcd/

6、在3台主机中分别执行脚本 etcd.sh

7、查看keepalived状态
systemctl status keepalived

8、查看etcd运行状态
在host1,host2,host3分别执行如下命令:[参数名称前面是两个’-‘,注意]
etcdctl –endpoints=https://${NODE_IP}:2379 –ca-file=/etc/etcd/ssl/ca.pem –cert-file=/etc/etcd/ssl/etcd.pem –key-file=/etc/etcd/ssl/etcd-key.pem cluster-health

9、在3台主机上安装kubeadm,kubelet,kubctl,docker
yum install kubelet kubeadm kubectl kubernetes-cni docker -y

10、在3台主机禁用docker启动项参数关于SELinux的设置[参数名称前面是两个’-‘,注意]
sed -i ‘s/–selinux-enabled/–selinux-enabled=false/g’ /etc/sysconfig/docker

11、在3台主机的kubelet配置文件中添加如下参数[参数名称前面是两个’-‘,注意]
sed -i ‘9a\Environment=”KUBELET_EXTRA_ARGS=–pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/osoulmate/pause-amd64:3.0″‘ /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

12、在3台主机添加docker加速器配置(可选步骤)
cat <<EOF > /etc/docker/daemon.json
{
“registry-mirrors”: [“https://yourself.mirror.aliyuncs.com”] #请自行申请阿里云账号获取镜像加速链接
}
EOF

13、在3台主机分别执行以下命令
systemctl daemon-reload
systemctl enable docker && systemctl restart docker
systemctl enable kubelet && systemctl restart kubelet

14、在3台主机中分别执行kubeadmconfig.sh生成配置文件config.yaml

15、在host1主机中首先执行kubeadm初始化操作
命令如下:
kubeadm init –config config.yaml

16、在host1主机中执行初始化后操作
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

17、将主机host1中kubeadm初始化后生成的证书和密钥文件拷贝至host2,host3相应目录下
scp -r /etc/kubernetes/pki root@172.18.0.155:/etc/kubernetes/
scp -r /etc/kubernetes/pki root@172.18.0.156:/etc/kubernetes/

18、为主机host1安装网络组件 podnetwork【这里选用flannel】
kubectl apply -f https://raw.githubusercontent.co ... on/kube-flannel.yml
systemctl stop kubelet    #由于kubelet会调用docker到默认url【谷歌】下载镜像,所以先禁用
systemctl restart docker
docker pull registry.cn-hangzhou.aliyuncs.com/osoulmate/flannel:v0.10.0-amd64
systemctl start kubelet

19、在host2,host3上执行如下命令
kubeadm init –config config.yaml
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl apply -f https://raw.githubusercontent.co ... on/kube-flannel.yml
systemctl stop kubelet #如果提示需要systemctl daemon-reload,则将守护进程重启后再停止kubelet服务。
systemctl restart docker
docker pull registry.cn-hangzhou.aliyuncs.com/osoulmate/flannel:v0.10.0-amd64
systemctl start kubelet

20、查看集群各节点状态【这里仅在host1主机查看结果】
[root@host1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
host1 Ready master 5m v1.10.0
host2 Ready master 1m v1.10.0
host3 Ready master 1m v1.10.0
[root@host1 ~]# kubectl get po –all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7997f8864c-k9dcx 1/1 Running 0 5m
kube-system coredns-7997f8864c-sv9rv 1/1 Running 0 5m
kube-system kube-apiserver-host1 1/1 Running 1 4m
kube-system kube-apiserver-host2 1/1 Running 0 1m
kube-system kube-apiserver-host3 1/1 Running 0 1m
kube-system kube-controller-manager-host1 1/1 Running 1 4m
kube-system kube-controller-manager-host2 1/1 Running 0 1m
kube-system kube-controller-manager-host3 1/1 Running 0 1m
kube-system kube-flannel-ds-88tz5 1/1 Running 0 1m
kube-system kube-flannel-ds-g9dpj 1/1 Running 0 2m
kube-system kube-flannel-ds-h58tp 1/1 Running 0 1m
kube-system kube-proxy-6fsvq 1/1 Running 1 5m
kube-system kube-proxy-g8xnb 1/1 Running 1 1m
kube-system kube-proxy-gmqv9 1/1 Running 1 1m
kube-system kube-scheduler-host1 1/1 Running 1 5m
kube-system kube-scheduler-host2 1/1 Running 1 1m
kube-system kube-scheduler-host3 1/1 Running 0 1m

21、高可用验证
将host1关机,在host3上执行
while true; do sleep 1; kubectl get node;date; done
在host2上观察keepalived是否已切换为主状态。

Q&A

1、为什么在kubeadm init时出现kubelet 版本不支持系统中安装的etcd的报错?

因为本文k8s管理组件kubeadm,kubectl,kubelet的安装源为阿里云源,阿里云源会和最新k8s版本保持同步。如出现版本不兼容的问题,请按照报错提示安装相应版本的etcd或kubelet,kubeadm,kubectl组件。

2、为什么安装时间同步软件chrony?

由于集群采用keepalived检测集群各节点的活动状态,如不能保证各节点时间同步,会导致心跳异常,进而影响集群的故障倒换。当然,你也可以采用其它时间同步措施,只要能保证各节点之间的时间同步即可。

3、步骤18中为什么用kubectl应用了网络组件后还要用docker pull从阿里云拉取镜像呢?

kubectl应用了flannel组件后默认会从谷歌镜像库中拉取镜像,所以要先停止kubelet服务,使其停止对docker的调用,在我们手动从阿里云拉取镜像后,再重启kubelet服务,k8s相关服务会自动识别镜像。在host2,host3主机kubeadm init完成后可能还会出现其它镜像包未拉取完成的情况,这时也可以采用这种方法:即停止kubelet服务,重启docker服务,手动拉取镜像【确定需要拉取那些镜像可先在主机上使用 kubectl get po –all-namespaces命令获取各主机镜像的当前状态。如READY列显示0/1表示镜像仍在拉取/创建中,可使用你下载的k8s压缩包中名称为阿里云镜像包的txt文档中的相应命令】,之后再启动kubelet服务。除flannel镜像外,理论上所有镜像在kubeadm init中都会从阿里云镜像库中拉取,所以,如果host2,host3在kubeadm init时有镜像没有拉取完成,可等待1-2分钟,如还未成功,直接重启kubelet服务即可。


链接https://www.kubernetes.org.cn/3773.html


回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条