kubeadm文档
kubeadm、kubelet 和 kubectl 三个组件

  • kubeadm 用于初始化Cluster;
  • kubelet 运行在Cluster 的所有节点上面,负责Pod和容器的启动和维护;
  • kubectl 命令行工具。通过 kubectl可以部署和管理应用,查看资源,维护组件。

    kubelet无法容器化

    如果kubelet 本身就运行在一个容器里,直接操作宿主机就会变得很麻烦。

  • 对于网络配置来说还好,kubelet 容器可以通过不开启 Network Namespace(即 Docker 的 host network 模式)的方式,直接共享宿主机的网络栈。

  • 要让 kubelet 隔着容器的 Mount Namespace 和文件系统,操作宿主机的文件系统,就无法实现。

    kubeadm init 的工作流程

    Preflight Checks

    kubeadm 首先要做的,是一系列的检查工作,以确定这台机器可以用来部署 Kubernetes。

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

  • Linux Cgroups 模块是否可用?
  • 机器的 hostname 是否标准?
  • 在 Kubernetes 项目里,机器的名字以及一切存储在 Etcd 中的 API 对象,都必须使用标准的 DNS 命名(RFC 1123)。用户安装的 kubeadm 和 kubelet 的版本是否匹配?
  • 机器上是不是已经安装了 Kubernetes 的二进制文件?
  • Kubernetes 的工作端口 10250/10251/10252 端口是不是已经被占用?
  • ip、mount 等 Linux 指令是否存在?Docker 是否已经安装?

    生成 Kubernetes 对外提供服务所需的各种证书和对应的目录

    Kubernetes 对外提供服务时,除非专门开启“不安全模式”,否则都要通过 HTTPS 才能访问 kube-apiserver。
    kubeadm 为 Kubernetes 项目生成的证书文件都放在 Master 节点的 /etc/kubernetes/pki 目录下。在这个目录下,最主要的证书文件是 ca.crt 和对应的私钥 ca.key。
    用户使用 kubectl 获取容器日志等 streaming 操作时,需要通过 kube-apiserver 向 kubelet 发起请求,这个连接也必须是安全的。kubeadm 为这一步生成的是 apiserver-kubelet-client.crt 文件,对应的私钥是 apiserver-kubelet-client.key。

需要指出的是,选择不让 kubeadm 为你生成这些证书,需要拷贝现有的证书到如下证书的目录里: /etc/kubernetes/pki/ca.{crt,key}

kubeadm 为其他组件生成访问 kube-apiserver 所需的配置文件

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

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

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

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

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

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

  1. [root@node1 manifests]# cat kube-apiserver.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. annotations:
  6. kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.0.2.15:6443
  7. creationTimestamp: null
  8. labels:
  9. component: kube-apiserver
  10. tier: control-plane
  11. name: kube-apiserver
  12. namespace: kube-system
  13. spec:
  14. containers:
  15. - command:
  16. - kube-apiserver
  17. - --advertise-address=10.0.2.15
  18. - --allow-privileged=true
  19. - --authorization-mode=Node,RBAC
  20. - --client-ca-file=/etc/kubernetes/pki/ca.crt
  21. ...
  22. image: k8s.gcr.io/kube-apiserver:v1.18.3
  23. imagePullPolicy: IfNotPresent
  24. livenessProbe:
  25. failureThreshold: 8
  26. httpGet:
  27. host: 10.0.2.15
  28. path: /healthz
  29. port: 6443
  30. scheme: HTTPS
  31. initialDelaySeconds: 15
  32. timeoutSeconds: 15
  33. name: kube-apiserver
  34. resources:
  35. requests:
  36. cpu: 250m
  37. volumeMounts:
  38. - mountPath: /etc/ssl/certs
  39. name: ca-certs
  40. readOnly: true
  41. - mountPath: /etc/pki
  42. name: etc-pki
  43. readOnly: true
  44. - mountPath: /etc/kubernetes/pki
  45. name: k8s-certs
  46. readOnly: true
  47. hostNetwork: true
  48. priorityClassName: system-cluster-critical
  49. volumes:
  50. - hostPath:
  51. path: /etc/ssl/certs
  52. type: DirectoryOrCreate
  53. name: ca-certs
  54. - hostPath:
  55. path: /etc/pki
  56. type: DirectoryOrCreate
  57. name: etc-pki
  58. - hostPath:
  59. path: /etc/kubernetes/pki
  60. type: DirectoryOrCreate
  61. name: k8s-certs
  62. status: {}

image定义了镜像:k8s.gcr.io/kube-apiserver:v1.18.3。这个镜像是 Kubernetes 官方维护的一个组件镜像。
commands是容器的启动命令 kube-apiserver —authorization-mode=Node,RBAC …,它就是容器里 kube-apiserver 这个二进制文件再加上指定的配置参数。

kubeadm 为集群生成一个 bootstrap token

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

安装默认插件

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 的部署参数

指定 kube-apiserver 的启动参数
kubeadm init —config kubeadm.yaml
可以给 kubeadm 提供一个 YAML 文件(比如,kubeadm.yaml),它的内容如下所示(我仅列举了主要部分)

  1. apiVersion: kubeadm.k8s.io/v1beta2
  2. bootstrapTokens:
  3. - groups:
  4. - system:bootstrappers:kubeadm:default-node-token
  5. token: abcdef.0123456789abcdef
  6. ttl: 24h0m0s
  7. usages:
  8. - signing
  9. - authentication
  10. kind: InitConfiguration
  11. localAPIEndpoint:
  12. advertiseAddress: 1.2.3.4
  13. bindPort: 6443
  14. nodeRegistration:
  15. criSocket: /var/run/dockershim.sock
  16. name: node1
  17. taints:
  18. - effect: NoSchedule
  19. key: node-role.kubernetes.io/master
  20. ---
  21. apiServer:
  22. timeoutForControlPlane: 4m0s
  23. apiVersion: kubeadm.k8s.io/v1beta2
  24. certificatesDir: /etc/kubernetes/pki
  25. clusterName: kubernetes
  26. controllerManager: {}
  27. dns:
  28. type: CoreDNS
  29. etcd:
  30. local:
  31. dataDir: /var/lib/etcd
  32. imageRepository: k8s.gcr.io
  33. kind: ClusterConfiguration
  34. kubernetesVersion: v1.18.0
  35. networking:
  36. dnsDomain: cluster.local
  37. serviceSubnet: 10.96.0.0/12
  38. scheduler: {}

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

  1. apiServerExtraArgs:
  2. advertise-address: 192.168.0.103
  3. anonymous-auth: false
  4. enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
  5. audit-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)
  • 指定自己的证书文件,指定特殊的容器运行时

其他资源
https://github.com/SongCF/kubesh

本地测试
https://github.com/kubernetes/minikube Run Kubernetes locally
https://github.com/AliyunContainerService/minikube the best tool for local Kubernetes application development
https://github.com/kubernetes-sigs/kind Kubernetes IN Docker - local clusters for testing Kubernetes

生产可用
https://github.com/kubernetes/kops Production Grade K8s Installation, Upgrades, and Management
https://github.com/kubernetes-incubator/kubespray Deploy a Production Ready Kubernetes Cluster
https://github.com/gjmzj/kubeasz 使用Ansible脚本安装K8S集群,介绍组件交互原理,方便直接,不受国内网络环境影响

Kubeadm已经生产可用了:https://kubernetes.io/blog/2018/12/04/production-ready-kubernetes-cluster-creation-with-kubeadm/

对于GFW,不能直接给kubeadm上代理,而是要让docker daemon翻,正确姿势参见:
https://stackoverflow.com/questions/26550360/docker-ubuntu-behind-proxy

“kubeadm config print init-defaults”这个命令可以告诉我们kubeadm.yaml版本信息。