DigitalOcean Kubernetes Challenge

DigitalOcean Kubernetes Challenge

My first step on Kubernetes

Year 2021 was most challenging for me, I attempted and I succeeded few tech challenges. I decided to do one final challenge of this year and that is DigitalOcean Kubernetes Challenge

This is my first step to learn Kubernetes

About this Challenge

Whether you’re new to Kubernetes, or you have been running production clusters for years, this challenge will give you an opportunity to level-up your Kubernetes skill set before the end of the year. This challenge is for everyone from beginner to export on K8s. There are four different challenges.

I choose Deploy an internal container registry

Choose your Challenge

New to Kubernetes? Try one of these challenges. You’ll get $60 in DigitalOcean credits for your project.

  • Deploy an internal container registry Kubernetes does not provide an internal container registry but it is often useful to add one. There are many projects which enable you to deploy an internal container registry, such as Harbour or Trow.
  • Deploy a log monitoring system So your applications produce logs. Lots of logs. How are you supposed to analyze them? A common solution is to aggregate and analyze them using the ELK stack, alongside fluentd or fluentbit.
  • Deploy a scalable SQL database cluster When deploying a database on Kubernetes, you have to make it redundant and scalable. You can rely on database management operators like KubeDB or database-specific solutions like Kubegres for PostgreSQL or the MySQL Operator for MySQL.
  • Deploy scalable NoSQL database cluster When it comes to cloud native, using No-SQL solutions has its advantages. You can deploy a cluster of MongoDB, Cassandra, or CouchDB instances to explore how to run a NoSQL database in Kubernetes.

Challenge run-book

Step 1: Install doctl - DigitalOcean CLI tool

Step: 2: Create a Kubernetes cluster

doctl kubernetes cluster create do-k8s-chlng

OUTPUT

PS C:\> doctl kubernetes cluster create do-k8s-chlng
Notice: Cluster is provisioning, waiting for cluster to be running
........................................................................
Notice: Cluster created, fetching credentials
Notice: Adding cluster credentials to kubeconfig file found in "C:\\Users\\Jagan/.kube/config"
Notice: Setting current-context to do-nyc1-do-k8s-chlng
ID                                      Name            Region    Version        Auto Upgrade    Status     Node Pools
66004701-3294-4599-b2eb-811f391efead    do-k8s-chlng    nyc1      1.21.5-do.0    false           running    do-k8s-chlng-default-pool

Step 3: Harbor installation steps

Our challenge starts here. I'm using Bitnami helm chart to deploy Harbor

Add bitnami repo to Helm

helm repo add bitnami https://charts.bitnami.com/bitnami

OUTPUT

PS C:\LAB\harbor> helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

Before installing helm chart we need to edit the yaml file, so create a yaml file

helm show values bitnami/harbor > harbor-values.yaml

open harbor-values.yaml in a editor

change the exterlname URL value to externalURL: https://hub.jagan-sekaran.me

set admin password harborAdminPassword: "<YOUR PASSWORD>" and commaonName commonName: 'hub.jagan-sekaran.me'

Install Harbor via helm

helm install harbor bitnami/harbor --values harbor-values.yaml -n harbor --create-namespace

OUTPUT

PS C:\LAB\harbor> helm install harbor bitnami/harbor --values harbor-values.yaml -n harbor --create-namespace
NAME: harbor
LAST DEPLOYED: Mon Dec 13 16:35:32 2021
NAMESPACE: harbor
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: harbor
CHART VERSION: 11.1.5
APP VERSION: 2.4.0

** Please be patient while the chart is being deployed **

1. Get the Harbor URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace harbor -w harbor'
  export SERVICE_IP=$(kubectl get svc --namespace harbor harbor --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo "Harbor URL: http://$SERVICE_IP/"

2. Login with the following credentials to see your Harbor application

  echo Username: "admin"
  echo Password: $(kubectl get secret --namespace harbor harbor-core-envvars -o jsonpath="{.data.HARBOR_ADMIN_PASSWORD}" | base64 --decode)

Check pods status - (everything is running now)

PS C:\LAB\harbor> kubectl get pod -n harbor
NAME                                    READY   STATUS    RESTARTS   AGE
harbor-chartmuseum-7fcffccd47-pftzv     1/1     Running   0          3m43s
harbor-core-85d8cf769d-8ngl6            0/1     Running   2          3m44s
harbor-jobservice-d79dc7b5b-4w5xt       0/1     Running   2          3m44s
harbor-nginx-8679695b9d-gs88w           1/1     Running   0          3m44s
harbor-notary-server-79bd9949d9-mk6l6   1/1     Running   0          3m44s
harbor-notary-signer-6f888ccbd-qr725    1/1     Running   0          3m43s
harbor-portal-58dfcc667d-jspp4          1/1     Running   0          3m43s
harbor-postgresql-0                     1/1     Running   0          3m43s
harbor-redis-master-0                   0/1     Pending   0          3m43s
harbor-registry-676f8ff5d6-lrz99        2/2     Running   0          3m44s
harbor-trivy-0                          0/1     Pending   0          3m43s

Get External-IP of Harbor LoadBalancer

PS C:\LAB\git_repos\DO-K8s-Challenge> kubectl get svc -n harbor
NAME                         TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                                     AGE  
harbor                       LoadBalancer   10.245.3.255     178.128.134.115   80:31632/TCP,443:32216/TCP,4443:30376/TCP   5m42s
harbor-chartmuseum           ClusterIP      10.245.86.36     <none>            80/TCP                                      5m42s
harbor-core                  ClusterIP      10.245.216.29    <none>            80/TCP                                      5m42s
harbor-jobservice            ClusterIP      10.245.169.149   <none>            80/TCP                                      5m42s
harbor-notary-server         ClusterIP      10.245.173.18    <none>            4443/TCP                                    5m42s
harbor-notary-signer         ClusterIP      10.245.101.201   <none>            7899/TCP                                    5m42s
harbor-portal                ClusterIP      10.245.168.69    <none>            80/TCP                                      5m42s
harbor-postgresql            ClusterIP      10.245.166.148   <none>            5432/TCP                                    5m42s
harbor-postgresql-headless   ClusterIP      None             <none>            5432/TCP                                    5m42s
harbor-redis-headless        ClusterIP      None             <none>            6379/TCP                                    5m42s
harbor-redis-master          ClusterIP      10.245.226.204   <none>            6379/TCP                                    5m42s
harbor-registry              ClusterIP      10.245.85.236    <none>            5000/TCP,8080/TCP                           5m42s
harbor-trivy                 ClusterIP      10.245.85.179    <none>            8080/TCP                                    5m42s

use the external IP to login to Harbor

  • UserName: admin
  • Password: (PASSWORD_entered_on_yaml)

Harbor Login

Create a new project and make it public, so pulling image doesn't need authentication.

Click new project

Create new project

Step 4: Push container to Harbor

Now lets try to push a container(httpd) image to Harbor

PS C:\LAB\harbor> docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
httpd        alpine    da799a8c8856   13 days ago   54.9MB

first we need to tag our container

docker tag httpd:alpine hub.jagan-sekaran.me/k8s/https:latest

OUTPUT

PS C:\LAB\harbor> docker tag httpd:alpine hub.jagan-sekaran.me/k8s/https:latest

PS C:\LAB\harbor> docker images
REPOSITORY                       TAG       IMAGE ID       CREATED       SIZE
httpd                            alpine    da799a8c8856   13 days ago   54.9MB
hub.jagan-sekaran.me/k8s/https   latest    da799a8c8856   13 days ago   54.9MB

Login to hub.jagan-sekaran.me on Docker

NOTE: if DNS is not resolved edit hosts file and add the IP of Harbor

docker login hub.jagan-sekaran.me

OUTPUT

PS C:\LAB\harbor> docker login hub.jagan-sekaran.me
Username: admin
Password: 
Login Succeeded

Now we can push our image to our hub

docker push hub.jagan-sekaran.me/k8s/https

OUTPUT (Successfully pushed)

PS C:\LAB\harbor> docker push hub.jagan-sekaran.me/k8s/https
Using default tag: latest
The push refers to repository [hub.jagan-sekaran.me/k8s/https]
96f5fd70e155: Pushed
af93ffae5924: Pushed
71a62b93fe7b: Pushed
fc8c77d3c450: Pushed
83efd5aabbd5: Pushed
8d3ac3489996: Pushed
latest: digest: sha256:452c02d860075a7ed16d443d9dfde61755d62d15bffb6492c4ba0d4022590052 size: 1572

Image available at Harbor

Image on Harbor

Step 5: Deploy the app

Lets deploy this app using httpd-deployemnt.yaml file

kubectl apply -f httpd-deployemnt.yaml

OUTPUT

PS C:\LAB\git_repos\DO-K8s-Challenge> kubectl apply -f httpd-deployemnt.yaml
service/httpd-service unchanged
deployment.apps/httpd-deployment created

PS C:\LAB\git_repos\DO-K8s-Challenge> kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
httpd-deployment-6559f66ffd-4pqlm   1/1     Running   0          9m58s

Finally we created our Kubernetes internal container registry (Harbor) and pushed our local image to container registry. Our K8s deployment was able to pull the image from Harbor and spin-up a pod successfully.