k8s简介
定义
容器集群管理平台
集群类型
一主多从(有风险,没有管理节点则工作节点不可用,适合测试环境)
多主多从(奇数台master,随意台node,适合生产环境)
etcd选举机制决定master为奇数台,选择一个 Leader 来处理写操作,并确保集群的一致性和高可用性。
重要集群组件
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
所有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发布项目。
部署过程
部署代理
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。
(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
(2)进入pod njcgj ,写测试页面test.html,内容为pod222
(3)进入pod wpmbl,写测试页面test.html,内容为pod333
(4)访问web.wordpress.com/test.html,每刷新一次,就显示不同内容,说明起到了负载均衡的效果
涉及文件下载地址
链接:https://pan.baidu.com/s/1Eb3B9PzHf_DfVqQWxg72mg?pwd=wys1
提取码:wys1
--来自百度网盘超级会员V6的分享
一些结果图
本文作者为A9bot,转载请注明。