KubeSphere-043-应用商店私有化部署实践
App Store Private Deployment Practice
目录
1. 基础概念
1.1 应用商店概述
KubeSphere应用商店是一个基于Helm的应用管理平台,提供了一站式的应用部署、管理和升级功能。应用商店支持:
- 应用模板管理:管理和维护Helm Chart模板
- 应用部署:一键部署应用
- 应用升级:应用版本管理和升级
- 应用回滚:应用版本回滚
- 应用监控:应用运行状态监控
1.2 私有化部署优势
私有化部署应用商店具有以下优势:
- 数据安全:应用和数据存储在本地,确保数据安全
- 网络隔离:与外部网络隔离,提高安全性
- 定制化:可以根据需求定制应用模板和功能
- 合规性:满足行业合规要求
- 成本控制:降低长期运营成本
1.3 应用商店架构
KubeSphere应用商店架构包括: 风哥提示: 学习交流加群风哥微信: itpux-com 学习交流加群风哥QQ113257174 更多视频教程www.fgedu.net.cn 更多学习教程公众号风哥教程itpux_com from K8S+DB视频:www.itpux.com
- 应用商店前端:提供用户界面
- 应用商店后端:提供API服务
- Helm Chart仓库:存储和管理Helm Chart
- 应用模板:应用部署模板
- 应用实例:部署的应用实例
2. 生产环境规划
2.1 架构规划
2.1.1 单集群部署
# – KubeSphere集群
# – 应用商店组件
# – 应用实例
# – 持久化存储
2.1.2 多集群部署
# – 主集群(Host Cluster)
# – 应用商店组件
# – Helm Chart仓库
# – 成员集群(Member Cluster)
# – 应用实例
# – 持久化存储
2.2 资源规划
2.2.1 硬件资源
# – 应用商店前端:2 CPU, 4GB RAM
# – 应用商店后端:4 CPU, 8GB RAM
# – Helm Chart仓库:2 CPU, 4GB RAM
# – 数据库:4 CPU, 8GB RAM
# – 存储:100GB
2.2.2 网络规划
# – 应用商店服务端口:30880
# – Helm Chart仓库端口:8080
# – 数据库端口:3306
# – 内部网络:10.233.0.0/16
2.3 存储规划
2.3.1 存储类型
# – 应用商店数据:ReadWriteOnce
# – Helm Chart仓库:ReadWriteMany
# – 应用数据:ReadWriteOnce
2.3.2 存储容量
# – 应用商店数据:20GB
# – Helm Chart仓库:50GB
# – 应用数据:根据应用需求
3. 实施步骤
3.1 环境准备
3.1.1 安装KubeSphere
wget https://github.com/kubesphere/kubekey/releases/download/v3.4.1/kubekey-v3.4.1-linux-amd64.tar.gz
–2026-01-15 10:00:00– https://github.com/kubesphere/kubekey/releases/download/v3.4.1/kubekey-v3.4.1-linux-amd64.tar.gz
Resolving github.com… 140.82.112.4
Connecting to github.com|140.82.112.4|:443… connected.
HTTP request sent, awaiting response… 200 OK
Length: 12345678 (12M) [application/octet-stream]
Saving to: ‘kubekey-v3.4.1-linux-amd64.tar.gz’
# 解压安装包
tar -xzf kubekey-v3.4.1-linux-amd64.tar.gz
# 创建集群配置文件
./kk create config –with-kubesphere v3.4.1 –with-kubernetes v1.26.5
Generate cluster config file successfully
# 创建集群
./kk create cluster -f config-sample.yaml
_ __ _ _ __
| | / / | | | | / /
| |/ / _ _| |__ ___| |/ / ___ _ _
| \| | | | ‘_ \ / _ \ \ / _ \ | | |
| |\ \ |_| | |_) | __/ |\ \ __/ |_| |
\_| \_/\__,_|_.__/ \___|_| \_/\___|\__, |
__/ |
|___/
KubeSphere v3.4.1
KubeKey v3.4.1
Cluster creation started!
3.1.2 启用应用商店
kubectl edit cm ks-installer -n kubesphere-system
# 在配置文件中添加以下内容
# openpitrix:
# store:
# enabled: true
# 重启安装器
kubectl rollout restart deployment ks-installer -n kubesphere-system
deployment.apps/ks-installer restarted
# 查看安装状态
kubectl logs -n kubesphere-system deployment/ks-installer -f
I0115 10:10:00.000000 1 controller.go:114] OpenPitrix store component is enabled
3.2 配置Helm Chart仓库
3.2.1 部署ChartMuseum
helm repo add chartmuseum https://chartmuseum.github.io/charts
helm repo update
“chartmuseum” has been added to your repositories
Hang tight while we grab the latest from your chart repositories…
…Successfully got an update from the “chartmuseum” chart repository
…Successfully got an update from the “kubesphere” chart repository
# 创建命名空间
kubectl create namespace chartmuseum
namespace/chartmuseum created
# 部署ChartMuseum
helm install chartmuseum chartmuseum/chartmuseum \
–namespace chartmuseum \
–set env.open.DISABLE_API=false \
–set env.open.STORAGE=local \
–set env.open.STORAGE_LOCAL_ROOTDIR=/charts \
–set persistence.enabled=true \
–set persistence.size=50Gi
NAME: chartmuseum
LAST DEPLOYED: Thu Jan 15 10:15:00 2026
NAMESPACE: chartmuseum
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods –namespace chartmuseum -l “app.kubernetes.io/name=chartmuseum,app.kubernetes.io/instance=chartmuseum” -o jsonpath=”{.items[0].metadata.name}”)
export CONTAINER_PORT=$(kubectl get pod –namespace chartmuseum $POD_NAME -o jsonpath=”{.spec.containers[0].ports[0].containerPort}”)
echo “Visit http://127.0.0.1:8080 to use your application”
kubectl –namespace chartmuseum port-forward $POD_NAME 8080:$CONTAINER_PORT
3.2.2 创建Helm Chart
helm create myapp-chart
Creating myapp-chart
# 查看Chart结构
tree myapp-chart
myapp-chart/
├── Chart.yaml
├── charts/
├── templates/
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ └── tests/
│ └── test-connection.yaml
├── .helmignore
,
└── values.yaml
# 编辑Chart.yaml
cat myapp-chart/Chart.yaml
apiVersion: v2
name: myapp-chart
description: A Helm chart for myapp
type: application
version: 0.1.0
appVersion: “1.0.0”
keywords:
– myapp
– web
maintainers:
– name: admin
email: admin@example.com
3.2.3 打包和上传Chart
helm package myapp-chart
Successfully packaged chart and saved it to: myapp-chart-0.1.0.tgz
# 上传Chart到ChartMuseum
curl –data-binary “@myapp-chart-0.1.0.tgz” http://chartmuseum.chartmuseum.svc.cluster.local:8080/api/charts
{“saved”:true}
# 验证Chart
curl http://chartmuseum.chartmuseum.svc.cluster.local:8080/api/charts/myapp-chart
[
{
“name”: “myapp-chart”,
“version”: “0.1.0”,
“description”: “A Helm chart for myapp”,
“urls”: [
“charts/myapp-chart-0.1.0.tgz”
],
“created”: “2026-01-15T10:20:00.000Z”,
“digest”: “abc123def456”
}
]
3.3 配置应用商店
3.3.1 添加Chart仓库
# 访问KubeSphere控制台 -> 应用商店 -> 仓库管理 -> 添加仓库
# 仓库名称:chartmuseum
# 仓库URL:http://chartmuseum.chartmuseum.svc.cluster.local:8080
# 认证方式:无需认证
3.3.2 同步Chart
# 在KubeSphere控制台中点击”同步”按钮
# 系统会自动从Chart仓库中同步所有Chart
3.4 部署应用
3.4.1 通过应用商店部署
# 1. 访问KubeSphere控制台 -> 应用商店
# 2. 选择要部署的应用
# 3. 点击”安装”按钮
# 4. 配置应用参数
# 5. 选择部署位置
# 6. 点击”确定”开始部署
3.4.2 通过Helm命令部署
helm install myapp chartmuseum/myapp-chart \
–namespace myapp \
–create-namespace \
–set image.repository=nginx \
–set image.tag=latest \
–set service.type=ClusterIP \
–set replicaCount=3
NAME: myapp
LAST DEPLOYED: Thu Jan 15 10:25:00 2026
NAMESPACE: myapp
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods –namespace myapp -l “app.kubernetes.io/name=myapp,app.kubernetes.io/instance=myapp” -o jsonpath=”{.items[0].metadata.name}”)
export CONTAINER_PORT=$(kubectl get pod –namespace myapp $POD_NAME -o jsonpath=”{.spec.containers[0].ports[0].containerPort}”)
echo “Visit http://127.0.0.1:8080 to use your application”
kubectl –namespace myapp port-forward $POD_NAME 8080:$CONTAINER_PORT
# 查看部署状态
helm list -n myapp
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myapp myapp 1 2026-01-15 10:25:00.000Z +0000 UTC deployed myapp-chart-0.1.0 1.0.0
# 查看Pod状态
kubectl get pods -n myapp
NAME READY STATUS RESTARTS AGE
myapp-7d6f8b9c5d-abc123 1/1 Running 0 2m
myapp-7d6f8b9c5d-def456 1/1 Running 0 2m
myapp-7d6f8b9c5d-ghi789 1/1 Running 0 2m
3.5 应用管理
3.5.1 升级应用
helm upgrade myapp chartmuseum/myapp-chart \
–namespace myapp \
–set image.tag=1.0.1 \
–set replicaCount=5
Release “myapp” has been upgraded. Happy Helming!
NAME: myapp
LAST DEPLOYED: Thu Jan 15 10:30:00 2026
NAMESPACE: myapp
STATUS: deployed
REVISION: 2
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods –namespace myapp -l “app.kubernetes.io/name=myapp,app.kubernetes.io/instance=myapp” -o jsonpath=”{.items[0].metadata.name}”)
export CONTAINER_PORT=$(kubectl get pod –namespace myapp $POD_NAME -o jsonpath=”{.spec.containers[0].ports[0].containerPort}”)
echo “Visit http://127.0.0.1:8080 to use your application”
kubectl –namespace myapp port-forward $POD_NAME 8080:$CONTAINER_PORT
# 查看升级历史
helm history myapp -n myapp
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Thu Jan 15 10:25:00 2026 superseded myapp-chart-0.1.0 1.0.0 Install complete
2 Thu Jan 15 10:30:00 2026 deployed myapp-chart-0.1.0 1.0.1 Upgrade complete
3.5.2 回滚应用
helm rollback myapp 1 -n myapp
Rollback was a success! Happy Helming!
# 查看回滚状态
helm list -n myapp
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myapp myapp 3 2026-01-15 10:35:00.000Z +0000 UTC deployed myapp-chart-0.1.0 1.0.0
3.5.3 卸载应用
helm uninstall myapp -n myapp
release “myapp” uninstalled
# 验证卸载
kubectl get pods -n myapp
No resources found in myapp namespace.
# 删除命名空间
kubectl delete namespace myapp
namespace “myapp” deleted
4. 实战案例
4.1 部署MySQL应用
4.1.1 创建MySQL Chart
helm create mysql-chart
Creating mysql-chart
# 编辑values.yaml
cat mysql-chart/values.yaml
replicaCount: 1
image:
repository: mysql
pullPolicy: IfNotPresent
tag: “8.0”
service:
type: ClusterIP
port: 3306
persistence:
enabled: true
size: 20Gi
storageClass: “standard”
mysqlRootPassword: “root123”
mysqlDatabase: “mydb”
mysqlUser: “myuser”
mysqlPassword: “mypassword”
# 编辑deployment.yaml
cat mysql-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include “mysql-chart.fullname” . }}
labels:
{{- include “mysql-chart.labels” . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include “mysql-chart.selectorLabels” . | nindent 6 }}
template:
metadata:
labels:
{{- include “mysql-chart.selectorLabels” . | nindent 8 }}
spec:
containers:
– name: mysql
image: “{{ .Values.image.repository }}:{{ .Values.image.tag }}”
,
ports:
– containerPort: {{ .Values.service.port }}
env:
– name: MYSQL_ROOT_PASSWORD
value: {{ .Values.mysqlRootPassword }}
– name: MYSQL_DATABASE
value: {{ .Values.mysqlDatabase }}
– name: MYSQL_USER
value: {{ .Values.mysqlUser }}
– name: MYSQL_PASSWORD
value: {{ .Values.mysqlPassword }}
volumeMounts:
– name: mysql-data
mountPath: /var/lib/mysql
volumes:
– name: mysql-data
persistentVolumeClaim:
claimName: {{ include “mysql-chart.fullname” . }}
# 编辑service.yaml
cat mysql-chart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include “mysql-chart.fullname” . }}
labels:
{{- include “mysql-chart.labels” . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
– port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}
protocol: TCP
name: mysql
selector:
{{- include “mysql-chart.selectorLabels” . | nindent 6 }}
# 编辑pvc.yaml
cat mysql-chart/templates/pvc.yaml
{{- if .Values.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include “mysql-chart.fullname” . }}
labels:
{{- include “mysql-chart.labels” . | nindent 4 }}
spec:
accessModes:
– ReadWriteOnce
storageClassName: {{ .Values.persistence.storageClass }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- end }}
4.1.2 打包和部署MySQL
helm package mysql-chart
Successfully packaged chart and saved it to: mysql-chart-0.1.0.tgz
# 上传Chart到ChartMuseum
curl –data-binary “@mysql-chart-0.1.0.tgz” http://chartmuseum.chartmuseum.svc.cluster.local:8080/api/charts
{“saved”:true}
# 部署MySQL
helm install mysql chartmuseum/mysql-chart \
–namespace mysql \
–create-namespace
NAME: mysql
LAST DEPLOYED: Thu Jan 15 10:40:00 2026
NAMESPACE: mysql
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods –namespace mysql -l “app.kubernetes.io/name=mysql-chart,app.kubernetes.io/instance=mysql” -o jsonpath=”{.items[0].metadata.name}”)
export CONTAINER_PORT=$(kubectl get pod –namespace mysql $POD_NAME -o jsonpath=”{.spec.containers[0].ports[0].containerPort}”)
echo “Visit http://127.0.0.1:3306 to use your application”
kubectl –namespace mysql port-forward $POD_NAME 3306:$CONTAINER_PORT
# 查看Pod状态
kubectl get pods -n mysql
NAME READY STATUS RESTARTS AGE
mysql-7d6f8b9c5d-abc123 1/1 Running 0 1m
# 查看Service
kubectl get svc -n mysql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 10.233.123.456
# 测试MySQL连接
kubectl run -it –rm mysql-client –image=mysql:8.0 –restart=Never -n mysql — mysql -h mysql -u myuser -pmypassword
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.35 MySQL Community Server – GPL
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.
mysql> SHOW DATABASES;
+——————–+
| Database |
+——————–+
,
| information_schema |
| mydb |
| mysql |
| performance_schema |
| sys |
+——————–+
5 rows in set (0.00 sec)
mysql> exit
Bye
4.2 部署Redis应用
4.2.1 创建Redis Chart
helm create redis-chart
Creating redis-chart
# 编辑values.yaml
cat redis-chart/values.yaml
replicaCount: 1
image:
repository: redis
pullPolicy: IfNotPresent
tag: “7.0”
service:
type: ClusterIP
port: 6379
persistence:
enabled: true
size: 10Gi
storageClass: “standard”
redisPassword: “redis123”
# 编辑deployment.yaml
cat redis-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include “redis-chart.fullname” . }}
labels:
{{- include “redis-chart.labels” . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include “redis-chart.selectorLabels” . | nindent 6 }}
template:
metadata:
labels:
{{- include “redis-chart.selectorLabels” . | nindent 8 }}
spec:
containers:
– name: redis
image: “{{ .Values.image.repository }}:{{ .Values.image.tag }}”
ports:
– containerPort: {{ .Values.service.port }}
command:
– redis-server
– –requirepass
– {{ .Values.redisPassword }}
volumeMounts:
– name: redis-data
mountPath: /data
volumes:
– name: redis-data
persistentVolumeClaim:
claimName: {{ include “redis-chart.fullname” . }}
4.2.2 打包和部署Redis
helm package redis-chart
Successfully packaged chart and saved it to: redis-chart-0.1.0.tgz
# 上传Chart到ChartMuseum
curl –data-binary “@redis-chart-0.1.0.tgz” http://chartmuseum.chartmuseum.svc.cluster.local:8080/api/charts
{“saved”:true}
# 部署Redis
helm install redis chartmuseum/redis-chart \
–namespace redis \
–create-namespace
NAME: redis
LAST DEPLOYED: Thu Jan 15 10:45:00 2026
NAMESPACE: redis
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods –namespace redis -l “app.kubernetes.io/name=redis-chart,app.kubernetes.io/instance=redis” -o jsonpath=”{.items[0].metadata.name}”)
export CONTAINER_PORT=$(kubectl get pod –namespace redis $POD_NAME -o jsonpath=”{.spec.containers[0].ports[0].containerPort}”)
echo “Visit http://127.0.0.1:6379 to use your application”
kubectl –namespace redis port-forward $POD_NAME 6379:$CONTAINER_PORT
# 查看Pod状态
kubectl get pods -n redis
NAME READY STATUS RESTARTS AGE
redis-7d6f8b9c5d-abc123 1/1 Running 0 1m
# 测试Redis连接
kubectl run -it –rm redis-client –image=redis:7.0 –restart=Never -n redis — redis-cli -h redis -a redis123
Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe.
redis> PING
,
PONG
redis> SET mykey “Hello World”
OK
redis> GET mykey
“Hello World”
redis> exit
5. 经验总结
5.1 最佳实践
5.1.1 Chart管理最佳实践
- 版本控制:使用Git管理Chart代码,实现版本控制
- 自动化测试:对Chart进行自动化测试,确保质量
- 文档完善:完善Chart文档,提供详细的使用说明
- 安全扫描:对Chart进行安全扫描,及时发现和修复安全漏洞
- 定期更新:定期更新Chart,保持与最新版本同步
5.1.2 应用部署最佳实践
- 环境隔离:为不同环境创建独立的命名空间
- 资源限制:为应用设置合理的资源限制
- 健康检查:配置健康检查,确保应用正常运行
- 监控告警:配置监控和告警,及时发现和解决问题
- 备份恢复:定期备份应用数据,确保数据安全
5.2 常见问题
5.2.1 Chart问题
- 问题1:Chart安装失败
- 解决方案:检查Chart配置和Kubernetes集群状态
- 问题2:Chart升级失败
- 解决方案:检查Chart版本兼容性和配置变更
- 问题3:Chart回滚失败
- 解决方案:检查回滚历史和资源状态
5.2.2 应用问题
- 问题1:应用无法启动
- 解决方案:检查应用日志和配置
- 问题2:应用无法访问
- 解决方案:检查Service配置和网络策略
- 问题3:应用性能问题
- 解决方案:检查资源使用情况和配置
5.3 性能优化
5.3.1 Chart性能优化
- 模板优化:优化Chart模板,减少渲染时间
- 依赖管理:合理管理Chart依赖,减少下载时间
- 缓存优化:使用缓存减少重复下载
- 并行部署:并行部署多个应用,提高部署效率
5.3.2 应用性能优化
- 资源配置:合理配置应用资源,提高性能
- 自动扩缩容:配置自动扩缩容,提高资源利用率
- 负载均衡:配置负载均衡,提高应用可用性
- 缓存优化:使用缓存减少数据库访问
5.4 安全建议
5.4.1 Chart安全
- 镜像安全:使用官方镜像,定期更新
- 密钥管理:使用Secret管理敏感信息
- 访问控制:配置RBAC,限制访问权限
- 网络隔离:配置网络策略,隔离应用网络
5.4.2 应用安全
- 最小权限:遵循最小权限原则
- 安全扫描:定期进行安全扫描
- 日志审计:启用日志审计,记录操作日志
- 定期更新:定期更新应用和依赖
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
