跳到主要内容

K3s 为 Ingress 签发证书

配置私有 CA 证书

首先是给自己搞个自签 CA 证书,这个证书是用来给你的域名签发证书的,这个证书是自签名的,所以你需要自己信任这个证书,这个证书的作用是用来给你的域名签发证书的,这个证书是自签名的,所以你需要自己信任这个证书。 可以的,下面是一个创建自签名证书颁发机构(CA)并用它来签发域名证书的步骤。注意这个例子是基于Linux操作系统和OpenSSL工具的。

sudo apt-get update
sudo apt-get install openssl

1、创建一个私钥:

openssl genpkey -algorithm RSA -out ca.key

2、 创建一个自签名的CA证书:

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt

在这个过程中,系统会提示你输入证书的相关信息,如国家、省份、城市、组织名等。

为了方便客户端安装,可以把格式转换一下(这两种文件格式本质上是相同的。.crt和.pem文件都可以包含PEM编码的证书。)

openssl x509 -in ca.crt -out ca.pem -outform PEM

为了让Linux系统信任自签发的CA证书,你需要将CA证书添加到系统的信任存储中。

sudo cp ca.crt /usr/local/share/ca-certificates/
# 有些系统是要 pem
sudo cp ca.pem /usr/local/share/ca-certificates/


sudo mkdir -p /usr/local/share/ca-certificates/harbor.quicktoolset.top
sudo cp ca.crt /usr/local/share/ca-certificates/harbor.quicktoolset.top/ca.crt
sudo update-ca-certificates

更新证书存储:

sudo update-ca-certificates

或者使用 K3s 的 CA 证书

在 Kubernetes 环境中,尤其是在 k3s 这类轻量级 Kubernetes 发行版中,Pods 对证书的信任取决于容器内配置的信任链。

k3s 作为 Kubernetes 发行版,会自动生成用于各种内部通讯的 CA 和证书,这些证书被用来保护 Kubernetes 控制平面组件之间的通信,比如 kube-apiserver, etcd 等。这些内部服务信任 k3s 自动生成的 CA 签发的证书。 但是对于运行在 Pod 中的应用程序,默认情况下它们不会自动信任 k3s 的 CA。

找到k3s的CA证书和密钥:k3s在安装时会生成自己的CA证书和密钥,它们通常位于 /var/lib/rancher/k3s/server/tls 目录下,名为 client-ca.crtclient-ca.key

sudo cp /var/lib/rancher/k3s/server/tls/client-ca.key ca.key
sudo cp /var/lib/rancher/k3s/server/tls/client-ca.crt ca.crt

# 为了避免误操作,这里拷贝下来
sudo chown $USER:$USER ca.key
sudo chown $USER:$USER ca.crt

# 添加到系统证书
sudo cp ca.crt /usr/local/share/ca-certificates/ca.crt
sudo update-ca-certificates

# 验证证书(后面签发后)
openssl s_client -connect yourdomain.com:443 -CAfile ca.crt

命令行自己生成证书(不推荐)

创建私有域名的CSR(证书签名请求):你需要为你的私有域名创建一个CSR和一个新的私钥。使用以下命令:

openssl req -new -newkey rsa:2048 -nodes -keyout private.domain.key -out private.domain.csr -subj "/CN=private.domain"

这会创建一个私钥(private.domain.key)和一个证书签名请求(private.domain.csr),其中CN(通用名称)设置为你的私有域名。

使用k3s的CA签发证书:现在你可以使用k3s的CA证书和密钥来签发你的私有域名证书。使用以下命令:

openssl x509 -req -in private.domain.csr -CA /var/lib/rancher/k3s/server/tls/client-ca.crt -CAkey /var/lib/rancher/k3s/server/tls/client-ca.key -CAcreateserial -out private.domain.crt -days 365

这将使用CA证书和密钥来签发你的私有域名证书,有效期为365天。

转换证书格式(如果需要):有些应用程序可能需要证书在特定格式下,比如PFX或PEM。使用openssl你可以轻易转换这些格式。例如,如果你需要一个PEM格式的证书,可以这样做:

cat private.domain.crt private.domain.key > private.domain.pem

使用 cert-manager 签发证书

以下是一个配置 cert-manager 使用自签名 CA 来自动签发 Ingress 域名证书的例子。

使用Helm来安装cert-manager,首先添加Helm仓库:

helm repo add jetstack https://charts.jetstack.io
helm repo update

然后安装 cert-manager:

kubectl create namespace cert-manager
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.6.1 \
--set installCRDs=true

配置自签名 CA 的 ClusterIssuer

首先,你需要将你的 CA 证书(ca.crt)和私钥(ca.key)添加到 Kubernetes 的 Secret 中:

apiVersion: v1
kind: Secret
metadata:
name: internal-ca-key-pair
namespace: cert-manager
type: kubernetes.io/tls
data:
tls.crt: <base64-encoded-ca-cert>
tls.key: <base64-encoded-ca-key>

<base64-encoded-ca-cert><base64-encoded-ca-key> 替换为你的 CA 证书和私钥的 Base64 编码值。

base64 -w0 ca.crt
base64 -w0 ca.key

然后,创建一个 ClusterIssuer 来使用这个 CA:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: internal-ca-issuer
spec:
ca:
secretName: internal-ca-key-pair

为 Ingress 创建证书

现在你可以创建一个 Certificate 资源来为你的 Ingress 签发证书了:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-ingress-cert
namespace: <your-namespace>
spec:
secretName: my-ingress-cert-tls
issuerRef:
name: internal-ca-issuer
kind: ClusterIssuer
dnsNames:
- example.com

<your-namespace>替换为你的命名空间,example.com替换为你的域名。

配置 Ingress 使用证书

最后,更新你的Ingress资源,使其使用由cert-manager创建的证书:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: <your-namespace>
annotations:
cert-manager.io/cluster-issuer: "ca-issuer"
spec:
tls:
- hosts:
- example.com
secretName: my-ingress-cert-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80

<your-namespace> 替换为你的命名空间,example.com替换为你的域名,以及更新backend的service名和端口号。

完成这些步骤后,cert-manager应该会自动为你的Ingress签发证书,并且当证书即将到期时自动续签。你可以通过查看Certificate资源的状态来确认证书是否已成功签发。

Pod 里面信任证书

使用 sudo update-ca-certificates 命令在宿主机(Kubernetes 节点)上添加 CA 证书时,你只是更新了该特定节点上的系统信任存储。但是,这个更新不会自动应用到在 Kubernetes 集群中运行的 Pod。Pod 内的容器通常使用自己的文件系统和 CA 证书存储,这意味着宿主机上的证书存储更改不会传递到容器中。

要使 Pod 信任额外的 CA 证书,你需要将证书注入到每个需要它的 Pod。这通常是通过创建一个包含 CA 证书的 Kubernetes Secret,然后将该 Secret 挂载到 Pod 的文件系统中完成的。这样,应用程序可以在容器内部引用这个证书,作为信任链的一部分。

以下是一个步骤示例,展示如何将额外的 CA 证书添加到 Pod 中:

1、创建一个包含你的 CA 证书的 Secret

首先,你需要将 CA 证书编码为 base64,然后创建一个 Secret。假设你的 CA 证书文件名为 ca.crt

kubectl create secret generic custom-ca --from-file=ca.crt=/path/to/your/ca.crt -n your-namespace

2、更新你的 Pod 定义来挂载 Secret

然后,在你的 Pod 配置中,添加一个 volume 来从 Secret 挂载证书,并在容器中选择一个合适的挂载点:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: your-namespace
spec:
containers:
- name: my-container
image: my-image
volumeMounts:
- name: ca-certificate
mountPath: /etc/ssl/certs
readOnly: true
volumes:
- name: ca-certificate
secret:
secretName: custom-ca

注意:你需要挂载到一个容器已知会检查的路径或者一个应用程序可以通过配置查找的路径。根据你的容器镜像,你可能需要将证书放在特定的位置或更新相应的证书目录索引。

3、配置应用程序信任挂载的 CA 证书

你的应用程序可能需要额外的配置来信任挂载的证书,比如设置环境变量或者修改配置文件来指向新的 CA 证书路径。

4、重启 Pod

应用配置更新后,你需要重新部署 Pod 以使更改生效。

通过这些步骤,你的 Pod 将能够信任通过 Secret 挂载的额外 CA 证书。这是 Kubernetes 集群中管理证书和信任链的通常做法。

References