> For the complete documentation index, see [llms.txt](https://bohans.gitbook.io/devops/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bohans.gitbook.io/devops/kubernetes/group-1/yu-dao-de-yi-xie-wen-ti/java-web-ying-yong-+-zi-yuan-xian-zhi.md).

# Java Web应用+资源限制

### <mark style="color:purple;">**问题描述**</mark>

构建了一个简单的使用springboot的web应用，应用使用redis作为数据库，意图测试同一个pod中的容器可以使用localhost进行通讯。

但使用过程中，总是会出现莫名奇妙的失败，Pod先进入running状态，之后崩掉。

<details>

<summary><mark style="color:orange;">出现问题的yaml文件</mark></summary>

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: hello
  labels:
    app: helloworld
spec:
  imagePullSecrets:
  - name: my-docker-secret
  containers:
  - name: redis
    image: redis:7.0.12
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: 6379
  - name: web
    image: registry.cn-hangzhou.aliyuncs.com/bohan838/web-redis:1.0
    env:
      - name: spring.redis.host
        value: localhost
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: 8890
    livenessProbe:
      tcpSocket:
        port: 8890
      initialDelaySeconds: 30
      timeoutSeconds: 1
  restartPolicy: Always
```

</details>

```properties
# kubectl get pod hello
NAME    READY   STATUS             RESTARTS      AGE
hello   1/2     CrashLoopBackOff   4 (23s ago)   4m5s
```

### <mark style="color:purple;">**问题解决过程**</mark>

上述问题最大的困难在于无法确定问题原因，因此首先需要定位问题发生地点，因此先需要确定究竟是web应用还是redis的责任。根据READY一列的显示，可以得出两个容器中有一个挂掉了，首先需要**确定是哪一个挂掉了**：

```properties
# kubectl exec -it hello -c redis -- ls /
bin   data  etc   lib	 lib64	 media	opt   root  sbin  sys  usr
boot  dev   home  lib32  libx32  mnt	proc  run   srv   tmp  var

# kubectl exec -it hello -c web -- ls /
error: unable to upgrade connection: container not found ("web")
```

可见，挂掉的是web服务。因此**查看web容器的日志信息**：

<details>

<summary>kubectl logs hello -c web</summary>

{% code overflow="wrap" %}

```log
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v2.7.17)

2023-11-30 07:39:41.808  INFO 1 --- [           main] c.e.helloworld.HelloWorldApplication     : Starting HelloWorldApplication v0.0.1-SNAPSHOT using Java 11.0.13 on hello with PID 1 (/app.jar started by root in /)
2023-11-30 07:39:41.813  INFO 1 --- [           main] c.e.helloworld.HelloWorldApplication     : No active profile set, falling back to 1 default profile: "default"
2023-11-30 07:39:48.400  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
2023-11-30 07:39:48.404  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2023-11-30 07:39:48.512  INFO 1 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 85 ms. Found 0 Redis repository interfaces.
2023-11-30 07:39:52.009  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8890 (http)
2023-11-30 07:39:52.024  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-11-30 07:39:52.025  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.82]
2023-11-30 07:39:52.609  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-30 07:39:52.609  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 10390 ms
```

{% endcode %}

</details>

**未见到任何错误信息！！（这便是最困难的点）**

虽然未见错误信息，但根据本地的代码测试，怀疑是因为web应用依赖于redis，而web启动比redis要快，因此导致环境准备未完成，所以错误（但在本地测试的情况是，这并不会导致服务宕机，并且具有明确的异常信息，但怀疑异常信息进入了标准错误流中因此不可见，所以最终还是沿着这个方向进行）。为了验证是否是因此而导致的宕机，采取了两种方案：

* 初始化容器：将redis作为web容器的init container，在这种情况下，因为redis是一个前台执行的应用，最终导致init过程无法结束，web容器无法启动（无效方案）
* 将redis作为service提前启动（将redis作为独立的pod，并用一个service使其可以被k8s集群内的容器使用）

**使用上述方案后，问题依然存在！！**

最后，只能怀疑是否是镜像出现了问题，因此使用docker运行该镜像，发现容器能够正常运行，因此排除镜像的问题。为了排除是镜像仓库的问题，在docker上测试的镜像是直接从镜像仓库中获取的。

整个尝试到最后，能够确认的便是：

1. 问题在于java web应用
2. docker上能够正常使用，原因在于k8s

### <mark style="color:purple;">**解决方案**</mark>

最后求助于网络，然后浏览到了oom相关的异常，因此怀疑可能是资源限定的问题，因此最后<mark style="color:blue;">**去掉了web容器的资源限制，问题果然得到了解决！**</mark>

<details>

<summary><mark style="color:orange;">去除资源限制后的yaml</mark></summary>

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: hello
  labels:
    app: helloworld
spec:
  imagePullSecrets:
  - name: my-docker-secret
  containers:
  - name: redis
    image: redis:7.0.12
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: 6379
  - name: web
    image: registry.cn-hangzhou.aliyuncs.com/bohan838/web-redis:1.0
    env:
      - name: spring.redis.host
        value: localhost
    ports:
      - containerPort: 8890
    livenessProbe:
      tcpSocket:
        port: 8890
      initialDelaySeconds: 30
      timeoutSeconds: 1
  restartPolicy: Always
```

</details>

<pre class="language-properties"><code class="lang-properties"><strong># kubectl exec hello -c web -- java -version
</strong>openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment 18.9 (build 11.0.13+8)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.13+8, mixed mode, sharing)
</code></pre>

{% content-ref url="/spaces/pYHRX8DEEQK5j0XpL9Sz/pages/XzhYQdAY9CjnTNT6p2Gy" %}
[Broken mention](broken://spaces/pYHRX8DEEQK5j0XpL9Sz/pages/XzhYQdAY9CjnTNT6p2Gy)
{% endcontent-ref %}
