k8s集群部署、以及简易搭建一个wordpress

k8s集群部署、以及简易搭建一个wordpress

此文属于个人瞎折腾笔记,正确性有待商议

本文安装详细参考此篇文章实战Kubernetes之快速部署 K8s 集群 v1.28.0-云社区-华为云

使用Docker、cri-dockerd 和 Kubernetes来搭建,并不是containerd和 Kubernetes

centos

安装前置

由于运行容器是用docker,那就要配置docker的镜像源

[root@k8s-master-01 k8s]# cat /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://dockerhub.azk8s.cn",
    "https://reg-mirror.qiniu.com",
    "https://registry.docker-cn.com",
    "http://hub-mirror.c.163.com",
    "https://3laho3y3.mirror.aliyuncs.com",
    "http://f1361db2.m.daocloud.io",
    "https://mirror.ccs.tencentyun.com"
  ]
}
# 1、修改主机名(看你想不想,其实改名字出问题问ai也方便些)
hostnamectl set-hostname k8s-master-01
hostnamectl set-hostname k8s-node-01
hostnamectl set-hostname k8s-node-02

# 2、三台机器添加host解析
cat >> /etc/hosts << "EOF"
192.168.236.135 k8s-master-01 m1
192.168.236.134 k8s-node-01 n1
192.168.236.133 k8s-node-02 n2
EOF

# 关闭和禁用防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭selinux,selinux 是 Linux 系统下的一个安全服务,需要关闭
setenforce 0  # 临时
最好永久,自行ai

# 关闭 Linux 的 swap 分区(必做环节)
swapoff -a  # 临时
最好永久,自行ai

安装 cri-dockerd

cri-dockerd 用于为 Docker 提供一个能够支持 K8s 容器运行时标准的工具,从而能够让 Docker 作为 K8s 容器引擎。通过 wget 下载 cri-dockerd 安装包,然后通过 rpm 命令进行安装。

# 通过 wget 命令获取 cri-dockerd软件
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.12/cri-dockerd-0.3.12-3.el7.x86_64.rpm

# 通过 rpm 命令执行安装包
rpm -ivh cri-dockerd-0.3.12-3.el7.x86_64.rpm

安装完成后修改配置文件(/usr/lib/systemd/system/cri-docker.service),在 “ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd://” 这一行增加 “–pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9”。

# 打开 cri-docker.service 配置文件
nano /usr/lib/systemd/system/cri-docker.service

# 修改对应的配置项
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9

配置文件修改后,重新加载配置并开启 cri-dockerd 服务。

# 加载配置并开启服务
systemctl daemon-reload
systemctl enable cri-docker && systemctl start cri-docker

编辑 “/etc/yum.repos.d/kubernetes.repo” 配置文件,添加阿里云的镜像库。(如果源炸了就ai,我换了太多个了,不清楚是哪个)

cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安装 kubeadm、kubelet 和 kubectl

所有K8S服务器上都需要安装 kubeadm、kubelet 和 kubectl 这三个工具。

  • kubeadm 用来初始化 K8s 集群;
  • kubelet 是每个节点的 K8s 管理员;
  • kubectl 是 K8s 的命令行交互工具。

这里装1.28,因为阿里云就的仓库最新就是这么新,1.30往后的那些我折腾不出来

sudo yum clean all
sudo yum makecache
sudo yum install -y kubelet-1.28.0 kubeadm-1.28.0 kubectl-1.28.0

# 开机启动 kubelet 服务
systemctl enable kubelet

Master 节点初始化 K8s

所有准备工作都完成了,于可以进行 K8s 的初始化了,只需要在 Master 节点上执行以下初始化命令。

kubeadm init \
  --apiserver-advertise-address=192.168.236.135 \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.28.0 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16 \
  --cri-socket=unix:///var/run/cri-dockerd.sock \
  --ignore-preflight-errors=all

其中,在以上返回结果中有 3 条命令需要立即执行,这是用来设置 kubectl 工具的管理员权限,执行之后就可以在 Master 节点上通过终端窗口使用 kubectl 命令。

# 在 Master 节点上执行以下命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

worker节点加入k8s集群

master节点拿信息

[root@k8s-master-01 k8s]# kubeadm token create --print-join-command
kubeadm join 192.168.236.135:6443 --token ubi2qj.c55fm182snz74t73 --discovery-token-ca-cert-hash sha256:e94b1bb74a6c98031e764f13ae5f54b260d1141698ee2e2f691bd104d8d13309

K8s 初始化之后,就可以在其他 2 个工作节点上执行 “kubeadm join” 命令,因为我们使用了 cri-dockerd ,需要在命令加上 “–cri-socket=unix:///var/run/cri-dockerd.sock” 参数。

# 在两个工作节点上执行
kubeadm join 192.168.9.86:6443 --token xxxxxx \
        --discovery-token-ca-cert-hash sha256:xxxxxx \
        --cri-socket=unix:///var/run/cri-dockerd.sock
        
        
即是
kubeadm join 192.168.236.135:6443 \
  --token ubi2qj.c55fm182snz74t73 \
  --discovery-token-ca-cert-hash sha256:e94b1bb74a6c98031e764f13ae5f54b260d1141698ee2e2f691bd104d8d13309 \
  --cri-socket unix:///var/run/cri-dockerd.sock

安装 K8s 网络插件

K8s 网络插件,也称为容器网络接口(CNI)插件,是实现 K8s 集群中容器间通信和网络连接的关键组件,否则 Pod 之间无法通信。Kubernetes 支持多种网络方案,这里我们使用 calico。

Calico 是通过执行一个 YAML 文件部署到 K8s 集群里的,所以我们首先需要通过 “wget” 命令下载这个 YAML 文件。

# 下载 Calico 插件部署文件
wget https://docs.projectcalico.org/manifests/calico.yaml

通过 vi 编辑器修改 “calico.yaml” 文件中的 “CALICO_IPV4POOL_CIDR” 参数,需要与前面 “kubeadm init” 命令中的 “–pod-network-cidr” 参数一样(10.244.0.0/16)。如果文件里的 “CALICO_IPV4POOL_CIDR” 参数前面有 “#”,表示被注释了,需要删除 “#”。

修改位置如下所示。(在 vi 中可以通过输入 “:set nu” 来查看行号,同时可以输入 “/CALICO_IPV4POOL_CIDR” 来快速定位到参数位置)

# 修改文件时注意格式对齐
4598 # The default IPv4 pool to create on startup if none exists. Pod IPs will be
4599 # chosen from this range. Changing this value after installation will have
4600 # no effect. This should fall within `--cluster-cidr`.
4601 - name: CALICO_IPV4POOL_CIDR
4602   value: "10.244.0.0/16"
4603 # Disable file logging so `kubectl logs` works.
4604 - name: CALICO_DISABLE_FILE_LOGGING
4605   value: "true"

最后,使用 “kubectl apply” 命令将 Calico 插件部署到集群里,部署 YAML 文件命令如下:

kubectl apply -f calico.yaml

Calico 部署会比较慢,大概等个几分钟,等待 Calico 部署完成后,再次通过命令 “kubectl get node” 查看节点状态,就可以看到所有节点已经准备就绪,此时集群正式搭建成功。

[root@k8s-master ~]# kubectl get node
NAME           STATUS   ROLES           AGE   VERSION
k8s-master     Ready    control-plane   12h   v1.28.0
k8s-worker1    Ready    <none>          12h   v1.28.0
k8s-worker2    Ready    <none>          10h   v1.28.0

搭建一个wordpress

首先需要你的本地有/home/eth/k8s/wp/data/wordpress/home/eth/k8s/wp/data/wordpress这两个文件给k8s做pv使用,由于我是用我自己的目录,所以看起来就很丑了,可自行在yaml中替换

---
# 1. 创建命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: wordpress-namespace
---
# 2. 创建 PersistentVolume: MySQL
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""  # 显式设置为空,避免与默认 StorageClass 冲突
  hostPath:
    path: /home/eth/k8s/wp/data/mysql
    type: DirectoryOrCreate
---
# 3. 创建 PersistentVolume: WordPress
apiVersion: v1
kind: PersistentVolume
metadata:
  name: wp-pv
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""  # 显式设置为空
  hostPath:
    path: /home/eth/k8s/wp/data/wordpress
    type: DirectoryOrCreate
---
# 4. 创建 PersistentVolumeClaim: MySQL(关键:禁用动态供应)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  namespace: wordpress-namespace
spec:
  storageClassName: ""  # ⚠️ 关键:必须设置为空,否则会被 local-path 劫持
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
# 5. 创建 PersistentVolumeClaim: WordPress(同上)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  namespace: wordpress-namespace
spec:
  storageClassName: ""  # ⚠️ 关键:禁用动态供应
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
# 6. 部署 MySQL
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  namespace: wordpress-namespace
  labels:
    app: wordpress
    tier: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate  # 确保 MySQL 停止后再启动 WordPress
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
        - image: mysql:5.7
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "MySecureRootPass123!"  # 🔐 请根据需要修改
            - name: MYSQL_DATABASE
              value: wordpress
            - name: MYSQL_USER
              value: wordpress
            - name: MYSQL_PASSWORD
              value: "MySecureDbPass123!"   # 🔐 请修改
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pv-claim
---
# 7. MySQL 服务(Headless)
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  namespace: wordpress-namespace
  labels:
    app: wordpress
    tier: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None  # Headless Service,适合有状态应用
---
# 8. 部署 WordPress
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  namespace: wordpress-namespace
  labels:
    app: wordpress
    tier: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
        - image: wordpress:6.0-apache
          name: wordpress
          env:
            - name: WORDPRESS_DB_HOST
              value: wordpress-mysql
            - name: WORDPRESS_DB_USER
              value: wordpress
            - name: WORDPRESS_DB_PASSWORD
              value: "MySecureDbPass123!"   # 必须与 MYSQL_PASSWORD 一致
            - name: WORDPRESS_DB_NAME
              value: wordpress
          ports:
            - containerPort: 80
              name: http
          volumeMounts:
            - name: wordpress-storage
              mountPath: /var/www/html
      volumes:
        - name: wordpress-storage
          persistentVolumeClaim:
            claimName: wp-pv-claim
---
# 9. WordPress 服务(NodePort,适合本地访问)
apiVersion: v1
kind: Service
metadata:
  name: wordpress-service
  namespace: wordpress-namespace
  labels:
    app: wordpress
    tier: frontend
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080  # 可通过 http://<任意节点IP>:30080 访问
      protocol: TCP
  selector:
    app: wordpress
    tier: frontend

然后运行

kubectl apply -f wordpress-local-final.yaml

查看状态

# 查看命名空间
kubectl get ns | grep wordpress

# 查看 PVC(应为 Bound)
kubectl get pvc -n wordpress-namespace

# 查看 PV(应为 Bound)
kubectl get pv

# 查看 Pod(稍等 1-2 分钟,应变为 Running)
kubectl get pods -n wordpress-namespace -w

访问wp

http://<任意节点IP>:30080

多节点副本的一些个人踩坑

后面的不用跟着做,都是错

wp副本为2

由于我们只设置了wp、mysql的副本数量都为1 即replicas: 1,所以其实现在是单节点无保障的运行

也就是说node2和master节点损坏,都会导致wp服务出问题

[root@k8s-master-01 k8s]# kubectl get pods -n wordpress-namespace -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
wordpress-f99656877-grphx          1/1     Running   0          19m   10.244.44.193   k8s-node-02   <none>           <none>
wordpress-mysql-5b4ddb96ff-j2sdv   1/1     Running   0          19m   10.244.44.194   k8s-node-02   <none>           <none>

如果给wp副本添加数量为2,就可以有两个

[root@k8s-master-01 wp]# kubectl get pods -n wordpress-namespace -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
wordpress-f99656877-crblb          1/1     Running   0          28s   10.244.154.196   k8s-node-01   <none>           <none>
wordpress-f99656877-grphx          1/1     Running   0          27m   10.244.44.193    k8s-node-02   <none>           <none>
wordpress-mysql-5b4ddb96ff-j2sdv   1/1     Running   0          27m   10.244.44.194    k8s-node-02   <none>           <none>

现在的情况中

  • k8s-node-01 上运行的 Pod → 使用的是 node01 的 /home/eth/k8s/wp/data/wordpress
  • k8s-node-02 上运行的 Pod → 使用的是 node02 的 /home/eth/k8s/wp/data/wordpress
  • 两个目录完全独立、不共享

但是这样子做会有问题,问题不在共用一个mysql,主要是因为wp是一个有状态应用,比如他的头像和主题,都会上传到对应node的wp目录里

那么会发生什么?

假设用户上传一张头像图片:

  1. 请求被路由到 k8s-node-02 上的 WordPress → 图片保存在 node02 的磁盘上
  2. 下次访问时,请求被路由到 k8s-node-01 上的 WordPress → 它去 node01 的磁盘找图片 → 找不到!→ 404

解决方法

方案一:搭建一个 NFS 服务器,大火一起用

方案二:OSS

这种情况下无状态应用更适合来做副本

同时为什么mysql不能给副本数量为2?

因为 数据库(MySQL)是有状态的、写唯一的系统,不像 WordPress 前端可以无状态多副本。

如果你强行改成 replicas: 2 并使用当前的 hostPath + PVC 存储方案,会发生:

问题 后果
❌ 两个 MySQL 实例尝试写同一个数据目录 数据损坏、崩溃、启动失败
❌ 每个副本都独立启动自己的 MySQL 服务 主键冲突、数据不一致
❌ 没有主从复制机制 写操作无法同步

🚫 结果:数据库损坏,WordPress 无法连接,服务彻底瘫痪。

数据库副本方案有三个

方案一:使用 StatefulSet + 主从复制(配置很复杂)

方案二:使用云数据库(厂商就会帮你备份了,所以单点也无所谓)

方案三:使用 Kubernetes 原生数据库 Operator

杂类笔记

apply -f的时候kubectl怎么判断是新、旧配置

当你使用 kubectl apply 时,Kubernetes 会根据以下几点来决定是创建新资源还是更新现有资源:

  1. 资源类型:如 Deployment、Service 等。
  2. 资源名称:在 YAML 文件中定义的 metadata.name
  3. 命名空间:如果 YAML 文件中指定了 metadata.namespace,则会在指定的命名空间内进行查找;如果没有指定,默认为 default 命名空间。

哪一步导致k8s通过cri-dockerd使用docker来拉取镜像

Master 节点和worker节点都加上的这两句导致的

 --cri-socket=unix:///var/run/cri-dockerd.sock

命令速记

kubectl get ns 

kubectl get pods -n wordpress-namespace -o wide

watch kubectl get pods -n wordpress-namespace

kubectl describe pods <pod-name> -n wordpress-namespace
#拿master节点信息
kubeadm token create --print-join-command
posted @ 2025-08-02 20:44  eth258  阅读(97)  评论(0)    收藏  举报