Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
91d9caf
Update Docker.md
CyC2018 Oct 31, 2026
5840c9c
Update Git.md
CyC2018 Oct 31, 2026
c159b92
Update HTTP.md
CyC2018 Oct 31, 2026
cdee1f2
Update Java IO.md
CyC2018 Oct 31, 2026
2fa8567
Update Java 基础.md
CyC2018 Oct 31, 2026
f5de46f
Update Java 容器.md
CyC2018 Oct 31, 2026
86d6c0e
Update Java 并发.md
CyC2018 Oct 31, 2026
f1611b6
Update Java 虚拟机.md
CyC2018 Oct 31, 2026
02aa880
Update Leetcode 题解 - 动态规划.md
CyC2018 Oct 31, 2026
5b0b1d2
Update Leetcode 题解 - 树.md
CyC2018 Oct 31, 2026
e1765ae
Update Leetcode 题解 - 双指针.md
CyC2018 Oct 31, 2026
7ddf0b9
Update Leetcode 题解 - 搜索.md
CyC2018 Oct 31, 2026
7a0bd0f
Update Leetcode 题解 - 数组与矩阵.md
CyC2018 Oct 31, 2026
90398b6
Update Leetcode 题解 - 栈和队列.md
CyC2018 Oct 31, 2026
3b01c68
Update Leetcode 题解 - 贪心思想.md
CyC2018 Oct 31, 2026
6c30963
Update Leetcode 题解 - 链表.md
CyC2018 Oct 31, 2026
bcaf348
Update Leetcode 题解 - 二分查找.md
CyC2018 Oct 31, 2026
cec7665
Update Leetcode 题解 - 位运算.md
CyC2018 Oct 31, 2026
42416c0
Update Leetcode 题解 - 分治.md
CyC2018 Oct 31, 2026
e000648
Update Leetcode 题解 - 哈希表.md
CyC2018 Oct 31, 2026
96a9afa
Update Leetcode 题解 - 图.md
CyC2018 Oct 31, 2026
6a87af1
Update Leetcode 题解 - 字符串.md
CyC2018 Oct 31, 2026
c35866a
Update Leetcode 题解 - 排序.md
CyC2018 Oct 31, 2026
8c66665
Update Leetcode 题解 - 数学.md
CyC2018 Oct 31, 2026
e1399e6
Update Linux.md
CyC2018 Oct 31, 2026
0cef132
Update MySQL.md
CyC2018 Oct 31, 2026
efed1f2
Update Redis - 进阶.md
CyC2018 Oct 31, 2026
d1432d6
Update Redis.md
CyC2018 Oct 31, 2026
1b915cc
Update Spring.md
CyC2018 Oct 31, 2026
4e9608a
Update 分布式.md
CyC2018 Oct 31, 2026
27f47f9
Update 大模型应用.md
CyC2018 Oct 31, 2026
7d846c6
Update 学习路线 - Java 后端.md
CyC2018 Oct 31, 2026
6254d27
Update 学习路线 - 大模型应用开发.md
CyC2018 Oct 31, 2026
d8c84ec
Update 学习路线 - 零基础.md
CyC2018 Oct 31, 2026
899f00e
Update 学习路线 - 面试冲刺.md
CyC2018 Oct 31, 2026
044e540
Update 微服务.md
CyC2018 Oct 31, 2026
488219b
Update 消息队列.md
CyC2018 Oct 31, 2026
b931e07
Update 算法 - 排序.md
CyC2018 Oct 31, 2026
8b057da
Update 算法 - 符号表.md
CyC2018 Oct 31, 2026
ae93e5b
Update 系统设计基础.md
CyC2018 Oct 31, 2026
cda92ad
Update 缓存.md
CyC2018 Oct 31, 2026
df12883
Update 计算机操作系统 - 死锁.md
CyC2018 Oct 31, 2026
c9de953
Update 计算机网络 - 应用层.md
CyC2018 Oct 31, 2026
42f623d
Update 计算机网络 - 目录.md
CyC2018 Oct 31, 2026
86d92e1
Update 设计模式 - 单例.md
CyC2018 Oct 31, 2026
75b965c
Update 集群.md
CyC2018 Oct 31, 2026
036b27e
Update 设计模式 - 适配器.md
CyC2018 Oct 31, 2026
88eb263
Update Socket.md
CyC2018 Oct 31, 2026
c86215d
Update 计算机操作系统 - 进程管理.md
CyC2018 Oct 31, 2026
4b0852f
Update 计算机网络 - 传输层.md
CyC2018 Oct 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions notes/Docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,14 @@ readinessProbe 是就绪探针:Pod 启动后要通过检查才会加入 Servic

### Pod 的创建过程

K8s 的各组件不直接互相调用,而是都通过 API Server 协作:每个组件监听(watch)自己关心的对象,发现实际状态与期望不一致就采取行动,再把结果写回 API Server。以订单服务中被调度到节点 d1-agent 的一个 Pod 为例:
K8s 的各组件不直接互相调用,而是都通过 API Server 协作:每个组件监听(watch)自己关心的对象,发现实际状态与期望不一致就采取行动,再把结果写回 API Server。以订单服务中被调度到节点 k3s-agent 的一个 Pod 为例:

<div align="center"> <img src="pics/k8s-pod-create.png" width="860px"/> </div><br>

1. kubectl 把 Deployment 发给 API Server,API Server 完成认证、鉴权和准入检查后写入 etcd;
2. 控制器管理器中的 Deployment 控制器发现新的 Deployment,创建 ReplicaSet;ReplicaSet 控制器发现副本数不足,创建 3 个 Pod 对象,这时的 Pod 还没有指定节点;
3. 调度器发现未调度的 Pod,先过滤掉不满足条件的节点(资源不足、有不能容忍的污点等),再给剩下的节点打分,选出 d1-agent 写入 Pod 的 nodeName;
4. d1-agent 上的 kubelet 发现分配给自己的 Pod,通过容器运行时接口(Container Runtime Interface, CRI)让 containerd 创建 Pod 沙箱:先启动一个 pause 容器持有网络命名空间,再调用 CNI 插件为它配置网卡、分配 IP 10.42.1.5;Pod 声明了存储卷时,还会通过 CSI 插件把卷挂载到节点上;
3. 调度器发现未调度的 Pod,先过滤掉不满足条件的节点(资源不足、有不能容忍的污点等),再给剩下的节点打分,选出 k3s-agent 写入 Pod 的 nodeName;
4. k3s-agent 上的 kubelet 发现分配给自己的 Pod,通过容器运行时接口(Container Runtime Interface, CRI)让 containerd 创建 Pod 沙箱:先启动一个 pause 容器持有网络命名空间,再调用 CNI 插件为它配置网卡、分配 IP 10.42.1.5;Pod 声明了存储卷时,还会通过 CSI 插件把卷挂载到节点上;
5. kubelet 拉取镜像(这里镜像已在节点上),创建并启动容器;
6. kubelet 执行探针,就绪探针通过后把 Pod 的状态更新为 Ready;
7. EndpointSlice 控制器把 10.42.1.5:8080 加入 order-service 的后端,各节点的 kube-proxy 随之更新转发规则。
Expand Down Expand Up @@ -389,21 +389,21 @@ Ingress 只是规则,真正处理请求的是 Ingress 控制器,例如 Traef

需要注意的是,Ingress 控制器通常不经过 Service 的虚拟 IP,而是从 EndpointSlice 取得 Pod 的地址后直接转发给 Pod(Traefik 的默认行为),Service 在这里只用来找到后端。Ingress API 已经冻结,不再增加新功能,新功能加在它的后继 Gateway API 中。

Pod 之间的通信由 CNI 插件实现。K8s 的网络模型要求每个 Pod 有集群内唯一的 IP,任意两个 Pod 不经过 NAT 就能直接通信。k3s 默认的 Flannel 给每个节点分配一个网段(实验中 d1-server 上的 Pod 是 10.42.0.x,d1-agent 上的是 10.42.1.x),跨节点的包用 VXLAN 封装后经节点之间的网络发送。
Pod 之间的通信由 CNI 插件实现。K8s 的网络模型要求每个 Pod 有集群内唯一的 IP,任意两个 Pod 不经过 NAT 就能直接通信。k3s 默认的 Flannel 给每个节点分配一个网段(实验中 k3s-server 上的 Pod 是 10.42.0.x,k3s-agent 上的是 10.42.1.x),跨节点的包用 VXLAN 封装后经节点之间的网络发送。

### Pod 异常状态的排查

Pod 的阶段(phase)只有 Pending、Running、Succeeded、Failed、Unknown 五种,kubectl get pods 的 STATUS 一栏显示得更细。常见的异常状态(k3s 实测,见[附录 A8](#a8-pod-的异常状态)):

- Pending:Pod 还没有调度到节点上。describe 的事件中有 FailedScheduling 时是调度失败,例如申请 20 个 CPU 时为 0/2 nodes are available: 2 Insufficient cpu;两个节点都有污点 dedicated=db:NoSchedule、Pod 没有对应的容忍时为 2 node(s) had untolerated taint;Pod 使用的 PVC 没有绑定到存储卷时也会停在这里;
- Pending:Pod 已被集群接受,但还有容器没有创建并运行起来,包括等待调度和拉取镜像的时间。describe 的事件中有 FailedScheduling 时是调度失败,例如申请 20 个 CPU 时为 0/2 nodes are available: 2 Insufficient cpu;两个节点都有污点 dedicated=db:NoSchedule、Pod 没有对应的容忍时为 2 node(s) had untolerated taint;Pod 使用的 PVC 没有绑定到存储卷时也会停在这里;
- ImagePullBackOff:拉取镜像失败,常见原因是镜像名或标签写错、私有仓库没有配置凭证(imagePullSecrets)、节点访问不了镜像仓库,kubelet 在 ErrImagePull 和 ImagePullBackOff 之间反复重试;
- CrashLoopBackOff:容器启动后反复退出,kubelet 每次重启前的等待时间按 10 秒、20 秒、40 秒翻倍,最长 5 分钟。kubectl logs --previous 查看上一次退出前的日志,例如把 server.port 写成 abc 时,日志中是 APPLICATION FAILED TO START 和具体的配置错误,退出码 1;
- OOMKilled:容器超过内存上限被内核杀掉,退出码 137,之后同样进入 CrashLoopBackOff。例如内存上限 256 MiB,JVM 堆却设为 300 MB 并在启动时全部占用,Java 应用的堆和堆外内存加起来要小于 limits;
- Running 但 READY 为 0/1:进程在运行,但就绪探针不通过,Pod 不会收到 Service 转发的请求,例如探针路径写成不存在的 /ready 时,事件中是 Readiness probe failed: HTTP probe failed with statuscode: 404。

排查的顺序通常是:kubectl get pods -o wide 看状态、重启次数和所在节点;kubectl describe pod 看事件;kubectl logs 看应用日志,容器重启过的加 --previous;kubectl exec 进入容器检查配置和网络;kubectl top pod 看资源占用(需要 metrics-server)。

节点 NotReady 指控制平面一段时间没有收到节点上 kubelet 的心跳,这个时间由 node-monitor-grace-period 决定(v1.31 默认 40 秒,v1.32 起 50 秒)。停掉工作节点 d1-agent 后 32 秒,它变为 NotReady(kubelet 约每 10 秒续约一次心跳,宽限期从最后一次心跳算起,所以比 40 秒短),Conditions 中是 Kubelet stopped posting node status,并被加上 node.kubernetes.io/unreachable 污点;上面的 Pod 同时被标记为未就绪,从 Service 的后端中摘除。Pod 默认容忍这个污点 300 秒,又过了约 5 分钟才被驱逐,Deployment 在 d1-server 上补足了副本(见[附录 A9](#a9-节点-notready))。
节点 NotReady 指控制平面一段时间没有收到节点上 kubelet 的心跳,这个时间由 node-monitor-grace-period 决定(v1.31 默认 40 秒,v1.32 起 50 秒)。停掉工作节点 k3s-agent 后 32 秒,它变为 NotReady(kubelet 约每 10 秒续约一次心跳,宽限期从最后一次心跳算起,所以比 40 秒短),Conditions 中是 Kubelet stopped posting node status,并被加上 node.kubernetes.io/unreachable 污点;上面的 Pod 同时被标记为未就绪,从 Service 的后端中摘除。Pod 默认容忍这个污点 300 秒,又过了约 5 分钟才被驱逐,Deployment 在 k3s-server 上补足了副本(见[附录 A9](#a9-节点-notready))。

排查 NotReady 时先用 kubectl describe node 看 Conditions:

Expand Down Expand Up @@ -601,16 +601,16 @@ $ docker inspect -f '{{.Name}} started {{.State.StartedAt}}' shop-mysql-1 shop-o

### A5 部署、自愈与滚动升级

两个节点的 k3s v1.31.4:server 节点 d1-server(控制平面兼工作节点)和 agent 节点 d1-agent 各运行在一个 Docker 特权容器中,容器内不能再用 OverlayFS,containerd 使用 native 快照(--snapshotter native)。订单服务的 1.0、1.1 两个镜像用 docker save 导出后导入两个节点的 containerd。
两个节点的 k3s v1.31.4:server 节点 k3s-server(控制平面兼工作节点)和 agent 节点 k3s-agent 各运行在一个 Docker 特权容器中,容器内不能再用 OverlayFS,containerd 使用 native 快照(--snapshotter native)。订单服务的 1.0、1.1 两个镜像用 docker save 导出后导入两个节点的 containerd。

```text
$ kubectl apply -f order.yaml
all ready after 21.1 s
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
order-service-5ccc589fd8-b76g2 1/1 Running 0 20s 10.42.1.5 d1-agent
order-service-5ccc589fd8-vb2lx 1/1 Running 0 20s 10.42.1.4 d1-agent
order-service-5ccc589fd8-vz9hj 1/1 Running 0 20s 10.42.0.8 d1-server
order-service-5ccc589fd8-b76g2 1/1 Running 0 20s 10.42.1.5 k3s-agent
order-service-5ccc589fd8-vb2lx 1/1 Running 0 20s 10.42.1.4 k3s-agent
order-service-5ccc589fd8-vz9hj 1/1 Running 0 20s 10.42.0.8 k3s-server
$ kubectl get svc order-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
order-service ClusterIP 10.43.210.38 <none> 80/TCP 21s
Expand All @@ -628,7 +628,7 @@ $ kubectl delete pod/order-service-5ccc589fd8-b76g2
new Pod object created after 0.34 s
3/3 ready again after 11.2 s
NAME READY STATUS RESTARTS AGE IP NODE
order-service-5ccc589fd8-494s9 1/1 Running 0 11s 10.42.0.9 d1-server
order-service-5ccc589fd8-494s9 1/1 Running 0 11s 10.42.0.9 k3s-server
...
NAME ADDRESSTYPE PORTS ENDPOINTS
order-service-m2pjv IPv4 8080 10.42.1.4,10.42.0.8,10.42.0.9
Expand All @@ -651,7 +651,7 @@ $ kubectl get events(Deployment 与 ReplicaSet 的事件,节选)
2026-10-28T10:21:40Z ReplicaSet SuccessfulCreate replicaset-controller Created pod: order-service-5ccc589fd8-b76g2
$ kubectl get events --field-selector involvedObject.name=order-service-5ccc589fd8-b76g2
TIME REASON FROM MESSAGE
<nil> Scheduled <none> Successfully assigned default/order-service-5ccc589fd8-b76g2 to d1-agent
<nil> Scheduled <none> Successfully assigned default/order-service-5ccc589fd8-b76g2 to k3s-agent
2026-10-28T10:21:40Z Pulled kubelet Container image "order-service:1.0" already present on machine
2026-10-28T10:21:51Z Created kubelet Created container app
2026-10-28T10:21:51Z Started kubelet Started container app
Expand Down Expand Up @@ -687,7 +687,7 @@ mnt mnt:[4026534203] mnt mnt:[4026534206]

### A7 Service 与 Ingress

在 d1-agent 上查看 kube-proxy 写入的规则(节选):
在 k3s-agent 上查看 kube-proxy 写入的规则(节选):

```text
$ iptables-save -t nat | grep default/order-service
Expand All @@ -698,7 +698,7 @@ $ iptables-save -t nat | grep default/order-service
-A KUBE-SEP-CRY6GKLRKVOMXZX4 -p tcp -m comment --comment "default/order-service" -m tcp -j DNAT --to-destination 10.42.0.8:8080
```

正文中的 Ingress,k3s 自带的 Traefik 2.11 处理,在 d1-server 上访问节点 IP 的 80 端口:
正文中的 Ingress,k3s 自带的 Traefik 2.11 处理,在 k3s-server 上访问节点 IP 的 80 端口:

```text
$ kubectl get ingress shop
Expand All @@ -718,7 +718,7 @@ $ wget --header "Host: other.example.com" http://172.19.0.2/orders/1024
$ kubectl patch svc order-service -p '{"spec":{"type":"NodePort"}}'
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
order-service NodePort 10.43.210.38 <none> 80:31887/TCP 103s
$ wget -qO- http://172.19.0.3:31887/orders/1024 (在 d1-server 上访问 d1-agent 的 NodePort)
$ wget -qO- http://172.19.0.3:31887/orders/1024 (在 k3s-server 上访问 k3s-agent 的 NodePort)
{"status":"SHIPPED","id":1024,"host":"order-service-5ccc589fd8-b76g2"}
```

Expand Down Expand Up @@ -770,39 +770,39 @@ Failed to convert to type java.lang.Integer
oom-demo 在第一次被杀之前 kubectl get pods 显示的状态是 OOMKilled。给两个节点都加上污点后创建 Pod:

```text
$ kubectl taint nodes d1-server d1-agent dedicated=db:NoSchedule
$ kubectl taint nodes k3s-server k3s-agent dedicated=db:NoSchedule
$ kubectl run -n lab taint-demo --image=order-service:1.0
Warning FailedScheduling 5s default-scheduler 0/2 nodes are available: 2 node(s) had untolerated taint {dedicated: db}. ...
$ kubectl taint nodes d1-server d1-agent dedicated=db:NoSchedule-
(8 秒后 taint-demo 在 d1-server 上 Running)
$ kubectl taint nodes k3s-server k3s-agent dedicated=db:NoSchedule-
(8 秒后 taint-demo 在 k3s-server 上 Running)
```

### A9 节点 NotReady

用 docker stop 停掉 d1-agent 所在的容器,相当于节点宕机:
用 docker stop 停掉 k3s-agent 所在的容器,相当于节点宕机:

```text
10:28:55 $ docker stop d1-k3s-agent
10:29:28 d1-agent NotReady after 32 s
10:28:55 $ docker stop k3s-agent
10:29:28 k3s-agent NotReady after 32 s
Type Status LastTransitionTime Reason Message
MemoryPressure Unknown Wed, 28 Oct 2026 18:29:27 +0800 NodeStatusUnknown Kubelet stopped posting node status.
DiskPressure Unknown Wed, 28 Oct 2026 18:29:27 +0800 NodeStatusUnknown Kubelet stopped posting node status.
PIDPressure Unknown Wed, 28 Oct 2026 18:29:27 +0800 NodeStatusUnknown Kubelet stopped posting node status.
Ready Unknown Wed, 28 Oct 2026 18:29:27 +0800 NodeStatusUnknown Kubelet stopped posting node status.
Taints: node.kubernetes.io/unreachable:NoSchedule
10:34:33 pods on d1-agent marked for deletion after 337 s
10:34:33 pods on k3s-agent marked for deletion after 337 s
NAME READY STATUS IP NODE
order-service-5ccc589fd8-24sqr 1/1 Terminating 10.42.1.8 d1-agent
order-service-5ccc589fd8-2f56l 1/1 Terminating 10.42.1.9 d1-agent
order-service-5ccc589fd8-2vrx4 1/1 Running 10.42.0.11 d1-server
order-service-5ccc589fd8-4gzps 1/1 Running 10.42.0.17 d1-server
order-service-5ccc589fd8-gzsbv 1/1 Running 10.42.0.16 d1-server
order-service-5ccc589fd8-24sqr 1/1 Terminating 10.42.1.8 k3s-agent
order-service-5ccc589fd8-2f56l 1/1 Terminating 10.42.1.9 k3s-agent
order-service-5ccc589fd8-2vrx4 1/1 Running 10.42.0.11 k3s-server
order-service-5ccc589fd8-4gzps 1/1 Running 10.42.0.17 k3s-server
order-service-5ccc589fd8-gzsbv 1/1 Running 10.42.0.16 k3s-server
$ kubectl get pod -o jsonpath='{.items[0].spec.tolerations}'
[{"effect":"NoExecute","key":"node.kubernetes.io/not-ready","operator":"Exists","tolerationSeconds":300},
{"effect":"NoExecute","key":"node.kubernetes.io/unreachable","operator":"Exists","tolerationSeconds":300}]
```

节点失联后,Pod 无法确认已经停止,一直显示 Terminating。恢复 d1-agent、重新部署后再停一次,每 4 秒查看 EndpointSlice 中各地址的 ready:
节点失联后,Pod 无法确认已经停止,一直显示 Terminating。恢复 k3s-agent、重新部署后再停一次,每 4 秒查看 EndpointSlice 中各地址的 ready:

```text
+33s node=Ready endpoints: 10.42.0.19=true 10.42.1.14=true 10.42.1.13=true
Expand Down
14 changes: 7 additions & 7 deletions notes/Git.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,30 +152,30 @@ target/
*.local.yml
```

需要注意的是,.gitignore 只对未跟踪的文件生效。已经提交过的文件即使后来写进 .gitignore,修改仍会出现在 git status 中,要先用 git rm --cached <file> 把它移出版本库(工作区的文件保留)。
需要注意的是,.gitignore 只对未跟踪的文件生效。已经提交过的文件即使后来写进 .gitignore,修改仍会出现在 git status 中,要先用 git rm --cached \<file> 把它移出版本库(工作区的文件保留)。

不需要全部自己编写,可以到 [https://github.com/github/gitignore](https://github.com/github/gitignore) 中进行查询。

## Git 命令一览

| 用途 | 命令 |
| --- | --- |
| 克隆仓库 | git clone <url> |
| 克隆仓库 | git clone \<url> |
| 查看状态 | git status |
| 加入暂存区 | git add <file> |
| 加入暂存区 | git add \<file> |
| 提交 | git commit -m "说明" |
| 查看历史 | git log --oneline --graph |
| 查看改动 | git diff(工作区与暂存区),git diff --staged(暂存区与最新提交) |
| 撤销工作区的修改 | git restore <file> |
| 撤销 git add | git restore --staged <file> |
| 撤销工作区的修改 | git restore \<file> |
| 撤销 git add | git restore --staged \<file> |
| 新建并切换分支 | git switch -c dev |
| 切换分支 | git switch master |
| 合并分支 | git merge dev |
| 变基 | git rebase master |
| 临时保存修改 | git stash,之后用 git stash pop 恢复 |
| 撤销最近一次提交,保留修改 | git reset --soft HEAD~1 |
| 回到某个提交,丢弃之后的修改 | git reset --hard <commit> |
| 用一个新提交抵消某次提交 | git revert <commit> |
| 回到某个提交,丢弃之后的修改 | git reset --hard \<commit> |
| 用一个新提交抵消某次提交 | git revert \<commit> |
| 下载远程分支的新提交,不合并 | git fetch |
| 拉取并合并远程分支 | git pull |
| 推送 | git push origin dev |
Expand Down
Loading