Is there an option to choose host port for publishing service via nodeport service when using kubectl expose?

12/28/2019

I want to expose tomcat service via nodeport service method.I'm trying to achieve the same using kubectl run command option instead of using manifest yaml file with kubectl (apply or create) command

[root@master ~]# kubectl run tom --image=tomcat --replicas=3 --port=8080 --labels="env=prod"
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/tom created

[root@master ~]# kubectl create service nodeport tomsvc  --tcp=32156:8080 --node-port=32666
service/tomsvc created
[root@master ~]#

[root@master ~]# kubectl get svc tomsvc
NAME     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
tomsvc   NodePort   10.98.117.174   <none>        32156:32666/TCP   30s
[root@master ~]#

Now the endpoints are not updated since we didn't have option to use label selector during kubectl create service

[root@master ~]# kubectl get ep tomsvc
NAME     ENDPOINTS   AGE
tomsvc   <none>      62s
[root@master ~]#

After changed the selector from default to env: prod,endpoints got updated

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2019-12-28T14:30:21Z"
  labels:
    app: tomsvc
  name: tomsvc
  namespace: default
  resourceVersion: "1834608"
  selfLink: /api/v1/namespaces/default/services/tomsvc
  uid: 696f4dde-341a-4118-b02b-6aa53df18f74
spec:
  clusterIP: 10.98.117.174
  externalTrafficPolicy: Cluster
  ports:
  - name: 32156-8080
    nodePort: 32666
    port: 32156
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomsvc
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}
~

Now i'm able to see endpoints updated with pod ip address and target port which are having labels as env: prod

[root@master ~]# kubectl get ep tomsvc
NAME     ENDPOINTS                                      AGE
tomsvc   10.36.0.2:8080,10.36.0.3:8080,10.36.0.4:8080   4m20s
[root@master ~]#

So to avoid using this option to edit nodeport service yaml file for updating selector,i saw there is an option kubectl expose option to publish service

Deleted that nodeport service and recreated using kubectl expose option

[root@master ~]# kubectl delete svc tomsvc
service "tomsvc" deleted

[root@master ~]# kubectl expose deployment tom --port=32156 --type=NodePort --target-port=8080
service/tom exposed
[root@master ~]# kubectl get svc tom
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
tom    NodePort   10.107.182.35   <none>        32156:30397/TCP   19s

Now endpoints automatically updated with pods which are having env: prod as label

[root@master ~]# kubectl get ep tom
NAME   ENDPOINTS                                      AGE
tom    10.36.0.2:8080,10.36.0.3:8080,10.36.0.4:8080   25s
[root@master ~]#

My questions is why there is no option to pass selector while using kubectl create service command and why there is no option --nodeport while running kubectl expose command?

Is there anything technically I'm misunderstanding here?

-- user10912187
kubernetes

1 Answer

12/30/2019

If you want to create deployment and expose it using kubectl run command you can do it by using following:

kubectl run tom --image=tomcat --replicas=3 --port=8080 --labels="env=prod" --expose=true --service-overrides='{ "spec": { "type": "NodePort" } }'

--expose=true creates a service (by default ClusterIP) and assigns it to the deployment using same selectors as specified for the deployment.

--service-overrides='{ "spec": { "type": "NodePort" } }' changes its type to NodePort.

-- KFC_
Source: StackOverflow