试着使用 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操作员。
安装运营商之后的观察。
我会查看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 控制器)
有一个名为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) 已部署。
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
$
部署样本应用程序
创建一个新的项目(命名空间)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进行访问。