ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一键部署利器:kubeadm

2022-01-28 18:04:03  阅读:421  来源: 互联网

标签:Kubernetes kubelet 部署 一键 apiserver 利器 kubeadm kube


Kubernetes 作为一个 Golang 项目,已经免去了很多类似于 Python 项目要安装语言级别依赖的麻烦。但是,除了将各个组件编译成二进制文件外,用户还要负责为这些二进制文件编写对应的配置文件、配置自启动脚本,以及为 kube-apiserver 配置授权文件等等诸多运维工作。

目前,各大云厂商最常用的部署的方法,是使用 SaltStack、Ansible 等运维工具自动化地执行这些步骤。但即使这样,这个部署过程依然非常繁琐。因为,SaltStack 这类专业运维工具本身的学习成本,就可能比 Kubernetes 项目还要高。

即使这样,这个部署过程依然非常繁琐。因为,SaltStack 这类专业运维工具本身的学习成本,就可能比 Kubernetes 项目还要高。

部署复杂问题难道没有什么简单方式了吗?

在 Kubernetes 社区里一直没有得到足够重视。直到 2017 年,在志愿者的推动下,社区才终于发起了一个独立的部署工具,名叫:kubeadm

项目的目的,就是要让用户能够通过这样两条指令完成一个 Kubernetes 集群的部署:

# 创建一个Master节点
kubeadm init

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

kubeadm 的工作原理

之前文章我们了解到Kubernetes 的架构和它的组件。在部署时,它的每一个组件都是一个需要被执行的、单独的二进制文件。所以不难想象,SaltStack 这样的运维工具或者由社区维护的脚本的功能,就是要把这些二进制文件传输到指定的机器当中,然后编写控制脚本来启停这些组件。

问题:

容器化技术出现后为什么我们不能使用docker来部署kubernetes?

答案:

在 Kubernetes 早期的部署脚本里,确实有一个脚本就是用 Docker 部署 Kubernetes 项目的,这个脚本相比于 SaltStack 等的部署方式,也的确简单了不少。但是,这样做会带来一个很麻烦的问题,即:如何容器化 kubelet(由于kubelet需要操作宿主机的网络、数据卷等,无法很好地在容器中实现,这就限制了通过容器部署kubernetes)。到目前为止,在容器里运行 kubelet,依然没有很好的解决办法,所以不推荐用容器去部署 Kubernetes 项目。

kubeadm 选择了一种妥协方案:把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。

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

apt-get install kubeadm

然后就可以使用“kubeadm init”部署 Master 节点了。

kubeadm init 的工作流程

1、kubeadm init后kubeadm 首先要做的,是一系列的检查工作,以确定这台机器可以用来部署 Kubernetes。这一步检查,我们称为“Preflight Checks”。

  • Preflight Checks 包括了很多方面,比如:

  • Linux 内核的版本必须是否是 3.10 以上?

  • Linux Cgroups 模块是否可用?

  • 机器的 hostname 是否标准?

  • 在 Kubernetes 项目里,机器的名字以及一切存储在 Etcd 中的 API 对象,都必须使用标准的 DNS 命名(RFC 1123)。

  • 用户安装的 kubeadm 和 kubelet 的版本是否匹配?机器上是不是已经安装了 Kubernetes 的二进制文件?

  • Kubernetes 的工作端口 10250/10251/10252 端口是不是已经被占用?

  • ip、mount 等 Linux 指令是否存在?Docker 是否已经安装?……

2、在通过了 Preflight Checks 之后,kubeadm 要为你做的,是生成 Kubernetes 对外提供服务所需的各种证书和对应的目录。

Kubernetes 对外提供服务时,除非专门开启“不安全模式”,否则都要通过 HTTPS 才能访问 kube-apiserver。这就需要为 Kubernetes 集群配置好证书文件。

kubeadm 为 Kubernetes 项目生成的证书文件都放在 Master 节点的 /etc/kubernetes/pki 目录下。在这个目录下,最主要的证书文件是 ca.crt 和对应的私钥 ca.key。

image

用户使用 kubectl 获取容器日志等 streaming 操作时,需要通过 kube-apiserver 向 kubelet 发起请求,这个连接也必须是安全的。kubeadm 为这一步生成的是 apiserver-kubelet-client.crt 文件,对应的私钥是 apiserver-kubelet-client.key。

Kubernetes 集群中还有 Aggregate APIServer 等特性,也需要用到专门的证书,这里我就不再一一列举了。需要指出的是,你可以选择不让 kubeadm 为你生成这些证书,而是拷贝现有的证书到如下证书的目录里:

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

kubeadm 就会跳过证书生成的步骤,把它完全交给用户处理。

证书生成后,kubeadm 接下来会为其他组件生成访问 kube-apiserver 所需的配置文件。这些文件的路径是:/etc/kubernetes/xxx.conf:

[17:07:02 root@lyp-master kubernetes]#ls /etc/kubernetes/
admin.conf  controller-manager.conf  kubelet.conf  manifests  pki  scheduler.conf

这些文件里面记录的是,当前这个 Master 节点的服务器地址、监听端口、证书目录等信息。这样,对应的客户端(比如 scheduler,kubelet 等),可以直接加载相应的文件,使用里面的信息与 kube-apiserver 建立安全连接。

3、kubeadm 会为 Master 组件生成 Pod 配置文件。

Kubernetes 有三个 Master 组件 kube-apiserver、kube-controller-manager、kube-scheduler,而它们都会被使用 Pod 的方式部署起来。

问题:Kubernetes 集群尚不存在,难道 kubeadm 会直接执行 docker run 来启动这些容器吗?

答:在 Kubernetes 中,有一种特殊的容器启动方法叫做“Static Pod”。它允许你把要部署的 Pod 的 YAML 文件放在一个指定的目录里。这样,当这台机器上的 kubelet 启动时,它会自动检查这个目录,加载所有的 Pod YAML 文件,然后在这台机器上启动它们。从这一点也可以看出,kubelet 在 Kubernetes 项目中的地位非常高,在设计上它就是一个完全独立的组件,而其他 Master 组件,则更像是辅助性的系统容器。

kubeadm 中,Master 组件的 YAML 文件会被生成在 /etc/kubernetes/manifests 路径下。

[17:13:10 root@lyp-master manifests]#ls
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

比如,kube-apiserver.yaml:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    scheduler.alpha.kubernetes.io/critical-pod: ""
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: 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.key
    image: k8s.gcr.io/kube-apiserver-amd64:v1.11.1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      ...
    name: kube-apiserver
    resources:
      requests:
        cpu: 250m
    volumeMounts:
    - mountPath: /usr/share/ca-certificates
      name: usr-share-ca-certificates
      readOnly: true
    ...
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/ca-certificates
      type: DirectoryOrCreate
    name: etc-ca-certificates
  ...

简单关注几个信息:

  • 这个 Pod 里只定义了一个容器,它使用的镜像是:k8s.gcr.io/kube-apiserver-amd64:v1.11.1 。
  • 这个镜像是 Kubernetes 官方维护的一个组件镜像。
  • 这个容器的启动命令(commands)是 kube-apiserver --authorization-mode=Node,RBAC …,这样一句非常长的命令。其实,它就是容器里 kube-apiserver 这个二进制文件再加上指定的配置参数而已。
  • 如果你要修改一个已有集群的 kube-apiserver 的配置,需要修改这个 YAML 文件。
  • 这些组件的参数也可以在部署时指定。

kubeadm 还会再生成一个 Etcd 的 Pod YAML 文件,用来通过同样的 Static Pod 的方式启动 Etcd。

这些 YAML 文件出现在被 kubelet 监视的 /etc/kubernetes/manifests 目录下,kubelet 就会自动创建这些 YAML 文件中定义的 Pod,即 Master 组件的容器。

Master 容器启动后,kubeadm 会通过检查 localhost:6443/healthz 这个 Master 组件的健康检查 URL,等待 Master 组件完全运行起来。

4、kubeadm 就会为集群生成一个 bootstrap token

只要持有这个 token,任何一个安装了 kubelet 和 kubadm 的节点,都可以通过 kubeadm join 加入到这个集群当中。

5、kubeadm 会将 ca.crt 等 Master 节点的重要信息,通过 ConfigMap 的方式保存在 Etcd 当中,供后续部署 Node 节点使用。

ConfigMap 的名字是 cluster-info。

6、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 join 192.168.9.1:6443 --token 8rzfx1.0mliir0mjure3cq0 \
    --discovery-token-ca-cert-hash sha256:cf6496e029192677b6761569f8d6e1088287d27447598dd57cb01809829ecea2 

配置kubeadm的部署参数

总结kubeadm 部署 Kubernetes 集群最关键的两个步骤,在master节点 kubeadm init 和 在node节点kubeadm join。

问题:

我要指定 kube-apiserver 的启动参数,该怎么办?

答:

强烈推荐你在使用 kubeadm init 部署 Master 节点时,使用下面这条指令:(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.102
  bindPort: 6443
  ...
etcd:
  local:
    dataDir: /var/lib/etcd
    image: ""
imageRepository: k8s.gcr.io
kubeProxy:
  config:
    bindAddress: 0.0.0.0
    ...
kubeletConfiguration:
  baseConfig:
    address: 0.0.0.0
    ...
networking:
  dnsDomain: cluster.local
  podSubnet: ""
  serviceSubnet: 10.96.0.0/12
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  ...

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

...
apiServerExtraArgs:
  advertise-address: 192.168.0.103
  anonymous-auth: false
  enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
  audit-log-path: /home/johndoe/audit.log

kubeadm 就会使用上面这些信息替换 /etc/kubernetes/manifests/kube-apiserver.yaml 里的 command 字段里的参数了。

当然还可以做其他定制修改。比如,你还可以修改 kubelet 和 kube-proxy 的配置,修改 Kubernetes 使用的基础镜像的 URL(默认的k8s.gcr.io/xxx镜像 URL 在国内访问是有困难的),指定自己的证书文件,指定特殊的容器运行时等等。

总结:

本篇介绍了 kubeadm 这个部署工具的工作原理和使用方法。

可以看到,kubeadm 的设计非常简洁。并且,它在实现每一步部署功能时,都在最大程度地重用 Kubernetes 已有的功能,这也就使得我们在使用 kubeadm 部署 Kubernetes 项目时,非常有“原生”的感觉。

kubeadm 的源代码,直接就在 kubernetes/cmd/kubeadm 目录下,是 Kubernetes 项目的一部分。其中,app/phases 文件夹下的代码,对应的就是这篇文章中详细介绍的每一个具体步骤。

题外话

大家可能会猜想,kubeadm 的作者一定是 Google 公司的某个“大神”吧。实际上,kubeadm 几乎完全是一位高中生的作品。他叫 Lucas Käldström,芬兰人,今年只有 18 岁。kubeadm,是他 17 岁时用业余时间完成的一个社区项目。

源社区的魅力也在于此:

一个成功的开源项目,总能够吸引到全世界最厉害的贡献者参与其中。尽管参与者的总体水平参差不齐,而且频繁的开源活动又显得杂乱无章难以管控,但一个有足够热度的社区最终的收敛方向,却一定是代码越来越完善、Bug 越来越少、功能越来越强大。

标签:Kubernetes,kubelet,部署,一键,apiserver,利器,kubeadm,kube
来源: https://www.cnblogs.com/yapong/p/15853434.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有