隐藏

如何在公网环境下搭建 k8s 集群?

发布:2022/12/16 17:10:25作者:管理员 来源:本站 浏览次数:675

笔者利用手头几台云服务器搭建 k8s 集群,由于这几台云服务属于不同的云服务厂商,无法搭建局域网环境的 k8s 集群,故笔者搭建的是公网环境的 k8s 集群,在此做个记录, 以下均在 ubuntu 20.04 环境下进行

创建虚拟网卡

由于主机内看到的只有内网 IP, 而且几台云服务器位于不同的内网, 直接搭建会将内网 IP 注册进集群导致搭建不成功。解决方案:使用虚拟网卡绑定公网 IP, 使用该公网 IP 来注册集群


# 所有主机都要创建虚拟网卡,并绑定对应的公网 ip

sudo ifconfig eth0:1 139.198.108.103

   该设置方式在重启服务器后失效,持久化需要将配置写入/etc/network/interfaces或/etc/netplan/50-cloud-init.yaml


更新 /etc/hosts


将集群所有节点的公网 ip 和 hostname 对应关系写入/etc/hosts中


sudo vi /etc/hosts


关闭 swap 分区


sudo swapoff -a

# 注释掉 fstab 中 swap 分区的挂载信息

sudo sed -ri 's/.*swap.*/#&/' /etc/fstab


配置 systemd 来管理 docker 的 cgroup


sudo mkdir /etc/docker

cat <<EOF | sudo tee /etc/docker/daemon.json

{

 "exec-opts": ["native.cgroupdriver=systemd"],

 "log-driver": "json-file",

 "log-opts": {

   "max-size": "100m"

 },

 "storage-driver": "overlay2"

}

EOF


sudo systemctl enable docker

sudo systemctl daemon-reload

sudo systemctl restart docker


允许 iptables 检查桥接流量


cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf

br_netfilter

EOF


cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

EOF

sudo sysctl --system


开启相关端口

master 节点

协议 方向 端口范围 作用 使用者

TCP 入站 6443 Kubernetes API 服务器 所有组件

TCP 入站 2379-2380 etcd 服务器客户端 API kube-apiserver、etcd

TCP 入站 10250 Kubelet API kubelet 自身、控制平面组件

TCP 入站 10251 kube-scheduler kube-scheduler 自身

TCP 入站 10252 kube-controller-manager kube-controller-manager 自身

worker 节点

协议 方向 端口范围 作用 使用者

TCP 入站 10250 Kubelet API kubelet 自身、控制平面组件

TCP 入站 30000-32767 NodePort 服务 所有组件

所有节点

协议 方向 端口范围 作用 使用者

UDP 入站 8472 vxlan Overlay 网络通信 Overlay 网络

安装 kubeadm、kubelet 和 kubectl


   kubeadm:用来初始化集群的指令


   kubelet:在集群中的每个节点上用来启动 Pod 和容器等


   kubectl:用来与集群通信的命令行工具


sudo apt install -y apt-transport-https ca-certificates curl


curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add

echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list


sudo apt update

sudo apt install -y kubelet kubeadm kubectl

sudo apt-mark hold kubelet kubeadm kubectl


修改 kubelet 启动参数


添加 kubelet 的启动参数--node-ip=公网IP, 每个主机都要添加并指定对应的公网 ip, 添加了这一步才能使用公网 ip 来注册进集群


sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf


image-20210809220253057

初始化 master 节点


sudo kubeadm init \

   --kubernetes-version=v1.22.0 \

   --apiserver-advertise-address=139.198.108.103 \

   --control-plane-endpoint=139.198.108.103 \

   --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \

   --service-cidr=10.10.0.0/16 \

   --pod-network-cidr=10.122.0.0/16


报错及解决:


ERROR ImagePull: failed to pull image registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.4: output: Error response from daemon: manifest for registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.4 not found: manifest unknown: manifest unknown


解决:


1.从官方镜像拉取 coredns


docker pull coredns/coredns


2.打 tag,修改镜像名


docker tag coredns/coredns:latest registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.4


3.删除多余镜像


docker rmi coredns/coredns:latest


初始化成功后输出如下

image-20210808145510236


根据输出提示执行以下命令


mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config


记录下该命令,用于之后将 worker 节点加入集群


kubeadm join 139.198.108.103:6443 --token hnop0o.t16okler9962rroq \

       --discovery-token-ca-cert-hash sha256:64c85683ac63f820e64787ed47674c7d470574feebcfe0f2142f45699cfe8ec6


修改kube-apiserver参数


在 master 节点,kube-apiserver 添加--bind-address和修改--advertise-addres


sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml


image-20210809221224565

安装 flannel 网络


在 master 节点执行






# 下载 flannel 的 yaml 配置文件

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml


修改 yaml 配置文件,添加两处地方和修改一处地方


vi kube-flannel.yml



args:

- --public-ip=$(PUBLIC_IP)

- --iface=eth0


env:

- name: PUBLIC_IP

  valueFrom:

    fieldRef:

      fieldPath: status.podIP


net-conf.json: |

 {

   "Network": "10.122.0.0/16",

     "Backend": {

       "Type": "vxlan"

     }

 }


image-20210809222538582


image-20210809222717398


image-20220126230053561


修改完后,开始安装网络插件




kubectl apply -f kube-flannel.yml


执行如下命令,等待一会儿,直到所有的容器组处于 Running 状态




watch -n 1 kubectl get pod -n kube-system -o wide


image-20220126233108588

worker 节点加入集群


使用初始化 master 节点成功后输出的命令来加入集群,或者在 master 节点重新打印 token 和加入命令



kubeadm token create --print-join-command


在 worker 节点执行命令加入集群


sudo kubeadm join 139.198.108.103:6443 --token wm2039.cf8qnsrgyip6qvsz --discovery-token-ca-cert-hash sha256:64c85683ac63f820e64787ed47674c7d470574feebcfe0f2142f45699cfe8ec6


image-20210808152039514


等待所有需要加入的节点加入成功后,在 master 节点执行下面命令,并等待所有节点状态变为 Ready (笔者搭建的一主两从的集群,均使用的公网 ip)



kubectl get nodes


image-20210808152200461

测试


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


image-20210809230648621


尝试 ping Pod 的 ip,如果无法 ping 通,执行



sudo iptables -P FORWARD ACCEPT


   docker 从 1.13 版本开始,可能将 iptables FORWARD chain 的默认策略设置为了 DROP,该设置会导致 ping 其他 node 上的 Pod ip 失败


查看 nginx 对外暴露的端口


kubectl get all


image-20210809230346570


可以看到对外暴露的端口是 30950, 如果分别通过集群内所有节点的公网 ip 访问这个端口,能请求到 nginx 主页,则证明部署成功


image-20210809232520672

安装 Dashboard


下载 dashboard 的 yaml 描述文件


wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml


修改下载下来的 recommend.yaml



kind: Service

apiVersion: v1

metadata:

 labels:

   k8s-app: kubernetes-dashboard

 name: kubernetes-dashboard

 namespace: kubernetes-dashboard

spec:

 ports:

   - port: 443

     targetPort: 8443

     nodePort: 30001    # 指定对外暴露的 port

 type: NodePort         # 指定服务类型为 NodePort

 selector:

   k8s-app: kubernetes-dashboard


image-20220903235042690


应用修改后的 yaml 文件,创建 dashboard 服务



kubectl apply -f recommended.yaml


现在可以通过 30001 端口访问 dashboard 的登录页面了


image-20220904000035011


如果使用的是 chrome 浏览器并出现了以上页面,可以鼠标点击页面任意地方,然后键盘输入 thisisunsafe。正常访问会进入 Login 页面,提示需要授权


image-20220904000346775


接下来创建 admin 用户来获取 token


vi dashboard-admin.yaml

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding

metadata:

 name: admin-user

roleRef:

 apiGroup: rbac.authorization.k8s.io

 kind: ClusterRole

 name: cluster-admin

subjects:

- kind: ServiceAccount

 name: admin-user

 namespace: kubernetes-dashboard

---

apiVersion: v1

kind: ServiceAccount

metadata:

 name: admin-user

 namespace: kubernetes-dashboard


创建 admin 用户并获取 token


kubectl apply -f dashboard-admin.yaml

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')


image-20220904000836247


在 Login 页面输入 token 后就可以成功访问 dashboard 页面了image-20220904001051285