nginx-ingress-controller日志持久化方案的解决

最近看到一篇公众号讲了nginx-ingress-controller的应用。下面有人评论如何做日志持久化,刚好工作上遇到该问题,整理一个方案,仅供参考。

nginx-ingress-controller的日志

nginx-ingress-controller的日志包括三个部分:

  • controller日志: 输出到stdout,通过启动参数中的–log_dir可已配置输出到文件,重定向到文件后会自动轮转,但不会自动清理
  • accesslog:输出到stdout,通过nginx-configuration中的字段可以配置输出到哪个文件。输出到文件后不会自动轮转或清理
  • errorlog:输出到stderr,配置方式与accesslog类似。

给controller日志落盘

  • 给nginx-ingress-controller挂一个hostpath: /data/log/nginx_ingress_controller/ 映射到容器里的/var/log/nginx_ingress_controller/ ,
  • 给nginx-ingress-controller配置log-dir和logtostderr参数,将日志重定向到/var/log/nginx_ingress_controller/中。

controller的日志需要做定时清理。由于controller的日志是通过klog(k8s.io/klog)输出的,会进行日志滚动,所以我们通过脚本定时清理一定时间之前的日志文件即可。

给nginx日志落盘

修改configmap: nginx-configuration。配置accesslog和errorlog的输出路径,替换默认的stdout和stderr。输出路径我们可以与controller一致,便于查找。

accesslog和errorlog都只有一个日志文件,我们可以使用logrotate进行日志轮转,将输出到宿主机上的日志进行轮转和清理。配置如:

$ cat /etc/logrotate.d/nginx.log
/data/log/nginx_ingress_controller/access.log {
  su root list
  rotate 7
  daily
  maxsize 50M
  copytruncate
  missingok
  create 0644 www-data root
}

官方提供的模板中,nginx-ingress-controller默认都是以33这个用户登录启动容器的,因此挂载hostpath路径时存在权限问题。我们需要手动在机器上执行chown -R 33:33 /data/log/nginx_ingress_controller.

自动化ops

nginx日志落盘中,第2、3两点均需要人工运维,有什么解决办法吗?

问题的关键是:有什么办法可以在nginx-ingress-controller容器启动之前加一个hook,将宿主机的指定目录执行chown呢?

可以用initContainer。initcontainer必须在containers中的容器运行前运行完毕并成功退出。利用这一k8s特性,我们开发一个docker image,里面只执行如下脚本:

#!/bin/bash
logdir=$LOG_DIR
userID=$USER_ID
echo "try to set dir: $logdir 's group as $userID"
chown -R $userID:$userID $logdir

脚本读取一些环境变量, 确认需要修改哪个目录,改成怎样的user group。

将脚本打包成dockerimage, 放在nginx-ingress-controller的deploy yaml中,作为initcontainers。 注意要对该initcontainer配置环境变量和volumeMount.

再说第二点,我们注意到nginx-ingress-controller的基础镜像中就自带了logrotate,那么问题就简单了,我们将写好的logrotate配置文件以configmap的形式挂载到容器中就可以了。

一个deploy yaml如下:

---
apiVersion: v1
kind: Service
metadata:
 name: ingress-nginx
 namespace: kube-system
spec:
 type: ClusterIP
 ports:
 - name: http
  port: 80
  targetPort: 80
  protocol: TCP
 - name: https
  port: 443
  targetPort: 443
  protocol: TCP
 selector:
  app: ingress-nginx
---
apiVersion: v1
kind: Service
metadata:
 name: default-http-backend
 namespace: kube-system
 labels:
  app: default-http-backend
spec:
 ports:
 - port: 80
  targetPort: 8080
 selector:
  app: default-http-backend
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: default
 namespace: kube-system
spec:
 backend:
  serviceName: default-http-backend
  servicePort: 80
---
kind: ConfigMap
apiVersion: v1
metadata:
 name: nginx-configuration
 namespace: kube-system
 labels:
  app: ingress-nginx
data:
 use-forwarded-headers: "true"
 # 此处配置nginx日志的重定向目标
 access-log-path: /var/log/nginx_ingress_controller/access.log
 error-log-path: /var/log/nginx_ingress_controller/error.log

---

# 创建一个configmap,配置nginx日志的轮转策略,对应的是nginx日志在容器内的日志文件
apiVersion: v1
data:
 nginx.log: |
  {{ user_nginx_log.host_path }}/access.log {
    rotate {{ user_nginx_log.rotate_count }}
    daily
    maxsize {{ user_nginx_log.rotate_size }}
    minsize 10M
    copytruncate
    missingok
    create 0644 root root
  }
  {{ user_nginx_log.host_path }}/error.log {
    rotate {{ user_nginx_log.rotate_count }}
    daily
    maxsize {{ user_nginx_log.rotate_size }}
    minsize 10M
    copytruncate
    missingok
    create 0644 root root
  }
kind: ConfigMap
metadata:
 name: nginx-ingress-logrotate
 namespace: kube-system
---

kind: ConfigMap
apiVersion: v1
metadata:
 name: tcp-services
 namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
 name: udp-services
 namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: nginx-ingress-serviceaccount
 namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
 name: nginx-ingress-clusterrole
rules:
 - apiGroups:
   - ""
  resources:
   - configmaps
   - endpoints
   - nodes
   - pods
   - secrets
  verbs:
   - list
   - watch
 - apiGroups:
   - ""
  resources:
   - nodes
  verbs:
   - get
 - apiGroups:
   - ""
  resources:
   - services
  verbs:
   - get
   - list
   - watch
 - apiGroups:
   - "extensions"
  resources:
   - ingresses
  verbs:
   - get
   - list
   - watch
 - apiGroups:
   - ""
  resources:
    - events
  verbs:
    - create
    - patch
 - apiGroups:
   - "extensions"
  resources:
   - ingresses/status
  verbs:
   - update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
 name: nginx-ingress-role
 namespace: kube-system
rules:
 - apiGroups:
   - ""
  resources:
   - configmaps
   - pods
   - secrets
   - namespaces
  verbs:
   - get
 - apiGroups:
   - ""
  resources:
   - configmaps
  resourceNames:
   # Defaults to "<election-id>-<ingress-class>"
   # Here: "<ingress-controller-leader>-<nginx>"
   # This has to be adapted if you change either parameter
   # when launching the nginx-ingress-controller.
   - "ingress-controller-leader-nginx"
  verbs:
   - get
   - update
 - apiGroups:
   - ""
  resources:
   - configmaps
  verbs:
   - create
 - apiGroups:
   - ""
  resources:
   - endpoints
  verbs:
   - get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
 name: nginx-ingress-role-nisa-binding
 namespace: kube-system
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: Role
 name: nginx-ingress-role
subjects:
 - kind: ServiceAccount
  name: nginx-ingress-serviceaccount
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
 name: nginx-ingress-clusterrole-nisa-binding
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: nginx-ingress-clusterrole
subjects:
 - kind: ServiceAccount
  name: nginx-ingress-serviceaccount
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: ingress-nginx
 namespace: kube-system
spec:
 selector:
  matchLabels:
   app: ingress-nginx
 template:
  metadata:
   labels:
    app: ingress-nginx
   annotations:
    prometheus.io/port: '10254'
    prometheus.io/scrape: 'true'
  spec:
   serviceAccountName: nginx-ingress-serviceaccount
   tolerations:
   - key: dedicated
    value: ingress-nginx
    effect: NoSchedule
   affinity:
    nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
       - key: "system/ingress"
        operator: In
        values:
        - "true"
   dnsPolicy: ClusterFirstWithHostNet
   hostNetwork: true
   # 配置initcontainer,确保在nginx-ingress-controller容器启动前将日志目录的权限配置好
   initContainers:
   - name: adddirperm
    image: "{{ image_registry.addr }}/{{ image.adddirperm }}"
    env:
    - name: LOG_DIR
     value: /var/log/nginx_ingress_controller
    - name: USER_ID
      value: "33"
    volumeMounts:
    - name: logdir
     mountPath: /var/log/nginx_ingress_controller
   containers:
   - name: nginx-ingress-controller
    image: "{{ image_registry.addr }}/{{ image.ingress }}"
    imagePullPolicy: IfNotPresent
    args:
    - /nginx-ingress-controller
    - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
    - --configmap=$(POD_NAMESPACE)/nginx-configuration
    - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
    - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
    - --publish-service=$(POD_NAMESPACE)/ingress-nginx
    - --annotations-prefix=nginx.ingress.kubernetes.io

    # 设置controller日志的输出路径和方式
    - --log_dir=/var/log/nginx_ingress_controller
    - --logtostderr=false
    securityContext:
     capabilities:
       drop:
       - ALL
       add:
       - NET_BIND_SERVICE
     # www-data -> 33
     runAsUser: 33
    env:
     - name: POD_NAME
      valueFrom:
       fieldRef:
        fieldPath: metadata.name
     - name: POD_NAMESPACE
      valueFrom:
       fieldRef:
        fieldPath: metadata.namespace
    ports:
    - name: http
     containerPort: 80
    - name: https
     containerPort: 443
    resources:
     requests:
      cpu: 100m
      memory: 256Mi
    livenessProbe:
     failureThreshold: 3
     httpGet:
      path: /healthz
      port: 10254
      scheme: HTTP
     initialDelaySeconds: 10
     periodSeconds: 10
     successThreshold: 1
     timeoutSeconds: 1
    readinessProbe:
     failureThreshold: 3
     httpGet:
      path: /healthz
      port: 10254
      scheme: HTTP
     periodSeconds: 10
     successThreshold: 1
     timeoutSeconds: 1
    volumeMounts:
    # 配置挂载容器中控制器组件和nginx的日志输出路径
    - name: logdir
     mountPath: /var/log/nginx_ingress_controller
    # 配置nginx日志的logrotate配置挂载路径
    - name: logrotateconf
     mountPath: /etc/logrotate.d/nginx.log
     subPath: nginx.log
   volumes:
   # 控制器组件和nginx的日志输出路径为宿主机的hostpath
   - name: logdir
    hostPath:
     path: {{ user_nginx_log.host_path }}
     type: ""
   # nginx日志的轮转配置文件来自于configmap
   - name: logrotateconf
    configMap:
     name: nginx-ingress-logrotate
     items:
     - key: nginx.log
      path: nginx.log
---

apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: default-http-backend
 namespace: kube-system
 labels:
  app: default-http-backend
spec:
 selector:
  matchLabels:
   app: default-http-backend
 template:
  metadata:
   labels:
    app: default-http-backend
  spec:
   terminationGracePeriodSeconds: 60
   tolerations:
   - key: dedicated
    value: ingress-nginx
    effect: NoSchedule
   affinity:
    nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
       - key: "system/ingress"
        operator: In
        values:
        - "true"
   containers:
   - name: default-http-backend
    # Any image is permissible as long as:
    # 1. It serves a 404 page at /
    # 2. It serves 200 on a /healthz endpoint
    image: "{{ image_registry.addr }}/{{ image.http_backend }}"
    imagePullPolicy: IfNotPresent
    livenessProbe:
     httpGet:
      path: /healthz
      port: 8080
      scheme: HTTP
     initialDelaySeconds: 30
     timeoutSeconds: 5
    ports:
    - containerPort: 8080
    resources:
     limits:
      cpu: 10m
      memory: 20Mi
     requests:
      cpu: 10m
      memory: 20Mi
---

最后,有的人建议将initcontainer去掉,改为基于原有的nginx-ingress-controller镜像加一层layer,将配置路径权限的脚本放在该层执行。 个人认为这种方法既不美观,也不方便。唯一的好处仅在于deploy yaml仍然简洁(但少不了volumeMount之类的配置)。不过还是看个人使用感受吧~

到此这篇关于nginx-ingress-controller日志持久化方案的解决的文章就介绍到这了,更多相关nginx ingress controller日志持久化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Nginx日志统计分析的常用命令总结

    本文主要给大家总结了关于Nginx日志统计分析的一些常用命令,分享出来供大家参考学习,下面来一起看看详细的介绍: 一.IP相关统计 统计IP访问量 awk '{print $1}' access.log | sort -n | uniq | wc -l 查看某一时间段的IP访问量(4-5点) grep "07/Apr/2017:0[4-5]" access.log | awk '{print $1}' | sort | uniq -c| sort -nr | wc -l 查看访问最频繁

  • Nginx日志按日期切割详解(按天切割)

    实现需求 本文实现的功能是在吗每天凌晨00:00把前一天的Nginx日志access.log重命名为access-xxxx-xx-xx.log格式,例如:access-2016-10-01.log,下面话不多说了,来看看详细的实现方法吧. 实现方法 脚本 vim /opt/nginx/cut_nginx_log.sh #!/bin/bash #此脚本用于自动分割Nginx的日志,包括access.log和error.log #每天00:00执行此脚本 将前一天的access.log重命名为acc

  • nginx服务器中access_log日志分析与配置详解

    前言 nginx的log日志分为:access log 和 error log 其中access log 记录了哪些用户,哪些页面以及用户浏览器.ip和其他的访问信息 error log 则是记录服务器错误日志 log_format 日志格式语法: log_format name(格式名字) 格式样式(即想要得到什么样的日志内容) 示例: log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$

  • nginx日志中添加请求的response日志(推荐)

    由于此功能在nginx内置的功能中没有,需要安装第三方模块ngx_lua,由于此模块需要Lua语言,所以需要安装相应的Lua语言包 1. 下载安装LuaJIT # cd /usr/local/src # wget http://luajit.org/download/LuaJIT-2.0.2.tar.gz # tar -xzvf LuaJIT-2.0.2.tar.gz # cd LuaJIT-2.0.2 # make 出现如下内容表示编译成功 OK Successfully built LuaJ

  • nginx日志配置指令详解

    日志对于统计排错来说非常有利的.本文总结了nginx日志相关的配置如access_log.log_format.open_log_file_cache.log_not_found.log_subrequest.rewrite_log.error_log. nginx有一个非常灵活的日志记录模式.每个级别的配置可以有各自独立的访问日志.日志格式通过log_format命令来定义.ngx_http_log_module是用来定义请求日志格式的. 1. access_log指令 语法: access_

  • 实现Nginx中使用PHP-FPM时记录PHP错误日志的配置方法

    nginx与apache不一样,在apache中可以直接指定php的错误日志,那样在php执行中的错误信息就直接输入到php的错误日志中,可以方便查询. 在nginx中事情就变成了这样:nginx只对页面的访问做access记录日志.不会有php的error log 信息.nginx把对php的请求发给php-fpm fastcgi进程来处理,默认的php-fpm只会输出php-fpm的错误信息,在php-fpm的errors log里也看不到php的errorlog. 原因是php-fpm的配

  • nginx日志切割shell脚本

    一.脚本思路 第一步就是重命名日志文件,不用担心重命名后nginx找不到日志文件而丢失日志.在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,linux是靠文件描述符而不是文件名定位文件. 第二步向nginx主进程发送USR1信号. nginx主进程接到信号后会从配置文件中读取日志文件名称,重新打开日志文件(以配置文件中的日志名称命名),并以工作进程的用户作为日志文件的所有者. 重新打开日志文件后,nginx主进程会关闭重名的日志文件并通知工作进程使用新打开的日志文件.

  • nginx关闭favicon.ico、robots.txt日志记录配置

    nginx日志最近发生大量访问favicon.ico无法找到的404错误日志,小编感觉很影响服务器性能,对于一个高并发的服务器每一个错误都会影响性能,所以需要关闭访问favicon.ico的日志记录功能. 复制代码 代码如下: # 把以下配置放到 server {} 块. #关闭favicon.ico不存在时记录日志location = /favicon.ico {log_not_found off;access_log off;} location = /robots.txt {allow a

  • nginx中用JSON格式记录日志的配置示例

    nginx的日志配置可以参见<nginx日志配置指令详解>一文.如果要想以json格式记录nginx日志以便logstash分析,该如何指定日志格式呢?可以按照下面的格式来实现. 定义nginx日志格式: 复制代码 代码如下: log_format logstash_json '{ "@timestamp": "$time_local", '                          '"@fields": { '      

  • PHP连接Nginx服务器并解析Nginx日志的方法

    php与nginx整合 PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀:同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析. FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担

  • nginx php-fpm中启用慢日志配置(用于检测执行较慢的PHP脚本)

    很多站长转到nginx+php-fpm后,饱受500,502问题困扰.当nginx收到如上错误码时,可以确定后端php-fpm解析php出了某种问题,比如,执行错误,执行超时. php-fpm.conf的配置文件中有一个参数request_slowlog_timeout是这样描述的 复制代码 代码如下: ; The timeout for serving a single request after which a PHP backtrace will be; dumped to the 'sl

随机推荐