Chemmy's Blog

chengming0916@outlook.com

本地路径映射(HostPath)

HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# 宿主机上目录位置
path: /data
# 此字段为可选
type: Directory

支持的 type 值如下:

取值 行为
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice 在给定路径上必须存在的块设备。
1
2
3
4
5
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-vol-default
provisioner: vendor-name.example

local

local 卷只能用作静态创建的持久卷。不支持动态配置。

hostPath 卷相比,local 卷能够以持久和可移植的方式使用,而无需手动将 Pod 调度到节点。系统通过查看 PersistentVolume 的节点亲和性配置,就能了解卷的节点约束。

使用 local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。

PersistentVolume 对象的 volumeMode 字段可被设置为 “Block” (而不是默认值 “Filesystem”),以将 local 卷作为原始块设备暴露出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node

NFS映射

1

Minio

1

Ceph

1

准备环境

证书

[[../杂项/OpenSSL生成自签名证书|OpenSSL生成自签名证书]]

[[GitOps/基于K3s搭建GitOps环境4-证书管理|基于K3s搭建GitOps环境4-证书管理]]

默认配置文件

1
helm show values harbor/harbor > harbor-values.yaml

安装

配置清单

harbor-value.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
expose:
type: ingress
tls:
enabled: true
certSource: secret
secret:
secretName: "example.io"
notarySecretName: "example.io"
ingress:
hosts:
core: harbor.example.io
notary: notary.example.io
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.entrypoints: websecure

externalURL: https://harbor.example.io

harborAdminPassword: "Harbor123456"

logLevel: info

chartmuseum:
enabled: true

database:
type: external
external:
host: "postgres.devops.svc.cluster.local"
port: "5432"
username: "harbor"
password: "harbor"
redis:
type: external
external:
addr: "redis.devops.svc.cluster.local:6379"
password: "passwd"

harbor-ingress.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
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-http
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/`)
kind: Rule
services:
- name: harbor-portal
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-api
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/api/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-service
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/service/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-v2
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/v2`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-chartrepo
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/chartrepo/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-c
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/c/`)
kind: Rule
services:
- name: harbor-core
port: 80

安装Harbor

1
2
3
4
5
6
7
# 添加Harbor仓库
helm repo add harbor https://helm.goharbor.io

# 使用部署或升级Harbor
helm upgrade harbor harbor/harbor --namespace harbor \
--install --create-namespace \
-f harbor-values.yaml

配置

配置library仓库源

1
2
3
4
5
6
7
kubectl edit configmap harobr-registry -n harbor

# 在auth: 后边添加新节点
proxy:
remoteurl: "https://registry-1.docker.io"


使用Harbor

配置镜像缓存

参考

Harbor 搭建镜像代理 | Northes

Kubernetes ≥ 1.25 Containerd配置Harbor私有镜像仓库_containerd登录镜像仓库-CSDN博客

结合Cert-Manager完成Harbor的Https证书自动签发 | 风格 | 风起于青萍之末 (lusyoe.github.io)

Containerd容器镜像管理-腾讯云开发者社区-腾讯云 (tencent.com)

通过helm在k8s上搭建Harbor - 简书 (jianshu.com)

Kubernetes 集群仓库 harbor Helm3 部署-腾讯云开发者社区-腾讯云 (tencent.com)

containerd基本使用命令 - 杨梅冲 - 博客园 (cnblogs.com)

Kubernetes1.21搭建harbor-腾讯云开发者社区-腾讯云 (tencent.com)

Helm部署

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
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/

#helm会使用kubectl默认的KUBECONFIG配置,这里我们需要将KUBECONFIG换成k3s的否则会链接失败。
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

#注意要指定端口号等信息,方便访问
# service.type=NodePort 默认是ClusterIP只能本机访问
# service.nodePort=30080 指定访问端口号
# replicaCount=2 2个节点

# helm v2
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--create-namespace \
--namespace kubernetes-dashboard \
# --set service.type=NodePort \
# --set service.nodePort=30080 \
# --set replicaCount=2

# helm v3+
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--create-namespace \
--namespace kubernetes-dashboard \
# --set service.type=NodePort \
# --set service.nodePort=30080 \
# --set replicaCount=2

配置远程访问

NodePort暴露端口

1
kubectl -n kubernetes-dashboard edit service kubernetes-dashboard-web
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
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
...
name: kubernetes-dashboard
namespace: kubernetes-dashboard
resourceVersion: "343478"
selfLink: /api/v1/namespaces/kubernetes-dashboard/services/kubernetes-dashboard
uid: 8e48f478-993d-11e7-87e0-901b0e532516
spec:
clusterIP: 10.100.124.90
externalTrafficPolicy: Cluster
ports:
- port: 443
protocol: TCP
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
# 修改开放端口方式
#type: ClusterIP
type: NodePort
status:
loadBalancer: {}

Traefik Ingress反向代理

创建证书请求文件dashboard-cert-manager.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: k3s-chemmy-io
namespace: default
spec:
secretName: k3s-chemmy-io-tls
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
commonName: k3s.chemmy.io
dnsNames:
- k3s.sample.net

此配置文件是测试版,正式版参考K3s部署cert-manager

1
2
3
4
5
6
7
8
9
10
11
kubectl apply -f dashboard-cert-manager.yaml

# 查看
kubectl get certificates

# 如果状态不是READY,检查
kubectl describe certificates k3s-chemmy-io

# 清理证书
kubectl delete certificates k3s-chemmy-io
kubectl delete secrets k3s-chemmy-io-tls

配置账户

新建dashboard-admin.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
#创建clusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard

新建用户

1
2
# 部署用户资源
kubectl apply -f dashboard-admin.yaml

获取token

1
2
3
4
5
# v1.24+
sudo k3s kubectl -n kubernetes-dashboard create token admin-user

# v1.23 及之前的版本
sudo k3s kubectl -n kubernetes-dashboard describe secret admin-user-token | grep '^token'

Kubectl部署

最新版本只支持Helm,旧版本v2.7支持Kubectl部署

下载 recommended.yaml

1
kubectl apply -f recommended.yaml

修改recommended.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
# 直接暴露端口使用NodePort,Traefik使用ClusterIP
#type: ClusterIP
type: NodePort
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
...

dashboard的默认webui证书是自动生成的,由于时间和名称存在问题,导致谷歌和ie浏览器无法打开登录界面,经过测试Firefox可以正常打开。解决证书问题参考Kubernetes Dashboard的安装与坑 - 简书 (jianshu.com)

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
---

# 注释内置自动生成的证书
#apiVersion: v1
#kind: Secret
#metadata:
# labels:
# k8s-app: kubernetes-dashboard
# name: kubernetes-dashboard-certs
# namespace: kubernetes-dashboard
#type: Opaque

---
...
---

kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.1.0
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
# 注释自动生成证书
# - --auto-generate-certificates
- --namespace=kubernetes-dashboard
# 添加证书配置及证书文件映射
- --token-ttl=3600
- --bind-address=0.0.0.0
- --tls-cert-file=tls.crt
- --tls-key-file=tls.key
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule

---
...

生成证书文件 tls.crt,tls.csr,tls.key

1
2
3
4
5
6
7
8
9
# 生成key
openssl genrsa -out tls.key 2048
# 生成csr
openssl req -new -out tls.csr -key tls.key -subj '/CN=0.0.0.0'
# 生成
openssl x509 -req -in tls.csr -signkey tls.key -out tls.crt

#创建secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=tls.crt --from-file=tls.key -n kubernetes-dashboard

subj子参数解释

缩写 翻译 英文对照
C 国家名称缩写 Country Name (2 letter code)
ST 州或省名称 State or Province Name (full name)
L 城市或区域称 Locality Name (eg, city)
O 组织名(或公司名) Organization Name (eg, company)
OU 组织单位名称(或部门名) Organizational Unit Name (eg, section)
CN 服务器域名/证书拥有者名称 Common Name (e.g. server FQDN or YOUR name)
emailAddress 邮件地址 Email

参考

k3s集群单节点部署与集群内DashBoard部署 - 知乎 (zhihu.com)

k3s集群搭建并安装kubernetes-dashboard - 东峰叵,com - 博客园 (cnblogs.com)

[K8S 快速入门(十九)通过Helm 安装 Kubernetes Dashboard_helm安装dashboard ingress-CSDN博客](https://blog.csdn.net/weixin_41947378/article/details/111661539#:~:text=通过Helm 安装 Kubernetes Dashboard 1 1. 下载 %23,外网访问 %23 将svc的ClusterIP改为NotePort,外网访问 … 5 5. 令牌方式登录仪表盘)

使用 traefik ingress暴露kubernetes-dashbord - HTTPS版本_svclb-traefik-CSDN博客

Kubernetes dashboardv2.7.0安装指南:从零开始搭建可视化界面 - 知乎

常用国内源

1
2
3
4
5
6
7
https://pypi.tuna.tsinghua.edu.cn/simple

https://mirrors.ustc.edu.cn/pypi/web/simple # 已暂时移除并重定向到 BFSU PyPI

https://mirrors.aliyun.com/pypi/simple/

http://mirrors.cloud.tencent.com/pypi/simple

查看当前镜像地址

1
2
3
4
5
pip config list

# 查看数据中对应路径
global.index-url = 'https://pypi.tuna.tsinghua.edu.cn/simple'
install.trusted-host = 'https://pypi.tuna.tsinghua.edu.cn'

临时使用

1
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

全局修改

1
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

换回默认

1
pip config unset global.index-url

在K3s集群中部署Redis,需依托Kubernetes资源清单,完成组件配置、存储挂载、网络访问等全流程操作。本文基于实际可直接复用的YAML配置文件,详细拆解Redis在K3s环境中的部署步骤,解析核心配置要点,确保部署过程规范、可落地。

一、环境说明

本次部署基于K3s集群,选用Redis 6.0.8版本,所有相关资源统一部署在redis命名空间下(需提前执行命令kubectl create namespace redis完成命名空间创建)。部署采用StatefulSet控制器保障Redis实例的稳定运行,结合PersistentVolumeClaim(PVC)实现数据持久化,通过IngressRouteTCP暴露外部访问入口,借助ConfigMap统一管理Redis配置文件,形成完整的部署闭环。

二、核心配置文件与部署步骤

1. 配置Redis配置文件(ConfigMap)

创建redis-config.yaml文件,通过ConfigMap存储Redis核心配置参数,涵盖网络绑定、数据持久化策略、密码认证等关键配置,确保Redis运行参数可灵活调整、统一管理,具体配置如下:

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: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: redis
labels:
app: redis
data:
redis.conf: |
daemonize no
bind 0.0.0.0
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
pidfile /data/redis-server.pid
logfile /data/redis.log
loglevel notice
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
requirepass passwd

配置文件创建完成后,执行以下命令部署ConfigMap:

1
kubectl apply -f redis-config.yaml

2. 配置持久化存储(PV/PVC)

K3s集群默认内置local-path存储类,可满足日常Redis数据持久化需求。本次部署提供两种PVC配置方式,用户可根据实际存储场景灵活选择。

方式1:仅创建PVC(基于local-path存储类)

创建redis-pvc-local-path.yaml文件,申请2Gi存储容量,访问模式设为ReadWriteOnce(仅允许单个节点读写),适配单节点Redis部署场景,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: redis
labels:
app: redis
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 2Gi

执行部署命令:

1
kubectl apply -f redis-pvc-local-path.yaml

方式2:手动创建PV+PVC(hostPath模式)

若需自定义存储路径,可创建redis-pvc-host-path.yaml文件,手动定义PersistentVolume(PV)和PVC。其中PV指定宿主机/mnt/redis/data路径作为存储目录,容量设为5Gi;PVC关联local-path存储类,申请2Gi存储容量,配置如下:

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
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-pv
namespace: redis
labels:
app: redis
spec:
storageClassName: redis-persistent-storage
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/redis/data

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
labels:
app: redis
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 2Gi

执行部署命令:

1
kubectl apply -f redis-pvc-host-path.yaml

3. 部署Redis StatefulSet

创建redis-deployment.yaml文件,采用StatefulSet控制器管理Redis Pod,配置包含初始化容器(调整内核参数)、存储卷挂载、配置文件挂载、启动命令指定等核心内容,确保Redis实例稳定启动,配置如下:

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
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: redis
labels:
app: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
initContainers:
- name: init-0
image: busybox
imagePullPolicy: IfNotPresent
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
command: [ "sysctl", "-w", "net.core.somaxconn=511" ]
securityContext:
privileged: true
# - name: init-1
# image: busybox
# imagePullPolicy: IfNotPresent
# terminationMessagePath: /dev/termination-log
# terminationMessagePolicy: File
# command: [ "sh", "-c", "echo never > /sys/kernel/mm/transparent_hugepage/enabled" ]
# securityContext:
# privileged: true
containers:
- name: redis
image: redis:6.0.8
imagePullPolicy: IfNotPresent
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- name: redis-persistent-storage
mountPath: /var/lib/redis
- name: redis-config
mountPath: /usr/local/etc/redis/redis.conf
subPath: redis.conf
command: [ "redis-server" ,"/usr/local/etc/redis/redis.conf" ]
env:
- name: TZ
value: "Asia/Shanghai"
volumes:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: redis-persistent-storage
persistentVolumeClaim:
claimName: redis-pvc
- name: redis-config
configMap:
name: redis-config

执行部署命令,启动Redis StatefulSet:

1
kubectl apply -f redis-deployment.yaml

4. 配置Service暴露集群内访问

创建redis-service.yaml文件,定义ClusterIP类型Service,暴露Redis 6379端口,供K3s集群内其他应用程序访问Redis服务,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: redis
labels:
app: redis
spec:
ports:
- name: redis
port: 6379
targetPort: 6379
protocol: TCP
selector:
app: redis
type: ClusterIP

执行部署命令:

1
kubectl apply -f redis-service.yaml

5. 配置IngressRouteTCP暴露外部访问

基于K3s默认集成的Traefik IngressController,创建redis-ingress.yaml文件,通过IngressRouteTCP暴露Redis的6379端口,实现集群外部对Redis服务的访问,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: redis-tcp
namespace: redis
labels:
app: redis
spec:
entryPoints:
- redis
routes:
- match: HostSNI(`*`)
services:
- name: redis
port: 6379

执行部署命令:

1
kubectl apply -f redis-ingress.yaml

注意:需提前在Traefik中配置名为redis的entryPoint(监听6379端口),否则IngressRouteTCP无法正常生效。

三、部署验证

Redis相关资源部署完成后,需通过以下命令检查资源状态,并验证服务可正常访问。

1. 检查资源状态

1
2
3
4
5
6
# 检查StatefulSet运行状态
kubectl get statefulset -n redis
# 检查Redis Pod运行状态
kubectl get pods -n redis
# 检查PVC绑定状态
kubectl get pvc -n redis

若所有资源状态均为Running/Bound,说明部署成功。

2. 访问Redis服务

  • 集群内访问:通过集群内部服务地址redis.redis.svc.cluster.local:6379访问,访问密码为配置文件中设置的passwd

  • 集群外访问:通过Traefik节点IP+6379端口访问,访问密码同样为passwd

四、关键配置说明

  • 内核参数调整:通过初始化容器(initContainers)执行sysctl -w net.core.somaxconn=511,提升Redis网络连接上限,避免因连接数不足导致服务异常。

  • 数据持久化:通过PVC挂载/var/lib/redis目录,结合Redis配置中的RDB和AOF双重持久化策略,确保数据不丢失;hostPath模式下,数据实际存储在宿主机/mnt/redis/data目录,local-path模式下存储在集群默认存储路径。

  • 配置管理:通过ConfigMap挂载redis.conf配置文件,后续需修改Redis运行参数时,仅需更新ConfigMap并重启Pod即可,无需重建镜像,提升维护效率。

  • 网络安全:采用ClusterIP类型Service限制集群内访问,通过IngressRouteTCP实现外部可控访问,同时Redis配置密码认证,多重保障服务安全。

五、总结

本文基于实际生产可用的YAML配置文件,完成了K3s集群中Redis的标准化部署,覆盖配置管理、数据持久化、网络访问、部署验证等核心环节。所有配置均保持原始内容不变,可直接复用至K3s环境,无需额外修改,能够满足中小规模业务场景下Redis的稳定运行需求,为K3s环境中Redis的部署提供了可落地的实践参考。

一、核心定位

本文作为GitOps环境搭建系列的第四篇,聚焦cert-manager证书管理的部署与配置。在K3s集群环境中,TLS/SSL证书是保障服务通信安全的核心基础设施,无论是公网HTTPS服务还是内网私有服务,都需要规范的证书管理方案。

在GitOps环境中,cert-manager扮演”证书自动化管理中枢”角色,为所有组件(Traefik、Gitea、ArgoCD、Tekton、Harbor等)提供自动化的证书签发、续签和轮换服务。通过cert-manager,可以实现Let’s Encrypt公网证书的自动获取,或自签名证书的内网安全通信,确保整个GitOps环境的HTTPS安全访问。

二、部署前置检查

部署前需验证K3s集群状态及Traefik运行情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 验证K3s集群状态
kubectl get nodes

# 2. 验证Traefik运行状态(证书验证依赖Traefik)
kubectl get pods -n kube-system -l app=traefik

# 3. 验证Helm可用性
helm version --short

# 4. 验证域名解析(替换为实际域名)
nslookup traefik.example.io
nslookup harbor.example.io
nslookup gitea.example.io

# 5. 检查cert-manager命名空间
kubectl get ns cert-manager 2>/dev/null || echo "命名空间不存在,将自动创建"

前置条件检查清单:

  • K3s集群运行正常
  • Traefik Pod处于Running状态
  • 域名已正确解析至K3s节点IP
  • Helm工具可用
  • 具备集群管理权限

三、部署cert-manager

3.1 Helm部署(推荐方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 添加cert-manager官方Helm仓库
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update

# 创建cert-manager命名空间
kubectl create namespace cert-manager

# 部署cert-manager
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.8.0 \
--set installCRDs=true \
--set prometheus.enabled=false

3.2 验证部署状态

1
2
3
4
5
6
7
8
# 查看cert-manager组件状态
kubectl get pods -n cert-manager -w

# 查看CRD资源
kubectl get crd | grep cert-manager

# 验证组件就绪
kubectl wait --for=condition=Ready pods -l app.kubernetes.io/instance=cert-manager -n cert-manager --timeout=300s

四、配置签发机构(ClusterIssuer)

cert-manager通过ClusterIssuer定义证书签发规则,支持Let’s Encrypt(公网)和自签名(内网)两种模式。

4.1 公网证书:Let’s Encrypt签发

测试环境ClusterIssuer(无速率限制):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# letsencrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: admin@example.io # 替换为管理员邮箱
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: traefik # K3s默认使用Traefik

生产环境ClusterIssuer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# letsencrypt-prod.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: admin@example.io # 替换为管理员邮箱
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik

Let’s Encrypt速率限制说明:

  • 测试环境:无限制,适合验证配置
  • 生产环境:每个域名每周50张证书,每个精确域名组合每周5张
  • 建议:先在测试环境验证,再切换到生产环境

4.2 内网证书:自签名签发

对于内网GitOps环境,推荐使用自签名CA证书。以下配置创建自签名CA并基于该CA签发子证书:

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
# selfsigned-issuer.yaml
# 参考:https://gitee.com/Chemmy/kube-template/blob/master/devops/cert-manager/selfsigned-cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: selfsigned-ca
namespace: cert-manager
spec:
isCA: true
commonName: selfsigned-ca
secretName: root-secret
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-cluster-issuer
kind: ClusterIssuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
ca:
secretName: root-secret

配置说明:

  1. 第一个ClusterIssuer:用于生成根CA证书
  2. Certificate资源:定义根CA证书的规格,生成后存储在root-secret
  3. 第二个ClusterIssuer:基于生成的根CA证书,用于签发其他子证书

应用配置:

1
2
3
4
5
6
7
8
9
# 应用自签名CA配置
kubectl apply -f selfsigned-issuer.yaml

# 验证CA证书生成
kubectl get certificate selfsigned-ca -n cert-manager
kubectl get secret root-secret -n cert-manager

# 等待CA证书就绪
kubectl wait --for=condition=Ready certificate selfsigned-ca -n cert-manager --timeout=300s

4.3 自定义CA证书导入(可选)

如果已有自定义CA证书,可先导入到Secret中,再创建引用该CA的ClusterIssuer:

1
2
3
4
5
# 导入自定义CA证书
kubectl create secret tls custom-ca-secret \
--namespace=cert-manager \
--cert=path/to/ca.crt \
--key=path/to/ca.key
1
2
3
4
5
6
7
8
# custom-ca-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: custom-ca-issuer
spec:
ca:
secretName: custom-ca-secret

K3s默认CA说明:
K3s会在首个Server节点启动时生成自签名CA证书,有效期为10年,存储在:

  • /var/lib/rancher/k3s/server/tls/client-ca.crt
  • /var/lib/rancher/k3s/server/tls/server-ca.crt

如需轮换K3s默认CA证书,可使用:

1
k3s certificate rotate-ca

4.4 应用签发机构配置

1
2
3
4
5
6
# 应用ClusterIssuer配置
kubectl apply -f letsencrypt-staging.yaml
kubectl apply -f selfsigned-issuer.yaml

# 验证签发机构状态
kubectl get clusterissuer

五、创建域名证书

5.1 GitOps组件证书配置

使用自签名CA签发GitOps环境通配符证书:

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
# gitops-certificates.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gitops-wildcard-cert
namespace: cert-manager
spec:
secretName: gitops-wildcard-tls
issuerRef:
name: selfsigned-cluster-issuer # 使用自签名CA签发机构
kind: ClusterIssuer
duration: 2160h # 90天有效期
renewBefore: 360h # 过期前15天自动续签
commonName: "*.example.io"
dnsNames:
- "*.example.io" # 通配符证书,覆盖所有GitOps组件
- traefik.example.io
- harbor.example.io
- gitea.example.io
- tekton.example.io
- argocd.example.io
- notary.example.io
subject:
organizations:
- Example Organization
organizationalUnits:
- DevOps Team
localities:
- Beijing
provinces:
- Beijing
countries:
- CN
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
usages:
- server auth
- client auth

5.2 单个组件证书配置(示例:Traefik)

1
2
3
4
5
6
7
8
9
10
11
12
13
# traefik-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: traefik-cert
namespace: kube-system
spec:
secretName: traefik-dashboard-tls
issuerRef:
name: selfsigned-cluster-issuer
kind: ClusterIssuer
dnsNames:
- traefik.example.io

5.3 应用证书配置

1
2
3
4
5
6
7
# 应用证书配置
kubectl apply -f gitops-certificates.yaml
kubectl apply -f traefik-certificate.yaml

# 查看证书状态
kubectl get certificates -A
kubectl describe certificate gitops-wildcard-cert -n cert-manager

六、验证证书签发

6.1 检查证书状态

1
2
3
4
5
6
7
8
9
10
11
# 查看所有证书
kubectl get certificates --all-namespaces

# 查看证书详情
kubectl describe certificate gitops-wildcard-cert -n cert-manager

# 查看生成的TLS Secret
kubectl get secret gitops-wildcard-tls -n cert-manager -o yaml

# 查看证书签发事件
kubectl get events --field-selector involvedObject.name=gitops-wildcard-cert -n cert-manager

6.2 测试证书使用(使用IngressRoute)

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
# 创建测试IngressRoute使用证书
cat > test-ingressroute.yaml << EOF
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: test-tls-ingressroute
namespace: default
annotations:
cert-manager.io/cluster-issuer: selfsigned-cluster-issuer
spec:
entryPoints:
- websecure
routes:
- match: Host(`test.example.io`)
kind: Rule
services:
- name: whoami
port: 80
tls:
secretName: test-tls-secret
EOF

# 应用测试配置
kubectl apply -f test-ingressroute.yaml

# 验证证书自动创建
kubectl get certificate test-tls-secret -n default

# 测试HTTPS访问
curl -k https://test.example.io

# 清理测试资源
kubectl delete -f test-ingressroute.yaml

6.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
# 创建带自动签发注解的IngressRoute
cat > auto-cert-test.yaml << EOF
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: auto-cert-test
namespace: default
annotations:
cert-manager.io/cluster-issuer: selfsigned-cluster-issuer
spec:
entryPoints:
- websecure
routes:
- match: Host(`auto-test.example.io`)
kind: Rule
services:
- name: whoami
port: 80
tls:
secretName: auto-test-tls-secret
EOF

# 应用配置
kubectl apply -f auto-cert-test.yaml

# 等待证书自动创建(约1-2分钟)
sleep 60

# 验证证书状态
kubectl get certificate auto-test-tls-secret -n default
kubectl describe certificate auto-test-tls-secret -n default

# 清理测试
kubectl delete -f auto-cert-test.yaml

七、生产环境最佳实践

7.1 证书管理策略

  1. 命名空间隔离:将CA证书、ClusterIssuer等核心资源部署在独立命名空间
  2. 网络策略限制:配置网络策略,限制对cert-manager组件的访问
  3. 监控告警:配置证书过期告警,提前发现证书问题
  4. 备份策略:定期备份关键证书和私钥

7.2 IngressRoute自动签发

在IngressRoute资源中添加注解,实现证书自动签发。cert-manager会自动检测注解并创建对应的Certificate资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# gitops组件自动签发示例
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: gitea-websecure
namespace: gitea
annotations:
cert-manager.io/cluster-issuer: "selfsigned-cluster-issuer" # 内网使用自签名
cert-manager.io/renew-before: "360h"
cert-manager.io/common-name: "Gitea Git Repository"
spec:
entryPoints:
- websecure
routes:
- match: Host(`gitea.example.io`)
kind: Rule
services:
- name: gitea-http
port: 3000
tls:
secretName: gitea-tls-secret

支持的高级注解:

  • cert-manager.io/cluster-issuer: 指定签发机构
  • cert-manager.io/issuer: 指定命名空间级签发机构
  • cert-manager.io/common-name: 证书通用名称
  • cert-manager.io/duration: 证书有效期(默认90天)
  • cert-manager.io/renew-before: 续签提前时间(默认30天)
  • cert-manager.io/usages: 证书用途(如server auth, client auth
  • cert-manager.io/private-key-algorithm: 私钥算法(如RSA, ECDSA

通配符证书配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: gitops-wildcard
namespace: gitops
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
cert-manager.io/dns-names: "*.example.io,example.io"
spec:
entryPoints:
- websecure
routes:
- match: HostRegexp(`{subdomain:[a-z]+}.example.io`)
kind: Rule
services:
- name: gitops-router
port: 80
tls:
secretName: gitops-wildcard-tls

优势:

  • 声明式配置:证书需求与路由配置一体化
  • 自动管理:cert-manager自动处理证书的签发、续签、轮换
  • 无缝集成:与Traefik IngressRoute深度集成
  • 多环境支持:通过注解轻松切换测试/生产环境签发机构

7.3 证书导出与备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 导出自签名CA证书和GitOps组件证书

# 导出根CA证书
kubectl get secret root-secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 --decode > ca.crt
kubectl get secret root-secret -n cert-manager -o jsonpath='{.data.tls\.crt}' | base64 --decode > root-ca.crt
kubectl get secret root-secret -n cert-manager -o jsonpath='{.data.tls\.key}' | base64 --decode > root-ca.key

# 导出GitOps通配符证书
kubectl get secret gitops-wildcard-tls -n cert-manager -o jsonpath='{.data.tls\.crt}' | base64 --decode > gitops.crt
kubectl get secret gitops-wildcard-tls -n cert-manager -o jsonpath='{.data.tls\.key}' | base64 --decode > gitops.key

# 查看证书链信息
openssl x509 -in ca.crt -text -noout | head -20
openssl x509 -in gitops.crt -text -noout | head -20

# 验证证书链
openssl verify -CAfile ca.crt gitops.crt

# 备份所有证书Secret
kubectl get secret root-secret gitops-wildcard-tls -n cert-manager -o yaml > cert-backup-$(date +%Y%m%d).yaml

八、常见问题修复

问题现象 排查方向 修复方案
证书签发失败 ClusterIssuer配置 检查ClusterIssuer状态:kubectl describe clusterissuer <name>
证书一直Pending 域名验证失败 检查域名解析,确认Traefik可访问,查看cert-manager日志
证书过期未续签 续签配置错误 检查renewBefore设置,查看cert-manager控制器日志
Let’s Encrypt速率限制 请求过于频繁 切换到测试环境,或等待限制解除
证书Secret不存在 签发过程错误 查看Certificate资源事件:kubectl describe certificate <name>
HTTPS访问证书错误 证书域名不匹配 检查证书dnsNames是否包含访问域名
自签名CA证书无效 CA证书未就绪 等待CA证书生成:kubectl wait --for=condition=Ready certificate selfsigned-ca

九、配置参考

所有cert-manager配置文件和部署脚本请参考:
https://gitee.com/Chemmy/kube-template/tree/master/devops/cert-manager

该目录包含:

  • cert-manager Helm配置
  • ClusterIssuer配置模板(包括自签名CA配置)
  • 证书配置示例
  • 生产环境优化配置
  • 监控和备份脚本

总结

本文完成了cert-manager在K3s集群中的标准化部署,实现了GitOps环境证书的自动化管理。通过cert-manager,可以轻松管理Let’s Encrypt公网证书和自签名内网证书,确保所有组件的HTTPS安全访问。

配置完成后,建议为每个GitOps组件配置相应的证书,并在IngressRoute资源中启用TLS自动签发。下一篇文章将部署Gitea代码仓库,为GitOps环境提供代码托管能力。

Linux 源

清华 https://mirrors.tuna.tsinghua.edu.cn

阿里 http://mirrors.aliyun.com

腾讯 https://mirrors.tencent.com

华为 https://mirrors.huaweicloud.com

中国科技大学 https://mirrors.ustc.edu.cn

华中科技大学 http://mirror.hust.edu.cn

Docker 镜像仓库

DockerHub(docker.io)

网易 http://hub-mirror.c.163.com

中国科技大学 https://docker.mirrors.ustc.edu.cn (不可用)

道客 https://docker.m.daocloud.cn (参考官方文档)

腾讯 https://mirror.ccs.tencentyun.com

华为 https://mirror.swr.myhuaweicloud.com

阿里云 https://registry.cn-hangzhou.aliyuncs.com

[^注]: 阿里可申请私有加速,需注册账号,注册后地址修改为 https://{私有ID}.mirror.aliyuncs.com。详细信息参考官方文档

谷歌镜像仓库(gcr.io k8s.gcr.io)

阿里 https://registry.aliyuncs.com/google_containers

中科大 https://gcr.mirrors.ustc.edu.cn (2022.8之后不再更新镜像,校外访问返回403)

华为 https://mirror.swr.myhuaweicloud.com

道客 https://m.daocloud.io/k8s.gcr.io 文档

CoreOS镜像仓库(quay.io )

道客 https://m.daocloud.io/quay.io 参考支持镜像列表

Github镜像仓库(ghcr.io )

道客 https://m.daocloud.io/ghcr.io 参考支持镜像列表

Helm 源

ArtifactHub https://artifacthub.io/

华为 https://mirrors.huaweicloud.com/helm/

bitnami https://charts.bitnami.com/bitnami

Google https://gcr.io/kubernetes-helm

容器配置

Docker(/etc/docker/daemon.json )

1
2
3
4
5
6
7
8
9
10
11
{

"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
],
"insecure-registries": [],
"exec-opts":["native.cgroupdriver=systemd"]

}

Containerd(/etc/containerd/config.toml)

1
2
3
4
5
6
7
8

[plugins.cri.registry]
[plugins.cri.registry.mirrors]
[plugins.cri.registry.mirrors."quay.io"]
endpoint = ["https://quay.tencentcloudcr.com"]
[plugins.cri.registry.mirrors."docker.io"]
endpoint = ["https://mirror.ccs.tencentyun.com"]

K3s中Containerd容器(/var/lib/rancher/k3s/agent/etc/containerd/config.toml)

K3s 默认的 containerd 配置文件目录为/var/lib/rancher/k3s/agent/etc/containerd/config.toml,但直接操作 containerd 的配置文件去设置镜像仓库或加速器相比于操作 docker 要复杂许多。K3s 为了简化配置 containerd 镜像仓库的复杂度,K3s 会在启动时检查/etc/rancher/k3s/中是否存在 文件,如果存在该文件,就会根据 registries.yaml 的内容转换为 containerd 的配置并存储到/var/lib/rancher/k3s/agent/etc/containerd/config.toml,从而降低了配置 containerd 镜像仓库的复杂度。

1
2
3
4
5
6
7
8
9
10
11
mirrors:
"172.31.6.200:5000":
endpoint:
- "http://172.31.6.200:5000"
"rancher.ksd.top:5000":
endpoint:
- "http://172.31.6.200:5000"
"docker.io":
endpoint:
- "https://fogjl973.mirror.aliyuncs.com"
- "https://registry-1.docker.io"

containerd 与 docker 都有默认仓库,并且都为 docker.io。如果配置中未指定 mirror 为 docker.io,重启 containerd 后会自动加载 docker.io 配置。与 docker 不同的是,containerd 可以修改 docker.io 对应的 endpoint( 默认为 https://registry-1.docker.io ),而 docker 无法修改。

docker 中可以通过 registry-mirrors 设置镜像加速地址。如果 pull 的镜像不带仓库地址(项目名+镜像名:tag),则会从默认镜像仓库去拉取镜像。如果配置了镜像加速地址,会先访问镜像加速仓库,如果没有返回数据,再访问默认吧镜像仓库。

k3s完整配置文件

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
mirrors:
"192.168.50.119":
endpoint:
- "http://192.168.50.119"
"docker.io":
endpoint:
- "https://7bezldxe.mirror.aliyuncs.com"
- "https://registry-1.docker.io"
configs:
"192.168.50.119":
auth:
username: '' # this is the registry username
password: '' # this is the registry password
tls:
cert_file: '' # path to the cert file used in the registry
key_file: '' # path to the key file used in the registry
ca_file: '' # path to the ca file used in the registry
"docker.io":
auth:
username: '' # this is the registry username
password: '' # this is the registry password
tls:
cert_file: '' # path to the cert file used in the registry
key_file: '' # path to the key file used in the registry
ca_file: '' # path to the ca file used in the registry

镜像转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#gcr.io
docker pull gcr.io/kubernetes-helm/tiller:v2.16.1
docker pull gcr.mirrors.ustc.edu.cn/kubernetes-helm/tiller:v2.16.1

#k8s.gcr.io
#docker pull k8s.gcr.io/kube-proxy:v1.15.5
docker pull gcr.mirrors.ustc.edu.cn/google-containers/kube-proxy:v1.15.5

#quay.io
docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
docker pull quay.mirrors.ustc.edu.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1


转换为gcr.io镜像

1
2
3
docker pull registry.aliyuncs.com/google_containers/coredns:1.6.5
docker tag registry.aliyuncs.com/google_containers/coredns:1.6.5 k8s.gcr.io/coredns:1.6.5
docker rmi registry.aliyuncs.com/google_containers/coredns:1.6.5

K8S批量下载docker images

1
kubeadm config images list
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#!/bin/bash
images=( # 下面的镜像应该去除"k8s.gcr.io/"的前缀,版本换成上面获取到的版本
kube-apiserver:v1.12.1
kube-controller-manager:v1.12.1
kube-scheduler:v1.12.1
kube-proxy:v1.12.1
pause:3.1
etcd:3.2.24
coredns:1.2.2
)

for imageName in ${images[@]} ; do
docker pull registry.aliyuncs.com/google_containers/$imageName
docker tag registry.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
docker rmi registry.aliyuncs.com/google_containers/$imageName
done

更新版

1
2
3
4
5
6
7
8
9
10
11

#!/bin/bash
url=registry.aliyuncs.com
version=v1.16.4
images=(`kubeadm config images list --kubernetes-version=$version|awk -F '/' '{print $2}'`)
for imagename in ${images[@]} ; do
docker pull $url/$imagename
docker tag $url/$imagename k8s.gcr.io/$imagename
docker rmi -f $url/$imagename
done

或(V1.3以上)

1
2
kubeadm init --image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.13.0 --pod-network-cidr 192.168.1.100/24

系列文章目录

本文是基于K3s搭建GitOps环境的系列文章总览,包含完整的组件规划和部署路线图。本系列旨在帮助您在K3s轻量级Kubernetes集群上构建完整的GitOps环境,实现从代码到部署的自动化流水线。

基础环境篇

  1. 基于K3s搭建GitOps环境1-K3s安装 - K3s集群部署与基础配置
  2. 基于K3s搭建GitOps环境2-配置Traefik - Traefik反向代理配置
  3. 基于K3s搭建GitOps环境3-配置内网域名 - CoreDNS内网域名解析
  4. 基于K3s搭建GitOps环境4-证书管理 - cert-manager证书管理

核心组件篇

  1. [[基于K3s搭建GitOps5-部署Gitea]] - 代码仓库部署
  2. [[基于K3s搭建GitOps6-部署ArgoCD]] - GitOps核心部署
  3. [[基于K3s搭建GitOps7-部署Tekton]] - CI流水线部署
  4. [[基于K3s搭建GitOps8-部署Harbor]] - 镜像仓库部署

GitOps环境架构

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

┌─────────────────────────────────────────────────────────────────┐
│ GitOps 完整链路 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ① 开发者 ──push──▶ Gitea (Git仓库) │
│ │
│ ② Tekton Pipeline ──webhook触发──▶ 克隆代码 │
│ │
│ ③ Tekton Pipeline ──构建──▶ Docker镜像 │
│ │ │
│ │ docker push │
│ ▼ │
│ ④ Harbor (镜像仓库) ◀── 推送镜像 │
│ │ • 存储镜像bits │
│ │ • Trivy CVE扫描 │
│ │ • Notary镜像签名(可选) │
│ │
│ ⑤ ArgoCD Application ──监听镜像Tag变化──▶ 检测到新镜像 │
│ │ │
│ │ 更新Deployment镜像Tag │
│ ▼ │
│ ⑥ K3s集群 ──kubectl apply──▶ 新Pod以新镜像启动 │
│ │
└─────────────────────────────────────────────────────────────────┘

组件规划

开放端口

端口 用途 说明
53 CoreDNS服务 内网域名解析
443, 80 Traefik入口 HTTPS/HTTP访问入口
5432/3306 数据库服务 PostgreSQL/MySQL(二选一)
6379 Redis缓存 缓存服务
8022 SSH管理 服务器管理端口
22 Git SSH git+ssh方式代码上传

域名规划(统一使用example.io)

组件 访问地址 说明
Traefik Dashboard https://traefik.example.io 反向代理管理界面
Harbor https://harbor.example.io 私有镜像仓库,支持镜像签名与安全扫描
Gitea https://gitea.example.io 轻量级代码仓库
Tekton https://tekton.example.io 云原生CI流水线
ArgoCD https://argocd.example.io GitOps持续部署核心
Notary https://notary.example.io 镜像签名服务(Harbor集成)

部署路线图

第一阶段:基础环境搭建(1-4天)

  1. 第1天:部署K3s集群,配置存储和网络
  2. 第2天:配置Traefik反向代理,启用Dashboard
  3. 第3天:配置CoreDNS内网域名解析
  4. 第4天:部署cert-manager,配置证书管理

第二阶段:核心组件部署(5-8天)

  1. 第5天:部署Gitea代码仓库,配置数据库连接
  2. 第6天:部署ArgoCD,配置GitOps工作流
  3. 第7天:部署Tekton,配置CI流水线
  4. 第8天:部署Harbor,配置镜像仓库和安全扫描

第三阶段:集成与优化(9-10天)

  1. 第9天:组件间联动配置,打通完整流水线
  2. 第10天:生产环境优化,配置监控和告警

环境要求

硬件要求

  • 最低配置:2核CPU,4GB内存,50GB存储
  • 推荐配置:4核CPU,8GB内存,100GB存储
  • 生产环境:根据业务规模弹性扩展

软件要求

  • 操作系统:Ubuntu 20.04+ / CentOS 7+ / RHEL 8+
  • 容器运行时:Containerd(K3s默认集成)
  • 网络:内网互通,可访问外网(用于拉取镜像)

配置参考

所有组件的详细配置文件和部署脚本请参考:KubeTemplate-devops

该仓库包含:

  • K3s集群部署脚本
  • 各组件Helm Chart配置
  • 示例应用部署文件
  • 监控和日志配置
  • 生产环境优化建议

注意事项

  1. 域名配置:所有示例域名使用example.io,实际部署时请替换为您的域名
  2. 证书管理:生产环境建议使用Let’s Encrypt证书,内网环境可使用自签名证书
  3. 存储配置:K3s默认使用local-path存储类,生产环境建议配置持久化存储
  4. 安全加固:部署完成后请及时修改默认密码,配置网络策略
  5. 备份策略:定期备份数据库和持久化卷数据

常见问题

Q1: K3s与其他Kubernetes发行版有何区别?

A: K3s是轻量级Kubernetes发行版,专为边缘计算和资源受限环境设计,相比标准K8s:

  • 安装包更小(约40MB)
  • 内存占用更低
  • 默认集成Containerd、Traefik、CoreDNS等组件
  • 简化了配置和管理

Q2: GitOps与传统CI/CD有何不同?

A: GitOps的核心思想是”Git作为单一可信源”:

  • 声明式配置:所有环境配置存储在Git仓库中
  • 自动同步:集群状态自动与Git仓库中的期望状态同步
  • 可追溯性:所有变更都有Git提交记录
  • 一键回滚:通过Git版本控制实现快速回滚

Q3: 如何选择数据库?

A: 本系列支持两种数据库方案:

  • PostgreSQL:功能丰富,适合复杂应用
  • MySQL:轻量快速,适合简单场景
    您可以根据实际需求选择一种,配置方法类似。

一、核心定位

本文作为GitOps环境搭建系列的第一篇,聚焦K3s集群的部署与基础配置。K3s是Rancher Labs推出的轻量级Kubernetes发行版,专为边缘计算、IoT设备和资源受限环境设计。相比标准Kubernetes,K3s具有安装包小(约40MB)、内存占用低、启动快速等优势,是构建轻量级GitOps环境的理想选择。

在GitOps环境中,K3s作为底层容器编排平台,承载所有GitOps组件(Gitea、ArgoCD、Tekton、Harbor等)的运行,提供容器调度、服务发现、存储管理、网络通信等核心能力。

二、部署前置检查

部署前需验证服务器环境,确保满足K3s运行要求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 检查操作系统版本(支持Ubuntu 20.04+/CentOS 7+/RHEL 8+)
cat /etc/os-release

# 2. 检查内核版本(需≥3.10)
uname -r

# 3. 检查内存和存储空间
free -h
df -h /

# 4. 检查网络连通性
ping -c 3 8.8.8.8

# 5. 检查防火墙状态(建议关闭或配置放行规则)
sudo systemctl status firewalld
# 或
sudo ufw status

前置条件检查清单:

  • 操作系统符合要求
  • 内核版本≥3.10
  • 内存≥2GB,存储≥20GB
  • 网络可访问外网(用于拉取镜像)
  • 防火墙已关闭或配置放行规则
  • 已配置sudo权限或root用户

三、K3s集群部署

3.1 Master节点安装

执行以下命令安装K3s Master节点:

1
2
3
4
# 使用国内镜像源加速安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn \
INSTALL_K3S_EXEC='--write-kubeconfig-mode=644' sh -

安装参数说明:

  • INSTALL_K3S_MIRROR=cn:使用中国区镜像源,加速安装过程
  • --write-kubeconfig-mode=644:设置kubeconfig文件权限为644,便于多用户访问
  • --service-node-port-range=1-65535:解除NodePort端口限制(默认30000-32767)
  • --advertise-address=192.168.1.100:指定集群管理IP(替换为实际IP)
  • --disable=traefik:禁用Traefik(如需自定义Traefik配置)
  • --disable=local-path:禁用本地存储(如需使用其他存储方案)

3.2 Worker节点加入集群

在Worker节点执行以下命令加入集群:

1
2
3
4
5
6
7
8
# 获取Master节点的token(在Master节点执行)
sudo cat /var/lib/rancher/k3s/server/node-token

# 在Worker节点执行加入命令(替换<k3s-server-ip>和<token>)
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
K3S_URL=https://<k3s-server-ip>:6443 \
K3S_TOKEN=<token> \
INSTALL_K3S_EXEC='--write-kubeconfig-mode=644' sh -

参数说明:

  • <k3s-server-ip>:Master节点的IP地址
  • <token>:从Master节点获取的加入令牌

3.3 配置kubeconfig

配置kubectl访问凭证:

1
2
3
4
5
6
7
# 设置KUBECONFIG环境变量
echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> ~/.bashrc
source ~/.bashrc

# 验证集群访问
kubectl get nodes
kubectl cluster-info

四、存储配置优化

4.1 修改local-path存储类回收策略

K3s默认使用local-path存储类,其回收策略为Delete(删除Pod时会删除关联的PV)。生产环境建议改为Retain,防止数据误删。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看当前存储类配置
kubectl get storageclasses.storage.k8s.io local-path -o yaml

# 创建修改后的存储类配置
cat > storage-class.yaml << EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
defaultVolumeType: local
storageclass.kubernetes.io/is-default-class: "true"
name: local-path
provisioner: rancher.io/local-path
reclaimPolicy: Retain # 修改为Retain,防止数据误删
volumeBindingMode: WaitForFirstConsumer
EOF

# 应用修改后的存储类
kubectl delete storageclasses.storage.k8s.io local-path
kubectl apply -f storage-class.yaml

4.2 自定义存储路径

如需自定义存储路径,可在安装时指定:

1
2
3
4
# 安装时指定存储路径
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn \
INSTALL_K3S_EXEC='--write-kubeconfig-mode=644 --default-local-storage-path=/mnt/storage/k3s' sh -

五、管理工具安装

5.1 Helm安装

Helm是Kubernetes的包管理工具,后续组件部署将大量使用:

1
2
3
4
5
6
7
8
# 在线安装(推荐)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Ubuntu使用snap安装
sudo snap install helm --classic

# 验证安装
helm version --short

5.2 命令自动补全

配置命令自动补全,提升操作效率:

1
2
3
4
5
6
7
8
9
10
11
# 安装bash-completion
sudo apt install bash-completion
source /usr/share/bash-completion/bash_completion

# kubectl自动补全
echo 'source <(kubectl completion bash)' >> ~/.bashrc
source ~/.bashrc

# helm自动补全
echo 'source <(helm completion bash)' >> ~/.bashrc
source ~/.bashrc

六、私有镜像库配置

K3s支持配置私有镜像库,加速镜像拉取或使用内网镜像仓库:

6.1 配置镜像加速器

1
2
3
4
5
6
7
8
9
10
11
# 创建registries.yaml配置文件
sudo cat > /etc/rancher/k3s/registries.yaml << EOF
mirrors:
"docker.io":
endpoint:
- "https://fogjl973.mirror.aliyuncs.com" # 阿里云镜像加速器
- "https://registry-1.docker.io"
EOF

# 重启K3s使配置生效
sudo systemctl restart k3s

6.2 配置私有Harbor仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置带认证的私有仓库
sudo cat > /etc/rancher/k3s/registries.yaml << EOF
mirrors:
"harbor.example.io": # 替换为您的Harbor域名
endpoint:
- "https://harbor.example.io"
configs:
"harbor.example.io":
auth:
username: admin
password: Harbor12345
tls:
ca_file: /opt/certs/ca.crt # 自签名证书路径
EOF

七、验证部署结果

7.1 基础功能测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 创建测试应用
kubectl create deploy whoami --image=traefik/whoami --replicas=2

# 2. 监控Pod启动状态
kubectl get pods --watch

# 3. 暴露服务
kubectl expose deploy whoami --port=80

# 4. 查看服务状态
kubectl get svc whoami -o wide

# 5. 扩容测试
kubectl scale deploy whoami --replicas=5
kubectl get pods

# 6. 清理测试资源
kubectl delete all --all

7.2 集群状态检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看所有节点状态
kubectl get nodes -o wide

# 查看所有命名空间资源
kubectl get all -A

# 查看核心组件状态
kubectl get pods -n kube-system

# 查看存储类
kubectl get storageclass

# 查看集群事件
kubectl get events --sort-by='.lastTimestamp'

八、常用运维命令

8.1 集群管理

1
2
3
4
5
6
7
8
9
10
11
12
# 查看集群信息
kubectl cluster-info

# 查看节点详细信息
kubectl describe node <node-name>

# 查看节点标签
kubectl get node --show-labels

# 查看资源使用情况
kubectl top nodes
kubectl top pods -A

8.2 应用管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看指定命名空间资源
kubectl get all -n <namespace>

# 查看Pod日志
kubectl logs -n <namespace> <pod-name>
kubectl logs -f -n <namespace> <pod-name> # 实时日志

# 进入Pod容器
kubectl exec -it -n <namespace> <pod-name> -- /bin/bash

# 重启Deployment
kubectl rollout restart deploy/<deploy-name> -n <namespace>

# 查看部署历史
kubectl rollout history deploy/<deploy-name> -n <namespace>

8.3 Helm管理

1
2
3
4
5
6
7
8
9
10
11
# 查看charts的values文件
helm show values bitnami/redis > values.yaml

# 添加Helm仓库
helm repo add <repo-name> <repo-url>

# 更新仓库索引
helm repo update

# 搜索chart
helm search repo <keyword>

九、常见问题修复

问题现象 排查方向 修复方案
节点NotReady 网络/容器运行时 检查网络连通性,重启containerd:sudo systemctl restart containerd
Pod一直Pending 资源不足/存储问题 检查节点资源:kubectl describe pod <pod-name>,查看事件
镜像拉取失败 镜像仓库/网络 检查镜像地址,配置镜像加速器或私有仓库
kubeconfig权限错误 文件权限 设置正确权限:sudo chmod 644 /etc/rancher/k3s/k3s.yaml
Helm安装失败 网络/版本 检查网络,使用国内镜像源或离线安装

十、配置参考

所有配置文件和部署脚本请参考:
https://gitee.com/Chemmy/kube-template/tree/master/devops/k3s

该目录包含:

  • K3s安装脚本
  • 存储类配置
  • 镜像仓库配置
  • 节点加入脚本
  • 生产环境优化配置

总结

本文完成了K3s集群的标准化部署,包括Master节点安装、Worker节点加入、存储配置优化、管理工具安装等核心步骤。K3s作为轻量级Kubernetes发行版,为后续GitOps组件部署提供了稳定可靠的底层平台。

部署完成后,建议进行全面的功能测试,确保集群各项功能正常。下一篇文章将基于此K3s集群,部署Traefik反向代理,为后续组件提供统一的访问入口。

0%