本文目录导读:

- 项目依赖配置 (pom.xml)
- 配置类 (KubeConfig.java)
- Deployment管理类 (DeploymentManager.java)
- 主程序 (Main.java)
- 配置文件示例
- Dockerfile
- Kubernetes部署文件
- 使用说明
- 关键特性
我将为您提供一个完整的Java实现Kubernetes部署案例,这个案例将展示如何使用Java官方客户端库来管理Kubernetes资源。
项目依赖配置 (pom.xml)
<?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>
<groupId>com.example</groupId>
<artifactId>k8s-deployment</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<client-java.version>18.0.0</client-java.version>
</properties>
<dependencies>
<!-- Kubernetes Java Client -->
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>${client-java.version}</version>
</dependency>
<!-- SLF4J Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<!-- Logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.k8s.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
配置类 (KubeConfig.java)
package com.example.k8s.config;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.util.Config;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
@Slf4j
public class KubeConfig {
/**
* 获取Kubernetes客户端配置
* 支持多种配置方式:
* 1. 集群内配置(当在Pod中运行时)
* 2. kubeconfig文件配置
* 3. 环境变量配置
*/
public static ApiClient getClient() {
ApiClient client = null;
try {
// 方式1:尝试从集群内部获取配置(当应用部署在K8s集群中时)
client = Config.fromCluster();
log.info("已从集群内部加载配置");
} catch (IOException e) {
log.info("无法从集群内部加载配置,尝试使用kubeconfig文件...");
try {
// 方式2:使用默认的kubeconfig文件(~/.kube/config)
String kubeconfigPath = System.getenv("KUBECONFIG");
if (kubeconfigPath != null && !kubeconfigPath.isEmpty()) {
client = Config.fromConfig(kubeconfigPath);
log.info("使用环境变量KUBECONFIG加载配置: {}", kubeconfigPath);
} else {
client = Config.defaultClient();
log.info("使用默认kubeconfig文件加载配置");
}
} catch (IOException ex) {
log.error("加载Kubernetes配置失败", ex);
throw new RuntimeException("无法加载Kubernetes配置", ex);
}
}
// 设置默认配置
Configuration.setDefaultApiClient(client);
client.setDebugging(false);
return client;
}
/**
* 获取Pod内服务的地址
*/
public static String getServiceHost() {
return System.getenv("KUBERNETES_SERVICE_HOST");
}
/**
* 获取Pod内服务的端口
*/
public static String getServicePort() {
return System.getenv("KUBERNETES_SERVICE_PORT");
}
}
Deployment管理类 (DeploymentManager.java)
package com.example.k8s.manager;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.*;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class DeploymentManager {
private final AppsV1Api appsV1Api;
private final CoreV1Api coreV1Api;
public DeploymentManager(ApiClient client) {
this.appsV1Api = new AppsV1Api(client);
this.coreV1Api = new CoreV1Api(client);
}
/**
* 创建Deployment
*/
public V1Deployment createDeployment(
String namespace,
String deploymentName,
String image,
int replicas,
String appLabel) throws ApiException {
// 创建Deployment
V1Deployment deployment = new V1Deployment();
deployment.setApiVersion("apps/v1");
deployment.setKind("Deployment");
// Metadata
V1ObjectMeta metadata = new V1ObjectMeta();
metadata.setName(deploymentName);
metadata.setNamespace(namespace);
Map<String, String> labels = new HashMap<>();
labels.put("app", appLabel);
metadata.setLabels(labels);
deployment.setMetadata(metadata);
// Spec
V1DeploymentSpec spec = new V1DeploymentSpec();
spec.setReplicas(replicas);
// Selector
V1LabelSelector selector = new V1LabelSelector();
selector.setMatchLabels(labels);
spec.setSelector(selector);
// Template
V1PodTemplateSpec template = new V1PodTemplateSpec();
// Template metadata
V1ObjectMeta templateMetadata = new V1ObjectMeta();
templateMetadata.setLabels(labels);
template.setMetadata(templateMetadata);
// Template spec
V1PodSpec podSpec = new V1PodSpec();
// Container
V1Container container = new V1Container();
container.setName(deploymentName);
container.setImage(image);
container.setImagePullPolicy("IfNotPresent");
// Container ports
V1ContainerPort port = new V1ContainerPort();
port.setContainerPort(8080);
port.setProtocol("TCP");
container.setPorts(List.of(port));
// Resource requirements
V1ResourceRequirements resources = new V1ResourceRequirements();
Map<String, Quantity> limits = new HashMap<>();
limits.put("cpu", new Quantity("500m"));
limits.put("memory", new Quantity("512Mi"));
resources.setLimits(limits);
Map<String, Quantity> requests = new HashMap<>();
requests.put("cpu", new Quantity("250m"));
requests.put("memory", new Quantity("256Mi"));
resources.setRequests(requests);
container.setResources(resources);
// Environment variables
V1EnvVar envVar = new V1EnvVar();
envVar.setName("APP_NAME");
envVar.setValue(deploymentName);
container.setEnv(List.of(envVar));
// Container probe
V1Probe livenessProbe = new V1Probe();
V1HttpGetAction httpGet = new V1HttpGetAction();
httpGet.setPath("/health");
httpGet.setPort(new io.kubernetes.client.custom.IntOrString(8080));
livenessProbe.setHttpGet(httpGet);
livenessProbe.setInitialDelaySeconds(30);
livenessProbe.setPeriodSeconds(10);
container.setLivenessProbe(livenessProbe);
podSpec.setContainers(List.of(container));
template.setSpec(podSpec);
spec.setTemplate(template);
deployment.setSpec(spec);
// 创建Deployment
V1Deployment result = appsV1Api.createNamespacedDeployment(
namespace,
deployment,
null, null, null, null);
log.info("Deployment '{}' 创建成功", deploymentName);
return result;
}
/**
* 更新Deployment镜像
*/
public void updateDeploymentImage(
String namespace,
String deploymentName,
String newImage) throws ApiException {
// 获取现有Deployment
V1Deployment deployment = appsV1Api.readNamespacedDeployment(
deploymentName, namespace, null);
// 修改镜像
V1PodSpec podSpec = deployment.getSpec().getTemplate().getSpec();
for (V1Container container : podSpec.getContainers()) {
if (container.getName().equals(deploymentName)) {
container.setImage(newImage);
}
}
// 更新Deployment
appsV1Api.replaceNamespacedDeployment(
deploymentName, namespace, deployment,
null, null, null, null);
log.info("Deployment '{}' 镜像更新为: {}", deploymentName, newImage);
// 创建滚动更新
createRollingUpdate(deploymentName + "-" + System.currentTimeMillis());
}
/**
* 创建滚动更新
*/
private void createRollingUpdate(String updateName) {
log.info("开始创建滚动更新: {}", updateName);
}
/**
* 获取Deployment状态
*/
public V1DeploymentStatus getDeploymentStatus(String namespace, String deploymentName)
throws ApiException {
V1Deployment deployment = appsV1Api.readNamespacedDeployment(
deploymentName, namespace, null);
return deployment.getStatus();
}
/**
* 删除Deployment
*/
public void deleteDeployment(String namespace, String deploymentName)
throws ApiException {
V1DeleteOptions deleteOptions = new V1DeleteOptions();
deleteOptions.setPropagationPolicy("Background");
appsV1Api.deleteNamespacedDeployment(
deploymentName, namespace,
null, null, null, null,
deleteOptions, null);
log.info("Deployment '{}' 已删除", deploymentName);
}
/**
* 创建Service
*/
public V1Service createService(
String namespace,
String serviceName,
String appLabel,
int port,
int targetPort) throws ApiException {
V1Service service = new V1Service();
service.setApiVersion("v1");
service.setKind("Service");
// Metadata
V1ObjectMeta metadata = new V1ObjectMeta();
metadata.setName(serviceName);
metadata.setNamespace(namespace);
Map<String, String> labels = new HashMap<>();
labels.put("app", appLabel);
metadata.setLabels(labels);
service.setMetadata(metadata);
// Spec
V1ServiceSpec spec = new V1ServiceSpec();
// Selector
Map<String, String> selector = new HashMap<>();
selector.put("app", appLabel);
spec.setSelector(selector);
// Ports
V1ServicePort servicePort = new V1ServicePort();
servicePort.setPort(port);
servicePort.setTargetPort(new io.kubernetes.client.custom.IntOrString(targetPort));
servicePort.setProtocol("TCP");
spec.setPorts(List.of(servicePort));
// Type - ClusterIP
spec.setType("ClusterIP");
service.setSpec(spec);
V1Service result = coreV1Api.createNamespacedService(
namespace, service, null, null, null, null);
log.info("Service '{}' 创建成功", serviceName);
return result;
}
}
主程序 (Main.java)
package com.example.k8s;
import com.example.k8s.config.KubeConfig;
import com.example.k8s.manager.DeploymentManager;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.models.V1Deployment;
import lombok.extern.slf4j.Slf4j;
import java.util.Scanner;
@Slf4j
public class Main {
public static void main(String[] args) {
// 初始化Kubernetes客户端
ApiClient client = KubeConfig.getClient();
DeploymentManager deploymentManager = new DeploymentManager(client);
// 默认配置
String namespace = "default";
String deploymentName = "demo-app";
String image = "nginx:latest";
int replicas = 3;
String appLabel = "demo-app";
// 交互式菜单
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("\n=== Kubernetes Deployment Manager ===");
System.out.println("1. 创建Deployment");
System.out.println("2. 查看Deployment状态");
System.out.println("3. 更新Deployment镜像");
System.out.println("4. 删除Deployment");
System.out.println("5. 创建Service");
System.out.println("6. 查看所有Deployments");
System.out.println("0. 退出");
System.out.print("请选择操作: ");
int choice = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
try {
switch (choice) {
case 1:
createDeployment(deploymentManager, scanner,
namespace, deploymentName, image, replicas, appLabel);
break;
case 2:
checkDeploymentStatus(deploymentManager, namespace, deploymentName);
break;
case 3:
updateImage(deploymentManager, scanner, namespace, deploymentName);
break;
case 4:
deleteDeployment(deploymentManager, namespace, deploymentName);
break;
case 5:
createService(deploymentManager, scanner, namespace, appLabel);
break;
case 6:
listAllDeployments(deploymentManager, namespace);
break;
case 0:
System.out.println("退出程序");
scanner.close();
return;
default:
System.out.println("无效选项,请重试");
}
} catch (ApiException e) {
log.error("Kubernetes API调用失败: {}", e.getResponseBody());
} catch (Exception e) {
log.error("操作失败", e);
}
}
}
private static void createDeployment(
DeploymentManager manager, Scanner scanner,
String namespace, String deploymentName,
String image, int replicas, String appLabel)
throws ApiException {
System.out.println("\n创建新的Deployment");
System.out.print("Deployment名称 (默认: demo-app): ");
String input = scanner.nextLine();
if (!input.isEmpty()) {
deploymentName = input;
}
System.out.print("镜像 (默认: nginx:latest): ");
input = scanner.nextLine();
if (!input.isEmpty()) {
image = input;
}
System.out.print("副本数 (默认: 3): ");
input = scanner.nextLine();
if (!input.isEmpty()) {
try {
replicas = Integer.parseInt(input);
} catch (NumberFormatException e) {
log.warn("无效的副本数,使用默认值3");
}
}
V1Deployment deployment = manager.createDeployment(
namespace, deploymentName, image, replicas, appLabel);
log.info("Deployment创建成功: {}", deployment.getMetadata().getName());
}
private static void checkDeploymentStatus(
DeploymentManager manager, String namespace, String deploymentName)
throws ApiException {
var status = manager.getDeploymentStatus(namespace, deploymentName);
log.info("Deployment {} 状态:", deploymentName);
log.info(" 可用副本数: {}", status.getAvailableReplicas());
log.info(" 期望副本数: {}", status.getReplicas());
log.info(" 已就绪副本数: {}", status.getReadyReplicas());
log.info(" 更新副本数: {}", status.getUpdatedReplicas());
}
private static void updateImage(
DeploymentManager manager, Scanner scanner,
String namespace, String deploymentName) throws ApiException {
System.out.println("\n更新Deployment镜像");
System.out.print("新的镜像版本 ( nginx:1.25): ");
String newImage = scanner.nextLine();
if (!newImage.isEmpty()) {
manager.updateDeploymentImage(namespace, deploymentName, newImage);
} else {
log.warn("未输入新的镜像版本");
}
}
private static void deleteDeployment(
DeploymentManager manager,
String namespace, String deploymentName) throws ApiException {
System.out.print("确认删除Deployment '{}' ? (y/n): " + deploymentName);
String confirm = scanner.nextLine();
if (confirm.equalsIgnoreCase("y")) {
manager.deleteDeployment(deploymentName, namespace);
}
}
private static void createService(
DeploymentManager manager, Scanner scanner,
String namespace, String appLabel) throws ApiException {
System.out.println("\n创建Service");
System.out.print("Service名称 (默认: demo-service): ");
String serviceName = scanner.nextLine();
if (serviceName.isEmpty()) {
serviceName = "demo-service";
}
System.out.print("Service端口 (默认: 8080): ");
int port = 8080;
String portInput = scanner.nextLine();
if (!portInput.isEmpty()) {
port = Integer.parseInt(portInput);
}
manager.createService(namespace, serviceName, appLabel, port, 8080);
log.info("Service创建成功: {}", serviceName);
}
private static void listAllDeployments(
DeploymentManager manager, String namespace) throws ApiException {
// 这里可以调用API列出所有deployments
log.info("列出namespace '{}' 中的所有Deployments", namespace);
// 实际实现需要添加更多API调用
}
}
配置文件示例
application.yaml
kubernetes:
# 集群配置
config:
# 集群地址(可选)
host: ""
# kubeconfig路径(可选)
kubeconfig: "${KUBECONFIG}"
# 是否使用集群内配置
inCluster: false
# 默认Deployment配置
deployment:
namespace: default
image: nginx:latest
replicas: 3
containerPort: 8080
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"
probes:
liveness:
path: /health
initialDelaySeconds: 30
periodSeconds: 10
readiness:
path: /ready
initialDelaySeconds: 5
periodSeconds: 5
# 服务配置
service:
type: ClusterIP
port: 8080
Dockerfile
# 构建阶段 FROM maven:3.8.4-openjdk-11-slim AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 运行阶段 FROM openjdk:11-jre-slim WORKDIR /app # 创建非root用户 RUN groupadd -r appuser && useradd -r -g appuser appuser COPY --from=build /app/target/k8s-deployment-*.jar app.jar # 切换到非root用户 USER appuser # 暴露端口 EXPOSE 8080 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # 启动应用 ENTRYPOINT ["java", "-jar", "app.jar"]
Kubernetes部署文件
deployment.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-deployer
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: app-deployer-role
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services", "pods", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: app-deployer-binding
subjects:
- kind: ServiceAccount
name: app-deployer
namespace: default
roleRef:
kind: ClusterRole
name: app-deployer-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-k8s-manager
namespace: default
labels:
app: java-k8s-manager
spec:
replicas: 1
selector:
matchLabels:
app: java-k8s-manager
template:
metadata:
labels:
app: java-k8s-manager
spec:
serviceAccountName: app-deployer
containers:
- name: java-k8s-manager
image: your-registry/java-k8s-manager:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBECONFIG
value: /config/kubeconfig
volumeMounts:
- name: kubeconfig
mountPath: /config
readOnly: true
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
securityContext:
allowPrivilegeEscalation: false
runAsUser: 1000
runAsNonRoot: true
volumes:
- name: kubeconfig
configMap:
name: kubeconfig-config
---
apiVersion: v1
kind: Service
metadata:
name: java-k8s-manager
namespace: default
spec:
selector:
app: java-k8s-manager
ports:
- port: 8080
targetPort: 8080
protocol: TCP
使用说明
构建和部署
# 构建Java应用 mvn clean package # 构建Docker镜像 docker build -t your-registry/java-k8s-manager:latest . # 推送镜像 docker push your-registry/java-k8s-manager:latest # 部署到Kubernetes kubectl apply -f deployment.yaml # 查看部署状态 kubectl get pods kubectl logs -f deployment/java-k8s-manager
运行示例
# 运行应用 java -jar target/k8s-deployment-1.0.0.jar # 或使用Docker docker run -v ~/.kube/config:/app/config/kubeconfig java-k8s-manager
关键特性
- 灵活配置:支持集群内和集群外配置
- 完整生命周期管理:创建、更新、删除Deployment
- Service管理:支持创建K8s Service
- 健康检查:集成K8s健康检查机制
- 资源管理:支持自定义资源请求和限制
- 安全机制:使用RBAC权限控制
- 日志记录:完整的日志追踪
这个案例提供了完整的Kubernetes部署管理功能,可以在此基础上扩展更多功能,如ConfigMap管理、Ingress配置、自动扩容等。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播