kubernetes学习笔记(7)- 部署一个微服务

前言

上篇文章 使用 kind 快速搭建集群中提到使用 kind 搭建好集群。

接下来写一个简单的微服务来进行验证,并尝试配置服务类型为 LoadBalancer 。

编写一个最简单的服务调用

在上篇文章中,编写了一个 b-serv 服务,它包含一个简单的/hello接口,并记录自己被调用的次数。本篇中它将作为微服务提供者(b-serv)而存在。

本次再添加一个 a-serv

它的代码同样很简单,如下:

go 复制代码
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	rootCount := 0
	tr := &http.Transport{
		MaxIdleConns:       10,
		IdleConnTimeout:    3 * time.Second, //3 秒超时
		DisableCompression: true,
	}
	client := &http.Client{Transport: tr}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		rootCount++
		fmt.Fprintf(w, "Hello! 我是 A 服务,我在集群中被调用了 %d 次\n", rootCount)
	})
	http.HandleFunc("/b", func(w http.ResponseWriter, r *http.Request) {
		resp, err := client.Get("http://b-serv/hello") // 远程调用 b-serv
		if err != nil {
			// 服务不可用
			log.Printf("b-serv 服务不可用:%s", err)
			fmt.Fprintln(w, "服务异常")
			return
		}
		defer resp.Body.Close()
		bytes, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Fprintf(w, "Some thing error: %s\n", err)
		}
		w.Write(bytes)
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}

代码也是相当的简单,a-serv 提供两个接口,分别是

  • / 接口, 记录自身被调用时长
  • /b 接口,远程调用 b-serv。具备最简单的服务降级。

Dockerfile 与 b-serv下的 Dockerfile 完全一致。

使用 docker 打包。docker build -t github.com/zidoshare/b-serv:0.0.1

使用 kind load docker-image github.com/zidoshare/b-serv:0.0.1 加载镜像到 node 中。

编写部署配置文件:demo.yaml

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: a-serv
  namespace: demo
spec:
  type: NodePort
  selector:
    app: a-serv
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: a-serv-deployment
  namespace: demo
  labels:
    app: a-serv
spec:
  replicas: 3
  selector:
    matchLabels:
      app: a-serv
  template:
    metadata:
      labels:
        app: a-serv
    spec:
      containers:
      - name: a-serv
        image: github.com/zidoshare/a-serv:0.0.1
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: b-serv
  namespace: demo
spec:
  selector:
    app: b-serv
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: b-serv-deployment
  namespace: demo
  labels:
    app: demo-serv
spec:
  replicas: 3
  selector:
    matchLabels:
      app: b-serv
  template:
    metadata:
      labels:
        app: b-serv
    spec:
      containers:
      - name: b-serv
        image: github.com/zidoshare/b-serv:0.0.1
        ports:
        - containerPort: 8080

两个微服务全部都部署 3 个实例。 通过 k8s 部署多个实例完全不需要太多的操作。

使用 kubectl apply -f demo.yaml 应用配置文件,进行部署。

使用 kubectl get pods -n demo 查看目前正在运行的pods:

text 复制代码
$ kubectl get pods -n demo
NAME                                 READY   STATUS    RESTARTS   AGE
a-serv-deployment-b4d787767-g8dtl    1/1     Running   0          107m
a-serv-deployment-b4d787767-q2xrf    1/1     Running   0          107m
a-serv-deployment-b4d787767-xfh74    1/1     Running   0          107m
b-serv-deployment-78556ddcc6-cszff   1/1     Running   0          107m
b-serv-deployment-78556ddcc6-qk9zz   1/1     Running   0          107m
b-serv-deployment-78556ddcc6-z7692   1/1     Running   0          106m

可以看到,应用已经按照预期运行。

查看服务:

shell 复制代码
$ kubectl get svc -n demo
NAME     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
a-serv   NodePort   10.96.129.146   <none>        80:30235/TCP   136m
b-serv   NodePort   10.96.75.216    <none>        80:31093/TCP   143m

此时 a 服务通过 NodePort 进行暴露,与之前访问 b-serv 一样,通过 node 的 internet ip 访问即可(具体怎么看,请参考上一篇):

shell 复制代码
$ curl http://172.18.0.4:30235/
Hello! 我是 A 服务,我在集群中被调用了 9 次
$ curl http://172.18.0.4:30235/b
B 服务就是我,我在集群中被调用了 8 次

分别验证了a-serva-serv 调用 b-serv。可以发现完全通了。

此时如果你使用 LoadBalancer 来暴露服务,通过 kubectl get svc -n demo 或发现externalIp 始终处于 pending 状态。这是因为我们还没有负载均衡实现。

通过 LoadBalancer 暴露微服务

通过 k8s 的文档可以知道, LoadBalancer 是由具体的云服务提供商来提供的,k8s并没有本地的实现。那么如何实现本地部署 LoadBanlancer 服务类型呢?此时,就需要 metallb 来提供了。

查看 metallb 官网。它是一个裸金 k8s 集群的负载均衡实现。也就是说,它可以实现本地的 loadBalancer 服务,而不需要云服务商提供。

通过 kind 文档发现,安装及其方便。

创建 metallb namespace

text 复制代码
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/master/manifests/namespace.yaml

创建 secret

text 复制代码
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

部署 metallb

text 复制代码
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/master/manifests/metallb.yaml

通过 kubectl get pods -n metallb-system 发现启动了两个pod:

shell 复制代码
$ kubectl get pods -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
controller-6dd9986f57-q2bkr   1/1     Running   0          155m
speaker-wt592                 1/1     Running   0          155m

要让 loadbalancer 暴露服务,首先我们需要有一个 Ip 地址池,用于 loadBanalcer 服务暴露,而这需要有 kind来分配,使用以下命令查看 kind分配的地址:

text 复制代码
$ docker network inspect -f '{{.IPAM.Config}}' kind
[{172.18.0.0/16  172.18.0.1 map[]} {fc00:f853:ccd:e793::/64   map[]}]

你会得到类似 172.18.0.0/16 这样的输出,每个人遇到的情况可能有所不同。

接下来我们为 metallb 选择一个范围。分配50的地址,应该足够了: 172.18.255.200 到 172.18.255.250。 编写配置metallb-configmap.yaml:

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.18.255.200-172.18.255.250

运行 kubectl apply -f metallb-configmap.yaml

做完简单的一切之后,我们尝试使用 loadBalancer。直接kubectl edit svc a-serv -n demo。找到 type: NodePort 直接修改为: type: LoadBalancer

查看服务列表:

shell 复制代码
$ kubectl get svc -n demo
NAME     TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
a-serv   LoadBalancer   10.96.129.146   172.18.255.200   80:30235/TCP   171m
b-serv   NodePort       10.96.75.216    <none>           80:31093/TCP   179m

此时有了 externalIp 。我们就可以直接访问该IP,从而访问a 服务啦。

shell 复制代码
$ curl http://172.18.255.200
Hello! 我是 A 服务,我在集群中被调用了 10 次
$ curl http://172.18.255.200
Hello! 我是 A 服务,我在集群中被调用了 6 次
$ curl http://172.18.255.200
Hello! 我是 A 服务,我在集群中被调用了 7 次

而且具有负载均衡的效果。

相关推荐
wan5555cn5 小时前
多张图片生成视频模型技术深度解析
人工智能·笔记·深度学习·算法·音视频
Broken Arrows6 小时前
Linux学习——管理网络安全(二十一)
linux·学习·web安全
今天也要学习吖6 小时前
谷歌nano banana官方Prompt模板发布,解锁六大图像生成风格
人工智能·学习·ai·prompt·nano banana·谷歌ai
雁于飞7 小时前
vscode中使用git、githup的基操
笔记·git·vscode·学习·elasticsearch·gitee·github
rannn_1117 小时前
【Javaweb学习|实训总结|Week1】html基础,CSS(选择器、常用样式、盒子模型、弹性盒布局、CSS定位、动画),js(基本类型、运算符典例)
css·笔记·学习·html
Ro Jace7 小时前
心灵笔记:第一性原理学习与实践
笔记
aramae8 小时前
C++ -- 模板
开发语言·c++·笔记·其他
wanzhong23339 小时前
ArcGIS学习-20 实战-地形研究
学习
wanzhong23339 小时前
ArcGIS学习-20 实战-县域水文分析
学习·arcgis