抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

前言

前段时间搭建了跨公有云厂商的k3s集群,部署了几个比较小的服务来测试一些稳定性。

结果还是有些让人失望的,跨越地域传输数据的网络的稳定性还是比较差,经常出现服务无法访问的情况,在网上也找了很多用其他软件构建虚拟内网的文档,试着搭建了一下,发现稳定性还是很脆弱。

奈何暂时放弃了使用公有云集群作为自己的生产k8s集群的方案,比较生产集群稳定性还是有一定要求,我自己自建了很多的服务,包括

  • spug 云上ssh工具,可以管理云主机,在必要的时候连接到云主机
  • bitwarden 非常好用而且开源的密码管理器,我现在的各种网站的密码都是使用的随机密码,大大降低了数据泄露的风险
  • outline 文档管理工具,自建的wiki,这篇文章就是使用outline写的
  • linkace 书签管理器

这篇文章叫《公有云安装k3s集群实践(二)》,实际上应该是《k3s公有云集群从入门到放弃》。

基于多方面考虑,直接搭建单节点k3s,把原来的k3s卸载,然后直接重新安装k3s,就能直接使用了。

1
2
3
4
5
6
7
8
#卸载k3s-server
/usr/local/bin/k3s-uninstall.sh

#卸载k3s-agent
/usr/local/bin/k3s-agent-uninstall.sh

#重新安装
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - server --disable traefik --docker --tls-san 公网IP

那我这篇文章要说什么呢?主要是讲一下我如何从docker-compose的服务管理,迁移到k8s的服务管理。

对比docker-compose、k8s服务管理的些许不同

比对不同主要是从我自身的角度出发,作为个人开发者,在实际使用上的不同来进行简单的对比:

  • docker-compose是单机模式,部署服务需要连接到对应的云主机,然后执行命令,它最大的作用是记住一些关键配置,不需要每次都docker run -d -p 8080:80 -v xxx:xxx nginx 和能让容器有多副本,仅此而已
  • k8s服务作为容器编排的top1,主要是足够的自动化,外部的devops只需要获取到k8s集群的kubeconfig就能够访问到k8s集群进行服务部署,就是配置服务文件会有一些门槛,但是经过了使用可视化的web界面来实践之后,直接把对应的deloyment.yaml文件拿下来改改就能够构建其他的服务,相比来说更灵活也更简单

从docker-compose迁移到k8s

目前k8s有提供工具来从docker-compose.yaml 文件转化为k8s运行需要的yaml文件,但是仍然需要做些许修改才能正常使用。

安装kompose

1
2
3
4
5
6
7
8
9
10
11
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.26.1/kompose-linux-amd64 -o kompose

# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.26.1/kompose-darwin-amd64 -o kompose

#授予文件执行权限
chmod +x kompose

#将kompose放到bin 就可以在外部直接执行了
sudo mv ./kompose /usr/local/bin/kompose

以linkace服务为例转化为k8s服务

linkacedocker-compose.yaml文件

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
---
version: '3.3'

services:
link:
image: linkace/linkace:${LINKACE_VERSION}
networks:
- gateway
container_name: link
restart: unless-stopped
env_file: .env
volumes:
- ./.env:/app/.env
- /data/logs/link/logs:/app/storage/logs
- /data/logs/link/backups:/app/storage/app/backups
healthcheck:
disable: false
environment:
- TZ=Asia/Shanghai
ports:
- 2022:80
networks:
gateway:
external: true
...

linkace.env文件

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
## LINKACE CONFIGURATION
LINKACE_VERSION=v1.10.4-php-nginx
## Basic app configuration
COMPOSE_PROJECT_NAME=linkace
# The app key is generated later, please leave it blank
APP_KEY=

## Configuration of the database connection
## Attention: Those settings are configured during the web setup, please do not modify them now.
# Set the database driver (mysql, pgsql, sqlsrv)
DB_CONNECTION=mysql
# Set the host of your database here
DB_HOST=mysql-host
# Set the port of your database here
DB_PORT=3306
# Set the database name here
DB_DATABASE=database
# Set both username and password of the user accessing the database
DB_USERNAME=username

DB_PASSWORD=password

## Redis cache configuration
# Set the Redis connection here if you want to use it
REDIS_HOST=host
REDIS_PASSWORD=
REDIS_PORT=6379

# Configure various driver
SESSION_DRIVER=redis
LOG_CHANNEL=stack
BROADCAST_DRIVER=log
CACHE_DRIVER=redis
QUEUE_DRIVER=database

可以看出结构非常的简单,我比较关心的主要是两个点

  • volumes 原来我的数据都是挂在宿主机上的,方便迁移到其他的机器
  • .env 我的.env中存储的是容器运行所需的环境变量

转化为k8s可执行文件

1
2
3
4
5
6
7
8
9
10
11
#转化为k8s可执行文件
kompose convert -f linkace/

#输入出了如下几个文件:
link-deployment.yaml
link-service.yaml
env-configmap.yaml
gateway-networkpolicy.yaml
link-claim0-persistentvolumeclaim.yaml
link-claim1-persistentvolumeclaim.yaml
link-claim2-persistentvolumeclaim.yaml

当看到一个简单的docker-compose.yaml文件通过kompose转化为7个文件的时候我还是有点震惊的,正常情况下只需要两个文件即可:deployment.yamlservice.yaml

开始手动修改link-deployment.yaml 文件让它变得更简单

生成的link-deployment.yaml文件内容:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yaml
kompose.version: 1.26.1 (a9d05d509)
creationTimestamp: null
labels:
io.kompose.service: link
name: link
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: link
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yaml
kompose.version: 1.26.1 (a9d05d509)
creationTimestamp: null
labels:
io.kompose.network/gateway: "true"
io.kompose.service: link
spec:
containers:
- env:
- name: APP_KEY
valueFrom:
configMapKeyRef:
key: APP_KEY
name: env
...#中间省略一大块 env的内容
- name: TZ
value: Asia/Shanghai
image: 'linkace/linkace:'
name: link
ports:
- containerPort: 80
resources: {}
volumeMounts:
- mountPath: /app/.env
name: link-claim0
- mountPath: /app/storage/logs
name: link-claim1
- mountPath: /app/storage/app/backups
name: link-claim2
restartPolicy: Always
volumes:
- name: link-claim0
persistentVolumeClaim:
claimName: link-claim0
- name: link-claim1
persistentVolumeClaim:
claimName: link-claim1
- name: link-claim2
persistentVolumeClaim:
claimName: link-claim2
status: {}

修改完的link-deployment.yaml 文件

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
apiVersion: apps/v1
kind: Deployment
metadata:
name: link-app
namespace: cloud-app
labels:
app: link-app
annotations:
deployment.kubernetes.io/revision: '1'
kubesphere.io/creator: flow
spec:
replicas: 1
selector:
matchLabels:
app: link-app
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
app: link-app
spec:
containers:
- env:
- name: APP_KEY
valueFrom:
configMapKeyRef:
key: APP_KEY
name: link-env
...#省略一大堆的配置
- name: TZ
value: Asia/Shanghai
image: 'linkace/linkace:v1.10.4-php-nginx'
name: link-app
ports:
- name: tcp-80
containerPort: 80
protocol: TCP
resources: {}
volumeMounts:
- mountPath: /app/storage/logs
name: link-logs
- mountPath: /app/storage/app/backups
name: link-backups
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
serviceAccountName: default
serviceAccount: default
securityContext: {}
imagePullSecrets:
- name: aliyun-docker
schedulerName: default-scheduler
volumes:
- name: link-logs
hostPath:
path: /data/link/logs
type: DirectoryOrCreate
- name: link-backups #volumeMounts.name
hostPath: #host-path
path: /data/link/backups #host-path
type: DirectoryOrCreate #DirectoryOrCreate/Directory/FileOrCreate/File
revisionHistoryLimit: 10
progressDeadlineSeconds: 600

---
kind: ConfigMap
apiVersion: v1
metadata:
name: link-env
namespace: cloud-app
labels:
app: link-env
annotations:
kubesphere.io/creator: flow
data:
APP_KEY:
BROADCAST_DRIVER: log
CACHE_DRIVER: redis
COMPOSE_PROJECT_NAME: linkace
DB_CONNECTION: mysql
DB_DATABASE: linkace
DB_HOST: host
DB_PASSWORD: password
DB_PORT: "3306"
DB_USERNAME: xxxx
LINKACE_VERSION: v1.10.4-php-nginx
LOG_CHANNEL: stack
QUEUE_DRIVER: database
REDIS_HOST: redis-host
REDIS_PASSWORD:
REDIS_PORT: "6379"
SESSION_DRIVER: redis
---
kind: Service
apiVersion: v1
metadata:
name: link-app-svc
namespace: cloud-app
labels:
app: link-app-svc
annotations:
kubesphere.io/creator: flow
spec:
ports:
- name: http-2008
protocol: TCP
port: 80
targetPort: 80
nodePort: 2008
selector:
app: link-app
type: NodePort
sessionAffinity: None
externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack

主要修改的内容:

  • metadata 原来的很多meta都是以kompose的数据来的,然后我直接将我现在在kubesphere上下载下来的deployment.yaml为模板来修改

  • env 这里使用了env来生成了一个ConfigMap的配置,然后直接在dpeloyment.yaml文件中引用,格式是这样的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    - name: APP_KEY   #env中kye的名字
    valueFrom:
    configMapKeyRef:
    key: APP_KEY #configMao中对应的key
    name: link-env #configMap的名字

    #如果觉得使用config麻烦,那就简单干脆
    - name: APP_KEY #env中kye的名字
    value: xxxx #直接填value值
  • volumes 的修改稍稍的麻烦一些,但是差不了太多,只是因为使用的volumes需要挂载到host

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #这块是容器里面的目录,需要挂载出来的
    volumeMounts:
    - mountPath: /app/storage/logs
    name: link-logs
    - mountPath: /app/storage/app/backups
    name: link-backups

    #宿主机上的位置
    volumes:
    - name: link-logs #和volumeMounts.name对应的名字
    hostPath:
    path: /data/link/logs
    type: DirectoryOrCreate
    - name: link-backups
    hostPath:
    path: /data/link/backups
    type: DirectoryOrCreate #DirectoryOrCreate/Directory/FileOrCreate/File

注意:

  1. hostPath.type 支持很多种文件,我这里主要是四种用法:
  • DirectoryOrCreate 文件夹,如果不存在则创建
  • Directory 文件夹,不存在则报错
  • FileOrCreate 文件,不存在则创建
  • File 文件,不存在则报错
  1. volumes.name 要和上下对应,不然找不到
  2. 关注一下service.nodePort 是你要在宿主机暴露的port,直接根据IP:nodePort对外可访问

总结

实际在k8s集群的网络联通测试上花了很多的时间和精力,但是确实么有特别靠谱的方法,所以暂时妥协用k3s单节点集群,就这其实也解决了我的服务从docker-compose迁移到k8s的问题,我将其他的机器也同样装上k3s,那还是没有体验上的差别,差别只是节点不能跨机器部署,单节点故障会导致服务不可用,对于个人服务来说不是特别重要。

另外并没有放弃使用k8s集群来做一些学习研究的工作,所以我申请了鹏城生态 的安全可靠,免费公益服务器来搭建k8s集群,来继续进行研究。

后面会将我其他的服务都逐步迁移到k8s中来进行管理,并且挖掘k8s一些好用的有意思的功能来进行应用。

学习的路上没有止境,我一直认为学习是为了更好的工作和生活,自建的服务是,docker是,k8s也是,节省了很多的人力物力去处理各种各样复杂的现实问题。

评论