SpringCloud kubernetes使用k8s作为注册中心,实现服务发现

首先搭建k8s集群。见 Centos安装k8s

使用springcloud 创建两个项目,我这里创建了一个talk一个project。想利用talk项目在k8s中,使用feign调用peoject项目。下面是具体实现

上代码

  1. SpringCloud kubernetes maven 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.shujunjun.project</groupId>
        <artifactId>shujunjun</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>talk</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>5.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-client-all</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-fabric8-all</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-bootstrap -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <!-- 负载均衡 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-fabric8-loadbalancer</artifactId>
        </dependency>

        <!-- 负载均衡 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-client-loadbalancer</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.5</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>
  1. 配置文件 bootstrap.yml
spring:
  cloud:
    kubernetes:
      discovery:
        # 让所有命名空间服务都可以发现服务
        all-namespaces: true
        # 发现未标记为“就绪”的服务端地址
        include-not-ready-addresses: true
        # ExternalName类型服务的列表  DiscoveryClient::getInstances 返回该列表 ServiceInstance::getMetadata
        include-external-name-services: true
        enabled: true
      config:
        name: talk-config
        namespace: default
        # 配置是否读取配置文件
        enabled: true
      # 启用属性源监控和配置重新加载
      reload:
        enabled: true
        # 允许监视配置映射中的更改
        monitoring-config-maps: true
        # 触发重新加载时使用的策略
        strategy: refresh
        # 指定如何侦听属性源的更改
        mode: event
      loadbalancer:
        # 通过服务名启用负载均衡
        mode: pod
  application:
    name: talk
  main:
    # 允许在Spring的ApplicationContext中覆盖已有的Bean定义
    allow-bean-definition-overriding: true

这里我设置了允许让k8s去覆盖定义的bean,同时设置了所有命名空间都可以发现服务。其次,利用talk-config 的configmap去设置服务的一些配置信息。这里测试使用,目前只设置了端口号

talk.config
[root@k8s-master shujunjun]# cat talk-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: talk-config
data:
  application.yml: |
   server:
     port: 8888

  1. 简单的feign调用接口
package com.shujunjun.project.feign;

import com.shujunjun.project.entity.dto.ProjectDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@FeignClient(name = "project", url = "${shujunjun.project.url:}")
public interface IProjectFeign {

    @GetMapping(value = "project")
    List<ProjectDTO> list();
}
  1. controller实现
package com.shujunjun.project.controller;

import com.shujunjun.project.entity.dto.ProjectDTO;
import com.shujunjun.project.feign.IProjectFeign;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class ProjectController {

    final IProjectFeign projectFeign;

    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping(value = "services")
    public List<String> getServices() {
        return discoveryClient.getServices();
    }

    @GetMapping(value = "project")
    public List<ProjectDTO> project() {
        return projectFeign.list();
    }
}
  1. project项目就是一个简单的接口
package com.shujunjun.project.controller;

import com.shujunjun.project.entity.Project;
import com.shujunjun.project.service.IProjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class ProjectController {
    

    final IProjectService projectService;
    

    @GetMapping(value = "project")
    public List<Project> project() {
        return projectService.list();
    }
}
  1. 使用docker build 镜像到k8s服务器
[root@k8s-slave1 talk]# ls
Dockerfile  talk.jar
[root@k8s-slave1 talk]# cat Dockerfile
FROM openjdk:17-jdk-alpine
EXPOSE 8080
ADD talk.jar app.jar
ENTRYPOINT ["java","-jar","-Duser.timezone=GMT+08","app.jar"]
  1. 构建talk项目镜像(project项目同理)
[root@k8s-slave1 talk]# docker build -t talk:latest .
[+] Building 20.6s (7/7) FINISHED                                                                                                                                                              docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                     0.0s
 => => transferring dockerfile: 92B                                                                                                                                                                      0.0s
 => [internal] load .dockerignore                                                                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                                                          0.0s
 => [internal] load metadata for docker.io/library/openjdk:17-jdk-alpine                                                                                                                                15.9s
 => [internal] load build context                                                                                                                                                                        1.4s
 => => transferring context: 93.37MB                                                                                                                                                                     1.4s
 => CACHED [1/2] FROM docker.io/library/openjdk:17-jdk-alpine@sha256:4b6abae565492dbe9e7a894137c966a7485154238902f2f25e9dbd9784383d81                                                                    0.0s
 => [2/2] ADD talk.jar app.jar                                                                                                                                                                           2.7s
 => exporting to image                                                                                                                                                                                   0.4s
 => => exporting layers                                                                                                                                                                                  0.4s
 => => writing image sha256:87f5c2f9ea674ad2570b43006bce21966fc63c87193fc482180c4e1257ff51ba                                                                                                             0.0s
 => => naming to docker.io/library/talk:latest                                                                                                                                                           0.0s
  1. 查看镜像
[root@k8s-slave1 talk]# docker images
REPOSITORY                                                                      TAG       IMAGE ID       CREATED          SIZE
talk                                                                            latest    87f5c2f9ea67   46 minutes ago   419MB
project                                                                         latest    8733fdc4c777   3 days ago       419MB
192.168.121.128:8082/oaim-web                                                   latest    b883ef6510d2   3 weeks ago      156MB
istio/proxyv2                                                                   1.16.7    d90c7490ed6d   8 months ago     261MB
istio/pilot                                                                     1.16.7    e73936e7d5be   8 months ago     202MB
redis                                                                           latest    7614ae9453d1   2 years ago      113MB
mysql                                                                           latest    3218b38490ce   2 years ago      516MB
calico/node                                                                     v3.19.1   c4d75af7e098   2 years ago      168MB
calico/pod2daemon-flexvol                                                       v3.19.1   5660150975fb   2 years ago      21.7MB
calico/cni                                                                      v3.19.1   5749e8b276f9   2 years ago      146MB
calico/kube-controllers                                                         v3.19.1   5d3d5ddc8605   2 years ago      60.6MB
kubernetesui/dashboard                                                          v2.0.0    8b32422733b3   3 years ago      222MB
registry.aliyuncs.com/google_containers/kube-proxy                              v1.18.0   43940c34f24f   3 years ago      117MB
registry.aliyuncs.com/google_containers/pause                                   3.2       80d28bedfe5d   4 years ago      683kB
registry.aliyuncs.com/google_containers/coredns                                 1.6.7     67da37a9a360   4 years ago      43.8MB
registry.cn-hangzhou.aliyuncs.com/kubeapps/k8s-gcr-kubernetes-dashboard-amd64   v1.8.3    0c60bcf89900   6 years ago      102MB
bingozhou/mysql5.7                                                              latest    8dbbe042b8f7   6 years ago      407MB

如上述显示所示,talk和project项目已经打包至k8s从节点。你也可以通过Nexus统一管理镜像

  1. 在k8s环境中创建具体服务

创建服务之前,给默认用户赋权限,否则项目启动会报错

 [project] [els.V1Service-1] i.k.c.informer.cache.ReflectorRunnable   : class io.kubernetes.client.openapi.models.V1Service#Reflector loop failed unexpectedly

io.kubernetes.client.openapi.ApiException: class V1Status {
    apiVersion: v1
    code: 403
    details: class V1StatusDetails {
        causes: null
        group: null
        kind: services
        name: null
        retryAfterSeconds: null
        uid: null
    }
    kind: Status
    message: services is forbidden: User "system:serviceaccount:default:default" cannot list resource "services" in API group "" at the cluster scope
    metadata: class V1ListMeta {
        _continue: null
        remainingItemCount: null
        resourceVersion: null
        selfLink: null
    }
    reason: Forbidden
    status: Failure
}

因此需要给默认用户足够权限。我这里为了方便赋的权限比较大,具体可以根据自己的情况设置
如下:auth.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-service-endpoints-reader
rules:
- apiGroups: [""]
  resources: ["pods", "services", "endpoints", "secrets", "configmaps"]
  verbs: ["get", "watch", "list"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-service-endpoints-reader-binding
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-service-endpoints-reader
  apiGroup: rbac.authorization.k8s.io
  1. 创建talk.yaml和对应需要的configmap配置
[root@k8s-master shujunjun]# ls
project-config.yaml  project.yaml  talk-config.yaml  talk.yaml
[root@k8s-master shujunjun]# cat talk-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: talk-config
data:
  application.yml: |
   server:
     port: 8888
[root@k8s-master shujunjun]# cat talk.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: talk
spec:
  replicas: 1
  selector:
    matchLabels:
      app: talk
  template:
    metadata:
      labels:
        app: talk
    spec:
    #  serviceAccountName: shujunjun
      containers:
      - name: talk
        image: talk:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8888

---

apiVersion: v1
kind: Service
metadata:
  name: talk
spec:
  type: LoadBalancer
  ports:
  - port: 8888
    targetPort: 8888
    nodePort: 8888
  selector:
    app: talk

project类似处理,这里不再赘述

  1. 部署应用
[root@k8s-master shujunjun]# kubectl apply -f talk.yaml
deployment.apps/talk created
service/talk created
部署效果
  1. 测试效果


    ok

    通过kubernetes使用feign调用成功


    查看k8s上其他服务

    也可以查看k8s中其他服务信息
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容