Github: https://github.com/blazingraptor/getting-started-k8s.git
Docker Hub: https://hub.docker.com/repository/docker/blazingraptor/getting-started-k8s/general
Clone the repo
blazingraptor@galactica:~/docker/scale-example$ git clone https://github.com/blazingraptor/getting-started-k8s.git Cloning into 'getting-started-k8s'... remote: Enumerating objects: 102, done. remote: Counting objects: 100% (37/37), done. remote: Compressing objects: 100% (27/27), done. remote: Total 102 (delta 16), reused 10 (delta 10), pack-reused 65 (from 1) Receiving objects: 100% (102/102), 71.75 KiB | 1.84 MiB/s, done. Resolving deltas: 100% (33/33), done.
Apply the LoadBalancer
blazingraptor@galactica:~/docker/getting-started-k8s$ cd Services/ blazingraptor@galactica:~/docker/getting-started-k8s/Services$ kubectl apply -f svc-lb.yml service/ps-lb created
Now the LoadBalancer is running
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Services$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 211d ps-lb LoadBalancer 10.107.92.89 localhost 80:31789/TCP 52s
Apply deployment
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl apply -f deploy.yml deployment.apps/web-deploy created
See replicas
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get pods NAME READY STATUS RESTARTS AGE web-deploy-55bdf4c5d5-2vt78 1/1 Running 0 20m web-deploy-55bdf4c5d5-k92lh 1/1 Running 0 20m web-deploy-55bdf4c5d5-n5kgp 1/1 Running 0 20m web-deploy-55bdf4c5d5-r7fzx 1/1 Running 0 20m web-deploy-55bdf4c5d5-xxgrk 1/1 Running 0 20m
Deployments are API resources
Inspect them
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE web-deploy 5/5 5 5 39m blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get deployments.apps NAME READY UP-TO-DATE AVAILABLE AGE web-deploy 5/5 5 5 39m
Get Replica Sets
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get rs NAME DESIRED CURRENT READY AGE web-deploy-55bdf4c5d5 5 5 5 47m blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get replicasets.apps NAME DESIRED CURRENT READY AGE web-deploy-55bdf4c5d5 5 5 5 47m
See the file that set the replica sets
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ cat deploy.yml;echo # Simple deployment used to deploy and manage the app in nigelpoulton/getting-started-k8s:1.0 apiVersion: apps/v1 kind: Deployment metadata: name: web-deploy labels: app: web spec: replicas: 5 selector: matchLabels: app: web template: metadata: labels: app: web spec: terminationGracePeriodSeconds: 1 containers: - name: hello-pod image: nigelpoulton/getting-started-k8s:1.0 imagePullPolicy: Always ports: - containerPort: 8080
Hash is based on this
We have 5 pods running. To connect to them, we need a service...
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d ps-lb LoadBalancer 10.99.228.61 localhost 80:31787/TCP 58m ps-nodeport NodePort 10.100.201.228 <none> 80:31111/TCP 40h
It's actually this
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get services | grep ps-lb ps-lb LoadBalancer 10.99.228.61 localhost 80:31789/TCP 58m
Describe it
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl describe services ps-lb Name: ps-lb Namespace: default Labels: <none> Annotations: <none> Selector: app=web Type: LoadBalancer IP Family Policy: SingleStack IP Families: IPv4 IP: 10.99.228.61 IPs: 10.99.228.61 LoadBalancer Ingress: localhost Port: <unset> 80/TCP TargetPort: 8080/TCP NodePort: <unset> 31787/TCP Endpoints: 10.1.0.19:8080,10.1.0.20:8080,10.1.0.21:8080 + 2 more... Session Affinity: None External Traffic Policy: Cluster Events: <none>
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl describe services ps-lb | grep Selector Selector: app=web
* Says send traffic to all pods in the cluster with the "app=web" label
Check label on the 5 replicas we have running
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS web-deploy-55bdf4c5d5-252qn 1/1 Running 0 55m app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-czcfc 1/1 Running 0 55m app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-hj65t 1/1 Running 0 55m app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-pjr6w 1/1 Running 0 55m app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-t95hq 1/1 Running 0 55m app=web,pod-template-hash=55bdf4c5d5
Same label here as well
Labels are dynamic
See the endpoints
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl get endpoints ps-lb NAME ENDPOINTS AGE ps-lb 10.1.0.19:8080,10.1.0.20:8080,10.1.0.21:8080 + 2 more... 80m
Describe endpoints
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl describe endpoints ps-lb Name: ps-lb Namespace: default Labels: <none> Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2024-06-01T18:01:13Z Subsets: Addresses: 10.1.0.19,10.1.0.20,10.1.0.21,10.1.0.22,10.1.0.23 NotReadyAddresses: <none> Ports: Name Port Protocol ---- ---- -------- <unset> 8080 TCP Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedToUpdateEndpoint 60m endpoint-controller Failed to update endpoint default/ps-lb: Operation cannot be fulfilled on endpoints "ps-lb": the object has been modified; please apply your changes to the latest version and try again
The fix
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl apply -f deploy.yml deployment.apps/web-deploy unchanged blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl describe endpoints ps-lb Name: ps-lb Namespace: default Labels: <none> Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2024-06-01T18:01:13Z Subsets: Addresses: 10.1.0.19,10.1.0.20,10.1.0.21,10.1.0.22,10.1.0.23 NotReadyAddresses: <none> Ports: Name Port Protocol ---- ---- -------- <unset> 8080 TCP Events: <none>
Get the public IP
blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d ps-lb LoadBalancer 10.99.228.61 localhost 80:31787/TCP 92m ps-nodeport NodePort 10.100.201.228 <none> 80:31111/TCP 40h blazingraptor@galactica:~/docker/getting-started-k8s/Deployments$ kubectl get services | grep ps-lb ps-lb LoadBalancer 10.99.228.61 localhost 80:31787/TCP 93m
localhost
Turn off Windows Firewall
I can load
172.16.0.12:31111
from ironman6 in Firefox
That means, I can port forward it to my router and visit it from any computer in the World.
Scale Up
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ grep replicas deploy.yml replicas: 5 blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ vim deploy.yml blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ grep replicas deploy.yml replicas: 7 blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl apply -f deploy.yml deployment.apps/web-deploy configured blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS web-deploy-55bdf4c5d5-2vt78 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-6s57x 1/1 Running 0 7s app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-k92lh 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-n5kgp 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-r7fzx 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-sjvxr 1/1 Running 0 7s app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-xxgrk 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5
Scale Down
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ grep replicas deploy.yml replicas: 7 blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ vim deploy.yml blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ grep replicas deploy.yml replicas: 4 blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl apply -f deploy.yml deployment.apps/web-deploy configured blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS web-deploy-55bdf4c5d5-2vt78 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-k92lh 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-n5kgp 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5 web-deploy-55bdf4c5d5-r7fzx 1/1 Running 0 6d2h app=web,pod-template-hash=55bdf4c5d5
Retag it
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ docker tag nigelpoulton/getting-started-k8s:1.0 blazingraptor/getting-started-k8s:1.0
See the image
blazingraptor@galactica:~$ docker images | grep blazingraptor | grep -E '(getting-started-k8s)' blazingraptor/getting-started-k8s 1.0 dc81d8418e19 21 months ago 263MB
Push the image
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s/Deployments$ docker push blazingraptor/getting-started-k8s:1.0 The push refers to repository [docker.io/blazingraptor/getting-started-k8s] 12ea4114bca0: Mounted from nigelpoulton/getting-started-k8s 5489c358f90b: Mounted from nigelpoulton/getting-started-k8s 70a5915a62dd: Mounted from nigelpoulton/getting-started-k8s de6bcbc6ed42: Mounted from nigelpoulton/getting-started-k8s daed7950b4bd: Mounted from nigelpoulton/getting-started-k8s 6f7801354ad0: Mounted from nigelpoulton/getting-started-k8s ac4d164fef90: Mounted from nigelpoulton/getting-started-k8s 1.0: digest: sha256:259aca2f1c980dd44e77e84ee686c7bff59c030f1d08a0b99609e072cad3c5c0 size: 1787
Prepare to delete the cluster (see it)
blazingraptor@galactica:~/docker/mysql-repl-k8s$ kubectl describe deployment web-deploy Name: web-deploy Namespace: default CreationTimestamp: Sat, 15 Feb 2025 11:47:59 -0500 Labels: app=web Annotations: deployment.kubernetes.io/revision: 1 Selector: app=web Replicas: 4 desired | 4 updated | 4 total | 4 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=web Containers: hello-pod: Image: nigelpoulton/getting-started-k8s:1.0 Port: 8080/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Node-Selectors: <none> Tolerations: <none> Conditions: Type Status Reason ---- ------ ------ Progressing True NewReplicaSetAvailable Available True MinimumReplicasAvailable OldReplicaSets: <none> NewReplicaSet: web-deploy-55bdf4c5d5 (4/4 replicas created) Events: <none>
Delete the cluster
blazingraptor@galactica:~/docker/scale-example/getting-started-k8s$ kubectl delete all -l app=web pod "web-deploy-55bdf4c5d5-2vt78" deleted pod "web-deploy-55bdf4c5d5-k92lh" deleted pod "web-deploy-55bdf4c5d5-n5kgp" deleted pod "web-deploy-55bdf4c5d5-r7fzx" deleted deployment.apps "web-deploy" deleted replicaset.apps "web-deploy-55bdf4c5d5" deleted