<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Service on 小杨的博客</title><link>https://luckycloveryh.github.io/fuyou/tags/service/</link><description>Recent content in Service on 小杨的博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>小杨</copyright><lastBuildDate>Mon, 06 Apr 2026 17:19:50 +0800</lastBuildDate><atom:link href="https://luckycloveryh.github.io/fuyou/tags/service/index.xml" rel="self" type="application/rss+xml"/><item><title>10 - Service、Ingress - 找到你并不容易</title><link>https://luckycloveryh.github.io/fuyou/p/k8s-service-ingress-replica/</link><pubDate>Mon, 06 Apr 2026 17:19:50 +0800</pubDate><guid>https://luckycloveryh.github.io/fuyou/p/k8s-service-ingress-replica/</guid><description>&lt;img src="https://cdn.jsdelivr.net/gh/luckycloveryh/picgo-bed@main/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20260524195307_536_12.jpg" alt="Featured image of post 10 - Service、Ingress - 找到你并不容易" />&lt;h2 id="service">Service
&lt;/h2>&lt;h3 id="什么是-service">什么是 Service
&lt;/h3>&lt;p>在 Kubernetes 集群里 Pod 的生命周期是比较“短暂”的，虽然 Deployment 和 DaemonSet 可以维持 Pod 总体数量的稳定，但在运行过程中，难免会有 Pod 销毁又重建，这就会导致 Pod集合处于动态的变化之中。 Pod 的 IP 地址经常变来变去，客户端该怎么访问呢？如果不处理好这个问题，Deployment 和 DaemonSet 把 Pod 管理得再完善也是没有价值的。&lt;/p>
&lt;p>其实，这个问题在业内早就有解决方案来针对这样“不稳定”的后端服务，那就是“负载均衡”，典型的应用有 LVS、Nginx 等等。它们在前端与后端之间加入了一个“中间层”，屏蔽后端的变化，为前端提供一个稳定的服务。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=YWY0OGMyYjUyMGZmNmExMTAzOGU5YjcxNTBjMjMwNTdfNkhlMUJYbGxIbE1Ed2JLQ3RkaVM1RWJpbFZ3Y2tlV0NfVG9rZW46TlhPSmJUa0Rub2VraXp4RnZKdmNiRzRRbkNjXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="使用-yaml-描述-service">使用 YAML 描述 Service
&lt;/h3>&lt;p>用命令 kubectl api-resources 查看它的基本信息，可以知道它的简称是svc，apiVersion 是 v1。注意，这说明它与 Pod 一样，属于 Kubernetes 的核心对象。&lt;/p>
&lt;p>我们就可以写出 Service 的 YAML 文件头了&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">apiVersion: v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kind: Service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">metadata:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: xxx-svc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>使用 kubectl expose 指令来创建service模板文件，需要用参数 &amp;ndash;port 和 &amp;ndash;target-port 分别指定映射端口和容器端口，而 Service 自己的 IP 地址和后端 Pod 的 IP 地址可以自动生成，用法上和Docker 的命令行参数 -p 很类似。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl expose deploy nginx-dep --port&lt;span class="o">=&lt;/span>&lt;span class="m">80&lt;/span> --target-port&lt;span class="o">=&lt;/span>&lt;span class="m">80&lt;/span> --dry-run&lt;span class="o">=&lt;/span>client -o yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">apiVersion: v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kind: Service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">metadata:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: nginx-svc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">spec:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> selector:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> app: nginx-dep
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ports:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - port: &lt;span class="m">80&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> targetPort: &lt;span class="m">80&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> protocol: TCP
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Service 的定义非常简单，在“spec”里只有两个关键字段，selector 和 ports。&lt;/p>
&lt;p>selector 是用来过滤出要代理的那些 Pod，因为我们指定要代理 Deployment，所以 Kubernetes 就为我们自动填上了 nginx-dep 的标签，会选择这个 Deployment 对象部署的所有 Pod。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MmFkZjlkMzI3ZGM3ODI3NDgwZTczMmU3MmNmZTdjNjNfVVF5N0E2SGFWSFQ0Tzd6dEd0a0lxWlF0S0Z0cTluczNfVG9rZW46UXhLWWI5eklvb1RrMEl4cVlnRmNoYXJYbmNSXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="在-kubernetes-里使用-service">在 Kubernetes 里使用 Service
&lt;/h3>&lt;p>为了方便查看 Service 的效果，我们添加一个Nginx的配置文件，使用ConfigMap来定义，通过Volume 挂载到 Pod中。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ConfigMap&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-conf&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">data&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">default.conf&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> server {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> listen 80;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> location / {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> default_type text/plain;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> return 200
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> &amp;#39;srv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\ndate: $time_iso8601\n&amp;#39;;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> }&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在 Deployment 中通过 “template.volumes”定义存储卷，使用“volumeMounts” 挂载到容器中。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">apps/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicas&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">template&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-conf-vol&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">configMap&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-conf&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">containers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx:1.22.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumeMounts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">mountPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/etc/nginx/conf.d&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-conf-vol&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>部署 Deployment 之后，就可以 kubectl apply 创建 Service 对象了&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="l">kubectl apply -f nginx-svc.yaml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>使用命令 kubectl get svc 查看对象状态&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=YjQ2ZTZmMjc2NmYyYTdiNGZkNzk1YzYwNGIzYzVmNWJfRWd6TkQzREwwUHZXQlBYWUszbkhiUmN6UzlTNkswZGVfVG9rZW46TDlYZ2JUOVlYbzZudzN4UldPZmN4V25FbklkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>Kubernetes 会自动为 Service 对象分配一个IP地址“10.111.193.124”，这个地址段是独立于Pod地址段的（在kubeadm 安装的配置文件里指定的）。Service 对象的 IP 地址还有一个特点，它是一个“虚地址”，不存在实体，只能用来转发流量。&lt;/p>
&lt;p>通过 kubectl describe 命令可以看到 Service 代理了哪些后端的 Pod：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="l">kubectl describe svc nginx-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZTg5Y2M2YzQwODg3YzExZjgyNmI3MmJjY2IwYmZkNjVfRkVSWUVxVk9zdEd3MzYxY0QwUjVnMXlRaGxrekZJcnVfVG9rZW46RDc1cmJMZll3b0k5VUh4TnBPeWNjc25ubk5mXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>通过截图可以看到 Service管理了两个 endpoint 对象，10.244.171.7:80 和 10.244.184.72:80，那这两个地址是不是实际 Pod 的地址呢？&lt;/p>
&lt;p>我们可以通过以下命令来验证&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl get pods -o wide
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZGZlNjZiMzVjMWQ2YWE2ZDYwZDhlYWJmYTQ2OGFlMWZfaTZuaEVnaTIwUmljRm5TMG1jbnprb05Ed2lHRHVZT25fVG9rZW46SW51NmJIVUpFb3o5Z3p4UkNzTGNJaVpVblJoXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>通过上面的截图我们就能够验证 Service 确实用一个静态 IP 地址代理了两个 Pod 的动态 IP 地址。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=Y2U5ZTRhOTRiZWM5Y2VkNWEzM2U1ODRiNGU4YjVmYTVfUDJDdVFVUWljNmhvVFFFT0lIUmNIeHEwV3VEVHJrNTZfVG9rZW46QXF6SWJYaHBFb3lmbjh4MEI0eWMwQ1FIbkVmXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="测试-service-的负载均衡效果">测试 Service 的负载均衡效果
&lt;/h3>&lt;p>我们使用 curl 命令在 master 节点或是 worker 节点上执行以下命令来访问 Service：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">curl 10.111.193.124
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=M2EyN2UzZmQ1ZWU3NDM5NjMyNTE0OTM5OTBmZDk3Y2Rfd3hMVEVQRU4ybDY5N3p2WG43dFY4YWpMUzdhQWpVdmFfVG9rZW46VzFtQWJEbmxSb0tnOWl4c1VVVmNwSGtSbnFoXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>用 curl 访问 Service 的 IP 地址，就会看到它把数据转发给后端的 Pod，输出信息会显示具体是哪个 Pod 响应了请求，就表明 Service 确实完成了对 Pod 的负载均衡任务。&lt;/p>
&lt;p>我们再删除一个 Pod，看看 Service 是否会更新后端 Pod 的信息，实现自动化的服务发现：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl delete pod nginx-dep-b4bfd684c-pncv8
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MDg0YmE3OWE1Y2MxMWMzZGQxMWVmNjEzMjFlZTY4YjdfQjFvb2NDOHR5MGI5R2wyWkRjOUlSMFF0cGxQeWRTNFpfVG9rZW46UEpGbGJITXVMbzBIbDB4Q0MwaWNLeDB6bm5nXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>Pod 被删除后，Deployment 对象会自动创建一个新的 Pod，Service 会实时监控 Pod 的变化，所以它也会立即更新后端代理的 Pod 地址。这样后端的 Pod 数量就可以按业务需要自由伸缩，对用户是无感的。&lt;/p>
&lt;h3 id="以域名的方式使用-service">以域名的方式使用 Service
&lt;/h3>&lt;p>Service 对象的 IP 地址是静态的，保持稳定，不过数字形式的 IP 地址用起来还是不太方便，如果要能有域名就更好了，DNS 在 Kubernetes 里能不能实现呢？&lt;/p>
&lt;p>Kubernetes 有一个插件来实现 DNS 的功能，在早期这个插件普遍使用 kube-dns，现在用 coredns 比较多。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=YjE1YzkyODJiMzk1YzI5NzYxYzczNzNmY2EwZmE4MzJfVE1wcGtOT0FJakJqSWxqWFQ5NWR5OG1UazVZYjdkbWdfVG9rZW46TnY5OWI2Q2tJb3RYdUJ4WEEyZ2M1TDh3bnhnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>因为 DNS 是一种层次结构，为了避免太多的域名导致冲突，Kubernetes 就把名字空间作为域名的一部分，减少了重名的可能性。&lt;/p>
&lt;p>Service 对象的域名完全形式是 “&lt;strong>对象名. 命名空间.svc.cluster.local&lt;/strong>”，但很多时候也可以省略后面的部分，直接写“对象名. 命名空间”甚至“对象名”也可以 。&lt;/p>
&lt;p>DNS 是在 &lt;strong>Kubernetes 集群内部生效&lt;/strong>，所以要测试需要在 Pod 内验证。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MTY0ZGVmYTRiNzg1ZjVlNGY5ODFjMDZkNzNhN2Y5YzdfNW9IOUNyaEhFS2syYnA0eExwQ1I5eUl1dnc2c0U2RndfVG9rZW46QUVFNmJtOGxrb2liNXZ4Z3NCZmN5ZjJQbmtoXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>可以看到，现在我们就不再关心 Service 对象的 IP 地址，只需要知道它的名字，就可以用DNS 的方式去访问后端服务。&lt;/p>
&lt;h3 id="如何让-service-对外暴露服务">如何让 Service 对外暴露服务
&lt;/h3>&lt;p>Service 是一种负载均衡技术，它不仅能够管理 Kubernetes 集群内部的服务，还能够向集群外部暴露服务。&lt;/p>
&lt;p>Service 对象有一个关键字段“type”，表示 Service 是哪种类型的负载均衡。前面我们创建 Service 都使用的默认值“ClusterIP”，这种类型的 Service 地址只能在集群内访问。&lt;/p>
&lt;p>我们可以通过命令查看这个字段的属性&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl explain service.spec.type
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ODVmOTQzN2I3OTNjMDdlODEzMjIzM2M2M2E0MGUwNmRfbGoyWDhvSGdacWVSRUpZVDJoUTE2Q1VyVTlnQ3NaOUVfVG9rZW46TnZoU2J5aFgxbzU2SHd4d2diVmNZS0Y1bnFiXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>我们可以看到 默认值是 “ClusterIP”，另外还有三种类型分别是“ExternalName” 、“NodePort” 和 “LoadBalancer”。 其中 “LoadBalancer” 是由云服务商提供的，需要借助云服务商用才能实现完整的效果。&lt;/p>
&lt;p>我们分别测一下这几种类型的 Service。&lt;/p>
&lt;h4 id="nodeport">NodePort
&lt;/h4>&lt;p>我们修改一下 Service 的 YAML 文件，加上 “type” 字段：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">NodePort&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">targetPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">protocol&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TCP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>更新对象，查看状态：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl apply -f nginx-svc.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl get svc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NjYxMmEzZGRkNWU0ODEwMDkxNTIyMmIzZjE1NTlmNDJfUVlOajhQS3dON0pqcHNGRk1kMmtZaFJ6NjIzQU0wbUVfVG9rZW46QVE0OWJ3eFVOb1ZZMlN4R1JWMmNma2FGbnlmXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>可以看到 nginx-svc 的 “TYPE” 变成了 “NodePort”，而在 “PORT” 列里的端口信息也不一样，除了集群内部使用的“80”端口，还多出了一个“32119”端口，这就是 Kubernetes 在节点上为 Service 创建的专用映射端口。&lt;/p>
&lt;p>因为这个端口号属于节点，外部能够直接访问，所以现在我们就不需要登录集群节点或者进入 Pod 内部，直接在集群外使用任意一个节点的 IP 地址，就能够访问 Service 和它代理的后端服务了。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=OTEwOGZmMjAyM2UwNDEzMDQ4MDYzZmM5MWNjYWRjMTlfYkhGc3N3dG1LS2o5QkFkN0ozcHRNTkkyalkwODBneElfVG9rZW46SmhxM2I0c01Lb0hLejl4eU5IVWNBc2NXbjhkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZmI4ZDFiMzgyZjIyYjQwMzNhOTNkN2U5ZjVmN2IzZmVfTmhPNkZhakY3Q2E4czJxYTVMdHJKTEd5WXRuU2EzNTRfVG9rZW46UjVPcmIxRlVIb09xakh4bnNMS2NjcVpYbnlkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h4 id="externalname">ExternalName
&lt;/h4>&lt;p>ExternalName Service 是 Kubernetes 中一个特殊的 service 类型，它不需要指定 selector 去选择哪些 Pod 实例提供服务，而是使用 DNS CNAME 机制把自己 CNAME 到你指定的另外一个域名上，你可以提供集群内的名字，比如mysql.db.svc 这样的建立在db命名空间内的 MySQL 服务，也可以指定 &lt;a class="link" href="http://www.baidu.com" target="_blank" rel="noopener"
>http://www.baidu.com&lt;/a> 这样的外部真实域名。&lt;/p>
&lt;p>我们需要使用 ping 和nslookup 命令，所以部署一个 busybox 的 deployment，busybox 镜像中提供很多常用的命令可以使用。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">apps/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busy-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busy-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicas&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busy-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">template&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busy-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">containers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busybox &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">busybox &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;-c&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;sleep 3600&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>创建一个 External Service&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">external-svc &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ExternalName&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">externalName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">www.baidu.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>登录到 Pod 中验证 External Service&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MzQ1ZmEzZGIyYTM1OTQ5NzAwM2RhY2ZkOTQ0MzRiYWRfSFNLMUpicktwWVdJRW5TVmVHMjZ4T0h5ZmVIcVdlSHNfVG9rZW46Q3haY2I0aEVmbzN2SWx4d0k2RmNHalVZbkRnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=M2FlNmVkYWEyM2NhNTRhMmRmZTFmZmYwMDY3NjNmOTJfaHZ0N1pHTFBUcUpxcEVMdFU1TXRMVnYwZE15dG1ZMHRfVG9rZW46VHE0VWJ4M2cwb01IR1V4MFdwa2MyZkdqbjYxXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>可以看到 external-svc 会被解析到一个 CNAME 指向 &lt;a class="link" href="https://www.baidu.com" target="_blank" rel="noopener"
>www.baidu.com&lt;/a>&lt;/p>
&lt;h4 id="loadbalancer">LoadBalancer
&lt;/h4>&lt;p>我们修改 service 的类型为 LoadBalancer 看一下效果&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">LoadBalancer&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">targetPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">protocol&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TCP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>更新SVC&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="l">kubectl apply -f nginx-svc-lb.yaml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZTVkYTMwYzNmZDY1MGQyMGJhNjQyYzQ5ZTg2NzNmMDFfRFRPeE5KR2J0N2xIT3k1TlNqVWZNVnJqYlpRM0JUU2VfVG9rZW46TzdiZmJYN2Uxb0VURUF4N25iRWNPdEoybkpkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>PORT 列没有变化，但是 EXTERNAL-IP 列会显示 pending，因为 LoadBalancer 类型的负载均衡需要云服务商提供，我们的环境会显示为 pending状态，但是 LoadBalancer 也是用了 NodePort 的实现方式，因为 PORT 列还保留了 NodePort 的端口。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NDY0MDVmZDk3NGVkMTQyNjNjM2JjYWI4NzJiOTI1MzJfZHFWTTJDTDZSTlExR0FabWR1aWt4T2V2V0RLNVluVXBfVG9rZW46VEtjSGI2MGpvbzQ4OGN4ZnByQWNMUndXblFnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h4 id="不同-service-类型的对比">不同 Service 类型的对比
&lt;/h4>&lt;ol>
&lt;li>ClusterIP：只能在集群内部使用。clusterIP 域名&lt;/li>
&lt;li>NodePort：可以作为集群流量入口，但也有一些缺点
&lt;ol>
&lt;li>端口数量有限。默认只在“30000~32767”这个范围内随机分配，只有 2000 多个，而且都不是标准端口号。&lt;/li>
&lt;li>需要在每个节点上都开端口，然后使用 kube-proxy 路由到真正的后端 Service，这对于大规模集群来说如果Pod 频繁变更，Service 收敛速度就会变慢。&lt;/li>
&lt;li>需要向外界暴露节点的 IP 地址，这在很多时候是不可行的，为了安全还需要在集群外再搭一个反向代理，增加了方案的复杂度。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;p>虽然有这些缺点，但 NodePort 仍然是 Kubernetes 对外提供服务的一种简单易行的方式，在没有更好的方案出现之后，我们暂且使用这种方式。&lt;/p>
&lt;ol>
&lt;li>ExternalName： 只是一个CNAME，应用场景有限。&lt;/li>
&lt;li>LoadBalancer：依赖云厂商实现。 生产环境&lt;/li>
&lt;/ol>
&lt;h4 id="service-的三个-port">Service 的三个 port
&lt;/h4>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-dep&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">NodePort&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># ClusterIP &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">targetPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 容器的端口&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodePort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">30080&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">protocol&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TCP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Service 的几个 port 的概念很容易混淆，它们分别是 port 、 targetPort 和 NodePort 。&lt;/p>
&lt;ul>
&lt;li>port 表示 Service 暴露的服务端口，也是客户端访问用的端口，例如 Cluster IP:port 是提供给集群内部客户访问 Service 的入口 。 需要注意的是， port 不仅是 Cluster IP 上暴露的端口，还可以是 external IP 和 Load Balancer IP 。 Service 的 port 并不监听在节点 IP 上，即无法通过节点 IP:port 的方式访问 Service 。&lt;/li>
&lt;li>NodePort 是 Kubemetes 提供给集群外部访问 Service 的入口的一种方式（另 一种方式是 Load Balancer ），所以可以通过 Node IP:nodePort 的方式提供集群外访问 Service 的入口 。 需要注意的是，我们这里说的集群外指的是 Pod 网段外，例如 Kubemetes 节点或因特网 。&lt;/li>
&lt;li>targetPort 很好理解，它是应用程序实际监听 Pod 内流量的端口，从 port 和 NodePort 上到来的数据，最终经过 Kube-proxy 流入后端 Pod 的 targetPort 进入容器。&lt;/li>
&lt;/ul>
&lt;h2 id="service-实现原理">Service 实现原理
&lt;/h2>&lt;p>在 Kubernetes 集群中，每个 Node 运行一个 &lt;code>kube-proxy&lt;/code> 进程。&lt;code>kube-proxy&lt;/code> 负责为 &lt;code>Service&lt;/code> 实现了一种 VIP（虚拟 IP）。&lt;/p>
&lt;h3 id="service-底层技术">Service 底层技术
&lt;/h3>&lt;ul>
&lt;li>userspace 早期的版本中使用&lt;/li>
&lt;li>iptables 默认&lt;/li>
&lt;li>IPVS SVC 比较多的场景 ，建议使用 IPVS 模式&lt;/li>
&lt;/ul>
&lt;h3 id="iptables">iptables
&lt;/h3>&lt;p>这种模式，kube-proxy 会监听 apiserver 对 Service 对象和 Endpoints 对象的添加和移除。对每个 Service，它会添加上 iptables 规则，从而捕获到达该 Service 的 clusterIP（虚拟 IP）和端口的请求，进而将请求重定向到 Service 的一组 backend 中的某一个 Pod 上面。我们还可以使用 Pod readiness 探针 验证后端 Pod 是否可以正常工作，以便 iptables 模式下的 kube-proxy 仅看到正常运行的后端，这样做意味着可以避免将流量通过 kube-proxy 发送到已知失败的 Pod 中，所以对于线上的应用来说一定要做 readiness 探针。&lt;/p>
&lt;p>iptables 模式的 kube-proxy 默认的策略是，随机选择一个后端 Pod。&lt;/p>
&lt;p>比如当创建 backend Service 时，Kubernetes 会给它指派一个虚拟 IP 地址，比如 10.0.0.10。假设 Service 的端口是 1234，该 Service 会被集群中所有的 kube-proxy 实例观察到。当 kube-proxy 看到一个新的 Service，它会安装一系列的 iptables 规则，从 VIP 重定向到 &lt;code>Service&lt;/code> 规则。 该 &lt;code>Service&lt;/code> 规则连接到 &lt;code>Endpoint&lt;/code> 规则，该 &lt;code>Endpoint&lt;/code> 规则会重定向（目标 &lt;code>NAT&lt;/code>）到后端的 Pod。&lt;/p>
&lt;p>查看 Kube-proxy 当前运行模式&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="l">root@master-01 manifests]# curl 127.0.0.1:10249/proxyMode&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">iptables&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>iptables 规则分析&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@master-01 case1&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl get pod -l app=tea -o wide &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tea-7f5fcf84f8-55dgc 1/1 Running &lt;span class="m">0&lt;/span> 132m 10.244.171.58 worker-01 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tea-7f5fcf84f8-l7zxx 1/1 Running &lt;span class="m">0&lt;/span> 132m 10.244.171.57 worker-01 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tea-7f5fcf84f8-nhjq2 1/1 Running &lt;span class="m">0&lt;/span> 132m 10.244.37.239 worker-02 &amp;lt;none&amp;gt; &amp;lt;none&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@master-01 case1&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl get svc tea-svc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o">(&lt;/span>S&lt;span class="o">)&lt;/span> AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tea-svc ClusterIP 10.107.48.138 &amp;lt;none&amp;gt; 80/TCP 108m
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SERVICES -d 10.107.48.138/32 -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http cluster IP&amp;#34;&lt;/span> -m tcp --dport &lt;span class="m">80&lt;/span> -j KUBE-SVC-DVHFM6YVY2RW3DPQ
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-3NPNUAJQIUYNQ6GJ
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-62HFJKX5HLTTQHKU
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -j KUBE-SEP-I5YFUSH4L5RO5MII
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-3NPNUAJQIUYNQ6GJ -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.171.57:8080
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-62HFJKX5HLTTQHKU -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.171.58:8080
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-I5YFUSH4L5RO5MII -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.37.239:8080
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>kube-proxy 针对 service 流量入口专门创建了 KUBE-SERVICES 链，&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">-A KUBE-SERVICES -d 10.107.48.138/32 -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http cluster IP&amp;#34;&lt;/span> -m tcp --dport &lt;span class="m">80&lt;/span> -j KUBE-SVC-DVHFM6YVY2RW3DPQ
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如果 访问地址 10.107.48.138/32，目标端口是 80，则会进入 KUBE-SVC-DVHFM6YVY2RW3DPQ 链&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-3NPNUAJQIUYNQ6GJ
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-62HFJKX5HLTTQHKU
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-DVHFM6YVY2RW3DPQ -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -j KUBE-SEP-I5YFUSH4L5RO5MII
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>这里利用了 iptables 的 random 模块，使连接有 33.3% 的概率进入 &lt;strong>KUBE-SEP-3NPNUAJQIUYNQ6GJ 链，&lt;/strong>&lt;/p>
&lt;p>50% 概率进入 **KUBE-SEP-62HFJKX5HLTTQHKU 链，**最后会匹配 &lt;strong>KUBE-SEP-I5YFUSH4L5RO5MII&lt;/strong> 链。&lt;/p>
&lt;p>因此，kube-proxy 的 iptables 模式采用随机数实现了服务的负载均衡。&lt;/p>
&lt;p>KUBE-SEP-3NPNUAJQIUYNQ6GJ 链的作用是 通过 DNAT 将请求发送到 10.244.171.57 的 8080 端口。&lt;/p>
&lt;p>同理，KUBE-SEP-62HFJKX5HLTTQHKU 链的作用是通过DNAT 将请求发送到 10.244.171.58 的 8080 端口。&lt;/p>
&lt;p>KUBE-SEP-I5YFUSH4L5RO5MII 链的作用是通过DNAT 将请求发送到 10.244.37.239 的 8080 端口。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-3NPNUAJQIUYNQ6GJ -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.171.57:8080
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-62HFJKX5HLTTQHKU -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.171.58:8080
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SEP-I5YFUSH4L5RO5MII -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/tea-svc:http&amp;#34;&lt;/span> -m tcp -j DNAT --to-destination 10.244.37.239:8080
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>分析完 ClusterIP 的 iptables 规则后，接下来看一下 NodrPort 的访问方式。NodePort 的访问入口链是 KUBE-NODEPORTS，通过节点的 31668 端口访问 NodePort，则会进入 KUBE-SVC-I277KLBDTTJWT3KA 链，接下来的跳转跟 ClusterIP 方式类似。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@master-01 ~&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl get svc coffee-svc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o">(&lt;/span>S&lt;span class="o">)&lt;/span> AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">coffee-svc NodePort 10.101.15.76 &amp;lt;none&amp;gt; 80:31668/TCP 5h17m
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-NODEPORTS -p tcp -m comment --comment &lt;span class="s2">&amp;#34;default/coffee-svc:http&amp;#34;&lt;/span> -m tcp --dport &lt;span class="m">31668&lt;/span> -j KUBE-SVC-I277KLBDTTJWT3KA
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-A KUBE-SVC-I277KLBDTTJWT3KA -m comment --comment &lt;span class="s2">&amp;#34;default/coffee-svc:http&amp;#34;&lt;/span> -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XM2ZPQCWY7D6I5CQ
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>综上所述， iptables 模式最主要的链是 KUBE-SERVICES 、 KUBE-SVC-＊和 KUBE-SEP-＊ 。&lt;/p>
&lt;ul>
&lt;li>KUBE-SERVICES 链是访问集群内服务的数据包入口点，它会根据匹配到的目标 IP :port 将数据包分发到相应的 KUBE-SVC-＊链；&lt;/li>
&lt;li>KUBE-SVC-＊链相当于一个负载均衡器，它会将数据包平均分发到 KUBE-SEP-＊ 链 。 每个 KUBE-SVC-＊ 链后面的 KUBE-SEP-＊链都和 Service 的后端 Pod 数量一样；&lt;/li>
&lt;li>KUBE-SEP-＊链通过 DNAT 将连接的目的地址和端口从 Service 的 IP:port 替换为后端Pod 的 IP : port ，从而将流量转发到相应的 Pod 。&lt;/li>
&lt;/ul>
&lt;p>我们用下图总结 Kube-proxy iptables 模式的工作流 ，演示了从客户端 Pod 到不同节点上的服务器 Pod 的流量路径 。 客户端通过 172.16.12.100:80 连接到服务 。&lt;/p>
&lt;p>Kubernetes API Server 会维护一个运行应用的后端 Pod 列表 。 每个节点上的 Kube-proxy 进程会根据 Service 和对应的 Endpoints 创建一系列的 iptables 规则 ，以将流量重定向到相应Pod （ 例如 10. 255. 255. 202: 8080 ） 。 整个过程客户端 Pod 无须感知集群的拓扑或集群内Pod 的任何 IP 信息 。&lt;/p>
&lt;p>iptables 模式与 userspace 模式相比虽然在稳定性和性能上均有不小的提升，但因为 iptables 使用 NAT 完成转发， 也存在不可忽视的性能损耗 。 另外，当集群 中存在上万服务 时，Node 上的 iptables rules 会非常庞大，对管理是个不小的负担，性能还会大打折扣 。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=OGIyNTRmYjI5ZGRhYmRmNjBlOTQ1MTU3MzFlMWQwNmRfNmpxRkZ0ZWxoWTNHbENaZlNYUWNMUWIydTgzZ0k3bVVfVG9rZW46TU0weGJMNDZ3bzZnYXZ4aWlMU2NRb3M1bnZnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="ipvs">IPVS
&lt;/h3>&lt;p>除了 iptables 模式之外，kubernetes 也支持 ipvs 模式，在 ipvs 模式下，kube-proxy 监视 Kubernetes 服务和端点，调用 &lt;code>netlink&lt;/code> 接口相应地创建 IPVS 规则， 并定期将 IPVS 规则与 Kubernetes 服务和端点同步。该控制循环可确保 IPVS 状态与所需状态匹配。访问服务时，IPVS 将流量定向到后端 Pod 之一。&lt;/p>
&lt;p>IPVS 代理模式基于类似于 iptables 模式的 netfilter 钩子函数，但是使用&lt;strong>哈希表&lt;/strong>作为基础数据结构，并且在内核空间中工作。 所以与 iptables 模式下的 kube-proxy 相比，IPVS 模式下的 kube-proxy 重定向通信的延迟要短，并且在同步代理规则时具有更好的性能。与其他代理模式相比，IPVS 模式还支持更高的网络流量吞吐量。所以对于较大规模的集群会使用 ipvs 模式的 kube-proxy，只需要满足节点上运行 ipvs 的条件，然后我们就可以直接将 kube-proxy 的模式修改为 ipvs，如果不满足运行条件会自动降级为 iptables 模式，现在都推荐使用 ipvs 模式，可以大幅度提高 Service 性能。&lt;/p>
&lt;p>IPVS 提供了更多选项来平衡后端 Pod 的流量，默认是 &lt;code>rr&lt;/code>，有如下一些策略：&lt;/p>
&lt;ul>
&lt;li>&lt;code>rr&lt;/code>：轮询调度&lt;/li>
&lt;li>&lt;code>lc&lt;/code>：最小连接数&lt;/li>
&lt;li>&lt;code>dh&lt;/code>：目标哈希&lt;/li>
&lt;li>&lt;code>sh&lt;/code>：源哈希&lt;/li>
&lt;li>&lt;code>sed&lt;/code>：最短期望延迟&lt;/li>
&lt;li>&lt;code>nq&lt;/code>： 不排队调度&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MzJkZDEzM2NiZmViMWRlZmE5OWZiZGQyMWMzZmI1NjRfTzFtUzVIUUNPN29BRGdRNnhWWENYaHdURnVWS1hqa0lfVG9rZW46WldSRWIxaWdFb0pPMjd4VjIwZ2NidVBhblJiXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>kube-proxy会监视 Kubernetes &lt;code>Service&lt;/code>对象和&lt;code>Endpoints&lt;/code>，调用&lt;code>netlink&lt;/code>接口以相应地创建ipvs规则并定期与Kubernetes &lt;code>Service&lt;/code>对象和&lt;code>Endpoints&lt;/code>对象同步ipvs规则，以确保 ipvs 状态与期望一致。访问服务时，流量将被重定向到其中一个后端 Pod。&lt;/p>
&lt;p>与 iptables 类似，ipvs 基于netfilter 的 hook 功能，但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量，并且在同步代理规则时具有更好的性能。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>注意：&lt;/strong> ipvs模式假定在运行kube-proxy之前在节点上都已经安装了IPVS内核模块。当kube-proxy以ipvs代理模式启动时，kube-proxy将验证节点上是否安装了IPVS模块，如果未安装，则kube-proxy将回退到iptables代理模式。&lt;/p>
&lt;/blockquote>
&lt;p>一个 IPVS 服务端口 80 到 Pod 端口 80 的映射的样例如下:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@node-01 ~&lt;span class="o">]&lt;/span>&lt;span class="c1"># ipvsadm -ln&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">IP Virtual Server version 1.2.1 &lt;span class="o">(&lt;/span>&lt;span class="nv">size&lt;/span>&lt;span class="o">=&lt;/span>4096&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">TCP 10.111.109.105:80 rr
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> -&amp;gt; 10.244.167.159:80 Masq &lt;span class="m">1&lt;/span> &lt;span class="m">0&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> -&amp;gt; 10.244.167.165:80 Masq &lt;span class="m">1&lt;/span> &lt;span class="m">0&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="iptabales-vs-ipvs">iptabales vs IPVS
&lt;/h3>&lt;p>​ iptables 和 IPVS 在刷新服务路由规则上的时延对比&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZDhhNjAxNWU3ZjAxYWMzMjhhNDVlNGVlODJjYjM5MDJfTzdsVzhFcm50V1BUYlRZZndjaWFnazdpeWFPdmRrN1dfVG9rZW46VXpLeGJIdFoxb1VjaTF4c29QdmMwTU0ybjVnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="kube-proxy-切换到-ipvs-模式">Kube-proxy 切换到 IPVS 模式
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="l">yum -y install ipvsadm ipset&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">kubectl edit configmap kube-proxy -n kube-system&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 默认是空代表用 iptables，可以修改成 ipvs&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">mode&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;ipvs&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>重启 kube-proxy&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="l">kubectl get pod -n kube-system|grep kube-proxy|awk &amp;#39;{system(&amp;#34;kubectl delete pod &amp;#34;$1&amp;#34; -n kube-system&amp;#34;)}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="endpoint">Endpoint
&lt;/h3>&lt;p>&lt;strong>Endpoint（端点）&lt;/strong> 是核心的网络资源对象，本质是「Service 与 Pod 之间的 “桥梁”」—— 它存储了对应 Service 要转发流量的 &lt;strong>Pod IP + 端口&lt;/strong> 列表，让 Service 知道该把请求发给哪些具体的 Pod。&lt;/p>
&lt;h2 id="ingress">Ingress
&lt;/h2>&lt;h3 id="什么是-ingress">什么是 Ingress
&lt;/h3>&lt;p>Service 本质上是一个由 kube-proxy 控制的四层负载均衡，但在四层上的负载均衡功能还是太有限了，只能够依据 IP 地址和端口号做一些简单的判断和组合，而现在的绝大多数应用都是跑在七层的 HTTP/HTTPS 协议上的，有更多的高级路由条件，比如主机名、URI、请求头、证书等等。&lt;/p>
&lt;p>Service 比较适合代理集群内部的服务。如果想要把服务暴露到集群外部，就只能使用 NodePort 或者 LoadBalancer 这两种方式 ，而这两种方式也都有各自的缺点，不能满足所有的场景。&lt;/p>
&lt;p>Kubernetes 就引入一个新的 API 对象，在七层上做负载均衡。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZWY5ZmQ5ZmJmN2ZiZjUwMmNiMDFlMzdiOGQ4ZTc3ZjBfSEVyR1ZZRzJlSmFnZ0dUT3dabXBZUW54U1lPSkVydE1fVG9rZW46SjZvRGJTU2Rsb1VFRWN4RGJXVmNxbmc5bnlnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>Ingress 作为流量的总入口，统管集群的进出口数据&lt;/p>
&lt;h3 id="什么是-ingress-controller">什么是 Ingress Controller
&lt;/h3>&lt;p>我们前面讲过 Service 本身是没有服务能力的，它只是一些 iptables 规则，真正配置、应用这些规则的实际上是节点上的 kube-proxy 组件。&lt;/p>
&lt;p>同样的，Ingress 也只是声明了一些 HTTP 路由规则，相当于一份静态的配置文件，要把这些规则在集群里实施运行，还需要有另外一个组件，这就是 Ingress Controller，它的作用就相当于 Service 的 kube-proxy，能够读取、应用 Ingress 规则，处理、调度流量。&lt;/p>
&lt;p>Ingress Controller 主要由社区来实现，比如我们熟悉的 Nginx， 就有 Nginx Ingress Controller。&lt;/p>
&lt;p>下图比较清楚地展示了 Ingress Controller 在 Kubernetes 集群中的地位。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=N2Q2MWNhNDUyMmU0NjQ2MzE3ZTkyMGQzZTdjMTQ3ZTNfVFhNcVhKajJJYUJzRERGUlNBT3R1dzBCNnZiNHMwRFlfVG9rZW46SVpKZWJidk1Kb0I3dlR4UHBVWmNVcGExbnNoXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="为什么要有-ingressclass">为什么要有 IngressClass
&lt;/h3>&lt;p>有了 Ingress 和 Ingress Controller，是不是就可以完美地管理集群的进出流量了呢？&lt;/p>
&lt;p>最初 Kubernetes 也是这么想的，一个集群里有一个 Ingress Controller，再给它配上许多不同的 Ingress 规则，应该就可以解决请求的路由和分发问题了。&lt;/p>
&lt;p>但随着 Ingress 在实践中的大量应用，很多用户发现这种用法会带来一些问题，比如：&lt;/p>
&lt;ul>
&lt;li>由于某些原因，项目组需要引入不同的 Ingress Controller，但 Kubernetes 不允许这样做；&lt;/li>
&lt;li>Ingress 规则太多，都交给一个 Ingress Controller 处理会让它不堪重负；&lt;/li>
&lt;li>多个 Ingress 对象没有很好的逻辑分组方式，管理和维护成本很高；&lt;/li>
&lt;li>集群里有不同的用户，他们对 Ingress 的需求差异很大甚至有冲突，无法部署在同一个 Ingress Controller 上。&lt;/li>
&lt;/ul>
&lt;p>Kubernetes 又提出了一个 Ingress Class 的概念，让它插在 Ingress 和 IngressController 中间，让它来协调流量规则和控制器，解除了 Ingress 和 Ingress Controller 的强绑定关系。&lt;/p>
&lt;p>现在，Kubernetes 用户可以转向管理 Ingress Class，用它来定义不同的业务逻辑分组，简化 Ingress 规则的复杂度。比如说，我们可以用 Class A 处理订单流量、Class B 处理物流流量、Class C 处理购物流量。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NjY4N2MzYjU2ZjZhNTJiOTFkMjY5NjA2ZjNhZjQxMDJfc2F4QnhQY1puT08yRnhLYXdhbXpjbHh2ZjNqUVcyUGlfVG9rZW46R2pVOGJlelgxb2M4VEJ4cGhMMWMyVzdxbkFjXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="部署-ingress-controller">部署 Ingress Controller
&lt;/h3>&lt;p>Ingress Controller 是一个要实际干活、处理流量的应用程序，由 Deployment 对象来管理。&lt;/p>
&lt;p>由于 Kubernetes 官网维护的 &lt;strong>&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"
>Ingress NGINX Controller&lt;/a>&lt;/strong> 已经退役不再维护，我们换成 Nginx 官方维护的&lt;/p>
&lt;p>&lt;a class="link" href="https://github.com/nginx/kubernetes-ingress" target="_blank" rel="noopener"
>Nginx Ingress Controller&lt;/a>，我们部署最新的稳定版本： &lt;a class="link" href="https://github.com/nginx/kubernetes-ingress/releases/tag/v5.3.4" target="_blank" rel="noopener"
>5.3.4&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=OWExNDE4NGFkZDc0ZGFiMzRhNTdjMGNkOWI5NWMzNTVfV3NpQzJ1Q0Uxcnd4d1FuYUhwZVZTV04xMVQyRDVBV2ZfVG9rZW46RlNHZ2IwYUY2b0Zrd0Z4RWJZbGNodXVwbjVkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>部署 Nginx Ingress Controller&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/common/ns-and-sa.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/rbac/rbac.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/common/nginx-config.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/common/ingress-class.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/deployment/nginx-ingress.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl apply -f deployments/service/nodeport.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kubectl create -f deploy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>检查部署结果&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">$ kubectl get pods -n nginx-ingress
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME READY STATUS RESTARTS AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx-ingress-55cc9cf8fc-jf6fh 1/1 Running &lt;span class="m">0&lt;/span> 47m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NjljYmZiMjc5ZjQzMDE2MmIwN2Q5ZGIwZDY5YTBkODlfVFU0U0JMeFk4TkhhZE1HYVd6M0hiVHdWWFNkc0RHbFJfVG9rZW46UXQ3R2JyVEJIb0Z6Rnd4OURHSmNYZEVEbnl5XzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;code>Nginx Ingress Controller&lt;/code> 会将创建的对象存放在 nginx-ingress 命名空间中。&lt;/p>
&lt;h3 id="使用-yaml-描述-ingress-和-ingress-class">使用 YAML 描述 Ingress 和 Ingress Class
&lt;/h3>&lt;p>首先用命令&lt;code>kubectl api-resources&lt;/code>查看它们的基本信息：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@master-01 ~&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl api-resources | grep -i ingress&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ingressclasses networking.k8s.io/v1 &lt;span class="nb">false&lt;/span> IngressClass
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ingresses ing networking.k8s.io/v1 &lt;span class="nb">true&lt;/span> Ingress
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ingress 和 Ingress Class 的 apiVersion 都是“networking.k8s.io/v1”，而且 Ingress 有一个简写“ing”。&lt;/p>
&lt;p>我们先使用命令创建一个 Ingress 对象&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl create ingress nginx-ing --rule&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;nginx.xxhf.cc/=nginx-svc:80&amp;#34;&lt;/span> --class&lt;span class="o">=&lt;/span>nginx --dry-run&lt;span class="o">=&lt;/span>client -o yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">apiVersion: networking.k8s.io/v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kind: Ingress
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">metadata:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: nginx-ing
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">spec:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ingressClassName: nginx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rules:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - host: nginx.xxhf.cc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paths:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - path: /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> pathType: Exact
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> backend:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> service:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: nginx-svc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> port:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> number: &lt;span class="m">80&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在这份 Ingress 的 YAML 里，有两个关键字段：“ingressClassName”和“rules”，分别对应了命令行参数，含义还是比较好理解的。&lt;/p>
&lt;p>Ingress Class 本身并没有什么实际的功能，只是起到联系 Ingress 和 Ingress Controller 的作用，所以它的定义非常简单，在“spec”里只有一个必需的字段“controller”，表示要使用哪个 Ingress Controller。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">networking.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">IngressClass&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># annotations:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># ingressclass.kubernetes.io/is-default-class: &amp;#34;true&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">controller&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx.org/ingress-controller&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=MDhjOTJjODUxYjIyM2Q2MDU2ODQ4MzZjNWY5NGViNTZfZnpsY3IyU2x6S0FQcHRwaXBWRnRUSG9yWUtHWW1reXpfVG9rZW46QjF6aWJ2ZXRIb3Blc0x4ME9qOGNEQ1I0bkRiXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="创建-ingress-规则">创建 Ingress 规则
&lt;/h3>&lt;p>应用 YAML 清单文件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl apply -f nginx-ingress.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>查看创建后的 ingress 对象&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">$ kubectl get ingress
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME CLASS HOSTS ADDRESS PORTS AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx-ing nginx nginx.xxhf.cc &lt;span class="m">80&lt;/span> 51m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>使用命令&lt;code> kubectl describe&lt;/code> 可以看到更详细的 Ingress 信息：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl describe ingress nginx-ing
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZGM0OWY5MjkzM2VlYjE2NjQ5ZTFhODBjODU2ZWFmMjRfYjFKaWkxeFJRaVIzSlNCZEZqeUFHdkdZM0p5Z01kUHJfVG9rZW46WjBtb2Jwc2hSb29HSTZ4TGp0WmNjV2g0bkJLXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;code>Ingress Class&lt;/code> 在部署 &lt;code>nginx-ingress-controller&lt;/code> 时已经自动创建了。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">$ kubectl get ingressclasses
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME CONTROLLER PARAMETERS AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx nginx.org/ingress-controller &amp;lt;none&amp;gt; 54m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=YjY0ZjYwOTIwZTJhNjA1NzA2MTQ5YmYzYWQzZTJkOGNfSHZwbk9jQ3p3VkZkVVpjRDAxZDdyOTJvTUc2SzdObEZfVG9rZW46VVJ6YmJ3ZEp2b3kyWjV4Y3laWWNFMkdGbk5kXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>通过 ingress 来访问 我们部署的 Nginx 应用&lt;/p>
&lt;p>因为实际干活的是 controller，所以我们看一下 nginx-ingress-controller 对外提供服务的地址，NodePort SVC 对外暴露的 30080 和 30443 端口，ingress 作为七层入口主要是从集群外部访问。如果集群部署在云厂商的环境中，建议使用 LoadBalance 类型的 SVC。&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NzAyNmY3MzRlM2JjMzFmMmQ4NzBiNDg5YjBiNzUxZjJfQzNPQ0V4dE80a0FnUWJMTGs4WGg4UEJ6RTJmZjVSek9fVG9rZW46WDJReWJpYklsb2RFem14VUhLTmM2U1pHbmtmXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>我们创建的 Ingress 规则是通过域名来访问 ，&lt;strong>因此需要在客户端所在服务器上修改静态解析文件，添加如下行：&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Plain" data-lang="Plain">&lt;span class="line">&lt;span class="cl">192.168.11.57 nginx.xxhf.cc # 修改为自己 Node 节点 IP
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="case-1--使用--http-协议访问-集群内应用">Case 1 : 使用 HTTP 协议访问 集群内应用
&lt;/h3>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NDFlZjJlMGJiYzMyMTI4NTY2NGE0NmQ4MmYxZGI4MzdfbFFEN2kyRUNlWG1QQjdqTEY2WTdzcjFKaUVLQTRFOXBfVG9rZW46WEJZbWJyQmR4bzVMSlN4SDB0UGNHYjZIbmxiXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="case-2-使用-https-协议访问--集群内应用">Case 2: 使用 HTTPS 协议访问 集群内应用
&lt;/h3>&lt;p>创建 TLS 类型 Secret&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">kubectl create secret tls cafe-secret &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --cert&lt;span class="o">=&lt;/span>cafe.xxhf.cc_bundle.crt &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --key&lt;span class="o">=&lt;/span>cafe.xxhf.cc.key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>给 ingress 添加 TLS 属性&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">networking.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Ingress&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cafe-ingress&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ingressClassName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tls&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hosts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">cafe.xxhf.cc &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 域名 &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">secretName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cafe-secret &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># TLS secret 名字 &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cafe.xxhf.cc &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">http&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">paths&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">path&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/tea&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pathType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Prefix&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">backend&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tea-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">number&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">path&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/coffee&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pathType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Prefix&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">backend&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">coffee-svc&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">number&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>访问&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=YWI5MDA1NTJhNjJjNTZjNzg5MzdkNmQ2M2EyNTdiZjNfYkJ4Q3BJcnZUZWNRYXF2akhCQnVicVJKbkdVbEJnQmpfVG9rZW46WEpGb2JuTXFPb3pFRHl4SVBZUWMzamVUbmVnXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="case-3--使用-annotaion-httpsdocsnginxcomnginx-ingress-controllerconfigurationingress-resourcesadvanced-configuration-with-annotations配置-ingress-控制器">Case 3: 使用 &lt;a class="link" href="https://docs.nginx.com/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations/" target="_blank" rel="noopener"
>annotaion &lt;/a>配置 Ingress 控制器
&lt;/h3>&lt;p>在 Kubernetes Ingress 里，&lt;strong>annotation（注解）&lt;/strong> 就是给 Ingress 控制器 “传参数、发指令” 的配置方式，用来实现 &lt;strong>路由、TLS、限流、重写、认证&lt;/strong> 等功能，不同 Ingress 控制器（nginx/treafik/apisix 等）支持不同 annotation。&lt;/p>
&lt;ol>
&lt;li>创建 htpasswd 文件&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">$ htpasswd -c htpasswd admin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">New password: &lt;span class="c1"># 输入密码&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Re-type new password:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Adding password &lt;span class="k">for&lt;/span> user admin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol>
&lt;li>创建 secret 文件&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-YAML" data-lang="YAML">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Secret&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">auth-passwd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx.org/htpasswd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">stringData&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">htpasswd&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> admin:$apr1$YUz1Uixv$y1xcvH.ls/VJhkI3KV7QD/&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol>
&lt;li>创建 ingress&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">apiVersion: networking.k8s.io/v1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kind: Ingress
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">metadata:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: ingress-with-auth
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> annotations:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nginx.org/basic-auth-secret: &lt;span class="s2">&amp;#34;auth-passwd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nginx.org/basic-auth-realm: &lt;span class="s1">&amp;#39;Please Input Your Username and Password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">spec:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ingressClassName: nginx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rules:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - host: auth.xxhf.cc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paths:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - path: /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> pathType: Prefix
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> backend:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> service:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> name: nginx-svc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> port:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> number: &lt;span class="m">80&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol>
&lt;li>测试连接&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZGUwNDczOTc2N2RkNDYwYTY0OGYxZGFkNDY1ZDM4OGZfUXlERXpLMjN3eDMzeER1dkF4RFh0aXdJQ0laaERuMnBfVG9rZW46WWcyWWJlYmk4b0ZFYmF4dElVNGNOaVFubmhoXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h2 id="附录">附录：
&lt;/h2>&lt;h3 id="如何部署多个-ingress-controller">如何部署多个 ingress controller
&lt;/h3>&lt;p>&lt;a class="link" href="https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/" target="_blank" rel="noopener"
>Kubernetes 社区维护 ingress-nginx&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@node-01 ~&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl get ingressclasses.networking.k8s.io &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME CONTROLLER PARAMETERS AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">external-nginx k8s.io/ingress-nginx &amp;lt;none&amp;gt; 92s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">internal-nginx k8s.io/ingress-nginx &amp;lt;none&amp;gt; 102s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;a class="link" href="https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-manifests/" target="_blank" rel="noopener"
>安装 NGINX 官方 Ingress Controller&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-Bash" data-lang="Bash">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>root@node-01 kubernetes-ingress-3.4.2&lt;span class="o">]&lt;/span>&lt;span class="c1"># kubectl get ingressclasses.networking.k8s.io &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NAME CONTROLLER PARAMETERS AGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">external-nginx k8s.io/external-ingress-nginx &amp;lt;none&amp;gt; 9h
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">internal-nginx k8s.io/internal-ingress-nginx &amp;lt;none&amp;gt; 9h
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx nginx.org/ingress-controller &amp;lt;none&amp;gt; 3m3s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="ingress-controller">Ingress Controller
&lt;/h3>&lt;p>Kubernetes 社区维护： &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"
>https://github.com/kubernetes/ingress-nginx&lt;/a>&lt;/p>
&lt;p>Nginx官方维护： &lt;a class="link" href="https://docs.nginx.com/nginx-ingress-controller/" target="_blank" rel="noopener"
>https://docs.nginx.com/nginx-ingress-controller/&lt;/a>&lt;/p>
&lt;p>Traefik: &lt;a class="link" href="https://github.com/traefik/traefik" target="_blank" rel="noopener"
>https://github.com/traefik/traefik&lt;/a>&lt;/p>
&lt;h3 id="loadbalancer-1">LoadBalancer
&lt;/h3>&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=ZjBmYmU3MjRmNzJlMjU0YWVjOWFlYWE4MTAwZTQ2ZmNfTmZWY0ZHRzBoaXZaRHdHVWJ0RHE5U3Z2Z05OZVBBNzlfVG9rZW46UGkzcWJ0ZFBxb3R3Rmp4WExoeGNnS281bnRiXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NGEyZGIxMzFlN2NkZjQxNGVkNzRmMGMxYjUzNzIzNWZfRFVxSjF4cFRZcmpsQld1Yng3TTlFcGZ3aTZPckU4bnhfVG9rZW46UDA2bmJtSUJCb284dkN4SFNyU2M1NnRHbmVkXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NjRhZjE4YzE0NDk1YTlhNzYwYmY3NjkyNGI3MzgzNjFfVENva1NLV0ZvQTY3b053WkQ4VkVxdTZ5bDAzT1JHeGVfVG9rZW46THgxZmI4UklqbzBwREt4cXFBWWNUMzZhbmxmXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="生产环境-ingrss-入口流量">生产环境 ingrss 入口流量
&lt;/h3>&lt;p>Kubernetes 中 ingress 请求入口流量详解: &lt;a class="link" href="https://mp.weixin.qq.com/s/uyXugwITl6jMcol9Uw6mEg" target="_blank" rel="noopener"
>https://mp.weixin.qq.com/s/uyXugwITl6jMcol9Uw6mEg&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://rcnmegz4pby5.feishu.cn/space/api/box/stream/download/asynccode/?code=NjNhNmRiZDliMWZiOWU5MzlkMWM5NTJjMzIyMDY0NmNfcnpGdmRVSWtmOUI1VXk3UGNBc0UzWXJ6R3V5ekk0TlRfVG9rZW46THdQVGI2Z0dsb2JSNnB4MW00TmNmWW9ubmZGXzE3NzU0NzEyOTc6MTc3NTQ3NDg5N19WNA"
loading="lazy"
alt="img"
>&lt;/p>
&lt;h3 id="下一代-ingress----gateway-api">下一代 Ingress &amp;ndash; Gateway API
&lt;/h3>&lt;p>&lt;a class="link" href="https://mp.weixin.qq.com/s/-PPIdsSts2TlRzbecPxTHQ" target="_blank" rel="noopener"
>https://mp.weixin.qq.com/s/-PPIdsSts2TlRzbecPxTHQ&lt;/a>&lt;/p>
&lt;h3 id="云原生代理-traefik--ingress-controllerhttpsmpweixinqqcomsj82ohvdhs7xkwvs8zzzsfq">&lt;a class="link" href="https://mp.weixin.qq.com/s/J82OHVdHs7XkwVs8zZzSfQ" target="_blank" rel="noopener"
>云原生代理 Traefik — Ingress Controller&lt;/a>
&lt;/h3>&lt;p>&lt;a class="link" href="https://mp.weixin.qq.com/s/J82OHVdHs7XkwVs8zZzSfQ" target="_blank" rel="noopener"
>https://mp.weixin.qq.com/s/J82OHVdHs7XkwVs8zZzSfQ&lt;/a>&lt;/p>
&lt;h3 id="ingress-nginx-退役">Ingress NGINX 退役
&lt;/h3>&lt;p>Ingress NGINX 退役及替代方案： &lt;a class="link" href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" target="_blank" rel="noopener"
>https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/&lt;/a>&lt;/p>
&lt;p>第三方 ingress 控制器：&lt;/p>
&lt;p>&lt;a class="link" href="https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#third-party-ingress-controllers" target="_blank" rel="noopener"
>https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#third-party-ingress-controllers&lt;/a>&lt;/p>
&lt;h3 id="nginx-ingress-controller-官方文档">NGINX Ingress Controller 官方文档
&lt;/h3>&lt;p>&lt;a class="link" href="https://docs.nginx.com/nginx-ingress-controller/install/manifests/" target="_blank" rel="noopener"
>https://docs.nginx.com/nginx-ingress-controller/install/manifests/&lt;/a>&lt;/p></description></item></channel></rss>