朱あなたがたは、あなたの春シリーズS1E11に話:クイズ春クラウドKubernetes @アリ雲K8Sを
春の雲Kubernates(以下SCKと表記)についてhttps://github.com/spring-cloud/spring-cloud-kubernetesを参照してください、この論文では、3つの主要な機能をテストしました:
- 春クラウドリボンは、サービスコールをしていると使用Kubernatesサービス検出
- ConfigMap設定Kubernatesを読み、動的にサポート修正後のリフレッシュ
- Kubernatesポッド情報の春ブーツアクチュエータ知覚
テスト手順を書きます
まず、我々はいくつかの点に注意してください、POMファイルを作成します。
- 春のブートバージョンが高すぎることはできません
- 春ブーツWebおよびアクチュエータ2つのモジュールを導入して、我々はテストにWebプロジェクトを開発しました
- リボン春クラウドモジュールの導入は、我々はサービスコールをテストする必要があります
- 春・クラウド・スターター・kubernetes-すべての私たちの主な試験対象物に依存しての導入
- 私たちは鏡の構築を支援するための追加導入ドッキングウィンドウ-mavenの-プラグインプラグイン
- 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パラメータは、我々は環境変数から注入したいことは注目に値します。
コードを見て、我々は、第1の構成クラスを定義します。
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();
}
}
我々は2つのインタフェースを定義し、ここで見ることができます:
- サーバーは、すべてのサービスを見つけるために、サービスの発見のために返す(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}
我々は3つのことをやりました:
- アプリケーション名を定義します
- k8sdemoあるアプリケーション名、に指定された名前をConfigMap
- ConfigMapは、自動更新の設定を有効にする(下図を参照して、デフォルトのイベントは方法です)
そして、エンドポイントのアクチュエータの一部を開くためにbootstrap.yamlを定義します。
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true
https://github.com/JosephZhu1983/SpringCloudK8Sのためのソースコード全体を参照してください。
アリクラウドクラスター構成K8S
クラスタ私は購入プロセスを省略し、これらのオプションは、フック上にある、イングレスは、特に私たちの後、パブリックネットワーク上でテストする必要が覚えています。
ほぼ30秒、K8Sクラスタは、あなたは私がホストされたバージョンを買って見ることができますダウン、なしで可用性の高い日に従事していなかった最初から自分自身を構築したい、このこいつはK8Sのホストされているバージョンと呼ばれる3ノードを、K8S私たちは自分自身のアリクラウドで管理ノードを指示し、唯一、作業ノードを買うお金を節約し、心配する必要があります。
kubectlを介してクラスタにアクセスするためには、コンフィギュレーション・kubeconfigを覚えて買いました。
与えられた構成アリ雲の下に直接(例えば、あなたおそらくローカルクラスタなど)の構成の元のコピーでカバー落下しないことを、直接、最終文書に貼り付けていない、ファイル形式があることに注意してください、あなたはクラスタ化する必要がある、コンテキストと3つのユーザー設定は、対応する場所に複製されます。
ミラーの構築
私たちは、K8S仮想マシンの展開とは異なり、配信は唯一の鏡である、ということを知っているので、我々はアリクラウドに画像をアップロードする必要があります。
まず、ローカルミラーを構築します:
mvn package docker:build -DskipTests
ビューミラーを完了した後:
そして、アリのクラウドサービスは、独自の倉庫を作成し、ミラーリング開始しました:
ミラータグの後鏡に記載の内部、リポジトリへのプッシュ。
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
ミラー、ミラーを表示するために倉庫の完了後:
アプリケーションのデプロイ
ミラーリングによってステートレスなアプリケーションを作成します。
ときあなたは、以下のメモを作成します:
- 右ミラーとタグを選択します
- 私は、アプリケーション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)、元数据区等,而且容器本身也有开销。
我这里展示的是编辑界面,创建界面略有不同但是类似:
创建应用的时候你可以把Service和Ingress一并创建。
完成后可以进入应用详情看到2个节点状态都是运行中:
测试应用启动情况
来到Ingress界面可以看到我们的公网Ingress记录,可以直接点击访问:
根节点输出的是IP,在之前的截图中我们可以看到服务运行在1.13和0.137两个IP上:
多刷新几次浏览器可以看到负载均衡的效果。
访问services可以查看到所有K8S的服务:
访问actuator/info可以看到有关K8S的详情(感谢SCK),显然我们代码里获取到的IIP是PodIP:
测试读取K8S配置
接下去我们来到配置项来配置ConfigMap:
这里配置项的名称需要和配置文件中的对应起来,也就是k8sdemo。然后配置项的Key需要和代码中的对应:
我们来看看应用的日志:
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,随后再来看看日志:
可以看到程序发现了配置的变更,刷新了上下文,然后获取到了最新的配置。
测试通过K8S服务发现进行服务调用:
访问client接口可以看到1.13正常从0.137获取到了数据:
多刷新几次:
我们访问到应用的负载均衡是由Ingress实现的,应用访问服务端的负载均衡是由Ribbon实现的。
查看JVM内存情况
还记得吗,我们在创建应用的时候给的内存是1.4GB,然后我们设置了JVM使用50%的内存(初始和最大都是50%),现在我们来看看是不是这样。
首先来看看pod的情况:
然后执行如下命令在Pod内运行jinfo
kubectl exec k8sdemo-7b44d9fbff-c4jkf -- jinfo 1
可以看到如下结果,初始和最大堆是700M左右,说明参数起作用了:
小结
本文我们简单展示了一下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)、ヘルスモニタリングの設定を確認するには、合理的です。