kubernetes 集群可以为证书签名,用于集群内部的TLS通信,ca就是集群的ca,每个pod里面serviceaccount的secret都带着。
1. 创建证书签名请求-csr
$ cat <<EOF | ./cfssl genkey - | ./cfssljson -bare server
{
"hosts": [
"nginx.default.svc.cluster.local"
],
"CN": "nginx.default.svc.cluster.local",
"key": {
"algo": "ecdsa",
"size": 256
}
}
EOF
2020/06/03 10:49:59 [INFO] generate received request
2020/06/03 10:49:59 [INFO] received CSR
2020/06/03 10:49:59 [INFO] generating key: ecdsa-256
2020/06/03 10:49:59 [INFO] encoded CSR
生成了私钥文件 server-key.pem 和签名请求文件 server.csr
2. 创建发送给 Kubernetes API的 csr 对象
$ cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: my-svc.default
spec:
request: $(cat server.csr | base64 | tr -d '\n')
usages:
- digital signature
- key encipherment
- server auth
EOF
certificatesigningrequest.certificates.k8s.io/my-svc.default created
查看csr对象,状态为Pending
$ k get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
my-svc.default 6m25s kubernetes.io/legacy-unknown kubernetes-admin Pending
3. 批准证书签名请求
$ k certificate approve my-svc.default
certificatesigningrequest.certificates.k8s.io/my-svc.default approved
$ k get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
my-svc.default 11m kubernetes.io/legacy-unknown kubernetes-admin Approved,Issued
4. 下载证书文件
$ k get csr my-svc.default -o jsonpath='{.status.certificate}' | base64 --decode > server.crt
得到证书文件 server.crt
5. 使用 server.crt 和 server-key.pem 创建 https server
5.1 创建证书和私钥的secret
k create secret generic https --from-file=server.crt --from-file=server-key.pem
5.2 创建nginx配置文件的cm
$ cat <<EOF | k apply -f -
> apiVersion: v1
> kind: ConfigMap
> metadata:
> name: nginx
> data:
> my-nginx-config.conf: |
> server {
> listen 80;
> listen 443 ssl;
> server_name www.example.com;
> ssl_certificate certs/server.pem;
> ssl_certificate_key certs/server-key.pem;
> ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
> ssl_ciphers HIGH:!aNULL:!MD5;
>
> location / {
> root /usr/share/nginx/html;
> index index.html index.htm;
> }
> }
> EOF
configmap/nginx created
5.3 创建nginx部署
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
initContainers:
- name: page-initiator
image: busybox
imagePullPolicy: Never
command: ['sh', '-c', 'echo $HOSTNAME > /data/index.html']
volumeMounts:
- mountPath: /data
name: page-volume
containers:
- image: nginx:1.7.9
name: nginx
imagePullPolicy: Never
volumeMounts:
- mountPath: /usr/share/nginx
name: page-volume
- mountPath: /etc/nginx/certs
name: certs
readOnly: true
- mountPath: /etc/nginx/conf.d
name: config
readOnly: true
ports:
- containerPort: 80
- containerPort: 443
volumes:
- name: page-volume
emptyDir: {}
- name: certs
secret:
secretName: https
- name: config
configMap:
name: nginx
items:
- key: my-nginx-config.conf
path: https.conf
6. 在pod中使用 serviceaccount 带的 ca.crt 访问 https 站点
$ k run curl --image=curlimages/curl --command -- sleep infinity
$ k exec -it curl-9c984d666-9hlfc -- sh
$ curl https://nginx.default.svc.cluster.local --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
nginx-7464848dfc-twmtv