一. 部署准备
1.1 部署Kubernetes集群的两种方式
目前生产部署Kubernetes集群主要有两种方式:
kubeadm
Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
Kubeadm官方链接
二进制包
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。
如果想更容易可控,推荐使用二进
制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
本文采用二进制包方式来部署Kubernetes1.18集群(单Master)
1.2 安装要求
条件 | 指标 |
---|---|
机器要求 | 单节点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 | 安装组件 |
---|---|---|
m1 | 192.168.118.103 | kube-apiserver,kube-controller-manager,kube-scheduler,etcd |
n1 | 192.168.118.104 | kubelet,kube-proxy,docker, etcd |
1.4 操作系统必要配置初始化
1.4.1 根据规划设置主机名
# 修改/etc/hosts文件(所有主机执行)
vi /etc/hosts
# 添加如下内容
192.168.118.103 m1
192.168.118.104 n1
# 设置主机名(每台主机分别执行)
hostnamectl set-hostname m1 # 主节点执行
hostnamectl set-hostname n1 # node1节点执行
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 |
---|---|
m1 | 192.168.118.103 |
n1 | 192.168.118.104 |
注:为了节省机器,这里与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.118.103",
"192.168.118.104"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
注:上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。
生成证书:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
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.118.103:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.118.103:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.118.103:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.118.103:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.118.103:2380,etcd-2=https://192.168.118.104: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.118.104:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.118.104:/usr/lib/systemd/system/
# 附: 如果这里嫌弃scp命令拷贝时需要输入密码麻烦,可配置ssh服务(所有节点执行)
ssh-keygen -t rsa # 连续按三次回车
ssh-copy-id m1
ssh-copy-id n1
在节点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.118.104:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.118.104:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.118.104:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.118.104:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.118.103:2380,etcd-2=https://192.168.118.104: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.118.103:2379,\
https://192.168.118.104: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.118.103:2379,\
https://192.168.118.104: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
启动之后:使用命令查看docker运行状态
systemctl status docker.service
出现如下内容证明安装配置成功
否则,使用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.118.103",
"192.168.118.104",
"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.118.103:2379,https://192.168.118.104:2379 \
--bind-address=192.168.118.103 \
--secure-port=6443 \
--advertise-address=192.168.118.103 \
--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 ' '
79ddd648de9e8c7a54cf63ae579a8262
# 创建上述配置文件中token文件
vim /opt/kubernetes/cfg/token.csv
79ddd648de9e8c7a54cf63ae579a8262,kubelet-bootstrap,10001,"system:node-bootstrapper"
# 格式: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=192.168.118.103: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=192.168.118.104 \\
--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.118.103:6443" # apiserver IP:PORT
#注意这里的TOKEN配置要与: /opt/kubernetes/cfg/token.csv里保持一致
TOKEN="79ddd648de9e8c7a54cf63ae579a8262"
# 创建上述配置文件中token文件
vim /opt/kubernetes/cfg/token.csv
79ddd648de9e8c7a54cf63ae579a8262,kubelet-bootstrap,10001,"system:node-bootstrapper"
scp -r kubernetes/ root@192.168.118.104:/opt/
scp -r /usr/bin/kubectl root@192.168.118.104:/usr/bin/
# 生成 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-bjm6QMzvUpee4GBFSiQD4rnLJZ8RZorF7VlEVKilKag
# 查看节点
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.118.103: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文件下载链接](https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-l inux-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集群部署完成! 撒花