containerPortなんて飾りです

# containers.portsの意味

https://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/

こちらのドキュメント内で示されているこちらdeployment

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
```

これを始めとして、kubernetesのmanifestは基本的に、サービスを公開するportに対して、`containers.ports.containerPort`を設定しています
この設定は直感的に、dockerコマンドの-pオプションのような、設定しないとアクセスできないもののように思えます
（なんなら上のドキュメントでは、コンテナポートの仕様を指定していることに注意してください、とわざわざ書いてあります）

が、実はアクセスするだけならこれは必要というわけではありません
これを設定しなくてもコンテナがlistenしているポートは勝手にクラスタ内に公開されてしまいます

試しに以下のような`container.ports`を設定しないmanifestをapplyして

```yaml:sample.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
  labels:
    app.kubernetes.io/name: test
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: test
  replicas: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: test
    spec:
      containers:
        - name: nginx-80
          image: nginx:latest
          volumeMounts:
            - mountPath: /etc/nginx/conf.d
              name: nginx-80
        - name: nginx-8080
          image: nginx:latest
          volumeMounts:
            - mountPath: /etc/nginx/conf.d
              name: nginx-8080
      volumes:
        - name: nginx-80
          configMap:
            name: nginx-80
        - name: nginx-8080
          configMap:
            name: nginx-8080
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-80
data:
  default.conf: |
    server {
        listen       80;
        server_name  localhost;

        location / {
            return 200 'port:80 ok\n';
        }
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-8080
data:
  default.conf: |
    server {
        listen       8080;
        server_name  localhost;

        location / {
            return 200 'port:8080 ok\n';
        }
    }
```

他のコンテナからアクセスすると、port:80もport:8080も問題なくレスポンスが返ります

```
bash-5.1# curl 10.1.0.54:80
port:80 ok
bash-5.1# curl 10.1.0.54:8080
port:8080 ok
```

もちろんservice経由でもアクセスできます

```yaml:service.yaml
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    app.kubernetes.io/name: test
  ports:
    - port: 80
      name: "80"
    - port: 8080
      name: "8080"
```

```
bash-5.1# curl test.default.svc:80
port:80 ok
bash-5.1# curl test.default.svc:8080
port:8080 ok
```

じゃあこの`containers.ports`は何の設定なのかという話ですが

`kubectl explain pods.spec.containers.ports` とやるとdescriptionにあります

```
List of ports to expose from the container. Exposing a port here gives the
system additional information about the network connections a container
uses, but is primarily informational. Not specifying a port here DOES NOT
prevent that port from being exposed. Any port which is listening on the
default "0.0.0.0" address inside a container will be accessible from the
network. Cannot be updated.

ContainerPort represents a network port in a single container.
```

参考：https://github.com/kubernetes/kubernetes/issues/4332

だからと言って、じゃあ無駄だから書かない、なんてことにはならないんですけどね

# そんなの困る

その動作は許されないという方は、networkPolicyを使って制御するしかなさそうですね
（networkPolicyの詳細に関しては、記事がたくさんあるのでそちらで:rolling_eyes:）