---
# System prepended metadata

title: 'Howdy K8s Gardener!!!! <img src="https://i.imgur.com/ZaIgBiK.png" width="50">'

---

# Howdy K8s Gardener!!!! <img src="https://i.imgur.com/ZaIgBiK.png" width="50">

# Create your first Gardener Kubernetes cluster

1. Logon to the [Gardener Dashboard](https://dashboard.garden.canary.k8s.ondemand.com/login) and choose CREATE YOUR FIRST PROJECT.

![](https://i.imgur.com/0gAU1F3.png)


2. Provide a project Name, and optionally a Description, and a Purpose, and choose CREATE. 

**Note:** You will not be able to change the project Name later. The rest of the details are editable.

:bangbang: Since we are going to create only trial clusters it will not be charged. No need to input the cost center.



![](https://i.imgur.com/muQ2lS8.png)

3. The result will be similar to this.

 ![](https://i.imgur.com/WAkvcZ7.png)

4. In the dashboard navigation on the left, choose CLUSTERS, and then choose the plus button.

![](https://i.imgur.com/qODnO51.png)

5. In the **Infrastructure** section choose **GCP** for IaaS provider. 
In the **Cluster Details** section of the configuration screen, change the autogenerated **Cluster Name**.
Make sure that the **trial secret** selected in the **Infrastructure Details > Secret** dropdown is ```trial-secret-gcp``` and give minimum **worker nodes as 2**.

![](https://i.imgur.com/CaQvLRg.png)


6. While the cluster is in creating state, you can go through the very interesting [value propostion of Gardener](https://github.wdf.sap.corp/pages/kubernetes/gardener/docs/service/valueproposition/) and more about in https://gardener.cloud



## Accessing cluster and Toolset:



1. Gardener has a useful feature to open a [Web Terminals](https://github.com/gardener/dashboard/blob/master/docs/Webterminals.md) and communicate with the kubernetes cluster. We will be using this web terminal with our preconfigured image containing tools needed for this handson.

2. Select your Cluster --> Overview Page --> Access --> Terminal
![](https://i.imgur.com/Zw0oo5f.png)


3. Choose **Cluster** as terminal Target and delete the pre-loaded image and input the following image and press **Create**

```
kesavanking/dkom-toolbelt:2.0
```

![](https://i.imgur.com/MfCMaBT.png)


4. Wait till the pod gets created and you will see a terminal in your browser. check cluster acess with `kubectl cluster-info`.


## Kubernetes Cluster :+1: 
Kubernetes coordinates a highly available cluster of computers that are connected to work as a single unit. The abstractions in Kubernetes allow you to deploy containerized applications to a cluster without tying them specifically to individual machines. To make use of this new model of deployment, applications need to be packaged in a way that decouples them from individual hosts: they need to be containerized. Containerized applications are more flexible and available than in past deployment models, where applications were installed directly onto specific machines as packages deeply integrated into the host. Kubernetes automates the distribution and scheduling of application containers across a cluster in a more efficient way. Kubernetes is an open-source platform and is production-ready.
![](https://i.imgur.com/yOS9KP0.png)

A Kubernetes cluster consists of two types of resources:
* The **Master** coordinates the cluster
* **Nodes** are the workers that run applications 


    
>     kubectl cluster-info


>     kubectl get nodes
It will give you the cluster details and number of nodes in the cluster.

## Deploy Your App :+1: 
Once you have a running Kubernetes cluster, you can deploy your containerized applications on top of it. To do so, you create a Kubernetes Deployment configuration. The Deployment instructs Kubernetes how to create and update instances of your application. Once you've created a Deployment, the Kubernetes master schedules mentioned application instances onto individual Nodes in the cluster.
![](https://i.imgur.com/hstZg2F.png)


Once the application instances are created, a Kubernetes Deployment Controller continuously monitors those instances. If the Node hosting an instance goes down or is deleted, the Deployment controller replaces it. **This provides a self-healing mechanism to address machine failure or maintenance.**

> ```
> kubectl create deployment pingme --image=kesavanking/k8s-dkom:1.0

>```
>  kubectl get deployments

## Explore Your App :+1:
When you created a Deployment, Kubernetes created a **Pod** to host your application instance. A Pod is a Kubernetes abstraction that represents a group of one or more application containers and some shared resources for those containers (Storage volumes,Unique Cluster IP address)
![](https://i.imgur.com/BSpoOrg.png)

A Pod always runs on a **Node**. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster.Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster. The Master's automatic scheduling takes into account the available resources on each Node.
![](https://i.imgur.com/12GmhYi.png)

You will use kubectl command line interface to get information about deployed applications and thier environments

* **kubectl get** - list resources
> ```
> kubectl get pods 
> ```
* **kubectl describe** - show detailed information about a resource
> ```
> kubectl describe pod <POD NAME>
> ```
* **kubectl logs** - print the logs from a container in a pod
> ```
> kubectl logs <POD NAME> -c k8s-dkom -f 
> ```
* **kubectl exec** - execute a command on a container in a pod
> ```
> kubectl exec -it  <POD NAME> -- /bin/sh
> ```

> ```
> ps -a
> ```
You can see the hello application running....
> ```
> exit
> ```
 
We have now opened console on the container.You can check the binary *hello-app* of the go application.


## Expose Your App :+1: 

Although each Pod has a unique IP address, those IPs are not exposed outside the cluster.A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services allow your applications to receive traffic. Services can be exposed in different ways by specifying a type in the ServiceSpec:

* ***ClusterIP*** (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.

* ***NodePort*** - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using <NodeIP>:<NodePort>. Superset of ClusterIP.
* ***LoadBalancer*** - Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. Superset of NodePort.
* ***ExternalName*** - Exposes the Service using an arbitrary name (specified by externalName in the spec) by returning a CNAME record with the name. No proxy is used. This type requires v1.7 or higher of kube-dns.

    ![](https://i.imgur.com/7X440Tu.png)

> ```
> kubectl get services
> ```
Gives you current services in the cluster.We have a Service called kubernetes that is created by default when minikube starts the cluster. 
You create a new service and expose it to external traffic we’ll use the expose command with LoadBalancer as parameter
> ```
> kubectl expose deployment pingme --type=LoadBalancer --port 80 --target-port 8080

> ```
>  kubectl get services
> ```

The External IP will be in pending state.Wait for a while till your application get a specific External IP.Once you've determined the external IP address for your application, copy the IP address. Point your browser to  External IP URL (such as http://203.0.113.0) to check if your application is accessible.


## Scale Your App :+1:
In the previous modules we created a Deployment, and then exposed it publicly via a Service. The Deployment created only one Pod for running our application. When traffic increases, we will need to scale the application to keep up with user demand.

Scaling is accomplished by changing the number of replicas in a Deployment
  ![](https://i.imgur.com/ZY4IXlO.png)
  
> ```
> kubectl scale deployment pingme --replicas=3
> ```
> ```
> kubectl get pods 
> ```

Now, you have multiple instances of your application running independently of each other.The load balancer you provisioned in the previous step will start routing traffic to these new replicas automatically.



## Update Your App 

Users expect applications to be available all the time and developers are expected to deploy new versions of them several times a day. In Kubernetes this is done with rolling updates. **Rolling updates** allow Deployments' update to take place with zero downtime by incrementally updating Pods instances with new ones. The new Pods will be scheduled on Nodes with available resources.

![](https://i.imgur.com/t9g8Hnx.png)

To update the image of the application to version 2, use the **set image **command, followed by the deployment name and the new image version:

> ```
> kubectl set image deployment/pingme k8s-dkom=kesavanking/k8s-dkom:2.0
> ```
> ```
> kubectl get pods -l app=pingme
> ```


You can see new containers will be creating with new image and you can access the service as we did in above module and check the version change in the web output

When you access the service output will be similar to this.

```
Hello SAP!
Version: 2.0.0
Hostname: pingme-76975fc9d6-bdm47
```

*Happy Kubernetes* :tada:


## Delete Your Resources

---
Once you completed your exercise please delete your resources for other participant's convenience..

> ```
> kubectl delete deployment pingme
> ```

> ```
> kubectl delete service pingme
> ```
> 
---

# Use Gardener Features for applications.


## Enough Hello World !!


We will deploy [minio](https://min.io/), a native kubernetes object storage using `helm`package manager. 


1. Add helm repo for minio

```helm repo add minio https://helm.min.io/```

2. Create `minio` namespace

```kubectl create ns minio```

3. Install the chart.

```helm install minio --namespace minio minio/minio```

4. Check if minio pod is running successfully.

```kubectl get pods -n minio```



## Expose minio via ingress
Now let's expose the minio object store through [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). Gardener by default provides an add-on for ingress controller which can be used for dev purposes.

Access the [Gardener dashboard](https://dashboard.garden.canary.k8s.ondemand.com/). Go to the project, click on the cluster which you created. Under `Overview Page`, go to **add-on section** and enable nginx ingress. Wait till the cluster gets reconciled and turns green.

![](https://i.imgur.com/aHRWt7M.png)


In the same overview page, under Infrastructure section you can find your **ingress domain** . It will be in the format of  ```*.ingress.<shootname>.<project>.shoot.canary.k8s-hana.ondemand.com```


:bangbang::bangbang: While copying ignore ***.** for ingress domain


**Example:**
INGRESS_DOMAIN = `ingress.<SHOOT>.<PROJECT>..shoot.canary.k8s-hana.ondemand.com`

Open `vim` Copy the below ingress object file and replace **INGRESS_DOMAIN**

```
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: minio
  annotations:
    cert.gardener.cloud/purpose: managed
spec:
  tls:
  # Must not exceed 64 characters.
  - hosts:
    - "minio.INGRESS_DOMAIN"
    # Certificate and private key reside in this secret.
    secretName: secret-tls
  rules:
  - host: minio.INGRESS_DOMAIN
    http:
      paths:
      - backend:
          serviceName: minio
          servicePort: 9000
```

Save the file, then do `kubectl apply -f <ingress file> -n minio`

## Request X.509 Certificates

You might have noticed an annotation ` cert.gardener.cloud/purpose: managed` in the ingress object which we created. Gardener let’s you request a commonly trusted X.509 certificate for your application endpoint. For more details you can [check here](https://gardener.cloud/v1.13.2/guides/administer_shoots/request_cert/)


TLS certificate will be stored as a secret. Check the status of the certificate creation 
    

`kubectl describe ing minio -n minio`


![](https://i.imgur.com/Wh0HyjW.png)

    kubectl get ingress -n minio
    
You could see the ingress url. Now access the ingress url in your browser.

![](https://i.imgur.com/KerJyUO.png)

Get Access key and secret key to login to minio:

**ACCESS KEY:**

```kubectl get secret minio -n minio -o jsonpath="{.data.accesskey}" | base64 --decode ```

**SECRET KEY:**

```kubectl get secret minio -n minio -o jsonpath="{.data.secretkey}" | base64 --decode```


Create a bucket and upload some files to the minio store. 
![](https://i.imgur.com/kYUJj9F.png)


# Volume Snapshot and Restore


[Volume snapshots](https://kubernetes.io/docs/concepts/storage/volume-snapshots) provide Kubernetes users with a standardized way to copy a volume's contents at a particular point in time without creating an entirely new volume. This functionality enables, for example, database administrators to backup databases before performing edit or delete modifications.


This section helps to gain the knowledge of taking volume snapshots and your applications and how to restore them in case of any disruptions or clone into a new volume.

Let's use the same volume which we provisioned while installing minio. 

:writing_hand::exclamation: Users are requested to upload some junk files to the objectstore so that we can see the real use of volume snapshot and restore.

![](https://i.imgur.com/x5s2Mgw.png)


### Volume Snapshot
1. Get the persistent volume claim name. You would see a persitent volume claim bound to the minio pod.

```kubectl get pvc -n minio```

![](https://i.imgur.com/x2yZ1QB.png)

2. Create a snapshot of the claim with the following manifest. Create a file using `vim`.

```
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: minio-snapshot
spec:
  volumeSnapshotClassName: default
  source:
    persistentVolumeClaimName: minio
```

Save the file and do,

```kubectl apply -f <snapshot manifest> -n minio```

3. Wait till the volumesnapshot becomes ready to use.

```kubectl get  volumesnapshot minio-snapshot -n minio```

![](https://i.imgur.com/QfEvubi.png)

4. Now we are safe to delete the minio deployment and we will see the restoration from the snapshot.

```helm uninstall minio -n minio```

### Restore Snapshot


1. Create a new persistent volume claim with the volumesnapshot.

Create a file using `vim`.
```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: minio-restore
spec:
  dataSource:
    name: minio-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Gi
```

Save the file and do ```kubectl apply -f <resstore_pvc file> -n minio```


2.  Deploy the minio helm chart with the created pvc.

```helm install minio  --namespace minio  minio/minio --set persistence.existingClaim=minio-restore```

3. Wait till the pod is ready.

```kubectl wait --for=condition=Ready pod  -l app=minio -n minio```

4. Access the same **ingress** url which you deployed before. You should see the same buckets and files being restored.:clap: :clap:


:warning::warning: Please show the results to the moderators for evaluation.:warning::warning:


# Hibernate your cluster :zzz:


Clusters are only needed 24 hours a day if they run productive workload. So whenever you do development in a cluster, or just use it for tests or demo purposes, you can save much money if you scale-down your Kubernetes resources whenever you don’t need them. However, scaling them down manually can become time-consuming the more resources you have.

Gardener offers a clever way to automatically scale-down all resources to zero: cluster hibernation. You can either [hibernate a cluster by pushing a button or by defining a hibernation schedule](https://gardener.cloud/documentation/guides/administer_shoots/hibernate-cluster/).

On the Gardener dashboard, choose CLUSTERS > [YOUR-CLUSTER] > OVERVIEW > Lifecycle > Hibernation > Hibernate Cluster.
![](https://i.imgur.com/GQMneLO.png)

You can even define a schedule to wakeup and hibernate your clusters.

As soon as the cluster was hibernated successfully, its status is shown as ZZZ in the list of clusters:


![](https://i.imgur.com/2835kTd.png)



--------------------


 :seedling: HAPPY GARDENING....:seedling: 

![]()<img src="https://i.imgur.com/ZaIgBiK.png" width="30">    https://gardener.cloud/


![]()<img src="https://i.imgur.com/3Oofwji.png" width="40">https://sap-cp.slack.com/archives/C9CEBQPGE



