K8S部署Springboot项目

适合ingress-nginx接入外部负载均衡的部署一文主要介绍了如何通过ingress-nginx对外暴露服务,以及与外部负载均衡的结合,下面我们通过将SpringBoot项目迁入K8S中,来完整了解下从一个Java项目的整体流程。

环境准备

  1. 命名空间
    K8S通过namespace划分集群资源。因此我们通过prod、test、develop来划分生产环境、测试环境、开发环境。
    在此我们主要以test进行演示。

  2. 镜像仓库
    我们通过harbor仓库来存储springboot项目的镜像,可参考Docker部署spring boot来了解helloworld项目从打包到上传harbor仓库的过程。

部署

1. 创建命名空间

kubectl create ns test

2. 添加harbor认证

通过secret 可以实现类似docker login登录harbor仓库认证过程。

#在对应的namespace下创建secret
kubectl create secret docker-registry harbor --namespace test --docker-server=harbor.test.cn --docker-username=admin --docker-password=admin --docker-email=test@test.cn

注意:一定要在对应的namespace下创建secret,否则会导致从harbor仓库pull镜像认证不通过。

3. 定义Deployment

通常Deployment、service、ingress 写在一份yaml文件中,为方便演示我们都进行单独分解。

# 1.vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld
  namespace: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
  template:
    metadata:
      name: helloworld
      labels:
        app: helloworld
    spec:
      hostAliases:
        - ip: "10.11.10.11"
          hostnames:
          - "api1.test.cn"
          - "api2.test.cn"
        - ip: "10.11.10.12"
          hostnames:
          - "api3.test.cn"
      containers:
        - name: helloworld
          env:
            - name: JAVA_OPTS
              value: "-Xmx128m -Xms128m -Dspring.profiles.active=test"
          image: harbor.test.cn/helloworld/helloworld:1311c4520122dfa67bb60e0103c9519fcb370e50
          imagePullPolicy: IfNotPresent
          livenessProbe:
            httpGet:
              path: /
              port: 8080
            initialDelaySeconds: 200
            timeoutSeconds: 5
          readinessProbe:
            httpGet:
              path: /
              port: 8080
            initialDelaySeconds: 180
            timeoutSeconds: 5
          ports:
            - containerPort: 8080
          resources:
            limits:
              cpu: "0.5"
              memory: "500Mi"
            requests:
              cpu: "0.5"
              memory: "500Mi"
          volumeMounts:
            - name: logdir
              mountPath: /logs
            - name: localtime
              mountPath: /etc/localtime
            - name: timezone
              mountPath: /etc/timezone
      imagePullSecrets:
        - name: harbor
      volumes:
        - name: logdir
          emptyDir: {}
        - name: localtime
          hostPath:
            path: /etc/localtime
        - name: timezone
          hostPath:
            path: /etc/timezone

# 2.应用配置文件
kubectl apply -f deployment.yaml

# 3.查看
# kubectl get pod -n test
NAME                                  READY   STATUS    RESTARTS   AGE
helloworld-6f78bd8668-j6hmp           1/1     Running   0          3d18h

要点:

  • hostAliases: 用于指定适用于该项目的hosts解析,可根据实际情况进行添加。
  • env: jvm启动参数通过环境变量env传递,而args只适用于dockder build阶段,因此不能使用。
  • resources: 容器默认会无限制占用宿主机资源,因此需要进行限制。对于java 项目 xms xmx只是堆内存,实际进程所占内存比这还大,例如某项目默认Xms Xmx都是128M,但是pod的资源限制为200M、300M都会导致OOM,因此调整的资源需要比Xmx还要大
  • hostPath: 将宿主机节点文件系统中的文件或目录挂载到集群中,由于基于宿主机的目录,多副本跨节点必须保证目录存在,否则可能导致失败
  • emptyDir: 当pod被分配给节点时,首先创建emptyDir卷,并且只要该pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。pod中的容器可以读取和写入emptyDir卷中的相同文件。尽管该卷可以挂在到每个容器中的相同或不同路径上。当出于任何原因从节点中删除pod时,emptyDir中的数据将被永久删除
  • 容器时区: 挂在宿主机的localtime和timezone,保证项目日志时间正常。
  • livenessProbe: 通过探针livenessProbe进行检测,httpGet获取的状态码等于200或小于400则正常。检测失败后,将根据使用restartPolicy策略。restartPolicy默认为always。
  • readinessProbe: 通过探针readinessProbe进行检测,httpGet获取的状态码等于200或小于400则正常。指示容器是否准备好服务请求。如果就绪探针失败,则端点控制器将从与Pod匹配的所有服务的端点中删除Pod的IP地址。默认每10秒检测一次,连续失败数为3,连续成功数为1。
  • initialDelaySeconds: 如果启动时间超过initialDelaySeconds会导致livenessProbe、readinessProbe检测不成功。readinessProbe 失败导致无法接受请求,livenessProbe失败导致容器不断重启。因此initialDelaySeconds要大于实际启动时间

注意:

  1. 对于SpringBoot项目的日志文件,我们并没有进行持久化存储,而是通过emptyDir临时存储,然后通过写入ELK做长期存储。
  2. 对于SpringBoot项目的数据文件,无论通过hostPath还是emptyDir都不合适,需通过PVC进行持久化存储。

4. 定义service

# 1.vim service.yaml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: test
spec:
  type: NodePort
  selector:
    app: helloworld
  ports:
    - port: 8080
      targetPort: 8080

# 2.应用配置文件
kubectl apply -f service.yaml
# 3.查看状态
# kubectl get svc -n test
NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
helloworld   NodePort   10.1.139.205   <none>        8080:30949/TCP   6d

# 4.访问
# curl 10.1.138.205:8080
Hello,world!

对于NodePort类型的service,通过集群所有节点的IP都可以访问服务

# curl 192.168.3.218:30949 
Hello,world!
# curl 192.168.3.219:30949 
Hello,world!
# curl 192.168.3.217:30949 
Hello,world!

# 原因:
# 所有节点lvs信息都有对service 30949端口的转发,因此集群内所有节点都可通过service访问服务
ipvsadm -l -n |grep -A 2 -B 2 30949
TCP  192.168.3.217:30949 rr
  -> 10.244.2.100:8080  

5.定义ingress

此部分细节可参考适合ingress-nginx接入外部负载均衡的部署选择适合自己的部署方式,本文我们使用默认的Deployment+NodePort进行部署。

# 1.vim ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: helloworld
  namespace: test
spec:
  rules:
    - host: hello.test.cn 
      http:
        paths:
          - path: /
            backend:
              serviceName: helloworld
              servicePort: 8080
# 2.应用
kubectl apply -f ingress.yaml
# 3.查看
# kubectl get ing -n test
NAME         CLASS    HOSTS           ADDRESS       PORTS   AGE
helloworld   <none>   hello.test.cn   10.1.217.16   80      4d18h
# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.1.217.16   <none>        80:30687/TCP,443:31826/TCP   15h
# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.1.217.16   <none>        80:30687/TCP,443:31826/TCP   15h
# 4.访问
# curl -x 192.168.3.218:30687 hello.test.cn
Hello,world!

注意: 默认ingress-nginx部署并不能让我们从外部通过80端口访问到服务,只能通过NodePort暴露的端口访问。

总结

以上是整个SpringBoot项目的部署过程及需要注意的地方,个人认为K8S部署SpringBoot项目最主要的应该是资源限制、健康检查及存储这三点。

  • 资源限制保证集群内容器合理占用宿主机资源,避免资源无限占用导致集群问题;
  • 健康检查保证集群内容器正常运行,合理摘除不健康的节点,保证请求的转发到健康节点;
  • 选择合适的存储方式,保证项目的运行时数据、日志文件合理存储;
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值