试着使用 ROSA 上的 Nginx Ingress Operator

首先

ROSA(Red Hat OpenShift on AWS)有一个内置的标准 Ingress 控制器,但我们将尝试使用 Nginx 的 Ingress Operator,以替代默认的 Ingress,并使用 Nginx 的 Ingress 控制器。

ROSA 是什么意思?

ROSA 是在 AWS 上提供的 Red Hat OpenShift 托管服务。虽然命名格式不同,但可以简单地说它是 AKS、EKS、GKE 的 Red Hat 版本。

使用的是 OpenShift,它是 Red Hat 的 Kubernetes 发行版。

请提供相关参考资料。

我参考了以下的GitHub仓库。

 

安装 Nginx Ingress Operator

从操作员中心安装Ingress操作员。

image.png
image.png
image.png

安装运营商之后的观察。

我会查看Pod。已安装的运算符正在以Pod的形式运行。

$ oc project nginx-ingress
Now using project "nginx-ingress" on server "https://api.f5cluster.m51o.p1.openshiftapps.com:6443".
$ oc get pods
NAME                                                         READY   STATUS    RESTARTS   AGE
nginx-ingress-operator-controller-manager-85b49c485b-p89sp   2/2     Running   0          90s
$ 

这一次,我将查看Service资源。
从名称来看,它似乎是提供指标的东西。

$ oc get svc
NAME                                                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-ingress-operator-controller-manager-metrics-service   ClusterIP   172.30.208.138   <none>        8443/TCP   38s
$ 

创建 Nginx Ingress 控制器

我会创建Nginx Ingress Controller。通过创建NginxIngress资源,将生成Nginx Ingress Controller的Pod。

创建和观察SCC

在创建 Ingress Controller 之前,OpenShift 需要以下的 SCC(安全上下文约束)。

kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-ingress-helm-operator/main/resources/scc.yaml

我会大致确认一下已经申请的yaml文件的内容。我可以看到正在创建一个名为nginx-ingress-admin的SCC。

$   curl https://raw.githubusercontent.com/nginxinc/nginx-ingress-helm-operator/main/resources/scc.yaml
# Create SCC for IC resources
kind: SecurityContextConstraints
apiVersion: security.openshift.io/v1
metadata:
  name: nginx-ingress-admin
allowPrivilegedContainer: false
runAsUser:
  type: MustRunAs
  uid: 101
seLinuxContext:
  type: MustRunAs
fsGroup:
  type: MustRunAs
supplementalGroups:
  type: MustRunAs
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowHostDirVolumePlugin: false
allowHostIPC: false
readOnlyRootFilesystem: false
seccompProfiles:    
- runtime/default
volumes:
 - secret
requiredDropCapabilities:
 - ALL
users:
 - 'system:serviceaccount:*:nginx-ingress'
allowedCapabilities:
  - NET_BIND_SERVICE
$ 

创建 Nginx Ingress 资源 (Ingress 控制器)

image.png
image.png
image.png

有一个名为nginxingress-sample-nginx-ingress-controller-788b95fb47-gdt2j的Pod被创建了出来。从名称上可以看出,这个新创建的Pod就是Nginx Ingress Controller。

$  oc get pods
NAME                                                            READY   STATUS    RESTARTS   AGE
nginx-ingress-operator-controller-manager-85b49c485b-p89sp      2/2     Running   0          9m50s
nginxingress-sample-nginx-ingress-controller-788b95fb47-27fcj   1/1     Running   0          6s
$ 

我也会查看Service。已创建了类型为Loadbalancer的Service资源。

$ oc get svc
NAME                                                        TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)                      AGE
nginx-ingress-operator-controller-manager-metrics-service   ClusterIP      172.30.208.138   <none>                                                                        8443/TCP                     15m
nginxingress-sample-nginx-ingress-controller                LoadBalancer   172.30.108.226   a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com   80:30936/TCP,443:32344/TCP   5m24s
$ 

让我们更仔细地看一下这个 Service Type=LoadBalancer。

$ oc describe service nginxingress-sample-nginx-ingress-controller
Name:                     nginxingress-sample-nginx-ingress-controller
Namespace:                nginx-ingress
Labels:                   app.kubernetes.io/instance=nginxingress-sample
                          app.kubernetes.io/managed-by=Helm
                          app.kubernetes.io/name=nginx-ingress
                          app.kubernetes.io/version=3.1.1
                          helm.sh/chart=nginx-ingress-0.17.1
Annotations:              meta.helm.sh/release-name: nginxingress-sample
                          meta.helm.sh/release-namespace: nginx-ingress
Selector:                 app.kubernetes.io/instance=nginxingress-sample,app.kubernetes.io/name=nginx-ingress
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       172.30.108.226
IPs:                      172.30.108.226
LoadBalancer Ingress:     a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30936/TCP
Endpoints:                10.128.2.71:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  32344/TCP
Endpoints:                10.128.2.71:443
Session Affinity:         None
External Traffic Policy:  Local
HealthCheck NodePort:     31957
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  EnsuringLoadBalancer  45m   service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   45m   service-controller  Ensured load balancer
$ 

交通流量似乎如下所示:新的经典负载均衡器 (ELB) 已部署。

ELB(NGINX専用)
Node Port
Pod Network (Ingress Controller Pod)80/TCP=>30396/TCP=>10.128.2.71:80/TCP443/TCP=>32344/TCP=>10.128.2.71:443/TCP

当我们调查最后一个 Pod Network 的 IP(Endpoint)的所有者时,我们发现它是 Nginx 的 Ingress Controller Pod。

$ oc get endpoints
NAME                                                        ENDPOINTS                        AGE
nginx-ingress-operator-controller-manager-metrics-service   10.131.0.121:8443                59m
nginxingress-sample-nginx-ingress-controller                10.128.2.71:443,10.128.2.71:80   49m
$ 
image.png

部署样本应用程序

创建一个新的项目(命名空间)hello-openshift,用于部署应用程序。

oc new-project hello-openshift

部署应用程序。

oc new-app --image=docker.io/openshift/hello-openshift  --labels=test=app

确认是否已创建了服务资源。

$ oc get svc
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
hello-openshift   ClusterIP   172.30.126.194   <none>        8080/TCP,8888/TCP   10s
$ 

使用Ingress资源发布示例应用程序

在hello-openshift应用程序项目的命名空间中创建Ingress资源。

宛先是刚刚创建的名为 hello-openshift 的 Service 资源。

OpenShift可以处理标准的Ingress资源和Route资源。

为了处理由Nginx Ingress Controller创建的Ingress资源,似乎需要以下注释。

  annotations:
    kubernetes.io/ingress.class: "nginx"

总体而言,情况如下。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  defaultBackend:
    service:
      name: hello-openshift
      port:
        number: 8080
  rules:
  - host: test.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-openshift
            port:
              number: 8080
oc apply -f ingress.yaml

确认 Ingress 资源的创建情况。

$ oc get ingress
NAME           CLASS    HOSTS              ADDRESS                                                                       PORTS   AGE
test-ingress   <none>   test.example.com   a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com   80      6s
$ 

我会伪造Host标头为test.example.com进行访问。

$  curl -H 'Host:test.example.com' a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com
Hello OpenShift!
$

我順利能夠進行訪問了。

注解: kubernetes.io/ingress.class 的補充項目。

中国境内的Ingress资源如下所述:

 annotations:
    kubernetes.io/ingress.class: "nginx"

如果添加了注解,在创建Ingress资源时,Nginx Ingress Controller的Deployment日志将显示此注解已被标记为已弃用,因此会发出警告并忽略。

W0624 05:10:44.855157       1 controller.go:3915] Using the DEPRECATED annotation 'kubernetes.io/ingress.class'. The 'ingressClassName' field will be ignored.

如果不附加此注释并创建Ingres资源,则似乎会将其作为OpenShift的标准Ingress处理。因此,如果想要将Ingress交给Nginx Ingress Controller处理,似乎需要添加注释。

以下的 test-ingress 是创建带有注释的 Ingress 资源的示例,test-ingress2 是创建没有注释的 Ingress 资源的示例。

$ oc get ingress
NAME            CLASS    HOSTS               ADDRESS                                                                       PORTS   AGE
test-ingress    <none>   test.example.com    a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com   80      59m
test-ingress2   <none>   test2.example.com   router-default.apps.f5cluster.m51o.p1.openshiftapps.com                       80      14s
$ 

除了注释部分和名称之外,这是相同的入口资源,但下面的内容表明与ROSA的标准应用程序域名相关联。

增加 Nginx 入口控制器 Pod

默认情况下,将部署一个 Nginx Ingress Controller 的 Pod。

为了实现冗长化,我们尝试将 Nginx Ingress Controller 的 Pod 增加到两个。
通过修改 NginxIngress 资源的 replicaCount 数量,我们成功地增加了 Pod 数量。

$ oc get nginxingress 
NAME                  AGE
nginxingress-sample   104m
$

寻找 replicaCount。

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: charts.nginx.org/v1alpha1
kind: NginxIngress
metadata:
  annotations:
    operator-sdk/primary-resource: /nginx
    operator-sdk/primary-resource-type: IngressClass.networking.k8s.io
  creationTimestamp: "2023-06-24T04:00:23Z"
  finalizers:
  - helm.sdk.operatorframework.io/uninstall-release
  generation: 2
  name: nginxingress-sample
  namespace: nginx-ingress
  resourceVersion: "1326212"
  uid: 9f9a09ac-b916-4779-9b6b-a86c688e3105
spec:
  controller:
    affinity: {}
    annotations: {}
    appprotect:
      enable: false

<省略>

    pod:
      annotations: {}
      extraLabels: {}
    podDisruptionBudget:
      annotations: {}
      enabled: false
    readyStatus:
      enable: true
      initialDelaySeconds: 0
      port: 8081
    replicaCount: 2  ## ここを 1=> 2 に増やす
    reportIngressStatus:
      annotations: {}
      enable: true
      enableLeaderElection: true
      ingressLink: ""

<省略>

Ingress 控制器的 Pod 增加了。(下面的两行)

$ oc get pods -o wide
NAME                                                            READY   STATUS    RESTARTS   AGE    IP             NODE                                              NOMINATED NODE   READINESS GATES
nginx-ingress-operator-controller-manager-85b49c485b-p89sp      2/2     Running   0          132m   10.131.0.121   ip-10-0-225-101.ap-northeast-1.compute.internal   <none>           <none>
nginxingress-sample-nginx-ingress-controller-788b95fb47-27fcj   1/1     Running   0          123m   10.128.2.71    ip-10-0-225-132.ap-northeast-1.compute.internal   <none>           <none>
nginxingress-sample-nginx-ingress-controller-788b95fb47-rx6gx   1/1     Running   0          13s    10.131.0.136   ip-10-0-225-101.ap-northeast-1.compute.internal   <none>           <none>
$ 

可以确认负载均衡服务的EndPoint也在增加。

$ oc get svc
NAME                                                        TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)                      AGE
nginx-ingress-operator-controller-manager-metrics-service   ClusterIP      172.30.208.138   <none>                                                                        8443/TCP                     133m
nginxingress-sample-nginx-ingress-controller                LoadBalancer   172.30.108.226   a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com   80:30936/TCP,443:32344/TCP   123m
$ oc describe svc nginxingress-sample-nginx-ingress-controller
Name:                     nginxingress-sample-nginx-ingress-controller
Namespace:                nginx-ingress
Labels:                   app.kubernetes.io/instance=nginxingress-sample
                          app.kubernetes.io/managed-by=Helm
                          app.kubernetes.io/name=nginx-ingress
                          app.kubernetes.io/version=3.1.1
                          helm.sh/chart=nginx-ingress-0.17.1
Annotations:              meta.helm.sh/release-name: nginxingress-sample
                          meta.helm.sh/release-namespace: nginx-ingress
Selector:                 app.kubernetes.io/instance=nginxingress-sample,app.kubernetes.io/name=nginx-ingress
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       172.30.108.226
IPs:                      172.30.108.226
LoadBalancer Ingress:     a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30936/TCP
Endpoints:                10.128.2.71:80,10.131.0.136:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  32344/TCP
Endpoints:                10.128.2.71:443,10.131.0.136:443
Session Affinity:         None
External Traffic Policy:  Local
HealthCheck NodePort:     31957
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  EnsuringLoadBalancer  124m  service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   123m  service-controller  Ensured load balancer
$ 


[附带] 公开使用Route资源的示例应用程序

我們試著用 OpenShift 的 Route 資源來公開相同的 Service,並確認它是否可行。OpenShift 的 Route 資源是基於 Ingress 的原理,但是有 OpenShift 獨特的實作方式。

在hello-openshift应用程序项目的命名空间中创建一个路由资源。
如果要使用路由公开HTTP服务,则使用oc expose命令会更简单。

$ oc expose service  hello-openshift 
route.route.openshift.io/hello-openshift exposed
$ 

查看已创建的Route资源。

$ oc get route
NAME              HOST/PORT                                                                  PATH   SERVICES          PORT       TERMINATION   WILDCARD
hello-openshift   hello-openshift-hello-openshift.apps.f5cluster.m51o.p1.openshiftapps.com          hello-openshift   8080-tcp                 None
$ 

我将尝试确认是否可以访问。如果未指定主机名,您会发现 ROSA 服务默认使用的基本域是 Red Hat 已获取的公共域名。

我会尝试使用curl命令进行确认访问。

$ curl http://hello-openshift-hello-openshift.apps.f5cluster.m51o.p1.openshiftapps.com
Hello OpenShift!
$ 

我已确认可以为同一服务创建Ingress和Route,并通过它们分别公开资源的URL进行访问。

广告
将在 10 秒后关闭
bannerAds