<p>I am trying to use Minikube and Docker to understand the concepts of Kubernetes architecture.</p>

<p>I created a spring boot application with Dockerfile, created tag and pushed to Dockerhub.</p>

<p>In order to deploy the image in K8s cluster, i issued the below command,</p>

<pre><code># deployed the image
$ kubectl run &lt;deployment-name&gt; --image=&lt;username/imagename&gt;:&lt;version&gt; --port=&lt;port the app runs&gt;

# exposed the port as nodeport
$ kubectl expose deployment &lt;deployment-name&gt; --type=NodePort
</code></pre>

<p>Everything worked and i am able to see the 1 pods running <code>kubectl get pods</code></p>

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

<p>Below command produced an yaml output</p>

<p><strong>Does <code>kubectl</code> command creates deployment Yaml file out of the box?</strong></p>

<pre><code> $ kubectl get deployments --output yaml 
</code></pre>

<pre><code>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: ""
</code></pre>

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

<pre><code>--dry-run
</code></pre>

<p>and</p>

<pre><code>--output yaml
</code></pre>

<p>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:</p>

<pre><code>kubectl run nginx-example --image=nginx:latest --port=80 --dry-run --output yaml
</code></pre>

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

<pre><code>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: {}
</code></pre>

<p>Same with <code>expose</code> command:</p>

<pre><code>kubectl expose deployment nginx-example --type=NodePort --dry-run --output yaml
</code></pre>

<p>produces the following output:</p>

<pre><code>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: {}
</code></pre>

<p>And now the coolest part. You can use simple output redirection:</p>

<pre><code>kubectl run nginx-example --image=nginx:latest --port=80 --dry-run --output yaml &gt; nginx-example-deployment.yaml

kubectl expose deployment nginx-example --type=NodePort --dry-run --output yaml &gt; nginx-example-nodeport-service.yaml
</code></pre>

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

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

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

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