Automating Kubernetes deployment using script - kubernetes

I have 'deployment.yaml' & 'service.yaml' files to deploy application in kubernetes (minikube).
To do a manual deployment I can use kubectl apply -f <file.yaml> to create resources but I am looking for a way to automate deployment using scripts. So I can trigger a script and all the needed yaml can be triggered and pods created accordingly.
Any suggestion or guidance will be helpful.

It sounds to me like you need some simple bash script where you put all commands you need
#!/bin/bash
NAMESPACE='mebbns'
DEPL_DIR='~/mebb_depl'
SVC_DIR='~/svc_depl'
kubectl create namespace $NAMESPACE
kubectl apply -n $NAMESPACE -f "$DEPL_DIR/deployment.yaml"
kubectl apply -n $NAMESPACE -f "$SVC_DIR/service.yaml"
kubectl get all -n $NAMESPACE
For more complex tasks you can check examples like setup-aks-vnet-acr.sh
kubectl Cheat Sheet should help you with basic commands you may require.

You can use a script to call kubectl for simple scenarious.
For more complex setups have a look at Argo cd https://argoproj.github.io/

There are many ways to automate your task. Any scripting language would be alright; such as Bash, Ansible, etc. If you are looking for sophisticated deployment tools, you can have a look at the common Kubernetes CI/CD tools
Kubernetes automation doesn't end with the CI/CD. When you have multiple applications with each of them has specific environment variables, security credentials, specific network and security requirements etc., then you will also need tools for organizing Kubernetes configuration, such as Helm and Kustomize.

Related

kubectl instead of yaml files in production?

I am trying to find the simpliest method to use kubernetes in production. YAML templates look like an overhead to me. E.g. all I want is expose simple backend service. I can do it with kubectl with 2 lean commands:
kubectl create deployment hello-server --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment hello-server --type LoadBalancer --port 80 --target-port 8080
But is it fine to use this in production? I would like to use Infrastructure-as-a-Code approach.
Is there a way to avoid working with kubernetes template files directly and still follow best practices? E.g. generating Yaml files from docker-compose files or similar?
What is the expected kubectl usage in production? Just
kubectl apply -f <folder>
while it is developers job to maintain template files in <folder> ? Is there a Declarative Management with kubectl without writing kubernetes templates myself? E.g. some files that contain the minimal info needed to templates to be generated.
Really want to use Kubernetes, please advice the simplest way to do this!
I am quoting the original question here:
kubectl create deployment hello-server --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment hello-server --type LoadBalancer --port 80 --target-port 8080
But is it fine to use this in production? I would like to use Infrastructure-as-a-Code approach.
Your first approach is a list of commands, that must be executed in a certain order. In addition, all these commands are not idempotent, so you cannot run the commands multiple times.
Also from the original question:
Is there a way to avoid working with kubernetes template files directly and still follow best practices? E.g. generating Yaml files from docker-compose files or similar?
What is the expected kubectl usage in production? Just
kubectl apply -f <folder>
The second approach is declarative, you only describe what you want, and the command is idempotent, so it can be run many times without problems. Your desired state is written in text files, so any change can be managed with a version control system, e.g. Git and the process can be done with validation in a CI/CD pipeline.
For production environments, it is best practice to use version control system like git for what your cluster contain. This make it easy to recover or recreate your system.

provide custom command line options for kubectl for kubernetes operator

I have one kubernetes operator (ex: kubectl get oracle_ctrl). Now I want to provide custom arguments for the kubectl command.
ex: kubectl apply oracle_ctrl --auto-discover=true --name=vcn1
I can write one more controller to do the same job. But I don't want to write one more controller and make use of existing controller.
Is it possible to use operator-sdk to provide custom args to kubectl?
No, this isn't possible.
kubernetes/kubectl#914 has a little bit further discussion of this, but its essential description is "we should start the proposal and design process to eventually write something better than kubectl create to support it". Your CRD can define additional columns to be shown in kubectl get but this is really the only kubectl-related extension point. You could potentially create a kubectl plugin or another CLI tool that does what you need.
Rather than using the kubectl imperative tools, it's often a better practice to directly write YAML artifacts and commit them to source control. You can parameterize these using tools like Helm or Kustomize. If kubectl apply -f or helm install is your primary way of loading things into the cluster, then you don't need custom CLI options to make this work.

kubectl deploy only one component from a yaml

I have a yaml file which works if I deploy it using
kubectl apply -f myComponents.yaml
My question is, is there a way to deploy just one component from this YAML? For example, if my YAML has both deployment and service and I just want to deploy the service
I am looking for something like
kubectl apply -f myComponents.yaml Service
No. ⛔
At least not yet. Currently, you can take advantage of tools like kustomize, to apply/create/delete what you'd like, but that's not necessarily the same thing.
Having said I've made a feature request for kubectl 💡.
✌️
No. You can use a command line tool to do this like yq though, depending on how fancy you want to be:
cat myComponents.yaml | yq 'some selector' | kubectl apply -f -

Kubernetes - validate deployments

I have a namespace namespace - which has ~10-15 deployments.
Creating a big yaml file, and apply it on a "deploy".
How do i validate, wait, watch, block, until all deployments have been rolledout ?
currently i am thinking of:
get list of deployments
foreach deployment - make api call to get status
once all deployments are "green" - end process, signaling deployment/ship is done.
what are the status'es of deployments, is there already a similar tool that can do it? https://github.com/Shopify/kubernetes-deploy is kind of what i am searching for, but it forces a yml structure and so on.
what would be the best approach?
Set a readiness probe and use kubectl rollout status deployment <deployment_name> to see the deployment rollout status
You'd better use Helm for managing deployments. Helm allows you to create reusable templates that can be applied to more than one environment. Read more here: https://helm.sh/docs/chart_template_guide/#getting-started-with-a-chart-template
You can create one big chart for all your services or you can create separate Helm charts for each your service.
Helm also allows you to run tests after deployment is done. Read more here: https://helm.sh/docs/developing_charts/#a-breakdown-of-the-helm-test-hooks
You probably want to use kubectl wait https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#wait
It lets you wait for a specific condition of a specific object
In your case:
kubectl -n namespace \
wait --for=condition=Available --timeout=32s \
deployment/name
use --dry-run option in the apply/create command to check the syntax.

Kubernates pass env variable to "kubectl create"

I need to pass dynamic env variable to kubectl create. Something like this
kubectl create -f app.yaml --Target=prod
Based on Target code deploys on different servers.
If you want to avoid installing 3rd party plugin then you can replace the text using sed "s/orginal/change/". It worked. I used this in Jenkins shell.
cat app.yaml | sed "s/l3-apps/l2-apps/" | kubectl create -f -
You can achieve this in two ways:
Use Helm. It is a "package manager" for Kubernetes and is built exactly for your use case (dynamic variables to configure behaviour of your resources). If it is only a single variable, "converting" your deployment is as simple as creating a new Helm chart, copy your files into templates/, modify values.yaml and use {{ .Values.target }} in your templates. See the quickstart guide for a more in-depth introduction to Helm.
If you consider Helm to be over the top for a single variable, use kubectl's capability to read from standard input. You'll need an additional templating tool (for example mustache). Rewrite your deployment to fit your templating tool. Create a dynamic data.yml in your deployment process (e.g. a simple bash script that reads from environment variables) and run something like mustache data.yml deployment.mustache | kubectl apply -f -.
kubectl config set-context allows you to configure cluster, namespace, user credentials and more and save it as a "context" in your ~/.kube/config.
The you can use --context option of kubectl exactly in a way that you used --Target in your example.
I've published a command-line tool ysed that also performs what you need.