浏览代码

Init commit

Kyle Zhang 5 月之前
当前提交
80aefb7d4f

+ 201 - 0
expose/expose-via-external-lb.md

@@ -0,0 +1,201 @@
+# 使用集群外的负载均衡软件
+
+在裸机环境中,可以使用 Nginx、HAProxy 等负载均衡软件,将外部流量转发到 Nginx Ingress Controller 的服务。
+
+使用 Nginx、HAProxy 等负载均衡软件, 任选一个
+
+## 1. 使用 Nginx 配置多个 Upstream 和 Proxy Protocol
+
+**步骤 1:配置 Nginx 作为负载均衡器**
+
+1. **编辑 Nginx 配置文件**:
+
+   打开 Nginx 配置文件(通常位于 `/etc/nginx/nginx.conf` 或 `/etc/nginx/conf.d/default.conf`),并添加 TCP 负载均衡配置。
+
+   ```nginx
+   stream {
+       log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
+       
+       access_log /var/log/nginx/access.log main;
+   
+       upstream ingress_http {
+           server <node1-ip>:30080;
+           server <node2-ip>:30080;
+           server <node3-ip>:30080;
+           # 添加更多节点...
+       }
+   
+       upstream ingress_https {
+           server <node1-ip>:30443;
+           server <node2-ip>:30443;
+           server <node3-ip>:30443;
+           # 添加更多节点...
+       }
+   
+       server {
+           listen 80;
+           proxy_pass ingress_http;
+           proxy_protocol on;
+       }
+   
+       server {
+           listen 443;
+           proxy_pass ingress_https;
+           proxy_protocol on;
+       }
+   }
+   ```
+
+   **配置说明**:
+
+   - `upstream ingress_http` 和 `upstream ingress_https` 定义了两个不同的 `upstream` 组,一个处理 HTTP 流量(端口 80),另一个处理 HTTPS 流量(端口 443)。
+   - `proxy_protocol on;` 启用 Proxy Protocol 以确保客户端的真实 IP 地址能够传递给 Nginx Ingress Controller。
+   - `<node1-ip>`, `<node2-ip>`, `<node3-ip>` 替换为实际节点的 IP 地址。
+
+2. **重启 Nginx**:
+
+   应用配置更改并重启 Nginx:
+
+   ```sh
+   sudo systemctl restart nginx
+   ```
+
+**步骤 2:验证 Nginx 配置**
+
+确保 Nginx 正确配置并能够处理 TCP 流量和 Proxy Protocol。检查 Nginx 状态和日志:
+
+```sh
+sudo systemctl status nginx
+tail -f /var/log/nginx/access.log
+```
+
+## 2. 使用 HAProxy 配置多个 Upstream 和 Proxy Protocol
+
+**步骤 1:配置 HAProxy 作为负载均衡器**
+
+1. **编辑 HAProxy 配置文件**:
+
+   打开 HAProxy 配置文件(通常位于 `/etc/haproxy/haproxy.cfg`),并添加 TCP 负载均衡配置。
+
+   ```cc
+   global
+       log /dev/log local0
+       log /dev/log local1 notice
+       chroot /var/lib/haproxy
+       stats socket /run/haproxy/admin.sock mode 660
+       stats timeout 30s
+       user haproxy
+       group haproxy
+       daemon
+   
+   defaults
+       log     global
+       option  httplog
+       option  dontlognull
+       timeout connect 5000ms
+       timeout client  50000ms
+       timeout server  50000ms
+   
+   frontend http_front
+       bind *:80
+       default_backend http_back
+   
+   frontend https_front
+       bind *:443
+       default_backend https_back
+   
+   backend http_back
+       server ingress1 <node1-ip>:30080 check send-proxy
+       server ingress2 <node2-ip>:30080 check send-proxy
+       server ingress3 <node3-ip>:30080 check send-proxy
+       # 添加更多节点...
+   
+   backend https_back
+       server ingress1 <node1-ip>:30443 check send-proxy
+       server ingress2 <node2-ip>:30443 check send-proxy
+       server ingress3 <node3-ip>:30443 check send-proxy
+       # 添加更多节点...
+   ```
+
+   **配置说明**:
+
+   - `backend http_back` 和 `backend https_back` 定义了两个不同的 `backend` 组,一个处理 HTTP 流量(端口 80),另一个处理 HTTPS 流量(端口 443)。
+   - `send-proxy` 启用 Proxy Protocol,将客户端的真实 IP 地址传递给后端服务。
+   - `<node1-ip>`, `<node2-ip>`, `<node3-ip>` 替换为实际节点的 IP 地址。
+
+2. **重启 HAProxy**:
+
+   应用配置更改并重启 HAProxy:
+
+   ```sh
+   sudo systemctl restart haproxy
+   ```
+
+**步骤 2:验证 HAProxy 配置**
+
+确保 HAProxy 正确配置并能够处理 TCP 流量和 Proxy Protocol。检查 HAProxy 状态和日志:
+
+```sh
+sudo systemctl status haproxy
+tail -f /var/log/haproxy.log
+```
+
+# 配置 Nginx Ingress Controller
+
+1. **部署 Nginx Ingress Controller**:
+
+   将 Nginx Ingress Controller 的 Service 类型设置为 `NodePort`。
+
+   ```sh
+   helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
+   kubectl create namespace ingress-nginx
+   helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.service.type=NodePort --set controller.service.nodePorts.http=30080 --set controller.service.nodePorts.https=30443 --set ingressClassResource.default=true --namespace ingress-nginx
+   ```
+
+2. **配置防火墙**:
+
+   在每个节点的防火墙中开放 30080 和 30443 端口。
+
+   确保 Nginx Ingress Controller 支持 Proxy Protocol,以正确处理客户端的真实 IP 地址。
+
+3. **检查 Nginx Ingress Controller 配置**:
+
+   ```sh
+   kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml
+   ```
+
+4. **确认配置**:
+
+   确保 ConfigMap 中包含 `use-proxy-protocol: "true"` 配置。如果没有,需要创建或更新 ConfigMap:
+
+   ```yaml
+   apiVersion: v1
+   kind: ConfigMap
+   metadata:
+     name: nginx-configuration
+     namespace: ingress-nginx
+   data:
+     use-proxy-protocol: "true"
+   ```
+
+   应用更新的 ConfigMap:
+
+   ```sh
+   kubectl apply -f nginx-configmap.yaml
+   ```
+
+5. **重启 Nginx Ingress Controller**:
+
+   重新启动 Nginx Ingress Controller 以使配置更改生效:
+
+   ```sh
+   kubectl rollout restart deployment nginx-ingress-controller -n ingress-nginx
+   ```
+
+# 总结
+
+配置集群外的负载均衡器(Nginx 或 HAProxy)以处理多个节点,并将流量分配到不同的 `upstream` 组,同时启用 Proxy Protocol,可以确保客户端的真实 IP 地址被正确传递到集群内部的 Nginx Ingress Controller。配置过程中:
+
+- **Nginx 配置**:定义两个 `upstream` 组,分别处理 HTTP 和 HTTPS 流量,并启用 Proxy Protocol。
+- **HAProxy 配置**:定义两个 `backend` 组,分别处理 HTTP 和 HTTPS 流量,并启用 Proxy Protocol。
+- **Ingress Controller 配置**:确认 Proxy Protocol 设置,以确保正确处理客户端 IP 地址。

+ 23 - 0
expose/expose-via-hostnetwork.md

@@ -0,0 +1,23 @@
+# 使用 HostNetwork 模式
+
+将 Nginx Ingress Controller 作为 `DaemonSet` 部署,并启用 `HostNetwork` 以直接监听宿主机的 80 和 443 端口。
+
+## **步骤:**
+
+### 1. **部署 Nginx Ingress Controller**:
+
+   将 Nginx Ingress Controller 部署为 `DaemonSet`,并启用 `HostNetwork`。
+
+   ```sh
+   helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
+   kubectl create namespace ingress-nginx
+   helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.kind=DaemonSet --set controller.hostNetwork=true --set ingressClassResource.default=true --namespace ingress-nginx
+   ```
+
+### 2. **端口冲突**:
+
+   确保没有其他进程在 80 和 443 端口上运行。
+
+### 3. **DNS 配置**:
+
+   将域名的 DNS A 记录指向集群中任意一台节点的 IP 地址。

+ 109 - 0
expose/expose-via-kubelet-nodeport.md

@@ -0,0 +1,109 @@
+# 修改 Kubelet NodePort 地址范围暴露80,443端口
+
+通过修改 Kubelet 配置,将 NodePort 的地址范围扩展至 1~32767,并将 Nginx Ingress Controller 的 Service NodePort 端口映射到 80 和 443。
+
+## **步骤:**
+
+### 1. **修改 Kubelet 配置**:
+
+   在每个节点上,修改 Kubelet 启动参数,将 `--service-node-port-range` 参数设置为 `1-32767`。
+
+   - 在 `kubeadm` 部署中,编辑 `/var/lib/kubelet/config.yaml` 文件:
+
+     ```yaml
+     serviceNodePortRange: 1-32767
+     ```
+     
+   - 或者在启动文件中添加:
+
+     在多数系统中,Kubelet 的启动参数可以在 `/etc/default/kubelet` 或 `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` 中找到。如果你使用的是 systemd 管理 Kubelet,请编辑 `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` 文件。
+     
+     ```sh
+     KUBELET_EXTRA_ARGS="--service-node-port-range=1-32767"
+     ```
+
+### 2. **重启 Kubelet**:
+
+   重新启动 Kubelet 以使更改生效。
+
+   ```sh
+   sudo systemctl daemon-reload
+   sudo systemctl restart kubelet
+   ```
+
+### 3. **部署 Nginx Ingress Controller**:
+
+   使用 Helm 安装 Nginx Ingress Controller,将其 Service NodePort 端口设置为 80 和 443。
+
+为了确保客户端的真实 IP 地址能够在 NodePort 类型的服务中正确传递,你需要将 `externalTrafficPolicy` 设置为 `Local`。这将确保源地址转换(source IP preservation)在负载均衡到具体的节点上时得到应用。
+
+   ```sh
+helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
+kubectl create namespace ingress-nginx
+helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.kind=DaemonSet --set controller.service.type=NodePort --set controller.service.nodePorts.http=80 --set controller.service.nodePorts.https=443 --set controller.service.externalTrafficPolicy=Local --set ingressClassResource.default=true --namespace ingress-nginx
+   ```
+
+### 4. 配置 Ingress Controller 以支持 Proxy Protocol
+
+如果还有上游反向代理并开启了Proxy Protocol,可以配置 Nginx Ingress Controller 支持 Proxy Protocol,以便正确处理客户端的真实 IP 地址。
+
+**步骤 1:检查 Nginx Ingress Controller 配置**
+
+```sh
+kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml > nginx-configmap.yaml
+```
+
+**步骤 2:确认 Proxy Protocol 配置**
+
+确保 ConfigMap 中包含 `use-proxy-protocol: "true"` 配置。如果没有,请创建或更新 ConfigMap:
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: nginx-configuration
+  namespace: ingress-nginx
+data:
+  use-proxy-protocol: "true"
+```
+
+应用更新的 ConfigMap:
+
+```sh
+kubectl apply -f nginx-configmap.yaml
+```
+
+**步骤 3:重启 Nginx Ingress Controller**
+
+重新启动 Nginx Ingress Controller 以使配置更改生效:
+
+```sh
+kubectl rollout restart deployment nginx-ingress-controller -n ingress-nginx
+```
+
+### 5. **DNS 配置**:
+
+   将域名的 DNS A 记录指向集群中任意一台节点的 IP 地址,或多个节点。
+
+## 总结
+
+通过以下步骤,你可以调整 NodePort 地址范围并配置 NodePort 服务的 `externalTrafficPolicy`:
+
+- **修改 Kubelet 配置**:调整 NodePort 地址范围为 `1-32767`。
+- **配置 NodePort 服务**:将 `externalTrafficPolicy` 设置为 `Local`,以确保源地址转换。
+- **配置 Ingress Controller**:确保 Proxy Protocol 支持,以正确处理客户端 IP 地址。
+
+这些步骤将确保你的 NodePort 服务能够正确处理客户端 IP 地址,并且符合你的网络配置要求。
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 148 - 0
expose/expose-via-metallb.md

@@ -0,0 +1,148 @@
+# 使用 MetalLB 暴露 Nginx Ingress 的 80 和 443 端口
+
+MetalLB 是一种用于裸机 Kubernetes 集群的负载均衡器实现,能够通过发布集群外部的 IP 地址来暴露服务。此部分文档介绍 MetalLB 的地址发布模式、安装步骤、以及如何配置地址池并发布服务。
+
+## 1. [地址发布模式](https://metallb.universe.tf/concepts/#external-announcement)
+
+MetalLB 提供两种主要的地址发布模式:
+
+- [**Layer 2(L2)模式**:](https://metallb.universe.tf/concepts/layer2/)
+  - 在 L2 模式下,MetalLB 通过 ARP (IPV4)/ NDP(IPv6)通告将服务的 IP 地址分配给集群节点,并由集群中的节点直接响应 ARP 请求。这种模式适用于与 Kubernetes 集群处于同一二层网络的环境。
+- [**BGP 模式**:](https://metallb.universe.tf/concepts/bgp/)
+  - 在 BGP 模式下,MetalLB 通过 Border Gateway Protocol (BGP) 将服务的 IP 地址通告给外部网络设备,如路由器。此模式适用于需要跨多个网络段进行负载均衡的场景。
+
+在裸机环境中,Layer 2 模式通常更容易配置和管理,因此我们将重点介绍 Layer 2 模式。
+
+## 2. [安装 MetalLB](https://metallb.universe.tf/installation/)
+
+1. **准备**
+
+   如果您在 IPVS 模式下使用 kube-proxy,自 Kubernetes v1.14.2 起您必须启用严格 ARP 模式。
+
+   *请注意,如果您使用 kube-router 作为服务代理,则不需要此功能,因为它默认启用严格 ARP。*
+
+   您可以通过编辑当前集群中的 kube-proxy 配置来实现此目的:
+
+   ```bash
+   kubectl edit configmap -n kube-system kube-proxy
+   ```
+
+   并设置:
+
+   ```yaml
+   apiVersion: kubeproxy.config.k8s.io/v1alpha1
+   kind: KubeProxyConfiguration
+   mode: "ipvs"
+   ipvs:
+     strictARP: true
+   ```
+   如果您尝试自动执行此更改,这些 shell 代码片段可能会对您有所帮助:
+   
+   ```sh
+   # see what changes would be made, returns nonzero returncode if different
+   kubectl get configmap kube-proxy -n kube-system -o yaml | \
+   sed -e "s/strictARP: false/strictARP: true/" | \
+   kubectl diff -f - -n kube-system
+   
+   # actually apply the changes, returns nonzero returncode on errors only
+   kubectl get configmap kube-proxy -n kube-system -o yaml | \
+   sed -e "s/strictARP: false/strictARP: true/" | \
+   kubectl apply -f - -n kube-system\
+   ```
+
+2. **安装 MetalLB**:
+
+   安装 MetalLB 组件:
+
+   ```sh
+   wget https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
+   kubectl apply -f metallb-native.yaml
+   ```
+
+3. **验证安装**:
+
+   使用以下命令检查 MetalLB 是否成功部署:
+
+   ```sh
+   kubectl get pods -n metallb-system
+   ```
+
+   确保所有 Pod 都在 `Running` 状态。
+
+## 3. [配置地址池并发布服务](https://metallb.universe.tf/configuration/#layer-2-configuration)
+
+1. **配置 IP 地址池**:
+
+   创建一个 IPAddressPool,用于定义 MetalLB 使用的 IP 地址池。在此示例中,我们使用 `Layer 2` 模式。
+
+   创建一个名为 `metallb-addresspool.yaml` 的配置文件:
+
+   ```yaml
+   apiVersion: metallb.io/v1beta1
+   kind: IPAddressPool
+   metadata:
+     name: first-pool
+     namespace: metallb-system
+   spec:
+     addresses:
+     - 192.168.11.64/27
+   ```
+
+   创建一个名为 `metallb-l2advertisement.yaml` 的配置文件:
+
+   ```yaml
+   apiVersion: metallb.io/v1beta1
+   kind: L2Advertisement
+   metadata:
+     name: layer2publish
+     namespace: metallb-system
+   spec:
+     ipAddressPools:
+     - first-pool
+   ```
+
+2. **应用配置**:
+
+   将 `metallb-config.yaml` 应用到 Kubernetes 集群:
+
+   ```sh
+   kubectl apply -f metallb-addresspool.yaml
+   kubectl apply -f metallb-l2advertisement.yaml
+   ```
+
+## 4. **部署 Nginx Ingress Controller**:
+
+安装 Nginx Ingress Controller,并将 Service 类型设置为 `LoadBalancer`,让 MetalLB 为其分配一个外部 IP 地址:
+
+为了确保客户端的真实 IP 地址能够在 NodePort 类型的服务中正确传递,你需要将 `externalTrafficPolicy` 设置为 `Local`。这将保留客户端源地址(source IP preservation)。
+
+```sh
+helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
+kubectl create namespace ingress-nginx
+helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.service.type=LoadBalancer --set controller.service.externalTrafficPolicy=Local --set ingressClassResource.default=true --namespace ingress-nginx
+```
+
+1. **验证服务暴露**:
+
+   使用以下命令检查 Nginx Ingress Controller 的 Service,确保它获得了一个 MetalLB 分配的外部 IP 地址:
+
+   ```
+   kubectl get svc -n ingress-nginx
+   ```
+
+   输出应包含类似如下的信息:
+
+   ```
+   NAME                                 TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE
+   ingress-nginx-controller             LoadBalancer   10.96.122.1   192.168.11.64   80:30820/TCP,443:31867/TCP   2m
+   ```
+
+使用 `Layer 2` 模式时,MetalLB 将会感知 ingress-nginx-controller Pod的所在节点,并让所在节点响应EXTERNAL-IP ARP/NDP 请求,确保请求不发送到不存在ingress-nginx-controller Pod的节点。
+
+## 5. **DNS 配置**:
+
+   将域名的 DNS A 记录指向 MetalLB 分配的外部 IP 地址(如 `192.168.11.64`),以便外部用户能够通过域名访问 Nginx Ingress Controller。
+
+## 6. 总结
+
+通过 MetalLB,您可以在裸机 Kubernetes 集群中轻松暴露 Nginx Ingress 的 80 和 443 端口。Layer 2 模式的配置相对简单,非常适合小型集群或与 Kubernetes 节点处于同一网络的环境。通过正确配置 IP 地址池和地址发布模式,MetalLB 能够为 Kubernetes 服务提供可靠的负载均衡功能。

+ 539 - 0
本地环境部署Ngnix_ingress_certmanager.md

@@ -0,0 +1,539 @@
+# 本地环境部署 K8s Nginx ingress
+
+[TOC]
+
+## 开始之前
+
+国内可能会无法连接一些网站,需要准备好代理,然后运行
+
+```sh
+export http_proxy=192.168.11.61:11714
+export https_proxy=192.168.11.61:11714
+export no_proxy=.cn,.aliyun.com,.aliyuncs.com,.163.com,.baiduce.com,.qiniu.com,.daocloud.io,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10,169.254.0.0/16
+```
+
+请将`192.168.11.61:11714`修改成你的代理服务器地址和端口。
+
+## 1. 部署并曝露 Nginx Ingress 的 80 和 443 端口
+
+**云厂商方案**:使用 LoadBalancer 曝露 80 和 443 端口,并通过 DNS 配置将流量指向负载均衡器。
+
+**在裸机环境中**,有几种方式可以暴露 Nginx Ingress Controller 的 80 和 443 端口:
+
+
+1. [通过集群外的负载均衡软件](./expose/expose-via-external-lb.md)
+2. [通过 MetalLB 组件](./expose/expose-via-metallb.md)
+3. [通过 HostNetwork 模式,将 Nginx-Ingress-Controller 部署成 DaemonSet](./expose/expose-via-hostnetwork.md)
+4. [修改 Kubelet 将 NodePort 地址范围修改成 1-32767 端口](./expose/expose-via-kubelet-nodeport.md)
+
+可以根据具体需求选择一种方式。可以重点关注一下 MetalLB 组件。
+
+## 2. 部署 cert-manager
+
+**请将下文的 yourdomain.com 替换成真实的域名。**
+
+### 2.1 [安装 Cert-Manager](https://cert-manager.io/docs/installation/helm/)
+
+1. **添加 Helm 仓库并安装 cert-manager**:
+
+   ```sh
+   helm repo add jetstack https://charts.jetstack.io
+   helm repo update
+   
+   # 安装最新版本:
+   helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true
+   # 指定安装版本:
+   helm install cert-manager jetstack/cert-manager \
+     --namespace cert-manager \
+     --create-namespace \
+     --version v1.15.2 \
+     --set installCRDs=true
+   ```
+
+2. **验证 cert-manager 是否成功部署**:
+
+   ```sh
+   kubectl get pods --namespace cert-manager
+   ```
+
+### 2.1 [部署 cert-manager-alidns-webhook](https://github.com/DEVmachine-fr/cert-manager-alidns-webhook)
+
+本地环境通常无法通过公网访问,无法通过http的方式让CA验证域名所有权。需要通过DNS的方式让CA验证域名所有权。下面以阿里云DNS为例。[其他的DNS resolver](https://cert-manager.io/docs/configuration/acme/dns01/#webhook)。
+
+1. **添加 cert-manager-webhook-alidns Helm 仓库**:
+
+   ```sh
+   helm repo add cert-manager-alidns-webhook https://devmachine-fr.github.io/cert-manager-alidns-webhook
+   helm repo update
+   ```
+
+2. **安装 cert-manager-alidns-webhook**:
+
+   ```sh
+   helm install alidns-webhook cert-manager-alidns-webhook/alidns-webhook \
+     --namespace cert-manager \
+     --set groupName=acme.yourdomain.com
+   ```
+
+   **配置说明**:
+
+   - `groupName` 应该是唯一的,建议使用你的域名或类似标识。
+   
+3. **创建阿里云AKSK secret:**
+
+   在阿里云控制台创建一个RAM用户,并赋予DNSFullAccess 策略。在这个用户下创建access key。然后在k8s 创建secret:
+
+   ```sh
+   kubectl -n cert-manager create secret generic alidns-secrets --from-literal="access-token=yourtoken" --from-literal="secret-key=yoursecretkey"
+   ```
+
+​		确保将 `yourtoken`和`yoursecretkey` 修改成从阿里云控制台获得的 AK/SK。
+
+## 3. 配置 ClusterIssuer 和 Issuer
+
+**请将下文的 yourdomain.com 替换成真实的域名。**
+
+### 步骤 1:创建 Let's Encrypt ClusterIssuer
+
+1. **创建 ClusterIssuer 文件:**
+
+   ```yaml
+   apiVersion: cert-manager.io/v1
+   kind: ClusterIssuer
+   metadata:
+     name: letsencrypt-staging
+   spec:
+     acme:
+       server: https://acme-staging-v02.api.letsencrypt.org/directory
+       email: your-email@example.com
+       privateKeySecretRef:
+         name: letsencrypt-staging
+       solvers:
+       - dns01:
+           webhook:
+             groupName: acme.yourdomain.com
+             solverName: alidns-solver
+             config:
+               regionId: cn-beijing
+               accessKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-id
+               secretKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-secret
+         selector:
+           dnsZones:
+           - yourdomain.com
+   ```
+
+   ```yaml
+   apiVersion: cert-manager.io/v1
+   kind: ClusterIssuer
+   metadata:
+     name: letsencrypt-prod
+   spec:
+     acme:
+       server: https://acme-v02.api.letsencrypt.org/directory
+       email: your-email@example.com
+       privateKeySecretRef:
+         name: letsencrypt-prod
+       solvers:
+       - dns01:
+           webhook:
+             groupName: acme.yourdomain.com
+             solverName: alidns-solver
+             config:
+               regionId: cn-beijing
+               accessKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-id
+               secretKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-secret
+         selector:
+           dnsZones:
+           - yourdomain.com
+   
+   ```
+
+2. **应用配置**:
+
+   ```sh
+   kubectl apply -f letsencrypt-staging.yaml
+   kubectl apply -f letsencrypt-prod.yaml
+   ```
+
+**配置说明**:
+
+- `groupName` 需要和之前helm指定的一致。
+- `email` 需要修改为你的邮箱。
+
+### 步骤 2:创建 Let's Encrypt Issuer
+
+1. **创建 Issuer 文件:**
+
+   ```yaml
+   apiVersion: cert-manager.io/v1
+   kind: Issuer
+   metadata:
+     name: letsencrypt-staging-issuer
+     namespace: your-namespace
+   spec:
+     acme:
+       server: https://acme-staging-v02.api.letsencrypt.org/directory
+       email: your-email@example.com
+       privateKeySecretRef:
+         name: letsencrypt-staging
+       solvers:
+       - dns01:
+           webhook:
+             groupName: acme.yourdomain.com
+             solverName: alidns-solver
+             config:
+               regionId: cn-beijing
+               accessKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-id
+               secretKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-secret
+         selector:
+           dnsZones:
+           - yourdomain.com
+   ```
+
+   ```yaml
+   apiVersion: cert-manager.io/v1
+   kind: Issuer
+   metadata:
+     name: letsencrypt-prod-issuer
+     namespace: your-namespace
+   spec:
+     acme:
+       server: https://acme-v02.api.letsencrypt.org/directory
+       email: your-email@example.com
+       privateKeySecretRef:
+         name: letsencrypt-prod
+       solvers:
+       - dns01:
+           webhook:
+             groupName: acme.yourdomain.com
+             solverName: alidns-solver
+             config:
+               regionId: cn-beijing
+               accessKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-id
+               secretKeySecretRef:
+                 name: alidns-secret
+                 key: access-key-secret
+         selector:
+           dnsZones:
+           - yourdomain.com
+   ```
+
+2. **应用配置**:
+
+   ```sh
+   kubectl apply -f letsencrypt-staging-issuer.yaml
+   kubectl apply -f letsencrypt-prod-issuer.yaml
+   ```
+
+**配置说明**:
+
+- `groupName` 需要和之前helm指定的一致。
+- `email` 需要修改为你的邮箱。
+- `namespace` 需要和你的应用的 namespace 一致,否则无法找到 Issuer, 无法颁发证书。而之前的ClusterIssuer是Cluster级别的,不需要指定namespace。
+
+## 4. 部署测试应用并请求证书
+
+### 步骤 1:部署测试应用
+
+1. **创建测试应用的 Deployment 和 Service**:
+
+   ```yaml
+   apiVersion: apps/v1
+   kind: Deployment
+   metadata:
+     name: test-app
+     namespace: your-namespace
+   spec:
+     replicas: 1
+     selector:
+       matchLabels:
+         app: test-app
+     template:
+       metadata:
+         labels:
+           app: test-app
+       spec:
+         containers:
+         - name: test-app
+           image: nginx:alpine
+           ports:
+           - containerPort: 80
+   ```
+
+   ```yaml
+   apiVersion: v1
+   kind: Service
+   metadata:
+     name: test-app
+     namespace: your-namespace
+   spec:
+     selector:
+       app: test-app
+     ports:
+     - port: 80
+       targetPort: 80
+   ```
+
+2. **应用配置**:
+
+   ```yaml
+   kubectl apply -f test-app-deployment.yaml
+   kubectl apply -f test-app-service.yaml
+   ```
+
+### 步骤 2:创建 Ingress 资源并请求证书
+
+1. **创建 Ingress 资源**:
+
+   使用 Let's Encrypt Staging 请求证书:
+
+   ```yaml
+   apiVersion: networking.k8s.io/v1
+   kind: Ingress
+   metadata:
+     name: test-app-ingress
+     namespace: your-namespace
+     annotations:
+       cert-manager.io/cluster-issuer: "letsencrypt-staging"
+   spec:
+     rules:
+     - host: ingress-test.yourdomain.com
+       http:
+         paths:
+         - path: /
+           pathType: Prefix
+           backend:
+             service:
+               name: test-app
+               port:
+                 number: 80
+     tls:
+     - hosts:
+       - ingress-test.yourdomain.com
+       secretName: test-app-tls
+   ```
+
+2. **应用配置**:
+
+   ```sh
+   kubectl apply -f test-app-ingress.yaml
+   ```
+
+3. **验证证书颁发情况**:
+
+   查看 Ingress 的证书是否成功颁发:
+
+   ```sh
+   kubectl describe certificate test-app-tls -n your-namespace
+   ```
+
+4. **测试从浏览器访问**:
+
+​	先在阿里云DNS控制台创建DNS记录。然后在本地浏览器访问 https://ingress-test.yourdomain.com 
+
+### 步骤 3:切换到 Let's Encrypt Production
+
+1. **更新 Ingress 资源**:
+
+   将 `cert-manager.io/cluster-issuer` 注解从 `letsencrypt-staging` 更改为 `letsencrypt-prod`:
+
+   ```yaml
+   apiVersion: networking.k8s.io/v1
+   kind: Ingress
+   metadata:
+     name: test-app-ingress
+     namespace: your-namespace
+     annotations:
+       cert-manager.io/cluster-issuer: "letsencrypt-prod"
+   spec:
+     rules:
+     - host: ingress-test.yourdomain.com
+       http:
+         paths:
+         - path: /
+           pathType: Prefix
+           backend:
+             service:
+               name: test-app
+               port:
+                 number: 80
+     tls:
+     - hosts:
+       - ingress-test.yourdomain.com
+       secretName: test-app-tls
+   ```
+
+2. **应用更新**:
+
+   ```sh
+   kubectl apply -f test-app-ingress.yaml
+   ```
+
+
+
+### 步骤4. 使用 ECC 证书并配置密钥大小和轮换策略
+
+**步骤 1:指定颁发 ECC 证书**
+
+1. **修改 Ingress 或 Certificate 资源的注解**:
+
+   [注解文档](https://cert-manager.io/docs/usage/ingress/#supported-annotations)
+
+   添加以下注解来指定 ECC 证书并设置密钥大小和轮换策略:
+   
+   ```yaml
+   apiVersion: networking.k8s.io/v1
+   kind: Ingress
+   metadata:
+     name: test-app-ingress
+     namespace: your-namespace
+     annotations:
+       cert-manager.io/cluster-issuer: "letsencrypt-prod"
+       cert-manager.io/private-key-algorithm: "ECDSA"
+       cert-manager.io/private-key-size: "256"
+       cert-manager.io/private-key-rotation-policy: "Always"
+   spec:
+     rules:
+     - host: ingress-test.yourdomain.com
+       http:
+         paths:
+         - path: /
+           pathType: Prefix
+           backend:
+             service:
+               name: test-app
+               port:
+                 number: 80
+     tls:
+     - hosts:
+       - ingress-test.yourdomain.com
+       secretName: test-app-tls
+   ```
+
+**配置说明**:
+
+- `private-key-size: "256"`:指定 ECC 密钥的大小为 256 位。常用的 ECC 密钥大小有 256、384 和 521 位,256 位通常足够提供高强度的安全性。
+- `private-key-rotation-policy: "Always"`:启用私钥轮换策略,即每次证书更新时都生成新的私钥。这种策略有助于提高安全性,因为它减少了私钥泄露或被攻击的风险。
+
+1. **应用更新**:
+
+   ```sh
+   kubectl apply -f test-app-ingress.yaml
+   ```
+
+
+
+## 5. 总结
+
+- **部署并曝露 Nginx Ingress 的 80 和 443 端口**
+  - **云厂商方案**:使用 LoadBalancer 曝露 80 和 443 端口,并通过 DNS 配置将流量指向负载均衡器。
+
+  - **裸机环境方案:**
+    - **负载均衡软件**:使用 Nginx 或 HAProxy 将流量转发到 Ingress Controller。
+    - **MetalLB**:使用 MetalLB 组件在裸机环境中实现 LoadBalancer。
+    - **HostNetwork**:将 Nginx Ingress Controller 作为 DaemonSet 部署,并直接监听 80 和 443 端口。
+    - **修改 Kubelet NodePort 范围**:扩展 NodePort 范围以允许 80 和 443 端口。
+
+- **Cert manager 和 Ingress 配置 SSL 证书**:使用 cert-manager 自动管理和应用 SSL
+  - **Cert-Manager 和 Alidns Webhook**:通过 Helm 安装 Cert-Manager 和 cert-manager-alidns-webhook。
+  - **ClusterIssuer 和 Issuer**:配置 Let's Encrypt 的 Staging 和 Production Issuer。
+  - **测试应用部署**:使用 Let's Encrypt Staging 验证证书颁发流程,成功后切换到 Production。
+  - **ECC 证书配置**:通过注解指定 ECC 证书,并设置密钥大小和轮换策略以增强安全性。
+
+
+
+## 6. 清理资源
+
+### 1. 清理测试应用和证书
+
+**删除测试应用的 Deployment 和 Service**:
+
+```sh
+kubectl delete deployment test-app -n your-namespace
+kubectl delete service test-app -n your-namespace
+```
+
+**删除 Ingress 资源和证书**:
+
+```sh
+kubectl delete ingress test-app-ingress -n your-namespace
+kubectl delete certificate test-app-tls -n your-namespace
+```
+
+**删除 Issuer 和 ClusterIssuer**:
+
+```sh
+kubectl delete issuer letsencrypt-staging-issuer -n your-namespace
+kubectl delete issuer letsencrypt-prod-issuer -n your-namespace
+kubectl delete clusterissuer letsencrypt-staging
+kubectl delete clusterissuer letsencrypt-prod
+```
+
+### 2. 清理 Cert-Manager 和 Alidns Webhook
+
+**删除 Cert-Manager 和 Alidns Webhook**:
+
+```sh
+helm uninstall cert-manager -n cert-manager
+helm uninstall cert-manager-webhook-alidns -n cert-manager
+kubectl delete namespace cert-manager
+```
+
+### 3. 清理 Nginx Ingress Controller
+
+**删除 Nginx Ingress Controller**:
+
+```sh
+helm uninstall ingress-nginx -n ingress-nginx
+kubectl delete namespace ingress-nginx
+```
+
+### 4. 清理暴露 80 和 443 端口的资源
+
+**清理负载均衡软件(如 NGINX 或 HAProxy 配置文件)**:
+
+如果你使用了集群外的负载均衡软件如 NGINX 或 HAProxy,请移除你为暴露 80 和 443 端口而添加的配置。具体步骤请参考[之前的文档](./expose/expose-via-external-lb.md)。
+
+**删除 MetalLB 资源(如果使用了 MetalLB 方式)**:
+
+```
+kubectl delete -f metallb-addresspool.yaml
+kubectl delete -f metallb-l2advertisement.yaml
+kubectl delete -f metallb-native.yaml
+kubectl delete namespace metallb-system
+```
+
+**对于 HostNetwork**
+
+之前删除 Nginx Ingress Controller就已经完成清理。
+
+**恢复 Kubelet 配置(如果修改过 NodePort 范围)**:
+
+如果你修改过 Kubelet 的 `--nodeport-addresses` 范围,请恢复默认设置。具体步骤请参考[之前的文档](./expose/expose-via-kubelet-nodeport.md)。
+
+如果你修改过 `/var/lib/kubelet/config.yaml` 文件,可以更新这一行,或者删除这一行:
+
+```yaml
+serviceNodePortRange: 30000-32767
+```
+
+## 最终清理总结
+
+- **删除应用和证书**:删除所有测试应用、证书、Ingress 和相关资源。
+- **清理 Cert-Manager 和 Alidns Webhook**:删除 Cert-Manager 和 Alidns Webhook 以及它们的命名空间。
+- **删除 Nginx Ingress Controller**:卸载 Nginx Ingress Controller 并删除相关的命名空间。
+- **清理暴露端口的配置**:移除所有暴露 80 和 443 端口的配置,包括 MetaLB 和集群外的负载均衡软件配置,恢复 Kubelet 的 NodePort 配置。