要真正发挥容器技术的实力,你就不能仅仅局限于对 Linux 容器本身的钻研和使用。 这些知识更适合作为你的技术储备,以便在需要的时候可以帮你更快的定位问题,并解决问题。 而更深入的学习容器技术的关键在于,如何使用这些技术来“容器化”你的应用。 比如,我们的应用既可能是 Java Web 和 MySQL 这样的组合,也可能是 Cassandra 这样的分布式 系统。而要使用容器把后者运行起来,你单单通过 Docker 把一个 Cassandra 镜像跑起来是没用 的。

要把 Cassandra 应用容器化的关键,在于如何处理好这些 Cassandra 容器之间的编排关系。比 如,哪些 Cassandra 容器是主,哪些是从?主从容器如何区分?它们之间又如何进行自动发现和通 信?Cassandra 容器的持久化数据又如何保持,等等。 这也是为什么我们要反复强调 Kubernetes 项目的主要原因:这个项目体现出来的容器化“表达能 力”,具有独有的先进性和完备性。

这就使得它不仅能运行 Java Web 与 MySQL 这样的常规组 合,还能够处理 Cassandra 容器集群等复杂编排问题。所以,对这种编排能力的剖析、解读和最佳 实践,将是本专栏最重要的一部分内容。 不过,万事开头难。 作为一个典型的分布式项目,Kubernetes 的部署一直以来都是挡在初学者前面的一只“拦路虎”。 尤其是在 Kubernetes 项目发布初期,它的部署完全要依靠一堆由社区维护的脚本。

其实,Kubernetes 作为一个 Golang 项目,已经免去了很多类似于 Python 项目要安装语言级别依 赖的麻烦。但是,除了将各个组件编译成二进制文件外,用户还要负责为这些二进制文件编写对应 的配置文件、配置自启动脚本,以及为 kube-apiserver 配置授权文件等等诸多运维工作。 目前,各大云厂商最常用的部署的方法,是使用 SaltStack、Ansible 等运维工具自动化地执行这些 步骤。

但即使这样,这个部署过程依然非常繁琐。因为,SaltStack 这类专业运维工具本身的学习成本,就 可能比 Kubernetes 项目还要高。 难道 Kubernetes 项目就没有简单的部署方法了吗? 这个问题,在 Kubernetes 社区里一直没有得到足够重视。直到 2017 年,在志愿者的推动下,社 区才终于发起了一个独立的部署工具,名叫:kubeadm。 这个项目的目的,就是要让用户能够通过这样两条指令完成一个 Kubernetes 集群的部署:

# 创建一个 Master 节点
$ kubeadm init# 将一个 Node 节点加入到当前集群中
$ kubeadm join <Master 节点的 IP 和端口 >

是不是非常方便呢? 不过,你可能也会有所顾虑:Kubernetes 的功能那么多,这样一键部署出来的集群,能用于生产 环境吗? 为了回答这个问题,在今天这篇文章,我就先和你介绍一下 kubeadm 的工作原理吧。 kubeadm 的工作原理 在上一篇文章《从容器到容器云:谈谈 Kubernetes 的本质》中,我已经详细介绍了 Kubernetes 的架构和它的组件。在部署时,它的每一个组件都是一个需要被执行的、单独的二进制文件。所以 不难想象,SaltStack 这样的运维工具或者由社区维护的脚本的功能,就是要把这些二进制文件传输 到指定的机器当中,然后编写控制脚本来启停这些组件。 不过,在理解了容器技术之后,你可能已经萌生出了这样一个想法,为什么不用容器部署 Kubernetes 呢?

这样,我只要给每个 Kubernetes 组件做一个容器镜像,然后在每台宿主机上用 docker run 指令启 动这些组件容器,部署不就完成了吗? 事实上,在 Kubernetes 早期的部署脚本里,确实有一个脚本就是用 Docker 部署 Kubernetes 项 目的,这个脚本相比于 SaltStack 等的部署方式,也的确简单了不少。

但是,这样做会带来一个很麻烦的问题,即:如何容器化 kubelet。 我在上一篇文章中,已经提到 kubelet 是 Kubernetes 项目用来操作 Docker 等容器运行时的核心 组件。可是,除了跟容器运行时打交道外,kubelet 在配置容器网络、管理容器数据卷时,都需要直 接操作宿主机。 而如果现在 kubelet 本身就运行在一个容器里,那么直接操作宿主机就会变得很麻烦。对于网络配 置来说还好,kubelet 容器可以通过不开启 Network Namespace(即 Docker 的 host network 模式)的方式,直接共享宿主机的网络栈。可是,要让 kubelet 隔着容器的 Mount Namespace 和 文件系统,操作宿主机的文件系统,就有点儿困难了。

比如,如果用户想要使用 NFS 做容器的持久化数据卷,那么 kubelet 就需要在容器进行绑定挂载 前,在宿主机的指定目录上,先挂载 NFS 的远程目录。 可是,这时候问题来了。由于现在 kubelet 是运行在容器里的,这就意味着它要做的这个“mount -F nfs”命令,被隔离在了一个单独的 Mount Namespace 中。即,kubelet 做的挂载操作,不能 被“传播”到宿主机上。 对于这个问题,有人说,可以使用 setns() 系统调用,在宿主机的 Mount Namespace 中执行这些 挂载操作;也有人说,应该让 Docker 支持一个–mnt=host 的参数。  

但是,到目前为止,在容器里运行 kubelet,依然没有很好的解决办法,我也不推荐你用容器去部署 Kubernetes 项目。

正因为如此,kubeadm 选择了一种妥协方案: 所以,你使用 kubeadm 的第一步,是在机器上手动安装 kubeadm、kubelet 和 kubectl 这三个二 进制文件。当然,kubeadm 的作者已经为各个发行版的 Linux 准备好了安装包,所以你只需要执 行:

$ apt-get install kubeadm

就可以了。 接下来,你就可以使用“kubeadm init”部署 Master 节点了。 kubeadm init 的工作流程 当你执行 kubeadm init 指令后,kubeadm 首先要做的,是一系列的检查工作,以确定这台机器 可以用来部署 Kubernetes。这一步检查,我们称为“Preflight Checks”,它可以为你省掉很多后 续的麻烦。 其实,Preflight Checks 包括了很多方面,比如: 在通过了 Preflight Checks 之后,kubeadm 要为你做的,是生成 Kubernetes 对外提供服务所 需的各种证书和对应的目录。

Kubernetes 对外提供服务时,除非专门开启“不安全模式”,否则都要通过 HTTPS 才能访问 kube-apiserver。这就需要为 Kubernetes 集群配置好证书文件。 kubeadm 为 Kubernetes 项目生成的证书文件都放在 Master 节点的 /etc/kubernetes/pki 目录 下。在这个目录下,最主要的证书文件是 ca.crt 和对应的私钥 ca.key。

此外,用户使用 kubectl 获取容器日志等 streaming 操作时,需要通过 kube-apiserver 向 kubelet 发起请求,这个连接也必须是安全的。kubeadm 为这一步生成的是 apiserver-kubeletclient.crt 文件,对应的私钥是 apiserver-kubelet-client.key。 除此之外,Kubernetes 集群中还有 Aggregate APIServer 等特性,也需要用到专门的证书,这里 我就不再一一列举了。

需要指出的是,你可以选择不让 kubeadm 为你生成这些证书,而是拷贝现 有的证书到如下证书的目录里:  

/etc/kubernetes/pki/ca.{crt,key}

  

这时,kubeadm 就会跳过证书生成的步骤,把它完全交给用户处理。 证书生成后,kubeadm 接下来会为其他组件生成访问 kube-apiserver 所需的配置文件。这些文 件的路径是:/etc/kubernetes/xxx.conf:

ls /etc/kubernetes/
admin.conf  controller-manager.conf  kubelet.conf  scheduler.conf

  

这些文件里面记录的是,当前这个 Master 节点的服务器地址、监听端口、证书目录等信息。这 样,对应的客户端(比如 scheduler,kubelet 等),可以直接加载相应的文件,使用里面的信息与 kube-apiserver 建立安全连接。 接下来,kubeadm 会为 Master 组件生成 Pod 配置文件。我已经在上一篇文章中和你介绍过 Kubernetes 有三个 Master 组件 kube-apiserver、kube-controller-manager、kubescheduler,而它们都会被使用 Pod 的方式部署起来。

你可能会有些疑问:这时,Kubernetes 集群尚不存在,难道 kubeadm 会直接执行 docker run 来 启动这些容器吗? 当然不是。 在 Kubernetes 中,有一种特殊的容器启动方法叫做“Static Pod”。它允许你把要部署的 Pod 的 YAML 文件放在一个指定的目录里。这样,当这台机器上的 kubelet 启动时,它会自动检查这个目 录,加载所有的 Pod YAML 文件,然后在这台机器上启动它们。

从这一点也可以看出,kubelet 在 Kubernetes 项目中的地位非常高,在设计上它就是一个完全独 立的组件,而其他 Master 组件,则更像是辅助性的系统容器。 在 kubeadm 中,Master 组件的 YAML 文件会被生成在 /etc/kubernetes/manifests 路径下。比 如,kube-apiserver.yaml:

apiVersion: v1
kind: Pod
metadata:annotations:scheduler.alpha.kubernetes.io/critical-pod: ""creationTimestamp: nulllabels:component: kube-apiservertier: control-planename: kube-apiservernamespace: kube-system
spec:containers:- command:- kube-apiserver- --authorization-mode=Node,RBAC- --runtime-config=api/all=true- --advertise-address=10.168.0.2...- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt- --tls-private-key-file=/etc/kubernetes/pki/apiserver.keyimage: k8s.gcr.io/kube-apiserver-amd64:v1.11.1imagePullPolicy: IfNotPresentlivenessProbe:...name: kube-apiserverresources:requests:cpu: 250mvolumeMounts:- mountPath: /usr/share/ca-certificatesname: usr-share-ca-certificatesreadOnly: true...hostNetwork: truepriorityClassName: system-cluster-criticalvolumes:- hostPath:path: /etc/ca-certificatestype: DirectoryOrCreatename: etc-ca-certificates...

关于一个 Pod 的 YAML 文件怎么写、里面的字段如何解读,我会在后续专门的文章中为你详细分 析。在这里,你只需要关注这样几个信息:

  • 1. 这个 Pod 里只定义了一个容器,它使用的镜像是:k8s.gcr.io/kube-apiserveramd64:v1.11.1 。这个镜像是 Kubernetes 官方维护的一个组件镜像。
  • 2. 这个容器的启动命令(commands)是 kube-apiserver --authorization-mode=Node,RBAC …,这样一句非常长的命令。其实,它就是容器里 kube-apiserver 这个二进制文件再加上指定的 配置参数而已。
  • 3. 如果你要修改一个已有集群的 kube-apiserver 的配置,需要修改这个 YAML 文件。
  • 4. 这些组件的参数也可以在部署时指定,我很快就会讲解到。 在这一步完成后,kubeadm 还会再生成一个 Etcd 的 Pod YAML 文件,用来通过同样的 Static Pod 的方式启动 Etcd。

所以,最后 Master 组件的 Pod YAML 文件如下所示:  

$ ls /etc/kubernetes/manifests/
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

  

而一旦这些 YAML 文件出现在被 kubelet 监视的 /etc/kubernetes/manifests 目录下,kubelet 就 会自动创建这些 YAML 文件中定义的 Pod,即 Master 组件的容器。 Master 容器启动后,kubeadm 会通过检查 localhost:6443/healthz 这个 Master 组件的健康检查 URL,等待 Master 组件完全运行起来。

然后,kubeadm 就会为集群生成一个 bootstrap token。在后面,只要持有这个 token,任何一 个安装了 kubelet 和 kubadm 的节点,都可以通过 kubeadm join 加入到这个集群当中。 这个 token 的值和使用方法会,会在 kubeadm init 结束后被打印出来。 在 token 生成之后,kubeadm 会将 ca.crt 等 Master 节点的重要信息,通过 ConfigMap 的方 式保存在 Etcd 当中,供后续部署 Node 节点使用。

这个 ConfigMap 的名字是 cluster-info。 kubeadm init 的最后一步,就是安装默认插件。Kubernetes 默认 kube-proxy 和 DNS 这两个插 件是必须安装的。它们分别用来提供整个集群的服务发现和 DNS 功能。其实,这两个插件也只是两 个容器镜像而已,所以 kubeadm 只要用 Kubernetes 客户端创建两个 Pod 就可以了。

kubeadm join 的工作流程 这个流程其实非常简单,kubeadm init 生成 bootstrap token 之后,你就可以在任意一台安装了 kubelet 和 kubeadm 的机器上执行 kubeadm join 了。 可是,为什么执行 kubeadm join 需要这样一个 token 呢? 因为,任何一台机器想要成为 Kubernetes 集群中的一个节点,就必须在集群的 kube-apiserver 上 注册。

可是,要想跟 apiserver 打交道,这台机器就必须要获取到相应的证书文件(CA 文件)。可 是,为了能够一键安装,我们就不能让用户去 Master 节点上手动拷贝这些文件。 所以,kubeadm 至少需要发起一次“不安全模式”的访问到 kube-apiserver,从而拿到保存在 ConfigMap 中的 cluster-info(它保存了 APIServer 的授权信息)。

而 bootstrap token,扮演的 就是这个过程中的安全验证的角色。 只要有了 cluster-info 里的 kube-apiserver 的地址、端口、证书,kubelet 就可以以“安全模 式”连接到 apiserver 上,这样一个新的节点就部署完成了。 接下来,你只要在其他节点上重复这个指令就可以了。 配置 kubeadm 的部署参数 我在前面讲解了 kubeadm 部署 Kubernetes 集群最关键的两个步骤,kubeadm init 和 kubeadm join。相信你一定会有这样的疑问:kubeadm 确实简单易用,可是我又该如何定制我的集群组件参 数呢?

$ kubeadm init --config kubeadm.yaml

  

这时,你就可以给 kubeadm 提供一个 YAML 文件(比如,kubeadm.yaml),它的内容如下所示 (我仅列举了主要部分):

apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.0
api:advertiseAddress: 192.168.0.102bindPort: 6443...
etcd:local:dataDir: /var/lib/etcdimage: ""
imageRepository: k8s.gcr.io
kubeProxy:config:bindAddress: 0.0.0.0...
kubeletConfiguration:baseConfig:address: 0.0.0.0...
networking:dnsDomain: cluster.localpodSubnet: ""serviceSubnet: 10.96.0.0/12
nodeRegistration:criSocket: /var/run/dockershim.sock...

  

通过制定这样一个部署参数配置文件,你就可以很方便地在这个文件里填写各种自定义的部署参数 了。比如,我现在要指定 kube-apiserver 的参数,那么我只要在这个文件里加上这样一段信息:

...
apiServerExtraArgs:advertise-address: 192.168.0.103anonymous-auth: falseenable-admission-plugins: AlwaysPullImages,DefaultStorageClassaudit-log-path: /home/johndoe/audit.log

  

然后,kubeadm 就会使用上面这些信息替换 /etc/kubernetes/manifests/kube-apiserver.yaml 里的 command 字段里的参数了。 而这个 YAML 文件提供的可配置项远不止这些。比如,你还可以修改 kubelet 和 kube-proxy 的配 置,修改 Kubernetes 使用的基础镜像的 URL(默认的k8s.gcr.io/xxx镜像 URL 在国内访问是 有困难的),指定自己的证书文件,指定特殊的容器运行时等等。这些配置项,就留给你在后续实 践中探索了。 总结 在今天的这次分享中,我重点介绍了 kubeadm 这个部署工具的工作原理和使用方法。紧接着,我 会在下一篇文章中,使用它一步步地部署一个完整的 Kubernetes 集群。 从今天的分享中,你可以看到,kubeadm 的设计非常简洁。并且,它在实现每一步部署功能时,都 在最大程度地重用 Kubernetes 已有的功能,这也就使得我们在使用 kubeadm 部署 Kubernetes 项目时,非常有“原生”的感觉,一点都不会感到突兀。 而 kubeadm 的源代码,直接就在 kubernetes/cmd/kubeadm 目录下,是 Kubernetes 项目的一 部分。其中,app/phases 文件夹下的代码,对应的就是我在这篇文章中详细介绍的每一个具体步 骤。

转载于:https://www.cnblogs.com/crazymagic/p/10555498.html

Kubernetes一键部署利器:kubeadm相关推荐

  1. docker学习总结第六篇:Kubernetes一键部署利器-kubeadm

    通过前面几篇文章的内容,我其实阐述了这样一个思想:要真正发挥容器技术的实力,你就不能仅仅局限于对 Linux 容器本身的钻研和使用. 这些知识更适合作为你的技术储备,以便在需要的时候可以帮你更快的定位 ...

  2. Kubernetes 一键部署利器:kubeadm

    文章目录 集群部署痛点 kubeadm 的工作原理 kubeadm init 的工作流程 kubeadm join 的工作流程 kubeadm 的部署配置参数 集群部署痛点 Kubernetes 的部 ...

  3. Kubernetes实战(二)- 一键部署神器kubeadm

    容器的核心在于"容器化"应用 比如,应用既可能是 Java Web和MySQL Cassandra这样的分布式系统 而要使用容器把后者运行起来,单通过Docker把一个Cassan ...

  4. kubernetes安装部署(kubeadm方式亲测)

    准备工作: 关闭防火墙 systemctl stop firewalld systemctl disable firewalld 关闭selinux sed -i 's/enforcing/disab ...

  5. k8s主从自动切换mysql_Kubernetes一键部署Mycat+Mysql主从集群

    Kubernetes一键部署一主一从,读写分离,自动切换的mycat+mysql架构,其中mycat配置文件.mysqsl数据文件的volume挂载未涉及,可根据实际情况进行修改.所有代码参照gith ...

  6. K8S:使用kubeadm一键部署

    一键部署 # 创建一个Master节点 $ kubeadm init# 将一个Node节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口> kubeadm ...

  7. 【docker】kubernetes集群一键部署包

    背景说明: 随着docker使用的逐步深入,docker的管理变得越来越麻烦,单纯的通过docker命令行的方式进行管理已经不能满足需求,同时也存在效率低下的问题.所以急需一个docker集群管理工具 ...

  8. Kubernetes单机部署-一键安装

    Kubernetes单机部署-一键安装 环境说明 安装步骤 Kubernetes的应用已经越来越广了,我们总是为他强大而神秘的功能所折服.总想自己也搭一套环境,奈何网上很多教程都存在或多或少的问题.遂 ...

  9. 利用Helm简化Kubernetes应用部署(1)

    目录 利用Helm简化Kubernetes应用部署  Helm基础  安装Helm  使用Visual Studio 2019为Helm编写一个简单的应用  利用Helm简化Kubernetes应用部 ...

最新文章

  1. 推荐|一个地面机器人采集的大型数据集
  2. css高清动图,CSS3+PNG实现GIF动画效果
  3. JSON在Android网络交互中的使用方法
  4. MySQL执行计划extra中的using index 和 using where using index 的区别
  5. bzoj2456: mode
  6. eclipse maven打包_自动化管理项目,Maven仓库配置、安装和使用
  7. idea 包拆分_idea springboot项目拆分多模块踩坑记(1)
  8. leetcode -- Construct Binary Tree from Preorder and Inorder Traversal
  9. kali系统安装DVWA
  10. Unity HDR (高动态范围 )
  11. 你不可不知的《哈利波特》秘密之卑鄙的海尔波
  12. 计算机d盘可以格式化吗,电脑d盘格式化对电脑有影响吗
  13. ABP理论学习之实体类
  14. 为什么百度查到的ip和ipconfig查到的不一样?
  15. 知网下载的PDF论文,如何加目录的方法
  16. 如何查看网站是否被百度(搜索引擎)收录
  17. Serverlet简介及理解
  18. MyCat启动报错,运行./mycat console报错 Unrecognized VM option 'AggressiveOpts'
  19. $.each与$().each
  20. Qt多线程之继承QObject(moveToThread方式)

热门文章

  1. Java格式化输出的四种方法
  2. 字符串查找函数strstr 简单模拟实现
  3. 详解《战地3》AA优化之道
  4. MySQL表名忽略大小写问题
  5. 开发www.miibeian.gov.cn的JAVAEE大师 -- I 服了油
  6. unity实现弓箭轨迹
  7. OpenGL ES 之 LUT(滤镜基准图)
  8. thinkphp + 美图秀秀api 实现图片裁切上传,带数据库
  9. php获取时间不准,php获取时间不准确怎么办
  10. 数据结构与算法期中考试