kubestronautへの道 ~CKS編 その18 killer coda「Ingress」~

tech article

今日覚えて帰ること

Ingress

ロードバランサー的なKubernetesリソース。
クラスター外部からのリクエストをクラスター内部のsvcへつなげてくれる。
Ingressコントローラーが実際のロードバランサーを生成するリソース。AWSでいうとこのリソースがELBを生成してくれる。
Ingressリソースと呼ばれているのがルーティングを担うリソース。
AWSで言うとターゲットグループ的な役割を担っている。

Ingress Create

Create Services for existing Deployments

There are two existing Deployments in Namespace world which should be made accessible via an Ingress.

First: create ClusterIP Services for both Deployments for port 80 . The Services should have the same name as the Deployments.

svcを作れ、と言っています。

CKS 受験層は svcの作成はできると思うのであまり詳細には解説しません。
-h でオプションを確認すれば暗記していなくてもコマンドラインから作成可能です。

controlplane $ k create svc -n world clusterip asia --tcp=80
service/asia created
controlplane $ k create svc -n world clusterip europe --tcp=80
service/europe created

Create Ingress for existing Services

The Nginx Ingress Controller has been installed.

Create a new Ingress resource called world for domain name world.universe.mine . The domain points to the K8s Node IP via /etc/hosts .

The Ingress resource should have two routes pointing to the existing Services:

http://world.universe.mine:30080/europe/

and

http://world.universe.mine:30080/asia/

先ほど作成した svc にトラフィックを流すような ingressリソース を作成せよ、と言っています。

ingress も kubectl から作成できますが、設定項目が多く大変なのでマニフェストファイルを apply
する方式で作成します。

以下を参考にします。

Ingress
FEATURE STATE: Kubernetes v1.19 クラスター内のServiceに対する外部からのアクセス(主にHTTP)を管理するAPIオブジェクトです。 Ingressは負荷分散、SSL終端、名前ベースの仮想ホスティングの機能を提供します。 用語 簡単のために、このガイドでは次の用語を定義します。 ノー...
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080

以下のように修正します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: world
  namespace: world
spec:
  ingressClassName: nginx
  rules:
  - host: world.universe.mine
    http:
      paths:
      - path: /asia
        pathType: Prefix
        backend:
          service:
            name: asia
            port:
              number: 80
      - path: /europe
        pathType: Prefix
        backend:
          service:
            name: europe
            port:
              number: 80

赤字の箇所は引用元の値から変更した箇所です。
こちらは説明不要だと思います。

少しわかりづらいな、と思うところは spec.rules.http.paths.backend.port.number の値です。
こちらはリスナー(ingress のトラフィックを待ち受けるターゲット)が開いているポートを指定します。
今回でいうと、europe, asiaという名前のsvcが待ち受けているポートを指定します。

青字の箇所は新たに追記した箇所です。

metadata.namespace は対象の Ingressリソースが配置される namespace を指定しています。

spec.ingressClassName は Ingressリソース がどの Ingressコントローラー によって処理されるのかを指定しています。

今まで意識したことがなかったのですが、Ingressコントローラー で ingressclass.kubernetes.io/is-default-class というアノテーションが true で設定されていない場合はデフォルトのコントローラーが存在しない扱いになるっぽくて、 Ingressリソース内で指定してやる必要があります。
バージョンによって違うかもしれません。

IngressClass を調べてみます。

controlplane $ k get ingressclasses.networking.k8s.io -A
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       53m

controlplane $ k get ingressclasses.networking.k8s.io -o yaml
apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
  kind: IngressClass
  metadata:
    creationTimestamp: "2024-08-20T12:40:17Z"
    generation: 1
    labels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/managed-by: Helm
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/version: 1.1.1
      helm.sh/chart: ingress-nginx-4.0.15
    name: nginx
    resourceVersion: "3025"
    uid: 23edc738-30dc-40e7-8c15-e2468995dd1b
  spec:
    controller: k8s.io/ingress-nginx
kind: List
metadata:
  resourceVersion: ""

アノテーションが設定されていないので、Ingressリソース内で指定する必要があります。
今まで他の問題集や killer shell で解いた問題では IngressClass を指定することはなかったので気にしたことはありませんでしたが、Ingressリソース を作成する際は常に記載しておくとよいかもしれません。

Ingress Secure

Secure an Ingress with a TLS certificate

Make sure to have solved the previous Scenario Ingress Create.

The Nginx Ingress Controller has been installed and an Ingress resource configured in Namespace world .

You can reach the application using

curl http://world.universe.mine:30080/europe

Generate a new TLS certificate using:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout cert.key -out cert.crt -subj "/CN=world.universe.mine/O=world.universe.mine"

Configure the Ingress to use the new certificate, so that you can call

curl -kv https://world.universe.mine:30443/europe

The curl verbose output should show the new certificate being used instead of the default Ingress one.

前回からの続きとなる問題のようです。
証明書を作成し、その証明書を用いてIngressに対してhttpsで通信できるようにせよ、と言っています。

まず指示通りに証明書を作成します。

controlplane $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout cert.key -out cert.crt -subj "/CN=world.universe.mine/O=world.universe.mine"
Generating a RSA private key
...............................................................................................+++++
...+++++
writing new private key to 'cert.key'
-----
controlplane $ 

ネクストステップが分からないので公式サイトを頼りにします。

Ingress
FEATURE STATE: Kubernetes v1.19 クラスター内のServiceに対する外部からのアクセス(主にHTTP)を管理するAPIオブジェクトです。 Ingressは負荷分散、SSL終端、名前ベースの仮想ホスティングの機能を提供します。 用語 簡単のために、このガイドでは次の用語を定義します。 ノー...

どうやら、まず Secretリソース を作成して、それから Ingressリソース に修正を加えてやればよさそうです。

まずは Secretリソース を作成します。
k create secret から -h を駆使すれば簡単にできます
また、使用する証明書と秘密鍵のパスを指定する必要があるので事前に調べておきます。

controlplane $ ll
total 84
drwx------ 12 root root 4096 Aug 21 12:35 ./
drwxr-xr-x 20 root root 4096 Aug 21 12:31 ../
-rw-------  1 root root  342 Aug 21 12:23 .ICEauthority

///

drwxr-xr-x  2 root root 4096 Aug 21 12:23 .vnc/
-rw-r--r--  1 root root  165 Aug  2 07:24 .wget-hsts
-rw-r--r--  1 root root 1220 Aug 21 12:35 cert.crt
-rw-------  1 root root 1708 Aug 21 12:35 cert.key
lrwxrwxrwx  1 root root    1 Aug  2 07:17 filesystem -> //
drwx------  3 root root 4096 Aug  2 07:23 snap/

controlplane $ k create secret -n world tls testsecret-tls --cert=cert.crt --key=cert.key
secret/testsecret-tls created

Secretリソース が完成したら Ingressリソースを編集していきます。
公式サイトに書いてある通りやれば特に難しい操作は必要ありません。
赤字で書いてある箇所が追記した部分です。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
  creationTimestamp: "2024-08-21T12:31:02Z"
  generation: 1
  name: world
  namespace: world
  resourceVersion: "2581"
  uid: d6b40a8f-5342-46ba-bd94-29214e202c41
spec:
  tls:
  - hosts:
      - world.universe.mine
    secretName: testsecret-tls
  ingressClassName: nginx
  rules:
  - host: world.universe.mine
    http:
      paths:
      - backend:
          service:
            name: europe
            port:
              number: 80
        path: /europe
        pathType: Prefix
      - backend:
          service:
            name: asia
            port:
              number: 80
        path: /asia
        pathType: Prefix
status:
  loadBalancer:
    ingress:
    - ip: 172.30.1.2

これで完了です。

タイトルとURLをコピーしました