diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..88ea017 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..7bca064 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,43 @@ +name: build +on: + workflow_dispatch: + push: + pull_request: + schedule: + # every day at 6am & 6pm pacific + - cron: "0 1,13 * * *" +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: azure/setup-kubectl@901a10e89ea615cf61f57ac05cecdf23e7de06d8 + - uses: medyagh/setup-minikube@latest + - name: install tools for mac os + if: matrix.os == 'macos-12' + shell: bash + run: | + brew install docker-machine docker + sudo docker --version + sysctl hw.physicalcpu hw.logicalcpu + sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off + sudo /usr/libexec/ApplicationFirewall/socketfilterfw -k + + - name: Build Docker images inside minikube + run: | + eval $(minikube docker-env) + cd minikube + docker build -t local/devex:v1 . + - name: Deploy to to Kubernetes + run: | + kubectl apply -f minikube/deploy/k8s.yaml + - name: Verify Deployment + run: | + minikube service list + minikube service local-devex-svc --url --wait=10 + kubectl get pods -A + kubectl wait --for=condition=ready pod -l app=local-devex + curl -vvv $(minikube service local-devex-svc --url) diff --git a/minikube/.gitignore b/minikube/.gitignore new file mode 100644 index 0000000..ab59273 --- /dev/null +++ b/minikube/.gitignore @@ -0,0 +1,2 @@ +local-dev-example-with-minikube +.DS_Store \ No newline at end of file diff --git a/minikube/Dockerfile b/minikube/Dockerfile new file mode 100644 index 0000000..2b4dd13 --- /dev/null +++ b/minikube/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:alpine + +# Set the Current Working Directory inside the container +WORKDIR $GOPATH/src/github.com/medyagh/local-dev-example-with-minikube/ + +# Copy everything from the current directory to the PWD (Present Working Directory) inside the container +COPY . . + +# Install the package +RUN go install -v ./... + +# This container exposes port 8080 to the outside world +EXPOSE 8080 + +# Run the executable +CMD ["local-dev-example-with-minikube"] \ No newline at end of file diff --git a/minikube/README.md b/minikube/README.md index e69de29..5aa0d6c 100644 --- a/minikube/README.md +++ b/minikube/README.md @@ -0,0 +1,87 @@ +# local-dev-example-with-minikube + + +This repo demos a simple go app being deployed to a Kubernetes cluster using minikube, and demonstrates changing the code and re-deploying a new version. + + +## Requirements +- Clone this repo! +- Install [minikube](https://minikube.sigs.k8s.io/docs/start/) +- Install [Docker CLI](https://minikube.sigs.k8s.io/docs/tutorials/docker_desktop_replacement/) (Docker Desktop is not required, Docker CLI is sufficent) + + +## Build and deploy the app to minikube for the first time! + +1. Start minikube + ```console + minikube start + ``` + +2. Point your terminal to minikube's Docker using `minikube docker-env` + ```console + # on Mac or Linux + eval $(minikube docker-env) + ``` + + ```console + # on Windows PowerShell + & minikube docker-env | Invoke-Expression + ``` + + Tip 1: if you close your terminal you will have to re-point your docker-env. + + Tip 2: to verify that your terminal is pointing to minikube's Docker you can run `minikube status` and it will show "docker-env: in-use" + +4. Build Docker image inside minikube + + ```console + docker build -t local/devex:v1 . + ``` +4. Deploy to Kubernetes + ```console + kubectl apply -f deploy/k8s.yaml + ``` +5. Accees the deployed service in your browser + ```console + minikube service local-devex-svc + ``` + Tip: you can try `$ minikube service list` to see all exposed serivces. + + +## Iterative development (how to redeploy after a code change) + +1. Make a change in the code (for example bump the version in `main.go`) +2. Ensure you're still pointing to minikube's Docker using `minikube docker-env`) +3. Delete the deployment and the image + ```console + kubectl delete -f deploy/k8s.yaml + docker rmi local/devex:v1 + ``` +4. Rebuild the image and re-deploy to Kubernetes + ```console + docker build -t local/devex:v1 . + kubectl apply -f deploy/k8s.yaml + ``` +5. Access the deployed service in your browser + ```console + minikube service local-devex-svc + ``` + +(for faster development you can combine steps 3 and 4 the commands in one) +``` +kubectl delete -f deploy/k8s.yaml;docker rmi local/devex:v1;docker build -t local/devex:v1 .;kubectl apply -f deploy/k8s.yaml +``` + + +### Mount Files to minikube (persistent storage example) + +- let's create a example file on our workstation (laptop) to share with our deployment in minikube +```console +mkdir -p ~/Desktop/local-devex +echo "Hello from laptop" > ~/Desktop/local-devex/hello-world.text +``` + +in a separate window run: +```console + minikube mount ~/Desktop/local-devex:/data/ +``` diff --git a/minikube/deploy/k8s.yaml b/minikube/deploy/k8s.yaml new file mode 100644 index 0000000..32b9f5e --- /dev/null +++ b/minikube/deploy/k8s.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: local-devex-deploy + labels: + app: local-devex +spec: + replicas: 1 + selector: + matchLabels: + app: local-devex + template: + metadata: + labels: + app: local-devex + spec: + containers: + - name: app + image: local/devex:v1 + ports: + - containerPort: 8080 + volumeMounts: + - mountPath: /data + name: test-volume + volumes: + - name: test-volume + hostPath: + # directory location on host + path: /data +--- +apiVersion: v1 +kind: Service +metadata: + name: local-devex-svc +spec: + type: NodePort + selector: + app: local-devex + ports: + - name: local-devex-port + protocol: TCP + port: 8080 + targetPort: 8080 \ No newline at end of file diff --git a/minikube/go.mod b/minikube/go.mod new file mode 100644 index 0000000..cf6c4f3 --- /dev/null +++ b/minikube/go.mod @@ -0,0 +1,3 @@ +module local-dev-example-with-minikube + +go 1.19 diff --git a/minikube/k8s.yaml b/minikube/k8s.yaml new file mode 100644 index 0000000..32b9f5e --- /dev/null +++ b/minikube/k8s.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: local-devex-deploy + labels: + app: local-devex +spec: + replicas: 1 + selector: + matchLabels: + app: local-devex + template: + metadata: + labels: + app: local-devex + spec: + containers: + - name: app + image: local/devex:v1 + ports: + - containerPort: 8080 + volumeMounts: + - mountPath: /data + name: test-volume + volumes: + - name: test-volume + hostPath: + # directory location on host + path: /data +--- +apiVersion: v1 +kind: Service +metadata: + name: local-devex-svc +spec: + type: NodePort + selector: + app: local-devex + ports: + - name: local-devex-port + protocol: TCP + port: 8080 + targetPort: 8080 \ No newline at end of file diff --git a/minikube/main.go b/minikube/main.go new file mode 100644 index 0000000..6d8d8f8 --- /dev/null +++ b/minikube/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "time" +) + +var version = "0.0.2" + +func indexHandler(w http.ResponseWriter, req *http.Request) { + localFile, err := os.ReadFile("/data/hello-world.txt") + if err != nil { + fmt.Printf("couldn't read file %v\n", err) + + } + fmt.Fprintf(w, "