升級ingress-nginx-controller的nginx版本

線上的k8s使用nginx所在的邊緣節點來將外部訪問導流到集羣內部容器,ingress-nginx-controller是k8s衆多ingress controller實現中的一種,以agent+nginx的方式提供服務。agent通過watch k8s的ingress、configmap、endpoint等資源的變化,修改nginx的配置文件,並負責nginx的reload等工作。如果ingress-nginx-controller插件中的nginx因某種原因需要升級,我們應該怎麼辦呢?(如nginx漏洞)
漏洞
遇到這個問題的時候,我第一個想到的是通過ingress-nginx-controller官方版本升級,於是去查詢ingress-nginx-controller的github倉庫查看插件版本對應的nginx版本,下圖對應的是0.20.0的插件版本
22
雖然在官方的github倉庫的最高版本是0.22.0,但是nginx版本是多少通過github並不清楚,而我又不希望通過下載每個官方鏡像去查看nginx版本,並且這個nginx版本取決於官方的更新速度,這給個人的升級帶來一定的不便,所以打算自己製作ingress-nginx-controller鏡像。那思路是怎樣的呢?既然我想替換nginx版本,那麼我可以用當前在線上跑的插件版本,提取其中的ingress-nginx-controller組件,再根據我們想要升級的nginx版本就可以製作一個新的鏡像了。想法雖然簡單,但是,安裝nginx指定版本,我們編譯的時候要添加什麼參數呢?這個我們可以通過當前版本的nginx -V去查看相關輸出,我們能看到nginx的版本和編譯相關信息。

nginx version: nginx/1.13.4
built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 
built with OpenSSL 1.0.2g  1 Mar 2016
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock 
--pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy 
--http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module 
--with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module 
--with-http_sub_module --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-file-aio --without-mail_pop3_module 
--without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_module --without-http_scgi_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' 
--add-module=/tmp/build/ngx_devel_kit-0.3.0 --add-module=/tmp/build/set-misc-nginx-module-0.31 --add-module=/tmp/build/nginx-module-vts-0.1.15 --add-module=/tmp/build/headers-more-nginx-module-0.32 
--add-module=/tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 --add-module=/tmp/build/nginx-http-auth-digest-7955af9c77598c697ac292811914ce1e2b3b824c 
--add-module=/tmp/build/ngx_http_substitutions_filter_module-bc58cb11844bc42735bbaef7085ea86ace46d05b

通過nginx -V我們能夠清晰的看到編譯nginx時我們的參數配置,以及所加載的模塊,所以將nginx升級到1.14.2時也是通過這些參數去編譯。
那麼升級的思路主要是安裝nginx了,爲了做到nginx版本間無干擾,準備用直接從debian鏡像開始構建

1、準備好nginx的源碼包

wget http://nginx.org/download/nginx-1.14.2.tar.gz

2、準備nginx add module相關模塊文件

相關文件
通過https://www.nginx.com/resources/wiki/modules/index.html查找編譯選項中的add-module模塊,將指定版本的nginx模塊的github倉庫下載到Dockerfile通目錄下。

3、編譯安裝nginx

./configure --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log \ 
--error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid \ 
--http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ 
--http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi \ 
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module \ 
--with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module \ 
--with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module \ 
--with-http_sub_module --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \ 
--with-threads --with-file-aio --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module \ 
--without-http_uwsgi_module --without-http_scgi_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
--add-module=/tmp/build/ngx_devel_kit-0.3.0 --add-module=/tmp/build/set-misc-nginx-module-0.31 --add-module=/tmp/build/nginx-module-vts-0.1.15 \
--add-module=/tmp/build/headers-more-nginx-module-0.32 --add-module=/tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 \
--add-module=/tmp/build/nginx-http-auth-digest-1.0.0 --add-module=/tmp/build/ngx_http_substitutions_filter_module-0.6.4

在編譯之前要先確認好是否缺少某些依賴庫,在我的實踐過程中,我首先安裝以下依賴

apt-get install openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev -y

也可以通過./configure檢查缺少哪些依賴,並通過提示安裝依賴。
編譯通過之後就是

make && make install
cp /usr/share/nginx/sbin/nginx /usr/sbin/

所以整個過程將它整理成一個Dockerfile文件如下所示:

FROM debian:latest
MAINTAINER polarwu

RUN apt-get update && apt-get install wget openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev libgeoip-dev gcc make -y
WORKDIR /
RUN wget http://nginx.org/download/nginx-1.14.2.tar.gz && tar -zxvf nginx-1.14.2.tar.gz
RUN mkdir /var/log/nginx && chmod 755 /var/log/nginx && mkdir /var/lib/nginx && chmod 755 /var/lib/nginx
ADD ./ngx_devel_kit-0.3.0 /tmp/build/ngx_devel_kit-0.3.0
ADD ./set-misc-nginx-module-0.31 /tmp/build/set-misc-nginx-module-0.31 
ADD ./nginx-module-vts-0.1.15 /tmp/build/nginx-module-vts-0.1.15 
ADD ./headers-more-nginx-module-0.32 /tmp/build/headers-more-nginx-module-0.32 
ADD ./nginx-goodies-nginx-sticky-module-ng-08a395c66e42 /tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42
ADD ./nginx-http-auth-digest-1.0.0 /tmp/build/nginx-http-auth-digest-1.0.0
ADD ./ngx_http_substitutions_filter_module-0.6.4 /tmp/build/ngx_http_substitutions_filter_module-0.6.4
RUN cd /nginx-1.14.2 && ./configure --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log \ 
--error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid \ 
--http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ 
--http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi \ 
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module \ 
--with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module \ 
--with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module \ 
--with-http_sub_module --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \ 
--with-threads --with-file-aio --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module \ 
--without-http_uwsgi_module --without-http_scgi_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
--add-module=/tmp/build/ngx_devel_kit-0.3.0 --add-module=/tmp/build/set-misc-nginx-module-0.31 --add-module=/tmp/build/nginx-module-vts-0.1.15 \
--add-module=/tmp/build/headers-more-nginx-module-0.32 --add-module=/tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 \
--add-module=/tmp/build/nginx-http-auth-digest-1.0.0 --add-module=/tmp/build/ngx_http_substitutions_filter_module-0.6.4

RUN cd /nginx-1.14.2 && make && make install
RUN cp /usr/share/nginx/sbin/nginx /usr/sbin/
RUN mkdir /etc/nginx/template
RUN rm -rf /nginx-1.14.2*
ADD ./nginx.tmpl /etc/nginx/template/
ADD ./ingress-controller /ingress-controller
ADD ./nginx-ingress-controller /
ADD ./GeoIP.dat /etc/nginx
ADD ./GeoLiteCity.dat /etc/nginx
RUN rm -rf /tmp/build
RUN apt-get remove wget gcc make -y && apt-get clean
EXPOSE 80
EXPOSE 443
CMD ["/nginx-ingress-controller"]

最後編寫一個yaml文件測試我們製作的鏡像是否正常運行

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx-ingress-lb
  labels:
    name: nginx-ingress-lb
  namespace: ingress-nginx
spec:
  selector:
    matchLabels:
      name: nginx-ingress-lb
  template:
    metadata:
      labels:
        name: nginx-ingress-lb
    spec:
      hostNetwork: true
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        nginx-ingress-lb: 'true'
      containers:
      - name: nginx-ingress-lb
        image: nginx-ingress-controller:nginx-v1.14.2
        readinessProbe:
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
        livenessProbe:
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          timeoutSeconds: 1
        ports:
        - containerPort: 80
          hostPort: 80
          name: http
        - containerPort: 443
          hostPort: 443
          name: https
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: KUBERNETES_MASTER
            value: http://192.168.1.123:8080
        args:
        - /nginx-ingress-controller
        - --default-backend-service=ingress-nginx/http-backend
        - --tcp-services-configmap=default/nginx-tcp-ingress-configmap
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-lb
  namespace: ingress-nginx
  labels:
    app: nginx-ingress-lb
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  selector:
    name: nginx-ingress-lb

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-tcp-ingress-configmap
  namespace: default
data:
  "8846": default/helloworld:8777

通過訪問10.142.233.79:8846(10.142.233.79爲nginx所在節點),我們升級的ingress-nginx-controller已經正常工作
hello

總結

文章介紹了通過升級nginx靈活配置ingress-nginx-controller插件下的nginx版本,並通過測試驗證了我們nginx和ingress-controller無縫升級,解決了我們的nginx漏洞整改需求。一般情況下,ingress-controller實現的功能是基於nginx,所以我們在升級nginx版本時應首先通過nginx -V查看nginx的相關編譯參數以便新版本按照現有nginx版本進行編譯,提供現有ingress-nginx-controller插件的功能需求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章