helm 部署并配置

helm 部署并配置

helm 部署

之前都是编辑一大堆 yaml 文件来部署服务到 k8s,什么 dployment, service, ingress 这些都得写,太麻烦了所以现在改造一下用 helm来管理 k8s 的依赖管理

首先创建一个 chart

1
helm create xxx


简单解释下里面的文件夹都是啥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
xxx
├─.helmignore
├─Chart.yaml # 创建的chart 一些信息
├─values.yaml # tempalet 里面需要的一些值
├─templates # 一些k8s中的模版 ingress,service,deployment 最主要用到的可能就这三个
| ├─NOTES.txt
| ├─_helpers.tpl
| ├─deployment.yaml
| ├─hpa.yaml
| ├─ingress.yaml
| ├─service.yaml
| ├─serviceaccount.yaml
| ├─tests
| | └test-connection.yaml
├─charts

那我们就留 deployment 和 service 两个模版由于我是用的是 k3s 里面的流量控制器不是 nginx 而是 traefik,所以我们用 crd 编辑一下,再把 deployment 里面不需要用到的删了,就跟配置 k8s 的 yaml 一样,如果不会的话最好看看 k8s 小编也不太精通还只是到会用的层面 QAQ ~
ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-ingress
spec:
entryPoints:
- web
routes:
- match: Host(`{{ .Values.ingress.host }}`) && PathPrefix(`{{ .Values.ingress.path }}`)
kind: Rule
services:
- name: { { include "deploy.fullname" . } }
port: { { .Values.service.port } }

deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "blog.fullname" . }}
labels:
{{- include "blog.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "blog.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "blog.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP

service

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: { { include "deploy.fullname" . } }
labels: { { - include "deploy.labels" . | nindent 4 } }
spec:
type: { { .Values.service.type } }
ports:
- port: { { .Values.service.port } }
targetPort: http
protocol: TCP
name: http
selector: { { - include "deploy.selectorLabels" . | nindent 4 } }

.Values.xxx 就是在 values.yaml 中定义的一些常量,然后在使用 helm 部署上去

1
2
3
4
5
6
7
helm upgrade <chart实例名称> <chart路径> \
-n <k8s pod> \
--set 'image.repository=$(APP_IMAGE_NAME)' \
--set 'image.tag=$(APP_IMAGE_TAG)' \
--install

我这里是用了makefile 来执行,镜像名称和tag 都是自动生成的所以 chart中的 repository 和 tag 我都没写在这里替换一下,你们可以直接写死或者跟我一样


最后这样就成功啦!!整个 helm 部署的过程还是很简单的,就是里面有很多高级的配置项值得去研究一下,helm 总的来说就是方便了我们部署,并不需要写一大堆文件然后挨个 kubectl apply 上去,所以赶紧用起来吧~

K3s 搭建

K3s 搭建

K3s 搭建


K3s 和 K8s 相比较:

  • 大小和性能:K3s 相对于 K8s 来说更加轻量级,占用更少的资源,适用于资源有限的环境。K3s 在二进制文件大小、内存占用和启动时间方面都比 K8s 更加高效。

  • 安装和配置:K3s 的安装和配置相对来说更简单和快速,减少了一些复杂的步骤和依赖项。K8s 则需要更多的配置和管理,适用于大规模、复杂的生产环境。

  • 可扩展性:K8s 具有非常强大的扩展性,可以管理大型集群并处理数千个容器。K3s 在规模和功能方面相对较小,更适合中小规模的部署。

  • 功能和生态系统:K8s 提供了丰富的功能和广泛的生态系统,拥有大量的插件和工具来扩展和定制。K3s 为了精简而移除了一些不常用的功能和组件,因此在功能和生态系统方面相对较小。

安装

机器配置要求具体可以看 https://docs.k3s.io/zh/installation/requirements

1. 安装脚本

1
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - --docker

k3s 默认使用的是 containerd 作为运行时容器

2. 检查操作系统是否满足需求

1
k3s check-config

3. 写一个 demo 服务

1
2
3
go mod tidy
vim main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello")
}

func main() {
http.HandleFunc("/", helloHandler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("Error starting the server:", err)
}
}

这里使用 go 语言搭建一个基本 http 服务 访问 ip:8080 就能返回 Hello

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 基于 golang 镜像构建
FROM golang:1.16-alpine AS build

# 设置工作目录
WORKDIR /app

# 复制源代码到容器中
COPY . .

# 构建可执行文件
RUN go init test
RUN go build -o app

# 生成最终镜像
FROM alpine:latest
COPY --from=build /app/app /app/app

# 设置容器启动命令
CMD ["/app/app"]

depolyment 部署文件

以下 depolyment 定义了一个 Deployment 和一个 NodePort 的 service

这里有个注意事项 ⚠️ 请看后面坑 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: my-app-srv
spec:
type: NodePort
selector:
app: my-app
ports:
- port: 30001
targetPort: 8080

Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
APP_NAME := app
DOCKER_IMAGE_NAME := my-app
DOCKER_IMAGE_TAG := latest
K8S_DEPLOYMENT_NAME := my-app
K8S_NAMESPACE := default

docker-build:
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .

k8s-deploy:
kubectl apply -f deployment.yaml -n $(K8S_NAMESPACE)

k8s-clean:
kubectl delete deployment $(K8S_DEPLOYMENT_NAME) -n $(K8S_NAMESPACE)

deploy: k8s-clean docker-build k8s-deploy

5. 配置 ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: www.hmlxy.cn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-srv
port:
number: 30001

创建 ingress

1
kubectl apply -f ingress.yml

5. 服务启动

到这所有准备工作都做完了只需要按下「启动按钮

1
make deploy

查看服务 service

访问 www.hmlxy.cn

成功 啦!!!

总结

这次的 k3s 部署花了将近一天的时间,踩了许许多多的坑,但是最后都解决了,也让我学到了不少新的知识。

踩坑

坑 1:无法从/var/lib/rpm 打开软件包数据库


注:

RPM 是”Red Hat Package Manager”(红帽软件包管理器)的缩写。它是一种常见的软件包管理工具,最初由 Red Hat 开发,并在多个 Linux 发行版中使用。RPM 用于在 Linux 系统上管理和安装软件包。

RPM 软件包是一种打包格式,其中包含软件的二进制文件、配置文件、文档和其他相关资源。使用 RPM,用户可以方便地安装、升级、删除和查询软件包。通过使用 RPM,系统管理员可以轻松地管理大量的软件包,同时确保软件包之间的依赖关系得到满足。

在使用 RPM 时,您可以使用命令行工具(如 rpm 命令)执行各种操作,例如安装软件包、列出已安装的软件包、查询软件包信息、升级软件包等。此外,还可以使用其他工具,如 Yum(基于 RPM 的软件包管理器)和 DNF(Dandified Yum),它们提供了更高级的功能,如解决依赖关系、自动更新等。

需要注意的是,RPM 主要用于基于 Red Hat 和 CentOS 等发行版的 Linux 系统。其他 Linux 发行版(如 Debian 和 Ubuntu)使用的是不同的软件包管理工具,例如 Debian 中的 dpkg 和 apt-get,以及 Ubuntu 中的 dpkg 和 apt。

fix:重新构建 rpm 数据库

1
2
3
4
5
cd /var/lib/rpm

rm -rf __db.*

rpm --rebuilddb

坑 2:操作系统没有打开用户命名空间


fix:打开就好

1
vim /etc/default/grub

在 GRUB_CMDLINE_LINUX=”…”这行中添加 user_namespace.enable=1 参数,确保在其他参数之间添加一个空格。

更新 GRUB 配置

1
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

重启电脑

坑 3:无法拉取镜像


可以看到我拉取镜像一直失败了,查看 k8s 文档

由于我一开始将 imagePullPolicy 字段省略了,并且通过我的 Makefile 文件可以看到我的镜像的 tag 是 latest 满足第一条,所以一直从远程拉取导致失败。只需要将 tag 改掉或者将 imagePullPolicy 设置为 IfNotPresent 或者 Never。建议改为 IfNotPresent

坑 4:无法访问程序


访问程序一直 404 curl 也是 404
一直以为是腾讯云域名解析错了的问题,思考了一下既然出了 404 那应该是路由没有匹配上,查看 ingress-controller

1
2
3
4
5
// 查看ingress-controller 控制器
kubectl get pods -n kube-system

// 查看控制器日志
kubectl logs -n kube-system traefik-56b8c5fb5c-7w7qd


果然报了一大堆错误 ❌ 看到「Cannot create service: service not found」这个日志我瞬间明白了,我一直以为 ingress 配置的 backend 是服务的名字,结果是 service 的名字 所以找不到 service 修改 ingress.yml 就好了