[TOC]

0x01 架构深入

1.节点状态

Q:什么是节点?
答:Kubernetes中节点(node)指的是一个工作机器曾经叫做 minion , 但是需要注意不同的集群中,节点可能是虚拟机也可能是物理机。
每个节点都由 master 组件管理,并包含了运行 Pod(容器组)所需的服务包括:容器引擎 / kubelet / kube-proxy

节点的状态包含如下信息:

  • Conditions:节点的状态正常的如下面的节点信息,实际在文件中是以JSON对象的形式存在;
    1
    2
    3
    4
    5
    6
    Ready 	            #如果节点是健康的且已经就绪可以接受新的 Pod。则节点Ready字段为 True。False表明了该节点不健康不能够接受新的 Pod。
    OutOfDisk #如果节点上的空白磁盘空间不够,不能够再添加新的节点时,该字段为 True 其他情况为 False
    MemoryPressure #如果节点内存紧张,则该字段为 True,否则为False
    PIDPressure #如果节点上进程过多,则该字段为 True,否则为 False
    DiskPressure #如果节点磁盘空间紧张,则该字段为 True,否则为 False
    NetworkUnvailable #如果节点的网络配置有问题,则该字段为 True,否则为 False
  • Addresses
    1
    2
    #ExternalIP:通常是节点的外部IP(可以从集群外访问的内网IP地址此字段为空)
    #InternalIP:通常是从节点内部可以访问的 IP 地址
  • Capacity and Allocatable : 描述了节点上的可用资源的情况即CPU,内存,该节点可调度的最大 pod 数量
    • Capacity 中的字段表示节点上的资源总数
    • Allocatable 中的字段表示该节点上可分配给普通 Pod 的资源总数。
  • Info : 描述了节点的基本信息该信息以信息由节点上的 kubelet 收集。
    1
    2
    3
    4
    * Linux 内核版本
    * Kubernetes 版本(kubelet 和 kube-proxy 的版本)
    * Docker 版本
    * 操作系统名称

Q:如何查看节点状态?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#查看所有节点的列表
$kubectl get nodes -o wide

#查看节点状态以及节点的其他详细信息
kubectl describe node <your-node-name>
$kubectl describe node node-1
Name: node-1 #节点名称
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=node-1
kubernetes.io/os=linux
Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 10.20.172.82/24 #IPaddress
projectcalico.org/IPv4IPIPTunnelAddr: 10.100.84.128 #Tunnel IP
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Tue, 16 Jun 2020 15:15:11 +0800 #加入时间
Taints: <none>
Unschedulable: false
Lease:
HolderIdentity: node-1
AcquireTime: <unset>
RenewTime: Wed, 17 Jun 2020 00:01:37 +0800

# (1) 描述了节点的状态
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Tue, 16 Jun 2020 23:17:13 +0800 Tue, 16 Jun 2020 23:17:13 +0800 CalicoIsUp Calico is running on this node
MemoryPressure False Tue, 16 Jun 2020 23:57:26 +0800 Tue, 16 Jun 2020 23:15:44 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Tue, 16 Jun 2020 23:57:26 +0800 Tue, 16 Jun 2020 23:15:44 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Tue, 16 Jun 2020 23:57:26 +0800 Tue, 16 Jun 2020 23:15:44 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Tue, 16 Jun 2020 23:57:26 +0800 Tue, 16 Jun 2020 23:16:35 +0800 KubeletReady kubelet is posting ready status

# (2) 依据你集群部署的方式(在哪个云供应商部署,或是在物理机上部署),Addesses 字段可能有所不同。
Addresses:
# 内部IP
InternalIP: 10.20.172.82
# 节点主机名称,启动 kubelet 时可以通过参数 --hostname-override 覆盖
Hostname: node-1

# (3) 容量描述了节点上的可用资源的情况
# Capacity 中的字段表示节点上的资源总数
Capacity:
cpu: 2
ephemeral-storage: 47285700Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 2037168Ki
pods: 110
# Allocatable 中的字段表示该节点上可分配给普通 Pod 的资源总数。
Allocatable:
cpu: 2
ephemeral-storage: 43578501048
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 1934768Ki
pods: 110
# 节点系统信息
System Info:
Machine ID: 6e65e151c0ef4248b78d6be0fb63eb58
System UUID: 564d504e-4027-b5c3-9c49-11f2de69bf26
Boot ID: 90c3795b-4823-41de-9893-ef6b89db9614
Kernel Version: 5.7.0-1.el7.elrepo.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://19.3.9 #容器版本
Kubelet Version: v1.18.3 #kubernetes 版本
Kube-Proxy Version: v1.18.3
PodCIDR: 10.100.1.0/24 # Pod子网
PodCIDRs: 10.100.1.0/24
Non-terminated Pods: (2 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system calico-node-jp55x 250m (12%) 0 (0%) 0 (0%) 0 (0%) 46m #节点的Calicao网络
kube-system kube-proxy-kglgh 0 (0%) 0 (0%) 0 (0%) 0 (0%) 46m #节点的kube-proxy代理
Allocated resources: #分配资源 配置资源情况
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 250m (12%) 0 (0%)
memory 0 (0%) 0 (0%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
Events: #事件信息
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Starting <invalid> kubelet, node-1 Starting kubelet.
Normal NodeHasSufficientMemory <invalid> (x2 over <invalid>) kubelet, node-1 Node node-1 status is now: NodeHasSufficientMemory
Normal NodeHasNoDiskPressure <invalid> (x2 over <invalid>) kubelet, node-1 Node node-1 status is now: NodeHasNoDiskPressure
Normal NodeHasSufficientPID <invalid> (x2 over <invalid>) kubelet, node-1 Node node-1 status is now: NodeHasSufficientPID
Normal NodeAllocatableEnforced <invalid> kubelet, node-1 Updated Node Allocatable limit across pods
Normal Starting <invalid> kube-proxy, node-1 Starting kube-proxy.
Normal NodeReady <invalid> kubelet, node-1 Node node-1 status is now: NodeReady

注意事项:

  • 1) 如果 Ready 类型Condition 的 status 持续为 Unkown 或者 False超过 pod-eviction-timeout(kube-controller-manager 的参数)所指定的时间(默认5分钟),节点控制器(node controller)将对该节点上的所有 Pod 执行删除的调度动作; 然而在某些特殊情况下(例如,节点网络故障)apiserver 不能够与节点上的 kubelet 通信导致删除 Pod 的指令不能下达到该节点的 kubelet 上,直到 apiserver 与节点的通信重新建立指令才下达到节点, 意味着虽然对Pod执行了删除的调用指令, 但是这些Pod仍然在失联的节点上运行。
    1
    2
    3
    4
    5
    6
    7
    # 不同版本的解决方式
    < kubernetes v1.5 : 节点控制器将从 apiserver 强制删除这些失联节点上的 Pod
    >= kubernetes v1.5 : 节点控制器将不会强制删除这些 Pod,直到已经确认他们已经停止运行为止,此时发现失联节点上的Pod仍然是在运行的(在该节点上运行docker ps即可以看见容器的运行状态), 然而 apiserver 中他们的状态已经变为 Terminating 或者 Unknown;
    == Kubernetes v1.12 : TaintNodesByCondition 特性利用node lifecycle controller 将自动创建该 Condition 对应的 污点。相应地调度器在选择合适的节点时,不再关注节点的 Condition而是检查节点的污点和 Pod 的容忍

    # 手动解决方式: 如果 Kubernetes 不能通过 cloud-controller-manager 判断失联节点是否已经永久从集群中移除(例如,在虚拟机或物理机上自己部署 Kubernetes 的情况)
    kubectl delete node your-node-name #删除 apiserver 中的节点对象, 此时Kubernetes 将删除该节点上的所有 Pod。


2.节点管理

描述:前面我们说过Node(节点)可以是一台物理主机或者虚拟机的资源池再或者云供应商创建的,在向 Kubernetes 中创建节点时,仅仅是创建了一个描述该节点的 API 对象。
当节点 API 对象创建成功后,Kubernetes将检查该节点是否有效。

注意事项:

  • Kubernetes 在 APIServer 上创建一个节点 API 对象(节点的描述),并且基于 metadata.name 字段对节点进行健康检查.
    如果节点有效(节点组件正在运行),则可以向该节点调度 Pod;否则该节点 API 对象将被忽略,直到节点变为有效状态。
  • Kubernetes 将保留无效的节点 API 对象,并不断地检查该节点是否有效。除非您使用 kubectl delete node my-first-k8s-node 命令删除该节点。
1
2
3
4
5
6
7
#例如,假设您创建如下节点信息:
apiVersion: v1
kind: Node
metadata:
name: "10.240.79.157"
labels:
name: "my-first-k8s-node"

节点控制器(Node Controller)
描述:在节点的生命周期中,节点控制器起到了许多作用。节点控制器是一个负责管理节点的 Kubernetes master 组件;

工作流程:

  • 1.首先节点控制器在注册节点时为节点分配 CIDR 地址块
    1
    2
    3
    4
    5
    6
    7
    $kubectl describe node node-1
    Addresses:
    InternalIP: 10.20.172.82
    projectcalico.org/IPv4Address: 10.20.172.82/24
    projectcalico.org/IPv4IPIPTunnelAddr: 10.100.84.128
    PodCIDR: 10.100.1.0/24
    PodCIDRs: 10.100.1.0/24
  • 2.第二,节点控制器通过(Kube-controller-manager)和云供应商(cloud-controller-manager)接口检查节点列表中每一个节点对象对应的虚拟机是否可用。
    • 云环境中只要节点状态异常,节点控制器检查其虚拟机在云供应商的状态,如果虚拟机不可用自动将节点对象从 APIServer 中删除
    • 本地局域网环境中如果节点状态异常它会不断地检查该节点是否有效,并不会将点对象从 APIServer 中删除,除非您手动删除;
  • 3.节点控制器监控节点的健康状况,每隔 --node-monitor-period 秒检查一次节点的状态;当节点变得不可触达时(例由于节点已停机,节点控制器不再收到来自节点的心跳信号),默认40秒未收到心跳,此时节点控制器将节点API对象的NodeStatus Condition取值从 NodeReady 更新为 Unknown;然后在等待 pod-eviction-timeout 为 5分钟 时间后,将节点上的所有 Pod 从节点驱逐。
    1
    2
    3
    4
    5
    # (1) NodeStatus(< V1.13) 和 node lease(>= V1.13)都被用来记录节点的心跳信号。
    - 1.1) NodeStatus 的更新频率远高于 node lease ,因为是每次节点向 master 发出心跳信号NodeStatus 都将被更新, 只有在 NodeStatus 发生改变,或者足够长的时间未接收到 NodeStatus 更新时,节点控制器才更新 node lease(默认为1分钟,比节点失联的超时时间40秒要更长)
    - 1.2) 由于 node lease 比 NodeStatus 更轻量级,该特性显著提高了节点心跳机制的效率,并使 Kubernetes 性能和可伸缩性得到了提升;
    - 1.3) 在v1.4 中优化了节点控制器的逻辑以便更好的处理大量节点不能触达 master 的情况;主要的优化点在于节点控制器在决定是否执行 Pod 驱逐的动作时,会检查集群中所有节点的状态。默认情况下节点控制器限制了驱逐 Pod 的速率为 `--node-eviction-rate (默认值是0.1)每秒`即每10s驱逐一个Pod;
    - 1.4) 当节点所在的高可用区出现故障时,节点控制器驱逐 Pod 的方式将不一样;

节点自注册(Self-Registration)
描述:如果 kubelet 的启动参数 --register-node 为 true(默认为 true),kubelet 会尝试将自己注册到 API Server。
kubelet自行注册时,将使用如下选项:

  • –kubeconfig:向 apiserver 进行认证时所用身份信息的路径
  • –cloud-provider:向云供应商读取节点自身元数据
  • –register-node:自动向 API Server 注册节点
  • –register-with-taints:注册节点时,为节点添加污点(逗号分隔,格式为 <key>=<value>:<effect>)
  • –node-ip:节点的 IP 地址
  • –node-labels:注册节点时,为节点添加标签
  • –node-status-update-frequency:向 master 节点发送心跳信息的时间间隔

如果 Node authorization mode 和 NodeRestriction admission plugin 被启用,kubelet 只拥有创建/修改其自身所对应的节点 API 对象的权限。

手动管理节点
描述:集群管理员可以创建和修改节点API对象。
如果管理员想要手工创建节点API对象,可以将 kubelet 的启动参数 --register-node 设置为 false,管理员可以修改节点API对象不管是否设置了该参数。
可以修改的内容有:增加/减少标签,标记节点为不可调度(unschedulable)
节点的标签与 Pod 上的节点选择器(node selector)配合可以控制调度方式,例如限定 Pod 只能在某一组节点上运行(后面会进行讲解);

执行如下命令可将节点标记为不可调度(unschedulable),此时将阻止新的 Pod 被调度到该节点上,但是不影响任何已经在该节点上运行的 Pod。

1
2
3
4
# 重启节点一直有效
$ kubectl cordon $NODENAME
$ kubectl cordon node-1
node/node-1 cordoned

Tips: DaemonSet Controller 创建的 Pod 将绕过 Kubernetes 调度器,并且忽略节点的 unschedulable 属性。因为我们假设 Daemons 守护进程属于节点,尽管该节点在准备重启前,已经排空了上面所有的应用程序。


节点容量(Node Capacity)
描述:节点API对象中描述了节点的容量(Capacity),例如,CPU数量、内存大小等信息。通常,节点在向 APIServer 注册的同时,在节点API对象里汇报了其容量(Capacity)。

  • 如果您手动管理节点,您需要在添加节点时自己设置节点的容量。
  • K8s调度器在调度 Pod 到节点上时,将确保节点上有足够的资源。

具体来说调度器检查节点上所有容器的资源请求之和不大于节点的容量。此时只能检查由 kubelet 启动的容器,不包括直接由容器引擎启动的容器,更不包括不在容器里运行的进程。


3.控制器

Q:什么是控制器?
A:在机器人技术和自动化技术中,控制循环是一个控制系统状态的无限循环。房间里的恒温器就是控制循环的一个应用例子;

  • 在恒温器上设定好目标温度,就是在告诉该 控制循环 你想要的 目标状态。
  • 房间里的实际温度,是 当前状态
  • 恒温器通过打开或关闭加热装置,不断地使 当前状态 接近于 目标状态

在 Kubernetes 中控制器就是上面所说的 控制循环,它不断监控着集群的状态,并对集群做出对应的变更调整。每一个控制器都不断地尝试着将 当前状态 调整到 目标状态。

作为一个底层设计原则Kubernetes使用了大量的控制器,每个控制器都用来管理集群状态的某一个方面。普遍来说任何一个特定的控制器都使用一种 API 对象作为其目标状态,并使用和管理多种类型的资源,以达到目标状态。使用许多个简单的控制器比使用一个全能的控制器要更加有优势。控制器可能会出故障,而这也是在设计 Kubernetes 时要考虑到的事情。

  • 1.可能存在多种控制器可以创建或更新相同类型的 API 对象,为了避免混淆,Kubernetes 控制器在创建新的 API 对象时,会将该对象与对应的控制 API 对象关联,并且只关注与控制对象关联的那些对象。

    • 例如,Deployment 和 Job,这两类控制器都创建 Pod。Job Controller 不会删除 Deployment Controller 创建的 Pod,因为控制器可以通过标签信息区分哪些 Pod 是它创建的。
  • 2.目标状态 vs 当前状态,Kubernetes 使用了 云原生(cloud-native)的视角来看待系统,并且可以持续应对变化。您的集群在运行的过程中,任何时候都有可能发生突发事件,而控制器则自动地修正这些问题。这就意味着,本质上,您的集群永远不会达到一个稳定不变的状态。

    • 通过控制器监控集群状态并利用负反馈原理不断接近目标状态的系统,相较于那种完成安装后就不再改变的系统,是一种更高级的系统形态,尤其是在您将运行一个大规模的复杂集群的情况下。


控制器模式
描述:在K8S中每个控制器至少追踪一种类型的资源,在资源对象中有一个 spec 字段代表了目标状态,资源对象对应的控制器负责不断地将当前状态调整到目标状态。

理论上控制器可以自己直接执行调整动作,实际上控制器发送消息到 API Server 而不是直接自己执行调整动作。

  • (1) API-Server 控制

Kubernetes 自带的控制器都是通过与集群中 API Server 交互来达到调整状态的目的,以 Kubernetes 中自带的一个控制器 Job Controller 为例;

Job 是一种 Kubernetes API 对象,一个 Job 将运行一个(或多个)Pod,执行一项任务,然后停止。当新的 Job 对象被创建时,Job Controller 将确保集群中有合适数量的节点上的 kubelet 启动了指定个数的 Pod,以完成 Job 的执行任务。Job Controller 自己并不执行任何 Pod 或容器,而是发消息给 API Server,由其他的控制组件配合 API Server,以执行创建或删除 Pod 的实际动作。

当新的 Job 对象被创建时,目标状态是指定的任务被执行完成。Job Controller 调整集群的当前状态以达到目标状态:创建 Pod 以执行 Job 中指定的任务, 控制器同样也会更新其关注的 API 对象。

例如:一旦 Job 的任务执行结束,Job Controller 将更新 Job 的 API 对象,将其标注为 Finished。(这有点儿像是恒温器将指示灯关闭,以表示房间里的温度已经到达指定温度。)

  • (2) 直接控制
    描述:某些特殊的控制器需要对集群外部的东西做调整,Kubernetes中真的提供了一个控制器可以水平伸缩集群中的节点。

例如:您想用一个控制器确保集群中有足够的节点,此时控制器需要调用云供应商的接口以创建新的节点或移除旧的节点。这类控制器将从 API Server 中读取关于目标状态的信息,并直接调用外部接口以实现调整目标。


4.集群内部通信

描述:我们知道 Kubernetes集群和Master节点(实际上是API Server)之间的通信路径()

Master-Node 之间的通信可以分为如下两类:

  • (1) Cluster to Master:所有从集群访问 Master 节点的通信,都是针对 apiserver 的(没有任何其他 master 组件发布远程调用接口),得益于下面这些措施,从集群(节点以及节点上运行的 Pod)访问 master 的连接是安全的,因此,可以通过不受信的网络或公网连接 Kubernetes 集群
    • API Server监听的HTTPS端口是您在安装k8s的时候进行设置的,并配置了一种或多种客户端认证方式 authentication;注意至少需要配置一种形式的 授权方式 authorization ,尤其是 匿名访问 anonymous requests 或 Service Account Tokens 被启用的情况下;
    • 节点上必须配置集群(apiserver)的公钥根证书(public root certificate),此时,在提供有效的客户端身份认证的情况下,节点可以安全地访问 APIServer;
    • 对于需要调用 APIServer 接口的 Pod,应该为其关联 Service Account,此时,Kubernetes将在创建Pod时自动为其注入公钥根证书(public root certificate)以及一个有效的 bearer token(放在HTTP请求头Authorization字段)。所有名称空间中,都默认配置了名为 kubernetes Kubernetes Service,该 Service对应一个虚拟 IP(默认为 10.96.0.1),发送到该地址的请求将由 kube-proxy 转发到 apiserver 的 HTTPS 端口上
  • (2) Master to Cluster: 存在着两条主要的通信路径前者是apiserver 访问集群中每个节点上的 kubelet 进程,后者是使用 apiserver 的 proxy 功能,从 apiserver 访问集群中的任意节点、Pod、Service;
    • apiserver 会访问 kubelet 情况如下抓取 Pod 的日志时,通过 kubectl exec -it 指令(或 kuboard 的终端界面)获得容器的命令行终端时,提供 kubectl port-forward 功能时,连接访问端点是 kubelet 的 HTTPS 端口,但是默认情况下apiserver 不校验 kubelet 的 HTTPS 证书,此时链接可能会收到 man-in-the-middle 攻击,如果在不受信网络或者公网上运行时是不安全的;如果要校验 kubelet 的 HTTPS 证书,可以通过 --kubelet-certificate-authority 参数为 apiserver 提供校验 kubelet 证书的根证书。如果不能完成这个配置,又需要通过不受信网络或公网将节点加入集群,则需要使用 SSH隧道 连接 apiserver 和 kubelet。同时,Kubelet authentication/authorization需要激活,以保护 kubelet AP
    • apiserver 访问 nodes, pods, services 的连接使用的是 HTTP 连接,没有进行身份认证也没有进行加密传输,此时可以通过增加 https 作为 节点/Pod/Service 请求 URL 的前缀,但是 HTTPS 证书并不会被校验,也无需客户端身份认证,因此该连接是无法保证一致性的
    • Kubernetes 支持 SSH隧道(tunnel)来保护 Master –> Cluster 访问路径(对于公网加入集群需要通信的情况下),SSH隧道当前已被不推荐使用(deprecated),Kubernetes 正在设计新的替代通信方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 高可用区出现故障时节点控制器驱逐Pod,将检查高可用区里故障节点的百分比(`NodeReady Condition 的值为 Unknown 或 False`);
# - 如果故障节点的比例不低于 `--unhealthy-zone-threshold(默认为 0.55)` 则降低驱逐 Pod 的速率;
# - 如果集群规模较小(少于等于 `--large-cluster-size-threshold` 个节点,默认值为 50),则停止驱逐 Pod;
# - 如果集群规模大于 `--large-cluster-size-threshold` 个节点,则驱逐 Pod 的速率降低到 `--secondary-node-eviction-rate` (默认值为 0.01)每秒;

# 针对每个高可用区使用这个策略的原因是,某一个高可用区可能与 master 隔开了,而其他高可用区仍然保持连接。如果您的集群并未分布在云供应商的多个高可用区上,此时,您只有一个高可用区(即整个集群)。

# 将集群的节点分布到多个高可用区最大的原因是,在某个高可用区出现整体故障时,可以将工作负载迁移到仍然健康的高可用区。因此,如果某个高可用区的所有节点都出现故障时,节点控制器仍然使用正常的驱逐 Pod 的速率(--node-eviction-rate)。

# 最极端的情况是,所有的高可用区都完全不可用(例如,集群中一个健康的节点都没有),此时节点控制器 master 节点的网络连接出现故障,并停止所有的驱逐 Pod 的动作,直到某些连接得到恢复。







```bash
{"level":"warn","ts":"2020-03-23T11:10:55.271+0800","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"passthrough:///https://192.168.2.176:2379","attempt":0,"error"
:"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
vim kubeadm-config.yaml
apiServer:
certSANs:
- k8s-master-01
- k8s-master-02
- k8s-master-03
- master.k8s.io
- 192.168.9.80
- 192.168.9.81
- 192.168.9.82
- 192.168.9.83
- 127.0.0.1
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta1
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "master.k8s.io:16443"
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.16.3
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.1.0.0/16
scheduler: {}

`