支持的集群类型
单主机集群
可增删主节点的高可用集群
可增删主节点的高可用集群
用途:建议用户在生产环境中使用
功能:高可用的Etcd集群;支持至少2个Master节点;支持高可用的Vespace存储;局域网内的时间同步组件;内置的镜像仓库(Alpha);应用级别的负载均衡(Alpha)等
其实,在内部实现中,为了使整个逻辑更加的简单,我们将主节点上的组件,只与本节点的apiserver联系,当然,Etcd节点为独立的模块,我们当前的Etcd节点都运行在master节点上。
我们默认增加的服务
增加时间同步模块
- Ufleet内置时间同步服务器Ufleet-ntpd,支持局域网环境
- 每个节点创建或者添加前,都会先与Ufleet-ntpd同步时间,同步完成后再执行安装任务
- 在前期测试中发现,如果时间不同步,将导致etcd集群极其不稳定,故建议在创建高可用集群时,优先保证各个节点时间同步
- 时间同步对于之后日志定位,监控等亦有重要的作用,不可忽视
集群内置traefik-ingress服务
- 用户创建ingress服务后,external-dns将自动获取到相关信息,并自动生成服务Host到IP的DNS记录,写入到etcd数据库中
- 用户通过ingress中指定的host,访问服务(用户配置:只需要将集群的Vip添加到用户使用的机器的DNS服务器地址中即可)
- traefik将自动做负载均衡
存储集群
- 新的版本,内置Vespace存储,即对于每个k8s集群,同时也是一个完整的存储集群,包含strategy策略节点,和storage存储节点
Launcher的架构设计
Launcher各模块简图及调用关系
流程介绍:
- 客户端通过restful 接口调用,进入sub模块
- 如果是删除,或者查询,直接调用Cluster的方法执行
- 如果是创建或者添加任务(创建集群,添加主节点,添加Node节点),则调用api模块,创建Job任务
- scheduler定时向api模块查询,获取任务和已注册worker(Ufleet有高可用版本,高可用版本下,同时存在多个worker,可提高多人共同使用下的创建和添加任务的效率);检查任务是否存在已过时,或者是否存在新的任务,存在则将任务分配给已注册的worker,并调用api模块写入数据库
- worker定时向api模块查询属于自己的任务,如果存在未执行任务,则调用任务执行
kubeadm与launcher
kubeadm的不足和可扩展
kubeadm的不足:
- 当前kubeadm不支持高可用集群的创建
- 只安装kubernetes组件
kubeadm可扩展:
- 对证书的处理方式很好:
如果存在证书,则读取并使用,不存在则生成,即使部分不存在也只生成对应的证书。基于此,我们生成证书时,没有生成apiserver.crt/key,因为服务器的证书中包含了主机IP或者域名,将导致apiserver证书不可重复使用,故存储也没有多大意义
- 可配置性好:
提供非常完整的配置项,将在下一节详细介绍。但注意,根据我们的经验,一般文档要晚于代码,对于新的特性,有时会发现文档中没有描述,这时如果是研发人员,可参考kubeadm的代码进行配置
launcher创建流程介绍
- 创建集群流程:
流程如右图所示,在第7步,launcher利用kubeadm完成kubernetes组件的创建。
- 添加Master节点流程与创建集群流程的差别:
添加Master节点流程与创建集群流程基本一致,差别在于:从数据库中获取本集群CA证书,集群已有配置,生成对应主机的证书和配置文件;往已存在etcd集群添加节点,并等待数据同步完成后开始执行安装任务。
- 添加Node节点流程:
从数据库中获取证书信息,根据节点和集群信息生成对应的配置文件,采用kubelet主动注册的功能,在kubelet启动后自动向集群主节点注册自己。
基于Kubeadm和我们的配置修改
Kubeadm功能介绍
kubeadm init :引导master节点的创建(to bootstrap a Kubernetes master node)
kubeadm join :添加一个worker节点到集群中(to bootstrap a Kubernetes worker node and join it to the cluster) (注:由于我们使用kubelet主动注册的功能,故这个功能我们没有用)
kubeadm upgrade :将集群升级到新的版本(to upgrade a Kubernetes cluster to a newer version)
kubeadm config :管理集群配置文件,可修改或者查看(if you initialized your cluster using kubeadm v1.7.x or lower, to configure your cluster for )
kubeadm upgrade :升级kubernetes组件
kubeadm token : 管理kubeadm join 使用的token (to manage tokens for kubeadm join) (注:由于我们使用kubelet主动注册的功能,故这个功能我们没有用)
kubeadm reset :恢复 kubeadm init或者 kubeadm join对主机的修改(to revert any changes made to this host by kubeadm init or kubeadm join)
Kubeadm 创建集群流程
对于每一步的详细内容,在下面介绍
Kubeadm 创建集群详细介绍
- preflight-checks:在对系统修改前,运行一系列的检查,可通过—skip-preflight-checks跳过这一步的检查(注:这里由于有对证书目录是否为空进行检查,而我们的证书是生成好以后再拷贝到主机上,并在运行时希望kubeadm加载我们的证书,故这里我们跳过了这一步的检查)
- generate self-signed CA: 生成一个自签名的CA证书(或者使用一个已存在的证书),在集群的各个组件中认证时使用.如果用户有指定他们自己的CA证书或者key,通过—cert-dir指定(默认为/etc/kubernetes/pki目录),则使用用户指定的证书。(注:我们就是这样做的,先把除了apiserver.crt/key外,其他的证书放到/etc/kubernetes/pki目录中,并通过参数 cert-dir,对应配置文件中的certificatesDir,指定了证书的位置,这里利用了kubeadm自动生成没有找到的证书的机制,生成apiserver.crt/key)
- generate kubeconfig files: 在/etc/kubernetes/目录中为kubelet,controller-manager和scheduler生成kubeconfig文件,访问API server时使用,每个组件都有他们自己的凭证;同时,也会生成一个具有管理员权限的admin.conf配置文件(注:可拷贝成~/.kube/config,执行kubectl时可读取到)
- dynamic kubelet config: 如果通过—feature-gates=DynamicKubeletConfig 启动了kubelet动态配置项,它将会生成kubelet init配置文件到 /var/lib/kubelet/config/init/kubelet文件中.这个功能当前默认是关闭,因为这个功能的优先级不高,但它在将来新的版本会是一个默认的选项(注:在v1.8.6版本中还不是一个默认的功能,我们当前也没有打开这个功能)
- generate manifests files and wait for control plane running: 生成API server, controller manager 和scheduler的manifest文件.如果没有指定etcd,则还会生成etcd的manifest文件(注:我们指定了etcd,故我们没有生成etcd.yaml文件)
静态Pod的manifests默认都要求放在/etc/kubernetes/manifests; kubelet会监视这个目录,如果有修改,或者新创建的文件,则会自动删除并启动或者创建新的静态Pod.(注:这里有个迟迟没有解决的问题,如果尝试去修改这个目录下的文件,就会发现,有时候修改后,Pod被删除了,但是新的Pod没有创建出来,这时,可以尝试将文件拷贝出这个目录,等个10几秒,然后拷贝回来,则可以正常启动静态Pod)
执行到这一步,回阻塞,但一旦控制组件起来并且正常运行,kubeadm init就会继续执行(注:这里要注意,由于google的镜像,在国内下载不了,早前的版本会一直等待,后来的版本会失败结束.如果有其他的镜像仓库,则可以通过配置项imageRepository指定为自己的镜像仓库)
- add labels and taints: 如果通过—feature-gates=DynamicKubeletConfig 启动了kubelet动态配置,它将会通过创建一个ConfigMap和一些RBAC规则来保证kubelet能够正常的访问,修改通过Node.spec.configSource指定的node,新创建的ConfigMap,这个功能默认关闭.(注:我们没有启用这个功能)
- generate bootstrap token: 添加一些标签和taints在主节点上,这样就没有额外的工作负载在这上面(注:我们当前在单主机和高可用集群中都删除了这个taint,并添加新的标签,以标记这个节点既是Master节点,又是Node节点)
- make node join works via join token: 生成token,使其他的Node节点可以注册到这个Master节点。可选,也可以通过—token指定(注:我们早先的版本,有使用kubeadm join的功能,这个token我们是自己生成后,通过这个配置指定,以保证多Master集群情况下,使用的是同一个token)
- make node join works via join token: 为了允许Node通过kubeadm join token 加入到集群,以及启动TLS,需要做的必要的配置:
1.加入所需要的全部的ConfigMap,启动相关的RBAC访问规则
2.使Bootstrap Token可以访问CSR的API
3.设置新的CSR请求自动批准
- install dns: 通过API server安装内部的DNS服务器(kube-dns)和kube-proxy.如果kubeadm通过–feature-gates=CoreDNS=true配置了使用CoreDNS,则CoreDNS会替代kube-dns作为默认的DNS服务安装到集群中.注意到,如果DNS服务器被部署,就不会执行调度任务直到CNI插件被安装.(注:这个特性在v1.9版本之后支持,当前我们使用的是v1.8的版本,并且由于当前我们提供的应用级别的负载均衡,通过DNS可直接访问应用的功能还处于测试阶段,我们采用kube-dns作为默认DNS,而CoreDNS作为额外的DNS服务器。这里的CNI即Container Network Interface,是指实现了CNI接口的网络插件,我们当前使用calico)
- change control plane if set self-hosting: 如果kubeadm init通过 alpha self-hosting功能启动了单主机的特性,(—feature-gates=SelfHosting=true),则静态Pod的控制器就会转成self-host模式,与没有指定的区别是,控制组件会有对应的leader(注:这里主要是指 kube-controller-manager和schduler,我们在单主机集群中没有启动这个选项)
Kubeadm 提供的参数
apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration api: advertiseAddress: <address|string> bindPort: <int> etcd: endpoints: - <endpoint1|string> - <endpoint2|string> caFile: <path|string> certFile: <path|string> keyFile: <path|string> dataDir: <path|string> extraArgs: <argument>: <value|string> <argument>: <value|string> image: <string> kubeProxy: config: mode: <value|string> networking: dnsDomain: <string> serviceSubnet: <cidr> podSubnet: <cidr> kubernetesVersion: <string> cloudProvider: <string> nodeName: <string> authorizationModes: - <authorizationMode1|string> - <authorizationMode2|string> token: <string> tokenTTL: <time duration>
selfHosted: <bool> apiServerExtraArgs: <argument>: <value|string> <argument>: <value|string> controllerManagerExtraArgs: <argument>: <value|string> <argument>: <value|string> schedulerExtraArgs: <argument>: <value|string> <argument>: <value|string> apiServerExtraVolumes: - name: <value|string> hostPath: <value|string> mountPath: <value|string> controllerManagerExtraVolumes: - name: <value|string> hostPath: <value|string> mountPath: <value|string> schedulerExtraVolumes: - name: <value|string> hostPath: <value|string> mountPath: <value|string> apiServerCertSANs: - <name1|string> - <name2|string> certificatesDir: <string> imageRepository: <string> unifiedControlPlaneImage: <string> featureGates: <feature>: <bool> <feature>: <bool>
Kubeadm 我们当前使用的参数模板
apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration api: advertiseAddress: {{HOSTIP}} bindPort: 6443 etcd: endpoints: {{ETCD_ENDPOINTS}} kubernetesVersion: {{KUBERNETES_VERISON}} networking: dnsDomain: cluster.local serviceSubnet: {{SERVICE_SUBNET}} podSubnet: {{POD_SUBNET}} token: {{JOIN_TOKEN}} nodeName: {{HOSTNAME}} certificatesDir: /etc/kubernetes/pki imageRepository: ufleet.io/google_containers
与Kops和Kubespray的比较
Kops和Launcher的比较
- 对于k8s组件,kops需预安装kubectl;launcher都自带有对应版本的kubectl,所以不需要预先安装(但由于部署存储节点时需要等包,故还需要安装)
- kops负责基础设施流程和kubernetes的创建流程;launcher只能在已运行的linux主机上运行
- kops以普通服务的方式运行kubernetes;launcher以容器化方式运行kubernetes服务
- kops与AWS和GCP等公有云关系密切,不能在裸机上执行;launcher针对裸主机设计,对公有云环境没有要求
- kops通过命令行运行,同步方式;launcher是独立的服务,通过restful api交互,发送请求后立即返回,异步执行
- kops高可用集群中的etcd节点,允许运行在node节点上;launcher高可用集群,etcd节点都运行在master节点上
- kops当前已经支持升级kubernetes,可指定版本安装,可指定网络插件;launcher当前不支持升级kubernetes版本,并且不能指定版本安装,默认使用calico插件,不可配置
Kubespray和Launcher的比较
- kubespray属于kubernetes孵化器中的项目,通过ansible playbook来定义系统和执行kubernetes集群安装任务的流程;launcher没有依赖其他的自动化运维工具,定义自己的安装流程,只支持安装部署kubernetes集群,但针对性更强,使用也更加简单
- kubespray需要先配置节点名到主机IP的DNS映射;launcher支持自动按照规则修改主机名,不需额外配置
- kubespray以普通服务的方式运行kubernetes;launcher以容器化方式运行kubernetes服务
- kubespray通过命令行运行,同步方式;launcher是独立的服务,通过restful api交互,发送请求后立即返回,异步执行
- kubespray高可用集群中的etcd节点,允许运行在node节点上;launcher高可用集群,etcd节点都运行在master节点上
- kubespray当前已经支持升级kubernetes,可指定版本安装,可指定网络插件;launcher当前不支持升级kubernetes版本,并且不能指定版本安装,默认使用calico插件,不可配置
支持多版本以及自动升级的思考
支持指定k8s版本安装
历史原因:在老的版本,我们为了支持在无法连接外网的局域网内执行安装任务,内置了特定版本的kubernetes文件和镜像,支持多个版本也没有特定的需求。
目标:考虑到将来的发展,在新的launcher版本中,会将与镜像和二进制文件等部分抽离,launcher将作为类似于框架代码,在kubeadm支持下,完成对指定版本的kubernetes执行安装部署任务。
方案:当前Ufleet已经内置镜像仓库,并且我们已经实现了kubelet等组件的容器化,对于kubectl、kuberadm等,将按版本存放到某一个特定的仓库容器镜像中。launcher将定时查询并更新支持的kubernetes版本。在安装过程中,自动更新配置文件,并通过镜像仓库获取到指定版本的kubernetes组件,执行安装任务。
支持k8s版本升级
目标:我们考虑在高可用集群,支持k8s版本升级,并最小化对用户的影响。
方案:其实对我们来说,在不影响用户的正常使用情况下升级,并不是很难。我们当前已经支持主节点的增加和删除,就是考虑到将来升级的。针对主节点,将按照如下流程:主节点切换为不可调度模式->迁移运行的Pod->删除主节点->使用新版本添加主节点->切换为正常可调度模式。
本文转自kubernetes中文社区-Kubernetes :Launcher 基于 kubeadm 的部署工具