假设现在有3个node节点和3个master节点,node1到底是连到master1还是连到master2还是master3,需要有人来分配,这个中间人就是load balancer,load balancer起到两个作用,一是负载。二是检查master状态,如果master1异常,就会使node连到master2上,如果master1正常,则正常提供服务。由于节点之间互相访问是通过IP连接,这里也是一样的,只不过是通过VIP(虚拟ip)连接。
keepalived:检查master状态,是否正常运行;配置虚拟IP。
haproxy:负载均衡服务器,起到负载作用。
master具体组件:apiserver, controller-manager, scheduler。
前提条件:
①固定四台主机IP,参考文章固定虚拟机IP
②可连外网
主机 | IP |
---|---|
master1 | 192.168.2.200 |
master2 | 192.168.2.201 |
master3 | 192.168.2.204 |
node1 | 192.168.2.202 |
虚拟IP | 192.168.2.203 |
我们以3台master,1台node为例,首先准备好4台服务器,分别在四台服务器上做操作。
# 关闭防火墙
systemctl disable firewalld #永久关闭,移除开机自启项,以后开机不会启动
systemctl stop firewalld #临时关闭,立刻关闭
# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config # 修改selinux配置文件为关闭状态,以后开机不会启动
setenforce 0 #临时关闭,立刻关闭
# 关闭swap分区
sed -ri 's/.*swap.*/#&/' /etc/fstab # 修改swap配置文件为关闭状态,以后开机不会启动
swapoff -a #临时关闭,立刻关闭
# 根据规划设置主机名
hostnamectl set-hostname
bash # 刷新
# 在master中添加hosts,每一个master都要执行
cat >> /etc/hosts << EOF
192.168.2.203 k8s-vip
192.168.2.200 master1
192.168.2.201 master2
192.168.2.204 master3
192.168.2.202 node1
EOF
# 将桥接的 IPv4 流量传递到 iptables 的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
cat >> /etc/sysctl.conf<.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.neigh.default.gc_thresh1=4096
net.ipv4.neigh.default.gc_thresh2=6144
net.ipv4.neigh.default.gc_thresh3=8192
EOF
#加载
modprobe br_netfilter
sysctl -p
sysctl --system # 生效
--------------------------------
# 时间同步
yum -y install ntpdate
ntpdate time.windows.com
如果执行过程中出错,参考这篇文章,错误汇总
# 安装相关依赖
yum install -y conntrack-tools libseccomp libtool-ltdl
# 安装keepalived
yum install -y keepalived
cat > /etc/keepalived/keepalived.conf <! Configuration File for keepalived
global_defs {
router_id k8s
}
vrrp_script check_haproxy {
script "killall -0 haproxy" # 检测haproxy是否存在
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state MASTER # 主节点
interface ens33 # ens33 为网卡名称,可以使用ifconfig查看自己的网卡名称
virtual_router_id 51
priority 250 # 权重,keepalived的master节点必须大于keepalived的backup节点
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab # 密钥,master和backup密钥必须一致
}
virtual_ipaddress {
192.168.2.203 # 虚拟ip
}
track_script {
check_haproxy
}
}
EOF
cat > /etc/keepalived/keepalived.conf <! Configuration File for keepalived
global_defs {
router_id k8s
}
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state BACKUP # 从节点
interface ens33 # ens33 为网卡名称
virtual_router_id 51
priority 200 # 必须小于MASTER权重
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab # 密钥,于MASTER一致
}
virtual_ipaddress {
192.168.2.203 # 虚拟ip
}
track_script {
check_haproxy
}
}
EOF
# 启动keepalived
systemctl start keepalived.service
# 设置开机启动
systemctl enable keepalived.service
# 查看启动状态
systemctl status keepalived.service
启动后查看master的网卡信息。由于虚拟IP配到了master1上,执行后,master1节点上会多出一个IP,即为虚拟IP;master2和master3上没有,挂上master1后才会出现。
ip a s ens33
# 安装haproxy
yum install -y haproxy
cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#---------------------------------------------------------------------
frontend kubernetes-apiserver
mode tcp
bind *:16443 #默认监听端口16443
option tcplog
default_backend kubernetes-apiserver
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
mode tcp
balance roundrobin
server master01.k8s.io 192.168.2.200:6443 check # 修改IP
server master02.k8s.io 192.168.2.201:6443 check # 修改IP
server master03.k8s.io 192.168.2.204:6443 check # 修改IP
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
bind *:1080
stats auth admin:awesomePassword
stats refresh 5s
stats realm HAProxy\ Statistics
stats uri /admin?stats
EOF
# 启动 haproxy
systemctl start haproxy
# 设置开启自启
systemctl enable haproxy
# 查看启动状态
systemctl status haproxy
启动后,检查端口,查看对应的端口是否包含 16443
netstat -tunlp | grep haproxy
所有节点安装Docker/kubeadm/kubelet ,Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。
# 下载docker的yum源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
# 安装docker,找上一步的yum源去安装
yum -y install docker-ce-18.06.1.ce-3.el7
# 开机自启动并且启动docker
systemctl enable docker && systemctl start docker
# 查看docker状态
systemctl status docker
# 查看docker版本
docker --version
# 设置docker拉取镜像的加速器
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
# 重启docker
systemctl daemon-reload
systemctl restart docker
cat >/etc/yum.repos.d/docker.repo<[docker-ce-edge]
name=Docker CE Edge - \$basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
# 重启docker
systemctl restart docker
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 安装kubelet、kubeadm、kubectl,同时指定版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# 启动并设置开机启动
systemctl start kubelet
systemctl enable kubelet
在具有vip的master上进行初始化操作,这里为master1
# 创建文件夹
mkdir /usr/local/kubernetes/manifests -p
# 到manifests目录
cd /usr/local/kubernetes/manifests/
# 新建yaml文件
vim kubeadm-config.yaml
下面内容修改IP 后复制进去
apiVersion: kubeadm.k8s.io/v1beta2 # 集群主版本,根据集群版本号决定
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.2.200 #本机ip
bindPort: 6443 #apiserver集群端口号
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: k8s-master1 #本机hostname
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
certSANs:
- k8s-master1
- k8s-master2
- k8s-master3
- 192.168.2.200 # master1 ip
- 192.168.2.201 # master2 ip
- 192.168.2.204 # master3 ip
- 192.168.2.203 # 虚拟vip keepalive出来的ip
- 127.0.0.1
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 2m0s # 注册时间2分钟
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes # 集群名字
controlPlaneEndpoint: "192.168.2.203:16443" # 虚拟ip + haproxy绑定的端口号
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.18.0 # 集群版本,需要与kubeadm版本一致
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 # pod 内网ip网段
serviceSubnet: 10.96.0.0/12 # svc 内网ip网段
scheduler: {}
这里补充一个自动生成kubeadm-config.yaml
文件的命令,生成模板后需要修改。kubeadm config print init-defaults > kubeadm-config.yaml
.
kubeadm init --config kubeadm-config.yaml
执行完成后,就会在拉取镜像【需要等待…】
初始化节点
如果上面的yaml文件已经执行过一次,再次执行就会报错,这时,就需要将集群初始化后才能执行。
步骤:
# 1. 还原由 kubeadm init 或 kubeadm join 所做的更改
kubeadm reset -f
# 2. 删除相关文件
rm -rf /etc/kubernetes/*
rm -rf /var/lib/etcd/*
然后再次执行yaml文件即可。
按照执行出的结果提示配置环境变量,使用kubectl工具
# 执行下方命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 查看节点
kubectl get nodes
# 查看集群健康状态
kubectl get cs
# 查看pod
kubectl get pods -n kube-system
由于没有安装网络插件,所以会有pending状态,无妨,继续往下执行就好了。
按照提示保存以下内容,一会要使用
kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
--discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08 \
--control-plane
–control-plane : 只有在添加master节点的时候才有
从官方地址获取到flannel的yaml,在master1上执行
# 创建文件夹
mkdir flannel
cd flannel
# 下载yaml文件
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
安装flannel网络,执行完apply之后需要等待一会,pending状态才会变成running。
kubectl apply -f kube-flannel.yml
检查,都已经running,且master已经ready。
kubectl get pods -n kube-system
从master1复制密钥及相关文件到master2、master3
# master1中执行,修改IP,分别改为master2/3的IP执行2遍
ssh root@192.168.2.201 mkdir -p /etc/kubernetes/pki/etcd # 修改IP;master2\master3的IP,用master1连接master2\master3;输入密码
# 复制相应的文件到master2/master3
scp /etc/kubernetes/admin.conf root@192.168.2.201:/etc/kubernetes
scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@192.168.2.201:/etc/kubernetes/pki
scp /etc/kubernetes/pki/etcd/ca.* root@192.168.2.201:/etc/kubernetes/pki/etcd
在master2、master3上执行在master1上init后输出的join命令,需要带上参数–control-plane表示把master控制节点加入集群。
# master2&master上依次执行
kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
--discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08 \
--control-plane
在master1上检查状态
kubectl get nodes
kubectl get pods --all-namespaces
向集群添加新节点,执行在kubeadm init输出的kubeadm join命令,不加参数–control-plane
# 在node1上执行
kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
--discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08
提示:
#token是有时间期限的,如果过期了,执行如下命令获取后再执行。 kubectl create token --print-join-command #补充一个生成certificate-key的命令 kubeadm init phase upload-certs --upload-certs
报错解决,没有错误继续往下
执行命令后,报错no such host,如下:
这时候,需要将node1节点里的hosts表里的内容保持与master节点一致,再次执行就可以了。
集群网络重新安装,因为添加了新的node节点
# 在master1节点上执行
kubectl apply -f flannel/kube-flannel.yml
检查状态
kubectl get nodes
kubectl get pods --all-namespaces
在Kubernetes集群中创建一个pod,验证是否正常运行:
# 创建nginx deployment
kubectl create deployment nginx --image=nginx
# 暴露端口
kubectl expose deployment nginx --port=80 --target-port=80 --type=NodePort
# 查看状态
kubectl get pod,svc
然后通过任何一个master或node节点或者虚拟IP加上端口号,都能够访问nginx页面;如果想要通过域名访问服务,可以参考这篇文章。注意一定要在master节点上添加污点容忍,不然无法通过虚拟IP 对应域名进行访问。这里要用第二种方式部署ingress-controller。
我们现在有3个master节点,1个node节点,经过上述测试,发现集群可以正常访问nginx服务,因为三台master在正常运行,我们现在模拟挂掉一台master,让另外2台master正常运行,看一下会有什么效果:
kubectl get nodes
命令,发现各个节点都处于ready状态kubectl get nodes
命令,发现报错了,显示无法连接到服务器。