Kubernetes(一)----使用二进制文件部署kubernetes1.18集群(超详细安装文档)
前言:
本篇博客列出的所有命令均是博主亲自实践,
所列举的问题也是博主在实际安装中碰到的.
大家遇到什么问题或者疑问可以在评论区指出,
我会持续更正博客文档~
希望大家在安装学习k8s的时候少走弯路
文章目录
- 4.1 生成kube-apiserver证书
- 4.2 从Github下载二进制文件
- 4.3 解压二进制包
- 4.4 部署kube-apiserver
- 4.5 部署kube-controller-manager
- 4.6 部署kube-scheduler
- 5.1 创建工作目录并拷贝二进制文件
- 5.2 部署kubelet
- 5.3 批准kubelet证书申请并加入集群
- 5.4 部署kube-proxy
- 5.5 部署CNI网络
- 5.6 授权apiserver访问kubelet
- 5.7 新增加Worker Node
- 7.1 etcd集群报错:member 39e6630289bd896d has already been bootstrapped
- 7.2 启动docker报错:unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid chara
- 7.3 kube-apiserver启动失败:Failed to start Kubernetes API Server
- 7.4 kube-controller-manager启动失败: Failed to start Kubernetes Controller Manager
- 7.5 kubectl get node命令报错No resources found in default namespace
- 7.6 kube-proxy启动失败 Failed to start Kubernetes Proxy
- 7.7 cni网络部署异常,报错: network plugin is not ready: cni config uninitialized
- 7.8 使用docker pull镜像报错:Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority
一. 部署准备
1.1 部署Kubernetes集群的两种方式
目前生产部署Kubernetes集群主要有两种方式:
kubeadm
Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
Kubeadm官方链接
二进制包
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。
如果想更容易可控,推荐使用二进
制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
本文采用二进制包方式来部署Kubernetes1.18集群(单Master)
下图为单Master架构图
1.2 安装要求
部署Kubernetes集群机器需要满足以下几个条件:
| 条件 | 指标 |
|---|---|
| 机器要求 | 单节点1,单Master集群3,高可用集群5+ |
| 操作系统 | CentOS7.x-86_x64(其它版本可能与本文档不兼容) |
| 内存(单主机或虚拟机) | 2GB+ |
| CPU | 2+ |
| 硬盘 | 30G+ |
| swap分区 | 禁止 |
| 系统语言 | 英文(使用中文可能会遇到各种莫名其妙的问题) |
# 附:查看linux系统内核版本命令
cat /etc/redhat-release # 查看centos系统的版本
uname -a # 查看centos内核版本信息
1.3 集群规划
软件环境:
| 软件 | 版本 |
|---|---|
| 操作系统 | 版本 |
| Docker | 19-ce |
| Kubernetes | 1.18 |
服务器整体规划:
| 主机名 | ip | 安装组件 |
|---|---|---|
| k8s-master | 192.168.226.144 | kube-apiserver,kube-controller-manager,kube-scheduler,etcd |
| k8s-node1 | 192.168.226.145 | kubelet,kube-proxy,docker, etcd |
| k8s-node2 | 192.168.226.146 | kubelet,kube-proxy,docker,etcd |
1.4 操作系统必要配置初始化
1.4.1 根据规划设置主机名
# 修改/etc/hosts文件(所有主机执行)
vi /etc/hosts
# 添加如下内容
192.168.226.144 k8s-master
192.168.226.145 k8s-node1
192.168.226.146 k8s-node2
# 设置主机名(每台主机分别执行)
hostnamectl set-hostname k8s-master # 主节点执行
hostnamectl set-hostname k8s-node1 # node1节点执行
hostnamectl set-hostname k8s-node2 # node2节点执行
1.4.2 关闭防火墙
# 关闭 firewalld 防火墙(允许 master 和 node 的网络通信)
systemctl stop firewalld
systemctl disable firewalld
systemctl status firewalld

1.4.3 关闭selinux
# 关闭 SElinux 安全模组(让容器可以读取主机的文件系统),所有节点执行
setenforce 0
sed -i.bak`date +%F` 's|SELINUX=.*|SELINUX=disabled|g' /etc/selinux/config
1.4.4 关闭swap
# 关闭 Swap 交换分区(启用了 Swap,则 Qos 策略可能会失效)(所有服务器都执行)
swapoff -a && sed -i.bak "s/\/dev\/mapper\/centos-swap/\#\/dev\/mapper\/centos-swap/g" /etc/fstab
1.4.5 将桥接的IPv4流量传递到iptables的链
# 所有节点执行
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system # 生效
1.4.6 时钟同步
# 时间同步(所有节点执行)
yum install ntpdate -y
ntpdate time.windows.com
二、Etcd集群部署
Etcd 是一个分布式键值存储系统,Kubernetes使用Etcd进行数据存储,所以先准备一个Etcd数据库.
为解决Etcd单点故障,应采用集群方式部署,这里使用3台组建集群,可容忍1台机器故障
| 节点名称 | IP |
|---|---|
| etcd-1 | 192.168.226.144 |
| etcd-2 | 192.168.226.145 |
| etcd-3 | 192.168.226.146 |
注:为了节省机器,这里与K8s节点机器复用。也可以独立于k8s集群之外部署,只要apiserver能连接到就行。
2.1 准备cfssl证书生成工具
cfssl是一个开源的证书管理工具,使用json文件生成证书,相比openssl更方便使用。
找任意一台服务器操作,这里用Master节点
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 --no-check-certificate
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 --no-check-certificate
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 --no-check-certificate
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
# 附: wget命令安装方式(所有机器执行)
yum install -y wget
2.2 生成Etcd证书
2.2.1 自签证书颁发机构(CA)
# 创建工作目录
mkdir -p ~/TLS/{etcd,k8s}
cd ~/TLS/etcd
自签CA:
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"www": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json << EOF
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
生成证书:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
ls *pem

2.2.2 使用自签CA签发Etcd HTTPS证书
创建证书申请文件:
cat > server-csr.json << EOF
{
"CN": "etcd",
"hosts": [
"192.168.226.144",
"192.168.226.145",
"192.168.226.146"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
注:上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。
生成证书:
2.3 从Github下载二进制文件
etcd-v3.4.9-linux-amd64.tar.gz文件github下载链接:
2.4 部署Etcd集群
以下在etcd-1(master)上操作,为简化操作,待会将节点1生成的所有文件拷贝到节点2和节点3
2.4.1 创建工作目录并解压二进制包
mkdir /opt/etcd/{bin,cfg,ssl} -p
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
mv etcd-v3.4.9-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/
2.4.2 创建etcd配置文件
# 注意:这里的主机地址需要根据自己的实际情况进行配置
cat > /opt/etcd/cfg/etcd.conf << EOF
#[Member]
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.226.144:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.226.144:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.226.144:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.226.144:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.226.144:2380,etcd-2=https://192.168.226.145:2380,etcd-3=https://192.168.226.146:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
配置解读:
ETCD_NAME:节点名称,集群中唯一
ETCD_DATA_DIR:数据目录
ETCD_LISTEN_PEER_URLS:集群通信监听地址
ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址
ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址
ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址
ETCD_INITIAL_CLUSTER:集群节点地址
ETCD_INITIAL_CLUSTER_TOKEN:集群Token
ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new是新集群,existing表示加入已有集
群
2.4.3 systemd管理etcd
cat > /usr/lib/systemd/system/etcd.service << EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd.conf
ExecStart=/opt/etcd/bin/etcd \
--cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--peer-cert-file=/opt/etcd/ssl/server.pem \
--peer-key-file=/opt/etcd/ssl/server-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \
--logger=zap
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
2.4.4 拷贝刚才生成的证书
# 把刚才生成的证书拷贝到配置文件中的路径:
cp ~/TLS/etcd/ca*pem ~/TLS/etcd/server*pem /opt/etcd/ssl/
2.4.5 启动并设置开机启动
systemctl daemon-reload
systemctl start etcd #注意: 这里如果单节点首次启动的话,需要等待比较长的时间,最后状态是失败.这是正常情况(可以想象3个节点的Zookeeper集群,如果只有一个节点启动,集群也是不可用的)
systemctl enable etcd

2.4.6 将上面节点1所有生成的文件拷贝到节点2和节点3
# 拷贝到节点二
scp -r /opt/etcd root@192.168.226.145:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.226.145:/usr/lib/systemd/system/
# 拷贝到节点3
scp -r /opt/etcd root@192.168.226.146:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.226.146:/usr/lib/systemd/system/
# 附: 如果这里嫌弃scp命令拷贝时需要输入密码麻烦,可配置ssh服务(所有节点执行)
ssh-keygen -t rsa # 连续按三次回车
ssh-copy-id k8s-master
ssh-copy-id k8s-node1
ssh-copy-id k8s-node2
在节点2和节点3分别修改etcd.conf配置文件中的节点名称和当前服务器IP:
vi /opt/etcd/cfg/etcd.conf
# 修改ETCD_NAME以及其它配置项里面涉及到的机器ip
# 节点二配置
#[Member]
ETCD_NAME="etcd-2"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.226.145:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.226.145:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.226.145:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.226.145:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.226.144:2380,etcd-2=https://192.168.226.145:2380,etcd-3=https://192.168.226.146:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
# 节点三配置
#[Member]
ETCD_NAME="etcd-3"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.226.146:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.226.146:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.226.146:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.226.146:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.226.144:2380,etcd-2=https://192.168.226.145:2380,etcd-3=https://192.168.226.146:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
配置文件配置完成后,启动etcd并设置开机启动
systemctl daemon-reload
systemctl start etcd
systemctl enable etcd
2.4.7 查看集群状态
# 查看集群状态
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.226.144:2379,\
https://192.168.226.145:2379,\
https://192.168.226.146:2379" endpoint health
# 查看集群节点列表
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.226.144:2379,\
https://192.168.226.145:2379,\
https://192.168.226.146:2379" member list --write-out=table
集群节点列表:
如果集群的状态或者节点列表信息异常,请查看日志,可以采用如下命令查看具体报错信息
systemctl status etcd.service # 查看节点etcd状态
journalctl -u etcd
journalctl -xe
三、安装Docker
以下在所有节点操作。这里采用二进制安装,用yum安装也一样。
3.1 解压二进制包
# 以下命令在docker二进制包存放目录下执行
tar zxvf docker-19.03.9.tgz
mv docker/* /usr/bin
3.2 systemd管理docker
cat > /usr/lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
3.3 创建配置文件
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
}
EOF
# 注意开始我在上述文件中配置了:"registry-mirrors":["https://b9pmyelo.mirror.aliyuncs.com"],但是遇到了docker启动失败的情况,所以把上述配置去掉了,只保留一个空的json串
# registry-mirrors 阿里云镜像加速器
3.4 启动并设置开机启动
systemctl daemon-reload
systemctl start docker
systemctl enable docker
启动之后:使用systemctl status docker.service命令查看docker运行状态
出现如下内容证明安装配置成功
否则,使用journalctl -xe查看具体的报错信息,并根据报错提示解决问题
四、部署Master Node
4.1 生成kube-apiserver证书
4.1.1 自签证书颁发机构(CA)
cd ~/TLS/k8s/
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
生成证书:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
ls *pem
如图:证明证书生成成功
注意: 如果执行:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca - #执行命令
#报错如下:
invalid character '?' looking for beginning of object key string
Failed to parse input: unexpected end of JSON input
# 此报错说明json的语法有问题,通常肉眼比较难发现,建议复制粘贴,不要手打
4.1.2 使用自签CA签发kube-apiserver HTTPS证书
cd ~/TLS/k8s/
# 创建证书申请文件
cat > server-csr.json << EOF
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",
"127.0.0.1",
"192.168.226.144",
"192.168.226.145",
"192.168.226.146",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
注:上述文件hosts字段中IP为所有Master/LB/VIP IP,一个都不能少!为了方便后期扩容可以写几个预留的IP
#生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server
ls server*pem # 列出生成的证书
如下,证明证书生成成功:
4.2 从Github下载二进制文件kubernetes-server-linux-amd64.tar
kubernetes-server-linux-amd64.tar下载链接
注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和Worker Node二进制文件
4.3 解压二进制包
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
tar zxvf kubernetes-server-linux-amd64.tar.gz #该命令需要在压缩包所在的目录下执行,否则需要使用全路径
cd kubernetes/server/bin
cp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin
cp kubectl /usr/bin/
4.4 部署kube-apiserver
4.4.1 创建配置文件
vi /opt/kubernetes/cfg/kube-apiserver.conf
KUBE_APISERVER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--etcd-servers=https://192.168.226.144:2379,https://192.168.226.145:2379,https://192.168.226.146:2379 \
--bind-address=192.168.226.144 \
--secure-port=6443 \
--advertise-address=192.168.226.144 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/24 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth=true \
--token-auth-file=/opt/kubernetes/cfg/token.csv \
--service-node-port-range=30000-32767 \
--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \
--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \
--tls-cert-file=/opt/kubernetes/ssl/server.pem \
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
注:上面两个\ \ 第一个是转义符,第二个是换行符,使用转义符是为了使用EOF保留换行符。
# 参数说明
--logtostderr:启用日志
---v:日志等级
--log-dir:日志目录
--etcd-servers:etcd集群地址
--bind-address:监听地址
--secure-port:https安全端口
--advertise-address:集群通告地址
--allow-privileged:启用授权
--service-cluster-ip-range:Service虚拟IP地址段
--enable-admission-plugins:准入控制模块
--authorization-mode:认证授权,启用RBAC授权和节点自管理
--enable-bootstrap-token-auth:启用TLS bootstrap机制
--token-auth-file:bootstrap token文件
--service-node-port-range:Service nodeport类型默认分配端口范围
--kubelet-client-xxx:apiserver访问kubelet客户端证书
--tls-xxx-file:apiserver https证书
--etcd-xxxfile:连接Etcd集群证书
--audit-log-xxx:审计日志
4.4.2 拷贝刚才生成的证书
把刚才生成的证书拷贝到配置文件中的路径:
cp ~/TLS/k8s/ca*pem ~/TLS/k8s/server*pem /opt/kubernetes/ssl/
4.4.3 启用 TLS Bootstrapping 机制
TLS Bootstraping: Master apiserver启用TLS认证后,Node节点kubelet和kube-proxy要与kube-
apiserver进行通信,必须使用CA签发的有效证书才可以.
当Node节点很多时,这种客户端证书颁发需
要大量工作,同样也会增加集群扩展复杂度。
为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书.
kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由
apiserver动态签署。
所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是
由我们统一颁发一个证书。
TLS bootstraping 工作流程:

# 首先生成自己的token
head -c 16 /dev/urandom | od -An -t x | tr -d ' '
# 创建上述配置文件中token文件
a85cbca976935a7abc872d46d5a0a39e,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
# 格式:token,用户名,UID,用户组
# 我的token使用的是自己生成的,这部分可自行生成替换
4.4.4 systemd管理apiserver
cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
4.4.5 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
注意:这里启动的时候可能会失败! 并且失败了不会给出提示,所以我们要确认kube-apiserver是否启动成功
使用如下命令:
systemctl status kube-apiserver.service
出现如下提示才说明启动成功
否则:
# 使用如下命令查看启动错误日志,并根据日志提示采取相应解决方案
cat /var/log/messages|grep kube-apiserver|grep -i error
4.4.6 授权kubelet-bootstrap用户允许请求证书
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap

4.5 部署kube-controller-manager
4.5.1 创建配置文件
cat > /opt/kubernetes/cfg/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--master=127.0.0.1:8080 \\
--bind-address=127.0.0.1 \\
--allocate-node-cidrs=true \\
--cluster-cidr=10.244.0.0/16 \\
--service-cluster-ip-range=10.0.0.0/24 \\
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--experimental-cluster-signing-duration=87600h0m0s"
EOF
参数说明:
--master:通过本地非安全本地端口8080连接apiserver。
--leader-elect:当该组件启动多个时,自动选举(HA)
--cluster-signing-cert-file/--cluster-signing-key-file:自动为kubelet颁发证书的CA,与apiserver
保持一致
4.5.2 systemd管理controller-manager
cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
4.5.3 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
启动之后.使用如下命令查看状态:
systemctl status kube-controller-manager.service
出现如下内容才说明启动成功!
否则,根据该命令的报错提示去排查解决问题,解决之后重新启动即可
4.6 部署kube-scheduler
4.6.1 创建配置文件
cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect \\
--master=127.0.0.1:8080 \\
--bind-address=127.0.0.1"
EOF
# 配置说明
--master:通过本地非安全本地端口8080连接apiserver。
--leader-elect:当该组件启动多个时,自动选举(HA)
4.6.2 systemd管理scheduler
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
4.6.3 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler
# 查看服务运行状态:
systemctl status kube-scheduler.service
如下提示,证明启动成功!
4.6.4 查看集群状态
通过kubectl工具查看当前集群组件状态:
kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}

五、部署Worker Node
下面的操作如果没有特别强调,还是在Master Node上
即它同时作为Worker Node
5.1 创建工作目录并拷贝二进制文件
在所有worker node创建工作目录:(资源所限,我们将master也视作workernode)
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs} # master节点已经有这些目录,剩下的节点创建这几个目录
# 以下命令在master节点上执行!!
cd kubernetes/server/bin # 注意,这是一个相对路径,因为每个人配置时所在的路径可能不一样
#这个命令的执行位置和kubernetes-server-linux-amd64.tar.gz文件的上传路径是同一个路径,如果忘记了,可以去4.3部分查看追溯
cp kubelet kube-proxy /opt/kubernetes/bin
拷贝后master节点**/opt/kubernetes/bin/**目录结构如下图:
5.2 部署kubelet
5.2.1 创建配置文件
cat > /opt/kubernetes/cfg/kubelet.conf << EOF
KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=k8s-master \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet-config.yml \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
EOF
# 参数说明
--hostname-override:显示名称,集群中唯一
--network-plugin:启用CNI
--kubeconfig:空路径,会自动生成,后面用于连接apiserver
--bootstrap-kubeconfig:首次启动向apiserver申请证书
--config:配置参数文件
--cert-dir:kubelet证书生成目录
--pod-infra-container-image:管理Pod网络容器的镜像
5.2.2 配置参数文件
cat > /opt/kubernetes/cfg/kubelet-config.yml << EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
- 10.0.0.2
clusterDomain: cluster.local
failSwapOn: false
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: true
x509:
clientCAFile: /opt/kubernetes/ssl/ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF
5.2.3 生成bootstrap.kubeconfig文件
KUBE_APISERVER="https://192.168.226.144:6443" # apiserver IP:PORT
#注意这里的TOKEN配置要与: /opt/kubernetes/cfg/token.csv里保持一致
TOKEN="a85cbca976935a7abc872d46d5a0a39e"
# 生成 kubelet bootstrap kubeconfig 配置文件
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig
kubectl config set-credentials "kubelet-bootstrap" \
--token=${TOKEN} \
--kubeconfig=bootstrap.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user="kubelet-bootstrap" \
--kubeconfig=bootstrap.kubeconfig
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
5.2.4 systemd管理kubelet
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
5.2.5 启动并设置开机启动
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
# 查看运行状态
systemctl status kubelet.service
出现如下内容证明启动成功!
5.3 批准kubelet证书申请并加入集群
# 查看kubelet证书请求
kubectl get csr

#批准申请 注意:此命令不要直接复制执行,将后面的node-csr-* 替换为kubectl get csr得到的name值
kubectl certificate approve node-csr-k7iFDZh4BHcYfC2YGibCOdBwgp-PRebwqh2eshX3PLg

# 查看节点
kubectl get node

注:由于网络插件还没有部署,节点会没有准备就绪 NotReady
5.4 部署kube-proxy
5.4.1 创建配置文件
cat > /opt/kubernetes/cfg/kube-proxy.conf << EOF
KUBE_PROXY_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--config=/opt/kubernetes/cfg/kube-proxy-config.yml"
EOF
5.4.2 配置参数文件
cat > /opt/kubernetes/cfg/kube-proxy-config.yml << EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
metricsBindAddress: 0.0.0.0:10249
clientConnection:
kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: k8s-master
clusterCIDR: 10.0.0.0/24
EOF
5.4.3 生成kube-proxy.kubeconfig文件
cd ~/TLS/k8s # 切换目录
# 创建证书请求文件
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
# 生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
# 查看证书
ls kube-proxy*pem


KUBE_APISERVER="https://192.168.226.144:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy \
--client-certificate=./kube-proxy.pem \
--client-key=./kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

# 拷贝配置文件到指定路径:
cp kube-proxy.kubeconfig /opt/kubernetes/cfg/
5.4.4 systemd管理kube-proxy
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.conf
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
5.4.5 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy
# 查看kube-proxy运行状态
systemctl status kube-proxy
如下图所示,说明启动成功!
5.5 部署CNI网络
首先下载二进制文件:
cni-plugins-linux-amd64-v0.8.6.tgz文件下载链接
解压二进制文件到指定目录
mkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin # 该命令需要在压缩包的同级目录下执行
部署CNI网络:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml --no-check-certificate

# 使用docker下载镜像flannel:v0.12.0-amd64到本地,供后续使用,这里如果遇到的问题,可以参考问题7.8
# 这里我用了一个大佬提供的镜像版本,当然只要镜像合适,可以自己搞或者用其他版本的
docker pull lizhenliang/flannel:v0.12.0-amd64

# 这个命令的使用就是用我们自己下载的镜像文件替换下载下来的kube-flannel.yml文件里面的
sed -i -r "s#quay.io/coreos/flannel:.*-amd64#lizhenliang/flannel:v0.12.0-amd64#g" kube-flannel.yml # 到这里,可能有的读者会疑问,为什么要使用该命令,具体的解释请参照问题7.7,7.8
默认镜像地址无法访问,修改为docker hub镜像仓库。
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system
如下图所示,网络插件配置成功,node准备就绪
5.6 授权apiserver访问kubelet
cat > apiserver-to-kubelet-rbac.yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
- pods/log
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:kube-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
EOF
kubectl apply -f apiserver-to-kubelet-rbac.yaml

5.7 新增加Worker Node
5.7.1 拷贝已部署好的Node相关文件到新节点
# 拷贝到全部的node节点,145,146. 我这里只给出一个节点的命令,master节点执行
scp -r /opt/kubernetes root@192.168.226.145:/opt/
scp -r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.226.145:/usr/lib/systemd/system
scp -r /opt/cni/ root@192.168.226.145:/opt/
scp /opt/kubernetes/ssl/ca.pem root@192.168.226.145:/opt/kubernetes/ssl
5.7.2 删除kubelet证书和kubeconfig文件(注意:在普通node上执行,非master)
# 这几个文件是证书申请审批后自动生成的,每个Node不同,必须删除重新生成。
rm /opt/kubernetes/cfg/kubelet.kubeconfig
rm -f /opt/kubernetes/ssl/kubelet*
5.7.3 修改主机名(非master节点执行)
# 这里只给出一台节点的命令
vi /opt/kubernetes/cfg/kubelet.conf
--hostname-override=k8s-node1
vi /opt/kubernetes/cfg/kube-proxy-config.yml
hostnameOverride: k8s-node1
5.7.4 启动并设置开机启动(非master节点执行)
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl start kube-proxy
systemctl enable kube-proxy
5.7.5 在Master上批准新Node kubelet证书申请(master节点执行)
kubectl get csr

# 注意该命令不要直接复制! 改成自己申请的name!
kubectl certificate approve node-csr-KZGu0Vf0og_7O33qJaokbqlzL2ecYO77eeOShf6ktAU
kubectl certificate approve node-csr-Mf2bxVOO68I4urdHvlEqpFn7FnYyYci3DVb9VWkvwJA
5.7.6 查看Node状态
kubectl get node
如下图,表示OK
注意,执行该命令第一时间节点的状态可能为NotReady,这不一定是有问题,过一段时间刷新即可!
六、部署Dashboard和CoreDNS
6.1 部署Dashboard(master节点执行)
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml --no-check-certificate
默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:
vi recommended.yaml
# 找到kind: Servive部分
# 按照下图内容添加: nodePort: 30001
# type: NodePort
# 需要注意添加的位置,以及空格数!
修改内容如下图所示:
kubectl apply -f recommended.yaml
kubectl get pods,svc -n kubernetes-dashboard

访问地址:
https://ip:30001 #我这里对应的ip为192.168.226.144
初始界面如下图:
# 创建service account并绑定默认cluster-admin管理员集群角色:
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
使用输出的token登录Dashboard

初始界面如下图:
6.2 部署CoreDNS
CoreDNS用于集群内部Service名称解析。
# 使用wget命令下载下来的coredns.yaml文件有语法问题,所以我这里提供个没有语法问题的yaml文件
提取码为:pm5t
kubectl apply -f coredns.yaml

kubectl get pods -n kube-system

kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ # nslookup kubernetes
Server: 10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local
/ #

至此,单Master k8s集群部署完成! 撒花
七、常见问题及解决方案
7.1 etcd集群报错:
启动集群节点etcd-3的时候报如下错误:
systemctl restart etcd # 启动etcd节点
Job for etcd.service failed because the control process exited with error code. See "systemctl status etcd.service" and "journalctl -xe" for details.
按照报错提示使用journalctl -xe命令查看具体报错信息如下:
journalctl -xe
# 日志中包含如下错误信息, 关键字etcd.service failed. 启动失败
Sep 11 16:51:56 k8snode2 etcd[58216]: {"level":"fatal","ts":"2020-09-11T16:51:56.694+0800","caller":"etcdmain/etcd.go:271","msg":"discovery failed","error":"member 39e6630
Sep 11 16:51:56 k8snode2 systemd[1]: etcd.service: main process exited, code=exited, status=1/FAILURE
Sep 11 16:51:56 k8snode2 systemd[1]: Failed to start Etcd Server.
Sep 11 16:51:56 k8snode2 systemd[1]: Unit etcd.service entered failed state.
Sep 11 16:51:56 k8snode2 systemd[1]: etcd.service failed.
Sep 11 16:51:56 k8snode2 systemd[1]: etcd.service holdoff time over, scheduling restart.
Sep 11 16:51:56 k8snode2 systemd[1]: Stopped Etcd Server.
Sep 11 16:51:56 k8snode2 systemd[1]: start request repeated too quickly for etcd.service
Sep 11 16:51:56 k8snode2 systemd[1]: Failed to start Etcd Server.
Sep 11 16:51:56 k8snode2 systemd[1]: Unit etcd.service entered failed state.
Sep 11 16:51:56 k8snode2 systemd[1]: etcd.service failed.
# 报错提示关键字:
member 39e6630289bd896d has already been bootstrapped
查看资料说是:
One of the member was bootstrapped via discovery service.
You must remove the previous data-dir to clean up the member information.
Or the member will ignore the new configuration and start with the old configuration.
That is why you see the mismatch.
大概意思:
其中一个成员是通过discovery service引导的。
必须删除以前的数据目录来清理成员信息。否则成员将忽略新配置,使用旧配置。
这就是为什么你看到了不匹配。
看到了这里,问题所在也就很明确了,启动失败的原因在于data-dir (/var/lib/etcd/default.etcd)中记录的信息与 etcd启动的选项所标识的信息不太匹配造成的。
问题分析
是什么原因导致了data-dir (/var/lib/etcd/default.etcd)中记录的信息与 etcd启动的选项所标识的信息不匹配呢?
经过排查,发现我这里存在的问题是:
节点三配置文件 /opt/etcd/cfg/etcd.conf
ETCD_NAME配置项配置错误(从节点一scp发送过来,忘记改了)
问题解决:
第一步: 修改配置文件
vi /opt/etcd/cfg/etcd.conf # 修改配置文件
# 修改配置
ETCD_NAME="etcd-3"
# 仔细检查其它配置项,确认无误后保存退出
第二步:删除每个节点edct的data目录
删除所有etcd节点的 data-dir 文件(不删也行),重启各个节点的etcd服务.
这个时候,每个节点的data-dir的数据都会被更新,就不会有以上故障了。
# 查看节点状态
systemctl status etcd.service
如下图.节点启动正常:
7.2 启动docker报错:unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid chara
journalctl -xe # 使用该命令查看报错详情
Sep 13 12:20:53 k8snode2 dockerd[61910]: unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid chara
Sep 13 12:20:53 k8snode2 systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE
Sep 13 12:20:53 k8snode2 systemd[1]: Failed to start Docker Application Container Engine.
-- Subject: Unit docker.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit docker.service has failed.
--
-- The result is failed.
Sep 13 12:20:53 k8snode2 systemd[1]: Unit docker.service entered failed state.
Sep 13 12:20:53 k8snode2 systemd[1]: docker.service failed.
Sep 13 12:20:54 k8snode2 systemd[1]: docker.service holdoff time over, scheduling restart.
Sep 13 12:20:54 k8snode2 systemd[1]: Stopped Docker Application Container Engine.
-- Subject: Unit docker.service has finished shutting down
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit docker.service has finished shutting down.
Sep 13 12:20:54 k8snode2 systemd[1]: start request repeated too quickly for docker.service
Sep 13 12:20:54 k8snode2 systemd[1]: Failed to start Docker Application Container Engine.
-- Subject: Unit docker.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit docker.service has failed.
--
-- The result is failed.
Sep 13 12:20:54 k8snode2 systemd[1]: Unit docker.service entered failed state.
Sep 13 12:20:54 k8snode2 systemd[1]: docker.service failed.
报错原因:
启动参数(flag)和配置文件 /etc/docker/daemon.json 的仓库冲突
解决方案:
去掉/etc/docker/daemon.json和启动参数的冲突项
即:将/etc/docker/daemon.json文件从
cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
修改为:
{
{
执行systemctl start docker命令重新启动docker
执行systemctl status docker.service命令查看docker运行状态
如下:docker启动成功,问题解决!

7.3 kube-apiserver启动失败:Failed to start Kubernetes API Server
kube-apiserver配置结束后,
执行systemctl start kube-apiserver命令启动:
执行:systemctl status kube-apiserver.service报错如下:
● kube-apiserver.service - Kubernetes API Server
Loaded: loaded (/usr/lib/systemd/system/kube-apiserver.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since Sun 2020-09-13 14:52:48 CST; 55min ago
Docs: https://github.com/kubernetes/kubernetes
Process: 62026 ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS (code=exited, status=1/FAILURE)
Main PID: 62026 (code=exited, status=1/FAILURE)
Sep 13 14:52:47 k8smaster kube-apiserver[62026]: --stderrthreshold severity logs at or above this threshold go ...lt 2)
Sep 13 14:52:47 k8smaster kube-apiserver[62026]: -v, --v Level number for the log level verbosity
Sep 13 14:52:47 k8smaster kube-apiserver[62026]: --version version[=true] Print version information and quit
Sep 13 14:52:47 k8smaster kube-apiserver[62026]: --vmodule moduleSpec comma-separated list of pattern=N s...gging
Sep 13 14:52:48 k8smaster systemd[1]: kube-apiserver.service holdoff time over, scheduling restart.
Sep 13 14:52:48 k8smaster systemd[1]: Stopped Kubernetes API Server.
Sep 13 14:52:48 k8smaster systemd[1]: start request repeated too quickly for kube-apiserver.service
Sep 13 14:52:48 k8smaster systemd[1]: Failed to start Kubernetes API Server.
Sep 13 14:52:48 k8smaster systemd[1]: Unit kube-apiserver.service entered failed state.
Sep 13 14:52:48 k8smaster systemd[1]: kube-apiserver.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
使用如下命令查看kube-apiserver的错误日志:
cat /var/log/messages|grep kube-apiserver|grep -i error
# 发现报错信息如下
Sep 13 14:06:09 k8smaster kube-apiserver: Error: --etcd-servers must be specified
Sep 13 14:06:09 k8smaster kube-apiserver: --alsologtostderr log to standard error as well as files
Sep 13 14:06:09 k8smaster kube-apiserver: --logtostderr log to standard error instead of files (default true)
报错提示很简单:–etcd-servers参数必须指定
查看kube-apiserver配置文件,发现如下低级错误:
cat /opt/kubernetes/cfg/kube-apiserver.conf
这里把–etcd-servers给分行了,应该是当时编辑的时候多点了个回车,修改回去即可
# 执行如下命令重启并查看kube-apiserver运行状态
systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
systemctl status kube-apiserver.service
服务启动成功!
7.4 kube-controller-manager启动失败: Failed to start Kubernetes Controller Manager
#使用如下命令查看kube-controller-manager状态报错
systemctl status kube-controller-manager.service
# 报错信息如下
● kube-controller-manager.service - Kubernetes Controller Manager
Loaded: loaded (/usr/lib/systemd/system/kube-controller-manager.service; disabled; vendor preset: disabled)
Active: failed (Result: start-limit) since Sun 2020-09-13 16:13:24 CST; 4s ago
Docs: https://github.com/kubernetes/kubernetes
Process: 62325 ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS (code=exited, status=1/FAILURE)
Main PID: 62325 (code=exited, status=1/FAILURE)
Sep 13 16:13:24 k8smaster systemd[1]: Unit kube-controller-manager.service entered failed state.
Sep 13 16:13:24 k8smaster systemd[1]: kube-controller-manager.service failed.
Sep 13 16:13:24 k8smaster systemd[1]: kube-controller-manager.service holdoff time over, scheduling restart.
Sep 13 16:13:24 k8smaster systemd[1]: Stopped Kubernetes Controller Manager.
Sep 13 16:13:24 k8smaster systemd[1]: start request repeated too quickly for kube-controller-manager.service
Sep 13 16:13:24 k8smaster systemd[1]: Failed to start Kubernetes Controller Manager.
Sep 13 16:13:24 k8smaster systemd[1]: Unit kube-controller-manager.service entered failed state.
Sep 13 16:13:24 k8smaster systemd[1]: kube-controller-manager.service failed.
可以看到,报错的关键信息指向:
Process: 62325 ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
肉眼并没有看出问题,怀疑是换行符之类的搞出的幺蛾子,重新把红线圈出来的一行编辑了一下
# 重新启动kube-controller-manager并查看其运行状态
systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
systemctl status kube-controller-manager.service
如图所示,启动成功
若以上日志暴露的信息不够,想要查看kube-controller-manager更具体的报错信息
可执行如下命令:
cat /var/log/messages|grep kube-controller-manager|grep -i error
7.3,7.4两个属于很基础,很简单的配置问题,按理说不应该犯
遇到这种问题的经验就是细心,耐心,仔细查看日志关键内容
还有,就是不要相信自己的眼睛!
7.5 kubectl get node命令报错No resources found in default namespace
# 使用kubectl get node命令查看集群节点报错如下:
No resources found in default namespace
前提:kubectl get csr命令使用正常
使用systemctl status kubelet.service命令查看kubelet状态,发现如下报错:
kubelet.service - Kubernetes Kubelet
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since Mon 2020-09-14 03:52:49 CST; 12min ago
Process: 9762 ExecStart=/opt/kubernetes/bin/kubelet $KUBELET_OPTS (code=exited, status=255)
Main PID: 9762 (code=exited, status=255)
Sep 14 03:52:49 k8smaster systemd[1]: Unit kubelet.service entered failed state.
Sep 14 03:52:49 k8smaster systemd[1]: kubelet.service failed.
Sep 14 03:52:49 k8smaster systemd[1]: kubelet.service holdoff time over, scheduling restart.
Sep 14 03:52:49 k8smaster systemd[1]: Stopped Kubernetes Kubelet.
Sep 14 03:52:49 k8smaster systemd[1]: start request repeated too quickly for kubelet.service
Sep 14 03:52:49 k8smaster systemd[1]: Failed to start Kubernetes Kubelet.
Sep 14 03:52:49 k8smaster systemd[1]: Unit kubelet.service entered failed state.
Sep 14 03:52:49 k8smaster systemd[1]: kubelet.service failed.
我这里比较特殊的地方是最开始kubelet是启动成功了,因为某种原因,启动后马上挂掉.
之后尝试重启,kubelet无法再次启动成功
查看该节点其它组件状态
使用systemctl status docker查看docker状态时,发现状态如下:
docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: https://docs.docker.com
原因,应该是前面安装docker的时候,忘记设置docker开机自动启动,虚拟机重启后docker没有启动,导致kubelet也不能正常启动
# 重新启动docker并设置开机自动启动
systemctl daemon-reload
systemctl start docker
systemctl enable docker

#启动kubelet
systemctl status kubelet.service
这里看到kubelet已经正常启动
最后运行kubectl get node命令,问题解决

闲话: 当时我执行kubectl get node
报错No resources found in default namespace时
按照这个报错搜索答案,根本就没有自己想要的
(而且如果这个时候滥用其他人的解决方案,可能会在错误的路上越走越远)
后面,就想着是不是某个组件的故障导致的这一问题?
然后发现了kubelet的问题
然后我检查了kubelet的配置,安装过程,认为是没什么问题的
接着就想,是不是它的问题也是因为别的地方异常导致的?
最终,我发现了原来是docker没有启动
废话了这么多,其实是在感慨,排查问题的方向很重要,找到真正的问题点才能解决问题
7.6 kube-proxy启动失败 Failed to start Kubernetes
systemctl status kube-proxy.service命令报错如下:
● kube-proxy.service - Kubernetes Proxy
Loaded: loaded (/usr/lib/systemd/system/kube-proxy.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since Mon 2020-09-14 04:44:42 CST; 18s ago
Main PID: 17210 (code=exited, status=1/FAILURE)
Sep 14 04:44:42 k8smaster systemd[1]: Unit kube-proxy.service entered failed state.
Sep 14 04:44:42 k8smaster systemd[1]: kube-proxy.service failed.
Sep 14 04:44:42 k8smaster systemd[1]: kube-proxy.service holdoff time over, scheduling restart.
Sep 14 04:44:42 k8smaster systemd[1]: Stopped Kubernetes Proxy.
Sep 14 04:44:42 k8smaster systemd[1]: start request repeated too quickly for kube-proxy.service
Sep 14 04:44:42 k8smaster systemd[1]: Failed to start Kubernetes Proxy.
Sep 14 04:44:42 k8smaster systemd[1]: Unit kube-proxy.service entered failed state.
Sep 14 04:44:42 k8smaster systemd[1]: kube-proxy.service failed.
这里给的报错信息其实不够详细,分析不出什么有价值的东西
# 使用该命令查看报错信息,发现输出内容为空
cat /var/log/messages|grep kube-proxy|grep -i error
# 最终,只能寄希望于这里面的日志能提供点足够有价值的信息
journalctl -xe
发现了如下关键信息**/opt/kubernetes/cfg/kube-proxy.kubeconfig: no such file or directory**
Sep 14 05:01:47 k8smaster kube-proxy[21344]: F0914 05:01:47.368947 21344 server.go:497] stat /opt/kubernetes/cfg/kube-proxy.kubeconfig: no such file or directory
Sep 14 05:01:47 k8smaster systemd[1]: kube-proxy.service: main process exited, code=exited, status=1/FAILURE
Sep 14 05:01:47 k8smaster systemd[1]: Unit kube-proxy.service entered failed state.
Sep 14 05:01:47 k8smaster systemd[1]: kube-proxy.service failed.
Sep 14 05:01:47 k8smaster systemd[1]: kube-proxy.service holdoff time over, scheduling restart.
Sep 14 05:01:47 k8smaster systemd[1]: Stopped Kubernetes Proxy.
那么/opt/kubernetes/cfg/kube-proxy.kubeconfig这个文件时什么呢?
是yml文件里配置的一个重要的配置文件
关键的配置都找不到,肯定无法启动
最终发现改文件实际上已经生成了,但是没有拷贝到指定的目录下:
# 执行命令将缺失的配置文件拷贝到指定目录下
cp kube-proxy.kubeconfig /opt/kubernetes/cfg/
之后重新启动,可以看到kube-proxy启动正常
7.7 cni网络部署异常,报错: network plugin is not ready: cni config uninitialized
cni网络部署配置完成之后,使用kubectl get pods -n kube-system
命令查看,显示如下: 节点状态为Init
使用如下命令查看日志:
journalctl -f -u kubelet
发现如下报错:
Sep 14 17:51:07 k8smaster kubelet[31776]: E0914 17:51:07.193420 31776 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
Sep 14 17:51:10 k8smaster kubelet[31776]: E0914 17:51:10.655750 31776 remote_image.go:113] PullImage "quay.io/coreos/flannel:v0.12.0-amd64" from image service failed: rpc error: code = Unknown desc = Error response from daemon: Get https://quay.io/v2/: x509: certificate signed by unknown authority
Sep 14 17:51:10 k8smaster kubelet[31776]: E0914 17:51:10.655824 31776 kuberuntime_image.go:50] Pull image "quay.io/coreos/flannel:v0.12.0-amd64" failed: rpc error: code = Unknown desc = Error response from daemon: Get https://quay.io/v2/: x509: certificate signed by unknown authority
报错关键信息提炼如下:
network plugin is not ready: cni config uninitialized
PullImage "quay.io/coreos/flannel:v0.12.0-amd64" from image service failed
x509: certificate signed by unknown authority
问题就出在quay.io/coreos/flannel:v0.12.0-amd64这个镜像上面
使用wget命令下载的kube-flannel.yml有关于这个镜像的配置,我们需要把这个镜像替换掉
使用docker将flannel:v0.12.0-amd64这个镜像下载到本地
docker pull lizhenliang/flannel:v0.12.0-amd64

接下来执行如下命令:
sed -i -r "s#quay.io/coreos/flannel:.*-amd64#lizhenliang/flannel:v0.12.0-amd64#g" kube-flannel.yml
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system
如下图所示,网络插件配置成功,node准备就绪,问题解决
7.8 使用docker pull镜像报错:Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority
问题描述: 使用docker pull命令下载镜像时报错如下:
Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority
从报错来看,是证书的问题,所以我们就生成证书
openssl genrsa -out client.key 4096

openssl req -new -x509 -text -key client.key -out client.cert
# 执行该命令的时候要输入一些信息,根据个人情况填写,非必填项选默认即可,如下图:
将生成的证书拷贝到指定目录下
mkdir -p /usr/local/share/ca-certificate
cp client.cert /usr/local/share/ca-certificate/domain.crt #我这里用cp而不是mv是为了留个备份
接下来在下载镜像就成功啦~
这时如果docker pull失败的话可以多试几次
更多推荐
所有评论(0)