如何自动化Kubernetes中GitLab所需TLS证书的Secret重映射流程
GitLab证书重映射自动化方案(Kubernetes+ArgoCD场景)
问题背景
- 运行GitLab镜像时,要求HTTPS证书必须用
<DNS>.crt和<DNS>.key的命名格式 - 已经通过带Let's Encrypt签发器的Ingress拿到了证书,但对应的Secret(
project-gitlab-tls)里的证书键名是默认的tls.crt和tls.key,不符合GitLab要求 - 手动用三条kubectl命令解码原Secret内容,重新创建了符合命名要求的
gitlab-registry-certsSecret,挂载到GitLab部署后能正常运行 - 现在用ArgoCD做部署工具,想把这个证书重映射的流程自动化,要求在集群生成、证书获取完成、GitLab部署创建前执行;之前试过用Job,但容器没权限操作集群,卡在这里了
可行自动化方案
方案一:给Job加集群权限
之前Job跑不起来,核心是容器没拿到操作集群的权限,给Job绑定对应的ServiceAccount和权限就行:
- 创建专用ServiceAccount:
apiVersion: v1 kind: ServiceAccount metadata: name: cert-remap-sa namespace: 你的命名空间
- 创建ClusterRole(如果只在单个命名空间操作,也可以用Namespace级的Role),赋予读取原Secret、创建/更新目标Secret的权限:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cert-remap-role rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "create", "update"]
- 把ServiceAccount和ClusterRole绑定:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cert-remap-binding subjects: - kind: ServiceAccount name: cert-remap-sa namespace: 你的命名空间 roleRef: kind: ClusterRole name: cert-remap-role apiGroup: rbac.authorization.k8s.io
- 编写Job,用带kubectl的镜像(比如
bitnami/kubectl)执行重映射脚本:
apiVersion: batch/v1 kind: Job metadata: name: cert-remap-job namespace: 你的命名空间 spec: template: spec: serviceAccountName: cert-remap-sa containers: - name: cert-remap image: bitnami/kubectl:latest command: ["/bin/sh", "-c"] args: - | # 拉取原Secret的证书和密钥内容 CRT=$(kubectl get secret project-gitlab-tls -n 你的命名空间 -o jsonpath='{.data.tls\.crt}') KEY=$(kubectl get secret project-gitlab-tls -n 你的命名空间 -o jsonpath='{.data.tls\.key}') # 替换成你的GitLab域名 DNS=gitlab.example.com # 创建或更新目标Secret kubectl create secret generic gitlab-registry-certs -n 你的命名空间 \ --from-literal=${DNS}.crt=$CRT \ --from-literal=${DNS}.key=$KEY \ --dry-run=client -o yaml | kubectl apply -f - restartPolicy: OnFailure
- 在ArgoCD里配置部署顺序:给GitLab的Deployment加
dependsOn,让它等这个Job执行完再部署,确保证书准备就绪
方案二:ArgoCD PreSync Hook + 外部脚本
如果偏好用外部主机执行脚本,可以用ArgoCD的PreSync钩子触发:
- 写个bash脚本
cert-remap.sh(放在有权限访问集群的外部主机上):
#!/bin/bash NAMESPACE="你的命名空间" ORIGINAL_SECRET="project-gitlab-tls" TARGET_SECRET="gitlab-registry-certs" DNS="gitlab.example.com" # 拉取原Secret内容 CRT=$(kubectl get secret $ORIGINAL_SECRET -n $NAMESPACE -o jsonpath='{.data.tls\.crt}') KEY=$(kubectl get secret $ORIGINAL_SECRET -n $NAMESPACE -o jsonpath='{.data.tls\.key}') # 创建或更新目标Secret kubectl create secret generic $TARGET_SECRET -n $NAMESPACE \ --from-literal=${DNS}.crt=$CRT \ --from-literal=${DNS}.key=$KEY \ --dry-run=client -o yaml | kubectl apply -f -
- 在ArgoCD的Application配置里加PreSync Hook,通过SSH调用外部脚本(要确保容器里能访问外部主机,比如提前放好SSH密钥):
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: gitlab namespace: argocd spec: # 其他应用配置(比如repo、目标命名空间等) syncPolicy: hooks: - name: pre-sync-cert-remap type: PreSync template: spec: containers: - name: run-script image: alpine:latest command: ["sh", "-c"] args: ["ssh 你的用户名@外部主机IP 'bash /脚本存放路径/cert-remap.sh'"] restartPolicy: OnFailure
更简便的证书使用方案
其实不用额外创建Secret,直接在GitLab的Deployment里改挂载配置就行:
GitLab的Volume挂载支持重命名文件,把原Secret里的tls.crt和tls.key直接映射成<DNS>.crt和<DNS>.key:
apiVersion: apps/v1 kind: Deployment metadata: name: gitlab namespace: 你的命名空间 spec: template: spec: volumes: - name: gitlab-cert secret: secretName: project-gitlab-tls items: - key: tls.crt path: gitlab.example.com.crt # 替换成你的GitLab域名 - key: tls.key path: gitlab.example.com.key # 替换成你的GitLab域名 containers: - name: gitlab image: gitlab/gitlab-ce:latest volumeMounts: - name: gitlab-cert mountPath: /etc/gitlab/ssl # GitLab证书存放路径,根据镜像调整 readOnly: true
这种方式一步到位,不用搞额外的自动化流程,直接绕过证书重命名的问题
内容的提问来源于stack exchange,提问作者A. Vreeswijk
相关产品推荐
相关产品推荐

