Bu örnekte iki bağımsız uygulama oluşturacağız ve her ikisi de kendi namespace alanlarında çalışacak. Namespace alanları, ana küme içindeki sanal kümeler gibidir. Esas olarak ilgili bileşen gruplarını izole etmek için kullanılırlar. Develop, qa, staging, sandbox, production gibi bir kümedeki her ortam için namespace alanlarını kullanabilirsiniz. Diğer bir yol, uygulama adlarını kullanmaktır. Bu örnekte, her şeyi görsel olarak bariz hale getirmek için ikisini de birleştireceğim. Bir namespace alanını silerseniz, içindeki tüm bileşenler de silinir. Namespace alanını arasında geçiş yapmak isterseniz kubectl config set-context --current --namespace={namespace} komutunu kullanabilirsiniz.


TCP server


Yapı


├── Makefile
├── deploy
│ └── k8s
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── namespace.yaml
│ └── service.yaml
├── docker
│ └── dev
│ └── Dockerfile
├── .env
└── main.go

Dosyalar


.env

TCP_HOST=0.0.0.0
TCP_PORT=8882

main.go

package main

import (
"log"
"net"
"net/http"
"os"

"github.com/joho/godotenv"
)

func main() {
_ = godotenv.Load()

lis, err := net.Listen("tcp", os.Getenv("TCP_HOST") + ":" + os.Getenv("TCP_PORT"))
if err != nil {
log.Fatalln(err)
}

rtr := http.NewServeMux()
rtr.HandleFunc("/teams", team)

if err := http.Serve(lis, rtr); err != nil && err != http.ErrServerClosed {
log.Fatalln(err)
}
}

func team(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte("Arsenal | Liverpool | Manchester United"))
}

Dockerfile


# STAGE 1: build
#
FROM golang:1.15-alpine3.12 as build

WORKDIR /source
COPY . .

RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o bin/main main.go

#
# STAGE 2: run
#
FROM alpine:3.12 as run

COPY --from=build /source/bin/main /main

ENTRYPOINT ["/main"]

Makefile

## Build application binary.
.PHONY: build
build:
go build -race -ldflags "-s -w" -o bin/main main.go

## Build application binary and run it.
.PHONY: run
run: build
bin/main

## Send a dummy request to the local server.
.PHONY: local-test
local-test:
curl --request GET http://localhost:8882/teams

## -------------------------------------------------------------

## Build, tag and push application image to registry then clean up.
.PHONY: push
push:
docker build -t you/football:latest -f ./docker/dev/Dockerfile .
docker push you/football:latest
docker rmi you/football:latest
docker system prune --volumes --force

## Deploy application to kubernetes cluster.
.PHONY: deploy
deploy:
kubectl apply -f deploy/k8s/namespace.yaml
kubectl apply -f deploy/k8s/configmap.yaml
kubectl apply -f deploy/k8s/deployment.yaml
kubectl apply -f deploy/k8s/service.yaml

## Send a dummy request to the exposed pod on kubernetes.
.PHONY: k8s-test
k8s-test:
curl --request GET $(shell minikube service football-service --url --namespace=football-develop-namespace)/teams

namespace.yaml

apiVersion: v1
kind: Namespace

metadata:
name: football-develop-namespace

configmap.yaml

apiVersion: v1
kind: ConfigMap

metadata:
name: football-configmap
namespace: football-develop-namespace

data:
TCP_HOST: 0.0.0.0
TCP_PORT: "8888"

deployment.yaml

apiVersion: apps/v1
kind: Deployment

metadata:
name: football-deployment
namespace: football-develop-namespace
labels:
app: football

spec:
replicas: 1
selector:
matchLabels:
app: football
template:
metadata:
labels:
app: football
spec:
containers:
- name: golang
image: you/football:latest
ports:
- containerPort: 8888
envFrom:
- configMapRef:
name: football-configmap

service.yaml

apiVersion: v1
kind: Service

metadata:
name: football-service
namespace: football-develop-namespace

spec:
type: NodePort
selector:
app: football
ports:
- protocol: TCP
port: 80
targetPort: 8888

HTTP server


Yapı


├── Makefile
├── deploy
│ └── k8s
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── namespace.yaml
│ └── service.yaml
├── docker
│ └── dev
│ └── Dockerfile
├── .env
└── main.go

Dosyalar


.env

HTTP_HOST=localhost
HTTP_PORT=8881

# You can use the K8S POD address here if you wish to test it against the actual K8S cluster.
# You can find out what it is by running `make k8s-test` command.
FOOTBALL_URL=http://localhost:8882

main.go

package main

import (
"io/ioutil"
"log"
"net/http"
"os"

"github.com/joho/godotenv"
)

func main() {
_ = godotenv.Load()

rtr := http.NewServeMux()
rtr.HandleFunc("/api/v1/teams", team)

if err := http.ListenAndServe(os.Getenv("HTTP_HOST") + ":" + os.Getenv("HTTP_PORT"), rtr); err != nil {
log.Fatalln(err)
}
}

func team(w http.ResponseWriter, _ *http.Request) {
req, err := http.NewRequest(http.MethodGet, os.Getenv("FOOTBALL_URL") + "/teams", nil)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("build request:" + err.Error()))
return
}

res, err := http.DefaultClient.Do(req)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("make request:" + err.Error()))
return
}
defer res.Body.Close()

bdy, err := ioutil.ReadAll(res.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("read body:" + err.Error()))
return
}

_, _ = w.Write([]byte(string(bdy)))
}

Dockerfile


# STAGE 1: build
#
FROM golang:1.15-alpine3.12 as build

WORKDIR /source
COPY . .

RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o bin/main main.go

#
# STAGE 2: run
#
FROM alpine:3.12 as run

COPY --from=build /source/bin/main /main

ENTRYPOINT ["/main"]

Makefile

## Build application binary.
.PHONY: build
build:
go build -race -ldflags "-s -w" -o bin/main main.go

## Build application binary and run it.
.PHONY: run
run: build
bin/main

## Send a dummy request to the local server.
.PHONY: local-test
local-test:
curl --request GET http://localhost:8881/api/v1/teams

## -------------------------------------------------------------

## Build, tag and push application image to registry then clean up.
.PHONY: push
push:
docker build -t you/api:latest -f ./docker/dev/Dockerfile .
docker push you/api:latest
docker rmi you/api:latest
docker system prune --volumes --force

## Deploy application to kubernetes cluster.
.PHONY: deploy
deploy:
kubectl apply -f deploy/k8s/namespace.yaml
kubectl apply -f deploy/k8s/configmap.yaml
kubectl apply -f deploy/k8s/deployment.yaml
kubectl apply -f deploy/k8s/service.yaml

## Send a dummy request to the exposed pod on kubernetes.
.PHONY: k8s-test
k8s-test:
curl --request GET $(shell minikube service api-service --url --namespace=api-develop-namespace)/api/v1/teams

namespace.yaml

apiVersion: v1
kind: Namespace

metadata:
name: api-develop-namespace

configmap.yaml

apiVersion: v1
kind: ConfigMap

metadata:
name: api-configmap
namespace: api-develop-namespace

data:
HTTP_HOST: 0.0.0.0
HTTP_PORT: "8888"
FOOTBALL_URL: http://football-service.football-develop-namespace

deployment.yaml

apiVersion: apps/v1
kind: Deployment

metadata:
name: api-deployment
namespace: api-develop-namespace
labels:
app: api

spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: golang
image: you/api:latest
ports:
- containerPort: 8888
envFrom:
- configMapRef:
name: api-configmap

service.yaml

apiVersion: v1
kind: Service

metadata:
name: api-service
namespace: api-develop-namespace

spec:
type: NodePort
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 8888

Test


Önce make publish ve make deploy komutları ile imajları aktarmanız ve ardından dağıtmanız gerekir.


TCP server


$ make k8s-test
curl --request GET http://192.168.99.100:32630/teams
Arsenal | Liverpool | Manchester United

HTTP server


$ make k8s-test
curl --request GET http://192.168.99.100:31233/api/v1/teams
Arsenal | Liverpool | Manchester United