使用KubeSphere3.3在Ubuntu20.04的Kubernetes1.24上部署Word Press
前言
之前已经部署了KubeSphere和K8S的基础环境:https://lizhiyong.blog.csdn.net/article/details/126236516
部署了大数据统一文件编排层Alluxio:https://lizhiyong.blog.csdn.net/article/details/126815426
以及Saas服务的简单体验:https://lizhiyong.blog.csdn.net/article/details/129868719
所以这次尝试部署一个Word Press服务,成功的话,下次就可以参照着部署在Saas服务搭个私有Blog,可能比租ECS或者轻量服务器还便宜。。。
具体参照官方文档:https://www.kubesphere.io/zh/docs/v3.3/quick-start/wordpress-deployment/
这个应用的后端服务是MySQL,持久化到PVC中,账户密码存在Secret中,暴露一个Service给前端服务使用。
前端服务就是Word Press,持久化到PVC中,账户密码存在另一个Secret中,暴露一个Service给Pod外部的租户使用。
这个案例大体上涵盖了K8S部署常见的有状态应用和无状态应用。部署成功后,外部租户就可以访问到Pod中的前端服务Word Press,前端服务也能够把数据持久化到后端的MySQL。在使用时,租户大概率不会发觉底层的变化。。。
实操
本文不是给纯小白看的,不过得益于KubeSphere对K8S的界面化封装,其实纯小白耐心点也能学会基础操作。。。应付工作还是足够的。
有点追求的话,还是建议深入理解下相关的原理。多说无益。
做平台开发当然是习惯了超级管理员。。。而且是自己玩,懒得创建项目和租户了。。。
http://192.168.88.20:30880
admin
Aa123456
直接上。。。
创建密钥
MySQL的密钥
下一步默认的方式即可:
此处Key=MYSQL_ROOT_PASSWORD,Value=123456。
此时的yaml:
apiVersion: v1
kind: Secret
metadata:
namespace: default
labels: {}
name: zhiyong-mysql-secret
annotations:
kubesphere.io/description: WordPress的MySQL密钥
type: Opaque
spec:
template:
metadata:
labels: {}
data:
MYSQL_ROOT_PASSWORD: MTIzNDU2
这种方式和:
kubectl create -f secret.yaml
做法其实是一致的。。。Base64加密的方式也很不安全。
Word Press的密钥
下一步:
此处Key=WORDPRESS_DB_PASSWORD,Value=123456。
此时的yaml:
apiVersion: v1
kind: Secret
metadata:
namespace: default
labels: {}
name: zhiyong-wordpress-secret
annotations:
kubesphere.io/description: WordPress的密钥
type: Opaque
spec:
template:
metadata:
labels: {}
data:
WORDPRESS_DB_PASSWORD: MTIzNDU2
其实还有另外的模式:
以后可以试试。此时创建了2个Secret:
创建PVC
使用默认的Local模式,10个G空间:
这种模式也没啥元数据:
保持默认即可,此时的yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: default
name: zhiyong-wordpress-pvc
labels: {}
annotations:
kubesphere.io/description: word press存储卷
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: local
此时PVC创建完毕:
创建应用
此时并没有创建应用的选项。。。
老的3.2版本也有这个应用的选项:https://v3-2.docs.kubesphere.io/zh/docs/quick-start/wordpress-deployment/
所以还是应该老老实实的先创建租户和项目。。。貌似KubeSphere的设计中不允许网管部署应用。。。
接下来参考官网:https://www.kubesphere.io/zh/docs/v3.3/quick-start/create-workspace-and-project/
由于新老版本涉及一些变化:https://www.kubesphere.io/zh/docs/v3.3/release/release-v331/
并不能照搬最新版官网文档。
可能还需要参考老版本的:https://v3-2.docs.kubesphere.io/zh/docs/quick-start/create-workspace-and-project/
创建租户
新版本:
内置角色 | 描述 |
---|---|
platform-self-provisioner | 创建企业空间并成为所创建企业空间的管理员。 |
platform-regular | 平台普通用户,在被邀请加入企业空间或集群之前没有任何资源操作权限。 |
platform-admin | 平台管理员,可以管理平台内的所有资源。 |
备注:内置角色由 KubeSphere 自动创建,无法编辑或删除。
老版本:
内置角色 | 描述 |
---|---|
workspaces-manager | 企业空间管理员,管理平台所有企业空间。 |
users-manager | 用户管理员,管理平台所有用户。 |
platform-regular | 平台普通用户,在被邀请加入企业空间或集群之前没有任何资源操作权限。 |
platform-admin | 平台管理员,可以管理平台内的所有资源。 |
所以还是要按照老版本的模式:
可以在这个界面创建各种租户。
先创建一个用户管理员:
users-manager
users-manager@zhiyong.com
Aa123456
然后切换到这个用户,创建如下4个租户:
用户 | 指定的平台角色 | 用户权限 |
---|---|---|
ws-manager | workspaces-manager | 创建和管理所有企业空间。 |
ws-admin | platform-regular | 被邀请到企业空间后,管理该企业空间中的所有资源(在此示例中,此用户用于邀请新成员加入该企业空间)。 |
project-admin | platform-regular | 创建和管理项目以及 DevOps 项目,并邀请新成员加入项目。 |
project-regular | platform-regular | project-regular 将由 project-admin 邀请至项目或 DevOps 项目。该用户将用于在指定项目中创建工作负载、流水线和其他资源。 |
ws-manager
ws-manager@zhiyong.com
Aa123456
ws-admin
ws-admin@zhiyong.com
Aa123456
project-admin
project-admin@zhiyong.com
Aa123456
project-regular
project-regular@zhiyong.com
Aa123456
此时可以看到新建4杆租户成功!!!
创建企业空间【NameSpace】
以 ws-manager
租户的身份登录 KubeSphere。
创建一个Demo的工作空间:
demo-workspace
管理员:ws-admin
遇到了这个报错:
Forbidden
workspacetemplates.tenant.kubesphere.io is forbidden: User "ws-manager" cannot create resource "workspacetemplates" in API group "tenant.kubesphere.io" at the cluster scope
把4个普通租户挨个激活以后还是有这种问题。。。所以使用admin
超级管理员来创建:
即可成功。。。这是KuberSphere的Bug,3.3.1的新版本已经修复。。。
然后以 ws-admin
身份重新登录,邀请 project-admin
和 project-regular
这2杆租户进入企业空间:
分别授予 demo-workspace-self-provisioner
和 demo-workspace-viewer
角色:
此时租户拉取配置成功:
接下来就可以创建项目。
创建项目
切换为:project-admin这个租户,创建项目:
然后邀请普通租户,分配给operator
身份:
项目的Ingress网关和配额暂时不管。之后切换到普通租户project-regular
,就可以部署项目:
重新创建密钥
删除之前的密钥,再重新操作一遍即可。不再赘述。
此时准备好了MySQL后端的Secret与Word Press的前端Secret。
重新创建PVC
删除之前的PVC,再重新操作一遍即可,不再赘述。
Forbidden
volumesnapshotclasses.snapshot.storage.k8s.io is forbidden: User "project-regular" cannot list resource "volumesnapshotclasses" in API group "snapshot.storage.k8s.io" at the cluster scope
不过有这个问题。。。不需要用admin来创建PVC,只是个展示的问题。
自制应用
此时可以自制应用:
暂时不用Sidecar做应用治理,所以先关闭它。
添加 MySQL 后端组件
先创建MySQL的有状态服务。
此时的yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
name: mysql-wordpress-v1
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: mysql-wordpress
template:
metadata:
labels:
version: v1
app: mysql-wordpress
spec:
containers:
- name: container-rt5e06
imagePullPolicy: IfNotPresent
image: 'mysql:5.6'
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1.5'
memory: 2000Mi
ports:
- name: tcp-3306
protocol: TCP
containerPort: 3306
servicePort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-mysql-secret
key: MYSQL_ROOT_PASSWORD
serviceAccount: default
initContainers: []
volumes: []
imagePullSecrets: null
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
serviceName: mysql-wordpress
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
annotations:
kubesphere.io/serviceType: statefulservice
kubesphere.io/description: 给WordPress用的MySQL
name: mysql-wordpress
spec:
sessionAffinity: None
selector:
app: mysql-wordpress
ports:
- name: tcp-3306
protocol: TCP
port: 3306
targetPort: 3306
clusterIP: None
然后从PVC挂载PV:
挂载PVC以后的yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
name: mysql-wordpress-v1
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: mysql-wordpress
template:
metadata:
labels:
version: v1
app: mysql-wordpress
annotations:
logging.kubesphere.io/logsidecar-config: '{}'
spec:
containers:
- name: container-rt5e06
imagePullPolicy: IfNotPresent
image: 'mysql:5.6'
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1.5'
memory: 2000Mi
ports:
- name: tcp-3306
protocol: TCP
containerPort: 3306
servicePort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-mysql-secret
key: MYSQL_ROOT_PASSWORD
volumeMounts:
- readOnly: false
mountPath: /var/lib/mysql
name: zhiyong-mysql
serviceAccount: default
initContainers: []
volumes: []
imagePullSecrets: null
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
serviceName: mysql-wordpress
volumeClaimTemplates:
- spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: local
metadata:
name: zhiyong-mysql
namespace: word-press-project
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
annotations:
kubesphere.io/serviceType: statefulservice
kubesphere.io/description: 给WordPress用的MySQL
name: mysql-wordpress
spec:
sessionAffinity: None
selector:
app: mysql-wordpress
ports:
- name: tcp-3306
protocol: TCP
port: 3306
targetPort: 3306
clusterIP: None
由于是All In One的模式:
也就没得选了。。。如果是多节点模式,那么还可以指定Pod运行在哪台机器。
添加 WordPress 前端组件
相似的操作,创建无状态应用:
自己玩玩,也就不搞探针探活了。。。
此时的yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
name: wordpress-v1
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: wordpress
template:
metadata:
labels:
version: v1
app: wordpress
spec:
containers:
- name: container-7ydkpj
imagePullPolicy: IfNotPresent
image: 'wordpress:4.8-apache'
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1'
memory: 2000Mi
ports:
- name: tcp-80
protocol: TCP
containerPort: 80
servicePort: 80
env:
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-wordpress-secret
key: WORDPRESS_DB_PASSWORD
- name: WORDPRESS_DB_HOST
value: mysql-wordpress
serviceAccount: default
initContainers: []
volumes: []
imagePullSecrets: null
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
annotations:
kubesphere.io/serviceType: statelessservice
kubesphere.io/description: WordPress服务
name: wordpress
spec:
sessionAffinity: None
selector:
app: wordpress
ports:
- name: tcp-80
protocol: TCP
port: 80
targetPort: 80
挂载PVC以后的yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
name: wordpress-v1
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: wordpress
template:
metadata:
labels:
version: v1
app: wordpress
annotations:
logging.kubesphere.io/logsidecar-config: '{}'
spec:
containers:
- name: container-7ydkpj
imagePullPolicy: IfNotPresent
image: 'wordpress:4.8-apache'
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1'
memory: 2000Mi
ports:
- name: tcp-80
protocol: TCP
containerPort: 80
servicePort: 80
env:
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-wordpress-secret
key: WORDPRESS_DB_PASSWORD
- name: WORDPRESS_DB_HOST
value: mysql-wordpress
volumeMounts:
- name: volume-jsr71k
readOnly: false
mountPath: /var/www/html
serviceAccount: default
initContainers: []
volumes:
- name: volume-jsr71k
persistentVolumeClaim:
claimName: zhiyong-wordpress-pvc
imagePullSecrets: null
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
annotations:
kubesphere.io/serviceType: statelessservice
kubesphere.io/description: WordPress服务
name: wordpress
spec:
sessionAffinity: None
selector:
app: wordpress
ports:
- name: tcp-80
protocol: TCP
port: 80
targetPort: 80
此时创建好了2个组件。
路由
路由暂且不设置。此时的yaml:
apiVersion: app.k8s.io/v1beta1
kind: Application
metadata:
name: word-press
namespace: word-press-project
labels:
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
annotations:
servicemesh.kubesphere.io/enabled: 'false'
kubesphere.io/description: WordPress应用
spec:
selector:
matchLabels:
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
addOwnerRef: true
componentKinds:
- group: ''
kind: Service
- group: apps
kind: Deployment
- group: apps
kind: StatefulSet
- group: networking.k8s.io
kind: Ingress
- group: servicemesh.kubesphere.io
kind: Strategy
- group: servicemesh.kubesphere.io
kind: ServicePolicy
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: word-press-project
labels:
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
name: word-press-ingress-rb11gi
spec:
rules: []
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
name: mysql-wordpress-v1
annotations:
servicemesh.kubesphere.io/enabled: 'false'
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: mysql-wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
template:
metadata:
labels:
version: v1
app: mysql-wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
annotations:
logging.kubesphere.io/logsidecar-config: '{}'
sidecar.istio.io/inject: 'false'
spec:
containers:
- name: container-rt5e06
imagePullPolicy: IfNotPresent
image: 'mysql:5.6'
ports:
- name: tcp-3306
protocol: TCP
containerPort: 3306
servicePort: 3306
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1.5'
memory: 2000Mi
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-mysql-secret
key: MYSQL_ROOT_PASSWORD
volumeMounts:
- readOnly: false
mountPath: /var/lib/mysql
name: zhiyong-mysql
serviceAccount: default
initContainers: []
volumes: []
imagePullSecrets: null
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
serviceName: mysql-wordpress
volumeClaimTemplates:
- spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: local
metadata:
name: zhiyong-mysql
namespace: word-press-project
totalReplicas: ''
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: mysql-wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
annotations:
kubesphere.io/serviceType: statefulservice
kubesphere.io/description: 给WordPress用的MySQL
servicemesh.kubesphere.io/enabled: 'false'
name: mysql-wordpress
spec:
sessionAffinity: None
selector:
app: mysql-wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
ports:
- name: tcp-3306
protocol: TCP
port: 3306
targetPort: 3306
clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
name: wordpress-v1
annotations:
servicemesh.kubesphere.io/enabled: 'false'
spec:
replicas: 1
selector:
matchLabels:
version: v1
app: wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
template:
metadata:
labels:
version: v1
app: wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
annotations:
logging.kubesphere.io/logsidecar-config: '{}'
sidecar.istio.io/inject: 'false'
spec:
containers:
- name: container-7ydkpj
imagePullPolicy: IfNotPresent
image: 'wordpress:4.8-apache'
resources:
requests:
cpu: '0.1'
memory: 100Mi
limits:
cpu: '1'
memory: 2000Mi
ports:
- name: tcp-80
protocol: TCP
containerPort: 80
servicePort: 80
env:
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: zhiyong-wordpress-secret
key: WORDPRESS_DB_PASSWORD
- name: WORDPRESS_DB_HOST
value: mysql-wordpress
volumeMounts:
- name: volume-jsr71k
readOnly: false
mountPath: /var/www/html
serviceAccount: default
initContainers: []
volumes:
- name: volume-jsr71k
persistentVolumeClaim:
claimName: zhiyong-wordpress-pvc
imagePullSecrets: null
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
---
apiVersion: v1
kind: Service
metadata:
namespace: word-press-project
labels:
version: v1
app: wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
annotations:
kubesphere.io/serviceType: statelessservice
kubesphere.io/description: WordPress服务
servicemesh.kubesphere.io/enabled: 'false'
name: wordpress
spec:
sessionAffinity: None
selector:
app: wordpress
app.kubernetes.io/version: v1
app.kubernetes.io/name: word-press
ports:
- name: tcp-80
protocol: TCP
port: 80
targetPort: 80
验证资源
耐心等一阵子,待拉取镜像和调度Pod成功后:
root@zhiyong-ksp1:/home/zhiyong# kubectl get pod -owide --all-namespaces | grep word
word-press-project mysql-wordpress-v1-0 1/1 Running 0 14m 10.233.107.217 zhiyong-ksp1 <none> <none>
word-press-project wordpress-v1-799755f6cc-wjt54 1/1 Running 1 (5m34s ago) 14m 10.233.107.216 zhiyong-ksp1 <none> <none>
此时PVC也挂载成功:
暴露服务
使用NodePort暴露即可。
暴露服务成功后:
直接使用IP+端口访问:
http://192.168.88.20:43302/
随便写点啥。然后访问:
http://192.168.88.20:43302/2023/05/29/伟大的虎鲸/
此时WordPress已经可用。。。
总结
KubeSphere的多租户做的还是比较完善,不能随意地使用超级管理员操作所有的功能。规范性也是相当的到位,划分了多种租户。必须遵循这套模式,按部就班地来。
通过这个简单的案例,K8S学徒工也可以照猫画虎部署一些应用了。平台化还是有好处的,让开发人员不必要掌握繁琐的kubectl命令,也无需专职的yaml攻城狮了。。。KubeSphere是个好东西。。。
K8S最适合的还是无状态的应用,所以简单的无状态应用【例如:Flink的实时ETL pipeline、简单规则的超限告警】都可以参照着这么玩了。。。
有状态应用要麻烦一点了。。。
K8S的Saas服务这么操作下来,应该也是可行的。。。
转载请注明出处:https://lizhiyong.blog.csdn.net/article/details/130939203