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 次

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

相关推荐
handler019 分钟前
Linux 内核剖析:进程优先级、上下文切换与 O(1) 调度算法
linux·运维·c语言·开发语言·c++·笔记·算法
lizhihai_9929 分钟前
股市学习心得-六张分时保命图
大数据·人工智能·学习
其实防守也摸鱼1 小时前
CTF密码学综合教学指南--第四章
网络·笔记·安全·网络安全·密码学·ctf
nashane1 小时前
HarmonyOS 6学习:应用签名文件丢失处理与更新完全指南
学习·华为·harmonyos·harmonyos 5
@codercjw1 小时前
公差的具体标注方法(书本上/理论上标注方法)
学习
久菜盒子工作室2 小时前
时寒冰:第五次产业大转移与未来30年国运:在“双向挤压”中实现惊险一跃
人工智能·学习
05候补工程师3 小时前
【ROS 2 具身智能】Gazebo 仿真避坑指南:从“幽灵机器人”到传感器数据流打通
人工智能·经验分享·笔记·ubuntu·机器人
chushiyunen3 小时前
pandas使用笔记、数据清洗、json_normalize
笔记·pandas
HERR_QQ3 小时前
端到端课程自用 4 规划 基于自规划AR的端到端规划 AI 笔记
人工智能·笔记·自动驾驶·transformer
Amazing_Cacao3 小时前
CFCA精品可可产区认证课程风土解析(美洲):打破风味堆叠的假象,建立时间轴上的层次展开阅读系统
学习