笔者利用手头几台云服务器搭建 k8s 集群,由于这几台云服务属于不同的云服务厂商,无法搭建局域网环境的 k8s 集群,故笔者搭建的是公网环境的 k8s 集群,在此做个记录, 以下均在 ubuntu 20.04 环境下进行
创建虚拟网卡
由于主机内看到的只有内网 IP, 而且几台云服务器位于不同的内网, 直接搭建会将内网 IP 注册进集群导致搭建不成功。解决方案:使用虚拟网卡绑定公网 IP, 使用该公网 IP 来注册集群
<code style="margin-left:0"># 所有主机都要创建虚拟网卡,并绑定对应的公网 ip sudo ifconfig eth0:1 139.198.108.103</code>
该设置方式在重启服务器后失效,持久化需要将配置写入
/etc/network/interfaces
或/etc/netplan/50-cloud-init.yaml
更新 /etc/hosts
将集群所有节点的公网 ip 和 hostname 对应关系写入/etc/hosts
中
<code style="margin-left:0">sudo vi /etc/hosts</code>
关闭 swap 分区
<code style="margin-left:0">sudo swapoff -a # 注释掉 fstab 中 swap 分区的挂载信息 sudo sed -ri 's/.*swap.*/#&/' /etc/fstab</code>
配置 systemd 来管理 docker 的 cgroup
<code style="margin-left:0">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</code>
允许 iptables 检查桥接流量
<code style="margin-left:0">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</code>
开启相关端口
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:用来与集群通信的命令行工具
<code style="margin-left:0">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</code>
修改 kubelet 启动参数
添加 kubelet 的启动参数--node-ip=公网IP
, 每个主机都要添加并指定对应的公网 ip, 添加了这一步才能使用公网 ip 来注册进集群
<code style="margin-left:0">sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf</code>
初始化 master 节点
<code style="margin-left:0">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</code>
报错及解决:
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
<code style="margin-left:0">1 docker pull coredns/coredns</code>
2.打 tag,修改镜像名
<code style="margin-left:0">1 docker tag coredns/coredns:latest registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.4</code>
3.删除多余镜像
<code style="margin-left:0"> 1 docker rmi coredns/coredns:latest</code>
初始化成功后输出如下
根据输出提示执行以下命令
<code style="margin-left:0">mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config</code>
记录下该命令,用于之后将 worker 节点加入集群
<code style="margin-left:0">kubeadm join 139.198.108.103:6443 --token hnop0o.t16okler9962rroq \ --discovery-token-ca-cert-hash sha256:64c85683ac63f820e64787ed47674c7d470574feebcfe0f2142f45699cfe8ec6</code>
修改kube-apiserver
参数
在 master 节点,kube-apiserver 添加--bind-address
和修改--advertise-addres
<code style="margin-left:0">sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml</code>
安装 flannel 网络
在 master 节点执行
<code style="margin-left:0"># 下载 flannel 的 yaml 配置文件 wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml</code>
修改 yaml 配置文件,添加两处地方和修改一处地方
<code style="margin-left:0">vi kube-flannel.yml</code>
<code style="margin-left:0">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" } }</code>
修改完后,开始安装网络插件
<code style="margin-left:0">kubectl apply -f kube-flannel.yml</code>
执行如下命令,等待一会儿,直到所有的容器组处于 Running 状态
<code style="margin-left:0">watch -n 1 kubectl get pod -n kube-system -o wide</code>
worker 节点加入集群
使用初始化 master 节点成功后输出的命令来加入集群,或者在 master 节点重新打印 token 和加入命令
<code style="margin-left:0">kubeadm token create --print-join-command</code>
在 worker 节点执行命令加入集群
<code style="margin-left:0">sudo kubeadm join 139.198.108.103:6443 --token wm2039.cf8qnsrgyip6qvsz --discovery-token-ca-cert-hash sha256:64c85683ac63f820e64787ed47674c7d470574feebcfe0f2142f45699cfe8ec6</code>
等待所有需要加入的节点加入成功后,在 master 节点执行下面命令,并等待所有节点状态变为 Ready (笔者搭建的一主两从的集群,均使用的公网 ip)
<code style="margin-left:0">kubectl get nodes</code>
测试
master 节点执行下面命令来部署 nginx
<code style="margin-left:0">kubectl create deploy my-nginx --image=nginx kubectl expose deploy my-nginx --port=80 --type=NodePort</code>
查看 nginx 部署的 pod 信息,可以看到 Pod ip,以及部署在哪一个节点上
<code style="margin-left:0">kubectl get pods -o wide</code>
尝试 ping Pod 的 ip,如果无法 ping 通,执行
<code style="margin-left:0">sudo iptables -P FORWARD ACCEPT</code>
docker 从 1.13 版本开始,可能将 iptables FORWARD chain 的默认策略设置为了 DROP,该设置会导致 ping 其他 node 上的 Pod ip 失败
查看 nginx 对外暴露的端口
<code style="margin-left:0">kubectl get all</code>
可以看到对外暴露的端口是 30950, 如果分别通过集群内所有节点的公网 ip 访问这个端口,能请求到 nginx 主页,则证明部署成功
安装 Dashboard
下载 dashboard 的 yaml 描述文件
<code style="margin-left:0">wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml</code>
修改下载下来的 recommend.yaml
<code style="margin-left:0">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</code>
应用修改后的 yaml 文件,创建 dashboard 服务
<code style="margin-left:0">kubectl apply -f recommended.yaml</code>
现在可以通过 30001 端口访问 dashboard 的登录页面了
如果使用的是 chrome 浏览器并出现了以上页面,可以鼠标点击页面任意地方,然后键盘输入 thisisunsafe。正常访问会进入 Login 页面,提示需要授权
接下来创建 admin 用户来获取 token
<code style="margin-left:0">vi dashboard-admin.yaml</code>
<code style="margin-left:0">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</code>
创建 admin 用户并获取 token
<code style="margin-left:0">kubectl apply -f dashboard-admin.yaml kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')</code>
在 Login 页面输入 token 后就可以成功访问 dashboard 页面了
本文作者: Ifan Tsai (菜菜)
本文链接: https://www.caiyifan.cn/p/d6990d10.html
版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
未经允许不得转载:木盒主机 » 公网环境搭建 k8s 集群