找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4693

积分

0

好友

648

主题
发表于 2 小时前 | 查看: 2| 回复: 0

此篇文章介绍 Azure Kubernetes Service(即 Azure AKS)服务的完整落地实践,涵盖集群创建、网络模型理解、应用暴露、Ingress-nginx 部署、证书自动化管理(cert-manager + Cloudflare DNS01)、内部负载均衡改造,以及最终通过 Application Gateway Ingress Controller(AGIC)实现生产级 HTTPS 流量路由。全过程基于真实 Azure 门户操作与 kubectl/helm 命令验证,适配 Azure CNI 网络模型与 West Europe 区域环境。

1. 创建 Azure AKS 集群

在 Azure 门户中,通过 Create a resource → Marketplace → Kubernetes service 启动集群创建流程。关键配置如下:

  • Subscription: starttech  
  • Resource group: test  
  • Region: West Europe  
  • Cluster name: testaks  
  • Kubernetes version: 1.33.7(LTS 版本,兼顾稳定性与新特性)  
  • Node pools: 1 个默认节点池,禁用虚拟节点与自动扩缩容  
  • Network configuration: 默认 Azure CNI Node Subnet(Pod 与 Node 共享同一 VNet 子网)

Azure门户中创建Kubernetes集群的配置界面截图,当前处于'Review + create'步骤。页面包含Basics、Node pools、Access等配置区域,显示了订阅为'startech'、资源组为'test'、区域为'West Europe'、集群名为'testaks'、K8s版本1.33.7等信息,节点池数量为1,虚拟节点和自动扩缩容均禁用

后续进入 Networking 配置页,确认网络策略引擎为 Azure,Load Balancer 类型为 Standard,DNS 名称前缀为 testaks-dns

一张网页截图,显示的是在 Azure 平台中创建 Kubernetes 集群的配置界面,页面标题为 'Create Kubernetes cluster',包含 Network configuration、Integrations、Monitoring、Advanced、Security 等多个配置区块

点击 Review + create 完成校验后部署。部署成功后跳转至资源概览页,状态显示 Your deployment is complete,集群运行状态为 Running,操作状态为 Succeeded

Azure 门户中部署完成页面截图,显示部署名称为 microsoft.aks-1774630447219,状态为‘Your deployment is complete’(您的部署已完成),绿色对勾图标

集群仪表盘显示关键元数据:  

  • 资源组:test  
  • 位置:West Europe  
  • Kubernetes 版本:1.33.7  
  • API 服务器地址:testaks-dns-r7f1zoc6.hcp.westeurope.azmk8s.io  
  • SKU:Base,定价层级:Free

Azure Kubernetes Service (AKS) 仪表盘截图,显示名为 'testaks-1774630447219' 的集群概览页面。左侧导航栏包含 Overview、Activity log、Access control (IAM)、Tags、Monitor 等选项

2. 理解 AKS 网络模型与资源拓扑

由于创建时未指定已有虚拟网络(VNet),Azure 自动创建配套资源:

  • 虚拟网络:aks-vnet-31772138  
  • 子网:aks-subnet(CIDR: 10.224.0.0/16)  
  • 负载均衡器:kubernetes(Public IP 类型)  
  • 网络安全组、VM、磁盘、网络接口等一并生成  

Azure 门户中 Kubernetes 服务(testaks)的 Networking 页面截图,当前选中 'Virtual network integration' 选项卡。左侧导航栏高亮显示 'Networking',右侧主区域显示虚拟网络集成信息:虚拟网络为 'aks-vnet-31772138',子网为 'aks-subnet';下方还显示 Application Gateway ingress controller 状态为 'Not enabled'。

Azure 门户中虚拟网络 'aks-vnet-31772138' 的子网页面截图,左侧导航栏高亮显示 'Subnets',主区域为子网列表,红色框标出四行子网信息,包含名称、IPv4地址段、可用IP数及分配情况

该集群采用 Azure CNI Node Subnet 模式,意味着 Pod IP 与 Node IP 处于同一 VNet 地址空间(如 10.224.0.0/16)。这种设计带来高性能直连,但也要求提前规划子网容量——若业务增长导致 Pod 数量激增,需确保子网 CIDR 足够容纳所有 Node + Pod IP。

Azure Kubernetes Service (AKS) 服务概览页面截图,显示名为 'aks-test-32254795-vms2' 的集群基本信息。页面包含状态、节点池、区域等概要信息,其中 'Internal IP' 字段被红色框标出,值为 '10.224.0.33'。

Kubernetes Pod 列表界面截图,显示 kube-system 命名空间下的多个运行中 Pod,包含 Pod 名称、命名空间、就绪状态、重启次数、年龄、CPU/内存使用率条形图、节点名称及 Pod IP 地址列;右侧红色框突出显示了多行 Pod IP 地址,均为 10.224.x.x 网段

查看资源组 MC_test_testaks_westeurope 可见 Azure 自动生成的底层资源,包括:

  • 公共 IP 地址(kubernetes LB 使用)  
  • 网络安全组(aks-agentpool-31772138-nsg)  
  • 虚拟机(aks-test-32254795-vms1/vms2)  
  • 虚拟网络(aks-vnet-31772138)  
  • 负载均衡器(kubernetes)  

Azure 门户中名为'MC_test_testaks_westeurope'的资源组页面截图,显示了资源组概览信息、标签、资源列表及左侧导航菜单。右侧资源列表包含公共IP地址、网络安全组、虚拟机、磁盘、网络接口、虚拟网络、负载均衡器和托管标识等资源,均位于'West Europe'区域。

3. 获取 AKS 集群 kubeconfig 并验证连接

为脱离 Azure 门户进行命令行操作,需获取集群认证凭据:

[root@k8sworker ~]# az login
[root@k8sworker ~]# az account set --subscription "starttech"
[root@k8sworker ~]# az aks get-credentials --resource-group test --name testaks
Merged "testaks" as current context in /root/.kube/config

验证节点状态:

[root@k8sworker ~]# kubectl get nodes
NAME                         STATUS   ROLES    AGE   VERSION
aks-test-32254795-vms1       Ready    <none>   25m   v1.33.7
aks-test-32254795-vms2       Ready    <none>   25m   v1.33.7

4. 部署应用并通过 LoadBalancer Service 暴露

4.1 部署 Nginx Deployment

# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            cpu: 250m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 1

应用部署:

[root@k8sworker aks]# kubectl create -f nginx-deploy.yaml
deployment.apps/nginx created
[root@k8sworker aks]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
nginx-68b45b8b47-s9dmr       1/1     Running   0          67s

4.2 创建 LoadBalancer Service

# nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
[root@k8sworker aks]# kubectl apply -f nginx-svc.yaml
service/nginx-service created
[root@k8sworker aks]# kubectl get svc
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
kubernetes      ClusterIP      10.0.0.1       <none>          443/TCP        39m
nginx-service   LoadBalancer   10.0.169.185   20.31.123.121   80:32424/TCP   44s

此时 Azure 自动分配公网 IP 20.31.123.121,并创建对应健康探针(TCP:80)与后端池规则。

Azure 门户中 Kubernetes 负载均衡器的前端 IP 配置界面截图,显示两个负载均衡器配置项列表,其中第二行被红色矩形框高亮,包含名称、IP 地址和规则数量信息

Azure 门户中 Load balancing rules 页面的截图,显示负载均衡规则健康状态面板。左侧导航栏高亮 'Load balancing rules',主内容区包含健康探针信息(Protocol/Port: TCP/80,IP address count: 2,Health probe ID),以及 Overall state 显示 100% 实例健康

访问 http://20.31.123.121 可见 Nginx 欢迎页(Anolis OS 版本):

网页截图,显示Nginx在Anolis OS上的默认欢迎页面。顶部为橙色横幅,写有'Welcome to nginx on Anolis OS!';下方正文区域说明该页用于测试Nginx HTTP服务器是否正常运行

4.3 绑定自定义域名并启用 HTTPS

为支持 HTTPS,需扩展 Service 监听 443 端口:

# nginx-svc.yaml(更新版)
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 443
[root@k8sworker aks]# kubectl apply -f nginx-svc.yaml
service/nginx-service configured
[root@k8sworker aks]# kubectl get svc
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                          AGE
kubernetes      ClusterIP      10.0.0.1       <none>          443/TCP                          55m
nginx-service   LoadBalancer   10.0.169.185   20.31.123.121   80:32424/TCP,443:30811/TCP       16m

Azure 自动新增 TCP:443 健康探针与负载均衡规则:

Kubernetes 仪表盘界面,显示 'Health probes' 页面,左侧导航栏高亮 'Health probes',中间表格列出两条 TCP 协议的健康探针记录,其 Name 列内容被红色方框突出标注,分别为 'a75070873f643a493830af6643a44-TCP-80' 和 'a75070873f643a493830af6643a44-TCP-443',对应 Port 分别为 32424 和 30811

一张 Azure 门户中 Kubernetes 负载均衡规则配置页面的截图,显示了负载均衡器的规则列表。红色框内为两行负载均衡规则记录,包含名称(以 a7507... 开头的 UUID 格式)、协议(TCP/80 和 TCP/443)、后端池(kubernetes)、健康探测信息及健康状态链接

在 DNS 提供商(如 Cloudflare)为域名 jsonjsonstart.dpdns.org 添加 A 记录指向 20.31.123.121

DNS管理界面截图,显示域名jsonjsonstart.dpdns.org的DNS记录管理页面,包含标题、描述文字、搜索框、添加过滤器和记录按钮,下方表格列有Type、Name、Content、Proxy status、TTL、Actions等字段,其中高亮显示一条A记录:名称为jsonjsonstart.dpdns....,内容为20.31.123.121,代理状态为DNS only,TTL为Auto

访问 http://jsonjsonstart.dpdns.org 成功,但 HTTPS 尚未生效(因无证书与 TLS 终止)。

一张网页截图,显示的是Nginx在Anolis OS系统上的默认欢迎页面。顶部为橙色横幅,写有'Welcome to nginx on Anolis OS!';下方是测试说明文字,指出该页面用于测试Nginx HTTP服务器是否正常运行;中间有一个带橙色标题栏的白色区域,标题为'Website Administrator',内含三行英文说明文字,提及默认index.html文件位置、内容放置建议及配置文件路径;底部左侧有NGINX标志,右侧有'POWERED BY'字样及一个绿色图标;右下角有中文水印'公众号·运维技术吧'。页面顶部浏览器地址栏显示'jsonsonstart.dpdns.org',并提示'不安全'。

5. 部署 ingress-nginx 并切换为 Internal LoadBalancer

5.1 安装 Helm 并部署 ingress-nginx

[root@k8sworker aks]# curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
[root@k8sworker aks]# helm version
version.BuildInfo{Version:"v3.20.1", GitCommit:"a2369ca71c0ef633bf6e4fccd66d634eb379b371", GitTreeState:"clean", GoVersion:"go1.25.8"}
[root@k8sworker aks]# helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace

部署后检查资源:

[root@k8sworker aks]# kubectl -n ingress-nginx get all
NAME                                                              READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-6797f4dc8c-wtxbv                    1/1     Running   0          64s

NAME                                                         TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE
service/ingress-nginx-controller                             LoadBalancer   10.0.76.231   20.93.232.76    80:31497/TCP,443:31454/TCP   65s
service/ingress-nginx-controller-admission                   ClusterIP      10.0.80.235   <none>          443/TCP                      65s

NAME                                                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller                     1/1     1            1           66s

NAME                                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-6797f4dc8c                   1         1         1       66s

Azure 门户中 Kubernetes 服务(testaks)的 Services and ingresses 页面截图,左侧导航栏高亮 'Services and ingresses',主区域为服务列表,包含 Name、Namespace、Status、Type、Cluster IP、External IP、Ports、Age 等列;其中三行被红色矩形框突出:nginx-service(LoadBalancer类型,Cluster IP 10.0.169.185,External IP 26.31.123.121,端口 80:32424/TC P,443:30811/TC P)、ingress-nginx-controller(LoadBalancer类型,Cluster IP 10.0.76.231,External IP 26.93.233.76,端口 80:31497/TC P,443:31454/TC P)、ingress-nginx-controller-admission(ClusterIP类型)

5.2 修改 Service 为 Internal LoadBalancer

默认 ingress-nginx-controller Service 是 Public 类型。为增强安全性并配合后续 AGIC 架构,需将其改为 Internal(Private)IP:

编辑 Service YAML,在 metadata.annotations 中添加:

service.beta.kubernetes.io/azure-load-balancer-internal: "true"

一张展示 Kubernetes Ingress NGINX 控制器 YAML 配置文件的网页截图,界面为 Azure Kubernetes Service(AKS)服务页面,当前选中 Yaml 标签页,显示了 YAML 代码内容,其中第20行 'service.beta.kubernetes.io/azure-load-balancer-internal: "true"' 被红色矩形框高亮标注

刷新后可见 External IP 已变为 Internal IP(如 10.224.0.62):

Azure 门户中 Kubernetes 服务(testaks)的 Services and ingresses 页面截图,左侧导航栏高亮 'Services and ingresses',主区域为服务列表,包含 Name、Namespace、Status、Type、Cluster IP、External IP、Ports、Age 等列;其中 'ingress-nginx-controller' 服务被勾选,其状态为 'Ok',类型为 'LoadBalancer',Cluster IP 为 '10.0.76.231',External IP 为 '10.224.0.62';另一条记录 'ingress-nginx-controller-admission' 状态也为 'Ok',类型为 'ClusterIP'。

该 Internal IP 属于 MC_test_testaks_westeurope 资源组下的 kubernetes-internal 负载均衡器:

Azure 门户中名为'MC_test_testaks_westeurope'的资源组页面截图,显示了资源组的基本信息(订阅、ID、标签、位置等)及其中包含的多个资源列表,包括公共IP地址、网络安全组、虚拟机、磁盘、网络接口、虚拟网络、负载均衡器和托管标识等;底部红色框标出了一项名为'kubernetes-internal'的负载均衡器资源

6. 部署 cert-manager + Cloudflare DNS01 实现自动证书签发

6.1 安装 cert-manager

[root@k8sworker aks]# helm repo add jetstack https://charts.jetstack.io
"jetstack" has been added to your repositories
[root@k8sworker aks]# helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.14.0 --set installCRDs=true

验证安装:

[root@k8sworker aks]# kubectl get pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-7cd8b77b5-p2nj5               1/1     Running   0          51s
cert-manager-cainjector-86db5d9886-kmb4f   1/1     Running   0          51s
cert-manager-webhook-6d4778b87b-4ff6f      1/1     Running   0          51s

6.2 配置 Cloudflare API Token

在 Cloudflare 控制台创建具有 Zone:ReadZone:DNS:Edit 权限的 API Token:

Cloudflare 控制台用户API令牌管理页面截图,左侧导航栏高亮显示'My Profile'和'API Tokens'选项,主区域标题为'User API Tokens',包含API令牌管理说明、蓝色'Create Token'按钮、无API令牌的表格提示以及API Keys部分

一张网页截图,显示的是‘User API Tokens’页面,标题下方有‘← Edit token’链接,接着是‘Edit zone DNS API token summary’的说明文字,指出该API令牌将影响特定账户和区域及其权限。下方列出账户信息:Jsonjsonstart@gmail.com的账户,其下子项为jsonjsonstart.dpdns.org - Zone:Read, DNS:Edit。底部有两个按钮:灰色的‘Cancel’和蓝色的‘Create Token’。

创建 Kubernetes Secret:

[root@k8sworker aks]# kubectl create secret generic cloudflare-api-token --from-literal=api-token="cfut_xlaD5nCoMU7t" -n cert-manager
secret/cloudflare-api-token created

⚠️ 注意:示例 Token 不完整,实际请使用 Cloudflare 控制台生成的完整密钥。

验证 Secret:

[root@k8sworker aks]# kubectl get secret -n cert-manager
NAME                         TYPE     DATA   AGE
cert-manager-webhook-ca      Opaque   3      9m8s
cloudflare-api-token         Opaque   1      48s
sh.helm.release.v1.cert-manager.v1  helm.sh/release.v1  1  9m21s

6.3 创建 ClusterIssuer 与 Certificate

cluster-issuer.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-cloudflare
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: jsonjsonstart@gmail.com
    privateKeySecretRef:
      name: letsencrypt-cloudflare-account-key
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token
            key: api-token
      selector:
        dnsNames:
          - "common.jsonjsonstart.dpdns.org"
          - "blog.jsonjsonstart.dpdns.org"
[root@k8sworker aks]# kubectl apply -f cluster-issuer.yaml
clusterissuer.cert-manager.io/letsencrypt-cloudflare created

certificate.yaml

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: blog-dpdns-org
  namespace: default
spec:
  secretName: blog-dpdns-org-tls
  issuerRef:
    name: letsencrypt-cloudflare
    kind: ClusterIssuer
  dnsNames:
    - "blog.jsonjsonstart.dpdns.org"
    - "common.jsonjsonstart.dpdns.org"
[root@k8sworker aks]# kubectl apply -f certificate.yaml
certificate.cert-manager.io/blog-dpdns-org created

查看证书申请状态:

[root@k8sworker aks]# kubectl describe certificate blog-dpdns-org -n default
...
Events:
  Type    Reason      Age   From                                  Message
  Normal  Issuing     2m12s cert-manager-certificates-trigger     Issuing certificate as Secret does not exist.
  Normal  Generated   2m12s cert-manager-certificates-request-manager  Stored new private key in temporary Secret resource 'blog-dpdns-org-v1y8z'
  Normal  Requested   2m12s cert-manager-certificates-request-manager  Created new CertificateRequest resource 'blog-dpdns-org-1'
  Normal  Issuing     26s   cert-manager-certificates-issuing    The certificate has been successfully issued

终端界面显示 Kubernetes 中 cert-manager 的证书描述信息,包含元数据、规格、状态和事件日志;底部红色框内为事件消息区域,记录证书创建与颁发过程,其中一条关键消息显示‘The certificate has been successfully issued’

证书已成功签发,有效期至 2026年6月26日

7. 创建 Ingress 资源并验证 TLS 终止

blog-ingress.yaml(面向 ingress-nginx):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: blog-ingress
  namespace: default
spec:
  tls:
  - hosts:
      - blog.jsonjsonstart.dpdns.org
    secretName: blog-dpdns-org-tls
  rules:
  - host: blog.jsonjsonstart.dpdns.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
[root@k8sworker aks]# kubectl create -f blog-ingress.yaml
Warning: annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/blog-ingress created

Azure 门户中 Kubernetes 服务(testaks)的 Services and ingresses 页面截图,左侧导航栏高亮 'Services and ingresses',主区域为 Ingresses 列表,包含一列数据:Name 为 'blog-ingress',Namespace 为 'default',Class 为 'nginx',Hosts 为 'blog.jonsonstart.dpdns.org',Address 为 '10.224.0.62',Ports 为 '80, 443',Age 为 '1 minute'。

由于 ingress-nginx Controller 使用 Internal IP,需在集群内验证 TLS:

[root@k8sworker aks]# kubectl exec -it nginx-68b45b8b47-ckzhl -- sh
sh-4.4# curl --resolve blog.jsonjsonstart.dpdns.org:443:10.224.0.62 https://blog.jsonjsonstart.dpdns.org -v
...
* Server certificate:
*  subject: CN=blog.jsonjsonstart.dpdns.org
*  start date: Mar 28 06:41:12 2026 GMT
*  expire date: Jun 26 06:41:11 2026 GMT
*  SSL certificate verify ok.

证书过期时间确认为 Jun 26 06:41:11 2026 GMT,TLS 握手成功。

8. 创建 Application Gateway 并手动配置路由(非 AGIC)

为实现更高级的 WAF、SSL 卸载与精细化路由,我们创建独立的 Application Gateway:

  • Gateway name: appgw-aks  
  • Tier: WAF V2  
  • Instance count: 2  
  • Virtual network: aks-vnet-31772138  
  • Subnet: aks-appgw(新建 /24 子网)  
  • Frontend IPs: Public (appgw-public-ip) + Private (10.225.0.10)  

Azure 门户中创建应用网关的配置界面截图,显示订阅、资源组、实例详情(包括网关名称 appgw-aks、区域 West Europe、层级 WAF V2、实例数 2、IPv4 仅选、HTTP2 启用、FIPS 已禁用、WAF 策略 appgw-aks)以及虚拟网络配置(虚拟网络 aks-vnet-31772138、子网 aks-appgw (10.225.0.0/24))

Azure 门户中创建应用网关的‘Frontends’配置页面截图,显示了前端IP地址类型选择(Public、Private、Both),当前选中Public;下方有‘Public IPv4 address’输入框,显示为‘(New) appgw-public-ip’并带下拉箭头,下方有蓝色链接‘Add new’

后端池指向 ingress-nginx Controller 的 Internal IP(10.224.0.62):

Microsoft Azure 门户界面,显示创建应用网关的‘Backends’(后端)配置页面。左侧为导航步骤栏,当前在‘Backends’步骤,已通过‘Basics’和‘Frontends’;下方有‘Add a backend pool’按钮及‘No results’提示。右侧为‘Add a backend pool.’配置面板,包含名称输入框(值为‘aks_backendpool’)、‘Add backend pool without targets’开关(设为‘Yes’)、‘Target type’下拉框(选中‘IP address or FQDN’),以及一个目标条目:IP地址‘10.224.62’。

路由规则配置 HTTPS Listener(端口 443),绑定上传的 PFX 证书(由 cert-manager 导出):

[root@k8sworker aks]# kubectl get secret blog-dpdns-org-tls -o jsonpath='{.data.tls\.crt}' | base64 -d > cert.crt
[root@k8sworker aks]# kubectl get secret blog-dpdns-org-tls -o jsonpath='{.data.tls\.key}' | base64 -d > cert.key
[root@k8sworker aks]# openssl pkcs12 -export -out cert.pfx -inkey cert.key -in cert.crt -passout pass:password

Microsoft Azure Portal 中 Application Gateway 的 'Add Backend setting' 配置页面截图,左侧显示 'Frontends' 区域包含公共和私有 IP 地址信息,中间为 'Routing rules' 添加路由规则按钮;右侧配置区域包括:Backend settings 名称 'aks_httpsetting'、协议 HTTP/HTTPS(选中 HTTPS)、端口 443;Backend HTTPS validation settings 中证书验证类型为 'Complete validation',证书颁发机构为 'Public CA';Additional backend settings 包含 Cookie-based affinity(Disable)、Connection draining(Disable)、Dedicated backend connection(Enable)、Request time-out(20 秒)、Override backend path(空)、Override hostname 选 'No';底部有 'Add' 和 'Cancel' 按钮

部署完成后,Gateway 拥有 Public IP(51.137.17.218)与 Private IP(10.225.0.10),并自动创建健康探针与后端健康检查:

Microsoft Azure 应用网关的前端 IP 配置页面截图,左侧导航栏高亮显示‘Frontend IP configurations’,主区域以表格形式列出两个配置:类型为 Public 的配置(名称 appGwPublicFrontendIpV4,IP 地址 51.137.17.218,关联监听器为 -),类型为 Private 的配置(名称 appGwPrivateFrontendIpV4,IP 地址 10.225.0.10,关联监听器为 aks_listener)

Azure 门户中 Application Gateway 的 Backend health 状态监控页面截图,显示 Backend health(后端健康)信息。左侧导航栏包含 Backend settings、Frontend IP configurations 等选项。主区域上方有说明文字,下方有两个状态卡片:All(1/1,红色心形图标)、Healthy(1/1,绿色对勾图标)。再下方是后端服务器健康详情表格,含 Server(backend pool)、Status(绿色 Healthy 标识)、Port、Protocol(Http)、Details(Success. Received 300 status code)及 Action 列

❗ 问题发现:Cloudflare 若将域名 blog.jsonjsonstart.dpdns.org 的 A 记录指向 Gateway Public IP 51.137.17.218,请求会失败——因为当前 Listener 仅绑定在 Private IP 10.225.0.10 上,Public IP 未配置任何 Listener。

9. 部署 Application Gateway Ingress Controller(AGIC)

为彻底解耦配置、实现声明式路由,我们启用官方 AGIC

  • 前提:AKS 必须启用 Azure CNI Node Subnet(已满足)  
  • 在 AKS 门户中,进入 Networking → Application Gateway ingress controller → Enable 即可一键部署  

Azure 门户中 'testaks | Networking' 页面的截图,显示左侧导航栏高亮 'Networking' 选项,右侧主内容区处于 'Virtual network integration' 标签页。页面显示虚拟网络(aks-vnet-31772138)和子网(aks-subnet)信息,下方红色框内为 'Application Gateway ingress controller' 模块,显示 'Ingress controller' 状态为 'Not enabled',并带有一个 'Manage' 按钮

启用后,AGIC 自动创建以下资源:

  • Application Gateway:ingress-appgateway(含 Public & Private IP)  
  • Public IP:ingress-appgateway-appgwip  
  • 托管标识:ingress-applicationgateway-testaks  
  • 新建子网:ingress-appgateway-subnet10.225.0.0/16)  

Azure 门户中一个名为 MC_test_testaks_westeurope 的资源组的资源列表界面截图,左侧为导航菜单,中间为资源表格,包含多个 Azure 资源如虚拟机、网络接口、应用网关等;红色框选区域突出显示了三个与 'ingress-appgateway' 相关的资源:ingress-appgateway(应用网关)、ingress-appgateway-appgwip(公共 IP 地址)、ingress-applicationgateway-testaks(托管标识),均位于 West Europe 区域

Azure 门户中虚拟网络(aks-vnet-31772138)的子网管理界面截图,显示了子网列表,包含名称、IPv4地址范围、可用IP数、分配对象、安全组和路由表等列。其中名为 'ingress-appgateway-subnet' 的子网被红色框高亮标出,其IPv4地址为10.225.0.0/16,可用IP数显示为'availability dependent on ...',Delegated to 列显示为'Microsoft.ContainerService',Security group 为'aks-agentpool-31772...'。

AGIC 的核心优势在于:它监听 Kubernetes Ingress 资源变更,并自动同步到 Application Gateway 的 Listener、Routing Rule、Backend Pool、Health Probe 等配置,无需手动维护。

9.1 创建 AGIC 专用 Ingress

blog-ingress-agic.yaml

# blog-ingress-agic.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: blog-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/ssl-redirect: "true"
    appgw.ingress.kubernetes.io/use-private-ip: "true"  # 强制使用 Internal IP
spec:
  tls:
  - hosts:
      - blog.jsonjsonstart.dpdns.org
    secretName: blog-dpdns-org-tls  # cert-manager 生成的证书
  rules:
  - host: blog.jsonjsonstart.dpdns.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service  # 你的后端 Service
            port:
              number: 80
[root@k8sworker aks]# kubectl create -f blog-ingress-agic.yaml
ingress.networking.k8s.io/blog-ingress created

AGIC 自动创建:

  • Listener:aks_listener(HTTPS:443,绑定 Private IP 10.225.0.10)  
  • Routing Rule:aks_rule  
  • Backend Pool:pool-default-nginx-service-80-bp-80(指向 Pod IP 10.224.0.29)  
  • Health Probe:pb-default-nginx-service-80-blog-ingress(HTTP GET /)  
  • TLS 证书:cert-default-blog-odpns-org-tls(自动上传)  

一个云服务管理界面的截图,显示了Ingresses(入口)列表页面。页面顶部有'Services'和'Ingresses'两个标签页,当前激活的是'Ingresses'。下方有筛选控件:'Filter by namespace'下拉框(当前选中'All namespaces')、'Ingress name: All'输入框及'Add label filter'按钮。主体是一个表格,包含列标题:Name、Namespace、Class、Hosts、Address、Ports、Age。表格中有一行数据:Name为'blog-ingress',Namespace为'default',Class为'azure/application-gateway',Hosts为'blog.json561420789.org',Address为'10.233.6.10',Ports为'80, 443',Age为'2 minutes'。

Azure 门户中 Application Gateway 的 Backend pools 页面截图,显示左侧导航栏选中 'Backend pools',顶部标题为 'ingress-appgateway | Backend pools',中间表格包含一列 'Name'(值为 'pool-default-nginx:service-80-bp-80'),以及 'Rules associated'(值为 1)和 'Targets'(值为 1)两列

一张Azure应用网关后端池配置界面的截图,显示‘Edit backend pool’页面。页面包含名称输入框,内容为‘pool-default-nginx-service-80-bp-80’;‘Add backend pool without targets’选项,当前选中‘No’;‘Backend targets’部分显示1个目标,其中‘Target’列被红色方框突出标出,值为‘10.224.0.29’;下方是目标类型下拉菜单(当前为‘IP address or FQDN’)及对应输入框;底部显示关联规则ID和右下角水印‘公众号 · 运维技术吧’。

Azure 门户中 Application Gateway 的 Backend health 状态监控页面截图,显示 Backend health(后端健康)信息。左侧导航栏包含 Backend settings、Frontend IP configurations 等选项。主区域上方有说明文字,下方有两个状态卡片:All(1/1,红色心形图标)、Healthy(1/1,绿色对勾图标)。再下方是后端服务器健康详情表格,含 Server(backend pool)、Status(绿色 Healthy 标识)、Port、Protocol(Http)、Details(Success. Received 300 status code)及 Action 列

AGIC 的本质是“控制器”,它只负责配置同步,不参与数据平面转发。因此,当 Ingress 资源创建后,Gateway 的所有路由组件即刻就绪,且后端健康检查直接命中 Pod IP(10.224.0.29),绕过 NodePort 层,延迟更低、路径更短。

总结与架构演进建议

本文完整覆盖了 Azure AKS 生产级流量接入链路:

Client → Cloudflare DNS → Application Gateway (Public IP) 
       ↓
       Application Gateway (Private IP) → AKS Ingress Controller (AGIC) → nginx-service → nginx Pod

关键结论:

  • Azure CNI 是 AGIC 的硬性前提:确保 Pod IP 可被 Gateway 直接路由。  
  • AGIC 实现真正的 GitOps:Ingress YAML 即基础设施即代码,Gateway 配置全自动同步。  
  • ⚠️ Public IP 与 Listener 必须显式绑定:若需对外暴露,应在 AGIC Ingress 中移除 appgw.ingress.kubernetes.io/use-private-ip: "true",或额外配置 Public IP Listener。  
  • 🔐 证书全生命周期自动化:cert-manager + Cloudflare DNS01 实现零人工干预续签。  

如需进一步提升可观测性与稳定性,建议结合 云栈社区 的 DevOps/SRE 实践指南,集成 Grafana、Prometheus 与 ELK Stack,构建端到端 SLO 监控体系。




上一篇:Spring事务面试核心:传播行为、隔离级别与七种失效场景详解
下一篇:MindsDB实战解析:用SQL零ETL查询大模型,重构数据管道与AI Agent开发
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-30 04:56 , Processed in 0.562696 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表