前言:
本篇博客列出的所有命令均是博主亲自实践,
所列举的问题也是博主在实际安装中碰到的.
大家遇到什么问题或者疑问可以在评论区指出,
我会持续更正博客文档~
希望大家在安装学习k8s的时候少走弯路

文章目录

一. 部署准备

二、Etcd集群部署

三、安装Docker

四、部署Master Node

五、部署Worker Node

六、部署Dashboard和CoreDNS

七、常见问题及解决方案

一. 部署准备

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

docker-19.03.9.tgz下载链接

以下在所有节点操作。这里采用二进制安装,用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文件

coredns.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失败的话可以多试几次
在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐