NICによるTCP/UDPの通信制御

この章では、実際にデプロイしたNGINX Ingress Controllerを使い、TCP/UDPのアプリケーションに対する通信制御方法を確認します 設定例は NGINX Inc GitHubの examples/custom-resources/ に管理されております

TCP / UDP の分散設定

TCP / UDP を分散するためアプリケーションをデプロイします

https://github.com/nginxinc/kubernetes-ingress/tree/v3.1.1/examples/custom-resources/basic-tcp-udp

Deployment、NodePortの内容を修正しデプロイ

TCP / UDP を分散するため、NGINX Ingress Controller のDeployment、NodePortの内容を修正しデプロイします。 Deploymentのargsで指定するパラメータの詳細は Command-line Arguments を参照してください

cd ~/kubernetes-ingress/deployments
cp deployment/nginx-plus-ingress.yaml deployment/nginx-plus-ingress-tcpudp.yaml
vi deployment/nginx-plus-ingress-tcpudp.yaml

コメントを付与した行を参考に適切な内容に修正してください

deployment/nginx-plus-ingress-tcpudp.yaml
 1** 省略 **
 2spec:
 3   serviceAccountName: nginx-ingress
 4   containers:
 5   - image: registry.example.com/root/nic/nginxplus-ingress-nap-dos:2.1.0
 6   imagePullPolicy: IfNotPresent
 7   name: nginx-plus-ingress
 8   ports:
 9   - name: dns-tcp         # DNS TCP を有効にします
10     containerPort: 5353
11   - name: dns-udp         # DNS UDP を有効にします
12     containerPort: 53
13     protocol: UDP
14   #- name: http
15   #  containerPort: 80
16   #- name: https
17   #  containerPort: 443
18** 省略 **
19    args:
20      - -nginx-plus
21      - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
22      - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
23     #- -enable-app-protect
24     #- -enable-app-protect-dos
25     #- -v=3 # Enables extensive logging. Useful for troubleshooting.
26     #- -report-ingress-status
27     #- -external-service=nginx-ingress
28     #- -enable-prometheus-metrics
29      - -global-configuration=$(POD_NAMESPACE)/nginx-configuration # Global Configuration を有効にします

単一のNodePortでTCP/UDP双方を設定できないため、2つのファイルに分けて設定します。

## cd ~/kubernetes-ingress/deployments
cp service/nodeport.yaml  service/nodeport-tcp.yaml
vi service/nodeport-tcp.yaml

以下の内容を参考に修正してください。

service/nodeport-tcp.yaml
 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: nginx-ingress
 5  namespace: nginx-ingress
 6spec:
 7  type: NodePort
 8  ports:
 9  - port: 5353        # DNS TCP を有効にします (ファイルからDNS UDPを削除します)
10    targetPort: 5353
11    protocol: TCP
12    name: dns-tcp
13  selector:
14    app: nginx-ingress
## cd ~/kubernetes-ingress/deployments
cp service/nodeport.yaml  service/nodeport-udp.yaml
vi service/nodeport-udp.yaml

以下の内容を参考に修正してください。

service/nodeport-udp.yaml
 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: nginx-ingress-udp
 5  namespace: nginx-ingress
 6spec:
 7  type: NodePort
 8  ports:
 9  - port: 53        # DNS UDP のポート番号を変更します (ファイルからDNS TCPを削除します)
10    targetPort: 53
11    protocol: UDP
12    name: dns-udp
13  selector:
14    app: nginx-ingress

TCP/UDPではGlobal Configurationにより外部から通信を待ち受ける設定を行います

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp/
cp global-configuration.yaml  global-configuration.yaml-bak
vi global-configuration.yaml

以下の内容を参考に修正してください。

global-configuration.yaml
 1apiVersion: k8s.nginx.org/v1alpha1
 2kind: GlobalConfiguration
 3metadata:
 4  name: nginx-configuration
 5  namespace: nginx-ingress
 6spec:
 7  listeners:
 8  - name: dns-udp
 9    port: 53       # DNS UDP のポート番号を 5353 -> 53 に変更
10    protocol: UDP
11  - name: dns-tcp
12    port: 5353
13    protocol: TCP

その他、NGINX Ingress ControlleでTCP/UDPを転送するための設定、サンプルアプリケーションを確認します。

TCPの設定です。Kindで TransportServer を指定します。

transport-server-tcp.yaml
 1apiVersion: k8s.nginx.org/v1alpha1
 2kind: TransportServer
 3metadata:
 4  name: dns-tcp
 5spec:
 6  listener:
 7    name: dns-tcp
 8    protocol: TCP
 9  upstreams:
10  - name: dns-app
11    service: coredns
12    port: 5353
13  action:
14    pass: dns-app

UDPの設定です。TCPとほぼ同様です

transport-server-udp.yaml
 1apiVersion: k8s.nginx.org/v1alpha1
 2kind: TransportServer
 3metadata:
 4  name: dns-udp
 5spec:
 6  listener:
 7    name: dns-udp
 8    protocol: UDP
 9  upstreams:
10  - name: dns-app
11    service: coredns
12    port: 5353
13  upstreamParameters:
14    udpRequests: 1
15    udpResponses: 1
16  action:
17    pass: dns-app

サンプルアプリケーションです。TCP/UDP共に5353で通信を待ち受けます。またDNSを 8.8.8.8:53 へと転送する動作となります。

修正した内容、各種リソースをデプロイします。 デプロイする内容に応じてディレクトリが変更となりますので注意ください

~/kubernetes-ingress/deployments 配下の内容を設定してください。(NICのDeployment, NodePort)

cd ~/kubernetes-ingress/deployments
kubectl apply -f service/nodeport-tcp.yaml
kubectl apply -f service/nodeport-udp.yaml
kubectl apply -f deployment/nginx-plus-ingress-tcpudp.yaml

~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp 配下の内容を設定してください。(サンプルアプリケーション、分散設定等)

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp
kubectl apply -f global-configuration.yaml
kubectl apply -f dns.yaml
kubectl apply -f transport-server-tcp.yaml
kubectl apply -f transport-server-udp.yaml

デプロイしたNodePortの内容を確認し、TCP/UDPの待ち受けているポートに対してリクエストを転送するようNGINXの設定を変更します。

kubectl get svc -n nginx-ingress
実行結果サンプル
1NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
2nginx-ingress            NodePort    10.108.250.160   <none>        5353:30292/TCP   6d14h
3nginx-ingress-udp        NodePort    10.99.147.245    <none>        53:31482/UDP     16m

確認したNode Portで割り当てられたポート番号宛に通信を転送するように、NGINXを設定します。 転送するポート番号は、環境に合わせて適切に変更してください。

cd ~/
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf-
cat << EOF > nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
   worker_connections  1024;
}


# TCP/UDP load balancing
#
stream {
   upstream tcp5353_backend {
      server node1:30292;    # DNS TCP(TCP/5353)に割り当てられたポート番号
   }
   upstream udp53_backend {
      server node1:31482;     # DNS UDP(UDP/53)に割り当てられたポート番号
   }

   server {
      listen 5353;            # DNS TCPを(TCP/5353)で待ち受けます
      proxy_pass tcp5353_backend;
   }
   server {
      listen 53 udp;          # DNS UDPを(UDP/53)で待ち受けます
      proxy_pass udp53_backend;
   }
}
EOF
sudo cp nginx.conf /etc/nginx/nginx.conf
sudo nginx -s reload

デプロイした結果の確認

kubectl get pod -n nginx-ingress | grep nginx-ingress
実行結果サンプル
1nginx-ingress-68949d7f46-qh9kp        1/1     Running   0             4s

NGINX Ingress ControllerのPodの詳細を確認します

## pod名は、kuebctl get pod -n nginx-ingress の出力結果を参照してください
kubectl describe pod nginx-ingress-68949d7f46-qh9kp -n nginx-ingress
実行結果サンプル
 1** 省略 **
 2
 3Containers:
 4  nginx-plus-ingress:
 5    Container ID:  docker://f1aa9d4434ebda4817f9ff957987120c85808bcdcb9d64978e76814c20e422fe
 6    Image:         registry.example.com/root/nic/nginxplus-ingress-nap-dos:2.1.0
 7    Image ID:      docker-pullable://registry.example.com/root/nic/nginxplus-ingress-nap-dos@sha256:8c9a8ce1cdda45c2a289cb20ce37a60e25b4d4669c2c9c9d4d0831c353c6c668
 8    Ports:         5353/TCP, 53/UDP, 8081/TCP, 9113/TCP
 9    Host Ports:    0/TCP, 0/UDP, 0/TCP, 0/TCP
10    Args:
11      -nginx-plus
12      -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
13      -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
14      -global-configuration=$(POD_NAMESPACE)/nginx-configuration
15    State:          Running
16
17** 省略 **

TCPは 5353/TCP 、UDP 53/UDP となっていることが確認できます。また global-configuration のargsが正しく記載されています

kubectl get globalconfiguration -n nginx-ingress
実行結果サンプル
1NAME                  AGE
2nginx-configuration   8m3s
kubectl get svc coredns
実行結果サンプル
1NAME      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
2coredns   ClusterIP   10.101.115.180   <none>        5353/UDP,5353/TCP   2m41s
kubectl get pod | grep coredns
実行結果サンプル
1coredns-75466b69b7-8b7r5   1/1     Running   0              3m29s
2coredns-75466b69b7-8tgrc   1/1     Running   0              3m29s

先程確認したとおり、TCP/UDPそれぞれのNodePortの内容が確認できます

kubectl get svc -n nginx-ingress
実行結果サンプル
1NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
2nginx-ingress            NodePort    10.108.250.160   <none>        5353:30292/TCP   6d14h
3nginx-ingress-udp        NodePort    10.99.147.245    <none>        53:31482/UDP     16m

動作確認

TCP/UDPのそれぞれで kubernetes.io の名前解決を行います。NGINX Ingress ControllerへQueryを送信します。

TCPでDNS Queryを送信します。Portは 5353 です。

dig node1 -p 5353  kubernetes.io +tcp
実行結果サンプル
 1; <<>> DiG 9.16.1-Ubuntu <<>> node1 -p 5353 kubernetes.io +tcp
 2;; global options: +cmd
 3;; connection timed out; no servers could be reached
 4
 5;; Got answer:
 6;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28171
 7;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
 8
 9;; OPT PSEUDOSECTION:
10; EDNS: version: 0, flags:; udp: 4096
11;; QUESTION SECTION:
12;kubernetes.io.                 IN      A
13
14;; ANSWER SECTION:
15kubernetes.io.          2474    IN      A       147.75.40.148
16
17;; Query time: 23 msec
18;; SERVER: 127.0.0.53#5353(127.0.0.53)
19;; WHEN: Fri Jan 21 06:46:38 UTC 2022
20;; MSG SIZE  rcvd: 71
21
22.. code-block:: cmdin

UDPでDNS Queryを送信します。Portは 53 です。

dig node1 -p 53  kubernetes.io
実行結果サンプル
 1; <<>> DiG 9.16.1-Ubuntu <<>> node1 -p 53 kubernetes.io
 2;; global options: +cmd
 3;; Got answer:
 4;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2308
 5;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
 6
 7;; OPT PSEUDOSECTION:
 8; EDNS: version: 0, flags:; udp: 65494
 9;; QUESTION SECTION:
10;node1.                         IN      A
11
12;; ANSWER SECTION:
13node1.                  0       IN      A       10.1.1.9
14
15;; Query time: 3 msec
16;; SERVER: 127.0.0.53#53(127.0.0.53)
17;; WHEN: Fri Jan 21 06:46:48 UTC 2022
18;; MSG SIZE  rcvd: 50
19
20;; Got answer:
21;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22877
22;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
23
24;; OPT PSEUDOSECTION:
25; EDNS: version: 0, flags:; udp: 65494
26;; QUESTION SECTION:
27;kubernetes.io.                 IN      A
28
29;; ANSWER SECTION:
30kubernetes.io.          210     IN      A       147.75.40.148
31
32;; Query time: 0 msec
33;; SERVER: 127.0.0.53#53(127.0.0.53)
34;; WHEN: Fri Jan 21 06:46:48 UTC 2022
35;; MSG SIZE  rcvd: 58

リソースの削除

サンプルアプリケーション、及び分散設定を削除します

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp
kubectl delete -f global-configuration.yaml
kubectl delete -f dns.yaml
kubectl delete -f transport-server-tcp.yaml
kubectl delete -f transport-server-udp.yaml

HTTP/HTTPSを待ち受ける設定に戻す場合、以下の操作を参考に実施してください。

NGINXの設定については、再度デプロイの後、待受のポート番号を確認して適切にnginx.confを変更してください。
手順は以下を参照してください。
cd ~/kubernetes-ingress/deployments
kubectl delete -f service/nodeport-tcp.yaml
kubectl delete -f service/nodeport-udp.yaml
kubectl delete -f deployment/nginx-plus-ingress-tcpudp.yaml

kubectl apply -f service/nodeport.yaml
kubectl apply -f deployment/nginx-plus-ingress.yaml
## 手順を参考にnginx.confを変更してください