目录
一、操作系统初始化
1、关闭防火墙
2、关闭 SELinu
3、 关闭 swap
4、添加hosts
5、同步系统时间
二、集群搭建 —— 使用外部Etcd集群
1、自签证书
2、自签 Etcd SSL 证书
① 创建 CA 配置文件:ca-config.json
② 创建 CA 证书签名请求文件:ca-csr.json
③ 生成 CA 证书和私钥
④ 创建证书签名请求文件:etcd-csr.json
⑤ 为 etcd 生成证书和私钥
3、Etcd 数据库集群部署
① 下载 etcd 到/k8s/etcd/ 并解压
② 创建 etcd 配置文件:etcd.conf
③ 创建 etcd 服务:etcd.service 将其部署为一个systemd的服务,在/usr/lib/systemd/system/etcd.service
④ 将 etcd 目录拷贝到另外两个节点
⑤ 修改两个节点配置文件
⑥ 启动 3个节点的 etcd 服务
三、部署安全的k8s Master 高可用集群
1、自签ApiServer SSL证书
① 创建 CA 配置文件:ca-config.json
② 创建 CA 证书签名请求文件:ca-csr.json
③ 生成 CA 证书和私钥
④ 创建证书签名请求文件:kubernetes-csr.json
⑤ 为 kubernetes 生成证书和私钥
2、部署 kube-apiserver 组件
① 下载k8s
② 创建 Node 令牌文件:token.csv
③ 创建 kube-apiserver 配置文件:kube-apiserver.conf
④ 创建 apiserver 服务:kube-apiserver.service
⑤ 启动 kube-apiserver 组件
⑥ 将 kubelet-bootstrap 用户绑定到系统集群角色,之后便于 Node 使用token请求证书
3、部署kube-controller-manager组件
① 创建 kube-controller-manager 配置文件:kube-controller-manager.conf
② 创建 kube-controller-manager 服务:kube-controller-manager.service
③ 启动 kube-controller-manager 组件
4、部署kube-scheduler组件
① 创建 kube-scheduler 配置文件:kube-scheduler.conf
② 创建 kube-scheduler 服务:kube-scheduler.service
③ 启动 kube-scheduler 组件
5、查看集群状态
① 查看组件状态
四、集群搭建--部署node节点
1、安装docker
2、Node 节点证书
① 创建 Node 节点的证书签名请求文件:kube-proxy-csr.json
② 为 kube-proxy 生成证书和私钥
③ node 节点创建工作目录
④ 将 k8s-master-1 节点的文件拷贝到 node 节点
3、安装kubelet
① 创建请求证书的配置文件:bootstrap.kubeconfig
② 创建 kubelet 配置文件:kubelet-config.yml
③ 创建 kubelet 服务配置文件:kubelet.conf
④ 创建 kubelet 服务:kubelet.service
⑤ 启动 kubelet
⑥master 给node授权
⑦授权成功 ,查看集群 node是否加入(此时的 node 还处于未就绪的状态,因为还没有安装 CNI 组件):
4、安装kube-proxy
① 创建 kube-proxy 连接 apiserver 的配置文件:kube-proxy.kubeconfig
② 创建 kube-proxy 配置文件:kube-proxy-config.yml
③ 创建 kube-proxy 配置文件:kube-proxy.conf
④ 创建 kube-proxy 服务:kube-proxy.service
⑤ 启动 kube-proxy
5、部署其他node节点
6、部署k8s容器集群网络
① K8S 集群网络
② 创建 CNI 工作目录
③ 装 CNI 插件
④ 部署 Flannel
⑤ 检查部署状态
⑥ 测试创建 Pod
7、部署CoreDNS服务
① 部署 CoreDNS
编辑 ② 验证 CoreDNS 服务名的DNS解析
遇到的问题1:解析时候报错
CroeDNS的配置说明
8、集群搭建--多master部署
1、部署Master2组件
① 将 k8s-master-1 上相关文件拷贝到 k8s-master-2 上
② 修改 k8s-master-2 上的配置文件
④ 验证
2、部署nginx负载均衡
① gcc等环境安装,后续有些软件安装需要这些基础环境
② 安装nginx
③ apiserver 负载配置
④ 启动 nginx
3、部署keepAlive
① 分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上安装 keepalive
② master 启动 keepalived
③ backup 启动 keepalived
④ 验证负载均衡
1、集群架构
2、资源规划
角色 | IP | 主机名 | 组件 |
k8s-master-1 | 192.168.134.135 | k8s-master-1 | kube_apiserver kube-controller-manager kube-scheduler etcd |
k8s-master-2 | 192.168.134.136 | k8s-master-2 | kube_apiserver kube-controller-manager kube-scheduler |
k8s-node-1 | 192.168.134.137 | k8s-node-1 | kubelet kube-proxy docker etcd |
k8s-node-2 | 192.168.134.138 | k8s-node-2 | kubelet kube-proxy docker etcd |
k8s-lb-master | 192.168.134.139 | k8s-lb-master | Nginx keepAlive |
k8s-lb-backup | 192.168.134.140 | k8s-lb-backup | Nginx keepAlive |
一、操作系统初始化
1、关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
2、关闭 SELinu
修改/etc/sysconfig/selinux,将SELINUX=enforcing 修改为 SELINUX=disabled
或者 sed -i 's/enforcing/disabled/' /etc/selinux/config 永久关闭
3、 关闭 swap
# # 永久生效
# vim /etc/fstab
# #将 [UUID=5b59fd54-eaad-41d6-90b2-ce28ac65dd81 swap swap defaults 0 0] 这一行注释掉
4、添加hosts
192.168.134.135 k8s-master-1
192.168.134.136 k8s-master-2
192.168.134.137 k8s-node-1
192.168.134.138 k8s-node-2
192.168.134.139 k8s-lb-master
192.168.134.140 k8s-lb-backup
5、同步系统时间
ntpdate time.windows.com 如果不联网 可以使用date -s 修改时间
二、集群搭建 —— 使用外部Etcd集群
1、自签证书
① k8s-master-1节点上 创建证书
② 使用cfssl工具生成证书,首先下载工具,依次命令
# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
# curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
# curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo
#添加授权
# chmod +x /usr/local/bin/cfssl*
2、自签 Etcd SSL 证书
创建几个目录,ssl 用于存放 etcd 自签证书,cfg 用于存放 etcd 配置文件,bin 用于存放 etcd 执行程序。
cd /
mkdir -p /k8s/etcd/{ssl,cfg,bin}
进入 etcd ssl目录
① 创建 CA 配置文件:ca-config.json
vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"etcd": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
说明:
- signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
- profiles:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
- expiry:证书过期时间
- server auth:表示client可以用该 CA 对server提供的证书进行验证;
- client auth:表示server可以用该CA对client提供的证书进行验证;
② 创建 CA 证书签名请求文件:ca-csr.json
vim ca-csr.json
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
}
}
③ 生成 CA 证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
④ 创建证书签名请求文件:etcd-csr.json
vim etcd-csr.json
{
"CN": "etcd",
"hosts": [
"192.168.134.135",
"192.168.134.137",
"192.168.134.138"
],
"key": {
"algo": "rsa",
"size": 2048
}
}
⑤ 为 etcd 生成证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-csr.json | cfssljson -bare etcd
3、Etcd 数据库集群部署
etcd集群采用一主多从部署,集群通过选举产生leader ,因此需要部署奇数个节点(3/5/7)才能正常工作。etcd使用raft一致性算法保证每个节点的一致性
① 下载 etcd 到/k8s/etcd/ 并解压
wget https://github.com/etcd-io/etcd/releases/download/v3.2.28/etcd-v3.2.28-linux-amd64.tar.gz
解压完之后 将 etcd,etcdctl 移到bin下
cp etcd-v3.2.28-linux-amd64/{etcd,etcdctl} /k8s/etcd/bin/
然后将源目录删除
② 创建 etcd 配置文件:etcd.conf
vim /k8s/etcd/cfg/etcd.conf
# [member]
ETCD_NAME=etcd-1
ETCD_DATA_DIR=/k8s/data/
ETCD_LISTEN_PEER_URLS=https://192.168.134.135:2380
ETCD_LISTEN_CLIENT_URLS=https://192.168.134.135:2379
# [cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.134.135:2380
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.134.135:2379
ETCD_INITIAL_CLUSTER=etcd-1=https://192.168.134.135:2380,etcd-2=https://192.168.134.137:2380,etcd-3=https://192.168.134.138:2380
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
ETCD_INITIAL_CLUSTER_STATE=new
# [security]
ETCD_CERT_FILE=/k8s/etcd/ssl/etcd.pem
ETCD_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem
ETCD_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem
ETCD_PEER_CERT_FILE=/k8s/etcd/ssl/etcd.pem
ETCD_PEER_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem
ETCD_PEER_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem
说明:
- ETCD_NAME:etcd在集群中的唯一名称
- ETCD_DATA_DIR:etcd数据存放目录
- ETCD_LISTEN_PEER_URLS:etcd集群间通讯的地址,设置为本机IP
- ETCD_LISTEN_CLIENT_URLS:客户端访问的地址,设置为本机IP
【集群】
- ETCD_INITIAL_ADVERTISE_PEER_URLS:初始集群通告地址,集群内部通讯地址,设置为本机IP
- ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址,设置为本机IP
- ETCD_INITIAL_CLUSTER:集群节点地址,以 key=value 的形式添加各个 etcd 的地址
- ETCD_INITIAL_CLUSTER_TOKEN:集群令牌,用于集群间做简单的认证
- ETCD_INITIAL_CLUSTER_STATE:集群状态
【安全】
- ETCD_CERT_FILE:客户端 etcd 数字证书路径
- ETCD_KEY_FILE:客户端 etcd 私钥路径
- ETCD_TRUSTED_CA_FILE:客户端 CA 证书路径
- ETCD_PEER_CERT_FILE:集群间通讯etcd数字证书路径
- ETCD_PEER_KEY_FILE:集群间通讯etcd私钥路径
- ETCD_PEER_TRUSTED_CA_FILE:集群间通讯CA证书路径
③ 创建 etcd 服务:etcd.service 将其部署为一个systemd的服务,在/usr/lib/systemd/system/etcd.service
通过EnvironmentFile指定 etcd.conf 作为环境配置文件
vim /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/k8s/etcd/cfg/etcd.conf
WorkingDirectory=${ETCD_DATA_DIR}
ExecStart=/k8s/etcd/bin/etcd
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
systemctl daemon-reload 创建完之后 重新加载下后台进程
etcd.service etcd.conf 更多的配置以及说明可以通过如下命令查看:
# /k8s/etcd/bin/etcd --help
④ 将 etcd 目录拷贝到另外两个节点
scp -r /k8s root@k8s-node-1:/k8s
scp -r /k8s root@k8s-node-2:/k8s
⑤ 修改两个节点配置文件
/k8s/etcd/cfg/etcd.conf
⑥ 启动 3个节点的 etcd 服务
systemctl start etcd
systemctl status etcd
systemctl enable etcd 设置开机自启动
查看etcd集群的状态
/k8s/etcd/bin/etcdctl \
--ca-file=/k8s/etcd/ssl/ca.pem \
--cert-file=/k8s/etcd/ssl/etcd.pem \
--key-file=/k8s/etcd/ssl/etcd-key.pem \
--endpoints=https://192.168.134.135:2379,https://192.168.134.137:2379,https://192.168.134.138:2379 \
cluster-health
/k8s/etcd/bin/etcdctl --ca-file=/k8s/etcd/ssl/ca.pem --cert-file=/k8s/etcd/ssl/etcd.pem --key-file=/k8s/etcd/ssl/etcd-key.pem --endpoints=https://192.168.134.135:2379,https://192.168.134.137:2379,https://192.168.134.138:2379 cluster-health
三、部署安全的k8s Master 高可用集群
1、自签ApiServer SSL证书
k8s集群中所有资源的访问和变更都是通过kube-apiserver的REST API来实现的,首先在master 节点上部署kube-apiserver组件
首先我们为apiserver签发一套SSL证书,过程与etcd类似,ssl用于存放自签证书,cfg用于存放配置文件,bin用于存放执行程序,logs用于存放日志文件
cd /
mkdir -p k8s/kubernetes/{ssl,cfg,bin,logs}
cd /k8s/kubernetes/ssl/
① 创建 CA 配置文件:ca-config.json
vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
② 创建 CA 证书签名请求文件:ca-csr.json
vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
}
}
③ 生成 CA 证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
④ 创建证书签名请求文件:kubernetes-csr.json
vim kubernetes-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"10.0.0.1",
"192.168.134.135",
"192.168.134.136",
"192.168.134.137",
"192.168.134.138",
"192.168.134.139",
"192.168.134.140",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
}
}
说明:
- hosts:指定会直接访问 apiserver 的IP列表,一般需指定 etcd 集群、kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP,Node 的IP一般不需要加入。
⑤ 为 kubernetes 生成证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json |cfssljson -bare kubernetes
2、部署 kube-apiserver 组件
① 下载k8s
将下载好的 kubernetes-v1.16.2-server-linux-amd64.tar.gz 上传到 /usr/local/src下,并解压:
先将 master 节点上部署的组件拷贝到 /k8s/kubernetes/bin 目录
cp {kube-apiserver,kube-controller-manager,kube-scheduler} /k8s/kubernetes/bin/
cp -p /usr/local/src/kubernetes/server/bin/kubectl /usr/local/bin/
② 创建 Node 令牌文件:token.csv
Master apiserver 启用 TLS 认证后,Node节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,当Node节点很多时,签署证书是一件很繁琐的事情,因此有了 TLS Bootstrap 机制,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。因此先为 apiserver 生成一个令牌文件,令牌之后会在 Node 中用到。
生成 token,一个随机字符串,可使用如下命令生成 token:apiserver 配置的 token 必须与 Node 节点 bootstrap.kubeconfig 配置保持一致。
head -c 16 /dev/urandom | od -An -t x | tr -d ' '
创建 token.csv,格式:token,用户,UID,用户组
vim /k8s/kubernetes/cfg/token.csv
bfa3cb7f6f21f87e5c0e5f25e6cfedad,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
③ 创建 kube-apiserver 配置文件:kube-apiserver.conf
kube-apiserver 有很多配置项,可以参考官方文档查看每个配置项的用途:kube-apiserver
vim /k8s/kubernetes/cfg/kube-apiserver.conf
KUBE_APISERVER_OPTS="--etcd-servers=https://192.168.134.135:2379,https://192.168.134.137:2379,https://192.168.134.138:2379 \
--bind-address=192.168.134.135 \
--secure-port=6443 \
--advertise-address=192.168.134.135 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/24 \
--service-node-port-range=30000-32767 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth=true \
--token-auth-file=/k8s/kubernetes/cfg/token.csv \
--kubelet-client-certificate=/k8s/kubernetes/ssl/kubernetes.pem \
--kubelet-client-key=/k8s/kubernetes/ssl/kubernetes-key.pem \
--tls-cert-file=/k8s/kubernetes/ssl/kubernetes.pem \
--tls-private-key-file=/k8s/kubernetes/ssl/kubernetes-key.pem \
--client-ca-file=/k8s/kubernetes/ssl/ca.pem \
--service-account-key-file=/k8s/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/k8s/etcd/ssl/ca.pem \
--etcd-certfile=/k8s/etcd/ssl/etcd.pem \
--etcd-keyfile=/k8s/etcd/ssl/etcd-key.pem \
--v=2 \
--logtostderr=false \
--log-dir=/k8s/kubernetes/logs \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/k8s/kubernetes/logs/k8s-audit.log"
重点配置说明:
- --etcd-servers:etcd 集群地址
- --bind-address:apiserver 监听的地址,一般配主机IP
- --secure-port:监听的端口 默认6443
- --advertise-address:集群通告地址,其它Node节点通过这个地址连接 apiserver,不配置则使用 --bind-address
- --tls-cert-file:服务端CA证书文件全路径
- --service-cluster-ip-range:Service 的 虚拟IP范围,以CIDR格式标识,该IP范围不能与物理机的真实IP段有重合。
- --service-node-port-range:Service 可映射的物理机端口范围,默认30000-32767
- --admission-control:集群的准入控制设置,各控制模块以插件的形式依次生效,启用RBAC授权和节点自管理
- --authorization-mode:授权模式,包括:AlwaysAllow,AlwaysDeny,ABAC(基于属性的访问控制),Webhook,RBAC(基于角色的访问控制),Node(专门授权由 kubelet 发出的API请求)。(默认值"AlwaysAllow")。
- --enable-bootstrap-token-auth:启用TLS bootstrap功能
- --token-auth-file:这个文件将被用于通过令牌认证来保护API服务的安全端口。
- --v:指定日志级别,0~8,越大日志越详细
④ 创建 apiserver 服务:kube-apiserver.service
vim /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
EnvironmentFile=-/k8s/kubernetes/cfg/kube-apiserver.conf
ExecStart=/k8s/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
⑤ 启动 kube-apiserver 组件
# systemctl daemon-reload 重新加载
# systemctl start kube-apiserver 启动
# systemctl enable kube-apiserver 设置开机自启动
检查启动状态
systemctl status kube-apiserver.service
查看启动日志
tail -f kube-apiserver.INFO
⑥ 将 kubelet-bootstrap 用户绑定到系统集群角色,之后便于 Node 使用token请求证书
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
3、部署kube-controller-manager组件
① 创建 kube-controller-manager 配置文件:kube-controller-manager.conf
vim /k8s/kubernetes/cfg/kube-controller-manager.conf
KUBE_CONTROLLER_MANAGER_OPTS="--leader-elect=true \
--master=127.0.0.1:8080 \
--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=/k8s/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/k8s/kubernetes/ssl/ca-key.pem \
--root-ca-file=/k8s/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/k8s/kubernetes/ssl/ca-key.pem \
--experimental-cluster-signing-duration=87600h0m0s \
--v=2 \
--logtostderr=false \
--log-dir=/k8s/kubernetes/logs"
重点配置说明:
- --leader-elect:当该组件启动多个时,自动选举,默认true
- --master:连接本地apiserver,apiserver 默认会监听本地8080端口
- --allocate-node-cidrs:是否分配和设置Pod的CDIR
- --service-cluster-ip-range:Service 集群IP段
② 创建 kube-controller-manager 服务:kube-controller-manager.service
vim /usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
EnvironmentFile=/k8s/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/k8s/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
③ 启动 kube-controller-manager 组件
启动组件
# systemctl daemon-reload
# systemctl start kube-controller-manager
# systemctl enable kube-controller-manager
systemctl status kube-controller-manager
#tail -f /k8s/kubernetes/logs/kube-controller-manager.INFO
4、部署kube-scheduler组件
① 创建 kube-scheduler 配置文件:kube-scheduler.conf
vim /k8s/kubernetes/cfg/kube-scheduler.conf
KUBE_SCHEDULER_OPTS="--leader-elect=true \
--master=127.0.0.1:8080 \
--address=127.0.0.1 \
--v=2 \
--logtostderr=false \
--log-dir=/k8s/kubernetes/logs"
② 创建 kube-scheduler 服务:kube-scheduler.service
vim /usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
EnvironmentFile=/k8s/kubernetes/cfg/kube-scheduler.conf
ExecStart=/k8s/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
③ 启动 kube-scheduler 组件
# systemctl daemon-reload
# systemctl start kube-scheduler
# systemctl enable kube-scheduler
查看状态
systemctl status kube-scheduler
查看启动日志
tail -f /k8s/kubernetes/logs/kube-scheduler.INFO
5、查看集群状态
① 查看组件状态
kubectl get cs
四、集群搭建--部署node节点
1、安装docker
① 卸载旧版本
yum remove docker docker-common docker-selinux
② 安装依赖包
# yum install -y yum-utils device-mapper-persistent-data lvm2
③ 安装 Docker 软件包源
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
安装gcc 相关
yum -y install gcc
④ 安装 Docker CE
# yum install docker-ce
⑤ 启动 Docker 服务
# systemctl start docker
⑥ 设置开机启动
# systemctl enable docker
⑦ 验证安装是否成功
# docker -v
# docker info
2、Node 节点证书
① 创建 Node 节点的证书签名请求文件:kube-proxy-csr.json
首先在 k8s-master-1 节点上,通过颁发的 CA 证书先创建好 Node 节点要使用的证书
vim kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
}
}
② 为 kube-proxy 生成证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
③ node 节点创建工作目录
在 k8s-node-1 节点上创建 k8s 目录
# mkdir -p /k8s/kubernetes/{bin,cfg,logs,ssl}
④ 将 k8s-master-1 节点的文件拷贝到 node 节点
将 kubelet、kube-proxy 拷贝到 node 节点上:
# scp -r /usr/local/src/kubernetes/server/bin/{kubelet,kube-proxy} root@k8s-node-1:/k8s/kubernetes/bin/
将证书拷贝到 k8s-node-1 节点上:
# scp -r /k8s/kubernetes/ssl/{ca.pem,kube-proxy.pem,kube-proxy-key.pem} root@k8s-node-1:/k8s/kubernetes/ssl/
3、安装kubelet
① 创建请求证书的配置文件:bootstrap.kubeconfig
bootstrap.kubeconfig 将用于向 apiserver 请求证书,apiserver 会验证 token、证书 是否有效,验证通过则自动颁发证书。
vim /k8s/kubernetes/cfg/bootstrap.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority: /k8s/kubernetes/ssl/ca.pem
server: https://192.168.134.135:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubelet-bootstrap
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: kubelet-bootstrap
user:
token: d36445ecbeb118755f2c253e4cbcd395
说明:
- certificate-authority:CA 证书
- server:master 地址
- token:master 上 token.csv 中配置的 token
② 创建 kubelet 配置文件:kubelet-config.yml
为了安全性,kubelet 禁止匿名访问,必须授权才可以,通过 kubelet-config.yml 授权 apiserver 访问 kubelet。
vim /k8s/kubernetes/cfg/kubelet-config.yml
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: /k8s/kubernetes/ssl/ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthroizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 100000
maxPods: 110
说明:
- address:kubelet 监听地址
- port:kubelet 的端口
- cgroupDriver:cgroup 驱动,与 docker 的 cgroup 驱动一致
- clusterDNS:集群DNS服务器IP地址
- clusterDomain:服务DNS域名后缀,例如cluster.local
- authentication:访问 kubelet 的授权信息,设置是否允许匿名访问或者是否使用webhook进行授权
- authorization:认证相关信息
- evictionHard:垃圾回收策略
- maxPods:最大pod数
③ 创建 kubelet 服务配置文件:kubelet.conf
vim /k8s/kubernetes/cfg/kubelet.conf
KUBELET_OPTS="--hostname-override=k8s-node-1 \
--network-plugin=cni \
--cni-bin-dir=/opt/cni/bin \
--cni-conf-dir=/etc/cni/net.d \
--cgroups-per-qos=false \
--enforce-node-allocatable="" \
--kubeconfig=/k8s/kubernetes/cfg/kubelet.kubeconfig \:q
--bootstrap-kubeconfig=/k8s/kubernetes/cfg/bootstrap.kubeconfig \
--config=/k8s/kubernetes/cfg/kubelet-config.yml \
--cert-dir=/k8s/kubernetes/ssl \
--pod-infra-container-image=kubernetes/pause:latest \
--v=2 \
--logtostderr=false \
--log-dir=/k8s/kubernetes/logs"
说明:
- --hostname-override:当前节点注册到K8S中显示的名称,默认为主机 hostname
- --network-plugin:启用 CNI 网络插件
- --cni-bin-dir:CNI 插件可执行文件位置,默认在 /opt/cni/bin 下
- --cni-conf-dir:CNI 插件配置文件位置,默认在 /etc/cni/net.d 下
- --cgroups-per-qos:必须加上这个参数和--enforce-node-allocatable,否则报错 [Failed to start ContainerManager failed to initialize top level QOS containers.......]
- --kubeconfig:会自动生成 kubelet.kubeconfig,用于连接 apiserver
- --bootstrap-kubeconfig:指定 bootstrap.kubeconfig 文件
- --config:kubelet 配置文件
- --cert-dir:证书目录
- --pod-infra-container-image:管理Pod网络的镜像,基础的 Pause 容器,默认是 k8s.gcr.io/pause:3.1
④ 创建 kubelet 服务:kubelet.service
vim /usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Before=docker.service
[Service]
EnvironmentFile=/k8s/kubernetes/cfg/kubelet.conf
ExecStart=/k8s/kubernetes/bin/kubelet $KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
⑤ 启动 kubelet
# systemctl daemon-reload
# systemctl start kubelet
# systemctl enable kubelet
# tail -f /k8s/kubernetes/logs/kubelet.INFO
⑥master 给node授权
kubelet启动后,还没加入到集群中,回向apiserver请求证书,需要手动在master-1上对node 授权。
去master-1上查看是否有新的客户端请求颁发证书
kubectl get csr
给客户端颁发证书,允许加入集群
kubectl certificate approve node-csr-WYQh3zST8magLIwnchP9jL_pxRBr2hPVTzhM0Wm-cqk
⑦授权成功 ,查看集群 node是否加入(此时的 node 还处于未就绪的状态,因为还没有安装 CNI 组件):
kubectl get node
颁发证书后,可以在 /k8s/kubenetes/ssl 下看到 master 为 kubelet 颁发的证书:
在 /k8s/kubenetes/cfg 下可以看到自动生成的 kubelet.kubeconfig 配置文件:
4、安装kube-proxy
① 创建 kube-proxy 连接 apiserver 的配置文件:kube-proxy.kubeconfig
vim /k8s/kubernetes/cfg/kube-proxy.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority: /k8s/kubernetes/ssl/ca.pem
server: https://192.168.134.135:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kube-proxy
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: kube-proxy
user:
client-certificate: /k8s/kubernetes/ssl/kube-proxy.pem
client-key: /k8s/kubernetes/ssl/kube-proxy-key.pem
② 创建 kube-proxy 配置文件:kube-proxy-config.yml
vim /k8s/kubernetes/cfg/kube-proxy-config.yml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
address: 0.0.0.0
metrisBindAddress: 0.0.0.0:10249
clientConnection:
kubeconfig: /k8s/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: k8s-node-1
clusterCIDR: 10.0.0.0/24
mode: ipvs
ipvs:
scheduler: "rr"
iptables:
masqueradeAll: true
说明:
- metrisBindAddress:采集指标暴露的地址端口,便于监控系统,采集数据
- clusterCIDR:集群 Service 网段
③ 创建 kube-proxy 配置文件:kube-proxy.conf
vim /k8s/kubernetes/cfg/kube-proxy.conf
KUBE_PROXY_OPTS="--config=/k8s/kubernetes/cfg/kube-proxy-config.yml \
--v=2 \
--logtostderr=false \
--log-dir=/k8s/kubernetes/logs"
④ 创建 kube-proxy 服务:kube-proxy.service
vim /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/k8s/kubernetes/cfg/kube-proxy.conf
ExecStart=/k8s/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
⑤ 启动 kube-proxy
# systemctl daemon-reload
# systemctl start kube-proxy
开机启动:
# systemctl enable kube-proxy
查看启动日志:
# tail -f /k8s/kubernetes/logs/kube-proxy.INFO
5、部署其他node节点
跟上述步骤一样,将k8s-node-1改成k8s-node-2即可
在master节点 查看是否加入集群
kubectl get node -o wide
6、部署k8s容器集群网络
① K8S 集群网络
Kubernetes 项目并没有使用 Docker 的网络模型,kubernetes 是通过一个 CNI 接口维护一个单独的网桥来代替 docker0,这个网桥默认叫 cni0。
Flannel 是 CNI 的一个插件,可以看做是 CNI 接口的一种实现。Flannel 是针对 Kubernetes 设计的一个网络规划服务,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。
② 创建 CNI 工作目录
通过给 kubelet 传递 --network-plugin=cni 命令行选项来启用 CNI 插件。 kubelet 从 --cni-conf-dir (默认是 /etc/cni/net.d)读取配置文件并使用该文件中的 CNI 配置来设置每个 pod 的网络。CNI 配置文件必须与 CNI 规约匹配,并且配置引用的任何所需的 CNI 插件都必须存在于 --cni-bin-dir(默认是 /opt/cni/bin)指定的目录。
由于前面部署 kubelet 服务时,指定了 --cni-conf-dir=/etc/cni/net.d,--cni-bin-dir=/opt/cni/bin,因此首先在node节点上创建这两个目录:
# mkdir -p /opt/cni/bin /etc/cni/net.d
③ 装 CNI 插件
可以从 github 上下载 CNI 插件:下载 CNI 插件 。
解压到 /opt/cni/bin:
# tar zxf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin/
④ 部署 Flannel
可通过此地址下载 flannel 配置文件:下载 kube-flannel.yml
注意如下配置:Network 的地址需与 kube-controller-manager.conf 中的 --cluster-cidr=10.244.0.0/16 保持一致。
在 k8s-master-1 节点上部署 Flannel:
# kubectl apply -f kube-flannel.yml
⑤ 检查部署状态
Flannel 会在 Node 上起一个 Flannel 的 Pod,可以查看 pod 的状态看 flannel 是否启动成功:
# kubectl get pods -n kube-system -o wide
Flannel 部署成功后,就可以看 Node 是否就绪:
# kubectl get nodes -o wide
在 Node 上查看网络配置,可以看到多了一个 flannel.1 的虚拟网卡,这块网卡用于接收 Pod 的流量并转发出去。
注意:此时可能会报错,node节点的状态为:notready,去node节点查看日志
journalctl -f -u kubelet.service
cni config uninitialized
解决办法 :把kubelet.conf中 指定cni的配置删掉 重启kubelet
⑥ 测试创建 Pod
例如创建一个 Nginx 服务:
# kubectl create deployment web --image=nginx
刚创建完事这个状态 过会就是正常了
在对应的节点上 docker ps -a 查看部署的容器
暴露端口并访问 Nginx:
kubectl expose deployment web --port=80 --type=NodePort
7、部署CoreDNS服务
从k8s1.11版本开始,集群的DNS服务便由CoreDNS提供,CoreDNS是CNCF基金会孵化的一个项目,使用go语言开发的高性能、插件式、易扩展的DNS服务端,目前已毕业。CoreDNS解决了KubeDNS的一些问题,支持自定义DNS记录及配置upstream DNS Server,可以统一管理kubernetes基于服务的内部DNS和数据中心的物理DNS。
在kubernetes集群推荐使用Service Name 作为服务的访问地址,因此需要一个kubernetes集群范围的DNS服务实现Service Name 到Cluster IP 的解析,这就是Kubernetes基于DNS的服务发现功能。
① 部署 CoreDNS
首先在两个node节点的kube-config.yml配置文件中 添加
clusterDNS:
- 10.0.0.2
clusterDomain: cluster.local
部署CoreDNS需要创建3个资源对象:ConfigMap、Deployment、Service
ConfigMap “coredns” 主要设置Coredns的主配置文件Corefile的内容,其中可以定义各种域名的解析方式和使用的插件
Deployment "coredns"主要设置CordDNS容器应用的内容,其中,replicas副本的数量通常应该根据集群的规模和服务数量确定,如果单个CoreDNS进程不足以支撑整个集群的DNS查询,则可以通过水平扩展提高查询能力,由于DNS服务是kubernetes集群的关键核心服务,所以建议为其 Deployment设置自动扩缩容控制器,自动管理副本数量
Service "coredns"是DNS服务的配置,需要设置固定的ClusterIP 地址,也需要将所有node上的kubelet启动参数cluster-dns 都设置成这个clusterip
下载CoreDNS配置文件:coredns.yaml
部署DNS服务
kubectl apply -f coredns.yaml
查看状态
kubectl get pods -n kube-system
ImagePullBackOff 这个错误是拉去不到镜像
查看详细日志
kubectl describe pod coredns-5fb6c888d6-hbbrt -n kube-system coredns-686c689586-q7cz9 :是pod name
或者 kubectl logs -n kube-system metrics-server-7dbf6c4558-dmmrs
根据日志 去node-2节点 拉去相应的镜像
docker pull
然后修改镜像的tag 0ad7f9e4a77d :为镜像的ID
docker tag 0ad7f9e4a77d registry.aliyuncs.com/google_containers/coredns/coredns:v1.10.0
完事重启下docker
在master节点再看下状态,如果换是同样的问题,就改一下cordDNS的配置文件,把拉去镜像那里改成你在node上拉去的地址
在重新加载cordDNS配置文件 查看 就OK了。
② 验证 CoreDNS 服务名的DNS解析
使用一个带有nslookup工具的pod 来验证DNS服务能否正常工作
vim busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
dnsPolicy: ClusterFirst
containers:
- name: busybox
image: busybox:1.28.4
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
运行完成创建
# kubectl apply -f busybox.yaml
YAML 格式:
apiVersion: v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Pod #该配置的类型,我们使用的是 POD
metadata: #译名为元数据,即 POD 的一些基本属性和信息
name: nginx #POD 的名称
namedpace #pod名称空间
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组
app: nginx #设置key为app,value为nginx的标签
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
imagePullPolicy: IfNotPresent #设置container的拉取策略,IfNotPresent存在时不进行拉取。
创建成功之后查看容器
kubectl get pod -owide 或者kubectl get pod --all-namespaces -owide 查看容器详细信息
然后去对应的节点上看下有没有镜像存在
查看pod容器日志
kubectl describe pod/podname
进入容器:
kubectl exec -it pod/busybox -- /bin/sh 或者kubectl exec -it busybox sh
报错的话 是权限问题
kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes
进入容器 执行 nslookup web 成功解析
遇到的问题1:解析时候报错
解决:可能是镜像版本的问题,修改配置文件镜像的版本,然后删除pod 重新创建,在进入容器OK。
CroeDNS的配置说明
CoreDNs 的主要功能是通过插件系统实现的。
常用的插件如下:
- loadbalance: 提供基于 DNS 的负载均衡功能。
- loop: 检测在 DNS 解析过中出现的简单循环问题
- cache:提供前端缓存功能。
- health:对 Endpoint 进行健康检查。
- kubernetes:从 Kubernetes 中读取 zone 数据。
- etcd:从 etcd 中读取 zone 数据,可用于自定义域名记录.
- fle:从 RFC1035 格式文件中读取 zone 数据。
- reload:定时自动重新加载 Corefile 配置文件的内容
- prometheus:为 Prometheus 系统提供采集性能指标数据的 URL
- errors:对错误信息进行日志记录
- log:对 DNS 查询进行日志记录
在下面的示例中为域名“cluster.local”设置了一系列插件,包括 errors、health readkubernetes、prometheus、forward、cache、loop、reload 和 loadbalance,在进行域名解析时,这些插件将以从上到下的顺序依次执行:
cluster.local {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local 169.169.0.0/16 {
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
8、集群搭建--多master部署
1、部署Master2组件
① 将 k8s-master-1 上相关文件拷贝到 k8s-master-2 上
创建k8s工作目录:
# mkdir -p /k8s/kubernetes
# mkdir -p /k8s/etcd
拷贝 k8s 配置文件、执行文件、证书:
# scp -r /k8s/kubernetes/{cfg,ssl,bin} root@k8s-master-2:/k8s/kubernetes
# cp /k8s/kubernetes/bin/kubectl /usr/local/bin/
拷贝 etcd 证书:
# scp -r /k8s/etcd/ssl root@k8s-master-2:/k8s/etcd
拷贝 k8s 服务的service文件:
# scp /usr/lib/systemd/system/kube-* root@k8s-master-2:/usr/lib/systemd/system
② 修改 k8s-master-2 上的配置文件
修改 kube-apiserver.conf,修改IP为本机IP
③ 启动 k8s-master-2 组件
重新加载配置:
# systemctl daemon-reload
启动 kube-apiserver:
# systemctl start kube-apiserver # systemctl enable kube-apiserver
启动 kube-controller-manager:
# systemctl start kube-controller-manager # systemctl enable kube-controller-manager
部署 kube-scheduler:
# systemctl start kube-scheduler # systemctl enable kube-scheduler
④ 验证
2、部署nginx负载均衡
为了保证 k8s master 的高可用,将使用 k8s-lb-master 和 k8s-lb-backup 这两台机器来部署负载均衡。这里使用 nginx 做负载均衡器,
下面分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上部署 nginx。
① gcc等环境安装,后续有些软件安装需要这些基础环境
# gcc安装:
# yum install gcc-c++
# PCRE pcre-devel 安装:
# yum install -y pcre pcre-devel
# zlib 安装:
# yum install -y zlib zlib-devel
#OpenSSL 安装:
# yum install -y openssl openssl-devel
② 安装nginx
# rpm -ivh https://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
③ apiserver 负载配置
# vim /etc/nginx/nginx.conf
增加如下配置:
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log /var/log/nginx/k8s-access.log main;
upstream k8s-apiserver {
server 192.168.31.24:6443;
server 192.168.31.26:6443;
}
server {
listen 6443;
proxy_pass k8s-apiserver;
}
}
④ 启动 nginx
# systemctl start nginx # systemctl enable nginx
3、部署keepAlive
为了保证 nginx 的高可用,还需要部署 keepalive,keepalive 主要负责 nginx 的健康检查和故障转移。
① 分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上安装 keepalive
# yum install keepalived -y
② master 启动 keepalived
修改 k8s-lb-master keepalived 配置文件
vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id NGINX_MASTER
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
}
# vrrp实例
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.134.100/24
}
track_script {
check_nginx
}
}
配置说明:
- vrrp_script:用于健康检查nginx状态,如果nginx没有正常工作,就会进行故障漂移,使备节点接管VIP,这里通过 shell 脚本来检查nginx状态
- state:keepalived 角色,主节点为 MASTER,备节点为 BACKUP
- interface:接口,配置本地网卡名,keepalived 会将虚拟IP绑定到这个网卡上
- virtual_router_id:#VRRP 路由ID实例,每个实例是唯一的
- priority:优先级,备服务器设置90
- advert_int:指定VRRP心跳包通告间隔时间,默认1秒
- virtual_ipaddress:VIP,要与当前机器在同一网段,keepalived 会在网卡上附加这个IP,之后通过这个IP来访问Nginx,当nginx不可用时,会将此虚拟IP漂移到备节点上。
增加 check_nginx.sh 脚本,通过此脚本判断 nginx 是否正常:
vim /etc/keepalived/check_nginx.sh
#!/bin/bash
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
exit 1;
else
exit 0;
fi
增加可执行权限:
# chmod +x /etc/keepalived/check_nginx.sh
启动 keepalived:
# systemctl start keepalived # systemctl enable keepalived
③ backup 启动 keepalived
修改 k8s-lb-backup keepalived 配置文件
vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id NGINX_BACKUP
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
}
# vrrp实例
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.134.100/24
}
track_script {
check_nginx
}
}
增加 check_nginx.sh 脚本:
vim /etc/keepalived/check_nginx.sh
#!/bin/bash
count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
exit 1;
else
exit 0;
fi
增加可执行权限:
# chmod +x /etc/keepalived/check_nginx.sh
启动 keepalived:
# systemctl start keepalived # systemctl enable keepalived
④ 验证负载均衡
keepalived 已经将VIP附加到MASTER所在的网卡上
BACKUP节点上并没有
关闭 k8s-lb-master 上的nginx,可看到VIP已经不在了
可以看到已经漂移到备节点上了,如果再重启 MASTER 上的 Ngnix,VIP又会漂移到主节点上
访问虚拟IP也可以访问