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: ""
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.
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.