<
K8s 快速上手 (二) 为服务挂载配置文件和存储盘
>
上一篇

K8s 快速上手(一) 在云主机上部署我的服务

没有下一篇咯
Toc
为部署在 K8s(k3s) 的服务挂载配置文件和存储盘

上一篇文章 「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.volumesspec.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 是否部署完成,部署完成后通过浏览器访问就可以看到效果了。

img1

我们可以通过 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 资源,他们分别是:

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 资源通过统一的端口和相应的路由配置向外网暴露服务。

Top
Foot