<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ray]]></title><description><![CDATA[Hi, I'm ray, nice to me you ! ]]></description><link>https://raymq.com</link><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Tue, 25 Aug 2026 05:09:15 GMT</lastBuildDate><atom:link href="https://raymq.com/feed" rel="self" type="application/rss+xml"/><pubDate>Tue, 25 Aug 2026 05:09:15 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[（三）Deployment]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/t3krlmbevqqdz14j20.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/hbexfhfvgxumttmwwz.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/zpcjpcn9ziht9wwlyb.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/10eqbywgyf0h9s2xcf.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/m7fxqf1n5qga9x94nn.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/etr9kjgs94464lqyrj.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/ik9d6dggsulcyky1gu.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/emw9vytpc2nt1iyem1.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/2p1y72bugc2faptzuz.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/yyidnxexkwv7h5vgou.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/4d8lv5livszqn8s3lp.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/Kubernetes/deployment">https://raymq.com/posts/Kubernetes/deployment</a></blockquote><div><p>Deployment 是 Kubernetes <strong>提供的一种自我修复机制来解决机器故障维护的问题</strong></p><p>前面提到了单独部署 Pod，但是这种方式只适合临时的 Pod，用于测试调试</p><p>用于生产，则需要 Deployment 等控制器<strong>管理部署 Pod，维持 Pod 的副本数量以及 Pod 监控和维护</strong>
<img height="1086" src="https://raymq.com/api/v3/objects/image/t3krlmbevqqdz14j20.png" width="1448"/>
对于 Kubernetes 对象的部署，例如 Pod、Deployment、Service 等，有三种部署方式：</p><ul><li>Using Generators (Run, Expose)</li><li>Using Imperative way (Create)</li><li>Using Declarative way (Apply)</li></ul><p>在本章，我们将会来学习如何使用 Deployment 来部署应用，并学会管理 Pod</p><p>以下命令均在 master 节点上执行，如需在 slave 上，会额外说明</p><h1 id="-deployment">创建 Deployment</h1><p>Deployment 的创建，有两种方法，一种是直接使用命令创建( kubectl create )，一种是通过 YAML( kubectl apply )</p><p>当我们创建一个 deployment 时，<code>kubectl create</code> 和 <code>kubectl apply</code> 效果是一样的，但是 <code>apply</code> 还具有更新 (update) 的功能</p><p><code>kubectl apply</code> 会在以前的配置、提供的输入和资源的当前配置之间 找出三方差异，以确定如何修改资源，<code>kubectl apply</code> 命令将会把推送的版本与以前的版本进行比较，并应用你所做的更改， <strong>但是不会自动覆盖任何你没有指定更改的属性</strong></p><p>另外还有 <code>kubectl replace</code> 、<code>kubectl edit</code></p><ul><li><code>kubectl replace</code> 是破坏性更新/替换，容易导致问题</li><li><code>kubectl edit</code> 可以更新 Deployment 等已存在的对象</li></ul><p>但我们应该使用以 <code>kubectl create</code> 和 <code>kubectl apply</code> 进行创建资源</p><h2 id="kubectl-create">kubectl create</h2><p>我们来使用 deployment 部署一个 Pod，这个 Pod 包含一个 Nginx 容器</p><pre class=""><code class="">kubeclt create deployment nginx-test --image=nginx:latest

# 格式 kubectl create deployment {deployment对象名称} --image={镜像名称和标签}
</code></pre><p>nginx 容器会以 Pod 的方式部署到节点中，但是被部署到哪个节点是随机的，当前只有一个 slave 节点，所以必定在此节点上</p><p>Deployment 会为我们自动创建 Pod，Pod 由 <code>{deployment名称}-{随机名称}</code> 组成</p><pre class=""><code class="">kubectl get deployment -o wide

kubectl get pods -o wide

# 清理资源
# kubectl delete deployment nginx-test
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/hbexfhfvgxumttmwwz.png"/></p><p>有一个不是很讲究的点需要说一下，那就是 kubectl get xxx 时，不管 xxx 加不加 s，都是可以</p><p>只是讲究语义时，我们会习惯性的根据我们的目的加 s，比如想获得全部对象 pods、nodes，对于单一对象则 pod xxx、node xxx</p><h2 id="kubectl-apply">kubectl apply</h2><pre class=""><code class=""># 通过 yaml 文件部署 nginx
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
</code></pre><p>使用 apply 创建时，yaml 文件需要有一些信息，比如：</p><pre class=""><code class="">kind: Deployment
... ...
medatada:
    name:nginx
... ...
    spec:
      containers:
      - image: nginx:latest
</code></pre><p>kubectl apply -f，在 yaml 中指定 <code>kind: Deployment</code></p><h2 id="-yaml">检查 YAML</h2><p>有时我们不知道我们的创建命令或 yaml 是否正确，可以使用 <code>--dry-run=client</code>，<code>--dry-run=client</code> 参数来表示当前内容只是预览而不真正提交</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">root@master:~# kubectl create deployment test-nginx --image=nginx:latest --dry-run=client
deployment.apps/test-nginx created (dry run)
</code></pre><p>命令的意思是：在本地模拟创建一个名为 <code>test-nginx</code> 的 Deployment，但不提交到 Kubernetes 集群
输出的意思是：命令格式没问题，模拟创建成功，但没有写入集群</p><p>此外加上 <code>-o json</code> 参数，可以快速获得需要的 YAML 模板，然后复制到 YAML 文件，根据需要改动、定制，除了 Deployment，其它 kubernetes 对象也可以使用这种方法</p><pre class=""><code class="">kubectl create deployment testnginx --image=nginx:latest --dry-run=client -o yaml
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/zpcjpcn9ziht9wwlyb.png"/></p><h2 id="-yaml">导出 yaml</h2><p>我们可以从已经创建的 Deployment 、Pod、Service 等对象导出 yaml 文件</p><pre class=""><code class="">kubectl get deployment nginx-deployment -o yaml &gt; mynginx.yaml

# 清理资源
kubectl delete deployment nginx-deployment

# 用导出的 yaml 再创建一个 deployment
kubectl apply -f mynginx.yaml
</code></pre>
<h1 id="-deployment">查看 Deployment</h1><p>查看 deployment 的信息，这里的 nginx 用的是 apply -y 创建的，不是 create 创建的</p><pre class=""><code class="">kubectl get deployments 

kubectl get deployments -o wide
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/10eqbywgyf0h9s2xcf.png"/>
查看集群中最近发生的事件，如创建 Deployment 到部署容器过程的详细事件记录</p><pre class=""><code class="">kubectl get events
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/m7fxqf1n5qga9x94nn.png"/>
查看 deployment 更加详细的信息，各种信息的集合</p><pre class=""><code class="">kubectl describe deployment nginx-deployment
# kubectl describe deployment nginx （名称前缀匹配 会匹配多个 nginx 当前只有一个）
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/etr9kjgs94464lqyrj.png"/>
我们可以看到，存在 3 个维持 Nginx Pod 副本，可以使用 kubectl scale 进行缩容，参数 --replicas 就是副本个数；或者使用 kubectl edit 进行编辑文件达到扩缩容</p><pre class=""><code class="">kubectl scale deployment nginx-deployment --replicas=1
</code></pre><h1 id="-pod">查看 Pod</h1><p>我们通过 Deployment 创建了应用，但这些 Pod 是怎么跟 Deployment 对象关联起来的？接下来我们需要了解如何查看 Pod</p><pre class=""><code class="">kubectl get pods -o wide

curl {nginx_ip}
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/ik9d6dggsulcyky1gu.png"/></p><p>对于没有指定的 Deployment、Pod、Service 等对象，会默认分配到 default 命名空间中，我们在执行<code>kubectl get {}</code> 时，会获取 default 命名空间中的对象， 后面加上 <code>--all-namespaces</code> 可以获得所有命名空间中的对象，使用 <code>--namespace=</code> 可以指定获取某个命名空间中的对象</p><pre class=""><code class="">kubectl get pods --all-namespaces

kubectl get pods --namespace=default
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/emw9vytpc2nt1iyem1.png"/></p><h1 id="">实时修改</h1><p>使用 <code>kubectl edit</code> 可以修改的是对象允许更新的字段例，例如 Deployment 的副本数和镜像，这里我们使用前面已经部署好的 Nginx 这个 Deployment</p><p><code>kubectl edit</code> 默认使用的是 <code>vi/vim</code> 编辑器</p><pre class=""><code class="">kubectl edit deployment nginx-deployment
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/2p1y72bugc2faptzuz.png"/></p><h1 id="">多个容器</h1><p>一个 Pod 中，是可以包含多个容器的，我们可以使用命令或 YAML 形式创建包含多个容器的 Pod 服务</p><pre class=""><code class="">kubectl create deployment nginx-test --image=nginx:latest --image=busybox:latest --dry-run=client -o yaml
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/yyidnxexkwv7h5vgou.png"/>
在 master 机器上用 Dashboard 中看看对于的信息</p><pre class=""><code class="">kubectl get services --namespace kubernetes-dashboard
</code></pre><p>登陆即可，IP 是 master 的 IP
<img src="https://raymq.com/api/v3/objects/image/4d8lv5livszqn8s3lp.png"/></p><h1 id="">总结</h1><p>本章我们粗略涉及了一下 deployment 的知识，但 deployment 不仅仅只有这么些内容，当前只是进行了基础操作，对于原理我们尚未涉及</p><p>但学习总得有个过程，先学基础概念，再到基础操作，然后深入原理</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/Kubernetes/deployment#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/Kubernetes/deployment</link><guid isPermaLink="true">https://raymq.com/posts/Kubernetes/deployment</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Sat, 15 Aug 2026 13:44:00 GMT</pubDate></item><item><title><![CDATA[（二）Pod]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/n6sj4gyz9ke4nzki62.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/qsxo3iiniihu23abj3.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/Kubernetes/pod">https://raymq.com/posts/Kubernetes/pod</a></blockquote><div><p>Pod 在 Kubernetes 中是最重要的对象之一，Pod 集群中<strong>创建和管理的、最小的可部署</strong>的计算单元</p><p>在 Kubernetes 中部署一个应用时，创建的便是 Pod，一个 Pod 中包含一个或多个容器，这些容器在 Pod 中能够共享网络、存储等环境，然后组成一个应用对外提供服务</p><p>我们不必过于关注这些概念，只需要知道，在 Kubernetes 中，是不会直接操作容器的，而是通过 Pod 封装了容器，集群通过管控 Pod ，便可控制容器的存储、网络等资源，实现资源隔离或共享</p><h1 id="-pod">创建 Pod</h1><p>以下命令 master 节点上执行</p><pre class=""><code class="">kubectl run nginxtest --image=nginx:latest --port=80

# -o wide 查看更多的 pods 信息
kubectl get pods -o wide

# ip 为 pods 中的 ip，curl 后需要显示 Welcome to nginx 
curl {nginx_ip}

# 清除
kubectl delete pod nginxtest
</code></pre><p>nginxtest 为 Pod 名称，并且为其映射端口为 80，这里创建了一个 nginx 应用，并且 这个 Pod 会被 挂载在 slave 节点上</p><p>一般来说，我们会选择 使用 xx.yaml 文件 进行 pod 的创建，以此来发挥 pod 全部能力</p><pre class=""><code class=""># nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginxtest
spec:
  containers:   
  - image: nginx:latest
    name: nginxtest
    ports:
    - containerPort: 80
      protocol: TCP
      
# 应用
kubeclt apply -y nginx.yaml
</code></pre><h1 id="-pod">了解 Pod</h1><p>Pod 是 Kubernetes 中调度资源的最小单位，一个 Pod 中可以包含多个容器，Pod 中的容器被打包在一起作为一个整体， <strong>Pod 中的容器不会被分配到不同节点中</strong>，<strong>它们一定被部署到同一个节点中</strong></p><p>每个 Pod 之间都是隔离的，也就是在 Pod 内无论怎么使用端口，都不会对另一个 Pod 产生影响，但是在 Pod 内，因为<strong>各个容器都是共享同一个 Pod 的网络，因此一个 Pod 内，不允许有两个进程占用相同的端口</strong>
<img height="821" src="https://raymq.com/api/v3/objects/image/n6sj4gyz9ke4nzki62.png" width="1916"/></p><p>与 主机相同，在同一主机下，不同的 app 使用的进程、端口，都是不同的，不然就会冲突</p>
<h1 id="pod-">Pod 是如何启动</h1><p>在 Kubernetes 中，当创建 Pod 时，会先启动一个 pause 容器，然后 Pod 中我们定义的容器会以 containerd 模式共享 pause 中的网络，在 Pod 网络中相当于交换机，但是 pause 不只是实现容器的网络互通，还有其它功能</p><p>我们的 nginxtest 是挂载在 slave 节点上的，所以需要在 slave 上查看 pause</p><pre class=""><code class="">crictl pods --name nginxtest

crictl images | grep pause
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/qsxo3iiniihu23abj3.png"/></p><h1 id="-pod-">查看 Pod 的信息</h1><p>以下命令master 节点上执行</p><pre class=""><code class=""># 查看 Pod 配置、状态和事件
kubectl describe pod nginxtest

# 查看容器日志
kubectl logs nginxtest

# 在容器中执行命令
kubectl exec nginxtest -- nginx -v
</code></pre><p>Pod 常见状态有：</p><ul><li>Pending：尝试启动容器，如果容器正常启动，则进入下一个阶段</li><li>Running：处于运行状态</li><li>Succeeded、Failed：正常结束或故障等导致容器结束</li><li>Unknown：因为某些原因无法取得 Pod 的状态</li></ul><p>Pod 被分配到某个节点时， Pod 会一直在该节点运行，直到停止或被终止，Pod 在整个生命周期中只会被调度一次。也就是说 Pod 是一次性的，如果 Pod 故障了，那么如果需要恢复应用的运行，是需要重新创建 Pod 的，而不是重启 Pod
 </p><p>在 Kubernetes 中，<strong>Pod 被认为是相对的临时性实体，而不是长期存在的</strong>。由于 Pod 本身不具有治愈能力，如果 节点故障或者节点资源耗尽、节点被维护、Pod 被驱逐等，那么 Pod 无法在节点上继续存活。无论 Pod 因为何种原因被删除，在 Pod 中的网络、存储卷等，也会被销毁，新的 Pod 被创建时，相关的网络、存储卷也会被重建</p><p>在删除 Pod 时，Kubernetes 会终止 Pod 中的所有容器，会向容器中的进程发生 SIGTERM 信号，等待进程的正常关闭，所以 Pod 可能不会被马上删除，当然如果进程不能正常关闭，Kubernetes 最多等待 30s，然后会使用 SIGKILL 强制杀死进程</p><h1 id="">容器重启策略</h1><pre class=""><code class=""># 一个简单的 pod.yaml 配置
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
spec:
  containers:
  - image: nginx:latest
    imagePullPolicy: Always
    name: nginx
    ... ...
  restartPolicy: Always
</code></pre><p>在这个 YAML 中，有两个 <code>*Policy</code> ，取值有 Always、OnFailure 和 Never 三种，它们代表了某种生命周期策略</p><p>对于每个容器，都可以设置 <code>imagePullPolicy</code> ，指示在拉取镜像时如果失败，是否进行重试</p><p>在 spec 中，有个 restartPolicy 字段，其值默认为 Always，指示 Pod 中所有容器的重启动作，但是在 Deployment、StatefulSet、DaemonSet 等控制器中，restartPolicy 只支持 Always ，不支持 OnFailure 和 Never</p><p>容器启动失败，重试间隔会越来越长，kubelet 会在 10s 后重试第一次，如果还是失败，第二次 20s 后再重试；按照 10s、20s、40s、80s ... 的间隔重试，但最长不超过 5 分钟。如果容器被成功运行且运行了 10 分钟以上，那么计时器会被重置，下次出现故障时，按照 10s、20s 的间隔时间重试</p><p>如果单独创建 Pod，并且设置了 <code>restartPolicy: Always</code>，那么 Pod 会一直停留在此节点上，如果 容器故障，Pod 可能会无限重试</p><h1 id="">总结</h1><p>本章粗略讲了 Pod 的一些基础知识，当然，不可能全部都能进行记忆，最重要的是，存在一个印象，等未来真实使用到这些知识时，你不会胆怯，这样，就足够了</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/Kubernetes/pod#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/Kubernetes/pod</link><guid isPermaLink="true">https://raymq.com/posts/Kubernetes/pod</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Sat, 15 Aug 2026 13:43:00 GMT</pubDate></item><item><title><![CDATA[（一）master 和 slave 集群环境配置]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/jtpr3tve5vnsp5ne6y.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/3l9nwf2ivnksxffg9y.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/Kubernetes/master-slave">https://raymq.com/posts/Kubernetes/master-slave</a></blockquote><div><p>集群使用环境为 Mac、UTM 虚拟机、Ubuntu 24.04 LTS ARM64 架构 镜像源、root 用户</p><ul><li>本章出现的 IP 不得照抄，需要按实际 IP 进行填写</li><li>Windows 用户，可以让 AI 重写此文件，以此达到配置集群的目的</li></ul><p>master、slave 虚拟机 均开启了共享主机网络功能，并在主机使用脚本让虚拟机自动监听 梯子 开放的端口，以此达到拉取外网镜像源能力</p><ul><li>脚本可以用 AI 生成，目的只有一个，那就是开放一个端口提供给虚拟机使其能访问外网</li></ul><p>master 机器为控制平面，master 初始化后，root 的 kubectl 配置固定为 <code>/root/.kube/config</code>；<code>kubeadm token</code> 使用控制平面上的 <code>/etc/kubernetes/admin.conf</code></p><p>下面配置 master、slave 双机 Kubernetes 集群</p><h1 id="-">一 配置主机网段</h1><p>master 主机</p><pre class=""><code class="">root@master:~# hostname
master
root@master:~# ip -4 -br addr
lo               UNKNOWN        127.0.0.1/8 
enp0s1           UP             192.168.64.2/24 metric 100 
docker0          DOWN           172.17.0.1/16 
root@master:~# ip route
default via 192.168.64.1 dev enp0s1 proto dhcp src 192.168.64.2 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.64.0/24 dev enp0s1 proto kernel scope link src 192.168.64.2 metric 100 
192.168.64.1 dev enp0s1 proto dhcp scope link src 192.168.64.2 metric 100 
root@master:~#
</code></pre><p>slave 主机</p><pre class=""><code class="">root@slave:~# hostname
slave
root@slave:~# ip -4 -br addr
lo               UNKNOWN        127.0.0.1/8 
enp0s1           UP             192.168.64.3/24 metric 100 
docker0          DOWN           172.17.0.1/16 
root@slave:~# ip route
default via 192.168.64.1 dev enp0s1 proto dhcp src 192.168.64.3 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.64.0/24 dev enp0s1 proto kernel scope link src 192.168.64.3 metric 100 
192.168.64.1 dev enp0s1 proto dhcp scope link src 192.168.64.3 metric 100 
root@slave:~#
</code></pre>
<p>分别在各自的 /etc/hosts 中加入双方的主机 ip
master 主机</p><pre class=""><code class="">127.0.0.1 localhost

192.168.64.2 master
192.168.64.3 slave

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</code></pre><p>slave 主机</p><pre class=""><code class="">127.0.0.1 localhost

192.168.64.2 master
192.168.64.3 slave

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</code></pre><p>需要确保双方能够互相 ping 通（<code>ping master</code>、<code>ping slave</code> 不丢包）。</p><h1 id="-">二 改造环境</h1><p>以下命令应该在 <strong>master</strong> 与 <strong>slave</strong> 机器上执行</p><h2 id="21--utm-">2.1 配置 UTM 宿主机代理</h2><p>创建 root 专用的代理环境文件：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cat &gt; /root/.utm-proxy-env &lt;&lt;&#x27;EOF&#x27;
export HTTP_PROXY=&#x27;http://192.168.64.1:17897&#x27;
export HTTPS_PROXY=&#x27;http://192.168.64.1:17897&#x27;
export http_proxy=&#x27;http://192.168.64.1:17897&#x27;
export https_proxy=&#x27;http://192.168.64.1:17897&#x27;
export NO_PROXY=&#x27;127.0.0.1,localhost,::1,master,slave,192.168.64.0/24,10.96.0.0/12,10.244.0.0/16,.svc,.svc.cluster.local,.cluster.local&#x27;
export no_proxy=&quot;$NO_PROXY&quot;
unset ALL_PROXY all_proxy
EOF

grep -qxF &#x27;source /root/.utm-proxy-env&#x27; /root/.bashrc || \
  echo &#x27;source /root/.utm-proxy-env&#x27; &gt;&gt; /root/.bashrc

source /root/.utm-proxy-env
</code></pre><p>APT 使用独立配置，避免环境变量是否被继承造成差异：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cat &gt; /etc/apt/apt.conf.d/99-utm-proxy &lt;&lt;&#x27;EOF&#x27;
Acquire::http::Proxy &quot;http://192.168.64.1:17897&quot;;
Acquire::https::Proxy &quot;http://192.168.64.1:17897&quot;;
EOF

nc -vz 192.168.64.1 17897
curl -fsSI https://pkgs.k8s.io | head
</code></pre><p><code>NO_PROXY</code> 中包含节点网段、Service 网段和 Pod 网段，因此外网 HTTP/HTTPS 请求走代理，<code>master:6443</code> 和 Kubernetes 集群内部地址保持直连</p><h2 id="22--linux-">2.2 准备 Linux 节点</h2><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 更新系统并安装基础工具
apt-get update
apt-get install -y ca-certificates curl gpg bash-completion netcat-openbsd

dpkg --print-architecture

# 关闭 Swap
swapoff -a
sed -ri &#x27;/\sswap\s/s/^#?/#/&#x27; /etc/fstab
swapon --show

# 加载内核模块
tee /etc/modules-load.d/k8s.conf &gt;/dev/null &lt;&lt;&#x27;EOF&#x27;
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# 配置内核网络参数
tee /etc/sysctl.d/k8s.conf &gt;/dev/null &lt;&lt;&#x27;EOF&#x27;
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sysctl --system

# 输出应为 1
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
</code></pre><p>这些配置的目的，是把普通 Linux 主机调整为适合 Kubernetes 节点运行的环境：关闭 Swap 保证 kubelet 能准确进行内存资源管理；加载 <code>overlay</code> 支持容器镜像的分层文件系统；加载 <code>br_netfilter</code> 并开启 <code>bridge-nf-call-iptables</code>，让 Pod 经过 Linux Bridge 的流量能够被 iptables/netfilter 处理；开启 <code>ip_forward</code>，让节点具备转发 Pod 网络数据包的能力，从而支持跨 Pod、跨节点通信</p><h1 id="--containerd">三 安装并配置 containerd</h1><p>以下命令应该在 <strong>master</strong> 与 <strong>slave</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 安装 containerd
apt-get install -y containerd
install -d -m 0755 /etc/containerd
containerd config default | tee /etc/containerd/config.toml &gt;/dev/null

# 使用 systemd cgroup
sed -i &#x27;s/SystemdCgroup = false/SystemdCgroup = true/&#x27; /etc/containerd/config.toml

# containerd 是独立的 systemd 服务，必须单独配置代理才能拉取镜像
install -d -m 0755 /etc/systemd/system/containerd.service.d
cat &gt; /etc/systemd/system/containerd.service.d/10-utm-proxy.conf &lt;&lt;&#x27;EOF&#x27;
[Service]
Environment=&quot;HTTP_PROXY=http://192.168.64.1:17897&quot;
Environment=&quot;HTTPS_PROXY=http://192.168.64.1:17897&quot;
Environment=&quot;NO_PROXY=127.0.0.1,localhost,::1,master,slave,192.168.64.0/24,10.96.0.0/12,10.244.0.0/16,.svc,.svc.cluster.local,.cluster.local&quot;
EOF

systemctl daemon-reload
systemctl enable --now containerd
systemctl restart containerd

# 检查服务
systemctl is-active containerd
ctr version
systemctl show containerd -p Environment --no-pager
grep -n &#x27;SystemdCgroup = true&#x27; /etc/containerd/config.toml
</code></pre><p>应该输出 active ，以及 <code>SystemdCgroup = true
![](https://raymq.com/api/v3/objects/image/s0clqqsodkq4p2w64h.png)
目的是为 Kubernetes 安装并配置**容器运行时 containerd**。Kubernetes 本身不直接创建和运行容器，而是由 kubelet 通过 CRI 调用 containerd 来完成镜像拉取、容器创建、启动和停止等操作；生成 </code>/etc/containerd/config.toml<code> 是为了建立默认配置；设置 </code>SystemdCgroup = true<code> 是让 containerd 和 kubelet 统一使用 </code>systemd` 管理 cgroup，避免资源管理方式不一致；最后启动并检查 containerd，确认容器运行时已经正常工作</p><h1 id="--kubeadmkubeletkubectl">四 安装 kubeadm、kubelet、kubectl</h1><p>以下命令应该在 <strong>master</strong> 与 <strong>slave</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 添加 Kubernetes 1.36 软件仓库
install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key \
  | gpg --dearmor --yes -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo &#x27;deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /&#x27; \
  | tee /etc/apt/sources.list.d/kubernetes.list &gt;/dev/null
  
# 安装并锁定版本
apt-mark unhold kubelet kubeadm kubectl 2&gt;/dev/null || true
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
systemctl enable --now kubelet

# 检查版本
kubeadm version -o short
kubelet --version
kubectl version --client

# 输出版本
v1.36.3
Kubernetes v1.36.3
Client Version: v1.36.2
Kustomize Version: v5.8.1
</code></pre><h1 id="--kubeadm-">五 创建 kubeadm 配置文件</h1><p>以下命令只在 <strong>master</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 创建配置文件
MASTER_IP=&quot;$(ip -4 route get 1.1.1.1 | awk &#x27;{for (i=1; i&lt;=NF; i++) if ($i==&quot;src&quot;) {print $(i+1); exit}}&#x27;)&quot;
K8S_VERSION=&quot;$(kubeadm version -o short)&quot;

: &quot;${MASTER_IP:?无法取得控制平面 IP}&quot;
: &quot;${K8S_VERSION:?无法取得 Kubernetes 版本}&quot;

printf &#x27;MASTER_IP=%s\nK8S_VERSION=%s\n&#x27; &quot;$MASTER_IP&quot; &quot;$K8S_VERSION&quot;

cat &gt; kubeadm-config.yaml &lt;&lt;EOF
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: &quot;${MASTER_IP}&quot;
  bindPort: 6443
nodeRegistration:
  name: master
  criSocket: unix:///run/containerd/containerd.sock
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: &quot;${K8S_VERSION}&quot;
controlPlaneEndpoint: &quot;master:6443&quot;
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF

# 检查文件
cat kubeadm-config.yaml
kubeadm config validate --config kubeadm-config.yaml
</code></pre><h1 id="--master">六 初始化 master</h1><p>以下命令只在 <strong>master</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 拉取镜像
kubeadm config images pull --config kubeadm-config.yaml

# 初始化集群并保存日志
set -o pipefail
kubeadm init --config kubeadm-config.yaml --upload-certs --v=5 \
  | tee kubeadm-init.out
  
# 为 root 配置 kubectl
install -d -m 0700 /root/.kube
install -o root -g root -m 0600 \
  /etc/kubernetes/admin.conf /root/.kube/config

# 验证 API Server
kubectl cluster-info
kubectl get nodes -o wide

# 确认直连 API Server
curl -k --noproxy &#x27;*&#x27; https://master:6443/livez
kubectl get nodes -o wide

第一条为 `ok`；第二条中 master 显示 `NotReady` 为正常。
</code></pre><p><strong>保留 <code>kubeadm join master:6443 --token xxxxx --discovery-token-ca-cert-hash xxxx</code> ！！！</strong></p><h1 id="--calico-">七 安装 Calico 网络插件</h1><p>以下命令只在 <strong>master</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 下载 Calico 清单
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml

# 使用清单
kubectl apply -f calico.yaml

# 观察 Pod 启动过程
# 当 calico-node、calico-kube-controllers、coredns 都进入 Running 即可退出
kubectl get pods -n kube-system -w

# 检查节点，master 从 NotReady 变为 Ready
kubectl get nodes -o wide
</code></pre><h1 id="--slave-">八 将 slave 加入集群</h1><p>以下命令注意区分 <strong>master</strong> 与 <strong>slave</strong> 机器上执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 使用上述保留的 token；如果丢失，在 master 重新生成
# kubeadm token create --print-join-command

# 在 slave 中加入 token
kubeadm join master:6443 --token xxxx --discovery-token-ca-cert-hash xxxx

# 回到 master 机器检查
kubectl get nodes -o wide
kubectl get pods -A -o wide

master、slave 均存在且为 Ready
</code></pre><h1 id="-">九 验证集群可用性</h1><p>以下命令只在 <strong>master</strong> 机器上执行</p><pre class=""><code class=""># 创建 Deployment 和 Service
kubectl create deployment web --image=nginx:alpine
kubectl expose deployment web --port=80
kubectl rollout status deployment/web --timeout=120s
kubectl get pods -o wide
kubectl get service web

# 测试 Pod 访问 Service
kubectl run curl-test \
  --image=curlimages/curl:latest \
  --restart=Never --rm -it \
  -- curl -s http://web
  
# 清理验证资源
kubectl delete deployment web
kubectl delete service web
</code></pre><p>能正常返回 Nginx HTML，则代表配置成功，可以清理验证资源了
<img height="732" src="https://raymq.com/api/v3/objects/image/jtpr3tve5vnsp5ne6y.png" width="1176"/></p><h1 id="-dashboard">安装 Dashboard</h1><p>Dashboard 是管理 Kubernetes 集群的 Web UI，以下命令在 <strong>master</strong> 机器执行</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 检查 helm 版本
helm version

# 安装 Dashboard
DASHBOARD_CHART_URL=&#x27;https://github.com/kubernetes-retired/dashboard/releases/download/kubernetes-dashboard-7.14.0/kubernetes-dashboard-7.14.0.tgz&#x27;

helm upgrade --install kubernetes-dashboard \
  &quot;$DASHBOARD_CHART_URL&quot; \
  --namespace kubernetes-dashboard \
  --create-namespace \
  --wait \
  --timeout 10m
  
# 检查 Helm Release、Pod 和 Service
# helm list 中的状态应为 deployed
# Dashboard 的 API、Auth、Web、Metrics Scraper 和 Kong Pod 应为 Running
# Service kubernetes-dashboard-kong-proxy 应监听 443/TCP
helm list --namespace kubernetes-dashboard

kubectl --namespace kubernetes-dashboard wait \
  --for=condition=Ready pod \
  --all \
  --timeout=600s
  
# Dashboard 会默认挂载到 slave 机器上
kubectl --namespace kubernetes-dashboard get pods,service -o wide
</code></pre><p>以下步骤非常重要，因为 Dashboard 需要使用 Token 进行校验登陆，所以此 Token 需保存</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 创建管理员 ServiceAccount
kubectl --namespace kubernetes-dashboard \
  create serviceaccount dashboard-admin \
  --dry-run=client -o yaml \
  | kubectl apply -f -

# 授予 cluster-admin 权限
kubectl create clusterrolebinding dashboard-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kubernetes-dashboard:dashboard-admin \
  --dry-run=client -o yaml \
  | kubectl apply -f -

# 创建长期 Token
kubectl apply -f - &lt;&lt;&#x27;EOF&#x27;
apiVersion: v1
kind: Secret
metadata:
  name: dashboard-admin-token
  namespace: kubernetes-dashboard
  annotations:
    kubernetes.io/service-account.name: dashboard-admin
type: kubernetes.io/service-account-token
EOF

# 等待 master 把 Token 写入 Secret
kubectl --namespace kubernetes-dashboard wait \
  --for=jsonpath=&#x27;{.data.token}&#x27; \
  secret/dashboard-admin-token \
  --timeout=60s
  
# 每次登陆，执行此命令，将输出的 Token 粘贴到暴露的 URL 即可
kubectl --namespace kubernetes-dashboard \
  get secret dashboard-admin-token \
  --output=jsonpath=&#x27;{.data.token}&#x27; \
  | base64 --decode
printf &#x27;\n&#x27;

# 通过打印出的节点进入 DashBoard 界面
MASTER_IP=&quot;$(
  ip -4 route get 1.1.1.1 \
    | awk &#x27;{for (i=1; i&lt;=NF; i++) if ($i==&quot;src&quot;) {print $(i+1); exit}}&#x27;
)&quot;

kubectl --namespace kubernetes-dashboard \
  get service kubernetes-dashboard-kong-proxy

printf &#x27;Dashboard 地址：https://%s:30443\n&#x27; &quot;$MASTER_IP&quot;
</code></pre><p>可以看到 Dashboard 也是非常好看的，
<img src="https://raymq.com/api/v3/objects/image/3l9nwf2ivnksxffg9y.png"/></p><h1 id="">总结</h1><p>本章实现了 master、slave 双机 k8s 集群，当然只是属于学习阶段，真实环境中需要配置的机器不只有一台，难度会往上增加</p><p>但核心是不变的，那就是 <strong>保持冷静</strong>，遇到问题，解决问题就好了</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/Kubernetes/master-slave#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/Kubernetes/master-slave</link><guid isPermaLink="true">https://raymq.com/posts/Kubernetes/master-slave</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Sat, 15 Aug 2026 13:42:00 GMT</pubDate></item><item><title><![CDATA[碎碎念（二）]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/fmftqmc7gujj1u5ezo.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/notes/5">https://raymq.com/notes/5</a></blockquote><div><p>今天是 2026年8月7日凌晨12点42分41秒，从这个记录的时间点开始，我写下这篇文章，我的思绪是嘈杂的，我不清楚我要写什么，但是我的目的很明确，我想记录一些话，一些在今天乃至未来，会改变我的话
<img height="2768" src="https://raymq.com/api/v3/objects/image/fmftqmc7gujj1u5ezo.png" width="2160"/>
这是我的 mt 说的话，从第一次认识，到今天这个时候，mt 一直在强调的就是 <strong>思考</strong> 每次与 mt 非工作时的闲聊，都能给我一些思考，在潜移默化的改变我，这些闲聊，默默的在我脑袋里埋下一颗种子，开始慢慢的生根发芽</p><p>从第一次面试反问 mt 强调要思考；到下班后 mt 请客吃麦当劳分享他的故事；到跟 mt 出差说要为共产主义，为社会做贡献；再到公司楼下遛弯 mt 分享以前实习生的事；到工作时 mt 说他能为我们兜底；最后到今天 mt 的回答...</p><p>回顾两年前与两个月前，我...我或许变了: 在两年前，我的为人着想的想法，仅仅只是一个想法，产生的念头源自于我在祈求某些事情成功后我将这么做去回报成功，但即使成功我也没有去行动，因为失败次数更多，这是一种功利的想法；直至两个月前，我开始思考，我开始写博客发视频，开始记录我的日常与学习笔记，我由衷的希望，我的笔记、我的博客、视频、甚至是口头话语，可以去帮助他人，去帮助那些在这条路上迷茫困惑的人，去帮助那些与我一样没有学历、没有天赋、没有背景...但却不甘堕落的那些人，我希望他们能变好...</p><p>我不是一个才华横溢之辈，也并非富甲一方，我做不到施舍钱财救济苦难之人，更不能靠自己的才华让社会变得更好，我所能做的，也只是发一些文章、视频，指引身处迷雾之人及时走出，同样的，我也会希望接受过帮助的人能在别人迷茫困惑时同样指引他们这或许就是 mt 所说的共产主义吧...</p><p>虽然这么做，还会同时满足我的被认可感，或者说也算是功利心吧，但是与两年前不同了，就算文章、视频...籍籍无名，但我还是会坚持...</p><p>我一直在焦虑，一直在困惑，一直在反复确认我所坚持的是否是对的...我把这些统称为情绪，这些情绪源自于我一直在思考，思考我的处境...我应该怎么做？我未来怎么办？为什么这么简单的事我都处理不好？就像 mt 说的，疑问来自于知识的积累，我所面临的知识积累不只有我的工作，还包括与他人言语相传、社交平台、电子群聊...这些每天接触到的东西，都会潜移默化的作为一种积累，存储到你的脑子某一个角落，等到哪天再去用时，你才会发现会因为这个积累导致很多你无法理解的事，你会有驱动的去搜索前后之因果...或许这就是 mt 想让我明白的吧</p><p>从实习第一天到现在，mt 一直没有正面的告诉我如何去学习，也正如他所说的，每个人的路都是不一样的，自己选择的路才是最好的，旁人言语，也不如自撞南墙，即使你会因此走错很多路、会始终无法明白当初的选择为什么会走错，但只有自己的选择，才无愧于心，才无愧于人...</p><p>愿 诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/notes/5#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/notes/5</link><guid isPermaLink="true">https://raymq.com/notes/5</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Thu, 06 Aug 2026 17:46:00 GMT</pubDate></item><item><title><![CDATA[（一）初识 Django]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/xibb61r463iz6792im.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/cp856h4cb9q6tpe9em.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/a0j8s96csbhkzmchy1.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/django/django1">https://raymq.com/posts/django/django1</a></blockquote><div><p>今天我们来学习什么是 Django 框架</p><p>在学任何东西时，首要的就是学习基础概念，你得知道它是干什么的，才能知道做出的东西的意义是什么</p><p>Django 是 Python 社区的两大最受欢迎的 Web 框架之一（另一个是 Flask），凭借功能强大的脚手架和诸多开箱即用的组件，用 Django 搭建 Web 应用快速而又省力。但因为过于强大，想要驾驭它需要花费不少的力气，本教材将通过实现一个新闻发布网站带你快速熟悉 Django 框架</p><h1 id="">来源</h1><p>Django 由 Adrian Holovaty 和 Simon Willison 在 2003 年的秋天写成，并在 2005 年正式发布。他们俩当时为一个新闻报社制作网站，对<strong>快速开发</strong>有着比较高的需求，并且希望能够在开发的同时也能够<strong>让非技术人员为网站添加内容</strong>。于是这也使得 Django 具备了两项鲜明的特点：</p><ul><li>高度强调<strong>可复用性</strong>和<strong>可插拔性</strong>，内置大量现成的成熟组件，开发效率极高</li><li>自带与数据库联动的<strong>后台管理系统</strong>，能够在开发的同时创建内容</li></ul><h1 id="mtv-">MTV 框架</h1><p>MTV 框架是每个 Django App 的组织结构</p><ul><li>M（Model）：创建数据模型，并执行数据库迁移</li><li>T（Template）：写出基本的 Django 模板，并从视图中传入数据</li><li>V（View）：在视图中访问数据库，实现业务逻辑，渲染模板，并接入路由表
如果大家了解过 MVC 框架的话，或许就不会陌生了，如下：</li></ul><table><thead><tr><th>      </th><th> MVC        </th><th> MTV      </th></tr></thead><tbody><tr><td> 数据模型 </td><td> Model      </td><td> Model    </td></tr><tr><td> 用户界面 </td><td> View       </td><td> Template </td></tr><tr><td> 业务逻辑 </td><td> Controller </td><td> View     </td></tr></tbody></table><p>大家熟知的 View，在 Django 里面代表的是业务逻辑，也就是 MVC 中的控制器</p><h1 id="">安装</h1><p>安装前需要确保环境中存在 python3 和 pip，然后就可以直接使用 pip 进行安装</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 一般情况下 python 都是 3.1.2 版本
python3 -m pip install django
</code></pre>
<h1 id="">初步体验</h1><p>安装好 Django 后，我们用 Django 自带的脚手架工具 django-admin 创建项目：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">source ～/django-env/bin/activate
django-admin startproject django_news
cd django_news
</code></pre><p><img height="348" src="https://raymq.com/api/v3/objects/image/xibb61r463iz6792im.png" width="645"/></p><pre class=""><code class="">django_news
├── django_news              // 项目全局文件目录
│   ├── __init__.py
│   ├── settings.py          // 全局配置
│   ├── urls.py              // 全局路由
│   └── wsgi.py              // WSGI服务接口（暂时不用纠结这个是神马）
└── manage.py                // 项目管理脚本
</code></pre><p>使用 manage.py 运行开发服务器（Development Server）</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">python manage.py runserver
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/cp856h4cb9q6tpe9em.png"/>
可以看到，出现了一堆红色的提示，不用管，按照提示，我们通过浏览器访问 <a href="localhost:8000">localhost:8000</a>，可以看到欢迎界面
<img src="https://raymq.com/api/v3/objects/image/a0j8s96csbhkzmchy1.png"/>
Django 开发服务器可以保持开启，并且后面修改代码会自动重新加载，非常方便。后面运行其他命令时，再打开一个终端（命令行）即可。</p><h1 id="">总结</h1><p>我认为，当你看完这一篇教程之后，你应该会有这么一个印象：</p><p>Django 是一个高度<strong>模块化</strong>的 Web 框架，提供了丰富的组件用于开发；有 MTV 框架；使用 xxx 命令启动开发服务器</p><p>但 Django 框架并非只有这么些内容，更多具体的知识，需要你主动去钻研学习</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/django/django1#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/django/django1</link><guid isPermaLink="true">https://raymq.com/posts/django/django1</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Fri, 31 Jul 2026 15:18:00 GMT</pubDate></item><item><title><![CDATA[（三）理解模版 Template]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/c8d30pksmskmizhudz.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/j7nhmfs2443qt2ubsr.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/django/django3">https://raymq.com/posts/django/django3</a></blockquote><div><p>上一章中，我们学会了如何实现视图，并将其接入路由配置中，使其能够被用户访问</p><p>接下来，我们将实现一个 Django 模板作为网页前端，从而给用户呈现更丰富的内容</p><h1 id="django-">Django 模板语言基础</h1><p>Django 模板本质上是一个 HTML 文档，只不过通过一些特殊的语法实现数据的填充</p><h2 id="">表达式插值</h2><p>最常用的语法，没有之一。通过在一对花括号 <code>{{}}</code> 放入一个表达式，就能够在视图中传入表达式中变量的内容，并最终渲染成包含变量具体内容的 HTML 代码。需要注意的是，所支持的表达式仅支持以下形式（可以自由组合）：</p><pre class="language-html lang-html"><code class="language-html lang-html">&lt;!-- 单个变量 --&gt;
{{ variable }}

&lt;!-- 获取字典的键或对象的属性 --&gt;
{{ dict.key }}
{{ object.attribute }}

&lt;!-- 获取列表中的某个元素 --&gt;
{{ list.0 }}

eg:
&lt;h1&gt;{{ name }}&lt;/h1&gt;
&lt;p&gt;{{ news.title }}&lt;/p&gt;
&lt;p&gt;{{ news.visitors.0 }}&lt;/p&gt;
</code></pre><p>如果我们在视图中传入以下上下文字典（Context Dictionary）：</p><pre class="language-python lang-python"><code class="language-python lang-python">{
    &#x27;name&#x27;: &#x27;Tuture&#x27;,
    &#x27;news&#x27;: {
        &#x27;title&#x27;: &#x27;Hello World&#x27;,
        &#x27;visitors&#x27;: [&#x27;Tom&#x27;, &#x27;Marc&#x27;],
    }
}
</code></pre><p>那么最终渲染成的 HTML 代码就是：</p><pre class="language-html lang-html"><code class="language-html lang-html">&lt;h1&gt;Tuture&lt;/h1&gt;
&lt;p&gt;Hello World&lt;/p&gt;
&lt;p&gt;Tom&lt;/p&gt;
</code></pre><h2 id="">条件语句</h2><p>顾名思义，有条件的语句，定义如下</p><pre class="language-html lang-html"><code class="language-html lang-html">{% if is_true %}
  &lt;h1&gt;It is true!&lt;/h1&gt;
{% else %}
  &lt;h1&gt;It is false!&lt;/h1&gt;
{% endif %}
</code></pre><p>如果变量 is_true 为真那么最终渲染出来的就是 <code>&lt;h1&gt;It is true!&lt;/h1&gt;</code>，否则就是 <code>&lt;h1&gt;It is false!&lt;/h1&gt;</code>，<strong>整个条件语句必须以 <code>{% endif %}</code> 结束，并且 <code>{% else %}</code> 是可选的</strong></p><h2 id="">循环语句</h2><p>循环语句用来在模板上展示任意长的列表内容</p><pre class="language-html lang-html"><code class="language-html lang-html">{% for elem in some_list %}
  &lt;p&gt;{{ elem }}&lt;/p&gt;
{% endfor %}
</code></pre><p>如果传入的 some_list 为 <code>[&#x27;Apple&#x27;, &#x27;Banana&#x27;, &#x27;Orange&#x27;]</code>，那么渲染出的 HTML 代码就是：</p><pre class="language-html lang-html"><code class="language-html lang-html">&lt;p&gt;Apple&lt;/p&gt;
&lt;p&gt;Banana&lt;/p&gt;
&lt;p&gt;Orange&lt;/p&gt;
</code></pre>
<h1 id="-django-">实现一个 Django 模板</h1><p>在 news 目录中创建一个 templates 目录，再在 templates 目录中创建一个 news 目录，并在内层的 news 目录中创建 index.html 文件
<img height="881" src="https://raymq.com/api/v3/objects/image/c8d30pksmskmizhudz.png" width="1206"/>
大家可能看到会有些疑问，为什么还要再创建一个 news 目录放置 index.html 文件？</p><p>这是由于 Django 的模板查找机制 会将所有应用里面的模板全部收集到一起，如果两个模板的名字冲突，就会导致其中一个模板不能被正确访问。如果放在 news 子文件夹里面，就能够通过 news/index.html 访问，通过命名空间的机制避免冲突
内容如下：</p><pre class="language-html lang-html"><code class="language-html lang-html">{% if news_list %}
  &lt;ul&gt;
  {% for elem in news_list %}
    &lt;li&gt;
      &lt;h3&gt;{{ elem.title }}&lt;/h3&gt;
      &lt;p&gt;{{ elem.content }}&lt;/p&gt;
    &lt;/li&gt;
  {% endfor %}
  &lt;/ul&gt;
{% else %}
  &lt;p&gt;暂无新闻&lt;/p&gt;
{% endif %}
</code></pre><p>刚好覆盖了上述的三种模板语法：表达式插值、条件语句和循环语句</p><p>完成模板编写后，我们需要在视图中对其进行渲染，打开 news/views.py 文件，修改代码：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.shortcuts import render

def index(request):
    context = {
        &#x27;news_list&#x27;: [
            {
                &quot;title&quot;: &quot;Raymq.com是个博客&quot;,
                &quot;content&quot;: &quot;一个作者倾尽心血的博客&quot;,
            },
            {
                &quot;title&quot;: &quot;Raymq.com 的专栏很棒&quot;,
                &quot;content&quot;: &quot;有很多知识可以去学习&quot;,
            },
        ]
    }

    return render(request, &#x27;news/index.html&#x27;, context=context)
</code></pre><p>这里我们调用 django.shortcuts.render 函数来渲染模板，这个函数通常接受三个参数（有其他参数，但是这里我们不关心）：</p><ul><li>request：请求对象，直接把视图的参数 request 传进来就可以</li><li>template_name：模板名称，这里就是我们刚刚创建的 news/index.html</li><li>context：传入模板的上下文对象，必须是一个字典，字典中的每个键对应模板中的变量，这里我们弄了些假数据，假装是从数据库里面取来的、</li></ul><p>继续访问 localhost:8000，看一下我们的首页内容：</p><p><img src="https://raymq.com/api/v3/objects/image/j7nhmfs2443qt2ubsr.png"/></p><h1 id="">总结</h1><p>这一章我们主要讲了模板怎么建立的，以及如何在视图渲染</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/django/django3#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/django/django3</link><guid isPermaLink="true">https://raymq.com/posts/django/django3</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Fri, 31 Jul 2026 01:00:00 GMT</pubDate></item><item><title><![CDATA[（二）理解视图 View]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/yzeq5tuuxoimp721cx.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/hqyhy1shvk2tceagny.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/f1ux9ftr68q2tpznav.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/1evl7wvjd7c101o5ps.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/1h5ptnjzop0vfjpw9p.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/6bsrytiwiwwpaox3rq.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/django/django2">https://raymq.com/posts/django/django2</a></blockquote><div><p>上一节我们讲了 Django 是一个高度<strong>模块化</strong>的框架</p><p>具体来说，一个 Django 应用由多个子应用组成，我们一般称之为 App（注意不是我们常说的移动应用 APP，而是 Application）<img height="447" src="https://raymq.com/api/v3/objects/image/yzeq5tuuxoimp721cx.png" width="762"/>
如上图可以看到 Django App 一般分为三大类：
<strong>内置</strong>：即 Django 框架自带的应用，包括 admin（后台管理）、auth（身份鉴权）、sessions（会话管理）等等
<strong>自定义</strong>：即用来实现我们自身业务逻辑的应用，这里我们将创建一个新闻展示应用
<strong>第三方</strong>：即社区提供的应用，数量极其丰富，功能涵盖几乎所有方面，能够大大减少开发成本</p><p>而所有的 Django 应用都在 django<em>news/settings.py 的 INSTALLED</em>APPS 列表中定义
<img src="https://raymq.com/api/v3/objects/image/hqyhy1shvk2tceagny.png"/></p><h1 id="-app">实现自定义 APP</h1><pre class="language-bash lang-bash"><code class="language-bash lang-bash">python3 manage.py startapp news
</code></pre><p><img src="https://raymq.com/api/v3/objects/image/f1ux9ftr68q2tpznav.png"/>
生成的 news 应用文件夹结构如下所示：</p><pre class=""><code class="">news                     // news 应用目录
├── __init__.py          // 初始化模块
├── admin.py             // 后台管理配置
├── apps.py              // 应用配置
├── migrations           // 数据库迁移文件目录
│   └── __init__.py      // 数据库迁移初始化模块
├── models.py            // 数据模型
├── tests.py             // 单元测试
└── views.py             // 视图
</code></pre><p>可以看到一个目录下有很多的文件，这是因为 Django 始终坚持<strong>解耦</strong>的原则 —— 尽量减少代码之间的耦合，把不相关的代码拆成多个模块，让同一个模块具有<strong>内聚性</strong></p><p>我们在 settings.py 中将 news 应用加入 INSTALLED_APPS 中
<img src="https://raymq.com/api/v3/objects/image/1evl7wvjd7c101o5ps.png"/></p><h2 id="">业务逻辑编写</h2><p>通过访问 localhost:8000/admin 已经可以访问后台管理系统了（虽然会跳转到登录界面）</p><p>接下来，我们同样希望能够访问到刚才创建的 news 应用，因此，这一步中我们将：</p><ul><li>在视图（View）中写一点业务逻辑</li><li>接入路由，使其能够被访问</li></ul><h3 id="django-">Django 的路由系统</h3><p>如果你对路由一直很迷惑，只需要记住<strong>路由的核心概念：决定&quot;从哪里到哪里应该怎么走&quot;的规则，本质都是&quot;根据输入找到对应处理逻辑&quot;</strong>。</p><p>Django 的路由系统是由全局路由和子应用路由组成。简单来说，根据用户输入的 URL，全局路由表进行匹配并选择正确的子应用路由，再由所选择的子应用路由匹配并选择正确的视图（View）如图：
<img src="https://raymq.com/api/v3/objects/image/1h5ptnjzop0vfjpw9p.png"/>
用户访问 <code>example.com/apple/buy</code>，然后全局路由根据 /apple/buy 先选择 apple 的路由表，再从 apple 路由表中根据 /buy 选择 /buy 路由，然后执行 /buy 对应的 BuyView 视图，返回给用户结果</p><h3 id="">编写第一个视图</h3><p>对视图访问的流程大致了解之后，我们就可以开始动手了</p><p>首先打开 news/views.py，写一个简单的视图函数，返回一串 Hello World!</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.http import HttpResponse

def index(request):
    return HttpResponse(&#x27;Hello World!&#x27;)
</code></pre><p>上面这个 index 函数可以说是一个最简单的视图函数了，实际大部分应用的视图要比这复杂得多。Django 同时支持 基于函数的视图（FBV，Function-based View）和 基于类的视图（CBV，Class-based View），这里显然是 FBV，接收一个 request 请求对象作为参数，返回了一个 HttpResponse 对象</p><h3 id="">将视图接入路由</h3><p>接着，我们要让路由系统能够访问到刚才写好的视图函数。因此先实现子应用 news 的路由表，创建 news/urls.py 文件，内容如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.urls import path
from . import views

urlpatterns = [
    path(&#x27;&#x27;, views.index, name=&#x27;index&#x27;),
]
</code></pre><p>每一个 Django 路由表模块（urls.py）中都约定必须包含一个 urlpatterns 列表用来存放路由映射表。列表中每个元素是一个用 django.urls.path 函数封装好的路由映射，通常接收以下三个参数：</p><ul><li>route：必须，实际的访问路由; 空字符串等于 /，空路由</li><li>view：必须，该路由将要访问的视图</li><li>name：可选，该路由的名称，方便后续在模板中使用</li></ul><p>我们将刚刚写好的 news 路由表接入全局路由表。由于我们希望新闻能够展示在首页（即通过 / 就能访问，无需 /news），因此 news 应用路由在全局路由中的 URL 是一个空字符串。在 django_news/urls.py 中修改，内容如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path(&#x27;admin/&#x27;, admin.site.urls),
    path(&#x27;&#x27;, include(&#x27;news.urls&#x27;)),
]
</code></pre><p>这里使用 django.urls.include 函数将 news 应用的路由表接入进来，并且 include 函数的参数是路由模块路径的字符串 news.urls，省去了手动 import 的麻烦</p><p><strong>添加路由规则时顺序是很重要的，因为在尝试匹配时会按照从上到下的顺序进行，因此应该把最模糊的路由（即空路由）放在最下面。</strong></p><p>如果你的开发服务器还在运行（如果没有可以再打开），访问 localhost:8000，就可以看到一串熟悉的字符了
<img src="https://raymq.com/api/v3/objects/image/6bsrytiwiwwpaox3rq.png"/></p><h1 id="">总结</h1><p>这一篇，主要讲解了一些 APP 的概念，以及路由的概念，以及如何编写一个视图并通过路由从而在网页进行体现</p><p>整体流程就是：news/view.py ——&gt; news/urls.py ——&gt; django_news/urls.py</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/django/django2#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/django/django2</link><guid isPermaLink="true">https://raymq.com/posts/django/django2</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Fri, 31 Jul 2026 01:00:00 GMT</pubDate></item><item><title><![CDATA[（四）理解模型 Model]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/74gcg1c9jcmh7sr50z.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/bf7xn9hclvznamqy1j.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/lxjidfjzths98rwydm.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/ndkuziuqics7m9jh14.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/mqpex0w3uts4x8gq85.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/ub0w5szpzwi99vs6cf.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/django/django4">https://raymq.com/posts/django/django4</a></blockquote><div><p>Django 的 MTV，我们已经讲了 T（Template）和 V（View），现在来到了最后一：M（Model）</p><p>数据模型是 Django 入门最大的难点，消化这一步的内容就需要花点力气了。下面我们先介绍一下 Django 的数据模型设计</p><p>Django 在数据模型方面的设计堪称典范，列举一些闪光点：</p><ul><li>由于高度解耦的设计，可轻松切换各种关系型数据库（默认的 SQLite，可选 MySQL、PostgreSQL、Oracle 等等）</li><li>强大的 ORM（Object Relation Mapping，对象关系映射）模块，使得用 Python 操作数据库非常轻松，免去了使用 SQL 的麻烦</li><li>优秀的数据库迁移机制（Migration），修改数据模式（Schema）比较方便，能够适应不断变化的功能需求</li></ul><p>我们暂且选择默认的 SQLite 数据库，省去了配置数据库的烦恼</p><h1 id="-orm">理解 ORM</h1><p>如果你写过 c++ 或 go ，对于 ORM 来说应该是不陌生的，ORM 能够将面向对象的代码转换成相应的 SQL 语句，从而对数据库进行操作</p><p>SQL 是用于访问和处理数据库的标准的计算机语言，但是直接写在代码里面显然难以维护，而且对使用者的要求也非常高，写的糟糕的 SQL 代码查询效率非常低下。因此，使用设计良好的 ORM 不仅让代码可读性更好，也能帮助开发者进行查询优化，节省不少力气</p><p>来看一些简单的 Django ORM 例子：</p><pre class="language-python lang-python"><code class="language-python lang-python"># 查询所有模型
# 等价于 SELECT * FROM Blog
Blog.objects.all()

# 查询单个模型
# 等价于 SELECT * FROM Blog WHERE ID=1
Blog.objects.get(id=1)

# 添加单个模型
# 等价于 INSERT INTO Blog (title, content) VALUES (&#x27;hello&#x27;, &#x27;world&#x27;)
blog = Blog(title=&#x27;hello&#x27;, content=&#x27;world&#x27;)
blog.save()
</code></pre>
<h1 id="">理解数据库迁移</h1><p>数据库迁移是指将用 Django 定义的模型转换成 SQL 代码（即迁移文件），并在数据库中进行建表操作（或更新表），如图
<img height="432" src="https://raymq.com/api/v3/objects/image/74gcg1c9jcmh7sr50z.png" width="771"/>
一般开发流程如下：
1、用 Django 定义了一个新的数据模型
2、用 makemigrations 命令创建迁移文件（存储在子应用的 migrations 目录里面）
3、用 migrate 命令执行迁移
4、在开发中发现第 1 步中定义的模型不完善，更新数据模型
5、跳转到第 2 步，反复循环</p><h1 id="">实现一个数据模型</h1><p>在 news/models.py 中定义数据模型 Post ，包括标题 title 字段和 content 字段，代码如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()

    def __str__(self):
        return self.title
</code></pre><p>创建数据迁移文件：</p><pre class="language-python lang-python"><code class="language-python lang-python">python3 manage.py makemigrations

# 输出:
Migrations for &#x27;news&#x27;:
  news/migrations/0001_initial.py
    - Create model Post
</code></pre><p>并且成功地自动创建了 news/migrations/0001_initial.py 迁移脚本，开始数据迁移</p><pre class="language-python lang-python"><code class="language-python lang-python">python manage.py migrate
</code></pre><p>输出如下
<img src="https://raymq.com/api/v3/objects/image/bf7xn9hclvznamqy1j.png"/></p><p>数据迁移完后，创建数据库迁移完成后，我们就可以创建用于登录后台管理的超级用户：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">python3 manage.py createsuperuser
</code></pre><p>按照提示填写用户名和密码即可，然后访问 localhost:8000/admin，进入后台系统的登录页面：
<img src="https://raymq.com/api/v3/objects/image/lxjidfjzths98rwydm.png"/>
可以看到一个奇怪的事，我们明明创建了 news 应用还有 Post 模型，为什么没有显示呢？</p><h1 id="">配置后台管理接口</h1><p>因为我们没有实现 news 应用的后台管理接口，在 news/admin.py 中写入：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.contrib import admin
from .models import Post

admin.site.register(Post)
</code></pre><p>再次访问 localhost:8000/admin 就可以看到 news 应用和 Post 模型了：
<img src="https://raymq.com/api/v3/objects/image/ndkuziuqics7m9jh14.png"/>
点击 Posts 一栏的 +Add 按钮，开始添加新闻：
<img src="https://raymq.com/api/v3/objects/image/mqpex0w3uts4x8gq85.png"/></p><h1 id="">视图中添加数据查询</h1><p>最后，我们在视图中加入从数据库中查询的代码，代码如下，对伪数据进行替换即可：</p><pre class="language-python lang-python"><code class="language-python lang-python">from django.shortcuts import render
from .models import Post

def index(request):
    context = { &#x27;news_list&#x27;: Post.objects.all() }
    return render(request, &#x27;news/index.html&#x27;, context=context)
</code></pre><p>访问 localhost:8000 就可以看到刚才在后台管理系统添加的新闻
<img src="https://raymq.com/api/v3/objects/image/ub0w5szpzwi99vs6cf.png"/></p><h1 id="">总结</h1><p>通过这四篇的教程，我们已经成功做出了一个简陋的 新闻发布网站，并且可以从 后台管理系统中添加新闻，最终展示到我们的网站首页上</p><p>希望这份专栏能够让你对 Django 里最重要的一些概念和操作有基本的了解</p><p>Django 还有很多很多的高级玩法，例如数据模型中的高级查询、字段索引、更换数据库等等，模板中的继承机制、内部标签等等，还有视图中如何处理各类请求（POST、PUT等），这些内容或许我不会出，但如果你对 Django 感兴趣，希望你能够主动去了解 学习</p><p>愿诸君顺遂</p></div><p style="text-align:right"><a href="https://raymq.com/posts/django/django4#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/django/django4</link><guid isPermaLink="true">https://raymq.com/posts/django/django4</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Fri, 31 Jul 2026 01:00:00 GMT</pubDate></item><item><title><![CDATA[IaaS、PaaS、SaaS 是什么？]]></title><description><![CDATA[<link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/agd1rktf6wi28vas0h.png"/><link rel="preload" as="image" href="https://raymq.com/api/v3/objects/image/bz89l8gphz66ihmio1.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/posts/cloud-native/iaas-paas-saas">https://raymq.com/posts/cloud-native/iaas-paas-saas</a></blockquote><div><h1 id="">序言</h1><p>今天我们来讲讲 IaaS、PaaS、SaaS</p><p>原因是今天配环境的时候，mt 给我发了一句 
<img alt="IaaS、PaaS、SaaS" height="194" src="https://raymq.com/api/v3/objects/image/agd1rktf6wi28vas0h.png" width="500"/>
emmm，说实话，我对这三个 aas 的理解来自于大二上学习 <strong>云计算</strong> 这门课，是为了应付考试刷了很多次题库，理解始终处于一种非常浅显的理解。</p><p>PaaS：平台即服务
SaaS：软件即服务
IaaS：基础设施即服务</p><p>我当时理解的其实就这么多，而对于 平台、软件 对应的服务是什么不知道。
å
希望阅读完以下内容，能让你对这些服务有基本的了解。</p><h1 id="">正文</h1><p>IaaS、PaaS、SaaS 是云计算的三大服务模式，分别代表 <strong>基础设施、平台和软件的服务化</strong>。
它们在资源管理、用户操作、应用开发等层面抽象程度不同，适用场景和用户角色也各有侧重。</p><h2 id="iaas">IaaS</h2><p><strong>IaaS：Infrastructure as a Service、基础设施即服务</strong>。为用户提供底层计算、存储、网络等基础资源，用户可以按需租用虚拟机、存储空间、网络等硬件资源，无需自建数据中心。用户负责在这些资源上安装操作系统、部署应用，拥有较高的灵活性和控制权。</p><p>看到这些，大家应该就能轻松想到，我们平常看到的各种云服务器。比如 AWS EC2、阿里云 ECS、OpenStack 等，就属于 IaaS。适用于需要高度定制化、对底层资源有特殊需求的企业或开发者。</p><p>它的优势：弹性扩展、资源利用率高、自动化运维；劣势：用户需自行管理操作系统、应用环境，运维压力较大。</p><p>这里你可能会有些迷糊，为什么已经是自动化运维了，还会存在用户运维压力较大呢？</p><p>本质上是，IaaS 卖的是基础设施的运维。</p><p>比如你的 云服务器 的物理机硬盘暴了，它能做到自动数据迁移；你设置好了访问流量策略，人多时加机器扩容，人少时缩容。而这些都是云厂商自动帮你做的，当你看到信息前你是无感的。</p><p>而用户的运维压力源自于，云厂商提供给你的是一个虚拟机，这台机器的系统你需要自己搭、端口开放策略自己决定、性能压力很大你需要自己排查（这里为什么不是自动扩缩容，因为云厂商只保证物理机性能没被别人抢走）</p><p>简单来说：<strong>IaaS 就是你租一个毛坯厨房（虚拟机），里面有水电气。然后就没了，什么锅啊、灶台啊、菜啊，自己想办法去。并且设备坏了，call 给云厂商给你换，但是你又得重新装修。</strong></p><h2 id="paas">PaaS</h2><p><strong>PaaS：Platform as a Service，平台即服务</strong>。 PaaS 在 IaaS 之上进一步抽象，提供应用开发、运行、管理所需的平台环境，包括数据库、中间件、开发框架、容器管理等。开发者只需关注应用代码，无需管理底层硬件和操作系统。</p><p>说白了，就是将底层硬件进行封装，使用可视化界面进行底层硬件管理。我们常见的 xx后台管理系统，就类似于PaaS。</p><p>比如 Google App Engine、Heroku、蓝鲸PaaS平台、OpenShift 等，就属于 PaaS。适用于快速开发、部署、迭代应用的场景，尤其是中小团队或需要敏捷开发的企业。（敏捷开发就是迭代速度要快</p><p>优势：开发效率高、自动化部署、资源弹性、运维简化；劣势：平台限制较多，部分场景下对底层资源的控制有限。</p><p>这里的平台限制，很好理解，就是固化。我平台只支持 python 3.9，我的代码使用了 3.12 的异步，部署到平台上，发现运行不了，你怎么解决？只能降级，因为平台不是你的，升级版本可能就是个把月后才会做的。</p><p>简单来说：<strong>PaaS 就是你租了一个标准的中央厨房（应用运行环境），灶台（操作系统）已经砌好，锅（数据库/中间件）已经架上，甚至连切好的葱姜蒜（常用依赖库）都给你装在小碗里了。但是，可能中央厨房会限制你每道菜烹饪时间为 xx分钟，你要是文火煲个鸡汤，你吃的没准还是生的。</strong></p><h2 id="saas">SaaS</h2><p><strong>SaaS：Software as a Service，软件即服务</strong>。SaaS是最高层的云服务，直接向用户提供完整的软件应用（比如邮箱、CRM、ERP、协同办公等），用户无需开发、部署、维护，只需通过浏览器或客户端使用就行了。</p><p>常见的就是 Salesforce、飞书、企微、蓝鲸SaaS应用等。适用于对IT能力要求低、希望快速上线业务的企业和个人。</p><p>优势：即开即用、无需运维、按需付费、升级维护由服务商负责；劣势：定制能力有限，数据安全需依赖服务商。</p><p>这就涉及到数据安全的问题了，hh，虽然小公司的数据不是什么非必要的数据......</p><p>简单来说：<strong>SaaS 就是你直接点外卖，然后吃就可以了</strong></p><h1 id="">结语</h1><p>这三种模式，在我看来就是一句话：降低技术门槛，让业务更加简便。</p><p>不知道各位看完后，是否对这三个模式有了基础的了解。</p><p>最后我想说一些额外的话，可能大家对于这些东西，会有疑问，说：我一定要学这东西吗？好多内容，我要不要都记住？</p><p>我的回答是：不需要，你只需看过，有印象，就够了。</p><p>最后附上一张 <a href="https://bk.tencent.com/docs/markdown/ZH/PaaS/2.12/%E4%BA%A7%E5%93%81%E7%99%BD%E7%9A%AE%E4%B9%A6/%E4%BA%A7%E5%93%81%E6%9E%B6%E6%9E%84%E5%9B%BE/Architecture.md">蓝鲸产品架构</a>
<img alt="蓝鲸产品架构" src="https://raymq.com/api/v3/objects/image/bz89l8gphz66ihmio1.png"/></p><p>愿诸君顺遂。</p></div><p style="text-align:right"><a href="https://raymq.com/posts/cloud-native/iaas-paas-saas#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/posts/cloud-native/iaas-paas-saas</link><guid isPermaLink="true">https://raymq.com/posts/cloud-native/iaas-paas-saas</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Thu, 23 Jul 2026 15:15:52 GMT</pubDate></item><item><title><![CDATA[计算机学习路线及个人心得]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://raymq.com/notes/4">https://raymq.com/notes/4</a></blockquote><div><p>大家好，我是 Ray。今天想和大家聊聊计算机专业，包括学习路线以及我个人的心得。</p><p>本人 bg 民办本准大三，目前在一家小厂实习，base 深圳做后端开发。因为我还没完整地经历大学四年，所以对于大三、大四应该怎么去学习，我没有一个绝对正确的看法。我只能根据自己的经历、身边同学的状态，以及对就业和考研的观察，谈谈我目前的想法。也因为学历问题，文中有些绝对性的话语只是针对我个人而言，还请各位多见谅。</p><p>到现在我越来越觉得，<strong>大学不存在一条绝对正确的学习路线。</strong></p><p>有人大一开始打竞赛，有人大二才接触开发；有人很早就进入实验室，有人到了大三才确定方向；有人选择就业，有人选择考研。真正重要的，并不是你一定要去复刻某个优秀学长的路，而是<strong>你有没有找到一条适合自己的路线，并且持续推进下去。</strong></p><p>很多人痛苦，是因为大一就用大四的就业压力折磨自己，大二就拿别人的实习经历审判自己，大三又因为过去两年没有完美规划而否定自己。我也经历过这种状态，每个阶段所面对的问题是不同的，不应该用同一种目标去硬套自己。</p><h1 id="-">一、 大一</h1><p>刚进入大学时，你会接触到很多事情：学生会、社团、班委、比赛、绩点、奖学金、谈恋爱、游戏，以及各种看起来必须参加的活动。大学当然可以丰富多彩，我没有资格决定别人应该怎么度过。我能做的只是根据自身的情况，对那些在计算机这条路上还处于迷茫阶段的人，给出一些建议。</p><ul><li><strong>社交活动：</strong> 如果你的目标是毕业后直接就业，那么学生会、班委和很多比赛活动，是完全没有必要的（比如大创、职规赛……）。这些事情在就业层面的价值极低，却会占用你大量白天没课的时间、晚上和周末的时间，甚至于你的寒暑假。当然，参加与否取决于你，只是我不太推荐。（如果你是92或者学校硬实力强，可以参与，<strong>重点是认识人而不是参与比赛</strong>）</li><li><strong>绩点：</strong> 如果你准备保研、考研、出国，或者毕业想进央国企（机关或者二级等单位比较看重学校经历），那么绩点非常重要。如果你主要准备大厂、私企就业，绩点不是决定性因素，<strong>只要不挂科就行</strong>。当然，这里的不挂科意味着你的成绩和你的平时分都不能太低。把更多时间放到技术学习、项目、面试准备上，不要为了一个并不影响目标的高分，牺牲大量可以用于提升专业能力的时间。
<br/>大一最重要的是，确定：<strong>你能不能静下心下来学习。</strong> 确定你能不能接受一个报错卡住自己半天，能不能主动搜索资料，能不能沉下心阅读又臭又长的文档，能不能在学完之后留下笔记，能不能在遇到困难时，不放弃地继续往下推进。</li></ul><p><strong>只有开始行动，你才会获得反馈。没有行动时，所有选择都只是想象。</strong></p><h2 id="1-">1. 方向探索</h2><p>如果你对竞赛、实验室或者学校项目没有明显兴趣，那么大一可以用一段时间探索开发方向。从入学开始，我认为<strong>一个月左右的时间去集中探索</strong>，通常已经足够让你对几个主要方向形成初步认识。</p><p>你可以去了解不同语言对应的岗位和应用场景，例如：</p><table><thead><tr><th> <strong>语言</strong>      </th><th> <strong>常见岗位与应用场景</strong>         </th></tr></thead><tbody><tr><td> <strong>Java</strong>    </td><td> 后端开发、企业级应用            </td></tr><tr><td> <strong>C++</strong>     </td><td> 嵌入式、音视频、游戏开发、客户端、后端开发 </td></tr><tr><td> <strong>Go</strong>      </td><td> 云原生、基础设施、后端开发         </td></tr><tr><td> <strong>JS / TS</strong> </td><td> 前端开发、全栈开发             </td></tr><tr><td> <strong>Python</strong>  </td><td> 数据处理、自动化、人工智能、部分后端场景  </td></tr></tbody></table><p>你不用一上来就去死记每门语言怎么写，你只需要收集起来：对应语言所做的岗位具体是干什么的，需要纵向深入的技术栈有哪些就行了。</p><p>选择方向时，需要同时考虑<strong>兴趣、岗位数量、学习难度和自身条件</strong>。方向确定后，至少坚持一段时间。<strong>频繁更换语言和技术栈，会让你一直停留在入门阶段。</strong> 每次换方向时都觉得自己学到了新东西，但实际上只是把同一道门槛反复跨了多次，始终没有真正迈过去。</p><p>比如选择 C++，你可能会面对嵌入式、音视频、Qt、游戏开发、后端等方向，不同方向的岗位数量差距较大，并且存在”生殖隔离“。（如果你是做音视频的，那你的纵向技术不能支撑你去做嵌入式）我接触到的大部分学 C++ 的人，主要选择 Qt、嵌入式或者硬件相关方向。纯 C++ 后端岗位相对少，通常集中在大厂，对基础和算法要求也更高（比如腾讯 wxg、网易雷火……）。这并不是说不能选择 C++，而是选择之前要了解对应的市场。方向没有高低，但存在岗位数量、竞争难度和学习成本的区别。</p><p>后面我会出两篇关于 C++ 和 Go 的学习路线。当然，最终的方向需要你自己决定。</p><h2 id="2-">2. 算法竞赛</h2><p>这里单指算法竞赛，比如 ICPC (ACM)、CCPC、蓝桥杯、天梯赛等。其余的，类似于大创赛等，我个人不敢恭维。</p><p>算法竞赛的好处是能实打实地提高你的算法能力，坏处是门槛较高，个人天赋决定了你的上限，但努力能拉高你的下限。竞赛是个不错的选择，如果你有中大厂梦，算法通常无法完全避免。未来面试中的算法题会不会被 AI 场景题取代我不知道，但至少目前来看，算法依然是很多中大厂筛选候选人的硬性方式之一。</p><h3 id="">自己摸索出的竞赛路线</h3><ol start="1"><li><strong>语言基础：</strong> 一般我会推荐 C++，因为 STL 库很方便（当然 Python 也可以）。学习基础的语法，比如输入输出，for、while、if，数组，结构体，字符串等（这里大家可以去买课，或者 B 站找。我当时是看<strong>英雄从哪出来</strong>的知识星球，付费的，纯分享不是广）。这里必须做到：<strong>所有代码必须由自己亲手敲一遍，不容商量。</strong></li><li><strong>刷题：</strong> 将基础的语法学完就可以去刷题了。去洛谷，从 B2001 开始，刷大概 150 多道题，大概刷到 B2150 左右吧。这一步是为了让你熟悉，基础语法是怎么解决实际问题的（虽然并不是真的实际生产问题），主要是练习“怎么将文字逻辑转换成代码”的能力。</li><li><strong>基础数据结构：</strong> 比如数组、链表、栈、队列、哈希表、树、图等。这里也必须做到：<strong>所有代码必须由自己亲手敲一遍，不容商量。</strong> 学完一个模块，可以去力扣或者洛谷刷对应的题目。对于图这种抽象的东西，我个人觉得学习成本过高了，可以适当推迟。</li><li><strong>STL 库：</strong> 比如 vector 、queue、stack、map 等。这一步见仁见智，有的人先学 STL 再学数据结构。但我认为<strong>先学数据结构比较好</strong>，因为 STL 也是封装好的数据结构，只是调用暴露的底层接口而已，有了数据结构基础，会更好理解 STL。同样，学完一个模块，刷对应的题。</li><li><strong>核心算法：</strong> 比如经典的十大排序，DFS、BFS，贪心，滑动窗口等。这一块大家可以去力扣看</li></ol><ul><li><a href="https://leetcode.cn/u/endlesscheng/">灵山茶艾府</a>，这个佬非常 nb，B 站有课，力扣个人题库相辅相成；</li></ul><p>或者</p><ul><li><a href="https://labuladong.online">labuladong</a>也是很有实力的佬，题库什么的也很全。</li></ul><p>这一块我没有什么更高深的见解，因为我涉及得不深，在竞赛方面我属于“痴呆”级别的，只参加过蓝桥杯，混了个三等奖就没继续学了。但以上路线可以当作各位入门算法的路线。</p><p>因为部分竞赛周期较长（比如 ICPC 从每年 9 月持续到次年 6 月，跨度近一年）。这就导致很多同学刚入学，在缺乏充分训练的情况下，要么无法通过校内选拔进入校队，要么参赛后难以取得理想成绩。如果你想打竞赛，就要做好准备——学习开发的时间或许得到大二下或者大三才能开始。好处是对于面试手撕，你可能会如鱼得水；坏处是算法与实际开发是截然不同的两条路线，大部分算法知识在常规业务开发中应用有限，<strong>投入产出比需要你自己权衡。</strong></p><h2 id="3-">3. 计算机四大件</h2><p>大一也是接触四大件最合适的时候，很多散播焦虑的视频天天在讲四大件。说实话，在日常业务开发中，四大件的底层原理对绝大多数开发者的日常工作影响不大。绝大多数人学习它们，是为了应付面试、考研或期末考试的。</p><p>通常所说的计算机四大件，包括：</p><ul><li>数据结构与算法</li><li>计算机网络</li><li>操作系统</li><li>计算机组成原理</li></ul><p>大一没有必要同时深入学习所有内容。对于刚开始接触开发的学生，可以<strong>优先学习数据结构与算法、计算机网络和基本编程知识，操作系统随后，计组最后</strong>。</p><ul><li><strong>数据结构与算法：</strong> 在学习时必须要做到代码必须经由你手去敲（这里可以参考我上面写的竞赛路线）。</li><li><strong>计算机网络：</strong> 能够帮助你理解客户端、服务器、HTTP、TCP/IP、端口、DNS、代理和负载均衡等开发中经常出现的概念。它是必学的。</li><li><strong>操作系统（OS）：</strong> 权重其实也很高，但可以适当放缓进度。因为在绝大多数实际业务开发中，我们使用的都是已经封装好的库（比如进程、线程、并发锁等），它在日常中更偏向于面试中的八股文。有精力的话，可以去深入了解其源码实现。</li><li><strong>计算机组成原理（计组）：</strong> 抽象程度极高，在刚学开发时优先级较低，看个人选择，我不太推荐。</li></ul><h2 id="4-">4. 大学生活</h2><p>大学当然不应该只有学习。游戏可以玩，社交可以参加，恋爱也可以谈。没有人能够一直保持高强度学习。</p><p>这里我主要讲谈恋爱……<strong>大一是你脱单的，最优时间，往后会越来越难......</strong></p><p>好的关系能够让两个人都轻松愉快，错误的关系也可能大量消耗时间和精力。所以<strong>恋爱并不是重点，关系质量才是重点</strong>（关系质量也可以延伸到交友这方面）。如果两个人能够互相支持、尊重彼此的目标，并且在一起之后都变得更稳定，那么这段关系是有价值的。如果一段关系长期让你痛苦、焦虑、内耗，甚至无法正常学习和生活，那么<strong>离开，是比勉强维持而言，最佳的决策。</strong></p><h1 id="-">二、 大二</h1><p>大二开始，焦虑会变得更加具体。如果大一什么都没有做，和我一样，那么你可能会突然发现，身边的人已经开始向不同方向推进：有人在算法比赛夺得头筹，有人开始做项目，有人刷力扣和背八股，有人在社交平台展示简历，甚至有人在大二上就拿到了实习 Offer。</p><p>而自己可能还在反复学习基础知识。这时候心理很容易失衡，会觉得自己学不会、找不到实习，甚至觉得自己没有价值。你也可能会产生一些不正常的比较心理：我明明成绩比他好，为什么他能获得荣誉？我明明比他努力，为什么他已经找到实习？为什么别人学得这么快，而我还在原地？</p><p>这种状态很常见。但<strong>别人获得什么，并不会减少你拥有的东西。</strong> 你真正能控制的，只有自己今天做了什么，当前方向推进到了什么程度，以及下一步准备干什么。</p><p>大二应该做的，是找到一个能够持续推进的方向，并且<strong>开始形成可以交付的能力。</strong> 所谓交付能力，就是你不只是看过课程、记过笔记、听懂概念，而是真的能够通过所学知识完整地完成一个东西。</p><p>现在 AI 非常给力，你完全可以通过 AI 去辅助实现。你可以在提出需求，与它讨论，从而构建项目。项目可大可小，重要的是你需要知道：需求是什么、结果是什么，逻辑怎么转换、数据如何存储、程序如何运行、出现问题怎么排查，最终如何部署或者展示。</p><p>确定方向后，需要问自己一个问题：<strong>我是否愿意接受这个方向的困难，并且持续走下去？</strong></p><p>这个过程会很煎熬。你会反复遇到看不懂的代码、无法解决的报错、复杂的环境配置、不熟悉的项目结构，以及大量不知道有什么用的概念。这就是学习的一部分，你无法避免。于我而言，我的学习路线也非常弯曲。具体经历可以看我的博客 raymq.com 的<strong>碎碎念（一）</strong>，里面记录了我这两年的学习过程。</p><h2 id="1-">1. 准备较早、计划尽早实习的人</h2><p>如果你在大一已经开始学习，并且经过一年时间对开发有了基础认识，那么大二上可以开始准备以下内容：</p><ul><li>个人项目</li><li>一份简历</li><li>刷算法题</li></ul><p>大二下学期就可以开始在 Boss 等平台投递简历了。<strong>投递不代表一定能够马上进入公司，投递本身就是一种最好的市场反馈。</strong> 如果简历已读不回，可能是学历、项目描述或简历表达存在问题，也可能是大环境确实太卷了或者不招大二的，无论哪种，投递本身都在帮你缩小问题的范围；如果笔试过不了，说明算法或者基础知识存在问题；如果面试中说不清项目，说明项目理解不够深入。<strong>越早接触市场，越早知道自己缺什么。</strong></p><h2 id="2-">2. 不准备过早实习的人</h2><p>不是所有人都必须在大二下找到实习。如果大二时你的技术体系还没有完全形成，或者想多体验体验校园生活，也可以到大三再准备实习。大三下实习在时间上并不算晚。如果前两年你有一一直在持续学习，那么大三大概率是有足够基础储备的，可以去做项目、准备面试和投递岗位了。不需要担心是否找得到，如果你真的有做到持续学习，那你必然不可能找不到，通常只是时间问题。</p><p><strong>关键不是必须在某个固定时间点去实习，而是不要一直停留在“原地准备”的阶段。</strong> 有些人从大一开始看教程，到了大三仍然觉得自己还没有准备好。但很多能力，只有在做项目、投简历和参加面试受挫时，才能真正获得。</p><h1 id="-">三、 大三与大四</h1><p>大三、大四我还没有亲身完整经历，所以就简单说一说我的观察，源于学习群以及身边大三、大四同学的真实状态。到了大三，一部分人准备就业，一部分人准备考研，一部分人准备考公、留学或者其他方向。</p><p>这个时候，<strong>最消耗人的状态是长期在两个方向之间左右摇摆。</strong></p><p>一边准备考研，一边羡慕别人实习；一边准备就业，一边担心自己学历不够；今天刷数学，明天做项目，后天又开始查考公资料。看起来每天都很忙，但没有任何一条路线获得了足够的有效投入。
<strong>选择可以调整，但你不能永远不做出决定。</strong></p><h1 id="-">四、 建立自己的学习节奏</h1><p>我最近看到一句话：“你可以在两周内学会任何东西。” 这里的“学会”当然不是精通，也不是两周之后就能成为这个领域的佼佼者，<strong>你克服了未知的恐惧，变得比大多数完全不懂的人更加擅长它。</strong> 和学车一样，起步总是难的，油门是不敢踩的，路是不敢上的......</p><p>很多改变不是因为天赋突然出现，而是因为你认真给某件事情分配了很多的时间与精力。我认为这句话有一定道理，但它不能被用来压榨自己。因为<strong>人总是高估一天能够完成多少事情，却低估一年能够积累多少东西。</strong> 一天没有学完，不代表失败；两周没有精通，也不代表没有收获。</p><p>真正有价值的是，你能不能在一年里反复经历这种小周期：</p><p>选择一个目标  —&gt;  学习  —&gt;  做出结果  —&gt;  发现问题  —&gt;  复盘调整</p><p>然后，进入下一个周期。</p><p>你想拥有你从未有过的东西，那么你必须去做你从未做过的事情。改变通常不是靠某一天突然爆发，而是不断让自己进入新的领域。但进入新领域并不等于每天都要把自己逼到极限。很多人能够连续高强度学习三天，却无法坚持三个月。</p><p><strong>真正拉开差距的，通常不是某一天学习了 12 个小时，而是在很长一段时间里，你的那根线没有彻底断掉。</strong></p><h1 id="-">五、 焦虑与自己</h1><p>这一部分，我想聊聊焦虑与自己。</p><p>我认为很多的焦虑来自于比较，<strong>信息茧房里的畸形比较</strong>。刷牛客，会觉得高手太多；刷抖音、小红书，会看到别人大一下就进大厂、拿高薪、参与顶级开源、获得各种比赛金奖；在学习群聊天，会觉得大家学历又好、Offer 又多，但就是喜欢串......看 AI 写代码，又觉得自己一点竞争优势都没有。</p><p>于是我们陷入一种很难受的内耗状态：<strong>学习时觉得自己太慢，休息时觉得自己浪费时间，做项目时觉得项目太 low，找实习时又觉得自己不配。</strong></p><p>这种比较背后，其实是巨大的同龄人压力。最痛苦的不是别人真的比你强，而是<strong>你每天都在用别人的结果，去审判你自己的过程。</strong></p><p>别人拿到 Offer，你会忘记他背后可能投递了几百份简历、被拒绝了无数次；别人展示完美的项目截图，你会忘记他可能为了一个 Bug 熬夜、踩坑；别人说自己学会了一项技术，你会默认他已经精通。</p><p>信息流通常只展示成果结果，不展示代价。我们看到的不是一个完整的人，而是一段被硬生生截取出来的成功片段。</p><p>同时，环境也会放大这种压力。如果一个环境里大家都在讨论绩点、比赛、实习、大厂和薪资，你很难完全不受影响；如果身边的人都在摆烂，你也很难长期保持上进；<strong>如果身边的人都在焦虑，你甚至可能因为自己“不够焦虑”而感到焦虑。</strong> 环境会影响一个人的默认选择，你每天看什么、听什么、和谁交流、把什么当成正常，最后都会逐渐影响你的价值观。</p><p>但环境并不是完全无法改变的。如果没有很好的同学、导师、伴侣或者公司环境，<strong>也可以尝试为自己创造一个小环境：</strong> 固定记笔记、写文章、写代码，和比自己厉害的人进行交流（这里推荐b站 <strong>爱学习的小q</strong>，q老师麾下的学习群非常权威，92、留子如过江之鲫）。环境可以影响人，但人也可以逐步筛选和重建环境。</p><p>二十多岁，是一个人从校园向社会过渡的阶段。社会关系、生存能力、职业方向和财富积累，都像是在从零开始构建。你会发现时间不够、精力不够，判断力也不够。以前只需要准备期末考试，现在每个选择都像会深刻影响未来的几年：要不要考研、要不要实习、要不要换方向、要不要去大城市、要不要继续深入某项技术。</p><p>在这种精力与判断力都捉襟见肘的时期，<strong>更需要保护好自己的注意力。</strong> 如果一段关系、一个圈子或者一种信息流会持续消耗你，让你无法学习、行动和正常生活，那么离开，是一个非常明智的选择。</p><p>认识自己，不仅仅是知道自己喜欢什么、适合什么，<strong>还需要知道自己什么时候容易被影响。</strong> 知道自己什么时候会因为攀比打乱节奏，什么时候会因为同龄人压力做出不属于自己的选择。</p><p>没有 Offer 时焦虑，有了 Offer 之后也焦虑；找实习前觉得有一份就不错，找到后又觉得和想象中不一样；入职前担心自己不够格，入职后又开始担心环境、导师、技术栈和未来的职业规划。人好像永远在为下一个阶段焦虑，永远想直接跳过二十多岁的生长过程。但这个过程，我们无法避免。</p><p>成长不只是找到一份工作，也不只是学会一门技术。它还包括不断重新理解自己：<strong>我能承受什么，我害怕什么，我愿意为什么投入时间，我不愿意继续被什么消耗。</strong> 焦虑不会因为获得某个结果就彻底消失，它只会换一种形式重新出现。</p><p><strong>所以，比起追求完全不焦虑，更现实的是：学会带着焦虑，继续行动。</strong></p><h1 id="-">六、 总结</h1><p>以我的经历来看，像我这样的人，最重要的不是突然变成天才，而是<strong>不要彻底断掉</strong>。</p><p>从入学到现在，我也有因为学历不好而自甘堕落的时候，有沉迷游戏的时候，有计划打乱的时候，有依赖 AI 快速学习之后感到心虚的时候，也有刚进入公司后看不懂项目代码、甚至手足无措的时候。但回头看，真正让我继续向前的，不是某一次突然开悟，而是一次次把自己拉回正轨，继续学习，继续记录。</p><p>计算机这条路，很少有一劳永逸的胜利。它更像是，不断把“不懂”变成“稍微懂一点”、把“稍微懂一点”变成“我理解了”，最后把“我理解了”变成“能够解释给别人听”。</p><p>对于普通人来说，真正能够依靠的，通常不是某个突然出现的好运，而是在很长一段时间里持续积累，并且<strong>没有彻底停下来</strong>。</p><p>这条路不浪漫，也不轻松，但它足够真实。</p><p>愿诸君顺遂。</p></div><p style="text-align:right"><a href="https://raymq.com/notes/4#comments">览毕，何不一言？</a></p></div>]]></description><link>https://raymq.com/notes/4</link><guid isPermaLink="true">https://raymq.com/notes/4</guid><dc:creator><![CDATA[ray]]></dc:creator><pubDate>Sun, 12 Jul 2026 09:18:00 GMT</pubDate></item></channel></rss>