适用于Kubernetes服务的强大,简单的SSL
嗨,我是埃文·布朗 (@evandbrown),我在Google Cloud Platform解决方案架构团队中工作。我最近写了 文章 和 教程 about using Jenkins on Kubernetes to automate the Docker 和 GCE image build process. Today I’m going to discuss how I used Kubernetes services 和 secrets to add SSL to the Jenkins web UI. After reading this, you’ll be able to add SSL termination (and HTTP->HTTPS redirects + basic auth) to your public HTTP Kubernetes services.
在一开始的时候
本着最低限度的精神,我构建的Jenkins-on-Kubernetes的第一个版本非常基础,但功能丰富:
- Jenkins领导者只是一个容器中的一个容器,但是它是由复制控制器管理的,因此,如果失败,它将自动重生。
- Jenkins领导者公开了两个端口-Web UI的TCP 8080和供构建代理注册的TCP 50000-这些端口可作为带有公共负载平衡器的Kubernetes服务使用。
这是第一个版本的视觉效果:
这可行,但是我有一些问题。首先,默认的Jenkins安装中未配置身份验证。领导者坐在任何人都可以访问的公共Internet上,直到您连接并配置身份验证。而且由于没有加密,所以配置身份验证是一种象征性手势。我们需要SSL,现在就需要它!
做你所知道的
我考虑了几毫秒,试图让SSL直接在Jenkins上运行。我以前从未做过,我想知道它是否像在SSL上使用SSL一样简单 Nginx的, something I do have experience with. I’m all for learning new things, but this seemed like a great place to not invent a new wheel: SSL on Nginx的 is straightforward 和 well documented (as are its reverse-proxy capabilities), 和 Kubernetes is all about building functionality by orchestrating 和 composing containers. Let’s use Nginx的, 和 add a few bonus features that Nginx的 makes simple: HTTP->HTTPS redirection, 和 basic access authentication.
SSL终止代理作为Nginx服务
我首先将一个 Docker文件 它从标准nginx映像继承而来,复制了一些Nginx配置文件,并添加了自定义入口点(start.sh)。入口点脚本检查环境变量(ENABLE_SSL)并相应地激活正确的Nginx配置(这意味着可以使用未加密的HTTP反向代理,但这会破坏目的)。该脚本还配置了基本访问身份验证(如果已启用)(ENABLE_BASIC_AUTH env var)。
最后,start.sh评估SERVICE_HOST_ENV_NAME和SERVICE_PORT_ENV_NAME环境变量。这些变量应设置为您要代理的Kubernetes服务的环境变量的名称。在此示例中,为我们的Jenkins领导者提供的服务巧妙地命名为jenkins,这意味着集群中的Pod将看到一个名为JENKINS_SERVICE_HOST和JENKINS_SERVICE_PORT_UI的环境变量(Jenkins领导者上8080映射到的端口)。 SERVICE_HOST_ENV_NAME和SERVICE_PORT_ENV_NAME只是简单地引用了用于特定方案的正确服务,从而允许在部署中通用使用该映像。
定义控制器和服务
像本示例中的其他所有Pod一样,我们将使用复制控制器部署Nginx,从而使我们能够进行横向或纵向扩展,并从容器故障中自动恢复。摘录自示例应用程序中的完整描述符 显示了pod规范的一些相关信息:
spec:
containers:
-
name: "nginx-ssl-proxy"
image: "gcr.io/cloud-solutions-images/nginx-ssl-proxy:latest"
env:
-
name: "SERVICE\_HOST\_ENV\_NAME"
value: "JENKINS\_SERVICE\_HOST"
-
name: "SERVICE\_PORT\_ENV\_NAME"
value: "JENKINS\_SERVICE\_PORT\_UI"
-
name: "ENABLE\_SSL"
value: "true"
-
name: "ENABLE\_BASIC\_AUTH"
value: "true"
ports:
-
name: "nginx-ssl-proxy-http"
containerPort: 80
-
name: "nginx-ssl-proxy-https"
containerPort: 443
吊舱将提供将TCP 80和443公开给公共负载平衡器的服务。这是服务描述符 (也可在示例应用中找到):
kind: "Service"
apiVersion: "v1"
metadata:
name: "nginx-ssl-proxy"
labels:
name: "nginx"
role: "ssl-proxy"
spec:
ports:
-
name: "https"
port: 443
targetPort: "nginx-ssl-proxy-https"
protocol: "TCP"
-
name: "http"
port: 80
targetPort: "nginx-ssl-proxy-http"
protocol: "TCP"
selector:
name: "nginx"
role: "ssl-proxy"
type: "LoadBalancer"
这里是使用SSL终止代理的概述。请注意,詹金斯不再直接暴露于公共互联网中:
现在,Nginx容器如何获得超级秘密的SSL密钥/证书和htpasswd文件(用于基本访问身份验证)?
保密,安全
Kubernetes有一个 秘密的API和资源。 “机密”旨在保存敏感信息,例如密码,OAuth令牌和ssh密钥。与逐字记录在pod定义或docker映像中相比,将这些信息保密是更加安全和灵活的。”
您可以通过3个简单的步骤在集群中创建机密:
Base64编码您的秘密数据(即SSL密钥对或htpasswd文件)
$ cat ssl.key | base64
LS0tLS1CRUdJTiBDRVJUS...
创建一个描述您的秘密的json文档,并添加base64编码的值:
apiVersion: "v1"
kind: "Secret"
metadata:
name: "ssl-proxy-secret"
namespace: "default"
data:
proxycert: "LS0tLS1CRUd..."
proxykey: "LS0tLS1CR..."
htpasswd: "ZXZhb..."
创建秘密资源:
$ kubectl create -f secrets.json
要从容器访问机密,请在您的pod规范中将其指定为卷安装。这是相关摘录 Nginx的代理模板 我们之前看过:
spec:
containers:
-
name: "nginx-ssl-proxy"
image: "gcr.io/cloud-solutions-images/nginx-ssl-proxy:latest"
env: [...]
ports: ...[]
volumeMounts:
-
name: "secrets"
mountPath: "/etc/secrets"
readOnly: true
volumes:
-
name: "secrets"
secret:
secretName: "ssl-proxy-secret"
定义了一个指向ssl-proxy-secret秘密资源的secret类型的卷,然后将其装入容器中的/ etc / secrets中。较早示例中的secrets规范定义了data.proxycert,data.proxykey和data.htpasswd,因此我们将看到这些文件出现(以base64解码)在/ etc / secrets / proxycert,/ etc / secrets / proxykey和/ etc / secrets / htpasswd供Nginx进程访问。
现在都在一起了
我有“容器和Kubernetes既有趣又酷!”时时刻刻,就像每天一样。我开始拥有“容器和Kubernetes极为有用和强大的功能,并通过帮助我轻松地完成重要的事情来增加我的工作的价值”。这个带有Nginx示例的SSL终止代理肯定是后者之一。我不必浪费时间学习使用SSL的新方法。我能够以一种可重用的方式,使用可重复使用的工具,快速地解决我的问题(从构思到工作大约需要2个小时)。
签出完整 使用Jenkins,Packer和Kubernetes进行自动映像构建 回购以查看SSL终止代理在实际集群中的使用方式,或在 Nginx的的SSL代理回购 (带有Dockerfile和Packer模板,因此您可以自己构建映像)。