Zhu의 예는 봄 시리즈 S1E11 이야기 : 퀴즈 봄 클라우드는 Kubernetes @ 알리 구름 K8S을

Zhu의 예는 봄 시리즈 S1E11 이야기 : 퀴즈 봄 클라우드는 Kubernetes @ 알리 구름 K8S을

우리는 세 가지 주요 기능 시험을 본 논문에서 (이하 SCK 라한다) 봄 클라우드 Kubernates https://github.com/spring-cloud/spring-cloud-kubernetes을 참조 소개 :

  • 서비스 요청을하고 봄 클라우드 리본 Kubernates 서비스 검색을 사용하여
  • ConfigMap 형 구성 Kubernates을 읽고 동적 지원 수정 후 새로 고침
  • Kubernates 포드 정보의 봄 부팅 액추에이터 인식

시험 절차를 쓰기

첫째, 우리는 몇 가지를주의하는 치어 파일을 만듭니다 :

  • 봄 부트 버전은 너무 높은 수 없습니다
  • 봄 부팅 웹 및 액추에이터 두 개의 모듈을 소개, 우리는 테스트 할 웹 프로젝트를 개발
  • 리본 봄 클라우드 모듈의 도입은, 우리는 서비스 호출을 테스트해야
  • 우리의 주요 테스트 대상에 모두 스프링 클라우드 스타터는 Kubernetes 의존의 도입
  • 우리가 거울을 구축 할 수 있도록 추가 도입 고정 표시기 - 받는다는 - 플러그인 플러그인
  • finalName 설정

다음과 같이 파일 :

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.9.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>me.josephzhu</groupId>
    <artifactId>springcloudk8sdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloudk8sdemo</name>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-all</artifactId>
            <version>1.0.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>k8sdemo</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <imageName>zhuye/${project.artifactId}</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

다음 주 \ 고정 표시기 디렉토리 \ SRC에의 Dockerfile 파일을 만듭니다 :

FROM openjdk:11-jdk-slim
VOLUME /tmp
ADD k8sdemo.jar app.jar
ENTRYPOINT exec java $JAVA_OPTS -jar /app.jar

JVM 매개 변수는 우리가 환경 변수에서 주입 할 것인지 주목된다.

코드를 봐, 우리는 먼저 구성 클래스를 정의 :

package me.josephzhu.springcloudk8sdemo;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "bean")
@Data
public class TestConfig {
    private String message;
    private String serviceName;
}

SCK의 도움으로, 구성은 우리가 구성 ConfigMap 형을 볼 수, ConfigMap 형에서로드 할 수 있습니다. 여기서 우리는 서버의 역할을하는 컨트롤러를 정의 :

package me.josephzhu.springcloudk8sdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

@RestController
public class TestServer {

    @Autowired
    private DiscoveryClient discoveryClient;

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

    @GetMapping
    public String ip() throws UnknownHostException {
        return InetAddress.getLocalHost().getHostAddress();
    }
}

우리는 여기에서 보는 두 개의 인터페이스를 정의 할 수 있습니다 :

  • 서버는 모든 서비스를 찾을 수있는 서비스 발견 (K8S 서비스)에 대한 반환
  • 루트는 현재 노드의 IP 주소를 반환

다음으로, 클라이언트와 같은 다른 제어 작용을 정의 :

package me.josephzhu.springcloudk8sdemo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.InetAddress;
import java.net.UnknownHostException;

@RestController
@Slf4j
public class TestClient {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private TestConfig testConfig;

    @GetMapping("client")
    public String client() throws UnknownHostException {
        String ip = InetAddress.getLocalHost().getHostAddress();
        String response = restTemplate.getForObject("http://"+testConfig.getServiceName()+"/", String.class);
        return String.format("%s -> %s", ip, response);
    }
}

여기서 고객 인터페이스는 RestTemplate 인터페이스를 통해 액세스 서버 루트 경로에 액세스 인터페이스 후 클라이언트와 서버의 IP 주소를 출력한다.

뭔가 우리가 직접적으로 무엇이 잘못되었는지 볼 잘못되면 우리는 그 다음 글로벌 예외 핸들러를 정의 :

package me.josephzhu.springcloudk8sdemo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
@Slf4j
public class GlobalAdvice {

    @ExceptionHandler(Exception.class)
    public String exception(Exception ex){
        log.error("error:", ex);
        return ex.toString();
    }
}

마지막으로, 우리는 시작 프로그램을 정의 :

package me.josephzhu.springcloudk8sdemo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestTemplate;

import java.lang.management.ManagementFactory;
import java.util.stream.Collectors;

@SpringBootApplication
@EnableDiscoveryClient
@EnableScheduling
@Slf4j
@RibbonClient(name = "k8sdemo")
public class Springcloudk8sdemoApplication {

    public static void main(String[] args) {
        log.info("jvm:{}",
                ManagementFactory.getRuntimeMXBean().getInputArguments().stream().collect(Collectors.joining(" ")));
        SpringApplication.run(Springcloudk8sdemoApplication.class, args);
    }

    @Autowired
    private TestConfig testConfig;

    @Scheduled(fixedDelay = 5000)
    public void hello() {
        log.info("config:{}", testConfig);
    }

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

이 프로그램에서 우리는 몇 가지 일을하기 시작했다 :

  • 이는 타이머를 정의하고, 5 초마다 출력 구성 (그 동적 리프레시 ConfigMap 형을 관찰하도록 배치)
  • RestTemplate 정의 및 리본과 함께 사용
  • JVM 때 변수 (환경 변수) 성공의 주입을 증명하기 위해, JVM 파라미터로 출력을 개시

프로파일 영역, 제 application.yaml :

spring:
  application:
    name: k8sdemo
  cloud:
    kubernetes:
      reload:
        enabled: true
      config:
        sources:
          - name: ${spring.application.name}

우리는 세 가지를했다 :

  • 응용 프로그램 이름을 정의합니다
  • k8sdemo있는 응용 프로그램 이름에 지정된 이름을 ConfigMap 형
  • ConfigMap 형 자동 새로 고침을 구성 가능합니다 (아래 그림 참조 기본 이벤트는 방법입니다)

image_1dm8j8hhpa1jsi1brb1gb81nh8m.png-374.9kB

그리고 엔드 포인트 액추에이터의 일부를 엽니 다 bootstrap.yaml을 정의합니다 :

management:
  endpoint:
    restart:
      enabled: true
    health:
      enabled: true
    info:
      enabled: true

https://github.com/JosephZhu1983/SpringCloudK8S의 전체 소스 코드를 참조하십시오

알리 클라우드 클러스터 구성 K8S

클러스터 내가 사는 과정을 생략, 이러한 옵션은 훅에있는, 흔들림 특히 우리 후 공용 네트워크에서 테스트 할 필요성을 기억한다.

image_1dm8jqua649k1hp811vb1nu31osr9.png-84.1kB

거의 30 초 K8S 클러스터, 당신은 당신은 내가 호스팅 버전을 구입 볼 수 아래없이 고 가용성의 일에 관여하지 않았다 처음부터 자신을 구축하고자이 빌어 먹을 것은 K8S의 호스팅 버전이라고 3 노드를 K8S 우리는, 작업 노드를 살 돈과 걱정을 저장해야, 자신의 알리 구름과 함께 관리 노드를 지시.

image_1dm8jgiu51v7mkkd14ks1fdt18vo1g.png-59.5kB

kubectl를 통해 클러스터에 액세스하려면, 구성 kubeconfig을 기억 샀다.

image_1dm8jfosa1kfcg2a5cd1oi5p0013.png-291.9kB

주어진 구성에서 알리 구름이 직접 구성의 원본에 포함 (예 : 당신에게로 가능 로컬 클러스터)에 속하지 않는 것에주의 최종 문서에 직접 붙여하지 않는 파일 형식이, 당신이 클러스터 필요 문맥 세 사용자 구성은 해당 장소에 복제된다.

거울의 건설

우리는 K8S 가상 머신 배포는 달리, 배달은 거울이다, 알고, 그래서 우리는 알리 구름에 이미지를 업로드해야합니다.
첫째, 로컬 미러를 구축 :

mvn package docker:build -DskipTests

보기 미러를 완료 한 후 :
image_1dm8k69r61uiu1efvc711eeq118u13.png-77.4kB

그리고 알리 클라우드 서비스는 자신의 창고를 만들 미러링 시작 :

image_1dm8k8bgh1q3c1g7g1hogp319701g.png-128.4kB

미러 후 미러 설명의 내부는 리포지토리에 푸시 태그 :

docker login --username=【你的账号】 registry.cn-shanghai.aliyuncs.com
docker tag 80026bb476ce registry.cn-shanghai.aliyuncs.com/zhuyedocker/test:v6
docker push registry.cn-shanghai.aliyuncs.com/zhuyedocker/test:v6

거울 거울을 볼 수있는 창고의 완료 후 :
image_1dm8kd82h1jld133i12685oo1t1t.png-87.2kB

응용 프로그램 배포

미러링함으로써 비 저장 응용 프로그램을 만들 수 :
image_1dm8kfhvkolh1opdj79hoc1p2g2a.png-54.2kB

때 다음과 같은 메모를 생성 :

  • 우측 거울 태그를 선택
  • 나는 응용 프로그램 1C CPU 1.4G 메모리 구성을 제공하기 위해 여기입니다
  • 포트 및 일관된 적용은 8080로 설정되어
  • 通过环境变量注入额外的JVM参数:-server -XX:+UseContainerSupport -XX:MaxRAMPercentage=50.0 -XX:InitialRAMPercentage=50.0 -XX:MinRAMPercentage=50.0 -XX:MaxMetaspaceSize=256M -XX:ThreadStackSize=256 -XX:+DisableExplicitGC -XX:+AlwaysPreTouch

这里我配置了JVM动态根据容器的资源限制来设置堆内存大小(此特性在部分版本的JDK8上支持,在9以后都支持),这比直接设置死Xms和Xmx好很多(设置死的话不方便进行扩容),这里我设置了50%,不建议设置更高(比如如果是2GB的内存限制,给堆设置为1.5GB显然是不合适的),毕竟Java进程所使用的内存除了堆之外还有堆外、线程栈(线程数*ThreadStackSize)、元数据区等,而且容器本身也有开销。

我这里展示的是编辑界面,创建界面略有不同但是类似:
image_1dm8khth11mvcob91jcv1rotark2n.png-103.6kB

创建应用的时候你可以把Service和Ingress一并创建。

image_1dm8lkjpr16mqihdlvgvc7e5134.png-12KB

完成后可以进入应用详情看到2个节点状态都是运行中:

image_1dm8lmgfpcoj0e10jk1mm31f0q3h.png-95.2kB

测试应用启动情况

来到Ingress界面可以看到我们的公网Ingress记录,可以直接点击访问:

image_1dm8ls39f12f2lra1cbq1v751ft74o.png-136.8kB

根节点输出的是IP,在之前的截图中我们可以看到服务运行在1.13和0.137两个IP上:
image_1dm8lqnph1tv31uqgpnv11p31ee4b.png-22.1kB

多刷新几次浏览器可以看到负载均衡的效果。

访问services可以查看到所有K8S的服务:
image_1dm8m0cmu36uqof7fs1ptso75v.png-27.8kB

访问actuator/info可以看到有关K8S的详情(感谢SCK),显然我们代码里获取到的IIP是PodIP:
image_1dm8lvlj347vg7d1e42b1613om5i.png-65.6kB

测试读取K8S配置

接下去我们来到配置项来配置ConfigMap:
image_1dm8m52su1o111dod1edci5i6sg6c.png-181kB
这里配置项的名称需要和配置文件中的对应起来,也就是k8sdemo。然后配置项的Key需要和代码中的对应:
image_1dm8m7jjbm0o166c11v41pg0fug6p.png-35.6kB

我们来看看应用的日志:

2019-10-03 11:30:33.442  INFO 1 --- [pool-1-thread-1] m.j.s.Springcloudk8sdemoApplication      : config:TestConfig(message=8888, serviceName=k8sdemo-svc)

的确正确获取到了配置,我们修改下配置项bean.message为9999,随后再来看看日志:
image_1dm8md75p151ei939ud10l31fns7j.png-346.5kB
可以看到程序发现了配置的变更,刷新了上下文,然后获取到了最新的配置。

测试通过K8S服务发现进行服务调用:

访问client接口可以看到1.13正常从0.137获取到了数据:
image_1dm8mfnon1nprljq1gel1pdt1o7n80.png-25.5kB
多刷新几次:
image_1dm8mhs2r1r9l1lfj1q0p4g8bqb8d.png-25.1kB

我们访问到应用的负载均衡是由Ingress实现的,应用访问服务端的负载均衡是由Ribbon实现的。

查看JVM内存情况

还记得吗,我们在创建应用的时候给的内存是1.4GB,然后我们设置了JVM使用50%的内存(初始和最大都是50%),现在我们来看看是不是这样。

首先来看看pod的情况:

image_1dm8mm02iuqj1pom1due1l441odm8q.png-72.3kB

然后执行如下命令在Pod内运行jinfo

kubectl exec k8sdemo-7b44d9fbff-c4jkf -- jinfo 1

可以看到如下结果,初始和最大堆是700M左右,说明参数起作用了:
image_1dm8mpup4nb91van1c2bse12nl97.png-290.1kB

小结

本文我们简单展示了一下Spring Cloud Kubernetes的使用,以及如何通过阿里云的K8S集群来部署我们的微服务,我们看到:

  • 如何通过SCK来读取ConfigMap的配置,支持动态刷新
  • 如何通过SCK来使用K8S的服务发现进行服务调用
  • JVM内存参数设置问题
  • 如何把镜像推到阿里云并且在阿里云的K8S跑起来我们的镜像

有关K8S和基于Spring Boot/Spring Cloud的微服务结合使用,有几点需要注意:

  • Spring Cloud 有自己的服务注册中心,比如Eureka。如果你希望统一使用K8S做服务发现,那么可以使用Spring Cloud Kubernetes。如果你希望使用Eureka作为服务发现,那么服务之间调用都建议通过Feign或Ribbon调用,而不是使用K8S的Service域名或Ingress调用,两套服务发现体系混用的话比较混乱而且有协同性问题。
  • 대신 응용 프로그램의 VM 배포 K8S에서 가장 중요한 차이점은 재조정에 포드 대상이 특정 프레임 워크를 들어, XXL 작업이 될 수 이와 같은 상태 기반 IP 응용 프로그램을 의존하기 때문에 IP 서비스가 고정 된 것으로 간주되지 않는 것입니다 문제와 개혁이 필요합니다.
  • 다양한 로그 수집 및 보존 문제를 고려 포드 서로 다른 라이프 사이클 및 VM 및 OOM 덤프.
  • + UseContainerSupport -XX : MaxRAMPercentage = 50.0 -XX : InitialRAMPercentage 이유는, 자원 및 기타 문제의 부족, 재시작 문제 K8S는 응용 프로그램이 합리적인 세트 reques의 적용과 한계 구성 및 JVM 매개 변수 (예 : -XX를 관찰 할 필요가 배포, 응용 프로그램을 다시 시작하지 상태 모니터링을 고려 = 50.0 -XX : MinRAMPercentage = 50.0)이, 상태 모니터링 구성은 합리적인 검토합니다.

추천

출처www.cnblogs.com/lovecindywang/p/11620544.html