公网云服务器搭建k8s不是一件很好玩的事,会遇到各种麻烦,个人建议如果有条件直接在内网组建即可
一、集群配置与建立
注意:选择的Master节点必须>=2核CPU
master | node1 | node2 | |
---|---|---|---|
IP(公网) | 211.159.224.10 | 124.223.56.111 | 47.103.203.223 |
IP(私有) | 10.0.16.15 | 10.0.16.14 | 172.17.59.2 |
操作系统 | Centos7.6 | Centos7.6 | Centos7.6 |
三台腾讯云服务器搭建k8s v1.23.0版本,下面具体的操作会在括号中表明是哪些主机需要的操作
二、前置工作
2.1 创建虚拟网卡(每个主机)
我们直接使用服务器公网IP启动K8S集群,但是直接是不行的,服务器上没有这个IP的网卡,所以我们需要在对应网卡上创建一个对应公网IP的虚拟网卡:
更新系统
yum -y update
yum -y upgrade
创建虚拟网卡
# 添加虚拟网卡
tee /etc/sysconfig/network-scripts/ifcfg-eth0:1 <<-'EOF'
DEVICE=eth0:1
ONBOOT=yes
BOOTPROTO=static
IPADDR=这里请修改为你实际的公网IP
NETMASK=255.255.255.0
EOF
# 重启生效
service network restart
2.2 安装前的设置(每个主机)
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
setenforce 0 # 临时
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
# 关闭swap
swapoff -a # 临时
sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
根据规划设置主机名
# 在master服务器上执行
hostnamectl set-hostname master
# 在node1服务器上执行
hostnamectl set-hostname node1
# 在node2服务器上执行
hostnamectl set-hostname node2
在master添加hosts (换成自己的IP)
cat >> /etc/hosts << EOF
<这里改成master节点公网IP> master
<这里改成node1节点公网IP> node1
<这里改成node2节点公网IP> node2
EOF
# 将桥接的IPv4流量传递到iptables的链
```bash
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 生效
sysctl --system
时间同步(每个主机)
yum install ntpdate -y
ntpdate time.windows.com
2.3 安装安装包(每个主机)
安装Docker
# 更新安装源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
# 安装
yum -y install docker-ce-18.06.1.ce-3.el7
安装kubeadm,kubelet和kubectl
由于版本更新频繁,这里指定版本号部署
# 更新安装源
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
# 安装
yum install -y kubelet-1.23.0 kubeadm-1.23.0 kubectl-1.23.0
开启自启+启动docker\kubelet
systemctl enable docker && systemctl start docker
systemctl enable kubelet && systemctl start kubelet
更新docker配置,不然k8s启动不了
# 如果已经存在daemon.json 建议删除重新按下面的来操作
tee /etc/docker/daemon.conf <<-'EOF'
{
"exec-opts":["native.cgroupdriver=systemd"],
"registry-mirrors": [
"http://mirrors.aliyuncs.com",
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"]
}
EOF
# 重启docker
systemctl daemon-reload && systemctl restart docker
2.4 开启云服务器端口(每个主机)
很重要的一步,如果开启的不好会导致服务无法访问,如果是云服务器还要登录服务商控制台在防火墙中打开以下端口
控制面/Master
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 6443 | Kubernetes API server | 所有 |
TCP | 入站 | 2379-2380 | etcd server client API kube-apiserver | etcd |
TCP | 入站 | 10250 | Kubelet API | 控制面板 |
TCP | 入站 | 10259 | kube-scheduler | 自身 |
TCP | 入站 | 10257 | kube-controller-manager | 自身 |
TCP | 入站 | 30000-32767 | NodePort Services | 所有 |
UDP | 入站 | 8472 | vxlan Overlay 网络通信 | Overlay 网络 |
尽管 etcd 的端口也列举在控制面的部分,但你也可以在外部自己托管 etcd 集群或者自定义端口。
批量开端口(master)
iptables -A INPUT -p tcp -m tcp --dport 6443 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 2379 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 2380 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 10250 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 10259 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 10257 -j ACCEPT
iptables -A INPUT -p tcp --dport 30000:32767 -j ACCEPT
iptables -I INPUT -p UDP --dport 8472 -j ACCEPT
service iptables save
工作节点
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 10250 | Kubelet API | 控制面板 |
TCP | 入站 | 30000-32767 | NodePort Services | 所有 |
UDP | 入站 | 8472 | vxlan Overlay 网络通信 | Overlay 网络 |
批量开端口(node1、node2)
iptables -A INPUT -p tcp -m tcp --dport 10250 -j ACCEPT
iptables -A INPUT -p tcp --dport 30000:32767 -j ACCEPT
iptables -I INPUT -p UDP --dport 8472 -j ACCEPT
service iptables save
NodePort Services是pod服务的默认端口范围。这里如果希望Master的IP也可以访问Pod服务,那么也可以给Master主机开放这些端口(建议)
四、搭建启动
- master初始化(master)
kubeadm init \
--apiserver-advertise-address=这里改成你的公网IP \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.0 \
--control-plane-endpoint=这里改成你的公网IP \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--v=5
创建成功的效果:
初始化成功后会给出提示,执行以下操作让Master主机上所有用户可以使用kubectl命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
并且还给出了其他节点加入集群的命令:
kubeadm join 211.159.224.96 --token esce21.q6hetwm8si29qxwn \
--discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
如果过期了可以重新获取:
kubeadm token create --print-join-command
2.如果这上步创建失败了,检查过问题后,按照下的步骤回退重新创建即可
rm -rf /etc/kubernetes/*
rm -rf ~/.kube/*
rm -rf /var/lib/etcd/*
lsof -i :6443|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10250|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10257|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10259|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :2379|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :2380|grep -v "PID"|awk '{print "kill -9",$2}'|sh
rm -rf /var/lib/kubelet/
rm -rf /var/lib/dockershim/
rm -rf /var/run/kubernetes
rm -rf /var/lib/cni
rm -rf /etc/kubernetes/*
rm -rf ~/.kube/*
rm -rf /var/lib/etcd/*
lsof -i :6443|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10257|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10259|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :2379|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :2380|grep -v "PID"|awk '{print "kill -9",$2}'|sh
echo "y" | kubeadm reset
注意,即使这样也没有删除掉k8s对本机网卡iptables转发的配置,完全的删除还需要执行:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm -C
ipvsadm --clear
执行ifconfig会发现还有一些虚拟veth、cni、flannel等设备都可以通过ip link delete xxx删除掉
如果创建失败是卡在:
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
则重新创建,在卡住的时候修改以下三行,这时会自动重试完成创建
vim /etc/kubernetes/manifests/etcd.yaml
- --listen-client-urls=https://0.0.0.0:2379
- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-peer-urls=https://0.0.0.0:2380
- 修改kube-apiserver参数(Master)
在 master 节点,kube-apiserver 添加–bind-address=0.0.0.0和修改–advertise-address=<公网IP>
vi /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 你的公网IP:6443
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --bind-address=0.0.0.0
- --advertise-address=你的公网IP
- work node加入(work node)
在每个work node上执行一下上面的join指令即可:
# 在执行时,需要把命令里的 \ 删掉
kubeadm join 211.159.224.96 --token esce21.q6hetwm8si29qxwn \
--discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
- 安装CNI网络插件(Master),使用flannel, 在master节点执行
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
修改 yaml 配置文件,添加两处地方:
vi kube-flannel.yml
containers:
- name: kube-flannel
#image: flannelcni/flannel:v0.17.0 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel:v0.17.0
command:
- /opt/bin/flanneld
args:
- --public-ip=$(PUBLIC_IP)
- --iface=eth0
- --ip-masq
- --kube-subnet-mgr
env:
- name: PUBLIC_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
安装插件:
kubectl apply -f kube-flannel.yml
- 检查状态(Master)
# 检查集群状态:
kubectl get nodes
#检查系统Pods状态:
watch -n 1 kubectl get pod -n kube-system -o wide
五、测试
master 节点执行下面命令来部署 nginx
kubectl create deploy my-nginx --image=nginx
kubectl expose deploy my-nginx --port=80 --type=NodePort
查看 nginx 部署的 pod 信息,可以看到 Pod ip,以及部署在哪一个节点上
kubectl get pods -o wide
每一台机子都ping一下Pod的IP,看看是否能Ping通,如果不行,先执行sudo iptables -P FORWARD ACCEPT, 如果还是不行, 那么检查主机的UDP端口8472是否开启
测试NodePort:
kubectl get svc -o wide
用每个主机的公网IP + 这里的端口号,看看是否都可以访问Nginx服务,如果都可以那么集群就ok了,如果不行就检查端口是否开放(特别是Master)
测试master直接进入子节点容器
kubectl exec -it my-nginx-9b596c8c4-k2zcp /bin/bash
如果这里超时连不上,则可以做一个内网转发,然后重试即可
iptables -t nat -A OUTPUT -d <连接超时的内网IP> -j DNAT --to-destination <连不上的子节点公网IP>
service iptables save