步骤 1:准备全部集群的直连 kubeconfig 配置文件

在默认情况下, Rancher UI 上复制的 kubeconfig 通过cluster agent代理连接到 K8S 集群。变更 SSL 证书会导致cluster agent无法连接 Rancher Server,从而导致kubectl无法使用 Rancher UI 上复制的 kubeconfig 去操作 K8S 集群。用户需要通过kubectl命令行修改配置,解决这个问题。在执行域名或 IP 变更之前,请准备好所有集群的直连 kubeconfig 配置文件,详情考参考:恢复 kubectl 配置文件

:::note 警告

  1. 如果您使用的是 2.1.x 以前的版本,可以在 Master 节点的/etc/kubernetes/.tmp路径下找到kubecfg-kube-admin.yml文件。该文件是具有集群管理员权限的直连 kubeconfig 配置文件;

    image-20190309173154246

  2. 执行域名变更或 IP 变更之前,请备份 Rancher Server,详情请参考备份和恢复

:::

步骤 2:准备证书

SSL 证书与域名或IP之间存在绑定关系,客户端通过域名或IP访问 Server 端时,需要进行 SSL 证书校验。如果客户端访问的域名或IP与 SSL 证书中预先绑定的域名或IP不一致,那么 SSL 会认为这个 Server 端是伪造的,导致证书校验失败,客户端无法连接 Server 端。如果您更换了域名或 IP,而且在生成 SSL 证书时没有绑定新的域名或 IP,出现上述问题就是一个正常的现象。解决该问题的方法也非常直接明了:生成一个新的 SSL 证书,绑定新的域名或 IP,替换已有的证书。如果您已经有后续域名或 IP 变更的具体规划,也可以在生成 SSL 证书 时绑定这次和以后需要替换的域名或 IP,这样可以减轻下次变更的工作量。总而言之,如果更换了 Server 端的域名或IP,一般会涉及到 SSL 证书更换。请参考下文,替换自签名 SSL 证书或权威认证证书。

  • 自签名 ssl 证书

    复制以下代码另存为create_self-signed-cert.sh或者其他您喜欢的文件名。修改代码开头的CN(域名),如果需要使用 ip 去访问 Rancher Server,那么需要给 ssl 证书添加扩展 IP,多个 IP 用逗号隔开。如果想实现多个域名访问 Rancher Server,则添加扩展域名(SSL_DNS),多个SSL_DNS用逗号隔开。

    1. #!/bin/bash -e
    2. help ()
    3. {
    4. echo ' ================================================================ '
    5. echo ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;'
    6. echo ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问Server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;'
    7. echo ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;'
    8. echo ' --ssl-size: ssl加密位数,默认2048;'
    9. echo ' --ssl-cn: 国家代码(2个字母的代号),默认CN;'
    10. echo ' 使用示例:'
    11. echo ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ '
    12. echo ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650'
    13. echo ' ================================================================'
    14. }
    15. case "$1" in
    16. -h|--help) help; exit;;
    17. esac
    18. if [[ $1 == '' ]];then
    19. help;
    20. exit;
    21. fi
    22. CMDOPTS="$*"
    23. for OPTS in $CMDOPTS;
    24. do
    25. key=$(echo ${OPTS} | awk -F"=" '{print $1}' )
    26. value=$(echo ${OPTS} | awk -F"=" '{print $2}' )
    27. case "$key" in
    28. --ssl-domain) SSL_DOMAIN=$value ;;
    29. --ssl-trusted-ip) SSL_TRUSTED_IP=$value ;;
    30. --ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;;
    31. --ssl-size) SSL_SIZE=$value ;;
    32. --ssl-date) SSL_DATE=$value ;;
    33. --ca-date) CA_DATE=$value ;;
    34. --ssl-cn) CN=$value ;;
    35. esac
    36. done
    37. # CA相关配置
    38. CA_DATE=${CA_DATE:-3650}
    39. CA_KEY=${CA_KEY:-cakey.pem}
    40. CA_CERT=${CA_CERT:-cacerts.pem}
    41. CA_DOMAIN=cattle-ca
    42. # ssl相关配置
    43. SSL_CONFIG=${SSL_CONFIG:-$PWD/openssl.cnf}
    44. SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'}
    45. SSL_DATE=${SSL_DATE:-3650}
    46. SSL_SIZE=${SSL_SIZE:-2048}
    47. ## 国家代码(2个字母的代号),默认CN;
    48. CN=${CN:-CN}
    49. SSL_KEY=$SSL_DOMAIN.key
    50. SSL_CSR=$SSL_DOMAIN.csr
    51. SSL_CERT=$SSL_DOMAIN.crt
    52. echo -e "\033[32m ---------------------------- \033[0m"
    53. echo -e "\033[32m | 生成 SSL Cert | \033[0m"
    54. echo -e "\033[32m ---------------------------- \033[0m"
    55. if [[ -e ./${CA_KEY} ]]; then
    56. echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份"${CA_KEY}"为"${CA_KEY}"-bak,然后重新创建 \033[0m"
    57. mv ${CA_KEY} "${CA_KEY}"-bak
    58. openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
    59. else
    60. echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m"
    61. openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
    62. fi
    63. if [[ -e ./${CA_CERT} ]]; then
    64. echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份"${CA_CERT}"为"${CA_CERT}"-bak,然后重新创建 \033[0m"
    65. mv ${CA_CERT} "${CA_CERT}"-bak
    66. openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
    67. else
    68. echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m"
    69. openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
    70. fi
    71. echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m"
    72. cat > ${SSL_CONFIG} <<EOM
    73. [req]
    74. req_extensions = v3_req
    75. distinguished_name = req_distinguished_name
    76. [req_distinguished_name]
    77. [ v3_req ]
    78. basicConstraints = CA:FALSE
    79. keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    80. extendedKeyUsage = clientAuth, serverAuth
    81. EOM
    82. if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} ]]; then
    83. cat >> ${SSL_CONFIG} <<EOM
    84. subjectAltName = @alt_names
    85. [alt_names]
    86. EOM
    87. IFS=","
    88. dns=(${SSL_TRUSTED_DOMAIN})
    89. dns+=(${SSL_DOMAIN})
    90. for i in "${!dns[@]}"; do
    91. echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG}
    92. done
    93. if [[ -n ${SSL_TRUSTED_IP} ]]; then
    94. ip=(${SSL_TRUSTED_IP})
    95. for i in "${!ip[@]}"; do
    96. echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG}
    97. done
    98. fi
    99. fi
    100. echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m"
    101. openssl genrsa -out ${SSL_KEY} ${SSL_SIZE}
    102. echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m"
    103. openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN}/CN=${SSL_DOMAIN}" -config ${SSL_CONFIG}
    104. echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m"
    105. openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \
    106. -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \
    107. -days ${SSL_DATE} -extensions v3_req \
    108. -extfile ${SSL_CONFIG}
    109. echo -e "\033[32m ====> 7. 证书制作完成 \033[0m"
    110. echo
    111. echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m"
    112. echo "----------------------------------------------------------"
    113. echo "ca_key: |"
    114. cat $CA_KEY | sed 's/^/ /'
    115. echo
    116. echo "ca_cert: |"
    117. cat $CA_CERT | sed 's/^/ /'
    118. echo
    119. echo "ssl_key: |"
    120. cat $SSL_KEY | sed 's/^/ /'
    121. echo
    122. echo "ssl_csr: |"
    123. cat $SSL_CSR | sed 's/^/ /'
    124. echo
    125. echo "ssl_cert: |"
    126. cat $SSL_CERT | sed 's/^/ /'
    127. echo
    128. echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m"
    129. cat ${CA_CERT} >> ${SSL_CERT}
    130. echo "ssl_cert: |"
    131. cat $SSL_CERT | sed 's/^/ /'
    132. echo
    133. echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m"
    134. echo "cp ${SSL_DOMAIN}.key tls.key"
    135. cp ${SSL_DOMAIN}.key tls.key
    136. echo "cp ${SSL_DOMAIN}.crt tls.crt"
    137. cp ${SSL_DOMAIN}.crt tls.crt
  • 权威认证证书

    把权威证书文件重命名为需要的文件名:

    1. cp xxx.key tls.key
    2. cp xxx.crt tls.crt

步骤 3:更新证书(可选)

:::note 提示 证书与域名或 IP 有绑定关系,一般情况更换域名或 IP 需更换证书。如果之前配置的证书是一个通配证书或者之前配置的证书已经包含了需要变更的域名或 IP,那么证书则可以不用更换。 :::

3.1. Rancher 单节点运行(默认容器自动生成自签名 SSL 证书)

默认情况,通过docker run运行的 Rancher Server 容器,会自动为 Rancher 生成 SSL 证书,这个证书会自动绑定 Rancher 系统设置中server-url配置的域名或IP。如果更换了域名或IP,证书会自动更新,无需单独操作。

3.2. Rancher 单节点运行(外置自签名 SSL 证书)

注意:操作前先备份,备份和恢复

如果是以映射证书文件的方式运行的单容器 Rancher Server,只需要停止原有 Rancher Server 容器,用新证书替换旧证书,保持文件名不变,然后重新运行容器即可。

3.3. Rancher HA 运行

注意:操作前先备份,备份和恢复

  1. 备份原有证书 YAML 文件

    1. kubectl --kubeconfig=kube_configxxx.yml -n cattle-system \
    2. get secret tls-rancher-ingress -o yaml > tls-ingress.yml
    3. kubectl --kubeconfig=kube_configxxx.yml -n cattle-system \
    4. get secret tls-ca -o yaml > tls-ca.yml
  2. 删除旧的 secret,然后创建新的 secret

    1. # 指定kube配置文件路径
    2. kubeconfig=xxx.yaml
    3. # 删除旧的secret
    4. kubectl --kubeconfig=$kubeconfig -n cattle-system \
    5. delete secret tls-rancher-ingress
    6. kubectl --kubeconfig=$kubeconfig -n cattle-system \
    7. delete secret tls-ca
    8. # 创建新的secret
    9. kubectl --kubeconfig=$kubeconfig -n cattle-system \
    10. create secret tls tls-rancher-ingress --cert=./tls.crt --key=./tls.key
    11. kubectl --kubeconfig=$kubeconfig -n cattle-system \
    12. create secret generic tls-ca --from-file=cacerts.pem
    13. # 重启Pod
    14. kubectl --kubeconfig=$kubeconfig -n cattle-system \
    15. delete pod `kubectl --kubeconfig=$kubeconfig -n cattle-system \
    16. get pod |grep -E "cattle-cluster-agent|cattle-node-agent|rancher" | awk '{print $1}'`

重要提示: 如果环境不是按照标准的 rancher 安装文档安装,secret名称可能不相同,请根据实际 secret 名称操作。

步骤 4:修改 Rancher Server IP 或域名

  1. 依次访问全局 > 系统设置,页面往下翻找到server-url文件;

    image-20200220190647637

  2. 单击右侧的省略号菜单,选择升级;

    image-20200220190801613

  3. 修改server-url地址;

    image-20200220190821898

  4. 最后单击保存

步骤 5:更新 ingress 配置文件

将 ingress 中的 host 字段修改成新的域名

  1. kubectl --kubeconfig=kube_configxxx.yml edit ingress rancher -n cattle-system
  2. spec:
  3. rules:
  4. - host: x.x.x
  5. http:
  6. paths:
  7. - backend:
  8. serviceName: rancher
  9. servicePort: 80
  10. tls:
  11. - hosts:
  12. - x.x.x
  13. secretName: tls-rancher-ingress

步骤 6:更新 agent 配置文件

  1. 通过新域名或IP登录 Rancher Server;

    :::note 警告 这一步非常重要! :::

  2. 通过浏览器地址栏查询集群IDc/后面以c开头的字段即为集群 ID;

    image-20200220205103937

  3. 访问https://<新的server_url>/v3/clusters/<集群ID>/clusterregistrationtokens页面;

  4. 打开clusterRegistrationTokens页面后,定位到data字段;

    image-20191214193741315

  5. 找到insecureCommand字段,复制 YAML 连接备用;

    image-20191214194320570

可能会有多组"baseType": "clusterRegistrationToken",如下图。这种情况以createdTS最大、时间最新的一组为准,一般是最后一组。 image-20191214193550681

  1. 使用kubectl工具,通过第一步准备的直连kubeconfig配置文件和上面步骤中获取的 YAML 文件,执行以下命令更新agent相关配置。

    1. curl -L -k <替换为上面步骤获取的YAML文件链接> | kubectl --kubeconfig=<直连kubeconfig配置文件> apply -f -

后续操作

上述步骤 1~6 演示了如何为单个集群更新 agent 配置,您需要按照这些步骤,为所有集群更新 agent 配置,才能够完成域名或 IP 变更。