运行 Nexus 3 与 Docker 在 Kubernetes 集群中
Run Nexus 3 with Docker in a Kubernetes cluster
Kubernetes 中 运行 sonatype\nexus3
允许使用 Docker 存储库的最佳设置是什么?
目前我有一个基本设置:
- 部署
sonatype\nexus3
- 内部服务公开端口 80 和 5000
- Ingress + kube-lego 提供对 Nexus 的 HTTPS 访问 UI
如何绕过不允许多个端口的入口限制?
tl;博士
Nexus 需要通过 SSL 提供服务,否则 docker 将无法连接到它。这可以通过 k8s ingress + kube-lego for a Let's Encrypt 证书来实现。任何其他真实证书也可以使用。但是,为了通过一个入口(因此,一个端口)同时为 nexus UI 和 docker 注册表提供服务,需要在入口后面设置一个反向代理来检测 docker 用户代理和将请求转发给注册表。
--(IF user agent docker) --> [nexus service]nexus:5000 --> docker registry
|
[nexus ingress]nexus.example.com:80/ --> [proxy service]internal-proxy:80 -->|
|
--(ELSE ) --> [nexus service]nexus:80 --> nexus UI
启动连接服务器
nexus-deployment.yaml
这使用了 azureFile 卷,但您可以使用任何卷。此外,由于显而易见的原因,未显示秘密。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nexus
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nexus
spec:
containers:
- name: nexus
image: sonatype/nexus3:3.3.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8081
- containerPort: 5000
volumeMounts:
- name: nexus-data
mountPath: /nexus-data
resources:
requests:
cpu: 440m
memory: 3.3Gi
limits:
cpu: 440m
memory: 3.3Gi
volumes:
- name: nexus-data
azureFile:
secretName: azure-file-storage-secret
shareName: nexus-data
添加运行状况和就绪探测器始终是个好主意,这样 kubernetes 就可以检测到应用何时宕机。点击 index.html
页面并不总是很好,所以我改用 REST API。这需要为具有 nx-script-*-browse
权限的用户添加授权 header。显然,您必须首先在没有探测的情况下启动系统来设置用户,然后再更新您的部署。
readinessProbe:
httpGet:
path: /service/siesta/rest/v1/script
port: 8081
httpHeaders:
- name: Authorization
# The authorization token is simply the base64 encoding of the `healthprobe` user's credentials:
# $ echo -n user:password | base64
value: Basic dXNlcjpwYXNzd29yZA==
initialDelaySeconds: 900
timeoutSeconds: 60
livenessProbe:
httpGet:
path: /service/siesta/rest/v1/script
port: 8081
httpHeaders:
- name: Authorization
value: Basic dXNlcjpwYXNzd29yZA==
initialDelaySeconds: 900
timeoutSeconds: 60
因为 nexus 有时需要很长时间才能启动,所以我使用了非常慷慨的初始延迟和超时。
nexus-service.yaml 为 UI 公开端口 80,为注册表公开端口 5000。这必须对应于通过 UI.
为注册表配置的端口
apiVersion: v1
kind: Service
metadata:
labels:
app: nexus
name: nexus
namespace: default
selfLink: /api/v1/namespaces/default/services/nexus
spec:
ports:
- name: http
port: 80
targetPort: 8081
- name: docker
port: 5000
targetPort: 5000
selector:
app: nexus
type: ClusterIP
启动反向代理(nginx)
proxy-configmap.yaml 添加nginx.conf作为ConfigMap数据卷。这包括用于检测 docker 用户代理的规则。这依赖于 kubernetes DNS 作为上游访问 nexus
服务。
apiVersion: v1
data:
nginx.conf: |
worker_processes auto;
events {
worker_connections 1024;
}
http {
error_log /var/log/nginx/error.log warn;
access_log /dev/null;
proxy_intercept_errors off;
proxy_send_timeout 120;
proxy_read_timeout 300;
upstream nexus {
server nexus:80;
}
upstream registry {
server nexus:5000;
}
server {
listen 80;
server_name nexus.example.com;
keepalive_timeout 5 5;
proxy_buffering off;
# allow large uploads
client_max_body_size 1G;
location / {
# redirect to docker registry
if ($http_user_agent ~ docker ) {
proxy_pass http://registry;
}
proxy_pass http://nexus;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto "https";
}
}
}
kind: ConfigMap
metadata:
creationTimestamp: null
name: internal-proxy-conf
namespace: default
selfLink: /api/v1/namespaces/default/configmaps/internal-proxy-conf
proxy-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: internal-proxy
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
proxy: internal
spec:
containers:
- name: nginx
image: nginx:1.11-alpine
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
volumeMounts:
- name: internal-proxy-conf
mountPath: /etc/nginx/
env:
# This is a workaround to easily force a restart by incrementing the value (numbers must be quoted)
# NGINX needs to be restarted for configuration changes, especially DNS changes, to be detected
- name: RESTART_
value: "0"
volumes:
- name: internal-proxy-conf
configMap:
name: internal-proxy-conf
items:
- key: nginx.conf
path: nginx.conf
proxy-service.yaml 代理特意为 ClusterIP
类型,因为入口会将流量转发给它。此示例中未使用端口 443。
kind: Service
apiVersion: v1
metadata:
name: internal-proxy
namespace: default
spec:
selector:
proxy: internal
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
type: ClusterIP
创建 Ingress
nexus-ingress.yaml 这一步假设你有一个 nginx 入口控制器。如果您有证书,则不需要入口,而是可以公开代理服务,但您将无法获得 kube-lego.
的自动化优势
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nexus
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
spec:
tls:
- hosts:
- nexus.example.com
secretName: nexus-tls
rules:
- host: nexus.example.com
http:
paths:
- path: /
backend:
serviceName: internal-proxy
servicePort: 80
我认为这可以通过使用 nginx ingress 来完成。通过为您的入口使用路径或子域。例如:
服务
apiVersion: v1
kind: Service
metadata:
labels:
app: nexus
name: nexus
namespace: default
selfLink: /api/v1/namespaces/default/services/nexus
spec:
ports:
- name: http
port: 80
targetPort: 8081
- name: docker
port: 5000
targetPort: 5000
selector:
app: nexus
type: ClusterIP
入口
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nexus
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
spec:
tls:
- hosts:
- nexus.example.com
- docker.example.com
secretName: nexus-tls
rules:
- host: nexus.example.com
http:
paths:
- path: /
backend:
serviceName: nexus
servicePort: 80
- host: docker.example.com
http:
paths:
- path: /
backend:
serviceName: nexus
servicePort: 5000
此处 https://nexus.example.com
将带您访问 Nexus UI 以及在普通 HTTP 端口上运行的所有注册表功能。 https://docker.example.com:5000
将公开您的 docker 存储库。虽然这需要您使用两个不同的主机名,但它更明确一点并且不依赖于客户端正确设置用户代理。这也恰好是 Nexus Helm 图表使用的策略,如下所示:
https://github.com/kubernetes/charts/tree/master/stable/sonatype-nexus
使用 Helm 完成 Nexus 设置
这假设您的 nginx ingress 具有正确的 TLS 配置 运行 并且您的集群可以处理 Persistent Volume Claims:
安装 Nexus
使用 helm 在集群中安装 Nexus:
helm install stable/sonatype-nexus --name registry --namespace foo
注意:您可以使用此命令撤销安装:
helm del --purge registry
调整 Nexus 部署
使用 helm 安装 Nexus 后,您会发现 deployment 用于 Nexus。添加 containerPort: 5000
到它,就在已经存在的 containterPort 下面。
调整 Nexus 服务
您还需要将端口 5000
添加到 Nexus 服务。将其放在默认端口下方:
- port: 5000
targetPort: 5000
protocol: TCP
name: docker
Ingress 配置示例:
此配置将 https://registry.example.com
指向端口 8081
的 Nexus UI 并将 https://docker.exmaple.com
指向端口 [=18= 的 docker 服务].
注意:在我的例子中,端口 8081
是 Nexus 部署中提供的默认端口,您在上面的步骤中对其进行了编辑。如果您的安装使用另一个端口,请调整它。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-com-ingress
namespace: foo
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
# Provide the docker backend that is used for docker login.
- host: docker.example.com
http:
paths:
- path: /
backend:
serviceName: registry-sonatype-nexus
servicePort: 5000
# Provide the nexus backend that is used for the UI etc.
- host: registry.exmaple.com
http:
paths:
- path: /
backend:
serviceName: registry-sonatype-nexus
servicePort: 8081
tls:
- secretName: example-com-tls
hosts:
- registry.example.com
- docker.example.com
配置 Nexus
您现在应该可以在 https://registry.example.com
打开 Nexus UI。使用默认凭据登录。用户:admin
密码:admin123
.
创建一个 docker 主机仓库并将 Repository Connector
下的 HTTP
设置为 5000
并禁用 Force Basic Authentication
.
登录、打标签、推送图片
您现在应该能够使用 Nexus 登录凭据将您的 docker 客户端登录到注册表:
docker login docker.example.com
使用此模式标记和推送图像:
docker tag <image>:<tag> <nexus-hostname>/<namespace>/<image>:<tag>
docker push <nexus-hostname>/<namespace>/<image>:<tag>
例如:
docker tag myapp:1.0.0 docker.example.com/foo/myapp:1.0.0
docker push docker.example.com/foo/myapp:1.0.0
Kubernetes 中 运行 sonatype\nexus3
允许使用 Docker 存储库的最佳设置是什么?
目前我有一个基本设置:
- 部署
sonatype\nexus3
- 内部服务公开端口 80 和 5000
- Ingress + kube-lego 提供对 Nexus 的 HTTPS 访问 UI
如何绕过不允许多个端口的入口限制?
tl;博士
Nexus 需要通过 SSL 提供服务,否则 docker 将无法连接到它。这可以通过 k8s ingress + kube-lego for a Let's Encrypt 证书来实现。任何其他真实证书也可以使用。但是,为了通过一个入口(因此,一个端口)同时为 nexus UI 和 docker 注册表提供服务,需要在入口后面设置一个反向代理来检测 docker 用户代理和将请求转发给注册表。
--(IF user agent docker) --> [nexus service]nexus:5000 --> docker registry
|
[nexus ingress]nexus.example.com:80/ --> [proxy service]internal-proxy:80 -->|
|
--(ELSE ) --> [nexus service]nexus:80 --> nexus UI
启动连接服务器
nexus-deployment.yaml 这使用了 azureFile 卷,但您可以使用任何卷。此外,由于显而易见的原因,未显示秘密。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nexus
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nexus
spec:
containers:
- name: nexus
image: sonatype/nexus3:3.3.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8081
- containerPort: 5000
volumeMounts:
- name: nexus-data
mountPath: /nexus-data
resources:
requests:
cpu: 440m
memory: 3.3Gi
limits:
cpu: 440m
memory: 3.3Gi
volumes:
- name: nexus-data
azureFile:
secretName: azure-file-storage-secret
shareName: nexus-data
添加运行状况和就绪探测器始终是个好主意,这样 kubernetes 就可以检测到应用何时宕机。点击 index.html
页面并不总是很好,所以我改用 REST API。这需要为具有 nx-script-*-browse
权限的用户添加授权 header。显然,您必须首先在没有探测的情况下启动系统来设置用户,然后再更新您的部署。
readinessProbe:
httpGet:
path: /service/siesta/rest/v1/script
port: 8081
httpHeaders:
- name: Authorization
# The authorization token is simply the base64 encoding of the `healthprobe` user's credentials:
# $ echo -n user:password | base64
value: Basic dXNlcjpwYXNzd29yZA==
initialDelaySeconds: 900
timeoutSeconds: 60
livenessProbe:
httpGet:
path: /service/siesta/rest/v1/script
port: 8081
httpHeaders:
- name: Authorization
value: Basic dXNlcjpwYXNzd29yZA==
initialDelaySeconds: 900
timeoutSeconds: 60
因为 nexus 有时需要很长时间才能启动,所以我使用了非常慷慨的初始延迟和超时。
nexus-service.yaml 为 UI 公开端口 80,为注册表公开端口 5000。这必须对应于通过 UI.
为注册表配置的端口apiVersion: v1
kind: Service
metadata:
labels:
app: nexus
name: nexus
namespace: default
selfLink: /api/v1/namespaces/default/services/nexus
spec:
ports:
- name: http
port: 80
targetPort: 8081
- name: docker
port: 5000
targetPort: 5000
selector:
app: nexus
type: ClusterIP
启动反向代理(nginx)
proxy-configmap.yaml 添加nginx.conf作为ConfigMap数据卷。这包括用于检测 docker 用户代理的规则。这依赖于 kubernetes DNS 作为上游访问 nexus
服务。
apiVersion: v1
data:
nginx.conf: |
worker_processes auto;
events {
worker_connections 1024;
}
http {
error_log /var/log/nginx/error.log warn;
access_log /dev/null;
proxy_intercept_errors off;
proxy_send_timeout 120;
proxy_read_timeout 300;
upstream nexus {
server nexus:80;
}
upstream registry {
server nexus:5000;
}
server {
listen 80;
server_name nexus.example.com;
keepalive_timeout 5 5;
proxy_buffering off;
# allow large uploads
client_max_body_size 1G;
location / {
# redirect to docker registry
if ($http_user_agent ~ docker ) {
proxy_pass http://registry;
}
proxy_pass http://nexus;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto "https";
}
}
}
kind: ConfigMap
metadata:
creationTimestamp: null
name: internal-proxy-conf
namespace: default
selfLink: /api/v1/namespaces/default/configmaps/internal-proxy-conf
proxy-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: internal-proxy
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
proxy: internal
spec:
containers:
- name: nginx
image: nginx:1.11-alpine
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
volumeMounts:
- name: internal-proxy-conf
mountPath: /etc/nginx/
env:
# This is a workaround to easily force a restart by incrementing the value (numbers must be quoted)
# NGINX needs to be restarted for configuration changes, especially DNS changes, to be detected
- name: RESTART_
value: "0"
volumes:
- name: internal-proxy-conf
configMap:
name: internal-proxy-conf
items:
- key: nginx.conf
path: nginx.conf
proxy-service.yaml 代理特意为 ClusterIP
类型,因为入口会将流量转发给它。此示例中未使用端口 443。
kind: Service
apiVersion: v1
metadata:
name: internal-proxy
namespace: default
spec:
selector:
proxy: internal
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
type: ClusterIP
创建 Ingress
nexus-ingress.yaml 这一步假设你有一个 nginx 入口控制器。如果您有证书,则不需要入口,而是可以公开代理服务,但您将无法获得 kube-lego.
的自动化优势apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nexus
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
spec:
tls:
- hosts:
- nexus.example.com
secretName: nexus-tls
rules:
- host: nexus.example.com
http:
paths:
- path: /
backend:
serviceName: internal-proxy
servicePort: 80
我认为这可以通过使用 nginx ingress 来完成。通过为您的入口使用路径或子域。例如:
服务
apiVersion: v1
kind: Service
metadata:
labels:
app: nexus
name: nexus
namespace: default
selfLink: /api/v1/namespaces/default/services/nexus
spec:
ports:
- name: http
port: 80
targetPort: 8081
- name: docker
port: 5000
targetPort: 5000
selector:
app: nexus
type: ClusterIP
入口
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nexus
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
spec:
tls:
- hosts:
- nexus.example.com
- docker.example.com
secretName: nexus-tls
rules:
- host: nexus.example.com
http:
paths:
- path: /
backend:
serviceName: nexus
servicePort: 80
- host: docker.example.com
http:
paths:
- path: /
backend:
serviceName: nexus
servicePort: 5000
此处 https://nexus.example.com
将带您访问 Nexus UI 以及在普通 HTTP 端口上运行的所有注册表功能。 https://docker.example.com:5000
将公开您的 docker 存储库。虽然这需要您使用两个不同的主机名,但它更明确一点并且不依赖于客户端正确设置用户代理。这也恰好是 Nexus Helm 图表使用的策略,如下所示:
https://github.com/kubernetes/charts/tree/master/stable/sonatype-nexus
使用 Helm 完成 Nexus 设置
这假设您的 nginx ingress 具有正确的 TLS 配置 运行 并且您的集群可以处理 Persistent Volume Claims:
安装 Nexus
使用 helm 在集群中安装 Nexus:
helm install stable/sonatype-nexus --name registry --namespace foo
注意:您可以使用此命令撤销安装:
helm del --purge registry
调整 Nexus 部署
使用 helm 安装 Nexus 后,您会发现 deployment 用于 Nexus。添加 containerPort: 5000
到它,就在已经存在的 containterPort 下面。
调整 Nexus 服务
您还需要将端口 5000
添加到 Nexus 服务。将其放在默认端口下方:
- port: 5000
targetPort: 5000
protocol: TCP
name: docker
Ingress 配置示例:
此配置将 https://registry.example.com
指向端口 8081
的 Nexus UI 并将 https://docker.exmaple.com
指向端口 [=18= 的 docker 服务].
注意:在我的例子中,端口 8081
是 Nexus 部署中提供的默认端口,您在上面的步骤中对其进行了编辑。如果您的安装使用另一个端口,请调整它。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-com-ingress
namespace: foo
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
# Provide the docker backend that is used for docker login.
- host: docker.example.com
http:
paths:
- path: /
backend:
serviceName: registry-sonatype-nexus
servicePort: 5000
# Provide the nexus backend that is used for the UI etc.
- host: registry.exmaple.com
http:
paths:
- path: /
backend:
serviceName: registry-sonatype-nexus
servicePort: 8081
tls:
- secretName: example-com-tls
hosts:
- registry.example.com
- docker.example.com
配置 Nexus
您现在应该可以在 https://registry.example.com
打开 Nexus UI。使用默认凭据登录。用户:admin
密码:admin123
.
创建一个 docker 主机仓库并将 Repository Connector
下的 HTTP
设置为 5000
并禁用 Force Basic Authentication
.
登录、打标签、推送图片
您现在应该能够使用 Nexus 登录凭据将您的 docker 客户端登录到注册表:
docker login docker.example.com
使用此模式标记和推送图像:
docker tag <image>:<tag> <nexus-hostname>/<namespace>/<image>:<tag>
docker push <nexus-hostname>/<namespace>/<image>:<tag>
例如:
docker tag myapp:1.0.0 docker.example.com/foo/myapp:1.0.0
docker push docker.example.com/foo/myapp:1.0.0