环境说明
- helm version:
v3.3.1
- kubernetes:
v1.17.9
- nexus:
3.29.0
部署
准备 storageClass
非 必要
操作,可以选择手动创建 pvc & pv,如果想部署 nfsStorageClass
的话,请参考早期整理的 文档。此篇文档实战部署步骤中基于 nfsStorageClass
进行实现。如果是用于 生产环境
的话,还是建议使用 ssd 或 iops 较高的 磁盘
作为数据盘使用,数据盘管理方式可以使用 localPv or hostPath 绑定到对应节点进行运行。
使用 helm
进行安装
添加 helm 仓库
1
2
3
|
helm repo add stable https //charts.helm.sh/stable
helm repo update
|
设置部署 values.yaml
配置文件
可以执行下面命令进行查看 默认
模板部署文件,或点击此 链接 查看。
1
|
helm show values stable/sonatype-nexus
|
修改后,完整 values.yaml 文件展示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
cat > prod-values.yaml << EOF
statefulset: # 使用 statefulset 进行部署
enabled: true
nexus:
imageName: sonatype/nexus3
imageTag: 3.30.1
imagePullPolicy: IfNotPresent
env:
- name: install4jAddVmParams
value: "-Xms1200M -Xmx1200M -XX:MaxDirectMemorySize=2G -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
- name: NEXUS_SECURITY_RANDOMPASSWORD
value: "false"
- name: TZ
value: "Asia/Shanghai"
resources:
limits:
cpu: 4
memory: 8192Mi
requests:
cpu: 250m
memory: 4800Mi
persistence:
enabled: true
storageClass: "nfs-retain"
storageSize: "100Gi"
service:
name: nexus-service
enabled: true
serviceType: ClusterIP
ports:
- name: manage # 此处为 service 对应暴露的端口, 如需暴露其他端口时,向下进行添加即可。
targetPort: 8081
port: 8081
- name: docker-proxy
targetPort: 8082
port: 8082
- name: docker-dev
targetPort: 8083
port: 8083
- name: docker-qa
targetPort: 8084
port: 8084
- name: docker-prod
targetPort: 8085
port: 8085
- name: docker-custom
targetPort: 8086
port: 8086
nexusProxy:
enabled: false
EOF
|
创建部署应用
1
2
3
|
kubectl create ns nexus
helm upgrade --install nexus -f ./prod-values.yaml -n nexus stable/sonatype-nexus # 部署安装
|
使用 traefik 将其暴露
traefik 部署安装使用,请参考 此篇文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
cat nexus-ingressroute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nexus-mirror
namespace: nexus
spec:
entryPoints:
- web
routes:
- match: Host(`mirror.treesir.pub`) && PathPrefix(`/`)
kind: Rule
services:
- name: nexus-service
port: 8081
kubectl apply -f ./nexus-ingressroute.yaml
|
初始化U/P: admin: admin123
Docker 私服的配置与优化
此步骤文档,记录创建 custom
、dev
、qa
、prod
环境的 docker 私服,并配置常见 docker proxy 类型私服,进行中间镜像的缓存进行使用。
仓库规划
docker 私服端口 使用规划
私服名称 |
私服作用 |
私服类型 |
私服端口 |
docker-custom |
存放,自定义 push的 镜像,与项目环境无关 |
hostd |
8086 |
idocker.io |
代理仓库 & custom 仓库的集合 |
group |
8082 |
docker-dev |
存放与项目dev环境镜像 |
hostd |
8083 |
docker-qa |
存放与项目qa环境镜像 |
hostd |
8084 |
docker-prod |
存放与项目prod环境镜像 |
hostd |
8085 |
docker 代理仓库列表
私服创建
创建 hostd 类型私服
且示例创建 docker-custom
, 其他仓库创建步骤是一样的,且需更具实际使用情况 更改 Deployment policy
策略 & 是否开启 匿名拉取镜像
即可,如在 prod
环境下,设置策略为 Disable redeploy
,即不允许对已存在的镜像做覆盖操作,push 时将提示错误。
-
创建 docker 使用的 blob 存储
建议对不同仓库类型的 私服做一下,blob存储的隔离 (可选)
-
选择创建 hostd
类型 docker 私服
创建 proxy 类型代理私服
且示例创建 docker-official
私服,因官方对匿名用户做了拉取到100次后,将降低带宽的使用,我们可以在配置的过程中,为其添加用户认证来增加拉取限制。
创建 group 类型私服
创建完成 对应 的 proxy 类型的私服后,就可以进行 group 类型私服, 一组仓库的集合的创建了。
-
组集合列表,如下所示
-
创建 group 组 idocker.io
配置 neuxs3 开启 使用 docker的认证管理
默认情况下,docker 认证在 neuxs3 中是没有被打开的,这里需要配置开启一下才行,不然会导致 执行 docker login
不成功。
使用 ingress 对端口进行暴露
在使用 traefik 暴露的docker私服中,因默认开启了 443 端口的监听,此时 docker 私服将默认使用 websecure
入口上的 ingressroute 路由规则,如不添加对应证书的话,将导致 match
上的规则不被匹配
创建 tls 证书生成脚本
gen-cert.sh
证书签发脚本,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/bin/bash
# scripts from https://www.jianshu.com/p/52fedb82ef53
usage()
{
echo "Usage: $0 [-a [rsa|ecc]] [-d <domain>] [-n <name>] [-h]"
echo " Options:"
echo " -a algorithm.[rsa|ecc]"
echo " -d domain.example: xxx.com,abc.org,*.abc.org"
echo " -n server key name"
echo " -h help"
exit 1
}
srv_key_name="server"
while getopts "a:d:n:h" arg #选项后面的冒号表示该选项需要参数
do
case $arg in
a)
alg=$OPTARG #算法
;;
d)
all_domain=$OPTARG #域名,逗号分隔
;;
n)
srv_key_name=$OPTARG #服务器证书名称
;;
h)
usage
exit 0
;;
?) #当有不认识的选项的时候arg为?
usage
exit 1
;;
esac
done
domain="domain.com"
san="DNS:*.${domain},DNS:${domain}"
if [ -n "${all_domain}" ]; then
#分割域名
OLD_IFS="$IFS"
IFS=","
domain_array=($all_domain)
IFS="$OLD_IFS"
domain_len=${#domain_array[@]}
domain=${domain_array[0]}
san=""
for ((i=0;i<domain_len;i++))
{
if [ $i = 0 ];then
san="DNS:${domain_array[i]}"
else
san="${san},DNS:${domain_array[i]}"
fi
}
fi
ca_subj="/C=CN/ST=Hubei/L=Wuhan/O=MY/CN=MY CA"
server_subj="/C=CN/ST=Hubei/L=Wuhan/O=MY/CN=${domain}"
#其中C是Country,ST是state,L是local,O是Organization,OU是Organization Unit,CN是common name
days=14610 # 有效期40年
echo "san:${san}"
sdir="certs"
ca_key_file="${sdir}/ca.key"
ca_crt_file="${sdir}/ca.crt"
srv_key_file="${sdir}/${srv_key_name}.key"
srv_csr_file="${sdir}/${srv_key_name}.csr"
srv_crt_file="${sdir}/${srv_key_name}.crt"
srv_p12_file="${sdir}/${srv_key_name}.p12"
srv_fullchain_file="${sdir}/${srv_key_name}-fullchain.crt"
cfg_san_file="${sdir}/san.cnf"
#algorithm config
if [[ ${alg} = "rsa" ]] ; then
rsa_len=2048
elif [[ ${alg} = "ecc" ]] ; then
ecc_name=prime256v1
else
usage
exit 1
fi #ifend
echo "algorithm:${alg}"
mkdir -p ${sdir}
if [ ! -f "${ca_key_file}" ]; then
echo "------------- gen ca key-----------------------"
if [[ ${alg} = "rsa" ]] ; then
openssl genrsa -out ${ca_key_file} ${rsa_len}
elif [[ ${alg} = "ecc" ]] ; then
openssl ecparam -out ${ca_key_file} -name ${ecc_name} -genkey
fi #ifend
openssl req -new -x509 -days ${days} -key ${ca_key_file} -out ${ca_crt_file} -subj "${ca_subj}"
fi
if [ ! -f "${srv_key_file}" ]; then
echo "------------- gen server key-----------------------"
if [[ ${alg} = "rsa" ]] ; then
openssl genrsa -out ${srv_key_file} ${rsa_len}
elif [[ ${alg} = "ecc" ]] ; then
openssl ecparam -genkey -name ${ecc_name} -out ${srv_key_file}
fi #ifend
openssl req -new -sha256 -key ${srv_key_file} -out ${srv_csr_file} -subj "${server_subj}"
printf "[ SAN ]\nauthorityKeyIdentifier=keyid,issuer\nbasicConstraints=CA:FALSE\nkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment\nsubjectAltName=${san}" > ${cfg_san_file}
openssl x509 -req -days ${days} -sha256 -CA ${ca_crt_file} -CAkey ${ca_key_file} -CAcreateserial -in ${srv_csr_file} -out ${srv_crt_file} -extfile ${cfg_san_file} -extensions SAN
cat ${srv_crt_file} ${ca_crt_file} > ${srv_fullchain_file}
openssl pkcs12 -export -inkey ${srv_key_file} -in ${srv_crt_file} -CAfile ${ca_crt_file} -chain -out ${srv_p12_file}
fi
|
脚本使用用法
1
|
./gen-cert.sh -a 算法 -d 域名 -n 证书文件名
|
执行脚本生成 tls 证书文件
由于 traefik 在使用 secret 资源对象引用证书文件时,名称必须是 tls.crt
和 tls.key
,这里我们在创建的时候就将名称设置为 tls
1
2
3
4
5
6
|
chmod a+x gen-cert.sh
./gen-cert.sh -a ecc -d idocker.io,*.idocker.io -n tls
ls certs/ # 在对应目录下,有如下文件即可
ca.crt ca.key ca.srl san.cnf tls.crt tls.csr tls-fullchain.crt tls.key tls.p12
|
将生成的证书,使用 secret 资源对象进行存储
1
2
3
|
kubectl create secret tls idocker-tls --cert=certs/tls.crt --key=certs/tls.key -n nexus
kubectl get secret idocker-tls -n nexus -o yaml
|
更新 traefik ingress 资源对象
最终,完整 nexus-ingressroute.yaml
配置文件如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nexus-mirror
namespace: nexus
spec:
entryPoints:
- web
routes:
- match: Host(`mirror.treesir.pub`) && PathPrefix(`/`)
kind: Rule
services:
- name: nexus-service
port: 8081
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nexus-idocker-http
namespace: nexus
spec:
entryPoints:
- websecure
routes:
- match: Host(`idocker.io`) || (Host(`idocker.io`) && Method(`GET`))
kind: Rule
services:
- name: nexus-service
port: 8082
- match: (Host(`idocker.io`) && Path(`/v1/search`)) || (Host(`idocker.io`) && Method(`PUT`,`HEAD`,`POST`,`PATCH`))
kind: Rule
priority: 100 # 权重值提高,在执行 curl https://idocker.io/v1/search?q=nginx 时,确认路由至 dokcer-custom 私服中
services:
- name: nexus-service
port: 8086
- match: Host(`dev.idocker.io`) && PathPrefix(`/`)
kind: Rule
services:
- name: nexus-service
port: 8083
- match: Host(`qa.idocker.io`) && PathPrefix(`/`)
kind: Rule
services:
- name: nexus-service
port: 8084
- match: Host(`prod.idocker.io`) && PathPrefix(`/`)
kind: Rule
services:
- name: nexus-service
port: 8085
tls:
secretName: idocker-tls
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: nexus
spec:
redirectScheme:
scheme: https
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nexus-idocker-https
namespace: nexus
spec:
entryPoints:
- web
routes:
- match: HostRegexp(`idocker.io`, `{subdomain:[a-z]+}.idocker.io`)
kind: Rule
services:
- name: nexus-service
port: 8082
middlewares:
- name: redirect-https
|
私服的使用
ingressroute 创建完成后,就是测试对应私服的使用了,直接拿来使用还不行,会提示证书报错,解决方法列表如下:
由于,不支持对泛域名的一次认证,如多个子域名时,还需进行一个多次的 copy 操作。
参考文档
nexus 其他高级使用说明,请参考 此篇文档
https://doc.traefik.io/traefik/routing/routers/
https://www.jianshu.com/p/52fedb82ef53
Todo