首页 文章

如何使用SSL和NGINX创建服务于自己容器的Kubernetes集群

提问于
浏览
1

我正在尝试使用以下服务构建一个Kubernetes集群:

  • Docker-registry(将包含我的django Docker镜像)

  • Nginx在端口80和443上都进行侦听

  • PostgreSQL

  • 几个django应用程序配有gunicorn

  • letsencrypt容器生成并自动续订签名的SSL证书

我的问题是在创建集群期间发生的鸡和蛋问题:

我的SSL证书存储在由letsencrypt容器生成的密钥卷中 . 为了能够生成证书,我们需要显示我们是域名的所有者,这是通过验证可从服务器名称访问的文件来完成的(基本上这包括Nginx能够通过端口80提供静态文件)

所以这里出现了我的第一个问题:要提供letsencrypt所需的静态文件,我需要启动nginx . 如果尚未安装秘密,则无法启动nginx的SSL部分,只有当let加密成功时才生成秘密...

所以,一个简单的解决方案可能是拥有2个Nginx容器:一个只在端口80上监听,然后先启动,然后让我们启动第二个Nginx容器,监听端口443

  • 在我看来,这种看起来像是浪费资源,但为什么不呢 .

现在假设我有2个nginx容器,我希望我的Docker Registry可以通过https访问 .

所以在我的nginx配置中,我将有一个docker-registry.conf文件,如下所示:

upstream docker-registry {
  server registry:5000;
}

server {
  listen 443;
  server_name docker.thedivernetwork.net;

  # SSL
  ssl on;
  ssl_certificate /etc/nginx/conf.d/cacert.pem;
  ssl_certificate_key /etc/nginx/conf.d/privkey.pem;

  # disable any limits to avoid HTTP 413 for large image uploads
  client_max_body_size 0;

  # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
  chunked_transfer_encoding on;

  location /v2/ {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    # To add basic authentication to v2 use auth_basic setting plus add_header
    auth_basic "registry.localhost";
    auth_basic_user_file /etc/nginx/conf.d/registry.password;
    add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

重要的部分是重定向到注册表容器的proxy_pass .

我面临的问题是我的Django Gunicorn服务器的配置文件也在同一个文件夹django.conf中:

upstream django {
    server django:5000;
}

server {
    listen 443 ssl;
    server_name example.com;
    charset     utf-8;

    ssl on;
    ssl_certificate /etc/nginx/conf.d/cacert.pem;
    ssl_certificate_key /etc/nginx/conf.d/privkey.pem;

    ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers          HIGH:!aNULL:!MD5;
    client_max_body_size 20M;

    location / {
        # checks for static file, if not found proxy to app
        try_files $uri @proxy_to_django;
    }

    location @proxy_to_django {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        #proxy_pass_header Server;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 65;
        proxy_read_timeout 65;

        proxy_pass   http://django;
    }

}

所以nginx只能在3个条件下成功启动:

安装

  • secret(可以通过将Nginx拆分为2个单独的容器来解决)

  • 注册服务已启动

  • django服务已启动

问题是django映像正在从注册表服务中提取其映像,因此我们再次处于死锁状态 .

我没有提到它,但是注册表和django都有不同的ServerName,所以nginx能够同时为它们服务

关于它的解决方案(但它非常脏!)将使用越来越多的配置重新加载nginx几次:

  • 我启动了docker注册服务

  • 我只使用registry.conf启动Nginx

  • 我创建了我的django rc和服务

  • 我用registry.conf和django.conf重新加载nginx

如果有办法让nginx开始忽略失败的配置,那么这也许可以解决我的问题 .

我怎样才能干净利落地完成这个设置?

谢谢你的帮助

蒂博

1 回答

  • 1

    您是否正在使用Kubernetes Services

    通过对每个Pod的服务,您可以拥有Pod的代理 . 即使pod未启动,只要服务启动,nginx会在查找时找到它,因为服务已分配IP .

    所以你启动服务,然后按照你想要的顺序启动nginx和你想要的任何Pod .

相关问题