上一篇文章 「K8s 快速上手(一) 在云主机上部署我的服务」 介绍了如何快在云主机上快速的搭建 K3s,并且将一个服务部署到 K3s 中。
这篇文章将介绍如何给部署的服务挂载配置文件或存储盘。
我们同样以上一篇文章的 nginx.yaml
为例,上一篇的 nginx.yaml
文件内容如下:
apiVersion: v1
kind: Namespace
metadata:
name: nginx-1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx-1
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx
namespace: nginx-1
spec:
selector:
app: nginx
type: NodePort
ports:
- nodePort: 30080
port: 8080
protocol: TCP
targetPort: 80
我们想将一个 nginx 配置文件挂载到 /etc/conf.d
目录下,我们这次需要使用到一个 K8s 资源 ConfigMap
。
使用 ConfigMap
能更加方便的管理配置文件并且也能以非常便捷的方式挂载到服务容器中。接下来我就来介绍一下如何使用。
假设我有一个 index.conf
的配置文件和一个 index.html
的文件分别想挂载到 nginx 容器的 /etc/conf.d/default.conf
和 /opt/index.html
目录下。这里的 index.html 只是用于演示,正常的生产环境的前端发布还是将前端文件一起 build 在镜像中才是最佳实践。
index.conf
的文件内容如下:
server {
listen 80;
server_name _;
location / {
root /opt;
index index.html;
}
}
index.html
的文件内容如下:
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello K8s</h1>
</body>
</html>
要挂载这两个文件,首先第一步我们需要创建一个 ConfigMap
资源,我们直接将这个资源也放在 nginx.yaml
文件中,在实际使用中可以按照需要拆分资源到不同的 YAML
文件。ConfigMap
资源的定义如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
namespace: nginx-1
data:
index.conf: |
server {
listen 80;
server_name _;
location / {
root /opt;
index index.html;
}
}
index.html: |
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello K8s</h1>
</body>
</html>
然后修改我们定义的 Deployment
资源,增加 spec.volumes
和 spec.containers[0].volumeMounts
字段,修改后的 Deployment
如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx-1
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d/default.conf
name: nginx-conf
subPath: index.conf
- mountPath: /opt/index.html
name: nginx-conf
subPath: index.html
volumes:
- configMap:
name: nginx-conf
name: nginx-conf
修改完成后使用应用一下 nginx.yaml
文件的变更:
➜ kubectl apply -f nginx.yaml
namespace/nginx-1 created
configmap/nginx-conf created
deployment.apps/nginx created
service/nginx created
通过 kubectl get pod -n nginx-1
查看 nginx
是否部署完成,部署完成后通过浏览器访问就可以看到效果了。
我们可以通过 kubectl logs -n nginx-1 {nginx Pod 的名字} -f
观察 nginx
的日志
假设我们要修改 ConfigMap
,但是在修改后不会直接生效,我们需要重新部署 nginx
,可以通过以下命令重新部署 nginx
:
kubectl rollout restart deployment -n nginx-1 nginx
有时候我们需要通过挂载存储盘将服务中的数据持久化,例如:Mysql。在生产环境中,我们一般不应该直接将机器的存储路径挂载到服务容器中,因为这样就无法做到快速扩容和缩容了,在生产环境中一般会使用云厂商提供的存储盘进行挂载。
但是我们在平常使用并不会购买云厂商的存储盘,所以我这里就以挂载到宿主机的存储路径作为演示。
假设我们需要把容器中的 /var/log/nginx/access.log
和 /var/log/nginx/error.log
挂载到宿主机的目录下。首先我们先修改一下 ConfigMap
文件,将容器的日志打到这两个文件。
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
namespace: nginx-1
data:
index.conf: |
server {
listen 80;
server_name _;
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
location / {
root /opt;
index index.html;
}
}
index.html: |
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello K8s</h1>
</body>
</html>
然后我们需要定义两个 K8s 资源,他们分别是:
PersistentVolume (持久卷,简称PV)是集群内,由管理员提供的网络存储的一部分。就像集群中的计算节点一样,PV也是集群中的一种资源。
PersistentVolumeClaim 持久卷声明,简称 PVC)是用户的一种存储请求。它和 Pod 类似,Pod 消耗 Node 资源,而 PVC 消耗PV资源。
PVC
可以理解为持久化存储的“接口”,它提供了对某种持久化存储的描述,但不提供具体的实现;而这个持久化存储的实现部分则由 PV
负责完成。
我们先为 nginx 定义这两个资源,他们的定义如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
namespace: nginx-1
spec:
storageClassName: manual
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/opt/nginx"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
namespace: nginx-1
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
我们可以先看 PV
资源,我们在 /opt/nginx
下定义了一个存储路径,并且这个 PV
的大小为 2Gi
,他的存储类型是 manual
也就是我们手动维护存储在宿主机的类型,如果使用的是云厂商托管的 K8s,可以查看云厂商支持什么类型。
注意 /opt/nginx
路径必须存在,我们需要提前在服务器创建这个路径。
mkdir -p /opt/nginx
然后我们定义了一个 PVC
资源 ,并且存储类型也是 manual
,并且需求是 1Gi
,注意这里的需求要小于等于你定义的 PV
,前面也提到它类似 Pod
会消耗 Node
的资源,类似我的服务跑多少 CPU 和内存就消耗多少服务器资源,这里就是我需要多少存储就消耗多少存储资源。
接下来就是修改 nginx 的 Deployment
资源,修改后的 Deployment
如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx-1
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d/default.conf
name: nginx-conf
subPath: index.conf
- mountPath: /opt/index.html
name: nginx-conf
subPath: index.html
- mountPath: /var/log/nginx
name: nginx-pvc
volumes:
- configMap:
name: nginx-conf
name: nginx-conf
- persistentVolumeClaim:
claimName: nginx-pvc
name: nginx-pvc
修改完成后应用这个 nginx.yaml
文件:
➜ kubectl apply -f nginx.yaml
namespace/nginx-1 unchanged
configmap/nginx-conf configured
persistentvolume/nginx-pv created
persistentvolumeclaim/nginx-pvc created
deployment.apps/nginx configured
service/nginx unchanged
等待 nginx 部署完成后,通过浏览器访问 nginx 产生日志,然后就可以在宿主机的 /opt/nginx/
目录下看到日志。
cat access.log
10.42.0.0 - - [31/Oct/2020:04:16:22 +0000] "GET / HTTP/1.1" 200 79 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "-"
这篇文章主要讲的是如何为服务挂载配置文件和存储盘,但是在实际的生产环境中,使用存储盘的方式还是有差异的。下一篇文章会介绍如何通过,K8s Ingress 资源通过统一的端口和相应的路由配置向外网暴露服务。