使用带有 minikube 的 Kubernetes api 服务器的自定义证书

Using a custom certificate for the Kubernetes api server with minikube

我一直在努力寻找如何做到这一点,但到目前为止一无所获,我对 Kubernetes 还很陌生,所以我可能只是看了看。我想为 Kubernetes API 服务器使用我自己的证书,这可能吗?如果是这样,有人可以给我一个 link 吗?

是的,您可以使用自己的证书并设置 Kubernetes API 服务器。

假设您已经创建了证书移动并将它们保存到特定节点目录:

{
  sudo mkdir -p /var/lib/kubernetes/

  sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
    service-account-key.pem service-account.pem \
    encryption-config.yaml /var/lib/kubernetes/
}

实例内部 IP 地址将用于向集群成员公布 API 服务器。获取内网IP:

INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \
  http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)

您可以创建 API 服务器的服务并进行设置。

注意:上面提到的示例专门考虑了 GCP 实例,因此您可能需要更改一些命令,例如。

INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \
      http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip) 

对于上述命令,如果您不使用它,您可以提供手动裸机 IP 列表而不是从 GCP 实例 API 获取。

到此请参考这个link:https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/08-bootstrapping-kubernetes-controllers.md#configure-the-kubernetes-api-server

在这里您可以找到从头开始创建和设置整个 Kubernetes 集群的所有详细信息以及详细的文档和命令:https://github.com/kelseyhightower/kubernetes-the-hard-way

好的,这就是我的想法。我们知道我们无法更改集群证书,但还有其他方法可以做到。我们应该可以通过入口代理。

首先我们启用了 ingres 插件:

➜  ~ minikube addons enable ingress

给定 tls.crttls.key 我们创建一个秘密(如果您使用 certmanager 则不需要这样做,但这需要一些额外的步骤,我不会在这里描述):

➜  ~ kubectl create secret tls my-tls --cert=tls.crt --key tls.key

和一个入口对象:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-k8s
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  tls:
  - hosts:
    - foo.bar.com
    secretName: my-tls
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes
            port:
              number: 443

注意文档对 CN 和 FQDN 的看法:k8s docs:

Referencing this secret in an Ingress tells the Ingress controller to secure the channel from the client to the load balancer using TLS. You need to make sure the TLS secret you created came from a certificate that contains a Common Name (CN), also known as a Fully Qualified Domain Name (FQDN) for https-example.foo.com.

这种方法的唯一问题是我们无法在从外部访问时使用证书进行身份验证。

但是我们可以使用代币。这是 k8s 文档中的一个页面:https://kubernetes.io/docs/reference/access-authn-authz/authentication/ 列出了所有可能的身份验证方法。

为了测试,我选择了 serviceaccout 令牌,但您可以随意尝试其他令牌。

让我们创建一个服务帐户,为其绑定一个角色,然后尝试访问集群:

➜  ~ kubectl create sa cadmin
serviceaccount/cadmin created
➜  ~ kubectl create clusterrolebinding --clusterrole cluster-admin --serviceaccount default:cadmin cadminbinding
clusterrolebinding.rbac.authorization.k8s.io/cadminbinding created

现在我们按照以下说明进行操作:access-cluster-api 从文档中尝试使用 sa 令牌访问集群。

➜  ~ APISERVER=https://$(minikube ip)
➜  ~ TOKEN=$(kubectl get secret $(kubectl get serviceaccount cadmin -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
➜  ~ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure -H "Host: foo.bar.com"
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.39.210:8443"
    }
  ]
}

note: I am testing it with invalid/selfsigned certificates and I don't own the foo.bar.com domain so I need to pass Host header by hand. For you it may look a bit different, so don't just copypate; try to understand what's happening and adjust it. If you have a domain you should be able to access it directly (no $(minikube ip) necessary).

如您所见,它成功了!我们从 api 服务器收到了有效响应。

但是我们可能不想使用curl访问k8s。

让我们用令牌创建一个 kubeconfig。

kubectl config set-credentials cadmin --token $TOKEN --kubeconfig my-config
kubectl config set-cluster mini --kubeconfig my-config --server https://foo.bar.com
kubectl config set-context mini --kubeconfig my-config --cluster mini --user cadmin
kubectl config use-context --kubeconfig my-config mini

现在我们可以使用此配置访问 k8s:

➜  ~ kubectl get po --kubeconfig my-config
No resources found in default namespace.