Skip to content

sajramay/kubernetes_notes

Repository files navigation

Minikube

Installation

https://github.com/kubernetes/minikube#installation

Commands

Start

$ minikube start

Status

$ minikube status

Kubernetes

Set Up

$ source <(kubectl completion bash)

Run a local registry (ignore this step if using DockerHub)

$ docker run -d -p 5000:5000 registry

Build Docker Image

$ docker build -t ramays/springldap .

Retag to Push to Local Registry

$ docker tag ramays/springldap localhost:5000/dev/ramays/springldap

Push to Local Registry

$ docker push localhost:5000/dev/ramays/springldap

Run a single pod using the Kubernetes command line, inspect the Pod and then invoke the Spring Boot App

$ kubectl run springldap --image=localhost:5000/dev/ramays/springldap --port=9090 --generator=run-pod/v1

$ kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
springldap   1/1     Running   0          107s

$ kubectl describe pod/springldap
Name:               springldap
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               minikube/192.168.0.21
Start Time:         Tue, 19 Feb 2019 23:47:12 +0000
Labels:             run=springldap
Annotations:        <none>
Status:             Running
IP:                 172.17.0.5
Containers:
  springldap:
    Container ID:   docker://59d3327a4135b62a7d5d01a9b0cb3923953757f6ba1845647f9c49ded5b97205
    Image:          localhost:5000/dev/ramays/springldap
    Image ID:       docker-pullable://localhost:5000/dev/ramays/springldap@sha256:3141232e1e660a788bf14f83d97ed4e1c240f1691c779fd7ac2fc8bee076a7f4
    Port:           9090/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Tue, 19 Feb 2019 23:47:13 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-rbxnm (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-rbxnm:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-rbxnm
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  3m3s  default-scheduler  Successfully assigned default/springldap to minikube
  Normal  Pulling    3m2s  kubelet, minikube  pulling image "localhost:5000/dev/ramays/springldap"
  Normal  Pulled     3m2s  kubelet, minikube  Successfully pulled image "localhost:5000/dev/ramays/springldap"
  Normal  Created    3m2s  kubelet, minikube  Created container
  Normal  Started    3m2s  kubelet, minikube  Started container

$ curl http://172.17.0.5:9090
<!DOCTYPE html>.....

General Inspection Commands

Check Services - Pods

$ kubectl get pods

Check Services - ReplicaSets

$ kubectl get rs

Check Services

$ kubectl get services

Pod information

$ kubectl get pods -o wide
$ kubectl describe pod springldap-xxxxx
$ kubectl get po springldap-xxxxx -o yaml

Meta Information

$ kubectl explain pods
$ kubectl explain pods.spec

CleanUp

$  kubectl delete all --all
pod "springldap-cdxlk" deleted
pod "springldap-cgjsl" deleted
pod "springldap-lw48v" deleted
replicationcontroller "springldap" deleted
service "kubernetes" deleted                     <-- will be recreated!
service "springldap-nodeport" deleted

Create a Pod Using YAML

apiVersion: v1
kind: Pod
metadata:
  name: springldap-manual
spec:
  containers:
  - image: localhost:5000/dev/ramays/springldap
    name: springldap
    ports:
    - containerPort: 9090
      protocol: TCP
$ kubectl create -f springldap-manual.yaml

Create a ReplicaSet, which will automatically create the pods. Note that ReplicationControllers are deprecated.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: springldap
spec:
  replicas: 3
  selector:
    matchLabels:
      app: springldap
  template:
    metadata:
      labels:
        app: springldap
    spec:
      containers:
      - name: springldap
        image: localhost:5000/dev/ramays/springldap
        ports:
        - containerPort: 9090
$ kubectl create -f springldap-rs.yaml
$ kubectl get pods,rs,services
NAME                   READY   STATUS    RESTARTS   AGE
pod/springldap-l9vkj   1/1     Running   0          54s
pod/springldap-l9xsh   1/1     Running   0          54s
pod/springldap-vcsl4   1/1     Running   0          54s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/springldap         3         3         3       54s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   7m29s

Using LoadBalancers and NodePorts

Clean up and recreate the pods using a ReplicaSet

$ kubectl delete all --all
$ kubectl create -f springldap-rs.yaml

Expose Spring Boot Pods through a Load-Balancer (not supported in Minikube v0.30.0)

$ kubectl expose rc springldap --type=LoadBalancer --name springldap-http

Expose Spring Boot Pods Through a NodePort

$ kubectl expose rc springldap --name springldap-nodeport

Check Services

$ kubectl get services
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP    71d
springldap-nodeport   ClusterIP   10.109.11.173   <none>        9090/TCP   6s
$ curl 10.109.11.173:9090

Edit and update YAML

$ kubectl replace -f springldap-rs.yaml

Scale Up

$ kubectl scale --replicas=6 -f springldap-rs.yaml

Scale Up

$ kubectl scale --replicas=6 replicaset springldap 

Delete a Single Pod (A new one will be started by the RC)

$ kubectl delete po springldap-xxxxx

Display Pods along with the app label

$ kubectl get pods -L app -o wide

Edit RC YAML and Apply Changes

$ kubectl edit rs springldap

Delete RC but Keep the Pods Runnning

$ kubectl delete rs springldap --cascade=false

Create ReplicaSet

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
  name: springldap
spec:
  replicas: 3
  selector:
    matchLabels:
      app: springldap
  template:
    metadata:
      labels:
        app: springldap
    spec:
      containers:
      - name: springldap
        image: localhost:5000/dev/ramays/springldap

A ReplicaSet is the replacement for ReplicationControllers

$ kubectl delete all --all
$ kubectl create -f springldap-rs.yaml
$ kubectl get pods,rs,services
NAME                   READY   STATUS    RESTARTS   AGE
pod/springldap-4m5bk   1/1     Running   0          10s
pod/springldap-n5r6p   1/1     Running   0          10s
pod/springldap-zspzn   1/1     Running   0          10s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/springldap         3         3         3       10s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   23s

Create a Service to Wrap the Pods

apiVersion: v1
kind: Service
metadata:
  name: springldap
spec:
  ports:
  - port: 80
    targetPort: 9090
  selector:
    app: springldap
$ kubectl delete all --all
$ kubectl create -f springldap-svc.yaml
service/springldap created

$ kubectl get pods,rc,services
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   37s
service/springldap   ClusterIP   10.107.146.119   <none>        80/TCP    3s

Note that only the service is created and no backing pods so curl at the service address does not do anything

$ curl 10.107.146.119
curl: (7) Failed to connect to 10.107.146.119 port 80: Connection refused

Service is targeted at port 9090 of the pods

$ kubectl describe service/springldap
Name:              springldap
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=springldap
Type:              ClusterIP
IP:                10.107.146.119
Port:              <unset>  80/TCP
TargetPort:        9090/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

Create the ReplicaSet which will create the pods

$ kubectl create -f springldap-rs.yaml
replicaset.apps/springldap created

$ kubectl get pods,rs,services
NAME                   READY   STATUS    RESTARTS   AGE
pod/springldap-nz8hx   1/1     Running   0          9s
pod/springldap-s2xjz   1/1     Running   0          9s
pod/springldap-t5r4d   1/1     Running   0          9s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.extensions/springldap   3         3         3       9s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   3m48s
service/springldap   ClusterIP   10.107.146.119   <none>        80/TCP    3m14s

Now we can invoke the spring boot service - note that this does not work from another machine

$ curl 10.107.146.119
<!DOCTYPE html>.....
$ curl 10.101.78.142  (does not work externally)

Get the environment for a particular Pod which will show the host and port that exposes this Pod through a Service.

$ kubectl get po
NAME                   READY   STATUS    RESTARTS   AGE
pod/springldap-nz8hx   1/1     Running   0          9s
pod/springldap-s2xjz   1/1     Running   0          9s
pod/springldap-t5r4d   1/1     Running   0          9s

$ kubectl exec springldap-nz8hx env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/jdk/bin
HOSTNAME=springldap-rkbfp
SPRINGLDAP_PORT_80_TCP_PORT=80                        
SPRINGLDAP_SERVICE_HOST=10.106.116.230                 <----
SPRINGLDAP_SERVICE_PORT=80                             <----
SPRINGLDAP_PORT_80_TCP=tcp://10.106.116.230:80
SPRINGLDAP_PORT_80_TCP_ADDR=10.106.116.230
KUBERNETES_SERVICE_HOST=10.96.0.1                      <----
KUBERNETES_SERVICE_PORT=443                            <----
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
SPRINGLDAP_PORT=tcp://10.106.116.230:80
SPRINGLDAP_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
JAVA_VERSION_MAJOR=8
JAVA_VERSION_MINOR=192
JAVA_VERSION_BUILD=12
JAVA_PACKAGE=server-jre
JAVA_JCE=standard
JAVA_HOME=/opt/jdk
GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
GLIBC_VERSION=2.28-r0
LANG=C.UTF-8
HOME=/root

Note that all services are available through environment variables. So if a mydatabase service is created, for example, that will be available through MYDATABASE_SERVICE_HOST and MYDATABASE_SERVICE_PORT

You cannot ping a Service IP because it is a virtual IP address and has no meaning without the port

$ curl 10.106.116.230
<!DOCTYPE html><html....

$ ping 10.106.116.230
PING 10.106.116.230 (10.106.116.230) 56(84) bytes of data.
^C
--- 10.106.116.230 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6131ms

Exposing the Service to External Clients

The Service can be exposed as a LoadBalancer, a NodePort or through an Ingress Service

NodePort

For a NodePort Service, each cluster node open a port on the node itself will redirect traffic received on that cluster node to the underlying Service. Then the Service is accessible through a dedicated port on all nodes. The NodePort values are from 30000 to 32768

apiVersion: v1
kind: Service
metadata:
  name: springldap-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 9090
    nodePort: 30090
  selector:
    app: springldap

Note that minikube only has a single node.

$ kubectl get -o wide nodes
NAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
minikube   Ready    master   88d   v1.13.3   192.168.0.21   <none>        Ubuntu 18.04.1 LTS   4.15.0-45-generic   docker://18.9.1

$ curl 192.168.0.21:30090
<!DOCTYPE html><html lang="en">....

$ kubectl get svc
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP        5d16h
springldap            ClusterIP   10.106.116.230   <none>        80/TCP         5d16h
springldap-nodeport   NodePort    10.110.130.36    <none>        80:30090/TCP   5m21s

$ curl 10.110.130.36
<!DOCTYPE html><html lang="en">....

The same would work for all Node IP addresses at port 30090

Configuration and Passwords through Kubernetes ConfigMaps and Secrets

Kubernetes allows configuration options to be separated out into ConfigMaps, simple maps with key value pairs in which the values can be literals to files, which the application does not need to be aware of. The contents of the map are made available to the containers as environment variables or as files in a volume.

Creating ConfigMap from a command line

$ kubectl create configmap spring-ldap-configmap --from-literal=database-name=MYDB

Creating ConfigMap from a file

$ kubectl create configmap spring-ldap-configmap --from-file=application.properties

Providing a ConfigMap entry to a Container

Single Entry As an Environment Variable

apiVersion: v1
kind: Pod
metadata:
  name: springldap-manual
spec:
  containers:
  - image: localhost:5000/dev/ramays/springldap
    env:                                          <----
    - name : INTERVAL                             <----
      valueFrom:                                  <----
        configMapKeyRef:                          <----
          name: spring-ldap-configmap             <----
          key: database-name                      <----
    name: springldap
    ports:
    - containerPort: 9090
      protocol: TCP

All entries as Environment Variables with a Prefix

The prefix is optional but useful for grouping config entries.

apiVersion: v1
kind: Pod
metadata:
  name: springldap-manual
spec:
  containers:
  - image: localhost:5000/dev/ramays/springldap
    envFrom:                                      <----
    - prefix: CONFIG_                             <----
      configMapRef:                               <----
        name: spring-ldap-configmap               <----
    name: springldap
    ports:
    - containerPort: 9090
      protocol: TCP

Create Secret from the Command Line

kubectl create secret generic spring-ldap-secret --from-literal=database-password=abc123

Using the Secret through an Environment Variable

    env:
    - name : DATABASE-PASSWORD
      valueFrom:
        configMapKeyRef:
          name: spring-ldap-secret
          key: database-password

Updating Your Application

Using Rolling Updates

This method is no longer recommended but is described here for completeness. In order to update a Replica Set from image v1 to image v2, you can use the kubectl rolling-update command. Let's say that you have an application with a Service (not shown) whose pods are created with the following ReplicaSet.

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
  name: springldap-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: springldap
  template:
    metadata:
      labels:
        app: springldap
    spec:
      containers:
      - name: springldap
        image: localhost:5000/dev/ramays/springldap:v1

If you want to update the image from v1 to v2 then run the following command.

$ kubectl rolling-update springldap-v1 springldap-v2 --image=localhost:5000/dev/ramays/springldap:v2

This command will create a new ReplicaSet that is a copy of the original ReplicaSet with the image updated. The command will then scale down the pods of the original ReplicaSet and scale up the pods of the new ReplicaSet until just the new ReplicaSet pods remain.

This approach is not recommended because it relies on the client to co-ordinate the change and not the server, and because it involves changing an existing ReplicaSet rather then creating and deploying a new one.

Using Deployments

A Deployment is a high level resource compared to ReplicaSets and Pods which are considered to be lower level resources. When you create a Deployment, a ReplicaSet is created which will create the Pods. So Deployments indirectly create Pods.

Official Kubernetes documentation recommends the use of Deployments over ReplicaSets directly.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springldap
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: springldap
    spec:
      containers:
      - name: springldap
        image: localhost:5000/dev/ramays/springldap
        ports:
        - containerPort: 9090
$ kubectl create -f springldap-deployment.yaml
$ kubectl get po,rs,deployment
NAME                              READY   STATUS    RESTARTS   AGE
pod/springldap-66886d747c-555xr   1/1     Running   0          5m16s
pod/springldap-66886d747c-bjcpv   1/1     Running   0          5m16s
pod/springldap-66886d747c-l2grh   1/1     Running   0          5m16s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.extensions/springldap-66886d747c   3         3         3       5m16s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/springldap   3/3     3            3           5m16s
$ kubectl rollout status deployment.extensions/springldap
deployment "springldap" successfully rolled out

Note that the deployment will not create a Service. You can create the Service using the sample above and it will connect to the Pods created by the Deployment by the label selector.

To trigger an update simply update the image in the deployment

$ kubectl set image deployment springldap springldap=localhost:5000/dev/ramays/springldap:v2

Note that the old ReplicaSet is stil there.

$ kubectl get po,rs,svc,deployment
NAME                              READY   STATUS    RESTARTS   AGE
pod/springldap-79587c76d7-hvlqk   1/1     Running   0          31s
pod/springldap-79587c76d7-lr5f4   1/1     Running   0          29s
pod/springldap-79587c76d7-tqgxv   1/1     Running   0          26s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.extensions/springldap-66886d747c   0         0         0       20m <-- OLD
replicaset.extensions/springldap-79587c76d7   3         3         3       31s <-- NEW

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   22m

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/springldap   3/3     3            3           20m

If there is an error with the new application, the rollout can be undone just as easily

$ kubectl rollout undo deployment springldap

About

Kubernetes Notes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published