K8s 部署 Spring boot 实践应用指南

2020-04-09  本文已影响0人  _1900

准备工作

对k8s知识有一定了解掌握,能够明白Pod、Deployment、Service、Ingress 具体概念
准备一套可用的k8s环境
准备一个部署的spring boot 应用

构建&上传镜像

k8s最小单元是Pod, 而Pod 是一组运行的容器,那么容器是怎么运行起来的呢 ? 就是通过构建的镜像。(目前我们使用的容器技术都是基于docker)

那先让我们来一起制作个镜像,

将一个可运行的项目打包成一个jar文件,创建一个文件DockerFile,DockerFile和jar放到同一个目录 编写DockerFile

FROM java:8 #定义使用环境信息

WORKDIR /app/spring-boot-hello/ # 创建工作目录

ADD  spring-boot-hello-1.0.jar /app/spring-boot-hello/ #把jar文件放到工作目录

EXPOSE  8080 #申明端口,并不是访问端口

ENTRYPOINT  ["java","-jar","spring-boot-hello-1.0.jar"] #执行命令

执行生成镜像命令
docker build -f ./DockerFile -t "/test/helloworld-server:v1" .

查看镜像 docker images

运行镜像是否正常 9000为宿主机访问端口
docker run -p 9000:8080 /test/helloworld-server:v1

通过curl或者浏览器访问 localhost:9000 服务是否正常,如果正常说明镜像制作成功,开始准备把镜像上传到仓库, 上传之前确定是否登录,如果没有登录执行 :docker login 仓库地址

如果仓库使用的是harbor tag的名字格式改为:
仓库地址/仓库/名称,
比如 harbor.com/test/helloword-service

修改镜像 tag
docker tag <imageid> reg.com/test/helloworld-server:v1

上传镜像
docker push reg.com/test/helloworld-server:v1
上传完镜像可以登录仓库查看是否上传成功。

部署到k8s

创建deployment

创建deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: helloworld-server
  labels:
    app: helloworld-server
spec:
  # 副本数
  replicas: 2
  selector:
    matchLabels:
      app: helloworld-server
  template:
    metadata:
      labels:
        app: helloworld-server
    spec:
      containers:
      - name: helloworld-server
        image: reg.com/test/helloworld-server:v1
        workingDir: /app/spring-boot-hello
        ports:
        - containerPort: 8080

执行 kubectl apply -f deployment.yaml

查看pod 是否创建成功 处于ready 状态
kubectl get pod -o wide

如果没有创建成功,通过log 或者 describe 查看具体原因
kubectl describe pod pod-namexxxxx

pod 的IP重启之后就会有变化,所以为了能够固定访问pod有了service的概念,pod绑定service,我们通过service来访问pod,service可以理解为集群内部的负载均衡流量的控制器,接下来我们开始创建service

创建service

创建service.ymal

apiVersion: v1
kind: Service
metadata:
  name: helloworld-server
  labels:
    app: helloworld-server
spec:
  type: NodePort
  selector:
    app: helloworld-server  # pod  app: helloworld-server 
  ports:
    - port: 80 
      targetPort: 8080  # containerPort

我们使用的service type是NodePort,yaml里没有申明nodePort 所以k8s会默认创建一个nodePort (30000-40000),然后我们通过node ip 加 nodePort 就可以访问service。

kubectl apply -f service.yaml

查看nodePort kubectl get svc -o -wide

通过curl node ip : nodePort 查看是否路由到pod的服务,service的路由是针对内部使用,所以对外我们还需要提供另一种访问方式 那就是Ingress,(还有其它访问方式,本章使用Ingress)接下俩就是创建Ingress

创建Ingress

ingress.ymal

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: helloworld-server
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: helloserver.com
    http:
      paths:
      - path: /?(.*)
        backend:
          serviceName: helloworld-server # service name
          servicePort: 80  # service port

kubectl apply -f ingress.ymal

安装ingress contoller

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/baremetal/deploy.yaml

查看ingress contoller pod 是否创建成功,一般情况pull镜像的时候会失败,需要手动 docker pull .

配置host nodeIP helloserver.com,通过 curl helloserver.com:ingress contoller nodePort 访问。可以配置HA proxy 解决不用加端口问题

查看ingress contoller nodePort
kubectl get svc -o -wide -n ingress-nginx

到目前为止整个访问流程就配置完成了,如果我们配置完之后仍然访问不了
,可以一步一步的排除

绑定关系

  1. Service selector 应该匹配 Pod 的标签
  2. Service targerPort应该匹配在 Pod 内容器的containerPort
  3. Service 端口可以是任意数字。多个 Service 可以使用同个端口,因为它们已经分配了不同的 IP 地址
  4. Ingress 的servicePort应该匹配在 Service 中的port
  5. Service 的名称应该匹配在 Ingress 中的serviceName的字段

故障排查

检查pod是否正常
kubectl describe pod <pod name>

检查service 绑定pod配置是否正确 从service 访问pod Endpoints
kubectl describe service <service-name> | grep Endpoints
一个 endpoint 是一对<ip address:port>,并且当 Service(至少)target 一个 pod 时。至少有一对

检查Ingress 配置
kubectl describe ingress <ingress-name>

如果你能在 /Backend/ 列中看到 endpoint,但依旧无法访问应用程序,那么可能是以下问题:

总结

如果你毫无头绪,那么在 Kubernetes 中进行故障排除可能是一项艰巨的任务。
你应该永远记住以从下至上的顺序解决问题:现检查 Pod,然后向上移动堆栈至 Service 和 Ingress。

上一篇下一篇

猜你喜欢

热点阅读