ConfigMap
ConfigMap
目录
[toc]
本节实战
实战项目 |
---|
💘 实战:yaml中|和>测试-2023.1.10(测试成功) |
💘 实战:ConfigMap创建测试-2023.1.8(测试成功) |
💘 实战:使用 ConfigMap 来填充我们的环境变量-2023.1.14(测试成功) |
💘 实战:使用 ConfigMap来设置命令行参数-2023.1.14(测试成功) |
💘 实战:通过数据卷来使用ConfigMap-2023.1.14(测试成功) |
💘 实战:在 ConfigMap 值被映射的数据卷里去控制路径-items-2023.1.14(测试成功) |
💘 实战:ConfigMap里使用SubPath-2023.1.14(测试成功) |
💘 实战:ConfigMap里使用subPathExpr-2023.1.15(测试成功) |
💘 实战:不可变更的 ConfigMap-2023.1.15(测试成功) |
前言
前面我们学习了一些常用的资源对象的使用,但是单纯依靠这些资源对象,还不足以满足我们的日常需求,一个重要的需求就是应用的配置管理、敏感信息的存储和使用(如:密码、Token 、私钥等)、安全管控、身份认证等等。
对于应用的可变配置在 Kubernetes 中是通过一个 ConfigMap 资源对象来实现的,ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时 Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。。不过需要注意 ConfigMap 并不提供保密或者加密功能。如果你想存储的数据是机密的,则可以使用 Secret 对象,或者使用其他第三方工具来保证你的数据的私密性,而不是用 ConfigMap。
我们知道许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息的需求,这些配置信息我们肯定不会直接写死到应用程序中去的,比如你一个应用连接一个 redis 服务,下一次想更换一个了的,还得重新去修改代码,重新制作一个镜像,这肯定是不可取的。而 ConfigMap 就给我们提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,还可以用来保存整个配置文件,比如我们可以用来配置一个 redis 服务的访问地址,也可以用来保存整个 redis 的配置文件等等。
值得注意的是 ConfigMap 虽然也是一个 K8s 资源对象,但是和其他 Kubernetes 对象都有一个 spec 属性不同的是,ConfigMap 使用 data 和 binaryData 字段,这些字段能够接收键值对作为其值,data 和 binaryData 字段都是可选的,data 字段设计用来保存 UTF-8 字符串,而 binaryData 则被设计用来保存二进制数据作为 base64编码的字串。data 或 binaryData 字段下面的每个键的名称都必须由字母数字字符或者 -、_ 或 .组成,在data 下保存的键名不可以与在 binaryData 下出现的键名有重叠。此外从 v1.19 版本开始,我们还可以添加一个immutable 字段到 ConfigMap 对象中,用于创建不可变更的 ConfigMap。
应用程序配置文件存储:ConfigMap的应用场景。
- 将应用程序配置文件解耦出来,存放在k8s中。
- 根据不同的业务环境,存放不同的应用配置文件。
你可以整一个nginx镜像,把它的配置文件给分离出来并存储到k8s的ConfigMap里面,然后再挂载到pod里进行使用。
1、创建
⚠️ yaml里易混淆的点
ConfigMap对象yaml文件:
apiVersion:v1kind:ConfigMapmetadata:name:cm-demonamespace:defaultdata:data.1:hellodata.2:worldconfig:|property.1=value-1property.2=value-2property.3=value-3
⚠️ 注意:以下3种用法可能会比较容易混淆,多看几次就能记清楚了。(一般使用||-
2种用法就足够了)
(1)|
用法
我们可以看到 config 后面有一个竖线符 |,这在 yaml 中表示保留换行,(最后一行的空白和换行符会被取掉,前面换行被被保留),而额外的缩进会被保留。
lines:|我是第一行我是第二行我是吴彦祖我是第四行我是第五行# JSON{"lines":"我是第一行\n我是第二行\n我是吴彦祖\n我是第四行\n我是第五行"}
(2)|+
和|-
用法
我们还可以使用竖线和加号或者减号进行配合使用,+ 表示保留文字块末尾的换行,- 表示删除字符串末尾的换行。
value:|hellohello# {"value":"hello\nhello"}value:|-hello# {"value":"hello"}value:|+hello# {"value":"hello\n\n"} (有多少个回车就有多少个\n)
(3)>
用法
使用 >右尖括号,用来表示折叠换行,只有空白行才会被识别为换行,原来的换行符都会被转换成空格。
lines:>我是第一行我也是第一行我仍是第一行我依旧是第一行我是第二行这么巧我也是第二行# JSON{"lines":"我是第一行 我也是第一行 我仍是第一行 我依旧是第一行\n我是第二行 这么巧我也是第二行"}
💘 实战:yaml中|和>测试-2023.1.10(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:ConfigMapmetadata:name:cm-demonamespace:defaultdata:data.1:hellodata.2:worldconfig:|property.1=value-1property.2=value-2property.3=value-3lines:>我是第一行我也是第一行我仍是第一行我依旧是第一行我是第二行这么巧我也是第二行
- 部署并测试
奇怪:这里不是第一次部署嘛?annotations这里为什么还会显示last-applied-configuration
呢?……😢
总感觉这里的演示情况和前面理论部分有点出入:……😢
前面的理论部分:
这里关于细节部分,还是有点疑惑……先就这样吧。
测试结束。😘
1.通过资源清单文件方法创建ConfigMap
ConfigMap 资源对象使用 key-value 形式的键值对来配置数据,这些数据可以在 Pod 里面使用,如下所示的资源清单:
apiVersion:v1kind:ConfigMapmetadata:name:cm-demonamespace:defaultdata:data.1:hellodata.2:worldconfig:|property.1=value-1property.2=value-2property.3=value-3
其中配置数据在 data 属性下面进行配置,前两个被用来保存单个属性,后面一个被用来保存一个配置文件。
当然同样的我们可以使用kubectl create -f xx.yaml来创建上面的 ConfigMap 对象。
- 注意:这里的key和value一定都是字符串
binaryData <map[string]string>
2.通过from-file关键字创建ConfigMap
但是如果我们不知道怎么创建 ConfigMap 的话,不要忘记 kubectl 是我们最好的帮手,可以使用kubectl create configmap -h来查看关于创建 ConfigMap 的帮助信息:
[root@master1 ~]#kubectl create configmap --helpCreateaconfigmapbasedonafile,directory,orspecifiedliteralvalue.……Examples:# Create a new configmap named my-config based on folder barkubectlcreateconfigmapmy-config--from-file=path/to/bar# Create a new configmap named my-config with specified keys instead of file basenames on diskkubectlcreateconfigmapmy-config--from-file=key1=/path/to/bar/file1.txt--from-file=key2=/path/to/bar/file2.txt# Create a new configmap named my-config with key1=config1 and key2=config2kubectlcreateconfigmapmy-config--from-literal=key1=config1--from-literal=key2=config2
💘 实战:ConfigMap创建测试-2023.1.8(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:mkdirtestcmcdtestcm/echohost=127.0.0.1>redis.confechoport=6379>>redis.confechohost=127.0.0.1>mysql.confechoport=3306>>mysql.confcatredis.confcatmysql.conf
(1)from-file 关键字:使用指定的目录进行创建 ConfigMap
- 然后,我们就可以使用 from-file 关键字来创建包含这个目录下面所有配置文件的 ConfigMap:
[root@master1 ~]#kubectl create cm cm-demo1 --from-file=testcm/configmap/cm-demo1created
其中 from-file 参数指定在该目录下面的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
- 创建完成后,同样我们可以使用如下命令来查看 ConfigMap 列表:
[root@master1 ~]#kubectl get cmNAMEDATAAGEcm-demo1246s
- 可以看到已经创建了一个 cm-demo1 的 ConfigMap 对象,然后可以使用 describe 命令查看详细信息:
[root@master1 ~]#kubectl describe cm cm-demo1Name:cm-demo1Namespace:defaultLabels:<none>Annotations:<none>Data====mysql.conf:----host=127.0.0.1port=3306redis.conf:----host=127.0.0.1port=6379BinaryData====Events:<none>
我们可以看到两个 key 是 testcm 目录下面的文件名称,对应的 value 值就是文件内容。
- 这里值得注意的是如果文件里面的配置信息很大的话,describe 的时候可能不会显示对应的值,要查看完整的键值,可以使用如下命令:
[root@master1 ~]#kubectl get cm cm-demo1 -oyamlapiVersion:v1data:mysql.conf:|host=127.0.0.1port=3306redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:55:22Z"name:cm-demo1namespace:defaultresourceVersion:"901730"uid:cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
(2)from-file 关键字:使用指定的文件进行创建 ConfigMap
除了通过文件目录进行创建,我们也可以使用指定的文件进行创建 ConfigMap。
- 同样的,以上面的配置文件为例,我们创建一个 redis 的配置的一个单独 ConfigMap 对象:
[root@master1 ~]#kubectl create cm cm-demo2 --from-file=testcm/redis.conf-ndefaultconfigmap/cm-demo2created
- 查看
[root@master1 ~]#kubectl get cm cm-demo2NAMEDATAAGEcm-demo2117s[root@master1 ~]#kubectl get cm cm-demo2 -oyamlapiVersion:v1data:redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:59:11Z"name:cm-demo2namespace:defaultresourceVersion:"902076"uid:95b6f6ed-977a-4830-8124-2ce28a61eb96
我们可以看到一个关联 redis.conf 文件配置信息的 ConfigMap 对象创建成功了。
- 另外值得注意的是 --from-file 这个参数可以使用多次,比如我们这里使用两次分别指定 redis.conf 和 mysql.conf 文件,就和直接指定整个目录是一样的效果了。
[root@master1 ~]#kubectl create cm cm-demo22 --from-file=testcm/redis.conf--from-file=testcm/mysql.conf-ndefaultconfigmap/cm-demo22created[root@master1 ~]#kubectl get cm cm-demo22NAMEDATAAGEcm-demo22210s[root@master1 ~]#kubectl get cm cm-demo22 -oyamlapiVersion:v1data:mysql.conf:|host=127.0.0.1port=3306redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T14:01:14Z"name:cm-demo22namespace:defaultresourceVersion:"902262"uid:b044c573-35dc-4867-86ff-4d7cc07faa1b
(3)from-file 关键字:使用字符串进行创建ConfigMap
- 另外,通过帮助文档我们可以看到我们还可以直接使用字符串进行创建,通过 --from-literal 参数传递配置信息,同样的,这个参数可以使用多次,格式如下:
[root@master1 ~]#kubectl create configmap cm-demo3 --from-literal=db.host=localhost--from-literal=db.port=3306configmap/cm-demo3created[root@master1 ~]#kubectl get cm cm-demo3 -oyamlapiVersion:v1data:db.host:localhostdb.port:"3306"#注意:这里的数字用引号阔起来了,被当做是字符串来处理kind:ConfigMapmetadata:creationTimestamp:"2023-01-10T13:41:55Z"name:cm-demo3namespace:defaultresourceVersion:"905135"uid:b10d8e47-c9bf-46d1-8868-914f18ea490d
注意:一般数据较小的话,可以直接在资源配置清单里写一下,数据量比较大的话,就可以写到文件里进行创建使用。
测试结束。😘
2、使用
ConfigMap 创建成功了,那么我们应该怎么在 Pod 中来使用呢?我们可以使用四种方式来使用 ConfigMap 配置 Pod中的容器:
- 在容器命令和参数内
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
这些不同的方法适用于不同的数据使用方式,对前三个方法,kubelet 会使用 ConfigMap 中的数据在 Pod 中启动容器。第四种方法需要编写代码才能读取 ConfigMap 数据。
1.使用 ConfigMap 来填充我们的环境变量
💘 实战:使用 ConfigMap 来填充我们的环境变量-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:Podmetadata:name:testcm1-podspec:containers:- name:testcm1image:busyboxcommand:["/bin/sh","-c","env"]env:#注意:这里是env方式- name:DB_HOSTvalueFrom:configMapKeyRef:#这里Ref翻译为引用name:cm-demo3key:db.host#注意:这个db.host仅仅只是cm-demo3这个ConnfigMap里的Key.- name:DB_PORTvalueFrom:configMapKeyRef:name:cm-demo3key:db.portenvFrom:#注意:这里是envFrom方式- configMapRef:name:cm-demo1
- 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo1 -oyamlapiVersion:v1data:mysql.conf:|host=127.0.0.1port=3306redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:55:22Z"name:cm-demo1namespace:defaultresourceVersion:"901730"uid:cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d[root@master1 ~]#kubectl get cm cm-demo3 -oyamlapiVersion:v1data:db.host:localhostdb.port:"3306"kind:ConfigMapmetadata:creationTimestamp:"2023-01-10T13:41:55Z"name:cm-demo3namespace:defaultresourceVersion:"905135"uid:b10d8e47-c9bf-46d1-8868-914f18ea490d
- 部署上面的testcm1-pod.yaml并查看
[root@master1 ~]#kubectl apply -f testcm1-pod.yamlpod/testcm1-podcreated[root@master1 ~]#kubectl get poNAMEREADYSTATUSRESTARTSAGEtestcm1-pod0/1Completed2(26s ago) 28s#这个 Pod 运行后会输出如下所示的信息:[root@master1 ~]#kubectl logs testcm1-podKUBERNETES_PORT=tcp:KUBERNETES_SERVICE_PORT=443HOSTNAME=testcm1-podDB_PORT=3306#这里SHLVL=1HOME=/rootmysql.conf=host=127.0.0.1#特别,注意下这里:这里的key:value是一个整体,是作为文件名`mysql.conf`的value的;port=3306redis.conf=host=127.0.0.1#这里port=6379KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binKUBERNETES_PORT_443_TCP_PORT=443KUBERNETES_PORT_443_TCP_PROTO=tcpKUBERNETES_PORT_443_TCP=tcp:KUBERNETES_SERVICE_PORT_HTTPS=443KUBERNETES_SERVICE_HOST=10.96.0.1PWD=/DB_HOST=localhost#这里
我们可以看到 DB_HOST 和 DB_PORT 都已经正常输出了,另外的环境变量是因为我们这里直接把 cm-demo1 给注入进来了,所以把他们的整个键值给输出出来了,这也是符合预期的。
符合预期,测试完成。😘
2.使用 ConfigMap来设置命令行参数
另外我们也可以使用 ConfigMap 来设置命令行参数,ConfigMap 也可以被用来设置容器中的命令或者参数值,如下Pod:
💘 实战:使用 ConfigMap来设置命令行参数-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:Podmetadata:name:testcm2-podspec:containers:- name:testcm2image:busyboxcommand:["/bin/sh","-c","echo $(DB_HOST) $(DB_PORT)"]env:- name:DB_HOSTvalueFrom:configMapKeyRef:name:cm-demo3key:db.host- name:DB_PORTvalueFrom:configMapKeyRef:name:cm-demo3key:db.port
- 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo3 -oyamlapiVersion:v1data:db.host:localhostdb.port:"3306"kind:ConfigMapmetadata:creationTimestamp:"2023-01-10T13:41:55Z"name:cm-demo3namespace:defaultresourceVersion:"905135"uid:b10d8e47-c9bf-46d1-8868-914f18ea490d
- 部署并查看
[root@master1 ~]#kubectl apply -f testcm2-pod.yamlpod/testcm2-podcreated#运行这个 Pod 后会输出如下信息:[root@master1 ~]#kubectl logs testcm2-podlocalhost3306
测试结束。😘
🍀 问题
注意:有的同学可能会说,既然我可以在容器中的命令行参数里使用这个变量,那么我是否可以在我的ConfigMap里去使用我的环境变量呢?
3.通过数据卷来使用ConfigMap
另外一种是非常常见的使用 ConfigMap 的方式:通过数据卷使用,在数据卷里面使用 ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。
💘 实战:通过数据卷来使用ConfigMap-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:Podmetadata:name:testcm3-podspec:volumes:- name:config-volumeconfigMap:name:cm-demo2containers:- name:testcm3image:busyboxcommand:["/bin/sh","-c","cat /etc/config/redis.conf"]volumeMounts:- name:config-volumemountPath:/etc/config
- 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo2 -oyamlapiVersion:v1data:redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:59:11Z"name:cm-demo2namespace:defaultresourceVersion:"902076"uid:95b6f6ed-977a-4830-8124-2ce28a61eb96
- 部署并测试
[root@master1 ~]#kubectl apply -f testcm3-pod.yamlpod/testcm3-podcreated[root@master1 ~]#kubectl logs testcm3-podhost=127.0.0.1port=6379
符合预期,测试结束。😘
💘 实战:在 ConfigMap 值被映射的数据卷里去控制路径-items-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:Podmetadata:name:testcm4-podspec:volumes:- name:config-volumeconfigMap:name:cm-demo1items:- key:mysql.confpath:path/to/msyql.confcontainers:- name:testcm4image:busyboxcommand:["/bin/sh","-c","cat /etc/config/path/to/msyql.conf"]volumeMounts:- name:config-volumemountPath:/etc/config
- 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo1 -oyamlapiVersion:v1data:mysql.conf:|host=127.0.0.1port=3306redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:55:22Z"name:cm-demo1namespace:defaultresourceVersion:"901730"uid:cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
- 部署并测试
[root@master1 ~]#kubectl apply -f testcm4-podpod/testcm4-podcreated[root@master1 ~]#kubectl logs testcm4-podhost=127.0.0.1port=3306
符合预期,测试结束。😘
⚠️ ConfigMap热更新&应用热更新
另外需要注意的是,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新。。这时可以增加一些监测配置文件变更的脚本,然后重加载对应服务就可以实现应用的热更新。以环境变量方式使用的ConfigMap 数据不会被自动更新,更新这些数据需要重新启动 Pod。
只有通过 Kubernetes API 创建的 Pod 才能使用 ConfigMap,其他方式创建的(比如静态 Pod)不能使用;ConfigMap 文件大小限制为 1MB(ETCD 的要求)。
💘 实战:测试ConfigMap热更新-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:Podmetadata:name:testcm5-podspec:volumes:- name:config-volumeconfigMap:name:cm-demo1items:- key:mysql.confpath:path/to/msyql.confcontainers:- name:testcm4image:busyboxcommand:["/bin/sh","-c","cat /etc/config/path/to/msyql.conf;sleep 24h"]volumeMounts:- name:config-volumemountPath:/etc/config
- 查看之前的cm
[root@master1 ~]#kubectl get cm cm-demo1 -oyamlapiVersion:v1data:mysql.conf:|host=127.0.0.1port=3306redis.conf:|host=127.0.0.1port=6379kind:ConfigMapmetadata:creationTimestamp:"2023-01-08T13:55:22Z"name:cm-demo1namespace:defaultresourceVersion:"901730"uid:cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
- 部署资源并查看
[root@master1 ~]#kubectl apply -f testcm5-pod.yamlpod/testcm5-podcreated[root@master1 ~]#kubectl logs testcm5-podhost=127.0.0.1port=3306
- 更新configmap里的信息
[root@master1 ~]#kubectl edit cm cm-demo1#将3306改成3307
- 查看pod打印日志及pod里的文件是否发生了变化
[root@master1 ~]#kubectl logs testcm5-podhost=127.0.0.1port=3306[root@master1 ~]#kubectl exec -it testcm5-pod -- cat /etc/config/path/to/msyql.confhost=127.0.0.1port=3307
可以看到pod打印日志依然是3306,但pod容器里的文件已经发生了变化,符合预期。
测试结束。😘
🍀 问题:ConfigMap支持动态更改吗?pod启动后,更改ConfigMap。
大佬回答:
支持的。我记得大概有1min多的延迟,相当于任何的ConfigMap如果mount到pod里面,那么会有一个什么样的动作呢? 它会把这个ConfigMap从apiserver下下来,然后放在本地docker的一个DRI里面,然后通过docker的mount mount到里面去。只要你的应用进程支持本地文件刷新的时候,它会重新去load,那么就可以动态更改。注意:(关键看你的应用支不支持热加载!)
3、使用SubPath
1.subPath
上面我们介绍了可以将 ConfigMap 以数据卷的形式挂载到容器中去,但是如果原本容器目录下已经有一些文件或者数据,将数据挂载进去后便会覆盖容器目录下的数据,这个时候我们可以指定 volumeMounts.subPath 属性来指定卷内的子路径,而不是其根路径。
注意:
subPath形式挂载的数据不能热更新,除非重建Pod。()
💘 实战:ConfigMap里使用SubPath-2023.1.14(测试成功)
- 实验环境
实验环境:1、win10,vmwrokstation虚机;2、k8s集群:3台centos7.61810虚机,1个master节点,2个node节点k8sversion:v1.25.4containerd:apiVersion:v1kind:ConfigMapmetadata:name:nginx-confignamespace:defaultdata:nginx.conf:|user nginx;worker_processes auto;error_log /var/log/nginx/error.log notice;pid /var/run/nginx.pid;events {worker_connections 1024;}http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request"''$status $body_bytes_sent "$http_referer"''"$http_user_agent""$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;#tcp_nopush on;keepalive_timeout 65;#gzip on;include /etc/nginx/conf.d