はじめに
ROSA(Red Hat OpenShift on AWS)
には、標準の Ingress Controller
が存在していますが、標準の Ingress
の代わりに Nginx
の Ingress Operator
を使用して、Nginx
のIngress Controller
を使用してみます。
ROSA(Red Hat OpenShift on AWS) とは?
ROSA
は、Red Hat OpenShift
の AWS
上で提供されているマネージド・サービスです。名前のフォーマットは違いますが、簡単に言うと、AKS
、EKS
、GKE
の Red Hat
版です。
Red Hat
の Kubernetes Districution である OpenShift
が使われています。
参考資料
以下の Git Hub のレポを参考にしました。
Nginx Ingress Operator のインストール
Operator Hub より Ingress Operator をインストールします。
ここは特に何の設定もせず、デフォルのままインストールボタンをクリックします。
Operatorインストール後の観察
Pod を見てみます。インストールされた Operator が 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
リソースを見てみます。
名前からして、metrics を提供するもののようです。
$ 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 Controller の作成
Nginx Ingress Controller
を作成していきます。NginxIngress
リソースを作成する事で、Nginx Ingress Controller
の Pod が生成されます。
SCC の作成と観察
Ingress Controller
の作成前に、OpenShift
では、以下の SCC(Security Context Cosntrain)
が必要になります。
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-ingress-helm-operator/main/resources/scc.yaml
一応、apply した 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
$
NginxIngess リソース (Ingress Controller) の作成
「Nginx Ingress Controller」というタブをクリックして、「Create NginxIngess」をクリックします。
殺風景ですが、とりあえずデフォルトのままNginxIngress
というカスタムリソースを作ります。
Namespace nginx-ingress
内に nginxingress-sample
という名前の NginxIngress
リソースが作成されました。
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
$
また Serivce
も確認してみます。Type=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 (Classic Load Balancer)
が、デプロイされていました。
ELB(NGINX専用) | Node Port | Pod Network (Ingress Controller Pod) | ||
---|---|---|---|---|
80/TCP | => | 30396/TCP | => | 10.128.2.71:80/TCP |
443/TCP | => | 32344/TCP | => | 10.128.2.71:443/TCP |
この最後の Pod Network
の IP (Ednpoint) の持ち主を調べてみると、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
$
ここで Nginx Ingress Controller
用に作成されてい ELB
は、ROSA
のものとは別に専用に作成されていました。(一番上のハイライトした行)
サンプルのアプリケーションのデプロイ
アプリケーションをデプロイするための 新しいプロジェクト (namespace)、 hello-openshift
を作成します。
oc new-project hello-openshift
アプリケーションをデプロイします。
oc new-app --image=docker.io/openshift/hello-openshift --labels=test=app
Service
リソースも作成されている事を確認します。
$ 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 リソースを使ったサンプル・アプリの公開
アプリケーションのプロジェクト(namespace)、hello-openshift
内に Ingress
リソースを作成します。
宛先は、先ほど作成された hello-openshift
という Service
リソースです。
OpenShift は、標準で Ingress
リソース も Route
リソースも処理できるようになっています。
Nginx Ingress Controller
に作成した Ingress
リソースを処理させるためには、以下の annotation
が必要になるようです。
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
$
-H で Host ヘッダーを test.example.com
に偽装してアクセスしてみます。
$ curl -H 'Host:test.example.com' a231a916ac00948919cea40dbc043dfd-866973151.ap-northeast-1.elb.amazonaws.com
Hello OpenShift!
$
無事アクセスできました。
補則 : annotation: kubernetes.io/ingress.class
Ingress
リソースに以下の
annotations:
kubernetes.io/ingress.class: "nginx"
annoation
を付けた場合、Ingress
リソース作成時に Nginx Ingress Controller
の Deployment
のログに、この annotation
は DEPRECATED なので、無視されると Warning が出ます。
W0624 05:10:44.855157 1 controller.go:3915] Using the DEPRECATED annotation 'kubernetes.io/ingress.class'. The 'ingressClassName' field will be ignored.
一方で、この annotation
を付けないで Ingres
リソースを作成した場合、OpenShift の標準の Ingress
として処理されるようです。そのため、Nginx Ingress Controller
に Ingress
を処理させたい場合は、annotation
を付ける必要がありそうです。
以下の test-ingress
は、annotation 付き、 test-ingress2
は、annotation 無しで 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
$
annotation
の部分と名前以外は同じ Ingress
リソースですが、下の方は ROSA
の標準のアプリケーションドメインと紐付いている事がわかります。
Nginx Ingress Controller Pod を増やす
デフォルトでは1個の Nginx Ingress Controller
の Pod
がデプロイされます。
冗長化を図るために、Nginx Ingress Controller
の Pod
を2つに増やしてみます。
これは、NginxIngress
リソースの replicaCaount
数を編集する事で増やす事ができました。
$ 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 Controller
の Pod
が増えました。(下の2行)
$ 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>
$
Service
Type=LoadBalancer
の 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リソースを使用したサンプル・アプリの公開
今度は同じ Service
を、OpenShift の Route
リソースで公開できるか確認してみます。
OpenShift の Route
リソースは、Ingress の元になった OpenShift 独自の実装です。
アプリケーションのプロジェクト(namespace) hello-openshift
内に Route
リソースを作成します。
Route
を使って HTTPで Service
を公開する場合は 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
$
アクセスできる確認してみます。特に Hostname を指定しなければ、ROSA のサービスが標準で持っている Red Hat が取得済みのパブリック・ドメインが、ベースのドメインとしてデフォルトで使用されているのがわかります。
curl
コマンドでアクセスできる確認してみます。
$ curl http://hello-openshift-hello-openshift.apps.f5cluster.m51o.p1.openshiftapps.com
Hello OpenShift!
$
同じ Service
に対して、Ingress
と Route
を作成し、それぞれのリソースが公開する URL経由でアクセスできる事が確認できました。