基于kubeadm快速部署kubernetes K8S V1.17.4集群-无坑完整版

image

基于kubeadm快速部署kubernetes K8S V1.17.4集群,并部署Dashboard Web页面,实现可视化查看Kubernetes资源

主机配置规划

服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟)
k8s-master CentOS7.7 2C/4G/20G 172.16.1.110 10.0.0.110
k8s-node01 CentOS7.7 2C/4G/20G 172.16.1.111 10.0.0.111
k8s-node02 CentOS7.7 2C/4G/20G 172.16.1.112 10.0.0.112

注意:没有swap分区

预定完成目标项

1、在所有节点上安装Docker和kubeadm

2、部署Kubernetes Master

3、部署容器网络插件

4、部署 Kubernetes Worker,并将节点加入Kubernetes集群中

5、部署Dashboard Web页面,可视化查看Kubernetes资源

关于二进制安装

kubeadm 是 Kubernetes 官方支持的安装方式,“二进制” 不是。本文档采用 kubernetes.io 官方推荐的 kubeadm 工具安装 kubernetes 集群。

架构图

image

安装docker、安装kubeadm,kubelet和kubectl

注意:所有机器都要安装

脚本如下:

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
[root@k8s-master k8s_install]# pwd
/root/k8s_install
# 脚本信息如下【支持多次执行】
[root@k8s-master k8s_install]# cat install_kubelet.sh
#!/bin/sh

##### 在 master 节点和 worker 节点都要执行 【所有机器执行】

# 加载环境变量
. /etc/profile
. /etc/bashrc

###############################################
# 添加主机名与IP对应关系(每台主机必须设置主机名)
# 如下命令:没有则添加信息 若使用请根据自身主机情况修改 ★★★★★ 「你需要修改处」
grep '172.16.1.110.*k8s-master' /etc/hosts || echo "172.16.1.110 k8s-master" >> /etc/hosts
grep '172.16.1.111.*k8s-node01' /etc/hosts || echo "172.16.1.111 k8s-node01" >> /etc/hosts
grep '172.16.1.112.*k8s-node02' /etc/hosts || echo "172.16.1.112 k8s-node02" >> /etc/hosts


###############################################
# 必要的基础配置或包安装
## 必须安装 nfs-utils 才能挂载 nfs 网络存储
yum install -y nfs-utils
## wget 用于下载文件
yum install -y wget
## 其他必要包
yum install -y conntrack ipvsadm ipset


# 关闭 防火墙
systemctl stop firewalld
systemctl disable firewalld
systemctl stop iptables
systemctl disable iptables

# 关闭 SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 关闭 swap , 本次涉及的机器没有swap,因此注释了
## 如果有swap分区则放开注释
#swapoff -a
#yes | cp /etc/fstab /etc/fstab_bak
#cat /etc/fstab_bak | grep -v swap > /etc/fstab

# 时间设置
## 时区设置:东八区,上海
ls -l /etc/localtime | grep 'Asia/Shanghai' || (rm -f /etc/localtime && ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime)
## 时间同步定时任务:没有则添加定,进行时间同步
crontab -l | grep 'ntpdate' || echo -e "# time sync\n*/10 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1" >> /var/spool/cron/root
## 查看硬件时间 hwclock --show
## 系统时间同步到硬件时间
hwclock --systohc

# 关闭邮件服务
systemctl stop postfix.service && systemctl disable postfix.service



###############################################
# 修改 /etc/sysctl.conf
# 开启 ip_forward 转发并解决流量路由不正确问题
# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward = 1#g" /etc/sysctl.conf
sed -i "s#^net.ipv4.tcp_tw_recycle.*#net.ipv4.tcp_tw_recycle = 0#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables = 1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables = 1#g" /etc/sysctl.conf
# IPv6 转发
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding = 1#g" /etc/sysctl.conf
sed -i "s#^net.netfilter.nf_conntrack_max.*#net.netfilter.nf_conntrack_max = 2310720#g" /etc/sysctl.conf
## 如下两条非必要
sed -i "s#^fs.file-max.*#fs.file-max = 52706963#g" /etc/sysctl.conf
sed -i "s#^fs.nr_open.*#fs.nr_open = 52706963#g" /etc/sysctl.conf

# 如果没有,追加
grep 'net.ipv4.ip_forward = 1' /etc/sysctl.conf || echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
grep 'net.ipv4.tcp_tw_recycle = 0' /etc/sysctl.conf || echo "net.ipv4.tcp_tw_recycle = 0" >> /etc/sysctl.conf
grep 'net.bridge.bridge-nf-call-ip6tables = 1' /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
grep 'net.bridge.bridge-nf-call-iptables = 1' /etc/sysctl.conf || echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
grep 'net.ipv6.conf.all.forwarding = 1' /etc/sysctl.conf || echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
grep 'net.netfilter.nf_conntrack_max = 2310720' /etc/sysctl.conf || echo "net.netfilter.nf_conntrack_max = 2310720" >> /etc/sysctl.conf
grep 'fs.file-max = 52706963' /etc/sysctl.conf || echo "fs.file-max = 52706963" >> /etc/sysctl.conf
grep 'fs.nr_open = 52706963' /etc/sysctl.conf || echo "fs.nr_open = 52706963" >> /etc/sysctl.conf

# 执行命令以生效
sysctl -p
#### 说明:上面的命令中/etc/sysctl.conf可以用/etc/sysctl.d/k8s.conf替换;生效使用sysctl -p /etc/sysctl.d/k8s.conf 命令


###############################################
# kube-proxy 开启ipvs的前置条件【本步骤可忽略,但推荐使用IPVS】
modprobe br_netfilter

cat > /etc/sysconfig/modules/ipvs.modules << EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF

chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4



###############################################
# 安装 docker
## 参考文档如下
# https://www.cnblogs.com/zhanglianghhh/p/9891293.html
# https://docs.docker.com/install/linux/docker-ce/centos/
# https://docs.docker.com/install/linux/linux-postinstall/

## 卸载旧版本 根据需要放开注释
#yum remove -y docker \
#docker-client \
#docker-client-latest \
#docker-common \
#docker-latest \
#docker-latest-logrotate \
#docker-logrotate \
#docker-selinux \
#docker-engine-selinux \
#docker-engine

## 设置 docker yum repository
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

## 安装docker
# yum install -y docker-ce
yum install -y docker-ce-19.03.8

## 启动docker服务,这样可以创建/etc/docker目录
systemctl start docker

## 配置daemon
## 1、修改docker Cgroup Driver为systemd;2、日志格式设定
## 如果不修改,在添加 worker 节点时可能会碰到如下错误
## [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
## Please follow the guide at https://kubernetes.io/docs/setup/cri/
cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF

## 开机自启动
systemctl stop docker && systemctl daemon-reload && systemctl enable docker && systemctl start docker



###############################################
# 配置K8S的yum源
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
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


# 卸载旧版本 根据需要放开注释
#yum remove -y kubelet kubeadm kubectl

# 由于版本更新频繁,这里指定版本号部署
## 安装kubelet、kubeadm、kubectl
## 将 ${1} 替换为 kubernetes 版本号,例如 1.17.4
## yum install -y kubelet-${1} kubeadm-${1} kubectl-${1}
yum install -y kubelet-1.17.4 kubeadm-1.17.4 kubectl-1.17.4


# 重启 docker,并启动 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet


# 打印分割线
echo "====================="

# 打印docker版本信息
docker version

执行上述脚本

kubelet 服务错误说明

用kubeadm的方法安装kubelet后,运行systemctl status kubelet 和 journalctl -f -u kubelet 发现kubelet服务启动失败,错误代码255。

image

后来查了资料,运行journalctl -xefu kubelet 命令查看systemd日志才发现,真正的错误是:

1
failed to load Kubelet config file /var/lib/kubelet/config.yaml, error failed to read kubelet config file "/var/lib/kubelet/config.yaml", error: open /var/lib/kubelet/config.yaml: no such file or directory

image

原因:

关键文件缺失,多发生于没有做 kubeadm init就运行了systemctl start kubelet。

暂时可以有不管,后面 kubeadm init 后会恢复正常。

部署Kubernetes Master与安装Pod网络插件(CNI)

注意:仅在master节点操作

kubeadm init 配置详解的官网地址如下:

1
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/

这里使用 flannel 网络

master节点所需镜像

kubernetes 服务启动依赖很多镜像,这些镜像要是在国内没有(fan qiang)的话,是下载不下来的。这里我们可以去阿里云容器镜像服务【别人放好的镜像】搜寻并下载指定版本的镜像替代。

image

image

下载完成后,通过 docker tag … 命令修改成指定名称的镜像即可。

需要哪些镜像及版本

需要哪些镜像及版本,查看方式如下:

1
2
3
4
5
6
7
8
9
10
[root@k8s-master ~]# kubeadm config images list --kubernetes-version v1.17.4
W0728 16:31:09.770937 8119 validation.go:28] Cannot validate kube-proxy config - no validator is available
W0728 16:31:09.770998 8119 validation.go:28] Cannot validate kubelet config - no validator is available
k8s.gcr.io/kube-apiserver:v1.17.4
k8s.gcr.io/kube-controller-manager:v1.17.4
k8s.gcr.io/kube-scheduler:v1.17.4
k8s.gcr.io/kube-proxy:v1.17.4
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.5

获取初始化默认配置文件并修改

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
[root@k8s-master k8s_install]# pwd
/root/k8s_install
[root@k8s-master k8s_install]# kubeadm config print init-defaults > kubeadm-config.yaml
# 做了适当修改
[root@k8s-master k8s_install]# cat kubeadm-config.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:
# 改为本机内网IP
advertiseAddress: 172.16.1.110
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: k8s-master
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
# 本次部署的版本为 v1.17.4
kubernetesVersion: v1.17.4
networking:
dnsDomain: cluster.local
# 添加如下行,指定pod网络的IP地址范围,因为flannel 就是这个网段
podSubnet: 10.244.0.0/16
# 默认值即可,无需改变。服务VIP使用可选的IP地址范围。默认10.96.0.0/12
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
# 添加如下配置段,调度方式从默认改为ipvs方式【如果上面初始化没有做ipvs,那么这段就不需要】
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs

kubeadm init与flannel网络安装

创建 init_master.sh文件并编写脚本进行批量下载镜像;之后修改镜像tag,与google的k8s镜像名称一致;再之后初始化并安装Pod网络插件。

脚本如下:

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
[root@k8s-master k8s_install]# pwd
/root/k8s_install
[root@k8s-master k8s_install]# cat init_master.sh
#!/bin/bash

##### 在 k8s master 节点执行

# 加载环境变量
. /etc/profile
. /etc/bashrc


###############################################
# 从国内下载 master 节点所需镜像,并对镜像重命名
# src_registry="registry.aliyuncs.com/google_containers"
src_registry="registry.cn-beijing.aliyuncs.com/google_registry"

# 定义镜像集合数组
# 具体版本信息根据 kubeadm config images list --kubernetes-version v1.17.4 得到的
images=(
kube-apiserver:v1.17.4
kube-controller-manager:v1.17.4
kube-scheduler:v1.17.4
kube-proxy:v1.17.4
pause:3.1
etcd:3.4.3-0
coredns:1.6.5
)
# 循环从国内获取的Docker镜像
for img in ${images[@]};
do
# 从国内源下载镜像
docker pull ${src_registry}/$img
# 改变镜像名称
docker tag ${src_registry}/$img k8s.gcr.io/$img
# 删除源始镜像
docker rmi ${src_registry}/$img
# 打印分割线
echo "======== $img download OK ========"
done
echo "********** k8s master docker images pull OK! **********"


###############################################
# kubeadm 初始化
##### 初始化方式1
# 这个初始化过程需要几分钟,具体时间取决于你的网络。
# --apiserver-advertise-address=x.x.x.x 本机内网地址 ★★★★★ 「你需要修改处」
# --service-cidr=x.x.x.x 为服务VIP使用可选的IP地址范围。默认10.96.0.0/12
# --pod-network-cidr=x.x.x.x 指定pod网络的IP地址范围。
#kubeadm init \
# --apiserver-advertise-address=172.16.1.110 \
# --kubernetes-version v1.17.4 \
# --service-cidr=10.96.0.0/12 \
# --pod-network-cidr=10.244.0.0/16

##### 初始化方式2 【推荐方式】
# --upload-certs 自动颁发证书,高可用有意义,单机可选
# kubeadm-config.yaml文件,通过上文已得到该文件
kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
echo "********** kubeadm init OK! **********"


# 配置 kubectl
mkdir -p $HOME/.kube/
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
echo "********** kubectl config OK! **********"


###############################################
# Kubernetes CNI扁平化网络:Flannel、Calico、Canal和Weave
# https://blog.csdn.net/RancherLabs/article/details/88885539
# 安装 kube-flannel 网络
# 若能够访问到quay.io这个registery,可以注释掉下面3行docker命令。 在 kube-flannel.yml 文件中可得到 flannel 版本信息
# 如果不能访问 quay.io这个registery,那么请使用下面3行
docker pull ${src_registry}/flannel:v0.12.0-amd64
docker tag ${src_registry}/flannel:v0.12.0-amd64 quay.io/coreos/flannel:v0.12.0-amd64
docker rmi ${src_registry}/flannel:v0.12.0-amd64
# 如果下载失败,那么可通过 https://github.com/coreos/flannel/blob/v0.12.0/Documentation/kube-flannel.yml 页面拷贝到本地
wget https://raw.githubusercontent.com/coreos/flannel/v0.12.0/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
echo "********** kube-flannel network OK! **********"


###############################################
# master节点验证所有pod状态
echo "********** kubectl get pods --all-namespaces -o wide **********"
# kubectl get pods -A -o wide # 与下面的命令等效
kubectl get pods --all-namespaces -o wide

# master节点查看node状态
echo "********** kubectl get nodes **********"
kubectl get nodes

echo "********** 获得 join 命令参数 **********"
kubeadm token create --print-join-command

执行上述脚本

部分命令说明:

查看所有pods运行信息

1
2
kubectl get pods --all-namespaces  # 或者kubectl get pods -A
kubectl get pods --all-namespaces -o wide

查看所有node节点信息,其中master也是一个节点

1
2
kubectl get nodes
kubectl get nodes -o wide

获得 join命令参数,复制后在其他node节点执行,执行后加入该master节点,形成一个集群

1
kubeadm token create --print-join-command

flannel扁平化网络查看

通过ifconfig命令,可见已经存在了扁平化网络。

image

扁平化网络说明:

Kubernetes 的网络模型假定了所有Pod都在一个可以直接连通的扁平化的网络空间中,这在GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes 假定这个网络已经存在。而在私有云里搭建 Kubernetes 集群,就不能假定这个网络已经存在。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后运行 Kubernetes。

同一个Pod内的多个容器之间通讯:lo

各Pod之间的通讯:Overlay Network

Pod与Service之间的通讯:各节点的Iptables规则或者ipvs

Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务。简单来说,它的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟IP地址。而且它还能在这些IP地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动的传递到目标容器内。

flannel网络如下图:

image

部署Kubernetes Node并加入Kubernetes集群

备注:仅在worker节点执行

获得 join命令初始化worker节点并加入master

在master执行如下命令获取join参数。

1
2
[root@k8s-master ~]# kubeadm token create --print-join-command
kubeadm join 172.16.1.110:6443 --token jb8qa8.wbjx2k7t8vuvqf4q --discovery-token-ca-cert-hash sha256:a694fbe124afd00c0024d4be102037d8f84c9e2e1da1c6638b7788ad71f556ef

有效时间,该 token 的有效时间为 2 个小时,2小时内可以使用此 token 初始化任意数量的 worker 节点。

本文根据规划在k8s-node01、k8s-node02机器上执行。

执行完毕后,在master机器查看节点信息:

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
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 47m v1.17.4
k8s-node01 NotReady <none> 30s v1.17.4
k8s-node02 NotReady <none> 25s v1.17.4
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready master 48m v1.17.4 172.16.1.110 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
k8s-node01 NotReady <none> 56s v1.17.4 172.16.1.111 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
k8s-node02 NotReady <none> 51s v1.17.4 172.16.1.112 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
# 因为此时在k8s-node01、k8s-node02没有flannel镜像,因此pod未启动
[root@k8s-master ~]# kubectl get pods -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-6955765f44-c9zfh 1/1 Running 0 48m 10.244.0.2 k8s-master <none> <none>
kube-system coredns-6955765f44-lrz5q 1/1 Running 0 48m 10.244.0.3 k8s-master <none> <none>
kube-system etcd-k8s-master 1/1 Running 0 48m 172.16.1.110 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 0 48m 172.16.1.110 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 0 48m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-dngrk 1/1 Running 0 46m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-h4sn6 0/1 Init:0/1 0 76s 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-flannel-ds-amd64-m92wp 0/1 Init:0/1 0 71s 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-proxy-28dwj 0/1 ContainerCreating 0 76s 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-proxy-c875m 1/1 Running 0 48m 172.16.1.110 k8s-master <none> <none>
kube-system kube-proxy-stg6w 0/1 ContainerCreating 0 71s 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 0 48m 172.16.1.110 k8s-master <none> <none>

说明:k8s-node01、k8s-node02状态为NotReady

获取worker节点镜像

备注:仅在worker节点执行

创建 init_worker.sh文件并编写脚本批量下载镜像;之后修改镜像tag,与google的k8s镜像名称一致;再之后下载Pod网络插件。

脚本如下:

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
[root@k8s-node01 k8s_install]# pwd
/root/k8s_install
[root@k8s-node01 k8s_install]# cat init_worker.sh
#!/bin/bash

##### 在 k8s worker 节点执行

# 加载环境变量
. /etc/profile
. /etc/bashrc


###############################################
# 从国内下载 node 节点所需镜像,并对镜像重命名
# src_registry="registry.aliyuncs.com/google_containers"
src_registry="registry.cn-beijing.aliyuncs.com/google_registry"
# 定义镜像集合数组
# 具体版本信息根据 kubeadm config images list --kubernetes-version v1.17.4 得到的
images=(
kube-apiserver:v1.17.4
kube-controller-manager:v1.17.4
kube-scheduler:v1.17.4
kube-proxy:v1.17.4
pause:3.1
etcd:3.4.3-0
coredns:1.6.5
)
# 循环从国内获取的Docker镜像
for img in ${images[@]};
do
# 从国内源下载镜像
docker pull ${src_registry}/$img
# 改变镜像名称
docker tag ${src_registry}/$img k8s.gcr.io/$img
# 删除源始镜像
docker rmi ${src_registry}/$img
# 打印分割线
echo "======== $img download OK ========"
done
echo "********** k8s node docker images pull OK! **********"



###############################################
# Kubernetes CNI网络:Flannel、Calico、Canal和Weave
# https://blog.csdn.net/RancherLabs/article/details/88885539
# 确保能够访问到quay.io这个registery。
#docker pull quay.io/coreos/flannel:v0.12.0-amd64
# 如果不能访问 quay.io这个registery,那么请使用下面3行。或从master那边将 flannel 镜像打包过来即可
docker pull ${src_registry}/flannel:v0.12.0-amd64
docker tag ${src_registry}/flannel:v0.12.0-amd64 quay.io/coreos/flannel:v0.12.0-amd64
docker rmi ${src_registry}/flannel:v0.12.0-amd64
echo "********** flannel image OK! **********"

本文根据规划在k8s-node01、k8s-node02机器上执行。

work执行完毕后在master机器查看信息

执行完毕后,在master机器查看节点信息:

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
# 所有节点都是Ready状态了
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 56m v1.17.4
k8s-node01 Ready <none> 9m35s v1.17.4
k8s-node02 Ready <none> 9m30s v1.17.4
[root@k8s-master ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready master 57m v1.17.4 172.16.1.110 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
k8s-node01 Ready <none> 9m47s v1.17.4 172.16.1.111 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
k8s-node02 Ready <none> 9m42s v1.17.4 172.16.1.112 <none> CentOS Linux 7 (Core) 3.10.0-1062.el7.x86_64 docker://19.3.8
[root@k8s-master ~]# kubectl get pods -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-6955765f44-c9zfh 1/1 Running 0 57m 10.244.0.2 k8s-master <none> <none>
kube-system coredns-6955765f44-lrz5q 1/1 Running 0 57m 10.244.0.3 k8s-master <none> <none>
kube-system etcd-k8s-master 1/1 Running 0 57m 172.16.1.110 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 0 57m 172.16.1.110 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 0 57m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-dngrk 1/1 Running 0 55m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-h4sn6 1/1 Running 0 10m 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-flannel-ds-amd64-m92wp 1/1 Running 0 9m57s 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-proxy-28dwj 1/1 Running 0 10m 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-proxy-c875m 1/1 Running 0 57m 172.16.1.110 k8s-master <none> <none>
kube-system kube-proxy-stg6w 1/1 Running 0 9m57s 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 0 57m 172.16.1.110 k8s-master <none> <none>

说明:k8s-node01、k8s-node02状态为Ready,且所有pod都正常运行

移除worker节点

正常情况下,无需移除 worker 节点,如果添加到集群出错,可以移除 worker 节点,再重新尝试添加。

比如:移除k8s-node01节点,步骤如下:

在准备移除的 worker 节点上执行

1
2
# 只在 worker 节点执行
[root@k8s-node01 ~]# kubeadm reset

在 master 节点上执行

1
2
3
# 只在 master 执行
[root@k8s-master ~]# kubectl delete node k8s-node01
node "k8s-node01" deleted

集群版本查看

执行如下命令即可

1
2
3
[root@k8s-master ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.4", GitCommit:"8d8aa39598534325ad77120c120a22b3a990b5ea", GitTreeState:"clean", BuildDate:"2020-03-12T21:03:42Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.4", GitCommit:"8d8aa39598534325ad77120c120a22b3a990b5ea", GitTreeState:"clean", BuildDate:"2020-03-12T20:55:23Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"linux/amd64"}

到这来,整个集群已经部署完毕,可以欢呼了!

部署 Dashboard

本次部署版本版本:v2.0.0-rc6。不能部署v1.10.0版本,因为该版本过低不匹配。

Dashboard 的GitHub地址:

1
https://github.com/kubernetes/dashboard/

版本选择

image

下载dashboard镜像

镜像下载脚本,在所有节点执行,因为dashboard会根据调度部署在任意节点。

脚本如下:

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
[root@k8s-master k8s_install]# pwd
/root/k8s_install
[root@k8s-master k8s_install]# cat install_dashboard.sh
#!/bin/sh

##### 在 master 节点和 worker 节点都要执行 【所有机器执行】

# 加载环境变量
. /etc/profile
. /etc/bashrc

###############################################
# 从国内下载 k8s dashboard 所需镜像,并对镜像重命名
src_registry="registry.cn-beijing.aliyuncs.com/google_registry"
# 定义镜像集合数组
# V1.17.x 版本对应的 dashboard 不能使用 dashboard:v1.10.1 该版本低,不匹配
images=(
dashboard:v2.0.0-rc6
metrics-scraper:v1.0.3
)
# 循环从国内获取的Docker镜像
for img in ${images[@]};
do
# 从国内源下载镜像
docker pull ${src_registry}/$img
# 改变镜像名称
docker tag ${src_registry}/$img kubernetesui/$img
# 删除源始镜像
docker rmi ${src_registry}/$img
# 打印分割线
echo "======== $img download OK ========"
done
echo "********** k8s dashboard docker images OK! **********"

部署 Dashboard

在k8s-master上操作

获取dashboard的recommended.yaml

1
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml

修改recommended.yaml配置,如下:

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
[root@k8s-master k8s_install]# pwd
/root/k8s_install
[root@k8s-master k8s_install]# vim recommended.yaml
………………
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
# 添加处
type: NodePort
ports:
- port: 443
targetPort: 8443
# 添加处
nodePort: 30001
selector:
k8s-app: kubernetes-dashboard
………………
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.0.0-rc6
# 修改处 从 Always 改为了 IfNotPresent
#imagePullPolicy: Always
imagePullPolicy: IfNotPresent
………………
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.3
# 添加如下行
imagePullPolicy: IfNotPresent

启动dashboard

1
kubectl apply -f recommended.yaml

查看dashboard运行情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@k8s-master ~]# kubectl get pods -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-6955765f44-kdcj7 1/1 Running 1 3h6m 10.244.0.5 k8s-master <none> <none>
kube-system coredns-6955765f44-v9pzk 1/1 Running 1 3h6m 10.244.0.4 k8s-master <none> <none>
kube-system etcd-k8s-master 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-9nzhv 1/1 Running 1 167m 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-flannel-ds-amd64-cft6f 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kube-system kube-flannel-ds-amd64-sm7d7 1/1 Running 1 167m 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-proxy-dprqm 1/1 Running 1 167m 172.16.1.112 k8s-node02 <none> <none>
kube-system kube-proxy-k9l5r 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kube-system kube-proxy-mdfsl 1/1 Running 1 167m 172.16.1.111 k8s-node01 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 1 3h6m 172.16.1.110 k8s-master <none> <none>
kubernetes-dashboard dashboard-metrics-scraper-7b8b58dc8b-hr7lf 1/1 Running 0 93s 10.244.2.2 k8s-node02 <none> <none>
kubernetes-dashboard kubernetes-dashboard-755dcb9575-9c5h8 1/1 Running 0 93s 10.244.3.2 k8s-node01 <none> <none>
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get pods -n kubernetes-dashboard -o wide # -n 指定namespace
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dashboard-metrics-scraper-7b8b58dc8b-hr7lf 1/1 Running 0 2m50s 10.244.2.2 k8s-node02 <none> <none>
kubernetes-dashboard-755dcb9575-9c5h8 1/1 Running 0 2m50s 10.244.3.2 k8s-node01 <none> <none>

查看services服务信息

1
2
3
4
5
6
7
8
9
10
11
12
13
# 或则使用 kubectl get svc -A
[root@k8s-master ~]# kubectl get services --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h19m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 3h19m
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.104.251.180 <none> 8000/TCP 4m55s
kubernetes-dashboard kubernetes-dashboard NodePort 10.111.61.235 <none> 443:30001/TCP 4m55s
[root@k8s-master ~]#
# 或则使用 kubectl get svc -n kubernetes-dashboard
[root@k8s-master ~]# kubectl get services --namespace=kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.104.251.180 <none> 8000/TCP 5m13s
kubernetes-dashboard NodePort 10.111.61.235 <none> 443:30001/TCP 5m13s

浏览器访问

根据规划,访问如下地址:

1
https://172.16.1.110:30001/

如果谷歌浏览器不能打开,参见如下博文:解决Google浏览器不能打开kubernetes dashboard方法【转】

1
https://blog.csdn.net/weixin_30535043/article/details/102395724

也可以使用火狐浏览器打开,浏览器添加例外后,访问得到如下页面:

image

使用令牌登录(需要创建能够访问 Dashboard 的用户)

创建service account并绑定默认cluster-admin管理员集群角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@k8s-master k8s_install]# pwd
/root/k8s_install
[root@k8s-master k8s_install]# cat account.yaml
# Create Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
---
# Create ClusterRoleBinding
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: kube-system
[root@k8s-master k8s_install]# kubectl apply -f account.yaml # 执行 yaml 文件

查看绑定信息

1
2
3
4
5
6
7
8
9
[root@k8s-master k8s_install]# kubectl get clusterrolebinding
NAME AGE
admin-user 58s
cluster-admin 5h47m
flannel 5h45m
kubeadm:kubelet-bootstrap 5h47m
kubeadm:node-autoapprove-bootstrap 5h47m
kubeadm:node-autoapprove-certificate-rotation 5h47m
………………

获取tocken

1
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

image

将得到的token信息用于访问,结果如下:【可能需要等几分钟页面才能刷出来】

image

完毕!


<-------------the end------------->
lightzhang wechat
欢迎扫一扫,订阅我的微信公众号!
坚持原创分享,你的支持就是我最大的动力!