Blog.091 K8S 单节点二进制部署 Day 1:Etcd 集群与 Flannel 网络配置
本章目录
1. K8S 的部署方式
2. K8S 二进制部署 ①
2.1 环境准备
2.2 部署 ectd 集群
2.3 部署 docker 引擎
2.4 flannel 网络配置
常见的 K8S 按照部署方式:
- Minikube:
Minikube 是一个工具,可以在本地快速运行一个单节点微型 K8S,仅用于学习、预览 K8S 的一些特性使用。
部署地址:https://kubernetes.io/docs/setup/minikube
- Kubeadmin:
Kubeadmin 也是一个工具,提供 kubeadm init 和 kubeadm join,用于快速部署 K8S 集群,新手推荐。
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
- 二进制安装部署:
生产首选,特点是稳定可调控,从官方下载发行版的二进制包,手动部署每个组件和自签 TLS 证书,组成 K8S 集群,新手推荐。
https://github.com/kubernetes/kubernetes/releases
Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。
推荐使用二进制包部署 Kubernetes 集群,虽然手动部署麻烦点,但期间可以学习很多工作原理,也利于后期维护。

先准备3台主机,首先搭建Master单节点集群。
因为 Master 是整个 K8S 集群的大脑,没有 Master 接下来的每一步操作都会变得不可控。
同时我们需要在节点上同时搭建 etcd 存储集群:
在生产环境中会使用 etcd 集群做高可用,它的数目必须是3台或3台以上的奇数台。
etcd 存储单独部署可以节约存储,和 Master 放在一起方便内网通信节约机器。
只要能保证内网环境稳定和服务器数量充足,一般都会单独部署。
- K8S 集群 Master01:192.168.80.10:kube-apiserver、kube-controller-manager、kube-scheduler、etcd
- K8S 集群 Node01:192.168.80.11:kubelet、kube-proxy、docker、flannel、etcd
- K8S 集群 Node02:192.168.80.12:kubelet、kube-proxy、docker、flannel、etcd
(1)所有主机关闭防火墙
1 systemctl stop firewalld 2 systemctl disable firewalld
(2)所有主机关闭 selinux
1 setenforse 0 2 sed -i ‘s/enforcing/disabled/’ /etc/selinux/config
(3)所有主机关闭 swap
1 swapoff -a 2 sed -ri ‘s/.*swap.*/#&/’ /etc/fstab
(4)根据规划设置主机名
1 hostnamectl set-hostname master01 2 hostnamectl set-hostname node01 3 hostnamectl set-hostname node02
(5)在 master 添加 hosts
1 cat >> /etc/hosts << EOF 2 192.168.80.10 master01 3 192.168.80.11 node01 4 192.168.80.12 node02 5 EOF
(6)所有主机将桥接的 ipv4 流量传递到 iptables 的链
1 cat > /etc/sysctl.d/k8s.conf << EOF 2 net.bridge.bridge-nf-call-ip6tables = 1 3 net.bridge.bridge-nf-call-iptables = 1 4 EOF 5 6 sysctl --system
(7)所有主机时间同步
1 yum install ntpdate -y 2 ntpdate time.windows.com
etcd 的目标是构建一个高可用的分布式键值数据库。
它的内部采用 raft 协议作为一致性算法,etcd 是 go 语言编写的。
etcd 作为服务发现系统,有以下的特点:
- 简单:安装配置简单,而且提供了 http api 进行交互,使用也很简单
- 安全:支持 ssl 证书验证
- 快速:单实例支持每秒 2k+ 读操作
- 可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性
etcd 目前默认使用 2379 端口提供 http api 服务;2380 端口和 peer 通信。
即 etcd 默认使用 2379 端口对外为客户端提供通讯,使用 2380 进行服务器间内部, etcd 和 etcd 之间通讯。
由于 etcd 的 leader 选举机制,要求至少为 3 台或以上的奇数台。
(1)准备签发证书环境
CFSSL 是 CloudFlare 公司开源的一款 PKI/PLS 工具。
CFSSL 包含一个命令行工具和一个用于签名、验证和捆绑 TLS 证书的 HTTP API 服务。使用 Go 语言编写。
CFSSL 使用配置文件生成证书,因此自签之前,需要生成它识别的 json 格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。
CFSSL 用来为 etcd 提供 TLS 证书,它支持签三种类型的证书:
- client 证书,服务端连接客户端时携带的证书,用于客户端验证服务端身份,如 kube-apiserver 访问 etcd;
- server 证书,客户端连接服务端时携带的证书,用于服务端验证客户端身份,如 etcd 对外提供服务;
- peer 证书,相互之间连接时使用的证书,如 etcd 节点之间进行验证和通信。
这里全部都使用同一套证书认证。
(2)master01:下载证书制作工具
1 #在 master01 上下载制作工具 2 wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl 3 wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson 4 wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo 5 或 6 curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl 7 curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson 8 curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo 9 10 #授予执行权限 11 chmod +x /usr/local/bin/cfssl*
或
1 [root@master01 etcd-cert]# cd /usr/local/bin/ 2 [root@master01 bin]# rz -E(cfssl cfssl-certinfo cfssljson) 3 [root@master01 bin]# chmod +x * 4 [root@master01 bin]# ls 5 cfssl cfssl-certinfo cfssljson
- cfss1:证书签发的工具命令
- cfssljson:将 cfss1 生成的证书(json 格式)变为文件承载式证书
- cfssl-certinfo:验证证书的信息
- cfssl-certinfo -cert <证书名称> :看证书的信息

(3)创建 K8S 工作目录,生成 CA 证书以及 etcd 证书私钥
1 #创建k8s工作目录 2 [root@master01 opt]# mkdir /opt/k8s 3 [root@master01 opt]# cd /opt/k8s/ 4 5 #上传etcd-cert.sh 和 etcd.sh 到/opt/k8s目录 6 [root@master01 k8s]# ls etcd-cert.sh etcd.sh 7 etcd-cert.sh etcd.sh 8 9 #添加x 权限 10 [root@master01 k8s]# chmod +x etcd-cert.sh etcd.sh 11 12 #创建用于生成CA证书,etcd服务器证书及私钥的目录 13 [root@master01 k8s]# mkdir /opt/k8s/etcd-cert 14 [root@master01 k8s]# mv etcd-cert.sh etcd-cert 15 [root@master01 k8s]# cd /opt/k8s/etcd-cert/ 16 17 #注意,看一下脚本,把ip改为自己的 18 [root@master01 etcd-cert]# vim etcd-cert.sh 19 20 #执行脚本,生成CA证书,etcd服务器证书以及私钥 21 [root@master01 etcd-cert]# ./etcd-cert.sh 22 23 [root@master01 etcd-cert]# ls 24 ca-config.json ca-csr.json ca.pem server.csr server-key.pem 25 ca.csr ca-key.pem etcd-cert.sh server-csr.json server.pe



(4)上传 etcd-cert.sh 和 etcd.sh 到 /opt/k8s 目录中
1 #etcd 二进制包地址: https://github.com/etcd-io/etcd/release 2 3 #上传etcd-v3.3.10 包到/opt/k8s目录中,解压 4 [root@master01 k8s]# ls etcd-v3.3.10-linux-amd64.tar.gz 5 etcd-v3.3.10-linux-amd64.tar.gz 6 7 [root@master01 k8s]# tar xf etcd-v3.3.10-linux-amd64.tar.gz 8 9 [root@master01 k8s]# ls etcd-v3.3.10-linux-amd64 10 Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
etcd 就是 etcd 服务的启动命令,后面可以跟各种启动参数;
etcdctl 主要为 etcd 服务提供了命令行操作。

(5)创建用于存放 etcd 配置文件,命令文件,证书的目录
1 [root@master01 k8s]# mkdir -p /opt/etcd/{cfg,bin,ssl} 2 [root@master01 k8s]# mv /opt/k8s/etcd-v3.3.10-linux-amd64/etcd /opt/k8s/etcd-v3.3.10-linux-amd64/etcdctl /opt/etcd/bin/ 3 [root@master01 k8s]# cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/ 4 5 [root@master01 k8s]# ls -R /opt/etcd/bin/ /opt/etcd/ssl/ 6 /opt/etcd/bin/: 7 etcd etcdctl 8 9 /opt/etcd/ssl/: 10 ca-key.pem ca.pem server-key.pem server.pem

1 [root@master01 k8s]# pwd 2 /opt/k8s 3 [root@master01 k8s]# ls etcd.sh 4 etcd.sh 5 6 [root@master01 k8s]# ./etcd.sh etcd01 192.168.23.103 etcd02=https://192.168.23.104:2380,etcd03=https://192.168.23.105:2380 7 8 #新开一个终端查看 9 [root@master01 k8s]# ps -ef | grep etcd

(6)另外打开一个窗口查看 etcd 进程是否正常

(7)把 etcd 相关证书文件和命令文件全部拷贝到另外两个 etcd 节点
1 [root@master01 k8s]# scp -r /opt/etcd/ 192.168.23.104:/opt/ 2 [root@master01 k8s]# scp -r /opt/etcd/ 192.168.23.105:/opt/ 3 4 #node1修改etcd文件 5 [root@node01 cfg]# vim /opt/etcd/cfg/etcd 6 #[Member] 7 ETCD_NAME="etcd02 8 ETCD_DATA_DIR="/var/lib/etcd/default.etcd" 9 ETCD_LISTEN_PEER_URLS="https://192.168.23.104:2380" 10 ETCD_LISTEN_CLIENT_URLS="https://192.168.23.104:2379" 11 12 #[Clustering] 13 ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.23.104:2380" 14 ETCD_ADVERTISE_CLIENT_URLS="https://192.168.23.104:2379" 15 ETCD_INITIAL_CLUSTER="etcd01=https://192.168.23.103:2380,etcd02=https://192.168.23.104:2380,etcd03=https://192.168.23.105:2380" 16 ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" 17 ETCD_INITIAL_CLUSTER_STATE="new" 18 19 #node2修改etcd文件 20 [root@node02 ~]# vim /opt/etcd/cfg/etcd 21 #[Member] 22 ETCD_NAME="etcd03" 23 ETCD_DATA_DIR="/var/lib/etcd/default.etcd" 24 ETCD_LISTEN_PEER_URLS="https://192.168.23.105:2380" 25 ETCD_LISTEN_CLIENT_URLS="https://192.168.23.105:2379" 26 27 #[Clustering] 28 ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.23.105:2380" 29 ETCD_ADVERTISE_CLIENT_URLS="https://192.168.23.105:2379" 30 ETCD_INITIAL_CLUSTER="etcd01=https://192.168.23.103:2380,etcd02=https://192.168.23.104:2380,etcd03=https://192.168.23.105:2380" 31 ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" 32 ETCD_INITIAL_CLUSTER_STATE="new"


(8)把 etcd 服务管理文件拷贝到另外两个 etcd 集群节点
1 [root@master01 k8s]# cd /usr/lib/systemd/system/ 2 [root@master01 system]# ls etcd.service 3 etcd.service 4 [root@master01 system]# pwd 5 /usr/lib/systemd/system 6 [root@master01 system]# scp etcd.service 192.168.23.104:`pwd` 7 [root@master01 system]# scp etcd.service 192.168.23.105:`pwd`

(9)在所有 etcd 节点上启动 etcd 服务
1 [root@master01 k8s]# systemctl restart etcd 2 [root@master01 k8s]# systemctl enable etcd 3 [root@master01 k8s]# systemctl status etcd 4 5 [root@node01 cfg]# systemctl daemon-reload 6 [root@node01 cfg]# systemctl start etcd 7 [root@node01 cfg]# systemctl enable etcd 8 [root@node01 cfg]# systemctl status etcd 9 10 [root@node02 ~]# systemctl daemon-reload 11 [root@node02 ~]# systemctl restart etcd 12 [root@node02 ~]# systemctl enable etcd.service 13 [root@node02 ~]# systemctl status etcd
(12)切换到 etcd3 版本查看集群节点状态和成员列表

1 export ETCDCTL_API=3 2 #v2和v3命令略有不同,etcd2 和etcd3也是不兼容的,默认是v2版本 3 etcdctl --write-out=table endpoint status 4 etcdctl --write-out=table member list 5 export ETCDCTL_API=2 6 #再切回v2版本

(1)所有 node 节点都要部署 docker 引擎
1 yum install -y yum-utils device-mapper-persistent-data 1vm2 2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 3 yum install -y docker-ce dqsker-ce-cli containerd.io 4 5 systemctl start docker.service 6 systemctl enable docker.service
K8S 中 pod 网络通信:
- pod 内 容器与容器之间的通信
在同一个 pod 内的容器(pod 内的容器是不会跨宿主机的)共享同一个网络命令空间,相当于它们在同一台机器上一样,可以用 localhost 地址访问彼此的端口。
- 同一个 node 内 pod 之间的通信
每个 pod 都有一个真实的全局 IP 地址,同一个 node 内的不同 pod 之间可以直接采用对方 pod 的 IP 地址进行通信,pod1 与 pod2 都是通过 veth 连接到同一个 docker0 网桥、网段,所以它们之间可以直接通信。
- 不同 node 上 pod 之间的通信
pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 node 之间的同新只能通过宿主机的物理网卡进行。
要想实现不同 node 上 pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通信。
因此要满足两个条件:pod 的 IP 不能冲突;将 pod 的 IP 和所在的 node 的 IP 关联起来,通过这个关联让不同 node 上 pod 之间直接通过内网 IP 地址通信。

Flannel 工作原理:
数据首先会从源 node 节点的 pod 发出,发出后会经由 docker0 网卡转发到 flannel0网卡,在 flannel0 网卡里有个 flanneld 服务会把这个数据包封装到 udp 报文中,然后根据自己在 tecd 中维护的路由表通过物理网卡转发到目标 node 节点,数据包到达目标 node 节点后会被 flanneld 服务解封装,然后经由 flannel0 网卡和 docker0 网卡转发到目标 pod 的容器。
- Overlay Network:
叠加网络,在二层或者三层基础网络上叠加的一层虚拟网络技术模式,该网络中的主机通过虚拟链路隧道连接起来(类似于 vpn);
- VXLAN:
将源数据包封装到 udp 中,并使用基础网络的 IP/MAC 作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址;
- Flannel:
让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。
Flannel 是 Overlay 网络的一种,也是将 tcp 源数据包封装在另一种网络包里面进行路由转发和通信,目前支持 udp、vxlan、host-gw 三种数据转发方式。
Flannel etcd:
存储管理 flannel 可分配的 IP 地址段资源;
监控 etcd 中每个 pod 的实际地址,并在内存中建立维护 pod 节点路由表。
(1)添加 flannel网络配置信息,写入分配的子网段到 etcd 中,供 flannel 使用
1 cd /opt/etcd/ssl 2 /opt/etcd/bin/etcdctl \ 3 --ca-file=ca.pem \ 4 --cert-file=server.pem \ 5 --key-file=server-key.pem \ 6 --endpoints="https://192.168.229.90:2379,https://192.168.229.80:2379,https://192.168.229.70:2379" \ 7 set /coreos.com/network/config '{"Network": "172.17.0.0/16","Backend": {"Type": "vxlan"}}'
- set /coreos.com/network/config:添加一条网络配置记求,这个配置将用于 flannel 分配给每个 docker 的虛拟 IP 地址段
- get <ckey>
- got /coreos.com/octwork/config:获取网络配置记录,后面不用再跟参数了
- Network:用于指定 flannel 地址池
- Backend:用于指定数据包以什么方式转发,默认为 udp 模式,Backend 为 vxlan 比起预设的 udp 性能相对好一些。

1 /opt/etcd/bin/etcdctl \ 2 --ca-file=ca.pem \ 3 --cert-file=server.pem \ 4 --key-file=server-key.pem \ 5 --endpoints="https://192.168.229.90:2379,https://192.168.229.80:2379,https://192.168.229.70:2379" \ 6 get /coreos.com/network/config

(2)拷贝 flannel 安装包到所有 node 节点
1 cd /opt 2 tar zxvf flannel-v0.10.0-1inux-amd64.tar.gz 3 flanneld 4 #flanneld为主要的执行文件 5 mk-docker-opts.sh 6 #mk-docker-opts . sh脚本用于生成Docker启动参数 7 README.md

(3)创建 k8s 工作目录
1 mkdir -p /opt/kubernetes/{cfg,bin,ss1} 2 cd /opt 3 mv mk-docker-opts.sh flanneld /opt/kubernetes/bin/

(4)开启 flannel 网络功能
1 cd /opt 2 chmod +x flannel.sh 3 ./flannel.sh https://192.168.229.90:2379,https://192.168.229.80:2379,https://192.168.229.70:2379

- flannel 启动后会生成一个 docker 网络相关信息配置文件 /run/flannel/subnet.env,包含了 docker 要使用 flannel 通讯的相关参数。
1 cat /run/flannel/subnet.env 2 DOCKER_OPT_BIP="--bip=172.17.26.1/24" 3 DOCKER_OPT_IPMASQ="--ip-masq= false" 4 DOCKER_OPT_MTU="--mtu=1450" 5 DOCKER_NETWORK_OPTIONS=" --bip=172.17.26.1/24 --ip-masq=false --mtu=1450"
- --bip:指定 docker 启动时的子网
- --ip-masq:设置 ipmasq=false 关闭 snat 伪装策略
- --mtu=1450:mtu 要留出 50 字节给外层的 vxlan 封包的额外开销使用
Flannel 启动过程解析:
- 从 etcd 中获取 network 的配置信息
- 划分 subnet, 并在 etcd 中进行注册
- 将子网信息记录到 /run/flannel/subnet.env 中

(5)配置 docker 连接 flannel
1 vim /lib/systemd/system/docker.service 2 [Service] 3 Type=notify 4 # the default is not to use systemd for cgroups because the delegate issues stillt 5 # exists and systemd currently dges not support the cgroup feature set requi red 6 # for containers run by docker
7 EnvironmentFile=/run/flannel/subnet.env 8 #添加
9 ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H fd:// --containerd=/run/containerd/containerd.sock 10 #修改
11 ExecReload=/bin/kill -s HUP $MAINPID 12 TimeoutSec=0 13 RestartSec=2 14 Restart=always

(6)重启 docker 服务,ifconfig 查看 docker0 和 flannel.1
1 systemctl daemon-reload 2 systemctl restart docker

(7)测试 ping 通对方 docker0 网卡证明 flannel 起到路由作用
1 ping 172.17.91.1 2 docker run -it centos:7 /bin/bash # node1 和 node2 都运行该命令 3 yum install net-tools -y # node1 和 node2 都运行该命令 4 ifconfig //再次测试 ping 通两个 node 中的 centos:7 容器




-
浙公网安备 33010602011771号