三主两从k8s集群搭建

A9bot 155 0

k8s简介

定义

容器集群管理平台

集群类型

一主多从(有风险,没有管理节点则工作节点不可用,适合测试环境)

多主多从(奇数台master,随意台node,适合生产环境)

etcd选举机制决定master为奇数台,选择一个 Leader 来处理写操作,并确保集群的一致性和高可用性。

重要集群组件

三主两从k8s集群搭建

kubectl:客户端命令行工具

ApiServer(集群管理入口):接收命令,对管理者进行身份识别和权限验证。

Scheduler(资源调度计算):在身份识别和权限验证通过之后,ApiServer通过这个组件来对资源(部署在容器上的 程序)进行调度,Scheduler需要从ETCD获取节点信息后再进行调度计算。

ETCD:集群数据库,存放集群节点的详细信息,如节点数量,节点资源使用率,节点是否设置了禁止调度等。

kubelet:接受master的调度指令,之后它去调用本节点的容器工具(docker之类),由容器工具来进行镜像拉取和部署

pod:容器镜像不跑在容器工具上,而在pod(容器组)里,pod提供cpu、内存等资源。访问资源就是访问pod的IP地址,根据访问的端口来判断用户要访问什么程序。

kubeproxy:接受用户请求,转到容器上的相应程序

ControllerMananger:管理控制器部署应用,对pod进行扩容缩容等操作

搭建集群环境

设备

9台CentOS-7.9,分别为3台mater,2台node,2台负载均衡,1台ansible,最后1台做为harbo仓库、MySQL数据库以及nfs存储服务器。

ip规划及资源分配

IP地址 主机名称 主机角色 主机最低配置
192.168.174.130 master01 管理节点 2核心CPU/4G内存/20G硬盘
192.168.174.131 master02 管理节点 2核心CPU/4G内存/20G硬盘
192.168.174.132 master03 管理节点 2核心CPU/2G内存/20G硬盘
192.168.174.133 node01 工作节点 1核心CPU/2G内存/20G硬盘
192.168.174.134 node02 工作节点 1核心CPU/2G内存/20G硬盘
192.168.174.135 ha01 主负载均衡 1核心CPU/1G内存/20G硬盘
192.168.174.136 ha02 备负载均衡 1核心CPU/1G内存/20G硬盘
192.168.174.137 ansible 批量控制写入 1核心CPU/1G内存/20G硬盘
192.168.174.138 harbor_db 私有仓库、mysql、nfs 2核心CPU/4G内存/50G硬盘

搭建过程

配置各主机IP、主机名和ssh

主机192.168.174.137安装ansible批量控制节点

(1) 本地安装ansible,将主机ip写入批量控制组。

            vi /etc/ansible/hosts

            [k8s]

            192.168.174.130

            192.168.174.131

            192.168.174.132

            192.168.174.133

            192.168.174.134

(2) ansible做免密登录

ssh-keygen #生成密钥对,一路回车

给组中主机下发

for ip in 192.168.174.{130..134}
> do
> ssh-copy-id $ip
> done
运行节点初始化脚本
如果静态ip连接不上外网,那么可以修改一下虚拟机nat模式的dhcp地址池范围,再运行命令“dhclient”,使用动态分配的地址连接互联网。

以下脚本在master、node、ansible、ha、harbor_db上运行
#!/bin/bash
echo "=====系统环境初始化脚本====="
sleep 3
echo "——>>> 关闭防火墙与SELinux <<<——"
sleep 3
systemctl stop firewalld
systemctl disable firewalld &> /dev/null
setenforce 0
sed -i '/SELINUX/{s/enforcing/disabled/}' /etc/selinux/config

echo "——>>> 创建阿里仓库 <<<——"
sleep 3
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 
yum -y install wget
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo  

echo "——>>> 设置时区并同步时间 <<<——"
sleep 3
timedatectl set-timezone Asia/Shanghai
yum -y install chrony
systemctl start chronyd
systemctl enable chronyd

echo "——>>> 设置系统最大打开文件数 <<<——"
sleep 3
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535   #软限制
* hard nofile 65535   #硬限制
EOF
fi

echo "——>>> 系统内核优化 <<<——"
sleep 3
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_syncookies = 1             #防范SYN洪水攻击,0为关闭
net.ipv4.tcp_max_tw_buckets = 20480     #此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死
net.ipv4.tcp_max_syn_backlog = 20480    #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数
net.core.netdev_max_backlog = 262144    #每个网络接口 接受数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目
net.ipv4.tcp_fin_timeout = 20           #FIN-WAIT-2状态的超时时间,避免内核崩溃
EOF

echo "——>>> 减少SWAP使用 <<<——"
sleep 3
echo "0" > /proc/sys/vm/swappiness

echo "——>>> 安装系统性能分析工具及其他 <<<——"
sleep 3
yum install -y gcc make autoconf vim sysstat net-tools iostat  lrzsz
改hosts文件

使ip对应主机名

192.168.174.130 master01
192.168.174.131 master02
192.168.174.132 master03
192.168.174.133 node01
192.168.174.134 node02
    ansible中修改,调用copy模块批量复制
 ansible k8s -m copy -a 'src=/etc/hosts dest=/etc'
开启网桥过滤功能

网桥为集群内容器提供网络通信功能

vi /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1  //对网桥上的IPv6数据包通过iptables处理
net.bridge.bridge-nf-call-iptables = 1   //对网桥上的IPv4数据包通过iptables处理
net.ipv4.ip_forward = 1          //开启IPv4路由转发,来实现集群中的容器与外部网络的通信
ansible k8s -m copy -a 'src=/etc/sysctl.d/k8s.conf dest=/etc/sysctl.d/'

ansible k8s -m shell -a 'modprobe br_netfilter' #加载这个模块

ansible k8s -m shell -a 'sysctl -p /etc/sysctl.d/k8s.conf' #加载内核参数
关闭SWAP
swap,虚拟内存管理技术,将物理内存中的数据暂时存放到硬盘中,以释放物理内存给其他程序应用。

为了保证kubelet正常工作,k8s强制要求禁用,否则集群初始化失败。
ansible k8s -m shell -a "swapoff -a"
ansible k8s -m shell -a "sed -ri 's/.*swap.*/#&/' /etc/fstab" #s表示替换,将所有“swap”的行的左边界替换成#,也就是注释掉
安装docker
ansible k8s -m shell -a "yum install -y yum-utils" #安装安装yum-utils依赖包提供yum-config-manager命令

ansible k8s -m shell -a "yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo" #安装阿里docker镜像源仓库

#线上安装
yum -y install docker-ce-20.10.9-3.el7

#本地安装

ansible k8s -m copy -a "src=/root/docker-ce-20.10.10.tar.gz dest=/root"

ansible k8s -m shell -a "tar -xf /root/docker-ce-20.10.10.tar.gz"

ansible k8s -m shell -a "cd /root/docker && yum install ./*.rpm -y"

ansible k8s -m shell -a "mkdir /etc/docker"

#启用Cgroup控制组(限制进程的资源使用量)

vim daemon.json

ansible k8s -m copy -a "src=./daemon.json dest=/etc/docker"

ansible k8s -m shell -a "systemctl enable docker --now"
daemon.json内容如下:
{
        "exec-opts": ["native.cgroupdriver=systemd"],
        "registry-mirrors": ["https://5f352q46.mirror.aliyuncs.com"] #自己的阿里云容器镜像加速器
}

安装HAProxy和Keepalived

三主两从k8s集群搭建

所有node节点要与master通信时,必须经由负载均衡来分配转发通信数据。keepalive虚拟一个IP,在两个负载均衡之间有选举机制,IP分配给主负载,如果主负载挂掉则把IP给到备用负载。保证高可用和负载均衡。

在ha01和ha02上执行:

yum install -y haproxy keepalived

修改/etc/haproxy/haproxy.cfg,删除原有内容以后添加下列内容:

global
  maxconn  2000                   #单个进程最大并发连接数
  ulimit-n  16384                 #每个进程可以打开的文件数量
  log  127.0.0.1 local0 err       #日志输出配置,所有日志都记录在本机系统日志,通过 local0 输出
  stats timeout 30s               #连接socket超时时间

defaults
  log global                      #定义日志为global(全局)
  mode  http                      #使用的连接协议
  option  httplog                 #日志记录选项,httplog表示记录与HTTP会话相关的日志
  timeout connect 5000            #定义haproxy将客户端请求转发至后端服务器所等待的超时时长
  timeout client  50000           #客户端非活动状态的超时时长
  timeout server  50000           #客户端与服务器端建立连接后,等待服务器端的超时时长
  timeout http-request 15s        #客户端建立连接但不请求数据时,关闭客户端连接超时时间
  timeout http-keep-alive 15s     # session 会话保持超时时间

frontend monitor-in               #监控haproxy服务本身
  bind *:33305                    #监听的端口
  mode http                       #使用的连接协议
  option httplog                  #日志记录选项,httplog表示记录与HTTP会话相关的日志
  monitor-uri /monitor            #监控URL路径

frontend k8s-master               #接收请求的前端名称,名称自定义,类似于Nginx的一个虚拟主机server。
  bind 0.0.0.0:6443               #监听客户端请求的 IP地址和端口(以包含虚拟IP)
  bind 127.0.0.1:6443 
  mode tcp                        #使用的连接协议
  option tcplog                   #日志记录选项,tcplog表示记录与tcp会话相关的日志
  tcp-request inspect-delay 5s    #等待数据传输的最大超时时间
  default_backend k8s-master      #将监听到的客户端请求转发到指定的后端

backend k8s-master                #后端服务器组,要与前端中设置的后端名称一致
  mode tcp                        #使用的连接协议
  option tcplog                   #日志记录选项,tcplog表示记录与tcp会话相关的日志
  option tcp-check                #tcp健康检查
  balance roundrobin              #负载均衡方式为轮询
  default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100

  server master01   192.168.174.130:6443  check  # 根据自己环境修改后端实例IP
  server master02   192.168.174.131:6443  check  # 根据自己环境修改后端实例IP
  server master03   192.168.174.132:6443  check  # 根据自己环境修改后端实例IP
systemctl enable haproxy --now

如果启动haproxy遇到错误:Starting frontend k8s-master: cannot bind socket [127.0.0.1:6443],解决办法:将/etc/haproxy/haproxy.cfg里的 bind 0.0.0.0:6443 和 bind 127.0.0.1:6443 先注释掉,启动haproxy后再把注释删掉。

修改keepalived配置文件(/etc/keepalived/keepalived.conf):

注意文件为json格式,不在里面写注释,使用时把注释删除。

#ha01(主):

! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
script_user root
    enable_script_security
}
vrrp_script chk_haproxy {
    script "/etc/keepalived/check_haproxy.sh" #状态检测脚本,自己准备,用来检测这台机器的haproxy是否挂掉。
    interval 5
    weight -5
    fall 2
rise 1
}
vrrp_instance VI_1 {
    state MASTER
    interface ens33 #自己的网卡名
    virtual_router_id 51
    priority 101 #优先级
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass abc123
    }
    virtual_ipaddress {
        192.168.174.100/24 #同网段的虚拟IP
    }
    track_script {
       chk_haproxy
    }
}
#ha02(备):

! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
script_user root
    enable_script_security
}
vrrp_script chk_haproxy {
    script "/etc/keepalived/check_haproxy.sh"
    interval 5
    weight -5
    fall 2
rise 1
}
vrrp_instance VI_1 {
    state BACKUP        #需要修改节点身份
    interface ens33 #网卡名 
    virtual_router_id 51
    priority 99         #备用节点优先级不能高于master
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass abc123
    }
    virtual_ipaddress {
        192.168.174.100/24
    }
    track_script {
       chk_haproxy
    }
}
/etc/keepalived/check_haproxy.sh内容如下,文件放入两台负载中,并加执行权限。

#!/bin/bash
count=$(ps -C haproxy | grep -v PID | wc -l)
if [ $count -eq 0 ];then
    systemctl stop keepalived
fi

chmod +x /etc/keepalived/check_haproxy.sh
systemctl enable keepalived --now

验证:把ha01的haproxy停掉,看虚拟的IP会不会转移到ha02上。

部署集群

使用kubeadm部署

(1)所有节点配置阿里云kubernetes软件源仓库

vim kubernetes.repo

内容如下:

[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

ansible k8s -m copy -a "src=kubernetes.repo dest=/etc/yum.repos.d"

(2)通过yum安装软件包

  • kubeadm:用于初始化集群,并配置集群所需的组件并生成对应的安全证书(https)和令牌(节点加入集群所需的token令牌);
  • kubelet:负责与 Master 节点通信,并根据 Master 节点的调度决策来创建、更新和删除 Pod,同时维护 Node 节点上的容器状态;
  • kubectl:用于管理k8集群的一个命令行工具;
ansible k8s -m shell -a "yum install -y kubeadm-1.23.0-0  kubelet-1.23.0-0 kubectl-1.23.0-0"

(3)kubelet开启Cgroup,监控容器的cpu、内存等资源使用量

vim kubelet

内容如下:
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

ansible k8s -m copy -a "src=kubelet dest=/etc/sysconfig/"

ansible k8s -m shell -a "systemctl enable kubelet"

(4)kubernetes集群初始化

#在master01上执行:

kubeadm config images list

#生成初始化配置文件
kubeadm config print init-defaults > kubeadm-config.yaml

#修改文件内容如下:
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.174.130 #master节点master01这台主机的IP
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  imagePullPolicy: IfNotPresent
  name: master01 #主机名
  taints: 
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  certSANs:
  - 192.168.174.100 #添加certSANS,把负载均衡IP加入进来,以生成安全证书来进行通信
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 192.168.174.100:6443 #添加此属性
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers #修改镜像源仓库为阿里云
kind: ClusterConfiguration
kubernetesVersion: 1.23.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
scheduler: {}
kubeadm init --config kubeadm-config.yaml --upload-certs 
#依据kubeadm-config.yaml这个文件初始化,把生成的证书上传到etcd数据库中
#初始化成功,集群创建完毕,会有以下三条命令,执行后就成为集群的管理员。

 mkdir -p $HOME/.kube
 sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
 sudo chown $(id -u):$(id -g) $HOME/.kube/config

#上述命令将集群管理文件拷贝到$HOME/.kube/下

同时,会有master、node加入集群的命令出现。

(5)加入集群

初始化后加入命令需要在24小时内执行,否则失效。

master节点加入命令样式:

 kubeadm join 192.168.174.100:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:da085512963f12acd747c13b5023de973193f877cd582843ceb2c7c3dcb96252 \
    --control-plane --certificate-key 9d6397a2b13ad45767e4e8cec2b5b0f0e2d16b56cfb1ffca8c34096baa10a4f3

    加入后同样在master节点上执行下列命令成为管理员:

    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
node节点加入命令样式:

kubeadm join 192.168.174.100:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:da085512963f12acd747c13b5023de973193f877cd582843ceb2c7c3dcb96252 

(6)安装pod网络管理工具calico(用于pod之间通信)

ansible k8s -m copy -a "src=calico-v3.24.1-img.tar.gz dest=/root/"

ansible k8s -m shell -a "mkdir /root/calico/ && mv /root/calico-v3.24.1-img.tar.gz /root/calico"

ansible k8s -m shell -a "cd /root/calico/ && tar -xf calico-v3.24.1-img.tar.gz"

#在所有节点中加载镜像,如果不行,在每台节点机器手动来执行
ansible k8s -m shell -a "cd /root/calico/ && for img in *.tar; do docker load -i $img; done" 

for img in *.tar
> do
> docker load -i $img
> done

#在master01创建网络
kubectl apply -f calico-3.24.1.yaml

#查看节点状态
kubectl get nodes

部署具体项目

步骤

1.集群服务对外提供访问,需要通过Ingress代理发布域名。
2.搭建私有镜像仓库,用于存储自己构建的项目镜像。
3.集群中容器数据(日志、图片等)持久化,通过NFS(外部存储服务器)作为后端存储。
4.部署项自所需的数据库,并配置好项目连接数据库的信息。
5.项目运行在什么环境中,需要将运行环境打包到镜像中。
6.在k8s中部署项目,并通过Ingress发布项目。

三主两从k8s集群搭建

部署过程

部署代理

ingress-nginx,负载均衡器,集群中的程序可以通过ingress发布域名进行访问。是一个在node上的pod。

将ingress-nginx文件夹的两个镜像传到node01和node02上

for img in *.tar;do docker load -i $img;done

将yaml文件传到master01上,构建pod

kubectl apply -f ingress-nginx.yaml

kubectl get pod -n ingress-nginx

搭建私有镜像仓库

#添加阿里云docker-ce仓库

yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装docker,传文件过来安装

yum install ./*.rpm -y
systemctl enable docker --now
 #harbor仓库需要通过docker-compose(单主机的容器编排管理工具)管理,传文件过来。

 chmod +x docker-compose 
 mv docker-compose /usr/bin #移动到可执行文件目录,使docker-compose全局可用

安装harbor

#把文件传过来

tar -xf harbor-v2.5.1.tgz 
cd harbor
docker load -i harbor.v2.5.1.tar.gz #导入镜像文件
mv harbor.yml.tmpl harbor.yml
vi harbor.yml

修改内容:

hostname: 192.168.174.138 #改成自己的harbor主机IP

#注释掉https通信方式,如下
#https: 
  # https port for harbor, default is 443
  # port: 443
  # The path of cert and key files for nginx
  # certificate: /your/certificate/path
  # private_key: /your/private/key/path

harbor_admin_password: 123456 #改个简单密码
./install.sh 

成功后可以访问harbor的web页面

配置私有仓库地址和镜像加速器

vim /etc/docker/daemon.json

内容如下:
{
  "insecure-registries": ["http://192.168.174.138"], 
  "registry-mirrors": ["https://5f352q46.mirror.aliyuncs.com"]
}

systemctl restart docker #重启后不会自动启动相关容器,手动执行以下命令。注意命令在harbor目录下执行,因为目录中docker-compose.yml文件定义了相关容器信息。
docker-compose down
docker-compose up -d #-d后台运行

部署nfs

yum install nfs-utils -y 

mkdir /wordpress_volume

vim /etc/exports

/wordpress_volume  192.168.0.0/255.255.0.0(rw,no_root_squash,no_all_squash,no_subtree_check)

#将目录wordpress_volume共享给192.168.0.0/24主机,权限是rw,当NFS客户端以root管理员访问时,映射为NFS服务器的root管理员。也可以写具体IP,用逗号分开。

systemctl enable nfs --now
#如果集群Master管理节点不需要将数据存储到NFS中,只需要在node01与node02节点安装即可。

#在node1、node2上安装nfs的客户端

yum install nfs-utils -y

systemctl enable nfs --now

showmount -e 192.168.174.138

部署StorageClass动态储存

如果使用 StorageClass 结合NFS作为后端存储,则需要一个 nfs-client-provisioner 程序, 充当它们之间的驱动,使动态储存的数据能到达nfs。

(1)部署nfs-client-provisioner

1)创建RBAC(基于角色的访问控制权限)为nfs-client-provisioner提供访问集群的权限

#在master01上

vim rbac.yaml

#内容如下

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

  #注意使用vim的粘贴模式,首行首字母可能会被吞掉,记得手动加一下。

  kubectl apply -f rbac.yaml

2)部署nfs-client-provisioner

#在master01上

vim deployment.yaml

#内容如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 192.168.174.138 #修改为实际nfs地址
            - name: NFS_PATH
              value: /wordpress_volume #修改为实际共享目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.174.138 #修改为实际nfs地址
            path: /wordpress_volume #修改为实际共享目录

kubectl apply -f deployment.yaml 
#因为文件中镜像下载地址不可访问,所以手动将镜像在node01、02上加载后在执行此步骤构建pod
#在node01、node02上

#将镜像拖入加载
docker load -i nfs-subdir-external-provisioner.tar 
kubectl get pod 
#如果nfs处于running状态就成功了

(2) 部署StorageClass

#在master01上:
vim class.yaml

#内容如下

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:                     #向底层存储系统传递配置信息
  archiveOnDelete: "false"      #PV被删除时,false表示数据也会被删除,设定为true数据保留

kubectl apply -f class.yaml

kubectl get sc

部署MySQL数据库

rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm

rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

yum install mysql-server -y

systemctl enable mysqld --now

grep password /var/log/mysqld.log

mysql -uroot -p'密码'  #p和密码之间没有空格

set global validate_password_policy=0; #修改密码复杂度策略,只验证长度

alter user root@"localhost" identified by "admin123456";

vim /etc/my.cnf

[mysqld]

#修改密码复杂度策略,只验证长度
validate_password_policy=0

#设置字符集支持中文
character-set-server=utf8

systemctl restart mysqld

mysql -uroot -padmin123456

CREATE USER 'root'@'%' IDENTIFIED BY 'admin123456'; #创建一个名为 root 的用户,并设置该用户可以从任何主机('%')连接到 MySQL 数据库。
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'admin123456'; #授予名为 root 的用户在所有数据库上的全部权限。

FLUSH PRIVILEGES;  刷新 MySQL 的权限表,以便立即使授权变更生效。

create database wordpress;

构建wordpress镜像

wget https://cn.wordpress.org/wordpress-6.0-zh_CN.tar.gz

tar -xf wordpress-6.0-zh_CN.tar.gz 

cd wordpress
cp wp-config-sample.php wp-config.php
vim wp-config.php

#修改内容如下

define( 'DB_NAME', 'wordpress' ); #数据库名

/** Database username */
define( 'DB_USER', 'root' ); #用户名

/** Database password */
define( 'DB_PASSWORD', 'admin123456' ); #密码

/** Database hostname */
define( 'DB_HOST', '192.168.174.138' ); #地址

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link 

 https://api.wordpress.org/secret-key/1.1/salt/ #访问这个地址,获取密钥和盐值,用于加密通信。

 WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */

 #将获取到的密钥和盐值复制替换到文件中

define('AUTH_KEY',         '_+k.TNd@2A?*sX*=TWA@K-Evv)u3+DMl|pXwQ*o[5oy;((I suo_Wk@0U0Ic7.:W');
define('SECURE_AUTH_KEY',  '&#|po0t,3b*d-[0g0AFp1/.%(-GS<I8sq&bYoj*ok31Ztr;vjn,Pe,qHE?>&6AUc');
define('LOGGED_IN_KEY',    '1v}EklP`o+@#Go$64A{V{-J`Z#J/&~2ATG7HAw|Hw,g|2|R@JZSY-|?icG:@*E]p');
define('NONCE_KEY',        'qQFa8.ud+[qniXy-C=W)59G<Bd$nI,Cit-=[g|<pBv^,!uXG+iB;8EIK(|,veQuN');
define('AUTH_SALT',        ')cB ?-hk{mgA]KUq.GPX<n.5m!;![0`5qw-)W2B|0zSZ3Hy_YY>RX%&O=Jj[neI6');
define('SECURE_AUTH_SALT', 'a.17{=|wTZA4f*xzQpj|`b_taR7WL*?N^C@ZUp_mu:MFU~>+EAiF;`n1#1oNT:@T');
define('LOGGED_IN_SALT',   ';%Y8FTt{9Z:1a#vJ+-pMtL!~J<ied$l%/*_GXH_9e af)/hg&d*2z!=E e;1v<z,');
define('NONCE_SALT',       'tQ*N+`,PZI|XTe_Fb4 LTki}xrh.y!e@erK!]Nd=~N];?B<|/nF8^E-*|h%S$]}&');
#写dockerfile
#在wordpress目录中进行
vim dockerfile

#内容如下

#定义基础镜像,在root目录下执行docker pull centos:7.9.2009
FROM centos:7.9.2009

#清理默认的仓库文件
RUN  rm -rf /etc/yum.repos.d/*

#下载阿里云软件仓库
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \
    yum -y install wget && \
    wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

#准备Nginx仓库
COPY ./nginx.repo /etc/yum.repos.d/

#准备PHP仓库,将php7.2.tar.gz放到wordpress目录
ADD php7.2.tar.gz /
RUN cd /php7.2/ && yum install ./*.rpm -y
RUN yum install nginx-1.20.2 -y

#拷贝优化好的nginx.conf配置文件,见下文
COPY ./nginx.conf /etc/nginx

#拷贝站点配置文件,见下文
RUN rm -rf /etc/nginx/conf.d/*
COPY ./wordpress.conf /etc/nginx/conf.d/

#拷贝项目文件到Nginx网页目录
RUN rm -rf /usr/share/nginx/html/*
COPY . /usr/share/nginx/html

#修改PHP运行用户和组,修改PHP时区
RUN sed -i "s/user = apache/user = nginx/" /etc/php-fpm.d/www.conf && \
    sed -i "s/group = apache/group = nginx/" /etc/php-fpm.d/www.conf && \
    sed -i "s#;date.timezone =#date.timezone = Asia/Shanghai#" /etc/php.ini

#修改项目文件属主为nginx
RUN chown -R nginx.nginx /usr/share/nginx/html/

#暴露端口
EXPOSE 80

#启动Nginx与PHP,需要把nginx挂载前台,否则容器会自动关闭。
CMD /usr/sbin/php-fpm -D && "nginx" "-g" "daemon off;"
#在wordpress目录下创建nginx.conf
vim nginx.conf

#定义nginx运行用户和组
user nginx;

#自动侦测可用的CPU核心数,一个worker对应一个CPU核心
worker_processes auto;

#错误日志文件
error_log /var/log/nginx/error.log;

#进程pid文件
pid /run/nginx.pid;

#自动调用配置文件
include /usr/share/nginx/modules/*.conf;

#设置每个worker可以建立的最大连接数
events {
    worker_connections 20000;
}

http {
    #access日志类型,及日志文件路径
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;

    #启用sendfile功能,sendfile是一个直接将数据从磁盘传送到网络接口的系统调用,大大提高了数据传输的效率
    sendfile            on;

    #启动tcp_nopush和tcp_nodelay功能,它能让系统尽可能把所有的数据打包到一个TCP包中再发送出去,从而减轻了网络拥塞,提高了网络吞吐量
    tcp_nopush          on;
    tcp_nodelay         on;

    #TCP连接的保持活动的超时时间(单位是秒),如果在这段时间内,客户端没有任何活动,服务器就会关闭这个连接
    keepalive_timeout   65;

    #这个指令设置了Nginx在处理请求时用来存储mime类型的哈希表的最大大小
    types_hash_max_size 4096;

    #自动调用的配置文件,mime是一种标识文件类型的方式,当Nginx发送一个文件到客户端时,让客户端知道这个文件是什么类型
    include             /etc/nginx/mime.types;

    #设置了默认的mime类型,如果Nginx无法确定一个文件的类型,就会把它当作application/octet-stream类型处理,application/octet-stream 是一种二进制文件的通用类型,通常表示这个文件是供下载而不是直接显示的
    default_type        application/octet-stream;

    #自动调用的虚拟web主机配置文件
    include /etc/nginx/conf.d/*.conf;

    #开启gzip压缩功能
    gzip  on;
    #禁用对特定的浏览器的gzip压缩,"msie6"是一个正则表达式,匹配IE6.0,因为这个版本的IE对gzip支持有问题
    gzip_disable "msie6";
    gzip_vary on;
    #当请求经过代理服务器时,Nginx是否压缩响应,"any"表示无论代理服务器返回的是什么,都压缩响应
    gzip_proxied any;
    #设置了gzip压缩的级别,范围是1到9,1表示最快但压缩率最低,9表示最慢但压缩率最高,6是一种折衷的选择,提供了良好的压缩率和合理的速度
    gzip_comp_level 6;
    #设置了压缩时使用的缓冲区数量和大小,Nginx会使用16个8KB的缓冲区进行压缩
    gzip_buffers 16 8k;
    #设置了需要压缩的HTTP版本,Nginx只会压缩HTTP 1.1或更高版本的响应
    gzip_http_version 1.1;
    #设置了需要压缩的响应的最小长度,只有长度超过256字节的响应才会被压缩
    gzip_min_length 256;
    #设置了对以下类型的文件进行压缩
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}
#在wordpress目录下创建wordpress.conf(网站配置文件)

#在wordpress目录下创建wordpress.conf(网站配置文件)

server {
        listen 80;
        server_name _;
        root /usr/share/nginx/html;

        location / {
                index index.php;
        }

        #设置静态资源缓存
        location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
            access_log off;
            log_not_found off;
            expires 30d;
        }

        #配置nginx连接php
        location ~ \.php$ {
            root           /usr/share/nginx/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
         }

}
#在wordpress目录下创建nginx.repo

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
#构建镜像

docker build -f dockerfile -t wordpress:v6.0 .

# -f 指定dockerfile的文件名,如果就叫dockerfile可以省略,-t 指定构建的容器名称, . 表示在当前目录构建。

镜像推送到私有仓库

在harbor web页面中创建一个公共项目,名为wordpress,不限容量。

#修改镜像标签
docker tag wordpress:v6.0 192.168.174.138/wordpress/wordpress:v6.0

#登录仓库
docker login 192.168.174.138
#账密是:admin 123456

#推送镜像到当前项目
docker push 192.168.174.138/wordpress/wordpress:v6.0
使k8s工作节点能访问私有仓库
#在node01、02上
vim /etc/docker/deamon.json

#添加私有仓库地址

"insecure-registries": ["http://192.168.174.138"]

systemctl restart docker

在集群上部署SVC、PVC

#在master01上

mkdir wordpress

kubectl create ns wordpress #创建新的名称空间,用来存放镜像

cd wordpress

vim wordpress-mysql-svc.yml #实现集群项目访问数据库的代理转发

#文件内容如下

apiVersion: v1
kind: Service
metadata:
  name: mysql                   #service名称,要与Endpoints名称保持一致
  namespace: wordpress
spec:
  type: ClusterIP               #service类型
  clusterIP: None               #类型headless service
  ports:
  - name: mysql                 #service端口名称
    port: 3306                  #service端口号
    protocol: TCP
    targetPort: 3306            #目标端口
---
apiVersion: v1
kind: Endpoints                 #Endpoints用于表示Service可以路由到的后端信息
metadata:
  name: mysql                   #Endpoints名称,要与service名称保持一致
  namespace: wordpress
subsets:                        #定义后端的信息
- addresses:                    #后端的IP地址
  - ip: 192.168.174.138         #MySQL数据库的IP地址
  ports:                        #后端的端口信息
  - name: mysql                 #端口名称,要与Service中的端口名称相匹配
    port: 3306                  #目标端口,要与Service中的目标端口相匹配
    protocol: TCP

kubectl apply -f wordpress-mysql-svc.yml

kubectl get svc -n wordpress 

kubectl get pod -n kube-system -o wide | grep coredns #查看集群的dns的IP

dig @172.16.140.69 mysql.wordpress.svc.cluster.local +short #通过DNS解析mysql,查看代理的IP是否正确

#创建 PVC 存储卷用于存储 Nginx 日志,pvc指导创建pv.pvc在节点容器上,pv实际在nfs上。

vim ngxlog-pvc.yml

#内容如下

apiVersion: v1                  #PVC版本
kind: PersistentVolumeClaim     #PVC类型
metadata:
  name: ngx-log                 #PVC名称
  namespace: wordpress          #名称空间
spec:
  storageClassName: nfs-client  #动态存储(前边创建好的)
  accessModes:                  #访问模式
    - ReadWriteOnce             #权限为读写
  resources:
    requests:
      storage: 3Gi              #需要的存储空间

kubectl apply -f ngxlog-pvc.yml

#创建 PVC 存储卷用于存储 wordpress 文章中的图片

vim tupian-pvc.yml

#内容如下

apiVersion: v1                  #PVC版本
kind: PersistentVolumeClaim     #PVC类型
metadata:
  name: tupian                  #PVC名称
  namespace: wordpress          #名称空间
spec:
  storageClassName: nfs-client  #动态存储(前边创建好的)
  accessModes:                  #访问模式
    - ReadWriteOnce             #权限为读写
  resources:
    requests:
      storage: 3Gi              #需要的存储空间

kubectl apply -f tupian-pvc.yml

控制器部署pod:wordpress

#通过 Deployment 控制器部署 wordpress

vim wordpress.yml

#内容如下

apiVersion: apps/v1             #控制器版本
kind: Deployment                #控制器类型
metadata:
  name: wordpress               #控制器名称
  namespace: wordpress          #名称空间
spec:
  selector:                     #标签选择器(通过标签选择管理的Pod是谁)
    matchLabels:                #标签类型(key-value)
      app: wordpress            #标签名称
  template:                     #创建Pod模板
    metadata:                   #模板详细信息
      labels:                   #给Pod打标签
         app: wordpress         #标签名称(要与选择器中定义的标签一致)
    spec:
      #定义存储卷
      volumes:
        - name: log                #存储卷名称(自定义,后边调用该名称)
          persistentVolumeClaim:   #存储卷类型PVC
            claimName: ngx-log     #上边创建好的PVC名称,用于存储Nginx日志
        - name: tupian             #存储卷名称(自定义,后边调用该名称)
          persistentVolumeClaim:   #存储卷类型PVC
            claimName: tupian      #上边创建好的PVC名称,用于存储博客图片
      containers:                  #定义容器列表
      - name: wordpress            #容器名称(自定义)
        image: 192.168.174.138/wordpress/wordpress:v6.0   #容器镜像
        ports: 
        - containerPort: 80        #容器端口
        #挂载存储卷到容器中
        volumeMounts:                     #挂载存储卷到容器
          - name: log                     #存储卷名称(上边定义好的)
            mountPath: "/var/log/nginx"   #挂载到容器的路径
          - name: tupian                  #存储卷名称(上边定义好的)
            mountPath: "/usr/share/nginx/html/wp-content/uploads/"  #挂载到容器的路径
---
#部署项目的Service代理
apiVersion: v1              #Service版本
kind: Service               #Service类型
metadata:
  name: wordpress-svc       #Service的名称
  namespace: wordpress      #名称空间
spec:
  selector:                 #标签选择器(通过标签选择代理的Pod是谁)
    app: wordpress          #标签名称
  ports:
  - port: 80                #Service监听的端口
    targetPort: 80          #转发给后端的Pod端口
---
#七层代理Ingress发布域名
apiVersion: networking.k8s.io/v1   #Ingress的版本
kind: Ingress                      #Ingress的类型
metadata:
  name: wordpress-ing              #Ingress的名称
  namespace: wordpress             #名称空间
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /    #注解
spec:
  ingressClassName: nginx          #控制器的类型Nginx
  rules:
  - host: web.wordpress.com        #定义访问的域名
    http:
      paths:                       #访问的路径
      - path: /                    #网页根路径,即/usr/share/nginx/html/
        pathType: Prefix           #Prefix类型匹配“/”下所有路径
        backend:                   #Ingress接收请求后转给后端的Service信息
          service:                 
            name: wordpress-svc    #Service名称,参考上边定义的Service名称
            port:                  #Service端口
              number: 80           #端口

kubectl apply -f wordpress.yml

kubectl get pod -n wordpress

kubectl describe pod -n wordpress #看一下pod被部署在哪个node上

kubectl get svc,ing -n wordpress #检查mysql代理和域名是否正确

kubectl get ns #找到ingress那个名称空间

kubectl get pod -n ingress-nginx -o wide #找域名对应的node节点IP

在同网段Windows主机上做一下域名映射即可访问
#删除命令 kubectl delete -f wordpress.yml
#排查命令 kubectl logs <podname> -n <namespace> --previous
#yaml文件中replicas参数,用于扩缩pod数量,改完后 kubectl apply -f wordpress.yml 更新一下
#如果docker镜像有问题,删除重新构建,同时注意删除node节点已经拉下来的错误镜像

负载均衡测试

由replicas =1 ,改为replicas =3,起3个pod。

三主两从k8s集群搭建

三主两从k8s集群搭建

(1)进入pod jwbn2,写测试页面test.html,内容为pod1。

kubectl -n wordpress exec -it wordpress-7fb84d9969-jwbn2 -- /bin/bash

cd /usr/share/nginx/html

vi test.html

写入pod111

三主两从k8s集群搭建

(2)进入pod njcgj ,写测试页面test.html,内容为pod222

三主两从k8s集群搭建

(3)进入pod wpmbl,写测试页面test.html,内容为pod333

三主两从k8s集群搭建

(4)访问web.wordpress.com/test.html,每刷新一次,就显示不同内容,说明起到了负载均衡的效果

三主两从k8s集群搭建

涉及文件下载地址

链接:https://pan.baidu.com/s/1Eb3B9PzHf_DfVqQWxg72mg?pwd=wys1
提取码:wys1
--来自百度网盘超级会员V6的分享

一些结果图

三主两从k8s集群搭建

三主两从k8s集群搭建

三主两从k8s集群搭建

三主两从k8s集群搭建

三主两从k8s集群搭建

三主两从k8s集群搭建

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论
分享
0
希望看到您的想法,请您发表评论x