はじめに
OKEでIngressを使用する際の設定方法を確認したいと思います。マニュアルに記載はあるのですがこの通りではできなかったので、参考にしながら確認しました。
Kubernetesクラスタは構築済みです。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.10.152 Ready node 5d17h v1.21.5
10.0.10.187 Ready node 5d17h v1.21.5
10.0.10.253 Ready node 5d17h v1.21.5
Ingress コントローラーの設定
ClusterRoleBindingsの設定
利用するOCIユーザがテナンシー管理者ではない場合、cluster-admin の clusterrole をユーザに与えます。
OCIDの確認
ユーザのOCIDを確認します。
OCIコンソールの「ユーザの詳細」からOCIDをコピーします。
ClusterRoleBindingsの作成
ここでは、ClusterRoleBindingsの名前を「ingress-adm」として設定します。
$ kubectl create clusterrolebinding ingress-adm --clusterrole=cluster-admin --user=ocid1.user.oc1..aaaaaaaa・・・pgasfa
clusterrolebinding.rbac.authorization.k8s.io/ingress-adm created
$ kubectl describe clusterrolebindings ingress-adm
Name: ingress-adm
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: cluster-admin
Subjects:
Kind Name Namespace
---- ---- ---------
User ocid1.user.oc1..aaaaaaaa4・・・asfa
Ingressコントローラーのデプロイ
GitHubリポジトリに公開されているマニフェストを使用してデプロイします。最新はこちらにあります。
ただ、このままではデプロイされるLoadBalancer のヘルスチェックがエラーになったので、直接 kubectl で apply しないで、ダウンロード後一部編集してから apply します。
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml
--2022-01-05 07:06:33-- https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19299 (19K) [text/plain]
Saving to: ‘deploy.yaml’
100%[===============================================================================================================================================================================================>] 19,299 --.-K/s in 0s
2022-01-05 07:06:33 (74.0 MB/s) - ‘deploy.yaml’ saved [19299/19299]
$ vim deploy.yaml
編集したマニフェストを以下に抜粋します。
・・・
---
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
### フレキシブル・シェイプを使用するために追記(任意) ###
service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "50"
### ここまで ###
labels:
helm.sh/chart: ingress-nginx-4.0.10
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.1.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
### コメントアウト ###
# externalTrafficPolicy: Local
### ここまで ###
ipFamilyPolicy: SingleStack
ipFamilies:
- IPv4
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
appProtocol: http
- name: https
port: 443
protocol: TCP
targetPort: https
appProtocol: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
---
・・・
フレキシブル・シェイプを使用するために追記した3行は任意です。
「externalTrafficPolicy: Local」はコメントアウト(もしくは削除)しました。
IngressコントローラーのGitHubリポジトリには以下の記載があります。
これをLocalに設定することでホップを節約できるのですが、OCIのロードバランサーは対応してないのかな?Localのままでデプロイすると、ロードバランサーのヘルスチェックがエラーになりました。
If the load balancers of your cloud provider do active healthchecks on their backends (most do), you can change the externalTrafficPolicy of the ingress controller Service to Local (instead of the default Cluster) to save an extra hop in some cases. If you're installing with Helm, this can be done by adding --set controller.service.externalTrafficPolicy=Local to the helm install or helm upgrade command.
編集したマニフェストを apply します。
$ kubectl apply -f deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
確認します。
$ kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-j2sdk 0/1 Completed 0 7m12s
pod/ingress-nginx-admission-patch-sbp8d 0/1 Completed 0 7m12s
pod/ingress-nginx-controller-54bfb9bb-7w8wm 1/1 Running 0 7m12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.96.202.169 129.159.68.246 80:32178/TCP,443:32206/TCP 7m12s
service/ingress-nginx-controller-admission ClusterIP 10.96.205.154 <none> 443/TCP 7m12s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 7m12s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-54bfb9bb 1 1 1 7m12s
NAME COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create 1/1 1s 7m12s
job.batch/ingress-nginx-admission-patch 1/1 2s 7m12s
OCIのコンソールでもロードバランサーがデプロイされていることが確認できます。
バックエンドの設定
Ingressの動作を確認するために、サンプルのDeploymentとServiceをデプロイします。
Deployment(Pod)のデプロイ
L7でのバランシングを確認するために、3つのDeploymentをデプロイします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx0
spec:
replicas: 2
selector:
matchLabels:
app: nginx-dep0
template:
metadata:
labels:
app: nginx-dep0
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx1
spec:
replicas: 2
selector:
matchLabels:
app: nginx-dep1
template:
metadata:
labels:
app: nginx-dep1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx2
spec:
replicas: 2
selector:
matchLabels:
app: nginx-dep2
template:
metadata:
labels:
app: nginx-dep2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
$ kubectl apply -f deployment.yaml
deployment.apps/nginx0 created
deployment.apps/nginx1 created
deployment.apps/nginx2 created
$ kubectl get pod -o wide -L app
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES APP
nginx0-7f59f499f8-gwjzt 1/1 Running 0 8m6s 10.244.0.168 10.0.10.187 <none> <none> nginx-dep0
nginx0-7f59f499f8-xq6zh 1/1 Running 0 8m6s 10.244.0.32 10.0.10.253 <none> <none> nginx-dep0
nginx1-76fccb476f-hn7lg 1/1 Running 0 8m6s 10.244.0.169 10.0.10.187 <none> <none> nginx-dep1
nginx1-76fccb476f-tj4s6 1/1 Running 0 8m6s 10.244.1.20 10.0.10.152 <none> <none> nginx-dep1
nginx2-f7cf4975b-988s5 1/1 Running 0 8m6s 10.244.0.170 10.0.10.187 <none> <none> nginx-dep2
nginx2-f7cf4975b-rzsnj 1/1 Running 0 8m6s 10.244.0.33 10.0.10.253 <none> <none> nginx-dep2
ClusterIPのデプロイ
IngressのバックエンドとなるClusterIPをデプロイします。各Deploymentごとに3つのClusterIPを作成します。
apiVersion: v1
kind: Service
metadata:
name: clusterip0
spec:
type: ClusterIP
ports:
- name: clusterip
protocol: TCP
port: 8080
targetPort: 80
selector:
app: nginx-dep0
---
apiVersion: v1
kind: Service
metadata:
name: clusterip1
spec:
type: ClusterIP
ports:
- name: clusterip
protocol: TCP
port: 8080
targetPort: 80
selector:
app: nginx-dep1
---
apiVersion: v1
kind: Service
metadata:
name: clusterip2
spec:
type: ClusterIP
ports:
- name: clusterip
protocol: TCP
port: 8080
targetPort: 80
selector:
app: nginx-dep2
$ kubectl apply -f ClusterIP.yaml
service/clusterip0 created
service/clusterip1 created
service/clusterip2 created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
clusterip0 ClusterIP 10.96.48.239 <none> 8080/TCP 12s
clusterip1 ClusterIP 10.96.118.101 <none> 8080/TCP 12s
clusterip2 ClusterIP 10.96.111.0 <none> 8080/TCP 12s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d18h
各ClusterIPの「Endpoints」に、selectorに合ったPodのIPアドレスが表示されているか確認します。
$ kubectl describe svc clusterip0
Name: clusterip0
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx-dep0
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.48.239
IPs: 10.96.48.239
Port: clusterip 8080/TCP
TargetPort: 80/TCP
Endpoints: 10.244.0.168:80,10.244.0.32:80
Session Affinity: None
Events: <none>
$ kubectl describe svc clusterip1
・・・省略・・・
$ kubectl describe svc clusterip2
・・・省略・・・
Ingressの設定
TLS Secret の作成
IngressでHTTPSを利用する場合には、事前に証明書をSecretとして作成します。
今回は自己証明書を使用します。
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a 2048 bit RSA private key
*********************************************************************************************************+++++
************************************************************************+++++
writing new private key to 'tls.key'
-----
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
Ingressのデプロイ
今回は「/path1」を指定した場合は「clusterip1」に、「/path2」を指定した場合は「clusterip2」にルーティングして、それ以外の場合は「clusterip0」にルーティングするようにします。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- path: /path1
pathType: Prefix
backend:
service:
name: clusterip1
port:
number: 8080
- path: /path2
pathType: Prefix
backend:
service:
name: clusterip2
port:
number: 8080
defaultBackend:
service:
name: clusterip0
port:
number: 8080
tls:
- secretName: tls-secret
$ kubectl apply -f sampleIngress-ga.yaml
ingress.networking.k8s.io/sample-ingress created
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
sample-ingress <none> * 80, 443 8s
デプロイした直後は「ADDRESS」が空白になっていますが、数分待つとLoadBalancerのIPアドレスが表示されます。
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
sample-ingress <none> * 129.159.68.246 80, 443 42s
詳細も確認しておきます。
$ kubectl describe ingress sample-ingress
Name: sample-ingress
Namespace: default
Address: 129.159.68.246
Default backend: clusterip0:8080 (10.244.0.168:80,10.244.0.32:80)
TLS:
tls-secret terminates
Rules:
Host Path Backends
---- ---- --------
*
/path1 clusterip1:8080 (10.244.0.169:80,10.244.1.20:80)
/path2 clusterip2:8080 (10.244.0.170:80,10.244.0.33:80)
Annotations: kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 10m (x2 over 10m) nginx-ingress-controller Scheduled for sync
動作確認
index.htmlファイルの準備
Ingress経由でリクエストを送ってレスポンスを確認します。ただ、このままだとどのPodにバランシングしているかわからないので、各Podのindex.htmlファイルにホスト名を記載しておきます。
また、nginx1とnginx2はそれぞれ「path1」「path2」配下にindex.htmlファイルを用意します。
$ kubectl exec -it nginx0-7f59f499f8-gwjzt -- /bin/bash
root@nginx0-7f59f499f8-gwjzt:/# echo `hostname` > /usr/share/nginx/html/index.html
root@nginx0-7f59f499f8-gwjzt:/# exit
exit
$ kubectl exec -it nginx1-76fccb476f-tj4s6 -- /bin/bash
root@nginx1-76fccb476f-tj4s6:/# mkdir /usr/share/nginx/html/path1
root@nginx1-76fccb476f-tj4s6:/# echo `hostname` > /usr/share/nginx/html/path1/index.html
root@nginx1-76fccb476f-tj4s6:/# exit
exit
・・・そのほかは省略・・・
動作確認
Ingress経由でHTTPリクエストをそれぞれ5回送って、動作を確認します。
$ for i in 1 2 3 4 5; do curl http://129.159.68.246/ ; done
nginx0-7f59f499f8-xq6zh
nginx0-7f59f499f8-gwjzt
nginx0-7f59f499f8-gwjzt
nginx0-7f59f499f8-xq6zh
nginx0-7f59f499f8-xq6zh
$ for i in 1 2 3 4 5; do curl http://129.159.68.246/path1/ ; done
nginx1-76fccb476f-tj4s6
nginx1-76fccb476f-hn7lg
nginx1-76fccb476f-tj4s6
nginx1-76fccb476f-hn7lg
nginx1-76fccb476f-tj4s6
$ for i in 1 2 3 4 5; do curl http://129.159.68.246/path2/ ; done
nginx2-f7cf4975b-988s5
nginx2-f7cf4975b-rzsnj
nginx2-f7cf4975b-rzsnj
nginx2-f7cf4975b-988s5
nginx2-f7cf4975b-988s5
HTTPSでも確認します。
$ for i in 1 2 3 4 5; do curl -k https://129.159.68.246/ ; done
nginx0-7f59f499f8-gwjzt
nginx0-7f59f499f8-xq6zh
nginx0-7f59f499f8-xq6zh
nginx0-7f59f499f8-gwjzt
nginx0-7f59f499f8-xq6zh
$ for i in 1 2 3 4 5; do curl -k https://129.159.68.246/path1/ ; done
nginx1-76fccb476f-hn7lg
nginx1-76fccb476f-tj4s6
nginx1-76fccb476f-hn7lg
nginx1-76fccb476f-tj4s6
nginx1-76fccb476f-tj4s6
$ for i in 1 2 3 4 5; do curl -k https://129.159.68.246/path2/ ; done
nginx2-f7cf4975b-rzsnj
nginx2-f7cf4975b-rzsnj
nginx2-f7cf4975b-988s5
nginx2-f7cf4975b-rzsnj
nginx2-f7cf4975b-988s5
それぞれ期待通りの動作であることが確認できます。