Nginx-ingress 是使用 Nginx 作为反向代理和负载平衡器的 Kubernetes 的 Ingress 控制器,容器服务 TKE 提供了产品化的能力,可以直接在集群内安装和使用 Nginx-ingress,具体可以参考文档https://cloud.tencent.com/document/product/457/50503
关于nginx-ingress的使用实践可以参考文档https://cloud.tencent.com/developer/article/1768089
使用nginx-ingress,会经常需要查下访问日志来定位问题,nginx-ingress组件也是支持直接将日志采集到腾讯云的cls,nginx-ingress实例默认配置的访问日志是写到容器的/var/log/nginx/nginx_access.log这个日志文件里面,然后配置日志采集规则采集这个日志文件到cls。
但是tke这边提供的nginx-ingress默认是不带日志切割功能的,如果运行时间长,nginx_access.log这个文件会非常大,占用较多的磁盘空间,因为日志是直接写在容器内,最终其实会落在node节点的容器存储目录,占用node节点磁盘空间。
如果容器存储目录没有单独挂盘,一般会直接在系统盘上,这个时候,随着文件增大,系统盘的可用磁盘空间不断减少,这个时候就会触发节点的kubelet的驱逐。 那么这里有什么办法可以解决这个问题,这里其实最终就是需要将nginx-ingress controller容器的/var/log/nginx/nginx_access.log日志文件进行轮转切割就行,因为日志是容器的文件里, 这里的方案是部署一个logrotate的sidecar容器来轮转切割这个日志文件,这来保证日志不会不断增加变得非常大。
下面我们来说下如何在nginx-ingress配置logrotate容器来轮转切割日志。
这里我们采集这个logrotate的镜像
代码语言:javascript复制docker pull realz/logrotate:latest
具体介绍可以参考github https://github.com/hortonworks/docker-logrotate
主要需要在容器配置这几个环境变量
代码语言:javascript复制CRON_EXPR="* * * * *"
LOGROTATE_LOGFILES=/var/lib/docker/containers/*/*.log
LOGROTATE_FILESIZE=10M
LOGROTATE_FILENUM=5
- CRON_EXPR:日志定时切割时间
- LOGROTATE_LOGFILES:需要切割的日志
- LOGROTATE_FILESIZE:日志文件多大就开始切割
- LOGROTATE_FILENUM:最多保留几个日志文件
这里我们是通过emptydir来共享/var/log/nginx/目录,这样logrotate容器可以直接访问nginx_access.log,下面我们说说如何在控制台配置。
首先配置一个数据卷,名称叫做lograte,类型选择使用临时目录,然后controller的容器挂载点挂载这个数据卷
然后添加一个logrotate容器,镜像选择realz/logrotate,挂载点同样挂载lograte这个数据卷,然后添加这4个环境变量,这里是测试配置,最终根据实际需要配置即可。
代码语言:javascript复制CRON_EXPR="* * * * *"
LOGROTATE_LOGFILES=/var/log/nginx/*.log
LOGROTATE_FILESIZE=1M
LOGROTATE_FILENUM=5
配置好之后,直接报错工作负载更新pod即可,完整的yaml如下
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: nginx-intranet-ingress-nginx-controller
qcloud-app: nginx-intranet-ingress-nginx-controller
name: nginx-intranet-ingress-nginx-controller
namespace: kube-system
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: nginx-intranet-ingress-nginx-controller
qcloud-app: nginx-intranet-ingress-nginx-controller
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
k8s-app: nginx-intranet-ingress-nginx-controller
qcloud-app: nginx-intranet-ingress-nginx-controller
name: nginx-intranet-ingress-nginx-controller
namespace: kube-system
spec:
containers:
- args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --ingress-class=nginx-intranet
- --configmap=kube-system/nginx-intranet-ingress-nginx-controller
- --publish-service=kube-system/nginx-intranet-ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
- --tcp-services-configmap=kube-system/nginx-intranet-ingress-nginx-tcp
- --udp-services-configmap=kube-system/nginx-intranet-ingress-nginx-udp
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
image: ccr.ccs.tencentyun.com/paas/nginx-ingress-controller:v0.41.0
imagePullPolicy: Always
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 10254
name: metrics
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
runAsUser: 101
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/local/certificates/
name: webhook-cert
readOnly: true
- mountPath: /var/log/nginx
name: lograte
- env:
- name: LOGROTATE_LOGFILES
value: /var/log/nginx/*.log
- name: CRON_EXPR
value: '* * * * *'
- name: LOGROTATE_FILESIZE
value: 1M
- name: LOGROTATE_FILENUM
value: "5"
image: realz/logrotate
imagePullPolicy: Always
name: logrotate
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
securityContext:
privileged: false
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/log/nginx
name: lograte
dnsPolicy: ClusterFirst
initContainers:
- command:
- sh
- -c
- |-
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w fs.file-max=1048576
image: ccr.ccs.tencentyun.com/tkeimages/busybox:latest
imagePullPolicy: Always
name: setsysctl
resources: {}
securityContext:
privileged: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: nginx-intranet-ingress-nginx
serviceAccountName: nginx-intranet-ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
defaultMode: 420
secretName: nginx-intranet-ingress-nginx-admission
- emptyDir: {}
name: lograte
pod运行后,我们通过ingress访问下后端的服务,生成一下访问日志
隔几分钟后,登陆容器查看日志可以发现日志被切割成多个了
通过上面的配置,我们就成功的通过logrotate切割了nginx-ingress controller的访问日志,并且这样还不影响cls采集日志。