php wap网站实现滑动式数据分页,免费企业网站建设介绍,营销展示型网站模板,wordpress置顶代码k8s 二进制安装 IP规划初始化部署 etcd 集群在 etcd01 节点上操作准备cfssl证书生成工具#xff0c;加权生成etcd证书上传etcd软件包启动 etcd 服务 部署 Master 组件部署 Worker Node 组件node 节点安装 docker部署组件 部署 CNI 网络组件部署 flannel简介部署 部署 Calico简… k8s 二进制安装 IP规划初始化部署 etcd 集群在 etcd01 节点上操作准备cfssl证书生成工具加权生成etcd证书上传etcd软件包启动 etcd 服务 部署 Master 组件部署 Worker Node 组件node 节点安装 docker部署组件 部署 CNI 网络组件部署 flannel简介部署 部署 Calico简介部署 部署 CoreDNSmaster02 节点部署负载均衡部署部署 Dashboard IP规划
主机名IPmaster01192.168.110.10master01192.168.110.40node01192.168.110.20node02192.168.110.30etcd01/lb01192.168.110.50etcd02/lb02192.168.110.60etcd03192.168.110.70
初始化
#关闭防火墙和核心防护
systemctl stop firewalld
systemctl disable firewalld
iptables -F iptables -t nat -F iptables -t mangle -F iptables -X
setenforce 0
sed -i s/enforcing/disabled/ /etc/selinux/config#设置主机名
hostnamectl set-hostname master01
su#在master添加hosts
cat /etc/hosts EOF
192.168.110.10 master01
192.168.110.40 master02
192.168.110.20 node01
192.168.110.30 node02
192.168.110.50 etcd01
192.168.110.60 etcd02
192.168.110.70 etcd03
EOF#调整内核参数
cat /etc/sysctl.d/k8s.conf EOF
net.bridge.bridge-nf-call-ip6tables 1
net.bridge.bridge-nf-call-iptables 1
net.ipv6.conf.all.disable_ipv61
net.ipv4.ip_forward1
EOFsysctl --system#时间同步
yum install ntpdate -y
ntpdate time.windows.com部署 etcd 集群
etcd是一个分布式键值存储系统用于在分布式系统中保存配置信息、元数据以及关键的共享状态。它是一个开源项目最初由CoreOS开发并维护现在由CNCF托管。etcd的设计目标是提供可靠的分布式存储以支持分布式系统的一致性和高可用性。 etcd 目前默认使用2379端口提供HTTP API服务 2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯使用端口2380来进行服务器间内部通讯。 etcd 在生产环境中一般推荐集群方式部署。由于etcd 的leader选举机制要求至少为3台或以上的奇数台。
在 etcd01 节点上操作
准备cfssl证书生成工具加权
#方法一下载
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo
chmod x /usr/local/bin/cfssl*#方法二上传已有压缩包 etcd.zip 到 /root
unzip etcd.zip
cd etcd/cfssl/
mv cfssl* /usr/local/bin/
chmod x /usr/local/bin/cfssl*生成etcd证书
#创建工作目录
mkdir /opt/k8s#上传 etcd-cert.sh 和 etcd.sh 到 /opt/k8s/ 目录中
cd ~/etcd/
mv etcd-cert.sh etcd.sh /opt/k8s
cd /opt/k8s
chmod x etcd-cert.sh etcd.sh#创建用于生成CA证书、etcd 服务器证书以及私钥的目录
mkdir /opt/k8s/etcd-cert
mv etcd-cert.sh etcd-cert/
cd /opt/k8s/etcd-cert/
./etcd-cert.sh#生成的证书
ls
ca-config.json ca-csr.json ca.pem server.csr server-key.pem
ca.csr ca-key.pem etcd-cert.sh server-csr.json server.pem上传etcd软件包
#上传 etcd-v3.4.26-linux-amd64.tar.gz 到 /opt/k8s 目录中
tar -xf etcd-v3.4.26-linux-amd64.tar.gz
cd /opt/k8sls etcd-v3.4.26-linux-amd64
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md启动 etcd 服务
#创建用于存放 etcd 配置文件命令文件证书的目录
mkdir -p /opt/etcd/{cfg,bin,ssl}cd etcd-v3.4.26-linux-amd64
mv etcd etcdctl /opt/etcd/bin/
cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/#进入卡住状态等待其他节点加入这里需要三台etcd服务同时启动如果只启动其中一台后服务会卡在那里直到集群中所有etcd节点都已启动可忽略这个情况
cd /opt/k8s/
./etcd.sh etcd01 192.168.110.50 etcd02https://192.168.110.60:2380,etcd03https://192.168.110.70:2380#可另外打开一个窗口查看etcd进程是否正常
ps -ef | grep etcd把etcd相关证书文件、命令文件和服务管理文件全部拷贝到另外两个etcd集群节点
scp -r /opt/etcd/ root192.168.110.60:/opt/
scp -r /opt/etcd/ root192.168.110.70:/opt/
scp /usr/lib/systemd/system/etcd.service root192.168.110.60:/usr/lib/systemd/system/
scp /usr/lib/systemd/system/etcd.service root192.168.110.70:/usr/lib/systemd/system/etcd02 节点上操作
vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAMEetcd02 #修改
ETCD_DATA_DIR/var/lib/etcd
ETCD_LISTEN_PEER_URLShttps://192.168.110.60:2380 #修改
ETCD_LISTEN_CLIENT_URLShttps://192.168.110.60:2379 #修改#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLShttps://192.168.110.60:2380 #修改
ETCD_ADVERTISE_CLIENT_URLShttps://192.168.110.60:2379 #修改
ETCD_INITIAL_CLUSTERetcd01https://192.168.110.50:2380,etcd02https://192.168.110.60:2380,etcd03https://192.168.110.70:2380
ETCD_INITIAL_CLUSTER_TOKENetcd-cluster
ETCD_INITIAL_CLUSTER_STATEnew#启动etcd服务
systemctl start etcd
systemctl enable etcd
systemctl status etcd#检查etcd群集状态
ETCDCTL_API3 /opt/etcd/bin/etcdctl --endpointshttps://192.168.110.50:2379,https://192.168.110.60:2379,https://192.168.110.70:2379 --cacert/opt/etcd/ssl/ca.pem --cert/opt/etcd/ssl/server.pem --key/opt/etcd/ssl/server-key.pem endpoint health --write-outtable#查看当前的 leader
ETCDCTL_API3 /opt/etcd/bin/etcdctl --endpointshttps://192.168.110.50:2379,https://192.168.110.60:2379,https://192.168.110.60:2379 --cacert/opt/etcd/ssl/ca.pem --cert/opt/etcd/ssl/server.pem --key/opt/etcd/ssl/server-key.pem endpoint status --write-outtable
etcd03 节点操作同 etcd02
部署 Master 组件
安装 apiserver 服务controller-manager 服务scheduler 服务和kubectl 工具
在 etcd01 上操作
#将 cfssl 工具传到master01
scp /usr/local/bin/cfssl* 192.168.110.10:/usr/local/bin/在 master01 上操作
#创建 /opt/k8s/ 目录上传 master.zip 并解压
mkdir /opt/k8s/
cd /opt/k8s/
unzip master.zip
chmod x *.sh[rootmaster01 k8s]# ls
admin.sh apiserver.sh controller-manager.sh master.zip scheduler.sh#创建kubernetes工作目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}#创建用于生成CA证书、相关组件的证书和私钥的目录上传 k8s-cert.sh
mkdir /opt/k8s/k8s-cert
mv /opt/k8s/k8s-cert.sh /opt/k8s/k8s-cert
cd /opt/k8s/k8s-cert/
./k8s-cert.sh[rootmaster01 k8s-cert]# ls *pem
admin-key.pem apiserver-key.pem ca-key.pem kube-proxy-key.pem
admin.pem apiserver.pem ca.pem kube-proxy.pem#复制CA证书、apiserver相关证书和私钥到 kubernetes工作目录的 ssl 子目录中
cp ca*pem apiserver*pem /opt/kubernetes/ssl/#上传 kubernetes-server-linux-amd64.tar.gz 到 /opt/k8s/ 目录中解压 kubernetes 压缩包
cd /opt/k8s/
tar zxvf kubernetes-server-linux-amd64.tar.gz#复制master组件的关键命令文件到 kubernetes工作目录的 bin 子目录中
cd /opt/k8s/kubernetes/server/bin
cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/
ln -s /opt/kubernetes/bin/* /usr/local/bin/#创建 bootstrap token 认证文件apiserver 启动时会调用然后就相当于在集群内创建了一个这个用户接下来就可以用 RBAC 给他授权
cd /opt/k8s/
vim token.sh
#!/bin/bash
#获取随机数前16个字节内容以十六进制格式输出并删除其中空格
BOOTSTRAP_TOKEN$(head -c 16 /dev/urandom | od -An -t x | tr -d )
#生成 token.csv 文件按照 Token序列号,用户名,UID,用户组 的格式生成
cat /opt/kubernetes/cfg/token.csv EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,system:kubelet-bootstrap
EOFchmod x token.sh
./token.sh
cat /opt/kubernetes/cfg/token.csv#在 master01 节点
mkdir /opt/etcd/ssl/ -p
#在 etcd 节点
cd /opt/etcd/ssl/
scp * 192.168.110.10:pwd
#在 master01 节点
[rootmaster01 k8s]# ls /opt/etcd/ssl/
ca-key.pem ca.pem server-key.pem server.pem
#二进制文件、token、证书都准备好后开启 apiserver 服务(修改 apiserver.sh 脚本里 ip)
cd /opt/k8s/
./apiserver.sh 192.168.110.10 https://192.168.110.50:2379,https://192.168.110.60:2379,https://192.168.110.70:2379
#检查进程是否启动成功
ps aux | grep kube-apiserver
netstat -natp | grep 6443 #安全端口6443用于接收HTTPS请求用于基于Token文件或客户端证书等认证#启动 scheduler 服务修改 KUBE_APISERVER 的IP
cd /opt/k8s/
./scheduler.sh
ps aux | grep kube-scheduler#启动 controller-manager 服务修改 KUBE_APISERVER 的IP
./controller-manager.sh
ps aux | grep kube-controller-manager#生成kubectl连接集群的kubeconfig文件修改 KUBE_APISERVER 的IP
./admin.sh#通过kubectl工具查看当前集群组件状态
kubectl get cs
#查看版本信息
kubectl version
#查看当前的 leader
kubectl -n kube-system get leases kube-scheduler
kubectl -n kube-system get leases kube-controller-manager部署 Worker Node 组件
安装kubeletkube-proxy 和 docker
node 节点安装 docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.iomkdir /etc/docker
cat /etc/docker/daemon.json EOF
{registry-mirrors: [https://docker.m.daocloud.io, https://docker.1panel.live],exec-opts: [native.cgroupdriversystemd],log-driver: json-file,log-opts: {max-size: 1g, max-file: 3}
}
EOFsystemctl start docker.service
systemctl enable docker.service docker info | grep Cgroup Driver部署组件
#创建kubernetes工作目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}#上传 node.zip 到 /opt 目录中解压 node.zip 压缩包获得kubelet.sh、proxy.sh
cd /opt/
unzip node.zip
chmod x kubelet.sh proxy.sh#在 master01 节点上操作
#把 kubelet、kube-proxy 拷贝到 node 节点
cd /opt/k8s/kubernetes/server/bin
scp kubelet kube-proxy root192.168.110.20:/opt/kubernetes/bin/
scp kubelet kube-proxy root192.168.110.30:/opt/kubernetes/bin/
#上传kubeconfig.sh文件到/opt/k8s/kubeconfig目录中生成kubelet初次加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件
#kubeconfig 文件包含集群参数CA 证书、API Server 地址客户端参数上面生成的证书和私钥集群 context 上下文参数集群名称、用户名。Kubenetes 组件如 kubelet、kube-proxy通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群连接到 apiserver。
mkdir /opt/k8s/kubeconfig
cd /opt/k8s/kubeconfig
chmod x kubeconfig.sh
./kubeconfig.sh 192.168.110.10 /opt/k8s/k8s-cert/
#把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点
scp bootstrap.kubeconfig kube-proxy.kubeconfig root192.168.110.20:/opt/kubernetes/cfg/
scp bootstrap.kubeconfig kube-proxy.kubeconfig root192.168.110.30:/opt/kubernetes/cfg/
#RBAC授权使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书
kubectl create clusterrolebinding kubelet-bootstrap --clusterrolesystem:node-bootstrapper --userkubelet-bootstrap
#自动批准 CSR 请求
kubectl create clusterrolebinding node-autoapprove-bootstrap --clusterrolesystem:certificates.k8s.io:certificatesigningrequests:nodeclient --userkubelet-bootstrap
kubectl create clusterrolebinding node-autoapprove-certificate-rotation --clusterrolesystem:certificates.k8s.io:certificatesigningrequests:selfnodeclient --userkubelet-bootstrap#在 node01 节点上操作
#启动 kubelet 服务
cd /opt/
./kubelet.sh 192.168.110.20
ps aux | grep kubelet
//在 master01 节点上操作通过 CSR 请求
#检查到 node01 节点的 kubelet 发起的 CSR 请求Pending 表示等待集群给该节点签发证书
kubectl get csr
[rootmaster01 kubeconfig]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-HD7lIMBUCLneSmDmaoDwXpe_FWJ75FylZ1iWGR69o2s 65s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
#通过 CSR 请求
kubectl certificate approve node-csr-HD7lIMBUCLneSmDmaoDwXpe_FWJ75FylZ1iWGR69o2s
#Approved,Issued 表示已授权 CSR 请求并签发证书
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 2m5s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
#查看节点由于网络插件还没有部署节点会没有准备就绪 NotReady
[rootmaster01 kubeconfig]# kubectl get node
NAME STATUS ROLES AGE VERSION
192.168.110.20 NotReady none 97m v1.20.15//在 node01 节点上操作
#加载 ip_vs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o ^[^.]*);do echo $i; /sbin/modinfo -F filename $i /dev/null 21 /sbin/modprobe $i;done
#启动proxy服务
cd /opt/
./proxy.sh 192.168.110.20
ps aux | grep kube-proxy
在 node02 节点操作同 node01
部署 CNI 网络组件
部署 flannel
简介
Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。 Flannel 是 Overlay 网络的一种也是将 TCP 源数据包封装在另一种网络包里面进行路由转发和通信目前支持 UDP、VXLAN、Host-gw 3种数据转发方式。
Flannel UDP 模式的工作原理 1、数据从主机A 上 Pod 的源容器中发出后经由所在主机的 cni0 网桥转发到 flannel0 接口flanneld 服务监听在 flannel0 接口的另外一端。 2、发送给 flannel0 接口的 IP 包信息将被 flanneld 进程接收flanneld 进程接收 IP 包后在原有的基础上进行 UDP 封包 3、Flannel 通过 etcd 服务维护了一张节点间的路由表。目标容器所在宿主机的 IP 地址flanneld 通过查询 etcd 很容易就能得到 4、flanneld 将封装好的 UDP 报文通过节点网络发往在主机B 监听 8285 端口的 flanneld 进程 5、运行在主机B 上的 flanneld 将 UDP 报文解包后得到原始 IP 包内核通过查询本机路由表将该 IP 包转发给 cni0 网桥 6、cni0 网桥将 IP 包转发给连接在网桥上的目标Pod。至此整个流程结束。回程报文将按照上面的数据流原路返回
由于在 UDP 模式下 flanneld 进行网络的封包和解包工作而 VXLAN 模式下封包解包的工作由内核完成因此性能上 UDP 模式会比在内核态做转发的 VXLAN 模式差。
VXLAN 模式是 Flannel 默认和推荐的模式flannel 会为每个节点分配一个 24 位子网并在每个节点上创建两张虚机网卡cni0 和 flannel.1 。 cni0 是一个网桥设备类似于 docker0 节点上所有的 Pod 都通过 veth pair 的形式与 cni0 相连。 flannel.1 则是一个 VXLAN 类型的设备充当 VTEP 设备VXLAN Tunnel Endpoint的角色实现对 VXLAN 报文的封包解包。 在 VXLAN 模式下flanneld 启动时先确保 VXLAN 设备已存在如果不存在则创建存在则跳过。并将 VTEP 设备的信息上报到 etcd 中当 flannel 网络有新节点加入并向 etcd 注册时 会在其它节点添加路由规则。 UDP 模式的 flannel0 网卡是三层转发使用 flannel0 是在物理网络之上构建三层网络属于 ip in udp VXLAN 模式是二层实现overlay 是数据帧属于 mac in udp 。
Flannel VXLAN 模式跨主机的工作原理 1、数据包从主机 A 上 Pod 的源容器中发出后经由所在主机的 cni0 网络接口转发到 flannel.1 设备 2、flannel.1 收到数据包后在内核态为数据包添加以太网头部目的 MAC 地址为目的 flannel.1 设备的 MAC 地址和 VXLAN 头部再将此数据帧进行 UDP 封装 3、flannel.1 通过查询本机的 FDB 转发数据库获取目的 flannel.1 设备对应的宿主机 IP 地址 4、通过节点网络将 UDP 报文发往在主机B 监听 8472 端口的 flannel.1 设备并在内核态进行解封装获取原始数据包 5、根据解包后得到的原始数据包中的目的IPflannel.1 将数据包发送给 cni0最后由 cni0 发送给连接在此接口上的PodB
部署
#在 node01 节点上操作
#上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中
cd /opt/
unzip flannel-v0.21.5.zip
docker load -i flannel.tar
docker load -i flannel-cni-plugin.tarmkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin#在 master01 节点上操作
#上传 kube-flannel.yml 文件到 /opt/k8s 目录中部署 CNI 网络
#在 node01 节点上
scp kube-flannel.yml 192.168.110.10:/opt/k8s
#在 master01 节点
cd /opt/k8s
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-flannel
kubectl get nodes[rootmaster01 k8s]# kubectl get pods -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-m86br 1/1 Running 0 31s
kube-flannel-ds-qkjw9 1/1 Running 0 31s
[rootmaster01 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.110.20 Ready none 132m v1.20.15
192.168.110.30 Ready none 22m v1.20.15#在node上查看flannel.1的端口
ip -d a show flannel.1
#通过路由信息看到发送到对端网段的数据包都会经过 flannel.1发出网关ip也是对端vtep设备的ip地址
route -n
#由于flannel.1 通过路由信息已经知道对端vtep的ip地址通过查询本地arp缓存表得到目的vtep的mac地址
ip neigh show dev flannel.1
#flannel.1可以通过查询本机的FDB表获取目的节点主机的ip
bridge fdb show flannel.1 [rootnode01 opt]# ip -d a show flannel.1
8: flannel.1: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1450 qdisc noqueue state UNKNOWN group default link/ether 9e:33:61:e2:14:9e brd ff:ff:ff:ff:ff:ff promiscuity 0 vxlan id 1 local 192.168.110.20 dev ens33 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 inet 10.244.0.0/32 scope global flannel.1valid_lft forever preferred_lft forever
[rootnode01 opt]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.110.2 0.0.0.0 UG 100 0 0 ens33
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.110.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
[rootnode01 opt]# ip neigh show dev flannel.1
10.244.1.0 lladdr 62:c5:6f:ed:55:96 PERMANENT
[rootnode01 opt]# bridge fdb show flannel.1
01:00:5e:00:00:01 dev ens33 self permanent
01:00:5e:00:00:fb dev ens33 self permanent
33:33:00:00:00:01 dev ens33 self permanent
01:00:5e:00:00:01 dev virbr0 self permanent
01:00:5e:00:00:fb dev virbr0 self permanent
52:54:00:9c:44:78 dev virbr0-nic master virbr0 permanent
52:54:00:9c:44:78 dev virbr0-nic vlan 1 master virbr0 permanent
33:33:00:00:00:01 dev docker0 self permanent
01:00:5e:00:00:01 dev docker0 self permanent
01:00:5e:00:00:fb dev docker0 self permanent
02:42:1e:24:eb:65 dev docker0 vlan 1 master docker0 permanent
02:42:1e:24:eb:65 dev docker0 master docker0 permanent
33:33:00:00:00:01 dev dummy0 self permanent
33:33:00:00:00:01 dev kube-ipvs0 self permanent
62:c5:6f:ed:55:96 dev flannel.1 dst 192.168.110.30 self permanent
部署 Calico
简介
Calico不使用隧道或NAT来实现转发而是把每个操作系统的协议栈认为是一个路由器然后把所有的容器认为是连在这个路由器上的网络终端在路由器之间跑标准的路由协议——BGP的协议然后让它们自己去学习这个网络拓扑该如何转发。 它不使用 cni0 网桥而是通过路由规则把数据包直接发送到目标节点的网卡所以性能高。
Calico 的模式 1、IPIP 模式在原有 IP 报文中封装一个新的 IP 报文新的 IP 报文中将源地址 IP 和目的地址 IP 都修改为对端宿主机 IP。Calico 默认使用 IPIP 的模式。 2、BGP 模式将节点做为虚拟路由器通过 BGP 路由协议来实现集群内容器之间的网络访问。 3、cross-subnetipip-bgp混合模式IPIP 模式和 BGP 模式都有对应的局限性对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式实现同子网机器使用 BGP 模式跨子网机器使用 IPIP 模式。
Calico 工作原理 IPIP 模式 Calico 会将容器的 IP 数据包经过 veth pair 设备发送到 tunl0 设备并被内核的 IPIP 驱动直接封装到宿主机网络的 IP 数据包中新封装的 IP 数据包再根据 Felix 维护的路由规则发送给目标节点目标节点通过 IPIP 驱动解包得到原始容器 IP 数据包然后根据路由规则经过 veth pair 设备送达到目标容器。
BGP 模式 Calico 是通过路由表来维护每个 Pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair 设备 然后把另一端接入到宿主机网络空间由于没有网桥CNI 插件还需要在宿主机上为每个容器的 veth pair 设备配置一条路由规则 用于接收传入的 IP 包。 有了这样的 veth pair 设备以后容器发出的 IP 包就会通过 veth pair 设备到达宿主机然后根据容器要访问的IP和宿主机的路由规则找到下一跳要到达的宿主机 IP。 流量到达下一跳的宿主机后根据当前宿主机上的路由规则直接到达对端容器的 veth pair 插在宿主机的一端最终进入容器。 这些路由规则都是 Felix 维护配置的而路由信息则是 Calico BIRD 组件基于 BGP 分发而来。 Calico 实际上是将集群里所有的节点都当做边界路由器来处理他们一起组成了一个全互联的网络彼此之间通过 BGP 交换路由 这些节点我们叫做 BGP Peer。
相比IPIP模式BGP模式下不需要tunl0设备参与报文传输报文直接通过物理网卡比如ens33转发到目标机器上不会进行二次IP报文的封装因此从性能上来看BGP是占优势的。但是由于没有二次封包BGP模式只能在同一个子网内使用无法跨网段使用。
部署
在 master01 节点
#上传 calico.yaml 文件到 /opt/k8s 目录中部署 Calico
#下载地址curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
cd /opt/k8s
vim calico.yaml#修改里面定义 Pod 的网络CALICO_IPV4POOL_CIDR需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样- name: CALICO_IPV4POOL_CIDRvalue: 10.244.0.0/16 #Calico 默认使用的网段为 192.168.0.0/16kubectl apply -f calico.yaml
kubectl get pods -n kube-system#等 Calico Pod 都 Running节点也会准备就绪
kubectl get nodes[rootmaster01 k8s]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-659bd7879c-khr55 1/1 Running 0 5m6s
calico-node-rf8lf 1/1 Running 0 5m6s
calico-node-rw5qp 1/1 Running 0 5m6s
[rootmaster01 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.110.20 Ready none 147m v1.20.15
192.168.110.30 Ready none 37m v1.20.15[rootnode02 opt]# ip route
default via 192.168.110.2 dev ens33 proto static metric 100
10.244.0.0 via 192.168.110.20 dev tunl0 proto bird onlink
10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink
unreachable 10.244.1.0/24 proto bird
10.244.60.64/26 via 192.168.110.20 dev tunl0 proto bird onlink
blackhole 10.244.193.64/26 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.110.0/24 dev ens33 proto kernel scope link src 192.168.110.30 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1#修改calico的网络模式IPIP变为BGP
kubectl edit ds calico-node -n kube-system
......- name: CALICO_IPV4POOL_IPIPvalue: Never #设置为Never时为BGP模式设置为Always时为IPIP模式设置为Cross-SubNet时为混合模式- name: IP_AUTODETECTION_METHOD #添加下面两行value: interfaceens33 #指定calico使用的网卡kubectl edit ippool ipipMode: Never #把ipipMode从Always修改成为Never使用BGP模式时查看IP会发现tunl0没有IP地址了查看route会发现不再使用tunl0了而是直接通过物理网卡转发。
ip addr
ip route[rootnode01 opt]# ip route
default via 192.168.110.2 dev ens33 proto static metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0 via 192.168.110.30 dev ens33 proto bird
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
blackhole 10.244.60.64/26 proto bird
10.244.193.64/26 via 192.168.110.30 dev ens33 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.110.0/24 dev ens33 proto kernel scope link src 192.168.110.20 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
部署 CoreDNS
CoreDNSCoreDNS 是 Kubernetes 的默认 DNS 实现。可以为 K8S 集群内的 Pod 提供 DNS 服务。 使用 CoreDNS 可以为集群中的 service 资源创建一个资源名称 与 ClusterIP 的对应关系解析从而避免将 service 的 ClusterIP 地址硬编码到应用程序代码中。
#在所有 node 节点上操作
#上传 coredns.tar 到 /opt 目录中
cd /opt
docker load -i coredns.tar//在 master01 节点上操作
#上传 coredns.yaml 文件到 /opt/k8s 目录中部署 CoreDNS
cd /opt/k8s
kubectl apply -f coredns.yaml
kubectl get pods -n kube-system [rootmaster01 k8s]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-659bd7879c-khr55 1/1 Running 0 30m
calico-node-5lk72 1/1 Running 0 10m
calico-node-rddmg 1/1 Running 0 10m
coredns-7f8c5c6967-l2tpc 1/1 Running 0 #DNS 解析测试
kubectl run -it --rm dns-test --imagebusybox:1.28.4 sh[rootmaster01 k8s]# kubectl run -it --rm dns-test1 --imagebusybox sh
If you dont see a command prompt, try pressing enter.
/ # nslookup kubernetes.default.svc.cluster.local.
Server: 10.0.0.2
Address: 10.0.0.2:53Name: kubernetes.default.svc.cluster.local
Address: 10.0.0.1#若执行失败可先给kubectl绑定默认cluster-admin管理员集群角色授权集群操作权限
kubectl create clusterrolebinding cluster-system-anonymous --clusterrolecluster-admin --usersystem:anonymousmaster02 节点部署
#从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点
scp -r /opt/etcd/ root192.168.110.40:/opt/
scp -r /opt/kubernetes/ root192.168.110.40:/opt
scp -r /root/.kube root192.168.110.40:/root
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service root192.168.110.40:/usr/lib/systemd/system/#修改配置文件kube-apiserver中的IP
vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS--logtostderrtrue \
--v4 \
--etcd-servershttps://192.168.80.10:2379,https://192.168.80.11:2379,https://192.168.80.12:2379 \
--bind-address192.168.80.20 \ #修改
--secure-port6443 \
--advertise-address192.168.80.20 \ #修改
......//在 master02 节点上启动各服务并设置开机自启
systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service//查看node节点状态
ln -s /opt/kubernetes/bin/* /usr/local/bin/
kubectl get nodes
kubectl get nodes -o wide #-owide输出额外信息对于Pod将输出Pod所在的Node名[rootlocalhost ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.110.20 Ready none 3h38m v1.20.15
192.168.110.30 Ready none 108m v1.20.15
[rootlocalhost ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
192.168.110.20 Ready none 3h38m v1.20.15 192.168.110.20 none CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://26.1.4
192.168.110.30 Ready none 108m v1.20.15 192.168.110.30 none CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://26.1.4
此时在master02节点查到的node节点状态仅是从etcd查询到的信息而此时node节点实际上并未与master02节点建立通信连接因此需要使用一个VIP把node节点与master节点都关联起来
负载均衡部署
配置load balancer集群双机热备负载均衡nginx实现负载均衡keepalived实现双机热备 在lb01、lb02节点上操作
#配置nginx的官方在线yum源配置本地nginx的yum源
cat /etc/yum.repos.d/nginx.repo EOF
[nginx]
namenginx repo
baseurlhttp://nginx.org/packages/centos/7/$basearch/
gpgcheck0
EOFyum install nginx -y#修改nginx配置文件配置四层反向代理负载均衡指定k8s群集2台master的节点ip和6443端口
vim /etc/nginx/nginx.conf
events {worker_connections 1024;
}#添加
stream {log_format main $remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent;access_log /var/log/nginx/k8s-access.log main;upstream k8s-apiserver {server 192.168.110.10:6443;server 192.168.110.40:6443;}server {listen 6443;proxy_pass k8s-apiserver;}
}http {
......//检查配置文件语法
nginx -t //启动nginx服务查看已监听6443端口
systemctl start nginx
systemctl enable nginx
netstat -natp | grep nginx //部署keepalived服务
yum install keepalived -y//修改keepalived配置文件
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {# 接收邮件地址notification_email {acassenfirewall.locfailoverfirewall.locsysadminfirewall.loc}# 邮件发送地址notification_email_from Alexandre.Cassenfirewall.locsmtp_server 127.0.0.1smtp_connect_timeout 30router_id NGINX_MASTER #lb01节点的为 NGINX_MASTERlb02节点的为 NGINX_BACKUP
}#添加一个周期性执行的脚本
vrrp_script check_nginx {script /etc/nginx/check_nginx.sh #指定检查nginx存活的脚本路径
}vrrp_instance VI_1 {state MASTER #lb01节点的为 MASTERlb02节点的为 BACKUPinterface ens33 #指定网卡名称 ens33virtual_router_id 51 #指定vrid两个节点要一致priority 100 #lb01节点的为 100lb02节点的为 90advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.80.100/24 #指定 VIP}track_script {check_nginx #指定vrrp_script配置的脚本}
}#创建nginx状态检查脚本
vim /etc/nginx/check_nginx.sh
#!/bin/bash
#egrep -cv grep|$$ 用于过滤掉包含grep 或者 $$ 表示的当前Shell进程ID即脚本运行的当前进程ID号
count$(ps -ef | grep nginx | egrep -cv grep|$$)if [ $count -eq 0 ];thensystemctl stop keepalived
fichmod x /etc/nginx/check_nginx.sh#启动keepalived服务一定要先启动了nginx服务再启动keepalived服务
systemctl start keepalived
systemctl enable keepalived
#lb01上查看VIP是否生成
ip a [rootetcd01 k8s-cert]# ip a
1: lo: LOOPBACK,UP,LOWER_UP mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
2: ens33: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:ef:81:c3 brd ff:ff:ff:ff:ff:ffinet 192.168.110.50/24 brd 192.168.110.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::8c65:44b1:be2a:c9f5/64 scope link noprefixroute valid_lft forever preferred_lft forever
3: virbr0: NO-CARRIER,BROADCAST,MULTICAST,UP mtu 1500 qdisc noqueue state DOWN group default qlen 1000link/ether 52:54:00:75:aa:99 brd ff:ff:ff:ff:ff:ffinet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0valid_lft forever preferred_lft forever
4: virbr0-nic: BROADCAST,MULTICAST mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000link/ether 52:54:00:75:aa:99 brd ff:ff:ff:ff:ff:ff#修改node节点上的bootstrap.kubeconfig,kubelet.kubeconfig配置文件为VIP
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig
server: https://192.168.80.100:6443vim kubelet.kubeconfig
server: https://192.168.80.100:6443vim kube-proxy.kubeconfig
server: https://192.168.80.100:6443#重启kubelet和kube-proxy服务
systemctl restart kubelet.service
systemctl restart kube-proxy.service#在 lb01 上查看 nginx 和 node 、 master 节点的连接状态
netstat -natp | grep nginx[rootetcd01 ~]# netstat -natp | grep nginx
tcp 0 0 0.0.0.0:6443 0.0.0.0:* LISTEN 9036/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9036/nginx: master
tcp 0 0 192.168.110.50:55238 192.168.110.40:6443 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:57196 192.168.110.10:6443 ESTABLISHED 9041/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40392 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40374 ESTABLISHED 9041/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41828 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41824 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41818 ESTABLISHED 9041/nginx: worker
tcp 0 0 192.168.110.50:55226 192.168.110.40:6443 ESTABLISHED 9041/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41820 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40368 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41834 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41822 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:57254 192.168.110.10:6443 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40358 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:55218 192.168.110.40:6443 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40336 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.50:57238 192.168.110.10:6443 ESTABLISHED 9044/nginx: worker
tcp 0 0 192.168.110.50:57206 192.168.110.10:6443 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.50:57198 192.168.110.10:6443 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.30:41826 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40394 ESTABLISHED 9044/nginx: worker
tcp 0 0 192.168.110.50:55274 192.168.110.40:6443 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:57360 192.168.110.10:6443 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:57236 192.168.110.10:6443 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.100:6443 192.168.110.20:40522 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:57218 192.168.110.10:6443 ESTABLISHED 9042/nginx: worker
tcp 0 0 192.168.110.50:55258 192.168.110.40:6443 ESTABLISHED 9043/nginx: worker
tcp 0 0 192.168.110.50:55372 192.168.110.40:6443 ESTABLISHED 9043/nginx: worker
#如果有问题检查防火墙核心防护在 master01 节点上进行检测
#测试创建pod
kubectl run nginx --imagenginx//查看Pod的状态信息
kubectl get pods[rootmaster01 opt]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 7skubectl get pods -o wide[rootmaster01 opt]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 70s 10.244.60.72 192.168.110.20 none none
#READY为1/1表示这个Pod中有1个容器#在对应网段的node节点上操作可以直接使用浏览器或者curl命令访问
curl 172.17.36.2[rootnode01 logs]# curl 10.244.60.72
!DOCTYPE html
html
head
titleWelcome to nginx!/title
... ...
pemThank you for using nginx./em/p
/body
/html#这时在master01节点上查看nginx日志
kubectl logs nginx[rootmaster01 opt]# kubectl logs nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
... ...
2025/02/10 08:51:22 [notice] 1#1: start worker process 31
2025/02/10 08:51:22 [notice] 1#1: start worker process 32
192.168.110.20 - - [10/Feb/2025:08:54:15 0000] GET / HTTP/1.1 200 615 - curl/7.29.0 -若执行失败可先给kubectl绑定默认cluster-admin管理员集群角色授权集群操作权限
kubectl create clusterrolebinding cluster-system-anonymous --clusterrolecluster-admin --usersystem:anonymous部署 Dashboard
Dashboard 仪表板是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群对容器化应用程序进行故障排除并管理集群本身及其伴随资源。您可以使用仪表板来概述群集上运行的应用程序以及创建或修改单个Kubernetes资源例如deploymentjobdaemonset等。例如您可以使用部署向导扩展部署启动滚动更新重新启动Pod或部署新应用程序。仪表板还提供有关群集中Kubernetes资源状态以及可能发生的任何错误的信息
#在 master01 节点上操作
#上传 recommended.yaml 文件到 /opt/k8s 目录中
cd /opt/k8s
vim recommended.yaml
#默认Dashboard只能集群内部访问修改Service为NodePort类型暴露到外部
kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:ports:- port: 443targetPort: 8443nodePort: 30001 #添加type: NodePort #添加selector:k8s-app: kubernetes-dashboardkubectl apply -f recommended.yaml#创建service account并绑定默认cluster-admin管理员集群角色
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrolecluster-admin --serviceaccountkube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk /dashboard-admin/{print $1})#使用输出的token登录Dashboard
https://192.168.110.20:30001 或者 https://192.168.110.30:30001 文章转载自: http://www.morning.fksyq.cn.gov.cn.fksyq.cn http://www.morning.fxpyt.cn.gov.cn.fxpyt.cn http://www.morning.rtsdz.cn.gov.cn.rtsdz.cn http://www.morning.kxwsn.cn.gov.cn.kxwsn.cn http://www.morning.rmyqj.cn.gov.cn.rmyqj.cn http://www.morning.cbqqz.cn.gov.cn.cbqqz.cn http://www.morning.fywqr.cn.gov.cn.fywqr.cn http://www.morning.mlwhd.cn.gov.cn.mlwhd.cn http://www.morning.ltqtp.cn.gov.cn.ltqtp.cn http://www.morning.hhqtq.cn.gov.cn.hhqtq.cn http://www.morning.xesrd.com.gov.cn.xesrd.com http://www.morning.lmmyl.cn.gov.cn.lmmyl.cn http://www.morning.xgjhy.cn.gov.cn.xgjhy.cn http://www.morning.yrhpg.cn.gov.cn.yrhpg.cn http://www.morning.qdcpn.cn.gov.cn.qdcpn.cn http://www.morning.ldhbs.cn.gov.cn.ldhbs.cn http://www.morning.qxkjy.cn.gov.cn.qxkjy.cn http://www.morning.xlxmy.cn.gov.cn.xlxmy.cn http://www.morning.qyfrd.cn.gov.cn.qyfrd.cn http://www.morning.wlgpz.cn.gov.cn.wlgpz.cn http://www.morning.ldmtq.cn.gov.cn.ldmtq.cn http://www.morning.nrrzw.cn.gov.cn.nrrzw.cn http://www.morning.bfhrj.cn.gov.cn.bfhrj.cn http://www.morning.rjfr.cn.gov.cn.rjfr.cn http://www.morning.jnhhc.cn.gov.cn.jnhhc.cn http://www.morning.xnwjt.cn.gov.cn.xnwjt.cn http://www.morning.fbmrz.cn.gov.cn.fbmrz.cn http://www.morning.sfwd.cn.gov.cn.sfwd.cn http://www.morning.dtlnz.cn.gov.cn.dtlnz.cn http://www.morning.ftlgy.cn.gov.cn.ftlgy.cn http://www.morning.czgfn.cn.gov.cn.czgfn.cn http://www.morning.jqcrf.cn.gov.cn.jqcrf.cn http://www.morning.dfffm.cn.gov.cn.dfffm.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.fxkgp.cn.gov.cn.fxkgp.cn http://www.morning.skqfx.cn.gov.cn.skqfx.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.zrgx.cn.gov.cn.zrgx.cn http://www.morning.zrkp.cn.gov.cn.zrkp.cn http://www.morning.kxypt.cn.gov.cn.kxypt.cn http://www.morning.mrfr.cn.gov.cn.mrfr.cn http://www.morning.klrpm.cn.gov.cn.klrpm.cn http://www.morning.lgkbn.cn.gov.cn.lgkbn.cn http://www.morning.zqsnj.cn.gov.cn.zqsnj.cn http://www.morning.jkpnm.cn.gov.cn.jkpnm.cn http://www.morning.lkpzx.cn.gov.cn.lkpzx.cn http://www.morning.qfbzj.cn.gov.cn.qfbzj.cn http://www.morning.tdscl.cn.gov.cn.tdscl.cn http://www.morning.lfttb.cn.gov.cn.lfttb.cn http://www.morning.pshpx.cn.gov.cn.pshpx.cn http://www.morning.lqffg.cn.gov.cn.lqffg.cn http://www.morning.mnkhk.cn.gov.cn.mnkhk.cn http://www.morning.snrhg.cn.gov.cn.snrhg.cn http://www.morning.qkqzm.cn.gov.cn.qkqzm.cn http://www.morning.fhqsm.cn.gov.cn.fhqsm.cn http://www.morning.glnmm.cn.gov.cn.glnmm.cn http://www.morning.qhqgk.cn.gov.cn.qhqgk.cn http://www.morning.bqdpy.cn.gov.cn.bqdpy.cn http://www.morning.bpmtx.cn.gov.cn.bpmtx.cn http://www.morning.plxnn.cn.gov.cn.plxnn.cn http://www.morning.gxcym.cn.gov.cn.gxcym.cn http://www.morning.pttrs.cn.gov.cn.pttrs.cn http://www.morning.rhpy.cn.gov.cn.rhpy.cn http://www.morning.czgtt.cn.gov.cn.czgtt.cn http://www.morning.dqrhz.cn.gov.cn.dqrhz.cn http://www.morning.rwmq.cn.gov.cn.rwmq.cn http://www.morning.wjpsn.cn.gov.cn.wjpsn.cn http://www.morning.rpjyl.cn.gov.cn.rpjyl.cn http://www.morning.knzdt.cn.gov.cn.knzdt.cn http://www.morning.jncxr.cn.gov.cn.jncxr.cn http://www.morning.lnwdh.cn.gov.cn.lnwdh.cn http://www.morning.lbssg.cn.gov.cn.lbssg.cn http://www.morning.zbkdm.cn.gov.cn.zbkdm.cn http://www.morning.tgnwt.cn.gov.cn.tgnwt.cn http://www.morning.qttg.cn.gov.cn.qttg.cn http://www.morning.dbrpl.cn.gov.cn.dbrpl.cn http://www.morning.mxmzl.cn.gov.cn.mxmzl.cn http://www.morning.21r000.cn.gov.cn.21r000.cn http://www.morning.rqqct.cn.gov.cn.rqqct.cn http://www.morning.aiai201.cn.gov.cn.aiai201.cn