tanke25616429のアウトプット

IT技術の基本を勉強したことをアウトプットします。Linux、Kubernetes、クラウド中心です。百番煎じくらいだけど誰かの役に立てばそれはそれでうれしい。

KubernetesのServiceで出てくる各種ポートの意味

本記事の目的

KubernetesでServiceを作成するとPortTragetPortNodePortといろいろなポートが出てくる。忘れがちなのでメモする。

[root@master01 ~]# kubectl describe svc nginx
Name:                     nginx
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.108.101.153
Port:                     <unset>  8080/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30082/TCP
Endpoints:                10.0.1.21:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

NodePort

KuberntesのServiceにはいくつかType(種類)がある。NodePort Serviceはその一つである。NodePort Serviceを作成すると、NodePortというポート番号が設定できる。

このとき、Kubernetesの各ノードのIPにアクセスできるネットワークから、以下のURLでServiceにアクセスできる*1

http://<各ワーカノードのIP(複数ある場合、どのワーカでもよい)>:<NodePortのポート番号>

以下に例を示す。192.168.0.102192.168.0.103はそれぞれワーカノードのIPアドレスである。アクセス元はワーカノードへの疎通性があるところなら何でもよいので、ここではマスターノードからアクセスする。nginxのデフォルトページの応答が返ってきていることがわかる。

[root@master01 ~]# curl http://192.168.0.102:30082
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master01 ~]# curl http://192.168.0.103:30082
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

それぞれのワーカノードで、NodePortとして設定されているポート番号(この場合は30082)の待ち受け状況を確認する。kube-proxという文字が見えるのでkube-proxyというプロセスがNodePortのポート番号で待ち受けているのが実態とわかる。

ワーカノード1で確認。

[root@worker01 ~]# ss -antu | grep 30082
tcp    LISTEN     0      128       *:30082                 *:*
[root@worker01 ~]# lsof -i :30082
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
kube-prox 3270 root    8u  IPv4  69766      0t0  TCP *:30082 (LISTEN)

ワーカノード2で確認。

[root@worker02 ~]# ss -antu |grep 30082
tcp    LISTEN     0      128       *:30082                 *:*
[root@worker02 ~]# lsof -i :30082
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
kube-prox 2369 root    8u  IPv4  43557      0t0  TCP *:30082 (LISTEN)

Port

KubernetesでServiceを作成するとデフォルトではClusterIP*2というIPが生成される。Portは作成したServiceへClusterIP経由でアクセスする際のポート番号である。ClusterIPはKubernetesクラスター内のコンテナからアクセスできる。以下のURLでアクセス可能。

http://<ClusterIP>:<Portで指定のポート番号>

以下に例を示す。コンテナ内に入り、コンテナ内からnginxの応答が返ってきていることがわかる。この例だとServiceのアクセス先とアクセス元のコンテナが同じなのでわかりにくいが、別に他のコンテナでも同じ方法でアクセスできる。

[root@master01 ~]# kubectl get service
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          119d
nginx        NodePort    10.108.101.153   <none>        8080:30082/TCP   11h
[root@master01 ~]# kubectl get pod nginx-f89759699-pksbl
NAME                    READY   STATUS    RESTARTS   AGE
nginx-f89759699-pksbl   1/1     Running   0          2d22h
[root@master01 ~]# kubectl exec nginx-f89759699-pksbl -it -- /bin/sh
# curl http://10.108.101.153:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

TargetPort

Serviceとして公開されたアプリケーションの処理の実体を担うコンテナがアクセスを待ち受けているポート番号である。このポートは外部からアクセスするためのURLになるものではない。http://<ClusterIP>:<Portで指定のポート番号>でアクセスを受けたとき、コンテナから見るとTargetPortでアクセスを受けたものとして処理される*3

確認するには、コンテナに入りhttp://localhost:<TargetPortで指定のポート番号>にアクセスしてみればよい。

[root@master01 ~]# kubectl exec nginx-f89759699-pksbl -it -- /bin/sh
# curl http://localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

なお、アプリケーション側の設定も正しい必要がある。例えばnginxではnginxのアプリケーションが待ち受けるポートの設定が記述されている。以下の通り、80番ポートでリッスンしており、KubernetesのServiceのTargetPortと一致していることがわかる。

# cat /etc/nginx/conf.d/default.conf
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

*1:マスターノードもワーカノードとして使う場合はマスターノードのIPからでもアクセス可能。

*2:ClusterIPはServiceのTypeでもある。

*3:NodePortでサービスを公開している場合、実際にはClusterIPのサービスがその裏で動いている。http://<各ワーカノードのIP>:<NodePortのポート番号>でアクセスを受けた後、いったんClusterIPでアクセスを受ける形になる。