Kubernetes中的跨命名空间通信

106 阅读2分钟

在这个例子中,我们将创建两个独立的应用程序,它们都将在各自的命名空间中运行。命名空间就像主集群中的虚拟集群。它们主要用于隔离相关组件组。你可以为集群中的每个环境使用命名空间,如开发、QA、暂存、沙盒、生产。另一种方法是使用应用程序名称。在这个例子中,我打算把这两种方法结合起来,以使事情在视觉上明显。如果你删除一个命名空间,里面的所有组件也会被删除。你可以使用kubectl config set-context --current --namespace={namespace} 命令来切换命名空间。

TCP服务器

结构

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

文件

.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"))
}
Docker文件
# 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"]
制作文件
## 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"
部署.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服务器

结构

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

文件

.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)))
}
Docker文件

# 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"]
制作文件
## 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
部署.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

测试

首先你需要推送你的服务镜像,然后用make publishmake deploy 命令进行部署。

TCP服务器

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

HTTP服务器

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