StatefulSet+健康检查+搭建Discuz论坛

StatefluSet控制器

1.介绍

Kubernetes中有很多的控制器,比如常用的ReplicaSet,Deployment,DaemonSet,StatefulSet等。以这四种为例,我们可以将它们分为两种,一种为有状态控制器,一种为无状态控制器,StatefulSet则为有状态控制器。

2.特点

  • 查询规范:kubectl explain stetafulset.spec

  • StatefulSet拥有统一的网络,并且有启动顺序

  • 通常用于管理b和部署有状态的服务,如:MySQL,Redis,MongoDB等;也就是说,如果我们的应用如有以下的任何一个特点,就可以使用statefulset控制器来部署

    • 有状态控制器通常有以下几个特点:

      • 稳定、唯一的网络标识

        • 唯一且不会发生变化,由 $(statefulset name)-(0-N)组成,N为一个无限大的正整数,从0开始
      • 稳定、持久的存储

        • 每个Pod都对应一个PVC,PVC的名称组成: ( v o l u m e C l a i m T e m p l a t e s n a m e ) − (volumeClaimTemplates name)- (volumeClaimTemplatesname)(pod name)-(0-N),N为一个无限大的正整数,从0开始
      • 有序、优雅的部署和伸缩

        • 严格按照从0到N的顺序创建,并且下一个Pod创建的前提是上一个Pod已经Running状态

        • 每扩容一个pod前提是上一个Pod已经Running状态

        • 每缩容一个pod前提是上一个Pod已经完全Delete

      • 有序、优雅的删除和停止

        • 严格按照从N到0的顺序删除,并且下一个Pod删除的前提是上一个Pod已经完全Delete
      • 有序、自动的滚动更新

        • 严格按照从N到1的顺序升级,并且下一个Pod升级的前提是上一个Pod已经Running状态

3.使用statefulset部署WordPress

kind: Service
apiVersion: v1
metadata:
  name: wordpress-test
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: wordpress-test
---
kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: wordpress-test
spec:
  serviceName: wordpress-test
  selector:
    matchLabels:
      app: wordpress-test
  template:
    metadata:
      labels:
        app: wordpress-test
    spec:
      containers:
        - name: php
          image: alvinos/php:wordpress-v2
        - name: nginx
          image: alvinos/nginx:wordpress-v2

健康检查

  • 存活性探测
  • 就绪性探测

一、 存活性探测

用于判断容器是否正常健康的运行,若探测失败,立即删除容器

​ 对线上业务来说,保证服务的正常稳定是重中之重,对故障服务的及时处理避免影响业务以及快速恢复一直 是开发运维的难点。Kubernetes 提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dy5pPwdd-1617967710706)(C:\Users\秋风、亦冷\AppData\Roaming\Typora\typora-user-images\image-20210408222040558.png)]

1.介绍

1)为什么需要存活探针?

如果没有探针,k8s无法知道应用是否还活着,只要进程还在运行,k8s则认为容器是健康的

2)存活性三种探测方式
2> ExecAction
  • 在容器内执行任意命令,并检查命令退出的状态码,探测结果:
    • 0为成功
    • 否则重启探测失败,容器重启
    • 若第一次检查失败,第二次不会重启,因为会生成新的manage.py
2> TCPSocketAction
  • 探针与容器指定端口建立tcp连接:
    • 若连接建立,则探测成功
    • 否则探测失败,容器重启
3> HTTPGetAction
  • 对容器的IP地址(指定的端与路径)执行http get请求:
    • 若探测器受到相应,且响应码为2xx,3xx,则认为探测成功
    • 若服务器无响应,或返回错误响应,则探测失败,容器重启

怎样保证pod中的容器正常启动?

怎样保证pod中容器正常对外提供服务?

只有容器启动了并且能够正常对外提供服务了,才能放到负载均衡上供给用户访问。

2、存活探测配置清单

  • 检查pod中容器是否能够正常启动
  • pod中所有容器的status=Running时,Pod的状态才会是Running状态。
  • 当存活性检查检测失败的时候,kebulet会删除容器,重新启动一个新的容器,继续检查。
  • 配置清单仅增加了livenessProbe(存货探针)的三种方式
1)exec
cat > Exec.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
  name: name-mysql
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: name-mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: alvinos/django:v1
          livenessProbe:
            exec:
              command:
                - cat
                - /root/test/manage.py
EOF
2)tcpSocket
  • 相当于ping
cat > tcpSocket.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
  name: name-mysql
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: name-mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: alvinos/django:v1
          livenessProbe:
            tcpSocket: 
              port: 80 
EOF
3)httpGet
cat > httpGet.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
  name: name-mysql
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: name-mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: alvinos/django:v1
          livenessProbe:
            httpGet:
              port: 80
              path: /index
EOF

1.1、监控检查参数

apiVersion: apps/v1
kind: Deployment
metadata:
  name: name-mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: alvinos/django:v1
          livenessProbe:
            tcpSocket: 
              port: 80 
		   failureThreshold: 1
# 检查失败最少测试,默认:3

# 其他参数:
delay=10s 	: 探测延时时间initialDelaySeconds
timeout=1s  :探测的超时时间
period=10s  :探测的频率
success=1   :成功多少次才算成功
failure=1   :失败多少次才算失败

failureThreshold:最少连续几次探测失败的次数,满足该次数则认为fail
initialDelaySeconds:容器启动之后开始进行存活性探测的秒数。不填立即进行
periodSeconds:执行探测的频率(秒)。默认为10秒。最小值为1。
successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功,满足该次数则认为success。(但是如果是liveness则必须是 1。最小值是 1。)
timeoutSeconds:每次执行探测的超时时间,默认1秒,最小1秒。

二、就绪型探测

1.介绍

用于判断容器是否正常对外提供服务,若探测失败,立即移除负载均衡

​ 即容器的 Ready 是否为 True,是否可以接收请求,如果 ReadinessProbe 探测失败,则容器的 Ready 将设置为 False,控制器将此 Pod 的 Endpoint 从对应的 service 的 Endpoint 列表中移除, 从此不再将任何请求调度此 Pod 上,直到下次探测成功。(剔除此 pod,不参与接收请求不会将流量转发给此 Pod)

  • 就绪性探测的特点是探测失败,立即移出负载均衡(endprints —> NotReadyAddresses)

2.存活性探测配置清单

1)exec
  • 通过执行一条命令,探测服务是否可以正常对外提供服务
kind: Pod
apiVersion: v1
metadata:
  name: exec-pod
spec:
  containers:
    - name: nginx
	  imagePullPolicy: IfNotPresent
	  image: nginx
	  readinessProbe:
  		exec:
		  command:
			- cat
			- /usr/share/nginx/html/index.html
2)tcpSocket
  • 通过 ping 某个端口的方式,探测服务是否可以正常对外提供服务
kind: Pod
apiVersion: v1
metadata:
  name: exec-pod
spec:
  containers:
    - name: nginx
	  imagePullPolicy: IfNotPresent
	  image: nginx
	  readinessProbe:
	    tcpSocket:
	    port: 80
3)httpGet
  • 通过访问某个 URL 的方式探测当前 POD 是否可以正常对外提供服务
kind: Pod
apiVersion: v1
metadata:
  name: readinessprobe-nginx
  namespace: default
  labels:
    provider: aliyun
    business: pms
    environmental: dev
spec:
  containers:
	- name: readinessprobe-nginx
      image: nginx
      imagePullPolicy: Always
      ports:
        - containerPort: 80
          name: http
          protocol: TCP
        - containerPort: 443
          name: https
          protocol: TCP
	  readinessProbe:
        httpGet:
          port: 80
          path: /demo.html

搭建DiscuzX论坛

  • discuz下载链接:https://gitee.com/3dming/DiscuzL/attach_files
  • 要求:
    • 通过使用无头服务访Pod(ingress —> headless service —> pod)
    • 要有健康检查(存活性、就绪性)
    • 有https加密访问
    • 有存储卷(hostPath)、数据持久化,防止容器停止或宕机数据随之丢失

1.准备discuz包

1.下载discuz包
[root@k8s-master1 ~]# wget https://gitee.com/3dming/DiscuzL/attach_files/644299/download

2.解压	# 此包默认是zip格式,无需改名
[root@k8s-master1 ~]# unzip download

3.授权可写、压缩	# 打包后续备用
[root@k8s-master1 ~]# chmod -R o+x upload
[root@k8s-master1 ~]# tar zcf discuz.gz upload	

4.解压到指定目录
[root@k8s-master1 ~]# mkdir -p /opt/discuz
[root@k8s-master1 ~]# tar xf discuz.gz -C /opt/discuz

3.若有多个主节点,则将包推送至其他主节点并解压
[root@k8s-master1 ~]# for i in m1 m2;do ssh root@$i "mkdir -pv /opt/discuz" ; scp discuz.gz root@$i:/opt/discuz/ ; ssh root@$i "cd /opt/discuz ; tar -xf discuz.gz -C /opt/discuz" ; done

2.创建证书

[root@k8s-master1 ~]# openssl genrsa -out tls.key 2048
[root@k8s-master1 ~]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=ShangHai/L=ShangHai/O=Ingress/CN=linux.discuz.com

PS:linux.discuz.com为指定访问的域名

3.部署证书

  • 注:若命名空间、域名不同,则需重新部署证书!
# 要先创建discuz命名空间,再部署证书
[root@k8s-master1 ~]# kubectl create ns discuz

# secretname要与配置清单内定义相同(discuz-secret )
[root@k8s-master1 ~]# kubectl -n discuz create secret tls discuz-secret --cert=tls.crt --key=tls.key

4.编写配置清单

#########################步骤思路#########################
# 1.部署MySQL集群
#    指定命名空间
#    创建Service提供负载均衡
#    使用控制器deployment部署MySQL服务
#
# 2.部署discuz应用
#    创建discuz命名空间
#    创建service提供负载均衡(配置无头服务headless service)
#    创建ingress,用于域名接续转发访问
#
#  3.服务之间的互连
#    discuz连接MySQL通过 ----->>> mysql-svc.mysql.svc.cluster.local
#########################步骤思路#########################
---
# MySQL命名空间无需创建(集群级资源)
apiVersion: v1
kind: Namespace
metadata:
  name: mysql
---
# 定义MySQL Service
apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  namespace: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
      name: mysql
      protocol: TCP
  selector:
    app: mysql
    deploy: discuz
---
# 定义MySQL控制器
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deployment
  namespace: mysql
spec:
  selector:
    matchLabels:
      app: mysql
      deploy: discuz
  template:
    metadata:
      labels:
        app: mysql
        deploy: discuz
    spec:
      #指定部署mysql到master1
      nodeName: k8s-master1
      containers:
        - name: mysql
          image: mysql:5.7
          # 存活性检测
          livenessProbe:
            tcpSocket:
              port: 3306
          # 就绪性检测
          readinessProbe:
            tcpSocket:
              port: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123"
            - name: MYSQL_DATABASE
              value: "discuz"
          volumeMounts:
            # 容器存储卷,被挂载路径
            - mountPath: /var/lib/mysql
              name: mysql-data
      volumes:
         - name: mysql-data
           hostPath:
             path: /opt/discuz/mysql
            # 宿主主机目录,挂载到上方容器指定路径
---
# 指定discuz命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: discuz
---
# 定义discuz Service
apiVersion: v1
kind: Service
metadata:
  name: discuz-svc
  namespace: discuz
spec:
  # 配置为无头Service(用Ingress域名解析转发)
  clusterIP: None
  ports:
    - port: 80
      targetPort: 80
      name: http
  selector:
    app: discuz
    deploy: discuz
---
# 定义discuz控制器
apiVersion: apps/v1
kind: Deployment
metadata:
  name: discuz-deployment
  namespace: discuz
spec:
  selector:
    matchLabels:
      app: discuz
      deploy: discuz
  template:
    metadata:
      labels:
        app: discuz
        deploy: discuz
    spec:
      # 因为没有nfs共享目录,此处需指定一台节点
      nodeName: k8s-master1
      containers:
        - name: php
          image: 18954354671/lnmp-php-wp:v3
          # 配置php存活检测
          livenessProbe:
            tcpSocket:
              port: 9000
          readinessProbe:
          # 配置php就绪检测
            tcpSocket:
              port: 9000
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: discuz-data
        - name: nginx
          image: 18954354671/lnmp-nginx-wp:v3
          # 配置nginx存活检测
          livenessProbe:
            httpGet:
              port: 80
              path: /
          # 配置nginx存活检测
          readinessProbe:
            httpGet:
              port: 80
              path: /
          volumeMounts:
            # 容器存储卷,被挂载路径
            - mountPath: /usr/share/nginx/html
              name: discuz-data
      volumes:
        - name: discuz-data
          hostPath:
            path: /opt/discuz/upload
            # 宿主主机目录,挂载到上方容器指定路径
---
# 定义Ingress(使用域名解析访问)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: discuz-ingress
  namespace: discuz
spec:
  # 配置https加密访问
  tls:
    # 配置域名
    - hosts:
        - linux.discuz.com
      # 部署证书时,要与此名相同(discuz-secret)
      secretName: discuz-secret
  rules:
    # 配置域名,同上
    - host: linux.discuz.com
      http:
        paths:
          - backend:
              serviceName: discuz-svc
              servicePort:  80

5.部署Discuz

# 部署discuz
[root@k8s-master1 ~]# kubectl apply -f config/discuz.yaml

# 获取discuz运行状态
[root@k8s-master1 ~]# kubectl get pods -n discuz 
NAME                                READY   STATUS    RESTARTS   AGE
discuz-deployment-cbbbfc54b-l22wq   2/2     Running   0          58m

# 获取mysql运行状态
[root@k8s-master1 ~]# kubectl get pods -n mysql 
NAME                               READY   STATUS    RESTARTS   AGE
mysql-deployment-c687787fc-l7n5s   1/1     Running   0          118m

# 获取discuz的域名信息
[root@k8s-master1 ~]# kubectl get ingress  -n discuz 
NAME             CLASS    HOSTS                          ADDRESS         PORTS     AGE
discuz-ingress   <none>   linux.discuz.com   192.168.12.12   80, 443

# 获取nginx暴露的443端口:32731
[root@k8s-master1 ~]# kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.96.60.88     <none>        80:32708/TCP,443:32731/TCP   36h
ingress-nginx-controller-admission   ClusterIP   10.106.141.57   <none>        443/TCP

6.测试访问

# 配置IP、域名:添加到windows的hosts文件
192.168.12.11 linux.discuz.com

# 浏览器访问测试
https://linux.discuz.com:32731
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐