K8s 部署 ECShop 商城完整实操|容器化搭建电商网站
K8s 部署 ECShop 商城完整实操|容器化搭建电商网站
依据实际操作日志整理(master30 / worker31 / worker32),与题目 12 项一一对应;
域名按本人要求使用*.ningcode.cn(镜像仓库为内网hub.laoma.cloud),如需更换域名,替换对应 hosts、证书 CN 和 ingress 中的 host 即可。
环境信息
| 主机 | IP | 角色 |
|---|---|---|
| master30 | 10.1.8.30 | 控制节点 + NFS 服务器 |
| worker31 | 10.1.8.31 | 工作节点(NFS 客户端) |
| worker32 | 10.1.8.32 | 工作节点(NFS 客户端,mysql-0 所在) |
| 共享目录 | 10.1.8.30:/ecshop | NFS 动态卷后端 |
| 镜像仓库 | hub.laoma.cloud(192.168.46.201) | 内网 registry |
| 业务域名 | shop.ningcode.cn / dashboard.ningcode.cn | Ingress 访问 |
1. 部署 NFS 服务器,提供共享目录 /ecshop
1.1 master30 安装 NFS 服务端并创建共享目录
apt install -y nfs-kernel-server
mkdir -m 777 /ecshop
echo hellow > /ecshop/index.html # 测试文件,验证挂载
vim /etc/exports # 添加共享配置
cat /etc/exports
# /etc/exports 增加一行
/ecshop *(rw)
exportfs -r
exportfs -v
# /ecshop <world>(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)
systemctl restart nfs-server
1.2 worker31 / worker32 安装 NFS 客户端
# worker31、worker32 分别执行
apt install -y nfs-common
2. 部署 NFS 动态卷制备,存储类型 ecshop
创建命名空间并切换默认命名空间(题目 3 的资源均在 ecshop 命名空间):
kubectl create ns ecshop
kubectl config set-context --current --namespace ecshop
编写 ecshop-nfs.yaml(ServiceAccount + RBAC + Provisioner Deployment + StorageClass):
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: ecshop
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-provisioner-runner
rules:
- 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"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: ecshop
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-subdir-provisioner
namespace: ecshop
spec:
replicas: 1
selector:
matchLabels:
app: nfs-provisioner
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccountName: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
imagePullPolicy: IfNotPresent
env:
- name: PROVISIONER_NAME
value: ecshop/nfs-provisioner
- name: NFS_SERVER
value: 10.1.8.30 # 替换成你的 master 节点 NFS 服务器 IP
- name: NFS_PATH
value: /ecshop
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
volumes:
- name: nfs-client-root
nfs:
server: 10.1.8.30 # NFS 服务器 IP,同上
path: /ecshop
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ecshop
provisioner: ecshop/nfs-provisioner
reclaimPolicy: Delete
volumeBindingMode: Immediate
应用并验证:
kubectl apply -f ecshop-nfs.yaml
# serviceaccount/nfs-provisioner created
# clusterrole.rbac.authorization.k8s.io/nfs-provisioner-runner created
# clusterrolebinding.rbac.authorization.k8s.io/run-nfs-provisioner created
# deployment.apps/nfs-subdir-provisioner created
# storageclass.storage.k8s.io/ecshop created
kubectl get sc
# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
# ecshop ecshop/nfs-provisioner Delete Immediate false 60s
创建测试 PVC 验证动态制备:
cat > test-pvc.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
namespace: ecshop
spec:
accessModes:
- ReadWriteMany
storageClassName: ecshop
resources:
requests:
storage: 1Gi
EOF
kubectl apply -f test-pvc.yaml
kubectl get pvc -n ecshop # test-pvc 状态为 Bound
3. 商城相关资源部署在 ecshop 命名空间
kubectl create ns ecshop
kubectl config set-context --current --namespace ecshop
后续 mysql、php、nginx、nfs-provisioner 等资源全部创建在 ecshop 命名空间。
4. 为 ecshop 命名空间设置 Quota
kubectl create quota ecshop-quota -n ecshop \
--hard=cpu=4,memory=8G,requests.cpu=4,requests.memory=8G,requests.storage=500G
# resourcequota/ecshop-quota created
注意:第一次写
request.cpu会报错must be a standard resource for quota,正确的资源名是requests.cpu/requests.memory。
验证:
kubectl get resourcequota -n ecshop
kubectl describe resourcequota ecshop-quota -n ecshop
5. 为 ecshop 命名空间设置 LimitRange
编写 LimitRange.yaml:
apiVersion: v1
kind: LimitRange
metadata:
name: limit-ecshop
namespace: ecshop
spec:
limits:
- type: Container
defaultRequest: # requests 默认值
cpu: 200m
memory: 256Mi
default: # limits 默认值
cpu: 500m
memory: 512Mi
min: # 最小
cpu: 100m
memory: 256Mi
max: # 最大
cpu: "1"
memory: 2048Mi
应用并验证:
kubectl apply -f LimitRange.yaml
# limitrange/limit-ecshop created
kubectl describe limitranges -n ecshop
# Name: limit-ecshop
# Namespace: ecshop
# Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
# ---- -------- --- --- --------------- ------------- -----------------------
# Container cpu 100m 1 200m 500m -
# Container memory 256Mi 2Gi 256Mi 512Mi -
说明:
2Gi即题目要求的2048Mi,随后 php/nginx/mysql Pod 创建时会被 LimitRanger 自动注入上述 requests/limits(日志中 Pod 注解可见LimitRanger plugin set)。
6. 部署 mysql 应用(StatefulSet + Secret + Probe + Service)
6.1 Secret(root 密码、业务用户 ecshop、数据库 ecshop)
echo -n "ningcode@123" | base64
# bmluZ2NvZGVAMTIz
编写 mysql-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: ecshop
type: Opaque
data:
# echo -n "Root@123456" | base64 修改为你想要的 root 密码
mysql-root-password: Um9vdEAxMjM0NTY=
# 业务用户 ecshop
mysql-user: ZWNzaG9w
mysql-password: bmluZ2NvZGVAMTIz
mysql-database: ZWNzaG9w
6.2 StatefulSet + Service
编写 mysql-sts.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: ecshop
spec:
selector:
matchLabels:
app: mysql
serviceName: "mysql-headless" # sts 绑定 headless 服务
replicas: 1
minReadySeconds: 10
template:
metadata:
labels:
app: mysql
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mysql
image: hub.laoma.cloud/library/mysql:5.7 # 从内网仓库拉取 mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-root-password
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-password
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-database
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
# 健康探针
livenessProbe:
exec:
command: ["mysqladmin","-uroot","-p$(MYSQL_ROOT_PASSWORD)","ping"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command: ["mysql","-uroot","-p$(MYSQL_ROOT_PASSWORD)","-e","SELECT 1"]
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: ecshop # NFS 动态卷
resources:
requests:
storage: 2Gi
---
# Headless Service 给 StatefulSet 内部网络使用
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
namespace: ecshop
spec:
selector:
app: mysql
clusterIP: None
ports:
- port: 3306
targetPort: mysql
---
# 业务访问用 service,普通 ClusterIP,供 ecshop 商城连接 mysql
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: ecshop
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: mysql
应用并验证:
kubectl apply -f mysql-secret.yaml
# secret/mysql-secret created
kubectl apply -f mysql-sts.yaml
# statefulset.apps/mysql created
# service/mysql-headless created
# service/mysql configured
kubectl get sts,pod,svc,pvc -n ecshop
# statefulset.apps/mysql 1/1
# pod/mysql-0 1/1 Running (调度到 worker32.ningcode.cn)
# service/mysql ClusterIP None 3306/TCP
# service/mysql-headless ClusterIP None 3306/TCP
# pvc/mysql-data-mysql-0 Bound 2Gi RWO ecshop
验证业务账号可登录:
kubectl exec -it mysql-0 -n ecshop -- mysql -uecshop -pningcode@123
# mysql: [Warning] Using a password on the command line interface can be insecure.
# Welcome to the MySQL monitor.
# Server version: 5.7.44 MySQL Community Server (GPL)
说明:镜像最初写
mysql:5.7拉取困难,后改为内网仓库hub.laoma.cloud/library/mysql:5.7(日志注释“从内网下镜像”)后正常启动。
7. 部署 php 应用(Deployment + ClusterIP Service)
7.1 商城源码共享 PVC(php、nginx 共用)
编写 ecshop-code-pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ecshop-code-pvc
namespace: ecshop
spec:
accessModes:
- ReadWriteMany
storageClassName: ecshop
resources:
requests:
storage: 10Gi
kubectl apply -f ecshop-code-pvc.yaml
kubectl get pvc -n ecshop
# ecshop-code-pvc Bound 10Gi RWX ecshop
7.2 php-fpm Deployment + Service
编写 php-fpm.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-fpm
namespace: ecshop
spec:
replicas: 1
selector:
matchLabels:
app: php-fpm
template:
metadata:
labels:
app: php-fpm
spec:
containers:
- name: php-fpm
image: hub.laoma.cloud/library/php:7.2-fpm-ecshop # 自己构建并推送到内网仓库
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9000
name: php-fpm
volumeMounts:
- name: ecshop-code
mountPath: /usr/share/nginx/html # 挂载商城源码共享 pvc
# 健康探针,tcp 探测 9000 端口
livenessProbe:
tcpSocket:
port: 9000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: 9000
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
volumes:
- name: ecshop-code
persistentVolumeClaim:
claimName: ecshop-code-pvc
---
apiVersion: v1
kind: Service
metadata:
name: php-fpm-svc
namespace: ecshop
spec:
selector:
app: php-fpm
type: ClusterIP
ports:
- port: 9000
targetPort: 9000
应用并验证:
kubectl apply -f php-fpm.yaml
# deployment.apps/php-fpm created
# service/php-fpm-svc created
kubectl describe pod php-fpm-<xxx>
# Image: hub.laoma.cloud/library/php:7.2-fpm-ecshop
# Port: 9000/TCP
# Liveness: tcp-socket :9000 delay=20s timeout=5s period=10s
# Readiness: tcp-socket :9000 delay=5s timeout=3s period=5s
# Mounts: /usr/share/nginx/html from ecshop-code (rw)
# Requests/Limits 由 LimitRanger 注入 200m/256Mi 与 500m/512Mi
注意:若先 apply php-fpm 再创建 PVC,Pod 会 Pending(
persistentvolumeclaim "ecshop-code-pvc" not found),先创建ecshop-code-pvc再 apply 即可。
8. 部署 nginx 应用(Deployment + ConfigMap + PVC + Service)
8.1 nginx 配置文件 ConfigMap
编写 nginx-configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-cm
namespace: ecshop
data:
nginx.conf: |
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass php-fpm-svc:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
8.2 nginx Deployment + Service
编写 nginx-deploy.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: ecshop
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hub.laoma.cloud/library/nginx:1.24
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
volumeMounts:
# 挂载商城源码共享 pvc(NFS 动态卷)
- name: ecshop-code
mountPath: /usr/share/nginx/html
# 挂载 configmap nginx 配置
- name: nginx-conf
mountPath: /etc/nginx/conf.d
# 健康探针,tcp 探测 80 端口
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
volumes:
- name: ecshop-code
persistentVolumeClaim:
claimName: ecshop-code-pvc
- name: nginx-conf
configMap:
name: nginx-cm
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: ecshop
spec:
selector:
app: nginx
type: ClusterIP # 对外统一走 ingress,因此使用 ClusterIP
ports:
- port: 80
targetPort: 80
应用并验证:
kubectl apply -f nginx-configmap.yaml
# configmap/nginx-cm created
kubectl apply -f nginx-deploy.yaml
# deployment.apps/nginx created
# service/nginx-svc created
kubectl get pods -n ecshop
# mysql-0 1/1 Running
# nfs-subdir-provisioner-... 1/1 Running
# nginx-... 1/1 Running
# php-fpm-... 1/1 Running
LNMP 联通性测试(在 nginx Pod 内写测试页):
kubectl exec -it nginx-<pod> -- bash
cat > /usr/share/nginx/html/index.html <<EOF
<h1>ECSHOP TEST PAGE</h1>
<p>NFS PVC working ok!</p>
EOF
cat > /usr/share/nginx/html/test.php <<EOF
<?php
phpinfo();
?>
EOF
kubectl get svc
# nginx-svc ClusterIP 10.101.87.156 <none> 80/TCP
# php-fpm-svc ClusterIP 10.111.180.43 <none> 9000/TCP
curl 10.101.87.156 # <h1>ECSHOP TEST PAGE</h1> NFS PVC working ok!
curl 10.101.87.156/test.php # phpinfo 输出(PHP Version 7.2.34,mysqli/pdo_mysql 已启用)
说明:nginx-svc 最初用 NodePort(80:32020)测试,确认 Metallb/Ingress 方案后删除重建为 ClusterIP,统一由 ingress-nginx 对外暴露。
9. 部署网络组件(metallb + ingress-nginx + 自签名证书)
9.1 部署 metallb(题目中写作 metallab)
wget http://192.168.46.200/class/course-materials/softwares/stage03/metallb-0.14.8.tar.gz
tar -xf metallb-0.14.8.tar.gz
grep image metallb-0.14.8/config/manifests/metallb-native.yaml
# quay.io/metallb/controller:v0.14.8
# quay.io/metallb/speaker:v0.14.8
sed -i 's/quay.io/hub.laoma.cloud/g' metallb-0.14.8/config/manifests/metallb-native.yaml
kubectl apply -f metallb-0.14.8/config/manifests/metallb-native.yaml
kubectl get all -n metallb-system
# pod/controller-... 1/1 Running
# pod/speaker-xxx 1/1 Running(每节点一个)
配置 IP 地址池与 L2 通告:
cat << 'EOF' > ippool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 10.1.8.40-10.1.8.80
EOF
kubectl apply -f ippool.yaml
cat << 'EOF' > L2.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
EOF
kubectl apply -f L2.yaml
9.2 部署 ingress-nginx 控制器
wget http://192.168.46.200/class/course-materials/softwares/stage03/ingress-nginx-controller-v1.11.2.tar.gz
tar -xf ingress-nginx-controller-v1.11.2.tar.gz
grep image: ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml | uniq
# 将镜像替换为内网仓库
sed -ir 's#@sha256.*##;s/registry.k8s.io/hub.laoma.cloud/' ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
kubectl apply -f ingress-nginx-controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml
将控制器 Service 改为 LoadBalancer,由 metallb 分配 EXTERNAL-IP:
kubectl edit svc ingress-nginx-controller -n ingress-nginx # type: LoadBalancer
kubectl get svc ingress-nginx-controller -n ingress-nginx
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# ingress-nginx-controller LoadBalancer 10.97.52.107 10.1.8.40 80:32455/TCP,443:30093/TCP
9.3 为 ingress-nginx 控制器提供自签名证书和私钥
生成商城域名自签名证书(最终以 shop.ningcode.cn 为准):
openssl genrsa -out shop.key 2048
openssl req -new -key shop.key -out shop.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=shop.ningcode.cn/emailAddress=webadmin@ningcode.cn"
openssl x509 -req -days 3650 -in shop.csr -signkey shop.key -out shop.crt
kubectl create secret tls www-tls -n ecshop --cert=shop.crt --key=shop.key
kubectl get secret www-tls -n ecshop
# www-tls kubernetes.io/tls 2
说明:日志中先生成了
www.ningcode.cn的证书(www.key/www.csr/www.crt)并创建www-tls,因域名与公网冲突,后重新生成shop.ningcode.cn证书,删除并用新证书重建同名 secretwww-tls(ingress 中引用的 secretName 不变)。
10. 配置 ingress 规则,通过 https://shop.ningcode.cn 访问商城
编写 tls-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecshop-ingress
namespace: ecshop
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- shop.ningcode.cn
secretName: www-tls
rules:
- host: shop.ningcode.cn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
kubectl apply -f tls-ingress.yaml
# ingress.networking.k8s.io/ecshop-ingress created
kubectl get ingress -n ecshop
# NAME CLASS HOSTS ADDRESS PORTS
# ecshop-ingress nginx shop.ningcode.cn 10.1.8.40 80, 443
本机解析测试(/etc/hosts):
vim /etc/hosts
# 10.1.8.30 master30.ningcode.cn master30
# 10.1.8.31 worker31.ningcode.cn worker31
# 10.1.8.32 worker32.ningcode.cn worker32
# 192.168.46.201 hub.laoma.cloud
# 10.1.8.40 shop.ningcode.cn
curl -I http://shop.ningcode.cn
# HTTP/1.1 308 Permanent Redirect
# Location: https://shop.ningcode.cn
curl -k https://shop.ningcode.cn # 返回商城测试页
11. 部署 Metric Server,为 php 和 nginx 配置 HPA(最小2、最大5)
11.1 部署 metrics-server
wget -O components.yaml http://192.168.46.200/class/course-materials/softwares/stage03/metrics-server-components-v0.7.1.yaml
# 添加 --kubelet-insecure-tls(自签 kubelet 证书环境)
sed -i '/metric-resolution/a\ - --kubelet-insecure-tls' components.yaml
grep image: components.yaml
# hub.laoma.cloud/metrics-server/metrics-server:v0.7.1
sed -i 's/registry.k8s.io/hub.laoma.cloud/g' components.yaml
kubectl apply -f components.yaml
kubectl get pods -n kube-system | grep metrics
# metrics-server-... 1/1 Running
kubectl top pods
# NAME CPU(cores) MEMORY(bytes)
# mysql-0 2m 180Mi
# nfs-subdir-provisioner-... 1m 6Mi
# nginx-... 1m 2Mi
# php-fpm-... 1m 12Mi
11.2 配置 HPA
kubectl autoscale deployment nginx --max=5 --min=2
# horizontalpodautoscaler.autoscaling/nginx autoscaled
kubectl get hpa
kubectl get pods -n ecshop # HPA 生效后 nginx 保持 2 个副本
# nginx-...-96ttd 1/1 Running
# nginx-...-mz597 1/1 Running
补充:题目要求 php 也配置 HPA(本日志中未执行),可同样执行
kubectl autoscale deployment php-fpm --max=5 --min=2。
12. 部署 Kubernetes Dashboard 并配置 https://dashboard.ningcode.cn
12.1 部署 Dashboard
wget -O recommended.yaml http://192.168.46.200/class/course-materials/softwares/stage03/kubernetes-dashboard-recommended-v2.6.1.yaml
grep image: recommended.yaml
# hub.laoma.cloud/kubernetesui/dashboard:v2.6.1
# hub.laoma.cloud/kubernetesui/metrics-scraper:v1.0.8
kubectl apply -f recommended.yaml
# namespace/kubernetes-dashboard created
# deployment.apps/kubernetes-dashboard created
# deployment.apps/dashboard-metrics-scraper created
确认/调整 dashboard Service(ClusterIP:443 供 ingress 后端 HTTPS 使用):
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
kubectl get svc -n kubernetes-dashboard
# kubernetes-dashboard ClusterIP <cluster-ip> <none> 443/TCP
12.2 Dashboard 自签名证书
openssl genrsa -out dashboard.key 2048
openssl req -new -key dashboard.key -out dashboard.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=dashboard.ningcode.cn/emailAddress=webadmin@ningcode.cn"
openssl x509 -req -days 3650 -in dashboard.csr -signkey dashboard.key -out dashboard.crt
kubectl create secret tls dashboard-tls -n kubernetes-dashboard --cert=dashboard.crt --key=dashboard.key
12.3 Dashboard Ingress
编写 dashboard-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
tls:
- hosts:
- dashboard.ningcode.cn
secretName: dashboard-tls
rules:
- host: dashboard.ningcode.cn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443
kubectl apply -f dashboard-ingress.yaml
# ingress.networking.k8s.io/dashboard-ingress created
vim /etc/hosts
# 10.1.8.41 dashboard.ningcode.cn
curl -k -I https://dashboard.ningcode.cn
# HTTP/2 200
12.4 登录账号(RBAC + token)
kubectl create clusterrolebinding kubernetes-dashboard-cluster-admin \
--clusterrole cluster-admin \
--serviceaccount kubernetes-dashboard:kubernetes-dashboard
# clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-cluster-admin created
kubectl -n kubernetes-dashboard create token kubernetes-dashboard
# 输出 eyJhbGciOiJSUzI1NiIs... 的 token,粘贴到 Dashboard 登录页

补充步骤(多出来的必要关键步骤)
补充1:ECShop 源码上传并部署到共享卷
# 1) 上传源码包(rz 上传 ECShop_V4.1.20_UTF8.zip 到 /root)
rz -E
# 2) 解压
cd /root
mkdir ecshop
apt install -y unzip
unzip ECShop_V4.1.20_UTF8.zip -d /root/ecshop/
# 3) 拷贝源码到 nginx Pod 的 html 目录(末尾 . 代表拷贝文件夹内部所有文件)
kubectl get pod | grep nginx
kubectl cp /root/ecshop/. nginx-<pod>:/usr/share/nginx/html/ -n ecshop
# 4) 进入 Pod 整理目录、清理测试文件、设置权限
kubectl exec -it nginx-<pod> -n ecshop -- bash
cd /usr/share/nginx/html
mv ECShop_V4.1.20_UTF8_release20250416/* ./ # 或 mv source/* ./
rm -rf ECShop_V4.1.20_UTF8_release20250416 source readme
rm -f index.html test.php *.txt *.jpg
mv ecshop/* ./ && rm -rf ecshop phalapi # 源码在 source/ecshop 子目录时
chmod -R 755 /usr/share/nginx/html
补充2:浏览器安装 ECShop(网页安装向导)
# 浏览器访问
https://shop.ningcode.cn
# 按安装向导填写数据库信息:
# 数据库主机: mysql(或 mysql:3306)
# 数据库端口: 3306
# 数据库名: ecshop
# 用户名: ecshop
# 密码: ningcode@123
# 安装完成后删除 install 目录:
kubectl exec -it nginx-<pod> -n ecshop -- bash
rm -rf /usr/share/nginx/html/install
补充3:自构建 php:7.2-fpm-ecshop 镜像(题目要求“自己构建”)
本环境使用内网仓库已有镜像 hub.laoma.cloud/library/php:7.2-fpm-ecshop;如需自构建:
# Dockerfile
FROM php:7.2-fpm
RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libzip-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) mysqli pdo_mysql gd zip mbstring \
&& docker-php-ext-enable mysqli pdo_mysql gd zip mbstring
docker build -t hub.laoma.cloud/library/php:7.2-fpm-ecshop .
docker login hub.laoma.cloud
docker push hub.laoma.cloud/library/php:7.2-fpm-ecshop
# 各节点(containerd)拉取:
# nerdctl -n k8s.io pull hub.laoma.cloud/library/php:7.2-fpm-ecshop
补充4:php-fpm 的 HPA
kubectl autoscale deployment php-fpm --max=5 --min=2
kubectl get hpa -n ecshop

补充5:域名与解析说明
- 考试/本机访问前在 master 及测试机
/etc/hosts写入:10.1.8.40 shop.ningcode.cn10.1.8.41 dashboard.ningcode.cn10.1.8.30 master30.ningcode.cn master30等节点记录192.168.46.201 hub.laoma.cloud
- 证书 CN、ingress host、secret 需与域名一致;更换域名时重新执行 openssl 生成并重建 tls secret。
补充6:排错记录(本次日志中出现的问题)
- Quota 命令
request.cpu报错 → 改为requests.cpu。 - mysql 镜像直接写
mysql:5.7拉取/启动异常 → 改用内网仓库hub.laoma.cloud/library/mysql:5.7(各节点“从内网下镜像”)。 - php-fpm Pending:
persistentvolumeclaim "ecshop-code-pvc" not found→ 先创建共享 PVC 再 apply。 - mysql 数据目录异常导致 CrashLoopBackOff →
kubectl delete pod/pvc --force后清理 NFS 上的archived-ecshop-*残留目录(rm -rf /ecshop/archived-*),再重新 apply sts/secret。 - 域名与公网冲突(www.ningcode.cn 被占用)→ 改为
shop.ningcode.cn并重建证书与 ingress。 - dashboard 域名无法解析 → 在
/etc/hosts增加10.1.8.41 dashboard.ningcode.cn。
更多推荐
所有评论(0)