目 录CONTENT

文章目录

K8S部署微服务实践

BKUN
2024-05-08 / 1 评论 / 0 点赞 / 2,466 阅读 / 1,857 字

概述

在当今云原生时代,微服务架构已成为构建复杂分布式系统的主流选择。Kubernetes(常简称为K8s)作为开源的容器编排系统,为微服务的管理和部署提供了强大的支持。然而,对于初学者或小型团队来说,直接在生产环境中部署K8s可能存在一定的挑战。因此,Minikube作为一个轻量级的K8s实现,为开发者提供了一个在本地机器上运行K8s集群的便捷方式,从而方便地进行微服务部署和测试。

微服务镜像包准备

打包流程,以Eureka为例展开,其余服务Dockerfile也这么写,下边就不一一列举了(因ENV放到环境变量原因,无需加额外参数)

Dockerfile配置文件

# 基礎鏡像 依賴的鏡像
FROM openjdk:8u342
WORKDIR work
ADD demo-eureka.jar demo-eureka.jar
# 設置命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","demo-eureka.jar"]

执行命令

docker build -t demo-eureka -f Dockerfile .
minikube image load demo-eureka

相关命令

方式一:打包docker镜像然后load到minikube

docker build -t <镜像名称> -f Dockerfile .
minikube image load <镜像名称>

方式二:直接使用minikube打包镜像

minikube image build -t <镜像名称> .

minikube 已上传镜像

minikube image ls

删除 minikube 镜像

minikube image rm <minikube image ls 的镜像名称>

加载 docker 镜像至 minikube

minikube image load <镜像名称>

添加镜像至 minikube

minikube image build -t <镜像名称> .

minikube 命令帮助

minikube help

微服务部署启动

SpringCloud Eureka集群(双节点)

对于eureka来说,要实现eureka的高可用,那就不是修改replicas这么方便了。由于部署的多个eureka之间需要将自己注册到彼此,因此要做一些特殊改动。

对于一般的后端微服务来说,在k8s中同时起多个相同的服务来做负载均衡,只需要简单的修改deployment的replicas,增加pod数量,然后通过对外暴露一个service来代理这些pod。

主要是用到了StatefulSet和headless service这两个k8s对象

StatefulSet
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态)

Headless Service
Headless Service 和普通service的一个显著的区别是,Headless Service的对应的每一个Endpoints,即每一个Pod,都会有对应的DNS域名。例如:我们可以用过这种域名来访问某个具体的pod
statefulSetName-0.serviceName.namespace.svc.cluster.local

这点在eureka的配置文件中defaultZone非常重要。

Eureka服务的yaml配置文件

#spring 注册中心名称
spring.application.name=serivce-eureka

#spring 注册中心配制
server.port=${PORT:11080}

#注册中心名称
eureka.instance.hostname=${EUREKA_INSTANCE_HOSTNAME:${spring.application.name}}
#实例名称显示IP配置
eureka.instance.preferIpAddress=true
# 实例ID
eureka.instance.instance-id=${EUREKA_INSTANCE_HOSTNAME:${spring.application.name}}:${server.port}@${random.long(1000000,9999999)}
#优先使用
#eureka.instance.ipAddress=127.0.0.1

#是否将自身注册  
eureka.client.registerWithEureka=false
#如果为true,启动时报警. 
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=${EUREKA_SERVER:http://127.0.0.1:${server.port}/eureka/}

# 设为false,关闭自我保护
#eureka.server.enable-self-preservation=false
# 清理间隔(单位毫秒,默认是60*1000)  心跳监控		
eureka.server.eviction-interval-timer-in-ms=30000

配置文件解读:PORTEUREKA_SERVER 等参数都会在Eureka的StatefulSet的yaml文件中定义;当K8S容器启动时,对应自定义参数会放到启动容器的环境变量中(可在容器执行env命令查看);届时应用会优先读取并覆盖替换为环境变量的参数。

Eureka的StatefulSet的yaml文件(本地镜像模式)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: demo
  name: demo-eureka
  labels:
    app: demo-eureka
spec:
  serviceName: 'serivce-eureka'
  replicas: 2
  selector: 
    matchLabels:
      app: demo-eureka
  template:
    metadata:
      labels:
        app: demo-eureka
    spec:
      #volumes:
      #- name: logs
      #  nfs:
      #    path: /home/docker/k8s_yaml/nfs_logs/demo-eureka
      #    server: 192.168.xx.xx
      #nodeName: serverxx
      #imagePullSecrets:
      #  - name: xxxxx
      containers:
      - name: demo-eureka
        image: demo-eureka
        imagePullPolicy: Never
        ports:
        - containerPort: 11080
        #volumeMounts:
        #  - name: logs
        #    mountPath: /opt/app/logs
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: EUREKA_SERVER
            value: "http://demo-eureka-0.serivce-eureka.demo:11080/eureka/,http://demo-eureka-1.serivce-eureka.demo:11080/eureka/"
          - name: EUREKA_INSTANCE_HOSTNAME
            value: ${POD_NAME}.serivce-eureka.demo
          - name: PORT
            value: '11080'

Eureka 集群需要通过容器的主机名相互通讯,需要配置 Headless Service 资源,这也是为什么defaultZone配置会写成是 “http://demo-eureka-0.serivce-eureka.demo:11080/eureka/,http://demo-eureka-1.serivce-eureka.demo:11080/eureka/” 的原因。

域名解读:{POD_NAME}-{INDEX}.{SERVICE_NAME}.

Headless Service 的 yaml文件

注:这里的clusterIP为None,这是区别Headless Service与普通Service的地方。

apiVersion: v1
kind: Service
metadata:
  namespace: demo
  name: serivce-eureka
  labels:
    app: demo-eureka
spec:
  clusterIP: None
  ports:
    - port: 11080
  selector:
    app: demo-eureka

端口转发执行命令

kubectl port-forward -n demo statefulsets/demo-eureka 11080:11080

浏览器本地访问

http://localhost:11080

K8S部署SpringCloud Config配置中心(单节点)

“K8s上部署配置中心服务模块,同时也可以进一步检测eureka集群是否可用”

Config Service的 Deployment 的yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: demo
  name: demo-config
  labels:
    app: demo-config
spec:
  serviceName: 'serivce-config'
  replicas: 1
  selector: 
    matchLabels:
      app: demo-config
  template:
    metadata:
      labels:
        app: demo-config
    spec:
      #volumes:
      #- name: logs
      #  nfs:
      #    path: /home/docker/k8s_yaml/nfs_logs/demo-config
      #    server: 192.168.xx.xx
      #nodeName: serverxx
      #imagePullSecrets:
      #  - name: mysecret
      containers:
      - name: demo-config
        image: demo-config
        imagePullPolicy: Never
        ports:
        - containerPort: 11084
        #volumeMounts:
        #  - name: logs
        #    mountPath: /opt/app/logs
        env:
          - name: POD_IP
            valueFrom:
                fieldRef:
                    fieldPath: status.podIP
          - name: eureka.client.serviceUrl.defaultZone
            value: "http://demo-eureka-0.serivce-eureka.demo:11080/eureka/,http://demo-eureka-1.serivce-eureka.demo:11080/eureka/"
          - name: spring.cloud.config.server.native.searchLocations
            value: "/export/demo/config"
          - name: eureka.instance.ipAddress
            value: ${POD_IP}

注意:为了通知注册中心 注册服务地址,eureka.instance.ipAddress 配置需从容器获取(例:POD_IP)。

K8S部署SpringCloud Service(多节点)

“K8s上部署应用服务模块”

注:若使用配置中心,配置优先级:配置中心 > yaml定义的配置 > Jar包内的配置。
1、如果部分配置如果需要抽到K8S yaml定义,需注释掉相关内容
2、从配置中心读取的配置不支持注册中心${PORT, 18080}(尤其这点需注意)

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: demo
  name: demo-auth
  labels:
    app: demo-auth
spec:
  serviceName: 'serivce-auth'
  replicas: 2
  selector: 
    matchLabels:
      app: demo-auth
  template:
    metadata:
      labels:
        app: demo-auth
    spec:
      #volumes:
      #- name: logs
      #  nfs:
      #    path: /home/docker/k8s_yaml/nfs_logs/demo-auth
      #    server: 192.168.xx.xx
      #nodeName: serverxx
      #imagePullSecrets:
      #  - name: xxxxx
      containers:
      - name: demo-auth
        image: demo-auth
        imagePullPolicy: Never
        ports:
        - containerPort: 11083
        #volumeMounts:
        #  - name: logs
        #    mountPath: /opt/app/logs
        env:
          - name: POD_IP
            valueFrom:
                fieldRef:
                    fieldPath: status.podIP
          - name: eureka.client.serviceUrl.defaultZone
            value: "http://demo-eureka-0.serivce-eureka.demo:11080/eureka/,http://demo-eureka-1.serivce-eureka.demo:11080/eureka/"
          - name: eureka.instance.ipAddress
            value: ${POD_IP}

微服务本地访问

kubectl port-forward 通过端口转发

kubectl port-forward 通过端口转发映射本地端口到指定的应用端口,从而访问集群中的应用程序(Pod).

执行命令

kubectl port-forward -n demo statefulsets/demo-eureka 11080:11080

本地浏览器打开:http://localhost:11080 即可访问

0

评论区