Does kubernetes kubectl run with image creates deployment yaml file

12/24/2019

I am trying to use Minikube and Docker to understand the concepts of Kubernetes architecture.

I created a spring boot application with Dockerfile, created tag and pushed to Dockerhub.

In order to deploy the image in K8s cluster, i issued the below command,

# deployed the image
$ kubectl run <deployment-name> --image=<username/imagename>:<version> --port=<port the app runs>

# exposed the port as nodeport
$ kubectl expose deployment <deployment-name> --type=NodePort

Everything worked and i am able to see the 1 pods running kubectl get pods

The Docker image i pushed to Dockerhub didn't had any deployment YAML file.

Below command produced an yaml output

Does kubectl command creates deployment Yaml file out of the box?

 $ kubectl get deployments --output yaml 
apiVersion: v1
items:
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    annotations:
      deployment.kubernetes.io/revision: "1"
    creationTimestamp: "2019-12-24T14:59:14Z"
    generation: 1
    labels:
      run: hello-service
    name: hello-service
    namespace: default
    resourceVersion: "76195"
    selfLink: /apis/apps/v1/namespaces/default/deployments/hello-service
    uid: 90950172-1c0b-4b9f-a339-b47569366f4e
  spec:
    progressDeadlineSeconds: 600
    replicas: 1
    revisionHistoryLimit: 10
    selector:
      matchLabels:
        run: hello-service
    strategy:
      rollingUpdate:
        maxSurge: 25%
        maxUnavailable: 25%
      type: RollingUpdate
    template:
      metadata:
        creationTimestamp: null
        labels:
          run: hello-service
      spec:
        containers:
        - image: thirumurthi/hello-service:0.0.1
          imagePullPolicy: IfNotPresent
          name: hello-service
          ports:
          - containerPort: 8800
            protocol: TCP
          resources: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
        dnsPolicy: ClusterFirst
        restartPolicy: Always
        schedulerName: default-scheduler
        securityContext: {}
        terminationGracePeriodSeconds: 30
  status:
    availableReplicas: 1
    conditions:
    - lastTransitionTime: "2019-12-24T14:59:19Z"
      lastUpdateTime: "2019-12-24T14:59:19Z"
      message: Deployment has minimum availability.
      reason: MinimumReplicasAvailable
      status: "True"
      type: Available
    - lastTransitionTime: "2019-12-24T14:59:14Z"
      lastUpdateTime: "2019-12-24T14:59:19Z"
      message: ReplicaSet "hello-service-75d67cc857" has successfully progressed.
      reason: NewReplicaSetAvailable
      status: "True"
      type: Progressing
    observedGeneration: 1
    readyReplicas: 1
    replicas: 1
    updatedReplicas: 1
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
-- Tim
docker
kubectl
kubernetes

2 Answers

12/24/2019

I think the easiest way to understand whats going on under the hood when you create kubernetes resources using imperative commands (versus declarative approach by writing and applying yaml definition files) is to run a simple example with 2 additional flags:

--dry-run

and

--output yaml

Names of these flags are rather self-explanatory so I think there is no further need for comment explaining what they do. You can simply try out the below examples and you'll see the effect:

kubectl run nginx-example --image=nginx:latest --port=80 --dry-run --output yaml

As you can see it produces the appropriate yaml manifest without applying it and creating actual deployment:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    run: nginx-example
  name: nginx-example
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-example
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: nginx-example
    spec:
      containers:
      - image: nginx:latest
        name: nginx-example
        ports:
        - containerPort: 80
        resources: {}
status: {}

Same with expose command:

kubectl expose deployment nginx-example --type=NodePort --dry-run --output yaml

produces the following output:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    run: nginx-example
  name: nginx-example
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx-example
  type: NodePort
status:
  loadBalancer: {}

And now the coolest part. You can use simple output redirection:

kubectl run nginx-example --image=nginx:latest --port=80 --dry-run --output yaml > nginx-example-deployment.yaml

kubectl expose deployment nginx-example --type=NodePort --dry-run --output yaml > nginx-example-nodeport-service.yaml

to save generated Deployment and NodePort Service definitions so you can further modify them if needed and apply using either kubectl apply -f filename.yaml or kubectl create -f filename.yaml.

Btw. kubectl run and kubectl expose are generator-based commands and as you may have noticed when creating your deployment (as you probably got the message: kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead.) they use --generator flag. If you don't specify it explicitly it gets the default value which for kubectl run is --generator=deployment/apps.v1beta1 so by default it creates a Deployment. But you can modify it by providing --generator=run-pod/v1 nginx-example and instead of Deployment it will create a single Pod. When we go back to our previous example it may look like this:

kubectl run --generator=run-pod/v1 nginx-example --image=nginx:latest --port=80 --dry-run --output yaml

I hope this answered your question and clarified a bit the mechanism of creating kubernetes resources using imperative commands.

-- mario
Source: StackOverflow

12/24/2019

Yes, kubectl run creates a deployment. If you look at the label field, you can see run: hello-service. This label is used later in the selector.

-- Mafor
Source: StackOverflow