Exposing ports of applications with k8s is different than exposing it with docker.
For pods, spec.containers.ports
field isn't used to expose ports. It mostly used for documenting purpouses and also to name ports so that you can reference them later in service object's target-port with their name, and not a number (https://stackoverflow.com/a/65270688/12201084).
So how do we expose pods to the outside?
It's done with service objects. There are 4 types of service: ClusterIP, NodePort, LoadBalancer and ExternalName.
They are all well explained in k8s documentation so I am not going to explain it here. Check out K8s docs on types of servies
Assuming you know what type you want to use you can now use kubectl to create this service:
kubectl expose pod <pod-name> --port <port> --target-port <targetport> --type <type>
kubectl expose deployment <pod-name> --port <port> --target-port <targetport> --type <type>
Where:
- --port - is used to pecify the port on whihc you want to expose the application
- --target-port - is used to specify the port on which the applciation is running
- --type - is used to specify the type of service
With docker you would use -p <port>:<target-port>
OK, but maybe you don't want to use kubeclt to create a service and you would like to keep the service in git or whatever as a yaml file. You can check out the examples in k8s docs, copy it and write you own yaml or do the following:
$ kubectl expose pod my-svc --port 80 --dry-run=client -oyaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
run: my-svc
name: my-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: my-svc
status:
loadBalancer: {}
Note: notice that if you don't pass a value for --target-port
it defaults to the same value as --port
Also notice the selector filed, that has the same values as the labels on a pod. It will forward the traffic to every pod with this label (within the namespace).
Now, if you don't pass the value for --type
, it defaults to ClisterIP so it means the service will be accessible only from within the cluster.
If you want to access the pod/application from the outside, you need to use either NodePort or LoadBalancer.
Nodeport opens some random port on every node and connecting to this port will forward the packets to the pod. The problem is that you can't just pick any port to open, and often you dont even get to pick the port at all (it's randomly assigned).
In case of type LoadBalancer you can use whateever port you'd like, but you need to run in cloud and use cloud provisioner to create and configure external loadbalancer for you and point it to your pod. If you are running on bare-metal you can use projects like MetalLB to make use of LoadBalancer type.
To summarize, exposing containers with docker is totally different than exposing them with kubernetes. Don't assume k8s will work the same way the docker works just with different notation, because it won't.
Read the docs and blogs about k8s services and learn how they work.