kubeadm

kubeadm 提供了kubeadm initkubeadm join ,可以快速创建 k8s 集群

kubeadm 通过执行必要的操作来启动和运行最小可用集群。按照设计,它只关注启动引导,而非配置机器

我们希望在 kubeadm 之上构建更高级别以及更加合规的工具,理想情况下,使用 kubeadm 作为所有部署工作的基准将会更加易于创建一致性集群

安装各种 “锦上添花” 的扩展,例如 Kubernetes Dashboard、监控方案、以及特定云平台的扩展,都不在讨论范围内

安装 kubeadm

https://developer.aliyun.com/mirror/kubernetes?spm=a2c6h.13651102.0.0.3e221b11Qo8aZk

kubeadm

1
kubeadm [command] [flags]

command:

1
2
3
4
5
6
7
8
9
10
11
alpha           # kubeadm 处于测试阶段的命令,尽量不要用,`kubeadm alpha --help`查看有哪些命令
certs # 处理kubernetes证书
completion # bash 命令补全,需要安装 bash-completion
config # 管理 kubeadm 集群的配置,该配置保留在集群的 ConfigMap 中
help # Help about any command
init # 设置一个Kubernetes控制平面
join # 将节点加入到k8s集群
reset # 还原使用`kubeadm init`或者`kubeadm join`对系统产生的环境变化
token # 管理 token
upgrade # 升级 k8s 版本
version # 查看版本信息

flags:

1
2
3
4
5
6
7
8
9
--add-dir-header # 如果为true,则将文件目录添加到日志消息的头部
-h, --help
--log-file string # 如果非空,则使用此日志文件
--log-file-max-size uint # 定义日志文件可以增长到的最大大小。单位是字节。当该值为0时,表示不限制文件的最大大小。1800(默认)
--one-output # 如果为真,则只将日志写入其本机的严重级别(vs也写入每个较低的严重级别)
--rootfs string # 到“真实的”主机根文件系统的路径。
--skip-headers # 如果为true,则避免在日志消息中使用头前缀
--skip-log-headers # 如果为true,在打开日志文件时避免头文件
-v, --v Level # 日志级别详细程度的编号

kubeadm completion

让 kubeadm 命令支持自动补全,只支持 bash 和 zsh 两种环境。
kubeadm completion bash 打印的脚本加载到环境变量即可:

1
2
3
4
5
6
7
yum install bash-completion -y
touch /etc/profile.d/kubeadm_completion.sh
kubeadm completion bash > /etc/profile.d/kubeadm_completion.sh
exit # 重新登录终端

[root@master01 ~]$kubeadm # tab键就会出现命令提示
alpha certs completion config help init join reset token upgrade version

kubeadm init

此命令初始化一个 Kubernetes 控制平面节点

参考:https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init

kubeadm init 执行流程:

  1. 检查系统状态,有的检查只报错,有的检查会退出流程
  2. 生成自签名 CA(可用使用用户提供的现有 CA)为集群中的每个组件设置身份,默认存放在 /etc/kubernetes/kpi
  3. 在 /etc/kubernetes/ 中为 kubelet、controller-manger 和 scheduler 编写配置文件,让它们可以连接 API Server,每个文件都需要有自己的标识。同时还需要为管理用途编写文件 admin.conf
  4. alpha 相关,略…
  5. 为 API Server、controller-manager 和 scheduler 生成静态的 manifest 文件。如果没有提供外部 etcd,也会为 etcd 生成一个额外的 Pod manifest 文件。
    静态 Pod 的 manifest 文件将会写入 /etc/kubernetes/manifest,kubelet 监控这个目录,在启动时判断是否生成 Pod。
    一旦控制平面 Pod 启动并运行,kubeadm init 将会继续运行
  6. alpha 相关,略…
  7. 将标签和 taint 应用到 master 节点,这样就不会有额外的工作负载运行在该节点上
  8. 生成 token 以让额外的 node 能够将它们自己注册到这个 master,默认有效期 24 小时
  9. 创建所有必需的配置让 node 能够通过 Bootstrap Token 和 TLS Bootstrap 机制来加入集群
    1. 编写一个 ConfigMap 来提供加入集群所需的所有信息,并设置相关的 RBAC 访问规则
    2. 让 Bootstrap Token 能够访问 CSR 鉴权 API
    3. 为所有新的 CSR 请求配置 auto-approval
  10. 安装内部的 DNS 服务(默认 CoreDNS),通过 Api Server 安装 kube-proxy 插件组件
    请注意:就算部署了 DNS 服务,在安装 CNI 之前它也不会被调度到 node 上
  11. alpha 相关,略…
1
2
kubeadm init [command]
kubeadm init [flags]

command:

1
phase # 使用此命令调用init工作流的单个阶段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kubeadm init phase [command]
# command:
addon # Install required addons for passing Conformance tests
bootstrap-token # Generates bootstrap tokens used to join a node to a cluster
certs # Certificate generation
control-plane # 生成建立控制平面所需的所有静态pod清单文件
etcd # Generate static Pod manifest file for local etcd
kubeconfig # 生成建立控制平面所需的所有kubeconfig文件和管理kubeconfig文件
kubelet-finalize # Updates settings relevant to the kubelet after TLS bootstrap
kubelet-start # Write kubelet settings and (re)start the kubelet
mark-control-plane # Mark a node as a control-plane
preflight # Run pre-flight checks
upload-certs # Upload certificates to kubeadm-certs
upload-config # Upload the kubeadm and kubelet configuration to a ConfigMap

# 每个命令都可以使用--help查询帮助,例如:`kubeadm init phase addon --help`

flags:标星的是需要指定的,其他没有标星的一般情况下使用默认值即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
★ --apiserver-advertise-address string # K8S API Server 将要监听的监听的 IP 地址,设置为master的IP,默认自动探测
★ --apiserver-bind-port int32 # API Server 绑定的端口,默认为 6443
--apiserver-cert-extra-sans strings # 可选的证书额外信息,用于指定 API Server 的服务器证书。可以是 IP 地址也可以是 DNS 名称
--cert-dir string # 证书的存储路径,缺省路径为 /etc/kubernetes/pki
--certificate-key string # 定义一个用于加密 kubeadm-certs Secret 中的控制平台证书的密钥
--config string # kubeadm 配置文件的路径
★ --control-plane-endpoint string # 为控制平面指定一个稳定的 IP 地址或 DNS 名称,即配置一个可以长期使用且是高可用的 VIP 或者域名,k8s 多 master 高可用基于此参数实现
--cri-socket string # 要连接的 CRI(容器运行时接口:Container Runtime Interface)套接字的路径。如果为空,则 kubeadm 将尝试自动检测此值;仅当安装了多个 CRI 或具有非标准 CRI 插槽时,才使用此选项
--dry-run # 不要应用任何更改;只是输出将要执行的操作,其实就是测试运行
--experimental-patches string # 用于存储 kustomize 为静态 pod 清单所提供的补丁的路径
--feature-gates string # 一组用来描述各种功能特性的键值(key=value)对。选项是:IPv6DualStack=true|false (ALPHA - default=false)
--ignore-preflight-errors strings # 可以忽略检查过程 中出现的错误信息,比如忽略 swap,如果为 all 就忽略所有
★ --image-repository string # 设置用于拉取控制平面镜像的容器仓库,默认为 k8s.gcr.io
★ --kubernetes-version string # 为控制平面选择一个特定的 Kubernetes 版本,默认为 stable-1
--node-name string # 指定master节点的名称,默认使用hostname
★ --pod-network-cidr string # 设置 pod ip 地址范围, control plane 会自动将 网络发布到其他节点的node,让其上启动的容器使用此网络,flannel插件的默认值是 10.244.0.0/16
★ --service-cidr string # 指定service 的IP 范围. (default "10.96.0.0/12")
--service-dns-domain string # 指定 service 的 dns 后缀, e.g. "myorg.internal". (default "cluster.local")
--skip-certificate-key- # 不打印 control-plane 用于加密证书的key.
--skip-phases strings # 跳过指定的阶段(phase)
--skip-token-print # 不打印 kubeadm init 生成的 default bootstrap token
--token string # 指定 node 和control plane 之间,简历双向认证的token ,格式为 [a-z0-9]{6}\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef
--token-ttl duration # token 自动删除的时间间隔。 (e.g. 1s, 2m, 3h). 如果设置为 '0', token 永不过期 (default 24h0m0s)
--upload-certs # 上传 control-plane 证书到 kubeadm-certs Secret

k8s 中有三个网段:node、service、pod,这三个网段千万不要冲突,否则通信会出现问题

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 多控制平面(多个master节点)
# 多个master通过HAProxy配置的负载均衡,再通过keepalived配置HAProxy的高可用,假设VIP为 10.0.0.1/24
kubeadm init --apiserver-advertise-address=10.0.0.71 \
--control-plane-endpoint=10.0.0.1 \
--apiserver-bind-port=6443 \
--kubernetes-version=v1.20.2 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.10.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers

# 单控制平面(一个master节点)
# 对于单控制平面,controller-plane-endpoint默认同apiserver-advertise-address
kubeadm init --apiserver-advertise-address=10.0.0.71 \
--apiserver-bind-port=6443 \
--kubernetes-version=v1.20.2 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.10.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers

kubeadm join

此命令用来初始化 Kubernetes 节点并将其加入集群

在执行完 kubeadm init 后,会在终端打印以后加入此集群时需要执行的kubeadm join 命令

参考:https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-join/

当节点加入 kubeadm 初始化的集群时,我们需要建立双向信任。 这个过程可以分解为发现TLS 引导两部分。

通常两个部分会使用相同的令牌。 在这种情况下可以使用 –token 参数,而不是单独指定每个令牌。

1
2
kubeadm join [api-server-endpoint] [flags]
kubeadm join [command]

command:

1
phase # 使用此命令可以调用连接工作流的单个阶段

api-server-endpoint:控制平面的 IP,如果是单控制平面,就是 master 节点的 IP,如果是多控制平面,就是 VIP

flags:

1

kubeadm alpha

kubeadm 处于测试阶段的命令,尽量不要用,kubeadm alpha --help 查看有哪些命令,v1.20.2 版本中只有一个:kubeconfig

kubeadm certs

1
kubeadm certs [command]

command:

1
2
3
4
certificate-key  # 生成证书密钥
check-expiration # 检查Kubernetes集群的证书过期情况
generate-csr # 生成密钥和证书签名请求
renew # 为Kubernetes集群更新证书
1
2
3
4
5
kubeadm certs check-expiration [flags]
# flags:
--cert-dir string
--config string
--kubeconfig string
1
2
3
4
5
kubeadm certs generate-csr [flags]
# flags:
--cert-dir string
--config string
--kubeconfig-dir string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubeadm certs renew [command]
# command:
admin.conf # 更新嵌入在kubeconfig文件中的证书,供管理员和kubeadm本身使用
all # 续期所有可用证书
apiserver # 更新服务Kubernetes API的证书
apiserver-etcd-client # 更新apiserver访问etcd时使用的证书
apiserver-kubelet-client # 更新证书以便API服务器连接到kubelet
controller-manager.conf # 更新嵌入在kubeconfig文件中的证书,以便控制器管理器使用
etcd-healthcheck-client # 将活动探测的证书更新到healthcheck etcd
etcd-peer # 为etcd节点之间的通信更新证书
etcd-server # 续证供etcd使用
front-proxy-client # 更新前端代理客户端证书
scheduler.conf # 更新kubeconfig文件中嵌入的证书,以便调度器管理器使用

# 每个命令都可以使用 --help 查询帮助,例如:`kubeadm certs renew admin.conf --help`

kubeadm config

kubeadm init 执行期间,kubeadm 将 ClusterConfiguration 对象上传到你的集群的 kube-system 名字空间下 名为 kubeadm-config 的 ConfigMap 对象中。 然后在 kubeadm joinkubeadm resetkubeadm upgrade 执行期间读取此配置。 要查看此 ConfigMap,请调用 kubectl get cm -o yaml -n kube-system kubeadm-config

你可以使用 kubeadm config print 命令打印默认配置, 并使用 kubeadm config migrate 命令将旧版本的配置转化成新版本。 kubeadm config images listkubeadm config images pull 命令可以用来列出并拉取 kubeadm 所需的镜像。

1
2
kubeadm config [command]
kubeadm config [flags]

command:

1
2
3
images # 与kubeadm使用的容器镜像交互
migrate # 将本地旧版本的配置对象转换为最新支持的版本,而无需变更集群中的任何内容
print # 打印对象
1
2
3
4
kubeadm config images [command] [flags]
# command:
list # 打印 kubeadm 要使用的镜像列表。配置文件用于自定义任何镜像或镜像存储库。
pull # 拉取 kubeadm 使用的镜像
1
2
3
4
5
6
7
8
kubeadm config images list [flags]
# flags
--allow-missing-template-keys
--config string
-o, --experimental-output string
--feature-gates string
--image-repository string
--kubernetes-version string
1
2
3
4
5
6
7
kubeadm config images pull [flags]
# flags
--config string # kubeadm 配置文件的路径
--cri-socket string
--feature-gates string
--image-repository string
--kubernetes-version string
1
2
3
4
kubeadm config migrate [flags]
# flags:
--new-config string # 使用新的 API 版本生成的 kubeadm 配置文件的路径。默认输出到stdout。
--old-config string # 使用旧 API 版本且应转换的 kubeadm 配置文件的路径。此参数是必需的
1
2
3
4
kubeadm config print [command]
# command:
init-defaults # 打印默认的初始化配置,可以用于`kubeadm init`
join-defaults # 打印默认连接配置,可以用于`kubeadm join`
1
2
3
4
kubeadm config print init-defaults [flags]
kubeadm config print join-defaults [flags]
# flags
--component-configs strings

flags:

1
--kubeconfig string  # 与集群通信时要使用的kubeconfig文件。(默认/etc/kubernetes/admin.conf)

kubeadm reset

kubeadm reset 负责从使用 kubeadm initkubeadm join 命令创建的文件中清除节点本地文件系统。对于控制平面节点,reset 还从 etcd 集群中删除该节点的本地 etcd 堆成员,还从 kubeadm ClusterStatus 对象中删除该节点的信息。 ClusterStatus 是一个 kubeadm 管理的 Kubernetes API 对象,该对象包含 kube-apiserver 端点列表。

kubeadm reset phase 可用于执行上述工作流程的各个阶段。 要跳过阶段列表,你可以使用 –skip-phases 参数,该参数的工作方式类似于 kubeadm joinkubeadm init 阶段运行器

“reset” 执行以下阶段:

1
2
3
4
preflight              Run reset pre-flight checks
update-cluster-status Remove this node from the ClusterStatus object.
remove-etcd-member Remove a local etcd member.
cleanup-node Run cleanup node.
1
2
kubeadm reset [command]
kubeadm reset [flags]

command:

1
phase # 调用重置工作流的单个阶段
1
2
3
4
5
6
kubeadm reset phase [command]
# command
cleanup-node # Run cleanup node.
preflight # Run reset pre-flight checks
remove-etcd-member # Remove a local etcd member.
update-cluster-status # Remove this node from the ClusterStatus object.

flags:

1
2
3
4
5
6
--cert-dir string # 存储证书的目录路径。需要清空此目录。默认"/etc/kubernetes/pki"
--cri-socket string # 要连接的 CRI 套接字的路径。如果为空,则 kubeadm 将尝试自动检测此值;仅当安装了多个CRI 或具有非标准 CRI 插槽时,才使用此选项
-f, --force # 在不提示确认的情况下重置节点
--ignore-preflight-errors strings # 忽略检查过程中出现的错误信息,比如swap,如果为all就忽略所有
--kubeconfig string # 与集群通信时使用的 kubeconfig 文件,默认 /etc/kubernetes/admin.conf
--skip-phases strings # 要跳过的阶段列表,四个阶段

注意:如果使用了外部 etcd,kubeadm reset 将不会删除任何 etcd 中的数据

kubeadm token

用于管理 kubeadm join 使用的令牌

使用 kubeadm init 默认生成的 token 有效期 24 小时

1
2
3
4
5
6
7
8
9
10
# 生成新 token
$kubeadm token create --print-join-command
kubeadm join 10.0.0.171:6443 --token mud4vy.ygs3zdmuz6rwggrt --discovery-token-ca-cert-hash sha256:83da17177796380c6038dd8a76bc7050fd9c3c6b55d53a7f7a652817cc73c8e6
# 查看目前有效的token
$kubeadm token list
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
mud4vy.ygs3zdmuz6rwggrt 23h 2021-01-23T23:46:03+08:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
# 查看 hash
$openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
83da17177796380c6038dd8a76bc7050fd9c3c6b55d53a7f7a652817cc73c8e6

kubeadm upgrade

用于升级 Kubernetes 集群到新版本

kubeadm version

用于打印 kubeadm 的版本信息

kubeadm help

部署 k8s 集群

部署规划图

学习环境,简单部署,准备三台主机,都是 centos7

角色 主机名 ip 地址
master1 master01.ljk.cn 10.0.0.71/24
node1 node01.ljk.cn 10.0.0.72/24
node2 node02.ljk.cn 10.0.0.73/24

安装 docker

注意:kubernetes 对 docker 的版本有要求,最新版本的 docker 一般来讲都不兼容

经过测试:kubernetes v1.20.2 最高支持 docker v19.03

在三台主机上均执行以下步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
yum list docker-ce.x86_64 --showduplicates | sort -r # 搜索可用版本
yum install -y docker-ce-19.03.9 # 安装指定版本
# 加速 和 优化
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://3417nt4m.mirror.aliyuncs.com"],
"exec-opts":["native.cgroupdriver=systemd"]
}
EOF
systemctl enable --now docker.service

安装 Kubernetes

在三台主机上均执行以下步骤:

1
2
3
4
5
6
7
8
9
10
11
12
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable --now kubelet

部署 dns,或者直接修改/etc/hosts

在三台主机上均执行以下步骤:

1
2
3
4
5
# cat /etc/hosts
...
10.0.0.71 master01.ljk.cn
10.0.0.72 node01.ljk.cn
10.0.0.73 node02.ljk.cn

kubeadm init 初始化

集群初始化,而且集群初始化只需要初始化一次

注意:kubeadm init 必须在 master 节点上运行,任意一 master 节点即可

1
2
3
4
# 提前下载组件镜像,这一步可以不用执行,init的时候会自动下载,但是下载时间一般很长,最好还是提前下载
kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers --kubernetes-version=v1.20.2
# 预检查一下,出现问题则修复
[root@master01 docker]$kubeadm init phase preflight

初始化,两种方式:

1
2
3
4
5
6
7
8
# 方式一
[root@master01 ~]$kubeadm init --apiserver-advertise-address=10.0.0.71 \
--apiserver-bind-port=6443 \
--kubernetes-version=v1.20.2 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.10.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--ignore-preflight-errors=NumCPU # 学习环境,忽略cpu数量的检查
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
# 方式二
[root@master01 ~]$kubeadm config print init-defaults > /etc/kubernetes/kubeadmin-init.yaml
# 修改advertiseAddress、imageRepository、kubernetesVersion、dnsDomain、serviceSubnet
[root@master01 ~]$cat /etc/kubernetes/kubeadmin-init.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 10.0.0.71
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: master01.ljk.cn
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
#controlPlaneEndpoint: 10.0.0.1:6443 #多控制平面开启此项,基于 VIP 的 Endpoint
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.20.2
networking:
dnsDomain: ljk.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.10.0.0/16
scheduler: {}

[root@master01 docker]$kubeadm init --config=/etc/kubernetes/kubeadmin-init.yaml --ignore-preflight-errors=NumCPU # 忽略检查cpu核心数,生产环境不要忽略
...
...
...
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.0.0.71:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:b794ecc7f2fc825b58e4e2108eab0dfa603c3d861de55bcc8c437949bed83fec

# 按照init成功后的提示
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 如果是root用户,也可以
export KUBECONFIG=/etc/kubernetes/admin.conf

# 安装网络插件 flannel,参考:https://github.com/coreos/flannel
# 这个链接可能需要科学上网
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

补充:如果是多控制平面,kubeadm init 需要添加 –control-plane-endpoint 参数,设置访问多个 master 的 VIP,通常是 keepalived+HAProxy 配置多个 master 的高可用

1
2
3
4
5
6
7
8
[root@master01 ~]$kubeadm init --apiserver-advertise-address=10.0.0.71 \
--control-plane-endpoint=10.0.0.1 \
--apiserver-bind-port=6443 \
--kubernetes-version=v1.20.2 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.10.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--ignore-preflight-errors=NumCPU

kubeadm join node 加入 k8s 集群

加入集群的 kubeadm join 命令在 kubeadm init 完成后会自动打印出来,如果将来 token 和 hash 过期失效了,使用 kubeadm token create --print-join-command 重新生成即可

1
2
3
4
5
6
7
8
# node1
[root@node01 kubernetes]$kubeadm join 10.0.0.71:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:b794ecc7f2fc825b58e4e2108eab0dfa603c3d861de55bcc8c437949bed83fec
# node2
[root@node02 ~]$kubeadm join 10.0.0.71:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:b794ecc7f2fc825b58e4e2108eab0dfa603c3d861de55bcc8c437949bed83fec

查看是否加入成功:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master01 ~]$kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01.ljk.cn Ready control-plane,master 53m v1.20.2
node01.ljk.cn Ready <none> 6m24s v1.20.2
node02.ljk.cn Ready <none> 10m v1.20.2

# 在每个节点上都生成一个flannel网卡,或者说是网络隧道,保障集群内部的通信
[root@master01 ~]$ip a # master
...
4: flannel.1: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN group default
link/ether 26:69:fd:2f:7a:3f brd ff:ff:ff:ff:ff:ff
[root@node01 kubernetes]$ip a # node1
...
4: flannel.1: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN group default
link/ether a2:74:d6:61:d5:5c brd ff:ff:ff:ff:ff:ff
[root@node02 ~]$ip a # node2
...
4: flannel.1: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN group default
link/ether fe:83:2b:fc:1e:01 brd ff:ff:ff:ff:ff:ff

部署 Web 服务 Dashboard

github 地址:https://github.com/kubernetes/dashboard/releases

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
# 1.下载配置清单
$wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.1.0/aio/deploy/recommended.yaml
# 2.修改配置清单
$vim recommended.yaml
...
spec:
type: NodePort # 添加此行
ports:
- port: 443
targetPort: 8443
nodePort: 30002 # 添加此行
selector:
k8s-app: kubernetes-dashboard
...
# 3.创建资源对象
kubectl apply -f ./recommended.yaml
# 4.查看
$kubectl get pod -n kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-79c5968bdc-5dv7w 1/1 Running 0 88m
kubernetes-dashboard-7448ffc97b-rg77t 1/1 Running 0 88m
# 5.创建管理 dashboard 的 service 账号
$cat admin-user.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
$kubectl apply -f admin-user.yml
# 6.查看 admin-user 的 token
$kubectl get secrets -A | grep admin-user
$kubectl describe secrets -n kubernetes-dashboard admin-user-token-wpz7j
Name: admin-user-token-wpz7j
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: admin-user
kubernetes.io/service-account.uid: 613c9277-f124-4622-88c9-714dc2479602

Type: kubernetes.io/service-account-token

Data
====
ca.crt: 1066 bytes
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjJ2THVKYzd4Q3hVeVI5QWVCMk5YUU5kbE9lRzJjZ1hHZkV0WndQUGczWmcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXdwejdqIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2MTNjOTI3Ny1mMTI0LTQ2MjItODhjOS03MTRkYzI0Nzk2MDIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.N7Hcf9JIgV5p_j8-YYJHMDrqGkGtsalTxbabTjXASyoR63gmvNmekPACQ9EDwu1MF2du3wkyReVb_aYD11tHw4XsNbfnoaytYqcQ9U8lhLXd8A7wlBnK8_EBa5-XP0-nRRSw7gUsG6s7xvrviWcndNO0nIUPgS--B1G8S-AR_Y0CJRzFF4FL0zhZvxCxSDwHO2OrjKpbxhuZOgzhOI_CXCEMghsCyUUFeNlRj2F-YulzVNLdJSzIh0UMyvoKVv6ylesRtyUJK8lo3tpcC0K4hTKsWYXHgibto024tT4D1KtYLqNhEhI4PkYogZQTsG3-ggVo5Nry5m8AL0CKCD0xoA

最后,打开浏览器,输入 https://10.0.0.171:30002/,除了10.0.0.171,10.0.0.71 和 10.0.0.72 也可以,然后 copy 刚才生产的 admin-user 用户的 token,成功登陆

k8s 集群升级

小版本升级,一般不会有很大更改,经过充分测试,直接升级即可

大版本升级,风险较大,可以像小版本一样,经过测试,然后直接升级;但是更推荐以下升级方式:

  1. 在备用的服务器上再部署一套 k8s 集群,使用最新的 k8s 版本

  2. 把业务离线导入新的 k8s 集群

  3. 经过测试后,切换负载均衡到新的 k8s 集群

  4. 下线的旧 k8s 集群,直接重装系统,安装最新的 ubuntu 或者 centos,然后作为 node 加入到新的 k8s 集群

  5. 升级完成

这种方法是比较稳妥的,只是成本比较高,需要有充足的备用的服务器,如果目前的 k8s 集群使用 30 台服务器,那备用的服务器差不多也得 20 台

升级 master

先升级 kubeadm,kubeadm 是 k8s 升级的“准升证”

  1. 验证当 k8s 前版本

    1
    $kubeadm version
  2. 各 master 安装指定新版本 kubeadm

    1
    2
    3
    4
    $apt-cache madison kubeadm #查看 k8s 版本列表
    $apt-get install kubeadm=1.17.4-00 #安装新版本 kubeadm
    $kubeadm version #验证 kubeadm 版本
    $apt install kubelet=1.17.4-00 kubectl=1.17.4-00 # kubectl 和 kubelet 也升级一下
  3. kubeadm 升级命令使用帮助

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $kubeadm upgrade --help
    Upgrade your cluster smoothly to a newer version with this command

    Usage:
    kubeadm upgrade [flags]
    kubeadm upgrade [command]

    Available Commands:
    apply Upgrade your Kubernetes cluster to the specified version
    diff Show what differences would be applied to existing static pod manifests. See also: kubeadm upgrade apply --dry-run
    node Upgrade commands for a node in the cluster
    plan Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter
  4. 升级计划

    1
    kubeadm upgrade plan #查看升级计划

  5. 开始升级

    1
    2
    3
    $kubeadm upgrade apply v1.17.4 #master1
    $kubeadm upgrade apply v1.17.4 #master2
    $kubeadm upgrade apply v1.17.4 #master3

  6. 验证镜像

    1
    $docker image ls

升级 node

升级客户端服务 kubectl kubelet

  1. 验证当前 node 版本信息

    1
    $kubectl get node
  2. 升级各 node 节点配置文件

    1
    $kubeadm upgrade node --kubelet-version v1.17.4  # master上执行
  3. 各 Node 节点升级 kubelet、kubeadm、kubectl 二进制包

    1
    $apt install kubelet=1.17.4-00 kubeadm=1.17.4-00 kubectl=1.17.4-00

测试运行 Nginx+Tomcat