Kubernetes for Developers

Revisión 2022

Why a cluster?

The container

The container

The container

The application (codes)
The runtime environment (service)

a single immutable image that contains everything needed to run an application

The container

The application (codes)
The runtime environment (service)

The container
running

A storage

A network

Server

docker run myapp1

myapp1

development environment

Server

docker run -p 443:80 loadbalancer
docker run myapp1
docker run myapp2

myapp1

myapp2

loadbalancer

production environment
(simple)

Server

docker compose up

myapp1

myapp2

loadbalancer

production environment
(complex)

myapi

database

version: '3'

services:

  loadbalancer:
    image: loadbalancer
        
  myapp:
    image: myapp
    deploy:
      replicas: 2

  myapi:
    image: myapi

  database:
    image: mysql
docker compose up
docker compose up
docker compose up

production environment
(complex
with success)

production environment
ERROR

ssh server
docker ps
docker compose up
docker compose up
docker compose up

Complexity + Success

container orchestrator knows the cluster

container orchestrator monitors and alters

container orchestrator solves the issues

Complex and successful environments

require monitoring, alerting and react to solve issues,
a
CONTAINER ORCHESTRATOR

docker docker compose kubernetes
1-2 nodes
dev environments
speed deploy
1-5 nodes
complex environments
repeated deploy
fixed size
no time to kubernetes
+3 nodes
complex environments
dynamic deploy
flexible resize
always need to learn

Kubernetes
cluster architecture

Kubernetes

cluster

master

node

node

worker
(minion)

worker
(minion)

Kubernetes architecture

node

master

kubectl
(cli)

dashboard
(ui)

REST client
(code)

kubelet

API
server

Scheduller

etcd

Controller
Manager

kube-proxy

Pod

Pod

Pod

Kubernetes
history & ecosystem

Historia de Kubernetes

Junio
2014

Julio
2014

Julio
2015

Marzo
2018

Commit inicial en GitHub (Google) k8s - Go

Microsoft, RedHat, IBM y Docker

Kubernetes v1.0

Nov
2015

Primer KubeCon

Feb
2016

Helm Package Manager

CNCF Certified

Kubernetes ecosytem

Curva de aprendizaje de Kubernetes

kubectl client

Instalación de kubernetes (dev)

brew install kubernetes-cli

Dev's clusters:

  • Docker Desktop
  • Rancher Desktop
  • minikube
  • kind
  • k3s

A single executable file that allows you to interact with the Kubernetes API using a command-line interface (CLI)

kubectl

kubectl version
Client Version: version.Info{Major:"1", Minor:"25",
Kustomize Version: v4.5.7
Server Version: version.Info{Major:"1", Minor:"25", 

kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:51076
CoreDNS is running at https://127.0.0.1:51076/api/v1/namespaces/kube-system

kubeconfig

  • $HOME/.kube/config <== file
  • --kubeconfig       <== options
  • export KUBECONFIG  <== environment

kubectl contexts

$ kubectl config get-contexts
CURRENT   NAME
          arn:aws:eks:us-east-1:040552251222:cluster/eksworkshop-eksctl
          arn:aws:eks:us-east-1:037282212900:cluster/sre
          docker-desktop
*         kind-ws-mooveit
          tp.w.uy

a context is an entity defined inside kubeconfig to alias cluster parameters with a human-readable name.
Kubernetes context only applies to the client side.

Kubernetes resources & manifests

❯ git clone git@github.com:moove-it/k8s-workshop.git

Namespace

  • additional property of each resource
  • logical isolation (virtual cluster)
  • teams spaces
  • environments
# kubectl apply -f namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace

Namespace

# kubectl apply -f namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
❯ kubectl create namespace test
namespace/test created

❯ kubectl get namespace
NAME                 STATUS   AGE
test                 Active   10s

❯ kubectl delete namespace test
namespace "test" deleted
❯ kubectl apply -f namespace.yaml
namespace/my-namespace created

❯ kubectl get namespaces
NAME                 STATUS   AGE
my-namespace         Active   32s

❯ kubectl delete -f namespace.yaml
namespace "my-namespace" deleted

imperative:

declarative:

with a yaml manifest

Pod

  • Refers to 1 or more containers
  • share storage
  • share network:
    • IP address
    • port ranges
# kubectl apply -f hostname-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hostname-pod-example
spec:
  containers:
    - name: hostname
      image: oguzpastirmaci/hostname

Pod

❯ kubectl apply -f hostname-pod.yaml -n my-namespace
pod/hostname-pod-example created

❯ kubectl get pods -n my-namespace
NAME                   READY   STATUS    RESTARTS   AGE
hostname-pod-example   1/1     Running   0          19s

❯ kubectl describe pod -n my-namespace hostname-pod-example
Name:             hostname-pod-example
Namespace:        my-namespace
Priority:         0
Service Account:  default
Node:             ws-mooveit-control-plane/172.18.0.2

❯ kubectl get all -n my-namespace
NAME                       READY   STATUS    RESTARTS   AGE
pod/hostname-pod-example   1/1     Running   0          2m40s

ReplicaSet

  • Scalability
  • High-availability
  • Starts pods at different worker nodes
# kubectl apply -f hostname-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: hostname-rs-example
  labels:
    name: hostname
spec:
  replicas: 3
  selector:
    matchLabels:
      name: hostname
  template:
      metadata:
        name: hostname-pod-example
        labels:
          name: hostname
          language: golang
      spec:
        containers:
          - name: hostname
            image: oguzpastirmaci/hostname

ReplicaSet

❯ kubectl apply -f hostname-replicaset.yaml -n my-namespace
replicaset.apps/hostname-rs-example created

❯ kubectl get all -n my-namespace
NAME                            READY   STATUS    RESTARTS   AGE
pod/hostname-pod-example        1/1     Running   0          3m52s
pod/hostname-rs-example-7k94n   1/1     Running   0          14s
pod/hostname-rs-example-j82pv   1/1     Running   0          14s
pod/hostname-rs-example-l2nqb   1/1     Running   0          14s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/hostname-rs-example   3         3         3       14s

❯ kubectl delete -f ws-02-hostname-pod.yaml -n my-namespace
pod "hostname-pod-example" deleted

❯ kubectl delete pod/hostname-rs-example-7k94n -n my-namespace
pod "hostname-rs-example-7k94n" deleted

❯ kubectl get all -n my-namespace
NAME                            READY   STATUS    RESTARTS   AGE
pod/hostname-rs-example-5ppll   1/1     Running   0          15s
pod/hostname-rs-example-j82pv   1/1     Running   0          2m13s
pod/hostname-rs-example-l2nqb   1/1     Running   0          2m13s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/hostname-rs-example   3         3         3       2m14s

Deployment

  • Updates ReplicaSet
  • Manage versions
  • Roll-back
# kubectl apply -f hostname-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-example-1
  labels:
    name: example-1
spec:
  replicas: 5
  selector:
    matchLabels:
      name: hostname
  strategy:
    type: RollingUpdate
  template:
      metadata:
        name: hostname-pod-example
        labels:
          name: hostname
          language: golang
      spec:
        containers:
          - name: hostname
            image: oguzpastirmaci/hostname

Deployment

Applications are seeing as
Deployments

# kubectl apply -f hostname-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-example-1
  labels:
    name: example-1
spec:
  replicas: 5
  selector:
    matchLabels:
      name: hostname
  strategy:
    type: RollingUpdate
  template:
      metadata:
        name: hostname-pod-example
        labels:
          name: hostname
          language: golang
      spec:
        containers:
          - name: hostname
            image: oguzpastirmaci/hostname

Deployment

❯ kubectl apply -f hostname-deployment.yaml -n my-namespace
deployment.apps/deploy-example-1 created

❯ kubectl get all -n my-namespace
NAME                            READY   STATUS    RESTARTS   AGE
pod/hostname-rs-example-5ppll   1/1     Running   0          13m
pod/hostname-rs-example-5vbv7   1/1     Running   0          23s
pod/hostname-rs-example-dqrbt   1/1     Running   0          23s
pod/hostname-rs-example-j82pv   1/1     Running   0          15m
pod/hostname-rs-example-l2nqb   1/1     Running   0          15m

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-example-1   5/5     5            5           23s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/hostname-rs-example   5         5         5       15m

❯ kubectl describe -n my-namespace deployments.apps/deploy-example-1
Name:                   deploy-example-1
Namespace:              my-namespace
CreationTimestamp:      Wed, 07 Sep 2022 16:08:28 -0300
Labels:                 name=example-1
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               name=hostname
Replicas:               5 desired | 5 updated | 5 total | 5 available 
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge

Service

  • IP -> Pods
  • Creates EndPoint
  • Types
  • It is not a loadbalancer
# kubectl apply -f hostname-service.yml
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
  labels:
    app: hostname
spec:
  type: ClusterIP
  selector:
    name: hostname
  ports:
  - port: 9999
    protocol: TCP
    targetPort: 8000

Service

❯ kubectl apply -f hostname-service.yaml -n my-namespace
service/hostname-svc created

❯ kubectl get all -n my-namespace
NAME                            READY   STATUS    RESTARTS   AGE
pod/hostname-rs-example-5ppll   1/1     Running   0          24m
pod/hostname-rs-example-5vbv7   1/1     Running   0          11m
pod/hostname-rs-example-dqrbt   1/1     Running   0          11m
pod/hostname-rs-example-j82pv   1/1     Running   0          25m
pod/hostname-rs-example-l2nqb   1/1     Running   0          25m

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/hostname-svc   ClusterIP   10.96.129.198   <none>        9999/TCP   31s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-example-1   5/5     5            5           11m

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/hostname-rs-example   5         5         5       25m

❯ kubectl describe svc hostname-svc -n my-namespace
Name:              hostname-svc
Namespace:         my-namespace
IP:                10.96.129.198
IPs:               10.96.129.198
Port:              <unset>  9999/TCP
TargetPort:        3000/TCP

How to access (as developer)

# kubectl apply -f hostname-service.yml
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
  labels:
    app: hostname
spec:
  type: ClusterIP
  selector:
    name: hostname
  ports:
  - port: 9999
    protocol: TCP
    targetPort: 8000

Endpoint is internal.
Two connection options:

  1. A pod
  2. Enable port-forward (dev)

How to access (with pod)

❯ kubectl run -n my-namespace nginx --image=nginx
pod/nginx created

❯ kubectl exec -n my-namespace nginx -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
HOSTNAME_SVC_SERVICE_PORT=9999
KUBERNETES_SERVICE_HOST=10.96.0.1
HOSTNAME_SVC_SERVICE_HOST=10.96.129.198

❯ kubectl exec -n my-namespace -it nginx -- bash
root@nginx:/#

❯ kubectl exec -n my-namespace -it nginx -- bash
root@nginx:/# curl $HOSTNAME_SVC_SERVICE_HOST:$HOSTNAME_SVC_SERVICE_PORT
<!DOCTYPE html><html><head><title>Hello!</title><link rel="stylesheet" 
href="http://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head><body><div class="container"><div class="jumbotron">
<h1>This page was served by: deploy-example-1-6cf5b4fdf9-985nw</h1></div>
</div></body></html>
root@nginx:/#

How to access (port-forward)

❯ kubectl port-forward -n my-namespace services/hostname-svc 8882:9999
Forwarding from 127.0.0.1:8882 -> 9999
Forwarding from [::1]:8882 -> 9999
Handling connection for 8882

# Browser connect to 
#
#  http://localhost:8888
#

Ingress (prod)







apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hostname-ing
  labels:
    name: hostname
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - path: /hostname(/|$)(.*)
        backend:
          serviceName: hostname-svc
          servicePort: 9999
  • Additional controller
  • Provides SSL / LB
  • Rules (path)
  • Links EndPoint

Local kubernetes
vs
Cloud kubernetes

EC2

worker nodes

loadbalancers

launch configurations

ECR
registry

Route53
DNS

control plane

VPC
networking

IAM
roles
permissions

KMS
key store

Certificate Manager

SSL/TLS certificates

kubernetes
CD
pipeline

git push
docker build
docker build
docker push
kubectl apply -f deploy.yaml

... a seguir

poner en container las apps

TODAS !

SRE Team puede colaborar