ROSAのコンソールのアクセス経路と提供元Podを調査してみた

# はじめに

[前回の記事](https://qiita.com/sugimount-a/items/73d3ad7864e69cba2cc7) では、ROSA クラスターをデプロイする方法を紹介しました。前回の記事にも書いてあるのですが、ROSA Cluster には 付属の Console 用の Web ページが提供されています。

こんな感じの画面です。

![image-20211229163413790.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9b09f7a7-813c-21d7-2558-8d020a96e28c.png)



なお、Console 用の URL は、ROSA CLI で確認が可能です。

```
$ rosa describe cluster --cluster my-rosa02 | grep Console
Console URL:                https://console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com
```



この Console のアクセス経路や提供元がよくわからなかったので調査してみました。2021年12月時点での内容なので、将来的に変更される可能性があるので、よろしくお願いします。



# アーキテクチャ図

まず結論を書きます。調査した内容を図解しました。Console を提供しているのは、ROSA Cluster 内の Master Node で稼働している Pod でした。

![image-20211229185829295.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e9003340-cf72-da72-d284-bdbb61445d59.png)



アクセスの流れをざっくり説明します。

- Console URL の名前解決は、Route 53 で提供をしている。
- Console URL の名前解決先は、CLB となっている
- CLB は、Infrastructure Node で稼働している Router 用にアクセスしている
- Router は、元々定義されていたルートに従って、Master Node で稼働している Console 用の Pod にルーティングする
- Console 用 Pod が、実際の Console 用 Web ページを提供している



それぞれのコンポーネントの詳細を確認した内容を紹介していきます。



# 名前解決

ROSA CLI で確認できる Console 用 URL を、まず名前解決してみるところからやってみます。

```
https://console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com
```



2つの Public IP が返ってきます。

- 54.178.182.119
- 18.176.227.196

```
> dig console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com A

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52315
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com. IN A

;; ANSWER SECTION:
console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com. 60 IN A 54.178.182.119
console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com. 60 IN A 18.176.227.196

;; Query time: 6 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Wed Dec 29 16:47:43 JST 2021
;; MSG SIZE  rcvd: 127

```



2つの IP アドレスだけでは何もわからないですが、ここで Route 53 が怪しいのではないかと思い、Route 53 を見に行きます。



# Route53

Public Hosted Zone が、ROSA によって自動生成されています。

![image-20211229164926006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e4c08dc3-dec2-33aa-abef-53ee76db80e1.png)



この Hosted Zone の中に、Console の URL に該当する Aレコードがあります。この A レコードは、CLB を指しています。

```
a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com
```

![image-20211229165038831.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/0605c6ca-ecc8-c385-632f-fb38a0b1bc54.png)



# ELB(CLB)

A レコードが指している CLB はこれです。

![image-20211229164641327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/7a6a4737-511a-cb81-9725-507374257f8a.png)



念のため、CLB の DNS name を名前解決すると、Console URL の Public IP と一致しています。

- 54.178.182.119
- 18.176.227.196

```
> dig a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com A

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64943
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com. IN A

;; ANSWER SECTION:
a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com. 30 IN A 54.178.182.119
a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com. 30 IN A 18.176.227.196

;; Query time: 0 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Wed Dec 29 16:39:46 JST 2021
;; MSG SIZE  rcvd: 137

```



この CLB に紐づくインスタンスを確認します。

- ROSA Cluster に存在する 9 台の Node が登録されている
- Infra Node の 2 台のみ InService となっている。それ以外の 7 台は OutOfService で使われていない。

![image-20211229165221881.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/ce813a7e-7a63-a49e-3ee3-c35ab4ffcb41.png)



Health Check はこんなかんじです。31097 Port が応答可能な Node に通信するようになっています。

![image-20211229165315912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9a7fd412-cf0d-5fa7-eeb2-d48f01393a28.png)





Listener はこんな感じです。

![image-20211229165417446.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/6b8014ef-8771-ea36-dbca-f2de7fc68f9d.png)



# OpenShift Router(HAProxy)

CLB の Listener は `openshift-ingress` ネームスペースの、`router-default` Service に紐づいています。

- `80:30821/TCP,443:30185/TCP` の部分で紐づいてることがわかる

```
$ kubectl get svc router-default
NAME             TYPE           CLUSTER-IP     EXTERNAL-IP                                                                    PORT(S)                      AGE
router-default   LoadBalancer   172.30.237.2   a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com   80:30821/TCP,443:30185/TCP   3h55m
```



このネームスペースでは、2個の Router Pod が動いています。動いているノードは Infrastructure Node の2台で稼働しています。

```
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP            NODE                                              NOMINATED NODE   READINESS GATES
router-default-56cb99fdf4-882nk   1/1     Running   0          4h47m   10.130.2.18   ip-10-0-129-250.ap-northeast-1.compute.internal   <none>           <none>
router-default-56cb99fdf4-cg6d6   1/1     Running   0          148m    10.131.2.52   ip-10-0-203-78.ap-northeast-1.compute.internal    <none>           <none>
```



Infrastructure Node 3台のうち2台で稼働していることがわかります。

```
$ kubectl get nodes -o wide | grep infra
ip-10-0-129-250.ap-northeast-1.compute.internal   Ready    infra,worker   149m   v1.22.3+ffbb954   10.0.129.250   <none>        Red Hat Enterprise Linux CoreOS 49.84.202112032104-0 (Ootpa)   4.18.0-305.28.1.el8_4.x86_64   cri-o://1.22.1-8.rhaos4.9.gite059965.el8
ip-10-0-160-228.ap-northeast-1.compute.internal   Ready    infra,worker   149m   v1.22.3+ffbb954   10.0.160.228   <none>        Red Hat Enterprise Linux CoreOS 49.84.202112032104-0 (Ootpa)   4.18.0-305.28.1.el8_4.x86_64   cri-o://1.22.1-8.rhaos4.9.gite059965.el8
ip-10-0-203-78.ap-northeast-1.compute.internal    Ready    infra,worker   149m   v1.22.3+ffbb954   10.0.203.78    <none>        Red Hat Enterprise Linux CoreOS 49.84.202112032104-0 (Ootpa)   4.18.0-305.28.1.el8_4.x86_64   cri-o://1.22.1-8.rhaos4.9.gite059965.el8
```



この Service の YAML を見てみます。

- 名前 `router-default` 
- Service Type : `LoadBalancer` 
- `healthCheckNodePort: 31097` と指定されている
- `externalTrafficPolicy: Local` となっていて、リクエストを受け取った Node は、受け取った Node で稼働している Pod にだけバランシングする。他の Node にバランシングはしない。

```yaml
$ kubectl get svc router-default -o yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "1800"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "5"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "4"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "2"
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
    traffic-policy.network.alpha.openshift.io/local-with-fallback: ""
  creationTimestamp: "2021-12-29T06:01:01Z"
  finalizers:
  - service.kubernetes.io/load-balancer-cleanup
  labels:
    app: router
    ingresscontroller.operator.openshift.io/owning-ingresscontroller: default
    router: router-default
  name: router-default
  namespace: openshift-ingress
  ownerReferences:
  - apiVersion: apps/v1
    controller: true
    kind: Deployment
    name: router-default
    uid: b16d86e4-963d-4d75-98d3-fd5ffee9f979
  resourceVersion: "33416"
  uid: 3ab86a9f-6f0f-4a0f-a340-f03432a66da3
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 172.30.237.2
  clusterIPs:
  - 172.30.237.2
  externalTrafficPolicy: Local
  healthCheckNodePort: 31097
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: http
    nodePort: 30821
    port: 80
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 30185
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - hostname: a3ab86a9f6f0f4a0fa340f03432a66da-1903487804.ap-northeast-1.elb.amazonaws.com
```



Deployment の YAML も確認してみます。長いので、適当に読み飛ばしてください。

```yaml
$ kubectl get deploy router-default -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "5"
  creationTimestamp: "2021-12-29T06:01:01Z"
  generation: 5
  labels:
    ingresscontroller.operator.openshift.io/owning-ingresscontroller: default
  name: router-default
  namespace: openshift-ingress
  resourceVersion: "57295"
  uid: b16d86e4-963d-4d75-98d3-fd5ffee9f979
spec:
  minReadySeconds: 30
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 50%
    type: RollingUpdate
  template:
    metadata:
      annotations:
        target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}'
        unsupported.do-not-use.openshift.io/override-liveness-grace-period-seconds: "10"
      creationTimestamp: null
      labels:
        ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
        ingresscontroller.operator.openshift.io/hash: 94bb8b965
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: ingresscontroller.operator.openshift.io/deployment-ingresscontroller
                  operator: In
                  values:
                  - default
                - key: ingresscontroller.operator.openshift.io/hash
                  operator: NotIn
                  values:
                  - 94bb8b965
              topologyKey: kubernetes.io/hostname
            weight: 100
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: ingresscontroller.operator.openshift.io/deployment-ingresscontroller
                operator: In
                values:
                - default
              - key: ingresscontroller.operator.openshift.io/hash
                operator: In
                values:
                - 94bb8b965
            topologyKey: kubernetes.io/hostname
      containers:
      - env:
        - name: DEFAULT_CERTIFICATE_DIR
          value: /etc/pki/tls/private
        - name: DEFAULT_DESTINATION_CA_PATH
          value: /var/run/configmaps/service-ca/service-ca.crt
        - name: RELOAD_INTERVAL
          value: 5s
        - name: ROUTER_ALLOW_WILDCARD_ROUTES
          value: "false"
        - name: ROUTER_CANONICAL_HOSTNAME
          value: router-default.apps.my-rosa02.pkyx.p1.openshiftapps.com
        - name: ROUTER_CIPHERS
          value: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        - name: ROUTER_CIPHERSUITES
          value: TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        - name: ROUTER_DISABLE_HTTP2
          value: "false"
        - name: ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK
          value: "false"
        - name: ROUTER_LOAD_BALANCE_ALGORITHM
          value: leastconn
        - name: ROUTER_METRICS_TLS_CERT_FILE
          value: /etc/pki/tls/metrics-certs/tls.crt
        - name: ROUTER_METRICS_TLS_KEY_FILE
          value: /etc/pki/tls/metrics-certs/tls.key
        - name: ROUTER_METRICS_TYPE
          value: haproxy
        - name: ROUTER_SERVICE_NAME
          value: default
        - name: ROUTER_SERVICE_NAMESPACE
          value: openshift-ingress
        - name: ROUTER_SET_FORWARDED_HEADERS
          value: append
        - name: ROUTER_TCP_BALANCE_SCHEME
          value: source
        - name: ROUTER_THREADS
          value: "4"
        - name: ROUTER_USE_PROXY_PROTOCOL
          value: "true"
        - name: ROUTE_LABELS
        - name: SSL_MIN_VERSION
          value: TLSv1.2
        - name: STATS_PASSWORD_FILE
          value: /var/lib/haproxy/conf/metrics-auth/statsPassword
        - name: STATS_PORT
          value: "1936"
        - name: STATS_USERNAME_FILE
          value: /var/lib/haproxy/conf/metrics-auth/statsUsername
        image: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:73d1c5f9417f9a851404baed48d4dd3051ff23e6568033fec1fa6b9c7af3d889
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 1936
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: router
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        - containerPort: 443
          name: https
          protocol: TCP
        - containerPort: 1936
          name: metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz/ready
            port: 1936
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
        startupProbe:
          failureThreshold: 120
          httpGet:
            path: /healthz/ready
            port: 1936
            scheme: HTTP
          periodSeconds: 1
          successThreshold: 1
          timeoutSeconds: 1
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: FallbackToLogsOnError
        volumeMounts:
        - mountPath: /etc/pki/tls/private
          name: default-certificate
          readOnly: true
        - mountPath: /var/run/configmaps/service-ca
          name: service-ca-bundle
          readOnly: true
        - mountPath: /var/lib/haproxy/conf/metrics-auth
          name: stats-auth
          readOnly: true
        - mountPath: /etc/pki/tls/metrics-certs
          name: metrics-certs
          readOnly: true
      dnsPolicy: ClusterFirst
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      priorityClassName: system-cluster-critical
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: router
      serviceAccountName: router
      terminationGracePeriodSeconds: 3600
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        operator: Exists
      topologySpreadConstraints:
      - labelSelector:
          matchExpressions:
          - key: ingresscontroller.operator.openshift.io/hash
            operator: In
            values:
            - 94bb8b965
        maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: ScheduleAnyway
      volumes:
      - name: default-certificate
        secret:
          defaultMode: 420
          secretName: my-rosa02-primary-cert-bundle-secret
      - configMap:
          defaultMode: 420
          items:
          - key: service-ca.crt
            path: service-ca.crt
          name: service-ca-bundle
          optional: false
        name: service-ca-bundle
      - name: stats-auth
        secret:
          defaultMode: 420
          secretName: router-stats-default
      - name: metrics-certs
        secret:
          defaultMode: 420
          secretName: router-metrics-certs-default
status:
  availableReplicas: 2
  conditions:
  - lastTransitionTime: "2021-12-29T06:20:26Z"
    lastUpdateTime: "2021-12-29T06:20:26Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: "2021-12-29T06:01:14Z"
    lastUpdateTime: "2021-12-29T06:36:24Z"
    message: ReplicaSet "router-default-56cb99fdf4" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 5
  readyReplicas: 2
  replicas: 2
  updatedReplicas: 2
```



上記の Deployment に含まれている Container Image 名は次のものが利用されています。

```
quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:73d1c5f9417f9a851404baed48d4dd3051ff23e6568033fec1fa6b9c7af3d889
```



なんだこれと思ったら、OpenShift 側で公開されている HAProxy 用のコンテナイメージとなっているようです。

https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/release.txt

![image-20211229173207191.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3df24744-9e59-e8e7-6b1b-2f4aaf5957b4.png)



# healthCheckNodePort について

Router の Service `router-default` には、`healthCheckNodePort: 31097` が指定されています。これは、この Service に関連している Pod が Node で稼働している場合、その Node でヘルスチェック用の Port が解放され、ヘルスチェック用のレスポンスを返してくれるようになります。

文章で書いても意味がよくわからないと思うので、実際の動作を確認します。現状の構成は次の図のようになっています。

- Infrastructure Node が 3 台稼働している
- Router 用の Pod が、3台のうち 2台で稼働している
- 下記アーキテクチャ図に IP アドレスを明記しているので、今後の手順は IP アドレスに着目するとわかりやすい

![image-20211229204645734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/60824d59-ae86-864d-4c5a-5f2d557088ab.png)





適当なインスタンスを ROSA Cluster が稼働している VPC に立てて、curl で動作確認をします。Router Pod が稼働している .228 の Node に対して curl を実行します。

![image-20211229205038531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/829742b9-15fc-ea3f-eb2b-35be9e233802.png)



curl の実行結果です。レスポンスコードが 200 になっているので、CLB から .228 の Node に対して、ヘルスチェックが正しく通ることがわかります。

- レスポンスコードが 200 
- localEndpoints が 1 

```
$ curl -v http://10.0.160.228:31097/healthz
*   Trying 10.0.160.228:31097...
* Connected to 10.0.160.228 (10.0.160.228) port 31097 (#0)
> GET /healthz HTTP/1.1
> Host: 10.0.160.228:31097
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json
< X-Content-Type-Options: nosniff
< Date: Wed, 29 Dec 2021 11:49:50 GMT
< Content-Length: 105
<
{
        "service": {
                "namespace": "openshift-ingress",
                "name": "router-default"
        },
        "localEndpoints": 1
* Connection #0 to host 10.0.160.228 left intact
}[
```



次に、Router Pod が稼働して**<u>いない</u>** .73 の Node に対して curl を実行します。

![image-20211229205506874.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/34a4a5fc-c42b-2573-4036-091b1877ee6f.png)



curl の実行結果です。レスポンスコードが 503 になっているので、CLB から .78 の Node に対して、ヘルスチェックが通らないことがわかります。

- レスポンスコードが 503
- localEndpoints が 0

```
$ curl -v http://10.0.203.78:31097/healthz
*   Trying 10.0.203.78:31097...
* Connected to 10.0.203.78 (10.0.203.78) port 31097 (#0)
> GET /healthz HTTP/1.1
> Host: 10.0.203.78:31097
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 503 Service Unavailable
< Content-Type: application/json
< X-Content-Type-Options: nosniff
< Date: Wed, 29 Dec 2021 11:54:10 GMT
< Content-Length: 105
<
{
        "service": {
                "namespace": "openshift-ingress",
                "name": "router-default"
        },
        "localEndpoints": 0
* Connection #0 to host 10.0.203.78 left intact
}
```



次に、.228 で稼働している Pod を手動で削除してみて、curl の動作が変化するか確認します。まず、削除すべき Pod の名前を確認します。

```
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP            NODE                                              NOMINATED NODE   READINESS GATES
router-default-56cb99fdf4-6stbs   1/1     Running   0          15m     10.128.4.46   ip-10-0-160-228.ap-northeast-1.compute.internal   <none>           <none>
router-default-56cb99fdf4-882nk   1/1     Running   0          5h21m   10.130.2.18   ip-10-0-129-250.ap-northeast-1.compute.internal   <none>           <none>
```



Pod を削除します。

```
kubectl delete pods router-default-56cb99fdf4-6stbs
```



.228 の Node 上の Pod が削除され、.78 の Node で新たに自動復元されている状況わかります。

```
$ kubectl get pods -o wide
NAME                              READY   STATUS        RESTARTS   AGE     IP            NODE                                              NOMINATED NODE   READINESS GATES
router-default-56cb99fdf4-6stbs   1/1     Terminating   0          16m     10.128.4.46   ip-10-0-160-228.ap-northeast-1.compute.internal   <none>           <none>
router-default-56cb99fdf4-7rbgd   1/1     Running       0          7s      10.131.2.58   ip-10-0-203-78.ap-northeast-1.compute.internal    <none>           <none>
router-default-56cb99fdf4-882nk   1/1     Running       0          5h22m   10.130.2.18   ip-10-0-129-250.ap-northeast-1.compute.internal   <none>           <none>
```



現状の構成です。

![image-20211229210432899.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/dd1b33d4-6d59-cd5a-2fd7-469c8a117caa.png)



.228 の Node のヘルスチェック用の Port が、 503 が返ってくるようになりました。

```
$ curl -v http://10.0.160.228:31097/healthz
*   Trying 10.0.160.228:31097...
* Connected to 10.0.160.228 (10.0.160.228) port 31097 (#0)
> GET /healthz HTTP/1.1
> Host: 10.0.160.228:31097
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 503 Service Unavailable
< Content-Type: application/json
< X-Content-Type-Options: nosniff
< Date: Wed, 29 Dec 2021 11:59:09 GMT
< Content-Length: 105
<
{
        "service": {
                "namespace": "openshift-ingress",
                "name": "router-default"
        },
        "localEndpoints": 0
* Connection #0 to host 10.0.160.228 left intact
}
```



一方、.78 の Node では、元々 503 だったが、200 を返すようになりました。

```
$ curl -v http://10.0.203.78:31097/healthz
*   Trying 10.0.203.78:31097...
* Connected to 10.0.203.78 (10.0.203.78) port 31097 (#0)
> GET /healthz HTTP/1.1
> Host: 10.0.203.78:31097
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json
< X-Content-Type-Options: nosniff
< Date: Wed, 29 Dec 2021 11:59:38 GMT
< Content-Length: 105
<
{
        "service": {
                "namespace": "openshift-ingress",
                "name": "router-default"
        },
        "localEndpoints": 1
* Connection #0 to host 10.0.203.78 left intact
}
```



こういったように、Service 配下の Pod が動いている Node でのみヘルスチェック用のポートを動的に準備してくれるのが healthCheckNodePort です。これにより、CLB のヘルスチェックが動的に対応され、Router Pod が稼働している Node へ適切にバランシングされることがわかります。



# OpenShift Route

以下のコマンドで、OpenShift の Router で稼働する Route を確認できます。OpenShift の Console 用の ルートは、`openshift-console` のネームスペースで定義されています。

```
$ oc get route -n openshift-console
NAME        HOST/PORT                                                              PATH   SERVICES    PORT    TERMINATION          WILDCARD
console     console-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com            console     https   reencrypt/Redirect   None
downloads   downloads-openshift-console.apps.my-rosa02.pkyx.p1.openshiftapps.com          downloads   http    edge/Redirect        None
```



コンソールで見ると、このルートです。

![image-20211229180409640.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/0a2cee5f-05e9-9399-9f19-58b25a9a8d68.png)



上記の定義により、Router Pod は受け取ったリクエストを、Console を提供する Pod へルーティングをしてくれます。



# Consoleを提供する Pod

Console を提供する Pod は、`openshift-console` のネームスペースで稼働しています。

Service の一覧です。`console` サービスが、Console を提供してくれています。

```
$ kubectl get svc -o wide
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE    SELECTOR
console     ClusterIP   172.30.156.193   <none>        443/TCP   3h2m   app=console,component=ui
downloads   ClusterIP   172.30.56.147    <none>        80/TCP    3h2m   app=console,component=downloads
```



deployment

```
$ kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
console     2/2     2            2           3h1m
downloads   2/2     2            2           3h2m
```



pods の一覧です。

```
$ kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE    IP            NODE                                              NOMINATED NODE   READINESS GATES
console-57d97474b7-84plz     1/1     Running   0          132m   10.130.0.42   ip-10-0-168-81.ap-northeast-1.compute.internal    <none>           <none>
console-57d97474b7-pthpv     1/1     Running   0          132m   10.129.0.45   ip-10-0-202-170.ap-northeast-1.compute.internal   <none>           <none>
downloads-5cfbb4b4b8-kr2bl   1/1     Running   0          160m   10.129.0.32   ip-10-0-202-170.ap-northeast-1.compute.internal   <none>           <none>
downloads-5cfbb4b4b8-rhrtq   1/1     Running   0          162m   10.128.2.8    ip-10-0-164-3.ap-northeast-1.compute.internal     <none>           <none>
```



node の一覧です。

- Console 用のコンテナは、Master Node で稼働していることがわかった

```
$ kubectl get nodes
NAME                                              STATUS   ROLES          AGE     VERSION
ip-10-0-129-250.ap-northeast-1.compute.internal   Ready    infra,worker   167m    v1.22.3+ffbb954
ip-10-0-150-162.ap-northeast-1.compute.internal   Ready    worker         3h3m    v1.22.3+ffbb954
ip-10-0-157-183.ap-northeast-1.compute.internal   Ready    master         3h12m   v1.22.3+ffbb954
ip-10-0-160-228.ap-northeast-1.compute.internal   Ready    infra,worker   167m    v1.22.3+ffbb954
ip-10-0-164-3.ap-northeast-1.compute.internal     Ready    worker         3h3m    v1.22.3+ffbb954
ip-10-0-168-81.ap-northeast-1.compute.internal    Ready    master         3h12m   v1.22.3+ffbb954
ip-10-0-201-136.ap-northeast-1.compute.internal   Ready    worker         3h3m    v1.22.3+ffbb954
ip-10-0-202-170.ap-northeast-1.compute.internal   Ready    master         3h12m   v1.22.3+ffbb954
ip-10-0-203-78.ap-northeast-1.compute.internal    Ready    infra,worker   167m    v1.22.3+ffbb954
```



# まとめ

ROSA で提供されている Console へのアクセス経路や、提供元 Pod を確認することが出来ました。通常利用する分には、このあたりは意識する必要はないですが、このあたりを理解していると、もしかすると運用の中で役に立つ日が来るかもしれません。