Skip to content

CKA自学笔记19:Ingress-nginx

演示场景:

  • 部署Ingress Controller。
  • 创建两个Deployment nginx-app-1nginx-app-2
  • 在运行主机上创建主机目录 /root/html-1/root/html-2 并挂载到两个Deployment上。
  • 创建Service。
  • 创建Service nginx-app-1nginx-app-2并将其映射到相关的Deploymentnginx-app-1nginx-app-2
  • 创建Ingress。
  • 创建Ingress资源nginx-app并将其映射到两个Servicesnginx-app-1nginx-app-1
  • 测试可访问性。
  • 向Ingress中定义的两个主机发送HTTP请求。

参考:

部署Ingress控制器

获取Ingress控制器的yaml文件。最新版本的链接在安装指南中。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

修改deploy.yaml文件中镜像源为阿里云的源。

deploy.yaml文件中需要修改的行:

image: k8s.gcr.io/ingress-nginx/controller:v1.2.1@sha256:5516d103a9c2ecc4f026efbd4b40662ce22dc1f824fb129ed121460aaa5c47f8
image: registry.k8s.io/ingress-nginx/controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5
image: k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660

修改内容:

  • k8s.gcr.io/ingress-nginx/controller 改为 registry.aliyuncs.com/google_containers/nginx-ingress-controller
  • registry.k8s.io/ingress-nginx/controller 改为 registry.aliyuncs.com/google_containers/nginx-ingress-controller
  • k8s.gcr.io/ingress-nginx/kube-webhook-certgen 改为 registry.aliyuncs.com/google_containers/kube-webhook-certgen

修改命令:

sed -i 's/k8s.gcr.io\/ingress-nginx\/kube-webhook-certgen/registry.aliyuncs.com\/google\_containers\/kube-webhook-certgen/g' deploy.yaml
sed -i 's/k8s.gcr.io\/ingress-nginx\/controller/registry.aliyuncs.com\/google\_containers\/nginx-ingress-controller/g' deploy.yaml

应用文件 deploy.yaml 来创建 Ingress Nginx。

一个新的命名空间namespace ingress-nginx 会被创建,Ingress Nginx相关的资源运行在这个namespace上。

kubectl apply -f deploy.yaml

查看Pod的状态。

kubectl get pod -n ingress-nginx

确保所以pod的运行状态都正常,类似如下结果:

NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-lgtdj        0/1     Completed   0          49s
ingress-nginx-admission-patch-nk9fv         0/1     Completed   0          49s
ingress-nginx-controller-556fbd6d6f-6jl4x   1/1     Running     0          49s

本地测试方式

让我们创建一个简单的 Web 服务器和相关的服务:

kubectl create deployment demo --image=httpd --port=80
kubectl expose deployment demo

接下来创建一个 Ingress 资源。以下示例使用将主机映射到 localhost:

kubectl create ingress demo-localhost --class=nginx --rule="demo.localdev.me/*=demo:80"

现在,将本地端口转发到Ingress控制器:

kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80

现在,在另一个终端中访问 http://demo.localdev.me:8080/,我们应该看到一个 HTML 页面,上面写着 "It works!"。

curl http://demo.localdev.me:8080/

运行结果;

<html><body><h1>It works!</h1></body></html>

删除演示中创建的临时资源。

kubectl delete ingress demo-localhost
kubectl delete service demo
kubectl delete deployment demo

创建Deployments

创建2个deployment nginx-app-1nginx-app-2

kubectl apply -f - << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app-1
spec:
  selector:
    matchLabels:
      app: nginx-app-1
  replicas: 1 
  template:
    metadata:
      labels:
        app: nginx-app-1
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
          - name: html
            mountPath: /usr/share/nginx/html
      volumes:
       - name: html
         hostPath:
           path: /opt/html-1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app-2
spec:
  selector:
    matchLabels:
      app: nginx-app-2
  replicas: 1 
  template:
    metadata:
      labels:
        app: nginx-app-2
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
          - name: html
            mountPath: /usr/share/nginx/html
      volumes:
       - name: html
         hostPath:
           path: /opt/html-2
EOF

执行命令 kubectl get pod -o wide 来获取pod的状态。 可以看到一个pod运行在节点 cka002,另外一个pod运行在节点cka003

  • Directory /opt/html-2/ is on cka002
  • Directory /opt/html-1/ is on cka002

通过curl命令来访问这2个pod,收到403 Forbidden错误。

curl 10.244.102.13
curl 10.244.112.19

登录到节点cka002,执行下面命令,在/opt/html-2/路径下创建文件index.html

cat <<EOF | sudo tee /opt/html-2/index.html
This is test 2 !!
EOF

登录到节点cka003,执行下面命令,在/opt/html-1/路径下创建文件index.html

cat <<EOF | sudo tee /opt/html-1/index.html
This is test 1 !!
EOF

执行命令kubectl get pod -o wide,再次检查2个pod的状态。

curl 10.244.102.13
curl 10.244.112.19

现在可以通过curl命令来访问这2个pod了,收到了正确的回复信息。

This is test 1 !!
This is test 2 !!

创建Service

创建 nginx-app-1nginx-app-2 这2个 Service,并将它们分别映射到相关的 Deployment nginx-app-1nginx-app-2

kubectl apply -f - << EOF
apiVersion: v1
kind: Service
metadata:
 name: nginx-app-1
spec:
 ports:
 - protocol: TCP
   port: 80
   targetPort: 80
 selector:
   app: nginx-app-1
---
kind: Service
apiVersion: v1
metadata:
 name: nginx-app-2
spec:
 ports:
 - protocol: TCP
   port: 80
   targetPort: 80
 selector:
   app: nginx-app-2
EOF

检查刚刚创建的service的状态。

kubectl get svc -o wide

尝试通过curl命令来访问刚刚创建的service。

curl 11.244.165.64
curl 11.244.222.177

收到了正确的信息,说明访问成功。

This is test 1 !!
This is test 2 !!

创建Ingress

创建 Ingress 资源 nginx-app,将其映射到我们创建的两个 Service nginx-app-1nginx-app-2,并将其所在的 namespace 改为 default

kubectl apply -f - << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginx-app
  namespace: default
spec:
  ingressClassName: "nginx"
  rules:
  - host: app1.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-app-1
            port: 
              number: 80
  - host: app2.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-app-2
            port:
              number: 80
EOF

查看所创建的Ingress资源的状态。

kubectl get ingress

可访问性测试

执行以下命令,来确定 Ingress 控制器正在节点 cka003 上运行。

kubectl get pod -n ingress-nginx -o wide

在当前节点上更新 /etc/hosts 文件。 将节点cka003的IP地址与两个主机名app1.comapp1.com进行映射,这些主机名表示Servicesnginx-app-1nginx-app-2。 Ingress Controllers正在节点cka003上运行。

cat <<EOF | sudo tee -a /etc/hosts
<cka003_ip>  app1.com
<cka003_ip>  app2.com
EOF

执行以下命令,可以得到 IP 地址或 FQDN。

kubectl get service ingress-nginx-controller --namespace=ingress-nginx

在输出结果中可以看到 EXTERNAL-IP 字段。如果该字段像下面一样显示为 <pending>,这意味着 Kubernetes 集群无法提供负载均衡器(通常是因为它不支持 LoadBalancer 类型的服务)。

由于没有配置阿里云 ELB,因此有以下两个选项可以解决这个问题。

选项 1:手动将节点 IP 添加到运行 ingress 控制器的节点上。

执行命令 kubectl get pod -n ingress-nginx -o wide 来查看 ingress 控制器 pod 运行在哪个节点上。

手动将 cka003 的外部 IP 补丁到 EXTERNAL-IP 字段。

kubectl patch svc ingress-nginx-controller \
 --namespace=ingress-nginx \
 -p '{"spec": {"type": "LoadBalancer", "externalIPs":["<cka003_ip>"]}}'

选项 2:将 ingress 控制器从 LoadBalancer 类型更改为 NodePort 类型。

两个 Pod 中各有一个 index.html 文件,Web 服务通过节点 IP 对外暴露。ingress-nginx-controller 作为中心入口点,为来自 Pod 的不同后端服务提供了两个端口。

发送HTTP请求到在Ingress中定义的2个主机节点。

curl http://app1.com:30011
curl http://app2.com:30011

curl app1.com:30011
curl app2.com:30011

可以得到下面的信息,说明访问成功。

This is test 1 !!
This is test 2 !!

删除上面演示中创建的临时资源。

kubectl delete ingress ingress-nginx-app
kubectl delete service nginx-app-1
kubectl delete service nginx-app-2
kubectl delete deployment nginx-app-1
kubectl delete deployment nginx-app-2